Prerequisites
Before you start, make sure you have:
- A Linux server. Ubuntu 22.04+ or Debian 12+ recommended. 2 vCPU / 2 GB RAM minimum; 4 GB+ for production.
- A public IP with ports
80and443open. - A domain name with an
Arecord pointing at the server (e.g.vault.yourcompany.com). A.localhostname is fine for offline/lab installs. - Docker 24+ with Compose v2.
- A Supabase project for auth, Postgres Data API, and storage. You'll need: project URL, anon (publishable) key, service-role key, and project ref.
curl -fsSL https://get.docker.com | sudo sh sudo usermod -aG docker $USER && newgrp docker docker compose version # must print v2.x
Clone the repository
Pull the source onto your server:
git clone https://github.com/abrotechit/secure-vault-enterprise.git openvault cd openvault
Pin to a tagged release in production: git checkout v1.0.0 (see the Releases page).
Configure your environment
Copy the example file and fill in the required values. The VITE_* trio must match the server-side Supabase values — Vite inlines them into the browser bundle at build time.
cp .env.example .env # then edit .env
# Database POSTGRES_PASSWORD=$(openssl rand -base64 32) # Supabase (server-side) SUPABASE_URL=https://abcd1234.supabase.co SUPABASE_PUBLISHABLE_KEY=eyJhbGciOi... SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOi... # Supabase (baked into the browser bundle) VITE_SUPABASE_URL=https://abcd1234.supabase.co VITE_SUPABASE_PUBLISHABLE_KEY=eyJhbGciOi... VITE_SUPABASE_PROJECT_ID=abcd1234 # Encryption — 32 random bytes KEK_DEMO_SECRET=$(openssl rand -base64 32) # Public URL APP_URL=https://vault.yourcompany.com APP_DOMAIN=vault.yourcompany.com
KEK_DEMO_SECRET is unrecoverable. If you lose it, every vault becomes permanently unreadable. Back it up offline before storing real secrets, and move custody to Azure Key Vault for production (see step 11).
Quick install (recommended)
The bundled script handles env generation, TLS, and bootstrap:
curl -Lso openvault.sh \ https://raw.githubusercontent.com/abrotechit/secure-vault-enterprise/main/openvault.sh chmod +x openvault.sh sudo ./openvault.sh install sudo ./openvault.sh start
install prompts you for:
| Prompt | What to enter |
|---|---|
| Domain | vault.yourcompany.com (or vault.local for offline) |
| Admin email | Used for Let's Encrypt and as suggested first admin |
| Let's Encrypt? | yes for public domains, no for .local / bare IP |
| Supabase URL / keys | Paste the four values from step 1 |
Manual install
If you prefer to drive Docker Compose yourself:
# Build the web image (Vite bakes VITE_* into the bundle) docker compose build # Start everything docker compose up -d # First-time database bootstrap (migrations + seed) ./scripts/bootstrap.sh
Verify the install
docker compose ps
# all services should be "running" / "healthy"
curl -k https://localhost/api/public/health
# → {"status":"ok","t":"2026-..."}First run — create your organization
- Open
https://your-domainand click Create one. - Provide a work email on a corporate domain (Gmail, Outlook, Yahoo, Proton are blocked by design).
- Pick an organization name and slug, then set a master password. This derives your account encryption key and cannot be recovered.
- You become the owner. Your email domain is auto-claimed for the org.
- Invite teammates from Admin → Users. Invites are limited to your organization's domain or its subdomains.
Day-to-day operations
| Command | What it does |
|---|---|
| ./openvault.sh start | docker compose up -d |
| ./openvault.sh stop | Stop containers, keep data |
| ./openvault.sh restart | Restart all services |
| ./openvault.sh status | Show service health |
| ./openvault.sh logs [service] | Tail logs (web, caddy, postgres, redis) |
| ./openvault.sh update | git pull + rebuild + restart |
| ./openvault.sh rebuild | Re-render Caddyfile after .env edits |
| ./openvault.sh uninstall | Stop containers; type 'wipe' to drop data |
Backups
Daily Postgres dump (run via cron):
docker compose exec -T postgres \ pg_dump -U openvault openvault \ | gzip > /backup/openvault-$(date +%F).sql.gz
Back up all three — losing any one leaves the others useless:
- postgres_data volume — vault ciphertext, audit log, accounts.
- KEK_DEMO_SECRET — the key that unwraps every vault DEK. Store offline (paper safe, hardware token, separate password manager).
- caddy_data volume — TLS certificates (optional; Caddy will re-issue if missing).
Upgrading
cd /path/to/openvault sudo ./openvault.sh update
This runs git pull, rebuilds the web image, applies new database migrations on boot, and restarts the stack. Tag a release first and review the changelog if you pin to versions.
Production hardening
- Move the KEK to Azure Key Vault. Replace local
KEK_DEMO_SECRETcustody with HSM-backed wrap/unwrap. Seedocs/AZURE_KEY_VAULT.mdin the repo. - Enable SAML SSO from Admin → SAML. JIT provisioning + group-to-role mapping included.
- Configure SCIM for automated user provisioning. See
docs/SCIM.md. - Tighten CSP. If you add routes using Argon2 WebAssembly, edit the
@cryptomatcher inscripts/install-templates/Caddyfile.tmpl, then./openvault.sh rebuild && ./openvault.sh restart. - Cloudflare proxy. Use "DNS only" (grey cloud) for the initial Let's Encrypt challenge, then switch to proxied.
Troubleshooting
| Symptom | Fix |
|---|---|
| docker compose build fails with VITE_SUPABASE_URL must be set | Run ./openvault.sh install (or set all four VITE_* values in .env), then rebuild. |
| TLS never provisions / self-signed warning on a public domain | Verify ports 80/443 are open AND the A record points here. Then ./openvault.sh restart. |
| 401 Unauthorized on server functions / SCIM / SSO | SUPABASE_SERVICE_ROLE_KEY is missing or wrong in .env. Fix it, then restart. |
| Unlock page complains about 'wasm-unsafe-eval' in console | CSP template drift. ./openvault.sh rebuild && ./openvault.sh restart. |
| Signup rejects email as 'not a corporate domain' | Free providers are blocked by design. Use a domain you own. |
| Invited teammate gets 'domain not allowed' | Invites must match the inviter's organization domain or a subdomain. |
| Lost the KEK_DEMO_SECRET | All vaults are unreadable. No recovery. Restore from the offline backup. |
| Need live logs | ./openvault.sh logs web (or caddy, postgres) |
Where to go next
The repo ships deeper docs for each subsystem:
- docs/SELF_HOST.md — Canonical self-host reference
- docs/AZURE_KEY_VAULT.md — Move KEK custody to Azure Key Vault
- docs/SCIM.md — Automated user provisioning
- docs/INTUNE.md — Force-install the browser extension via Intune
- docs/BACKUP_RESTORE.md — Backup and restore drills
- docs/RUNBOOK.md — Operational runbook
- docs/THREAT_MODEL.md — Threat model
- docs/COMPLIANCE.md — Compliance notes
