Como hospedar o Directus em uma VPS com PostgreSQL e Docker Compose

Ilustração representando o Directus rodando em um servidor VPS integrado ao PostgreSQL via Docker

Fala aí, beleza? Pra hospedar o Directus numa VPS, o caminho oficial é o Docker: um docker-compose.yml sobe três serviços (PostgreSQL com a imagem postgis/postgis, Redis e o próprio Directus com a imagem directus/directus em versão fixada), e o Nginx entra na frente como proxy reverso com SSL

Neste guia o foco é deixar a coisa pronta pra produção: banco privado, uploads persistentes, segredos trocados, healthchecks corretos e a licença MSCL conferida antes de qualquer uso comercial 🙂

A base de tudo é a documentação oficial de deploy do Directus

O que você precisa antes de instalar o Directus na VPS

Você precisa de um servidor com Docker e o plugin Compose, acesso root e um domínio apontado pro IP da máquina

A documentação diz o porquê de usar Docker: ele elimina muitos problemas de configuração ligados ao ambiente

E o Directus é distribuído como imagem Docker, então um ambiente com suporte a Docker é obrigatório

Quanto de hardware o Directus pede?

Pelos requisitos oficiais do Directus:

  • Mínimo obrigatório: 1x 0,25 vCPU / 512 MB
  • Mínimo recomendado: 2x 1 vCPU / 2 GB

Dimensione pela linha do recomendado, beleza?

A mesma VPS vai rodar o PostgreSQL e o Redis junto com o Directus, então ir no mínimo obrigatório é pedir pra ter dor de cabeça

Checklist do servidor:

  • Docker Engine com o plugin Compose
  • PostgreSQL em versão LTS (é o que o Directus suporta, além de MySQL, SQLite, MS SQL Server, MariaDB, CockroachDB e OracleDB)
  • Acesso root
  • Domínio apontado pro IP da VPS (necessário pro SSL)
  • Portas 22, 80, 443 e 8055 liberadas no firewall

Qual VPS usar pro Directus?

A recomendação principal da Hora de Codar pra este projeto é a VPS da Hostinger (este artigo contém links de afiliado da Hostinger)

O motivo é técnico, não benchmark: segundo a página oficial de hospedagem Docker da Hostinger, os planos VPS trazem armazenamento NVMe SSD e processadores AMD EPYC

E tem dois detalhes que casam MUITO com este tutorial: um template de Ubuntu 24.04 64-bit com Docker já instalado e o Docker Manager no painel, uma interface web pra implantar e gerenciar contêineres, inclusive a partir de arquivos Docker Compose

Pra completar, o backup automático semanal vem por padrão, segundo a documentação oficial da Hostinger

Licença do Directus 12: quando você pode usar de graça em projeto comercial?

Resposta curta: depende do tamanho da tua empresa (ou se é projeto pessoal), e você precisa conferir isso ANTES de colocar em produção

A partir do Directus 12, o projeto passou a usar a Monospace Sustainable Core License (MSCL), uma licença customizada baseada na Fair Core License

O código é source-available

Cada versão converte pra GPL-3.0 depois de 4 anos

Como a licença é aplicada na prática?

O Directus 12 aplica a licença ativamente: a instância self-hosted roda no tier Core por padrão, e limites maiores e recursos extras exigem licença válida (breaking changes da v12)

Quem atualiza pra v12 e está acima dos limites do Core ganha 30 dias de carência antes de um fluxo de resolução entrar em ação, segundo a documentação oficial de breaking changes

Em qual perfil você se encaixa?

  • Projeto pessoal ou de teste, sem registrar grant: roda no tier Core, que é o padrão e é gratuito, mas vem com limites: 3 seats, 25 coleções e sem SSO
  • Pessoa física em projeto pessoal, ou pessoa/empresa com menos de US$ 5 milhões de receita anual e menos de 50 funcionários: pode pedir uma chave gratuita de uso comercial pelo Open Innovation Grant, com seats e coleções ilimitados, SSO e policies de acesso customizadas
  • Organização acima desses limites: ainda pode rodar no tier Core gratuito (dentro dos limites dele) ou, se precisar de mais, contratar o tier Team pago ou falar direto com o time de vendas do Directus

Tome cuidado com isso!

Recomendação de CMS sem olhar licença é o tipo de coisa que vira problema só depois que o cliente já está usando

Passo a passo: Directus com PostgreSQL e Docker Compose na VPS

