Skip to content

Run with Docker

In progress

The image runs the sync server and the web vault on one port: /v1/… is the API (including the /v1/ws WebSocket), everything else is the web vault. Put it behind a reverse proxy that terminates TLS; the apps refuse servers without HTTPS.

From the repository root:

Terminal window
docker build -f apps/server/Dockerfile -t octapass-server .

The build compiles the crypto core to WebAssembly, builds the web vault and the server, and copies them into a distroless image that runs as a non-root user. Base images are pinned by digest.

A complete example lives in deploy/octap.app: copy the folder, change the domain and the invited email, and run docker compose up -d --build. The essentials:

services:
octapass:
build: { context: ../.., dockerfile: apps/server/Dockerfile }
restart: unless-stopped
ports: ["127.0.0.1:8380:8080"] # only your proxy should reach it
environment:
OCTAPASS_PUBLIC_URL: https://vault.example.com
OCTAPASS_WEB_ORIGINS: https://vault.example.com
OCTAPASS_SIGNUPS: invite
OCTAPASS_INVITES: [email protected]
OCTAPASS_TRUST_PROXY: "true"
OCTAPASS_SMTP_URL: ${OCTAPASS_SMTP_URL:-}
OCTAPASS_EMAIL_TO_LOG: ${OCTAPASS_EMAIL_TO_LOG:-false}
OCTAPASS_BACKUP_DIR: /backups
volumes:
- octapass-data:/data
- octapass-backups:/backups
read_only: true
tmpfs: [/tmp]
cap_drop: [ALL]
security_opt: ["no-new-privileges:true"]
volumes:
octapass-data:
octapass-backups:

Then forward https://vault.example.com to 127.0.0.1:8380 in your proxy (Caddy, Traefik, nginx or a Cloudflare Tunnel), with WebSockets allowed.

  • Who can sign up. With OCTAPASS_SIGNUPS=invite, only the emails in OCTAPASS_INVITES (comma-separated) can create an account. They’re invited at every start until their account exists; octapass-server admin invite adds more without a restart.
  • The verification code. Sign-up needs a code sent by email. Set OCTAPASS_SMTP_URL, or set OCTAPASS_EMAIL_TO_LOG=true and read the code with docker compose logs octapass | grep "verification code". The code is never returned to the browser outside dev mode.
  • The web vault always uses the server it’s served from. Its pages get a content security policy that allows only that origin plus wasm-unsafe-eval (the crypto core), and cross-origin isolation headers. API responses keep default-src 'none'.
  • PostgreSQL instead of SQLite: add a postgres:17 service and set OCTAPASS_DATABASE_URL=postgres://octapass:<password>@db:5432/octapass. Scheduled backups are SQLite only; use pg_dump there.
  • GET /healthz: the process is alive
  • GET /readyz: the database and storage are reachable
  • octapass-server healthcheck exits 0 when /healthz answers. The image uses it as its HEALTHCHECK, since it has no shell or curl.

Run them in the container: docker compose exec octapass octapass-server admin …. See configuration.

Terminal window
git pull && docker compose up -d --build

Database migrations run automatically at startup, behind a lock, so only one instance migrates at a time. Back up first: see backups.