SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor · Atualizado 2026-10-11

Como hospedar o Supabase em um VPS com Docker

Veja como executar a stack oficial do Supabase com Docker, trocar os segredos padrão, entender os 11 serviços, calcular a RAM e fazer backup e atualização.

O que você vai configurar

Hospedar o Supabase por conta própria significa executar a stack oficial do Docker Compose no seu servidor: Postgres, uma API REST à frente dele, um serviço de autenticação, armazenamento de ficheiros, WebSockets em tempo real e o dashboard Studio. Clone um repositório, edite um ficheiro .env e inicie onze contentores que, em conjunto, funcionam como um projeto Supabase sob o seu controlo.

A instalação é curta. O problema costuma estar no ficheiro .env. Ele inclui segredos de demonstração publicados no repositório, e uma stack iniciada com esses valores predefinidos fica acessível a qualquer pessoa que os encontre. Este guia explica quais os segredos que deve substituir, para que serve cada serviço, quanta memória a stack realmente precisa e como atualizá-la sem eliminar a base de dados.

Se o Compose ainda for novo para si, leia primeiro Noções básicas do Docker Compose num VPS. Tudo o que se segue pressupõe que docker compose version já apresenta uma versão.

O que a stack contém efetivamente

O Supabase não é um único programa. O ficheiro Compose inicia um conjunto de serviços separados na mesma rede. Saber qual é a função de cada um transforma uma parede de nomes de contentores num sistema que pode depurar.

  • db é o PostgreSQL com as extensões do Supabase carregadas. Todos os outros serviços comunicam com ele. Se este contentor não estiver saudável, todos os restantes também falham.
  • api-gw é o gateway da API. Desde a versão de agosto de 2026, executa o Envoy. Antes, era um serviço chamado kong, e o Kong continua disponível como substituição opcional. Escuta na porta 8000 e encaminha /rest/v1/, /auth/v1/ e /storage/v1/ para o backend correto. É o único contentor que deve expor.
  • rest é o PostgREST. Lê o esquema do Postgres e disponibiliza-o como uma API REST. Assim, uma tabela nova torna-se um novo endpoint sem escrever código.
  • auth é o GoTrue. Emite os tokens Web JSON (JWT) que identificam os utilizadores.
  • storage e imgproxy tratam dos carregamentos de ficheiros e do redimensionamento de imagens.
  • realtime transmite as alterações da base de dados através de websockets.
  • studio e meta são o dashboard e a API de administração que lhe dá suporte.
  • functions é o runtime edge baseado em Deno, e supavisor é o pooler de ligações do Postgres.

Os logs e as análises (Logflare e vector) saíram do ficheiro Compose predefinido em junho de 2026. Agora estão num ficheiro de substituição opcional que ativa com sh run.sh config add logs. Isto usa a mesma sobreposição de ficheiros Compose descrita em executar uma stack a partir de vários ficheiros Compose.

É por isso que os valores de recursos abaixo são os que são. Não está a executar uma base de dados. Está a executar uma base de dados mais dez serviços de suporte.

Dimensionamento: planeie 8 GB de RAM

A stack consumia aproximadamente 2.5 a 3 GB de memória residente numa instalação nova em julho de 2026, antes dos seus próprios dados ou tráfego. Nessa medição, o serviço de analytics e o processo Node.js do Studio eram os dois maiores consumidores individuais. O analytics já não faz parte da stack predefinida. Portanto, só consome memória se ativar a substituição da configuração de logs. Um servidor com 2 GB inicia os contentores, mas depois o kernel termina um deles através do out of memory killer. O sintoma é um contentor preso num ciclo de reinício, com o código de saída 137. A documentação de self-hosting do Supabase, consultada em outubro de 2026, indica 4 GB de RAM, 2 CPU cores e 40 GB de SSD como requisitos mínimos. Para uma configuração recomendada, indica 8 GB, 4 cores e 80 GB.

