Vaulx ships as a single Alpine-based Docker image with all SQL migrations embedded at build time. There is no migration tool to run separately — on every startup the server applies any pending migrations, configures S3 bucket CORS, seeds the admin account if it does not yet exist, and starts serving traffic. This makes production deployments straightforward: build the image, supply environment variables, and expose portDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/noelzappy/vaulx/llms.txt
Use this file to discover all available pages before exploring further.
8080 behind a TLS-terminating reverse proxy.
Docker Compose Deployment
This approach works on any Linux host (VPS, dedicated server, etc.) where Docker and Docker Compose are installed.Set your environment variables
Copy
.env.example to .env and fill in every variable with production values. At minimum, change SESSION_SECRET to a cryptographically random string of at least 32 characters before the app is publicly accessible.Build and start the stack in the background
Dockerfile in the repo root, starts the db (Postgres 16 Alpine) and app services, waits for the database health check to pass, then launches the app. Migrations and admin seeding happen automatically on first boot.Add a domain and TLS
Place a reverse proxy (Nginx, Caddy, Traefik, etc.) in front of the Vaulx container to terminate TLS and forward traffic to port Caddy automatically provisions a Let’s Encrypt certificate. Nginx and Traefik require separate certificate configuration.
8080. Vaulx itself does not handle TLS.Example Caddyfile snippet:Dokploy Deployment
Dokploy is an open-source platform-as-a-service that manages deployments, databases, and domains on your own server. It is the recommended managed deployment path for Vaulx.Create a Postgres service in Dokploy
In the Dokploy dashboard, navigate to Services and create a new Postgres service. Use PostgreSQL 16 and note the generated connection string — you will need it for
DATABASE_URL in the next steps.Create an application in Dokploy
Create a new Application with the following settings:
Dokploy will clone the repository and build the Docker image using the two-stage
| Setting | Value |
|---|---|
| Source | Your Git repository (GitHub, GitLab, or Gitea) |
| Build type | Dockerfile |
| Dockerfile path | Dockerfile (repo root) |
| Published port | 8080 |
Dockerfile (Go builder → Alpine runtime).Set all environment variables
In the Environment tab of your application, add the following variables:
Deploy the application
Trigger a deploy from the Dokploy dashboard (or push to your linked branch). Dokploy builds the image and starts the container. On first start the app will:
- Run all pending database migrations automatically
- Connect to the database and S3 bucket, then apply the bucket CORS policy
- Seed the admin account using
SEED_ADMIN_EMAILandSEED_ADMIN_PASSWORDif the account does not yet exist - Start serving HTTP on
$PORT
Add a domain and enable HTTPS
In the Domains tab of your Dokploy application, add your domain and enable HTTPS. Dokploy provisions a Let’s Encrypt certificate and routes traffic to port
8080 automatically.HTTPS is required — the session cookie has Secure: true, so the login flow will not work over plain HTTP in production.Environment Variables Reference
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL | Yes | — | Postgres connection string, e.g. postgres://user:pass@host:5432/db?sslmode=disable |
SESSION_SECRET | Yes | — | Random string ≥ 32 chars used to sign and verify session cookies |
PORT | No | 8080 | HTTP port the server listens on |
SEED_ADMIN_EMAIL | Yes | — | Email address for the admin account seeded on first boot |
SEED_ADMIN_PASSWORD | Yes | — | Password for the seeded admin account (min 8 chars, at least one digit) |
HETZNER_ACCESS_KEY | Yes | — | Hetzner Object Storage access key (S3-compatible) |
HETZNER_SECRET_KEY | Yes | — | Hetzner Object Storage secret key |
HETZNER_S3_ENDPOINT | Yes | https://fsn1.your-objectstorage.com | Base URL of the S3-compatible storage endpoint |
HETZNER_BUCKET | Yes | vaulx | Bucket name where uploaded files are stored |
First-Boot Behavior
Every time the Vaulx container starts it runs the following sequence before accepting HTTP traffic:- Migrations —
golang-migrateapplies any pending.sqlfiles from themigrations/directory, which is embedded directly into the binary at build time viaembed.FS. No external migration tooling is needed on the host. - Database & storage connect — The server opens the PostgreSQL connection pool and connects to the configured S3-compatible storage bucket.
- Storage CORS — The server sets the CORS policy on the configured S3 bucket to allow browser-initiated presigned uploads from your domain.
- Admin seed — If no user with
SEED_ADMIN_EMAILexists in the database, the server creates anadmin-role account with the provided email and password. Subsequent restarts skip this step if the account already exists. - HTTP listener — The server starts accepting requests on
$PORT.
Docker Image Details
TheDockerfile uses a two-stage build:
| Stage | Base image | Purpose |
|---|---|---|
builder | golang:1.25-alpine | Installs templ, downloads Go modules, runs templ generate, compiles the server binary with CGO_ENABLED=0 |
| Runtime | alpine:3.20 | Copies only the compiled server binary and the web/static/ directory; adds ca-certificates and tzdata |
server binary at compile time, so the runtime image contains everything needed to deploy and upgrade the schema with no extra tooling.