SSD Nodes Learn Hosting plans →
تعلیمی Matt Connorتحریر: Matt Connor · اپ ڈیٹ شدہ 2026-08-27

VPS پر Docker کے ساتھ Supabase self-host کریں

اپنے VPS پر official Supabase Docker stack چلائیں، demo secrets بدلیں، 14 services کا کام سمجھیں، RAM کی ضرورت جانیں، backups لیں اور محفوظ updates کریں۔

آپ کیا بنا رہے ہیں

Supabase کو self-host کرنے کا مطلب ہے کہ آپ اپنے سرور پر official Docker Compose stack چلا رہے ہیں: Postgres، اس کے سامنے REST API، auth service، file storage، realtime websockets، اور Studio dashboard۔ آپ ایک repository clone کرتے ہیں، ایک .env file میں ترمیم کرتے ہیں، اور تقریباً fourteen containers شروع کرتے ہیں جو مل کر ایک ایسا Supabase project چلاتے ہیں جس کا کنٹرول آپ کے پاس ہوتا ہے۔

انسٹالیشن مختصر ہے۔ مسئلہ .env file میں پیدا ہوتا ہے۔ اس میں demo secrets شامل ہوتے ہیں جو repository میں شائع کیے گئے ہیں، اور ان default values کے ساتھ شروع کیا گیا stack ہر اس شخص کے لیے کھلا ہوتا ہے جو اسے تلاش کر لے۔ اس guide میں بتایا گیا ہے کہ کون سے secrets تبدیل کرنے ضروری ہیں، ہر service کس مقصد کے لیے ہے، stack کو حقیقت میں کتنی memory درکار ہوتی ہے، اور database حذف کیے بغیر اسے کیسے update کرنا ہے۔

اگر Compose آپ کے لیے نیا ہے تو پہلے VPS پر Docker Compose کی بنیادی باتیں پڑھیں۔ ذیل کے تمام مراحل فرض کرتے ہیں کہ docker compose version پہلے ہی version دکھاتا ہے۔

اس stack میں اصل میں کیا شامل ہے

Supabase ایک پروگرام نہیں ہے۔ Compose file ایک ہی network پر الگ الگ services کا مجموعہ شروع کرتی ہے۔ ہر service کا کردار سمجھنے سے container names کی طویل فہرست کو debug کرنا آسان ہو جاتا ہے۔

  • db، Supabase extensions کے ساتھ چلنے والا PostgreSQL ہے۔ باقی تمام services اس سے رابطہ کرتی ہیں۔ اگر یہ container صحت مند نہ ہو تو باقی سب بھی ناکام ہو جاتے ہیں۔
  • kong API gateway ہے۔ یہ port 8000 پر سنتا ہے اور /rest/v1/، /auth/v1/ اور /storage/v1/ کو درست backend تک route کرتا ہے۔ صرف اسی container کو public طور پر expose کرنا چاہیے۔
  • rest PostgREST ہے۔ یہ آپ کے Postgres schema کو پڑھ کر اسے REST API کے طور پر فراہم کرتا ہے۔ اس طرح نئی table کے لیے بغیر code لکھے نیا endpoint بن جاتا ہے۔
  • auth GoTrue ہے۔ یہ ان JSON web tokens (JWT) کو جاری کرتا ہے جو آپ کے users کی شناخت کرتے ہیں۔
  • storage اور imgproxy file uploads اور image resizing سنبھالتے ہیں۔
  • realtime database changes کو websockets کے ذریعے stream کرتا ہے۔
  • studio اور meta dashboard اور اس کے پیچھے موجود admin API ہیں۔
  • analytics (Logflare) اور vector logs جمع کرتے ہیں، جبکہ supavisor Postgres connection pooler ہے۔

اسی فہرست کی وجہ سے نیچے دیے گئے resource numbers وہی ہیں جو آپ دیکھیں گے۔ آپ صرف database نہیں چلا رہے۔ آپ database کے ساتھ ایک درجن support services بھی چلا رہے ہیں۔

Sizing: 8 GB RAM کے لیے منصوبہ بندی کریں

جولائی 2026 تک نئی installation پر، آپ کے اپنے data یا traffic کے بغیر، یہ stack idle حالت میں تقریباً 2.5 سے 3 GB resident memory استعمال کرتا ہے۔ Analytics service اور Studio کا Node.js process دو سب سے بڑے واحد صارف ہیں۔ 2 GB کا server containers شروع کر دے گا، لیکن پھر kernel کا out of memory killer ان میں سے کسی ایک کو بند کر دے گا، عموماً analytics یا db۔ اس کی علامت یہ ہے کہ کوئی container exit code 137 کے ساتھ بار بار restart ہوتا رہے۔

