althing-chamber: scaffold deploy stack on ana-docker
Two-service compose (chamber + forseti sidecar daemon) sharing a single
SQLite store via bind-mount under /opt/docker/conf/althing-chamber/data.
eventbus.bridge_from_db is the cross-process glue — forseti's commits
reach chamber's SSE subscribers via the bridge.
Pattern matches task-board's build-on-host deploy:
- elway playbook clones vh/althing into /opt/docker/build/
- docker build -t althing-chamber:local . (no registry)
- playbook uploads compose + seeds .env one-time, brings both
services up, polls /health
- Gitea Actions workflow lives in vh/althing; reference copy here.
Internal tooling — host port 7881 (chamber's default of 7878 collides
with task-board). LAN-direct, no Traefik. Container always listens on
8000 internally.
Scaffold will fail to bring the chamber container up healthy until
galdrabok-side commits land:
- Dockerfile at vh/althing repo root (two-stage: uv-bookworm-slim
build → python:3.12-slim runtime, locked per open_questions §2
of the v1 contract).
- GET /health endpoint on the chamber app (200, no DB read).
- ALTHING_BIND / ALTHING_PORT env-var support in
core.cli.chamber_serve / core.chamber.cli (env > config.yaml >
defaults precedence).
Coordinated via althing thread 01KRMAK7RD7TP6C8DF4KXV31RT.
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
# althing-chamber
|
||||
|
||||
Web UI + moderator daemon for the althing inter-agent message bus.
|
||||
Two services share a single SQLite store via a bind-mount; the chamber
|
||||
serves FastAPI/HTMX, the forseti daemon runs the moderation + curation
|
||||
loops. Cross-process glue is `eventbus.bridge_from_db` polling the same
|
||||
DB both processes write.
|
||||
|
||||
**Server:** ana-docker
|
||||
**URL:** `http://10.250.50.70:7881` (configurable via `.env`)
|
||||
**Upstream repo:** [vh/althing](https://gitea.phasefinal.com/vh/althing)
|
||||
**Image:** `althing-chamber:local` — built on the host from the git repo
|
||||
by the deploy playbook. Not pulled from a registry.
|
||||
|
||||
## Services in this stack
|
||||
|
||||
| Container | Role | Port | Healthcheck |
|
||||
|---|---|---|---|
|
||||
| `althing-chamber` | FastAPI/HTMX web UI; SSE subscribers; `/health` endpoint | host 7881 → container 8000 | `python urllib /health` |
|
||||
| `althing-forseti` | Moderator + curator daemon; writes events that chamber's bridge picks up | — (no HTTP) | none (process-up signal only) |
|
||||
|
||||
Both use the same `${ALTHING_IMAGE}`; the `command:` line in compose picks
|
||||
which entrypoint (`althing-chamber` vs `althing-forseti`) runs in each
|
||||
container.
|
||||
|
||||
## Deploy
|
||||
|
||||
Two paths — automated (preferred) and manual (escape hatch / first-time).
|
||||
|
||||
### Automated (Gitea Actions, push-to-main)
|
||||
|
||||
The vh/althing repo ships `.gitea/workflows/deploy.yaml`. Every push to
|
||||
main + manual `workflow_dispatch` triggers the elway playbook below
|
||||
pinned to the triggering commit SHA. A reference copy of the workflow
|
||||
lives next to this README at
|
||||
[`gitea-workflow-deploy.yaml.example`](gitea-workflow-deploy.yaml.example);
|
||||
the canonical source is in the vh/althing repo. The example header
|
||||
lists the two repo secrets required (`DEPLOY_SSH_KEY`,
|
||||
`MGMT_REPO_TOKEN`).
|
||||
|
||||
### Manual (elway from a workstation)
|
||||
|
||||
```bash
|
||||
# First deploy (or update to latest main)
|
||||
scripts/elway ana-docker --playbook playbooks/deploy-althing-chamber.yaml
|
||||
|
||||
# Pin to a specific ref (tag, branch, or commit SHA)
|
||||
scripts/elway ana-docker --playbook playbooks/deploy-althing-chamber.yaml --var ref=v0.1.0
|
||||
```
|
||||
|
||||
## Path layout (on ana-docker)
|
||||
|
||||
| Host path | Container path | Purpose | Restic? |
|
||||
|---|---|---|---|
|
||||
| `/opt/docker/build/althing-chamber/` | — | git checkout used as docker build context | excluded |
|
||||
| `/opt/docker/compose/althing-chamber/` | — | compose.yaml + .env | included (via `/opt/docker`) |
|
||||
| `/opt/docker/conf/althing-chamber/data/` | `/app/data` | SQLite + state for BOTH services | **included** |
|
||||
|
||||
## Network model
|
||||
|
||||
Internal tooling, LAN-only. Chamber's container port 8000 is published
|
||||
on the host at `0.0.0.0:7881` (configurable via `ALTHING_BIND` /
|
||||
`ALTHING_PORT`); access is direct via `http://10.250.50.70:7881`. No
|
||||
Traefik, no TLS terminator, no public hostname.
|
||||
|
||||
Forseti has no port — it's a daemon. The two services communicate only
|
||||
via the shared SQLite file under the `${ALTHING_DATA_DIR}` bind-mount;
|
||||
no docker network coupling beyond compose's default bridge.
|
||||
|
||||
## Env-var contract
|
||||
|
||||
| Var | In env? | In `~/.althing/config.yaml`? | Notes |
|
||||
|---|---|---|---|
|
||||
| `ALTHING_ROOT` | ✓ (set in compose) | n/a | Overrides the default `~/.althing/` dir. Container sets `/app/data`. |
|
||||
| `ALTHING_DB` | ✓ (set in compose) | n/a | Explicit SQLite path. Defaults to `${ALTHING_ROOT}/althing.db`. |
|
||||
| `ALTHING_BIND` | ✓ (deploy-time) | also accepted | Bind address for the chamber HTTP server. Container always sets 0.0.0.0 internally. |
|
||||
| `ALTHING_PORT` | ✓ (deploy-time) | also accepted | Chamber listens here internally (always 8000 inside the container). |
|
||||
|
||||
Env-var support for `ALTHING_BIND` / `ALTHING_PORT` was added on the
|
||||
galdrabok side as part of the container-deploy cycle (env > config.yaml
|
||||
> defaults precedence).
|
||||
|
||||
## First-deploy sequence (when galdrabok's Dockerfile lands)
|
||||
|
||||
1. Generate a deploy keypair on ana-docker (private stays on host;
|
||||
pubkey lands in `~lkraven/.ssh/authorized_keys`).
|
||||
2. Wire two secrets in `vh/althing` Actions settings:
|
||||
- `DEPLOY_SSH_KEY` — the private key from step 1.
|
||||
- `MGMT_REPO_TOKEN` — Gitea PAT with `read:repository` on this repo,
|
||||
used by the workflow to clone the management repo for the playbook.
|
||||
3. Push to vh/althing's main branch (or trigger `workflow_dispatch`);
|
||||
the Actions runner clones both repos, configures SSH, runs
|
||||
`scripts/elway ana-docker --playbook playbooks/deploy-althing-chamber.yaml --var ref=$SHA`.
|
||||
4. Playbook: clones into `/opt/docker/build/althing-chamber`, builds
|
||||
the image, uploads compose + .env (one-time seed), brings both
|
||||
services up, polls `/health` until 200.
|
||||
Reference in New Issue
Block a user