Voltar ao Blog
HermesTailscaleTroubleshootingSelf-Hosting

Hermes Agent com Tailscale não conecta: soluções

O Hermes Desktop não alcança seu gateway remoto pelo Tailscale? Quatro causas cobrem quase todos os casos, do bind em localhost ao regex de CORS.

Por Hermify Team||9 min de leitura
Cena escura com o wordmark do Tailscale sobre um laptop tentando alcançar um gateway remoto do Hermes através de uma malha, com o texto em negrito 'Tailscale Not Connecting'

A Tailnet Está No Ar e o Hermes Continua Sem Responder

Você instalou o Tailscale no VPS, entrou na tailnet pelo laptop e confirmou que os dois lados se pingam nos endereços 100.x.x.x. O hermes serve está rodando no host com a porta aberta, e o app Hermes Desktop no laptop fica girando em "Could not connect to Hermes gateway." Nada no log do gateway parece bravo. Nada no Tailscale aparece em vermelho.

Essa falha silenciosa quase sempre é uma de quatro causas, e três delas falham em silêncio por design. Este post percorre cada uma, como confirmar qual é a sua e a correção exata. Comece pelo topo: a primeira causa pega a maioria dos setups remotos recém-montados, e cada causa seguinte assume que as anteriores já foram descartadas.

Causa 1: hermes serve Está Vinculado a 127.0.0.1

O hermes serve faz bind em 127.0.0.1 por padrão. Esse é o padrão certo para um setup só-laptop e o errado para qualquer coisa que você queira alcançar pela tailnet. Um processo vinculado ao loopback só responde a requisições que se originam na mesma máquina, e um peer do Tailscale não é a mesma máquina. A porta está aberta, o firewall está ok, o túnel está no ar e o socket recusa a conexão.

Sintoma: do laptop, curl -v http://<hermes-vps>:8642/api/health retorna Connection refused ou trava até estourar o timeout. De uma sessão SSH no VPS, o mesmo curl http://127.0.0.1:8642/api/health responde na hora. Se o loopback responde e a tailnet não, essa é a sua causa.

A correção é fazer bind do hermes serve no IP de Tailscale do host explicitamente:

TAILSCALE_IP=$(tailscale ip -4)
hermes serve --host "$TAILSCALE_IP" --port 8642

Fazer bind na interface da tailnet em vez de 0.0.0.0 é a forma que você quer. 0.0.0.0 também funciona e é o que muitos guias sugerem, mas expõe o socket em cada interface que a máquina tem, incluindo qualquer uma acidentalmente pública, e devolve toda a história de autenticação para a camada de aplicação. Fazer bind no IP de Tailscale é defesa em profundidade: o socket só é alcançável de dentro da tailnet.

Torne isso permanente colocando a mesma flag na unit do systemd ou no command do docker-compose.yml. Se você roda em Docker, publique a porta direto no IP de Tailscale com -p ${TAILSCALE_IP}:8642:8642 em vez do -p 8642:8642 padrão (que publica em todas as interfaces do host).

Para a instalação completa do Tailscale de primeira vez, o guia de acesso remoto seguro com Hermes Agent + Tailscale percorre a receita de ponta a ponta.

Causa 2: O Regex de CORS do Dashboard Rejeita Sua Origem de Tailscale

Você faz bind do gateway no IP de Tailscale, a API responde em /api/health e o dashboard web carrega seu HTML de http://<hermes-vps>:8642/. Depois cada chamada de API que o dashboard faz falha com um erro de CORS no console do navegador: has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

O que acontece: builds antigos do Hermes traziam um allow_origin_regex hardcoded no dashboard que só casava com ^https?://(localhost|127\.0\.0\.1)(:\d+)?$. O regex era seguro em um laptop e silenciosamente inútil em qualquer outro lugar. Um hostname de Tailscale como http://hermes-vps:8642 ou um IP como http://100.64.1.5:8642 nunca casa, então o preflight falha e o navegador descarta o fetch. A feature request que acompanha a correção tem o histórico completo.

A correção é uma variável de ambiente:

export HERMES_DASHBOARD_CORS_ORIGINS="http://hermes-vps:8642,http://100.64.1.5:8642"
hermes serve --host "$TAILSCALE_IP" --port 8642

