Revaulter GitHub

Installing Revaulter

Revaulter is distributed as a container image and runs as a single-container service.

Requirements#

  • A container runtime (Docker, Podman, etc.)
  • A database: SQLite or PostgreSQL
  • HTTPS access for the web UI
  • A webhook endpoint for notifications (Discord, Slack, or any HTTP endpoint)

HTTPS is required for Revaulter because it uses WebCrypto. You can either configure Revaulter to start a HTTPS server (which requires providing TLS certificates to Revaulter directly) or use a reverse proxy that performs TLS termination, such as Caddy, Traefik, Nginx, etc.

Container images#

ImageDescription
ghcr.io/italypaleale/revaulter:2Revaulter server
ghcr.io/italypaleale/revaulter-cli:2Revaulter CLI

Both images are available for amd64 and arm64.

Configuration#

Revaulter is configured via a YAML file and/or environment variables. Inside the container, it looks for config.yaml at:

  1. The path set in the REVAULTER_CONFIG environment variable
  2. /etc/revaulter/config.yaml
  3. $HOME/.revaulter/config.yaml
  4. The same directory as the binary

Required configuration#

KeyEnv varDescription
webhookUrlWEBHOOKURLWebhook endpoint for notifications
databaseDSNDATABASEDSNDatabase connection string (see Database below)
secretKeySECRETKEYInstance-wide secret for key derivation (see Secret key below)
KeyEnv varDefaultDescription
baseUrlBASEURLhttps://localhost:<port>Public URL where users access the web UI. Used for webhook links and WebAuthn origin validation.
sessionSigningKeySESSIONSIGNINGKEYRandom at startupSecret used to sign session tokens. Set this in production so sessions survive restarts.
tlsPathTLSPATHConfig file directoryDirectory containing tls-cert.pem and tls-key.pem. Revaulter watches for changes and auto-reloads.
tlsCertPEMTLSCERTPEMPEM-encoded TLS certificate (alternative to tlsPath)
tlsKeyPEMTLSKEYPEMPEM-encoded TLS key (alternative to tlsPath)

Optional configuration#

KeyEnv varDefaultDescription
webhookFormatWEBHOOKFORMATplainWebhook format: plain, slack, or discord
webhookKeyWEBHOOKKEYValue sent as Authorization header on webhook requests (include the scheme, e.g. Bearer abc123)
portPORT8080Port to bind to
bindBIND0.0.0.0Address/interface to bind to
disableSignupDISABLESIGNUPfalseDisable creation of new user accounts
sessionTimeoutSESSIONTIMEOUT5mSession duration before re-authentication is required (max: 1h)
requestTimeoutREQUESTTIMEOUT5mDefault timeout for requests (can be overridden per-request; max: 24h)
trustedProxiesTRUSTEDPROXIESComma-separated list of IPs/CIDRs to trust for X-Forwarded-* headers
forceSecureCookiesFORCESECURECOOKIESfalseForce the Secure flag on cookies (set to true when behind a TLS-terminating reverse proxy)
trustedRequestIdHeaderTRUSTEDREQUESTIDHEADERHeader to trust as request ID (e.g. X-Request-ID, CF-Ray)
logHealthChecksLOGHEALTHCHECKSfalseInclude /healthz requests in the request logs
logLevelLOGLEVELinfoLog level: debug, info, warn, error
logAsJsonLOGASJSONautoEmit JSON logs (defaults to true when no TTY is attached)

Optional WebAuthn configuration#

These settings are necessary in some scenarios only. Revaulter derives sensible defaults from baseUrl.

KeyEnv varDefaultDescription
webauthnRpIdWEBAUTHNRPIDDerived from baseUrlWebAuthn Relying Party ID
webauthnRpNameWEBAUTHNRPNAMERevaulterWebAuthn Relying Party display name
webauthnOriginsWEBAUTHNORIGINSbaseUrlAllowed WebAuthn origins

Database#

Revaulter supports SQLite and PostgreSQL. The backend is detected automatically from the DSN:

DSN formatBackend
postgres://user:pass@host:5432/dbnamePostgreSQL
sqlite:///path/to/file.dbSQLite
/path/to/file.db (no scheme)SQLite

SQLite requires no external dependencies and is a good default for single-node deployments.

