Self-Hosting
Deploy Sevro on your own infrastructure with Docker or Kubernetes.
Quick start with Docker Compose
The repository includes a docker-compose.yml that runs Postgres and Sevro:
git clone https://github.com/jackcaldwell/sevro.git
cd sevro
docker compose up -dThis starts:
- Postgres 17 on the internal network (port 5432, no host mapping by default)
- Sevro server on port 8080
Configuration
Sevro is configured via environment variables:
| Variable | Default | Description |
|---|---|---|
DB_URL | postgres://postgres:postgres@localhost:5432/postgres | Postgres connection string |
SERVER_ADDR | :8080 | Server listen address |
SEVRO_ENCRYPTION_KEY | (dev key) | AES-256-GCM key for encrypting connection credentials. Set this in production! |
SEVRO_UI_DEV_URL | (unset) | URL of the admin UI dev server for proxying (development only) |
SEVRO_SUPABASE_URL | (unset) | Supabase URL for JWT auth (optional) |
SEVRO_SUPABASE_JWT_SECRET | (unset) | Supabase JWT secret (optional) |
Encryption key
The SEVRO_ENCRYPTION_KEY is used to encrypt connection credentials at rest. If not set, Sevro generates a deterministic dev key — this is insecure for production.
Generate a secure key:
openssl rand -base64 32Set it as an environment variable:
export SEVRO_ENCRYPTION_KEY="your-base64-key-here"Initial setup
After starting Sevro for the first time:
# 1. Apply migrations
docker compose exec sevro /app/sevro migrate
# 2. Create an admin API key
docker compose exec sevro /app/sevro bootstrap --name admin --subject adminSave the raw token — it's shown only once.
Building from source
# Build the server and CLI
go build -o bin/sevroserver ./cmd/fxserver
go build -o bin/sevro ./cmd/sevro
# Run migrations
./bin/sevro migrate --db "postgres://postgres:postgres@localhost:5432/postgres"
# Start the server
./bin/sevroserverDocker image
Build the Docker image:
docker build -t sevro:latest .Run it:
docker run -d \
--name sevro \
-p 8080:8080 \
-e DB_URL="postgres://user:pass@db-host:5432/sevro" \
-e SEVRO_ENCRYPTION_KEY="your-key" \
sevro:latestThe Docker image is Alpine-based and includes both sevroserver and sevro (the CLI). The entrypoint automatically applies migrations before starting the server.
Kubernetes
Sevro is a single binary with a Postgres dependency — it deploys cleanly on Kubernetes.
Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: sevro
spec:
replicas: 1
selector:
matchLabels:
app: sevro
template:
metadata:
labels:
app: sevro
spec:
containers:
- name: sevro
image: sevro:latest
ports:
- containerPort: 8080
env:
- name: DB_URL
valueFrom:
secretKeyRef:
name: sevro-secrets
key: db-url
- name: SEVRO_ENCRYPTION_KEY
valueFrom:
secretKeyRef:
name: sevro-secrets
key: encryption-key
- name: SERVER_ADDR
value: ":8080"
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: sevro
spec:
selector:
app: sevro
ports:
- port: 8080
targetPort: 8080Health check
Sevro exposes a /healthz endpoint that checks database connectivity:
curl http://localhost:8080/healthz{
"status": "ok",
"version": "0.0.1",
"database": "connected"
}Admin UI
The admin UI is a static SPA built with React + TanStack Router. To serve it alongside Sevro:
-
Build the UI:
cd admin && npm run build -
Serve the
admin/dist/directory via a reverse proxy (nginx, Caddy) in front of Sevro, or use theSEVRO_UI_DEV_URLenv var during development to proxy to the Vite dev server.
Production checklist
- Set
SEVRO_ENCRYPTION_KEYto a securely generated value - Use a managed Postgres instance with automated backups
- Put Sevro behind a TLS-terminating reverse proxy
- Create API keys with least-privilege roles (editor/viewer) for applications
- Set up monitoring on the
/healthzendpoint - Enable Postgres connection pooling (PgBouncer) if needed