SSD Nodes Learn Hosting plans →
गाइड Matt Connorलेखक: Matt Connor · अपडेट किया गया: 2026-11-06

Actual Budget को VPS पर कैसे host करें: पूरी गाइड

Actual Budget को Docker Compose के जरिए VPS पर सेटअप करना सीखें। HTTPS की अनिवार्यता, डेटा वॉल्यूम कॉन्फ़िगरेशन, बैंक इम्पोर्ट और सुरक्षित बैकअप लेने की पूरी प्रक्रिया यहाँ समझें।

आप क्या बना रहे हैं

Actual Budget एक self-hosted envelope budgeting app है। जब लोग YNAB का कोई ऐसा विकल्प ढूंढते हैं जिसे वे स्वयं host कर सकें, तो यह सबसे आम जवाब होता है। इसका सर्वर एक container, एक data volume और एक HTTPS नाम का उपयोग करता है। यह सर्वर मुख्य रूप से फाइलों को store और sync करता है।

कुछ भी टाइप करने से पहले इसकी architecture को समझना उपयोगी है। बजट स्वयं एक SQLite database है जो आपके browser और प्रत्येक mobile app के अंदर रहता है। जिस सर्वर को आप install करने जा रहे हैं, वह एक sync endpoint है: यह account list, budget files और वह change log रखता है जो phone और laptop के बीच सामंजस्य बनाए रखता है। यही कारण है कि सर्वर डाउन होने पर भी app काम करती रहती है, और यदि आपके पास किसी एक client में भी copy मौजूद है, तो सर्वर खो जाने पर भी आपका बजट सुरक्षित रहता है।

सर्वर को HTTPS की आवश्यकता क्यों है

Actual को चलने के लिए HTTPS की आवश्यकता होती है, और यह केवल औपचारिकता नहीं है। Actual को पूरी तरह से काम करने के लिए SharedArrayBuffer नामक एक ब्राउज़र फीचर की आवश्यकता होती है, और ब्राउज़र इसे केवल तभी सक्षम करते हैं जब पेज specification के अनुसार secure context में cross-origin isolated हो। एक secure context का अर्थ है https:// या http://localhost। यदि आप किसी अन्य मशीन पर ब्राउज़र में http://203.0.113.10:5006 से ऐप लोड करते हैं, तो ब्राउज़र पेज को वह फीचर नहीं देता है, इसलिए बजट लोड नहीं होता है। फोन के लिए भी कोई अपवाद नहीं है। Actual के FAQ में कहा गया है कि एक आधिकारिक iOS ऐप बीटा टेस्टिंग में है और वह आपके अपने सर्वर से कनेक्ट होता है, और अभी तक कोई आधिकारिक Android ऐप नहीं है। इसलिए, अधिकांश फोन पर आप उसी वेब ऐप का उपयोग करते हैं, जिसे Progressive Web App के रूप में होम स्क्रीन पर इंस्टॉल किया जाता है, और वही secure-context नियम वहां भी लागू होता है।

अतः, दो व्यावहारिक सेटअप हैं। कंटेनर के सामने एक वास्तविक नाम पर एक वास्तविक certificate लगाएँ, जो कि यह गाइड करती है। या फिर सर्वर को ACTUAL_HTTPS_KEY और ACTUAL_HTTPS_CERT के साथ एक self-signed certificate दें, जैसा कि प्रोजेक्ट के दस्तावेज़ों में बताया गया है, और हर डिवाइस पर ब्राउज़र की चेतावनी को स्वीकार करें। Let's Encrypt से एक मुफ्त certificate प्राप्त करने में पांच मिनट लगते हैं, इसलिए पहला विकल्प चुनें।

Docker Compose के साथ Actual Budget इंस्टॉल करें

यदि सर्वर नया है तो पहले Docker इंस्टॉल करें। यदि Compose फ़ाइल सिंटैक्स आपके लिए नया है, तो Docker Compose basics for a VPS गाइड में नीचे उपयोग किए गए फ़ील्ड्स की जानकारी दी गई है।

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

उस फ़ाइल में तीन विवरण महत्वपूर्ण हैं।

इमेज actualbudget/actual-server:latest है, जिसे प्रोजेक्ट द्वारा Docker Hub पर पब्लिश किया गया है और ghcr.io/actualbudget/actual पर मिरर किया गया है। कम पावर वाली मशीनों के लिए latest-alpine टैग उपलब्ध है।

