SSD Nodes Learn Hosting plans →
Anleitungen Matt ConnorVon Matt Connor · Aktualisiert 2026-10-28

Actual Budget per Docker auf dem eigenen VPS hosten

Installieren Sie Actual Budget per Docker Compose auf einem VPS. Dieser Leitfaden erklärt Datenvolume, HTTPS-Pflicht, erste Budgetdatei, Bankimporte und Backups.

Was Sie erstellen

Actual Budget ist eine selbst gehostete Anwendung für Umschlagbudgetierung. Sie ist die übliche Antwort, wenn eine selbst hostbare Alternative zu YNAB gesucht wird. Der Server besteht aus einem Container, einem Datenvolume und einem HTTPS-Namen. Alle Funktionen, die ein normales Budget benötigt, laufen problemlos auf dem kleinsten mietbaren VPS. Der Server speichert hauptsächlich Dateien und synchronisiert sie.

Die Architektur sollten Sie verstehen, bevor Sie Befehle eingeben. Das Budget selbst ist eine SQLite-Datenbank. Sie liegt im Browser und in jeder mobilen App. Der Server, den Sie gleich installieren, ist ein Synchronisierungsendpunkt. Er enthält die Kontoliste, die Budgetdateien und das Änderungsprotokoll. Damit können Telefon und Laptop denselben Stand verwenden. Deshalb funktioniert die Anwendung weiter, wenn der Server nicht erreichbar ist. Der Verlust des Servers führt außerdem nicht zum Verlust Ihres Budgets, solange mindestens ein Client noch eine Kopie besitzt.

Warum der Server HTTPS benötigt

Actual erfordert HTTPS, und dies ist keine Formalität. Actual benötigt eine Browser-Funktion namens SharedArrayBuffer, um überhaupt zu funktionieren. Browser aktivieren diese Funktion nur, wenn die Seite in einem sogenannten sicheren Kontext (secure context) isoliert ist, der eine Cross-Origin-Isolation aufweist. Ein sicherer Kontext ist https:// oder http://localhost. Laden Sie die Anwendung von http://203.0.113.10:5006 in einem Browser auf einem anderen Rechner, stellt der Browser der Seite diese Funktion nicht bereit, weshalb das Budget nicht geladen wird. Für Smartphones gibt es keine Ausnahme. Laut FAQ von Actual befindet sich eine offizielle iOS-App in der Beta-Phase, die eine Verbindung zu Ihrem eigenen Server herstellt; eine offizielle Android-App gibt es noch nicht. Auf den meisten Smartphones verwenden Sie daher dieselbe Web-App, die als Progressive Web App auf dem Startbildschirm installiert wird, und die gleiche Regel für den sicheren Kontext findet Anwendung.

Es gibt also zwei praktikable Setups. Platzieren Sie ein echtes Zertifikat für einen echten Domainnamen vor dem Container, was in dieser Anleitung beschrieben wird. Oder statten Sie den Server mit einem selbstsignierten Zertifikat unter Verwendung von ACTUAL_HTTPS_KEY und ACTUAL_HTTPS_CERT aus, wie in der Projektdokumentation beschrieben, und akzeptieren Sie auf jedem Gerät eine Browser-Warnung. Ein kostenloses Zertifikat von Let's Encrypt ist in fünf Minuten eingerichtet, wählen Sie daher die erste Option.

Actual Budget mit Docker Compose installieren

Installieren Sie zuerst Docker, wenn der Server frisch eingerichtet ist. Falls Ihnen die Syntax von Compose-Dateien noch nicht vertraut ist, behandelt der Leitfaden Docker-Compose-Grundlagen für einen VPS die unten verwendeten Felder.

sudo install -d -m 755 /opt/actual
sudo install -d -m 700 /opt/actual/data

Schreiben Sie /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:/data

In dieser Datei sind drei Details wichtig.

Das Image ist actualbudget/actual-server:latest. Das Projekt veröffentlicht es auf Docker Hub und spiegelt es unter ghcr.io/actualbudget/actual. Für leistungsschwache Rechner gibt es den Tag latest-alpine.

