Skip to main content

Self-Hosting

Deploy CorvidAgent to your own infrastructure — Docker, systemd, or bare metal.

Docker

01

Start with Docker Compose

terminal
$ git clone https://github.com/CorvidLabs/corvid-agent.git
$ cd corvid-agent
$ cp .env.example .env
# Edit .env with your API keys

$ docker compose -f deploy/docker-compose.yml up -d

Builds a multi-stage image (Angular client in stage 1, production server in stage 2). Database persists via a named db-data volume at /app/data.

02

Pass Environment Variables

terminal
$ export ANTHROPIC_API_KEY=sk-ant-...
$ export API_KEY=your-secret-key
$ export LOG_LEVEL=info

$ docker compose -f deploy/docker-compose.yml up -d

The Compose file forwards key variables. You can also set them in your .env file.

03

Verify Image Signatures

terminal
# Verify image signature (Cosign keyless via Sigstore)
$ cosign verify \
  --certificate-identity-regexp "https://github.com/CorvidLabs/corvid-agent" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  ghcr.io/corvidlabs/corvid-agent:latest

# Verify SBOM attestation
$ cosign verify-attestation --type spdxjson \
  --certificate-identity-regexp "https://github.com/CorvidLabs/corvid-agent" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
  ghcr.io/corvidlabs/corvid-agent:latest | jq -r '.payload' | base64 -d | jq .

Released images are signed with Cosign (keyless, via Sigstore/Fulcio) and include an SPDX SBOM attestation.

04

Localnet Docker Networking

.env
# If Algorand localnet runs on the host machine:
LOCALNET_ALGOD_URL=http://host.docker.internal:4001
LOCALNET_KMD_URL=http://host.docker.internal:4002
LOCALNET_INDEXER_URL=http://host.docker.internal:8980

The Compose file includes extra_hosts: ["host.docker.internal:host-gateway"] for Linux compatibility.

systemd

01

Install the Service

terminal
# Install and enable the systemd service
$ ./deploy/daemon.sh install

# Check status
$ systemctl status corvid-agent

# View logs
$ journalctl -u corvid-agent -f

The service unit is at deploy/corvid-agent.service. It runs as a dedicated user with auto-restart on failure.

macOS LaunchAgent

01

Install the LaunchAgent

terminal
# Copy the plist to LaunchAgents
$ cp deploy/com.corvidlabs.corvid-agent.plist ~/Library/LaunchAgents/

# Load and start
$ launchctl load ~/Library/LaunchAgents/com.corvidlabs.corvid-agent.plist

# Check status
$ launchctl list | grep corvid

Starts on login and restarts on crash. Edit the plist to adjust the working directory and environment variables for your setup.

Reverse Proxy

When BIND_HOST=0.0.0.0, always place the server behind a reverse proxy with TLS. Configs are in the deploy/ directory.

Caddy

Caddyfile
corvid.example.com {
  reverse_proxy localhost:3000
}

Automatic HTTPS via Let’s Encrypt. Config at deploy/caddy/.

nginx

nginx.conf
location / {
  proxy_pass http://127.0.0.1:3000;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
}

WebSocket upgrade headers are required for real-time streaming. Config at deploy/nginx/.

Environment Variables

Core Server

PORT 3000
BIND_HOST 127.0.0.1 (use 0.0.0.0 for Docker)
API_KEY auto-generated if exposed
ADMIN_API_KEY for elevated admin ops
ALLOWED_ORIGINS comma-separated CORS origins
LOG_LEVEL debug | info | warn | error
LOG_FORMAT text | json

AI Providers

ANTHROPIC_API_KEY for Claude models
OPENAI_API_KEY for voice TTS/STT
ENABLED_PROVIDERS anthropic,ollama
OLLAMA_HOST http://localhost:11434

Multi-Tenant & Backups

MULTI_TENANT false (set true for isolation)
BACKUP_DIR ./backups
BACKUP_MAX_KEEP 10

Rate Limiting

RATE_LIMIT_GET 600 req/min/IP
RATE_LIMIT_MUTATION 60 req/min/IP

Auth-tier multipliers: public ×0.5, user ×1, admin ×2. Health and WebSocket endpoints are exempt.

Monitoring

Health Endpoints

terminal
# Liveness probe (is the process running?)
$ curl http://localhost:3000/health/live

# Readiness probe (ready for requests?)
$ curl http://localhost:3000/health/ready

Both return HTTP 200 when healthy. Docker healthcheck uses /health/live every 30s. No authentication required.

Logging

LOG_LEVEL debug, info, warn, error
LOG_FORMAT text (human) or json (structured)

Use LOG_FORMAT=json in production for structured log aggregation.

Self-Test Suite

terminal
$ curl -X POST http://localhost:3000/api/selftest/run \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"scope": "all"}'

Scopes: unit, e2e, all. Verifies server health, database integrity, and agent connectivity.

Database Backups

01

Create a Backup

terminal
# Trigger backup (requires ADMIN_API_KEY)
$ curl -X POST http://localhost:3000/api/backup \
  -H "Authorization: Bearer $ADMIN_API_KEY"

# Schedule with cron (every 6 hours)
0 */6 * * * curl -s -X POST http://localhost:3000/api/backup \
  -H "Authorization: Bearer $ADMIN_API_KEY" >> /var/log/corvid-backup.log 2>&1

Performs a WAL checkpoint before copying. Old backups beyond BACKUP_MAX_KEEP are pruned automatically.

02

Restore from Backup

terminal
# Stop the server first

# Replace the database
$ cp backups/corvid-agent-2026-02-28T12-00-00-000Z.db corvid-agent.db

# Remove stale WAL/SHM files
$ rm -f corvid-agent.db-wal corvid-agent.db-shm

# Restart the server
$ bun run start

Upgrading

Bare Metal

terminal
$ git pull origin main
$ bun install
$ bun run build:client
$ bun run start

Migrations run automatically on startup.

Docker

terminal
$ docker compose -f deploy/docker-compose.yml build
$ docker compose -f deploy/docker-compose.yml up -d

Always create a backup before upgrading.