ezBookkeeping
Overview
ezBookkeeping is a lightweight, open source, self-hosted personal finance application for tracking accounts, income and expenses across multiple currencies. It pairs precise double-entry-style bookkeeping with a fast, mobile-friendly web interface, so capturing a purchase takes seconds while the underlying ledger stays accurate.
The SecureAnyCloud image delivers ezBookkeeping fully installed and configured on Ubuntu 24.04 as a single hardened Go service behind an nginx reverse proxy. A complete private bookkeeping service is running within minutes of launch.
What you get:
- ezBookkeeping 1.6.1 (the official upstream
linux-amd64release, MIT), a single self-contained Go binary serving both the JSON API and the prebuilt web frontend - nginx as a reverse proxy on port 80, forwarding to the application on loopback
127.0.0.1:8080 - All persistent data (the SQLite database, the object store for receipt images and avatars, and the application log) on a dedicated, independently resizable Azure data disk mounted at
/var/lib/ezbookkeeping - Two secrets generated per VM on first boot: the key that signs every login session, and the password for the single administrator account, written to a root-only file
- Self-registration switched off, so nobody can claim your instance before you sign in
ezbookkeeping.serviceandnginx.serviceas systemd units, enabled and active- 24/7 SecureAnyCloud support
ezBookkeeping 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 SecureAnyCloud's provisioning and 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 comfortable starting point. ezBookkeeping is a single Go binary with an embedded database and idles at around 25 MiB of memory.
- NSG inbound: allow
22/tcpfrom your management network and80/tcp(HTTP) from your users. Add443/tcpif you enable HTTPS.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for ezBookkeeping by SecureAnyCloud, 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 select Review + create and Create.
Step 2 - Deploy from the Azure CLI
Accept the Marketplace terms once, then create the VM:
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:ezbookkeeping-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name ezbookkeeping \
--image sac1647283583153:ezbookkeeping-ubuntu-24-04:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku StandardOpen HTTP so you can reach the web UI:
az vm open-port --resource-group <your-rg> --name ezbookkeeping --port 80 --priority 900Step 3 - Connect to your VM
Connect over SSH:
ssh azureuser@<vm-public-ip>Step 4 - Confirm the services are running
Both services that back ezBookkeeping should report active. The unauthenticated /healthz.json endpoint answers through nginx on port 80:
systemctl is-active ezbookkeeping nginx curl -s http://127.0.0.1/healthz.json; echoExpected: two lines of active, then a JSON body reporting "status":"ok" and "version":"1.6.1".
Step 5 - Retrieve your administrator credentials
On the first boot of every VM, a one-shot service (ezbookkeeping-firstboot.service) generates a session signing key and an administrator password that are both unique to that VM. It creates the single administrator account directly in the database and writes the credentials to a root-only file. No shared or default login ships in the image.
Read the credentials file:
sudo cat /root/ezbookkeeping-credentials.txtThe file (mode 0600, root only) contains the sign-in URL (EZBOOKKEEPING_URL), the username (EZBOOKKEEPING_USERNAME) and the password (EZBOOKKEEPING_PASSWORD).
You can verify the sign-in round trip from the VM's own shell. The commands below read the per-VM credentials, post a real sign-in, then use the returned session token against an authenticated endpoint:
U=$(sudo grep '^EZBOOKKEEPING_USERNAME=' /root/ezbookkeeping-credentials.txt | cut -d= -f2-)
P=$(sudo grep '^EZBOOKKEEPING_PASSWORD=' /root/ezbookkeeping-credentials.txt | cut -d= -f2-)
TOKEN=$(curl -s -X POST http://127.0.0.1/api/authorize.json \
-H 'Content-Type: application/json' \
-d "$(jq -nc --arg u "$U" --arg p "$P" '{loginName:$u,password:$p}')" \
| jq -r '.result.token // empty')
echo -n 'signed in as -> ' curl -s -H "Authorization: Bearer $TOKEN" \
http://127.0.0.1/api/v1/users/profile/get.json | jq -r '.result.username'Expected: signed in as -> admin, confirming the credentials in the file authenticate end to end.
Step 6 - Sign in and review the overview
Browse to http://<vm-public-ip>/ and sign in with the username and password from the credentials file.
ezBookkeeping opens the Overview. It summarizes the current month's income and expense, your asset and liability totals, net assets, and an income and expense trend chart.
Step 7 - Add accounts and record transactions
Open Accounts from the left navigation and add your accounts: cash, current and savings accounts, credit cards, investments or debts. Then open Transaction Categories and either create your own categories or accept the preset set.
With accounts and categories in place, record spending from Transaction Details. Each transaction carries a time, category, amount, account, optional tags, a description and, if you want, an attached receipt image. The list view totals income and expense for the selected date range.
Use Import on the transaction list to bring in existing records from CSV. Use Export from the settings menu to take your data out again at any time.
Step 8 - Read the statistics
Open Statistics & Analysis to see your spending by category, by account and over time, as pie, bar or trend charts. Use Insights Explorer for ad hoc questions about your data.
Step 9 - Confirm the version, the stack and the data disk
Check the installed version, the data disk mount and the database file:
/opt/ezbookkeeping/ezbookkeeping --version findmnt /var/lib/ezbookkeeping
sudo ls -l /var/lib/ezbookkeeping/dataExpected: ezBookkeeping version 1.6.1, /var/lib/ezbookkeeping mounted from the dedicated data disk (/dev/sdc), and the SQLite database owned by the ezbookkeeping service account at mode 0640.
The database, the object store and the logs all 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 ezbookkeeping-firstboot.service runs after the network is up. It does the following, in order:
- Generates the two per-VM secrets and writes them into the configuration.
- Initializes the database schema.
- Creates the single administrator account with the offline CLI.
- Resolves the instance address from the Azure instance metadata service.
- Writes the credentials file at mode
0600(root only). - Only then allows anything to serve.
That last point matters. Both ezbookkeeping.service and nginx.service are gated on a bootstrap-ready marker that first boot creates after the credentials are written. On a brand new VM, nothing answers port 80 until the lockdown is complete. There is no window in which a freshly launched instance is reachable without its own unique credentials.
Verify the first-boot state:
systemctl is-active ezbookkeeping-firstboot.service
sudo stat -c '%a %U:%G %n' /root/ezbookkeeping-credentials.txt test -f /var/lib/sac/data/ezbookkeeping-bootstrap-ready && echo 'bootstrap marker present'Expected: active, then 600 root:root /root/ezbookkeeping-credentials.txt, then bootstrap marker present.
The session signing key deserves a note of its own. ezBookkeeping signs every login session with [security] secret_key. The upstream sample configuration ships that value empty, and the application resolves an empty value to a built-in default. Any instance left that way signs its sessions with a value anyone can look up.
This image never ships a usable key. One is generated for your VM on first boot, and a guard that runs before the service starts refuses to launch the application if the key is missing, still a sample value, or the upstream default. To check the key, run:
sudo awk -F= '/^secret_key/ {gsub(/ /,"",$2); print "session signing key length: " length($2) " chars"}' \
/etc/ezbookkeeping/ezbookkeeping.ini
sudo /usr/local/sbin/ezbookkeeping-secret-guard.shExpected: a key length of 48 characters, then the guard confirming the per-VM signing key is valid. The key itself is never printed.
The application is bound to the loopback address only, so nginx on port 80 is the single public entry point. Confirm the listeners:
sudo ss -tlnp | grep -E ':80 |:8080 'Opening self-registration for household members
Self-registration is disabled by default, so a passer-by cannot create an account on your instance before you sign in for the first time. The registration route is not merely hidden. It is not served at all, and the sign-in page shows the "Create an account" link greyed out and inactive.
To invite household members, enable registration and restart the service:
sudo sed -i 's/^enable_register = false/enable_register = true/' /etc/ezbookkeeping/ezbookkeeping.ini
sudo systemctl restart ezbookkeepingOnce everyone has registered, set the value back to false and restart again so the instance is closed to new sign-ups.
Alternatively, you can create each account yourself from the VM, which never opens registration at all:
sudo -u ezbookkeeping /opt/ezbookkeeping/ezbookkeeping userdata user-add \
--conf-path=/etc/ezbookkeeping/ezbookkeeping.ini \
--username <new-username> --email <new-email> \
--nickname <display-name> --password <new-password> --default-currency USDEnabling HTTPS with your own domain
The image serves plain HTTP on port 80 so it works immediately on a bare IP address. To add TLS, terminate it in front of the VM with an Azure Application Gateway or Azure Front Door. Alternatively, issue a certificate directly on the VM once a DNS record points at it:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain>Certbot rewrites the nginx site and installs a renewal timer. After enabling HTTPS, update the [server] section of /etc/ezbookkeeping/ezbookkeeping.ini so protocol is https and domain is your hostname. Then restart the service so generated links use the right address.
Allow 443/tcp in the NSG.
Backup and maintenance
Everything worth backing up lives under /var/lib/ezbookkeeping on the dedicated data disk: the SQLite database, the object store and the logs. The simplest backup is a snapshot of that disk from the Azure portal or CLI.
For a file-level backup, stop the service briefly so the database is quiescent, archive the directory, then start the service again:
sudo systemctl stop ezbookkeeping
sudo tar czf /var/tmp/ezbookkeeping-backup.tar.gz -C /var/lib ezbookkeeping
sudo systemctl start ezbookkeepingUbuntu security updates are applied automatically by unattended-upgrades, which is enabled in the image.
To move to a newer ezBookkeeping release, download the upstream linux-amd64 tarball, replace the contents of /opt/ezbookkeeping, and restart the service. Your configuration in /etc/ezbookkeeping/ezbookkeeping.ini and your data on the data disk are untouched, and the application updates its own database schema on start.
Support
SecureAnyCloud provides 24/7 technical support for this image by email at sales@secureanycloud.com and via live chat, with a one-hour average response for critical issues. We can help with deployment, retrieving the first-boot credentials, opening registration for household members, multi-currency configuration, importing existing records, TLS termination, backups and scaling.
Deploy on Azure
Launch ezBookkeeping on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com