SSD Nodes Learn Hosting plans →
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-10-28

استضافة Actual Budget على VPS خاص بك عبر Docker

ثبّت Actual Budget على VPS باستخدام Docker Compose، واضبط وحدة البيانات وHTTPS، ثم أنشئ أول ميزانية واستورد معاملاتك وأنشئ نسخاً احتياطية.

ما الذي ستبنيه

Actual Budget هو تطبيق مستضاف ذاتياً لإدارة الميزانية بنظام الأظرف، وهو الخيار المعتاد لمن يبحثون عن بديل لـ YNAB يمكن استضافته بأنفسهم. يتكوّن الخادم من حاوية واحدة، ووحدة تخزين بيانات واحدة، واسم HTTPS واحد. تعمل عليه كل الوظائف الأساسية للميزانية بسلاسة على أصغر VPS يمكنك استئجاره، لأن الخادم يخزّن الملفات ويزامنها في الغالب.

من المهم فهم البنية قبل كتابة أي أمر. الميزانية نفسها هي قاعدة بيانات SQLite موجودة داخل متصفحك وداخل كل تطبيق جوّال. أما الخادم الذي ستثبّته فهو نقطة نهاية للمزامنة؛ إذ يحتفظ بقائمة الحسابات، وملفات الميزانية، وسجل التغييرات الذي يتيح للهاتف والكمبيوتر المحمول الوصول إلى الحالة نفسها. لذلك يظل التطبيق يعمل عند توقف الخادم، كما أن فقدان الخادم لا يؤدي إلى فقدان ميزانيتك ما دام أحد العملاء لا يزال يحتفظ بنسخة منها.

لماذا يحتاج الخادم إلى HTTPS

يتطلب Actual استخدام HTTPS، وهذا ليس إجراءً شكلياً. يحتاج Actual إلى ميزة في المتصفح تُسمّى SharedArrayBuffer لكي يعمل أصلاً، ولا يفعّلها المتصفح إلا عندما تكون الصفحة معزولة عن المصادر الأخرى ضمن ما تسميه المواصفة سياقاً آمناً. السياق الآمن هو https:// أو http://localhost. حمّل التطبيق من http://203.0.113.10:5006 في متصفح على جهاز آخر، ولن يسلّم المتصفح هذه الميزة إلى الصفحة، ولذلك لا تُحمّل الميزانية. ولا تحصل الهواتف على استثناء. يذكر FAQ الخاص بـActual أن تطبيق iOS الرسمي قيد الاختبار التجريبي ويتصل بخادمك الخاص، وأنه لا يوجد تطبيق Android رسمي حتى الآن. لذلك تستخدم في معظم الهواتف تطبيق الويب نفسه، وتثبّته على الشاشة الرئيسية كتطبيق Progressive Web App، وينطبق عليه حكم السياق الآمن نفسه.

لذلك توجد إعدادات عملية اثنتان. ضع شهادة حقيقية أمام الحاوية على اسم حقيقي، وهذا ما يفعله هذا الدليل. أو امنح الخادم شهادة موقّعة ذاتياً باستخدام ACTUAL_HTTPS_KEY وACTUAL_HTTPS_CERT، كما يوثّق المشروع، واقبل ظهور تحذير المتصفح على كل جهاز. تستغرق الشهادة المجانية من Let's Encrypt خمس دقائق، لذا اختر الخيار الأول.

ثبّت Actual Budget باستخدام Docker Compose

ثبّت Docker أولاً إذا كان الخادم جديداً. إذا كانت صياغة ملف Compose جديدة عليك، يشرح دليل أساسيات Docker Compose لخادم 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

هناك 3 تفاصيل مهمة في هذا الملف.

الصورة هي actualbudget/actual-server:latest، وقد نشرها المشروع على Docker Hub وتتوفر نسخة معكوسة منها على ghcr.io/actualbudget/actual. توجد علامة latest-alpine للأجهزة منخفضة الطاقة.

تكتب الحاوية كل شيء ضمن /data. ستجد داخلها server-files، الذي يحتوي على account.sqlite مع بيانات تسجيل الدخول ورموز الجلسة، وuser-files، الذي يحتوي على ملفات الميزانية نفسها. اربط هذا المسار، وإلا فسيحذف docker compose pull ميزانيتك عند إعادة إنشاء الحاوية. يمكن لـACTUAL_DATA_DIR نقلها، لكن الإعداد الافتراضي مناسب.

