SSD Nodes Learn Hosting plans →
Mga Gabay Matt ConnorNi Matt Connor · Na-update 2026-10-30

Paano i-self-host ang Actual Budget sa VPS

I-run ang Actual Budget sa VPS gamit ang Docker Compose: alamin ang data volume, bakit kailangan ng browser ang HTTPS, bank imports, at tamang backups.

Mga itinatayo mo

Ang Actual Budget ay isang self-hosted envelope budgeting app. Ito ang karaniwang sagot kapag naghahanap ang mga tao ng YNAB alternative na maaari nilang i-host mismo. Isang container, isang data volume, at isang HTTPS name ang kailangan sa server. Kumportable itong tumakbo sa pinakamaliit na VPS na maaari mong rentahan dahil pangunahing nagse-save lang ng files at nagsi-sync ang server.

Mahalagang maunawaan muna ang architecture bago ka mag-type ng kahit ano. Ang budget mismo ay isang SQLite database na nasa browser mo at nasa bawat mobile app. Ang server na ii-install mo ay isang sync endpoint. Naglalaman ito ng listahan ng accounts, mga budget file, at change log na ginagamit para magtugma ang data sa phone at laptop. Kaya gumagana pa rin ang app kapag down ang server. Kaya hindi mawawala ang budget mo kapag nawala ang server, basta may isang client na may hawak pa ring kopya nito.

Bakit kailangan ng server ang HTTPS

Humihingi ang Actual ng HTTPS, at hindi ito simpleng pormalidad. Kailangan ng Actual ng feature ng browser na tinatawag na SharedArrayBuffer para gumana. Ine-enable lamang ito ng mga browser kapag cross-origin isolated ang page sa tinatawag ng specification na secure context. Ang secure context ay https:// o http://localhost. Kapag ni-load ang app mula sa http://203.0.113.10:5006 sa browser ng ibang machine, hindi kailanman ibinibigay ng browser ang feature na iyon sa page, kaya hindi naglo-load ang budget. Walang eksepsiyon para sa mga phone. Ayon sa FAQ ng Actual, beta testing ang isang opisyal na iOS app at kumokonekta ito sa sarili mong server. Wala pa ring opisyal na Android app. Kaya sa karamihan ng phone, ang parehong web app ang ginagamit at ini-install sa home screen bilang Progressive Web App. Pareho pa rin ang secure-context rule.

May dalawang setup na maaaring gamitin. Maglagay ng totoong certificate sa totoong domain name sa harap ng container, gaya ng ginagawa ng gabay na ito. O bigyan ang server ng self-signed certificate gamit ang ACTUAL_HTTPS_KEY at ACTUAL_HTTPS_CERT, gaya ng nakadokumento sa project, at tanggapin ang browser warning sa bawat device. Limang minuto lang ang pagkuha ng libreng certificate mula sa Let's Encrypt, kaya piliin ang unang opsiyon.

I-install ang Actual Budget gamit ang Docker Compose

I-install muna ang Docker kung bago ang server. Kung bago sa iyo ang syntax ng Compose file, ipinapaliwanag ng gabay na mga pangunahing kaalaman sa Docker Compose para sa VPS ang mga field na gagamitin sa ibaba.

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

Isulat ang /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

Mahalaga ang tatlong detalye sa file na iyon.

Ang image ay actualbudget/actual-server:latest, na inilabas ng project sa Docker Hub at may mirror sa ghcr.io/actualbudget/actual. May latest-alpine tag para sa mga machine na mababa ang power.

Isinusulat ng container ang lahat sa ilalim ng /data. Sa loob nito ay makikita ang server-files, na naglalaman ng account.sqlite kasama ang iyong login at session tokens, at user-files, na naglalaman mismo ng mga budget file. I-mount ang path na iyon; kung hindi, buburahin ng susunod na docker compose pull ang iyong budget. Maaaring ilipat ito ng ACTUAL_DATA_DIR, pero sapat na ang default.

Sa 127.0.0.1 lamang na-publish ang port. Kapag plain 5006:5006 ang ginamit, ipa-publish ito sa lahat ng interface. Gumagawa ang Docker ng sarili nitong rules bago ang ufw, kaya magiging bukas sa internet ang app kahit may deny-all firewall. Ipinaliliwanag ang problemang ito sa kung bakit nilalampasan ng Docker published ports ang ufw. Kapag naka-bind sa loopback, ang reverse proxy na nasa parehong server lamang ang makaka-access dito.