ہر قابلِ اعتماد استعمال کے لیے اسے 8 GB RAM اور 4 vCPU دیں۔ اگر آپ یہ قبول کرتے ہیں کہ ایک ہی وقت میں heavy query اور Studio session سست ہوں گے تو solo development instance کے لیے 4 GB کافی ہے۔ Disk بھی اہم ہے، کیونکہ Postgres، storage volume اور log data سب project directory کے تحت محفوظ ہوتے ہیں۔ 40 GB سے شروع کریں اور اس کی نگرانی کریں۔ Plan منتخب کرنے سے پہلے services کی memory requirements گننا ایک مفید عادت ہے، خاص طور پر ہر اس software کے لیے جسے آپ self-host کرتے ہیں، کیونکہ PhotoPrism اور Immich کی حقیقی RAM کی کم از کم ضروریات ان کے quick start صفحات میں بتائی گئی مقدار سے کہیں زیادہ ہیں۔

تنصیب: سرکاری repository clone کریں

تجویز کردہ طریقہ main repository سے docker directory کو اپنی project directory میں copy کرتا ہے۔ یہ علیحدگی اہم ہے، کیونکہ اس کا مطلب ہے کہ بعد میں ہونے والا git pull آپ کے .env کو overwrite نہیں کر سکے گا۔

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 کئی gigabytes کی images download کرتا ہے۔ اس کے اختتام پر ہر service کا status Pulled ہونا چاہیے۔ یہاں manifest unknown error کا مطلب ہے کہ pinned image tag upstream سے remove کر دیا گیا ہے۔ اس کا حل tags کو دستی طور پر edit کرنا نہیں، بلکہ repository کی نئی copy pull کرنا ہے۔

پہلی بار شروع کرنے سے پہلے یہ secrets تبدیل کریں

Stack شروع کرنے سے پہلے یہ کام کریں، بعد میں نہیں۔ ان میں سے کئی values پہلی boot پر data میں لکھ دی جاتی ہیں، اس لیے بعد میں انہیں تبدیل کرنے کا مطلب database کو reset کرنا ہے۔

Repository میں ایک generator موجود ہے جو ہر value درست طور پر تیار کرتا ہے۔ اس میں وہ دو API keys بھی شامل ہیں جن پر آپ کے نئے JWT secret سے دستخط ہونا ضروری ہیں۔

sh utils/generate-keys.sh --update-env

یہ script JWT_SECRET، ANON_KEY، SERVICE_ROLE_KEY، SECRET_KEY_BASE، REALTIME_DB_ENC_KEY، VAULT_ENC_KEY، PG_META_CRYPTO_KEY اور Logflare tokens کے لیے نئی values کو .env میں لکھتی ہے۔ اسے openssl درکار ہے، جو کسی بھی معمول کی Ubuntu image میں موجود ہوتا ہے۔

دو values یہ script set نہیں کرتی۔ آپ کو انہیں .env میں دستی طور پر edit کرنا ہوگا:

  • POSTGRES_PASSWORD۔ صرف حروف اور digits استعمال کریں۔ یہاں punctuation کئی services کے تیار کردہ connection strings کو توڑ دیتا ہے، کیونکہ وہ strings کو جوڑ کر یہ values بناتی ہیں۔ Failure parsing error کے بجائے authentication error جیسی دکھائی دیتی ہے، اس لیے لوگ غلط جگہ troubleshooting شروع کر دیتے ہیں۔
  • DASHBOARD_USERNAME اور DASHBOARD_PASSWORD۔ یہ Studio کے لیے basic authentication credentials ہیں۔ فراہم کردہ default password لفظاً this_password_is_insecure_and_should_be_updated ہے۔

سمجھیں کہ ANON_KEY اور SERVICE_ROLE_KEY من گھڑت کیوں نہیں ہو سکتے۔ دونوں JWTs ہیں جن پر JWT_SECRET سے دستخط کیے گئے ہیں۔ Gateway ہر request پر اس signature کی تصدیق کرتا ہے، اس لیے ایسی key جس کا آپ کے secret سے میل نہ ہو، {"message":"Invalid authentication credentials"} کے ساتھ reject ہو جاتی ہے۔ Self-hosting میں یہ سب سے عام failure ہے: operator نے JWT_SECRET تبدیل کیا، لیکن demo keys برقرار رکھیں۔ تینوں values ہمیشہ ایک ساتھ generate کریں۔

