This repo is for third-party images built from someone else's source. We
now own a fork at lair/vibe-kanban, so its image is built there, next to
the code, by .gitea/workflows/container.yml. The quadlets move with it.
Leaving this job here was actively harmful, not just redundant: it built
from the BloopAI mirror and pushed to the same
git.lair.cafe/lair/vibe-kanban-remote:latest on a daily 07:00 cron. The
mirror still contains upstream's product sunset, which replaced the kanban
board with an export-only page — so the next scheduled run would have
republished a sunset image over :latest. bob is pinned to an immutable tag
and would not have picked it up, but the tag would have been wrong for
anything that did.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0182wzZE8DguMPWhxD21gfP2
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
Builds crates/remote/Dockerfile from our mirror at git.lair.cafe rather than
from GitHub, and resolves the version from the mirror's tags rather than
GitHub's releases API. BloopAI has announced a sunset; the mirror exists so
this build outlives them, which is pointless if the build still asks
github.com what to build. Nothing in this image's path touches GitHub.
Gitea mirrors carry tags but not releases, so latest is resolved by filtering
to the strict release pattern v<semver>-<14-digit datestamp> and sorting on
the datestamp -- which also skips the malformed historical tags in the
upstream repo (vv.20250708094151, vv0.0.40-nbump.2....).
FEATURES is deliberately left unset: the Dockerfile strips the private
billing crate only when it is empty, which is the documented self-host path.
Setting it would send the build looking for BloopAI/vibe-kanban-private over
SSH, which we cannot reach.
Consumed by the vibe-kanban quadlets on bob (kanban.internal).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TsmUEtbyTkgQ18tCFYXo1h
Upstream ships /opt/hermes (app + .venv + scripts) read-only root, which
blocks the agent self-modifying and the gateway auto-installing the
WhatsApp bridge's node_modules in place. Add a derived Containerfile layer
(FROM the upstream build) that chowns/chmods /opt/hermes writable by the
runtime hermes user. Done in the image, not a volume: a volume over
/opt/hermes copies-up once then freezes the app, silently defeating
AutoUpdate=registry. Persistence stays on the /opt/data volume.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011D3YeWKpjg5bT488fVanCH
The image's command selects mode; no command = interactive CLI which
crash-loops under systemd. Switched to the supported headless setup: one
container running `gateway run` with the dashboard supervised alongside
via HERMES_DASHBOARD=1 (same netns so the dashboard can reach the gateway,
which two bridge-networked containers could not). Image fails closed on a
0.0.0.0 dashboard bind, so HERMES_DASHBOARD_INSECURE=1 opts into the chosen
trusted-LAN exposure on :5100. Verified live on bob: gateway stable, dash
HTTP 200 across the LAN, inference endpoint reachable, enrolled in
podman-auto-update.timer. Dropped the redundant separate dashboard quadlet.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011D3YeWKpjg5bT488fVanCH
Confirmed against upstream: dashboard binds 0.0.0.0:9119 by default
(HERMES_DASHBOARD_HOST/PORT), so bridge + PublishPort=5100:9119 needs no
override. LLM backend uses Hermes' `custom` OpenAI-compatible provider
pointed at the local sovereign inference (hanzalova.internal:31313/v1).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011D3YeWKpjg5bT488fVanCH
Builds container images for lair infra and publishes to git.lair.cafe.
Hermes Agent (NousResearch) is built directly from its upstream Dockerfile
at the latest release tag, published as git.lair.cafe/lair/hermes; the build
is release-triggered (daily API poll) and self-healing (gated on registry
presence, not a committable pin). Includes a draft rootful quadlet for bob
matching the agent-zero/open-webui convention. Convention follows gongfoo.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011D3YeWKpjg5bT488fVanCH