Simulan ito:

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

Magiging stable ang log kapag iniulat ng server na nakikinig ito sa port 5006. Suriin muna ito locally bago baguhin ang DNS:

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

Ang 200 ay nangangahulugang naghahatid ng serbisyo ang app. Ang curl: (7) Failed to connect ay nangangahulugang walang tumanggap sa koneksyon sa 127.0.0.1:5006. Patakbuhin ang docker compose ps --all, dahil ang plain docker compose ps ay naglilista lamang ng mga tumatakbong container. Kung exited ang status ng container, karaniwang sanhi nito ang permission problem sa mounted volume, na makikita bilang EACCES line sa log.

Maglagay ng certificate at totoong pangalan sa harap

Ituro ang isang A record sa VPS, budget.example.com, at hintaying mag-resolve ito. Pagkatapos, i-install ang nginx at i-issue ang certificate. Sinasaklaw nang buo ng gabay na Certbot sa Ubuntu 24.04 gamit ang nginx ang pag-issue ng certificate at ang renewal timer.

Ang 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 ang linyang madalas nakakaligtaan. Sa pang-araw-araw na sync, ang mga pagbabago mo lamang ang ipinapadala. Ngunit ina-upload ang buong budget file kapag una mong nirehistro ang isang budget sa server at muli kapag ni-reset mo ang sync. Naka-default ang nginx sa 1 MB na request body. Kaya kapag lumampas dito ang file, mabibigo ang buong upload at lalabas ang 413 Request Entity Too Large sa nginx access log, habang generic sync error lamang ang ipinapakita ng app. May hiwalay na limit ang server: naka-default sa 20 ang ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB at sa 50 ang ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SYNC_SIZE_LIMIT_MB. Itakda ang nginx limit na mas mataas sa limit na naaangkop sa iyo.

I-reload at subukan:

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

Unang paggamit: ang password at ang iyong unang budget file

Buksan ang https://budget.example.com sa isang browser. Hihilingin sa unang screen na magtakda ka ng server password. Pinoprotektahan ng password na ito ang buong server, kaya bumuo ng mahaba at random na password at itago ito sa lugar na mahahanap mo ulit, gaya ng isang self-hosted na Vaultwarden password manager. Walang kailangang gawin na user account bilang default: iisa ang password ng server, kaya ang pagbabahagi ng budget ay nangangahulugan ding pagbabahagi ng password na iyon. Posible lamang ang magkakahiwalay na login kung ikokonekta mo ang isang OpenID provider, na sinusuportahan ng Actual para sa mga multi-user setup.

Pagkatapos, gumawa ng budget file. Tatanungin ka ng Actual kung ie-enable ang end-to-end encryption. Piliin ang yes. Sa ganitong paraan, ciphertext lamang ang itinatago ng server, na tamang pagpili para sa financial data sa isang nirentahang machine. May kapalit ito: hindi kailanman ipinapadala sa server ang encryption password. Kaya kapag nawala ito, mawawala ang file at walang reset na available. Isulat ang password bago mo lampasan ang screen na iyon.

Itakda ang iyong starting balances batay sa kasalukuyang figures mula sa bangko, sa halip na mag-import ng maraming taong history. Gumagana ang envelope budgeting mula sa perang mayroon ka ngayon, kaya walang mawawala sa iyo kung walang lumang history.

Pagkuha ng mga transaksiyon

Dito mas mahalaga ang pagiging tapat kaysa sa entusiasmo, dahil ang paraan ng pag-import ang pangunahing dahilan kung bakit umaayaw ang mga tao sa self-hosted budgeting.

Ang manual na paglalagay ang batayang paraan at palagi itong gumagana. Para sa envelope method, masasabi ring ito mismo ang layunin, dahil kapag ikaw mismo ang nag-type ng isang binili, mas napapansin mo ito.

Ang file import ang humahawak sa maramihan. Nagbabasa ang Actual ng CSV, QIF, OFX, QFX, at CAMT, at lahat ng bangko ay nag-e-export ng kahit isa sa mga ito. Mag-import bawat account mula sa screen ng account, at i-map ang mga column kapag CSV ang file.

