Actual Budget on Ubuntu 24.04 on Azure User Guide
Overview
Actual Budget is a free, open source, local first personal finance application built around the proven envelope budgeting method. Give every unit of money a job across category groups, reconcile your accounts and get an honest, precise picture of your finances. Actual runs as a self hosted sync server with a bundled web app, and the same server keeps the Actual desktop and mobile clients in sync, so all of your financial data stays private on infrastructure you control. The cloudimg image delivers Actual Budget fully installed and configured on Ubuntu 24.04 as a Node.js sync server behind an nginx reverse proxy, so a complete budgeting service is running within minutes of launch. Backed by 24/7 cloudimg support.
Actual Budget is licensed under the MIT License. All product and company names are trademarks or registered trademarks of their respective holders. This image repackages the upstream open source release with cloudimg's provisioning and support.
What is included:
- Actual Budget 26.6 (the
@actual-app/sync-server26.6.0 release, MIT), installed globally with npm on Node.js 22 LTS - nginx as a reverse proxy on port 80, forwarding to the sync server on loopback
127.0.0.1:5006 - All persistent data (the
account.sqliteserver database, plus the server-files and user-files budget blobs) on a dedicated, independently resizable Azure data disk mounted at/var/lib/actual - A per-VM server password generated on first boot and written to a root-only file, so no default or shared login ships in the image
actual-budget.serviceandnginx.serviceas systemd units, enabled and active- 24/7 cloudimg support

Prerequisites
An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point; scale up for larger households or heavy sync activity. NSG inbound: allow 22/tcp from your management network and 80/tcp (HTTP) from your users. Add 443/tcp if you enable HTTPS.
Step 1 — Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Actual Budget by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Then Review + create and Create.
Step 2 — Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name actual-budget \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
Open HTTP to reach the web UI:
az vm open-port --resource-group <your-rg> --name actual-budget --port 80 --priority 900
Step 3 — Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 — Confirm the services are running
The two services that back Actual Budget should both report active, and the unauthenticated /account/needs-bootstrap health endpoint answers through nginx on port 80:
systemctl is-active actual-budget nginx
curl -s http://127.0.0.1/account/needs-bootstrap; echo
Expected: two lines of active, then a JSON body reporting "bootstrapped":true. The Actual sync server listens only on the loopback address 127.0.0.1:5006; nginx on port 80 is the only exposed application port, so the server is never reachable directly.

Step 5 — Retrieve your server password
On the first boot of every VM, a one-shot service (actual-budget-firstboot.service) starts the sync server, generates a server password that is unique to that VM, and applies it through Actual's own bootstrap mechanism, which bcrypt-hashes it into the server database. No shared or default password ships in the image.
sudo cat /root/actual-budget-credentials.txt
The file (mode 0600, root only) contains the sign-in URL (ACTUAL_URL) and the server password (ACTUAL_SERVER_PASSWORD).

You can prove the sign-in round-trip from the VM's own shell. This reads the per-VM password and posts a real sign-in; a correct password answers HTTP 200 and the server returns a session token:
PASS=$(sudo grep '^ACTUAL_SERVER_PASSWORD=' /root/actual-budget-credentials.txt | cut -d= -f2-)
echo -n 'sign-in HTTP status -> '
curl -s -o /dev/null -w '%{http_code}\n' -X POST http://127.0.0.1/account/login \
-H 'Content-Type: application/json' \
-d "$(jq -nc --arg p "$PASS" '{loginMethod:"password",password:$p}')"
Expected: sign-in HTTP status -> 200, confirming the password in the file signs in.
Step 6 — Sign in and create your budget
Browse to http://<vm-public-ip>/ and enter the server password from the credentials file. Actual then offers to Start fresh with a new empty budget, Import my budget from an Actual, YNAB or nYNAB export, or View demo data. Choose Start fresh to begin. Actual opens the monthly envelope budget, where you assign every unit of available money to a category group so you always know what is left to spend.

Step 7 — Add accounts and review reports
Open Accounts and add your asset accounts (checking, savings, credit cards). You can create a local account and enter transactions manually, import QIF/OFX/QFX files, or configure bank sync so transactions download automatically.

The Reports dashboard summarises your finances with configurable widgets for net worth, cash flow, income and expenses over time, so you can see trends at a glance.

To keep budgeting on the move, install the Actual desktop or mobile app, point it at http://<vm-public-ip>/, enter the same server password, and your budget stays in sync across every device.
Step 8 — Confirm the version, the stack and the data disk
node -e "console.log('@actual-app/sync-server ' + require('/opt/actual/lib/node_modules/@actual-app/sync-server/package.json').version)"
node --version
findmnt /var/lib/actual
Expected: @actual-app/sync-server 26.6.0, Node.js v22, and /var/lib/actual mounted from the dedicated data disk (/dev/sdc). The server database and all budget files live on that disk, which is independently resizable and survives instance replacement — resize it from the Azure portal if you need more room.

First-boot service and security model
A one-shot actual-budget-firstboot.service runs after the network is up. It starts the sync server, generates a fresh server password unique to the VM, applies it through the server's own POST /account/bootstrap endpoint, resolves the instance address from the Azure instance metadata service, writes the credentials file at mode 0600 (root only) and drops a sentinel so it runs exactly once. The image ships with an empty database and no usable login; the per-VM password is created on first boot.
systemctl is-active actual-budget-firstboot.service
sudo stat -c '%a %U:%G %n' /root/actual-budget-credentials.txt
Expected: active, then 600 root:root /root/actual-budget-credentials.txt.

Enabling HTTPS with your own domain
The image serves the web UI over plain HTTP on port 80. For a browser-trusted certificate, point a DNS record at the VM, open port 443 in the NSG, and install a certificate from your CA (for example Let's Encrypt):
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com
Certbot updates the nginx site to serve your domain certificate. Actual is served behind the proxy on loopback, so no application configuration change is needed; your budget is then reachable over HTTPS at your domain.
Backup and maintenance
Actual stores everything, including the account.sqlite server database and all budget files, under /var/lib/actual on the dedicated data disk, so a backup is a single directory. Snapshot the data disk and OS disk from the Azure portal for a full point-in-time copy, or archive the tree:
sudo tar -C /var/lib -czf /var/backups/actual-$(date +%F).tar.gz actual
Keep the OS current with sudo apt-get update && sudo apt-get upgrade; the image ships with unattended security updates enabled. Review the Actual Budget documentation before moving between releases, and always back up before an upgrade. Actual also supports optional per-file end to end encryption, configured inside the app, if you want the budget data encrypted at rest with a key only you hold.
Support
This image is backed by 24/7 cloudimg support for deployment and initial configuration, retrieving the first-boot server password, multi device sync setup, importing existing budgets from YNAB, nYNAB or Actual exports, end to end encryption, HTTPS and custom domain setup, performance tuning and storage administration. Email support@cloudimg.co.uk or use the live chat in the support portal; critical issues receive a one-hour average response.