SSD Nodes Learn 8GB RAM — $66/বছর
নির্দেশিকা Matt Connorদ্বারা Matt Connor · আপডেট করা হয়েছে 2026-08-01

নিজের VPS-এ Actual Budget হোস্ট করার নিয়ম

Docker Compose দিয়ে VPS-এ Actual Budget চালান। data volume, browser-এর HTTPS প্রয়োজনীয়তা, প্রথম budget file, bank import এবং নির্ভরযোগ্য backup সম্পর্কে জানুন।

আপনি যা তৈরি করছেন

Actual Budget হলো নিজে হোস্ট করা একটি envelope budgeting অ্যাপ। নিজে হোস্ট করা যায় এমন YNAB বিকল্প খুঁজলে এটিই সাধারণত ব্যবহৃত হয়। সার্ভারটি একটি container, একটি data volume এবং একটি HTTPS নাম নিয়ে গঠিত। সাধারণ বাজেটের জন্য প্রয়োজনীয় সবকিছু সবচেয়ে ছোট VPS-এও স্বচ্ছন্দে চলে, কারণ সার্ভারটি মূলত ফাইল সংরক্ষণ ও sync করে।

কোনো কমান্ড টাইপ করার আগে architecture বোঝা দরকার। বাজেটটি নিজেই একটি SQLite database, যা আপনার browser এবং প্রতিটি mobile app-এর ভিতরে থাকে। আপনি যে server ইনস্টল করতে যাচ্ছেন, সেটি একটি sync endpoint। এটি account list, budget files এবং change log সংরক্ষণ করে। এই change log-এর মাধ্যমে phone এবং laptop একই অবস্থায় থাকে। তাই server বন্ধ থাকলেও app কাজ করে। একটি client-এ বাজেটের কপি থাকা অবস্থায় server হারালেও বাজেট হারায় না।

সার্ভারের HTTPS প্রয়োজন কেন

Actual HTTPS চায়, এবং এটি আনুষ্ঠানিকতার বিষয় নয়। ব্রাউজার Web Crypto API প্রকাশ করে কেবল সেই পরিবেশে, যাকে specification-এ secure context বলা হয়। Actual তার end-to-end encryption-এর জন্য এই interface ব্যবহার করে। একটি secure context হলো https:// অথবা http://localhost। অন্য কোনো মেশিনের ব্রাউজার থেকে http://203.0.113.10:5006-এ app লোড করলে ওই feature-গুলো থাকে না, কারণ ব্রাউজার সেগুলো page-এ দেয়নি। Official mobile build-গুলোও সাধারণ http:// server URL প্রত্যাখ্যান করে।

তাই কার্যকর setup দুটি। Container-এর সামনে একটি বাস্তব name-এ একটি বাস্তব certificate বসান—এই guide-এ সেটিই করা হয়েছে। অথবা project-এর documentation অনুযায়ী ACTUAL_HTTPS_KEY এবং ACTUAL_HTTPS_CERT ব্যবহার করে server-কে self-signed certificate দিন এবং প্রতিটি device-এ browser warning গ্রহণ করুন। Let's Encrypt-এর একটি free certificate পেতে পাঁচ মিনিট লাগে, তাই প্রথম option-টি নিন।

Docker Compose দিয়ে Actual Budget ইনস্টল করুন

সার্ভারটি নতুন হলে আগে Docker ইনস্টল করুন। Compose ফাইলের syntax আপনার কাছে নতুন হলে, নিচের ব্যবহৃত field-গুলোর ব্যাখ্যা VPS-এর জন্য Docker Compose-এর মৌলিক বিষয় গাইডে রয়েছে।

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

/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

এই ফাইলের 3টি বিষয় গুরুত্বপূর্ণ।

ইমেজটি হলো actualbudget/actual-server:latest। এটি project Docker Hub-এ প্রকাশ করে এবং ghcr.io/actualbudget/actual-এ mirror করে। কম ক্ষমতার মেশিনের জন্য latest-alpine tag রয়েছে।

Container-টি /data-এর অধীনে সবকিছু লেখে। এর মধ্যে server-files পাবেন। এতে আপনার login এবং session token-সহ account.sqlite থাকে। user-files-এ budget file-গুলো থাকে। এই path-টি mount করুন। না হলে পরের docker compose pull আপনার budget মুছে ফেলবে। ACTUAL_DATA_DIR এটি সরাতে পারে, তবে default-ই যথেষ্ট।

