Deployment Guide
This guide covers deploying the oracle and agent services as Docker containers.
Infrastructure Overview
graph TB
subgraph Oracle Machine
oracle[moog-oracle container]
oracle-secrets[secrets.yaml<br/>oracle-wallet.json]
end
subgraph Agent Machine
agent[moog-agent container]
agent-secrets[secrets.yaml<br/>agent-wallet.json<br/>docker/config.json]
docker[Docker socket]
end
subgraph External Services
mpfs[MPFS Service]
cardano[Cardano Blockchain<br/>preprod]
github[GitHub API]
antithesis[Antithesis Platform]
end
oracle --> mpfs
oracle --> github
agent --> mpfs
agent --> antithesis
agent --> docker
mpfs --> cardano
oracle-secrets -.-> oracle
agent-secrets -.-> agent
Prerequisites
- Docker and Docker Compose on each machine
- Cardano wallets for both oracle and agent roles (created with
moog wallet create) - GitHub PAT with
reposcope for the oracle (used to validate requests against GitHub) - GitHub PAT with
reposcope for the agent (used to download test assets) - Antithesis credentials for the agent (registry password, platform user)
- MPFS service accessible from both machines (default:
https://mpfs.plutimus.com) - Moog token already created by the oracle (
moog oracle token boot)
Oracle Deployment
Secrets setup
Create the secrets directory:
/secrets/moog-oracle/oracle.json — the oracle wallet file (from moog wallet create).
/secrets/moog-oracle/secrets.yaml:
githubPAT: ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
walletPassphrase: your_wallet_passphrase # if wallet is encrypted
Docker Compose
Use the compose file from CD/moog-oracle/docker-compose.yaml:
services:
moog-oracle:
image: ghcr.io/cardano-foundation/moog/moog-oracle:${MOOG_VERSION:-latest}
secrets:
- oracle-wallet
- secrets
environment:
- MOOG_MPFS_HOST=https://mpfs.plutimus.com
- MOOG_WALLET_FILE=/run/secrets/oracle-wallet
- MOOG_TOKEN_ID=<your-token-id>
- MOOG_SECRETS_FILE=/run/secrets/secrets
- MOOG_WAIT=240
restart: always
volumes:
- tmp:/tmp
secrets:
oracle-wallet:
file: /secrets/moog-oracle/oracle.json
secrets:
file: /secrets/moog-oracle/secrets.yaml
volumes:
tmp:
Start and verify
Look for log lines showing successful polling and validation cycles. The oracle polls every MOOG_WAIT seconds (default 240).
Agent Deployment
Secrets setup
Create the secrets directory:
/secrets/moog-agent/agent.json — the agent wallet file.
/secrets/moog-agent/docker/config.json — Docker registry credentials for pulling/pushing Antithesis images.
/secrets/moog-agent/secrets.yaml:
agentEmail: agent@example.com
agentEmailPassword: xxxx-xxxx-xxxx-xxxx # Google app password
githubPAT: ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
antithesisPassword: your_antithesis_password
slackWebhook: https://hooks.slack.com/services/... # optional
trustedRequesters: # optional, ignored when --trust-all-requesters is used
- requester_pkh_1
- requester_pkh_2
Docker Compose
Use the compose file from CD/moog-agent/docker-compose.yaml:
services:
moog-agent:
image: ghcr.io/cardano-foundation/moog/moog-agent:${MOOG_VERSION:-latest}
secrets:
- agent-wallet
- secrets
- source: docker
target: /run/secrets/docker/config.json
environment:
- MOOG_MPFS_HOST=https://mpfs.plutimus.com
- MOOG_WALLET_FILE=/run/secrets/agent-wallet
- MOOG_TOKEN_ID=<your-token-id>
- MOOG_SECRETS_FILE=/run/secrets/secrets
- MOOG_WAIT=240
- MOOG_ANTITHESIS_USER=cardano
- DOCKER_CONFIG=/run/secrets/docker
restart: always
privileged: true
command: "--poll-interval 60 --minutes 1440 --trust-all-requesters"
volumes:
- tmp:/tmp
- /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt:ro
- /var/run/docker.sock:/var/run/docker.sock:rw
secrets:
agent-wallet:
file: /secrets/moog-agent/agent.json
secrets:
file: /secrets/moog-agent/secrets.yaml
docker:
file: /secrets/moog-agent/docker/config.json
volumes:
tmp:
Privileged mode and Docker socket
The agent container requires privileged mode and access to the Docker socket because it runs docker compose to validate test assets locally before pushing them to Antithesis. See Security for implications.
Start and verify
The agent polls for pending test runs every --poll-interval seconds (default 60) and checks for email results within the --minutes window.
Environment Variables Reference
| Variable | Used by | Description |
|---|---|---|
MOOG_MPFS_HOST |
oracle, agent | URL of the MPFS service |
MOOG_WALLET_FILE |
oracle, agent | Path to the wallet JSON file |
MOOG_TOKEN_ID |
oracle, agent | The moog token asset ID on Cardano |
MOOG_SECRETS_FILE |
oracle, agent | Path to secrets.yaml |
MOOG_WAIT |
oracle, agent | Seconds between polling cycles |
MOOG_ANTITHESIS_USER |
agent | Antithesis platform username |
DOCKER_CONFIG |
agent | Path to Docker config directory (for private registries) |
Service Lifecycle
sequenceDiagram
participant O as Oracle
participant M as MPFS
participant GH as GitHub
participant A as Agent
participant AT as Antithesis
loop Every MOOG_WAIT seconds
O->>M: Query pending requests
O->>GH: Validate requests (users, roles, repos)
O->>M: Submit state update transaction
end
loop Every poll-interval seconds
A->>M: Query pending test runs
A->>GH: Download test assets
A->>A: Local docker compose validation
A->>AT: Push test to Antithesis
A->>M: Report test acceptance
end
loop Every poll-interval seconds
A->>A: Check email for results
A->>M: Report test completion
end
PAT Management
GitHub Personal Access Tokens are required by both oracle and agent for GitHub API access.
Scope requirements
repo— needed to access repository contents, CODEOWNERS files, and user profile repos
Rotation
PATs have an expiration date. When a PAT expires:
- The oracle/agent will receive 401 errors from GitHub API
- All validation requests will fail
- The service will continue polling but accomplish nothing, burning rate limit on failed auth
To rotate a PAT:
- Create a new PAT at github.com/settings/tokens
- Update
secrets.yamlwith the new token - Restart the service:
docker compose restart
Set a calendar reminder
Create a reminder 1 week before PAT expiry to avoid service disruption.
Rate limits
GitHub API has a per-user rate limit of 5,000 requests/hour. This limit is shared across all PATs belonging to the same GitHub user. If both oracle and agent use PATs from the same user, they share the 5,000 request budget.
See Troubleshooting for diagnosing PAT issues.
Monitoring
Log checking
Health verification
# Check pending requests
moog token | jq '.requests | length'
# Check system facts
moog facts test-runs pending --pretty
# Check GitHub rate limit
curl -s -H "Authorization: token <PAT>" \
https://api.github.com/rate_limit | jq '.rate'
Updating
Image version bump
Configuration changes
For changes to secrets.yaml or environment variables, restart the service:
No state is lost on restart — the service resumes polling from the current on-chain state.