Self-hosted deployment
Self-hosted deployment is Enterprise-only. You run the same Next.js dashboard, Go validation engine, PostgreSQL 16, and Redis 7 on your VPC or on-prem host. New organizations unlock Enterprise entitlements when VALGUARD_PLAN=enterprise. Production installs also require a staff-issued VALGUARD_LICENSE_KEY (local Ed25519 verify + optional heartbeat — no customer AI payloads leave your network).
Repo operator guide (clone checkout): docs/self-host.md. Production env catalog: docs hub and FAQ.
Ubuntu host (recommended)
Fresh Ubuntu 22.04/24.04, sudo-capable deploy user (not root). DNS A records for the app and API hosts should point at the VM before TLS.
git clone <your-valguard-mirror> ValGuard && cd ValGuard cp .env.example .env bash scripts/install-ubuntu.sh --host \ --self-host \ --license-key '<JWT from ValGuard staff>' \ --app-domain app.example.com \ --api-domain api.example.com \ --certbot-email ops@example.com VALGUARD_PLAN=enterprise make seed-user
--self-host writes VALGUARD_PLAN=enterprise, enables license enforcement, and installs valguard-license-check. Pass --license-key or paste when prompted (existing keys are never overwritten). The installer provisions apt Postgres + Redis, migrates, seeds templates, and installs systemd + nginx TLS. Lab without public DNS: add --skip-ssl --skip-dns-check.
Lab compose (engine + Postgres + Redis)
Only the Go engine has a production Dockerfile. The lab compose runs Postgres, Redis, and the engine. Next.js stays on the host.
cp deploy/self-host/.env.example deploy/self-host/.env docker compose -f deploy/self-host/docker-compose.yml --env-file deploy/self-host/.env up -d # or: make self-host-lab # Repo .env: DATABASE_URL → localhost:5432, REDIS_URL → localhost:6380, # VALGUARD_PLAN=enterprise, VALGUARD_LICENSE_KEY=<JWT>, same INTERNAL_PROXY_SECRET as compose make migrate-up make seed-templates make seed-playbook-templates VALGUARD_PLAN=enterprise make seed-user make web-install && make web
Renewals: paste a rotated JWT in Admin → System (Self-host license) or host .env, then restart proxy/web (72h overlap).
Required environment
VALGUARD_PLAN=enterprise— default plan for new orgs (hosted SaaS leaves this unset so signup stays Free).VALGUARD_LICENSE_KEY— staff-issued deployment JWT (enforce mode blocks API without a valid key).DATABASE_URL,REDIS_URLINTERNAL_PROXY_SECRET,BETTER_AUTH_SECRET,ABUSE_HMAC_SECRETAPP_URL,API_PUBLIC_URL, matchingNEXT_PUBLIC_*(rebuild web after changing public URLs)- Stripe keys are optional when you bill Enterprise offline.
Upgrades
git pull make migrate-up make seed-templates make seed-playbook-templates make license-check-build make web-rebuild-prod make proxy-build && sudo systemctl restart valguard-proxy make license-check
Not included in this guide
- Customer-run license server, air-gap update channel, or offline package mirrors (licensing is a staff-issued JWT verified locally + optional SaaS heartbeat)
- Kubernetes / Helm operator
- A separate self-host Stripe SKU
Talk to sales for Enterprise contracts and support SLA.