Port-টি কেবল 127.0.0.1-এ publish করা হয়েছে। সরাসরি 5006:5006 ব্যবহার করলে এটি প্রতিটি interface-এ publish হয়। Docker নিজস্ব rule-গুলো ufw-এর আগে লিখে, তাই deny-all firewall থাকলেও app-টি internet-এর জন্য উন্মুক্ত হয়ে যাবে। এই অপ্রত্যাশিত আচরণটি কেন Docker-এর published port ufw এড়িয়ে যায়-এ ব্যাখ্যা করা হয়েছে। loopback-এ bind করলে একই server-এর reverse proxy ছাড়া কেউ এতে পৌঁছাতে পারবে না।

এটি চালু করুন:

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

Server port 5006-এ listening করছে জানালে log স্থির হয়। DNS পরিবর্তন করার আগে localভাবে পরীক্ষা করুন:

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

200-এর অর্থ app অনুরোধ গ্রহণ করছে। curl: (7) Failed to connect-এর অর্থ container চলছে না। docker compose ps দেখাবে যে এটি exited হয়েছে। সাধারণত কারণ হলো mounted volume-এ permission সমস্যা। Log-এ এটি EACCES line হিসেবে দেখা যায়।

সামনে একটি সার্টিফিকেট এবং প্রকৃত নাম যুক্ত করুন

VPS-এর দিকে একটি A record নির্দেশ করুন, budget.example.com, এবং এটি resolve হওয়া পর্যন্ত অপেক্ষা করুন। এরপর nginx ইনস্টল করুন এবং সার্টিফিকেট ইস্যু করুন। Ubuntu 24.04-এ nginx সহ Certbot গাইডে ইস্যু করা এবং renewal timer সম্পর্কে সম্পূর্ণ নির্দেশনা রয়েছে।

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 হলো যে লাইনটি মানুষ প্রায়ই ভুলে যায়। সম্পূর্ণ sync হলে budget file-টি পুরোপুরি upload হয়। Nginx-এর ডিফল্ট request body সীমা 1 MB। তাই file-এর আকার এই সীমা ছাড়িয়ে গেলে sync ব্যর্থ হয়। nginx access log-এ 413 Request Entity Too Large দেখা যায়, কিন্তু app কেবল একটি সাধারণ sync error দেখায়। সার্ভারের নিজস্ব আলাদা সীমা রয়েছে: ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB-এর ডিফল্ট মান 20 এবং ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SYNC_SIZE_LIMIT_MB-এর ডিফল্ট মান 50। তাই আপনার ক্ষেত্রে প্রযোজ্য সীমাটির চেয়ে nginx limit বেশি নির্ধারণ করুন।

Reload করে পরীক্ষা করুন:

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

প্রথমবার চালানো: পাসওয়ার্ড এবং আপনার প্রথম বাজেট ফাইল

ব্রাউজারে https://budget.example.com খুলুন। প্রথম স্ক্রিনে সার্ভারের পাসওয়ার্ড সেট করতে বলা হবে। এই একটি পাসওয়ার্ড পুরো সার্ভারকে সুরক্ষিত রাখে। তাই একটি দীর্ঘ, এলোমেলো পাসওয়ার্ড তৈরি করুন এবং এমন কোথাও সংরক্ষণ করুন যেখানে পরে আবার খুঁজে পাবেন, যেমন নিজে হোস্ট করা Vaultwarden পাসওয়ার্ড ম্যানেজার। তৈরি করার মতো কোনো user account নেই। Actual-এর server নকশাগতভাবে single-password ভিত্তিক। তাই একটি budget শেয়ার করার অর্থ ওই পাসওয়ার্ড শেয়ার করা।

এরপর একটি budget file তৈরি করুন। Actual end-to-end encryption চালু করতে বলবে। Yes নির্বাচন করুন। এতে server-এ শুধু ciphertext সংরক্ষিত হবে, আর ভাড়া করা machine-এ financial data রাখার জন্য এটিই সঠিক পদ্ধতি। তবে এর একটি বাস্তব মূল্য আছে: encryption password কখনো server-এ পৌঁছায় না। তাই এটি হারালে file-টি হারিয়ে যাবে এবং reset করার কোনো ব্যবস্থা থাকবে না। ওই screen পার হওয়ার আগে পাসওয়ার্ডটি লিখে রাখুন।

বছরের পর বছর ধরে থাকা history import না করে আপনার bank-এর বর্তমান figures থেকে starting balances সেট করুন। Envelope budgeting আপনার হাতে থাকা বর্তমান অর্থ থেকে সামনে এগিয়ে কাজ করে। তাই পুরোনো history না থাকলে আপনার কোনো ক্ষতি হবে না।

লেনদেন ইমপোর্ট করা

এখানে উৎসাহের চেয়ে সততা বেশি গুরুত্বপূর্ণ। কারণ self-hosted budgeting থেকে মানুষ সরে যাওয়ার প্রধান কারণ হলো ইমপোর্ট ব্যবস্থার সীমাবদ্ধতা।

