source: Klonkt/deploy/DEPLOY.md@ b7e382f

main
Last change on this file since b7e382f was d2b7247, checked in by Robin Genis <roboburr@…>, 2 months ago

chore(branding): stale product names in comments + deploy templates -> Klonkt

Cosmetic only — comments (CSS/EJS/SQL/ecosystem.config.cjs headers) and the deploy/ doc
templates: old names (PrutCMS/PrutFolio) -> Klonkt, stale Prutter (removed DM feature) mentions
dropped, deploy/ Dutch comments translated to English. No code, identifiers, rendered strings,
package name, PWA id, real infra paths, or roboburr refs touched.

  • Property mode set to 100644
File size: 5.8 KB
Line 
1# Klonkt — Deployment Guide
2
3End-to-end production install on a fresh Ubuntu 22.04 / Debian 12 VPS
4(TransIP, Hetzner, etc.). Assumes a non-root user with sudo.
5
6---
7
8## 0. Prerequisites
9
10- VPS with Ubuntu 22.04 LTS or Debian 12.
11- DNS A/AAAA records for your domain pointing at the server's IP. Wait for
12 propagation (`dig +short YOUR-DOMAIN` should return the right IP) before
13 running certbot.
14- SSH access as a non-root user (e.g. `robin`).
15
16---
17
18## 1. System packages
19
20```bash
21sudo apt update && sudo apt upgrade -y
22sudo apt install -y curl ca-certificates git nginx ufw sqlite3
23```
24
25Install Node.js 20 LTS via NodeSource (don't use the OS-default — it's old):
26
27```bash
28curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
29sudo apt install -y nodejs
30node --version # should print v20.x.x
31```
32
33Install PM2 globally:
34
35```bash
36sudo npm install -g pm2
37```
38
39---
40
41## 2. Firewall
42
43```bash
44sudo ufw allow OpenSSH
45sudo ufw allow 'Nginx Full' # opens 80 + 443
46sudo ufw enable
47```
48
49---
50
51## 3. App user + project clone
52
53```bash
54# As root or via sudo, create a deploy user if you don't already have one
55# (skip if you're already on a non-root user)
56
57# As your user:
58mkdir -p ~/klonkt
59cd ~/klonkt
60# Clone or rsync your code here. e.g. via git:
61# git clone <your-repo> .
62
63npm ci --omit=dev
64```
65
66`ensureLocalHtmx()` in `server.js` will copy the bundled HTMX from
67`node_modules/htmx.org/dist/htmx.min.js` to `src/assets/js/htmx.min.js` on
68first boot. You don't have to do that step manually.
69
70---
71
72## 4. Environment variables
73
74Create `.env` in the project root:
75
76```ini
77NODE_ENV=production
78PORT=3000
79
80# 32+ random hex chars — required, the app refuses to boot without it.
81# Generate: openssl rand -hex 32
82SESSION_SECRET=<paste-strong-random-string>
83
84# Optional: pin the audio HMAC secret instead of letting the app generate one
85# in storage/.audio-secret. Generate the same way as SESSION_SECRET.
86# AUDIO_SECRET=<paste-different-random-string>
87
88# Optional: override storage paths
89# DATABASE_PATH=/home/robin/klonkt/storage/database.sqlite
90# AUDIO_PATH=/home/robin/klonkt/storage/audio
91# AVATAR_PATH=/home/robin/klonkt/storage/media/avatars
92# COVER_PATH=/home/robin/klonkt/storage/media/audio-covers
93# MEDIA_PATH=/home/robin/klonkt/storage/media
94```
95
96`chmod 600 .env` — keep it readable only by your user.
97
98---
99
100## 5. First boot
101
102```bash
103npm run migrate # creates storage/database.sqlite + tables
104```
105
106Then start with PM2:
107
108```bash
109pm2 start ecosystem.config.cjs --env production
110pm2 save
111pm2 startup # follow the printed command to make PM2 survive reboots
112```
113
114Check it's up:
115
116```bash
117curl -I http://127.0.0.1:3000/ # expect 200 / 302
118pm2 logs klonkt # live logs; Ctrl-C to detach
119```
120
121Register your first user (becomes god) by visiting
122`http://YOUR-SERVER-IP:3000/auth/register` BEFORE you point nginx at it
123(or just wait until SSL is up — registration works the same).
124
125---
126
127## 6. nginx + SSL
128
129```bash
130sudo cp deploy/nginx.conf.example /etc/nginx/sites-available/klonkt
131sudo $EDITOR /etc/nginx/sites-available/klonkt # replace <YOUR-DOMAIN>
132sudo ln -s /etc/nginx/sites-available/klonkt /etc/nginx/sites-enabled/
133sudo rm -f /etc/nginx/sites-enabled/default
134sudo nginx -t
135sudo systemctl reload nginx
136```
137
138Install certbot and provision certs:
139
140```bash
141sudo apt install -y certbot python3-certbot-nginx
142sudo mkdir -p /var/www/letsencrypt
143sudo certbot --nginx -d YOUR-DOMAIN -d www.YOUR-DOMAIN
144```
145
146Certbot edits the nginx config in place to wire in the certificate paths.
147Renewals run automatically via the certbot systemd timer; verify with:
148
149```bash
150sudo systemctl status certbot.timer
151```
152
153Now visit `https://YOUR-DOMAIN/`. You should see your site over HTTPS, with
154HSTS active.
155
156---
157
158## 7. Backups
159
160```bash
161chmod +x deploy/backup.sh
162mkdir -p ~/backups/klonkt ~/klonkt/logs
163
164# Test it once
165./deploy/backup.sh
166
167# Schedule nightly at 03:00
168( crontab -l 2>/dev/null ; \
169 echo "0 3 * * * /home/$USER/klonkt/deploy/backup.sh >> /home/$USER/klonkt/logs/backup.log 2>&1" \
170) | crontab -
171
172crontab -l # verify
173```
174
175Restore is a tar -xzf into a clean directory + `npm ci` + start.
176
177---
178
179## 8. Updating
180
181```bash
182cd ~/klonkt
183git pull
184npm ci --omit=dev
185pm2 reload klonkt # zero-downtime within fork mode
186```
187
188The DB schema migrates automatically on boot (`ensureColumn` adds new columns
189idempotently). For destructive changes you'd need to write an explicit
190migration — not yet needed.
191
192---
193
194## 9. Multi-tenant setup
195
196After your first user/site is created (auto on first registration), use
197`/admin/sites` to create more sites. Each site gets its own URL prefix
198(`/sites/<slug>/`) and its own PWA scope, so installing the PWA from one
199site won't navigate into another.
200
201---
202
203## 10. Troubleshooting
204
205| Symptom | Check |
206|---|---|
207| `❌ FATAL: SESSION_SECRET is required` | `.env` missing or unreadable. `pm2 stop klonkt && pm2 start ecosystem.config.cjs --env production`. |
208| `❌ FATAL: SESSION_SECRET too weak for production` | Make it 32+ chars: `openssl rand -hex 32`. |
209| WS disconnects every minute | Check nginx `proxy_read_timeout` is ≥ 90s in `/ws/` block. |
210| Audio plays but seek stutters | nginx must have `proxy_buffering off` on `/audio/stream/`. |
211| 502 from nginx | `pm2 list` — is the app up? `pm2 logs klonkt --lines 100`. |
212| HTMX 404s on `/assets/js/htmx.min.js` | `ls node_modules/htmx.org/dist/htmx.min.js` — if missing, `npm install htmx.org`. The boot-copy step needs the package. |
213
214---
215
216## 11. What's NOT included
217
218- Email sending (password reset prints the URL to the console / page in
219 non-production). Hook up an SMTP or transactional service when needed.
220- Cluster mode / horizontal scaling. Single fork only — see comments in
221 `ecosystem.config.cjs` for what would have to change first.
222- Off-site backup replication. The local rotation keeps 14 days; copy the
223 tar.gz files off-server with rsync/restic/whatever you prefer.
Note: See TracBrowser for help on using the repository browser.