Recipe: a plain VPS
Vaultbase on one Linux server from scratch, with HTTPS, real client IPs, backups and updates.
One Ubuntu 24.04 server running Vaultbase as a service, with Caddy in front for HTTPS. It takes about fifteen minutes. The deployment guide explains each piece in more depth; this page is the order to do them in.
You need:
- A VPS with a public IPv4 address. 1 vCPU and 1 GB of RAM is enough to start.
- A domain, here
api.example.com, with anArecord pointing at the server (and anAAAArecord if the server has IPv6). - SSH access as a user that can run
sudo.
1. Open only SSH, HTTP and HTTPS
Section titled “1. Open only SSH, HTTP and HTTPS”sudo ufw allow OpenSSHsudo ufw allow 80,443/tcpsudo ufw enableVaultbase listens on port 8091, which stays closed: Caddy is the only way in.
2. Install Vaultbase
Section titled “2. Install Vaultbase”curl -fsSL https://get.vaultbase.dev | sudo sh -s -- --verify-sigThe script installs the binary to /usr/local/bin/vaultbase and creates
a vaultbase system user. It writes /etc/vaultbase/vaultbase.env with a
fresh JWT secret and setup key, and starts a hardened systemd service.
Data lives in /var/lib/vaultbase. --verify-sig requires the release’s
cosign signature check, and fails if cosign isn’t installed (without the
flag the check runs whenever cosign is there). See Installation
for the other flags.
3. Keep it behind the proxy
Section titled “3. Keep it behind the proxy”Edit /etc/vaultbase/vaultbase.env and add:
# Listen on loopback only: Caddy, on the same machine, is the only client.VAULTBASE_HOST=127.0.0.1# Trust X-Forwarded-For from Caddy, so rate limits, sign-in lockouts and# the audit log see the caller's address instead of 127.0.0.1.VAULTBASE_TRUSTED_PROXIES=127.0.0.1/32,::1/128The server made an encryption key at its first start, in
/var/lib/vaultbase/.encryption-key. It encrypts secret settings and
encrypted fields. Back it up with the database: without it those values
can’t be read. (To keep your own key in the env file instead, set
VAULTBASE_ENCRYPTION_KEY now, while nothing has been encrypted yet.)
Then restart it:
sudo systemctl restart vaultbasecurl -s http://127.0.0.1:8091/_/healthIf you’d rather use Postgres than SQLite, set VAULTBASE_DATABASE_URL now,
before you create the first admin. The choice is made once per install. See
Postgres.
4. Put Caddy in front
Section titled “4. Put Caddy in front”Install Caddy from its own package repository (Ubuntu’s package is older
than the {client_ip} placeholder used below):
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl gpgcurl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpgcurl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.listsudo apt update && sudo apt install -y caddyReplace /etc/caddy/Caddyfile with:
api.example.com { reverse_proxy 127.0.0.1:8091 { # The address Caddy saw, set (not appended), so a client can't forge it. header_up X-Forwarded-For {client_ip} }}sudo systemctl reload caddyCaddy gets a Let’s Encrypt certificate for the domain on the first request
and renews it. It sets X-Forwarded-Proto itself, so sign-in cookies get the
Secure flag. It proxies the realtime WebSocket (/realtime) and the SSE
stream (/api/v1/realtime) without extra settings.
Check it from your own machine:
curl -s https://api.example.com/_/healthcurl -s https://api.example.com/_/ready5. Create the first admin
Section titled “5. Create the first admin”On the server, without exposing anything:
Run it as the vaultbase user, as the service runs: a file it writes as
root in the data directory would stop the service from starting.
Then sign in at https://api.example.com/_/. (The browser setup page works
too; it asks for the setup key from /etc/vaultbase/vaultbase.env.)
In the admin, open Settings → CORS and add the origins of your web apps to the allowed origins, so browsers may call the API and connect to realtime.
6. Back it up
Section titled “6. Back it up”In the admin, Settings → Backup & restore schedules backups of the database. Send
them to S3-compatible storage, so a lost server doesn’t take its backups with
it. Also keep a copy of /etc/vaultbase/vaultbase.env and
/var/lib/vaultbase/.encryption-key off the server: they hold the JWT
secret and the encryption key, and a backup without the key can’t decrypt
encrypted values. See Backups.
With local file storage, scheduled backups also keep the uploaded files (since 0.34.0): each file is stored once, and a restore puts the missing ones back. With the S3 copy on, they go to the bucket too.
7. Update
Section titled “7. Update”sudo vaultbase update --check # is a newer release out?sudo vaultbase update --yes && sudo systemctl restart vaultbaseRead the release notes before a minor version (0.x.0); they list anything to do first. Self-update shows how to run it from cron.
When something’s wrong
Section titled “When something’s wrong”journalctl -u vaultbase -fshows the server’s log; the structured logs are in/var/lib/vaultbase/logs/.sudo -u vaultbase vaultbase doctorchecks the configuration and the database.502from Caddy: Vaultbase isn’t running or isn’t on 127.0.0.1:8091 (systemctl status vaultbase).- Every request in the audit log comes from
127.0.0.1:VAULTBASE_TRUSTED_PROXIESis missing, or the service wasn’t restarted. A value under Settings → Security → Trusted proxies in the admin takes precedence over the env var, so check it too. - The service won’t start and the log says
database.json can't be read: a command was run as root in the data directory. Runsudo chown -R vaultbase:vaultbase /var/lib/vaultbaseand start it.