Torna al blog
HermesTailscaleTroubleshootingSelf-Hosting

Hermes Agent con Tailscale non si connette: le soluzioni

Hermes Desktop non raggiunge il tuo gateway remoto via Tailscale? Quattro cause coprono quasi tutti i casi, dal bind su localhost al regex CORS.

Di Hermify Team||8 min di lettura
Scena scura con il wordmark Tailscale sopra un laptop che tenta di raggiungere un gateway Hermes remoto attraverso una mesh, con il testo in grassetto 'Tailscale Not Connecting'

La Tailnet È Su e Hermes Continua a Non Rispondere

Hai installato Tailscale sul VPS, sei entrato nella tailnet dal laptop e hai confermato che entrambi i lati si pingano sugli indirizzi 100.x.x.x. hermes serve gira sull'host con la porta aperta e l'app Hermes Desktop sul laptop resta in loop su "Could not connect to Hermes gateway." Niente nel log del gateway sembra arrabbiato. Niente in Tailscale è in rosso.

Quel fallimento silenzioso è quasi sempre una di quattro cause, e tre falliscono in silenzio per design. Questo post scorre ognuna, come confermare quale sia la tua e il fix esatto. Parti dall'alto: la prima causa acchiappa la maggior parte dei setup remoti appena avviati, e ogni causa sotto assume che quelle sopra siano state escluse.

Causa 1: hermes serve È Bindato su 127.0.0.1

hermes serve fa il bind su 127.0.0.1 di default. È il default giusto per un setup solo-laptop e quello sbagliato per qualsiasi cosa tu voglia raggiungere via tailnet. Un processo bindato sul loopback risponde solo alle richieste che partono dalla stessa macchina, e un peer Tailscale non è la stessa macchina. La porta è aperta, il firewall va bene, il tunnel è su, e il socket rifiuta la connessione.

Sintomo: dal laptop, curl -v http://<hermes-vps>:8642/api/health restituisce Connection refused o resta appeso fino al timeout. Da una sessione SSH sul VPS, lo stesso curl http://127.0.0.1:8642/api/health risponde subito. Se il loopback risponde e la tailnet no, questa è la tua causa.

Il fix è bindare hermes serve all'IP Tailscale dell'host esplicitamente:

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

Bindare sull'interfaccia della tailnet invece che su 0.0.0.0 è la forma che vuoi. 0.0.0.0 funziona anche e molte guide lo consigliano, ma espone il socket su ogni interfaccia della macchina, comprese quelle accidentalmente pubbliche, e rimette tutta la storia dell'autenticazione sul livello applicativo. Bindare all'IP Tailscale è difesa in profondità: il socket è raggiungibile solo da dentro la tailnet.

Rendi la modifica permanente mettendo lo stesso flag nella unit systemd o nel command del docker-compose.yml. Se giri in Docker, pubblica la porta direttamente sull'IP Tailscale con -p ${TAILSCALE_IP}:8642:8642 invece del -p 8642:8642 di default (che pubblica su ogni interfaccia dell'host).

Per l'installazione Tailscale iniziale completa, la guida all'accesso remoto sicuro con Hermes Agent + Tailscale scorre la ricetta da capo a fondo.

Causa 2: Il Regex CORS del Dashboard Rifiuta la tua Origin di Tailscale

Bindi il gateway all'IP Tailscale, l'API risponde su /api/health e il dashboard web carica l'HTML da http://<hermes-vps>:8642/. Poi ogni chiamata API del dashboard fallisce con un errore CORS nella console del browser: has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Cosa succede: vecchie build di Hermes portavano un allow_origin_regex hardcoded nel dashboard che matchava solo ^https?://(localhost|127\.0\.0\.1)(:\d+)?$. Il regex era sicuro sul laptop e silenziosamente inutile ovunque altro. Un hostname Tailscale come http://hermes-vps:8642 o un IP come http://100.64.1.5:8642 non matcha mai, quindi la preflight fallisce e il browser scarta la fetch. La feature request che segue il fix ha lo storico completo.

Il fix è una variabile d'ambiente:

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

Elenca ogni origin da cui carichi davvero il dashboard: il nome MagicDNS, l'IP grezzo di Tailscale e ogni alias di Funnel o serve che hai aggiunto. Sono supportati i wildcard (http://*.tail1a2b3.ts.net:8642) se preferisci matchare l'intero nome della tailnet invece di elencare ogni dispositivo.

Due manopole affini su cui si inciampa:

  • HERMES_DASHBOARD_HOST sovrascrive l'indirizzo che il dashboard dichiara al browser. Se l'hai lasciato su localhost, il dashboard rende link che riportano a http://localhost:8642/api/... e il browser cerca di colpire il proprio loopback invece della tailnet. Impostalo sul tuo hostname o IP Tailscale.
  • L'app Hermes Desktop porta anche lei una Origin. Se usi il desktop pacchettizzato invece del dashboard nel browser, il suo renderer manda Origin: null (Electron carica via file://). Le build vecchie lo accettavano solo se il server era bindato al loopback, che è l'esclusività mutuale descritta nell'issue #38412. Le build recenti accettano null se è presente in HERMES_DASHBOARD_CORS_ORIGINS insieme alle origin reali: aggiungi la stringa letterale null alla lista per permettere il client desktop.

Riavvia hermes serve dopo ogni modifica a queste env var. I valori si leggono all'avvio, non per richiesta.

Causa 3: Il Tunnel Tailscale Cade in DERP o Non Si Alza

Se il dashboard alla fine carica ma ogni messaggio impiega diversi secondi per partire e le note vocali balbettano, il tunnel è su ma lento. Tailscale sta relayando ogni pacchetto attraverso un server DERP fino al tuo VPS, e il round-trip è dominato da quel salto extra invece che dal modello. Se non passa proprio niente, probabilmente il tunnel non è mai salito.

