vakaGitHub

Self-hosting

Vaka is one Rust binary (vaka-server) plus ClickHouse. Metadata (users, projects, issues, tokens, alert rules) lives in SQLite or Postgres. One instance comfortably serves 20 to 30 apps and websites on a 2 vCPU / 4 GB machine.

docker compose

cp .env.example .env
docker compose up -d                       # SQLite metadata (default)
docker compose --profile postgres up -d    # with Postgres; also set VAKA_DB_URL

The compose file runs ghcr.io/erikhellman/vaka:latest and clickhouse/clickhouse-server:24.8 with a low-memory ClickHouse profile. Data is kept in the vaka-data, clickhouse-data and postgres-data volumes.

Put a TLS-terminating reverse proxy (Caddy, nginx, Traefik, Cloudflare) in front of port 8080 and set VAKA_PUBLIC_URL to the public HTTPS URL. Example Caddyfile:

vaka.example.com {
    reverse_proxy localhost:8080
}

Fly.io

The repository ships a ready Fly.io setup: fly.toml for the server (app vaka) and deploy/fly/clickhouse/ for a private ClickHouse app (vaka-clickhouse, no public ports, reached at vaka-clickhouse.internal:8123). Metadata stays in SQLite on a volume. Change the app names, region and VAKA_PUBLIC_URL in both files for your own deployment.

fly apps create vaka && fly apps create vaka-clickhouse
fly volumes create vaka_data -a vaka -r arn -s 3
fly volumes create clickhouse_data -a vaka-clickhouse -r arn -s 10
PW=$(openssl rand -hex 24)
fly secrets set -a vaka-clickhouse --stage CLICKHOUSE_PASSWORD=$PW
fly secrets set -a vaka --stage VAKA_CLICKHOUSE_PASSWORD=$PW \
  VAKA_ADMIN_EMAIL=you@example.com VAKA_ADMIN_PASSWORD=...
fly deploy -c deploy/fly/clickhouse/fly.toml --ha=false
fly deploy --ha=false

Both apps run a single machine each (volumes are per machine); use --ha=false so Fly does not create a second one. Volume snapshots are taken daily by Fly.

Configuration

All settings are environment variables.

Variable Default Meaning
VAKA_PUBLIC_URL http://localhost:8080 Public URL, used in links, alerts and install guides
VAKA_LISTEN 0.0.0.0:8080 Listen address
VAKA_ADMIN_EMAIL, VAKA_ADMIN_PASSWORD First owner account, created on start when no users exist
VAKA_DB_URL sqlite://$VAKA_DATA_DIR/vaka.db?mode=rwc sqlite://... or postgres://user:pass@host/db
VAKA_DATA_DIR ./data (/data in Docker) SQLite database and uploaded debug files
VAKA_CLICKHOUSE_URL http://localhost:8123 ClickHouse HTTP interface
VAKA_CLICKHOUSE_USER / _PASSWORD / _DATABASE default / empty / vaka ClickHouse credentials
VAKA_DEFAULT_RETENTION_DAYS 90 Retention for new projects
VAKA_RESEND_API_KEY Enables email alerts and invite emails via Resend
VAKA_EMAIL_FROM Vaka <vaka@localhost> Sender for emails
VAKA_GEOIP_DB Optional MaxMind/DB-IP country .mmdb file

Country lookup uses CF-IPCountry (Cloudflare) or similar proxy headers when present, otherwise the GeoIP database if configured.

Vaka creates the ClickHouse database and tables and runs metadata migrations on start.

Running without Docker

cargo build --release -p vaka-server -p vaka
VAKA_CLICKHOUSE_URL=http://localhost:8123 ./target/release/vaka-server

Backups

Upgrades

Pull the new image and restart: docker compose pull && docker compose up -d. Migrations run automatically. Read the release notes for anything that needs manual steps.

Health and monitoring

GET /health returns {"ok": true, "db": true, "clickhouse": true, "version": "..."} and 503 when a dependency is down. Logs go to stdout; set VAKA_LOG=debug (tracing filter syntax) for more.