Der Container schreibt alle Daten unter /data. Darin finden Sie server-files mit account.sqlite, die Ihre Anmelde- und Sitzungstoken enthalten, sowie user-files, das die Budgetdateien selbst enthält. Binden Sie diesen Pfad ein. Andernfalls verwirft docker compose pull beim nächsten Start Ihr Budget. Mit ACTUAL_DATA_DIR können Sie den Pfad ändern. Der Standardwert ist jedoch ausreichend.

Der Port wird nur auf 127.0.0.1 veröffentlicht. Ein unverändertes 5006:5006 veröffentlicht den Port auf jeder Schnittstelle. Docker schreibt seine eigenen Regeln vor den ufw-Regeln. Dadurch wäre die Anwendung trotz einer standardmäßigen Deny-All-Firewall aus dem Internet erreichbar. Diese unerwartete Wirkung wird unter warum veröffentlichte Docker-Ports ufw umgehen erklärt. Durch die Bindung an die Loopback-Schnittstelle kann nur der Reverse Proxy auf demselben Server darauf zugreifen.

Starten Sie den Container:

cd /opt/actual
docker compose up --detach
docker compose logs -f actual

Das Log ist vollständig, sobald der Server meldet, dass er auf Port 5006 lauscht. Prüfen Sie den Dienst lokal, bevor Sie DNS konfigurieren:

curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:5006/

Ein 200 bedeutet, dass die Anwendung Anfragen verarbeitet. curl: (7) Failed to connect bedeutet, dass auf 127.0.0.1:5006 keine Verbindung angenommen wurde. Führen Sie docker compose ps --all aus, da das einfache docker compose ps nur laufende Container auflistet. Wenn der Container als beendet angezeigt wird, liegt die Ursache meist an fehlenden Berechtigungen für das eingebundene Volume. Im Log ist dies als Zeile vom Typ EACCES sichtbar.

Setzen Sie ein Zertifikat und einen echten Namen davor

Verweisen Sie mit einem A-Record auf die VPS, budget.example.com, und warten Sie, bis der DNS-Eintrag aufgelöst wird. Installieren Sie anschließend nginx und stellen Sie das Zertifikat aus. Der Leitfaden Certbot unter Ubuntu 24.04 mit nginx behandelt die Ausstellung und den Erneuerungs-Timer vollständig.

Der Proxy-Block:

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 ist die Zeile, die häufig vergessen wird. Bei der täglichen Synchronisierung werden nur Ihre Änderungen übertragen. Die vollständige Budgetdatei wird jedoch hochgeladen, wenn Sie ein Budget erstmals beim Server registrieren und erneut, wenn Sie die Synchronisierung zurücksetzen. Nginx begrenzt den Request-Body standardmäßig auf 1 MB. Sobald die Datei größer wird, schlagen diese vollständigen Uploads fehl. Im nginx-Access-Log erscheint dann 413 Request Entity Too Large, während die Anwendung nur einen allgemeinen Synchronisierungsfehler anzeigt. Der Server hat eigene, separate Grenzwerte: ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB ist standardmäßig auf 20 und ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SYNC_SIZE_LIMIT_MB auf 50 gesetzt. Setzen Sie das nginx-Limit daher höher als den für Sie geltenden Wert.

Laden Sie die Konfiguration neu und testen Sie:

sudo nginx -t && sudo systemctl reload nginx
curl -fsS -o /dev/null -w '%{http_code}\n' https://budget.example.com/

Erster Start: das Passwort und Ihre erste Budgetdatei

Öffnen Sie https://budget.example.com in einem Browser. Auf dem ersten Bildschirm legen Sie ein Serverpasswort fest. Dieses eine Passwort schützt den gesamten Server. Generieren Sie daher ein langes, zufälliges Passwort und bewahren Sie es an einem Ort auf, an dem Sie es wiederfinden, beispielsweise in einem selbst gehosteten Vaultwarden-Passwortmanager. Standardmäßig müssen Sie keine Benutzerkonten anlegen: Der Server hat ein einziges Passwort. Ein Budget zu teilen bedeutet daher, dieses Passwort zu teilen. Separate Anmeldungen sind nur möglich, wenn Sie einen OpenID-Provider anbinden. Actual unterstützt OpenID für Setups mit mehreren Benutzern.

