-
Notifications
You must be signed in to change notification settings - Fork 0
CONTAINERS
⚠️ Auto-generated from the repository — do not edit here. Source: https://github.com/luisgf/infrabroker/tree/main/docs
infrabroker ships an official OCI image and a self-contained compose demo. Containers are the fastest way to evaluate the broker and the vehicle for MCP-client installs from the registry; they are not the recommended production layout (see the warning at the end).
ghcr.io/luisgf/infrabroker:<X.Y.Z> # matches each release tag
ghcr.io/luisgf/infrabroker:latest
-
Contents: the six release binaries (
signer,broker,broker-ctl,mcp-broker,mcp-broker-http,control-plane) under/usr/local/bin/, bit-identical to the release archives (the image copies the prebuilt binaries; nothing is compiled in the Dockerfile). -
Base:
distroless/static— CA roots for outbound TLS (signer, OIDC, Azure Key Vault), anonrootuser (uid 65532), and no shell or package manager. The SSH client is pure Go; noopensshinside. -
Entrypoint:
mcp-broker(the stdio MCP frontend — what an MCP client launches). Arguments after the image name go tomcp-broker. -
Architectures:
linux/amd64,linux/arm64.
docker run --rm ghcr.io/luisgf/infrabroker -versionMount a directory with your config.json (and the PKI material it points to)
and pass -i so the MCP client owns stdin/stdout:
docker run -i --rm -v /secure/path:/config \
ghcr.io/luisgf/infrabroker -config /config/config.json
# podman is a drop-in replacement (rootless works):
podman run -i --rm -v /secure/path:/config:Z \
ghcr.io/luisgf/infrabroker -config /config/config.jsonRegister it in Claude Code:
claude mcp add infrabroker -- docker run -i --rm \
-v /secure/path:/config ghcr.io/luisgf/infrabroker -config /config/config.jsonNote that the container needs network reachability to your signer and to the managed hosts. For personal use the native binary is simpler (no mounts, no network namespace to think about) — see the Quickstart.
Everything else in the image is selected with --entrypoint:
docker run --rm --entrypoint /usr/local/bin/signer \
-v /secure/path:/config -p 9443:9443 \
ghcr.io/luisgf/infrabroker -config /config/signer.jsonexamples/compose/ in the repository spins up the full remote-signing
topology against a toy target — nothing touches real servers:
| Service | What it is |
|---|---|
pki-init |
One-shot provisioner: SSH CA, mTLS PKI, service configs into a volume |
signer |
Holds the CA key and the policy (only broker-1 may reach host demo) |
sshd |
Toy target host trusting the demo CA (TrustedUserCAKeys), user demo
|
broker |
HTTP+mTLS frontend — runs without the CA key (remote signing) |
git clone https://github.com/luisgf/infrabroker && cd infrabroker/examples/compose
docker compose up --build -d # or: podman compose up --build -d
# health via each service's monitor endpoint (plain HTTP, demo-only — the
# real listeners are the mTLS APIs; monitor is bound to 127.0.0.1 here):
curl -s http://127.0.0.1:9160/healthz && curl -s http://127.0.0.1:9180/healthzRun a command through the broker (the sshd container carries curl and the
demo agent's client certificate, so it doubles as the "agent" for testing):
docker compose exec sshd curl -s \
--cacert /demo/pki/agents_ca.crt \
--cert /demo/pki/agent.crt --key /demo/pki/agent.key \
https://broker:8443/v1/ssh_run -d '{"host":"demo","command":"id"}'
# {"stdout":"uid=1000(demo) ...","stderr":"","exit_code":0,"serial":...}What just happened: the broker generated an ephemeral Ed25519 key in RAM,
asked the signer for a certificate scoped to host:demo with a TTL of
minutes, opened the SSH connection itself and returned only the output. See
the same serial on both sides of the trust boundary:
docker compose exec sshd sh -c 'tail -1 /demo/state/signer_audit.log' # outcome: issued
docker compose exec sshd sh -c 'tail -1 /demo/state/broker_audit.log' # outcome: executedAccess is scoped by host and caller — an undeclared host is refused (404),
and the signer only mints certs for host demo to caller broker-1:
docker compose exec sshd curl -s --cacert /demo/pki/agents_ca.crt \
--cert /demo/pki/agent.crt --key /demo/pki/agent.key \
https://broker:8443/v1/ssh_run -d '{"host":"prod-db","command":"id"}'
# unknown host: "prod-db" (404)This shows host/caller scoping, not the per-command firewall: the demo host
declares no command_policy, so any command runs on demo. The command
allow/deny/require_approval engine (with a 403 on denial) is a separate
layer — see Architecture: AI-action firewall
and Tool usage.
Connect Claude Code to the demo over stdio (the provisioner also wrote an
mcp.json for this):
claude mcp add infrabroker-demo -- docker run -i --rm \
--network infrabroker-demo -v infrabroker-demo-state:/demo \
ghcr.io/luisgf/infrabroker -config /demo/mcp.jsonThen ask the model to run something on demo (ssh_execute) — and watch the
audit log grow. Tear everything down (PKI and state included):
docker compose down -vRe-running up re-provisions from scratch; up over a live volume is a no-op
(the provisioner is idempotent).
The demo avoids Docker-only features on purpose: explicit project, network and
volume names (infrabroker-demo, infrabroker-demo-state) so the stdio
one-liner works identically, and healthcheck/depends_on conditions from the
compose spec. It requires either podman compose delegating to the
docker-compose provider or podman-compose recent enough to support
depends_on: condition:. Rootless podman works — nothing in the demo needs
privileged ports on the host.
!!! warning "Demo ≠ production"
The demo trades away everything the hardened deployment is about: all
material lives in one volume, services share it, TTLs and cert lifetimes
are short but the PKI is self-signed and disposable. Production runs each
service as its own system user via deploy/install.sh (systemd), with
per-service PKI directories and optionally the CA key in Azure Key Vault —
see Operations and the
deploy README.
!!! note "Kubernetes: target vs runtime"
infrabroker already brokers access to Kubernetes clusters (the k8s_*
tools: per-operation bound ServiceAccount tokens, default-deny policy —
see Tool usage §10). Running the
broker itself inside a cluster (manifests/Helm) is deliberately not
shipped yet; it is on the roadmap and needs its own answer for CA-key
custody in-cluster. The image works fine as a building block if you roll
your own.