SSD Nodes Learn 8GB RAM — $66/سنة
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-08-01

كيفية استضافة Actual Budget على VPS باستخدام Docker

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

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

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

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

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

يتطلب Actual استخدام HTTPS، وهذا ليس إجراءً شكليًا. لا تتيح المتصفحات Web Crypto API، وهي الواجهة التي يستخدمها Actual للتشفير من طرف إلى طرف، إلا ضمن ما تسميه المواصفة سياقًا آمنًا. السياق الآمن هو https:// أو http://localhost. إذا حمّلت التطبيق من http://203.0.113.10:5006 في متصفح على جهاز آخر، فلن تتوفر هذه الميزات ببساطة، لأن المتصفح لم يسلّمها إلى الصفحة. كما ترفض إصدارات الهاتف المحمول الرسمية عنوان خادم http:// العادي.

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

شغّله:

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 أن الحاوي لا يعمل، بينما سيعرض docker compose ps أنه خرج. والسبب المعتاد هو مشكلة أذونات في وحدة التخزين المرتبطة، وتظهر في السجل كسطر 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 مستضاف ذاتيًا. لا توجد حسابات مستخدمين لإنشائها. صُمم خادم Actual ليعمل بكلمة مرور واحدة، لذلك تعني مشاركة ميزانية مشاركة كلمة المرور.

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

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

استيراد المعاملات

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

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

يتولى استيراد الملفات معظم العمل. يقرأ Actual ملفات CSV وQIF وOFX وQFX، وكل بنك يصدّر واحدًا منها على الأقل. استورد البيانات لكل حساب من شاشة الحساب، وعيّن الأعمدة مرة واحدة، وسيتذكر Actual هذا التخطيط للحساب.

تتوفر مزامنة تلقائية مع البنوك، لكنها تحتاج إلى خدمة تابعة لجهة خارجية، لأن الخادم لا يستطيع الاتصال بالبنوك بمفرده. يدعم Actual خدمات SimpleFIN Bridge للبنوك في أمريكا الشمالية، وEnable Banking لأوروبا، وAkahu لنيوزيلندا، وPluggy.ai للبرازيل. لا يزال GoCardless مدعومًا، لكنه لا يقبل حسابات جديدة. عليك إنشاء حساب لدى المزوّد بنفسك، وإنشاء بيانات الاعتماد، ثم إضافتها إلى الخادم. تفرض SimpleFIN Bridge رسومًا قدرها 15 دولارًا أمريكيًا سنويًا لما يصل إلى 25 مؤسسة، اعتبارًا من July 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 على جانب العميل أمرًا منفصلًا ويستحق المعرفة. يحتفظ المتصفح بنسخ حديثة من ملف الميزانية، ويمكن الوصول إليها من قائمة الملفات. ويتيح ذلك معالجة حالة «حذفت فئة بالخطأ» من دون لمس الخادم مطلقًا.

تحديث الخادم

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

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

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

يُحمّل التطبيق، لكن المزامنة لا تكتمل أبدًا. راقب سجل وصول nginx بحثًا عن 413. هذا يعني أن client_max_body_size مضبوط على قيمة منخفضة جدًا. أما 502 فيعني أن nginx يعمل وأن الحاوية لا تعمل.

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

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

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

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

FAQ

هل يحتاج Actual Budget إلى HTTPS لكي يعمل؟

نعم، عمليًا. تستخدم ميزة التشفير من طرف إلى طرف في Actual واجهة Web Crypto API في المتصفح. ولا تتيح المتصفحات هذه الواجهة إلا ضمن سياق آمن، أي https:// أو http://localhost. عند استخدام HTTP العادي من جهاز آخر، لا تتوفر هذه الميزات. كما ترفض تطبيقات الهاتف الرسمية عنوان URL لخادم HTTP عادي. استخدم شهادة Let's Encrypt على اسم مضيف حقيقي، أو شهادة موقعة ذاتيًا مع ACTUAL_HTTPS_KEY وACTUAL_HTTPS_CERT إذا كنت ستستخدم متصفح سطح مكتب فقط.

هل يستطيع Actual استيراد معاملات حسابي المصرفية تلقائيًا؟

فقط من خلال خدمة خارجية تسجل فيها بنفسك: SimpleFIN Bridge في أمريكا الشمالية، أو Enable Banking في أوروبا، أو Akahu في نيوزيلندا، أو Pluggy.ai في البرازيل. خدمة GoCardless مدعومة، لكنها لا تقبل حسابات جديدة. تُخزَّن بيانات اعتماد API هذه على خادمك، ولا يشملها التشفير من طرف إلى طرف. كما أن المزامنة يدوية، لذلك تضغط زرًا ولا تُجرى أي عملية استطلاع في الخلفية. ولا تحتاج عملية استيراد CSV وQIF وOFX وQFX إلى أي جهة خارجية.

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

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

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

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

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

يحتاج إلى موارد قليلة جدًا. تعرض الحاوية الملفات والأصول الثابتة، وتُجرى حسابات الميزانية في المتصفح. يكفيه vCPU مشترك واحد مع 1 GB من RAM ليعمل دون مشاكل. كما يبقى حجم دليل البيانات لميزانية منزلية تتضمن عدة سنوات من السجل في نطاق عشرات الميغابايت. ينتج ضغط القرص عن النسخ الاحتياطية والحاويات الأخرى، وليس عن Actual.