Mirror from bluesky-social/pds
1# PDS
2
3Welcome to the repository for the official Bluesky PDS (Personal Data Server). This repository includes container images and documentation designed to assist technical people with self-hosting a Bluesky PDS.
4
5## FAQ
6
7### What is Bluesky?
8
9Bluesky is a social media application built on AT Protocol.
10
11Please visit the [Bluesky website](https://bsky.app/) for more information.
12
13### What is AT Protocol?
14
15The Authenticated Transfer Protocol, aka atproto, is a protocol for large-scale distributed social applications.
16
17Please visit the [AT Protocol docs](https://atproto.com/guides/overview) for additional information.
18
19### Where is the code?
20
21* [Canonical TypeScript code](https://github.com/bluesky-social/atproto)
22* [Experimental Go code](https://github.com/bluesky-social/indigo)
23
24## Self-hosting PDS
25
26Self-hosting a Bluesky PDS means running your own Personal Data Server that is capable of federating with the wider Bluesky social network.
27
28### Preparation for self-hosting PDS
29
30Launch a server on any cloud provider, [Digital Ocean](https://digitalocean.com/) and [Vultr](https://vultr.com/) are two popular choices.
31
32Ensure that you can ssh to your server and have root access.
33
34**Server Requirements**
35* Public IPv4 address
36* Public DNS name
37* Public inbound internet access permitted on port 80/tcp and 443/tcp
38
39**Server Recommendations**
40| | |
41| ---------------- | ---------------- |
42| Operating System | Ubuntu 22.04 |
43| Memory (RAM) | 2+ GB |
44| CPU Cores | 2+ |
45| Storage | 40+ GB SSD |
46| Architectures | amd64, arm64 |
47
48**Note:** It is a good security practice to restrict inbound ssh access (port 22/tcp) to your own computer's public IP address. You can check your current public IP address using [ifconfig.me](https://ifconfig.me/).
49
50### Open your cloud firewall for HTTP and HTTPS
51
52One of the most common sources of misconfiguration is not opening firewall ports correctly. Please be sure to double check this step.
53
54In your cloud provider's console, the following ports should be open to inbound access from the public internet.
55
56* 80/tcp (Used only for TLS certification verification)
57* 443/tcp (Used for all application requests)
58
59**Note:** there is no need to set up TLS or redirect requests from port 80 to 443 because the Caddy web server, included in the Docker compose file, will handle this for you.
60
61### Configure DNS for your domain
62
63From your DNS provider's control panel, set up a domain with records pointing to your server.
64
65| Name | Type | Value | TTL |
66| ----------------- | ---- | ------------- | ---- |
67| `example.com` | `A` | `12.34.56.78` | 600 |
68| `*.example.com` | `A` | `12.34.56.78` | 600 |
69
70**Note:**
71* Replace `example.com` with your domain name.
72* Replace `12.34.56.78` with your server's IP address.
73* Some providers may use the `@` symbol to represent the root of your domain.
74* The wildcard record is required when allowing users to create new accounts on your PDS.
75
76
77
78## Automatic install on Ubuntu 22.04 or Debian 11
79
80On your server via ssh, run the installer script:
81
82```bash
83wget https://raw.githubusercontent.com/bluesky-social/pds/main/installer.sh
84```
85
86```bash
87sudo bash installer.sh
88```
89
90## Installing manually on Ubuntu 22.04
91
92### Open ports on your Linux firewall
93
94If your server is running a Linux firewall managed with `ufw`, you will also need to open these same ports on the server itself.
95
96```bash
97$ sudo ufw allow 80/tcp
98$ sudo ufw allow 443/tcp
99```
100
101### Install Docker
102
103On your server, install Docker CE (Community Edition), using the the following instructions. For other operating systems you may reference the [official Docker install guides](https://docs.docker.com/engine/install/).
104
105**Note:** All of the following commands should be run on your server via ssh.
106
107#### Uninstall old versions
108
109```bash
110sudo apt-get remove docker docker-engine docker.io containerd runc
111```
112
113#### Set up the repository
114
115```bash
116sudo apt-get update
117sudo apt-get install \
118 ca-certificates \
119 curl \
120 gnupg
121```
122
123```bash
124sudo install -m 0755 -d /etc/apt/keyrings
125curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
126sudo chmod a+r /etc/apt/keyrings/docker.gpg
127```
128
129```bash
130echo \
131 "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
132 "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
133 sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
134```
135
136#### Install Docker Engine
137
138```bash
139sudo apt-get update
140```
141
142```bash
143sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
144```
145
146#### Verify Docker Engine installation
147
148```bash
149sudo docker run hello-world
150```
151
152### Set up the PDS directory
153
154```bash
155sudo mkdir /pds
156sudo mkdir --parents /pds/caddy/data
157sudo mkdir --parents /pds/caddy/etc/caddy
158```
159
160### Create the Caddyfile
161
162Be sure to replace `example.com` with your own domain.
163
164```bash
165cat <<CADDYFILE | sudo tee /pds/caddy/etc/caddy/Caddyfile
166{
167 email you@example.com
168}
169
170*.example.com, example.com {
171 tls {
172 on_demand
173 }
174 reverse_proxy http://localhost:3000
175}
176CADDYFILE
177```
178
179### Create the PDS env configuration file
180
181You should fill in the first 5 values, but leave the rest untouched unless you have good reason to change it.
182
183See the PDS environment variables section at the end of this README for explanations of each value
184
185Your PDS will need two secp256k1 private keys provided as hex strings. You can securely generate these keys using `openssl` with the following command:
186
187**Note:**
188* Replace `example.com` with your domain name.
189
190```bash
191PDS_HOSTNAME="example.com"
192PDS_JWT_SECRET="$(openssl rand --hex 16)"
193PDS_ADMIN_PASSWORD="$(openssl rand --hex 16)"
194PDS_REPO_SIGNING_KEY_K256_PRIVATE_KEY_HEX="$(openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32)"
195PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX="$(openssl ecparam --name secp256k1 --genkey --noout --outform DER | tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32)"
196
197cat <<PDS_CONFIG | sudo tee /pds/pds.env
198PDS_HOSTNAME=${PDS_HOSTNAME}
199PDS_JWT_SECRET=${PDS_JWT_SECRET}
200PDS_ADMIN_PASSWORD=${PDS_ADMIN_PASSWORD}
201PDS_REPO_SIGNING_KEY_K256_PRIVATE_KEY_HEX=${PDS_REPO_SIGNING_KEY_K256_PRIVATE_KEY_HEX}
202PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=${PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX}
203PDS_DB_SQLITE_LOCATION=/pds/pds.sqlite
204PDS_BLOBSTORE_DISK_LOCATION=/pds/blocks
205PDS_DID_PLC_URL=https://plc.bsky-sandbox.dev
206PDS_BSKY_APP_VIEW_ENDPOINT=https://api.bsky-sandbox.dev
207PDS_BSKY_APP_VIEW_DID=did:web:api.bsky-sandbox.dev
208PDS_CRAWLERS=https://bgs.bsky-sandbox.dev
209PDS_CONFIG
210```
211
212### Start the PDS containers
213
214#### Download the Docker compose file
215
216Download the `compose.yaml` to run your PDS, which includes the following containers:
217
218* `pds` Node PDS server running on http://localhost:3000
219* `caddy` HTTP reverse proxy handling TLS and proxying requests to the PDS server
220* `watchtower` Daemon responsible for auto-updating containers to keep the server secure and federating
221
222```bash
223curl https://raw.githubusercontent.com/bluesky-social/pds/main/compose.yaml | sudo tee /pds/compose.yaml
224```
225
226#### Create the systemd service
227
228```bash
229 cat <<SYSTEMD_UNIT_FILE >/etc/systemd/system/pds.service
230[Unit]
231Description=Bluesky PDS Service
232Documentation=https://github.com/bluesky-social/pds
233Requires=docker.service
234After=docker.service
235
236[Service]
237Type=oneshot
238RemainAfterExit=yes
239WorkingDirectory=/pds
240ExecStart=/usr/bin/docker compose --file /pds/compose.yaml up --detach
241ExecStop=/usr/bin/docker compose --file /pds/compose.yaml down
242
243[Install]
244WantedBy=default.target
245SYSTEMD_UNIT_FILE
246```
247
248#### Start the service
249
250```bash
251sudo systemctl daemon-reload
252```
253
254```bash
255sudo systemctl start pds
256```
257
258**Ensure that containers are running**
259
260There should be a caddy, pds, and watchtower container running.
261
262```bash
263sudo systemctl status pds
264```
265
266```bash
267sudo docker ps
268```
269
270### Verify your PDS is online
271
272You can check if your server is online and healthy by requesting the healthcheck endpoint.
273
274```bash
275curl https://example.com/xrpc/_health
276{"version":"0.2.2-beta.2"}
277```
278
279### Connecting to your server
280
281You can use the Bluesky app to connect to your server to create an account.
282
2831. Download the Bluesky app
2841. Enter the URL of your PDS (e.g. `https://example.com/`)
2851. Create an account
2861. Create a post
287
288## PDS environment variables
289
290You will need to customize various settings configured through the PDS environment variables. See the below table to find the variables you'll need to set.
291
292| Environment Variable | Value | Should update? | Notes |
293| ----------------------------------------- | --------------------------------------------- | -------------- |------ |
294| PDS_HOSTNAME | example.com | ✅ | Public domain you intend to deploy your service at |
295| PDS_JWT_SECRET | jwt-secret | ✅ | Use a secure high-entropy string that is 32 characters in length |
296| PDS_ADMIN_PASSWORD | admin-pass | ✅ | Use a secure high-entropy string that is 32 characters in length |
297| PDS_REPO_SIGNING_KEY_K256_PRIVATE_KEY_HEX | 3ee68... | ✅ | See above Generate Keys section - once set, do not change |
298| PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX | e049f... | ✅ | See above Generate Keys section - once set, do not change |
299| PDS_DB_SQLITE_LOCATION | /pds/pds.sqlite | ❌ | Or use `PDS_DB_POSTGRES_URL` depending on which database you intend to use |
300| PDS_BLOBSTORE_DISK_LOCATION | /pds/blocks | ❌ | Only update if you update the mounted volume for your docker image as well |
301| PDS_DID_PLC_URL | https://plc.bsky-sandbox.dev | ❌ | Do not adjust if you intend to federate with the Bluesky federation sandbox |
302| PDS_BSKY_APP_VIEW_URL | https://api.bsky-sandbox.dev | ❌ | Do not adjust if you intend to federate with the Bluesky federation sandbox |
303| PDS_BSKY_APP_VIEW_DID | did:web:api.bsky-sandbox.dev | ❌ | Do not adjust if you intend to federate with the Bluesky federation sandbox |
304| PDS_CRAWLERS | https://bgs.bsky-sandbox.dev | ❌ | Do not adjust if you intend to federate with the Bluesky federation sandbox |
305
306There are additional environment variables that can be tweaked depending on how you're running your service. For instance, storing blobs in AWS S3, keys in AWS KMS, or setting up an email service.
307
308Feel free to explore those [Here](https://github.com/bluesky-social/atproto/blob/simplify-pds/packages/pds/src/config/env.ts). However, we will not be providing support for more advanced configurations.