ম্যানুয়াল এন্ট্রি হলো প্রাথমিক পদ্ধতি এবং এটি সব সময় কাজ করে। envelope পদ্ধতিতে এটিই মূল বিষয় বলা যায়। কারণ কোনো কেনাকাটা টাইপ করলে আপনি সেটি লক্ষ্য করেন।

ফাইল ইমপোর্টে বেশিরভাগ লেনদেন সামলানো যায়। Actual CSV, QIF, OFX এবং QFX পড়তে পারে। প্রতিটি ব্যাংক অন্তত একটি ফরম্যাটে ডেটা export করে। account screen থেকে প্রতিটি account-এর জন্য ইমপোর্ট করুন। একবার কলামগুলো map করুন। এরপর Actual ওই account-এর জন্য সেই বিন্যাস মনে রাখবে।

স্বয়ংক্রিয় bank sync আছে। তবে এর জন্য third-party service প্রয়োজন। কারণ server নিজে থেকে ব্যাংকের সঙ্গে যোগাযোগ করতে পারে না। Actual North American ব্যাংকের জন্য SimpleFIN Bridge, Europe-এর জন্য Enable Banking, New Zealand-এর জন্য Akahu এবং Brazil-এর জন্য Pluggy.ai সমর্থন করে। GoCardless এখনও সমর্থিত, কিন্তু নতুন account গ্রহণ করছে না। আপনাকে নিজে provider-এর সঙ্গে sign up করতে হবে, credentials তৈরি করতে হবে এবং সেগুলো server-এ যোগ করতে হবে। July 2026 অনুযায়ী SimpleFIN Bridge সর্বোচ্চ 25টি institution-এর জন্য বছরে 15 US dollars চার্জ করে। অন্যগুলোর মূল্য নির্ধারণ পদ্ধতি আলাদা।

এটির ওপর নির্ভর করার আগে দুটি সীমাবদ্ধতা মেনে নিন। API credentials server-এ থাকে এবং end-to-end encryption-এর আওতায় পড়ে না। কারণ server-কে সেগুলো ব্যবহার করতে হয়। আর Actual স্বয়ংক্রিয়ভাবে poll করে না। Sync শুরু করতে আপনাকে একটি button চাপতে হয়। এটি background job নয়।

ব্যাকআপ, কারণ এখানে শুধু ফাইল

আপনার প্রয়োজনীয় সবকিছু /opt/actual/data-এর অধীনে রয়েছে। কোনো export ধাপ নেই এবং script করার মতো কোনো database dump নেই।

একমাত্র ঝুঁকি হলো SQLite। server এতে লিখতে থাকা অবস্থায় account.sqlite কপি করলে অসম্পূর্ণ transaction কপি হতে পারে। restore করার চেষ্টা না করা পর্যন্ত আপনি তা বুঝতে পারবেন না। কপি চলাকালীন কয়েক সেকেন্ডের জন্য container বন্ধ রাখুন:

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

VPS-এ restic backups-এ বর্ণিত পদ্ধতি ব্যবহার করে এটিকে schedule-এ রাখুন। সেখানে repository setup, retention এবং restore drill অন্তর্ভুক্ত রয়েছে। restore drill চালান। যে backup কখনো restore করা হয়নি, সেটি কেবল একটি অনুমান।

Actual-এর নিজস্ব client-side backup আলাদা বিষয়, এবং এটি জানা গুরুত্বপূর্ণ। browser budget file-এর সাম্প্রতিক কপিগুলো সংরক্ষণ করে। এগুলো file menu থেকে পাওয়া যায়। ফলে server-এ কোনো পরিবর্তন না করেই “ভুল করে কোনো category মুছে ফেলেছি” পরিস্থিতি সামলানো যায়।

সার্ভার আপডেট করা

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

Compose নতুন image থেকে container পুনরায় তৈরি করে এবং একই volume পুনরায় সংযুক্ত করে। তাই ডেটা অক্ষত থাকে। Client-গুলোকেও আপডেট করুন। Server এবং app-এর version কাছাকাছি থাকা উচিত। Server-এর তুলনায় অনেক পুরোনো client version mismatch বার্তা দেখিয়ে sync করতে অস্বীকার করতে পারে। Major version পরিবর্তনের আগে backup নিন। কারণ প্রথমবার চালুর সময় migration চলে এবং downgrade করার কোনো পথ নেই।

কী ব্যর্থ হয় এবং আপনি কী দেখবেন

অ্যাপ লোড হয়, কিন্তু sync কখনও শেষ হয় না। nginx access log-এ 413 পর্যবেক্ষণ করুন। এর অর্থ client_max_body_size মান খুব কম সেট করা হয়েছে। এর পরিবর্তে 502 দেখা গেলে nginx চালু আছে, কিন্তু container চালু নেই।

