···12121313## What's different about Tranquil PDS
14141515-It is a superset of the reference PDS, including: passkeys and 2FA (WebAuthn/FIDO2, TOTP, backup codes, trusted devices), SSO login and signup, did:web support (PDS-hosted subdomains or bring-your-own), multi-channel communication (email, discord, telegram, signal) for verification and alerts, granular OAuth scopes with a consent UI showing human-readable descriptions, app passwords with granular permissions (read-only, post-only, or custom scopes), account delegation (letting others manage an account with configurable permission levels), automatic backups to s3-compatible object storage (configurable retention and frequency, one-click restore), and a built-in web UI for account management, OAuth consent, repo browsing, and admin.
1515+It is a superset of the reference PDS, including: passkeys and 2FA (WebAuthn/FIDO2, TOTP, backup codes, trusted devices), SSO login and signup, did:web support (PDS-hosted subdomains or bring-your-own), multi-channel communication (email, discord, telegram, signal) for verification and alerts, granular OAuth scopes with a consent UI showing human-readable descriptions, app passwords with granular permissions (read-only, post-only, or custom scopes), account delegation (letting others manage an account with configurable permission levels), automatic backups (configurable retention and frequency, one-click restore), and a built-in web UI for account management, OAuth consent, repo browsing, and admin.
16161717-The PDS itself is a single small binary with no node/npm runtime. It does require postgres, valkey, and s3-compatible storage, which makes setup heavier than the reference PDS's sqlite. The tradeoff is that these are battle-tested pieces of infra that we already know how to scale, back up, and monitor.
1717+The PDS itself is a single small binary with no node/npm runtime. It requires postgres and stores blobs on the local filesystem. Valkey is optional (enables distributed rate limiting for multi-node setups). The tradeoff vs the reference PDS's sqlite is that postgres is a battle-tested piece of infra that we already know how to scale, back up, and monitor.
18181919## Quick Start
2020
···7788## Prerequisites
991010-- A VPS with at least 2GB RAM and 20GB disk
1010+- A VPS with at least 2GB RAM
1111+- Disk space for blobs (depends on usage; plan for ~1GB per active user as a baseline)
1112- A domain name pointing to your server's IP
1213- A **wildcard TLS certificate** for `*.pds.example.com` (user handles are served as subdomains)
1314- Root or sudo access
···42434344## Standalone Containers (No Compose)
44454545-If you already have postgres, valkey, and minio running on the host (eg., from the [Debian install guide](install-debian.md)), you can run just the app containers.
4646+If you already have postgres and valkey running on the host (eg., from the [Debian install guide](install-debian.md)), you can run just the app containers.
46474748Build the images:
4849```sh
···5051podman build -t tranquil-pds-frontend:latest ./frontend
5152```
52535353-Run the backend with host networking (so it can access postgres/valkey/minio on localhost):
5454+Run the backend with host networking (so it can access postgres/valkey on localhost) and mount the blob storage:
5455```sh
5556podman run -d --name tranquil-pds \
5657 --network=host \
5758 --env-file /etc/tranquil-pds/tranquil-pds.env \
5959+ -v /var/lib/tranquil:/var/lib/tranquil:Z \
5860 tranquil-pds:latest
5961```
6062···104106105107```bash
106108mkdir -p /etc/containers/systemd
107107-mkdir -p /srv/tranquil-pds/{postgres,minio,valkey,certs,acme,config}
109109+mkdir -p /srv/tranquil-pds/{postgres,valkey,blobs,backups,certs,acme,config}
108110```
109111110112## Create Environment File
···152154```bash
153155source /srv/tranquil-pds/config/tranquil-pds.env
154156echo "$DB_PASSWORD" | podman secret create tranquil-pds-db-password -
155155-echo "$MINIO_ROOT_PASSWORD" | podman secret create tranquil-pds-minio-password -
156157```
157158158159## Start Services and Initialize
159160160161```bash
161162systemctl daemon-reload
162162-systemctl start tranquil-pds-db tranquil-pds-minio tranquil-pds-valkey
163163+systemctl start tranquil-pds-db tranquil-pds-valkey
163164sleep 10
164165```
165166166166-Create the minio buckets:
167167-```bash
168168-podman run --rm --pod tranquil-pds \
169169- -e MINIO_ROOT_USER=minioadmin \
170170- -e MINIO_ROOT_PASSWORD=your-minio-password \
171171- cgr.dev/chainguard/minio-client:latest-dev \
172172- sh -c "mc alias set local http://localhost:9000 \$MINIO_ROOT_USER \$MINIO_ROOT_PASSWORD && mc mb --ignore-existing local/pds-blobs && mc mb --ignore-existing local/pds-backups"
173173-```
174174-175167Run migrations:
176168```bash
177169cargo install sqlx-cli --no-default-features --features postgres
···215207## Enable All Services
216208217209```bash
218218-systemctl enable tranquil-pds-db tranquil-pds-minio tranquil-pds-valkey tranquil-pds-app tranquil-pds-frontend tranquil-pds-nginx
210210+systemctl enable tranquil-pds-db tranquil-pds-valkey tranquil-pds-app tranquil-pds-frontend tranquil-pds-nginx
219211```
220212221213## Configure Firewall
···260252261253```sh
262254mkdir -p /srv/tranquil-pds/{data,config}
263263-mkdir -p /srv/tranquil-pds/data/{postgres,minio,valkey,certs,acme}
255255+mkdir -p /srv/tranquil-pds/data/{postgres,valkey,blobs,backups,certs,acme}
264256```
265257266258## Clone Repository and Build Images
···342334sleep 15
343335```
344336345345-Create the minio buckets:
346346-```sh
347347-source /srv/tranquil-pds/config/tranquil-pds.env
348348-podman run --rm --network tranquil-pds_default \
349349- -e MINIO_ROOT_USER="$MINIO_ROOT_USER" \
350350- -e MINIO_ROOT_PASSWORD="$MINIO_ROOT_PASSWORD" \
351351- cgr.dev/chainguard/minio-client:latest-dev \
352352- sh -c 'mc alias set local http://minio:9000 $MINIO_ROOT_USER $MINIO_ROOT_PASSWORD && mc mb --ignore-existing local/pds-blobs && mc mb --ignore-existing local/pds-backups'
353353-```
354354-355337Run migrations:
356338```sh
357339apk add rustup
+11-41
docs/install-debian.md
···4455## Prerequisites
6677-- A VPS with at least 2GB RAM and 20GB disk
77+- A VPS with at least 2GB RAM
88+- Disk space for blobs (depends on usage; plan for ~1GB per active user as a baseline)
89- A domain name pointing to your server's IP
910- A wildcard TLS certificate for `*.pds.example.com` (user handles are served as subdomains)
1011- Root or sudo access
···3738sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE pds TO tranquil_pds;"
3839```
39404040-## Install minio
4141+## Create Blob Storage Directories
41424243```bash
4343-curl -O https://dl.min.io/server/minio/release/linux-amd64/minio
4444-chmod +x minio
4545-mv minio /usr/local/bin/
4646-mkdir -p /var/lib/minio/data
4747-useradd -r -s /sbin/nologin minio-user
4848-chown -R minio-user:minio-user /var/lib/minio
4949-cat > /etc/default/minio << 'EOF'
5050-MINIO_ROOT_USER=minioadmin
5151-MINIO_ROOT_PASSWORD=your-minio-password
5252-MINIO_VOLUMES="/var/lib/minio/data"
5353-MINIO_OPTS="--console-address :9001"
5454-EOF
5555-cat > /etc/systemd/system/minio.service << 'EOF'
5656-[Unit]
5757-Description=MinIO Object Storage
5858-After=network.target
5959-[Service]
6060-User=minio-user
6161-Group=minio-user
6262-EnvironmentFile=/etc/default/minio
6363-ExecStart=/usr/local/bin/minio server $MINIO_VOLUMES $MINIO_OPTS
6464-Restart=always
6565-LimitNOFILE=65536
6666-[Install]
6767-WantedBy=multi-user.target
6868-EOF
6969-systemctl daemon-reload
7070-systemctl enable minio
7171-systemctl start minio
4444+mkdir -p /var/lib/tranquil/blobs /var/lib/tranquil/backups
7245```
73467474-Create the buckets (wait a few seconds for minio to start):
7575-```bash
7676-curl -O https://dl.min.io/client/mc/release/linux-amd64/mc
7777-chmod +x mc
7878-mv mc /usr/local/bin/
7979-mc alias set local http://localhost:9000 minioadmin your-minio-password
8080-mc mb local/pds-blobs
8181-mc mb local/pds-backups
8282-```
4747+We'll set ownership after creating the service user.
83488449## Install valkey
8550···142107143108```bash
144109useradd -r -s /sbin/nologin tranquil-pds
110110+chown -R tranquil-pds:tranquil-pds /var/lib/tranquil
145111cp /opt/tranquil-pds/target/release/tranquil-pds /usr/local/bin/
146112147113cat > /etc/systemd/system/tranquil-pds.service << 'EOF'
148114[Unit]
149115Description=Tranquil PDS - AT Protocol PDS
150150-After=network.target postgresql.service minio.service
116116+After=network.target postgresql.service
151117[Service]
152118Type=simple
153119User=tranquil-pds
···156122ExecStart=/usr/local/bin/tranquil-pds
157123Restart=always
158124RestartSec=5
125125+ProtectSystem=strict
126126+ProtectHome=true
127127+PrivateTmp=true
128128+ReadWritePaths=/var/lib/tranquil
159129[Install]
160130WantedBy=multi-user.target
161131EOF
+3-3
docs/install-kubernetes.md
···4455- cloudnativepg (or your preferred postgres operator)
66- valkey
77-- s3-compatible object storage (minio operator, or just use a managed service)
77+- a PersistentVolume for blob storage
88- the app itself (it's just a container with some env vars)
991010You'll need a wildcard TLS certificate for `*.your-pds-hostname.example.com`. User handles are served as subdomains.
11111212The container image expects:
1313- `DATABASE_URL` - postgres connection string
1414-- `S3_ENDPOINT`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `S3_BUCKET`
1515-- `BACKUP_S3_BUCKET` - bucket for repo backups (optional but recommended)
1414+- `BLOB_STORAGE_PATH` - path to blob storage (mount a PV here)
1515+- `BACKUP_STORAGE_PATH` - path for repo backups (optional but recommended)
1616- `VALKEY_URL` - redis:// connection string
1717- `PDS_HOSTNAME` - your PDS hostname (without protocol)
1818- `JWT_SECRET`, `DPOP_SECRET`, `MASTER_KEY` - generate with `openssl rand -base64 48`