From de93e108ad513e24023b9253ee5e14c4e8421132 Mon Sep 17 00:00:00 2001 From: Bendik Aagaard Lynghaug Date: Mon, 28 Sep 2026 11:15:29 +0200 Subject: [PATCH] podman: make the stack podman-friendly (drop docker.sock runner, pin XFF subnet) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - bootstrap.sh / kanidm-setup.sh: docker compose -> podman compose; run rootful (as root) so Caddy can bind 80/443 and Kanidm sees a stable source IP - compose.yml: remove the in-compose act_runner (it mounted docker.sock) — the host gitea-runner already covers it; pin the project network to 172.18.0.0/16 so Kanidm's X-Forwarded-For trust (172.16/12) stays valid under Podman, whose default pool hands out unmatched 10.89.x addresses - README / deploy.yml: podman + host-runner notes Co-Authored-By: Claude Opus 4.8 --- .gitea/workflows/deploy.yml | 16 +++++++--------- README.md | 23 ++++++++++------------- bootstrap.sh | 13 +++++++------ compose.yml | 33 ++++++++++++++------------------- kanidm-setup.sh | 2 +- 5 files changed, 39 insertions(+), 48 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 129b4dd..35223a8 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -1,12 +1,10 @@ -# Deploy from this repo: on the vel's own host, a runner registered -# against prosjekt.klingenbergbygg.no with the label `tomtervel` -# (the `runner` profile in compose.yml) checks out this repo and -# brings the stack up. Rolling out a new portal version is a commit -# that bumps PORTAL_RELEASE in .env.example and, on the host, in .env. -# -# Until that runner exists, this workflow queues and does nothing; -# deploy by hand with `git pull && docker compose up -d --build` on -# the host. +# Deploy from this repo onto the vel's own host (kasse). There is no +# `tomtervel`-labelled runner, so this workflow queues and does nothing; +# deploy by hand on the host with: +# cd /srv/tomtervel/infrastructure && git pull --ff-only && sudo sh bootstrap.sh +# (bootstrap.sh runs `podman compose up -d --build`, rootful). Rolling out +# a new portal version is a commit that bumps PORTAL_RELEASE in .env.example +# and, on the host, in .env. name: deploy on: push: diff --git a/README.md b/README.md index b677a8c..4cebcbc 100644 --- a/README.md +++ b/README.md @@ -19,13 +19,14 @@ so nothing about the vel's members or records depends on anyone else. ## First start -On a fresh Linux host with docker (compose plugin) and openssl: +On a fresh Linux host with podman + podman-compose and openssl (run rootful, +i.e. as root, so Caddy can bind 80/443 and Kanidm sees a stable source IP): ```sh git clone https://prosjekt.klingenbergbygg.no/tomtervel/infrastructure /srv/tomtervel/infrastructure cd /srv/tomtervel/infrastructure cp .env.example .env # set PORTAL_HOST and ID_HOST; DNS must point here -sh bootstrap.sh # renders configs, makes the internal cert, starts, recovers Kanidm admin +sudo sh bootstrap.sh # renders configs, makes the internal cert, starts, recovers Kanidm admin sh kanidm-setup.sh # logs in, creates the portal client and desk groups, restarts portal ``` @@ -53,22 +54,18 @@ and in again. A push to tomtervel/questions is linted on push and tells the portal to reload over NATS. That reload reaches the host it runs on: today -Klingenberg Bygg's. For this host, start the runner profile once with -a registration token from the tomtervel org's Actions settings: - -```sh -docker compose --profile runner up -d -``` - -and give the content repo's `lint-and-reload.yml` a reload job with -`runs-on: tomtervel` that runs +Klingenberg Bygg's. On this host the runner is a **host service** +(`pacman -S gitea-runner`, registered against prosjekt.klingenbergbygg.no) — +not an in-compose container — so it reaches NATS on the published +`127.0.0.1:4222`. Give the content repo's `lint-and-reload.yml` a reload job +whose `runs-on` matches that runner's host label, running `nats --server nats://portal:$NATS_PASSWORD@127.0.0.1:4222 pub portal.content.reload ""`. -Until then, `docker compose restart portal` picks up new content. +Until then, `podman compose restart portal` picks up new content. ## Upgrading portal Bump `PORTAL_RELEASE` in `.env` (a tag of uhhm/portal) and -`docker compose up -d --build portal`. Keep `IRIS_RELEASE` in the +`podman compose up -d --build portal`. Keep `IRIS_RELEASE` in the content repo's workflow matched to it. ## Backups diff --git a/bootstrap.sh b/bootstrap.sh index 576e566..ae637b9 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,10 +1,11 @@ #!/bin/sh # First start on a fresh host. Idempotent: rerunning renders configs -# again and skips what exists. Needs docker with the compose plugin, -# openssl, and DNS for PORTAL_HOST and ID_HOST already pointing here. +# again and skips what exists. Needs podman + podman-compose and openssl, +# and DNS for PORTAL_HOST and ID_HOST already pointing here. Run rootful +# (as root) so Caddy can bind 80/443 and Kanidm sees a stable source IP. # # cp .env.example .env # fill in the hosts -# sh bootstrap.sh +# sudo sh bootstrap.sh set -eu cd "$(dirname "$0")" [ -f .env ] || { echo "copy .env.example to .env and fill it in first"; exit 1; } @@ -43,7 +44,7 @@ if [ ! -f certs/kanidm-key.pem ]; then echo "internal Kanidm certificate made" fi -docker compose up -d --build +podman compose up -d --build echo "containers up; Caddy is fetching certificates for $PORTAL_HOST and $ID_HOST" # The Kanidm admin accounts exist only after the first start; their @@ -52,8 +53,8 @@ echo "containers up; Caddy is fetching certificates for $PORTAL_HOST and $ID_HOS if [ ! -f .kanidm-recovered ]; then echo echo "=== Kanidm admin recovery (write these passwords down) ===" - docker compose exec kanidm kanidmd recover-account admin - docker compose exec kanidm kanidmd recover-account idm_admin + podman compose exec kanidm kanidmd recover-account admin + podman compose exec kanidm kanidmd recover-account idm_admin touch .kanidm-recovered fi diff --git a/compose.yml b/compose.yml index e7f8371..8a19626 100644 --- a/compose.yml +++ b/compose.yml @@ -8,7 +8,7 @@ # .env, makes Kanidm's internal cert, starts it all, # recovers the Kanidm admin, creates the portal client # and desk groups. -# docker compose up -d --build every time after that. +# podman compose up -d --build every time after that. name: tomtervel @@ -79,27 +79,22 @@ services: kanidm: condition: service_started - # Optional: a Gitea Actions runner on this host, so the content repo's - # lint-and-reload can reach this NATS. Register it once against - # prosjekt.klingenbergbygg.no with the label `tomtervel`, then give - # the content repo a reload job with `runs-on: tomtervel`. - # docker compose --profile runner up -d - runner: - profiles: ["runner"] - image: gitea/act_runner:latest - restart: unless-stopped - environment: - GITEA_INSTANCE_URL: https://prosjekt.klingenbergbygg.no - GITEA_RUNNER_REGISTRATION_TOKEN: ${RUNNER_REGISTRATION_TOKEN:-} - GITEA_RUNNER_NAME: tomtervel - GITEA_RUNNER_LABELS: tomtervel:host - volumes: - - runner_data:/data - - /var/run/docker.sock:/var/run/docker.sock + # The Gitea Actions runner is a host service on kasse (pacman gitea-runner), + # registered against prosjekt.klingenbergbygg.no. It reaches this NATS via the + # published 127.0.0.1:4222 port above, so no in-compose runner — and no + # docker.sock/podman.sock mount — is needed here. volumes: caddy_data: caddy_config: nats_data: kanidm_data: - runner_data: + +# Pin the project network subnet inside 172.16/12 so Kanidm's X-Forwarded-For +# trust (kanidm/server.toml.tpl) stays valid under Podman — its default pool +# hands out 10.89.x addresses that Caddy's forwarded client IP can't match. +networks: + default: + ipam: + config: + - subnet: 172.18.0.0/16 diff --git a/kanidm-setup.sh b/kanidm-setup.sh index ee031c1..e138422 100755 --- a/kanidm-setup.sh +++ b/kanidm-setup.sh @@ -36,7 +36,7 @@ $K system oauth2 update-claim-map-join $C groups array secret=$($K system oauth2 show-basic-secret $C 2>/dev/null | tail -1) sed -i "s|^OAUTH2_CLIENT_SECRET=.*|OAUTH2_CLIENT_SECRET=$secret|" .env portal.env -docker compose restart portal +podman compose restart portal echo "client $C configured; portal restarted with its secret" echo echo "Give people their desk (membership is read at login):"