forked from
lewis.moe/bspds-sandbox
PDS software with bells & whistles you didn’t even know you needed. will move this to its own account when ready.
1# Tranquil PDS Production Installation on OpenBSD
2> **Warning**: These instructions are untested and theoretical, written from the top of Lewis' head. They may contain errors or omissions. This warning will be removed once the guide has been verified.
3This guide covers installing Tranquil PDS on OpenBSD 7.8.
4## Prerequisites
5- A VPS with at least 2GB RAM and 20GB disk
6- A domain name pointing to your server's IP
7- A **wildcard TLS certificate** for `*.pds.example.com` (user handles are served as subdomains)
8- Root access (or doas configured)
9## Why nginx over relayd?
10OpenBSD's native `relayd` supports WebSockets but does **not** support HTTP/2. For a modern PDS deployment, we recommend nginx which provides HTTP/2, WebSocket support, and automatic OCSP stapling.
11## 1. System Setup
12```sh
13pkg_add curl git
14```
15## 2. Install Rust
16```sh
17pkg_add rust
18```
19OpenBSD ships Rust in ports. For the latest stable, use rustup:
20```sh
21pkg_add rustup
22rustup-init -y
23source ~/.cargo/env
24rustup default stable
25```
26## 3. Install postgres
27```sh
28pkg_add postgresql-server postgresql-client
29mkdir -p /var/postgresql/data
30chown _postgresql:_postgresql /var/postgresql/data
31su - _postgresql -c "initdb -D /var/postgresql/data -U postgres -A scram-sha-256"
32rcctl enable postgresql
33rcctl start postgresql
34psql -U postgres -c "CREATE USER tranquil_pds WITH PASSWORD 'your-secure-password';"
35psql -U postgres -c "CREATE DATABASE pds OWNER tranquil_pds;"
36psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE pds TO tranquil_pds;"
37```
38## 4. Install minio
39OpenBSD doesn't have a minio package. Options:
40**Option A: Use an external S3-compatible service (recommended for production)**
41aws s3, backblaze b2, or upcloud managed object storage. Skip to step 5 and configure the S3 credentials in step 9.
42**Option B: Build minio from source**
43```sh
44pkg_add go
45mkdir -p /tmp/minio-build && cd /tmp/minio-build
46ftp -o minio.tar.gz https://github.com/minio/minio/archive/refs/tags/RELEASE.2025-10-15T17-29-55Z.tar.gz
47tar xzf minio.tar.gz
48cd minio-*
49go build -o minio .
50cp minio /usr/local/bin/
51mkdir -p /var/minio/data
52useradd -d /var/minio -s /sbin/nologin _minio
53chown -R _minio:_minio /var/minio
54cat > /etc/minio.conf << 'EOF'
55MINIO_ROOT_USER=minioadmin
56MINIO_ROOT_PASSWORD=your-minio-password
57EOF
58chmod 600 /etc/minio.conf
59cat > /etc/rc.d/minio << 'EOF'
60#!/bin/ksh
61daemon="/usr/local/bin/minio"
62daemon_user="_minio"
63daemon_flags="server /var/minio/data --console-address :9001"
64. /etc/rc.d/rc.subr
65rc_pre() {
66 . /etc/minio.conf
67 export MINIO_ROOT_USER MINIO_ROOT_PASSWORD
68}
69rc_cmd $1
70EOF
71chmod +x /etc/rc.d/minio
72rcctl enable minio
73rcctl start minio
74```
75Create the blob bucket:
76```sh
77ftp -o /usr/local/bin/mc https://dl.min.io/client/mc/release/openbsd-amd64/mc
78chmod +x /usr/local/bin/mc
79mc alias set local http://localhost:9000 minioadmin your-minio-password
80mc mb local/pds-blobs
81```
82## 5. Install redis
83OpenBSD has redis in ports (valkey not available yet):
84```sh
85pkg_add redis
86rcctl enable redis
87rcctl start redis
88```
89## 6. Install deno (for frontend build)
90```sh
91curl -fsSL https://deno.land/install.sh | sh
92export PATH="$HOME/.deno/bin:$PATH"
93echo 'export PATH="$HOME/.deno/bin:$PATH"' >> ~/.profile
94```
95## 7. Clone and Build Tranquil PDS
96```sh
97mkdir -p /opt && cd /opt
98git clone https://tangled.org/lewis.moe/bspds-sandbox tranquil-pds
99cd tranquil-pds
100cd frontend
101deno task build
102cd ..
103cargo build --release
104```
105## 8. Install sqlx-cli and Run Migrations
106```sh
107cargo install sqlx-cli --no-default-features --features postgres
108export DATABASE_URL="postgres://tranquil_pds:your-secure-password@localhost:5432/pds"
109sqlx migrate run
110```
111## 9. Configure Tranquil PDS
112```sh
113mkdir -p /etc/tranquil-pds
114cp /opt/tranquil-pds/.env.example /etc/tranquil-pds/tranquil-pds.conf
115chmod 600 /etc/tranquil-pds/tranquil-pds.conf
116```
117Edit `/etc/tranquil-pds/tranquil-pds.conf` and fill in your values. Generate secrets with:
118```sh
119openssl rand -base64 48
120```
121## 10. Create rc.d Service
122```sh
123useradd -d /var/empty -s /sbin/nologin _tranquil_pds
124cp /opt/tranquil-pds/target/release/tranquil-pds /usr/local/bin/
125mkdir -p /var/tranquil-pds
126cp -r /opt/tranquil-pds/frontend/dist /var/tranquil-pds/frontend
127chown -R _tranquil_pds:_tranquil_pds /var/tranquil-pds
128cat > /etc/rc.d/tranquil_pds << 'EOF'
129#!/bin/ksh
130daemon="/usr/local/bin/tranquil-pds"
131daemon_user="_tranquil_pds"
132daemon_logger="daemon.info"
133. /etc/rc.d/rc.subr
134rc_pre() {
135 export FRONTEND_DIR=/var/tranquil-pds/frontend
136 while IFS='=' read -r key value; do
137 case "$key" in
138 \#*|"") continue ;;
139 esac
140 export "$key=$value"
141 done < /etc/tranquil-pds/tranquil-pds.conf
142}
143rc_cmd $1
144EOF
145chmod +x /etc/rc.d/tranquil_pds
146rcctl enable tranquil_pds
147rcctl start tranquil_pds
148```
149## 11. Install and Configure nginx
150```sh
151pkg_add nginx
152cat > /etc/nginx/nginx.conf << 'EOF'
153worker_processes 1;
154events {
155 worker_connections 1024;
156}
157http {
158 include mime.types;
159 server {
160 listen 80;
161 listen [::]:80;
162 server_name pds.example.com;
163 location /.well-known/acme-challenge/ {
164 root /var/www/acme;
165 }
166 location / {
167 return 301 https://$host$request_uri;
168 }
169 }
170 server {
171 listen 443 ssl http2;
172 listen [::]:443 ssl http2;
173 server_name pds.example.com;
174 ssl_certificate /etc/ssl/pds.example.com.fullchain.pem;
175 ssl_certificate_key /etc/ssl/private/pds.example.com.key;
176 ssl_protocols TLSv1.2 TLSv1.3;
177 ssl_ciphers HIGH:!aNULL:!MD5;
178 ssl_prefer_server_ciphers on;
179 ssl_session_cache shared:SSL:10m;
180 location / {
181 proxy_pass http://127.0.0.1:3000;
182 proxy_http_version 1.1;
183 proxy_set_header Upgrade $http_upgrade;
184 proxy_set_header Connection "upgrade";
185 proxy_set_header Host $host;
186 proxy_set_header X-Real-IP $remote_addr;
187 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
188 proxy_set_header X-Forwarded-Proto $scheme;
189 proxy_read_timeout 86400;
190 }
191 }
192}
193EOF
194mkdir -p /var/www/acme
195rcctl enable nginx
196```
197## 12. Obtain Wildcard SSL Certificate
198User handles are served as subdomains (e.g., `alice.pds.example.com`), so you need a wildcard certificate.
199
200OpenBSD's native `acme-client` only supports HTTP-01 validation, which can't issue wildcard certs. You have a few options:
201
202**Option A: Use certbot with DNS validation (recommended)**
203```sh
204pkg_add certbot
205certbot certonly --manual --preferred-challenges dns \
206 -d pds.example.com -d '*.pds.example.com'
207```
208Follow the prompts to add TXT records to your DNS. Then update nginx.conf to point to the certbot certs.
209
210**Option B: Use a managed DNS provider with API**
211If your DNS provider has a certbot plugin, you can automate renewal.
212
213**Option C: Use acme.sh**
214[acme.sh](https://github.com/acmesh-official/acme.sh) supports many DNS providers for automated wildcard cert renewal.
215
216After obtaining the cert, update nginx to use it and restart:
217```sh
218rcctl restart nginx
219```
220## 13. Configure Packet Filter (pf)
221```sh
222cat >> /etc/pf.conf << 'EOF'
223pass in on egress proto tcp from any to any port { 22, 80, 443 }
224EOF
225pfctl -f /etc/pf.conf
226```
227## 14. Verify Installation
228```sh
229rcctl check tranquil_pds
230ftp -o - https://pds.example.com/xrpc/_health
231ftp -o - https://pds.example.com/.well-known/atproto-did
232```
233## Maintenance
234View logs:
235```sh
236tail -f /var/log/daemon
237```
238Update Tranquil PDS:
239```sh
240cd /opt/tranquil-pds
241git pull
242cd frontend && deno task build && cd ..
243cargo build --release
244rcctl stop tranquil_pds
245cp target/release/tranquil-pds /usr/local/bin/
246cp -r frontend/dist /var/tranquil-pds/frontend
247DATABASE_URL="postgres://tranquil_pds:your-secure-password@localhost:5432/pds" sqlx migrate run
248rcctl start tranquil_pds
249```
250Backup database:
251```sh
252pg_dump -U postgres pds > /var/backups/pds-$(date +%Y%m%d).sql
253```