SSD Nodes Learn Hosting plans →
מדריכים Matt Connorמאת Matt Connor · עודכן 2026-10-30

איך להתקין Actual Budget על שרת VPS עם Docker

מדריך מלא להרצת Actual Budget בשרת פרטי. למדו איך להגדיר Docker Compose, למה HTTPS הוא חובה עבור Web Crypto API, איך לבצע גיבויים לקבצי ה-SQLite ואיך להגדיר סנכרון נתונים.

מה אתם בונים

Actual Budget הוא יישום לניהול תקציב בשיטת המעטפות שניתן לארח באופן עצמי, והוא מהווה את התשובה המקובלת עבור מי שמחפש חלופה ל-YNAB שניתן להריץ על שרת פרטי. השרת מורכב ממכולה (container) אחת, נפח נתונים (data volume) אחד ושם מתחם HTTPS אחד. כל מה שדרוש לניהול תקציב סטנדרטי פועל ללא קושי על ה-VPS הקטן ביותר שניתן לשכור, כיוון שהשרת משמש בעיקר לאחסון קבצים ולסנכרון שלהם.

כדאי להבין את הארכיטקטורה לפני שמתחילים להקליד פקודות. התקציב עצמו הוא מסד נתונים מסוג SQLite שנשמר בתוך הדפדפן שלכם ובתוך כל יישום מובייל. השרת שאתם עומדים להתקין משמש כנקודת קצה לסנכרון: הוא מחזיק את רשימת החשבונות, את קובצי התקציב ואת יומן השינויים המאפשר לטלפון ולמחשב הנייד להישאר מסונכרנים. זו הסיבה שהיישום ממשיך לעבוד גם כשהשרת מושבת, וזו הסיבה שאובדן השרת אינו גורר אובדן של התקציב שלכם, כל עוד לאחד הלקוחות (clients) נותר עותק של הנתונים.

מדוע השרת זקוק ל-HTTPS

Actual דורש HTTPS, ואין מדובר בפורמליות בלבד. Actual זקוק לתכונת דפדפן הנקראת SharedArrayBuffer כדי לפעול כלל, והדפדפנים מאפשרים אותה רק כאשר הדף מבודד במקורות שונים (cross-origin isolated) במה שהמפרט מכנה הקשר מאובטח (secure context). הקשר מאובטח הוא https:// או http://localhost. אם תטענו את היישום מ-http://203.0.113.10:5006 בדפדפן במחשב אחר, הדפדפן לעולם לא יעניק את התכונה הזו לדף, ולכן ה-budget לא ייטען. אין חריגים עבור טלפונים. ה-FAQ של Actual מציין כי אפליקציית iOS רשמית נמצאת בבדיקות בטא ומתחברת לשרת שלכם, וכי עדיין אין אפליקציית Android רשמית; לכן, ברוב הטלפונים תשתמשו באותו יישום אינטרנט, המותקן למסך הבית כ-Progressive Web App, וכלל ה-secure-context חל גם עליו.

לפיכך, קיימות שתי תצורות עבודה אפשריות. האחת היא הצבת תעודה אמיתית על שם מתחם אמיתי לפני המכולה, וזה מה שמדריך זה מבצע. השנייה היא מתן תעודה בחתימה עצמית לשרת באמצעות 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

ישנם שלושה פרטים בקובץ זה שחשוב לשים אליהם לב.

ה-image הוא actualbudget/actual-server:latest, אשר מפורסם על ידי הפרויקט ב-Docker Hub ומשוכפל ב-ghcr.io/actualbudget/actual. קיים תג latest-alpine עבור מכונות בעלות הספק נמוך.

המכולה כותבת את כל הנתונים תחת /data. בתוכה תמצאו את server-files, המכיל את account.sqlite עם פרטי ההתחברות ואסימוני ההפעלה שלכם, ואת user-files, המכיל את קובצי התקציב עצמם. עגנו (mount) נתיב זה, אחרת docker compose pull יגרום לאובדן התקציב שלכם. ניתן להשתמש ב-ACTUAL_DATA_DIR כדי להעביר אותו, אך ברירת המחדל תקינה.

הפורט מפורסם ב-127.0.0.1 בלבד. שימוש ב-5006:5006 בלבד יפרסם את השירות בכל ממשק רשת, ו-Docker כותב חוקים משלו לפני אלו של ufw, כך שהיישום יהיה חשוף לאינטרנט גם אם מוגדר firewall שחוסם הכל. הפתעה זו מוסברת ב-מדוע פורטים שמפורסמים על ידי 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, הסיבה הנפוצה היא בעיית הרשאות בנפח המעוגן (mounted volume), שניתן לראות כשורה EACCES בלוגים.

הגדרת תעודה ושם מתחם

הצביעו עם רשומת A אל ה-VPS, בכתובת budget.example.com, והמתינו לפתרון ה-DNS. לאחר מכן, התקינו את nginx והנפיקו את התעודה. המדריך Certbot ב-Ubuntu 24.04 עם nginx מכסה את תהליך ההנפקה ואת טיימר החידוש באופן מלא.

