mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 12:31:29 +00:00
docs(readme): fix demo path command — point at deploy/demo-up.sh wrapper
Operator reproduction (verbatim log captured 2026-05-14):
$ docker compose -f deploy/docker-compose.yml -f deploy/docker-compose.demo.yml up -d --build
... build succeeds, containers come up ...
dependency failed to start: container certctl-server is unhealthy
$ docker compose ... logs certctl-server | tail -1
certctl-server | Failed to load configuration: phase-2 SEC-H3
fail-closed guard (missing TS): CERTCTL_DEMO_MODE_ACK=true requires
CERTCTL_DEMO_MODE_ACK_TS=<unix-epoch> set within the last 24h —
refuse to start.
Root cause
==========
README.md L95 documented a bare `docker compose ... up` command that
ignores the Phase 2 SEC-H3 fail-closed guard added in
internal/config/config.go::Validate (commit 2026-05-13). The guard
pairs CERTCTL_DEMO_MODE_ACK=true with a required
CERTCTL_DEMO_MODE_ACK_TS=<unix-epoch> that must be within the last
24h, so a forgotten demo deploy doesn't accidentally end up serving
production traffic with auth-type=none.
The demo overlay (deploy/docker-compose.demo.yml) passes the
timestamp through from the shell via
`CERTCTL_DEMO_MODE_ACK_TS: "${CERTCTL_DEMO_MODE_ACK_TS:-}"`. The
README command never exported it, so the server saw an empty value,
the guard refused to boot, the healthcheck never passed, and the
dependent certctl-agent container refused to start.
The deploy/demo-up.sh wrapper (which already exists; it's used by
CI cold-DB smoke and was added in the same SEC-H3 commit chain)
mints `CERTCTL_DEMO_MODE_ACK_TS="$(date +%s)"` before exec'ing
`docker compose` with the same -f flags. Drop-in replacement for
the bare compose invocation.
Fix
===
README.md "Demo path" code block now points at the wrapper script:
./deploy/demo-up.sh -d --build
Plus a one-paragraph explanation of why the wrapper is the supported
entry point and what the SEC-H3 timestamp gate is defending against.
The bare `docker compose ... up` form is documented as failing-closed
so a future operator who tries it understands the error message they
see.
Affected paths
==============
- README.md (the Quick Start "Demo path" block; lines 92-100 before,
93-103 after this change)
Out of scope (tracked separately if needed)
============================================
- The `WARN[0000] ... defaulting to a blank string` lines on docker
compose stdout (POSTGRES_PASSWORD, CERTCTL_API_KEY, etc.) are red
herrings — they fire on the BASE compose's env interpolation but
the demo overlay immediately overrides those with hardcoded
demo-safe values. They're noise; not a footgun. Leaving them
alone — silencing the WARN would require either an .env shim or
setting empty defaults at the base layer, both of which are
worse than the current warn-but-correct behaviour.
- The bare `docker compose -f base.yml up` production path
(README L108) is unchanged. That path requires a real .env and
will fail closed on placeholders — which is the correct
behaviour. The README already documents .env setup for that
path.
This commit is contained in:
@@ -92,10 +92,12 @@ Security: three authentication paths — API keys (SHA-256 hashed + constant-tim
|
||||
```bash
|
||||
git clone https://github.com/certctl-io/certctl.git
|
||||
cd certctl
|
||||
docker compose -f deploy/docker-compose.yml -f deploy/docker-compose.demo.yml up -d --build
|
||||
./deploy/demo-up.sh -d --build
|
||||
```
|
||||
|
||||
Wait ~30 seconds, then open **https://localhost:8443** in your browser. The demo overlay flips the base into demo-mode auth (every request served as the synthetic admin actor `actor-demo-anon` — the server emits a prominent ⚠ DEMO MODE banner at boot reminding you this posture is for evaluation only) and seeds 180 days of realistic history across 13 issuers, 8 agents, managed + discovered certs, jobs, deploys, audit, and notification events. The `certctl-tls-init` init container self-signs an ECDSA-P256 cert on first boot — accept the browser warning for the demo, or feed the generated `ca.crt` to your client.
|
||||
Wait ~30 seconds, then open **https://localhost:8443** in your browser. The `demo-up.sh` wrapper exports a fresh `CERTCTL_DEMO_MODE_ACK_TS=$(date +%s)` and forwards the remaining args to `docker compose -f docker-compose.yml -f docker-compose.demo.yml up`. The timestamp export is required by the Phase 2 SEC-H3 fail-closed guard in `internal/config/config.go::Validate` — demo deploys must re-ACK every 24h so a forgotten demo container never silently ends up serving production traffic with `auth-type=none`. The bare `docker compose ... up` command without the timestamp refuses to boot; the wrapper script is the supported entry point.
|
||||
|
||||
The demo overlay flips the base into demo-mode auth (every request served as the synthetic admin actor `actor-demo-anon` — the server emits a prominent ⚠ DEMO MODE banner at boot reminding you this posture is for evaluation only) and seeds 180 days of realistic history across 13 issuers, 8 agents, managed + discovered certs, jobs, deploys, audit, and notification events. The `certctl-tls-init` init container self-signs an ECDSA-P256 cert on first boot — accept the browser warning for the demo, or feed the generated `ca.crt` to your client.
|
||||
|
||||
**Production path — `.env` required, fail-closed on placeholders:**
|
||||
|
||||
|
||||
Reference in New Issue
Block a user