The supported Base deployment path is Docker Compose on a single host.
Entrypoint: deploy/compose/docker-compose.yml
One-command install (creates local secret files and starts services):
./deploy/compose/install-master.sh --project-name base-mission-master --port 3180Exact cardinality after install:
| Service | Role |
|---|---|
base-master-validator |
Master API, coordination, aggregation, health/version, digest-aware challenge watcher |
master-postgres |
PostgreSQL 16 control plane (private) |
challenge-prism |
One long-lived combined Prism challenge service |
Cardinality is exactly one application container, one PostgreSQL container, and one long-lived container per active challenge. There is no gateway, broker sidecar, challenge PostgreSQL, evaluator, or worker sidecar service in this topology.
The watcher runs inside base-master-validator and is the only supported challenge
auto-update path:
- Resolve approved immutable image pin (
repository@sha256:<digest>). - Persist desired/current digest and rollout phase (durable intent).
- Controlled pull of the desired image.
- Targeted recreate of only the affected Compose service (project boundary).
- Health + version verification before commit.
- On failure: restore previous digest, bounded backoff, resume after restart.
It never mutates live Swarm fabric, never runs evaluator containers, and only acts inside the configured Compose project.
Each validator Compose install enables a host-side timer by default
(base-validator-image-updater@<project>.timer) that tracks
ghcr.io/baseintelligence/base-validator-runtime:latest by digest, rewrites
project .env pins atomically, and recreates only the agent service. Runtime
is always repository@sha256:<digest> (never bare :latest). Image auto-update
remains host-side even though shipping Compose also mounts host docker.sock
into the agent (prod prep for a later challenges-on-validator path). Opt out
with install-validator.sh --no-auto-update.
dbnetwork: internal bridge. Master + PostgreSQL only. No host publication of5432.appnetwork: internal bridge. Master + challenge services.- Only the master public API is published, bound to loopback in the test range
3100-3199(default3180).
Secrets are host files (mode 0600, parent dirs 0700), bind-mounted read-only.
Compose manifests never embed secret values. Production failed-closed when the
required *_FILE paths are missing, empty, world/group-readable, or replaced by
inline environment secrets. Operator-local state for greenfield install lives
under ${XDG_STATE_HOME:-~/.local/state}/base-compose/<project>/.
Every deployable first-party reference is immutable: repository@sha256:<64 hex>. Mutable latest tags are rejected by the contract tests.
Base and Prism do not launch evaluator containers. Prism runs in PRISM_COMBINED_MODE=true and verifies/ingests external results. External long-lived TEE runtimes are never lifecycle-managed by this Compose project.
Validators never run master. An independent validator install is agent-only
(no master app, PostgreSQL control plane, or challenge services). Shipping
Compose mounts host docker.sock into the agent for later challenges-on-validator
migration prep; it does not add a master/postgres/challenges stack.
--master-url / validator.agent.master_url is a client pointer to the
Base master / coordination API the operator actually runs.
Do not conflate these roles:
| Concept | Role |
|---|---|
master_url (--master-url) |
Base master coordination API (register/heartbeat/pull/result). Required and explicit. |
registry_url / weights_url |
Public registry / weights aliases. When the master hosts both, installers set them equal to master_url. Product docs may also document network defaults separately. |
| Hostname | Role | Operator guidance |
|---|---|---|
https://chain.joinbase.ai |
Authoritative public Base master API for this network (role=master). Settings defaults, installer samples, and public weights examples use this host. |
Network validators: --master-url https://chain.joinbase.ai. Verify GET /health returns role=master / ready. |
http://127.0.0.1:<port> or private operator master |
Disposable local smoke / private operator control plane | Allowed when the operator explicitly passes that URL; never invented as a silent default. |
Docker Compose installers must not invent alternate public master hostname or IP
defaults. Historical Swarm advertise addresses under deploy/swarm/ are unsupported
for greenfield Compose installs.
Entrypoint: deploy/compose/docker-compose.validator.yml
One-command install for an independent validator (no master source tree required once artifacts and image pins exist):
# Public network shipping example
./deploy/compose/install-validator.sh \
--project-name base-validator-live \
--master-url https://chain.joinbase.ai
# Local disposable master only (secondary smoke/dev)
# ./deploy/compose/install-validator.sh \
# --project-name base-mission-validator-a \
# --master-url http://127.0.0.1:3180Or, with only the validator deployment artifacts on a clean host directory:
docker compose -p base-validator-live \
-f docker-compose.validator.yml --env-file .env up -dEach validator is an independent Compose project with its own network, volume, protocol identity, optional submission wallet, and credentials. Required inputs:
| Input | Role |
|---|---|
COMPOSE_PROJECT_NAME |
Unique project name (distinct network + state volume) |
BASE_VALIDATOR_IMAGE_* |
Immutable image repository + sha256 digest |
BASE_VALIDATOR_CONFIG |
Host path to validator.yaml (validator.agent.master_url required) |
BASE_VALIDATOR_PROTOCOL_IDENTITY |
Host directory for the protocol signing wallet |
BASE_VALIDATOR_BROKER_TOKEN |
Host secret file mounted read-only |
BASE_DOCKER_GID / BASE_DOCKER_SOCKET |
Host docker group + socket path (group_add + bind) |
Validators never receive master PostgreSQL credentials, challenge volumes, aggregation controls, or master challenge lifecycle operators. Host docker.sock is mounted into the agent (uid 1000 + group_add docker GID) for production prep; the project remains agent-only. Teardown of one validator project does not affect another validator or the master:
docker compose -p base-mission-validator-a -f docker-compose.validator.yml down
# preserve identity/state for reinstall, or add -v to drop disposable stateThe validator service runs read_only: true with user: "1000:1000". Writable surfaces are:
| Path | Purpose |
|---|---|
/var/lib/base/state (named volume) |
Runtime state + HOME (defaults to this path so bittensor can write $HOME/.bittensor) |
/tmp (tmpfs) |
Temporary files |
Do not set HOME to /var/lib/base: that path is not itself a volume, so bittensor membership/wallet caches fail with read-only filesystem errors. install-validator.sh and docker-compose.validator.yml default HOME=/var/lib/base/state.
Protocol identity (BASE_VALIDATOR_PROTOCOL_IDENTITY → /var/lib/base/identity) is mounted read-only. Bind a real directory tree with parents traversable by uid 1000 (typically parent mode 0755). A host symlink whose parent is mode 0700 prevents wallet load inside the container even when the leaf wallet files look correct.
Operator scripts live next to the manifests (mode-aware, Compose-only, no Swarm):
# Control-plane PostgreSQL + provenance metadata (no secret values in artifacts)
./deploy/compose/backup-master.sh --project-name base-mission-master --output-dir ./backup-master
./deploy/compose/restore-master.sh --project-name base-mission-master --backup-dir ./backup-master
# Challenge-owned SQLite volume (Prism long-lived data)
./deploy/compose/backup-challenge.sh --project-name base-mission-master --service challenge-prism
# Non-destructive teardown retains postgres/challenge volumes
./deploy/compose/teardown-master.sh --project-name base-mission-master
# Explicit data destruction of owned volumes only
./deploy/compose/teardown-master.sh --project-name base-mission-master --destroy-dataProduction rejects inline or missing file-backed secrets (admin_token_file mode
0600 / parent 0700) and never embeds secret values in Compose YAML or /metrics.
Operational metrics for the weight plane are exposed on GET /metrics
(low-cardinality counters: accepted/rejected/replay pushes, aggregation outcomes,
fetch failures, submit outcomes) without tokens or DSN material.
- Docker Swarm installers, overlays, secrets, replicated jobs, placement constraints
- LLM gateway services, tokens, routes, and provider clients
- Application-launched
docker run/docker compose runevaluator jobs
Historical deploy/swarm/ material is not a supported operator path for new installs.