Use 8 GB de RAM e 4 vCPU para qualquer serviço de que dependa. 4 GB são suficientes para uma instância de desenvolvimento individual, desde que aceite que uma query pesada e uma sessão do Studio em simultâneo serão lentas. O disco também é importante, porque o Postgres, o volume de armazenamento e, se ativar os logs, os dados de log ficam todos no diretório do projeto. Comece com 40 GB e monitorize o consumo. Contar os serviços antes de escolher um plano é um hábito útil para qualquer software que aloje por conta própria, porque PhotoPrism e Immich também têm requisitos mínimos reais de RAM: a página de início rápido do Immich, consultada em outubro de 2026, exige pelo menos 6 GB de RAM e 2 CPU cores. Se ainda precisar de menos recursos do que isso para o seu projeto, compare com o que o plano gratuito cloud do Supabase inclui na prática, porque uma aplicação pequena, que se mantenha abaixo de 500 MB e nunca fique inativa durante uma semana, pode ser executada aí sem custos.

Instalação: clone o repositório oficial

O procedimento suportado copia o diretório docker do repositório principal para um diretório de projeto seu. Essa separação é importante, porque impede que um git pull posterior substitua o seu .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 transfere vários gigabytes de imagens. Deve terminar com todos os serviços marcados como Pulled. Um erro manifest unknown neste ponto significa que a tag da imagem fixada foi removida no repositório upstream. A correção é obter uma cópia mais recente do repositório, em vez de editar as tags manualmente.

Os segredos que deve alterar antes do primeiro arranque

Faça isto antes de iniciar a stack, não depois. Vários destes valores são gravados nos dados durante o primeiro arranque. Alterá-los mais tarde implica repor a base de dados.

O repositório inclui um gerador que produz todos os valores corretamente, incluindo as duas chaves de API que têm de ser assinadas com o seu novo segredo JWT.

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

Esse script grava novos valores para JWT_SECRET, ANON_KEY, SERVICE_ROLE_KEY, SECRET_KEY_BASE, REALTIME_DB_ENC_KEY, VAULT_ENC_KEY, PG_META_CRYPTO_KEY, os tokens Logflare, as chaves de protocolo S3 e MINIO_ROOT_PASSWORD em .env. Em outubro de 2026, também grava valores aleatórios para POSTGRES_PASSWORD e DASHBOARD_PASSWORD. Precisa de openssl, que está presente em qualquer imagem normal do Ubuntu. Como agora também reescreve a palavra-passe da base de dados, execute-o com --update-env apenas antes do primeiro arranque, nunca numa stack que já contenha dados.

Ainda vale a pena verificar manualmente dois valores em .env:

  • POSTGRES_PASSWORD. O script preenche-o com hexadecimal aleatório, o que é seguro. Se o substituir pelo seu próprio valor, use apenas letras e dígitos. A pontuação neste valor quebra as strings de ligação que vários serviços criam juntando strings. A falha parece um erro de autenticação, e não um erro de análise, o que leva a procurar a causa no local errado.
  • DASHBOARD_USERNAME e DASHBOARD_PASSWORD. Estas são as credenciais de autenticação básica do Studio. O script define uma palavra-passe aleatória, mas mantém o nome de utilizador predefinido supabase. A palavra-passe predefinida fornecida é literalmente this_password_is_insecure_and_should_be_updated. Se não executou o script, altere-a agora.

Entenda por que ANON_KEY e SERVICE_ROLE_KEY não podem ser inventadas. Ambas são JWTs assinadas com JWT_SECRET. O gateway aceita apenas as chaves exatas em .env, e os serviços atrás dele verificam a assinatura com base em JWT_SECRET. Por isso, uma chave que não corresponda é rejeitada com HTTP 401. O gateway Envoy predefinido responde 401 Unauthorized, tal como a substituição atual do Kong, que executa o Kong 3.9 e devolve {"message":"Unauthorized"}. As instalações anteriores a março de 2026 executavam o Kong 2.8, que responde {"message":"Invalid authentication credentials"}. Esta é a falha mais comum em instalações self-hosted: o operador alterou JWT_SECRET, mas manteve as chaves de demonstração. Gere as três em conjunto, sempre.

Trate SERVICE_ROLE_KEY como uma palavra-passe de root. Ignora completamente a segurança ao nível das linhas. Deve ser usada em código do lado do servidor e em nenhum outro local.

Defina SITE_URL como o endereço da sua aplicação e API_EXTERNAL_URL como o endereço público da API, com /auth/v1 no fim, por exemplo https://supabase.example.com/auth/v1. Defina SUPABASE_PUBLIC_URL com o mesmo endereço público, sem o caminho. O Auth cria as ligações de confirmação de email e de callback OAuth a partir desses valores. Se os deixar nos valores localhost predefinidos, todos os seus utilizadores serão encaminhados para a própria máquina.

