## Deploying plebsaber.stream on Debian 12 with Caddy (SvelteKit + adapter-node) This guide sets up a production deployment of this SvelteKit app on Debian 12 using: - SvelteKit with `@sveltejs/adapter-node` (Node server) - Node.js 20 LTS - systemd service to keep the app running - Caddy as reverse proxy with automatic HTTPS for `plebsaber.stream` ### 1) Prerequisites - Debian 12 server with root or sudo access - DNS A/AAAA records pointing `plebsaber.stream` (and optionally `www`) to this server - Caddy installed (from official repo) Install Caddy (if not already): ```bash sudo apt update sudo apt install -y debian-keyring debian-archive-keyring curl curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo apt update sudo apt install -y caddy ``` Install Node.js 20 (via NodeSource): ```bash curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt install -y nodejs node -v ``` Create a deploy user and directories: ```bash sudo useradd -r -m -d /srv/plebsaber -s /usr/sbin/nologin plebsaber || true sudo mkdir -p /srv/plebsaber/app sudo chown -R plebsaber:plebsaber /srv/plebsaber ``` ### 2) Copy the app to the server From your local machine (run in project root): ```bash npm ci npm run build tar -czf plebsaber.build.tgz node_modules build package.json package-lock.json scp plebsaber.build.tgz user@server:/srv/plebsaber/app/ ``` On the server: ```bash sudo -u plebsaber bash -lc 'cd /srv/plebsaber/app && tar -xzf plebsaber.build.tgz' ``` If building on the server instead: ```bash sudo -u plebsaber bash -lc ' cd /srv/plebsaber/app && git clone . && npm ci && npm run build ' ``` ### 3) Systemd service Create `/etc/systemd/system/plebsaber.service`: ```ini [Unit] Description=Plebsaber SvelteKit service After=network.target [Service] Type=simple User=plebsaber WorkingDirectory=/srv/plebsaber/app Environment=NODE_ENV=production ExecStart=/usr/bin/node build/index.js Restart=always RestartSec=5 # Hardening NoNewPrivileges=true ProtectSystem=full ProtectHome=true PrivateTmp=true AmbientCapabilities= [Install] WantedBy=multi-user.target ``` Reload and start: ```bash sudo systemctl daemon-reload sudo systemctl enable --now plebsaber.service sudo systemctl status plebsaber.service --no-pager ``` The Node server listens on `0.0.0.0:3000` by default. ### 4) Caddy reverse proxy Create or edit `/etc/caddy/Caddyfile`: ```caddy plebsaber.stream { encode zstd gzip @static { path /favicon.ico path /robots.txt } reverse_proxy 127.0.0.1:3000 { health_uri /healthz } log { output file /var/log/caddy/plebsaber.access.log format json } } ``` Reload Caddy: ```bash sudo systemctl reload caddy ``` ### 5) Optional: health endpoint Add a simple health route for Caddy health checks: Create `src/routes/healthz/+server.ts`: ```ts import type { RequestHandler } from '@sveltejs/kit'; export const GET: RequestHandler = async () => { return new Response('ok', { headers: { 'content-type': 'text/plain' } }); }; ``` Rebuild and redeploy if you add this file. ### 6) Updating the app Deploying a new version: ```bash npm ci npm run build tar -czf plebsaber.build.tgz node_modules build package.json package-lock.json scp plebsaber.build.tgz user@server:/srv/plebsaber/app/ ssh user@server 'sudo -u plebsaber bash -lc "cd /srv/plebsaber/app && tar -xzf plebsaber.build.tgz" && sudo systemctl restart plebsaber.service' ``` ### 7) Notes - This project is configured with `@sveltejs/adapter-node` and includes server routes under `src/routes/api/beatleader/...` for server-side BeatLeader requests. - If you need environment variables, set them in the systemd unit with `Environment=KEY=VALUE` or `EnvironmentFile=`. - Ensure your firewall allows inbound 80/443 (Caddy) and blocks 3000 from the internet.