SERVICE_ROLE_KEY کو root password کی طرح محفوظ رکھیں۔ یہ row level security کو مکمل طور پر bypass کرتا ہے۔ اسے صرف server-side code میں رکھیں، کسی اور جگہ نہیں۔

SITE_URL اور API_EXTERNAL_URL میں وہ address set کریں جہاں تک آپ کے users حقیقتاً پہنچیں گے، مثلاً https://supabase.example.com۔ Auth انہی values سے email confirmation اور OAuth callback links بناتا ہے۔ انہیں http://localhost:8000 پر چھوڑنے سے آپ کے تمام users اپنے ہی machine پر بھیج دیے جائیں گے۔

پھر اپنی values کی تصدیق کریں:

sh run.sh secrets

اسے شروع کریں اور صحت کی تصدیق کریں

sh run.sh start
docker compose ps

run.sh start، docker compose up -d --wait کو wrap کرتا ہے، اس لیے health checks کامیاب ہونے تک واپس نہیں آتا۔ ہر service کو running (healthy) یا running دکھانا چاہیے۔ پہلی boot میں دو سے چار منٹ لگتے ہیں، کیونکہ Postgres ابتدائیisation scripts چلاتا ہے اور اس سے پہلے کوئی چیز اس سے connect نہیں کر سکتی۔

اگر کوئی container دوبارہ شروع ہو رہا ہو تو اس کے logs کو service name کے ذریعے پڑھیں:

docker compose logs db
docker compose logs auth

Studio اب port 8000 پر دستیاب ہے، اور یہ آپ کے مقرر کردہ dashboard username اور password طلب کرے گا۔

عوامی انٹرنیٹ پر port 8000 نہ رکھیں

Kong کا port 8000 سادہ HTTP استعمال کرتا ہے۔ ہر API key اور ہر user password نیٹ ورک پر plain text میں منتقل ہوتا ہے، جبکہ Studio credentials basic authentication استعمال کرتے ہیں، جو encryption کے بجائے base64 encoding ہے۔

اس کے سامنے reverse proxy رکھیں، وہیں TLS (transport layer security) terminate کریں، اور Kong کو loopback address پر bind کریں تاکہ کوئی دوسری سروس اس تک رسائی حاصل نہ کر سکے۔ docker-compose.yml میں kong port mapping کو 127.0.0.1:8000:8000 کر دیا جاتا ہے، اور proxy اسی تک درخواستیں forward کرتا ہے۔ کئی Compose ایپس کے سامنے Traefik میں certificate کے حصے کی وضاحت کی گئی ہے۔

باقی ports کو بھی firewall میں بند کریں، کیونکہ Docker اپنے iptables rules لکھ کر ports publish کرتا ہے، جنہیں سادہ ufw configuration نہیں دیکھتی۔ یہ مسئلہ Docker containers آپ کے ufw rules کو نظرانداز کیوں کرتے ہیں میں بیان کیا گیا ہے۔

ڈائریکٹری کا نہیں، database کا backup لیں

Postgres کا data ./volumes/db/data میں bind mount کے طور پر موجود ہے۔ Container کے چلنے کے دوران اس directory کو copy کرنے سے نامکمل copy بنتی ہے، کیونکہ Postgres writes کو buffer کرتا ہے اور disk پر موجود files صرف checkpoint کے وقت consistent ہوتی ہیں۔ اسے restore کرنا عموماً کامیاب ہو جاتا ہے، لیکن کبھی کبھار آخری transactions خاموشی سے ضائع ہو جاتی ہیں۔ Backup کے لیے یہ بدترین ممکنہ failure mode ہے۔

اس کے بجائے dump بنائیں۔ pg_dumpall container کے اندر چلتا ہے اور consistent snapshot تیار کرتا ہے:

docker exec -t supabase-db pg_dumpall -U postgres > supabase-$(date +%F).sql

اس پر اعتماد کرنے سے پہلے تصدیق کریں کہ file خالی نہیں ہے۔ پھر مقررہ schedule کے مطابق یہ dumps server سے باہر منتقل کریں۔ اسی مقصد کے لیے restic کے ذریعے encrypted offsite backups استعمال کیے جاتے ہیں۔ اسی وقت اپنے .env کا بھی backup لیں۔ JWT_SECRET ضائع ہونے کا مطلب ہے کہ جاری کیے گئے تمام tokens invalid ہو جائیں گے اور محفوظ شدہ encrypted secrets ناقابل مطالعہ ہو جائیں گے۔

Uploaded files ./volumes/storage میں موجود ہوتی ہیں۔ یہ عام files ہیں، اس لیے ان کی سادہ copy کافی ہے۔

