אירוח עצמי של Supabase על שרת VPS באמצעות Docker
למדו כיצד להריץ את Supabase על שרת עצמאי. המדריך מפרט אילו secrets חובה להחליף בקובץ .env, דרישות זיכרון RAM מינימליות, ניהול גיבויים ועדכון בטוח של 11 המכולות.
מה אתם בונים
אירוח עצמי של Supabase משמעו הרצת ה-stack הרשמי של Docker Compose על השרת שלכם: Postgres, ממשק REST API לפניו, שירות אימות (auth), אחסון קבצים, שירות WebSocket בזמן אמת, ולוח הבקרה Studio. אתם משכפלים מאגר אחד, עורכים קובץ .env אחד, ומפעילים אחת-עשרה מכולות שמתנהגות יחד כפרויקט Supabase בשליטתכם.
ההתקנה קצרה. החלק שמשתבש הוא קובץ ה-.env. הוא מגיע עם secrets לדוגמה שפורסמו במאגר, ו-stack שמופעל עם ברירות מחדל אלו חשוף לכל מי שימצא אותו. מדריך זה מכסה את ה-secrets שעליכם להחליף, את תפקידו של כל שירות, את כמות הזיכרון שה-stack באמת דורש, וכיצד לעדכן אותו מבלי למחוק את מסד הנתונים שלכם.
אם Docker Compose חדש לכם, קראו תחילה את יסודות Docker Compose ב-VPS. כל מה שמופיע להלן מניח ש-docker compose version כבר מציג גרסה.
מה כולל ה־stack בפועל
Supabase אינו תוכנה אחת. קובץ ה-Compose מפעיל קבוצה של שירותים נפרדים על רשת אחת, והבנה של תפקיד כל אחד מהם הופכת רשימה ארוכה של שמות מכולות למערכת שניתן לבצע בה ניפוי שגיאות.
dbהוא PostgreSQL עם התוספים של Supabase טעונים. כל שירות אחר מתקשר מולו. אם מכולה זו אינה תקינה, כל השאר יכשלו גם הם.api-gwהוא ה-API gateway. מאז גרסת אוגוסט 2026 הוא מריץ Envoy; לפני כן זה היה שירות בשםkong, ו-Kong עדיין זמין כאפשרות לבחירה (opt-in). הוא מאזין בפורט 8000 ומנתב את/rest/v1/,/auth/v1/ו-/storage/v1/ל-backend המתאים. זו המכולה היחידה שצריך לחשוף החוצה.restהוא PostgREST. הוא קורא את ה-schema של Postgres ומגיש אותו כ-REST API, כך שטבלה חדשה הופכת ל-endpoint חדש ללא צורך בכתיבת קוד.authהוא GoTrue. הוא מנפיק את ה-JSON web tokens (JWT) שמזהים את המשתמשים שלכם.storageו-imgproxyמטפלים בהעלאות קבצים ובשינוי גודל תמונות.realtimeמזרים שינויים במסד הנתונים דרך websockets.studioו-metaהם ה-dashboard וה-admin API שמאחוריו.functionsהוא ה-edge runtime מבוסס Deno, ו-supavisorהוא ה-connection pooler של Postgres.
יומנים וניתוח נתונים (Logflare יחד עם vector) יצאו מקובץ ה-Compose המוגדר כברירת מחדל ביוני 2026. כעת הם נמצאים בקובץ override אופציונלי שניתן להפעיל באמצעות sh run.sh config add logs, באותה שיטת שכבות של קובצי Compose המתוארת ב-הרצת stack אחד מכמה קובצי Compose.
רשימה זו היא הסיבה לכך שמספרי המשאבים להלן הם כפי שהם. אתם לא מריצים רק מסד נתונים. אתם מריצים מסד נתונים פלוס עשרה שירותי תמיכה.
תכנון גודל: הקצו 8 GB של RAM
נכון ליולי 2026, ה-stack צורך במצב המתנה כ-2.5 עד 3 GB של זיכרון פיזי בהתקנה נקייה, עוד לפני הוספת נתונים או תעבורה. במדידה זו, שירות ה-analytics ותהליך ה-Node.js של ה-Studio היו הצרכנים הגדולים ביותר. מאחר ש-analytics אינו חלק מה-stack המוגדר כברירת מחדל, הוא יצרוך זיכרון רק אם תפעילו את דריסת הלוגים. שרת עם 2 GB יצליח להעלות את ה-containers, אך אחד מהם יופסק על ידי ה-kernel באמצעות ה-OOM killer; התסמין לכך הוא container שתקוע במצב אתחול חוזר עם exit code 137. תיעוד האירוח העצמי של Supabase, כפי שנבדק באוקטובר 2026, מציין 4 GB של RAM, 2 ליבות CPU ו-40 GB של SSD כדרישות מינימום, ו-8 GB, 4 ליבות ו-80 GB כדרישות מומלצות.
הקצו 8 GB של RAM ו-4 vCPU לכל שירות שאתם מסתמכים עליו. 4 GB יספיקו לסביבת פיתוח אישית, בתנאי שתקבלו בהבנה ששאילתה כבדה והרצת Studio במקביל יגרמו לאיטיות. גם לנפח הדיסק יש חשיבות, שכן Postgres, נפח האחסון (storage volume) ונתוני הלוגים (אם הופעלו) נמצאים כולם תחת תיקיית הפרויקט. התחילו עם 40 GB ועקבו אחר הצריכה. כדאי לסגל הרגל של ספירת השירותים לפני בחירת תוכנית אירוח לכל פרויקט שאתם מארחים בעצמכם, שכן ל-PhotoPrism ו-Immich יש דרישות סף משמעותיות ל-RAM: דף ה-quick start של Immich, כפי שנבדק באוקטובר 2026, דורש לפחות 6 GB של RAM ו-2 ליבות CPU. אם מדובר בשרת חזק מדי עבור הצרכים הנוכחיים של הפרויקט שלכם, השוו זאת ל-מה שתוכנית הענן החינמית של Supabase כוללת בפועל, שכן אפליקציה קטנה שאינה חורגת מ-500 MB ואינה נשארת במצב המתנה במשך שבוע עשויה לרוץ שם ללא עלות.
התקנה: שכפול המאגר הרשמי
הנתיב הנתמך מעתיק את הספרייה docker מתוך המאגר הראשי אל ספריית פרויקט משלכם. הפרדה זו חשובה, כיוון שהיא מבטיחה שפעולת git pull עתידית לא תדרוס את ה-.env שלכם.
git clone --depth 1 https://github.com/supabase/supabase
mkdir supabase-project
cp -rf supabase/docker/* supabase-project
cp supabase/docker/.env.example supabase-project/.env
cd supabase-project
docker compose pullהפקודה docker compose pull מורידה כמה גיגה-בייטים של תמונות. התהליך אמור להסתיים כאשר כל שירות מסומן כ-Pulled. שגיאת manifest unknown בשלב זה משמעותה שתג התמונה המקובע הוסר במקור, והפתרון הוא למשוך עותק חדש יותר של המאגר במקום לערוך תגים באופן ידני.
הסודות שעליך לשנות לפני ההפעלה הראשונה
בצע זאת לפני הפעלת ה-stack, ולא לאחר מכן. חלק מהערכים הללו נכתבים לתוך הנתונים בעת ה-boot הראשון, לכן שינוי שלהם בשלב מאוחר יותר מחייב איפוס של מסד הנתונים.
המאגר כולל מחולל שמייצר כל ערך בצורה תקינה, כולל שני מפתחות ה-API שחייבים להיות חתומים באמצעות ה-JWT secret החדש שלך.
sh utils/generate-keys.sh --update-envהסקריפט כותב ערכים חדשים עבור JWT_SECRET, ANON_KEY, SERVICE_ROLE_KEY, SECRET_KEY_BASE, REALTIME_DB_ENC_KEY, VAULT_ENC_KEY, PG_META_CRYPTO_KEY, אסימוני ה-Logflare, מפתחות פרוטוקול ה-S3 ו-MINIO_ROOT_PASSWORD לתוך .env. נכון לאוקטובר 2026, הוא כותב גם ערכים אקראיים עבור POSTGRES_PASSWORD ו-DASHBOARD_PASSWORD. הוא זקוק ל-openssl, שקיים בכל תמונת Ubuntu סטנדרטית. מכיוון שהוא כעת משכתב גם את סיסמת מסד הנתונים, הרץ אותו עם --update-env רק לפני ההפעלה הראשונה, ולעולם לא מול stack שכבר מכיל נתונים.
עדיין כדאי לבדוק ידנית שני ערכים ב-.env:
POSTGRES_PASSWORD. הסקריפט ממלא אותו בערך hex אקראי, וזה בטוח. אם תחליף אותו בערך משלך, השתמש באותיות ובספרות בלבד. סימני פיסוק כאן משבשים את מחרוזות החיבור ששירותים שונים בונים על ידי שרשור מחרוזות, והכשל נראה כשגיאת אימות במקום כשגיאת ניתוח (parsing), מה שגורם למשתמשים לחפש את הבעיה במקום הלא נכון.DASHBOARD_USERNAMEו-DASHBOARD_PASSWORD. אלו הם פרטי האימות הבסיסיים עבור ה-Studio. הסקריפט מגדיר סיסמה אקראית אך משאיר את שם המשתמש כברירת המחדלsupabase. סיסמת ברירת המחדל שמגיעה עם התוכנה היא פשוטthis_password_is_insecure_and_should_be_updated, לכן אם דילגת על הסקריפט, שנה אותה כעת.
הבן מדוע לא ניתן להמציא את ANON_KEY ו-SERVICE_ROLE_KEY. שניהם JWTs החתומים עם JWT_SECRET. ה-gateway מקבל רק את המפתחות המדויקים ב-.env, והשירותים שמאחוריו מאמתים את החתימה מול JWT_SECRET, לכן מפתח שאינו תואם נדחה עם שגיאת HTTP 401. ה-Envoy gateway המוגדר כברירת מחדל משיב 401 Unauthorized, וכך גם ה-Kong override הנוכחי, שמריץ את Kong 3.9 ומחזיר {"message":"Unauthorized"}. התקנות מלפני מרץ 2026 הריצו את Kong 2.8, שמשיב {"message":"Invalid authentication credentials"}. זהו כשל האירוח העצמי הנפוץ ביותר: המפעיל שינה את JWT_SECRET אך השאיר את מפתחות ההדגמה. צור את כל השלושה יחד, תמיד.
התייחס ל-SERVICE_ROLE_KEY כאל סיסמת root. הוא עוקף לחלוטין את אבטחת רמת השורה (row level security). מקומו בקוד צד השרת בלבד, ולא בשום מקום אחר.
הגדר את SITE_URL לכתובת האפליקציה שלך, ואת API_EXTERNAL_URL לכתובת הציבורית של ה-API עם /auth/v1 בסוף, לדוגמה https://supabase.example.com/auth/v1. הגדר את SUPABASE_PUBLIC_URL לאותה כתובת ציבורית ללא הנתיב. ה-Auth בונה את קישורי אימות האימייל וקישורי ה-OAuth callback שלו מתוך הערכים הללו, לכן השארתם על ערכי ברירת המחדל localhost תשלח כל אחד מהמשתמשים שלך למכונה של עצמם.
לאחר מכן בדוק מה יש לך:
sh run.sh secretsהפעלת השירות ואימות תקינותו
sh run.sh start
docker compose psהפקודה run.sh start עוטפת את docker compose up -d --wait, ולכן היא לא תחזיר שליטה עד שכל בדיקות התקינות יעברו בהצלחה. כל שירות אמור להציג running (healthy) או running. אתחול ראשוני אורך בין שתיים לארבע דקות, כיוון ש-Postgres מריץ את סקריפטי האתחול שלו לפני שכל שירות אחר יכול להתחבר.
אם מכולה נמצאת במצב של אתחול מחדש, ניתן לקרוא את הלוגים שלה לפי שם השירות:
docker compose logs db
docker compose logs authלאחר מכן, Studio יהיה זמין בפורט 8000, והוא יבקש את שם המשתמש והסיסמה ללוח הבקרה שהגדרת.
אל תחשפו את פורט 8000 לאינטרנט הציבורי
ה־gateway בפורט 8000 משתמש ב-HTTP גלוי. כל מפתח API וכל סיסמת משתמש עוברים ברשת כטקסט חשוף, ופרטי הגישה ל-Studio מבוססים על אימות בסיסי (basic authentication), שהוא קידוד base64 ולא הצפנה.
הציבו reverse proxy לפני השירות, בצעו בו TLS termination, והגדירו את ה-gateway להאזין לכתובת ה-loopback בלבד כדי למנוע גישה חיצונית. ב-docker-compose.yml, שורת הפורט תחת שירות ה-api-gw משתנה ל-127.0.0.1:${API_GW_HTTP_PORT:-${KONG_HTTP_PORT:-8000}}:8000/tcp, וה-proxy מעביר את הבקשות לשם. בהתקנות שבוצעו לפני המעבר ל-Envoy באוגוסט 2026, אותה שורת פורט מופיעה תחת שירות בשם kong. המדריך Traefik לפני מספר יישומי Compose מכסה את נושא התעודות. אותו proxy משמש בסופו של דבר כנקודת כניסה לכל השירותים על השרת, החל מה-stack הזה ועד לשירותים כמו ספריית Jellyfin המעוצבת כחנות וידאו משנות ה-90, כאשר כל אחד מהם דורש שם מתחם במקום פורט פתוח נוסף. אם ה-dashboard מיועד לשימושכם האישי בלבד, דלגו על ה-proxy וגשו לפורט ה-loopback דרך SSH tunnel, בדומה לגישה שבה משתמש open-kritt בהתקנה עצמית כדי להשאיר את ממשק הסריקה מחוץ לאינטרנט הציבורי לחלוטין.
סגרו את שאר הפורטים ב-firewall, כיוון ש-Docker מפרסם פורטים על ידי כתיבת חוקי iptables משלו, שקונפיגורציית ufw בסיסית אינה מזהה. מלכודת זו מוסברת ב-מדוע מכולות Docker מתעלמות מחוקי ה-ufw שלכם.
גבו את מסד הנתונים, לא את הספרייה
הנתונים של Postgres נמצאים ב-bind mount בנתיב ./volumes/db/data. העתקת הספרייה בזמן שהמכולה רצה יוצרת עותק לא עקבי (torn copy), כיוון ש-Postgres מבצעת כתיבות ב-buffer והקבצים בדיסק עקביים רק בנקודת checkpoint. שחזור מתוך עותק כזה בדרך כלל יצליח, אך לעיתים יגרום לאובדן שקט של הטרנזקציות האחרונות – תרחיש הכשל הגרוע ביותר עבור גיבוי.
בצעו dump במקום זאת. הפקודה pg_dumpall רצה בתוך המכולה ומייצרת snapshot עקבי:
docker exec -t supabase-db pg_dumpall -U postgres > supabase-$(date +%F).sqlוודאו שהקובץ אינו ריק לפני שאתם מסתמכים עליו. לאחר מכן, העבירו את ה-dumps הללו מחוץ לשרת לפי לוח זמנים, למטרה זו נועד גיבוי מוצפן מחוץ לאתר באמצעות restic. גיבוי מתוזמן שנכשל בשקט אינו שונה מאי-קיום גיבוי כלל, לכן הגדירו משימת cron או systemd שתבצע שליחת התראה לטלפון כאשר היא מסתיימת עם קוד שגיאה שאינו אפס. גבו את .env באותו הזמן. אובדן של JWT_SECRET משמעותו שכל token שהונפק הופך ללא תקף וכל סוד מוצפן שנשמר הופך לבלתי קריא.
קבצים שהועלו נמצאים ב-./volumes/storage, ומכיוון שמדובר בקבצים רגילים, העתקה פשוטה שלהם היא תקינה.
עדכון ללא אובדן נתונים
Supabase מקבעת גרסאות של images בתוך docker-compose.yml, כך ששום דבר לא משתנה עד שתבחר בכך. כדאי לאמץ קיבוע גרסאות (pinning) בכל stack שאתה בונה באופן ידני; זו הסיבה ש־שרת relay של RustDesk בהתקנה עצמית מקבע את שני ה־images של השרת במקום להשתמש ב־tag דינמי: עדכון צריך להיות פעולה שאתה בוחר לבצע בבוקר שבו יש לך זמן פנוי לכך. בצע גיבוי (dump) תחילה, בכל פעם.
docker compose pull
sh run.sh recreateהפקודה recreate עוצרת את ה־stack ומפעילה אותו מחדש על גבי ה־images החדשים. הנתונים שלך נשמרים מכיוון שהם נמצאים ב־bind mounts על ה־host, ולא בתוך המכולות. קרא את CHANGELOG.md במאגר לפני קפיצה לגרסה ראשית (major version), כיוון ששדרוג גרסה ראשית של Postgres הוא שלב נפרד ש־recreate אינו מבצע. Postgres 17 היא ברירת המחדל מאז יוני 2026, והתקנה קיימת על Postgres 15 עוברת אליה באמצעות sudo bash utils/upgrade-pg17.sh, המשתמש ב־pg_upgrade כדי להעביר את הנתונים במקומם ומבקש אישור בכל שלב מרכזי. התהליך דורש שכל המכולות יהיו פעילות ושיהיה שטח דיסק פנוי של לפחות פי שניים מגודל מסד הנתונים שלך ועוד 5 GB; בכל מקרה, Supabase ממליצה על גיבוי עצמאי משלך לפני תחילת התהליך.
כדי להחיל שינויים בקובץ ה-Compose עצמו, הרץ את sh update.sh מתוך תיקיית הפרויקט, או את sh update.sh --dry-run כדי לראות תחילה מה ישתנה. הפקודה ממזגת את קובצי ה-upstream עם העריכות שלך, לעולם אינה דורסת ערכים קיימים ב-.env (היא רק מוסיפה מפתחות חדשים), ומארכבת את התצורה שלך תחת backups/ לפני הכתיבה, אם כי לא את מסד הנתונים. התקנה ללא קובץ .supabase-version דורשת את --from ואת גרסת ה-release שממנה התחילה. זה חשוב במיוחד עבור גרסת אוגוסט 2026, שהחליפה את שירות kong ב-api-gw ומחייבת עדכון של docker-compose.yml. הדרך הידנית עדיין עובדת גם היא: שכפל (clone) שוב את מאגר ה-upstream והעתק את תיקיית docker שלו מעל הפרויקט שלך, תוך הקפדה לא לדרוס את .env.
איפוס מלא, שמשמיד את הכל כולל מסד הנתונים ומחזיר את .env לברירות המחדל (הקובץ הישן נשמר כ-.env.old), הוא סקריפט נפרד המבקש אישור:
sh reset.shFAQ
מדוע קריאות ה-API שלי מחזירות "Invalid authentication credentials"?
הודעה זו מגיעה מ-Kong 2.8, ה-gateway שהיה בשימוש בהתקנות שבוצעו לפני מרץ 2026. ה-gateway המוגדר כברירת מחדל כיום, Envoy, וגרסת ה-override הנוכחית של Kong, המריצה את Kong 3.9, מדווחים על אותה בעיה כ-401 Unauthorized פשוט. כך או כך, המפתח ששלחת אינו תואם ל-ANON_KEY או ל-SERVICE_ROLE_KEY ב-.env, או שהמפתחות לא נחתמו עם ה-JWT_SECRET שנמצא כרגע ב-.env. בסטאק שמעולם לא הכיל נתונים, צור מחדש את שלושתם יחד עם sh utils/generate-keys.sh --update-env. בסטאק פעיל, הרץ את הסקריפט ללא ה-flag וענה בשלילה, כך שהוא רק ידפיס ערכים חדשים; העתק את JWT_SECRET, ANON_KEY ו-SERVICE_ROLE_KEY לתוך .env באופן ידני, והשאר את POSTGRES_PASSWORD ללא שינוי. לאחר מכן הרץ את sh run.sh recreate כדי שהשירותים יקראו את הערכים החדשים.
האם ניתן להריץ Supabase ב-self-hosting על שרת VPS עם 2 GB RAM?
לא בצורה אמינה. התיעוד הרשמי של Supabase ל-self-hosting מציין 4 GB RAM כמינימום נכון לאוקטובר 2026, והסטאק צרך קרוב ל-3 GB במצב המתנה נכון ליולי 2026 במדידה שכללה את שירותי ה-logging (שכיום הם אופציונליים). שרת עם 2 GB יאבד מכולות בגלל ה-out of memory killer, ואתה תראה קוד יציאה 137 ב-docker compose ps. השתמש ב-8 GB עבור סביבת ייצור והתייחס ל-4 GB כרף התחתון עבור פיתוח אישי.
האם Supabase ב-self-hosting כולל edge functions?
כן. קובץ ה-Compose כולל את סביבת הריצה של הפונקציות מבוססות Deno, והוא מגיש כל מה שתשים תחת ./volumes/functions. הוא אינו כולל את רשת הפריסה הגלובלית של הפלטפורמה המנוהלת, לכן הפונקציות שלך ירוצו על השרת היחיד שלך, במיקום אחד.
כיצד ניתן להתחבר למסד הנתונים Postgres ישירות?
השתמש ב-docker exec -it supabase-db psql -U postgres עבור shell אינטראקטיבי על השרת עצמו. עבור לקוח חיצוני, התחבר דרך Supavisor בפורט 5432 עם המשתמש postgres.<POOLER_TENANT_ID> וה-POSTGRES_PASSWORD שלך. אל תפתח את הפורט הזה לאינטרנט. גש אליו דרך VPN או מנהרת SSH.
מדוע קישורי אימות האימייל שלי מפנים ל-localhost?
הערכים SITE_URL ו-API_EXTERNAL_URL ב-.env נותרו על ערכי ברירת המחדל שלהם. שירות ה-auth בונה כל קישור אימות ואיפוס סיסמה על סמך שני הערכים הללו, לכן הוא שולח את הכתובת שהוגדרה לו. הגדר את שניהם לכתובת ה-URL הציבורית האמיתית שלך וצור את הסטאק מחדש.