Liste cada origem de onde você realmente carrega o dashboard: o nome de MagicDNS, o IP cru do Tailscale e qualquer alias de Funnel ou serve que você tenha adicionado. Coringas são suportados (http://*.tail1a2b3.ts.net:8642) se você preferir casar o nome inteiro da tailnet em vez de listar cada dispositivo.

Duas manivelas relacionadas em que as pessoas tropeçam:

  • HERMES_DASHBOARD_HOST sobrescreve o endereço que o dashboard anuncia para o navegador. Se você deixou em localhost, o dashboard renderiza links de volta para http://localhost:8642/api/... e o navegador tenta bater no próprio loopback em vez da tailnet. Ajuste para seu hostname ou IP de Tailscale.
  • O app Hermes Desktop também carrega uma Origin. Se você usa o desktop empacotado em vez do dashboard do navegador, o renderer dele envia Origin: null (o Electron carrega via file://). Builds antigos aceitavam isso só quando o servidor estava vinculado ao loopback, que é a exclusividade mútua descrita na issue #38412. Builds recentes aceitam null quando está presente em HERMES_DASHBOARD_CORS_ORIGINS junto com suas origens reais: adicione a string literal null à lista para permitir o cliente desktop.

Reinicie o hermes serve após qualquer mudança nessas env vars. Os valores são lidos na inicialização, não por request.

Causa 3: O Túnel do Tailscale Está Caindo para DERP ou Não Sobe

Se o dashboard acaba carregando mas cada mensagem leva vários segundos para enviar e as notas de voz engasgam, o túnel está no ar mas lento. O Tailscale está retransmitindo cada pacote por um servidor DERP até seu VPS, e o round-trip é dominado por esse salto extra em vez do modelo. Se nada passa, o túnel provavelmente nem chegou a subir.

Confirme qual dos dois é o seu com tailscale status. Um peer saudável mostra direct <ip>:<port> na linha dele. Um peer relayed via DERP mostra relay "<region>". Se o peer não aparece ou está marcado como offline, o túnel nunca se estabeleceu.

A correção muda em cada caso:

  • Preso no DERP. Abra UDP 41641 de saída tanto no firewall do host VPS quanto no firewall da rede do cliente. Essa é a porta que o Tailscale usa para túneis WireGuard diretos; se um lado bloqueia a saída UDP, ambos os peers caem para DERP mesmo com o par autenticado. Confirme com sudo ufw allow 41641/udp no VPS e pingando o peer de novo depois de tailscale down && tailscale up. Redes corporativas e Wi-Fi de hotel são os suspeitos usuais de bloquear saída UDP. Se a conexão direta continua impossível, o DERP dá conta de texto mas você sente na voz.
  • Peer marcado offline ou túnel nunca subiu. A chave do nó expirou. O Tailscale rotaciona chaves a cada 180 dias por padrão, e um dispositivo que ficou offline durante a janela de rotação volta como "offline" no console admin até você reautenticar. Corrija com tailscale up --force-reauth no lado afetado e faça login de novo pelo navegador. Para evitar a rotação por completo em instalações VPS do lado servidor, marque o nó (tailscale up --advertise-tags=tag:server) e desabilite a expiração de chave para essa tag no console admin do Tailscale: nós marcados pulam a checagem de 180 dias por padrão.
  • O modo economia de bateria matou o cliente no laptop. macOS e Windows deixam o SO pausar serviços em segundo plano em modos agressivos, e o app na bandeja do Tailscale pode se desconectar sozinho em silêncio. Se a tailnet apagou logo depois que você tirou da tomada, olhe o ícone na bandeja antes de diagnosticar mais nada.

Causa 4: Você Aponta para uma URL de Localhost a Partir de um Cliente Remoto

O último caso silencioso é aquele em que cada camada funciona e o cliente faz a pergunta errada. Se você configurou a Remote Gateway URL do Hermes Desktop como http://localhost:8642 ou http://127.0.0.1:8642, o app tenta alcançar sua própria interface de loopback em vez de atravessar a tailnet, e nenhuma correção do lado servidor vai ajudar.

Sintoma: no laptop, o app desktop mostra "Could not connect." Do mesmo laptop, curl http://<hermes-vps>:8642/api/health responde saudável.

A correção é uma única configuração. No Hermes Desktop, abra Settings depois Connection e ajuste a Remote Gateway URL para uma de:

  • http://<magic-dns-name>:8642 - preferido, sobrevive a mudanças de IP do Tailscale.
  • http://<tailscale-ip>:8642 - o endereço cru 100.x.x.x. Estável o suficiente para um setup fixo.

O nome de MagicDNS é o que o tailscale status mostra na primeira coluna da linha do VPS. Se você nunca habilitou MagicDNS, faça isso no console admin em DNS: é um toggle só e economiza toda sessão de debug por mudança de IP na vida da tailnet.

Já que você está em Settings, confira o campo de credenciais. Se o gateway está atrás de um token (HERMES_AUTH_TOKEN), o cliente precisa do mesmo token, e um token velho gera um 4403 no WebSocket que se parece muito com uma falha de conexão. A issue do WebSocket 4403 tem mais detalhe sobre esse modo de falha específico.

Ordem de Diagnóstico que Poupa Tempo

Quando a tailnet está no ar e o Hermes não responde, siga as causas nessa ordem em vez de reconstruir o setup do Tailscale:

  1. hermes serve está vinculado ao loopback? curl http://<tailscale-ip>:8642/api/health do cliente responde em um segundo. A maior taxa de acerto em setups remotos recém-montados.
  2. O regex de CORS do dashboard rejeita sua origem? Abra as devtools do navegador no dashboard e procure uma entrada CORS em vermelho na aba de rede. Se aparecer, defina HERMES_DASHBOARD_CORS_ORIGINS e reinicie.
  3. O túnel é direto ou relayed? tailscale status mostra direct ou relay por peer. Offline significa que a chave do nó expirou e você precisa de --force-reauth.
  4. O cliente pede localhost? Abra as configurações de conexão do app desktop e confirme que a Remote Gateway URL aponta para o hostname da tailnet, não localhost.

Para a receita Docker base no VPS, veja o guia Docker do Hermes Agent. Se preferir pular a malha por completo, self-hosting vs Hermes Agent gerenciado cobre os trade-offs.

Quando Você Prefere Não Rodar uma Malha

O Tailscale é a forma certa para um Hermes auto-hospedado quando você quer manter a caixa no seu próprio VPS e alcançá-la de qualquer lugar. Também é mais um sistema para manter vivo: uma janela de rotação de chaves, uma env var de CORS, uma regra de firewall para UDP 41641 e uma configuração de cliente que precisa casar com o nome da tailnet do dia. Se sua leitura é que um assistente de IA pessoal não deveria exigir uma VPN em malha e uma sessão de debug no console do navegador para te responder oi, comece com a Hermify. A Hermify roda um Hermes Agent gerenciado no Telegram com a mesma memória e skills, no ar em cerca de um minuto, sem portas para abrir nem tailnet para manter.

Fontes

Lance seu próprio agente Hermes

Traga sua chave de API, conecte o Telegram e tenha um agente de IA que evolui sozinho no ar em 60 segundos.

Começar agora