يُنشر المنفذ على 127.0.0.1 فقط. يؤدي استخدام 5006:5006 مجرداً إلى نشر المنفذ على كل الواجهات، ويضيف Docker قواعده قبل قواعد ufw، لذلك سيصبح التطبيق متاحاً عبر الإنترنت حتى مع وجود جدار ناري يمنع كل الاتصالات. يشرح سبب تجاوز المنافذ التي ينشرها Docker لقواعد ufw هذه المفاجأة. يعني الربط مع loopback أن reverse proxy الموجود على الخادم نفسه فقط يستطيع الوصول إلى التطبيق.

شغّله:

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، فالسبب المعتاد هو مشكلة صلاحيات في volume المرتبط، وستظهر في السجل كسطر EACCES.

ضع شهادة واسم نطاق فعلياً أمام الخدمة

وجّه سجل A إلى VPS، budget.example.com، وانتظر حتى يُحلّ الاسم. ثم ثبّت nginx وأصدر الشهادة. يغطي دليل Certbot على Ubuntu 24.04 مع nginx الإصدار ومؤقت التجديد بالكامل.

كتلة الوكيل:

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 هو السطر الذي ينساه الناس. ترسل المزامنة اليومية تغييراتك فقط، لكن يُرفع ملف الميزانية بالكامل عند تسجيل ميزانية لأول مرة مع الخادم، وكذلك عند إعادة ضبط المزامنة. يضبط nginx حجم نص الطلب افتراضياً على 1 MB. لذلك، عندما يتجاوز الملف هذا الحجم، تفشل عمليات الرفع الكاملة وتظهر 413 Request Entity Too Large في سجل وصول nginx، بينما يعرض التطبيق خطأ مزامنة عاماً فقط. لدى الخادم حدود منفصلة خاصة به: القيمة الافتراضية لـ ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB هي 20، والقيمة الافتراضية لـ ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SYNC_SIZE_LIMIT_MB هي 50. لذلك اضبط حد nginx على قيمة أعلى من الحد المنطبق عليك.

أعد التحميل واختبر:

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 المستضاف ذاتياً. لا توجد حسابات مستخدمين لإنشائها تلقائياً: للخادم كلمة مرور واحدة، لذا تعني مشاركة الميزانية مشاركة كلمة المرور تلك. لا تصبح عمليات تسجيل الدخول المنفصلة ممكنة إلا عند ربط موفّر OpenID، إذ يدعم Actual إعدادات المستخدمين المتعددين.

بعد ذلك، أنشئ ملف ميزانية. يسألك Actual عما إذا كنت تريد تفعيل التشفير التام بين الطرفين. اختر نعم، وعندها لا يخزّن الخادم إلا النص المشفّر، وهذا هو الخيار الصحيح للبيانات المالية على جهاز مستأجر. لكن لذلك تكلفة فعلية: لا تصل كلمة مرور التشفير إلى الخادم، لذلك إذا فقدتها يضيع الملف ولا توجد إمكانية لإعادة تعيينها. دوّنها قبل النقر للانتقال من تلك الشاشة.

عيّن الأرصدة الافتتاحية بالاعتماد على الأرقام الحالية في مصرفك بدلاً من استيراد سجل يمتد لسنوات. تعمل الميزانية بطريقة المظاريف انطلاقاً من الأموال المتاحة لديك الآن، لذلك لا يسبب غياب السجل أي تكلفة.

إدخال المعاملات

هنا تكون الصراحة أهم من الحماس، لأن قصة الاستيراد هي السبب الرئيسي لعزوف الناس عن استخدام تطبيقات إعداد الميزانية المستضافة ذاتياً.

الإدخال اليدوي هو الأساس، وهو يعمل دائماً. وفي طريقة الأظرف، يمكن اعتباره جوهر الطريقة، لأن كتابة عملية شراء تجعلك تنتبه إليها.

يتولى استيراد الملفات الجزء الأكبر من العمل. يقرأ Actual ملفات CSV وQIF وOFX وQFX وCAMT، وكل بنك يصدّر واحداً منها على الأقل. استورد البيانات لكل حساب من شاشة الحساب، وعيّن الأعمدة عندما يكون الملف بصيغة CSV.

