Docker ile VPS'te Supabase Self-Host Etme
Resmi Supabase Docker yığınını kendi sunucunuzda çalıştırın: değiştirilecek secret'lar, 14 hizmetin görevi, RAM gereksinimi, yedekleme ve güncelleme adımları.
Oluşturulanlar
Supabase'i kendi sunucunuzda barındırmak, resmi Docker Compose yığınını çalıştırmak anlamına gelir. Bu yığın Postgres'i, önünde çalışan bir REST API'yi, bir kimlik doğrulama hizmetini, dosya depolamayı, gerçek zamanlı websockets bağlantılarını ve Studio kontrol panelini içerir. Tek bir repository klonlanır, bir .env dosyası düzenlenir ve birlikte kontrol edilen bir Supabase projesi gibi çalışan yaklaşık fourteen container başlatılır.
Kurulum kısadır. Sorunların ortaya çıktığı bölüm .env dosyasıdır. Bu dosyada repository'de yayımlanmış demo secret'lar bulunur. Bu varsayılanlarla başlatılan bir yığın, onu bulan herkesin erişimine açıktır. Bu kılavuzda değiştirilmesi gereken secret'lar, her hizmetin amacı, yığının gerçekte ne kadar belleğe ihtiyaç duyduğu ve veritabanı silinmeden nasıl güncelleneceği açıklanır.
Compose kullanımı yeniyse önce VPS üzerinde Docker Compose temelleri bölümünü okuyun. Aşağıdaki tüm işlemlerde docker compose version komutunun zaten bir sürüm yazdırdığı varsayılır.
Yığının gerçekte içerdiği bileşenler
Supabase tek bir program değildir. Compose dosyası, aynı ağ üzerinde ayrı hizmetlerden oluşan bir küme başlatır. Hangi hizmetin ne yaptığını bilmek, çok sayıda container adından oluşan karmaşık yapıyı hata ayıklanabilir hale getirir.
db, Supabase uzantıları yüklenmiş PostgreSQL'dir. Diğer tüm hizmetler bununla iletişim kurar. Bu container sağlıksız durumdaysa diğer her şey de başarısız olur.kongAPI gateway'dir. 8000 portunu dinler ve/rest/v1/,/auth/v1/ve/storage/v1/isteklerini doğru arka uçlara yönlendirir. Dış erişime açılması gereken tek container budur.restPostgREST'tir. Postgres şemanızı okur ve bunu REST API olarak sunar. Böylece yeni bir tablo, kod yazılmadan yeni bir endpoint haline gelir.authGoTrue'dur. Kullanıcılarınızı tanımlayan JSON web token'larını (JWT) üretir.storageveimgproxydosya yüklemelerini ve görüntü boyutlandırmayı yönetir.realtimeveritabanı değişikliklerini websockets üzerinden yayınlar.studiovemeta, dashboard ile bunun arkasındaki admin API'dir.analytics(Logflare) vevectorlogları toplar.supavisorise Postgres bağlantı havuzlayıcısıdır.
Aşağıdaki kaynak kullanım değerlerinin bu seviyelerde olmasının nedeni budur. Bir veritabanı çalıştırmıyorsunuz. Bir veritabanının yanı sıra bir düzine destek hizmeti çalıştırıyorsunuz.
Boyutlandırma: 8 GB RAM planlayın
Temiz bir kurulumda, kendi verileriniz veya ağ trafiğiniz eklenmeden önce yığın, Temmuz 2026 itibarıyla yaklaşık 2.5 ila 3 GB yerleşik bellek kullanır. Analytics service ve Studio Node.js işlemi, tek başına en fazla kaynak kullanan iki bileşendir. 2 GB RAM'e sahip bir sunucu container'ları başlatır, ardından kernel out of memory killer bunlardan birini sonlandırır; bu genellikle analytics veya db olur. Belirti, exit code 137 ile sürekli yeniden başlatılan bir container'dır.
Güvenilecek her ortam için 8 GB RAM ve 4 vCPU tahsis edin. Ağır bir sorgu ile aynı anda yürütülen bir Studio oturumunun yavaş olmasını kabul ediyorsanız, tek kullanıcılı bir geliştirme instance'ı için 4 GB yeterlidir. Disk de önemlidir, çünkü Postgres, storage volume ve log verilerinin tümü project directory altında bulunur. 40 GB ile başlayın ve disk kullanımını izleyin.
Kurulum: resmi repository'yi klonlama
Desteklenen yöntem, ana repository içindeki docker dizinini kendi proje dizinine kopyalar. Bu ayrım önemlidir; çünkü daha sonra çalıştırılan git pull komutu, .env dosyanızın üzerine yazamaz.
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 pulldocker compose pull birkaç gigabaytlık image indirir. Tüm servislerin Pulled olarak işaretlenmesiyle tamamlanmalıdır. Buradaki manifest unknown hatası, sabitlenen image etiketinin upstream'den kaldırıldığı anlamına gelir. Çözüm, etiketleri elle düzenlemek yerine repository'nin daha yeni bir kopyasını çekmektir.
İlk başlatmadan önce değiştirmeniz gereken gizli değerler
Bunu yığını başlatmadan önce yapın. Başlattıktan sonra yapmayın. Bu değerlerin birkaçı ilk açılışta verilere yazılır. Daha sonra değiştirmek veritabanının sıfırlanmasını gerektirir.
Depoda, iki API anahtarı da yeni JWT gizli anahtarınızla imzalanacak şekilde tüm değerleri doğru biçimde üreten bir oluşturucu bulunur.
sh utils/generate-keys.sh --update-envBu betik, JWT_SECRET, ANON_KEY, SERVICE_ROLE_KEY, SECRET_KEY_BASE, REALTIME_DB_ENC_KEY, VAULT_ENC_KEY ve PG_META_CRYPTO_KEY için yeni değerleri ve Logflare belirteçlerini .env içine yazar. Ubuntu'nun normal bir imajında bulunan openssl bileşenine ihtiyaç duyar.
Betik iki değeri ayarlamaz. Bunları .env içinde elle düzenlemeniz gerekir:
POSTGRES_PASSWORD. Yalnızca harf ve rakam kullanın. Buradaki noktalama işaretleri, birkaç hizmetin dizeleri birleştirerek oluşturduğu bağlantı dizelerini bozar. Hata, ayrıştırma hatası yerine kimlik doğrulama hatası gibi görünür. Bu da sorunun yanlış yerde aranmasına neden olur.DASHBOARD_USERNAMEveDASHBOARD_PASSWORD. Bunlar Studio için temel kimlik doğrulama bilgileridir. Dağıtımla gelen varsayılan parola tam olarakthis_password_is_insecure_and_should_be_updateddeğeridir.
ANON_KEY ve SERVICE_ROLE_KEY değerlerinin neden rastgele oluşturulamayacağını anlayın. Her ikisi de JWT_SECRET ile imzalanan JWT değerleridir. Gateway, her istekte bu imzayı doğrular. Bu nedenle gizli anahtarınızla eşleşmeyen bir anahtar {"message":"Invalid authentication credentials"} ile reddedilir. Bu, kendi sunucusunda barındırma sırasında en sık karşılaşılan hatadır: yönetici JWT_SECRET değerini değiştirir, ancak örnek anahtarları kullanmaya devam eder. Üçünü de her zaman birlikte oluşturun.
SERVICE_ROLE_KEY değerini root parolası gibi koruyun. Bu değer satır düzeyi güvenliğini tamamen devre dışı bırakır. Sunucu tarafındaki kodda bulunmalıdır. Başka hiçbir yerde bulunmamalıdır.
SITE_URL ve API_EXTERNAL_URL değerlerini, kullanıcılarınızın gerçekten erişeceği adres olarak ayarlayın. Örneğin https://supabase.example.com kullanabilirsiniz. Auth, e-posta onayı ve OAuth geri çağırma bağlantılarını bu değerlerden oluşturur. Bu değerleri http://localhost:8000 olarak bırakmak, tüm kullanıcılarınızı kendi makinelerine yönlendirir.
Ardından ayarlarınızı kontrol edin:
sh run.sh secretsBaşlatın ve sağlıklı olduğunu doğrulayın
sh run.sh start
docker compose psrun.sh start, docker compose up -d --wait komutunu sarar; bu nedenle sağlık kontrolleri başarılı olana kadar geri dönmez. Her hizmette running (healthy) veya running görüntülenmelidir. İlk başlatma iki ila dört dakika sürer; çünkü Postgres, başka hiçbir bileşen bağlanamadan önce başlatma komut dosyalarını çalıştırır.
Bir container yeniden başlatılıyorsa günlüklerini hizmet adına göre okuyun:
docker compose logs db
docker compose logs authStudio artık 8000 portundadır ve belirlediğiniz dashboard kullanıcı adını ve parolasını ister.
8000 numaralı portu genel internete açmayın
Kong, 8000 numaralı portta düz HTTP kullanır. Her API anahtarı ve her kullanıcı parolası ağ üzerinden açık metin olarak iletilir. Studio kimlik bilgileri de şifreleme yerine base64 kodlaması kullanan basic authentication yöntemidir.
Önüne bir reverse proxy yerleştirin ve TLS'yi (transport layer security) burada sonlandırın. Kong'u loopback adresine bağlayarak başka hiçbir bileşenin ona erişememesini sağlayın. docker-compose.yml içinde kong port eşlemesi 127.0.0.1:8000:8000 olur ve proxy istekleri buna yönlendirir. Birden fazla Compose uygulamasının önünde Traefik sertifika yapılandırmasını açıklar.
Docker, kendi iptables kurallarını yazarak portları yayımladığı için geri kalan portları da firewall üzerinde kapatın. Naif bir ufw yapılandırması bu kuralları görmez. Bu tuzak, Docker container'larının ufw kurallarınızı neden yok saydığı bölümünde açıklanır.
Dizini değil, veritabanını yedekleyin
Postgres verileri ./volumes/db/data konumundaki bir bind mount içinde tutulur. Container çalışırken bu dizinin kopyalanması tutarsız bir kopya oluşturur. Bunun nedeni, Postgres'in yazma işlemlerini arabelleğe alması ve diskteki dosyaların yalnızca bir checkpoint sırasında tutarlı olmasıdır. Bu kopyayı geri yüklemek genellikle işe yarar. Ancak son işlemler bazen sessizce kaybolabilir. Bu, bir yedekleme için en kötü hata türüdür.
Bunun yerine dump alın. pg_dumpall container içinde çalışır ve tutarlı bir anlık görüntü oluşturur:
docker exec -t supabase-db pg_dumpall -U postgres > supabase-$(date +%F).sqlDosyaya güvenmeden önce boş olmadığını kontrol edin. Ardından bu dump dosyalarını belirli bir zamanlamayla sunucu dışına aktarın. restic ile şifreli uzak yedekleme bunun için kullanılır. .env öğesini de aynı zamanda yedekleyin. JWT_SECRET kaybedilirse verilen tüm token'lar geçersiz hale gelir ve depolanan tüm şifreli sırlar okunamaz.
Yüklenen dosyalar ./volumes/storage içinde bulunur. Bunlar normal dosyalardır. Bu nedenle düz kopyalama yeterlidir.
Veri kaybı olmadan güncelleme
Supabase, imaj sürümlerini docker-compose.yml dosyasında sabitler. Bu nedenle siz değiştirene kadar hiçbir şey değişmez. Her seferinde önce dump alın.
docker compose pull
sh run.sh recreaterecreate, stack'i durdurur ve yeni imajlarla yeniden başlatır. Verileriniz, container'ların içinde değil, host üzerindeki bind mount'larda bulunduğu için korunur. Büyük bir sürüm yükseltmesinden önce repository içindeki CHANGELOG.md dosyasını okuyun. Postgres major yükseltmeleri otomatik değildir ve dump ile restore gerektirir.
Compose dosyasındaki değişiklikleri almak için upstream repository'yi yeniden clone edin ve içindeki docker dizinini projenizin üzerine kopyalayın. .env dosyasının üzerine yazmamaya dikkat edin.
Veritabanı dahil her şeyi silen tam sıfırlama ayrı bir script'tir ve onay ister:
sh reset.shFAQ
API çağrılarım neden "Invalid authentication credentials" döndürüyor?
ANON_KEY veya SERVICE_ROLE_KEY, şu anda .env içinde bulunan JWT_SECRET ile imzalanmamış. Ağ geçidi her istekte imzayı doğrular ve eşleşmeyen imzaları reddeder. sh utils/generate-keys.sh --update-env ile üçünü birlikte yeniden oluşturun. Ardından hizmetlerin yeni değerleri okuması için sh run.sh recreate komutunu çalıştırın.
2 GB RAM'e sahip bir VPS üzerinde self-hosted Supabase çalıştırılabilir mi?
Güvenilir biçimde çalıştırılamaz. Stack, Temmuz 2026 itibarıyla boşta yaklaşık 3 GB RAM kullanır. Bunun nedeni yaklaşık on dört hizmet çalıştırmasıdır. Bu nedenle 2 GB RAM'e sahip bir sunucuda konteynerler out of memory killer tarafından sonlandırılır ve docker compose ps içinde 137 çıkış kodu görülür. Üretim ortamı için 8 GB kullanın. Tek başına geliştirme için 4 GB'ı alt sınır kabul edin.
self-hosted Supabase edge functions içerir mi?
Evet. Compose dosyası Deno tabanlı functions runtime içerir. ./volumes/functions altında yer alan her şeyi sunar. Hosted platformun global deployment network'ünü içermez. Bu nedenle functions tek sunucunuzda ve tek konumda çalışır.
Postgres veritabanına doğrudan nasıl bağlanılır?
Sunucunun kendisinde etkileşimli bir shell açmak için docker exec -it supabase-db psql -U postgres kullanın. Harici bir istemci için Supavisor üzerinden 5432 portuna postgres.<POOLER_TENANT_ID> kullanıcısı ve POSTGRES_PASSWORD ile bağlanın. Bu portu internete açmayın. Bağlantıyı VPN veya SSH tunnel üzerinden kurun.
Auth onay e-postalarındaki bağlantılar neden localhost adresine yönlendi?
.env içindeki SITE_URL ve API_EXTERNAL_URL varsayılan değerlerinde bırakılmış. Auth hizmeti her onay ve password reset bağlantısını bu iki değerden oluşturur. Bu nedenle kendisine bildirilen adresi gönderir. İkisini de gerçek genel URL'nize ayarlayın ve stack'i yeniden oluşturun.