Actual Budget on a VPS: Self-Hosted Personal Finance and Budgeting
Actual Budget is an open-source, local-first personal finance application based on envelope budgeting — the same methodology as YNAB (You Need A Budget). It stores data locally in a SQLite database with optional sync to a self-hosted server, keeping your complete financial history private. YNAB costs $109/year. Actual Budget is free, self-hosted, and gives you the same zero-based budgeting approach without sending your bank transactions to a cloud service.
Actual Budget vs YNAB vs Firefly III
- Actual Budget: Envelope budgeting (same as YNAB), local-first SQLite, clean UI, sync server optional, active development
- YNAB: $109/year, bank import automation, larger community, mobile app, cloud-hosted
- Firefly III: More complex, full double-entry accounting, better for detailed financial tracking, older UI
- Choose Actual Budget: YNAB methodology at zero cost, privacy-first, data ownership
Step 1: Docker Compose Setup
<code">mkdir -p /opt/actual && cd /opt/actual nano docker-compose.yml
<code">version: '3.8'
services:
actual:
image: actualbudget/actual-server:latest
container_name: actual-budget
restart: always
ports:
- "127.0.0.1:5006:5006"
environment:
ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB: 20
ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SYNC_SIZE_LIMIT_MB: 50
volumes:
- actual_data:/data
<code">mkdir -p data docker compose up -d docker compose logs -f actual
Step 2: Nginx Reverse Proxy
<code">sudo nano /etc/nginx/sites-available/actual
<code">server {
listen 80;
server_name budget.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name budget.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/budget.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/budget.yourdomain.com/privkey.pem;
client_max_body_size 20M;
location / {
proxy_pass http://127.0.0.1:5006;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
<code">sudo ln -s /etc/nginx/sites-available/actual /etc/nginx/sites-enabled/ sudo certbot --nginx -d budget.yourdomain.com sudo systemctl reload nginx
Step 3: Initial Setup
- Visit
https://budget.yourdomain.com - Create a password for the server (this is the sync password, not a user account)
- Choose “Start fresh” or “Import from YNAB” if migrating
- Create your first budget file
Step 4: Set Up Envelope Budgeting
<code"># Actual Budget uses zero-based/envelope budgeting: # 1. Enter your income as "To Budget" amount # 2. Assign every dollar to a category: # - Housing: $1,500 # - Groceries: $600 # - Transport: $400 # - Savings: $500 # - Emergency Fund: $200 # - Entertainment: $150 # - Total assigned = income (zero-based: every dollar has a job) # Categories to create: # Income: Salary, Freelance, Other Income # Fixed: Rent/Mortgage, Car Payment, Insurance, Subscriptions # Variable: Groceries, Dining Out, Gas, Entertainment, Clothing # Savings: Emergency Fund, Vacation, New Car, Retirement
Step 5: Import Bank Transactions
<code"># Import transactions from bank CSV export: # Bank website → Download transactions → CSV format # Actual Budget CSV format: # date, payee, amount, notes # 2025-03-01, Whole Foods, -87.43, Weekly groceries # 2025-03-01, Netflix, -15.99, Monthly subscription # 2025-03-01, Employer, 4200.00, March salary # Import: Budget → Transactions → Import → select CSV # Map columns: date, payee, amount # Actual categorizes automatically based on payee history # For OFX/QFX (standard bank format): # Most banks export in OFX — Actual imports this directly
Step 6: Sync Across Devices
<code"># Actual Budget supports sync between devices via your VPS server # All data is end-to-end encrypted before leaving the device # Mobile app (iOS/Android) → Settings → Advanced → Server URL: # https://budget.yourdomain.com # Desktop app (downloaded from actualbudget.org) → Settings: # Server URL: https://budget.yourdomain.com # Each device syncs changes when online — offline-first design # Your VPS stores encrypted budget file blobs, cannot read contents
Step 7: Reports and Insights
<code"># Built-in reports in Actual Budget:
# - Net Worth over time (assets - liabilities)
# - Spending by category (monthly breakdown)
# - Income vs Expense trend
# - Cash flow analysis
# Export data for custom analysis:
# Budget → More → Export data → downloads SQLite file or JSON
# Analyze with Python:
import sqlite3
import pandas as pd
conn = sqlite3.connect("budget.sqlite")
transactions = pd.read_sql("SELECT * FROM transactions", conn)
monthly_spending = transactions.groupby(
[pd.to_datetime(transactions.date).dt.to_period('M'), 'category']
)['amount'].sum().unstack()
print(monthly_spending.tail(6))
Getting Started
Actual Budget uses under 50 MB RAM — one of the lightest self-hosted applications available. It runs comfortably on the smallest Ubuntu VPS at VPS.DO. Since budget data is end-to-end encrypted client-side, even a compromised VPS cannot expose your financial information. For individuals and couples tracking finances privately, Actual Budget provides YNAB-equivalent envelope budgeting at zero software cost.
Conclusion
Self-hosted Actual Budget provides privacy-first personal finance management with envelope budgeting methodology, multi-device sync via your VPS, CSV and OFX import from banks, and offline-first operation. The end-to-end encryption means your VPS only stores encrypted blobs — financial data is never exposed even if the server is compromised. For the YNAB methodology at zero subscription cost with complete data ownership, Actual Budget is the definitive self-hosted alternative.