Supabase na VPS z Docker: instalacja i aktualizacje
Uruchom oficjalny stos Supabase Docker na własnym serwerze. Sprawdź 14 usług, sekrety do zmiany, wymagania RAM, kopie zapasowe i aktualizacje.
Co jest wdrażane
Self-hosting Supabase oznacza uruchomienie oficjalnego stosu Docker Compose na własnym serwerze: Postgresa, interfejsu REST API, usługi uwierzytelniania, magazynu plików, mechanizmu WebSocket dla funkcji realtime oraz panelu Studio. Należy sklonować jedno repozytorium, zmodyfikować jeden plik .env i uruchomić około czternastu kontenerów, które razem działają jak kontrolowany projekt Supabase.
Instalacja jest krótka. Problemy powoduje plik .env. Zawiera przykładowe dane uwierzytelniające opublikowane w repozytorium. Stos uruchomiony z tymi wartościami domyślnymi jest dostępny dla każdej osoby, która je znajdzie. W tym przewodniku opisano dane uwierzytelniające, które należy zastąpić, przeznaczenie poszczególnych usług, rzeczywiste wymagania dotyczące pamięci oraz sposób aktualizacji bez usuwania bazy danych.
Jeśli Compose nie jest jeszcze znany, należy najpierw przeczytać Podstawy Docker Compose na VPS. Wszystkie poniższe czynności zakładają, że polecenie docker compose version wyświetla już wersję.
Co faktycznie zawiera stos
Supabase nie jest jednym programem. Plik Compose uruchamia zestaw oddzielnych usług w jednej sieci. Wiedza o ich rolach ułatwia diagnozowanie problemów zamiast analizowania samej listy nazw kontenerów.
dbto PostgreSQL z załadowanymi rozszerzeniami Supabase. Wszystkie pozostałe usługi komunikują się z nim. Jeśli ten kontener jest w złym stanie, pozostałe usługi również przestają działać.kongto brama API. Nasłuchuje na porcie 8000 i przekazuje/rest/v1/,/auth/v1/oraz/storage/v1/do właściwego zaplecza. Jest to jedyny kontener, który powinien być wystawiany na zewnątrz.restto PostgREST. Odczytuje schemat Postgres i udostępnia go jako interfejs REST API. Dzięki temu nowa tabela staje się nowym punktem końcowym bez konieczności pisania kodu.authto GoTrue. Wystawia tokeny JSON Web Token (JWT), które identyfikują użytkowników.storageiimgproxyobsługują przesyłanie plików oraz zmianę rozmiaru obrazów.realtimeprzesyła zmiany w bazie danych za pośrednictwem WebSocketów.studioimetato pulpit administracyjny oraz obsługujący go interfejs administracyjny API.analytics(Logflare) ivectorzbierają logi, asupavisorto pula połączeń PostgreSQL.
To wyjaśnia wartości zasobów podane poniżej. Nie jest uruchamiana tylko baza danych. Uruchamiana jest baza danych oraz kilkanaście usług pomocniczych.
Wymagania: zaplanuj 8 GB pamięci RAM
Po świeżej instalacji stos wykorzystuje w stanie bezczynności około 2.5 do 3 GB pamięci rezydentnej (stan na lipiec 2026), przed dodaniem własnych danych i ruchu sieciowego. Usługa analityczna i proces Studio Node.js to dwa największe pojedyncze odbiorniki pamięci. Serwer z 2 GB uruchomi kontenery, a następnie jądro zakończy jeden z nich za pomocą mechanizmu out-of-memory killer, zwykle analytics lub db. Objawem jest kontener, który pozostaje w stanie ponownego uruchamiania i kończy pracę z kodem wyjścia 137.
W przypadku środowiska, od którego zależy działanie usługi, należy przydzielić 8 GB pamięci RAM i 4 vCPU. 4 GB wystarczy dla pojedynczej instancji deweloperskiej, jeśli można zaakceptować spowolnienie przy jednoczesnym wykonywaniu ciężkiego zapytania i korzystaniu z sesji Studio. Znaczenie ma również miejsce na dysku, ponieważ Postgres, wolumin danych i dane dzienników znajdują się w katalogu projektu. Na początek należy przydzielić 40 GB i monitorować jego wykorzystanie.
Instalacja: klonowanie oficjalnego repozytorium
Obsługiwana metoda kopiuje katalog docker z głównego repozytorium do własnego katalogu projektu. To rozdzielenie ma znaczenie, ponieważ późniejsza operacja git pull nie może nadpisać elementu .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 pulldocker compose pull pobiera kilka gigabajtów obrazów. Polecenie powinno zakończyć działanie po oznaczeniu każdej usługi jako Pulled. Błąd manifest unknown w tym miejscu oznacza, że przypisany tag obrazu został usunięty z repozytorium nadrzędnego. Należy wtedy pobrać nowszą kopię repozytorium, a nie ręcznie edytować tagi.
Sekrety, które należy zmienić przed pierwszym uruchomieniem
Należy wykonać te czynności przed uruchomieniem stosu, a nie po nim. Kilka z tych wartości jest zapisywanych w danych podczas pierwszego uruchomienia, dlatego ich późniejsza zmiana wymaga zresetowania bazy danych.
W repozytorium znajduje się generator, który poprawnie tworzy wszystkie wartości, w tym 2 klucze API, które muszą zostać podpisane nowym sekretem JWT.
sh utils/generate-keys.sh --update-envTen skrypt zapisuje nowe wartości dla JWT_SECRET, ANON_KEY, SERVICE_ROLE_KEY, SECRET_KEY_BASE, REALTIME_DB_ENC_KEY, VAULT_ENC_KEY, PG_META_CRYPTO_KEY oraz tokeny Logflare w .env. Wymaga openssl, który jest dostępny w każdym standardowym obrazie Ubuntu.
2 wartości nie są ustawiane przez skrypt i należy je ręcznie zmienić w .env:
POSTGRES_PASSWORD. Należy używać wyłącznie liter i cyfr. Znaki interpunkcyjne powodują uszkodzenie parametrów połączeń tworzonych przez kilka usług przez łączenie ciągów. Błąd wygląda wtedy jak błąd uwierzytelniania, a nie błąd analizy składni, co kieruje diagnostykę w niewłaściwe miejsce.DASHBOARD_USERNAMEiDASHBOARD_PASSWORD. Są to dane uwierzytelniania podstawowego dla Studio. Domyślne hasło dostarczane z systemem to dosłowniethis_password_is_insecure_and_should_be_updated.
Należy rozumieć, dlaczego ANON_KEY i SERVICE_ROLE_KEY nie mogą być wymyślonymi wartościami. Oba są tokenami JWT podpisanymi za pomocą JWT_SECRET. Gateway weryfikuje ten podpis przy każdym żądaniu, dlatego klucz, który nie pasuje do tego sekretu, jest odrzucany z błędem {"message":"Invalid authentication credentials"}. Jest to najczęstszy problem podczas samodzielnego hostowania: operator zmienia JWT_SECRET, ale pozostawia klucze demonstracyjne. Zawsze należy wygenerować wszystkie 3 wartości razem.
SERVICE_ROLE_KEY należy traktować jak hasło konta root. Całkowicie omija zabezpieczenia na poziomie wierszy. Należy umieszczać je wyłącznie w kodzie po stronie serwera.
SITE_URL i API_EXTERNAL_URL należy ustawić na adres, pod którym użytkownicy będą faktycznie uzyskiwać dostęp do usługi, na przykład https://supabase.example.com. Auth tworzy na podstawie tych wartości łącza potwierdzenia adresu e-mail i powrotu OAuth. Pozostawienie wartości http://localhost:8000 powoduje kierowanie każdego użytkownika na jego własny komputer.
Następnie należy sprawdzić skonfigurowane wartości:
sh run.sh secretsUruchomienie i potwierdzenie poprawnego działania
sh run.sh start
docker compose psrun.sh start opakowuje docker compose up -d --wait, dlatego nie zwraca wyniku, dopóki testy poprawności działania nie zakończą się pomyślnie. Każda usługa powinna mieć stan running (healthy) lub running. Pierwsze uruchomienie trwa od dwóch do czterech minut, ponieważ Postgres wykonuje skrypty inicjalizacyjne, zanim jakikolwiek inny komponent będzie mógł nawiązać połączenie.
Jeśli kontener jest uruchamiany ponownie, należy odczytać jego dzienniki, podając nazwę usługi:
docker compose logs db
docker compose logs authStudio jest następnie dostępne na porcie 8000 i poprosi o ustawioną nazwę użytkownika oraz hasło do panelu.
Nie wystawiaj portu 8000 do publicznego Internetu
Kong na porcie 8000 obsługuje zwykły protokół HTTP. Wszystkie klucze API i wszystkie hasła użytkowników są przesyłane przez sieć jawnym tekstem. Dane uwierzytelniające Studio korzystają z uwierzytelniania podstawowego, które polega na kodowaniu base64, a nie na szyfrowaniu.
Należy umieścić przed nim odwrotny serwer proxy, zakończyć tam TLS (transport layer security) oraz powiązać Kong z adresem loopback, aby nic innego nie mogło uzyskać do niego dostępu. W docker-compose.yml mapowanie portów kong zmienia się na 127.0.0.1:8000:8000, a serwer proxy przekazuje żądania do tego portu. W sekcji Traefik przed kilkoma aplikacjami Compose opisano konfigurację certyfikatów.
Pozostałe porty również należy zamknąć w zaporze sieciowej, ponieważ Docker publikuje porty, zapisując własne reguły iptables, których standardowa konfiguracja ufw nie uwzględnia. Ten problem opisano w sekcji dlaczego kontenery Docker ignorują reguły ufw.
Wykonuj kopię zapasową bazy danych, a nie katalogu
Dane Postgres znajdują się w montowaniu bind mount pod adresem ./volumes/db/data. Skopiowanie tego katalogu podczas działania kontenera tworzy niespójną kopię, ponieważ Postgres buforuje zapisy, a pliki na dysku są spójne dopiero w punkcie kontrolnym. Przywrócenie takiej kopii zwykle się powiedzie, ale czasami po cichu utracone zostaną ostatnie transakcje. Jest to najgorszy możliwy scenariusz awarii kopii zapasowej.
Zamiast tego wykonaj zrzut. pg_dumpall działa wewnątrz kontenera i tworzy spójny obraz danych:
docker exec -t supabase-db pg_dumpall -U postgres > supabase-$(date +%F).sqlPrzed użyciem pliku sprawdź, czy nie jest pusty. Następnie zgodnie z harmonogramem przesyłaj zrzuty poza serwer. Do tego służy szyfrowane tworzenie kopii zapasowych poza serwerem za pomocą restic. W tym samym czasie wykonuj kopię zapasową .env. Utrata JWT_SECRET spowoduje unieważnienie każdego wydanego tokenu i uniemożliwi odczyt każdego przechowywanego zaszyfrowanego sekretu.
Przesłane pliki znajdują się w ./volumes/storage. Są to zwykłe pliki, dlatego można je po prostu skopiować.
Aktualizacja bez utraty danych
Supabase przypina wersje obrazów w docker-compose.yml, dlatego nic się nie zmieni, dopóki nie zostanie wykonana aktualizacja. Za każdym razem najpierw należy utworzyć zrzut.
docker compose pull
sh run.sh recreaterecreate zatrzymuje stos i uruchamia go ponownie na nowych obrazach. Dane pozostają zachowane, ponieważ znajdują się w powiązanych montowaniach na hoście, a nie wewnątrz kontenerów. Przed przejściem na nową wersję główną należy zapoznać się z plikiem CHANGELOG.md w repozytorium, ponieważ aktualizacje głównych wersji Postgres nie są wykonywane automatycznie i wymagają utworzenia zrzutu oraz jego odtworzenia.
Aby uwzględnić zmiany w samym pliku Compose, należy ponownie sklonować repozytorium nadrzędne i skopiować jego katalog docker do projektu, uważając, aby nie nadpisać .env.
Pełny reset, który usuwa wszystko, w tym bazę danych, jest wykonywany za pomocą oddzielnego skryptu wymagającego potwierdzenia:
sh reset.shFAQ
Dlaczego wywołania API zwracają komunikat „Invalid authentication credentials”?
Wartość ANON_KEY lub SERVICE_ROLE_KEY nie została podpisana za pomocą JWT_SECRET znajdującego się obecnie w .env. Bramka weryfikuje podpis przy każdym żądaniu i odrzuca niezgodność. Wygeneruj wszystkie trzy wartości jednocześnie za pomocą sh utils/generate-keys.sh --update-env, a następnie uruchom sh run.sh recreate, aby usługi odczytały nowe wartości.
Czy można uruchomić self-hosted Supabase na VPS z 2 GB pamięci?
Nie w sposób niezawodny. Od lipca 2026 stos podczas bezczynności zużywa około 3 GB, ponieważ uruchamia około czternastu usług. Z tego powodu serwer z 2 GB traci kontenery z powodu działania mechanizmu out of memory killer, a w docker compose ps pojawia się kod zakończenia 137. W środowisku produkcyjnym należy użyć 8 GB. W przypadku samodzielnego tworzenia aplikacji 4 GB należy traktować jako minimum.
Czy self-hosted Supabase zawiera edge functions?
Tak. Plik Compose zawiera środowisko uruchomieniowe funkcji oparte na Deno. Obsługuje ono wszystko, co zostanie umieszczone w ./volumes/functions. Nie obejmuje globalnej sieci wdrażania platformy hostowanej. Funkcje są więc uruchamiane na jednym serwerze i w jednej lokalizacji.
Jak połączyć się bezpośrednio z bazą danych Postgres?
Użyj docker exec -it supabase-db psql -U postgres, aby otworzyć interaktywną powłokę bezpośrednio na serwerze. W przypadku klienta zewnętrznego połącz się przez Supavisor na porcie 5432, używając użytkownika postgres.<POOLER_TENANT_ID> i wartości POSTGRES_PASSWORD. Nie należy otwierać tego portu na internet. Dostęp należy uzyskać przez VPN lub tunel SSH.
Dlaczego odnośniki w wiadomościach e-mail z potwierdzeniem uwierzytelniania prowadziły do localhost?
Wartości SITE_URL i API_EXTERNAL_URL w .env pozostały domyślne. Usługa uwierzytelniania tworzy każdy odnośnik potwierdzenia i resetowania hasła na podstawie tych dwóch wartości. Wysyła więc adres skonfigurowany w tych ustawieniach. Ustaw obie wartości na rzeczywisty publiczny URL i utwórz stos ponownie.