Skip to main content
Calseta is designed for self-hosting. A single docker compose up starts everything you need.

Prerequisites

  • Docker and Docker Compose v2
  • At least 2 GB RAM
  • PostgreSQL 15+ (included in Docker Compose, or bring your own)

Quick Start

git clone https://github.com/calseta/calseta.git
cd calseta
cp .env.local.example .env
docker compose up
Three services start:
ServicePortDescription
api8000FastAPI REST API
mcp8001MCP server (SSE transport)
db5432PostgreSQL 15
A worker process runs inside the API container, processing enrichment, webhook dispatch, and workflow execution from the task queue.

Environment Configuration

All configuration is via environment variables. Copy .env.local.example for development or .env.prod.example for production.

Required Variables

VariableDescription
DATABASE_URLPostgreSQL connection string (postgresql+asyncpg://...)
ENCRYPTION_KEYKey for encrypting auth configs at rest

Enrichment Provider Keys

VariableDescription
VIRUSTOTAL_API_KEYVirusTotal v3 API key
ABUSEIPDB_API_KEYAbuseIPDB v2 API key
OKTA_DOMAINOkta domain (e.g., company.okta.com)
OKTA_API_TOKENOkta API token
ENTRA_TENANT_IDMicrosoft Entra tenant ID
ENTRA_CLIENT_IDEntra application (client) ID
ENTRA_CLIENT_SECRETEntra client secret
Enrichment providers without configured keys are automatically disabled — they won’t block other providers or cause errors.

Optional Configuration

VariableDefaultDescription
LOG_FORMATtextjson for production, text for development
LOG_LEVELINFODEBUG, INFO, WARNING, ERROR, CRITICAL
CORS_ALLOWED_ORIGINSComma-separated origins (disabled by default)
RATE_LIMIT_DEFAULT_PER_MINUTE60Default rate limit
MAX_REQUEST_BODY_SIZE_MB10Maximum request body size
APPROVAL_NOTIFIERnoneWorkflow approval channel: slack, teams, none

Database Setup

Using Docker Compose (default)

The included docker-compose.yml runs PostgreSQL 15 with a named volume for persistence. No additional setup needed.

Bring Your Own PostgreSQL

Point DATABASE_URL to your existing PostgreSQL 15+ instance:
DATABASE_URL=postgresql+asyncpg://calseta:password@your-host:5432/calseta
Requirements:
  • PostgreSQL 15 or later
  • pgcrypto extension enabled (CREATE EXTENSION IF NOT EXISTS pgcrypto)
  • A dedicated database for Calseta

Running Migrations

Migrations run automatically on startup. To run them manually:
docker compose exec api alembic upgrade head

Creating Your First API Key

After starting Calseta, create an admin API key:
docker compose exec api python -m app.cli.create_api_key \
  --name "Admin" \
  --scopes "admin"
Save the returned key immediately — it cannot be retrieved after creation.

Production Deployment

Security Checklist

  • Set a strong ENCRYPTION_KEY
  • Use LOG_FORMAT=json for structured logging
  • Set HTTPS_ENABLED=true if behind a TLS-terminating proxy
  • Configure TRUSTED_PROXY_COUNT to match your proxy depth
  • Set CORS_ALLOWED_ORIGINS to your frontend domain (if applicable)
  • Use a managed PostgreSQL service (RDS, Cloud SQL, Azure Database)

Secrets Management

By default, secrets come from environment variables or .env file. For cloud deployments, two optional backends are supported: Azure Key Vault:
AZURE_KEY_VAULT_URL=https://your-vault.vault.azure.net/
Uses Managed Identity or DefaultAzureCredential. Install with pip install calseta[azure]. AWS Secrets Manager:
AWS_SECRETS_MANAGER_SECRET_NAME=calseta/production
AWS_REGION=us-east-1
Uses the standard AWS credential chain. Install with pip install calseta[aws].
Only one cloud secrets backend is active at a time. If neither is configured, the Azure and AWS SDKs are never imported — no startup penalty.

Infrastructure as Code

Terraform modules for deploying Calseta on AWS (ECS + RDS) and Azure (Container Apps + Azure Database for PostgreSQL) are coming soon. Follow the GitHub repo for updates.

Docker Images

Pre-built images are available from GitHub Container Registry:
docker pull ghcr.io/calseta/calseta-api:latest
docker pull ghcr.io/calseta/calseta-mcp:latest
docker pull ghcr.io/calseta/calseta-worker:latest
Tagged versions follow v{major}.{minor}.{patch}.

Health Checks

  • API: GET http://localhost:8000/health
  • MCP: GET http://localhost:8001/health

Reverse Proxy

Place Calseta behind nginx, Caddy, or a cloud load balancer for TLS termination. Set TRUSTED_PROXY_COUNT so rate limiting reads the correct client IP from X-Forwarded-For.
server {
    listen 443 ssl;
    server_name calseta.yourcompany.com;

    location / {
        proxy_pass http://localhost:8000;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /mcp/ {
        proxy_pass http://localhost:8001;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}