تتوفر مزامنة تلقائية مع البنوك، لكنها تحتاج إلى خدمة من جهة خارجية لأن الخادم لا يستطيع الاتصال بالبنوك بنفسه. يدعم Actual خدمات SimpleFIN Bridge للبنوك في أمريكا الشمالية، وEnable Banking لأوروبا، وAkahu لنيوزيلندا، وPluggy.ai للبرازيل. ما تزال GoCardless مدعومة، لكنها لا تقبل حسابات جديدة. عليك التسجيل لدى مزود الخدمة بنفسك، وإنشاء بيانات الاعتماد، ثم إضافتها إلى الخادم. تفرض SimpleFIN Bridge رسوماً قدرها 15 دولاراً أمريكياً سنوياً، إضافة إلى الضريبة، لما يصل إلى 25 مؤسسة اعتباراً من أكتوبر 2026، بينما تختلف أسعار الخدمات الأخرى.

هناك حدّان يجب تقبلهما قبل الاعتماد على هذه الميزة. تُخزَّن بيانات اعتماد API على الخادم، ولا تشملها التشفير من طرف إلى طرف، لأن الخادم يحتاج إلى استخدامها. ولا تتم أي مزامنة أثناء إغلاق Actual: تكون المزامنة التلقائية متوقفة افتراضياً، وبعد تفعيلها تعمل فقط ما دام التطبيق مفتوحاً، لذلك لا يستطلع الخادم بنوكك من تلقاء نفسه.

النسخ الاحتياطية، لأن البيانات مجرد ملفات

كل ما يهمك موجود ضمن /opt/actual/data. لا توجد خطوة تصدير، ولا تفريغ لقاعدة بيانات تحتاج إلى إنشاء برنامج نصي له.

المشكلة الوحيدة هي SQLite. قد يؤدي نسخ account.sqlite أثناء كتابة الخادم فيه إلى التقاط معاملة غير مكتملة، ولن تعرف ذلك حتى تحاول الاستعادة. أوقف الحاوية للثواني القليلة التي تستغرقها عملية النسخ:

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

جدول ذلك باستخدام الأسلوب الموضح في النسخ الاحتياطية باستخدام restic على VPS، فهو يغطي إعداد المستودع، والاحتفاظ بالنسخ، واختبار الاستعادة. نفّذ اختبار الاستعادة. فالنسخة الاحتياطية التي لم تستعدها من قبل ليست سوى تخمين.

النسخ الاحتياطية التلقائية الخاصة بتطبيق Actual أمر منفصل ويجدر بك معرفته، لكنها متاحة في تطبيق سطح المكتب فقط. يحتفظ التطبيق بما يصل إلى 10 نسخ حديثة من ملف الميزانية، ويمكن الوصول إليها من File > Load Backup. يغطي ذلك حالة «حذفت فئة عن طريق الخطأ» من دون لمس الخادم على الإطلاق. أما تطبيق الويب في المتصفح فلا يحتفظ بنسخ مماثلة، لذلك إذا كان الجميع في المنزل يستخدمون المتصفح، فالنسخة الاحتياطية للخادم المذكورة أعلاه هي النسخة الوحيدة المتاحة لديك.

تحديث الخادم

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

ينشئ Compose الحاوية مجدداً من الصورة الجديدة، ثم يعيد ربط وحدة التخزين نفسها، لذلك تبقى البيانات محفوظة. حدّث العملاء أيضاً. يتوقف العميل الأقدم من البيانات التي يتلقاها عن تطبيق التغييرات، ويعرض رسالة «يلزم التحديث». أنشئ نسخة احتياطية قبل الانتقال بين إصدارين رئيسيين، لأن عمليات الترحيل تُنفَّذ عند أول تشغيل، ولا يوجد مسار للرجوع إلى إصدار أقدم. يتعامل Actual مع وسم latest المتحرك بمرونة لأن حالته عبارة عن مجلد من الملفات، أما التطبيق الذي يستخدم قاعدة بيانات فعلية فلا يتعامل معه بهذه المرونة. يوضّح استضافة Chatwoot ذاتياً الوسوم المثبتة وتفريغ قاعدة البيانات قبل الترقية اللذين تتطلبهما هذه الممارسة.

ما الذي يتعطل، وما الذي ستراه

يُحمِّل التطبيق، لكن المزامنة لا تكتمل أبداً. افحص سجل الوصول في nginx بحثاً عن 413. هذا يعني أن قيمة client_max_body_size مضبوطة على مستوى منخفض جداً. أما 502 فيعني أن nginx لم يحصل على استجابة صالحة من upstream. غالباً ما يكون السبب أن الحاوية متوقفة أو لا تستمع على 5006، لذا افحص docker compose ps --all وسجل الحاوية قبل أي شيء آخر.

