Fork of official Bluesky PDS (Personal Data Server).
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 hosting a Bluesky PDS.
4
5Head over to the [ATProto Touchers Discord](https://discord.atprotocol.dev/) to chat with other folks hosting instances and get important updates about the PDS distribution!
6
7## Table of Contents
8
9<!-- markdown-toc -i README.md -->
10
11<!-- toc -->
12
13- [PDS](#pds)
14 - [Table of Contents](#table-of-contents)
15 - [FAQ](#faq)
16 - [What is Bluesky?](#what-is-bluesky)
17 - [What is AT Protocol?](#what-is-at-protocol)
18 - [Where is the code?](#where-is-the-code)
19 - [What is the current status of federation?](#what-is-the-current-status-of-federation)
20 - [Self-hosting a PDS](#self-hosting-a-pds)
21 - [Deploying a PDS onto a VPS](#deploying-a-pds-onto-a-vps)
22 - [Open your cloud firewall for HTTP and HTTPS](#open-your-cloud-firewall-for-http-and-https)
23 - [Configure DNS for your domain](#configure-dns-for-your-domain)
24 - [Check that DNS is working as expected](#check-that-dns-is-working-as-expected)
25 - [Installing on Ubuntu 20.04/22.04/24.04 and Debian 11/12/13](#installing-on-ubuntu-200422042404-and-debian-111213)
26 - [Verifying that your PDS is online and accessible](#verifying-that-your-pds-is-online-and-accessible)
27 - [Creating an account using pdsadmin](#creating-an-account-using-pdsadmin)
28 - [Creating an account using an invite code](#creating-an-account-using-an-invite-code)
29 - [Using the Bluesky app with your PDS](#using-the-bluesky-app-with-your-pds)
30 - [Setting up SMTP](#setting-up-smtp)
31 - [Common SMTP issues](#common-smtp-issues)
32 - [Logging](#logging)
33 - [Updating your PDS](#updating-your-pds)
34 - [goat CLI](#goat-cli)
35 - [Environment Variables](#environment-variables)
36 - [License](#license)
37
38<!-- tocstop -->
39
40## FAQ
41
42### What is Bluesky?
43
44Bluesky is a social media application built on AT Protocol.
45
46Please visit the [Bluesky website](https://bsky.social/) for more information.
47
48### What is AT Protocol?
49
50The Authenticated Transfer Protocol, aka atproto, is a protocol for large-scale distributed social applications.
51
52Please visit the [AT Protocol docs](https://atproto.com/guides/overview) for additional information.
53
54### Where is the code?
55
56* [TypeScript code](https://github.com/bluesky-social/atproto/tree/main/packages/pds)
57* [Go code](https://github.com/bluesky-social/indigo)
58
59### What is the current status of federation?
60
61The AT Protocol network is open to federation!
62
63✅ Federated domain handles (e.g. `@nytimes.com`)
64
65✅ Federated feed generators (custom algorithms)
66
67✅ Federated relays (event firehose)
68
69✅ Federated app views (API service)
70
71✅ Federated data (PDS hosting)
72
73✅ Federated moderation (labeling)
74
75## Self-hosting a PDS
76
77Self-hosting a Bluesky PDS means running your own Personal Data Server that is capable of federating with the wider Bluesky social network.
78
79### Deploying a PDS onto a VPS
80
81This README provides instructions for deploying a PDS using our install script onto a Virtual Private Server. [Digital Ocean](https://digitalocean.com/) and [Vultr](https://vultr.com/) are two popular choices for VPS hosting.
82
83Ensure that you can ssh to your server and have root access.
84
85**Server Requirements**
86* Public IPv4 address
87* Public DNS name
88* Public inbound internet access permitted on port 80/tcp and 443/tcp
89
90**Server Recommendations**
91| | |
92| ---------------- | ------------ |
93| Operating System | Ubuntu 24.04 |
94| Memory (RAM) | 1 GB |
95| CPU Cores | 1 |
96| Storage | 20 GB SSD |
97| Architectures | amd64, arm64 |
98| Number of users | 1-20 |
99
100**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/).
101
102### Open your cloud firewall for HTTP and HTTPS
103
104One of the most common sources of misconfiguration is not opening firewall ports correctly. Please be sure to double check this step.
105
106In your cloud provider's console, the following ports should be open to inbound access from the public internet.
107
108* 80/tcp (Used only for TLS certification verification)
109* 443/tcp (Used for all application requests)
110
111**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.
112
113### Configure DNS for your domain
114
115From your DNS provider's control panel, set up a domain with records pointing to your server.
116
117| Name | Type | Value | TTL |
118| --------------- | ---- | ------------- | --- |
119| `example.com` | `A` | `12.34.56.78` | 600 |
120| `*.example.com` | `A` | `12.34.56.78` | 600 |
121
122**Note:**
123* Replace `example.com` with your domain name.
124* Replace `12.34.56.78` with your server's IP address.
125* Some providers may use the `@` symbol to represent the root of your domain.
126* The wildcard record is required when allowing users to create new accounts on your PDS.
127* The TTL can be anything but 600 (10 minutes) is reasonable
128
129### Check that DNS is working as expected
130
131Use a service like [DNS Checker](https://dnschecker.org/) to verify that you can resolve domain names.
132
133Examples to check (record type `A`):
134* `example.com`
135* `random.example.com`
136* `test123.example.com`
137
138These should all return your server's public IP.
139
140### Installing on Ubuntu 20.04/22.04/24.04 and Debian 11/12/13
141
142Note that this script assumes a relatively "fresh" VPS that is not also concurrently hosting a web server or anything else on port 80/443. If you intend to run a PDS alongside an existing webserver on the same VPS, you will not want to use this install script.
143
144On your server, download the install script using `curl`:
145
146```bash
147curl https://raw.githubusercontent.com/bluesky-social/pds/main/installer.sh > installer.sh
148```
149
150And then run the installer using `bash`. You will need `sudo` permissions to continue:
151
152```bash
153sudo bash installer.sh
154```
155
156The install script is interactive and will prompt for input during the install process. You will need to provide your public DNS address, an admin email address (which does not need to be from the same domain), and be prompted to create a PDS user account with its own email address and handle. If you plan to reuse an existing AT handle, you can skip user account creation, though if it is your first time deploying a PDS you may want to create an account using your domain like `account.your-domain.net` for testing purposes.
157
158Upon completion of a successful installation, you'll receive output similar to the following:
159
160```
161========================================================================
162PDS installation successful!
163------------------------------------------------------------------------
164
165Check service status : sudo systemctl status pds
166Watch service logs : sudo docker logs -f pds
167Backup service data : /pds
168PDS Admin command : pdsadmin
169
170Required Firewall Ports
171------------------------------------------------------------------------
172Service Direction Port Protocol Source
173------- --------- ---- -------- ----------------------
174HTTP TLS verification Inbound 80 TCP Any
175HTTP Control Panel Inbound 443 TCP Any
176
177Required DNS entries
178------------------------------------------------------------------------
179Name Type Value
180------- --------- ---------------
181your-domain.net A your-ip-address
182*.your-domain.net A your-ip-address
183
184Detected public IP of this server: your-ip-address
185
186To see pdsadmin commands, run "pdsadmin help"
187
188========================================================================
189```
190
191And, following account creation:
192
193```
194Account created successfully!
195-----------------------------
196Handle : handle.your-domain.net
197DID : did:plc:your-did
198Password : your-password
199-----------------------------
200Save this password, it will not be displayed again.
201```
202
203### Verifying that your PDS is online and accessible
204
205> [!TIP]
206> The most common problems with getting PDS content consumed in the live network usually result from users trying to port the provided Caddy configuration to Nginx, Apache, or other reverse proxies. Getting TLS certificates, WebSockets, and virtual server names provisioned can be challenging. We are not currently providing tech support for other configurations.
207
208After installation, your PDS should be live and accessible on the web. You can check if your server is online and healthy by making a request to `https://your-domain.net/xrpc/_health` (the healthcheck endpoint). You should see a JSON response with a version, like:
209
210Visit `https://your-domain.net/xrpc/_health` in your browser. You should see a JSON response with a version, like:
211
212```
213{"version":"0.2.2-beta.2"}
214```
215
216You'll also need to check that WebSockets are working, for the rest of the network to pick up content from your PDS. You can test by installing a tool like `wsdump` and running a command like:
217
218```bash
219wsdump "wss://example.com/xrpc/com.atproto.sync.subscribeRepos?cursor=0"
220```
221
222Note that there will be no events output on the WebSocket until they are created in the PDS, so the above command may continue to run with no output immediately post-installation.
223
224### Creating an account using pdsadmin
225
226You'll now have access to some additional command line tools on this server. Use `pdsadmin` to create an account if you haven't already:
227
228```bash
229sudo pdsadmin account create
230```
231
232### Creating an account using an invite code
233
234If needed, use `pdsadmin` to create an invite code:
235
236```bash
237sudo pdsadmin create-invite-code
238```
239
240When creating an account using the app, enter this invite code.
241
242### Using the Bluesky app with your PDS
243
244You can use the Bluesky app to connect to your PDS.
245
2461. Get the Bluesky app
247 * [Bluesky for Web](https://bsky.app/)
248 * [Bluesky for iPhone](https://apps.apple.com/us/app/bluesky-social/id6444370199)
249 * [Bluesky for Android](https://play.google.com/store/apps/details?id=xyz.blueskyweb.app)
2501. Enter the URL of your PDS (e.g. `https://example.com/`)
251
252_Note: because the subdomain TLS certificate is created on-demand, it may take 10-30s for your handle to be accessible. If you aren't seeing your first post/profile, wait 30s and try to make another post._
253
254### Setting up SMTP
255
256To be able to verify users' email addresses and send other emails, you need to set up an SMTP server.
257
258As an alternative to running your own SMTP server, you can use an email service. [Resend](https://resend.com/) and [SendGrid](https://sendgrid.com/) are two popular choices.
259
260Create an account and API key on an email service, ensure your server allows access on the required ports, and then you can add these configuration variables to `/pds/pds.env` on your server (example with Resend):
261
262```
263PDS_EMAIL_SMTP_URL=smtps://resend:<your api key here>@smtp.resend.com:465/
264PDS_EMAIL_FROM_ADDRESS=admin@your.domain
265```
266
267If you prefer to use a standard SMTP server (a local one or from your email provider), put your account's username and password in the URL:
268
269```
270PDS_EMAIL_SMTP_URL=smtps://username:password@smtp.example.com/
271```
272
273Alternatively, if you're running a local sendmail-compatible mail service like Postfix or Exim on the same host, you can configure the PDS to use the sendmail transport by using such URL:
274
275```
276PDS_EMAIL_SMTP_URL=smtp:///?sendmail=true
277```
278
279_Note: Your PDS will need to be restarted with those variables. This varies depending on your setup. If you followed this installation guide, run `systemctl restart pds`. You might need to restart the server or recreate the container, depending on what you are using._
280
281#### Common SMTP issues
282
283If you find that your test messages using cURL or other sources go out correctly, but you are not receiving emails from your PDS, you may need to URL encode your username and password on `/pds/pds.env` and restart the PDS service.
284
285If the username and/or password contain special characters, the special characters will need to be [percent encoded](https://en.wikipedia.org/wiki/Percent-encoding). For some email services, the username will contain an extra `@` symbol that will also need to be percent encoded. For example, the URL `user&name@oci:p@ssword@smtphost:465` after percent encoding for the username and password fields would become `user%26name%40oci:p%40ssword@smtphost:465`.
286
287If you are migrating an account, Bluesky's UI will ask you to confirm your email address. The confirmation code email is meant to come from your PDS. If you are encountering issues with SMTP and want to confirm the address before solving it, you can find the confirmation code on the `email_token` table on `accounts.sqlite`.
288
289### Logging
290
291By default, logs from the PDS are printed to `stdout` and end up in Docker's log. You can browse them by running:
292
293```
294[sudo] docker logs pds
295```
296
297Note: these logs are not persisted, so they will be lost after server reboot.
298
299Alternatively, you can configure the logs to be printed to a file by setting `LOG_DESTINATION`:
300
301```
302LOG_DESTINATION=/pds/pds.log
303```
304
305You can also change the minimum level of logs to be printed (default: `info`):
306
307```
308LOG_LEVEL=debug
309```
310
311### Updating your PDS
312
313It is recommended that you keep your PDS up to date with new versions. You can use the `pdsadmin` tool to update your PDS.
314
315```bash
316sudo pdsadmin update
317```
318
319### goat CLI
320
321The PDS image includes [goat](https://github.com/bluesky-social/goat), our command line tool for performing admin functions. `goat` is more portable than the `pdsadmin` scripts and can be used locally or within the container installed by this script.
322
323### Environment Variables
324
325| Environment Variable | Default |
326| ------------------------------------------- | ---------------------------------- |
327| `PDS_HOSTNAME` | None |
328| `PDS_JWT_SECRET` | None |
329| `PDS_ADMIN_PASSWORD` | None |
330| `PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX` | None |
331| `PDS_DATA_DIRECTORY` | `/pds` |
332| `PDS_BLOBSTORE_DISK_LOCATION` | `/pds/blocks` |
333| `PDS_BLOB_UPLOAD_LIMIT` | `5242880` (5MB) |
334| `PDS_DID_PLC_URL` | `https://plc.directory` |
335| `PDS_BSKY_APP_VIEW_URL` | `https://api.bsky.app` |
336| `PDS_BSKY_APP_VIEW_DID` | `did:web:api.bsky.app` |
337| `PDS_REPORT_SERVICE_URL` | `https://mod.bsky.app` |
338| `PDS_REPORT_SERVICE_DID` | `did:plc:ar7c4by46qjdydhdevvrndac` |
339| `PDS_CRAWLERS` | `https://bsky.network` |
340| `LOG_ENABLED` | `true` |
341| `PDS_EMAIL_SMTP_URL` | None |
342| `PDS_EMAIL_FROM_ADDRESS` | None |
343| `PDS_PRIVACY_POLICY_URL` | None |
344| `PDS_RATE_LIMITS_ENABLED` | `true` |
345
346
347## License
348
349This project is dual-licensed under MIT and Apache 2.0 terms:
350
351- MIT license ([LICENSE-MIT.txt](https://github.com/bluesky-social/pds/blob/main/LICENSE-MIT.txt) or http://opensource.org/licenses/MIT)
352- Apache License, Version 2.0, ([LICENSE-APACHE.txt](https://github.com/bluesky-social/pds/blob/main/LICENSE-APACHE.txt) or http://www.apache.org/licenses/LICENSE-2.0)
353
354Downstream projects and end users may choose either license individually, or both together, at their discretion. The motivation for this dual-licensing is the additional software patent assurance provided by Apache 2.0.