Cara Self-Host Actual Budget di VPS dengan Docker
Pelajari cara menjalankan Actual Budget di VPS dengan Docker Compose, termasuk volume data, HTTPS untuk Web Crypto API, file anggaran pertama, impor bank, dan backup.
Yang akan Anda bangun
Actual Budget adalah aplikasi penganggaran berbasis amplop yang di-host sendiri. Aplikasi ini biasanya menjadi pilihan ketika pengguna mencari alternatif YNAB yang dapat di-host sendiri. Servernya terdiri dari satu container, satu volume data, dan satu nama HTTPS. Semua fungsi yang dibutuhkan anggaran biasa dapat berjalan dengan baik pada VPS terkecil yang dapat Anda sewa, karena server terutama menyimpan file dan melakukan sinkronisasi.
Arsitekturnya perlu dipahami sebelum Anda menjalankan perintah apa pun. Anggaran itu sendiri adalah database SQLite yang berada di dalam browser dan setiap aplikasi seluler. Server yang akan Anda instal adalah endpoint sinkronisasi. Server ini menyimpan daftar akun, file anggaran, dan log perubahan yang memungkinkan ponsel dan laptop menggunakan data yang sama. Karena itu, aplikasi tetap berfungsi ketika server tidak tersedia. Kehilangan server juga tidak menyebabkan anggaran hilang selama masih ada satu klien yang menyimpan salinannya.
Mengapa server memerlukan HTTPS
Actual memerlukan HTTPS, dan ini bukan sekadar formalitas. Browser hanya menyediakan Web Crypto API, yaitu antarmuka yang digunakan Actual untuk enkripsi end-to-end, dalam kondisi yang menurut spesifikasi disebut secure context. Secure context adalah https:// atau http://localhost. Jika aplikasi dibuka dari http://203.0.113.10:5006 menggunakan browser pada mesin lain, fitur tersebut tidak tersedia karena browser tidak pernah meneruskannya ke halaman. Build mobile resmi juga menolak URL server http:// biasa.
Jadi, ada dua konfigurasi yang dapat digunakan. Pasang sertifikat yang valid pada nama domain yang valid di depan container, seperti yang dilakukan dalam panduan ini. Atau berikan server sertifikat yang ditandatangani sendiri menggunakan ACTUAL_HTTPS_KEY dan ACTUAL_HTTPS_CERT, sebagaimana didokumentasikan oleh proyek, lalu terima peringatan browser pada setiap perangkat. Sertifikat gratis dari Let's Encrypt dapat diperoleh dalam lima menit, jadi gunakan opsi pertama.
Instal Actual Budget dengan Docker Compose
Instal Docker terlebih dahulu jika server masih baru. Jika sintaks file Compose masih baru bagi Anda, panduan dasar-dasar Docker Compose untuk VPS menjelaskan kolom yang digunakan di bawah.
sudo install -d -m 755 /opt/actual
sudo install -d -m 700 /opt/actual/dataTulis /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:/dataAda tiga detail penting dalam file tersebut.
Image-nya adalah actualbudget/actual-server:latest, yang dipublikasikan oleh proyek ke Docker Hub dan dicerminkan di ghcr.io/actualbudget/actual. Tersedia tag latest-alpine untuk mesin berdaya rendah.
Container menulis semua data di bawah /data. Di dalamnya terdapat server-files, yang menyimpan account.sqlite berisi login dan token sesi Anda, serta user-files, yang menyimpan file anggaran itu sendiri. Mount path tersebut. Jika tidak, docker compose pull berikutnya akan menghapus anggaran Anda. ACTUAL_DATA_DIR dapat memindahkannya, tetapi nilai default sudah memadai.
Port hanya dipublikasikan pada 127.0.0.1. 5006:5006 tanpa alamat akan memublikasikan port pada semua interface, dan Docker menulis aturannya sendiri sebelum ufw. Akibatnya, aplikasi akan terbuka ke Internet meskipun firewall menerapkan penolakan semua koneksi. Hal ini dijelaskan dalam alasan port yang dipublikasikan Docker melewati ufw. Binding ke loopback berarti hanya reverse proxy pada server yang sama yang dapat mengaksesnya.
Jalankan:
cd /opt/actual
docker compose up --detach
docker compose logs -f actualLog akan stabil setelah server melaporkan bahwa server sedang listening pada port 5006. Periksa secara lokal sebelum mengubah DNS:
curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:5006/Respons 200 berarti aplikasi sedang melayani permintaan. Respons curl: (7) Failed to connect berarti container tidak berjalan, dan docker compose ps akan menampilkan bahwa container tersebut telah berhenti. Penyebab yang umum adalah masalah permission pada volume yang di-mount, yang terlihat sebagai baris EACCES dalam log.
Pasang sertifikat dan nama domain yang sebenarnya di depan
Arahkan record A ke VPS, budget.example.com, lalu tunggu hingga resolusinya selesai. Setelah itu, instal nginx dan terbitkan sertifikat. Panduan Certbot di Ubuntu 24.04 dengan nginx menjelaskan proses penerbitan dan timer pembaruan secara lengkap.
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 adalah baris yang sering terlupakan. File budget diunggah secara utuh saat sinkronisasi penuh. Secara default, nginx menetapkan ukuran body permintaan sebesar 1 MB. Setelah ukuran file melebihi batas tersebut, sinkronisasi gagal dengan 413 Request Entity Too Large pada access log nginx, sedangkan aplikasi hanya menampilkan error sinkronisasi umum. Server memiliki batasnya sendiri: ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB secara default bernilai 20 dan ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SYNC_SIZE_LIMIT_MB secara default bernilai 50. Jadi, tetapkan batas nginx di atas nilai yang berlaku untuk Anda.
Muat ulang dan uji:
sudo nginx -t && sudo systemctl reload nginx
curl -fsS -o /dev/null -w '%{http_code}\n' https://budget.example.com/First run: password dan file anggaran pertama
Buka https://budget.example.com di browser. Layar pertama meminta Anda menetapkan password server. Satu password ini melindungi seluruh server, jadi buat password acak yang panjang dan simpan di tempat yang dapat Anda temukan kembali, misalnya password manager Vaultwarden yang di-host sendiri. Anda tidak perlu membuat akun pengguna. Server Actual memang dirancang menggunakan satu password, jadi berbagi anggaran berarti berbagi password tersebut.
Selanjutnya, buat file anggaran. Actual menanyakan apakah enkripsi end-to-end ingin diaktifkan. Pilih ya agar server hanya menyimpan ciphertext. Ini merupakan pilihan yang tepat untuk data keuangan pada mesin sewaan. Namun, ada konsekuensi nyata: password enkripsi tidak pernah dikirim ke server. Jika Anda kehilangannya, file tersebut tidak dapat dipulihkan dan tidak ada fitur reset. Catat password itu sebelum melanjutkan dari layar tersebut.
Tetapkan saldo awal berdasarkan angka terkini dari bank Anda, bukan dengan mengimpor riwayat selama bertahun-tahun. Penganggaran berbasis amplop berjalan ke depan berdasarkan uang yang Anda miliki sekarang, sehingga tidak memiliki riwayat tidak menimbulkan masalah.
Memasukkan transaksi
Di sinilah kejujuran lebih penting daripada antusiasme, karena dukungan impor adalah alasan utama orang berhenti menggunakan aplikasi pengelolaan anggaran self-hosted.
Input manual adalah dasar dan selalu berfungsi. Untuk metode amplop, cara ini bisa dibilang merupakan inti metode tersebut, karena mengetikkan pembelian membuat Anda menyadarinya.
Impor file menangani sebagian besar transaksi. Actual dapat membaca CSV, QIF, OFX, dan QFX, dan setiap bank mengekspor setidaknya salah satu format tersebut. Impor setiap akun dari layar akun, petakan kolom satu kali, dan Actual akan mengingat tata letak tersebut untuk akun itu.
Sinkronisasi bank otomatis tersedia, tetapi memerlukan layanan pihak ketiga karena server tidak dapat berkomunikasi dengan bank secara mandiri. Actual mendukung SimpleFIN Bridge untuk bank di Amerika Utara, Enable Banking untuk Eropa, Akahu untuk Selandia Baru, dan Pluggy.ai untuk Brasil. GoCardless masih didukung, tetapi tidak menerima akun baru. Anda harus mendaftar sendiri ke penyedia layanan, membuat kredensial, lalu menambahkannya ke server. SimpleFIN Bridge mengenakan biaya 15 dolar AS per tahun untuk hingga 25 institusi per Juli 2026, sedangkan penyedia lainnya menerapkan harga yang berbeda.
Ada dua batasan yang perlu diterima sebelum Anda mengandalkan fitur ini. Kredensial API tersimpan di server dan tidak dilindungi enkripsi end-to-end karena server harus menggunakannya. Actual juga tidak melakukan polling: sinkronisasi dijalankan dengan menekan tombol, bukan sebagai tugas latar belakang.
Cadangan, karena hanya berupa file
Semua yang penting bagi Anda berada di bawah /opt/actual/data. Tidak ada langkah ekspor dan tidak ada database dump yang perlu dibuatkan skrip.
Satu hal yang perlu diperhatikan adalah SQLite. Menyalin account.sqlite saat server sedang menulis ke file tersebut dapat menangkap transaksi yang belum selesai. Anda baru akan mengetahuinya saat mencoba memulihkan cadangan. Hentikan container selama beberapa detik yang diperlukan untuk menyalin file:
cd /opt/actual
docker compose stop
restic -r sftp:backup@backup.example.com:/srv/restic backup /opt/actual/data
docker compose startJadwalkan proses tersebut dengan pendekatan pada cadangan restic di VPS, yang mencakup penyiapan repository, retensi, dan pengujian pemulihan. Jalankan pengujian pemulihan. Cadangan yang belum pernah dipulihkan hanyalah perkiraan.
Cadangan sisi klien bawaan Actual adalah hal yang terpisah dan juga perlu diketahui. Browser menyimpan salinan terbaru file anggaran, yang dapat diakses dari menu file. Fitur ini dapat menangani kasus "saya tidak sengaja menghapus kategori" tanpa menyentuh server sama sekali.
Memperbarui server
cd /opt/actual
docker compose pull
docker compose up --detachCompose membuat ulang container dari image baru dan memasang kembali volume yang sama, sehingga data tetap ada. Perbarui client juga. Versi server dan aplikasi sebaiknya tetap berdekatan. Client yang jauh lebih lama daripada server dapat menolak sinkronisasi dan menampilkan pesan ketidakcocokan versi. Buat cadangan sebelum melakukan lompatan versi mayor. Migrasi berjalan saat start pertama, dan tidak ada jalur downgrade. Actual dapat menangani tag latest yang berubah-ubah karena statusnya berupa direktori berisi file. Aplikasi yang menggunakan database sungguhan tidak memiliki toleransi yang sama. Panduan self-hosting Chatwoot menjelaskan tag yang dipatok dan dump sebelum upgrade yang diperlukan dalam praktik tersebut.
Yang rusak dan hal yang akan terlihat
Aplikasi terbuka, tetapi sinkronisasi tidak pernah selesai. Periksa access log nginx untuk 413. Nilai client_max_body_size terlalu rendah. 502 menunjukkan bahwa nginx aktif, tetapi container tidak aktif.
Opsi enkripsi tidak tersedia, atau aplikasi seluler menolak URL tersebut. Halaman tidak berada dalam secure context. Bilah alamat akan menampilkan http:// dengan alamat IP atau hostname yang bukan localhost. Perbaiki sertifikat, bukan mencari jalan keluar sementara.
Muncul pesan bahwa file anggaran tidak kompatibel dengan versi ini. Versi client dan server sudah tidak sama. Perbarui keduanya ke release yang sama, lalu reload.
Container restart terus-menerus. Baca docker compose logs actual. Permission error pada /data berarti direktori yang di-mount tidak dapat ditulisi oleh user container. Address-in-use error berarti ada proses lain yang sudah menggunakan port 5006 pada loopback.
Pemuatan pertama terasa lambat. Seluruh file anggaran diunduh ke browser saat Anda membukanya. Proses ini merupakan satu transfer besar, kemudian pembacaan lokal. Ini bukan masalah kapasitas server, dan menambah RAM tidak akan mengubahnya.
FAQ
Apakah Actual Budget memerlukan HTTPS agar dapat digunakan?
Ya, dalam praktiknya. Enkripsi end-to-end Actual menggunakan Web Crypto API pada browser. Browser hanya menyediakan API tersebut dalam konteks aman, yaitu https:// atau http://localhost. Jika diakses melalui HTTP biasa dari mesin lain, fitur tersebut tidak tersedia. Aplikasi seluler resmi juga menolak URL server HTTP biasa. Gunakan sertifikat Let's Encrypt pada hostname yang sebenarnya, atau sertifikat yang ditandatangani sendiri dengan ACTUAL_HTTPS_KEY dan ACTUAL_HTTPS_CERT jika Anda hanya menggunakan browser desktop.
Apakah Actual dapat mengimpor transaksi bank saya secara otomatis?
Hanya melalui layanan pihak ketiga yang Anda daftarkan sendiri: SimpleFIN Bridge di Amerika Utara, Enable Banking di Eropa, Akahu di Selandia Baru, atau Pluggy.ai di Brasil. GoCardless didukung, tetapi tidak menerima akun baru. Kredensial API tersebut tersimpan di server Anda dan tidak dilindungi oleh enkripsi end-to-end. Sinkronisasi juga dilakukan secara manual. Anda harus menekan tombol, dan tidak ada proses yang memeriksa pembaruan di latar belakang. Impor CSV, QIF, OFX, dan QFX sama sekali tidak memerlukan pihak ketiga.
Apa saja yang harus saya cadangkan?
Direktori data yang di-mount, yaitu /opt/actual/data dalam panduan ini. Direktori tersebut berisi server-files/account.sqlite yang menyimpan login dan sesi, serta user-files yang menyimpan file anggaran. Hentikan container sebelum menyalin data. Penyalinan database SQLite yang sedang digunakan dapat merekam penulisan yang belum selesai. Tidak ada data state lain pada server.
Apa yang terjadi jika saya kehilangan kata sandi enkripsi?
File tersebut tidak dapat dipulihkan. Kata sandi tidak pernah dikirim ke server. Inilah tujuan utama enkripsi end-to-end. Karena itu, tidak ada opsi reset maupun jalur dukungan untuk memulihkannya. Simpan kata sandi di password manager segera setelah membuat file, lalu simpan salinannya di lokasi yang tidak bergantung pada server yang sama.
Berapa banyak sumber daya server yang diperlukan Actual Budget?
Sangat sedikit. Container menyajikan aset dan file statis, sedangkan perhitungan anggaran dilakukan di browser. Satu vCPU bersama dengan RAM 1 GB dapat menjalankannya tanpa masalah. Direktori data untuk anggaran rumah tangga dengan riwayat beberapa tahun biasanya tetap berukuran puluhan megabita. Penggunaan disk terutama berasal dari backup dan container lain, bukan dari Actual. Jika Anda menyiapkan server yang juga harus menjalankan aplikasi yang lebih berat, server foto biasanya menjadi penentu kebutuhan minimum. Baca berapa banyak RAM yang sebenarnya diperlukan PhotoPrism dan Immich sebelum memilih paket.