May automatic bank sync, pero kailangan nito ng third-party service dahil hindi direktang nakakakonekta ang server sa mga bangko. Sinusuportahan ng Actual ang SimpleFIN Bridge para sa mga bangko sa North America, Enable Banking para sa Europe, Akahu para sa New Zealand, at Pluggy.ai para sa Brazil. Sinusuportahan pa rin ang GoCardless, pero hindi na ito tumatanggap ng mga bagong account. Ikaw mismo ang mag-sign up sa provider, gumawa ng credentials, at idagdag ang mga ito sa server. Naniningil ang SimpleFIN Bridge ng 15 US dollars bawat taon, dagdag ang tax, para sa hanggang 25 institutions noong October 2026. Iba naman ang pricing ng iba pang provider.

May dalawang limitasyong dapat mong tanggapin bago ka umasa rito. Nasa server ang API credentials at hindi saklaw ng end-to-end encryption, dahil kailangang gamitin ng server ang mga ito. Wala ring nagsi-sync habang sarado ang Actual: naka-off bilang default ang automatic syncing, at kapag in-on mo ito, tumatakbo lamang ito habang bukas ang app. Hindi kailanman kusang nagpo-poll ang server sa mga bangko mo.

Mga backup, dahil mga file lang ito

Nasa ilalim ng /opt/actual/data ang lahat ng mahalaga sa iyo. Walang export step at walang database dump na kailangang i-script.

Ang isang dapat bantayan ay SQLite. Kapag kinopya ang account.sqlite habang sinusulatan pa ito ng server, maaaring makuha ang transaksyong hindi pa tapos, at malalaman mo lang iyon kapag sinubukan mo nang mag-restore. Ihinto ang container sa ilang segundo habang isinasagawa ang pagkopya:

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

Ilagay ito sa isang schedule gamit ang paraan sa mga restic backup sa isang VPS, na sumasaklaw sa pag-set up ng repository, retention, at restore drill. Isagawa ang restore drill. Ang backup na hindi mo kailanman na-restore ay hula lamang.

Hiwalay ang automatic backup ng Actual at mahalagang malaman ang tungkol dito, pero nasa desktop app lamang ito. Pinananatili nito ang hanggang 10 pinakabagong kopya ng budget file, na maa-access sa File > Load Backup. Sapat ito para sa sitwasyong “aksidenteng nabura ko ang isang category” nang hindi ginagalaw ang server. Walang ganitong mga kopya ang web app sa browser. Kaya kung browser ang ginagamit ng lahat sa bahay, ang server backup sa itaas ang tanging mayroon ka.

Pag-update ng server

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

Muling ginagawa ng Compose ang container mula sa bagong image at ikinakabit muli ang parehong volume, kaya nananatili ang data. I-update rin ang mga client. Kapag mas luma ang client kaysa sa data na natatanggap nito, hihinto itong mag-apply ng mga pagbabago at magpapakita ng mensaheng Update Required. Gumawa ng backup bago lumipat sa pangunahing bagong bersyon, dahil tumatakbo ang migrations sa unang pagsisimula at walang downgrade path. Hindi gaanong sensitibo ang Actual sa floating na latest tag dahil directory ng mga file ang state nito. Hindi ganoon ang app na gumagamit ng aktuwal na database. Ipinapakita sa pag-self-host ng Chatwoot ang pinned tags at ang pre-upgrade dump na kailangan sa ganitong proseso.

Mga masisirang bahagi at mga makikita mo

Nilo-load ang app pero hindi natatapos ang sync. Suriin ang nginx access log para sa 413. Ibig sabihin, masyadong mababa ang itinakdang client_max_body_size. Samantala, ang 502 ay nangangahulugang hindi nakatanggap ang nginx ng magagamit na response mula sa upstream. Kadalasan, hinto ang container o hindi ito nakikinig sa 5006. Kaya suriin muna ang docker compose ps --all at ang container log bago ang iba pa.

Hindi naglo-load ang app sa ibang device, o nag-uulat na nawawala ang SharedArrayBuffer. Wala sa secure context ang page. Ipapakita ng address bar ang http:// na may IP address o hostname na hindi localhost. Ayusin ang certificate sa halip na maghanap ng workaround.