कंटेनर सब कुछ /data के अंतर्गत लिखता है। इसके अंदर आपको server-files मिलता है, जिसमें आपके लॉगिन और सेशन टोकन के साथ account.sqlite होता है, और user-files होता है, जिसमें बजट फ़ाइलें होती हैं। उस पाथ को माउंट करें ताकि कंटेनर बदलने पर भी आपका बजट सुरक्षित रहे। ACTUAL_DATA_DIR इसे कहीं और ले जा सकता है, लेकिन डिफ़ॉल्ट पाथ ठीक है।

पोर्ट केवल 127.0.0.1 पर पब्लिश किया गया है। एक साधारण 5006:5006 हर इंटरफ़ेस पर पब्लिश हो जाता है, और Docker ufw से पहले अपने नियम लिख देता है, इसलिए deny-all फ़ायरवॉल होने पर भी ऐप इंटरनेट के लिए खुला रहेगा। यह समस्या why Docker published ports bypass ufw में समझाई गई है। लूपबैक पर बाइंड करने का मतलब है कि केवल उसी सर्वर पर मौजूद रिवर्स प्रॉक्सी ही इसे एक्सेस कर सकती है।

इसे स्टार्ट करें:

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

जब सर्वर यह रिपोर्ट कर दे कि वह पोर्ट 5006 पर लिसन कर रहा है, तो लॉग स्थिर हो जाता है। DNS को छूने से पहले इसे स्थानीय रूप से चेक करें:

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

200 का मतलब है कि ऐप चल रहा है। curl: (7) Failed to connect का मतलब है कि 127.0.0.1:5006 पर कनेक्शन स्वीकार नहीं किया गया। docker compose ps --all चलाएं, क्योंकि साधारण docker compose ps केवल चल रहे कंटेनरों को ही दिखाता है। यदि कंटेनर exited स्थिति में दिखता है, तो इसका सामान्य कारण माउंट किए गए वॉल्यूम पर परमिशन की समस्या होती है, जो लॉग में EACCES लाइन के रूप में दिखाई देती है।

एक सर्टिफिकेट और एक वास्तविक नाम का उपयोग करें

VPS पर एक A record पॉइंट करें, budget.example.com, और इसके resolve होने की प्रतीक्षा करें। फिर nginx इंस्टॉल करें और सर्टिफिकेट जारी करें। Ubuntu 24.04 पर nginx के साथ Certbot गाइड में जारी करने की प्रक्रिया और renewal timer की पूरी जानकारी दी गई है।

प्रॉक्सी ब्लॉक:

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 वह लाइन है जिसे लोग अक्सर भूल जाते हैं। Day-to-day sync केवल आपके बदलावों को भेजता है, लेकिन जब आप पहली बार सर्वर के साथ बजट रजिस्टर करते हैं या जब भी आप sync को reset करते हैं, तो पूरी बजट फाइल अपलोड की जाती है। Nginx का डिफ़ॉल्ट request body limit 1 MB है, इसलिए जैसे ही फाइल इससे बड़ी होती है, वे पूर्ण अपलोड विफल हो जाते हैं और nginx access log में 413 Request Entity Too Large दिखाई देता है, जबकि ऐप केवल एक सामान्य sync error दिखाता है। सर्वर की अपनी अलग सीमाएँ हैं: ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB डिफ़ॉल्ट रूप से 20 है और ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SYNC_SIZE_LIMIT_MB डिफ़ॉल्ट रूप से 50 है, इसलिए nginx की सीमा को उस मान से ऊपर सेट करें जो आप पर लागू होता है।

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 खोलें। पहली स्क्रीन आपसे सर्वर पासवर्ड सेट करने के लिए कहेगी। यह एक पासवर्ड पूरे सर्वर की सुरक्षा करता है, इसलिए एक लंबा रैंडम पासवर्ड जनरेट करें और उसे किसी सुरक्षित स्थान पर रखें, जैसे कि self-hosted Vaultwarden password manager। डिफ़ॉल्ट रूप से इसमें कोई यूज़र अकाउंट बनाने की आवश्यकता नहीं होती है: सर्वर का केवल एक पासवर्ड होता है, इसलिए बजट साझा करने का अर्थ है उस पासवर्ड को साझा करना। अलग-अलग लॉगिन तभी संभव हैं यदि आप किसी OpenID प्रदाता को कनेक्ट करते हैं, जिसे Actual मल्टी-यूज़र सेटअप के लिए सपोर्ट करता है।