Erstellen Sie anschließend eine Budgetdatei. Actual fragt, ob Sie die Ende-zu-Ende-Verschlüsselung aktivieren möchten. Bestätigen Sie mit Ja. Der Server speichert dann nur Chiffretext. Für Finanzdaten auf einer gemieteten Maschine ist das die richtige Einstellung. Die Verschlüsselung hat jedoch einen konkreten Nachteil: Das Verschlüsselungspasswort wird nie an den Server übertragen. Wenn Sie es verlieren, ist die Datei verloren. Eine Zurücksetzung ist nicht möglich. Schreiben Sie das Passwort auf, bevor Sie diesen Bildschirm verlassen.

Legen Sie die Anfangssalden anhand der aktuellen Werte Ihrer Bank fest, statt jahrelange Buchungshistorien zu importieren. Die Umschlagbudgetierung arbeitet mit dem Geld, das Sie jetzt haben. Eine leere Historie verursacht daher keinen Nachteil.

Transaktionen importieren

Hier ist Ehrlichkeit wichtiger als Enthusiasmus, denn die Import-Funktionalität ist der Hauptgrund, warum Nutzer bei selbst gehosteten Budget-Anwendungen abspringen.

Die manuelle Eingabe ist die Basis und funktioniert immer. Bei der Umschlagmethode ist dies wohl der Kernpunkt, da das bewusste Eintippen eines Kaufs dazu führt, dass man ihn wahrnimmt.

Der Datei-Import bewältigt das Volumen. Actual liest CSV, QIF, OFX, QFX und CAMT, und jede Bank exportiert mindestens eines dieser Formate. Der Import erfolgt pro Konto über den Kontobildschirm; bei CSV-Dateien ordnen Sie die Spalten manuell zu.

Ein automatischer Bankabgleich ist möglich, erfordert jedoch einen Drittanbieter-Dienst, da der Server nicht eigenständig mit Banken kommunizieren kann. Actual unterstützt SimpleFIN Bridge für nordamerikanische Banken, Enable Banking für Europa, Akahu für Neuseeland und Pluggy.ai für Brasilien. GoCardless wird weiterhin unterstützt, akzeptiert jedoch keine neuen Konten. Sie registrieren sich selbst beim Anbieter, generieren Zugangsdaten und fügen diese auf dem Server hinzu. SimpleFIN Bridge kostet Stand Oktober 2026 15 US-Dollar pro Jahr zuzüglich Steuern für bis zu 25 Institute; die anderen Anbieter haben abweichende Preismodelle.

Zwei Einschränkungen sollten Sie akzeptieren, bevor Sie sich darauf verlassen. Die API-Zugangsdaten liegen auf dem Server und sind nicht durch eine Ende-zu-Ende-Verschlüsselung geschützt, da der Server sie verwenden muss. Zudem findet kein Abgleich statt, während Actual geschlossen ist: Die automatische Synchronisierung ist standardmäßig deaktiviert. Sobald sie aktiviert ist, läuft sie nur, während die Anwendung geöffnet ist; der Server fragt Ihre Banken also nie eigenständig ab.

Backups, da es sich nur um Dateien handelt

Alles, was für Sie von Bedeutung ist, befindet sich unter /opt/actual/data. Es gibt keinen Export-Schritt und keinen Datenbank-Dump, der skriptgesteuert werden müsste.

Die einzige Falle ist SQLite. Wenn Sie account.sqlite kopieren, während der Server gerade darauf schreibt, kann eine halb abgeschlossene Transaktion erfasst werden. Dies bemerken Sie erst, wenn Sie eine Wiederherstellung versuchen. Stoppen Sie den Container für die wenigen Sekunden, die der Kopiervorgang dauert:

cd /opt/actual
docker compose stop
restic -r sftp:backup@backup.example.com:/srv/restic backup /opt/actual/data
docker compose start

Planen Sie dies mit dem Ansatz aus restic Backups auf einem VPS ein, der die Einrichtung des Repositorys, die Aufbewahrungsrichtlinien und die Wiederherstellungsübung abdeckt. Führen Sie die Wiederherstellungsübung durch. Ein Backup, das Sie noch nie wiederhergestellt haben, ist lediglich eine Vermutung.

Die automatischen Backups von Actual sind eine separate Angelegenheit und nützlich zu kennen, existieren jedoch nur in der Desktop-Anwendung. Sie speichert bis zu 10 aktuelle Kopien der Budgetdatei, die über File > Load Backup erreichbar sind. Dies deckt den Fall "Ich habe versehentlich eine Kategorie gelöscht" ab, ohne den Server überhaupt zu berühren. Die Web-App im Browser speichert keine solchen Kopien. Wenn also alle im Haushalt den Browser verwenden, ist das oben genannte Server-Backup Ihr einziges Backup.

Server aktualisieren

cd /opt/actual
docker compose pull
docker compose up --detach

Compose erstellt den Container aus dem neuen Image neu und bindet dasselbe Volume wieder ein. Dadurch bleiben die Daten erhalten. Aktualisieren Sie auch die Clients. Ein Client, der älter ist als die von ihm empfangenen Daten, übernimmt keine Änderungen mehr und zeigt die Meldung „Update Required“ an. Erstellen Sie vor einem Sprung auf eine neue Hauptversion ein Backup. Beim ersten Start werden Migrationen ausgeführt. Ein Zurückstufen ist nicht möglich. Actual toleriert ein veränderliches latest-Tag, weil sein Zustand aus einem Verzeichnis mit Dateien besteht. Bei einer Anwendung mit einer echten Datenbank gilt das nicht. Chatwoot selbst hosten beschreibt die dafür erforderlichen festen Tags und den Dump vor dem Upgrade.

Was fehlschlägt und was Sie sehen werden

Die Anwendung lädt, aber die Synchronisierung wird nie abgeschlossen. Überprüfen Sie das nginx-Zugriffsprotokoll auf 413. Das bedeutet, dass client_max_body_size zu niedrig eingestellt ist. Ein 502 bedeutet hingegen, dass nginx keine verwertbare Antwort vom Upstream erhalten hat. Meistens liegt das daran, dass der Container gestoppt ist oder nicht auf 5006 lauscht. Überprüfen Sie daher vor allen anderen Schritten docker compose ps --all und das Container-Protokoll.

Die Anwendung lädt auf einem anderen Gerät nicht oder meldet, dass SharedArrayBuffer fehlt. Die Seite befindet sich nicht in einem sicheren Kontext. Die Adressleiste zeigt http:// mit einer IP-Adresse oder einem Hostnamen, der nicht localhost entspricht. Korrigieren Sie das Zertifikat, anstatt das Problem zu umgehen.

Eine Meldung besagt, dass die Budget-Datei nicht mit dieser Version kompatibel ist. Die Datei wurde in einer neueren Version von Actual geöffnet als der Client, den Sie aktuell verwenden. Aktualisieren Sie den Client auf mindestens diese Version oder stellen Sie ein Backup wieder her, das vor dem Zugriff der neueren Version erstellt wurde, und laden Sie die Seite neu.

Der Container startet in einer Endlosschleife neu. Lesen Sie docker compose logs actual. Ein Berechtigungsfehler bei /data bedeutet, dass das eingehängte Verzeichnis für den Benutzer des Containers nicht beschreibbar ist. Ein Fehler bezüglich einer bereits verwendeten Adresse bedeutet, dass ein anderer Prozess bereits Port 5006 auf dem Loopback-Interface belegt.

Der erste Ladevorgang fühlt sich langsam an. Die gesamte Budget-Datei wird beim Öffnen in den Browser geladen. Es handelt sich um eine große Übertragung, danach erfolgen lokale Lesezugriffe. Dies ist kein Problem der Serverdimensionierung; mehr RAM wird daran nichts ändern.