Depois, verifique o que configurou:

sh run.sh secrets

Inicie-o e confirme que está saudável

sh run.sh start
docker compose ps

run.sh start envolve docker compose up -d --wait, por isso não retorna até que as verificações de integridade sejam concluídas com êxito. Cada serviço deve apresentar running (healthy) ou running. A primeira inicialização demora de dois a quatro minutos porque o Postgres executa os respetivos scripts de inicialização antes de qualquer outro componente poder estabelecer uma ligação.

Se um contentor estiver a reiniciar, leia os respetivos logs pelo nome do serviço:

docker compose logs db
docker compose logs auth

O Studio fica então disponível na porta 8000 e solicita o nome de utilizador e a palavra-passe do dashboard que definiu.

Não exponha a porta 8000 à Internet pública

O gateway na porta 8000 usa HTTP simples. Todas as chaves de API e palavras-passe de utilizadores atravessam a rede em texto simples. As credenciais do Studio usam autenticação básica, que é codificação base64 e não encriptação.

Coloque um reverse proxy à frente do gateway e termine o TLS (transport layer security) nesse proxy. Faça o gateway escutar no endereço de loopback para impedir qualquer outro acesso. Em docker-compose.yml, a linha da porta sob o serviço api-gw passa a ser 127.0.0.1:${API_GW_HTTP_PORT:-${KONG_HTTP_PORT:-8000}}:8000/tcp, e o proxy encaminha os pedidos para essa porta. Numa instalação anterior à mudança para Envoy em agosto de 2026, a mesma linha da porta fica sob um serviço chamado kong. O artigo Traefik à frente de várias aplicações Compose explica a parte dos certificados. Esse mesmo proxy acaba por ficar à frente de tudo o resto no servidor, desde esta stack até algo tão pouco sério como uma biblioteca Jellyfin reconstruída como uma loja de vídeo dos anos 90. Cada serviço deve usar um nome de host, e não outra porta aberta. Se um dashboard for apenas para si, não use o proxy. Aceda à porta de loopback através de um túnel SSH, como faz self-hosted open-kritt para manter completamente a interface de análise fora da Internet pública.

Feche também o restante no firewall. O Docker publica portas ao criar as suas próprias regras do iptables, que uma configuração ingénua do ufw não consegue ver. Essa armadilha é explicada em por que os contentores Docker ignoram as regras do ufw.

Faça backup do banco de dados, não do diretório

Os dados do Postgres ficam em um bind mount em ./volumes/db/data. Copiar esse diretório enquanto o container está em execução produz uma cópia inconsistente, porque o Postgres armazena gravações em buffers e os arquivos no disco só ficam consistentes em um checkpoint. A restauração normalmente funcionará, mas às vezes perderá silenciosamente as últimas transações. Esse é o pior tipo de falha possível em um backup.

Em vez disso, faça um dump. pg_dumpall é executado dentro do container e produz um snapshot consistente:

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

Verifique se o arquivo não está vazio antes de confiar nele. Depois, envie esses dumps para fora do servidor conforme uma programação definida. É para isso que servem os backups criptografados fora do servidor com restic. Um dump agendado que falha silenciosamente é indistinguível de nenhum backup. Por isso, configure o job do cron ou do systemd para enviar um alerta para o seu celular quando terminar com código diferente de zero. Faça backup do seu .env ao mesmo tempo. Perder JWT_SECRET invalida todos os tokens emitidos e torna ilegível todo segredo criptografado armazenado.

Os arquivos enviados ficam em ./volumes/storage. Eles são arquivos comuns, portanto uma cópia simples é suficiente.

Atualizar sem perder dados

O Supabase fixa as versões das imagens em docker-compose.yml, portanto nada muda até que você faça essa alteração. Vale a pena usar o mesmo princípio de fixação em qualquer stack montada manualmente. Por isso, um relay RustDesk auto-hospedado fixa as duas imagens do servidor em vez de seguir uma tag móvel. Uma atualização deve ser algo que você escolhe para uma manhã em que tenha tempo disponível. Faça um dump antes, sempre.

docker compose pull
sh run.sh recreate

