Why Your Budget Belongs on Your Own Server
Most personal finance apps ask you to hand over your bank credentials, transaction history, and spending patterns to a third-party cloud service. Actual Budget, an open-source fork of the original YNAB-style zero-based budgeting tool, changes that arrangement entirely. You run the server. You own the data. Nobody else sees your numbers unless you choose to share them.
Actual Budget operates on a zero-based budgeting model, meaning every dollar you earn gets assigned a job before you spend it. The interface is clean, fast, and deliberately simple – categories, accounts, and a monthly budget grid. There are no subscriptions, no ads, and no API calls going to a company’s cloud backend.
Self-hosting it takes about twenty minutes if you already run Docker.

What You Need Before You Start
This guide assumes you have a Linux machine or a home server running Docker and Docker Compose. A Raspberry Pi 4, a repurposed desktop, or a cloud VPS with 512MB of RAM will all handle Actual Budget without strain. The app is lightweight by design – it runs a small Node.js server and stores data in SQLite files, not a heavy relational database.
You will also want a reverse proxy like Nginx or Caddy if you plan to access your budget from outside your home network. If you are only accessing it on your local network, you can skip the reverse proxy entirely and connect directly via the server’s local IP address. For anyone already running a WireGuard VPN on a home server, accessing Actual Budget remotely through that VPN tunnel is a clean solution that avoids exposing the service to the open internet – setting up WireGuard VPN on a Raspberry Pi is a solid starting point if you need that layer first.
Before writing a single line of configuration, create a dedicated directory for your Actual Budget data. Running mkdir -p ~/actualbudget/data gives you a clean folder structure. All budget files, including your SQLite database and any uploaded attachments, will persist in that data folder even when you update or restart the container.
Installing Actual Budget with Docker Compose
Create a file called docker-compose.yml inside your ~/actualbudget directory. Paste the following configuration into it:
- Image: actualbudget/actual-server:latest
- Container name: actual_budget
- Port mapping: 5006:5006
- Volume: ./data:/data
- Restart policy: unless-stopped
A minimal working compose file looks like this:
version: “3.8”
services:
actual:
image: actualbudget/actual-server:latest
container_name: actual_budget
ports:
– “5006:5006”
volumes:
– ./data:/data
restart: unless-stopped
Run docker compose up -d from inside the ~/actualbudget directory. Docker will pull the image and start the container in detached mode. Open a browser and navigate to http://your-server-ip:5006. You will see the Actual Budget setup screen on your first visit, where it asks you to set a server password. Set something strong – this password gates access to every budget file stored on the instance.

Setting Up Your First Budget
After logging in, Actual Budget prompts you to create a new budget file or import one from YNAB or a previous Actual export. If you are starting fresh, click Create new file and give it a name. The app then drops you into the main budget view: a grid of months across the top, categories down the left, and columns for budgeted, spent, and remaining amounts.
Adding accounts is the first real setup task. Go to Add account in the left sidebar and choose between an on-budget account, which flows into your category totals, and an off-budget account, used for tracking assets like investments or loans without affecting your monthly spending plan. Add your checking account, savings accounts, and any credit cards you actively use. For each account, enter the current balance. Actual Budget is not a bank aggregator – it does not connect to your bank automatically by default. You enter transactions manually, import CSV files from your bank, or use the optional bank sync integration if you self-host a supported sync provider.
Build your category groups next. A practical starting structure includes groups like Housing, Food, Transportation, Utilities, and Personal. Within each group, create specific categories – Groceries and Dining Out under Food, for example. Once your categories exist, click into the current month and type budget amounts into each row. Zero-based budgeting means your total budgeted amount should equal your expected income for the month. Actual Budget shows a running “to be budgeted” number at the top that counts down to zero as you assign funds.
Keeping the Data Safe and the App Updated
Actual Budget stores everything in a single SQLite file inside your ./data directory. Backing it up is straightforward: copy that folder to an external drive, an encrypted cloud bucket, or a remote server on a schedule using a cron job. A daily cron that runs cp -r ~/actualbudget/data ~/backups/actualbudget-$(date +%F) gives you dated snapshots with minimal effort. Because the data is just flat files with no running database daemon to coordinate, you can restore from backup by stopping the container, replacing the data folder, and restarting.
Updating the app is equally simple. Pull the latest image with docker pull actualbudget/actual-server:latest, then restart the container with docker compose down followed by docker compose up -d. Your data folder is mounted as a volume outside the container, so updates never touch your budget files. The Actual Budget project releases updates regularly, and the changelog is worth checking before major version jumps to catch any migration notes for the SQLite schema.
If you want access from a phone or a second computer without exposing port 5006 to the internet, Actual Budget’s web interface works on mobile browsers without any native app required. Point your phone’s browser at the local IP while connected to your home Wi-Fi, or route through a VPN to reach it from anywhere.

What Running It Actually Feels Like
After a month of use, the self-hosted setup disappears into the background. Actual Budget’s interface responds instantly because the server is local, budget files load in under a second, and there is no spinner waiting on a remote API. The manual transaction entry, which some people see as friction, turns out to be the point – entering a purchase by hand creates a moment of awareness that most automated tools actively work to eliminate. That friction is where the budgeting actually happens.





