15 settembre 2026
Dal laptop alla produzione: guida pratica a deploy, sicurezza e automazione per web app full‑stack
Un percorso “hands-on” su Ubuntu: server, runtime, reverse proxy, HTTPS, backup e CI/CD per pubblicare applicazioni in modo affidabile.
Portare una web app dalla macchina locale a un ambiente pubblico e sicuro richiede competenze che vanno oltre il framework: Linux, rete, processi, certificati, reverse proxy, backup e automazione. In questo articolo raccolgo un approccio pratico e progressivo: prima si costruisce tutto a mano su un server Ubuntu (come una VPS), poi si automatizza con pipeline CI/CD. L’obiettivo è capire davvero cosa succede “dietro le quinte” e acquisire un metodo riutilizzabile con qualunque stack (FastAPI/Vue, Node, Ruby, ecc.).
Portare una web app dal tuo laptop a un ambiente di produzione pubblico, sicuro e manutenibile è uno di quei passaggi che separano il “funziona sul mio PC” da un prodotto davvero utilizzabile. È anche il punto in cui tanti frontend (e non solo) iniziano a toccare con mano concetti come: SSH, firewall, reverse proxy, certificati TLS, processi in background, log, backup e automazione.
Qui trovi un percorso tecnico ma lineare per arrivarci: prima si configura tutto manualmente su Ubuntu, poi si passa all’automazione con CI/CD. L’ordine non è un dettaglio: fare le cose “a mano” una volta ti dà consapevolezza, e rende più semplice scegliere in seguito soluzioni gestite (PaaS, hosting automatici, ecc.) senza usarle “alla cieca”.
Il problema reale: la tua app non è raggiungibile
In locale hai:
- un frontend (Vue/React/SPA o SSR)
- un backend (Python/Node/Ruby…)
- magari un database o un servizio di ricerca
Finché gira sul tuo computer, gli utenti non possono accedervi. La soluzione è spostare codice e runtime in un ambiente di produzione (tipicamente una VPS), esporre solo ciò che serve e proteggere il tutto.
Sì, esistono piattaforme che collegano GitHub e fanno “deploy con un click”. Sono utilissime, ma iniziare da lì spesso significa non capire:
- dove finiscono i processi
- come passa il traffico
- chi può entrare nel server
- come ruotano i certificati
- cosa fai quando qualcosa si rompe alle 3 di notte
Filosofia operativa: manuale prima, automatico dopo
Un buon percorso di apprendimento segue questa sequenza:
- Provisioning del server e accesso sicuro
- Installazione dei runtime e avvio dei servizi applicativi
- Gestione di dati/servizi di supporto (es. motore di ricerca)
- HTTPS, DNS, CDN e hardening
- CI/CD e quality gates
- Monitoraggio, log, performance e manutenzione
Il valore è nel metodo: cambiano i comandi e i package, ma la struttura resta la stessa per quasi qualsiasi stack.
1) Fondamenta: server Ubuntu e accesso sicuro
Un setup solido parte prima ancora di clonare il repo.
VPS e sistema operativo
Scegli una VPS (DigitalOcean, Linode, AWS, ecc.) e installa una versione LTS di Ubuntu (ad esempio Ubuntu 24.04 LTS). L’hardware può essere virtuale o fisico: ciò che conta è che tu abbia un sistema Linux accessibile via rete.
SSH key, niente password
La misura più importante “subito” è questa:
- autenticazione via chiave SSH
- disabilitare login con password
Riduci drasticamente brute force e credential stuffing, perché non c’è una password da indovinare.
No root login
Altro caposaldo:
- creare un utente non-root
- disabilitare il login diretto di
root
Così anche in caso di compromissione riduci l’impatto e aumenti la tracciabilità.
Firewall: esporre solo ciò che serve
Appena il server è online, qualcuno lo scannerizza. Sempre. Configura un firewall (es. UFW) per consentire solo:
- SSH (porta eventualmente non standard, ma non è “sicurezza” da sola)
- HTTP/HTTPS quando serviranno
- niente porte applicative aperte “per comodità”
2) Runtime applicativo: backend stabile e reverse proxy
A questo punto puoi portare il codice sul server (clone da Git o trasferimento). Poi serve farlo girare in modo ripetibile.
Python/Node e ambienti isolati
Se hai un backend Python:
- installa Python e dipendenze di sistema
- crea un virtualenv
- installa requirements in modo deterministico
Attenzione alle VPS piccole: la swap
Su macchine con poca RAM potresti incontrare errori durante build/compilazioni di dipendenze. Una soluzione pragmatica è configurare swap usando spazio disco, così da evitare installazioni che falliscono per OOM (Out Of Memory).
Process manager e application server
Per un backend Python tipico (es. FastAPI) è comune combinare:
- Uvicorn (ASGI server)
- Gunicorn (process manager / multi-worker)
- Supervisor o systemd per mantenere i processi attivi e riavviarli
L’obiettivo non è “quale tool è il migliore”, ma ottenere:
- processi che ripartono dopo crash
- log gestibili
- avvio automatico al reboot
Nginx come reverse proxy (con Unix socket)
Il pattern più diffuso in produzione:
- Nginx esposto su 80/443
- backend non esposto direttamente a Internet
- comunicazione interna via Unix socket (o loopback)
Vantaggi: migliore controllo su header, timeouts, buffering, rate limiting, compressione, e soprattutto superficie d’attacco ridotta.
3) Servizi di supporto: dati, ricerca e backup
Molte app “vere” non sono solo frontend+API. C’è spesso un pezzo in più: ricerca, job queue, cache, ecc.
Migrare dati dal locale al server
Serve un flusso chiaro per:
- esportare/dumpare i dati in locale
- trasferirli
- ripristinarli sul server
Self-host di un motore di ricerca
Se ospiti un search engine (es. Meilisearch) sulla stessa VPS:
- crea un utente dedicato (separazione privilegi)
- configura un servizio systemd per esecuzione in background
- evita di esporre porte pubbliche se non necessario
Backup automatici
Non basta “fare backup ogni tanto”. Serve:
- script schedulati (cron/systemd timers)
- rotazione e retention
- test periodici di restore
Il backup che non hai mai provato a ripristinare è solo una speranza.
Dashboard in sicurezza: SSH tunneling
Per accedere a dashboard/strumenti interni senza aprire porte:
- usa SSH tunneling
Ottieni accesso locale al servizio remoto senza esporlo su Internet.
4) DNS, HTTPS, CDN e hardening
Quando l’app è online, arrivano due esigenze immediate: un dominio e una connessione sicura.
Dominio e record DNS
Collega il dominio alla VPS configurando record DNS (A/AAAA, eventualmente CNAME). È un passaggio spesso sottovalutato, ma fondamentale per:
- routing corretto
- certificati TLS
- CDN
HTTPS con Let’s Encrypt (e rinnovo automatico)
Let’s Encrypt rilascia certificati con durata limitata (tipicamente 90 giorni). Quindi serve:
- emissione del certificato
- rinnovo automatico
- reload di Nginx al rinnovo
Se non automatizzi, prima o poi ti scade in un weekend.
CDN per asset statici
Gli asset frontend sono perfetti per una CDN:
- riduci latenza globale
- scarichi traffico dalla VPS
- migliori performance percepite
Una strategia comune: backend sulla VPS, frontend statico servito via CDN, con caching aggressivo e invalidazione controllata.
5) Automazione: dal deploy manuale a CI/CD
Dopo aver fatto un deploy manuale completo, l’automazione ha finalmente senso: sai cosa stai automatizzando.
Protezione del branch principale
Regola pratica:
- niente push diretti su
main/master - passare da branch + PR
- required checks prima del merge
pre-commit: qualità prima ancora della PR
pre-commit permette di applicare regole locali al commit:
- formatting
- lint
- controlli banali ma costosi se scoperti tardi
Ti evita di “sporcare” la history con commit correttivi.
GitHub Actions: pipeline ripetibile
Una pipeline tipica:
- lint/format
- unit test
- (poi) integration/E2E
E soprattutto: bloccare il merge se i check falliscono. È il modo più semplice per ridurre regressioni e deploy rotti.
Deploy con un click (o senza click)
Una volta che main è “verde”, puoi arrivare a:
- deploy automatico
- oppure deploy manuale ma tracciato
Il punto non è solo la comodità: è la riproducibilità.
6) Operazioni: log, monitoraggio, difesa dai bot e performance
Quando l’app è in produzione, il lavoro non è finito: è iniziato.
Log Nginx e analisi leggibile
I log grezzi sono utili, ma poco fruibili. Uno strumento come GoAccess può trasformarli in report e dashboard per capire:
- endpoint più richiesti
- errori
- picchi di traffico
- user agent sospetti
Monitorare risorse
Un tool come btop rende immediato vedere:
- RAM/swap
- CPU
- I/O disco
- processi che degradano le performance
Bloccare IP malevoli
Dai log emergono pattern non umani (hit enormi, scanning). Ha senso:
- bloccare IP aggressivi
- applicare rate limiting
- ridurre sprechi di risorse
Load testing
Con una libreria come Locust puoi simulare utenti e stimare:
- throughput sostenibile
- latenza sotto carico
- punto di rottura
È uno dei modi più concreti per capire “quanto regge” la tua architettura prima che lo scoprano gli utenti.
Sintesi: un metodo riutilizzabile per qualsiasi stack
Il valore di questo percorso non è legato a FastAPI o Vue, a un provider specifico o a un tool “di moda”. È un modello mentale:
- metti in sicurezza l’accesso (SSH, utenti, firewall)
- separa responsabilità (reverse proxy, servizi dedicati, systemd)
- cura affidabilità (backup, rinnovi, restart)
- automatizza dopo aver capito (pre-commit, CI, deploy)
- osserva e difendi (log, monitoraggio, blocchi, test di carico)
Una volta che hai fatto almeno un deploy completo in questo modo, le piattaforme gestite diventano una scelta consapevole: saprai cosa stanno facendo al posto tuo, quali compromessi accetti e dove intervenire quando qualcosa non torna.