Self-host ShowMeTheMoney with Docker Compose
ShowMeTheMoney, the envelope budgeting app, runs on your own server as one container and PostgreSQL. This guide takes you from an empty folder to the whole household signed in over HTTPS, with backups and updates sorted.
What you need
- A machine running Docker with Compose, on
linux/amd64orlinux/arm64. A Raspberry Pi works. - For HTTPS from outside your home: a domain or subdomain pointing at that machine, with ports 80 and 443 reaching it. On your home network only, you can skip HTTPS for a first try.
- A few minutes. The app sets up its own database when it starts; there is no separate migration step.
1. Create the folder and Compose file
Make a folder for it, for example ~/showmethemoney, and save this as compose.yaml inside it. It runs the app behind Caddy, which gets and renews an HTTPS certificate on its own:
services:
postgres:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: smtm
POSTGRES_PASSWORD: choose-a-password
POSTGRES_DB: smtm
volumes:
- postgres_data:/var/lib/postgresql/data
app:
image: ohbrer/showmethemoney:1.0.3
restart: unless-stopped
depends_on: [postgres]
environment:
DATABASE_URL: postgres://smtm:choose-a-password@postgres:5432/smtm?sslmode=disable
AUTH_PASSWORD_ENABLED: "true"
SESSION_COOKIE_SECURE: "true"
APP_SECRET_KEY: "at-least-32-random-characters" # openssl rand -base64 48
SERVE_OVER_TLS: "true"
caddy:
image: caddy:2
restart: unless-stopped
depends_on: [app]
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
volumes:
postgres_data:
caddy_data:
Next to it, save a file called Caddyfile with your own domain:
budget.example.com {
reverse_proxy app:8080
}
Already run a reverse proxy, such as Traefik, nginx or a Caddy of your own? Use the shorter file on the download page instead, which publishes the app on port 8080, and point your proxy at it.
2. Choose the passwords
Replace the two placeholders before the first start:
- The database password,
choose-a-password, which appears twice: once for PostgreSQL and once inDATABASE_URL. Use letters and digits only, so it needs no escaping in the URL. APP_SECRET_KEY, which encrypts the secrets the app stores (a SimpleFIN bank connection, authenticator keys). Generate one withopenssl rand -base64 48.
Keep a copy of APP_SECRET_KEY with your backups. A database restored without it keeps every transaction and envelope, but a bank connection has to be made again and authenticator apps enrolled again.
3. Start it
docker compose up -d
docker compose logs -f app
The log shows the database being set up, then the server listening. Press Ctrl+C to stop following the log; the app keeps running. Then open https://budget.example.com (your domain).
4. Create your account and invite the household
The first account created becomes the administrator; after that, sign-up closes. Invite everyone else from Settings › Members: up to four people in all, each with their own sign-in, sharing the same envelopes.
Each member can add a second factor (an authenticator app, or emailed codes once mail is set up) from Settings › Security. To make it compulsory for everyone, add SECOND_FACTOR_REQUIRED: "true" to the app's environment.
5. Start your trial, then add your licence
As the administrator, open Settings › Licence and start the free 30-day trial. The trial key is emailed to you; paste it in. When you subscribe, the licence key you receive goes in the same place. One subscription covers one household's installation. If it ever lapses, everything stays readable and exportable. See pricing.
6. Optional: mail
Mail is needed for invitations, emailed sign-in codes and statement reminders. Add your mail provider's details to the app's environment:
SMTP_HOST: smtp.example.com
SMTP_PORT: "587"
SMTP_USERNAME: you@example.com
SMTP_PASSWORD: your-smtp-password
SMTP_FROM: budget@example.com
Then run docker compose up -d again to apply it. Without mail everything else works: Settings › Members shows each invitation link for you to copy and send yourself.
7. Back it up
Everything lives in PostgreSQL. From the folder with compose.yaml:
# Back up
docker compose exec postgres pg_dump -U smtm smtm > backup.sql
# Restore into a fresh database
docker compose exec -T postgres psql -U smtm smtm < backup.sql
Run the backup on a schedule (a nightly cron job is plenty) and copy the files somewhere off the machine, along with APP_SECRET_KEY. Each book can also be exported from inside the app as a single file, encrypted with a password if you like.
8. Update
Administrators are told in the app when a new version is out. Change the version on the image: line to the new one (or use latest), then:
docker compose pull
docker compose up -d
The app upgrades its database on start. Take a backup first, as with any update.
Common questions
Can I use single sign-on instead of passwords?
Yes. OpenID Connect works with an identity provider you already run, such as Authentik or Keycloak, alongside passwords or instead of them. The settings are listed in the project's environment example.
Can I reach it without opening ports to the internet?
Yes. Leave Caddy out, use the download page's Compose file and reach it on your home network, or through a VPN such as WireGuard or Tailscale. Use HTTPS whenever it is reachable from outside.
My proxy is on another machine. What do I change?
The app believes the forwarded visitor address only from proxies it trusts, by default anything on the same machine or a private network. For a proxy elsewhere, set TRUSTED_PROXIES to its address, for example TRUSTED_PROXIES: "203.0.113.7".
Can I move from the desktop app to a server, or back?
Yes. Export each book from the app as a file and import it on the other. Your licence moves with a click in Settings › Licence.
Want to know what the server version offers before installing? See running ShowMeTheMoney on your own server.