SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-27

Como instalar o Supabase com Docker em um VPS

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

O que você vai criar

Fazer self-hosting do Supabase significa executar a stack oficial do Docker Compose no seu próprio servidor: Postgres, uma API REST à sua frente, um serviço de autenticação, armazenamento de ficheiros, WebSockets em tempo real e o dashboard Studio. Você clona um repositório, edita um ficheiro .env e inicia cerca de catorze 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 são 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 é novo para você, leia primeiro Noções básicas do Docker Compose num VPS. Tudo abaixo pressupõe que docker compose version já apresenta uma versão.

O que a stack realmente contém

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 lista de nomes de contentores num sistema que pode ser depurado.

  • db é o PostgreSQL com as extensões do Supabase carregadas. Todos os outros serviços comunicam com ele. Se este contentor estiver não saudável, os restantes também falham.
  • kong é o gateway da API. Escuta na porta 8000 e encaminha /rest/v1/, /auth/v1/ e /storage/v1/ para o backend correto. É o único contentor que deve expor publicamente.
  • rest é o PostgREST. Lê o esquema do Postgres e disponibiliza-o como uma API REST. Assim, uma nova tabela torna-se um novo endpoint sem ser necessário escrever código.
  • auth é o GoTrue. Emite os JSON Web Tokens (JWT) que identificam os utilizadores.
  • storage e imgproxy tratam dos uploads de ficheiros e do redimensionamento de imagens.
  • realtime transmite 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.
  • analytics (Logflare) e vector recolhem os logs, e supavisor é o pooler de ligações do Postgres.

É por isso que os valores de recursos apresentados abaixo são os que são. Não está a executar apenas uma base de dados. Está a executar uma base de dados e uma dúzia de serviços de suporte.

Dimensionamento: planeie 8 GB de RAM

A stack utiliza 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. O serviço de analytics e o processo Node.js do Studio são os dois maiores consumidores individuais. Um servidor com 2 GB inicia os contentores, mas depois o kernel elimina um deles através do out-of-memory killer, normalmente analytics ou db. O sintoma é um contentor preso num ciclo de reinício com código de saída 137.

Use 8 GB de RAM e 4 vCPU para qualquer instalação da qual dependa. 4 GB são suficientes para uma instância de desenvolvimento individual, se aceitar que uma consulta 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 os dados de logs ficam todos no diretório do projeto. Comece com 40 GB e monitorize o consumo. Contar os serviços antes de escolher um plano é uma prática útil para qualquer software alojado por si, porque o PhotoPrism e o Immich têm requisitos mínimos reais de RAM muito acima do que as respetivas páginas de início rápido indicam.

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 no 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 e para os tokens do Logflare em .env. Precisa de openssl, que está presente em qualquer imagem normal do Ubuntu.

Há dois valores que o script não define e que deve editar manualmente em .env:

  • POSTGRES_PASSWORD. Use apenas letras e dígitos. A pontuação neste valor interrompe as strings de ligação que vários serviços montam pela concatenação de strings. A falha parece um erro de autenticação, não um erro de análise, o que leva a procurar o problema no local errado.
  • DASHBOARD_USERNAME e DASHBOARD_PASSWORD. Estas são as credenciais de autenticação básica do Studio. A palavra-passe predefinida incluída é literalmente this_password_is_insecure_and_should_be_updated.

Entenda por que razão ANON_KEY e SERVICE_ROLE_KEY não podem ser inventados. Ambos são JWTs assinados com JWT_SECRET. O gateway verifica essa assinatura em todos os pedidos. Por isso, uma chave que não corresponda ao seu segredo é rejeitada com {"message":"Invalid authentication credentials"}. Esta é a falha mais comum em instalações próprias: o operador altera JWT_SECRET, mas mantém as chaves de demonstração. Gere os três valores 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 usado em código do lado do servidor e em nenhum outro local.

Defina SITE_URL e API_EXTERNAL_URL para o endereço que os seus utilizadores vão realmente aceder, por exemplo https://supabase.example.com. O Auth cria as ligações de confirmação de email e de callback OAuth a partir desses valores. Se os deixar como http://localhost:8000, todos os seus utilizadores serão enviados para a própria máquina.