May mensaheng hindi compatible ang budget file sa bersyong ito. Nabuksan ang file sa mas bagong bersyon ng Actual kaysa sa client na ginagamit mo ngayon. I-update ang client sa bersyong iyon o mas bago, o i-restore ang backup na ginawa bago nabuksan ng mas bagong bersyon ang file, saka i-load muli.

Paulit-ulit na nagre-restart ang container. Basahin ang docker compose logs actual. Ang permission error sa /data ay nangangahulugang hindi maisulat ng user ng container ang mounted directory. Ang address-in-use error ay nangangahulugang may ibang process nang gumagamit sa 5006 sa loopback.

Mabagal ang unang pag-load. Ida-download sa browser ang buong budget file kapag binuksan mo ito. Isang malaking transfer muna ito, saka isinasagawa ang mga lokal na pagbasa. Hindi ito problema sa server sizing, at walang mababago ang pagdagdag ng RAM.

FAQ

Kailangan ba ng HTTPS ang Actual Budget para gumana?

Oo, sa aktuwal na paggamit. Kailangan ng Actual ang SharedArrayBuffer feature ng browser para gumana, at ine-enable lang ito ng mga browser sa isang secure context, ibig sabihin, https:// o http://localhost. Kapag plain HTTP mula sa ibang machine, hindi maglo-load ang app. Nasa beta testing ang isang official iOS app at wala pang official Android app, kaya ginagamit ng karamihan sa mga phone ang parehong web app at napapailalim sa parehong requirement. (FAQ) Gumamit ng Let's Encrypt certificate sa isang totoong hostname, o ng self-signed certificate na may ACTUAL_HTTPS_KEY at ACTUAL_HTTPS_CERT kung kaya mong tanggapin ang certificate warning sa bawat device.

Maaari bang awtomatikong mag-import ang Actual ng mga transaksyon ko sa bangko?

Sa pamamagitan lang ito ng third-party service na ikaw mismo ang sasalihan: SimpleFIN Bridge sa North America, Enable Banking sa Europe, Akahu sa New Zealand, o Pluggy.ai sa Brazil. Supported ang GoCardless pero hindi na ito tumatanggap ng mga bagong account. Nasa server mo ang mga API credential na iyon at hindi saklaw ng end-to-end encryption. Naka-off bilang default ang automatic syncing at, kapag na-enable, tumatakbo lang habang bukas ang Actual, kaya walang nagpu-poll sa background sa server. Hindi kailangan ng anumang third party para sa pag-import ng CSV, QIF, OFX, QFX at CAMT.

Ano mismo ang kailangan kong i-back up?

Ang naka-mount na data directory, na /opt/actual/data sa gabay na ito. Naglalaman ito ng server-files/account.sqlite para sa mga login at session, at user-files para sa mga budget file. Ihinto ang container bago mag-copy, dahil maaaring makakuha ng bahagyang naisulat na data ang pagkopya ng live na SQLite database. Walang ibang state na naka-store sa server.

Ano ang mangyayari kung mawala ko ang encryption password?

Hindi na mare-recover ang file. Hindi kailanman napupunta sa server ang password, na siyang pangunahing dahilan ng end-to-end encryption, kaya walang reset at walang support path. I-save ito sa password manager sa mismong paggawa mo ng file, at magtabi ng kopya sa lugar na hindi nakadepende sa server na ito.

Gaano karaming server resources ang kailangan ng Actual Budget?

Napakakaunti. Nagsu-serve ang container ng static assets at mga file, at sa browser ginagawa ang mga budget calculation. Kaya itong patakbuhin ng isang shared vCPU na may 1 GB RAM nang walang problema, at nananatili sa sampu-sampung megabyte ang data directory para sa household budget na may ilang taong history. Ang disk pressure ay karaniwang nagmumula sa mga backup mo at iba mo pang container, hindi sa Actual. Kung nagso-size ka ng box na kailangan ding magpatakbo ng mas resource-intensive na application, karaniwang photo server ang nagtatakda ng minimum requirement, kaya tingnan muna kung gaano karaming RAM ang talagang kailangan ng PhotoPrism at Immich bago pumili ng plan. Pareho ang prinsipyo sa media stack: transcoding ang nagtatakda ng plan, samantalang kaunting-kaunti lang ang resource cost ng browser front end gaya ng Halcyon, na ginagawang 90s video store na maaaring libutin ang Jellyfin library, halos katulad ng Actual.

Nakatulong ba ang artikulong ito?