Il problema che hai (e che abbiamo visto decine di volte)
Il tuo team rilascia una nuova feature e il sito va in crash. Oppure passi giorni a configurare server a mano, dimenticando un permesso. O ancora: i test li esegue solo il collega 'bravo' prima di mettere in produzione, e quando non c'è si rilascia a occhi chiusi. Se riconosci una di queste scene, sai già che il ciclo di sviluppo è il collo di bottiglia. Noi, di Meteora Web, ci siamo passati. Dal 2017 lavoriamo con aziende che passano dal caos delle release manuali a pipeline automatizzate che tagliano errori e tempi morti. Questa guida copre tutto quello che serve per costruire una cultura DevOps solida e pipeline CI/CD funzionanti – dal banco di sviluppo al server di produzione.
DevOps non è uno strumento, è una cultura (e un metodo per smettere di litigare)
Troppe volte vediamo team che comprano Jenkins, installano GitLab e poi continuano a lavorare come prima: gli sviluppatori scrivono codice, lo buttano oltre il muro agli ops, e quando qualcosa si rompe la colpa vola da una parte all'altra. DevOps elimina quel muro. Non significa che tutti devono saper fare tutto, ma che dev e ops condividono obiettivi, metriche e processi. L'infrastruttura è codice, i deploy sono ripetibili, i test sono automatici.
Da dove iniziare concretamente
Prima di toccare uno strumento, rispondi a tre domande:
- Quanto tempo passa tra un commit e il deploy in produzione?
- Quanti passaggi manuali ci sono in mezzo?
- Quante volte un deploy rompe qualcosa che funzionava?
Se la risposta alla prima è "giorni" e alla terza "spesso", hai già il tuo primo obiettivo: ridurre il tempo e aumentare la confidenza. Non serve tutto subito. Inizia con un solo repository, un solo ambiente staging, una pipeline che lancia test e deploya su staging automaticamente. Poi estendi.
GitHub Actions: la CI/CD integrata che usiamo quasi sempre
Per progetti nuovi, GitHub Actions è la scelta più rapida. È integrato con il tuo repository, non devi gestire server, e la sintassi YAML è pulita. Noi, di Meteora Web, lo usiamo per progetti Laravel, Vue e WordPress su misura. Ecco un esempio concreto: workflow che esegue test, build e deploy su un server Linux via SSH.
Sponsored Protocol
name: Deploy to production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
extensions: mbstring, pdo, bcmath
- name: Install dependencies
run: composer install --no-dev --optimize-autoloader
- name: Run tests
run: php artisan test
- name: Deploy via SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.DEPLOY_HOST }}
username: ${{ secrets.DEPLOY_USER }}
key: ${{ secrets.DEPLOY_KEY }}
script: |
cd /var/www/project
git pull origin main
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan optimize
Attenzione ai segreti: non scrivere mai host, user o chiavi nel file YAML. Usa i secret di GitHub. Vediamo spesso progetti in cui le credenziali sono in chiaro nel repository – è il primo errore che correggiamo.
Trigger intelligenti
Non tutto deve andare in produzione con ogni push. Usa filtri: branches, paths, tags. Esempio: esegui la pipeline solo se tocchi file in src/ o tests/, non quando modifichi la documentazione.
Pipeline CI: test, linting e build automatici
La "CI" (Continuous Integration) è il cuore del processo. Ogni volta che un dev fa un push, la piattaforma esegue automaticamente linting (ESLint, PHP_CodeSniffer), unit test, analisi statica e build. Se una fase fallisce, la pipeline si blocca e il team viene notificato. Non si arriva al deploy con codice rotto.
Step pratici per una CI solida
- Lint: imposta regole condivise e blocca la pipeline se non passano.
- Unit test: copertura minima (es. 70%), ma meglio test significativi che percentuali gonfiate.
- Build: compila asset (npm run build), verifica che il pacchetto sia deployabile.
- Security scan: strumenti come Dependabot o Snyk per vulnerabilità nelle dipendenze. Lo integriamo sempre nei nostri progetti.
Un consiglio: non lanciare tutti i test su ogni push in ogni ramo. Per feature branch, esegui solo unit test veloci. La suite completa va sui rami principali prima del merge.
Sponsored Protocol
CD: deploy automatico su staging e produzione
La Continuous Delivery (CD) è la naturale evoluzione: dopo che la CI passa, il codice viene deployato automaticamente in un ambiente staging, e con un clic (o automaticamente dopo approval) in produzione. L'obiettivo è rendere il deploy un'operazione noiosa e ripetibile, non un evento stressante.
Staging first
Ogni deploy in produzione dovrebbe passare prima da staging. Staging è identico a produzione per infrastruttura, dati (anonimizzati) e configurazioni. Noi usiamo lo stesso playbook Ansible per entrambi, cambiando solo il target host.
GitLab CI/CD: l'alternativa self-hosted che controlli al 100%
Se per motivi di compliance o dati sensibili non vuoi dipendere da GitHub Actions, GitLab CI/CD con runner self-hosted è la scelta. Noi di Meteora Web abbiamo scelto GitLab per diversi progetti con clienti del Sud Italia che trattano dati sanitari: full control, nessun limite di minuti, repository privati senza costi nascosti.
Confronto rapido
| Caratteristica | GitHub Actions | GitLab CI/CD |
|---|---|---|
| Runner hosted gratuiti | 2000 min/mese (con repo pubblico) | 400 min/mese |
| Self-hosted runner | Sì | Sì, nativo |
| Registry container | GHCR | GitLab Container Registry |
| Auto DevOps | No | Sì (template predefiniti) |
GitLab CI/CD si configura con un file .gitlab-ci.yml nella root. Ecco un esempio che deploya su un server con Docker dopo test e build:
stages:
- test
- build
- deploy
variables:
DOCKER_TLS_CERTDIR: "/certs"
test:
stage: test
image: php:8.2-cli
script:
- composer install
- php artisan test
build:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
deploy:
stage: deploy
image: alpine:latest
script:
- apk add --no-cache openssh-client
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
- ssh server.com "docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA && docker stack deploy ..."
Nota: i segreti (variabili protette) si impostano nelle CI/CD Settings del progetto.
Sponsored Protocol
Infrastructure as Code con Terraform: smetti di configurare a mano
Se ancora entri in SSH per installare pacchetti o modificare Nginx, stai perdendo tempo e sicurezza. L'infrastruttura come codice (IaC) significa descrivere server, reti, database e DNS in file versionati. Terraform è lo strumento più diffuso: dichiari lo stato desiderato e lui lo applica.
Provider, stato e moduli
Ogni provider (AWS, DigitalOcean, Cloudflare) ha una documentazione. Il file di stato (terraform.tfstate) tiene traccia delle risorse reali – va conservato in un backend remoto (S3, GitLab). I moduli riutilizzabili evitano di riscrivere la stesso codice per ogni progetto.
provider "digitalocean" {
token = var.do_token
}
resource "digitalocean_droplet" "web" {
image = "ubuntu-22-04-x64"
name = "web-prod-01"
region = "fra1"
size = "s-2vcpu-4gb"
ssh_keys = [var.ssh_key_id]
}
output "ip" {
value = digitalocean_droplet.web.ipv4_address
}
Noi usiamo Terraform per ogni nuovo progetto: provisioning di server, database, bilanciatori e domini in un unico comando. Non si dimentica mai un firewall o un record DNS.
Ansible: configurazione server e deploy senza sorprese
Ansible completa Terraform: mentre Terraform crea l'infrastruttura, Ansible la configura (installa PHP, Nginx, configura vhost, deploya l'applicazione). È agentless: basta SSH e Python sul server.
---
- name: Deploy Laravel application
hosts: webservers
become: yes
tasks:
- name: Ensure git is installed
apt:
name: git
state: present
- name: Clone repository
git:
repo: 'https://github.com/user/project.git'
dest: /var/www/project
version: main
- name: Install composer dependencies
composer:
command: install
working_dir: /var/www/project
no_dev: yes
- name: Set permissions
file:
path: /var/www/project/storage
state: directory
mode: '0775'
owner: www-data
Combina Terraform + Ansible in una pipeline CI/CD: dopo il terraform apply, lancia un playbook Ansible per configurare e deployare. Automazione completa.
Sponsored Protocol
Feature flags: deploy continuo senza rompere la produzione
Anche con pipeline perfette, alcune funzionalità vanno attivate gradualmente. I feature flags (o toggles) permettono di deployare codice spento e accenderlo in seguito senza un nuovo deploy. Strumenti come LaunchDarkly o un semplice database flags gestito dall'app. Noi, nei progetti Laravel, usiamo un model FeatureFlag con cache: basta un pannello admin per attivare una nuova funzione su una percentuale di utenti.
Vantaggio concreto
Deployi il codice il lunedì, lo testi in produzione su un piccolo gruppo. Se va bene, aumenti la percentuale. Se qualcosa si rompe, disattivi il flag in un secondo, senza rollback. Riduce il rischio e permette rilasci più frequenti.
Blue-Green e Canary deployment: zero downtime reale
Deploy senza fermare il servizio è possibile con due strategie complementari.
Blue-Green
Mantieni due ambienti identici (blue e green). Il traffico va su blue. Deployi la nuova versione su green, testi, poi cambi il load balancer per puntare su green. Se qualcosa va male, torni a blue. Zero downtime, rollback immediato. Il costo è doppio: due server per ambiente.
Canary
Invece di switch totale, instradare una piccola percentuale di traffico sulla nuova versione (es. 5% degli utenti). Monitori errori e latenza. Se stabile, aumenti gradualmente fino al 100%. Strumenti: Kubernetes (con service mesh come Istio) o bilanciatori di carico configurabili. Per progetti più piccoli, un semplice proxy Nginx con weighted upstream può simulare il canary.
Monitoring e alerting: se non misuri, non migliori
Pipeline CI/CD e infrastruttura automatizzata sono inutili se non sai se la produzione è sana. Il monitoring non è un optional, è il feedback loop che chiude il ciclo DevOps.
Sponsored Protocol
Prometheus + Grafana
Prometheus raccoglie metriche (CPU, memoria, request rate, error rate). Grafana le visualizza in dashboard. Puoi anche esporre metriche personalizzate dalla tua applicazione (es. numero di ordini processati, tempo medio di risposta).
SLO/SLA
Service Level Objective (SLO): la soglia che ti impegni a mantenere (es. uptime 99.9%, latenza sotto 200ms). Service Level Agreement (SLA) è il contratto con il cliente. Imposta alert quando superi il burn rate dell'SLO, non quando è già rotto.
# example alert rule in Prometheus
groups:
- name: exemplo
rules:
- alert: HighErrorRate
expr: job:request_errors:rate1m{job="api"} > 0.05
for: 5m
labels:
severity: critical
annotations:
summary: "Error rate above 5% for 5 minutes"
Noi includiamo sempre un setup di base con Prometheus e Grafana nei progetti che richiedono uptime garantito. I costi di un monitoraggio trascurato sono molto più alti di qualche ora di setup.
In sintesi – cosa fare adesso
- Audita il tuo processo attuale. Cronometra i passaggi manuali. Scegli un progetto pilota (non il più critico).
- Imposta una pipeline CI. GitHub Actions o GitLab CI: inizi con lint e test su ogni push del ramo principale.
- Aggiungi staging automatico. Deploy automatico su staging dopo CI passata.
- Automatizza l'infrastruttura. Terraform per il provisioning, Ansible per la configurazione. Versiona tutto.
- Introduci feature flags. Anche semplici: un file di configurazione nel repository.
- Scegli una strategia di deploy. Blue-green se hai budget, canary se hai traffico variabile.
- Monitora. Almeno uptime e error rate. Poi metriche applicative.
Ogni passo riduce il rischio e aumenta la frequenza di rilascio. Non serve fare tutto insieme: inizia con un pezzo, misura il miglioramento, continua. Noi accompagniamo i clienti in questo percorso da 8 anni. Se vuoi confrontarti, siamo a Sciacca ma lavoriamo ovunque. Il divario digitale si colma anche così – con pipeline che funzionano, non con slide.