Loading theme
~/saverio

Claude Code sulla tua VPS: codice da ovunque, anche dal telefono

28 mar 2026· 5 min
claude-codeaimobiletailscalehetzner

Claude Code sulla tua VPS: codice da ovunque, anche dal telefono

Cosa otterrai: Claude Code che gira sul tuo server Hetzner, accessibile da qualsiasi device: terminale desktop, browser, o telefono. Dai istruzioni in linguaggio naturale; Claude edita il codice, lancia comandi, committa e pusha. Coolify prende il push e fa il deploy in automatico.


Perché far girare Claude Code sul server?

Potresti far girare Claude Code in locale e collegarlo a GitHub. Ma farlo girare sul server ti dà qualcosa di diverso:

  • Accesso diretto al codebase, container Docker, database e log
  • Niente sync di file o upload necessari
  • Le sessioni persistono tra cambi di device: parti dal desktop, continui dal telefono
  • Coolify auto-deploya a ogni push senza dover lasciare il server

Il telefono diventa un thin client. Tutto il calcolo e il contesto vivono sulla VPS.


Prerequisiti


Installa Claude Code

SSH al server e installa Node.js + Claude Code:

# Node.js 22
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt install -y nodejs

# Claude Code
npm install -g @anthropic-ai/claude-code
claude --version

Installa tmux se non c'è:

apt install -y tmux

Clona la tua repo

Coolify costruisce le immagini Docker da GitHub; non tiene un clone locale sul server. A Claude Code serve una copia locale per lavorare.

Genera una chiave SSH per l'accesso a GitHub:

ssh-keygen -t ed25519 -C "p1-hetzner" -f ~/.ssh/id_ed25519 -N ""
cat ~/.ssh/id_ed25519.pub

Aggiungi la chiave pubblica su GitHub → Settings → SSH and GPG keys → New SSH key.

Poi clona:

ssh-keyscan github.com >> ~/.ssh/known_hosts
git clone [email protected]:YOUR_USER/platform.git /root/platform
git -C /root/platform config user.name "Il Tuo Nome"
git -C /root/platform config user.email "[email protected]"

Configura i permessi auto

Di default, Claude Code chiede conferma prima di ogni edit di file o comando bash. Per uso da server, disabilitalo:

mkdir -p ~/.claude
cat > ~/.claude/settings.json << 'EOF'
{
  "permissions": {
    "allow": [
      "Bash(*)",
      "Read(*)",
      "Write(*)",
      "Edit(*)",
      "Glob(*)",
      "Grep(*)",
      "WebFetch(*)",
      "TodoWrite(*)"
    ],
    "deny": []
  }
}
EOF

Claude Code ora editerà file, eseguirà comandi e committerà senza fermarsi a chiedere.


Sistema fail2ban per Tailscale

fail2ban monitora i log SSH e banna gli IP dopo tentativi falliti. I tuoi nodi Tailscale stanno nel range 100.64.0.0/10; mettili in whitelist così fail2ban non ti chiude mai fuori:

cat > /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
ignoreip = 127.0.0.1/8 ::1 100.64.0.0/10

[sshd]
enabled = true
port = 2222
EOF
systemctl restart fail2ban

Per sbannare un IP subito:

fail2ban-client set sshd unbanip 100.87.104.91

Sistema il ts-input di Tailscale (importante)

Le versioni recenti di Tailscale aggiungono una catena iptables chiamata ts-input che implementa il filtro host basato su ACL. Di default droppa tutto il traffico peer Tailscale (100.64.0.0/10) prima ancora che UFW lo veda, incluse le tue connessioni SSH.

Controlla se la regola è presente:

iptables -L ts-input -n --line-numbers

Se vedi DROP -- 100.64.0.0/10, Tailscale sta bloccando l'SSH peer. Crea un servizio systemd per rimuoverla in automatico a ogni boot:

cat > /etc/systemd/system/tailscale-fix-iptables.service << 'EOF'
[Unit]
Description=Remove Tailscale DROP rule for peer SSH access
After=tailscaled.service
Wants=tailscaled.service

[Service]
Type=oneshot
ExecStart=/bin/bash -c 'sleep 3; iptables -D ts-input $(iptables -L ts-input --line-numbers -n | grep "DROP.*100.64.0.0/10" | awk "{print $1}") 2>/dev/null || true'
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable tailscale-fix-iptables
systemctl start tailscale-fix-iptables

Perché succede: Tailscale forza la sua policy ACL a livello iptables. Se l'ACL non permette esplicitamente una porta, Tailscale droppa il traffico. Il fix permanente è aggiornare la tua ACL Tailscale su tailscale.com/admin/acls per permettere tutto il traffico tra i tuoi nodi ({"acls": [{"action": "accept", "src": ["*"], "dst": ["*:*"]}]}). Finché non lo fai, il servizio systemd se ne occupa a ogni restart.


Alias di comodità

Aggiungi a ~/.zshrc:

# Avvia o ri-attacca la sessione Claude Code
alias dev='cd /root/platform && TERM=xterm-256color tmux new-session -A -s dev'
alias claude-attach='TERM=xterm-256color tmux attach -t dev'

Lancia Claude Code

dev
claude

Al primo avvio, Claude Code rileva la tua env var ANTHROPIC_API_KEY e ti chiede se usarla. Se hai un abbonamento Claude Pro/Max, scegli No e autenticati con l'account. Costa meno e usa la quota dell'abbonamento.


Collegati dal telefono

Claude Code ha una modalità Remote Control che fa da ponte tra il tuo telefono e la sessione del server in esecuzione.

Dentro Claude Code:

/rc

Claude Code attiva il Remote Control e stampa l'URL della sessione:

/remote-control is active. Code in CLI or at
https://claude.ai/code/session_XXXX

Sul telefono:

  • Apri l'app Claude (deve essere aggiornata) → le sessioni Remote Control compaiono in automatico
  • Oppure apri direttamente l'URL della sessione nel browser del telefono

Adesso stai controllando la sessione del server dal telefono. Scrivi istruzioni; Claude edita codice, esegue test, committa, pusha.


Workflow: desktop vs telefono

Da desktop (controllo completo):

ssh -i ~/.ssh/hetzner-platform -o IdentitiesOnly=yes -p 2222 [email protected]
dev                    # avvia/ri-attacca tmux + va nella repo
claude                 # lancia Claude Code

Usalo quando devi vedere i diff, rivedere l'output con cura o lavorare su modifiche complesse multi-file.

Da telefono (istruzioni veloci):

  1. Apri l'app Claude → tap sulla sessione Remote Control attiva
  2. Scrivi l'istruzione: "aggiungi un endpoint /health all'API"
  3. Guarda Claude lavorare in real time sul server
  4. Quando ha finito, Coolify prende il push e fa il deploy

Usalo per fix rapidi, piccole feature o per controllare lo stato lontano dalla scrivania.

Riconnetterti dopo una pausa:

La sessione tmux resta viva anche quando ti disconnetti. Per riprendere da dove avevi lasciato:

# Da desktop
ssh [email protected] -p 2222
claude-attach          # ri-attacca alla sessione esistente

# Da telefono
# Apri l'app Claude → la sessione è ancora elencata, tap per riconnetterti

Hetzner Cloud Firewall: cosa tenere

Docker bypassa UFW, quindi il Cloud Firewall di Hetzner è la vera porta per i servizi Coolify. Ecco il setup minimo sicuro:

PortaProtocolloSorgenteScopo
2222TCP100.64.0.0/10SSH (solo Tailscale)
80TCPRange IPv4 CloudflareHTTP (via proxy Cloudflare)
443TCPRange IPv4 + IPv6 CloudflareHTTPS (via proxy Cloudflare)
8000TCPTuo IP + CIDR webhook GitHubDashboard Coolify + auto-deploy
6001TCPTuo IPCoolify real-time
6002TCPTuo IPTerminale Coolify
ICMPany100.64.0.0/10Ping (solo Tailscale)

Cosa rimuovere:

  • Porta 3000 esposta direttamente (le app girano dietro Traefik su 80/443)
  • Any IPv4 / Any IPv6 sulle porte 80/443 se sei dietro al proxy Cloudflare: chiunque può bypassare Cloudflare e arrivare al tuo origin
  • Vecchi IP personali sulla 2222 una volta che sei completamente su Tailscale

Range IPv4 Cloudflare (aggiungili tutti alle porte 80 e 443):

173.245.48.0/20
103.21.244.0/22
103.22.200.0/22
103.31.4.0/22
141.101.64.0/18
108.162.192.0/18
190.93.240.0/20
188.114.96.0/20
197.234.240.0/22
198.41.128.0/17
162.158.0.0/15
104.16.0.0/13
104.24.0.0/14
172.64.0.0/13
131.0.72.0/22

IPv6:

2400:cb00::/32
2606:4700::/32
2803:f800::/32
2405:b500::/32
2405:8100::/32
2a06:98c0::/29
2c0f:f248::/32

Troubleshooting

ProblemaCausaFix
ssh: Connection refused via TailscaleRegola DROP ts-input attivaiptables -D ts-input $(iptables -L ts-input --line-numbers -n | grep "DROP.*100.64" | awk '{print $1}')
ssh: Connection refused dopo molti tentativiBan di fail2banfail2ban-client set sshd unbanip YOUR_TAILSCALE_IP
missing or unsuitable terminal: xterm-ghosttytmux non conosce GhosttyUsa TERM=xterm-256color tmux ...
Remote Control non visibile nell'app ClaudeApp non aggiornataAggiorna l'app Claude dallo store
Sito giù dopo modifiche al firewallIP Cloudflare rimossi da 80/443Riaggiungi i range IP Cloudflare a entrambe le porte
Claude Code chiede confermasettings.json mancanteCrea ~/.claude/settings.json con le regole di allow di sopra