FAQ

Benötigt Actual Budget HTTPS, um zu funktionieren?

In der Praxis ja. Actual benötigt die Browser-Funktion SharedArrayBuffer, um zu laufen. Browser aktivieren diese nur in einem sicheren Kontext, also https:// oder http://localhost. Über unverschlüsseltes HTTP von einem anderen Rechner aus wird die Anwendung nicht geladen. Eine offizielle iOS-App befindet sich in der Beta-Phase, eine offizielle Android-App gibt es noch nicht; daher nutzen die meisten Smartphones dieselbe Web-App und unterliegen derselben Regel. (FAQ) Verwenden Sie ein Let's Encrypt-Zertifikat für einen echten Hostnamen oder ein selbstsigniertes Zertifikat mit ACTUAL_HTTPS_KEY und ACTUAL_HTTPS_CERT, wenn Sie mit einer Zertifikatswarnung auf jedem Gerät leben können.

Kann Actual meine Banktransaktionen automatisch importieren?

Nur über einen Drittanbieter-Dienst, bei dem Sie sich selbst anmelden: SimpleFIN Bridge in Nordamerika, Enable Banking in Europa, Akahu in Neuseeland oder Pluggy.ai in Brasilien. GoCardless wird unterstützt, akzeptiert aber keine neuen Konten. Diese API-Zugangsdaten liegen auf Ihrem Server und sind nicht durch eine Ende-zu-Ende-Verschlüsselung geschützt. Die automatische Synchronisierung ist standardmäßig deaktiviert und läuft nach der Aktivierung nur, während Actual geöffnet ist; im Hintergrund findet auf dem Server keine Abfrage statt. Für den Import von CSV, QIF, OFX, QFX und CAMT ist kein Drittanbieter erforderlich.

Was genau muss ich sichern?

Das eingebundene Datenverzeichnis, das in dieser Anleitung /opt/actual/data entspricht. Es enthält server-files/account.sqlite mit Anmeldedaten und Sitzungen sowie user-files mit den Budget-Dateien. Stoppen Sie den Container vor dem Kopieren, da das Kopieren einer laufenden SQLite-Datenbank einen Schreibvorgang erfassen kann, der nur teilweise abgeschlossen ist. Nichts anderes auf dem Server hält einen Zustand fest.

Was passiert, wenn ich das Verschlüsselungspasswort verliere?

Die Datei kann nicht wiederhergestellt werden. Das Passwort erreicht den Server nie, was der eigentliche Zweck der Ende-zu-Ende-Verschlüsselung ist; daher gibt es keine Zurücksetzungsfunktion und keinen Support-Weg. Speichern Sie es in einem Passwort-Manager, sobald Sie die Datei erstellen, und bewahren Sie eine Kopie an einem Ort auf, der nicht von diesem Server abhängt.

Wie viel Serverleistung benötigt Actual Budget?

Sehr wenig. Der Container stellt statische Assets und Dateien bereit, die Budget-Berechnungen finden im Browser statt. Eine geteilte vCPU mit 1 GB RAM reicht problemlos aus, und das Datenverzeichnis für ein Haushaltsbudget mit mehreren Jahren Historie bleibt im zweistelligen Megabyte-Bereich. Die Festplattenlast entsteht durch Ihre Backups und andere Container, nicht durch Actual. Wenn Sie ein System planen, auf dem gleichzeitig ressourcenhungrigere Anwendungen laufen, bestimmt meist ein Fotoserver die Mindestanforderungen. Prüfen Sie daher wie viel RAM PhotoPrism und Immich tatsächlich benötigen, bevor Sie sich für einen Plan entscheiden. Die gleiche Logik gilt für einen Media-Stack: Transkodierung bestimmt den Plan, während ein Browser-Frontend wie Halcyon, das eine Jellyfin-Bibliothek in eine begehbare Videothek der 90er Jahre verwandelt kaum mehr Ressourcen verbraucht als Actual.

War dieser Artikel hilfreich?