لن يُحمِّل التطبيق على جهاز آخر، أو يُبلغ بأن SharedArrayBuffer مفقود. الصفحة ليست ضمن سياق آمن. سيعرض شريط العنوان http:// مع عنوان IP أو اسم مضيف ليس localhost. أصلح الشهادة بدلاً من الالتفاف على المشكلة.

ظهور رسالة تفيد بأن ملف الميزانية غير متوافق مع هذا الإصدار. فُتح الملف في إصدار أحدث من Actual مقارنة بالعميل الذي تستخدمه الآن. حدّث العميل إلى ذلك الإصدار على الأقل، أو استعد نسخة احتياطية أُخذت قبل أن يلمس الإصدار الأحدث الملف، ثم أعد التحميل.

تُعاد تشغيل الحاوية في حلقة متكررة. اقرأ docker compose logs actual. يعني خطأ الصلاحيات في /data أن الدليل الموصول غير قابل للكتابة من مستخدم الحاوية. أما خطأ استخدام العنوان فيعني أن شيئاً آخر يستخدم 5006 على loopback.

يبدو التحميل الأول بطيئاً. يُنزَّل ملف الميزانية بالكامل إلى المتصفح عند فتحه. هذه عملية نقل كبيرة واحدة، ثم عمليات قراءة محلية. لا تتعلق المشكلة بحجم الخادم، ولن تؤدي إضافة 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 في البرازيل. يدعم Actual خدمة GoCardless، لكنها لا تقبل حسابات جديدة. تبقى بيانات اعتماد API هذه على خادمك، ولا تشملها التشفير من طرف إلى طرف. تكون المزامنة التلقائية متوقفة افتراضياً، وبعد تفعيلها تعمل فقط أثناء فتح Actual، لذلك لا يستعلم الخادم عن البيانات في الخلفية. لا يحتاج استيراد CSV وQIF وOFX وQFX وCAMT إلى أي جهة خارجية.

ما الذي يجب أن أنسخه احتياطياً تحديداً؟

دليل البيانات الموصول، وهو /opt/actual/data في هذا الدليل. يحتوي على server-files/account.sqlite، الذي يضم بيانات تسجيل الدخول والجلسات، وعلى user-files، الذي يضم ملفات الميزانية. أوقف الحاوية قبل النسخ، لأن نسخ قاعدة بيانات SQLite قيد التشغيل قد يلتقط عملية كتابة غير مكتملة. لا توجد بيانات حالة أخرى على الخادم.

ماذا يحدث إذا فقدت كلمة مرور التشفير؟

لا يمكن استرداد الملف. لا تصل كلمة المرور إلى الخادم، وهذا هو الهدف الأساسي من التشفير من طرف إلى طرف، لذلك لا توجد طريقة لإعادة تعيينها ولا مسار للحصول على الدعم. خزّنها في مدير كلمات مرور فور إنشاء الملف، واحتفظ بنسخة في مكان لا يعتمد على هذا الخادم نفسه.

ما مقدار موارد الخادم التي يحتاج إليها Actual Budget؟

يحتاج إلى موارد قليلة جداً. تقدّم الحاوية الملفات والأصول الثابتة، وتُجرى حسابات الميزانية في المتصفح. يشغّله vCPU مشترك واحد مع 1 GB من الذاكرة دون مشاكل، ويبقى دليل البيانات لميزانية منزلية تمتد لعدة سنوات من السجل ضمن عشرات الميغابايت. ينتج ضغط القرص عن النسخ الاحتياطية والحاويات الأخرى لديك، لا عن Actual. إذا كنت تجهّز خادماً يجب أن يشغّل خدمة أكثر استهلاكاً للموارد إلى جانبه، فعادةً ما يكون خادم الصور هو الذي يحدد الحد الأدنى، لذلك تحقّق من مقدار الذاكرة التي يحتاج إليها PhotoPrism وImmich فعلياً قبل اختيار الخطة. ينطبق المنطق نفسه على حزمة الوسائط: يحدد تحويل الترميز الخطة، بينما تستهلك واجهة أمامية في المتصفح مثل Halcyon، التي تحوّل مكتبة Jellyfin إلى متجر فيديو من حقبة 90s يمكن استكشافه موارد تقارب ما يستهلكه Actual.

هل كان هذا المقال مفيدًا؟