Deployment
Artic runs as a Docker Compose stack with a hub service and dynamically spawned agent containers.
Docker Compose
Configuration
The docker-compose.yml defines the hub service:
services:
hub:
build: hub/
ports:
- "9000:9000"
environment:
- DATABASE_URL=postgresql+asyncpg://user:pass@host:5432/artic
- INTERNAL_SECRET=artic-dev-secret
- JWT_SECRET=artic-jwt-dev-secret
- TWELVE_DATA_API_KEY=your-key # optional
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- artic-net
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
artic-net:
driver: bridge
Key Details
- Docker Socket Mount: The hub needs access to Docker to spawn agent containers
- Network: All containers share
artic-net(bridge driver) - Agent DNS: Containers are addressable as
artic-agent-{container-id}:8000 - Port Allocation: Hub allocates ports atomically via thread-safe lock (
hub/docker/ports.py)
Starting the Stack
# Start hub
docker compose up -d
# View logs
docker compose logs -f hub
# Stop everything
docker compose down
Database Setup
PostgreSQL
Artic requires a PostgreSQL database. Options:
Option 1: External PostgreSQL
DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/artic
Option 2: Add PostgreSQL to docker-compose.yml
services:
db:
image: postgres:16
environment:
POSTGRES_DB: artic
POSTGRES_USER: artic
POSTGRES_PASSWORD: secret
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
Migrations
Database migrations are managed by Alembic:
cd hub
alembic upgrade head
Environment Variables
Required
| Variable | Purpose |
|---|---|
DATABASE_URL | PostgreSQL connection string |
INTERNAL_SECRET | Agent→Hub push authentication |
JWT_SECRET | JWT token signing key |
Optional
| Variable | Purpose |
|---|---|
TWELVE_DATA_API_KEY | Candle data (rate-limited 8 req/min) |
CMC_API_KEY | CoinMarketCap token metadata |
OPENAI_API_KEY | OpenAI LLM provider |
ANTHROPIC_API_KEY | Anthropic LLM provider |
DEEPSEEK_API_KEY | DeepSeek LLM provider |
GEMINI_API_KEY | Google Gemini LLM provider |
HASHKEY_API_KEY | HashKey Global exchange |
HASHKEY_SECRET | HashKey Global signing |
HASHKEY_SANDBOX | true for sandbox mode |
HSK_RPC_URL | HashKey Chain RPC endpoint |
HSK_PRIVATE_KEY | On-chain logger private key |
TELEGRAM_BOT_TOKEN | Telegram bot client |
Production Considerations
Security
- Change
INTERNAL_SECRETandJWT_SECRETto strong random values - Store all API keys in encrypted DB secrets, not
.env - Use TLS termination (nginx/Caddy) in front of hub
Networking
- Hub port 9000 should be behind a reverse proxy
- Agent containers communicate internally on
artic-net - Agent ports are internal-only (not exposed to host)
Monitoring
- Hub health:
GET /health - Agent health: Hub polls each container's
/healthendpoint - WebSocket for real-time client monitoring
- Log entries persisted to PostgreSQL for historical analysis
Scaling
- Each agent runs in its own Docker container
- Hub manages container lifecycle and resource allocation
- Agents are stateless (state in PostgreSQL) — can be restarted without data loss