בלוק ה-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 היא השורה שאנשים נוטים לשכוח. סנכרון שוטף שולח רק את השינויים שלכם, אך קובץ התקציב המלא מועלה בעת רישום תקציב חדש מול השרת ובכל פעם שאתם מאפסים את הסנכרון. ברירת המחדל של 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 תשאל אם להפעיל הצפנה מקצה לקצה (end-to-end encryption). בחרו בחיוב; השרת יאחסן רק טקסט מוצפן, וזו הבחירה הנכונה עבור נתונים פיננסיים על שרת שכור. למחיר יש משמעות ממשית: סיסמת ההצפנה לעולם אינה מגיעה לשרת, לכן אם תאבדו אותה, הקובץ יאבד ולא ניתן יהיה לשחזר אותו. רשמו אותה לפני שתמשיכו מעבר למסך זה.

הגדירו את יתרות הפתיחה שלכם לפי הנתונים העדכניים מהבנק, במקום לייבא היסטוריה של שנים. שיטת התקצוב לפי מעטפות (envelope budgeting) פועלת קדימה מהכסף שברשותכם כעת, כך שאין כל חיסרון בהתחלה ללא היסטוריה.

ייבוא עסקאות

כאן הכנות חשובה יותר מהתלהבות, שכן תהליך הייבוא הוא הסיבה העיקרית לכך שאנשים נוטשים פתרונות תקציב בניהול עצמי.

הזנה ידנית היא בסיס העבודה והיא תמיד עובדת. בשיטת המעטפות, ניתן לטעון שזהו העיקר, שכן הקלדת רכישה היא הפעולה שגורמת לכם לשים לב אליה.

ייבוא קבצים מטפל בכמות גדולה של נתונים. Actual קורא קובצי CSV, QIF, OFX, QFX ו־CAMT, וכל בנק מייצא לפחות אחד מהפורמטים הללו. בצעו ייבוא לכל חשבון ממסך החשבון, ובצעו מיפוי של העמודות כאשר הקובץ הוא בפורמט CSV.

סנכרון בנקאי אוטומטי קיים, אך הוא דורש שירות צד-שלישי מכיוון שהשרת אינו יכול לתקשר עם בנקים באופן עצמאי. Actual תומך ב־SimpleFIN Bridge עבור בנקים בצפון אמריקה, ב־Enable Banking עבור אירופה, ב־Akahu עבור ניו זילנד וב־Pluggy.ai עבור ברזיל. השירות GoCardless עדיין נתמך אך אינו מקבל חשבונות חדשים. עליכם להירשם אצל הספק בעצמכם, להפיק אישורי גישה ולהוסיף אותם לשרת. נכון לאוקטובר 2026, SimpleFIN Bridge גובה 15 דולר ארה"ב לשנה בתוספת מס עבור עד 25 מוסדות, והאחרים מתמחרים זאת באופן שונה.

ישנן שתי מגבלות שיש לקבל לפני שמסתמכים על כך. אישורי ה־API נשמרים על השרת ואינם מוגנים על ידי הצפנה מקצה-לקצה (end-to-end encryption), כיוון שהשרת חייב להשתמש בהם. בנוסף, שום דבר לא מסתנכרן בזמן ש־Actual סגור: סנכרון אוטומטי כבוי כברירת מחדל, וברגע שמפעילים אותו הוא פועל רק בזמן שהיישום פתוח, כך שהשרת לעולם לא פונה לבנקים שלכם באופן עצמאי.

גיבויים, כיוון שמדובר בקבצים בלבד

כל המידע שחשוב לכם נמצא תחת /opt/actual/data. אין צורך בשלב ייצוא (export) או בהרצת סקריפט לגיבוי מסד נתונים.

המלכודת היחידה היא SQLite. העתקה של account.sqlite בזמן שהשרת כותב אליו עלולה לתעד טרנזקציה שלא הושלמה, ולא תדעו זאת עד שתנסו לשחזר. עצרו את ה-container למשך השניות הבודדות שההעתקה אורכת:

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

הגדירו זאת בלוח זמנים לפי הגישה המתוארת ב-גיבויי restic ב-VPS, המכסה את הגדרת ה-repository, שמירת גרסאות (retention) ותרגול שחזור. בצעו תרגול שחזור. גיבוי שמעולם לא שוחזר הוא בגדר ניחוש בלבד.

הגיבויים האוטומטיים המובנים של Actual הם עניין נפרד שכדאי להכיר, אך הם קיימים רק באפליקציית ה-desktop. היא שומרת עד 10 עותקים אחרונים של קובץ התקציב, הנגישים דרך File > Load Backup, מה שמאפשר לטפל במקרים של "מחקתי קטגוריה בטעות" מבלי לגעת בשרת כלל. אפליקציית ה-web בדפדפן אינה שומרת עותקים כאלה, לכן אם כל בני הבית משתמשים בדפדפן, הגיבוי השרתי שלעיל הוא היחיד שעומד לרשותכם.

עדכון השרת

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

