Solução de problemas
Problemas prováveis ao rodar o TWS Panel em uma VPS real e como resolver cada um.
Porta 25 bloqueada pelo provedor
Seção intitulada “Porta 25 bloqueada pelo provedor”Sintomas: você envia e recebe e-mails internamente, mas nenhuma mensagem de fora chega;
testes de conexão na porta 25 falham (telnet SEU-IP 25 trava).
Causa: muitos provedores (Hetzner, AWS, OCI, contas novas em geral) bloqueiam a porta 25 de saída/entrada por padrão como medida anti-spam.
Solução:
- Abra um chamado no provedor pedindo a liberação da porta 25 (alguns têm opção no painel);
- Confirme o UFW:
sudo ufw allow 25/tcp; - Verifique do lado de fora:
nc -zv SEU-IP 25.
E-mail caindo em spam
Seção intitulada “E-mail caindo em spam”Sintomas: mensagens enviadas chegam, mas vão direto para a pasta de spam (especialmente Gmail e Outlook).
Diagnóstico (nesta ordem):
- Envie para mail-tester.com — ele aponta exatamente o que está faltando. Alvo: ≥ 9/10.
- Abra o checklist DNS do domínio no painel e clique em Verificar agora: A, MX, SPF, DKIM e DMARC precisam estar ✅.
- PTR amarelo (sem nome reverso válido) é a causa nº 1: só o provedor da VPS configura. O card do PTR diz onde trocar (Contabo, Hetzner, Vultr) ou gera o texto pronto do chamado.
- Confira as listas de bloqueio no painel (Envios → Reputação). Se estiver listado, use Pedir remoção na lista correspondente.
- Veja a nota de entregabilidade em Envios → Nota: ela lista o que falta, item por item.
- IP novo sem reputação: nas primeiras 2–4 semanas envie volume baixo e crescente (dezenas/dia, não milhares). Veja “warm-up de IP” em email-deliverability.md.
- Mantenha o DMARC em
p=nonecoletando relatórios até tudo estabilizar; endureça paraquarantine/rejectdepois.
Certificado TLS do Stalwart inválido
Seção intitulada “Certificado TLS do Stalwart inválido”Sintomas: clientes de e-mail avisam “certificado não confiável” ao conectar.
Causa: o certificado de mail.<domínio> ainda não foi emitido — enquanto isso o
Stalwart usa um autoassinado. Quase sempre falta o registro A de mail.<domínio>
apontando para a VPS, ou ele está com a nuvem laranja na Cloudflare.
Solução: abra E-mail no painel: o card “Certificado do servidor de e-mail” diz o
que falta. Crie o registro A de mail.<domínio> com o IP da VPS (na Cloudflare, nuvem
cinza), confira as portas 80 e 443 liberadas e clique em “Conferir de novo”. O painel
instala e renova o certificado sozinho.
Domínios e SSL
Seção intitulada “Domínios e SSL”Caddy não emite certificado
Seção intitulada “Caddy não emite certificado”Sintomas: site no ar só em HTTP, erro de ACME nos logs do container paas-caddy
(docker logs paas-caddy).
Causa: o registro A do domínio ainda não aponta para a VPS (ou a propagação não terminou).
Solução:
- Use o botão Verificar DNS no painel antes de emitir o certificado;
- Confira manualmente:
dig +short seudominio.comdeve retornar o IP da VPS; - Se acabou de criar o registro, aguarde a propagação (minutos a horas, dependendo do TTL);
- Se houver proxy na frente (ex.: Cloudflare com nuvem laranja), desative-o para a emissão inicial. O painel não tem modo DNS-01: o Caddy central espera conexão direta nas portas 80/443. Depois que o certificado sair, use Tentar emitir agora na página Certificados se ele ainda estiver pendente;
- Verifique se o UFW/liberação do provedor permite 80 e 443.
O site abre sem www, mas com www não (ou o contrário)
Seção intitulada “O site abre sem www, mas com www não (ou o contrário)”Sintoma: example.com abre e www.example.com dá erro de conexão (ou o inverso). Na página
Domínios do projeto, a linha do par mostra “aguardando o DNS”.
Causa: cada nome precisa do seu próprio registro de DNS. O painel só pede o certificado do par (e liga o redirecionamento para o nome principal) depois que o DNS dele aponta para a VPS; antes disso, o nome não responde.
Solução:
- Em Domínios → Conectar novo domínio, digite o nome e veja a orientação: um registro para cada
nome (
@ewww, tipo A com o IP da VPS; owwwtambém pode ser um CNAME para o domínio sem www). - No Cloudflare, deixe a nuvem cinza nos dois. Com a laranja, a linha do par diz que o proxy está ligado e o certificado não sai.
- Clique em Verificar DNS: o resultado vem nome por nome. O par que falha é só aviso.
- Se a linha disser “já é de outro projeto”, “é do painel” ou “é do servidor de e-mail”, o painel não toma o nome: use outro projeto ou remova o nome de lá.
- Para não ter o redirecionamento, clique em Desligar na linha do par.
Limites conhecidos (documentados, não implementados): a verificação do DNS do par lê só registros A (IPv4); um registro AAAA apontando para outro lugar não é detectado. Depois de reiniciar o painel sem resposta de DNS, um par que já redirecionava só é mantido quando a primeira conferência responder; até lá ele não é recriado.
A verificação do domínio de aplicações falha
Seção intitulada “A verificação do domínio de aplicações falha”Sintomas: em Configurações → Domínio de aplicações, Verificar DNS e salvar mostra “Não foi salvo” e uma mensagem do servidor, em português mesmo com a interface em inglês.
Causas e soluções:
- Só existe o registro do nome exato (
apps.example.com). A verificação consulta um nome aleatório (paas-check-…apps.example.com), então só um registro curinga (*.apps) passa. Crie o registro com o nome*.apps(ou*.apps.example.com, conforme o provedor). - Nuvem laranja da Cloudflare: a mensagem fala em “proxy da Cloudflare”. Mude o registro curinga para a nuvem cinza (“Somente DNS”). Atrás do proxy, o certificado de cada projeto não sai.
- IP errado, ou mais de um registro A: deixe só o IP da VPS.
- Registro AAAA para outro lugar: apague o AAAA curinga (ou aponte para o IPv6 da VPS, se o painel o conhece).
- “O DNS não respondeu agora”: nada foi salvo e nada mudou; tente de novo em instantes.
- Acabou de criar o registro: espere a propagação (minutos a horas) e verifique de novo.
- Confira de fora:
dig +short qualquer-coisa.apps.example.comdeve devolver o IP da VPS.
Certificado de um projeto não sai (limite do Let’s Encrypt)
Seção intitulada “Certificado de um projeto não sai (limite do Let’s Encrypt)”Sintomas: o navegador mostra erro de certificado ao abrir o projeto (o Caddy redireciona o HTTP para HTTPS), e a página Certificados mostra o domínio como “Falhou”.
Causa: o Let’s Encrypt limita a 50 certificados novos por semana por domínio registrado (para
projeto-k3x9q.apps.example.com, o domínio registrado é example.com), e a 5 certificados idênticos
por semana. Criar e apagar muitos projetos em poucos dias esgota o limite dos 50. O limite dos idênticos
só atinge domínio próprio (repetir o mesmo nome): cada endereço sob o domínio de aplicações ganha um
sufixo novo a cada criação.
Solução:
-
Abra Certificados e leia a causa que o painel mostra (mensagem do servidor, em português).
-
Se for o limite, espere: ele volta aos poucos ao longo da semana. O painel não consegue contorná-lo.
-
Depois, clique em Tentar emitir agora. Enquanto isso o painel segue com as tentativas automáticas, com intervalo crescente.
-
Para não gastar o limite à toa, não apague e recrie projetos várias vezes. No assistente, o projeto é criado com um endereço provisório (
nome-xxxxx.localhost, único, sem IP e sem certificado público) e só troca para o endereço sob a base ao clicar em Criar projeto. -
Para não gastar o limite ao restaurar numa VPS nova, restaure a cópia externa cifrada do painel: ela traz os certificados e a conta do Let’s Encrypt do Caddy (veja Restaurar em outro servidor).
Recebi o alerta “Certificado de … não renovou” ou “emissão falhando repetidamente”
Seção intitulada “Recebi o alerta “Certificado de … não renovou” ou “emissão falhando repetidamente””Sintomas: um alerta (e um aviso no Telegram ou no e-mail) diz que o certificado automático de um nome não renovou, está prestes a vencer ou que o Caddy tenta emitir e falha repetidamente.
Causa: o Let’s Encrypt não manda mais e-mail de vencimento, então o painel confere sozinho a cada 30 minutos. O alerta aparece quando o Caddy devia ter renovado e não renovou (falta 1/4 da validade), ou quando o log mostra 3 ou mais rodadas de falha durante pelo menos 1 hora. A causa mais comum é o DNS do nome ter deixado de apontar para a VPS, a nuvem laranja da Cloudflare ou as portas 80 e 443 fechadas.
Solução:
- Abra Certificados: o cartão do nome mostra o estado do alerta e a causa traduzida, com o que fazer.
- Corrija a causa (DNS, nuvem cinza, portas) e clique em Tentar emitir agora.
- O alerta se resolve sozinho depois de duas conferências seguidas sem problema (cerca de 1 hora). Se você já o reconheceu, ele não volta enquanto o problema durar.
Projeto com endereço provisório (nome-xxxxx.localhost)
Seção intitulada “Projeto com endereço provisório (nome-xxxxx.localhost)”Sintomas: o projeto mostra um aviso âmbar “Endereço provisório” e o endereço nome-xxxxx.localhost não abre.
Causa: o assistente cria o projeto com esse endereço provisório e só o troca ao clicar em Criar projeto.
Se você fechou o assistente antes, o projeto ficou com ele. .localhost sempre aponta para o computador de quem
acessa, não para a VPS, então ele não funciona num painel público.
Solução: abra o projeto, vá em Domínios (o aviso tem o atalho) e troque o endereço:
- com o domínio de aplicações configurado, clique em Usar o endereço automático (…): o painel adiciona o endereço sob a base, o torna principal e remove o provisório (se algo falhar, clique de novo e ele continua de onde parou);
- sem o domínio de aplicações, a tela explica as saídas: Configurar o domínio de aplicações (em Configurações) ou Conectar novo domínio com um domínio seu.
Não edite o /etc/hosts: isso não faz o
site da VPS aparecer.
Domínio .localhost não abre (painel na sua máquina)
Seção intitulada “Domínio .localhost não abre (painel na sua máquina)”Sintomas: meuapp.localhost não resolve no navegador, com o painel rodando no seu próprio computador.
Solução: .localhost depende do sistema operacional resolver para 127.0.0.1 — funciona
nativamente no Linux/macOS modernos e no Chrome; se falhar, adicione ao /etc/hosts:
127.0.0.1 meuapp.localhost. Isso vale só para o painel local. Em dev, lembre-se de que .localhost é servido em HTTP puro.
Painel e wizard
Seção intitulada “Painel e wizard”Painel não abre depois do install.sh
Seção intitulada “Painel não abre depois do install.sh”Sintomas: o endereço https://SEU-IP-COM-HÍFENS.sslip.io/?token=... não abre, ou o
instalador avisa que ele não respondeu em 3 minutos.
Checklist (na VPS, em /opt/tws-panel):
- Os containers estão de pé?
sudo docker compose ps; - O certificado saiu? A causa mais comum são as portas 80 e 443 bloqueadas num firewall do
provedor (no painel da hospedagem): libere as duas e rode
sudo docker compose restart. Para ver o que o proxy diz:sudo docker logs paas-caddy --tail 50; - Enquanto isso, o acesso por túnel SSH funciona: o banner do instalador mostra o comando (veja Acesso por túnel SSH);
- Token correto? Reexiba o link completo com
sudo ./scripts/show-token.sh.
O painel em si escuta só dentro da VPS (127.0.0.1): o endereço http://SEU-IP:9000 não abre,
de propósito.
Salvar ou clicar falha com 403 forbidden_origin
Seção intitulada “Salvar ou clicar falha com 403 forbidden_origin”Sintomas: o painel abre, mas as ações que gravam (salvar, entrar, fazer deploy) voltam
403 forbidden_origin. Acontece quando você abre o painel atrás de outro proxy (um balanceador,
um túnel, um CDN) que remove o cabeçalho Sec-Fetch-Site ou reescreve o Origin. Atrás do Caddy que
o próprio painel instala, não é preciso configurar nada.
Correção (na VPS, em /opt/tws-panel):
-
Acrescente ao
.enva origem exata em que você abre o painel, sem barra no fim; separe várias com vírgula. Não use*:ALLOWED_ORIGINS=https://painel.example.com -
Recrie o container para ele ler a variável:
Janela do terminal sudo docker compose up -d
A variável vem vazia por padrão, e então só a origem do próprio painel é aceita.
“Token inválido” no wizard
Seção intitulada ““Token inválido” no wizard”Sintoma: o assistente diz “Token inválido. Confira o valor exibido pelo instalador no terminal.”
Causa: token errado, copiado com espaço extra, ou o servidor foi reiniciado com outro
SETUP_TOKEN no ambiente.
Solução: o arquivo /data/setup-token (volume paas_data) tem prioridade sobre a variável
SETUP_TOKEN do ambiente, que é só o ponto de partida da instalação. Reexiba a URL + token com
sudo ./scripts/show-token.sh (lê o volume, sem reinstalar nada). Ao concluir o assistente o token é
apagado de propósito; para reabrir o assistente e gerar um token novo, rode
sudo ./scripts/reset-setup.sh (ou --full, que também apaga a conta de administrador).
Perdi o token / quero recomeçar o wizard do zero
Seção intitulada “Perdi o token / quero recomeçar o wizard do zero”- Perdeu o token:
sudo ./scripts/show-token.sh— imprime o banner com a URL e o token. - Recomeçar o wizard:
sudo ./scripts/reset-setup.sh— apagasetup-state.jsondo volume (com confirmação interativa) e o wizard volta ao passo 0; a conta admin é mantida. Com--fullapaga tambémusers.jsonesessions.json(a conta admin deixa de existir e todos são deslogados). Os dois modos geram um setup token NOVO (o antigo deixa de valer; veja comshow-token.sh). Projetos, domínios e e-mail NÃO são tocados.
Perdi o acesso SSH durante o hardening
Seção intitulada “Perdi o acesso SSH durante o hardening”Não entre em pânico — é para isso que existe o rollback. O hardening agenda uma reversão
automática (via at) que restaura a configuração anterior em ~5 minutos se você não
confirmar o acesso pelo painel. Aguarde o rollback, entre novamente e revise o plano de
correções antes de reaplicar. Cada arquivo alterado tem backup em /var/backups/paas/.
Perdeu a chave, a senha ou o celular da verificação em duas etapas? Veja
Perdi o acesso: e agora?.
Deploy bloqueado por guardrail
Seção intitulada “Deploy bloqueado por guardrail”Sintomas: deploy retorna 409 guardrail_blocked e a UI abre o modal de blockers.
Solução: o modal lista cada violação com evidência (arquivo:serviço) e sugestão de
correção. Corrija o compose/código (recomendado) — ex.: remova a porta do banco publicada no
host, troque credenciais fracas. Se tiver certeza do risco (ex.: banco exposto só em ambiente
de homologação), marque Entendo os riscos e quero fazer o deploy mesmo assim (override) e confirme o override — ele fica auditado em
Auditoria (guardrail.override). Quatro regras protegem o próprio painel e não aceitam override
(panel-resource, network-hijack, reserved-name, panel-image): o compose precisa mudar.
O que cada regra barra, como ler a mensagem e exemplos de antes e depois estão em
Como escrever um compose que o painel aceita.
“You have to authenticate first” no servidor de e-mail depois de restaurar
Seção intitulada ““You have to authenticate first” no servidor de e-mail depois de restaurar”A senha de administração do servidor de e-mail guardada no painel e a que está na configuração do servidor em execução são diferentes (acontece depois de restaurar o painel ou o e-mail). O painel confere isso depois da restauração e tenta corrigir, e Sincronizar com o servidor de e-mail também tenta o reparo uma vez antes de mostrar erro. Se ainda aparecer “O painel não conseguiu autenticar no servidor de e-mail”, clique em Reparar agora (na própria tela de E-mail, junto da mensagem, ou no aviso âmbar do Dashboard), ou pare o servidor de e-mail e inicie de novo em E-mail. Nenhum dado é apagado. Detalhes em Restaurar em outro servidor.
“535 5.7.8 Authentication credentials invalid” no teste de notificação por e-mail
Seção intitulada ““535 5.7.8 Authentication credentials invalid” no teste de notificação por e-mail”O servidor de e-mail recusou o login da caixa postmaster@ porque a senha que o painel guardou não é a que o servidor tem (acontece depois de restaurar o e-mail: a caixa volta com a senha do backup). O painel mostra “a senha guardada pelo painel não é a do servidor” e, em Configurações → Notificações, o botão Abrir E-mail para sincronizar. Em E-mail, clique em Sincronizar com o servidor de e-mail: ele confere e reaplica a senha que o painel guarda para a postmaster@ e para as caixas de projeto (“Realinhei a senha de N caixas”). Se preferir, use Trocar senha na caixa postmaster@ do domínio. Só as senhas que diferem são regravadas. Atenção: a senha de uma caixa de projeto (ou da postmaster@) trocada direto no webmail é desfeita por esse passo; caixa de usuário comum não é tocada. Depois, envie o teste de novo. Detalhes em Restaurar em outro servidor.
“Cannot connect to the Docker daemon”
Seção intitulada ““Cannot connect to the Docker daemon””Solução: systemctl status docker — se o install.sh acabou de instalar, pode ser
necessário sudo systemctl enable --now docker. O painel acessa apenas o socket local
(/var/run/docker.sock); nunca exponha o Docker via TCP.
Build falha com “requires BuildKit” ou “buildx plugin not found”
Seção intitulada “Build falha com “requires BuildKit” ou “buildx plugin not found””O log mostra buildx Docker CLI plugin not found: falling back to the classic builder seguido de algo como
the --chmod option requires BuildKit. Dockerfiles modernos (COPY --chmod/--link, RUN --mount, segredos,
heredocs) só constroem com o plugin buildx do Docker.
O painel já cuida disso: a imagem dele traz o buildx (é o Docker dentro do painel que faz os builds), o deploy confere o plugin antes de construir e pede BuildKit no build. Se mesmo assim a mensagem aparecer:
- Atualize o painel para a versão mais recente (a imagem antiga não traz o buildx). O deploy para cedo, com a mensagem “O Docker do painel está sem o plugin buildx”, em vez de quebrar no meio do build.
- Abra Saúde da máquina (no fim do assistente, ou em /health) e veja o cartão Docker e BuildKit. Ele mostra o buildx no painel e no Docker da VPS. Se a VPS estiver sem o plugin e a origem do Docker for reconhecida, clique em Corrigir (senha do painel e código do app; o painel instala só o pacote do plugin e o Docker não reinicia).
- Se a origem não for reconhecida, o cartão mostra os comandos para rodar por SSH:
sudo apt-get update && sudo apt-get install -y docker-buildx-plugin(Docker do repositório oficial,docker-ce) ousudo apt-get install -y docker-buildx(pacotedocker.iodo Ubuntu). Confira comdocker buildx version.
Conferir se o projeto voltou bem depois de reiniciar a VPS
Seção intitulada “Conferir se o projeto voltou bem depois de reiniciar a VPS”Abra o projeto e vá na aba Logs. No topo, cada serviço mostra se está rodando, se está
saudável, quantos reinícios teve e desde quando está no ar. Um serviço “reiniciando sem
parar” ou “com problema” é o que precisa de atenção: escolha-o no seletor Serviço e leia as
últimas linhas (as de erro vêm marcadas). Se a aba disser que o projeto está parado, use
Iniciar no topo da página do projeto. Se disser que o Docker não está respondendo, o
problema é da máquina, não do projeto: veja systemctl status docker na VPS.
O Dashboard diz “Monitoramento em modo reduzido” ou mostra “Sem dados”
Seção intitulada “O Dashboard diz “Monitoramento em modo reduzido” ou mostra “Sem dados””- “Modo reduzido”: o container do painel foi criado antes da atualização que trouxe as montagens do servidor (
/proce/sys/fs/cgroup, somente leitura). Recrie-o:cd /opt/tws-panel && sudo git pull && sudo docker compose up -d --build(umdocker restartnão pega montagens). Para conferir:sudo docker inspect tws-panel --format '{{json .Mounts}}'. - “Sem dados” logo depois da atualização: a primeira medida leva cerca de 1 minuto; as taxas (CPU, rede, disco) precisam de duas leituras, então aparecem a partir do segundo minuto.
- “A última gravação das medidas falhou”: confira o espaço livre em disco da VPS (
df -h); o painel nunca para por isso, apenas fica sem guardar histórico até haver espaço. - “Steal” do provedor sempre em 0: normal em alguns tipos de virtualização que não o informam; não é erro.
Não achou seu problema?
Seção intitulada “Não achou seu problema?”Abra uma issue no repositório com o template de bug — inclua logs (sem segredos), versão do commit e ambiente. Veja CONTRIBUTING.md.