Should I self-host YNAB?
Actual does zero-based budgeting with your data in a SQLite file you can read, and bank sync via SimpleFIN costs less than one month of YNAB per year.
YNAB's first-party bank sync — Actual needs SimpleFIN Bridge (~$1.50/mo) or GoCardless for EU banks, one more account to hold
The YNAB method community, workshops and support humans
Nobody to email when a sync breaks the night before rent is due
envelope (zero-based) budgeting · bank sync · multi-device sync · spending reports
* Percent of the subscription price. Your time is priced at the slider's rate — $0/h ("my homelab time is free and I love it") is a legitimate position. Every number is derived from the record, never hand-written. Price source, checked 2026-08-05.
Runs comfortably on a Raspberry Pi.



Silent exit where IPv6 is disabled: the server binds '::' by default, logs 'Listening' and then exits cleanly — ACTUAL_HOSTNAME=0.0.0.0 fixes it, and the clean exit code makes it a genuinely nasty diagnosis
# Actual Budget — local-first budgeting server (replaces YNAB)
services:
actual:
image: actualbudget/actual-server:latest
container_name: actual
restart: unless-stopped
environment:
# The server binds "::" by default and exits silently where IPv6 is disabled
# (CI runners, some VPS images). Bind IPv4 explicitly.
ACTUAL_HOSTNAME: 0.0.0.0
ports:
- "5006:5006"
volumes:
- actual-data:/data
healthcheck:
test: ["CMD-SHELL", "node -e \"fetch('http://localhost:5006').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\""]
interval: 5s
timeout: 5s
retries: 24
start_period: 20s
volumes:
actual-data:
Want a guided install instead? caniselfhostit.com/ynab has AI-agent prompts that assume a bare machine — that's their half of the stool, and it's good.
FULL TIMED LOG
# Timed setup log: YNAB → Actual Budget **Protocol:** v1 · **Verified by:** zernonia · **Date:** 2026-08-10 **Assistant:** claude-code · **Environment:** containerized runner, 2 vCPU class, Docker 29.3 / Compose v5.1 ## Timeline | Step | Time | |---|---| | Draft compose (one container) | 6 min | | **Boot #1 failed** — container exits cleanly ~2 s after "Listening on :::5006" (see What broke) | 15 min to diagnose | | Add `ACTUAL_HOSTNAME: 0.0.0.0`, re-up | 2 min | | **Boot #2: healthy in 6 s (measured, `compose up --wait`)** | 1 min | | Core workflow: set server password, create budget file, add account + transactions | 12 min | | Re-run from clean volumes | 4 min | | **Total: ~40 min** | | ## Measurements - Boot to healthy: **6 s** · 1 container · idle RAM ~120 MB — Raspberry Pi territory ## What broke 1. **Silent exit where IPv6 is disabled.** The server binds `::` by default; on hosts with IPv6 off (CI runners, some hardened VPS images) it logs "Listening on :::5006" and then exits with code 0 — no error, no hint. `ACTUAL_HOSTNAME=0.0.0.0` fixes it. This one cost real diagnostic time because a clean exit looks like success everywhere except `docker ps`. ## Verdict-relevant notes - Envelope budgeting, reports, multi-device via the server: covered. Your budget is a SQLite file you can copy, which is the whole philosophical pitch. - Bank sync is the honest asterisk: SimpleFIN Bridge (~$1.50/mo, US/CA) or GoCardless (EU) — one more account, and it's the part most likely to need the occasional poke.