Actual Budget Self-Hosted: One Container, Two Catches
Actual Budget self-hosted is one container with no database. What the guides skip: the server never backs itself up, and bank sync is manual and paid.

⚡ The short version
Actual Budget self-hosts as one container with no database beside it, which makes it one of the easiest things on this site to install. Two things the install guides leave out: the server keeps no backups of its own, because automatic backups only exist in the desktop app, and bank sync is neither automatic nor free. Both are fine once you know them and both are unpleasant surprises at month three.
Almost every guide to this app stops at the moment the container starts. That is the easy part, and what follows it decides whether you are still using Actual in six months.
Everything below about Actual Budget comes from the project’s own repository and documentation source, read on 28 September 2026, plus the container registry read the same day. Where the project does not publish a number, this post says so instead of filling the gap.
Is It Really Just One Container?
Yes. The project publishes one compose file with one service in it, and no database, cache or worker beside it.
That puts Actual in the same group as Uptime Kuma and Navidrome — apps that store text and settings in a file and serve them back, which is why counting the services in fifteen projects found seven of them installing as a single container. Actual is one of those seven, and the reason is that it ships SQLite inside the image rather than asking you for PostgreSQL.
Here is the file the project ships, trimmed of its comments and pinned to the current stable release:
services:
actual_server:
image: docker.io/actualbudget/actual-server:26.9.0
ports:
- '5006:5006'
volumes:
- ./actual-data:/data
healthcheck:
test: ['CMD-SHELL', 'node scripts/health-check.js']
interval: 60s
timeout: 10s
retries: 3
start_period: 20s
restart: unless-stopped
Two details in there are worth the ten seconds. The tag is 26.9.0, not v26.9.0: the git tag carries the v and the registry does not, and asking for the v-prefixed form returns a 404. And the healthcheck is the project’s own script, so docker ps tells you whether the app is answering rather than whether the process is alive.
If you have never run a compose file before, the Docker workflow for self-hosting covers the surrounding commands. Actual needs nothing beyond them.
Which Tag for a Raspberry Pi?
The Alpine one, if the Pi is running a 32-bit OS. Read from the registry on 28 September 2026:
| Tag | Architectures published |
|---|---|
26.9.0 and latest |
linux/amd64, linux/arm64 |
26.9.0-alpine and latest-alpine |
linux/amd64, linux/arm64, linux/arm/v7, linux/arm/v6 |
The documentation recommends the Alpine images because they are small, which is true and is not the reason that matters. The reason that matters is that they are the only ones that publish 32-bit ARM at all. A Pi 4 on 64-bit Raspberry Pi OS takes either tag; the same Pi on the 32-bit image takes only the Alpine one, because the plain tag’s manifest list has no 32-bit ARM entry for Docker to match. The Raspberry Pi self-hosting guide has more on which workloads belong on that hardware.
Where Does Your Money Data Actually Sit?
In two places at once, and that is the design rather than an accident.
Actual is local-first. The full budget lives in the browser or app you are using and the server holds a synced copy, which is why it keeps working with the network down. The project describes it as data local by default, syncing in the background when the internet is available.
On the server side, the one directory you mounted splits in two:
| Path | What the server puts there |
|---|---|
/data/server-files |
account.sqlite — the hashed server password, the list of budget files it knows about, the active session token |
/data/user-files |
every budget file, stored as a binary blob |
Read the second row twice, because it changes what a backup means. The server does not hold a readable copy of your budget, only blobs it passes around. The readable export, a zip holding db.sqlite and metadata.json, comes from the client through Settings and cannot be lifted off the server with a file copy.
The sync size limit is a default, not a ceiling, and it bites old budgets. Actual caps a sync upload at 20 MB out of the box, and 50 MB for an encrypted file. A budget file grows because the app stores every change you ever made, so a file several years old can walk into that limit. The project's fix is a sync reset, which compresses that history into a single file; the config keys to raise the limit are documented too.
Who Backs Up the Server, You or Actual?
You do, and this is the first of the two catches.
Actual does keep automatic backups — up to ten, plus several from the current day, leaving a copy no more than about fifteen minutes old. The documentation puts a caution box around that feature: it is currently only available in the desktop app. Run the container and reach it through a browser, which is what every self-hosting guide describes, and nothing on that server is copying anything.
So the backup is yours, and it is the easy shape: stop the container, archive the mounted directory, start it again. That is exactly the case the guide to backing up Docker volumes walks through, and a single-container app with one data directory is the version of it with no database dump step in the middle.
One honest wrinkle. Because the server’s copy is a blob rather than a database you can open, the archive proves nothing until you have restored it once and watched the app read it back. The backup strategy post calls testing the restore the step that matters most, and it matters more here: you cannot inspect the archive to reassure yourself, so the restore is the only evidence there is. Pair it with an occasional export from inside the app.
End-to-End Encryption or Plain Sync?
Take it if you do not control the server, and understand it is a one-way door before you touch it.
Encryption adds a second password, separate from the server password, after which the server passes around data it cannot read. The documentation is blunt about the cost: you will not be able to recover your data if you forget that password. Lose it and the local copy together and the budget is gone.
✅ Turn it on if
- The server is rented, shared, or somewhere you would not store a bank statement
- Two people share the instance and should not read each other's budgets — separate files take separate passwords
- You are using bank sync, because the provider credentials are stored on the server
❌ Leave it off if
- The box is yours, at home, and already behind full-disk encryption
- You are new to Actual and still deciding whether you will keep it
- You have nowhere reliable to keep a second password you can never reset
Three mechanics nobody mentions. Enabling it forces a sync reset, because the server has to forget the unencrypted data it holds, and every other device then reverts to the new version. It cannot be switched off — the documented route back is to export, start a fresh file and import. And local data stays unencrypted either way, so the protection covers the server and the wire, not the laptop; the project recommends full-disk encryption for that half. The bank-sync line above is the project’s own: its documentation asks for encryption and a strong passphrase precisely because the provider keys end up on your server.
Will It Pull In Your Bank Transactions?
Not on its own, and this is the second catch.
The documentation states it directly: Actual does not sync bank data automatically. To fetch new transactions you click Bank Sync, on one account or on all of them. If what you wanted was a feed that fills itself in while you ignore it, that is a different product.
The provider situation is the other half, and it moves. As of the documentation read on 28 September 2026:
| Provider | Region | State |
|---|---|---|
| SimpleFIN Bridge | North American banks | Supported, and a paid subscription of its own |
| GoCardless | European banks | Not accepting new accounts |
| Enable Banking | European banks | Supported, behind the experimental-features flag |
| Akahu | New Zealand banks | Supported, behind the experimental-features flag |
| Pluggy.ai | Brazilian banks | Supported |
Read the two European lines together, because most write-ups only know the first one. GoCardless, the route every older guide sends you to, is closed to newcomers. Enable Banking is the documented replacement and is open — but it ships as an experimental feature, so the option does not appear until you turn experimental features on, and the project warns that experimental work may not be in the latest stable release. If you would rather not put an experimental integration in front of your bank, importing a file from your bank by hand is supported, and is how plenty of people use Actual anyway.
Whichever provider you use, you bring your own credentials: you sign up, generate keys, and Actual stores them on your server. SimpleFIN charges for its bridge. This post does not print the figure, because the only number available here sits in a documentation page rather than on SimpleFIN’s own site — check it at the source. There is no version of this where Actual is free and the bank connection is too.
Plaid is not one of the options. It gets named in older write-ups and comparison posts, and it is not on the supported-provider list at all — the integration was deleted in release 24.5.0 as no longer working. The five above are the list; the only Plaid route left is a third-party project the docs link under community repositories.
One Shared Password or an Account Each?
One shared password, unless you add an identity provider.
A default install has a single server password. Everyone in the household types the same one, and the server has no idea which of them is which. For a couple sharing a budget that is often exactly right and needs nothing further.
If you want named users, the project has them: a User Directory with Basic and Admin roles, per-file access and the ability to transfer ownership of a budget. The documentation gates all of it behind one requirement — it needs an OpenID provider configured, because the usernames come from that provider. So named accounts mean running something like self-hosted SSO with Authentik first, which is a much larger project than the budgeting app it is fronting. The server’s login method setting takes password, header or openid, with openid still described as in preview.
There is a middle route that costs nothing: separate budget files, each with its own encryption password. Two people then share one server and genuinely cannot open each other’s budgets, with no identity provider anywhere.
Whatever you choose, do not put port 5006 on the open internet with one password in front of it. Put it behind a reverse proxy with real certificates, or keep it on a private network and reach it through Tailscale.
Should You Run It, or Not?
Run it if you want an envelope budget you own, and you are the sort of person who will actually open it every few days. It is genuinely one container, it is quick on hardware you already have, and the data is in a format you can export whenever you like.
Do not run it if the appeal was automation. An app that pulls transactions in by itself and nags you about them is a category Actual deliberately is not in: the sync is a button, the categorising is yours, and the discipline is the product.
And do not run it first if the alternative is losing the data. This is the one app on a home server where the file is irreplaceable — nobody else holds a copy of your budget, unlike the photos that are also on your phone. Have the backup working before the second month. The wider case for moving off subscriptions is in the ten apps that replace SaaS; this is one of the few where the replacement costs a backup habit rather than disk space.
Frequently Asked Questions About Self-Hosting Actual Budget
Is Actual Budget free to self-host?
The software is, and it stays free however many budgets or people you put on it. Two things around it are not. Bank sync runs through a third-party provider whose account you pay for yourself, and the server is a machine you are already renting or already running. Actual itself asks for no licence, no account and no tier, and nothing in the app is held behind a paid plan.
Does Actual Budget need PostgreSQL or Redis?
Neither. The project’s own compose file, read on 28 September 2026, defines exactly one service and mounts a single directory into the container. The server keeps its own state in a SQLite file it creates there, and your budget files sit beside it as binary blobs. Any guide that hands you a database container alongside Actual is describing a different application.
Does self-hosted Actual Budget run on a Raspberry Pi?
Yes, and which tag you pick decides whether it runs on an older one. Read from the registry on 28 September 2026, the default image publishes amd64 and arm64 only. The Alpine variant of the same release publishes amd64, arm64, arm/v6 and arm/v7, so a 32-bit Pi OS install needs the Alpine tag rather than the plain one. On a 64-bit Pi either works.
Can I turn off end-to-end encryption later?
No, and the project says so plainly in its own documentation. Enabling it is a one-way move. The only route back to an unencrypted file is to export your data, start a fresh file and import it, which is the backup and restore path rather than a setting. Decide before you switch it on, not after.
Does Actual Budget import bank transactions automatically?
No. The documentation states that Actual does not sync bank data automatically, and that fetching new transactions means clicking Bank Sync, either on one account or on all of them. So the integration saves you typing, not attention. If an unwatched feed of transactions is the thing you are buying a budgeting app for, this is the wrong one.
Product links on this site are plain links. We earn nothing from them — see our disclosure policy.