From 2784e0fa7c5ae89bc991cbd145f1a738ad5bb36b Mon Sep 17 00:00:00 2001 From: Michael Czechowski Date: Wed, 29 Apr 2026 02:00:29 +0200 Subject: [PATCH] docs(ops): document registry secrets, rollback, Gitea runner image operations.md lists the full secret/variable matrix the deploy workflow expects, the new compose.yaml + compose.netcup.yaml invocation, and a note on why both workflow jobs pin catthehacker/ubuntu:runner-latest. self-hosting.md updates the example LIBRENOTES_IMAGE value to the Gitea Packages path and switches the quick-start to compose.netcup.yaml. --- docs/operations.md | 52 +++++++++++++++++++++++++++++++------------- docs/self-hosting.md | 16 +++++++++----- 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/docs/operations.md b/docs/operations.md index 996a4a3..b73b85a 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -21,26 +21,32 @@ The workflow expects these secrets and variables on the repo: | Name | Type | Purpose | | ---- | ---- | ------- | -| `REGISTRY` | secret | hostname of the OCI registry | -| `REGISTRY_USER` | secret | robot account | -| `REGISTRY_PASS` | secret | robot token | -| `DEPLOY_HOST` | secret | `user@host` SSH target | -| `DEPLOY_KEY` | secret | passphrase-less private key | -| `DEPLOY_PATH` | secret | absolute path on host with `docker-compose.*.yml` | -| `HEALTH_URL` | secret | e.g. `https://librenot.es/healthz` | +| `REGISTRY` | secret | registry hostname, e.g. `git.librete.ch` | +| `REGISTRY_USER` | secret | robot account or PAT username with `package:write` | +| `REGISTRY_PASS` | secret | robot/PAT token | +| `DEPLOY_HOST` | secret | `user@host` SSH target, e.g. `root@netcup` | +| `DEPLOY_KEY` | secret | passphrase-less private key (PEM) | +| `DEPLOY_PATH` | secret | absolute path on host with the compose stack, e.g. `/srv/librenotes` | +| `HEALTH_URL` | secret | e.g. `https://ln.cloud.librete.ch/healthz` | | `DEPLOY_ENABLED` | variable | `true` to enable the workflow | +The image is pushed to `${REGISTRY}/public/librenotes`; main pushes +publish `:main` and `:`, tag pushes publish `:vX.Y.Z` and +`:latest`. + ### Production compose stack -On the deployment host, place `docker-compose.yml` and -`docker-compose.prod.yml` from this repo at `$DEPLOY_PATH`, -together with an `.env` file containing the runtime configuration -(JWT secret, SMTP credentials, public base URL, image tag). +On the deployment host, place `compose.yaml` and +`compose.netcup.yaml` from this repo at `$DEPLOY_PATH`, together +with an `.env` file containing `LIBRENOTES_IMAGE` plus the runtime +configuration (JWT secret, SMTP credentials, public base URL). +See `.env.netcup.example` for the full key list. Bring it up with: ```sh -docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d +docker compose -f compose.yaml -f compose.netcup.yaml pull +docker compose -f compose.yaml -f compose.netcup.yaml up -d ``` ### Rollback @@ -52,11 +58,27 @@ on health-check failure — failed health alerts the operator via the workflow itself, who can then redeploy the prior tag manually. ```sh -# Example: roll back to v0.1.2 -sed -i 's/^LIBRENOTES_IMAGE=.*/LIBRENOTES_IMAGE=registry.librete.ch\/librenotes:v0.1.2/' .env -docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d +# Example: roll back to v0.1.0 +perl -i -pe 's|^LIBRENOTES_IMAGE=.*|LIBRENOTES_IMAGE=git.librete.ch/public/librenotes:v0.1.0|' .env +docker compose -f compose.yaml -f compose.netcup.yaml pull +docker compose -f compose.yaml -f compose.netcup.yaml up -d ``` +### Gitea Actions runner + +Workflows run on the netcup `act_runner` (see `runner/` stack in +the netcup umbrella). Both jobs declare `container: catthehacker/ubuntu:runner-latest` +because: + +- The default runner label image (`node:20-bookworm`) lacks `make` + and `docker`, both required by the workflows. +- The `runner-latest` image bundles `make`, `git`, `curl`, `ssh`, + `node`, plus a docker CLI. + +The runner config (`runner/config.yaml`) declares +`/var/run/docker.sock` as a `valid_volume` so the build job can +mount the host socket and push images via `docker/build-push-action`. + ## Backups `scripts/backup.sh` is a self-contained backup driver suitable for diff --git a/docs/self-hosting.md b/docs/self-hosting.md index 434b682..720c42d 100644 --- a/docs/self-hosting.md +++ b/docs/self-hosting.md @@ -23,10 +23,16 @@ Docker Compose. For day-2 ops (deploys, backups) see ```sh git clone https://git.librete.ch/public/librenotes cd librenotes -cp .env.example .env # edit values, see below -docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d +cp .env.netcup.example .env # edit values, see below +docker compose -f compose.yaml -f compose.netcup.yaml pull +docker compose -f compose.yaml -f compose.netcup.yaml up -d ``` +The `compose.netcup.yaml` overlay is the production-style overlay +shipped in this repo; it pulls a published image, drops host port +binding (assumes a fronting reverse proxy), and joins an external +`edge` docker network. Adapt to your topology if needed. + Visit `https://your-domain/` and sign in. ## Environment configuration @@ -45,7 +51,7 @@ Place them in an `.env` file next to the Compose stack. | `LIBRENOTES_SMTP_FROM` | yes | Envelope sender, e.g. `no-reply@notes.example.com`. | | `LIBRENOTES_DATA_DIR` | no | Default `/data` inside the container. | | `LIBRENOTES_DB` | no | Default `/var/lib/librenotes/librenotes.db`. | -| `LIBRENOTES_IMAGE` | yes (prod) | Image tag to pull, e.g. `registry.librete.ch/librenotes:v0.1.0`. | +| `LIBRENOTES_IMAGE` | yes (prod) | Image tag to pull, e.g. `git.librete.ch/public/librenotes:v0.1.0`. | Generate a JWT secret: @@ -109,8 +115,8 @@ to use `curl`/`wget`). Pull the new image and restart: ```sh -docker compose -f docker-compose.yml -f docker-compose.prod.yml pull -docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d +docker compose -f compose.yaml -f compose.netcup.yaml pull +docker compose -f compose.yaml -f compose.netcup.yaml up -d ``` To pin a specific version, set `LIBRENOTES_IMAGE` to that tag in