Actual Budget zelf hosten op uw VPS met Docker
Installeer Actual Budget op een VPS met Docker Compose. Leer over het datavolume, verplichte HTTPS, uw eerste budgetbestand, bankimports en back-ups.
Wat u bouwt
Actual Budget is een zelfgehoste app voor budgetteren met enveloppen. Het is doorgaans het antwoord voor wie een alternatief voor YNAB zoekt dat men zelf kan hosten. De server bestaat uit één container, één datavolume en één HTTPS-naam. Alles wat een normaal budget nodig heeft, werkt probleemloos op de kleinste VPS die u kunt huren, omdat de server voornamelijk bestanden opslaat en deze synchroniseert.
Het is belangrijk dat u de architectuur begrijpt voordat u iets invoert. Het budget zelf is een SQLite-database die in uw browser en in elke mobiele app staat. De server die u zo gaat installeren, is een sync-eindpunt. Deze bevat de accountlijst, de budgetbestanden en het wijzigingslogboek waarmee een telefoon en een laptop dezelfde gegevens behouden. Daarom blijft de app werken wanneer de server niet beschikbaar is. Daarom gaat uw budget niet verloren wanneer u de server kwijtraakt, zolang één client nog een kopie bevat.
Waarom de server HTTPS nodig heeft
Actual vereist HTTPS; dat is geen formaliteit. Browsers stellen de Web Crypto API, de interface die Actual gebruikt voor end-to-endversleuteling, alleen beschikbaar in wat de specificatie een beveiligde context noemt. Een beveiligde context is https:// of http://localhost. Laad de app vanuit http://203.0.113.10:5006 in een browser op een andere machine. Deze functies zijn dan eenvoudigweg niet beschikbaar, omdat de browser ze nooit aan de pagina heeft doorgegeven. De officiële mobiele builds weigeren ook een gewone http://-server-URL.
Er zijn dus twee werkbare configuraties. Plaats een geldig certificaat op een echte naam vóór de container. Dat is de configuratie in deze handleiding. Of geef de server een zelfondertekend certificaat met ACTUAL_HTTPS_KEY en ACTUAL_HTTPS_CERT, zoals het project documenteert, en accepteer op elk apparaat een browserwaarschuwing. Een gratis certificaat van Let's Encrypt is binnen vijf minuten beschikbaar. Kies daarom de eerste optie.
Actual Budget installeren met Docker Compose
Installeer eerst Docker als de server nog leeg is. Als de syntaxis van Compose-bestanden nieuw voor u is, behandelt de handleiding De basis van Docker Compose 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:/dataIn dat bestand zijn drie details van belang.
De image is actualbudget/actual-server:latest. Het project publiceert deze op Docker Hub en spiegelt deze op ghcr.io/actualbudget/actual. Er is een tag latest-alpine voor machines met weinig vermogen.
De container schrijft alles onder /data. Daarin vindt u server-files, met daarin account.sqlite met uw aanmeldingsgegevens en sessietokens, en user-files, met daarin de budgetbestanden zelf. Koppel dat pad als volume, anders verwijdert de volgende docker compose pull uw budget. Met ACTUAL_DATA_DIR kunt u dit wijzigen, maar de standaardwaarde volstaat.
De poort wordt alleen gepubliceerd op 127.0.0.1. Een ongewijzigde 5006:5006 publiceert op elke interface. Docker schrijft zijn eigen regels vóór ufw, waardoor de toepassing via internet bereikbaar zou zijn, zelfs met een firewall die al het verkeer weigert. Waarom door Docker gepubliceerde poorten ufw omzeilen legt dit gedrag uit. Door aan loopback te binden, kan alleen de reverse proxy op dezelfde server de toepassing bereiken.
Start de container:
cd /opt/actual
docker compose up --detach
docker compose logs -f actualHet logboek is stabiel zodra de server meldt dat deze naar poort 5006 luistert. Controleer dit 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 toepassing antwoordt. curl: (7) Failed to connect betekent dat de container niet actief is. Met docker compose ps ziet u dat deze is beëindigd. De gebruikelijke oorzaak is een rechtenprobleem op het aangekoppelde volume. In het logboek is dit zichtbaar als een regel met EACCES.
Zet een certificaat en een echte naam ervoor
Laat een A-record naar de VPS wijzen, budget.example.com, en wacht totdat het record is verwerkt. Installeer daarna nginx en geef het certificaat uit. De handleiding Certbot op Ubuntu 24.04 met nginx behandelt het uitgeven van het certificaat en de vernieuwingstimer volledig.
Het proxyblok:
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 tijdens een volledige synchronisatie in zijn geheel geüpload. Nginx staat standaard een request body van 1 MB toe. Zodra het bestand groter wordt, mislukt de synchronisatie met 413 Request Entity Too Large in het nginx-accesslog. De app toont dan alleen een algemene synchronisatiefout. De server heeft 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 limiet die voor u van toepassing is.
Herlaad nginx en test:
sudo nginx -t && sudo systemctl reload nginx
curl -fsS -o /dev/null -w '%{http_code}\n' https://budget.example.com/Eerste gebruik: het wachtwoord en uw eerste budgetbestand
Open https://budget.example.com in een browser. Op het eerste scherm stelt u een serverwachtwoord in. Met dat ene wachtwoord wordt de hele server beveiligd. Genereer daarom een lang, willekeurig wachtwoord en bewaar het op een plek waar u het terug kunt vinden, bijvoorbeeld in een zelf gehoste Vaultwarden-wachtwoordmanager. U hoeft geen gebruikersaccounts aan te maken. De server van Actual gebruikt bewust één wachtwoord. Een budget delen betekent daarom dat u dat wachtwoord deelt.
Maak vervolgens een budgetbestand. Actual vraagt of u end-to-end-encryptie wilt inschakelen. Kies ja. De server slaat dan alleen ciphertext op. Dat is de juiste keuze voor financiële gegevens op een gehuurde machine. Daar staat een reëel nadeel tegenover: het encryptiewachtwoord wordt nooit naar de server gestuurd. Als u het kwijtraakt, is het bestand verloren en kunt u het wachtwoord niet opnieuw instellen. Schrijf het wachtwoord op voordat u dit scherm verlaat.
Stel uw beginsaldi in op basis van de actuele bedragen bij uw bank. Importeer niet meteen jaren aan transactiegeschiedenis. Budgetteren met enveloppen werkt vooruit vanaf het geld dat u nu hebt. Een lege geschiedenis kost u daarom niets.
Transacties importeren
Hier is eerlijkheid belangrijker dan enthousiasme, omdat het importproces de belangrijkste reden is waarom mensen afhaken bij zelfgehost budgetbeheer.
Handmatige invoer is de basis en werkt altijd. Bij een envelopmethode is dit mogelijk juist het belangrijkste onderdeel, omdat u door een aankoop in te voeren de uitgave bewuster opmerkt.
Bestandsimport verwerkt het grootste volume. Actual kan CSV, QIF, OFX en QFX lezen, en elke bank exporteert ten minste een van deze indelingen. Importeer transacties per rekening vanuit het rekeningscherm, wijs de kolommen eenmalig toe en Actual onthoudt die indeling voor de rekening.
Automatische banksynchronisatie is beschikbaar, maar hiervoor is een service van derden nodig 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. U registreert zich zelf bij de provider, genereert de benodigde gegevens en voegt deze toe aan de server. SimpleFIN Bridge kost vanaf juli 2026 15 US dollars per jaar voor maximaal 25 instellingen. De andere providers hanteren andere tarieven.
Accepteer deze twee beperkingen voordat u hierop vertrouwt. De API-referenties staan op de server en vallen niet onder end-to-end-encryptie, omdat de server ze moet gebruiken. Actual voert ook geen polling uit: synchronisatie start wanneer u op een knop drukt en is geen achtergrondtaak.
Back-ups, omdat het alleen om bestanden gaat
Alles wat u belangrijk vindt, staat onder /opt/actual/data. Er is geen exportstap en er hoeft geen databasesdump te worden gescript.
De enige valkuil is SQLite. Als u account.sqlite kopieert terwijl de server ernaar schrijft, kan de kopie een onvoltooide transactie bevatten. U merkt dat pas wanneer u probeert te herstellen. Stop de container gedurende de paar seconden die het kopiëren duurt:
cd /opt/actual
docker compose stop
restic -r sftp:backup@backup.example.com:/srv/restic backup /opt/actual/data
docker compose startPlan dit volgens de aanpak in restic-back-ups op een VPS, met instructies voor het instellen van de repository, bewaarbeleid en de hersteltest. Voer de hersteltest uit. Een back-up die u nog nooit hebt hersteld, is slechts een gok.
De client-side back-ups van Actual zijn iets anders en zijn ook nuttig. De browser bewaart recente kopieën van het budgetbestand. U kunt deze openen via het bestandsmenu. Daarmee kunt u een categorie herstellen die u per ongeluk hebt verwijderd, zonder de server aan te raken.
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, zodat de gegevens behouden blijven. Werk ook de clients bij. De versies van de server en de app moeten 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. Bij de eerste start worden migraties uitgevoerd en er is geen mogelijkheid om te downgraden.
Wat er misgaat en wat u ziet
De app wordt geladen, maar de synchronisatie wordt nooit voltooid. Controleer het nginx-toegangslogboek op 413. Dat betekent dat client_max_body_size te laag is ingesteld. Een 502 betekent daarentegen dat nginx actief is en de container niet.
Versleutelingsopties ontbreken of de mobiele app weigert de URL. De pagina bevindt zich niet in een beveiligde context. In de adresbalk ziet u http:// met een IP-adres of een hostnaam die niet localhost is. Los het certificaatprobleem op in plaats van dit te omzeilen.
Er verschijnt een melding dat het budgetbestand niet compatibel is met deze versie. De client- en serverversies lopen niet meer gelijk. Werk beide bij naar dezelfde release en laad de pagina opnieuw.
De container wordt telkens opnieuw gestart. Lees docker compose logs actual. Een machtigingsfout op /data betekent dat de gekoppelde directory niet schrijfbaar is voor de gebruiker van de container. Een foutmelding dat het adres al in gebruik is, betekent dat iets anders poort 5006 op de loopbackinterface al gebruikt.
Het laden van de pagina lijkt de eerste keer traag. Wanneer u het budgetbestand opent, wordt het volledige bestand naar de browser gedownload. Daarna worden de gegevens lokaal gelezen. Dit is geen probleem met de servercapaciteit. Meer RAM toevoegen verandert dit niet.
FAQ
Heeft Actual Budget HTTPS nodig om te werken?
Ja, in de praktijk wel. De end-to-end-versleuteling van Actual gebruikt de Web Crypto API van de browser. Browsers stellen deze API alleen beschikbaar in een beveiligde context, namelijk https:// of http://localhost. Via gewoon HTTP vanaf een andere machine zijn deze functies niet beschikbaar. De officiële mobiele apps weigeren bovendien een URL van een server met gewoon HTTP. Gebruik een Let's Encrypt-certificaat op een echte hostnaam. U kunt ook een zelfondertekend certificaat gebruiken met ACTUAL_HTTPS_KEY en ACTUAL_HTTPS_CERT als u uitsluitend een desktopbrowser gebruikt.
Kan Actual mijn banktransacties automatisch importeren?
Alleen via een service van derden waarvoor u zelf een account aanmaakt: 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-referenties staan op uw server en vallen niet onder end-to-end-versleuteling. Synchronisatie is ook handmatig. U drukt dus op een knop; er wordt niets op de achtergrond opgevraagd. Voor het importeren van CSV, QIF, OFX en QFX is geen derde partij nodig.
Wat moet ik precies back-uppen?
De gekoppelde gegevensdirectory, in deze handleiding /opt/actual/data. Deze bevat server-files/account.sqlite met aanmeldgegevens en sessies en user-files met de budgetbestanden. Stop de container voordat u de gegevens kopieert. Bij het kopiëren van een actieve SQLite-database kan namelijk een gedeeltelijke schrijfbewerking worden vastgelegd. Nergens anders op de server wordt status opgeslagen.
Wat gebeurt er als ik het wachtwoord voor de versleuteling verlies?
Het bestand kan niet worden hersteld. Het wachtwoord wordt nooit naar de server verzonden. Dat is precies het doel van end-to-end-versleuteling. Daarom is er geen manier om het wachtwoord opnieuw in te stellen en geen ondersteuningsprocedure om het te herstellen. Sla het op in een wachtwoordbeheerder zodra u het bestand aanmaakt. Bewaar ook een kopie op een locatie die niet afhankelijk is van dezelfde server.
Hoeveel serverresources heeft Actual Budget nodig?
Zeer weinig. De container levert statische assets en bestanden. De budgetberekeningen worden in de browser uitgevoerd. Een gedeelde vCPU met 1 GB RAM is voldoende om Actual zonder problemen uit te voeren. De gegevensdirectory voor een huishoudbudget met een geschiedenis van meerdere jaren blijft enkele tientallen megabytes groot. Schijfruimte wordt vooral gebruikt door uw back-ups en andere containers, niet door Actual.