הפקודה Compose יוצרת מחדש את ה-container מה-image החדש ומחברת אליו את אותו ה-volume, כך שהנתונים נשמרים. יש לעדכן גם את הלקוחות. לקוח שגרסתו ישנה מהנתונים שהוא מקבל יפסיק להחיל שינויים ויציג הודעת Update Required. בצעו גיבוי לפני קפיצת גרסה משמעותית, כיוון שתהליכי מיגרציה מופעלים בהפעלה הראשונה ולא ניתן לבצע שחזור לגרסה קודמת (downgrade). הכלי Actual סלחני כלפי תגית latest דינמית (floating) כיוון שהמצב שלו הוא ספריית קבצים, בעוד שיישום המשתמש בבסיס נתונים אמיתי אינו כזה, והמדריך אירוח עצמי של Chatwoot מפרט את השימוש בתגיות מקובעות (pinned) ואת ביצוע ה-dump לפני השדרוג הנדרש כנוהל עבודה תקין.

מה משתבש ומה תראה

היישום נטען אך הסנכרון לעולם לא מסתיים. בדוק את ה-access log של Nginx עבור 413. המשמעות היא ש-client_max_body_size מוגדר נמוך מדי. 502 לעומת זאת, מציין ש-Nginx לא קיבל תגובה תקינה מה-upstream. לרוב זה קורה כי המכולה עצרה או אינה מאזינה בפורט 5006, לכן בדוק את docker compose ps --all ואת הלוג של המכולה לפני כל דבר אחר.

היישום לא נטען במכשיר אחר, או מדווח ש-SharedArrayBuffer חסר. הדף אינו נמצא בהקשר מאובטח. שורת הכתובת תציג http:// עם כתובת IP או שם מארח שאינם localhost. תקן את התעודה במקום לנסות לעקוף את הבעיה.

הודעה שהקובץ התקציבי אינו תואם לגרסה זו. הקובץ נפתח בגרסה חדשה יותר של Actual מאשר הלקוח שבו אתה משתמש כעת. עדכן את הלקוח לפחות לגרסה זו, או שחזר גיבוי שנלקח לפני שהגרסה החדשה נגעה בקובץ, ולאחר מכן טען מחדש.

המכולה מתחילה מחדש בלולאה. קרא את docker compose logs actual. שגיאת הרשאות ב-/data משמעותה שהספרייה המעוגנת (mounted) אינה ניתנת לכתיבה על ידי המשתמש של המכולה. שגיאת "כתובת בשימוש" (address-in-use) מציינת שמשהו אחר כבר תופס את פורט 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 בברזיל. GoCardless נתמך אך אינו מקבל חשבונות חדשים. פרטי הגישה ל-API הללו נשמרים בשרת שלכם ואינם מוגנים בהצפנה מקצה-לקצה. סנכרון אוטומטי כבוי כברירת מחדל, ומרגע הפעלתו, הוא רץ רק בזמן ש-Actual פתוח, כך ששום תהליך אינו מבצע פניות ברקע בשרת. ייבוא קובצי CSV, QIF, OFX, QFX ו-CAMT אינו דורש צד-שלישי כלל.

מה בדיוק עלי לגבות?

את ספריית הנתונים המעוגנת (mounted), שהיא /opt/actual/data במדריך זה. היא מכילה את server-files/account.sqlite עם פרטי ההתחברות והסשנים, ואת user-files עם קובצי התקציב. עצרו את המכולה לפני ההעתקה, כיוון שהעתקת מסד נתונים מסוג SQLite בזמן פעולה עלולה לתפוס כתיבה חלקית. שום דבר אחר בשרת אינו מחזיק מצב (state).

מה קורה אם אאבד את סיסמת ההצפנה?

לא ניתן לשחזר את הקובץ. הסיסמה לעולם אינה מגיעה לשרת, וזו כל המטרה של הצפנה מקצה-לקצה, לכן אין אפשרות לאיפוס ואין נתיב תמיכה. שמרו אותה במנהל סיסמאות ברגע יצירת הקובץ, והחזיקו עותק במקום שאינו תלוי בשרת זה.

כמה משאבי שרת דורש Actual Budget?

מעט מאוד. המכולה מגישה נכסים סטטיים וקבצים, וחישובי התקציב מתבצעים בדפדפן. ליבת vCPU משותפת אחת עם 1 GB של RAM מריצה אותו ללא בעיות, וספריית הנתונים עבור תקציב משק בית עם היסטוריה של כמה שנים נשארת בטווח של עשרות מגה-בייטים. עומס על הדיסק נובע מהגיבויים שלכם ומהמכולות האחרות, לא מ-Actual. אם אתם מתכננים שרת שצריך להריץ במקביל יישומים תובעניים יותר, שרת תמונות הוא בדרך כלל מה שקובע את הרף, לכן בדקו כמה RAM באמת צריכים PhotoPrism ו-Immich לפני שתבחרו תוכנית. אותו היגיון תקף למערך מדיה: קידוד (transcoding) הוא שקובע את התוכנית, בעוד שחזית דפדפן כמו Halcyon, שהופכת ספריית Jellyfin לחנות וידאו נוסטלגית משנות ה-90 דורשת משאבים מעטים כמעט כמו Actual.

האם המאמר הזה היה מועיל?