Complete guide to installing and running Arkon.
| Requirement | Minimum | Recommended |
|---|---|---|
| Docker + Docker Compose | v20+ / v2+ | Latest |
| RAM | 2 GB | 4 GB |
| Disk | 5 GB | 20 GB |
| Ports | 3000 (app), 5432 (database) | — |
No Node.js, PostgreSQL, or other dependencies needed — Docker handles everything.
git clone https://github.com/arkon-ai/arkon.git
cd arkoncp .env.example .envEdit .env with your preferred editor. At minimum, set these:
# Database password (also used by Docker Compose to create the DB)
POSTGRES_PASSWORD=your-secure-password
# Admin login passphrase (min 12 characters)
MC_ADMIN_TOKEN=your-admin-passphrase-here
# Agent authentication tokens (tenant:token pairs)
MC_AGENT_TOKENS=default:your-agent-token-here
# Base URL (where Arkon is accessible)
ARKON_BASE_URL=http://localhost:3000
# Session encryption (generate with: openssl rand -base64 32)
NEXTAUTH_SECRET=your-generated-secret-here
NEXTAUTH_URL=http://localhost:3000See .env.example for all optional variables (notifications, gateway integration, infrastructure monitoring).
docker compose up -dThis starts:
- arkon — The application on port 3000
- db — TimescaleDB (PostgreSQL) on port 5432
Migrations run automatically on first startup.
Open http://localhost:3000 in your browser. The setup wizard guides you through:
- Create your account — Organization name, admin email, password
- Register your first agent — Name, framework, generates an API token
- Install the SDK — Copy-paste integration code for your framework
- Send your first event — Test button or curl command
- Explore — Quick links to key features
Using the token generated during setup:
curl -X POST http://localhost:3000/api/ingest \
-H "Authorization: Bearer YOUR_AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "message_sent",
"agent": "my-agent",
"content": "Hello from my agent!",
"metadata": { "model": "claude-sonnet-4-6", "tokens": 150 }
}'You should see the event appear on the dashboard within seconds.
To monitor your servers' health, register nodes in Arkon and set up metric reporting.
Option A: Push-based (recommended)
Create a reporter script on each server that POSTs metrics to /api/infra/report:
#!/bin/bash
curl -s -X POST https://your-arkon-url/api/infra/report \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"hostname\": \"$(hostname)\",
\"cpu_percent\": $(cat /proc/loadavg | awk '{print $1 * 100 / '$(nproc)'}'),
\"memory_percent\": $(free | awk '/Mem:/ {printf "%.1f", $3/$2 * 100}'),
\"disk_percent\": $(df / | awk 'NR==2 {print $5}' | tr -d '%')
}"Schedule with cron: * * * * * /path/to/reporter.sh
Option B: SSH-based collection
Configure MC_CRON_KEY_PATH in .env and register nodes with SSH credentials via the API.
# Check what's using the port
lsof -i :3000
# Or change the port in .env and docker-compose.ymlNote: Arkon defaults to port 3000. If you change the port (via the
PORTenvironment variable or inecosystem.config.js), make sure your reverse proxy config points to the same port.
# Check the database container is running
docker compose ps
docker compose logs db# Re-run migrations
docker compose exec arkon npx tsx scripts/migrate.ts
# Or check the logs
docker compose logs arkon | grep -i migration- Check the agent token matches one in
MC_AGENT_TOKENS - Check the ingest endpoint is reachable:
curl http://localhost:3000/api/health - Check application logs:
docker compose logs arkon -f
docker compose down -v # removes containers AND database volume
docker compose up -d # fresh startgit pull origin main
docker compose build
docker compose up -dMigrations run automatically on startup. Your data is preserved in the database volume.
For production use:
- Use a strong
MC_ADMIN_TOKEN— this is your login password - Generate a real
NEXTAUTH_SECRET—openssl rand -base64 32 - Put Arkon behind a reverse proxy (Nginx, Caddy, Traefik) with TLS
- Set
ARKON_BASE_URLto your public HTTPS URL - Back up the database — schedule
pg_dumpvia cron - Monitor disk usage — TimescaleDB hypertables grow with event volume
Example Nginx config:
server {
listen 443 ssl;
server_name arkon.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/arkon.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/arkon.yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000; # Must match the PORT in your .env / ecosystem.config.js
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}