Infrastruttura
cipi php
PHP 8.5 è preinstallato durante il setup. Puoi aggiungere altre versioni in qualsiasi momento; da v4.5.12 Cipi analizza le sorgenti APT per codename Ubuntu — di solito la PPA ondrej/php su 24.04, packages.sury.org su 26.04 quando Launchpad non ha una suite, oppure Ubuntu main come ultima risorsa (co-installabili 8.3–8.5 dove il repository scelto le supporta).
cipi php install, cipi php switch, cipi app create e cipi app edit accettano quindi solo 8.3, 8.4 e 8.5. Le versioni legacy (7.4–8.2) restano rilevabili e rimovibili, così puoi ancora ripulire un server pre-4.5.4 con cipi php remove <old-version>.$ cipi php list # list installed versions, status, and system default $ cipi php install 8.4 # install an additional PHP version (8.3–8.5) $ cipi php switch 8.4 # set system default (root/cipi, API pool) $ cipi php remove 8.1 # remove a version, incl. legacy (blocks if default or apps use it) $ cipi php upgrade # apply security patches to all installed PHP packages
Aggiornamenti di sicurezza
Da v4.7.13, i pacchetti PHP sono esclusi da unattended-upgrades e gestiti da Cipi. cipi php upgrade esegue apt-get update e --only-upgrade su ogni pacchetto php* e libphp* installato, poi riavvia i pool PHP-FPM interessati. Quando SMTP è configurato e i pacchetti sono stati aggiornati, Cipi invia un'email (trigger php_upgrade; disabilita con cipi notifications disable php_upgrade).
Un controllo settimanale parte automaticamente la domenica alle 03:30 tramite crontab di root (wrappato da cipi-cron-notify). Log: /var/log/cipi/php-upgrade.log. I server esistenti ricevono il cron con cipi self-update (migrazione 4.7.13).
PHP predefinito di sistema vs PHP specifico per app
Il default di sistema è la versione PHP usata dagli utenti root e cipi, dal pool FPM dell'API Cipi e dal queue worker dell'API. Usa cipi php switch <ver> per cambiarla. Il comando migra il pool API, riavvia il worker API e invia una notifica email se SMTP è configurato.
Ogni app ha la propria versione PHP (impostata a app create o tramite cipi app edit --php=). Deployer, Composer, i trigger di deploy nel crontab e cipi sync import girano sempre con il PHP configurato per l'app — mai con il default di sistema.
Per passare un'app esistente a una versione diversa:
$ cipi app edit myapp --php=8.5
Cambia la versione PHP a caldo con zero downtime: aggiorna il pool FPM, il socket Nginx, i worker Supervisor, il crontab, la config Deployer e .env in un'unica operazione atomica.
cipi db
Cipi crea automaticamente un database dedicato per ogni app Laravel durante app create. MariaDB (porta 3306) è il default nativo; da v4.8.0 puoi anche installare PostgreSQL opzionale (porta 5432) e scegliere un engine per database o app. Le app custom non ricevono un database — usa cipi db create --name=<app> se ti serve (es. per WordPress o un altro CMS). Dopo il setup viene mostrato un URL di connessione pronto all'uso (MariaDB: mariadb+ssh://), che combina credenziali SSH, IP del server e informazioni sul database per client GUI come TablePlus, DBeaver o Sequel Pro.
Engine (v4.8.0+)
$ cipi db install pgsql # install optional PostgreSQL $ cipi db uninstall pgsql|mariadb # remove a non-default engine (destroys data) $ cipi db default mariadb|pgsql # server-wide default when --engine is omitted $ cipi db engines # installed engines, ports, and default
Ciclo di vita del database
$ cipi db create # interactive $ cipi db create --name=analytics # non-interactive (default engine) $ cipi db create --name=analytics --engine=pgsql $ cipi db list [--engine=mariadb|pgsql] # list databases with sizes $ cipi db backup myapp [--engine=…] $ cipi db restore myapp backup.sql.gz [--engine=…] $ cipi db password myapp [--engine=…] # regenerate password $ cipi db delete analytics [--engine=…]
Le app Laravel memorizzano l'engine scelto nei metadati dell'app; backup, sync e cipi app reset-db-password lo seguono. Usa cipi app create --engine=pgsql (o il prompt interattivo) per provisionare un'app Laravel su PostgreSQL — .env e l'URL di connessione corrispondono all'engine. Reset password root: cipi reset db-password [--engine=].
cipi alias
Aggiungi più domini o sottodomini a qualsiasi app. Dopo aver aggiunto alias, esegui cipi ssl install per provisionare o rinnovare il certificato con copertura SAN per tutti i domini. Da v4.8.0, cipi alias add|remove rigenera il vhost e riapplica SSL con certbot install --redirect così HTTPS non viene perso.
$ cipi alias add myapp www.myapp.com $ cipi alias add myapp myapp.it $ cipi alias list myapp $ cipi alias remove myapp myapp.it
Per i redirect canonici www ↔ apex, preferisci cipi www invece di gestire a mano l'host counterpart.
cipi www
Disponibile da v4.8.0. Gestisci alias www/apex e redirect canonici 301 per un'app. Lo stato vive in apps.json (www_redirect); Nginx emette un server block dedicato al redirect (percorso ACME lasciato pubblico) che sopravvive alla rigenerazione del vhost. SSL viene riapplicato tramite certbot install --redirect.
$ cipi www add myapp # add counterpart host (www ↔ apex) $ cipi www force-to-root myapp # 301 www.domain → domain $ cipi www force-from-root myapp # 301 domain → www.domain $ cipi www clear myapp # clear redirect state $ cipi www status myapp # inspect redirect state
force-to-root / force-from-root aggiungono automaticamente l'alias mancante quando serve.
cipi domains
Disponibile da v4.5.5. Comando di top level che elenca ogni dominio e alias su tutte le app in un'unica tabella — la controparte globale di cipi alias list <app> per app. Ideale per auditare l'intera mappa dominio→app o individuare un dominio a cui manca ancora un certificato.
$ cipi domains # list all domains and aliases across every app
Ogni riga mostra le seguenti colonne:
| Colonna | Descrizione |
|---|---|
| DOMAIN | Il nome del dominio o dell'alias. Le righe sono ordinate alfabeticamente per dominio. |
| APP | L'app proprietaria del dominio. |
| KIND | primary o alias. |
| TYPE | Laravel o Custom. |
| PHP | La versione PHP dell'app. |
| DOCROOT | public per app Laravel, /<docroot> per app custom. |
| BRANCH | Il branch Git deployato per l'app. |
| LAST DEPLOY | Età relativa leggibile (just now, 10m ago, 2h ago, 3d ago, 2w ago, 2mo ago, 2y ago) — derivata dal mtime del symlink current dell'app, che Deployer riallinea atomicamente a ogni deploy riuscito. Mostra - quando l'app non è mai stata deployata. |
| SSL | Stato del certificato per nome (✓/✗), rilevato da /etc/letsencrypt/live/<domain>. |
| REPOSITORY | Il repository Git, oppure (SFTP only) per app custom senza repo. |
| (suffix) | Quando l'app proprietaria è sospesa, ogni riga termina con ⏸ suspended (giallo). Il footer riporta anche quante app sono sospese. |
Un footer riassume i totali — numero di domini, app, certificati e app sospese — così puoi auditare l'intera mappa a colpo d'occhio.
cipi ssl
Certbot gestisce i certificati Let's Encrypt. I certificati si rinnovano automaticamente tramite un cron settimanale. cipi ssl status mostra le date di scadenza con avvisi a colori: verde (>30 giorni), giallo (14–30 giorni), rosso (<14 giorni).
$ cipi ssl install myapp # provision / renew — includes all aliases (SAN) $ cipi ssl force myapp # re-apply HTTP→HTTPS redirect (no new issuance) $ cipi ssl renew # force renewal of all certificates $ cipi ssl status # show all certs with expiry dates # DNS-01 via Cloudflare (v5.0+) — wildcard certs $ cipi ssl dns set --provider=cloudflare --token=YOUR_CF_TOKEN $ cipi ssl install myapp --dns=cloudflare $ cipi ssl install myapp --dns=cloudflare --wildcard
Da v4.8.0, cipi ssl force <app> riapplica il redirect HTTP → HTTPS per un'app che ha già un certificato Let's Encrypt — senza emetterne uno nuovo. cipi ssl install imposta anche force_https in apps.json automaticamente.
Da v5.0, le challenge opzionali DNS-01 via Cloudflare sostituiscono il flusso HTTP-01 predefinito quando ti servono certificati wildcard o non puoi esporre la porta 80. Configura una volta con cipi ssl dns set, poi passa --dns=cloudflare (e opzionalmente --wildcard) a cipi ssl install.
cipi alias add, esegui sempre di nuovo cipi ssl install per provisionare un nuovo certificato SAN che copra tutti i domini. Se il redirect HTTPS è andato perso dopo un cambio vhost, usa cipi ssl force invece di riemettere.
cipi backup
Esegui backup di database e storage su Amazon S3 o qualsiasi provider compatibile S3 (Hetzner Object Storage, DigitalOcean Spaces, Backblaze B2, MinIO, ecc.).
Configurazione
$ cipi backup configure # → AWS Access Key ID # → AWS Secret Access Key # → Bucket name # → Region # → Endpoint URL (leave empty for AWS; required for other providers)
Endpoint compatibili S3
| Provider | URL endpoint |
|---|---|
| AWS S3 | lascia vuoto |
| Hetzner | https://<datacenter>.your-objectstorage.com |
| DigitalOcean Spaces | https://<region>.digitaloceanspaces.com |
| Backblaze B2 | https://s3.<region>.backblazeb2.com |
| MinIO | https://your-minio-host |
Esecuzione dei backup
$ cipi backup configure # configure S3 credentials $ cipi backup run # backup all apps $ cipi backup run myapp # backup a single app $ cipi backup list # list all backups $ cipi backup list myapp # list backups for one app $ cipi backup prune myapp --weeks=4 # delete backups older than 4 weeks
Ogni backup viene caricato su s3://your-bucket/cipi/appname/YYYY-MM-DD_HHMMSS/ e contiene:
db.sql.gz— dump del database compressoshared.tar.gz— l'intera directoryshared/(.env+storage/)
Da v4.7.14, lo staging dei backup usa di default /var/tmp (disco) invece di /tmp (spesso un tmpfs RAM di dimensioni limitate), così le app grandi non falliscono a metà backup quando il tmpfs si riempie. Override con tmpdir in backup.json (impostato via cipi backup configure) o la variabile d'ambiente CIPI_BACKUP_TMPDIR.
Pianificazione backup automatici
# Add to root crontab (crontab -e)
0 2 * * * /usr/local/bin/cipi backup run >> /var/log/cipi/backup.log 2>&1
Pulizia backup obsoleti da S3
I backup si accumulano nel tempo. Usa cipi backup prune per eliminare da S3 le cartelle di backup più vecchie di N settimane. Eseguilo come job cron insieme al backup stesso.
$ cipi backup prune myapp --weeks=4 # delete backups older than 4 weeks $ cipi backup prune myapp --weeks=2 # keep only the last 2 weeks
Aggiungi entrambi i comandi al crontab di root per eseguirli automaticamente:
# root crontab — backup at 02:00, prune at 03:00 (keep 4 weeks)
0 2 * * * /usr/local/bin/cipi backup run myapp >> /var/log/cipi/backup.log 2>&1
0 3 * * * /usr/local/bin/cipi backup prune myapp --weeks=4 >> /var/log/cipi/backup-prune.log 2>&1
cipi backup prune legge le credenziali S3 da /etc/cipi/backup.conf, scritto da cipi backup configure. Funziona con qualsiasi provider compatibile S3. Regola --weeks in base alla tua policy di retention (es. --weeks=2 per due settimane, --weeks=8 per due mesi).
Crontab utente
Cipi aggiunge automaticamente una voce crontab per lo scheduler Laravel quando crei un'app:
# installed automatically by cipi app create
* * * * * /usr/bin/php8.5 /home/myapp/current/artisan schedule:run >> /dev/null 2>&1
Questa voce gira come utente Linux myapp ogni minuto, usando la versione PHP selezionata per l'app. Viene aggiornata automaticamente quando cambi versione PHP con cipi app edit myapp --php=X.
Visualizzare il crontab attuale
# as root — view the app user's crontab $ crontab -u myapp -l # or after switching to the app user $ su - myapp myapp@server:~$ crontab -l
Aggiungere job cron personalizzati
Puoi aggiungere job cron extra al crontab dell'utente app. Passa prima all'utente app per assicurarti che i job girino con il contesto utente e i permessi file corretti:
$ su - myapp
myapp@server:~$ crontab -e
Esempi di voci che potresti aggiungere:
# existing Laravel scheduler (do not remove) * * * * * /usr/bin/php8.5 /home/myapp/current/artisan schedule:run >> /dev/null 2>&1 # nightly database backup at 2 AM 0 2 * * * /usr/local/bin/cipi db backup myapp >> /home/myapp/logs/backup.log 2>&1 # custom script every 15 minutes */15 * * * * /home/myapp/current/scripts/sync.sh >> /home/myapp/logs/sync.log 2>&1
cipi app edit myapp --php=<current-version> per ripristinarla. Tieni sempre la riga schedule:run come prima voce così è facile identificarla.
/home/myapp/. I job che richiedono accesso root vanno aggiunti al crontab di root, con crontab -e come root.
Verificare che cron funzioni
# check system cron log $ grep CRON /var/log/syslog | grep myapp | tail -20 # check Laravel scheduler execution $ cipi app artisan myapp schedule:list
cipi schedule
Da v5.0, gestisci la voce crontab dello scheduler Laravel che esegue schedule:run (il crontab esisteva già; ora è attivabile/disattivabile e tracciato in apps.json).
$ cipi schedule on myapp $ cipi schedule off myapp $ cipi schedule status myapp
cipi worker & Laravel Horizon
Ogni app ottiene un worker Supervisor predefinito per la queue default. Puoi aggiungere queue aggiuntive con conteggi processo e timeout personalizzati.
$ cipi worker add myapp --queue=emails --processes=3 $ cipi worker add myapp --queue=exports --processes=1 --timeout=7200 $ cipi worker list myapp $ cipi worker edit myapp --queue=default --processes=3 $ cipi worker remove myapp emails $ cipi worker restart myapp # restart all workers for the app $ cipi worker stop myapp # stop all workers for the app (used during deploys) # Laravel Horizon (v5.0+) — mutually exclusive with queue:work workers $ cipi worker horizon enable myapp $ cipi worker horizon status myapp $ cipi worker horizon disable myapp
Con Horizon abilitato, il deploy esegue horizon:terminate e riavvia i worker tramite cipi-worker. Non puoi far girare worker classici queue:work e Horizon sulla stessa app contemporaneamente.
| Flag | Descrizione |
|---|---|
| --queue=<name> | Nome della queue da consumare (es. default, emails, exports)
|
| --processes=<n> | Numero di processi worker paralleli |
| --timeout=<seconds> | Timeout del job in secondi. Il default è 60. |
I worker vengono fermati prima dello swap del symlink e riavviati dopo ogni deploy, evitando che Supervisor usi percorsi artisan obsoleti. Supervisor è configurato con autorestart=unexpected così i worker si riavviano solo in caso di uscita inattesa, non su stop graceful.
Helper utente app: cipi-worker
Ogni utente app può riavviare, fermare o controllare i worker senza root — tramite un helper sudo ristretto installato in /usr/local/bin/cipi-worker:
# run as the app user (SSH or sudo su - myapp) $ sudo cipi-worker status myapp $ sudo cipi-worker stop myapp # used by Deployer before symlink swap $ sudo cipi-worker restart myapp
Come root, usa cipi worker list|restart|stop <app>. Non esiste un comando admin cipi worker status — usa cipi worker list o l'helper utente app sopra.
cipi health
Da v5.0, configura healthcheck HTTP per app. Un cron gira ogni 5 minuti; dopo 3 fallimenti consecutivi Cipi notifica tramite il trigger health_fail (SMTP se configurato).
$ cipi health set myapp --url=https://myapp.com/up --expect=200 $ cipi health check myapp $ cipi health list $ cipi health unset myapp
cipi firewall
Cipi installa UFW con le porte 22, 80 e 443 aperte di default. Usa i comandi firewall per gestire regole aggiuntive senza toccare UFW direttamente.
$ cipi firewall allow 3306 # open a port $ cipi firewall allow 3306 --from=10.0.0.5 # allow from specific IP $ cipi firewall allow 3306 --from=10.0.0.0/24 # allow from subnet $ cipi firewall deny 8080 # block a port $ cipi firewall list # show all rules
cipi ban
Ispeziona e gestisci i ban Fail2ban direttamente dalla CLI. Cipi configura Fail2ban con ban progressivi: ban base di 24 ore che raddoppia a ogni recidiva fino a un tetto di 7 giorni, con tentativi massimi ridotti a 3. Una jail dedicata recidive banna i recidivi per 7 giorni dopo 3 ban entro 24 ore.
$ cipi ban list # list all banned IPs, grouped by jail $ cipi ban unban 203.0.113.42 # unban a specific IP from all jails
cipi ban list
Elenca ogni IP attualmente bannato da Fail2ban, raggruppato per jail (es. sshd, recidive). Utile per un controllo rapido della sicurezza o prima di un unban.
cipi ban unban <IP>
Rimuove l'IP indicato da tutte le jail Fail2ban in un colpo solo. Comodo quando un utente legittimo o un runner CI viene bloccato per errore.
cipi self-update. Non serve configurazione manuale.
cipi service
Controlla e gestisci i servizi di sistema che alimentano Cipi direttamente dalla CLI. Nginx usa un reload graceful (zero downtime) invece di un restart completo.
$ cipi service list # status of all services $ cipi service list nginx # status of a specific service $ cipi service restart # restart all services $ cipi service restart nginx # graceful reload (zero downtime) $ cipi service restart php # restart all PHP-FPM versions $ cipi service start fail2ban $ cipi service stop supervisor # asks for confirmation
Nomi servizio supportati: nginx, mariadb, postgresql (alias: pgsql, postgres — se installato via cipi db install pgsql), valkey-server, supervisor, fail2ban, php<ver>-fpm (es. php8.5-fpm). La keyword php punta a tutte le versioni PHP-FPM installate in una volta. Per il backend cache, redis-server, redis e valkey sono accettati come alias di valkey-server.
Valkey — il fork compatibile Redis con licenza BSD — è incluso nello stack predefinito e sostituisce redis-server da Cipi 4.5.6. È installato con password, legato solo a localhost, e le credenziali (utente, password) sono salvate in /etc/cipi/server.json e mostrate a fine installazione. valkey-server è aggiunto alla blacklist di unattended-upgrades — Cipi lo gestisce, quindi non viene aggiornato automaticamente. Vedi la sezione Valkey per i dettagli e la migrazione automatica Redis → Valkey.
cipi ssh — Gestione chiavi SSH
Gestisci le chiavi SSH autorizzate per l'utente cipi — il punto di ingresso SSH admin. L'utente cipi (gruppo cipi-ssh) usa solo chiave pubblica; il login root è disabilitato. Gli utenti app (gruppo cipi-apps) si connettono con password — vedi SSH come utente app.
Comandi
$ cipi ssh list # list all authorized keys with fingerprint, comment, and current-session marker $ cipi ssh add [key] # add a new SSH public key (validates format, prevents duplicates) $ cipi ssh remove [n] # remove a key by number $ cipi ssh rename [n] [name] # change the display name / comment of a key
Meccanismi di sicurezza
cipi ssh remove include due salvaguardie per evitare il lockout:
- Protezione sessione corrente — non puoi rimuovere la chiave usata dalla tua sessione SSH attiva.
- Protezione ultima chiave — non puoi rimuovere l'ultima chiave autorizzata rimasta.
Commenti delle chiavi
Le chiavi SSH sono memorizzate con i commenti originali intatti, così è facile capire a chi appartiene ogni chiave. Usa cipi ssh rename per cambiare il nome visualizzato di una chiave:
# list keys to find the number $ cipi ssh list # rename key #2 $ cipi ssh rename 2 "john-macbook"
Notifiche email
Quando SMTP è configurato, Cipi invia un avviso email ogni volta che una chiave viene aggiunta, rimossa o rinominata. La notifica include hostname del server, indirizzo IP, fingerprint della chiave, commento della chiave, timestamp e conteggio chiavi rimanenti. Le notifiche di rename includono anche il vecchio e il nuovo nome della chiave.
cipi — Server e self-update
Comandi di top level per lo stato del server e l'auto-gestione di Cipi.
$ cipi status # CPU, RAM, disk, services, PHP versions, apps $ cipi version # show installed Cipi version $ cipi self-update # update Cipi to the latest version $ cipi self-update --check # check for updates without installing
Reset password e credenziali
Cipi fornisce comandi per rigenerare le password a livello server. Le nuove password sono memorizzate in /etc/cipi/server.json (crittografate via Vault) e mostrate a schermo. Salvale subito — vengono mostrate una sola volta.
$ cipi reset root-password # regenerate the root Linux user SSH password $ cipi reset db-password [--engine=…] # regenerate root password (default or chosen engine) $ cipi reset valkey-password # regenerate the Valkey password and restart the service
cipi reset valkey-password (alias cipi reset redis-password) riavvia il servizio Valkey. I client connessi verranno disconnessi temporaneamente. Se le tue app usano Valkey per cache o sessioni, aspettati una breve interruzione.