इसके बाद एक बजट फ़ाइल बनाएँ। Settings खोलें और Encryption सेक्शन में Enable encryption पर क्लिक करें। इसे इनेबल करने पर सर्वर आपके बजट डेटा के लिए केवल ciphertext स्टोर करेगा, जो किराए की मशीन पर वित्तीय डेटा रखने के लिए सही तरीका है। इसकी एक कीमत है: एन्क्रिप्शन पासवर्ड कभी भी सर्वर तक नहीं पहुँचता है, इसलिए यदि आप इसे खो देते हैं और आपके पास बजट की कोई स्थानीय कॉपी नहीं है, तो फ़ाइल हमेशा के लिए नष्ट हो जाएगी। यदि कोई स्थानीय कॉपी मौजूद है, तो आप एन्क्रिप्शन की (key) को रीसेट कर सकते हैं और फिर से सिंक कर सकते हैं। उस स्क्रीन से आगे बढ़ने से पहले इसे कहीं लिख लें।

अपने शुरुआती बैलेंस को अपने बैंक के वर्तमान आंकड़ों के आधार पर सेट करें, न कि वर्षों के इतिहास को इम्पोर्ट करके। लिफाफा बजटिंग (Envelope budgeting) आपके पास मौजूद वर्तमान धन से आगे की ओर काम करती है, इसलिए इतिहास खाली होने से आपको कोई नुकसान नहीं होता है।

ट्रांजैक्शन को इम्पोर्ट करना

यहाँ उत्साह से अधिक ईमानदारी मायने रखती है, क्योंकि इम्पोर्ट की प्रक्रिया ही मुख्य कारण है कि लोग self-hosted बजटिंग का उपयोग करना छोड़ देते हैं।

मैन्युअल एंट्री आधारभूत तरीका है और यह हमेशा काम करता है। लिफाफा पद्धति (envelope method) के लिए यह तर्कसंगत रूप से महत्वपूर्ण है, क्योंकि खरीदारी को टाइप करने से ही आप उसके प्रति जागरूक होते हैं।

फाइल इम्पोर्ट थोक डेटा को संभालने के लिए है। Actual CSV, QIF, OFX, QFX और CAMT को पढ़ सकता है। अकाउंट स्क्रीन से प्रति अकाउंट इम्पोर्ट करें, और जब फाइल CSV हो तो कॉलम को मैप करें।

ऑटोमैटिक बैंक सिंक की सुविधा उपलब्ध है, और इसके लिए थर्ड-पार्टी सर्विस की आवश्यकता होती है क्योंकि सर्वर अपने आप बैंकों से बात नहीं कर सकता। Actual उत्तरी अमेरिकी बैंकों के लिए SimpleFIN Bridge, यूरोप के लिए Enable Banking, न्यूजीलैंड के लिए Akahu और ब्राजील के लिए Pluggy.ai का समर्थन करता है। GoCardless अभी भी समर्थित है लेकिन नए अकाउंट स्वीकार नहीं कर रहा है। आप स्वयं प्रदाता के साथ साइन अप करें, क्रेडेंशियल्स जनरेट करें, और उन्हें सर्वर में जोड़ें। अक्टूबर 2026 तक, SimpleFIN Bridge 25 संस्थानों तक के लिए प्रति वर्ष 15 US डॉलर प्लस टैक्स शुल्क लेता है, और अन्य की कीमत अलग-अलग है।

इस पर निर्भर होने से पहले दो सीमाओं को स्वीकार करें। API क्रेडेंशियल्स सर्वर पर रहते हैं और end-to-end encryption द्वारा सुरक्षित नहीं होते हैं, क्योंकि सर्वर को उनका उपयोग करना पड़ता है। और जब Actual बंद होता है तो कुछ भी सिंक नहीं होता है: ऑटोमैटिक सिंकिंग डिफ़ॉल्ट रूप से बंद रहती है, और एक बार जब आप इसे चालू कर देते हैं तो यह केवल तभी चलती है जब ऐप खुला हो, इसलिए सर्वर कभी भी अपने आप आपके बैंकों को पोल (poll) नहीं करता है।

Backups, क्योंकि यह केवल files हैं

आपकी सभी महत्वपूर्ण जानकारी /opt/actual/data के अंतर्गत है। इसमें कोई export step या script करने के लिए database dump की आवश्यकता नहीं है।

एकमात्र समस्या SQLite है। यदि आप server द्वारा write करते समय account.sqlite को copy करते हैं, तो यह एक अधूरा transaction capture कर सकता है, और आपको इसका पता तब तक नहीं चलेगा जब तक आप restore करने का प्रयास नहीं करेंगे। copy करने के दौरान कुछ seconds के लिए container को stop करें:

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