Se tu já subiu uma API NestJS com Docker Compose ou um WordPress em Docker Compose, a lógica é bem semelhante: um arquivo descreve os serviços, volumes guardam o que não pode sumir e o proxy expõe tudo com HTTPS

Passo 1: preparar o servidor

Ação: na Hostinger, use o template Ubuntu 24.04 com Docker já instalado: ele poupa a etapa de instalação do Docker, mas os passos de Nginx, SSL e systemd do tutorial oficial de deploy em Ubuntu (testado nas versões 20.04 e 22.04) continuam valendo

Em outro ambiente, instale o Docker (Engine, CLI, containerd, Buildx e o plugin Compose) seguindo esse mesmo tutorial oficial de deploy em Ubuntu

Depois, libere no UFW as portas 22, 80, 443 e 8055, como o tutorial oficial faz

Resultado esperado: Docker e Compose disponíveis no terminal e o firewall com essas quatro portas abertas

Erro comum: ativar o UFW sem liberar a porta 22

Aí o firewall corta o teu próprio SSH e você fica trancado pra fora do servidor haha

Passo 2: criar o docker-compose.yml

Ação: crie uma pasta pro projeto e, dentro dela, o docker-compose.yml com base no exemplo oficial

A estrutura segue o exemplo oficial: três serviços, cada um com healthcheck declarado (é isso que sustenta o depends_on com condition: service_healthy lá na frente), e os volumes abaixo garantem que uploads e extensões não se percam quando o contêiner é recriado

# Baseado no docker-compose oficial do Directus
services:
  database:
    image: postgis/postgis:17-3.5
    volumes:
      - ./data/database:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: "directus"
      POSTGRES_PASSWORD: "troque-esta-senha"
      POSTGRES_DB: "directus"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U directus"]
      interval: 10s
      timeout: 5s
      retries: 5
    # sem "ports": o banco fica só na rede interna do Compose

  cache:
    image: redis:7
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  directus:
    image: directus/directus:12.5.0
    ports:
      - "8055:8055"
    volumes:
      - ./uploads:/directus/uploads
      - ./extensions:/directus/extensions
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8055/server/ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    depends_on:
      database:
        condition: service_healthy
      cache:
        condition: service_healthy
    environment:
      SECRET: "troque-por-um-valor-aleatorio-longo"
      DB_CLIENT: "pg"
      DB_HOST: "database"
      DB_PORT: "5432"
      DB_DATABASE: "directus"
      DB_USER: "directus"
      DB_PASSWORD: "troque-esta-senha"
      CACHE_ENABLED: "true"
      CACHE_AUTO_PURGE: "true"
      CACHE_STORE: "redis"
      REDIS: "redis://cache:6379"
      PUBLIC_URL: "https://seudominio.com"
      # ADMIN_EMAIL e ADMIN_PASSWORD são opcionais: pré-configuram o admin
      # em setups automatizados. Sem elas, você cria o admin no onboarding
      # do Studio, no primeiro acesso.

E o que significam esses volumes?

Cada linha liga uma pasta da VPS a uma pasta do contêiner

Se o contêiner for recriado, o que está em ./uploads, ./extensions e ./data/database continua lá

E os healthchecks, pra que servem exatamente?

Sem eles, o Compose não tem como saber se o PostgreSQL ou o Redis já estão prontos pra receber conexão: ele só sabe se o contêiner "existe", não se o serviço dentro dele já respondeu

Com pg_isready no database, redis-cli ping no cache e um wget em /server/ping no próprio directus, cada serviço avisa quando está de fato saudável, e só assim o depends_on com condition: service_healthy consegue segurar a subida do Directus até banco e cache estarem prontos

Sem esse healthcheck, o directus tentaria conectar antes da hora e o docker compose up tende a falhar ou ficar travado

A versão 12.5.0 é a mais recente do Directus na data da consulta, publicada em 07/10/2026 (releases no GitHub)

A documentação recomenda fixar a versão explicitamente, então nada de latest

Repare que o serviço database não tem ports

O Directus fala com o PostgreSQL pela rede interna do Compose, então não tem por que publicar a porta 5432 pra internet

Resultado esperado: uma pasta com o docker-compose.yml, os três serviços declarados e o healthcheck de cada um presente no arquivo

Erro comum: esquecer um dos volumes, o que só aparece como problema depois, quando o contêiner é recriado e os arquivos somem. Outro erro comum é copiar o depends_on com condition: service_healthy sem copiar o healthcheck correspondente: sem o healthcheck, essa condition nunca é satisfeita

Passo 3: definir os segredos

