Jak zainstalować Actual Budget na własnym VPS
Dowiedz się, jak uruchomić Actual Budget przy użyciu Docker Compose. Poradnik wyjaśnia konfigurację wolumenów, wymóg HTTPS dla Web Crypto API oraz proces synchronizacji danych.
Co budujesz
Actual Budget to samodzielnie hostowana aplikacja do budżetowania metodą kopertową. Jest to najczęściej wybierana alternatywa dla YNAB, którą można uruchomić na własnej infrastrukturze. Serwer składa się z jednego kontenera, jednego wolumenu danych oraz jednej nazwy HTTPS. Wszystkie funkcje niezbędne do prowadzenia budżetu działają wydajnie na najmniejszym dostępnym serwerze VPS, ponieważ serwer pełni głównie rolę magazynu plików i punktu synchronizacji.
Przed rozpoczęciem konfiguracji warto zrozumieć architekturę rozwiązania. Sam budżet jest bazą danych SQLite, która znajduje się wewnątrz przeglądarki oraz każdej aplikacji mobilnej. Serwer, który zainstalujesz, jest punktem końcowym synchronizacji: przechowuje listę kont, pliki budżetu oraz dziennik zmian, który zapewnia spójność danych między telefonem a laptopem. Dzięki temu aplikacja działa nawet wtedy, gdy serwer jest niedostępny, a utrata serwera nie oznacza utraty budżetu, o ile przynajmniej jeden klient posiada jego kopię.
Dlaczego serwer wymaga HTTPS
Actual wymaga HTTPS i nie jest to tylko formalność. Przeglądarki udostępniają Web Crypto API, interfejs wykorzystywany przez Actual do szyfrowania typu end-to-end, wyłącznie w kontekście uznawanym przez specyfikację za bezpieczny. Bezpieczny kontekst to https:// lub http://localhost. Wczytanie aplikacji z http://203.0.113.10:5006 w przeglądarce na innym urządzeniu powoduje, że te funkcje są niedostępne, ponieważ przeglądarka nie udostępniła ich stronie. Oficjalne kompilacje mobilne również odrzucają adresy serwerów korzystające ze zwykłego http://.
Istnieją zatem dwie możliwe konfiguracje. Pierwszą, opisaną w tym przewodniku, jest umieszczenie kontenera za serwerem proxy z poprawnym certyfikatem przypisanym do rzeczywistej nazwy domenowej. Drugą opcją jest użycie certyfikatu z podpisem własnym z ACTUAL_HTTPS_KEY i ACTUAL_HTTPS_CERT, co zostało opisane w dokumentacji projektu, przy czym należy zaakceptować ostrzeżenie przeglądarki na każdym urządzeniu. Uzyskanie darmowego certyfikatu od Let's Encrypt zajmuje pięć minut, dlatego zaleca się wybór pierwszej opcji.
Instalacja Actual Budget przy użyciu Docker Compose
Jeśli serwer jest świeży, najpierw zainstaluj Docker. Jeśli składnia plików Compose jest nowa, przewodnik Podstawy Docker Compose dla VPS omawia pola użyte poniżej.
sudo install -d -m 755 /opt/actual
sudo install -d -m 700 /opt/actual/dataUtwórz plik /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:/dataW tym pliku istotne są trzy szczegóły.
Obraz to actualbudget/actual-server:latest, publikowany przez projekt w Docker Hub i udostępniany w ghcr.io/actualbudget/actual. Dostępny jest tag latest-alpine dla maszyn o niskiej wydajności.
Kontener zapisuje wszystkie dane w /data. Wewnątrz znajduje się server-files, przechowujący account.sqlite z danymi logowania i tokenami sesji, oraz user-files, zawierający pliki budżetu. Zamontuj tę ścieżkę, w przeciwnym razie docker compose pull spowoduje utratę danych budżetu. ACTUAL_DATA_DIR pozwala na zmianę lokalizacji, ale ustawienie domyślne jest poprawne.
Port jest publikowany wyłącznie na 127.0.0.1. Zapis 5006:5006 publikuje usługę na wszystkich interfejsach, a Docker dodaje własne reguły przed ufw, więc aplikacja byłaby dostępna z Internetu nawet przy zaporze typu deny-all. To zjawisko wyjaśniono w dlaczego publikowane porty Dockera omijają ufw. Powiązanie z interfejsem zwrotnym (loopback) oznacza, że dostęp do usługi ma tylko reverse proxy działający na tym samym serwerze.
Uruchom usługę:
cd /opt/actual
docker compose up --detach
docker compose logs -f actualDziennik ustabilizuje się, gdy serwer zgłosi nasłuchiwanie na porcie 5006. Sprawdź działanie lokalnie przed konfiguracją DNS:
curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:5006/Kod 200 oznacza, że aplikacja działa poprawnie. curl: (7) Failed to connect oznacza, że kontener nie jest uruchomiony, a docker compose ps pokaże, że proces zakończył działanie. Typową przyczyną jest problem z uprawnieniami do zamontowanego wolumenu, widoczny jako linia EACCES w dzienniku.
Konfiguracja certyfikatu i nazwy domenowej
Skieruj rekord A na adres IP serwera VPS, budget.example.com, i poczekaj na propagację zmian DNS. Następnie zainstaluj nginx i wygeneruj certyfikat. Przewodnik Certbot na Ubuntu 24.04 z nginx szczegółowo opisuje proces wydawania certyfikatu oraz harmonogram jego odnawiania.
Blok proxy:
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 to parametr, o którym użytkownicy często zapominają. Plik budżetu jest przesyłany w całości podczas pełnej synchronizacji. Domyślny limit rozmiaru treści żądania w nginx wynosi 1 MB, więc po przekroczeniu tego rozmiaru synchronizacja kończy się niepowodzeniem, a w dzienniku dostępu nginx pojawia się błąd 413 Request Entity Too Large, podczas gdy aplikacja wyświetla jedynie ogólny komunikat o błędzie synchronizacji. Serwer posiada własne limity: ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB domyślnie wynosi 20, a ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SYNC_SIZE_LIMIT_MB domyślnie 50, dlatego należy ustawić limit w nginx na wartość wyższą niż stosowany limit aplikacji.
Przeładuj konfigurację i przetestuj:
sudo nginx -t && sudo systemctl reload nginx
curl -fsS -o /dev/null -w '%{http_code}\n' https://budget.example.com/Pierwsze uruchomienie: hasło i pierwszy plik budżetu
Otwórz https://budget.example.com w przeglądarce. Pierwszy ekran wymaga ustawienia hasła serwera. To jedno hasło zabezpiecza cały serwer, więc wygeneruj długie, losowe hasło i przechowaj je w bezpiecznym miejscu, na przykład w samodzielnie hostowanym menedżerze haseł Vaultwarden. Nie ma potrzeby tworzenia kont użytkowników. Serwer Actual został zaprojektowany z myślą o jednym haśle, więc udostępnienie budżetu oznacza udostępnienie tego hasła.
Następnie utwórz plik budżetu. Actual zapyta, czy włączyć szyfrowanie end-to-end. Wybierz opcję twierdzącą; serwer będzie przechowywał wyłącznie tekst zaszyfrowany, co jest właściwym rozwiązaniem dla danych finansowych na wynajmowanej maszynie. Koszt tego rozwiązania jest realny: hasło szyfrujące nigdy nie trafia na serwer, więc w przypadku jego utraty plik przepadnie bez możliwości resetu. Zapisz je, zanim przejdziesz dalej.
Ustaw salda początkowe na podstawie aktualnych danych z banku, zamiast importować historię z wielu lat. Budżetowanie kopertowe działa w oparciu o środki, którymi dysponujesz obecnie, więc brak historii nie stanowi żadnej przeszkody.
Importowanie transakcji
W tym miejscu uczciwość jest ważniejsza niż entuzjazm, ponieważ proces importu danych jest głównym powodem, dla którego użytkownicy rezygnują z samodzielnie hostowanych narzędzi budżetowych.
Ręczne wprowadzanie danych to standard, który zawsze działa. W przypadku metody kopertowej jest to wręcz kluczowy element, ponieważ konieczność wpisania zakupu sprawia, że użytkownik zwraca na niego uwagę.
Import plików pozwala obsłużyć większe wolumeny danych. Actual odczytuje formaty CSV, QIF, OFX oraz QFX, a każdy bank oferuje eksport do przynajmniej jednego z nich. Importu dla poszczególnych kont dokonuje się z poziomu ekranu konta; po jednorazowym zmapowaniu kolumn Actual zapamiętuje układ dla danego konta.
Dostępna jest automatyczna synchronizacja bankowa, która wymaga zewnętrznej usługi, ponieważ serwer nie może samodzielnie komunikować się z bankami. Actual obsługuje SimpleFIN Bridge dla banków w Ameryce Północnej, Enable Banking dla Europy, Akahu dla Nowej Zelandii oraz Pluggy.ai dla Brazylii. GoCardless jest nadal wspierany, ale nie przyjmuje nowych kont. Użytkownik samodzielnie rejestruje się u dostawcy, generuje dane uwierzytelniające i dodaje je do serwera. Według stanu na lipiec 2026 roku, SimpleFIN Bridge kosztuje 15 dolarów amerykańskich rocznie za obsługę do 25 instytucji, a pozostali dostawcy stosują inne cenniki.
Przed rozpoczęciem korzystania z tej funkcji należy zaakceptować dwa ograniczenia. Dane uwierzytelniające API znajdują się na serwerze i nie są objęte szyfrowaniem end-to-end, ponieważ serwer musi mieć do nich dostęp. Ponadto Actual nie wykonuje odpytywania automatycznego: synchronizacja jest procesem inicjowanym ręcznie przyciskiem, a nie zadaniem działającym w tle.
Kopie zapasowe, ponieważ to tylko pliki
Wszystkie istotne dane znajdują się w /opt/actual/data. Nie jest wymagany żaden proces eksportu ani skryptowanie zrzutów bazy danych.
Jedynym zagrożeniem jest SQLite. Kopiowanie account.sqlite w trakcie zapisu przez serwer może spowodować przechwycenie nieukończonej transakcji, co zostanie wykryte dopiero podczas próby przywracania. Należy zatrzymać kontener na kilka sekund potrzebnych do wykonania kopii:
cd /opt/actual
docker compose stop
restic -r sftp:backup@backup.example.com:/srv/restic backup /opt/actual/data
docker compose startNależy zaplanować to zadanie zgodnie z podejściem opisanym w kopie zapasowe restic na VPS, które obejmuje konfigurację repozytorium, retencję oraz procedurę odtwarzania. Należy przeprowadzić próbę odtwarzania. Kopia zapasowa, która nigdy nie została przywrócona, jest jedynie przypuszczeniem.
Własne kopie zapasowe Actual po stronie klienta to odrębna kwestia, którą warto znać. Przeglądarka przechowuje ostatnie kopie pliku budżetu, dostępne z menu pliku, co pozwala na rozwiązanie problemu typu "przypadkowe usunięcie kategorii" bez ingerencji w serwer.
Aktualizacja serwera
cd /opt/actual
docker compose pull
docker compose up --detachCompose odtwarza kontener z nowego obrazu i ponownie podpina ten sam wolumen, dlatego dane pozostają zachowane. Należy również zaktualizować klientów. Oczekuje się, że wersje serwera i aplikacji będą zbliżone. Klient znacznie starszy od serwera może odmówić synchronizacji i wyświetlić komunikat o niezgodności wersji. Przed przejściem na główną wersję należy wykonać kopię zapasową, ponieważ migracje są uruchamiane przy pierwszym starcie i nie ma ścieżki powrotu do starszej wersji. Actual toleruje zmienny tag latest, ponieważ jego stan jest przechowywany jako katalog plików. Nie dotyczy to aplikacji korzystającej z rzeczywistej bazy danych. W artykule samodzielne wdrażanie Chatwoot opisano przypinanie tagów oraz wykonanie zrzutu przed aktualizacją, czego wymaga taka procedura.
Co ulega awarii i co zobaczysz
Aplikacja ładuje się, ale synchronizacja nigdy się nie kończy. Sprawdź log dostępu nginx pod kątem 413. Oznacza to, że client_max_body_size jest ustawione na zbyt niską wartość. Z kolei 502 oznacza, że nginx działa, ale kontener nie.
Opcje szyfrowania są niedostępne lub aplikacja mobilna odrzuca adres URL. Strona nie znajduje się w bezpiecznym kontekście. Pasek adresu wyświetli http:// wraz z adresem IP lub nazwą hosta, która nie jest localhost. Napraw certyfikat, zamiast stosować obejścia.
Komunikat o niezgodności pliku budżetu z tą wersją. Wersje klienta i serwera przestały być spójne. Zaktualizuj oba komponenty do tej samej wersji i przeładuj aplikację.
Kontener restartuje się w pętli. Przeczytaj docker compose logs actual. Błąd uprawnień na /data oznacza, że zamontowany katalog nie jest zapisywalny dla użytkownika kontenera. Błąd "address-in-use" oznacza, że inny proces już zajmuje port 5006 na interfejsie loopback.
Pierwsze ładowanie trwa długo. Cały plik budżetu jest pobierany do przeglądarki w momencie otwarcia. Jest to jeden duży transfer, po którym następują odczyty lokalne. Nie jest to problem z wydajnością serwera i dodanie pamięci RAM nie przyniesie zmiany.
FAQ
Czy Actual Budget wymaga HTTPS do działania?
Tak, w praktyce. Szyfrowanie end-to-end w Actual korzysta z interfejsu Web Crypto API przeglądarki, a przeglądarki udostępniają go wyłącznie w bezpiecznym kontekście, czyli https:// lub http://localhost. Przy połączeniu przez zwykłe HTTP z innej maszyny funkcje te są niedostępne, a oficjalne aplikacje mobilne odrzucają adresy URL serwerów bez HTTPS. Należy użyć certyfikatu Let’s Encrypt dla rzeczywistej nazwy hosta lub certyfikatu z podpisem własnym z ACTUAL_HTTPS_KEY i ACTUAL_HTTPS_CERT, jeśli korzysta się wyłącznie z przeglądarki na komputerze stacjonarnym.
Czy Actual może automatycznie importować transakcje bankowe?
Tylko za pośrednictwem zewnętrznej usługi, na którą użytkownik rejestruje się samodzielnie: SimpleFIN Bridge w Ameryce Północnej, Enable Banking w Europie, Akahu w Nowej Zelandii lub Pluggy.ai w Brazylii. GoCardless jest obsługiwany, ale nie przyjmuje nowych kont. Dane uwierzytelniające API są przechowywane na serwerze i nie są objęte szyfrowaniem end-to-end. Synchronizacja również odbywa się ręcznie – użytkownik naciska przycisk, a w tle nie działa żaden proces odpytujący. Import plików CSV, QIF, OFX oraz QFX nie wymaga żadnych zewnętrznych usług.
Co dokładnie należy archiwizować?
Podmontowany katalog danych, który w tym przewodniku oznaczono jako /opt/actual/data. Zawiera on server-files/account.sqlite z danymi logowania i sesjami oraz user-files z plikami budżetu. Przed kopiowaniem należy zatrzymać kontener, ponieważ kopiowanie aktywnej bazy danych SQLite może skutkować zapisem niepełnych danych. Żaden inny element na serwerze nie przechowuje stanu aplikacji.
Co się stanie, jeśli zgubię hasło szyfrujące?
Pliku nie da się odzyskać. Hasło nigdy nie trafia na serwer, co jest istotą szyfrowania end-to-end, dlatego nie istnieje procedura resetowania ani ścieżka wsparcia technicznego. Hasło należy zapisać w menedżerze haseł w momencie tworzenia pliku i przechowywać kopię w miejscu niezależnym od tego serwera.
Jakich zasobów serwerowych wymaga Actual Budget?
Bardzo niewielkich. Kontener serwuje statyczne zasoby i pliki, a obliczenia budżetowe odbywają się w przeglądarce. Jeden współdzielony vCPU z 1 GB pamięci RAM wystarcza do bezproblemowej pracy, a katalog danych dla budżetu domowego z kilkuletnią historią zajmuje kilkadziesiąt megabajtów. Obciążenie dysku wynika z kopii zapasowych i innych kontenerów, a nie z samego Actual. Przy dobieraniu parametrów serwera, który ma obsługiwać również bardziej wymagające aplikacje, to zazwyczaj serwer zdjęć wyznacza dolną granicę wymagań, dlatego przed wyborem planu warto sprawdzić ile pamięci RAM faktycznie potrzebują PhotoPrism i Immich.