इसे restic backups on a VPS में बताए गए तरीके के साथ schedule करें, जिसमें repository setup, retention और restore drill शामिल हैं। Restore drill को चलाकर देखें। जिस backup को आपने कभी restore नहीं किया है, वह केवल एक अनुमान है।

Actual के अपने automatic backups एक अलग विषय हैं और इनके बारे में जानना उपयोगी है, लेकिन ये केवल desktop app में मौजूद होते हैं। यह budget file की 10 हालिया copies रखता है, जिन्हें File > Load Backup से access किया जा सकता है। यह server को छुए बिना "मैंने गलती से category delete कर दी" जैसी समस्याओं को हल करता है। Browser में चलने वाला web app ऐसी कोई copy नहीं रखता है, इसलिए यदि घर में सभी browser का उपयोग करते हैं, तो ऊपर बताए गए server backup को schedule करें। आप Settings > Export data से manual budget backup भी save कर सकते हैं।

सर्वर को अपडेट करना

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

Compose नई image से container को फिर से बनाता है और उसी volume को reattach करता है, इसलिए डेटा सुरक्षित रहता है। clients को भी अपडेट करें। यदि कोई client प्राप्त होने वाले डेटा से पुराना है, तो वह बदलाव लागू करना बंद कर देता है और Update Required संदेश दिखाता है। अपडेट करने से पहले backup लें, क्योंकि नए version में खोली गई budget फाइल पुराने client के साथ असंगत (incompatible) हो सकती है। Actual आमतौर पर floating latest tag का सुझाव देता है, लेकिन यह अभी भी SQLite databases का उपयोग करता है, और self-hosting Chatwoot में उन pinned tags और pre-upgrade dump के बारे में बताया गया है जिनकी आवश्यकता होती है।

क्या खराब होता है और आपको क्या दिखाई देगा

ऐप लोड होता है लेकिन सिंक कभी पूरा नहीं होता। 413 के लिए nginx एक्सेस लॉग की जाँच करें। इसका मतलब है कि client_max_body_size बहुत कम सेट है। 502 का मतलब है कि nginx को अपस्ट्रीम से कोई उपयोगी रिस्पॉन्स नहीं मिला। अक्सर ऐसा इसलिए होता है क्योंकि कंटेनर बंद है या 5006 पर लिसन नहीं कर रहा है, इसलिए किसी भी अन्य चीज़ से पहले docker compose ps --all और कंटेनर लॉग की जाँच करें।

ऐप किसी अन्य डिवाइस पर लोड नहीं होगा, या रिपोर्ट करेगा कि SharedArrayBuffer गायब है। जाँचें कि पेज HTTPS का उपयोग करता है और Actual से क्रॉस-ऑरिजिन आइसोलेशन हेडर प्राप्त करता है। यदि एड्रेस बार में http:// के साथ एक IP एड्रेस या होस्टनेम दिखाई देता है जो localhost नहीं है, तो इसे बायपास करने के बजाय सर्टिफिकेट को ठीक करें।

एक संदेश कि बजट फ़ाइल इस वर्ज़न के साथ संगत नहीं है। फ़ाइल को आपके द्वारा वर्तमान में उपयोग किए जा रहे क्लाइंट की तुलना में Actual के नए वर्ज़न में खोला गया है। क्लाइंट को कम से कम उस वर्ज़न तक अपडेट करें, या नए वर्ज़न द्वारा फ़ाइल को छूने से पहले लिए गए बैकअप को रिस्टोर करें, फिर रीलोड करें।

कंटेनर लूप में रीस्टार्ट होता है। docker compose logs actual पढ़ें। /data पर परमिशन एरर का मतलब है कि माउंट की गई डायरेक्टरी कंटेनर के यूजर द्वारा राइट करने योग्य नहीं है। एड्रेस-इन-यूज़ एरर का मतलब है कि लूपबैक पर 5006 को किसी और चीज़ ने पहले ही होल्ड कर रखा है।

पहली बार लोड होने में धीमा महसूस होता है। जब आप इसे पहली बार किसी डिवाइस पर खोलते हैं तो पूरी बजट फ़ाइल ब्राउज़र में डाउनलोड हो जाती है। यह एक बड़ा ट्रांसफर है, उसके बाद लोकल रीड्स होते हैं। यह सर्वर साइजिंग की समस्या नहीं है, और RAM जोड़ने से इसमें कोई बदलाव नहीं आएगा।

FAQ

क्या Actual Budget को काम करने के लिए HTTPS की आवश्यकता है?