Depois, verifique o que tem:

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 Kong na porta 8000 usa HTTP simples. Cada chave de API e cada palavra-passe de utilizador atravessam a rede em texto simples. As credenciais do Studio usam autenticação básica, que é apenas codificação base64, não encriptação.

Coloque um reverse proxy à frente do serviço e termine o TLS (transport layer security) nesse proxy. Faça o Kong escutar no endereço de loopback para impedir qualquer outro acesso. Em docker-compose.yml, o mapeamento de portas kong passa a ser 127.0.0.1:8000:8000, e o proxy encaminha os pedidos para essa porta. Traefik à frente de várias aplicações Compose explica a parte dos certificados. Esse mesmo proxy acaba por ficar à frente de todos os outros serviços do servidor, desde esta stack até algo tão pouco sério como uma biblioteca Jellyfin reconstruída como uma videolocadora dos anos 90, e cada serviço precisa de um nome de host em vez de outra porta aberta. Se um dashboard for apenas para seu uso, ignore o proxy e aceda à porta de loopback através de um túnel SSH. É a mesma abordagem usada por self-hosted open-kritt para manter completamente a sua interface de análise fora da Internet pública.

Feche também o restante no firewall, porque 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 suas 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, por isso nada muda até que as atualize. Vale a pena copiar esta prática de fixação em qualquer stack que monte manualmente. É por isso que um relay RustDesk self-hosted fixa as duas imagens do servidor em vez de seguir uma tag mutável: uma atualização deve ser algo que escolhe fazer numa manhã em que tenha tempo para isso. Faça sempre um dump primeiro.

docker compose pull
sh run.sh recreate

recreate para a stack e inicia-a novamente com as imagens novas. Os seus dados permanecem disponíveis porque ficam nos bind mounts do host, e não dentro dos contentores. Consulte CHANGELOG.md no repositório antes de avançar para uma versão principal, porque as atualizações principais do Postgres não são automáticas e exigem um dump e uma restauração.

Para obter as alterações ao próprio ficheiro Compose, 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, que elimina tudo incluindo a base de dados, é feita por um script separado e pede confirmação:

sh reset.sh

FAQ

Por que minhas chamadas de API retornam "Credenciais de autenticação inválidas"?

Seu ANON_KEY ou SERVICE_ROLE_KEY não foi assinado com o JWT_SECRET atualmente definido em .env. O gateway verifica a assinatura de cada solicitação e rejeita valores incompatíveis. Gere os três novamente com sh utils/generate-keys.sh --update-env e execute sh run.sh recreate para que os serviços leiam os novos valores.

Posso executar o Supabase auto-hospedado em um VPS com 2 GB?

Não de forma confiável. A pilha fica próxima de 3 GB em estado ocioso desde July 2026 porque executa cerca de fourteen serviços. Por isso, um servidor com 2 GB perde containers para o out of memory killer, e você vê 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 auto-hospedado inclui edge functions?

Sim. O arquivo Compose inclui o runtime de funções baseado em Deno e serve tudo o que você colocar em ./volumes/functions. Ele não inclui a rede global de implantação da plataforma hospedada. Portanto, suas funções são executadas no seu único servidor, em uma única localização.

Como me conecto diretamente ao banco de dados Postgres?

Use docker exec -it supabase-db psql -U postgres para abrir um shell interativo no próprio servidor. Para um cliente externo, conecte-se ao Supavisor na porta 5432 com o usuário postgres.<POOLER_TENANT_ID> e seu POSTGRES_PASSWORD. Não exponha essa porta à internet. Acesse-a por uma VPN ou por um túnel SSH.

Por que os e-mails de confirmação da autenticação direcionaram para localhost?

SITE_URL e API_EXTERNAL_URL em .env permaneceram com os valores padrão. O serviço de autenticação cria todos os links de confirmação e redefinição de senha a partir desses dois valores. Por isso, ele envia o endereço configurado. Defina ambos com sua URL pública real e recrie a pilha.