# First Deployment This runbook creates the first production PDS deployment. It assumes the repository has already been cloned locally and that production secrets are stored outside Git. ## 1. Local Preflight From this repository: ```sh scripts/preflight.sh --local ``` Optional remote check: ```sh ssh -i @ 'bash -s' < scripts/preflight.sh ``` The remote preflight should warn about missing Docker before installation. Warnings are expected before provisioning. ## 2. Cloudflare DNS Create or confirm: ```text pds.3drx.top A proxied ``` Keep `_atproto.3drx.top` unset until the account DID is known. Ensure Cloudflare WebSockets are enabled for the zone. ## 3. Cloudflare Origin Certificate Create an Origin CA certificate for `pds.3drx.top`. Store the certificate and private key outside Git. Suggested VM paths: ```text /pds/certs/cloudflare-origin.pem /pds/certs/cloudflare-origin.key ``` Permissions: ```sh sudo chown root:root /pds/certs/cloudflare-origin.* sudo chmod 0644 /pds/certs/cloudflare-origin.pem sudo chmod 0600 /pds/certs/cloudflare-origin.key ``` Set Cloudflare SSL/TLS mode to Full (strict) after the origin certificate is installed. ## 4. VM Preparation SSH to the VM: ```sh ssh -i @ ``` Create `/pds` on the root disk: ```sh sudo mkdir -p /pds sudo chown root:root /pds sudo chmod 0755 /pds ``` Add swap because the VM has about 1 GB RAM: ```sh sudo fallocate -l 2G /swapfile sudo chmod 0600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab ``` Install Docker and the Docker Compose plugin using the official Docker Debian instructions. Do not commit package manager logs or generated configuration. ## 5. R2 Buckets and Credentials Create: - live blob bucket, for example `` - backup bucket or prefix, for example `` Create scoped credentials: - live blob credentials: read/write to the live blob bucket - backup credentials: read/write to the backup bucket or prefix Store real credentials only in ignored files on the VM or a password manager. Validate live blob credentials from a safe shell after exporting the real values from an ignored env file or password manager: ```sh scripts/verify-r2-blobstore.sh ``` ## 6. Install PDS Use the official PDS installer as the base deployment path. Deployment choices: - `PDS_HOSTNAME=pds.3drx.top` - invite required: enabled - public signup: disabled - initial account: one account only After installation, update `/pds/pds.env` using `config/pds.env.example` as the reference. Add the R2 live blobstore settings and keep real secrets out of Git. For this deployment, place the real shared R2 credential only in `/etc/pds-r2.env` and apply it with: ```sh sudo /usr/local/sbin/apply-r2-config.sh ``` ## 7. Configure Origin TLS in Caddy Use `config/caddy-origin-ca.Caddyfile.example` as a reference. Configure Caddy to serve `pds.3drx.top` with the Cloudflare Origin CA certificate and key. Restart PDS/Caddy according to the installed service layout. ## 8. Configure Handle Get the created account DID from installer output, `pdsadmin`, or another atproto tool. Add: ```text _atproto.3drx.top TXT did=did:plc: ``` Then change the account handle to `3drx.top` using the Bluesky app or an atproto CLI. ## 9. Install Backup Timer Copy templates and scripts to production paths: ```sh sudo install -m 0755 scripts/backup-pds.sh /usr/local/sbin/backup-pds.sh sudo install -m 0644 config/systemd/pds-backup.service.example /etc/systemd/system/pds-backup.service sudo install -m 0644 config/systemd/pds-backup.timer.example /etc/systemd/system/pds-backup.timer ``` Create an ignored env file on the VM, for example `/etc/pds-backup.env`, based on `config/pds-backup.env.example`. Enable the timer: ```sh sudo systemctl daemon-reload sudo systemctl enable --now pds-backup.timer ``` Run one manual backup: ```sh sudo systemctl start pds-backup.service sudo journalctl -u pds-backup.service -n 100 --no-pager ``` ## 10. Acceptance Checks ```sh scripts/healthcheck.sh ``` Verify: - `https://pds.3drx.top/xrpc/_health` returns JSON - WebSocket connection opens - image uploads land in R2 - account handle is `@3drx.top` - manual backup archive exists in R2