For PostgreSQL, use a standard connection string, for example:

postgres://revaulter:password@db.example.com:5432/revaulter

⚠️ Warning: When using SQLite, the database file must not be stored on a networked filesystem, like NFS or SMB.

Secret key#

Generate a secret key:

openssl rand -base64 32

⚠️ Warning: Rotating secretKey bricks every existing account on the instance. The secret key is used to derive the WebAuthn PRF salt that every user’s in-browser key derivation is bound to. Treat this value as immutable for the lifetime of the instance. If you must rotate it, every user will need to re-register from scratch.

📝 Note: secretKey is not used to encrypt anything stored in the database. All request payloads and responses are end-to-end encrypted in the browser; the server only stores opaque envelopes.

Session signing key#

Generate a session signing key:

openssl rand -base64 32

Set sessionSigningKey in production so session tokens remain valid across restarts. If this value is omitted, Revaulter generates a random signing key at startup; existing sessions are invalidated whenever the process restarts.

TLS#

Revaulter requires HTTPS for WebAuthn to work (browsers enforce a secure context). You have two options:

  1. Reverse proxy (recommended): Terminate TLS at a reverse proxy (Caddy, Traefik, Nginx, etc.) and forward plain HTTP to Revaulter.
    • Set forceSecureCookies: true in this case.
  2. Direct TLS: Provide certificates via tlsPath (a directory containing tls-cert.pem and tls-key.pem) or via tlsCertPEM/tlsKeyPEM. Revaulter watches the tlsPath directory and auto-reloads certificates.

Docker Compose example#

services:
  revaulter:
    image: ghcr.io/italypaleale/revaulter:2
    ports:
      - "8080:8080"
    volumes:
      - ./config.yaml:/etc/revaulter/config.yaml:ro
      - revaulter-data:/data
    restart: unless-stopped

volumes:
  revaulter-data:

With a config.yaml:

webhookUrl: "https://discord.com/api/webhooks/your-webhook-id/your-webhook-token"
webhookFormat: "discord"
databaseDSN: "/data/revaulter.db"
secretKey: "<your-secret-key>"
sessionSigningKey: "<your-session-signing-key>"
baseUrl: "https://revaulter.example.com"

If you want Revaulter to handle TLS directly:

services:
  revaulter:
    image: ghcr.io/italypaleale/revaulter:2
    ports:
      - "443:8080"
    volumes:
      - ./config.yaml:/etc/revaulter/config.yaml:ro
      - ./tls:/etc/revaulter/tls:ro
      - revaulter-data:/data
    restart: unless-stopped

volumes:
  revaulter-data:

And add to config.yaml:

tlsPath: "/etc/revaulter/tls"
port: 8080

Place tls-cert.pem and tls-key.pem in the ./tls directory.

Podman Quadlet example#

First, store the config file as a Podman secret:

podman secret create revaulter-config ~/.config/revaulter/config.yaml

Create a container unit file at ~/.config/containers/systemd/revaulter.container (rootless) or /etc/containers/systemd/revaulter.container (rootful):

[Unit]
Description=Revaulter
After=network-online.target

[Container]
Image=ghcr.io/italypaleale/revaulter:latest
PublishPort=8080:8080
Secret=revaulter-config,target=/etc/revaulter/config.yaml
Volume=revaulter-data.volume:/data
AutoUpdate=registry

[Service]
Restart=always

[Install]
WantedBy=default.target

Create a volume unit file at the same location, revaulter-data.volume:

[Volume]

Then reload and start:

# Rootless
systemctl --user daemon-reload
systemctl --user enable --now revaulter

# Rootful
systemctl daemon-reload
systemctl enable --now revaulter

To update the config later, recreate the secret and restart the service:

podman secret rm revaulter-config
podman secret create revaulter-config ~/.config/revaulter/config.yaml
systemctl --user restart revaulter

User setup#

After starting Revaulter:

  1. Open the web UI at your configured baseUrl.
  2. Create an account: registration uses WebAuthn, so you’ll need a passkey-capable authenticator with PRF support.
  3. After registration, the UI shows your request key: this is the per-user key that CLI requests are routed by.
  4. Optionally configure allowed IP addresses for your account from the settings page.

Account self-registration can be disabled by setting disableSignup: true after initial setup.

Edit this page on GitHub