Actual Budget zelf hosten op een VPS met Docker
Leer hoe u Actual Budget installeert op een VPS met Docker Compose. Wij behandelen de noodzakelijke HTTPS-configuratie, het databeheer, bankimport en het inrichten van backups.
Wat u gaat bouwen
Actual Budget is een zelfgehoste applicatie voor budgetbeheer op basis van het enveloppesysteem. Het is het standaardantwoord wanneer mensen op zoek zijn naar een YNAB-alternatief dat zij zelf kunnen hosten. De server bestaat uit één container, één datavolume en één HTTPS-naam. Alles wat een normaal budget nodig heeft, draait probleemloos op de kleinste VPS die u kunt huren, omdat de server hoofdzakelijk bestanden opslaat en synchroniseert.
Het is nuttig om de architectuur te begrijpen voordat u begint met typen. Het budget zelf is een SQLite-database die zich in uw browser en in elke mobiele app bevindt. De server die u gaat installeren is een synchronisatie-eindpunt: deze bevat de lijst met rekeningen, de budgetbestanden en het wijzigingslogboek waarmee een telefoon en een laptop met elkaar kunnen synchroniseren. Daarom blijft de app werken als de server offline is, en daarom verliest u uw budget niet als de server verloren gaat, zolang ten minste één client nog een kopie heeft.
Waarom de server HTTPS vereist
Actual vereist HTTPS, en dit is geen formaliteit. Browsers stellen de Web Crypto API, de interface die Actual gebruikt voor end-to-end encryptie, alleen beschikbaar in wat de specificatie een veilige context noemt. Een veilige context is https:// of http://localhost. Laadt u de applicatie vanaf http://203.0.113.10:5006 in een browser op een andere machine, dan zijn deze functies simpelweg niet aanwezig, omdat de browser ze nooit aan de pagina heeft verstrekt. De officiële mobiele builds weigeren bovendien een onbeveiligde http:// server-URL.
Er zijn dus twee werkbare configuraties. Plaats een geldig certificaat op een echte domeinnaam voor de container, wat deze handleiding beschrijft. Of voorzie de server van een zelfondertekend certificaat met ACTUAL_HTTPS_KEY en ACTUAL_HTTPS_CERT, zoals gedocumenteerd door het project, en accepteer op elk apparaat een browserwaarschuwing. Een gratis certificaat van Let's Encrypt kost vijf minuten tijd, dus kies voor de eerste optie.
Actual Budget installeren met Docker Compose
Installeer eerst Docker als de server nieuw is. Als de syntaxis van het Compose-bestand nieuw voor u is, behandelt de gids Docker Compose-basisprincipes voor een VPS de velden die hieronder worden gebruikt.
sudo install -d -m 755 /opt/actual
sudo install -d -m 700 /opt/actual/dataSchrijf /opt/actual/docker-compose.yml:
services:
actual:
image: actualbudget/actual-server:latest
container_name: actual
restart: unless-stopped
ports:
- '127.0.0.1:5006:5006'
volumes:
- ./data:/dataDrie details in dat bestand zijn van belang.
De image is actualbudget/actual-server:latest, gepubliceerd door het project op Docker Hub en gespiegeld op ghcr.io/actualbudget/actual. Er is een latest-alpine-tag voor apparaten met een laag vermogen.
De container schrijft alles onder /data. Binnenin vindt u server-files, dat account.sqlite bevat met uw inloggegevens en sessietokens, en user-files, dat de budgetbestanden zelf bevat. Koppel dit pad, anders gooit de volgende docker compose pull uw budget weg. ACTUAL_DATA_DIR kan het verplaatsen, maar de standaardinstelling is prima.
De poort wordt alleen gepubliceerd op 127.0.0.1. Een kale 5006:5006 publiceert op elke interface, en Docker schrijft zijn eigen regels vóór ufw, waardoor de applicatie open zou staan voor het internet, zelfs met een deny-all firewall. Die verrassing wordt uitgelegd in waarom Docker-gepubliceerde poorten ufw omzeilen. Binden aan loopback betekent dat alleen de reverse proxy op dezelfde server deze kan bereiken.
Start het:
cd /opt/actual
docker compose up --detach
docker compose logs -f actualHet logbestand stabiliseert zodra de server meldt dat deze luistert op poort 5006. Controleer het lokaal voordat u DNS aanpast:
curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:5006/Een 200 betekent dat de applicatie actief is. curl: (7) Failed to connect betekent dat de container niet draait, en docker compose ps zal tonen dat deze is afgesloten. De gebruikelijke oorzaak is een rechtenprobleem op de gekoppelde volume, zichtbaar als een EACCES-regel in het logbestand.
Plaats een certificaat en een domeinnaam voor de service
Wijs een A-record naar de VPS, budget.example.com, en wacht tot dit is opgelost. Installeer vervolgens nginx en vraag het certificaat aan. De handleiding Certbot op Ubuntu 24.04 met nginx behandelt de uitgifte en de timer voor vernieuwing volledig.
Het proxy-blok:
server {
listen 443 ssl;
http2 on;
server_name budget.example.com;
ssl_certificate /etc/letsencrypt/live/budget.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/budget.example.com/privkey.pem;
client_max_body_size 100m;
location / {
proxy_pass http://127.0.0.1:5006;
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;
}
}client_max_body_size is de regel die mensen vaak vergeten. Het budgetbestand wordt in zijn geheel geüpload bij een volledige synchronisatie. Nginx hanteert standaard een limiet van 1 MB voor de request body. Zodra het bestand groter wordt, mislukt de synchronisatie met 413 Request Entity Too Large in het nginx access log, terwijl de applicatie slechts een algemene synchronisatiefout toont. De server heeft zijn eigen afzonderlijke limieten: ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB staat standaard op 20 en ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SYNC_SIZE_LIMIT_MB op 50. Stel de nginx-limiet daarom hoger in dan de waarde die voor u van toepassing is.
Herlaad en test:
sudo nginx -t && sudo systemctl reload nginx
curl -fsS -o /dev/null -w '%{http_code}\n' https://budget.example.com/Eerste keer opstarten: het wachtwoord en uw eerste budgetbestand
Open https://budget.example.com in een browser. Het eerste scherm vraagt u om een serverwachtwoord in te stellen. Dit ene wachtwoord beveiligt de gehele server; genereer daarom een lang, willekeurig wachtwoord en bewaar het op een plek waar u het terug kunt vinden, zoals een zelfgehoste Vaultwarden wachtwoordmanager. Er hoeven geen gebruikersaccounts te worden aangemaakt. De server van Actual is ontworpen met één wachtwoord, wat betekent dat het delen van een budget inhoudt dat u ook het wachtwoord deelt.
Maak vervolgens een budgetbestand aan. Actual vraagt of u end-to-end encryptie wilt inschakelen. Kies voor ja; de server slaat dan alleen versleutelde gegevens op, wat de juiste keuze is voor financiële data op een gehuurde machine. De consequentie is reëel: het encryptiewachtwoord bereikt de server nooit. Als u dit verliest, is het bestand onherstelbaar en bestaat er geen mogelijkheid tot herstel. Noteer het wachtwoord voordat u verdergaat in het scherm.
Stel uw beginsaldi in op basis van de huidige cijfers van uw bank in plaats van jaren aan historie te importeren. Envelopbudgettering werkt vooruit vanaf het geld dat u nu bezit, waardoor een lege historie geen nadelige gevolgen heeft.
Transacties importeren
Hier is eerlijkheid belangrijker dan enthousiasme, omdat het importproces de voornaamste reden is waarom mensen afhaken bij zelfgehost budgetbeheer.
Handmatige invoer is de basis en werkt altijd. Voor de enveloppenmethode is dit wellicht zelfs het doel, aangezien het handmatig invoeren van een aankoop ervoor zorgt dat u zich bewust bent van uw uitgaven.
Bestandsimport verwerkt de bulk. Actual leest CSV, QIF, OFX en QFX, en elke bank exporteert ten minste één van deze formaten. Importeer per rekening vanuit het rekeningscherm, wijs de kolommen één keer toe en Actual onthoudt die indeling voor de betreffende rekening.
Automatische banksynchronisatie is beschikbaar, maar vereist een externe dienst omdat de server niet zelfstandig met banken kan communiceren. Actual ondersteunt SimpleFIN Bridge voor Noord-Amerikaanse banken, Enable Banking voor Europa, Akahu voor Nieuw-Zeeland en Pluggy.ai voor Brazilië. GoCardless wordt nog steeds ondersteund, maar accepteert geen nieuwe accounts meer. U meldt zich zelf aan bij de provider, genereert inloggegevens en voegt deze toe aan de server. SimpleFIN Bridge kost per juli 2026 15 US dollar per jaar voor maximaal 25 instellingen; de andere aanbieders hanteren andere prijzen.
Er zijn twee beperkingen waar u rekening mee moet houden voordat u hierop vertrouwt. De API-inloggegevens staan op de server en vallen niet onder de end-to-end encryptie, omdat de server deze moet kunnen gebruiken. Daarnaast voert Actual geen automatische polling uit: synchronisatie is een handeling die u zelf start met een knop, niet een achtergrondproces.
Backups, want het zijn slechts bestanden
Alles wat voor u van belang is, bevindt zich onder /opt/actual/data. Er is geen exportstap vereist en er hoeft geen database-dump te worden gescript.
Het enige aandachtspunt is SQLite. Het kopiëren van account.sqlite terwijl de server ernaar schrijft, kan resulteren in een onvoltooide transactie. U komt hier pas achter op het moment dat u een herstelactie probeert uit te voeren. Stop de container voor de paar seconden die het kopiëren in beslag neemt:
cd /opt/actual
docker compose stop
restic -r sftp:backup@backup.example.com:/srv/restic backup /opt/actual/data
docker compose startPlan dit in volgens de methode in restic backups op een VPS, waarin het opzetten van de repository, retentie en de herstelprocedure worden behandeld. Voer de herstelprocedure daadwerkelijk uit. Een back-up die u nooit heeft hersteld, is slechts een aanname.
De eigen client-side back-ups van Actual zijn een afzonderlijke zaak en het is nuttig om hiervan op de hoogte te zijn. De browser bewaart recente kopieën van het budgetbestand, toegankelijk via het bestandsmenu. Dit dekt scenario's zoals "ik heb per ongeluk een categorie verwijderd" zonder dat de server hiervoor hoeft te worden aangeraakt.
De server bijwerken
cd /opt/actual
docker compose pull
docker compose up --detachCompose maakt de container opnieuw aan op basis van de nieuwe image en koppelt hetzelfde volume opnieuw. De gegevens blijven daardoor behouden. Werk ook de clients bij. Server- en applicatieversies moeten doorgaans dicht bij elkaar blijven. Een client die veel ouder is dan de server kan synchronisatie weigeren met een melding over een versieverschil. Maak een back-up voordat u een grote versiesprong uitvoert. Migraties worden namelijk bij de eerste start uitgevoerd en teruggaan naar een vorige versie is niet mogelijk. Actual kan goed overweg met een zwevende latest-tag, omdat de status bestaat uit een map met bestanden. Dat geldt niet voor een applicatie met een echte database. In Chatwoot zelf hosten worden de vaste tags en de dump vóór de upgrade beschreven die in dat geval nodig zijn.
Wat er misgaat en wat u zult zien
De applicatie laadt, maar de synchronisatie wordt nooit voltooid. Controleer het nginx-toegangslogboek op 413. Dit betekent dat client_max_body_size te laag is ingesteld. Een 502 betekent daarentegen dat nginx actief is, maar de container niet.
Versleutelingsopties ontbreken of de mobiele app weigert de URL. De pagina bevindt zich niet in een beveiligde context. De adresbalk toont http:// met een IP-adres of een hostnaam die niet localhost is. Los het certificaatprobleem op in plaats van eromheen te werken.
Een melding dat het budgetbestand niet compatibel is met deze versie. De versies van de client en de server lopen uiteen. Update beide naar dezelfde release en herlaad de pagina.
De container start in een lus opnieuw op. Lees docker compose logs actual. Een rechtenfout op /data betekent dat de gekoppelde map niet beschrijfbaar is voor de gebruiker van de container. Een foutmelding over een adres dat al in gebruik is, betekent dat een ander proces poort 5006 op loopback al bezet houdt.
De eerste keer laden voelt traag aan. Het volledige budgetbestand wordt naar de browser gedownload wanneer u het opent. Dit is één grote overdracht, gevolgd door lokale leesacties. Dit is geen probleem met de servercapaciteit en het toevoegen van RAM zal dit niet veranderen.
FAQ
Heeft Actual Budget HTTPS nodig om te werken?
Ja, in de praktijk wel. De end-to-end encryptie van Actual maakt gebruik van de Web Crypto API van de browser, en browsers stellen deze alleen beschikbaar in een beveiligde context, oftewel https:// of http://localhost. Via onbeveiligd HTTP vanaf een andere machine zijn deze functies niet beschikbaar, en de officiële mobiele apps weigeren een server-URL zonder HTTPS. Gebruik een Let's Encrypt-certificaat op een echte hostnaam, of een zelfondertekend certificaat met ACTUAL_HTTPS_KEY en ACTUAL_HTTPS_CERT als u de applicatie uitsluitend via een desktopbrowser gebruikt.
Kan Actual mijn banktransacties automatisch importeren?
Alleen via een externe dienst waar u zich zelf voor aanmeldt: SimpleFIN Bridge in Noord-Amerika, Enable Banking in Europa, Akahu in Nieuw-Zeeland of Pluggy.ai in Brazilië. GoCardless wordt ondersteund, maar accepteert geen nieuwe accounts. Deze API-inloggegevens staan op uw server en vallen niet onder de end-to-end encryptie. Synchronisatie gebeurt handmatig; u drukt op een knop en er vindt geen polling op de achtergrond plaats. Voor het importeren van CSV, QIF, OFX en QFX is geen externe partij nodig.
Wat moet ik precies back-uppen?
De gemounte datamap, in deze handleiding /opt/actual/data genoemd. Deze bevat server-files/account.sqlite met inloggegevens en sessies, en user-files met de budgetbestanden. Stop de container voordat u kopieert, omdat het kopiëren van een actieve SQLite-database kan leiden tot een gedeeltelijke schrijfopdracht. Geen enkele andere plek op de server bevat relevante statusinformatie.
Wat gebeurt er als ik het encryptiewachtwoord verlies?
Het bestand kan niet worden hersteld. Het wachtwoord bereikt de server nooit, wat juist het doel is van end-to-end encryptie; er is dus geen resetmogelijkheid en geen ondersteuningstraject. Sla het wachtwoord op in een wachtwoordmanager zodra u het bestand aanmaakt en bewaar een kopie op een locatie die niet afhankelijk is van deze server.
Hoeveel servercapaciteit heeft Actual Budget nodig?
Zeer weinig. De container serveert statische assets en bestanden, en de budgetberekeningen vinden plaats in de browser. Eén gedeelde vCPU met 1 GB RAM is ruim voldoende, en de datamap voor een huishoudbudget met meerdere jaren aan historie blijft beperkt tot enkele tientallen megabytes. Schijfbelasting wordt veroorzaakt door uw back-ups en andere containers, niet door Actual. Als u een server kiest die ook zwaardere taken moet uitvoeren, is een fotoserver meestal de bepalende factor voor de systeemeisen; controleer daarom hoeveel RAM PhotoPrism en Immich daadwerkelijk nodig hebben voordat u een abonnement kiest.