Skip to content
Built inServers and containers

Run the Crunu server with Docker Compose

Host the Crunu server on your own machine with Docker Compose: Caddy for automatic TLS or Cloudflare Tunnel with no open ports, and SQLite or Postgres.

Support
Works with Crunu today: Docker support is part of the product.
Crunu features
Self-hosting and Encrypted vault
Checked
Against Crunu 6.0.0 on October 28, 2026
Example. Kiteline is a fictional company.

Crunu features that work with Docker

Each feature below works the same way in every integration: the server keeps ciphertext, and only the people, machines and tokens you grant can decrypt.

  • Self-hosting

    Run the same Crunu server on your own Docker host, Cloudflare Workers, Vercel or Google Cloud Run, and move between them with one archive.

    Learn more

  • Encrypted vault

    Keep .env files, cloud credentials and API keys in projects and environments, encrypted on your devices before anything reaches the server.

    Learn more

How it works with Docker

On this page

What Crunu does with Docker

Crunu runs in the cloud at app.crunu.com, so most teams never deploy a server. If you'd rather keep it on your own machine, the server ships with a Docker Compose setup: the server container plus Caddy, which issues the TLS certificate for your domain by itself.

The server is blind wherever it runs. Its database holds ciphertext, public keys, signed documents and metadata, and it has no key that decrypts a value. See self-hosting for how the options compare.

What you need

  • A machine with Docker, and a domain with an A or AAAA record pointing at it.
  • Ports 80 and 443 open, so Caddy can get a certificate.
  • Node.js 24 and the Crunu server's files on that machine. The commands below run from the server's directory.

Start the server

Choose the server's address once. Sign-in signatures, share links, passkeys and enrolled machines are all bound to it, and moving to another platform later keeps the same address.

Shell
node scripts/server-init.mjs --origin https://vault.company.example --out deploy/docker/.env
docker compose -f deploy/docker/compose.yml up -d --build

server-init writes a .env file with 0600 permissions and new values for SERVER_KEY, BOOTSTRAP_TOKEN and CRON_SECRET. Save a copy of it in a password manager right away: the server can't be restored without it. The database is SQLite in a Docker volume by default. For Postgres next to the server, run server-init with --docker-postgres.

Then check the deployment and create the first owner with the bootstrap key from .env:

Shell
node scripts/doctor.mjs https://vault.company.example

Cloudflare Tunnel instead of open ports

The server can also reach the internet through a Cloudflare Tunnel. Nothing is published on the machine, cloudflared connects to the server directly, and Cloudflare terminates TLS. Put the tunnel token in deploy/docker/.env, point the tunnel's public hostname at the service server:8080, and add the tunnel file on top of the main one:

Shell
docker compose -f deploy/docker/compose.yml -f deploy/docker/compose.tunnel.yml up -d --build

The tunnel file gives cloudflared a fixed address on its own Docker network, and the server trusts the client address header only from that address, so network restrictions see the real client address.

How the container runs

The Compose setup runs the server with a read-only root filesystem, no Linux capabilities and an unprivileged user, and it's tested to restart on the same database. The server applies schema migrations by itself at startup. An update is the same docker compose … up -d --build after you fetch the new version.

The image embeds a ready-made web client from dist/web/. If that directory is missing, or holds a different version than the server, the build stops instead of building an unsigned web client on its own.

Backups and moving

crunu-server export writes the whole database to one archive with no plaintext values in it, and crunu-server import loads it into an empty database on any supported platform: Docker, Cloudflare Workers, Vercel or Google Cloud Run. Keep the same .env and the same address, and only the DNS record changes.

That archive moves a server you run. Moving from app.crunu.com to your own server isn't one step, because only the operator can reach the cloud database. Export each environment as a .env file or download an offline copy, then add the files to your server. History, access settings and the audit log don't carry over this way.

The crunu agent in containers

The crunu agent's install script has a no-root mode for CI and containers. It's tested in node:24, Ubuntu 24.04 and Alpine 3.22 images. In CI and other short-lived containers, crunu works with a service token: it signs in and decrypts inside its own process, with no state files. A minimal image without ca-certificates can't verify the server's certificate, and crunu tells you which package to install.

The background agent service needs systemd and runs on Linux hosts. See systemd.

Questions and answers

Not covered here? Write to support@crunu.com and a person will answer.

Where do I get the server?

The server isn't published as a public download. Write to support@crunu.com.

Which database does it use?

SQLite in a Docker volume by default, or Postgres next to the server.

Can I avoid opening ports?

Yes. Run it behind Cloudflare Tunnel with the tunnel Compose file, and Cloudflare terminates TLS.

Can I move from app.crunu.com to my own server?

Not in one step. Export each environment as a .env file or download an offline copy. History, access settings and the audit log don't carry over this way.

Try it with Docker

Create your organization at app.crunu.com, add one environment and connect it. Free during early access.