Documentação
Manual da Devora
Como colocar uma aplicação no ar aqui — e o que preparar no código para que ela funcione.
É uma IA lendo isto? /llms.txt traz o mesmo conteúdo em texto puro.
Fundamento
Como as coisas se organizam
Uma organização é a conta. Dentro dela ficam os projetos, e é o projeto que você abre para trabalhar.
Dentro do projeto ficam os serviços — os programas que rodam —, os endereços por onde eles respondem, as variáveis de ambiente e, opcionalmente, um banco de dados. Um repositório com um site e uma API vira UM projeto com dois serviços, não dois projetos.
As aplicações rodam distribuídas entre as máquinas do cluster. Os bancos ficam num servidor separado, dedicado só a eles, alcançável pela rede privada.
Primeiro passo
Publicar uma aplicação do GitHub
- 1
Conecte o GitHub
Uma vez por conta. A lista de repositórios se atualiza sozinha sempre que você abre a tela, e também quando você adiciona ou remove um repositório da instalação lá no GitHub.
- 2
Escolha o repositório
A plataforma lê os arquivos dele e sugere o construtor, a porta e o banco que ele parece precisar. Confira a sugestão — ela acerta na maioria dos casos, não em todos.
- 3
Confirme a porta
É o erro mais comum. Se o app escuta em outra coisa que não a 3000, diga aqui. Endereço apontando para a porta errada responde 502 com o app perfeitamente saudável por trás.
- 4
Publique
A primeira construção leva alguns minutos: o código é clonado, a imagem é montada e enviada ao registro interno, e só então o serviço sobe.
O projeto nasce com um endereço gratuito em .apps.devoracloud.com, já com HTTPS. Ele serve para testar antes de apontar o domínio de verdade.
Repositório com vários programas dentro (monorepo) precisa dizer qual Dockerfile usar — apps/web/Dockerfile, por exemplo. O contexto da construção continua sendo a raiz, então o lockfile compartilhado é encontrado normalmente. Para publicar o segundo programa, acrescente um serviço ao mesmo projeto em vez de criar outro.
Estrutura
Vários serviços no mesmo projeto
Um produto costuma ter mais de um programa: o site que o cliente abre e a API que responde por trás. Os dois vivem no mesmo repositório, cada um com seu Dockerfile e sua porta.
Eles ficam no MESMO projeto, como serviços. O serviço novo herda o repositório e a branch do principal — muda só o caminho do Dockerfile e a porta.
As variáveis do projeto valem para todos os serviços. É o que importa na prática: o segredo que assina o token no site e é conferido pela API fica gravado uma vez, no projeto, e os dois enxergam. Variável que precisa ser só de um serviço também é possível.
O serviço principal é o que responde pelo endereço do projeto. Ele não pode ser removido — removê-lo é excluir o projeto.
Dados
Banco de dados
Dentro do projeto, o botão de adicionar cria um banco. Estão disponíveis PostgreSQL, MySQL, MariaDB, MongoDB e Redis.
Assim que o banco fica de pé, a variável de conexão é injetada na aplicação automaticamente — DATABASE_URL para os relacionais, REDIS_URL para o Redis. Você não copia nem cola nada.
Por padrão o banco só é alcançável pela rede privada. Abrir o acesso público publica uma porta dedicada, protegida por firewall; use quando precisar conectar de um cliente SQL na sua máquina, e feche depois.
Antes de excluir
Excluir um banco apaga os dados de forma definitiva. Não existe cópia automática para restaurar depois. Tire seu próprio dump antes.
Endereços
Domínio próprio
- 1
Um registro TXT
Em _devora-verify.seudominio.com, com o valor que a tela mostra. É a prova de que o domínio é seu.
- 2
Um CNAME
Apontando para o endereço que a tela indica — o subdomínio do próprio projeto, não a zona genérica.
Provou uma vez, provou a zona inteira: se exemplo.com já foi verificado na sua conta, então app.exemplo.com e painel.exemplo.com entram já verificados, sem TXT novo.
O certificado HTTPS é emitido automaticamente assim que o DNS aponta para cá. Cada endereço tem a sua própria porta: dá para o site responder na 3000 e o painel na 8787 dentro do mesmo projeto.
A ordem importa
Aponte o DNS antes de esperar o certificado. Enquanto o domínio resolver para outro servidor, a emissão falha — e cinco falhas seguidas bloqueiam aquele domínio por uma hora na autoridade certificadora.
Escala
Réplicas e escala automática
Um projeto pode rodar em várias cópias, espalhadas entre as máquinas. Com a escala automática ligada, a plataforma sobe e desce a quantidade conforme o uso de CPU, dentro do mínimo e do máximo que você definir. Isso funciona bem para aplicação sem estado.
Em três casos, mais de uma cópia causa perda de dado silenciosa — sem erro em log nenhum. Neles, deixe a escala automática desligada e a quantidade fixa em 1:
- O app guarda estado em memória e grava o conjunto inteiro de volta. A última cópia a escrever apaga o que as outras fizeram.
- O app tem um agendador embutido (cobrança, sincronização, bloqueio por inadimplência). Duas cópias executam a rotina duas vezes.
- O app usa volume em disco. O volume é local da máquina — cada cópia enxerga uma pasta diferente, e uma remarcação de tarefa sobe com a pasta vazia.
Rotina
Deploy automático por push
Com o GitHub conectado, todo push na branch configurada dispara uma publicação nova. Não precisa clicar em nada.
A publicação aparece marcada como via GitHub, com o commit que a originou. Se o build falhar, a versão anterior continua no ar — a nova só substitui a antiga depois de subir.
A branch é a que o projeto declara. Repositório que usa master em vez de main funciona igual, desde que esteja escrito corretamente nas configurações.
Para quem escreve o código — pessoa ou IA
Preparar uma aplicação para a Devora
Estas são as regras que separam um app que sobe de primeira de um que sobe quebrado. Cada uma traz a consequência real de ignorá-la.
Leia a porta de process.env.PORT
Não fixe a porta no código. Escute em 0.0.0.0, nunca em localhost.
Se ignorar: O roteador entrega na porta declarada e ninguém atende. O visitante recebe 502 com o container saudável.
Rode as migrações na inicialização, não na construção
Um migrate deploy antes de subir o servidor. Durante a construção da imagem não existe banco para conectar.
Se ignorar: O banco fica com zero tabelas e o app responde erro na primeira consulta. Foi o defeito mais comum nas migrações reais.
Falhe alto quando a migração falhar
Se o migrate der erro, o processo deve morrer com a mensagem no log — não subir mesmo assim.
Se ignorar: O app fica no ar servindo erro, o painel mostra verde, e ninguém descobre até um cliente reclamar.
Variáveis NEXT_PUBLIC_* são argumentos de construção
No Next.js elas são gravadas dentro do pacote durante o build. Declare cada uma como ARG e promova a ENV antes da linha que constrói.
Se ignorar: O valor de desenvolvimento fica embutido para sempre. A API de produção continua apontando para localhost.
Nada importante no disco do container
Upload, imagem, anexo: mande para o armazenamento S3. Disco de container some quando a cópia é recriada.
Se ignorar: Os arquivos desaparecem no próximo deploy, sem aviso e sem como recuperar.
Não guarde estado só na memória do processo
Sessão, fila, cache compartilhado: coloque no banco ou no Redis. Com mais de uma cópia, cada processo tem a sua memória.
Se ignorar: O usuário perde a sessão a cada requisição que cai noutra cópia, e escritas somem sem erro nenhum.
Um agendador embutido exige uma cópia só
Se o app tem cron interno, diga isso a quem for publicar. A alternativa é mover a rotina para um serviço próprio.
Se ignorar: Cobrança em duplicidade, mensagem enviada duas vezes, cliente bloqueado por engano.
Responda algo em /
Qualquer resposta abaixo de 500 serve — inclusive um redirecionamento para o login. É por aí que a plataforma sabe que o app está vivo.
Se ignorar: O app é considerado fora do ar e o dono recebe aviso de queda que não existe.
Log no stdout, sem arquivo
Escreva na saída padrão. Não abra arquivo de log dentro do container.
Se ignorar: O log fica preso num disco que ninguém alcança, exatamente quando você precisa dele.
Todo segredo vem do ambiente
Chave de API, segredo de token, credencial de terceiro: só de variável de ambiente. Nunca comitado, nunca com valor padrão que funcione.
Se ignorar: O segredo vaza no repositório e passa a valer para qualquer um que clone o código.
Monorepo: um serviço por programa, no mesmo projeto
Site e API do mesmo repositório entram como dois serviços do mesmo projeto, cada um com seu Dockerfile e sua porta. Não crie dois projetos.
Se ignorar: Com dois projetos, os segredos precisam ser copiados de um para o outro na mão — e no dia em que um for trocado e o outro não, o token deixa de ser aceito e ninguém entende por quê.
Dockerfile: diga o caminho, mantenha o contexto na raiz
Em monorepo, informe o caminho completo do Dockerfile do serviço. O contexto continua na raiz para achar o lockfile compartilhado.
Se ignorar: A construção morre com "open Dockerfile: no such file or directory" num repositório que tem Dockerfile.
Honestidade
O que ainda não existe
Melhor saber antes de depender:
- Backup automático de banco. Não há motor de cópia rodando. Se os dados importam, tire seu próprio dump.
- Terminal SQL e troca de senha do banco. Dá para ver as credenciais, não para alterá-las pelo painel.
- Alerta de infraestrutura por e-mail. Queda de aplicação avisa por e-mail; disco enchendo, ainda não.
Esta lista é curta de propósito: cada item sai daqui quando for resolvido, e nada entra na documentação antes de funcionar.
Automação
API pública
REST versionada, autenticada por chave de API com escopo. A chave completa aparece uma única vez, no momento em que é criada.
curl https://api.devoracloud.com/v1/projects \ -H "Authorization: Bearer dc_live_..." \ -H "X-Devora-Org: minha-org"