ڈیٹا ضائع کیے بغیر اپ ڈیٹ

Supabase، docker-compose.yml میں image versions کو pin کرتا ہے، اس لیے جب تک آپ خود version نہ بدلیں، کچھ بھی خودکار طور پر تبدیل نہیں ہوتا۔ کسی بھی stack کو دستی طور پر assemble کرتے وقت pinning اختیار کرنا مفید ہے۔ اسی وجہ سے self-hosted RustDesk relay اپنی دونوں server images کو pin کرتا ہے، کسی مسلسل تبدیل ہونے والے tag کو follow نہیں کرتا۔ upgrade ایسا کام ہونا چاہیے جسے آپ اس صبح کرنے کا انتخاب کریں جب آپ کے پاس اس کے لیے وقت ہو۔ ہر بار پہلے dump ضرور بنائیں۔

docker compose pull
sh run.sh recreate

recreate stack کو روکتا ہے اور نئی images کے ساتھ اسے دوبارہ شروع کرتا ہے۔ آپ کا ڈیٹا محفوظ رہتا ہے کیونکہ وہ containers کے اندر نہیں بلکہ host پر موجود bind mounts میں رہتا ہے۔ major version upgrade سے پہلے repository میں CHANGELOG.md پڑھیں، کیونکہ Postgres کے major upgrades خودکار نہیں ہوتے اور ان کے لیے dump اور restore درکار ہوتا ہے۔

Compose file میں ہونے والی تبدیلیاں شامل کرنے کے لیے upstream repository کو دوبارہ clone کریں اور اس کی docker directory کو اپنے project میں copy کریں۔ اس دوران .env کو overwrite نہ کریں۔

مکمل reset ایک الگ script کے ذریعے ہوتا ہے اور اس میں database سمیت سب کچھ حذف ہو جاتا ہے۔ یہ script confirmation طلب کرتی ہے:

sh reset.sh

FAQ

میری API calls میں "Invalid authentication credentials" کیوں واپس آتا ہے؟

آپ کے ANON_KEY یا SERVICE_ROLE_KEY پر اس JWT_SECRET کے ذریعے دستخط نہیں کیے گئے جو اس وقت .env میں موجود ہے۔ gateway ہر request پر signature کی تصدیق کرتا ہے اور عدم مطابقت کی صورت میں request مسترد کر دیتا ہے۔ sh utils/generate-keys.sh --update-env کے ذریعے تینوں values ایک ساتھ دوبارہ بنائیں، پھر sh run.sh recreate چلائیں تاکہ services نئی values پڑھ سکیں۔

کیا میں 2 GB VPS پر self-hosted Supabase چلا سکتا ہوں؟

قابلِ اعتماد طور پر نہیں۔ July 2026 تک یہ stack idle حالت میں تقریباً 3 GB memory استعمال کرتا ہے، کیونکہ اس میں تقریباً fourteen services چلتی ہیں۔ اس لیے 2 GB server پر out of memory killer containers بند کر دیتا ہے، اور آپ docker compose ps میں exit code 137 دیکھتے ہیں۔ Production کے لیے 8 GB استعمال کریں، جبکہ solo development کے لیے 4 GB کو کم از کم حد سمجھیں۔

کیا self-hosted Supabase میں edge functions شامل ہیں؟

ہاں۔ Compose file میں Deno based functions runtime شامل ہے، اور یہ ./volumes/functions کے اندر رکھی ہوئی ہر چیز serve کرتا ہے۔ اس میں hosted platform کا global deployment network شامل نہیں، اس لیے آپ کی functions ایک ہی location میں موجود آپ کے ایک server پر چلتی ہیں۔

میں Postgres database سے براہِ راست کیسے connect کروں؟

خود server پر interactive shell کے لیے docker exec -it supabase-db psql -U postgres استعمال کریں۔ کسی external client کے لیے port 5432 پر Supavisor کے ذریعے postgres.<POOLER_TENANT_ID> user اور اپنے POSTGRES_PASSWORD کے ساتھ connect کریں۔ اس port کو internet کے لیے open نہ کریں۔ اس تک VPN یا SSH tunnel کے ذریعے پہنچیں۔

.env میں SITE_URL اور API_EXTERNAL_URL اپنی default values پر رہ گئے تھے۔ auth service ہر confirmation اور password reset link انہی دو values سے بناتی ہے، اس لیے وہ وہی address بھیجتی ہے جو اسے دیا گیا ہو۔ دونوں values کو اپنے حقیقی public URL پر set کریں اور stack دوبارہ بنائیں۔