La sua app funziona su localhost. Ora vuole condividerla con un dominio vero, senza tenere acceso il portatile. I pezzi mancanti sono un VPS, un processo applicativo gestito, il DNS e un reverse proxy HTTPS.
Questa guida mostra il percorso con una piccola app Node.js. Claude Code può aiutare a ispezionare il progetto e a preparare la configurazione da sottoporre a revisione; la responsabilità delle modifiche al server resta sua. Il modello non viene installato sul VPS, e l'accesso a Claude e la relativa fatturazione sono separati dall'hosting.
Guida animata. La dashboard è una dimostrazione fittizia, non un monitoraggio di infrastruttura reale.
Guardi la panoramica della distribuzione
Guarda la panoramica della distribuzione (video in inglese).
Cosa abbiamo effettivamente testato: una vera dashboard, creata in origine da Claude Code, è stata distribuita dal nostro operatore su un VPS Linux usa e getta. Abbiamo verificato il DNS pubblico, l'HTTPS attendibile, il reindirizzamento da HTTP a HTTPS, i processi dell'applicazione e del proxy senza privilegi root e l'accesso dopo il riavvio del servizio applicativo. Non è stata eseguita alcuna nuova distribuzione autonoma da parte di Claude. Il prompt suggerito qui sotto ha scopo didattico e non è una risposta registrata.
Prima di iniziare
- Un VPS Linux con systemd e un account SSH con accesso sudo. Usi prima un VPS di prova; non sovrascriva i servizi o la configurazione web di un sito esistente.
- Un runtime Node.js LTS supportato installato sul server e Caddy installato come servizio di sistema. Installi questi prerequisiti prima di seguire i passaggi di distribuzione.
- Un dominio o sottodominio di cui possa modificare i record DNS.
- Una piccola app autonoma. Il nostro esempio serve
index.htmltramiteserver.mjs, senza dipendenze di pacchetti né database.
Le applicazioni basate su framework hanno il proprio comando di build, il proprio comando di avvio, le proprie dipendenze e il proprio piano di storage. Non dia per scontato che un progetto Next.js, Python o basato su database possa usare invariato questo esempio di due file.
1. Chieda a Claude Code di ispezionare il progetto prima di modificarlo
Parta dalla directory del suo progetto locale. Una prima richiesta utile è:
Inspect this project without changing files. Identify its runtime,
build and start commands, configuration and secrets. Propose a Linux
VPS deployment using a non-root systemd service and Caddy HTTPS.
Bind the app to 127.0.0.1:3000. Explain each proposed file and
verification step. Do not connect to a server or edit DNS.
I flussi di lavoro documentati di Claude Code prevedono la pianificazione prima delle modifiche. Riveda le modifiche proposte invece di accettare ciecamente i comandi di distribuzione. Tenga chiavi API, credenziali di produzione e chiavi SSH private fuori dai prompt e dai repository: l'accesso in sola lettura non rende riservati i file sensibili.
2. Prepari e trasferisca l'applicazione
Per questo esempio minimale, salvi il suo HTML come index.html e usi il server seguente. Per impostazione predefinita è in ascolto solo sul loopback e non espone file arbitrari del progetto:
import {createServer} from 'node:http';
import {readFileSync} from 'node:fs';
import {fileURLToPath} from 'node:url';
const page=readFileSync(new URL('./index.html',import.meta.url));
export function createAppServer(){
return createServer((req,res)=>{
const pathname=new URL(req.url,'http://localhost').pathname;
if(pathname!=='/' && pathname!=='/index.html'){
res.writeHead(404,{'Content-Type':'text/plain; charset=utf-8'});res.end('Not found');return;
}
res.writeHead(200,{'Content-Type':'text/html; charset=utf-8','X-Content-Type-Options':'nosniff'});res.end(page);
});
}
if(process.argv[1]===fileURLToPath(import.meta.url)){
const host=process.env.HOST||'127.0.0.1';const port=Number(process.env.PORT||3000);
const server=createAppServer();server.listen(port,host,()=>console.log(`Demo app listening on ${host}:${port}`));
process.on('SIGTERM',()=>server.close(()=>process.exit(0)));
}
Lo esegua in locale con node server.mjs, apra http://127.0.0.1:3000, quindi lo fermi prima di proseguire. Su un VPS che usa già la porta 3000, scelga un'altra porta privata e la usi in modo coerente sia nel servizio sia nel proxy.
Dalla directory del suo progetto locale, sostituisca deploy e VPS_IP con il suo account SSH e con l'indirizzo effettivo del server:
ssh deploy@VPS_IP 'mkdir -p ~/my-app'
scp index.html server.mjs deploy@VPS_IP:~/my-app/
Sul server, installi questi due file non riservati in una directory applicativa leggibile:
sudo install -d -m 0755 /opt/my-app
sudo install -m 0644 ~/my-app/index.html ~/my-app/server.mjs /opt/my-app/
command -v node
Annoti il percorso assoluto dell'eseguibile Node. Deve essere accessibile al di fuori della shell di login e della home directory. Un'installazione di Node tramite gestore di versioni, riservata all'utente e situata in /home, non è adatta al servizio rinforzato descritto qui sotto. Non copi mai un .env di sviluppo, una chiave privata o un dump di database in una directory web pubblica.
3. Esegua l'app come servizio systemd non root
Usi sudoedit /etc/systemd/system/my-app.service. Sostituisca /ABSOLUTE/PATH/TO/node con il percorso reale dell'eseguibile valido per l'intero server che ha appena verificato:
[Unit]
Description=My Node web app
After=network.target
[Service]
Type=simple
DynamicUser=true
WorkingDirectory=/opt/my-app
ExecStart=/ABSOLUTE/PATH/TO/node /opt/my-app/server.mjs
Environment=NODE_ENV=production
Environment=HOST=127.0.0.1
Environment=PORT=3000
Restart=on-failure
RestartSec=2
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
[Install]
WantedBy=multi-user.target
I controlli di esecuzione di systemd documentano l'account dinamico e le impostazioni di rafforzamento. Questo profilo è adatto alla nostra app in sola lettura; le app che scrivono upload o database richiedono uno storage persistente e permessi configurati deliberatamente.
sudo systemctl daemon-reload
sudo systemctl enable --now my-app.service
sudo systemctl status my-app.service --no-pager
curl -fsS http://127.0.0.1:3000/
Risolva gli errori dell'applicazione prima di toccare il DNS. Un servizio abilitato è configurato per l'avvio al boot, ma questo non è la prova di un test di riavvio completato.
4. Punti un sottodominio al VPS
Crei un record A per l'hostname scelto, ad esempio app.example.com, che punti all'indirizzo IPv4 pubblico del suo VPS. Con Cloudflare, la nostra dimostrazione con server diretto ha usato solo DNS e un TTL automatico. Non copi l'IP della nostra dimostrazione nei record del suo sito.
Verifichi la risposta pubblica con dig +short A app.example.com. Controlli anche dig +short AAAA app.example.com: se esiste un record IPv6, deve raggiungere la stessa distribuzione funzionante anche tramite IPv6. Il DNS si limita ad associare un indirizzo: non avvia l'app né configura l'HTTPS.
5. Metta Caddy davanti all'app privata
Mantenga il servizio Node su 127.0.0.1:3000. Renda raggiungibili le porte web pubbliche 80 e 443 attraverso il firewall del provider e quello dell'host, senza rimuovere il suo accesso SSH. Non esponga la porta 3000 a internet.
Aggiunga questo blocco di sito alla configurazione del suo servizio Caddy installato, sostituendo l'hostname di esempio. Conservi gli altri blocchi di sito:
app.example.com {
encode zstd gzip
reverse_proxy 127.0.0.1:3000
}
La direttiva reverse_proxy inoltra le richieste pubbliche all'applicazione privata. Con un hostname pubblico idoneo e condizioni di convalida del certificato funzionanti, l'HTTPS automatico di Caddy ottiene e rinnova i certificati e reindirizza HTTP a HTTPS.
Per il servizio di sistema Caddy standard e il relativo percorso di configurazione:
sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
sudo systemctl reload caddy
Il nostro VPS di ripresa usava un servizio Caddy dedicato e percorsi di configurazione isolati, anziché il servizio condiviso standard qui sopra. Il principio di instradamento è lo stesso; questi percorsi e nomi di servizio rivolti al lettore sono adattamenti, non la trascrizione letterale di un'installazione.
6. Verifichi il risultato pubblico e il riavvio del servizio
curl -I http://app.example.com/
curl -I https://app.example.com/
sudo systemctl restart my-app.service
curl --retry 5 --retry-delay 1 --retry-connrefused -I https://app.example.com/
Controlli che ci sia un reindirizzamento da HTTP a HTTPS, una risposta HTTPS riuscita e un certificato valido nel browser. Non usi curl -k per nascondere gli errori di attendibilità. Apra la pagina da un'altra rete, non solo dall'interno del VPS.
Un controllo di riavvio fallito richiede un'indagine: esamini journalctl -u my-app.service -n 50 --no-pager e i log del servizio Caddy. Errori DNS, IPv6 errato, un'app ferma, una porta upstream sbagliata e una convalida del certificato bloccata sono problemi diversi.
Abbiamo verificato il riavvio di un servizio applicativo, non il riavvio di un VPS né una configurazione ad alta disponibilità. Prima di ospitare un'applicazione aziendale reale, pianifichi anche aggiornamenti, backup, monitoraggio, gestione dei segreti ed eventuali dati persistenti.
Dal progetto locale a un indirizzo pubblico
Il percorso completo è lineare: preparare il progetto, trasferirlo sul VPS, mantenerlo in esecuzione come servizio gestito non root, puntare il DNS al server e terminare l'HTTPS pubblico sul reverse proxy. Claude Code può aiutare a preparare e spiegare questi elementi; la revisione e i controlli operativi restano comunque importanti.
Scopra i piani VPS Linux di SharpHeberg quando sarà pronto a mettere online un progetto locale. L'hosting fornisce l'ambiente server, non un abbonamento a Claude incluso né un modello Claude ospitato in locale.