Quickstart for the Compose-based local + CI deployment stack (issue #60).
This document covers the Compose-based deployment of echidnabot — a reproducible local-dev / CI-smoke stack that brings up:
-
postgres— PostgreSQL 16 (alpine) persistence layer -
echidnabot— the bot itself, built from the rootContainerfile -
echidna-server— optional canned-JSON stub of the ECHIDNA REST API, enabled under--profile dev
Per estate policy the file is compose.yml (Compose v2 canonical name),
omits the deprecated top-level version: key, and works with both
docker compose and podman-compose.
|
Note
|
This stack is sized for development + CI smoke. Production deployment
recommendations (HA Postgres, secrets management, ingress, observability)
are out of scope here — see ROADMAP.adoc "Deployment" section for the
remaining work.
|
-
Docker 24+ with the
composeplugin (docker compose version≥ v2.20), OR Podman 4+ withpodman-compose -
~2 GB free disk for the Postgres image + Rust build cache
-
No host port conflicts on 8080 (echidnabot)
# 1. Clone + branch (replace with your fork if you're contributing)
git clone https://github.com/hyperpolymath/echidnabot.git
cd echidnabot
# 2. Configure environment (copy the template, edit secrets)
cp .env.example .env
$EDITOR .env
# 3. Bring up the core stack (postgres + echidnabot)
docker compose up -d
# 4. Verify
docker compose ps
docker compose logs -f echidnabot
curl -s http://127.0.0.1:8080/healthTo also bring up the canned-JSON ECHIDNA stub (no real prover orchestrator needed for end-to-end smoke):
docker compose --profile dev up -d
curl -s http://127.0.0.1:9100/api/provers # only if you publish that portThe stub is on the internal Compose network only — it’s reached by
echidnabot via DNS name echidna-server:9100.
| Service | Image | Notes |
|---|---|---|
|
|
Pinned major; named volume |
|
Built from |
Publishes |
|
|
Optional, profile |
Single bridge network echidnabot-net. Services resolve each other
by name: postgres, echidnabot, echidna-server.
| Name | Purpose |
|---|---|
|
Postgres data dir (mounted at |
Migrations under ./migrations/ are bind-mounted read-only into
/docker-entrypoint-initdb.d/ on the Postgres service. The Postgres
official image only runs init scripts on first boot (empty data
dir); subsequent schema changes should land via sqlx-migrate at
echidnabot startup once the PostgresStore backend is wired.
All configuration is driven through .env (see .env.example for
the full template). Highlights:
| Variable | Meaning |
|---|---|
|
Credentials for the Postgres service. The defaults are obviously fake
( |
|
sqlx-compatible Postgres URL. Default points at the in-stack
|
|
Where echidnabot’s dispatcher POSTs verification requests. Defaults to
the in-stack stub ( |
|
Optional. Leave commented for a no-platform smoke; uncomment to wire the GitHub adapter. |
|
Optional. Points at a local Jaeger / Tempo / OTel collector. Consumed by the OpenTelemetry path landing in PR #65. |
|
Standard |
The first-boot init runs migrations/*.sql automatically. To re-apply
against an existing DB (idempotent — uses IF NOT EXISTS):
docker compose exec -T postgres \
psql -U "${POSTGRES_USER:-echidnabot}" -d "${POSTGRES_DB:-echidnabot}" \
< migrations/20260602000001_initial_schema.sqldocker compose exec postgres \
psql -U "${POSTGRES_USER:-echidnabot}" -d "${POSTGRES_DB:-echidnabot}"docker compose build echidnabot
docker compose up -d echidnabotValidate the compose file syntax + interpolation without launching anything
(requires a .env file — copy from .env.example first):
cp .env.example .env # one-time
docker compose config # core stack
docker compose --profile dev config # including stub
podman-compose config # Podman pathEvery service has a healthcheck:
-
postgres—pg_isreadyevery 5 s, ready after ~10 s -
echidnabot—/healthover/dev/tcpevery 10 s, ready after ~20 s -
echidna-server—wget --spider /healthevery 10 s
echidnabot.depends_on.postgres uses condition: service_healthy so
the bot won’t start until Postgres accepts connections.
GitHub Actions can drive this stack directly:
- name: Bring up stack
run: docker compose --profile dev up -d --wait
- name: Smoke test
run: |
curl -fsS http://127.0.0.1:8080/health
docker compose exec -T postgres \
psql -U echidnabot -d echidnabot -c '\dt'
- name: Tear down
if: always()
run: docker compose --profile dev down -vThe --wait flag blocks until every service reaches healthy, which
removes the need for ad-hoc sleep calls.
-
PostgresStore not yet wired: the runtime currently uses the SQLite backend (
src/store/sqlite.rs). Addingsrc/store/postgres.rs+ an sqlx feature toggle is a separate piece of work; this stack provisions Postgres so that work can land cleanly on top. -
No Kubernetes / Helm: out of scope for issue #60. Tracked in
ROADMAP.adoc"Deployment" section. -
No pre-built prover images: the
echidna-serverservice here is a stub, not a real prover orchestrator. Pre-built prover images are a separate (gated) roadmap item.