Skip to content

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. 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. 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. 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. 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. 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. 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"
Documentação · Devora Cloud · Devora Cloud