SSD Nodes Learn 8GB RAM — $66/taon
Mga Gabay Matt ConnorNi Matt Connor · Na-update 2026-08-02

Paano Mag-self-host ng Supabase sa VPS gamit ang Docker

Alamin ang mga secret na dapat palitan, papel ng 14 na service, RAM requirements, backup, at ligtas na pag-update ng official Supabase Docker stack sa sarili mong VPS.

Ang itinatayo mo

Ang self-hosting ng Supabase ay nangangahulugang pinapatakbo mo ang opisyal na Docker Compose stack sa sarili mong server: Postgres, isang REST API sa harap nito, isang auth service, file storage, realtime websockets, at ang Studio dashboard. Magko-clone ka ng isang repository, mag-e-edit ng isang .env file, at magpapatakbo ng humigit-kumulang labing-apat na container na sama-samang gumaganang parang Supabase project na ikaw ang kumokontrol.

Maikli ang installation. Ang karaniwang nagkakaproblema ay ang .env file. May kasama itong mga demo secret na naka-publish sa repository, at ang stack na sinimulan gamit ang mga default na iyon ay bukas sa sinumang makahanap nito. Tinutukoy ng gabay na ito ang mga secret na kailangan mong palitan, ang gamit ng bawat service, kung gaano karaming memory ang talagang kailangan ng stack, at kung paano ito i-update nang hindi dine-delete ang database.

Kung bago sa iyo ang Compose mismo, basahin muna ang Mga pangunahing kaalaman sa Docker Compose sa isang VPS. Ipinapalagay ng lahat ng nasa ibaba na nagpi-print na ng version ang docker compose version.

Mga aktuwal na laman ng stack

Ang Supabase ay hindi iisang program. Ang Compose file ay nagsisimula ng magkakahiwalay na service sa iisang network. Kapag alam mo kung ano ang bawat isa, mas madali mong madi-debug ang maraming pangalan ng container.

  • Ang db ay PostgreSQL na may naka-load na Supabase extension. Dito kumokonekta ang lahat ng iba pang service. Kapag unhealthy ang container na ito, mabibigo rin ang lahat ng iba pa.
  • Ang kong ang API gateway. Nakikinig ito sa port 8000 at niruruta ang /rest/v1/, /auth/v1/, at /storage/v1/ sa tamang backend. Ito lang ang container na dapat mong i-expose.
  • Ang rest ay PostgREST. Binabasa nito ang schema ng Postgres at inihahain ito bilang REST API. Dahil dito, nagiging bagong endpoint ang bagong table nang walang kailangang code.
  • Ang auth ay GoTrue. Gumagawa ito ng JSON web token (JWT) na tumutukoy sa iyong mga user.
  • Ang storage at imgproxy ang humahawak sa mga file upload at pag-resize ng image.
  • Ang realtime ang nagse-stream ng mga pagbabago sa database gamit ang websockets.
  • Ang studio at meta ang dashboard at ang admin API na ginagamit nito.
  • Ang analytics (Logflare) at vector ang kumokolekta ng mga log, at ang supavisor ang Postgres connection pooler.

Iyan ang dahilan kung bakit ganoon ang mga resource number sa ibaba. Hindi lang database ang pinapatakbo mo. Database ito na may kasamang isang dosenang support service.

Pagpapalaki: maglaan ng 8 GB ng RAM

Ang stack ay gumagamit ng humigit-kumulang 2.5 hanggang 3 GB na resident memory sa bagong install, noong Hulyo 2026, bago isama ang sarili mong data o network traffic. Ang analytics service at ang Studio Node.js process ang dalawang pinakamalalaking indibidwal na consumer. Magsisimula ang mga container sa isang 2 GB server, ngunit mawawala ang isa sa kernel out-of-memory killer, karaniwang analytics o db. Ang sintomas ay container na patuloy na nagre-restart na may exit code 137.

Maglaan ng 8 GB ng RAM at 4 vCPU para sa anumang kritikal sa iyo. Gumagana ang 4 GB para sa isang solo development instance kung tatanggapin mong magiging mabagal ang sabay na heavy query at Studio session. Mahalaga rin ang disk dahil nasa ilalim ng project directory ang Postgres, storage volume, at log data. Magsimula sa 40 GB at i-monitor ito.

Pag-install: i-clone ang opisyal na repository

Kinokopya ng suportadong paraan ang docker directory mula sa pangunahing repository papunta sa sarili mong project directory. Mahalaga ang paghihiwalay na ito dahil hindi mao-overwrite ng kasunod na git pull ang iyong .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