Ação: preencha as variáveis de verdade

  • DB_CLIENT como pg, junto com DB_HOST, DB_PORT, DB_DATABASE, DB_USER e DB_PASSWORD
  • SECRET trocado por um valor aleatório e seguro
  • PUBLIC_URL com a URL final do teu domínio, como pede o tutorial oficial de deploy em Ubuntu
  • ADMIN_EMAIL e ADMIN_PASSWORD, opcionais: se preenchidas, pré-configuram a conta de administrador; se deixadas de lado, você cria o admin na tela de onboarding do Studio, no primeiro acesso

E o Redis, precisa mesmo?

Ele é usado pra cache e escala, é recomendado pra cache, mas só vira obrigatório quando o Directus é escalado horizontalmente

Numa instância única dá pra rodar sem, porém manter como no exemplo oficial (com o healthcheck do passo anterior) é o caminho mais tranquilo

Resultado esperado: nenhuma variável com valor de exemplo

Erro comum: subir com o SECRET de exemplo da documentação

A própria documentação avisa que esse valor precisa ser trocado

E não comite esse arquivo com as senhas num repositório público, né?

Passo 4: subir os contêineres e acessar o painel

Ação: suba a stack com o plugin Compose (docker compose up -d já deixa em segundo plano; o tutorial oficial de Ubuntu, por sua vez, roda docker compose up em primeiro plano e deixa tudo em segundo plano depois, através de um serviço systemd) e abra http://IP_DO_SERVIDOR:8055 no navegador

Com os healthchecks declarados no passo 2, o Compose só marca database e cache como saudáveis depois que pg_isready e redis-cli ping respondem de verdade, e só então inicia o directus

Se preferir interface visual, o Docker Manager da Hostinger implanta e gerencia contêineres a partir do arquivo Compose

Checagem: a tela de login do Directus aparece; se você definiu ADMIN_EMAIL e ADMIN_PASSWORD, entre com esses dados: senão, complete o onboarding do Studio na primeira tela

Erro comum: a página não carrega porque a porta 8055 não foi liberada no UFW no passo 1

Passo 5: colocar o Nginx como proxy reverso com SSL

Ação: siga a etapa de Nginx e SSL do tutorial oficial de Ubuntu

Que proxy reverso?

É o Nginx recebendo o acesso do domínio nas portas 80 e 443 e repassando pro Directus na 8055, como um recepcionista que atende na porta da frente e encaminha pra sala certa

O SSL é o que faz o painel abrir com HTTPS

Resultado esperado: o Directus respondendo no teu domínio com HTTPS

Erro comum: tentar gerar o certificado antes de o domínio apontar pro IP da VPS

Checagem final: o setup está pronto?

  1. Faça login pelo domínio com HTTPS
  2. Envie um arquivo pela biblioteca de arquivos do painel
  3. Reinicie os contêineres
  4. Confira se o arquivo continua lá
  5. Confira com docker compose ps se os três serviços aparecem como healthy

Se passou nos cinco, os uploads estão persistindo e os healthchecks estão funcionando de verdade 😀

Erros comuns ao rodar o Directus na VPS e como corrigir

O serviço directus não sobe, fica esperando database ou cache

Causa: o depends_on usa condition: service_healthy, mas o healthcheck do serviço correspondente não foi declarado (ou foi declarado errado)

Solução: confira se database tem o healthcheck com pg_isready e se cache tem o healthcheck com redis-cli ping, exatamente como no Passo 2

Prevenção: depois de qualquer edição no docker-compose.yml, rode docker compose ps e confira se os três serviços aparecem como healthy antes de seguir em frente

Uploads ou extensões sumiram depois de recriar o contêiner

Causa: faltou o volume ./uploads:/directus/uploads ou ./extensions:/directus/extensions

Solução: adicione os volumes no docker-compose.yml e recrie o serviço

Prevenção: faça a checagem final do passo a passo (upload, reinício, conferência) logo na primeira instalação

Os dados do banco se perderam

Causa: o serviço database rodou sem o volume ./data/database:/var/lib/postgresql/data

Solução: declare o volume antes de cadastrar conteúdo de verdade

Se os dados já foram embora, o caminho é restaurar um backup

Prevenção: conferir os volumes antes de liberar o painel pra equipe

A atualização quebrou a instância

Causa: imagem com tag latest ou upgrade feito sem ler as notas da versão

A v12.5.0, por exemplo, traz possíveis breaking changes em validação de acesso por IP em policies, enforcement de 2FA pelas policies efetivas e na configuração de cache de schema (a variável CACHE_SCHEMA_MAX_ITERATIONS foi removida), segundo a documentação oficial de breaking changes

