+9
-13
README.md
+9
-13
README.md
···
6
6
7
7
This particular PDS thrives under harsh conditions. It is a dandelion growing through the cracks in the sidewalk concrete.
8
8
9
-
It has full compatibility with Bluesky's reference PDS: same endpoints, same behavior, same client compatibility. Everything works: repo operations, blob storage, firehose, OAuth, handle resolution, account migration, the lot.
10
-
11
-
Another excellent PDS is [Cocoon](https://tangled.org/hailey.at/cocoon), written in go.
9
+
It has full compatibility with Bluesky's reference PDS.
12
10
13
11
## What's different about Tranquil PDS
14
12
15
-
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.
13
+
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), and a built-in web UI for account management, repo browsing, and admin.
16
14
17
-
The PDS itself is a single small binary with no node/npm runtime. It requires postgres. Blobs are stored on the local filesystem by default (S3 optional). Valkey is optional (supported as an alternative to the built-in cache).
15
+
The PDS itself is a single binary with no nodeJS runtime. However, at time of writing, Tranquil requires postgres running separately. Blobs are stored on the local filesystem by default (S3 optional). Valkey is also optional (as an alternative to the built-in cache).
18
16
19
17
## Quick Start
20
18
21
19
```bash
22
20
cp .env.example .env
23
-
podman compose up -d
21
+
podman compose up db -d
24
22
just run
25
23
```
26
24
···
41
39
42
40
### Quick Deploy (Docker/Podman Compose)
43
41
44
-
Edit `.env.prod` with your values. Generate secrets with `openssl rand -base64 48`.
42
+
Edit `.env` with your values. Generate secrets with `openssl rand -base64 48`.
45
43
46
44
```bash
47
-
cp .env.prod.example .env.prod
45
+
cp .env.example .env
48
46
podman-compose -f docker-compose.prod.yaml up -d
49
47
```
50
48
51
49
### Installation Guides
52
50
53
-
| Guide | Best For |
54
-
|-------|----------|
55
-
| [Debian](docs/install-debian.md) | Debian 13+ with systemd |
56
-
| [Containers](docs/install-containers.md) | Podman with quadlets or OpenRC |
57
-
| [Kubernetes](docs/install-kubernetes.md) | You know what you're doing |
51
+
- [Debian](docs/install-debian.md)
52
+
- [Containers](docs/install-containers.md)
53
+
- [Kubernetes](docs/install-kubernetes.md)
58
54
59
55
## Maintainers to ping
60
56
+42
-48
docs/install-containers.md
+42
-48
docs/install-containers.md
···
1
-
# Tranquil PDS Containerized Production Deployment
1
+
# Tranquil PDS containerized production deployment
2
2
3
3
This guide covers deploying Tranquil PDS using containers with podman.
4
4
···
7
7
8
8
## Prerequisites
9
9
10
-
- A VPS with at least 2GB RAM
10
+
- A server :p
11
11
- Disk space for blobs (depends on usage; plan for ~1GB per active user as a baseline)
12
12
- A domain name pointing to your server's IP
13
13
- A **wildcard TLS certificate** for `*.pds.example.com` (user handles are served as subdomains)
14
-
- Root or sudo access
14
+
- Root/sudo/doas access
15
15
16
-
## Quick Start (Docker/Podman Compose)
16
+
## Quickstart (docker/podman compose)
17
17
18
18
If you just want to get running quickly:
19
19
···
39
39
podman-compose -f docker-compose.prod.yaml restart nginx
40
40
```
41
41
42
+
The end!!!
43
+
44
+
Or wait, you want more? Perhaps a deployment that comes back on server restart?
45
+
42
46
For production setups with proper service management, continue to either the Debian or Alpine section below.
43
47
44
-
## Standalone Containers (No Compose)
48
+
## Standalone containers (no compose)
45
49
46
50
If you already have postgres running on the host (eg. from the [Debian install guide](install-debian.md)), you can run just the app containers.
47
51
···
91
95
92
96
---
93
97
94
-
# Debian 13+ with Systemd Quadlets
98
+
# Debian with systemd quadlets
95
99
96
-
Quadlets are the modern way to run podman containers under systemd.
100
+
Quadlets are a nice way to run podman containers under systemd.
97
101
98
-
## Install Podman
102
+
## Install podman
99
103
100
104
```bash
101
105
apt update
102
106
apt install -y podman
103
107
```
104
108
105
-
## Create Directory Structure
109
+
## Create the directory structure
106
110
107
111
```bash
108
112
mkdir -p /etc/containers/systemd
109
113
mkdir -p /srv/tranquil-pds/{postgres,blobs,backups,certs,acme,config}
110
114
```
111
115
112
-
## Create Environment File
116
+
## Create an environment file
113
117
114
118
```bash
115
119
cp /opt/tranquil-pds/.env.example /srv/tranquil-pds/config/tranquil-pds.env
···
121
125
openssl rand -base64 48
122
126
```
123
127
124
-
For quadlets, also add `DATABASE_URL` with the full connection string (systemd doesn't support variable expansion).
125
-
126
-
## Install Quadlet Definitions
128
+
## Install quadlet definitions
127
129
128
130
Copy the quadlet files from the repository:
129
131
```bash
···
136
138
137
139
Optional quadlets for valkey and minio are also available in `deploy/quadlets/` if you need them.
138
140
139
-
Note: Systemd doesn't support shell-style variable expansion in `Environment=` lines. The quadlet files expect DATABASE_URL to be set in the environment file.
140
-
141
-
## Create nginx Configuration
141
+
## Create nginx configuration
142
142
143
143
```bash
144
144
cp /opt/tranquil-pds/nginx.frontend.conf /srv/tranquil-pds/config/nginx.conf
145
145
```
146
146
147
-
## Clone and Build Images
147
+
## Clone and build images
148
148
149
149
```bash
150
150
cd /opt
···
154
154
podman build -t tranquil-pds-frontend:latest ./frontend
155
155
```
156
156
157
-
## Create Podman Secrets
157
+
## Create podman secrets
158
158
159
159
```bash
160
160
source /srv/tranquil-pds/config/tranquil-pds.env
161
161
echo "$DB_PASSWORD" | podman secret create tranquil-pds-db-password -
162
162
```
163
163
164
-
## Start Services and Initialize
164
+
## Start services and initialize
165
165
166
166
```bash
167
167
systemctl daemon-reload
···
169
169
sleep 10
170
170
```
171
171
172
-
Run migrations:
173
-
```bash
174
-
cargo install sqlx-cli --no-default-features --features postgres
175
-
DATABASE_URL="postgres://tranquil_pds:your-db-password@localhost:5432/pds" sqlx migrate run --source /opt/tranquil-pds/migrations
176
-
```
177
-
178
-
## Obtain Wildcard SSL Certificate
172
+
## Obtain a wildcard SSL cert
179
173
180
174
User handles are served as subdomains (eg. `alice.pds.example.com`), so you need a wildcard certificate. Wildcard certs require DNS-01 validation.
181
175
···
209
203
systemctl restart tranquil-pds-nginx
210
204
```
211
205
212
-
## Enable All Services
206
+
## Enable all services
213
207
214
208
```bash
215
209
systemctl enable tranquil-pds-db tranquil-pds-app tranquil-pds-frontend tranquil-pds-nginx
216
210
```
217
211
218
-
## Configure Firewall
212
+
## Configure firewall if you're into that sort of thing
219
213
220
214
```bash
221
215
apt install -y ufw
···
225
219
ufw enable
226
220
```
227
221
228
-
## Certificate Renewal
222
+
## Cert renewal
229
223
230
224
Add to root's crontab (`crontab -e`):
231
225
```
···
234
228
235
229
---
236
230
237
-
# Alpine 3.23+ with OpenRC
231
+
# Alpine with OpenRC
238
232
239
-
Alpine uses OpenRC, not systemd. We'll use podman-compose with an OpenRC service wrapper.
233
+
Alpine uses OpenRC, not systemd. So instead of quadlets we'll use podman-compose with an OpenRC service wrapper.
240
234
241
-
## Install Podman
235
+
## Install podman
242
236
243
237
```sh
244
238
apk update
···
253
247
rc-service podman start
254
248
```
255
249
256
-
## Create Directory Structure
250
+
## Create the directory structure
257
251
258
252
```sh
259
253
mkdir -p /srv/tranquil-pds/{data,config}
260
254
mkdir -p /srv/tranquil-pds/data/{postgres,blobs,backups,certs,acme}
261
255
```
262
256
263
-
## Clone Repository and Build Images
257
+
## Clone the repo and build images
264
258
265
259
```sh
266
260
cd /opt
···
270
264
podman build -t tranquil-pds-frontend:latest ./frontend
271
265
```
272
266
273
-
## Create Environment File
267
+
## Create an environment file
274
268
275
269
```sh
276
270
cp /opt/tranquil-pds/.env.example /srv/tranquil-pds/config/tranquil-pds.env
···
282
276
openssl rand -base64 48
283
277
```
284
278
285
-
## Set Up Compose and nginx
279
+
## Set up compose and nginx
286
280
287
281
Copy the production compose and nginx configs:
288
282
```sh
···
297
291
Edit `/srv/tranquil-pds/config/nginx.conf` to update cert paths:
298
292
- Change `/etc/nginx/certs/live/${PDS_HOSTNAME}/` to `/etc/nginx/certs/`
299
293
300
-
## Create OpenRC Service
294
+
## Create OpenRC service
301
295
302
296
```sh
303
297
cat > /etc/init.d/tranquil-pds << 'EOF'
304
298
#!/sbin/openrc-run
305
299
name="tranquil-pds"
306
-
description="Tranquil PDS AT Protocol PDS (containerized)"
300
+
description="Tranquil PDS AT Protocol PDS"
307
301
command="/usr/bin/podman-compose"
308
302
command_args="-f /srv/tranquil-pds/docker-compose.yml up"
309
303
command_background=true
···
331
325
chmod +x /etc/init.d/tranquil-pds
332
326
```
333
327
334
-
## Initialize Services
328
+
## Initialize services
335
329
336
330
Start services:
337
331
```sh
···
349
343
DATABASE_URL="postgres://tranquil_pds:$DB_PASSWORD@$DB_IP:5432/pds" sqlx migrate run --source /opt/tranquil-pds/migrations
350
344
```
351
345
352
-
## Obtain Wildcard SSL Certificate
346
+
## Obtain wildcard SSL cert
353
347
354
348
User handles are served as subdomains (eg. `alice.pds.example.com`), so you need a wildcard certificate. Wildcard certs require DNS-01 validation.
355
349
···
381
375
rc-service tranquil-pds restart
382
376
```
383
377
384
-
## Enable Service at Boot
378
+
## Enable service at boot time
385
379
386
380
```sh
387
381
rc-update add tranquil-pds
388
382
```
389
383
390
-
## Configure Firewall
384
+
## Configure firewall if you're into that sort of thing
391
385
392
386
```sh
393
387
apk add iptables ip6tables
···
409
403
/etc/init.d/ip6tables save
410
404
```
411
405
412
-
## Certificate Renewal
406
+
## Cert renewal
413
407
414
408
Add to root's crontab (`crontab -e`):
415
409
```
···
418
412
419
413
---
420
414
421
-
# Verification and Maintenance
415
+
# Verification and maintenance
422
416
423
-
## Verify Installation
417
+
## Verify installation
424
418
425
419
```sh
426
420
curl -s https://pds.example.com/xrpc/_health | jq
427
421
curl -s https://pds.example.com/.well-known/atproto-did
428
422
```
429
423
430
-
## View Logs
424
+
## View logs
431
425
432
426
**Debian:**
433
427
```bash
···
462
456
rc-service tranquil-pds restart
463
457
```
464
458
465
-
## Backup Database
459
+
## Backup database
466
460
467
461
**Debian:**
468
462
```bash
···
474
468
podman exec tranquil-pds-db-1 pg_dump -U tranquil_pds pds > /var/backups/pds-$(date +%Y%m%d).sql
475
469
```
476
470
477
-
## Custom Homepage
471
+
## Custom homepage
478
472
479
473
The frontend container serves `homepage.html` as the landing page. To customize it, either:
480
474
+21
-25
docs/install-debian.md
+21
-25
docs/install-debian.md
···
1
-
# Tranquil PDS Production Installation on Debian
1
+
# Tranquil PDS production installation on debian
2
2
3
-
This guide covers installing Tranquil PDS on Debian 13.
3
+
This guide covers installing Tranquil PDS on Debian.
4
+
5
+
It is a "compile the thing on the server itself" -style guide.
6
+
This cop-out is because Tranquil isn't built and released via CI as of yet.
4
7
5
8
## Prerequisites
6
9
7
-
- A VPS with at least 2GB RAM
8
-
- Disk space for blobs (depends on usage; plan for ~1GB per active user as a baseline)
10
+
- A server :p
11
+
- Disk space enough for blobs (depends on usage; plan for ~1GB per active user as a baseline)
9
12
- A domain name pointing to your server's IP
10
13
- A wildcard TLS certificate for `*.pds.example.com` (user handles are served as subdomains)
11
-
- Root or sudo access
14
+
- Root/sudo/doas access
12
15
13
-
## System Setup
16
+
## System setup
14
17
15
18
```bash
16
19
apt update && apt upgrade -y
17
20
apt install -y curl git build-essential pkg-config libssl-dev
18
21
```
19
22
20
-
## Install Rust
23
+
## Install rust
21
24
22
25
```bash
23
26
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
···
38
41
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE pds TO tranquil_pds;"
39
42
```
40
43
41
-
## Create Blob Storage Directories
44
+
## Create blob storage directories
42
45
43
46
```bash
44
47
mkdir -p /var/lib/tranquil/blobs /var/lib/tranquil/backups
···
54
57
echo 'export PATH="$HOME/.deno/bin:$PATH"' >> ~/.bashrc
55
58
```
56
59
57
-
## Clone and Build Tranquil PDS
60
+
## Clone and build Tranquil PDS
58
61
59
62
```bash
60
63
cd /opt
···
66
69
cargo build --release
67
70
```
68
71
69
-
## Install sqlx-cli and Run Migrations
70
-
71
-
```bash
72
-
cargo install sqlx-cli --no-default-features --features postgres
73
-
export DATABASE_URL="postgres://tranquil_pds:your-secure-password@localhost:5432/pds"
74
-
sqlx migrate run
75
-
```
76
-
77
72
## Configure Tranquil PDS
78
73
79
74
```bash
···
87
82
openssl rand -base64 48
88
83
```
89
84
90
-
## Install Frontend Files
85
+
## Install frontend files
91
86
92
87
```bash
93
88
mkdir -p /var/www/tranquil-pds
···
95
90
chown -R www-data:www-data /var/www/tranquil-pds
96
91
```
97
92
98
-
## Create Systemd Service
93
+
## Create systemd service
99
94
100
95
```bash
101
96
useradd -r -s /sbin/nologin tranquil-pds
···
127
122
systemctl start tranquil-pds
128
123
```
129
124
130
-
## Install and Configure nginx
125
+
## Install and configure nginx
131
126
132
127
```bash
133
128
apt install -y nginx certbot python3-certbot-nginx
···
264
259
systemctl reload nginx
265
260
```
266
261
267
-
## Obtain Wildcard SSL Certificate
262
+
## Obtain a wildcard SSL cert
268
263
269
264
User handles are served as subdomains (eg., `alice.pds.example.com`), so you need a wildcard certificate.
270
265
···
289
284
systemctl reload nginx
290
285
```
291
286
292
-
## Configure Firewall
287
+
## Configure firewall if you're into that sort of thing
293
288
294
289
```bash
295
290
apt install -y ufw
···
299
294
ufw enable
300
295
```
301
296
302
-
## Verify Installation
297
+
## Verify installation
303
298
304
299
```bash
305
300
systemctl status tranquil-pds
···
323
318
systemctl stop tranquil-pds
324
319
cp target/release/tranquil-pds /usr/local/bin/
325
320
cp -r frontend/dist/* /var/www/tranquil-pds/
326
-
DATABASE_URL="postgres://tranquil_pds:your-secure-password@localhost:5432/pds" sqlx migrate run
327
321
systemctl start tranquil-pds
328
322
```
329
323
324
+
Tranquil should auto-migrate if there are any new migrations to be applied to the db, so you don't need to worry.
325
+
330
326
Backup database:
331
327
```bash
332
328
sudo -u postgres pg_dump pds > /var/backups/pds-$(date +%Y%m%d).sql
333
329
```
334
330
335
-
## Custom Homepage
331
+
## Custom homepage
336
332
337
333
Drop a `homepage.html` in `/var/www/tranquil-pds/` and it becomes your landing page. Account dashboard is at `/app/` so you won't break anything.
338
334
+2
-2
docs/install-kubernetes.md
+2
-2
docs/install-kubernetes.md
···
1
-
# Tranquil PDS on Kubernetes
1
+
# Tranquil PDS on kubernetes
2
2
3
3
If you're reaching for kubernetes for this app, you're experienced enough to know how to spin up:
4
4
···
19
19
20
20
Health check: `GET /xrpc/_health`
21
21
22
-
## Custom Homepage
22
+
## Custom homepage
23
23
24
24
Mount a ConfigMap with your `homepage.html` into the container's frontend directory and it becomes your landing page. Go nuts with it. Account dashboard is at `/app/` so you won't break anything.
25
25
+2
-2
frontend/public/homepage.html
+2
-2
frontend/public/homepage.html
···
420
420
and alerts, granular OAuth scopes with human-readable descriptions,
421
421
app passwords with configurable permissions (read-only, post-only,
422
422
or custom scopes), account delegation with permission levels and
423
-
audit logging, and a built-in web UI for account management, OAuth
424
-
consent, repo browsing, and admin.
423
+
audit logging, and a built-in web UI for account management,
424
+
repo browsing, and admin.
425
425
</p>
426
426
</div>
427
427
</section>