recreate para a stack e inicia-a novamente com as novas imagens. Os seus dados permanecem porque estão nos bind mounts do host, e não dentro dos containers. Leia CHANGELOG.md no repositório antes de atualizar para uma versão principal, porque uma atualização principal do Postgres é uma etapa separada que recreate não executa. O Postgres 17 é o padrão desde junho de 2026. Uma instalação existente no Postgres 15 passa para essa versão com sudo bash utils/upgrade-pg17.sh, que usa pg_upgrade para migrar os dados no local e pede confirmação em cada etapa principal. Todos os containers precisam de estar em execução. Também é necessário ter espaço livre em disco equivalente a pelo menos duas vezes o tamanho da base de dados, mais 5 GB. O Supabase continua a recomendar um backup independente criado por você antes de iniciar.

Para aplicar alterações ao próprio ficheiro Compose, execute sh update.sh a partir do diretório do projeto. Em alternativa, execute sh update.sh --dry-run para ver primeiro o que seria alterado. O comando combina os ficheiros upstream com as suas próprias alterações. Nunca substitui valores existentes em .env; apenas acrescenta novas chaves. Antes de gravar, arquiva a sua configuração em backups/, mas não a base de dados. Uma instalação sem um ficheiro .supabase-version precisa de --from e da release a partir da qual foi iniciada. Isto é especialmente importante para a release de agosto de 2026. Ela substituiu o serviço kong por api-gw e exige uma atualização de docker-compose.yml. O procedimento manual também continua a funcionar: clone novamente o repositório upstream e copie o diretório docker para o seu projeto. Tenha cuidado para não substituir .env.

A reposição completa destrói tudo, incluindo a base de dados, e repõe .env nos valores predefinidos. O valor antigo é mantido como .env.old. É executada por um script separado e pede confirmação:

sh reset.sh

FAQ

Por que as minhas chamadas à API retornam "Invalid authentication credentials"?

Essa mensagem exata vem do Kong 2.8, o gateway usado na stack em instalações anteriores a março de 2026. O gateway Envoy predefinido e a configuração atual do Kong, que executa o Kong 3.9, comunicam o mesmo problema como um simples 401 Unauthorized. Em qualquer dos casos, a chave enviada não corresponde a ANON_KEY ou SERVICE_ROLE_KEY em .env, ou essas chaves não foram assinadas com JWT_SECRET atualmente definido em .env. Numa stack que nunca teve dados, regenere os três em conjunto com sh utils/generate-keys.sh --update-env. Numa stack em execução, execute o script sem a flag e responda no, para que este apenas apresente novos valores; copie JWT_SECRET, ANON_KEY e SERVICE_ROLE_KEY manualmente para .env e mantenha POSTGRES_PASSWORD inalterado. Em seguida, execute sh run.sh recreate para que os serviços leiam os novos valores.

Posso executar o Supabase self-hosted numa VPS com 2 GB?

Não de forma fiável. A documentação oficial do Supabase para self-hosting indica 4 GB de RAM como mínimo desde outubro de 2026, e a stack permanecia perto de 3 GB em julho de 2026, numa medição que incluía os serviços de logging, atualmente opcionais. Um servidor com 2 GB perde contentores para o out of memory killer, e verá o código de saída 137 em docker compose ps. Use 8 GB em produção e considere 4 GB o mínimo para desenvolvimento individual.

O Supabase self-hosted inclui edge functions?

Sim. O ficheiro Compose inclui o runtime de funções baseado em Deno e serve tudo o que colocar em ./volumes/functions. Não inclui a rede global de deployment da plataforma alojada. Por isso, as suas funções são executadas no seu único servidor, numa única localização.

Como me ligo diretamente à base de dados Postgres?

Use docker exec -it supabase-db psql -U postgres para abrir uma shell interativa no próprio servidor. Para um cliente externo, ligue-se através do Supavisor na porta 5432, com o utilizador postgres.<POOLER_TENANT_ID> e o seu POSTGRES_PASSWORD. Não exponha essa porta à Internet. Aceda através de uma VPN ou de um túnel SSH.

Por que motivo os emails de confirmação da autenticação apontavam para localhost?

SITE_URL e API_EXTERNAL_URL em .env mantiveram os valores predefinidos. O serviço de autenticação constrói todos os links de confirmação e reposição de palavra-passe a partir desses dois valores. Por isso, envia o endereço que recebeu na configuração. Defina ambos com o seu URL público real e recrie a stack.

Este artigo foi útil?