Gestire le app Laravel con cipi.yml
Di Andrea Pollastri · Aggiornato il: · lettura gratuita, nessun paywall
Lo stato che un'app si aspetta sul server — alias, PHP, worker, health, backup — di solito vive in un pannello o nella testa di qualcuno. Da Cipi 5.1 può vivere in un cipi.yml alla radice del repository, revisionato nello stesso pull request del codice che ne dipende. Questa guida è il loop pratico: generate, plan, apply, poi l'opt-in così ogni deploy riconcilia.
Perché il file sta accanto al codice
Una release che aggiunge un job in coda senza un worker è a metà. Un rollback che lascia l'upload_max_filesize della settimana scorsa è a metà. Lo stato del server di solito vive altrove: un pannello, una pagina wiki o la memoria di chi ha configurato il box.
Un cipi.yml committato accanto all'applicazione Laravel rende quello stato parte dello stesso pull request del codice che ne dipende. Il file è dichiarativo: descrive lo stato finale, non i passi. Cipi legge cosa c'è sul server, lo confronta con il file e ti mostra la differenza prima di toccare qualsiasi cosa.
La pagina prodotto cipi.yml — la config che viaggia con il codice è la panoramica. Lo schema completo è in Docs → Deploy → cipi.yml. Questa guida è il loop quotidiano su una sola app.
Parti dal server già in produzione
Non devi scrivere il file a mano. Su un box Cipi 5.1+, stampa la configurazione attuale dell'app — alias, versione PHP e impostazioni per-app, database extra, queue worker letti da Supervisor, Horizon, Reverb, lo scheduler e i profili di backup dell'app — come file pronto da committare:
$ cipi yml generate myapp > cipi.yml
$ cipi yml plan myapp # reports nothing to do
Committa quel file alla radice del repository. Cipi lo cerca in current/cipi.yml, poi current/cipi.yaml, poi shared/cipi.yml — override con --file=<path> se lo tieni altrove.
Preferisci un template vuoto e commentato? cipi yml example myapp ne stampa uno con database e profili placeholder già nel namespace dell'app, così il template valida così com'è.
I comandi che userai
| Comando | Cosa fa |
|---|---|
cipi yml generate |
Stampa la configurazione dell'app com'è sul server, pronta da committare |
cipi yml example |
Un template vuoto commentato, namespaced all'app così valida così com'è |
cipi yml validate |
Fa il parse del file e controlla ogni valore rispetto allo schema. Non cambia nulla |
cipi yml plan |
Il diff: ogni alias, worker, database, setting e profilo che verrebbe aggiunto, cambiato o rimosso |
cipi yml apply |
Applica il plan. Aggiungi --yes per script e CI |
cipi yml auto |
on / off / status — riconcilia dopo ogni deploy riuscito |
$ cipi yml generate myapp
$ cipi yml example myapp
$ cipi yml validate myapp
$ cipi yml plan myapp
$ cipi yml apply myapp [--yes]
$ cipi yml auto myapp on|off|status
Cosa puoi dichiarare
Sette aree. Non devi dichiararle tutte: vengono riconciliate solo le sezioni che scrivi.
- Alias — la lista dichiarata sostituisce quella attuale. Un alias che cancelli dal file viene rimosso da Nginx. I wildcard come
*.myapp.comsono accettati. Il dominio primario non si gestisce qui. - PHP e php.ini — fissa l'app a PHP 8.3, 8.4 o 8.5 (già installato sul server) e imposta gli override per-app:
upload_max_filesize,post_max_size,memory_limite il resto. I valori di sistema restano concipi ini set. - Database extra — oltre a quello creato con l'app, su MariaDB o PostgreSQL. Le credenziali finiscono in
shared/cipi-databases.enve non tornano mai nel repository. I database vengono creati, mai droppati. - Queue worker e Horizon — dichiara ogni coda con processi, tries e timeout, e Supervisor viene allineato. Oppure imposta
horizon: truee lascia le code a Horizon. Da 5.1.2,horizon: falseviene letto davvero: primafalsevaleva come chiave assente. - Laravel Reverb — da 5.1.2,
reverb: trueassegna all'app una porta localhost, un programma Supervisor, un proxy nginx per/app/{key}e/apps/{id}/…sul suo dominio, e genera le credenzialiREVERB_*. Solo app Laravel. Un'app che già possiede/appo/appsnon può condividere quel dominio con Reverb. - Scheduler — un booleano accende o spegne
* * * * * artisan schedule:run. Niente crontab da copiare sul server successivo. - Healthcheck — una probe HTTP su uno dei domini dell'app, ogni cinque minuti e di nuovo subito dopo ogni deploy. In opzione, rollback automatico di una release che fallisce — solo il symlink del codice; le migration non vengono disfatte.
- Profili di backup — profili per-app con scope, schedule, retention, destinazioni e cifratura. I nomi devono essere
myappomyapp-*.
Un file completo
Questo è quello che una app di produzione si porta dietro di solito. Gran parte la puoi generare; i commenti sono per il pull request.
version: 1
app:
php: "8.5"
aliases:
- "www.myapp.com"
- "*.myapp.com"
ini:
upload_max_filesize: 50M
post_max_size: 60M
memory_limit: 512M
databases:
- name: myapp_reporting
- name: myapp_analytics
engine: pgsql
workers:
horizon: false
reverb: false
queues:
- queue: default
processes: 2
- queue: emails
processes: 1
tries: 5
timeout: 300
schedule: true
health:
url: "https://myapp.com/up"
expect: 200
backup:
profiles:
- name: myapp-db
scope: db
databases: ["myapp", "myapp_*"]
exclude_tables: ["*.jobs", "*.telescope_*"]
every: 30m
keep: 48
destinations: [local]
- name: myapp-nightly
scope: all
cron: "0 2 * * *"
keep_days: 14
destinations: [s3]
encrypt: true
Plan, poi apply
Non cambia nulla finché non guardi il diff. cipi yml plan myapp elenca ogni alias, worker, database, setting e profilo che verrebbe aggiunto, cambiato o rimosso. Leggilo come un pull request.
$ cipi yml validate myapp
$ cipi yml plan myapp
$ cipi yml apply myapp # asks for confirmation
$ cipi yml apply myapp --yes # scripts and CI
Un file che fallisce la validazione viene rifiutato per intero e non viene mai applicato a metà. È lo stesso percorso fail-closed del deploy quando yml auto è acceso: email yml_fail, nessuno stato a metà sul box.
Una settimana di cambiamenti veri
Tratta il file come codice applicativo. Ognuno di questi è un commit di una riga (o un blocco), revisionato, poi applicato — o applicato in automatico dopo la release se yml auto è già acceso.
- Lunedì — alias. Aggiungi
www.myapp.come*.myapp.comper i subdomain multi-tenant. Ricorda: la lista è autorevole. Togliere un alias dal file lo toglie da Nginx. - Martedì — php.ini. Un form inizia ad accettare upload da 40 MB. Alza
upload_max_filesizeepost_max_sizeinapp.ini. I default di sistema restano concipi ini set. - Mercoledì — una nuova coda. La release aggiunge una coda
emails. Aggiungi il worker conprocesses,triesetimeout. Supervisor allinea il file. Se passi l'app a Horizon, impostahorizon: truee togli la lista delle code. - Giovedì — un database extra. Il reporting vuole il suo MariaDB (o
engine: pgsql). Chiamalomyapp_reporting. Le credenziali finiscono in/home/myapp/shared/cipi-databases.env— mai in Git. Cipi crea i database; non li droppa se poi togli la riga. - Venerdì — health e backup. Punta
health.urlahttps://myapp.com/up(deve essere uno dei domini dell'app). Aggiungi un profilo economicomyapp-dbogni 30 minuti e una copia cifrata notturna su S3.
PHP 8.5 deve già essere installato (cipi php install 8.5) prima di fissare app.php. Il file non installa un runtime che non è sul box.
Opt-in dopo ogni deploy
I deploy ignorano il file finché non dici il contrario. È voluto: il primo commit di cipi.yml non deve sorprendere la produzione.
$ cipi yml auto myapp on # riconcilia dopo ogni deploy riuscito
$ cipi yml auto myapp status
$ cipi yml auto myapp off # back to manual apply
Con l'opt-in, ogni deploy riuscito riconcilia — sia da cipi deploy sia dal webhook Git. Una release senza cipi.yml è un no-op silenzioso. Un file che fallisce la validazione viene segnalato via email (yml_fail) e non applicato a metà. Una riconciliazione riuscita spara yml_apply.
Cosa il file non tocca
- Può solo configurare un'app che esiste già — mai crearla, rinominarla o cancellarla.
- Le sezioni che ometti restano intatte. L'unica eccezione voluta è la lista alias: è autorevole.
- Il database primario dell'app e i profili di backup di sistema restano tuoi.
generateli lascia fuori di proposito. - I database vengono creati, mai droppati. Togliere una riga dal file non cancella il database.
- Nessun campo porta un comando shell o un path da includere. Le chiavi sconosciute sono errori.
Perché è sicuro accettarlo da Git
Il file arriva da un repository, quindi chi può committare ne controlla il contenuto. Lo schema è fail-closed da cima a fondo:
- I database devono chiamarsi
<app>o<app>_*; i profili di backup<app>o<app>-*. - L'URL dell'healthcheck deve risolvere su uno dei domini dell'app — altrimenti un commit potrebbe puntare il prober dei cinque minuti a un indirizzo interno e leggere la risposta dalle email di alert.
- Il parser implementa un sottoinsieme piccolo di YAML e rifiuta a priori anchor, alias, tag, merge key, block scalar e flow mapping.
Quando yml auto è acceso, chi può pushare su quel repository può cambiare alias, PHP, worker, healthcheck e profili di backup dell'app. È il punto del configuration-as-code: tratta l'accesso in scrittura al repo di conseguenza.
Porta il file con la prossima release
Genera quello che il server ha già, committa, leggi il plan, poi accendi yml auto quando ti fidi del loop. La panoramica e lo schema completo sono a un click.
Domande frequenti
Devo scrivere cipi.yml a mano?
No. cipi yml generate <app> stampa la configurazione attuale dell'app come file pronto da committare, e cipi yml example stampa un template vuoto commentato se preferisci partire da zero.
Un deploy applica il file in automatico?
Solo dopo l'opt-in con cipi yml auto <app> on. Fino ad allora i deploy ignorano il file e riconcili a mano con plan e apply.
Cosa succede a quello che il file non menziona?
Restano intatti. Vengono riconciliate solo le sezioni che dichiari — con un'eccezione voluta: la lista alias è autorevole, quindi togliere un alias dal file lo toglie dal server.
Un commit può rompere il server?
Lo schema non porta comandi shell né path da includere, un'app può toccare solo i propri database e profili di backup, e un file che fallisce la validazione viene rifiutato per intero invece di essere applicato a metà. I deploy ignorano il file finché non accendi yml auto.
Funziona con il webhook Git?
Sì. Con cipi yml auto acceso, sia cipi deploy sia un deploy da webhook riconciliano dopo una release riuscita.