Solução: volte pra versão fixada anterior e restaure o backup, se o banco já tiver sido alterado

Prevenção: versão sempre fixada e leitura das notas antes de trocar

Recursos limitados ou aviso de licença depois de ir pra v12

Causa: acabaram os 30 dias de carência e a instância está acima dos limites do tier Core

Solução: confira teu perfil de licença e, se tu se encaixa, registre a instância no Open Innovation Grant

Prevenção: resolver a licença durante a carência, não depois

Como evitar a maioria desses problemas?

Na Hostinger, a VPS já recebe backup automático toda semana, segundo a documentação oficial

Além disso, dá pra criar snapshots manuais: crie um antes de cada upgrade (só dá pra ter um snapshot por vez, e ele expira em 1 dia)

Se precisar de backup diário, ele é um upgrade pago

Repare que nenhum desses erros se resolve trocando de servidor, todos são de configuração e rotina…

Quer ver outro deploy em VPS na prática?

O vídeo abaixo é do canal Hora de Codar e mostra a configuração da Evolution API e do n8n numa VPS

Conteúdo complementar do Hora de Codar para conhecer o canal; não é uma demonstração específica desta notícia ou versão.

Próximo passo: atualizar o Directus com segurança

Com o Directus no ar, o próximo passo é ter uma rotina de manutenção, antes que a próxima versão te pegue de surpresa

  • Antes de mudar a versão fixada no docker-compose.yml, crie um snapshot manual da VPS
  • Leia as notas da versão nova, principalmente a parte de breaking changes
  • Confira se a instância está no tier certo ou registrada no Open Innovation Grant
  • Depois do upgrade, repita a checagem final: login, upload, reinício, conferência do arquivo e docker compose ps mostrando os serviços healthy

Se ainda vai contratar o servidor, dá pra conferir a VPS para este projeto e já começar pelo template Ubuntu 24.04 com Docker

Bora colocar teu CMS no ar? Até o próximo post! 🙂

Perguntas frequentes

Preciso de licença paga pra usar o Directus em produção?

Não necessariamente. O tier Core é gratuito, mas vem com limites (3 seats, 25 coleções e sem SSO). Se tua empresa tem menos de US$ 5 milhões de receita anual e menos de 50 funcionários, ou se é um projeto pessoal de pessoa física, dá pra pedir uma chave gratuita de uso comercial sem esses limites pelo Open Innovation Grant. Acima desses limites, as opções são continuar no Core gratuito dentro dos limites dele, contratar o tier Team pago ou falar com o time de vendas do Directus.

Quanto de hardware a VPS precisa ter pro Directus?

O mínimo obrigatório, segundo a documentação oficial, é 1x 0,25 vCPU com 512 MB de RAM, e o mínimo recomendado é 2x 1 vCPU com 2 GB. Como a mesma VPS também vai rodar o PostgreSQL e o Redis, dimensionar pela linha do recomendado evita dor de cabeça.

O Redis é obrigatório pra rodar o Directus?

Não. O Redis é recomendado pra cache, mas só se torna obrigatório quando o Directus é escalado horizontalmente (várias instâncias rodando em paralelo). Numa instância única, dá pra rodar sem ele, mas manter como no exemplo oficial, com o healthcheck correspondente, é o caminho mais tranquilo.

Por que o serviço directus não sobe mesmo com database e cache rodando?

Isso costuma acontecer quando o docker-compose.yml usa depends_on com condition: service_healthy, mas os serviços database e cache não têm um healthcheck declarado. Sem o healthcheck (pg_isready no database e redis-cli ping no cache), o Compose nunca marca esses serviços como saudáveis, e o directus fica esperando uma condição que não se cumpre. A correção é declarar o healthcheck em cada serviço, como no exemplo oficial.

A VPS da Hostinger já vem com backup?

Sim. Por padrão, a VPS da Hostinger recebe um backup automático semanal. Também dá pra criar snapshots manuais (só um por vez, e ele expira em 1 dia). Se você precisar de backup diário, esse recurso é um upgrade pago.


Quer aprender mais sobre inteligência artificial e programação na prática? Conheça o canal Hora de Codar no YouTube e acompanhe os próximos vídeos.

Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

Formações

Formação Claude Code

Formação Claude Code

Domine Claude Code do absoluto zero até o avançado

  • 120 aulas
  • 4 projetos
  • 9h 48min

Blog | Mais populares