Conferma quale dei due è il tuo con tailscale status. Un peer in salute mostra direct <ip>:<port> sulla sua riga. Un peer relayato via DERP mostra relay "<region>". Se il peer è assente o marcato offline, il tunnel non si è mai stabilito.

Il fix cambia in ogni caso:

  • Bloccato in DERP. Apri UDP 41641 in uscita sia sul firewall dell'host VPS sia su quello della rete client. È la porta che Tailscale usa per i tunnel WireGuard diretti; se un lato blocca l'uscita UDP, entrambi i peer ricadono in DERP anche se la coppia è autenticata. Conferma con sudo ufw allow 41641/udp sul VPS e ripingando il peer dopo tailscale down && tailscale up. Reti aziendali e Wi-Fi d'albergo sono i soliti sospetti a bloccare l'uscita UDP. Se una connessione diretta resta impossibile, DERP regge sul testo ma lo senti sulla voce.
  • Peer marcato offline o tunnel mai salito. La chiave del nodo è scaduta. Tailscale ruota le chiavi ogni 180 giorni di default, e un dispositivo rimasto offline durante la finestra di rotazione torna come "offline" nella console admin finché non riautentichi. Sistemi con tailscale up --force-reauth dal lato interessato e rifai login via browser. Per evitare del tutto la rotazione sulle installazioni VPS lato server, tagga il nodo (tailscale up --advertise-tags=tag:server) e disabilita la scadenza chiave per quel tag nella console admin di Tailscale: i nodi taggati saltano il controllo dei 180 giorni di default.
  • Il risparmio energetico ha ucciso il client sul laptop. macOS e Windows lasciano al SO mettere in pausa i servizi in background nelle modalità aggressive, e la app da menubar di Tailscale può disconnettersi da sola in silenzio. Se la tailnet si è spenta subito dopo aver staccato la spina, guarda l'icona nel tray prima di diagnosticare altro.

Causa 4: Punti a una URL Localhost da un Client Remoto

L'ultimo caso silenzioso è quello in cui ogni strato funziona e il client sta facendo la domanda sbagliata. Se hai configurato la Remote Gateway URL di Hermes Desktop come http://localhost:8642 o http://127.0.0.1:8642, l'app cerca di raggiungere la propria interfaccia di loopback invece di attraversare la tailnet, e nessun fix lato server aiuterà.

Sintomo: sul laptop, l'app desktop mostra "Could not connect." Dallo stesso laptop, curl http://<hermes-vps>:8642/api/health risponde in salute.

Il fix è un'unica impostazione. In Hermes Desktop, apri Settings poi Connection e imposta la Remote Gateway URL su una tra:

  • http://<magic-dns-name>:8642 - preferito, sopravvive ai cambi di IP Tailscale.
  • http://<tailscale-ip>:8642 - l'indirizzo grezzo 100.x.x.x. Abbastanza stabile per un setup fisso.

Il nome MagicDNS è quello che tailscale status mostra nella prima colonna per la riga del VPS. Se non hai mai abilitato MagicDNS, fallo nella console admin sotto DNS: è un solo toggle e ti risparmia ogni sessione di debug per cambio IP per tutta la vita della tailnet.

Già che sei in Settings, controlla il campo credenziali. Se il gateway sta dietro a un token (HERMES_AUTH_TOKEN), il client ha bisogno dello stesso token, e uno vecchio produce un 4403 sul WebSocket che sembra molto un fallimento di connessione. L'issue del WebSocket 4403 ha più dettagli su quel particolare modo di fallire.

Ordine Diagnostico che Fa Risparmiare Tempo

Quando la tailnet è su e Hermes non risponde, segui le cause in quest'ordine invece di ricostruire il setup Tailscale:

  1. hermes serve è bindato sul loopback? curl http://<tailscale-ip>:8642/api/health dal client risponde in un secondo. Il tasso di successo più alto sui setup remoti appena avviati.
  2. Il regex CORS del dashboard rifiuta la tua origin? Apri le devtools del browser sul dashboard e cerca una voce CORS in rosso nella scheda network. Se c'è, imposta HERMES_DASHBOARD_CORS_ORIGINS e riavvia.
  3. Il tunnel è diretto o relayato? tailscale status mostra direct o relay per peer. Offline significa che la chiave del nodo è scaduta e serve --force-reauth.
  4. Il client chiede localhost? Apri le impostazioni di connessione dell'app desktop e conferma che la Remote Gateway URL punti al hostname della tailnet, non a localhost.

Per la ricetta Docker sottostante sul VPS, vedi la guida Docker di Hermes Agent. Se preferisci saltare del tutto la mesh, self-hosting vs Hermes Agent gestito copre i compromessi.

Quando Preferisci Non Gestire una Mesh

Tailscale è la forma giusta per un Hermes self-hosted quando vuoi tenere la macchina sul tuo VPS e raggiungerla da qualsiasi posto. È anche un sistema in più da tenere vivo: una finestra di rotazione chiavi, una env var CORS, una regola di firewall per UDP 41641 e un'impostazione client che deve combaciare con il nome della tailnet del giorno. Se la tua lettura è che un assistente IA personale non dovrebbe richiedere una VPN mesh e una sessione di debug nella console del browser per risponderti ciao, inizia con Hermify. Hermify gestisce un Hermes Agent su Telegram con la stessa memoria e le stesse skill, attivo in circa un minuto, senza porte da aprire né tailnet da mantenere.

Fonti

Avvia il tuo Hermes Agent

Porta la tua chiave API, collega Telegram e ottieni un agente IA che migliora da solo, online in 60 secondi.

Inizia ora