# Deploy runbook — librenotes Derived from [`netcup/DEPLOY-TEMPLATE.md`](https://git.librete.ch/libretech/netcup/src/branch/main/DEPLOY-TEMPLATE.md). Section ordering and headings stable across stacks. ## 1. Target | Field | Value | |-------|-------| | Vhost | `ln.cloud.librete.ch` | | Server path | `/srv/librenotes/` | | Repo | `git.librete.ch/public/librenotes` | | Image source | `${LIBRENOTES_IMAGE}` from `git.librete.ch/public/librenotes` (registry image, no source build on remote) | | Cert | edge caddy via INWX DNS-01 | | Edge net container name | `librenotes` (matches `caddy/Caddyfile` reverse_proxy target on `:8080`) | ## 2. Required env / secrets `/srv/librenotes/.env` (gitignored, mode 0600): | Variable | Notes | |----------|-------| | `LIBRENOTES_IMAGE` | published tag, e.g. `git.librete.ch/public/librenotes:v0.1.0` | | `LIBRENOTES_BASE_URL` | `https://ln.cloud.librete.ch` | | `LIBRENOTES_JWT_SECRET` | `openssl rand -base64 48` | | `LIBRENOTES_SMTP_HOST`, `..._PORT`, `..._USER`, `..._PASS`, `..._FROM` | outbound mail (uberspace per `netcup/.env`) | ## 3. First-time deploy ```sh ssh netcup 'docker network ls | grep -q edge || docker network create edge' ssh netcup 'mkdir -p /srv && cd /srv && git clone ssh://tengo@git.librete.ch:41240/public/librenotes.git' scp librenotes/.env netcup:/srv/librenotes/.env ssh netcup 'chmod 600 /srv/librenotes/.env' ssh netcup 'cd /srv/librenotes && docker compose -f compose.yaml -f compose.netcup.yaml pull && docker compose -f compose.yaml -f compose.netcup.yaml up -d' ``` ## 4. Update deploy ```sh n-deploy librenotes # Bump LIBRENOTES_IMAGE in /srv/librenotes/.env then: ssh netcup 'cd /srv/librenotes && docker compose -f compose.yaml -f compose.netcup.yaml pull && docker compose -f compose.yaml -f compose.netcup.yaml up -d' ``` ## 5. Smoke / health ```sh n-ping ln.cloud.librete.ch n-cert ln.cloud.librete.ch n-svcs librenotes n-logs librenotes librenotes --tail=200 ``` UI smoke: signup magic-link email arrives, login succeeds, note creation persists. ## 6. Logs + troubleshooting | Symptom | First check | |---------|-------------| | 502 from edge | container off `edge` net or down | | SMTP failure | `LIBRENOTES_SMTP_*` correct; firewall to uberspace | | State loss | bind-mount `./state:/var/lib/librenotes` permissions | ## 7. Rollback ```sh # Edit LIBRENOTES_IMAGE to prior tag in /srv/librenotes/.env, then: ssh netcup 'cd /srv/librenotes && docker compose -f compose.yaml -f compose.netcup.yaml pull && docker compose -f compose.yaml -f compose.netcup.yaml up -d' ``` ## 8. Stack-specific notes - **Bind mounts** `./data:/data` (notes payload) and `./state:/var/lib/librenotes` (DB/state) — back up both. - Multi-tenant by base URL — single image instance per tenant config. - Image is published from `public/librenotes` CI; never builds on remote. ## 9. Issue tracking - Deploy issues: `git.librete.ch/public/librenotes/issues` - Cross-stack: `libretech/netcup` - After every deploy: append to `netcup/deployments.md`.