हाँ, व्यावहारिक रूप से। Actual को चलने के लिए ब्राउज़र के SharedArrayBuffer फीचर की आवश्यकता होती है, और ब्राउज़र इसे केवल सुरक्षित संदर्भ में ही सक्षम करते हैं, जिसका अर्थ है https:// या http://localhost। किसी अन्य मशीन से सादे HTTP पर ऐप लोड नहीं होगा। एक आधिकारिक iOS ऐप बीटा टेस्टिंग में है और अभी तक कोई आधिकारिक Android ऐप नहीं है, इसलिए अधिकांश फोन उसी वेब ऐप का उपयोग करते हैं और उसी नियम का पालन करते हैं। (FAQ) एक वास्तविक होस्टनाम पर Let's Encrypt सर्टिफिकेट का उपयोग करें, या यदि आप हर डिवाइस पर सर्टिफिकेट चेतावनी के साथ काम चला सकते हैं, तो ACTUAL_HTTPS_KEY और ACTUAL_HTTPS_CERT के साथ सेल्फ-साइन्ड सर्टिफिकेट का उपयोग करें।

क्या Actual मेरे बैंक ट्रांजेक्शन को स्वचालित रूप से इम्पोर्ट कर सकता है?

केवल एक थर्ड-पार्टी सर्विस के माध्यम से जिसके लिए आप स्वयं साइन अप करते हैं: उत्तरी अमेरिका में SimpleFIN Bridge, यूरोप में Enable Banking, न्यूजीलैंड में Akahu, या ब्राजील में Pluggy.ai। GoCardless समर्थित है लेकिन नए अकाउंट स्वीकार नहीं कर रहा है। वे API क्रेडेंशियल्स आपके सर्वर पर रहते हैं और एंड-टू-एंड एन्क्रिप्शन के अंतर्गत नहीं आते हैं। स्वचालित सिंकिंग डिफ़ॉल्ट रूप से बंद रहती है और, एक बार सक्षम होने पर, केवल तभी चलती है जब Actual खुला हो, इसलिए सर्वर पर बैकग्राउंड में कुछ भी पोल नहीं होता है। CSV, QIF, OFX, QFX और CAMT इम्पोर्ट के लिए किसी थर्ड-पार्टी की आवश्यकता नहीं होती है।

मुझे वास्तव में किसका बैकअप लेना होगा?

माउंट की गई डेटा डायरेक्टरी का, जो इस गाइड में /opt/actual/data है। इसमें लॉगिन और सेशन के साथ server-files/account.sqlite, और बजट फाइलों के साथ user-files शामिल हैं। कॉपी करने से पहले कंटेनर को रोक दें, क्योंकि लाइव SQLite डेटाबेस को कॉपी करने से अधूरा राइट कैप्चर हो सकता है। सर्वर पर अन्य कुछ भी स्टेट होल्ड नहीं करता है।

यदि मैं एन्क्रिप्शन पासवर्ड खो दूँ तो क्या होगा?

यदि आपके पास अभी भी बजट की एक लोकल कॉपी है, तो आप एन्क्रिप्शन की को रीसेट कर सकते हैं और फिर से सिंक कर सकते हैं। यदि आपने पासवर्ड और हर लोकल कॉपी दोनों खो दिए हैं, तो एन्क्रिप्टेड फाइल को रिकवर नहीं किया जा सकता है। फाइल बनाते ही इसे पासवर्ड मैनेजर में स्टोर करें, और एक कॉपी ऐसी जगह रखें जो इसी सर्वर पर निर्भर न हो।

Actual Budget को कितने सर्वर की आवश्यकता है?

बहुत कम। कंटेनर स्टेटिक एसेट्स और फाइलों को सर्व करता है, और बजट की गणना ब्राउज़र में होती है। डिस्क का दबाव आपके बैकअप और अन्य कंटेनरों से आता है, Actual से नहीं। यदि आप एक ऐसे बॉक्स का आकार निर्धारित कर रहे हैं जिसे इसके साथ कुछ अधिक भारी चलाना है, तो फोटो सर्वर आमतौर पर न्यूनतम आवश्यकता तय करता है, इसलिए PhotoPrism और Immich को वास्तव में कितनी RAM चाहिए यह देखने के बाद ही कोई प्लान चुनें। यही तर्क मीडिया स्टैक पर भी लागू होता है: ट्रांसकोडिंग प्लान तय करती है, जबकि Halcyon, जो Jellyfin लाइब्रेरी को 90 के दशक के वीडियो स्टोर में बदल देता है जैसा ब्राउज़र फ्रंट एंड, Actual जितना ही कम संसाधन लेता है।

क्या यह लेख उपयोगी था?