Encryption বিকল্পগুলি দেখা যাচ্ছে না, অথবা mobile app URL প্রত্যাখ্যান করছে। পৃষ্ঠাটি secure context-এ নেই। address bar-এ IP address অথবা localhost নয় এমন hostname-সহ http:// দেখা যাবে। বিকল্প ব্যবস্থা না করে certificate ঠিক করুন।

budget file এই version-এর সঙ্গে সামঞ্জস্যপূর্ণ নয়—এমন বার্তা দেখা যাচ্ছে। Client এবং server version আলাদা হয়ে গেছে। উভয়টিকে একই release-এ update করে reload করুন।

container বারবার restart হচ্ছে। docker compose logs actual পড়ুন। /data-এর ক্ষেত্রে permission error দেখালে mounted directory-টি container-এর user লিখতে পারছে না। address-in-use error দেখালে loopback-এ অন্য কোনো process ইতিমধ্যে 5006 ব্যবহার করছে।

প্রথমবার load হতে ধীর মনে হয়। আপনি file খুললে পুরো budget file browser-এ download হয়। প্রথমে একটি বড় transfer হয়, এরপর local read হয়। এটি server sizing-এর সমস্যা নয়, এবং RAM বাড়ালেও এর পরিবর্তন হবে না।

FAQ

কাজ করার জন্য Actual Budget-এর কি HTTPS দরকার?

বাস্তবে, দরকার। Actual-এর end-to-end encryption ব্রাউজারের Web Crypto API ব্যবহার করে। ব্রাউজারগুলো এটি কেবল secure context-এ চালু করে, অর্থাৎ https:// অথবা http://localhost-এ। অন্য কোনো মেশিন থেকে সাধারণ HTTP ব্যবহার করলে এই ফিচারগুলো উপলভ্য থাকে না। Official mobile apps-ও সাধারণ HTTP server URL প্রত্যাখ্যান করে। প্রকৃত hostname-এ Let's Encrypt certificate ব্যবহার করুন। অথবা কেবল desktop browser ব্যবহার করলে ACTUAL_HTTPS_KEY এবং ACTUAL_HTTPS_CERT সহ self-signed certificate ব্যবহার করুন।

Actual কি স্বয়ংক্রিয়ভাবে আমার ব্যাংক লেনদেন import করতে পারে?

শুধু এমন third-party service-এর মাধ্যমে, যেটিতে আপনাকে নিজে sign up করতে হবে: North America-তে SimpleFIN Bridge, Europe-এ Enable Banking, New Zealand-এ Akahu, অথবা Brazil-এ Pluggy.ai। GoCardless সমর্থিত, কিন্তু নতুন account গ্রহণ করছে না। এই API credentials আপনার server-এ থাকে এবং end-to-end encryption-এর আওতাভুক্ত নয়। Sync-ও manual, তাই আপনাকে একটি button চাপতে হবে এবং background-এ কোনো polling চলবে না। CSV, QIF, OFX এবং QFX import-এর জন্য কোনো third party দরকার নেই।

ঠিক কোন জিনিসের backup নিতে হবে?

Mounted data directory-এর, যা এই guide-এ /opt/actual/data। এতে login ও session-সহ server-files/account.sqlite এবং budget files-সহ user-files থাকে। Copy করার আগে container বন্ধ করুন, কারণ চলমান SQLite database copy করলে অসম্পূর্ণ write ধরা পড়তে পারে। Server-এর অন্য কোনো স্থানে state সংরক্ষিত থাকে না।

Encryption password হারালে কী হবে?

File পুনরুদ্ধার করা যাবে না। Password কখনো server-এ পৌঁছায় না। End-to-end encryption-এর মূল উদ্দেশ্য এটিই। তাই password reset বা support path কোনোটিই নেই। File তৈরি করার সঙ্গে সঙ্গেই password manager-এ এটি সংরক্ষণ করুন। একই server-এর ওপর নির্ভর করে না—এমন কোনো স্থানে একটি copy রাখুন।

Actual Budget-এর জন্য server-এর কতটা resource দরকার?

খুব কম। Container static assets ও files serve করে, আর budget calculation ব্রাউজারে হয়। 1 GB RAM-সহ একটি shared vCPU-তে এটি কোনো সমস্যা ছাড়াই চলে। কয়েক বছরের history-সহ একটি household budget-এর data directory সাধারণত কয়েক দশ megabyte-এর মধ্যে থাকে। Disk pressure Actual থেকে নয়, আপনার backup এবং অন্য containerগুলো থেকে আসে।