rob thijssen 3619470d79
Some checks failed
images / hermes (push) Failing after 17m32s
images / vibe-kanban-remote (push) Successful in 21m35s
docs(vibe-kanban-remote): commit the deployed quadlets
Mirrors the hermes convention of keeping the consuming quadlet alongside the
image definition. Four units: a private network, postgres 16 with
wal_level=logical, remote-server, and electric.

Records why the start order matters -- remote-server's migrations create the
electric_sync role, its grants and the publication that electric then connects
with, so electric cannot come up first -- and why electric has its own env
file, which is to avoid depending on systemd expanding one Environment= value
into another inside a quadlet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TsmUEtbyTkgQ18tCFYXo1h
2026-07-20 18:26:25 +03:00

lair/containers

Container images required by lair infrastructure, built and published to the Gitea registry at git.lair.cafe. Convention follows gongfoo's images/ setup.

Layout

images/<name>/          one directory per image
  Containerfile         (when we author the image ourselves)
  build.sh              local build helper
  readme.md             what it is and how it's built
.gitea/workflows/
  images.yml            builds + publishes every image, on push / daily / dispatch

Images

Image Published as Source
hermes git.lair.cafe/lair/hermes:{version,latest} built from NousResearch/hermes-agent's Dockerfile at the latest release tag
vibe-kanban-remote git.lair.cafe/lair/vibe-kanban-remote:{version,latest} built from our mirror BloopAI/vibe-kanban's crates/remote/Dockerfile at the latest release tag — deliberately never touches GitHub, since upstream is sunsetting

How builds work

  • Trigger: push under images/**, a daily cron poll, or manual dispatch.
  • Release-tracking: each image job resolves the upstream's latest release via its API and builds that exact ref. For upstreams that ship their own Dockerfile (hermes) we build directly from the upstream git context; for images we author, the version is passed as a --build-arg with the Containerfile pin as fallback.
  • Self-healing: a build runs only when the resolved version isn't already in the registry — and because the registry (not a committed pin) is the source of truth, a failed build simply retries on the next poll instead of stranding a stale image. (Lesson borrowed from gongfoo.)

Adding an image

  1. mkdir images/<name>, add a Containerfile (or build from an upstream context) + build.sh + readme.md.
  2. Add a job to .gitea/workflows/images.yml that logs in, builds git.lair.cafe/lair/<name>:latest, and pushes.
  3. Consumers pull git.lair.cafe/lair/<name>:latest with AutoUpdate=registry.

Required secret

Secret Purpose
REGISTRY_TOKEN Gitea token with write:package for git.lair.cafe; used as podman login -u $GITEA_ACTOR -p $REGISTRY_TOKEN. Set in this repo's (or the lair org's) Actions secrets.

Build jobs run on self-hosted runners labelled metal + podman.

Description
Container images required by lair infra, built and published to git.lair.cafe
Readme 64 KiB
Languages
Shell 58.7%
Dockerfile 41.3%