Nagda-download ang docker compose pull ng ilang gigabyte ng images. Dapat itong magtapos na may Pulled na marka sa bawat service. Ang error na manifest unknown dito ay nangangahulugang inalis sa upstream ang naka-pin na image tag. Ang tamang pag-aayos ay kumuha ng mas bagong kopya ng repository sa halip na manu-manong mag-edit ng mga tag.

Mga lihim na dapat mong palitan bago ang unang pagsisimula

Gawin ito bago mo simulan ang stack, hindi pagkatapos. Isinusulat ang ilan sa mga value na ito sa data sa unang boot, kaya ang pagpapalit sa mga ito pagkatapos ay nangangahulugang kailangan mong i-reset ang database.

May generator ang repository na gumagawa ng bawat value nang tama, kabilang ang dalawang API key na dapat pirmahan gamit ang bago mong JWT secret.

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

Isinusulat ng script na iyon ang mga bagong value para sa JWT_SECRET, ANON_KEY, SERVICE_ROLE_KEY, SECRET_KEY_BASE, REALTIME_DB_ENC_KEY, VAULT_ENC_KEY, PG_META_CRYPTO_KEY at mga Logflare token sa .env. Kailangan nito ang openssl, na makikita sa anumang karaniwang Ubuntu image.

May dalawang value na hindi nito itinatakda at dapat mong i-edit nang manu-mano sa .env:

  • POSTGRES_PASSWORD. Mga letra at digit lamang ang gamitin. Sinisira ng punctuation dito ang connection string na binubuo ng ilang serbisyo sa pamamagitan ng pagsasama ng mga string. Nagmumukhang authentication error ang failure sa halip na parsing error, kaya sa maling lugar naghahanap ng sanhi ang mga tao.
  • DASHBOARD_USERNAME at DASHBOARD_PASSWORD. Ito ang basic authentication credentials para sa Studio. Ang default password na kasama sa package ay literal na this_password_is_insecure_and_should_be_updated.

Unawain kung bakit hindi maaaring basta imbentuhin ang ANON_KEY at SERVICE_ROLE_KEY. Pareho itong JWT na nilagdaan gamit ang JWT_SECRET. Bine-verify ng gateway ang signature na iyon sa bawat request, kaya tinatanggihan ang key na hindi tumutugma sa secret mo gamit ang {"message":"Invalid authentication credentials"}. Ito ang pinakakaraniwang self-hosting failure: pinalitan ng operator ang JWT_SECRET ngunit pinanatili ang mga demo key. Palaging buuin nang sabay ang tatlong ito.

Ituring ang SERVICE_ROLE_KEY na parang root password. Lubusan nitong nilalampasan ang row level security. Dapat itong nasa server-side code lamang at wala nang iba.

Itakda ang SITE_URL at API_EXTERNAL_URL sa address na aktuwal na pupuntahan ng mga user, halimbawa https://supabase.example.com. Binubuo ng Auth ang mga link para sa email confirmation at OAuth callback mula sa mga value na iyon. Kung iiwan ang mga ito sa http://localhost:8000, ipapadala ang bawat user sa sarili nilang machine.

Pagkatapos, suriin ang mga value mo:

sh run.sh secrets

Simulan ito at kumpirmahing gumagana nang maayos

sh run.sh start
docker compose ps

Binabalot ng run.sh start ang docker compose up -d --wait, kaya hindi ito nagbabalik hangga't hindi pumapasa ang mga health check. Dapat ipakita ng bawat service ang running (healthy) o running. Tumatagal ng dalawa hanggang apat na minuto ang unang boot dahil pinapatakbo muna ng Postgres ang mga initialization script nito bago makakonekta ang iba pang component.

Kung paulit-ulit na nagre-restart ang isang container, basahin ang mga log nito ayon sa service name:

docker compose logs db
docker compose logs auth

Nasa port 8000 na ang Studio, at hihingin nito ang dashboard username at password na itinakda mo.

Huwag ilagay ang port 8000 sa pampublikong internet

Plain HTTP ang ginagamit ng Kong sa port 8000. Dumadaan sa network nang clear text ang bawat API key at bawat password ng user. Basic authentication ang ginagamit ng Studio credentials, na base64 encoding at hindi encryption.

Maglagay ng reverse proxy sa harap nito. Doon i-terminate ang TLS (transport layer security). I-bind ang Kong sa loopback address upang wala nang ibang makapag-access dito. Sa docker-compose.yml, nagiging 127.0.0.1:8000:8000 ang port mapping na kong, at doon nagpapasa ang proxy. Sinasaklaw ng Traefik sa harap ng ilang Compose app ang bahagi tungkol sa certificate.

Isara rin ang iba pang port sa firewall. Naglalagay ang Docker ng sarili nitong iptables rules kapag nagpa-publish ito ng mga port, kaya hindi nakikita ng karaniwang ufw configuration ang mga ito. Ipinaliwanag ang problemang ito sa kung bakit binabalewala ng Docker containers ang iyong ufw rules.

