commit d7b2feb2d558a6cc0358d5f2c899a8f93e9f0373 Author: notplants <@notplants> Date: Thu Feb 19 11:50:14 2026 -0500 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..159881a --- /dev/null +++ b/README.md @@ -0,0 +1,107 @@ +# bluesky-pds + + + +* **Category**: Apps +* **Status**: 0 +* **Image**: ghcr.io/bluesky-social/pds +* **Healthcheck**: Yes +* **Backups**: No +* **Email**: No +* **Tests**: No +* **SSO**: No + + + +## About + +A [Bluesky PDS](https://github.com/bluesky-social/pds) (Personal Data Server) +is a self-hosted server for the AT Protocol, allowing you to own your social +data and federate with the Bluesky network. + +## Basic usage + +1. Set up Docker Swarm and [`abra`] +2. Deploy [`coop-cloud/traefik`] +3. `abra app new bluesky-pds` (do **not** use `--secrets` yet, see below) +4. `abra app config YOURAPPDOMAIN` - set `DOMAIN` to something that resolves to + your Docker swarm box +5. Generate the PLC rotation key and create secrets (see below) +6. `abra app deploy YOURAPPDOMAIN` +7. Verify the PDS is running: `curl https://YOURAPPDOMAIN/xrpc/_health` + +## Generating secrets + +The JWT secret and admin password can be generated automatically: + +```bash +abra app secret generate YOURAPPDOMAIN pds_jwt_secret v1 +abra app secret generate YOURAPPDOMAIN pds_admin_password v1 +``` + +The PLC rotation key is a secp256k1 private key and must be generated manually: + +```bash +openssl ecparam --name secp256k1 --genkey --noout --outform DER | \ + tail --bytes=+8 | head --bytes=32 | xxd --plain --cols 32 +``` + +Then store it as a secret: + +```bash +abra app secret insert YOURAPPDOMAIN pds_plc_rotation_key v1 +``` + +## Account management + +Create an account on your PDS: + +```bash +abra app run YOURAPPDOMAIN app -- \ + goat pds admin account create \ + --admin-password "$(abra app secret get YOURAPPDOMAIN pds_admin_password v1)" \ + --handle user.YOURAPPDOMAIN \ + --email user@example.com \ + --password yourpassword +``` + +Create an invite code: + +```bash +abra app run YOURAPPDOMAIN app -- \ + goat pds admin account create-invite \ + --admin-password "$(abra app secret get YOURAPPDOMAIN pds_admin_password v1)" +``` + +## Handle configuration + +User handles on a PDS can work in two ways: + +1. **Subdomain handles** (e.g. `user.pds.example.com`): Requires a wildcard DNS + record (`*.pds.example.com`) pointing to your server, and wildcard TLS + certificates (which require DNS challenge configuration in Traefik). + +2. **Domain handles** (e.g. `user.com`): Users can use their own domain as a + handle by adding a DNS TXT record at `_atproto.user.com` with the value + `did=did:plc:`. This works without any additional server + configuration. + +Domain handles are recommended for most deployments as they don't require +wildcard TLS configuration. + +## DNS setup + +At minimum, create an A record pointing your PDS domain to your server: + +``` +pds.example.com A +``` + +For subdomain handles, also add a wildcard record: + +``` +*.pds.example.com A +``` + +[`abra`]: https://git.coopcloud.tech/coop-cloud/abra +[`coop-cloud/traefik`]: https://git.coopcloud.tech/coop-cloud/traefik