[{"data":1,"prerenderedAt":134},["ShallowReactive",2],{"seo-verification":3,"blog-self-host-actual-budget-on-a-vps-your-private-ynab-alternative-ma-en":6,"promo-bar-likely":133},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-self-host-actual-budget-on-a-vps-your-private-ynab-alternative-ma-en",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"noindex":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":28,"featuredImage":30,"bgImage":31,"posterImage":32,"relatedSolution":33,"intro":36,"sections":37,"ctaTitle":128,"ctaBody":129,"ctaButton":130,"ctaUrl":131,"relatedPosts":132},173,"self-host-actual-budget-on-a-vps-your-private-ynab-alternative",{"fr":12,"en":10,"ar":13,"es":14},"self-host-actual-budget-vps","استضافة-actual-budget-على-vps-بديل-ynab-الخاص-بك","alojar-actual-budget-en-un-vps","Self-Host Actual Budget on a VPS: Your Private YNAB Alternative","Self-host Actual Budget on a VPS — an MIT-licensed, zero-based budgeting app with bank sync, multi-device access and end-to-end encrypted sync. No subscription.",12,1,false,"2026-07-07T00:00:00+00:00","2026-10-29T03:10:23+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},7,"Self-hosting","self-hosting","bg-indigo-500\u002F10 text-indigo-400","cloud",[29],{"id":23,"name":24,"slug":25,"color":26,"icon":27},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fself-host-actual-budget-vps-poster.svg",{"categorySlug":34,"appSlug":35},"erp-business-management","actual-budget","YNAB proved that zero-based (envelope) budgeting works, but its $99\u002Fyear subscription and cloud-only model aren't for everyone. Actual Budget (MIT, ~26 k GitHub stars) brings the same methodology — assign every dollar a job before you spend it — to a self-hosted Node.js server that runs on a single Docker container. Your data stays in an SQLite file on your own VPS; every device syncs, with optional end-to-end encryption. Here is how to deploy it in minutes.",[38,42,45,55,58,61,83,86,104,107,110,113,124],{"type":39,"title":40,"body":41},"h2","Why self-host your budget instead of using YNAB","The envelope budgeting method is straightforward: allocate every incoming dollar to a named category (rent, food, savings, emergency fund) before spending it. When a category runs out, you either stop spending or consciously move money from another envelope. YNAB popularised this approach in a polished app — but it costs $99\u002Fyear, stores your financial data on its servers, and can't be audited. Actual Budget replicates the method (including the coveted 'roll with the punches' flexibility) with full source code on GitHub under the MIT licence. Self-hosting it on a VPS means your transactions, balances and budget history never leave your infrastructure — and the annual cost is whatever a small VPS costs.",{"type":39,"title":43,"body":44},"Deploy Actual Budget with Docker in two minutes","Actual ships as a single Docker image — no database server, no message broker, no configuration files. One container, one volume, one port. On your Ubuntu 22.04 VPS, run: `docker run -d --restart=always -p 5006:5006 -v actual-budget:\u002Fdata --name actual-budget actualbudget\u002Factual-server`. The server is ready in under two seconds on port 5006. Open `http:\u002F\u002F\u003Cyour-vps-ip>:5006` in a browser, click 'Create new budget', and you are budgeting. The entire SQLite database is stored in the `actual-budget` Docker volume — back it up with a single `docker run --rm -v actual-budget:\u002Fdata alpine tar -czf - \u002Fdata`. The folder mounted on `\u002Fdata` holds two subfolders, `server-files` and `user-files`: that is where the server’s entire state lives. For a lasting deployment, prefer a `docker-compose.yml` file (the official documentation points to the one in the repository, `packages\u002Fsync-server\u002Fdocker-compose.yml`) and start it with `docker compose up --detach`.",{"type":46,"title":47,"items":48},"ul","What you get out of the box",[49,50,51,52,53,54],"Zero-based envelope budgeting — assign every dollar to a category before spending; Actual flags overspending in real time.","Multi-device sync — phone, tablet and desktop all share the same live budget via the encrypted server.","Optional end-to-end encryption — once enabled in the settings, the server only stores ciphertext; your transactions are readable only on your devices.","Optional bank sync: Enable Banking (European banks, experimental feature), SimpleFIN Bridge (North America), Akahu (New Zealand) or Pluggy.ai (Brazil); per the documentation, GoCardless no longer accepts new accounts. Manual import of OFX\u002FQFX\u002FCSV files remains possible.","Reporting: net-worth chart, cash-flow, spending by category, and fully custom reports.","YNAB 4 and nYNAB import — migrate your full history in about five minutes.",{"type":39,"title":56,"body":57},"Requirements in figures for Actual Budget","Actual is one of the lightest services to host. On the machine side: a VPS with 1 GB of RAM running Ubuntu 22.04 is plenty, the application using around 80 MB at rest (check this on your own instance with `docker stats`). On the network side: a domain name, a DNS record pointing to the VPS, and ports 80 and 443 open for the reverse proxy; port 5006 can stay closed to the public once Caddy is in place. As for the server’s own figures: the default port is 5006, the data folder is `\u002Fdata` (variable `ACTUAL_DATA_DIR`), and file uploads are capped by default at 20 MB for sync and 50 MB for encrypted sync. A very old or large budget can exceed these thresholds; a sync reset then compresses the history. For bank sync, add an account with your chosen provider, its API keys and, for Enable Banking, a Production application whose redirect URL uses HTTPS.",{"type":39,"title":59,"body":60},"Add HTTPS so you can sync from anywhere","To access your budget from outside the VPS — on mobile or from another country — you need HTTPS. The simplest path is Caddy. Install it on the same VPS and add a one-line Caddyfile: `budget.yourdomain.com { reverse_proxy localhost:5006 }`. Caddy handles the Let's Encrypt certificate automatically. Once the domain resolves, open `https:\u002F\u002Fbudget.yourdomain.com` on your phone, tap the browser's 'Add to Home Screen' button, and Actual becomes a full PWA icon on your home screen. All sync traffic between your devices and the server goes through this TLS channel. This is not just a convenience. Actual needs a secure context to enable `SharedArrayBuffer`, which its SQLite engine uses: without HTTPS, the app refuses to start in the browser. The official documentation lists three causes for this block: no HTTPS, `Cross-Origin-Embedder-Policy` and `Cross-Origin-Opener-Policy` headers set incorrectly, or a browser that is too old. With the default `actual-server`, both headers are already sent; if you go through Nginx, do not duplicate them (see troubleshooting below). Bank sync adds a second reason: the redirect URL registered with the provider must use `https`.",{"type":62,"title":63,"steps":64},"steps","Setup in six steps",[65,68,71,74,77,80],{"title":66,"body":67},"Create a VPS (1 GB RAM, Ubuntu 22.04)","Actual idles under 80 MB RAM. Even the smallest VPS plan gives you plenty of headroom.",{"title":69,"body":70},"Deploy the container","`docker run -d --restart=always -p 5006:5006 -v actual-budget:\u002Fdata --name actual-budget actualbudget\u002Factual-server`",{"title":72,"body":73},"Create your budget","Open port 5006 in a browser, click 'Create new budget', add your bank accounts with opening balances.",{"title":75,"body":76},"Set up envelope categories","Create categories (Housing, Food, Transport, Savings…) and allocate your expected monthly income across them.",{"title":78,"body":79},"Secure with HTTPS","Install Caddy, add `budget.yourdomain.com { reverse_proxy localhost:5006 }` to your Caddyfile, and reload.",{"title":81,"body":82},"Install on mobile","Open the HTTPS URL on your phone and use 'Add to Home Screen' — Actual Budget becomes a PWA icon.",{"type":39,"title":84,"body":85},"Bank sync: Enable Banking, an experimental feature","Actual’s official documentation lists Enable Banking among its sync providers, for European banks, and calls it an experimental feature: it may have bugs, missing functionality, incomplete documentation, and may be removed in a future release. It may also be absent from the latest stable release; the page advises enabling experimental features and using the `nightly` images for the most recent implementation. User feedback is gathered in GitHub issue no. 7799 (opened in May 2026, labelled “experimental feature”, still open when we reviewed it). It contains no list of guaranteed banks: it is up to you to check, in Actual’s wizard, that your country and bank appear, then to test on a single account before relying on it. Also remember that the provider’s keys live on your server: a properly hardened VPS and protected backups are part of the setup.",{"type":62,"title":87,"steps":88},"Set up Enable Banking in Actual in five steps",[89,92,95,98,101],{"title":90,"body":91},"Create the application at Enable Banking","Sign in to your Enable Banking account, create a new application and choose the Production type.",{"title":93,"body":94},"Declare the redirect URL over HTTPS","Use your domain followed by `\u002Fenablebanking\u002Fauth_callback`, for example `https:\u002F\u002Fbudget.example.com\u002Fenablebanking\u002Fauth_callback`, then click Register. The scheme must be `https`.",{"title":96,"body":97},"Link your accounts on the Enable Banking side","First link the accounts you want in Enable Banking’s interface; otherwise, the documentation warns, you will see neither a list of banks nor a list of accounts in Actual.",{"title":99,"body":100},"Enter the application ID and the key","Copy the Application ID (format `12345678-1234-1234-1234-123456789012`) with no space before or after. In Actual: More → Bank Sync → Set up Enable Banking, paste the ID and provide the `.pem` private key file.",{"title":102,"body":103},"Link an Actual account to your bank","In an Actual account, choose Link account → Enable Banking, select your country and bank, then follow the bank’s authorization flow. Check the first imported transactions before moving on to another account.",{"type":39,"title":105,"body":106},"How to back up your budget","All data lives in the `actual-budget` Docker volume. A daily cron backup is one command: `docker run --rm -v actual-budget:\u002Fdata -v \u002Fbackups:\u002Fout alpine tar czf \u002Fout\u002Factual-budget-$(date +%Y%m%d).tar.gz \u002Fdata`. Restore by reversing the tar into a fresh volume before starting the container. Actual also has a built-in export: from Settings, in the Data section, click “Export data”. This creates a portable ZIP of your entire budget that you can import on any other Actual instance. Two clarifications. First, this volume also holds your bank-sync credentials: the documentation says they are stored on the server, outside end-to-end encryption, so anyone with access to the database can read them. Treat the archive as a secret: restricted permissions, an encrypted copy kept off the VPS. Second, after a restore, the documentation recommends a sync reset (Settings → Advanced → Reset Sync), done from the device holding the most recent changes, so the backup does not sync back to its old state. Test a full restore on a throwaway instance at least once: a backup that has never been restored remains a hypothesis.",{"type":39,"title":108,"body":109},"End-to-end encryption: what it covers and what it does not","Actual’s end-to-end encryption is optional. To enable it, open the budget, go to the settings, Encryption section, click “enable encryption” and choose a password: a key derived from that password encrypts your data before it leaves the device. A few points to know before clicking. It is irreversible: you cannot turn it off, and going back to an unencrypted file means a backup and restore. If you lose the password, the documentation is clear: your encrypted data is unrecoverable, unless you keep a local copy, with which you can reset the key. Each new device must enter the password once, and it should differ from the server password. Enabling it requires a sync reset, and encryption costs a slight slowdown during sync. Finally, it covers only the budget data: bank-sync keys stay on the server side, and the device’s local data is not encrypted, hence the value of disk encryption.",{"type":39,"title":111,"body":112},"Update Actual without losing your data","Updating means replacing the image, not the data. With Docker Compose: `docker compose pull && docker compose up -d`. With this guide’s `docker run` command, the documentation describes three steps: `docker stop`, then `docker container rm` on the container, then the same `docker run` relaunched with `--pull=always`. As long as the `actual-budget` volume is kept, the budget survives the container’s replacement. Before each update, make the backup from the previous section; this matters most if you use a `nightly` image to try bank sync, as the documentation recommends backing up before trying that branch. One known trap: when going back from a `nightly` image to a stable tag, you may hit “This budget cannot be loaded with this version of the app”; the restore page then points to a manual SQLite migration, which is best not improvised on the only copy of your data. After the update, open the app and check the last synced transaction and an account balance.",{"type":46,"title":114,"items":115},"Troubleshooting: real messages and known causes",[116,117,118,119,120,121,122,123],"`SharedArrayBufferMissing` (fatal error on load) — no HTTPS, COOP\u002FCOEP headers missing or duplicated, or a browser that is too old. With Nginx, hide the upstream headers (`proxy_hide_header Cross-Origin-Embedder-Policy;` and `proxy_hide_header Cross-Origin-Opener-Policy;`) and set them once: `require-corp` and `same-origin`.","`Enable Banking API error: status=403 body={\"code\":403,\"message\":\"Application is not active\"}` — the Enable Banking application is not yet activated; the account list stays empty with no error in the interface (reported in issue no. 7799).","Application not found although the ID is correct — a leading space in the Application ID is enough to make the connection fail; remove it (a user asked in the issue for the space to be trimmed and the message clarified).","`URL \"app:\u002F\u002Factual\u002Fenablebanking\u002Fauth_callback\" uses unsupported scheme` — Enable Banking support only handles `https` redirects; it suggested an HTTPS redirect that then forwards to the app scheme.","`Could not validate the credentials. Please check your Application ID and secret key.` — reported only in Firefox with values that worked in Chromium; no workaround is recorded, try another browser for the initial setup.","Empty payees or payees identical to the notes, wrong card balance — these behaviours are reported in issue no. 7799 (for example the first balance returned, sometimes the available credit, shown in place of the booked debt). They are limits of the experimental implementation, not an error in your installation: compare with the bank statement.","`PostError: network-failure`, `Wrong transactions period requested`, several Enable Banking applications — reported in the same issue with no recorded fix. If you created a second application, unlink the accounts and put them all under one: syncing the accounts linked through the first one failed after the second was added.","Detailed logs — add `DEBUG=actual-sensitive:enable-banking,actual-sensitive:bank-sync` to the container environment, restart, reproduce the error, then remove the variable.",{"type":125,"title":126,"body":127},"tip","Never post “sensitive” logs as they are","The documentation warns that these logs may contain credentials, bank information or other private data: do not paste them into a public issue or on Discord. Also avoid `DEBUG=*` or `DEBUG=actual*`, which enable sensitive output too; for ordinary debugging, `DEBUG=actual:*` is enough. Review and redact the excerpt before passing it to the maintainer helping you, and restore the previous `DEBUG` value once the diagnosis is done.","Deploy Actual Budget on your VPS","Private, zero-based budgeting with no subscription — your financial data stays on your own server, synced across every device.","Deploy Actual Budget","\u002Fvps-cloud",[],true,1794270480703]