I-back up ang database, hindi ang directory

Nasa bind mount ang data ng Postgres sa ./volumes/db/data. Kapag kinopya mo ang directory habang tumatakbo ang container, magkakaroon ka ng hindi kumpletong kopya dahil bina-buffer ng Postgres ang mga write at nagiging consistent lang ang mga file sa disk kapag may checkpoint. Karaniwang gagana ang pag-restore nito, pero kung minsan ay tahimik nitong mawawala ang mga huling transaction. Ito ang pinakamasamang posibleng failure mode para sa isang backup.

Mag-dump sa halip. Tumatakbo ang pg_dumpall sa loob ng container at gumagawa ito ng consistent na snapshot:

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

Tiyaking hindi empty ang file bago mo ito pagkatiwalaan. Pagkatapos, regular na ipadala ang mga dump na iyon sa labas ng server. Para rito ang encrypted offsite backups gamit ang restic. I-back up din ang iyong .env kasabay nito. Kapag nawala ang JWT_SECRET, magiging invalid ang bawat na-issue nang token at hindi na mababasa ang bawat naka-store na encrypted secret.

Nasa ./volumes/storage ang mga uploaded file. Ordinary files ang mga ito, kaya sapat na ang plain copy.

Mag-update nang hindi nawawala ang data

Naka-pin ang mga image version ng Supabase sa docker-compose.yml, kaya walang magbabago hangga't hindi mo ito ina-update. Gumawa muna ng dump sa bawat pagkakataon.

docker compose pull
sh run.sh recreate

Ihihinto ng recreate ang stack at sisimulan itong muli gamit ang mga bagong image. Mananatili ang iyong data dahil nasa bind mounts ito sa host, hindi sa loob ng mga container. Basahin ang CHANGELOG.md sa repository bago magsagawa ng major version jump, dahil hindi awtomatiko ang mga major upgrade ng Postgres at nangangailangan ang mga ito ng dump at restore.

Para makuha ang mga pagbabago mismo sa Compose file, i-clone muli ang upstream repository at kopyahin ang directory na docker nito sa iyong project. Tiyaking hindi mao-overwrite ang .env.

Ang full reset, na nagbubura ng lahat kabilang ang database, ay hiwalay na script at humihingi ito ng confirmation:

sh reset.sh

FAQ

Bakit nagbabalik ng "Invalid authentication credentials" ang mga API call ko?

Hindi nilagdaan ang iyong ANON_KEY o SERVICE_ROLE_KEY gamit ang JWT_SECRET na kasalukuyang nasa .env. Bine-verify ng gateway ang signature sa bawat request at tinatanggihan ang mga hindi nagtutugmang signature. Muling i-generate ang tatlo gamit ang sh utils/generate-keys.sh --update-env, pagkatapos ay patakbuhin ang sh run.sh recreate para mabasa ng mga serbisyo ang mga bagong value.

Maaari ko bang patakbuhin ang self-hosted Supabase sa isang 2 GB VPS?

Hindi ito maaasahan. Umaabot sa halos 3 GB ang idle memory usage ng stack noong July 2026 dahil nagpapatakbo ito ng humigit-kumulang fourteen services. Dahil dito, inaalis ng out of memory killer ang mga container sa isang 2 GB server, at makikita mo ang exit code 137 sa docker compose ps. Gumamit ng 8 GB para sa production, at ituring ang 4 GB bilang minimum para sa solo development.

Kasama ba sa self-hosted Supabase ang edge functions?

Oo. Kasama sa Compose file ang Deno based functions runtime, at sine-serve nito ang anumang ilalagay mo sa ilalim ng ./volumes/functions. Hindi kasama rito ang global deployment network ng hosted platform. Kaya tumatakbo ang iyong functions sa iisang server at sa iisang lokasyon.

Paano ako direktang kokonekta sa Postgres database?

Gamitin ang docker exec -it supabase-db psql -U postgres para sa interactive shell sa mismong server. Para sa external client, kumonekta sa Supavisor sa port 5432 gamit ang user na postgres.<POOLER_TENANT_ID> at ang iyong POSTGRES_PASSWORD. Huwag buksan ang port na iyon sa internet. I-access ito sa pamamagitan ng VPN o SSH tunnel.

Iniwan sa default values ang SITE_URL at API_EXTERNAL_URL sa .env. Binubuo ng auth service ang bawat link para sa confirmation at password reset mula sa dalawang value na ito. Kaya ipinapadala nito ang address na itinakda rito. Itakda ang dalawang value sa iyong totoong public URL at muling i-create ang stack.