Docker Compose
Run Wealthfolio with a compose.yml that bundles restart policies, env files, and reverse proxy integration in a single declarative file.
If you already manage your homelab with Compose, this is the path you
want. The Wealthfolio repo ships a production-ready compose.yml that
plays nicely with any reverse proxy (Coolify, Nginx, Caddy, Traefik).
Prerequisites
- Docker + Docker Compose v2 (
docker compose, notdocker-compose) opensslandargon2for generating secrets
Get the compose file
The official compose file lives in the project repo. Pull it locally:
mkdir -p /opt/wealthfolio && cd /opt/wealthfolio
curl -fsSL https://raw.githubusercontent.com/afadil/wealthfolio/main/compose.yml -o compose.ymlIt declares a single service backed by the afadil/wealthfolio:latest
image, with a named volume, healthcheck, resource limits, and security
hardening (read-only filesystem + dropped privileges).
Create your .env
Generate the required secrets and write them to .env:
SECRET=$(openssl rand -base64 32)
HASH=$(printf 'your-password' | argon2 yoursalt16chars! -id -e)
cat > .env <<EOF
WF_SECRET_KEY='${SECRET}'
WF_AUTH_PASSWORD_HASH='${HASH}'
WF_CORS_ALLOW_ORIGINS=https://wealthfolio.example.com
EOF
chmod 600 .envSingle quotes around WF_AUTH_PASSWORD_HASH are mandatory. Compose
interpolates $ in .env files by default, and the Argon2 hash is full
of $ characters. Single-quote it, or double every $ ($$argon2id$$...).
Compose 2.30+ also supports format: raw in env_file to skip
interpolation entirely. See the
escaping table.
Start it
docker compose up -dThe compose file uses expose (not ports), so the container is only
reachable from other containers on the same Docker network, perfect for
sitting behind a reverse proxy. To expose it directly to your host (for
local testing), use the dev overlay:
docker compose -f compose.yml -f compose.dev.yml up -dNow http://localhost:8088 works from the host.
Inspect & manage
docker compose logs -f # Follow logs
docker compose ps # Status
docker compose restart # Bounce the container
docker compose down # Stop and remove (volume persists)
docker compose pull && docker compose up -d # Update to latestReverse proxy integration
The shipped compose file is built for “publish via expose, terminate at the proxy.” Add Wealthfolio to your existing proxy network:
# compose.override.yml
services:
wealthfolio:
networks:
- proxy
networks:
proxy:
external: trueThen point your proxy at wealthfolio:8088 over the proxy network. See
Reverse proxy setup for full
examples.
Traefik labels
If you’re on Traefik, add labels in your compose.override.yml:
services:
wealthfolio:
labels:
- traefik.enable=true
- traefik.http.routers.wealthfolio.rule=Host(`wealthfolio.example.com`)
- traefik.http.routers.wealthfolio.entrypoints=websecure
- traefik.http.routers.wealthfolio.tls.certresolver=letsencrypt
- traefik.http.services.wealthfolio.loadbalancer.server.port=8088Set WF_CORS_ALLOW_ORIGINS=https://wealthfolio.example.com in your
.env to match.
Pinning the version
afadil/wealthfolio:latest rolls forward on every release. For
production, pin a tag:
services:
wealthfolio:
image: afadil/wealthfolio:3.3.0Then update deliberately by bumping the tag and running
docker compose up -d.
Backups
The compose file uses a named volume wealthfolio-data. Back it up by
running a sidecar tar:
docker run --rm \
-v wealthfolio_wealthfolio-data:/data \
-v "$(pwd):/backup" \
alpine tar czf /backup/wealthfolio-$(date +%Y%m%d).tar.gz -C / data(Volume name is <compose-project>_<volume-name>. Adjust if your
project name differs.)
Back up .env (which holds WF_SECRET_KEY) separately from the
data volume. The encrypted secrets in the volume are useless without
the key.
Configuration
Every variable Wealthfolio reads is documented in the Configuration reference.