Avanzato
cipi api
Cipi può abilitare opzionalmente un layer REST API sul server tramite cipi api <domain>. È alimentato dal package Laravel cipi/api (release corrente 1.13.0), che espone:
- REST API — app (inclusa creazione Octane), alias, redirect www, deploy, SSL, database multi-engine, log app, stato server (
/api/*) - Server MCP — 36 tool su
/mcp(Streamable HTTP) - Swagger UI — riferimento interattivo su
/docs
Richiede PHP 8.2+ e Laravel 12+ sull'host del pannello. Si tratta di automazione a livello server — distinta dal package per-app Cipi Agent (cipi/agent su ogni app Laravel).
Il package cipi/api
Su un server Cipi normale non installi mai il package manualmente — cipi api <domain> provisiona Laravel in /opt/cipi/api, Nginx, SSL, job queue SQLite e cipi-queue.service. Per riferimento o setup personalizzati:
$ composer require cipi/api $ php artisan vendor:publish --tag=cipi-config $ php artisan vendor:publish --tag=cipi-assets $ php artisan migrate $ php artisan cipi:seed-api-user $ php artisan cipi:token-create
Il .env del pannello usa CIPI_APPS_JSON=/etc/cipi/apps.json (o proiezione apps-public.json per campi non sensibili). Le ability dei token sono definite in config/cipi.php — elencale con php artisan cipi:token-abilities (stessa lista di cipi api token create da Cipi 4.6.3).
Sorgente e changelog: github.com/cipi-sh/api (MIT). Client wrapper: cipi-cli.
Comandi
$ cipi api <domain> # configure API at root (e.g. api.myhosting.com) $ cipi api ssl # install Let's Encrypt certificate for API domain $ cipi api token list # list tokens $ cipi api token create # create a new token (choose abilities) $ cipi api token revoke <id> # revoke a token $ cipi api status # Laravel + cipi-api versions, queue worker, pending jobs, FPM pool $ cipi api fix-permissions # repair panel storage/database ownership (www-data) $ cipi api update # soft update: composer update on Laravel and API packages $ cipi api upgrade # full rebuild with rollback at /opt/cipi/api.old
Risoluzione problemi Panel API
Dopo cipi self-update, file di proprietà root sotto /opt/cipi/api possono impedire a PHP-FPM (www-data) di scrivere log o il database job SQLite — il browser mostra un HTTP 500 su /docs o /mcp. Cipi normalmente ripara la proprietà automaticamente durante self-update; se i problemi persistono:
$ cipi api fix-permissions # chown storage, database, bootstrap/cache, .env → www-data $ cipi api status # confirm Laravel version, queue worker, pending jobs
cipi api status stampa le versioni installate di Laravel e del package cipi/api, se cipi-queue.service è attivo, job asincroni in sospeso nel database SQLite del pannello e statistiche pool PHP-FPM per il vhost API (inclusi slow request quando configurati).
Da v4.7.18 (migration 4.7.15–4.7.18), i fallimenti Panel API su Ubuntu 25.10+ / 26.04 sono risolti end-to-end: sudo-rs rifiuta wildcard cipi db restore * * (l'intero file sudoers veniva ignorato — I'm afraid I can't do that), quindi la whitelist usa solo * finale; il sourcing di common.sh non interrompe più comandi read-only quando /etc/cipi è rimontato read-only; open_basedir dell'API include /usr/local/bin/ per helper log; e cipi db list mostra database vuoti e segnala errori vault/MariaDB. Esegui cipi self-update per applicare.
Creazione token e permessi granulari
L'autenticazione usa Sanctum. Ogni token può avere una o più ability che limitano le operazioni consentite:
apps-view— leggere appapps-create— creare appapps-edit— modificare app (PHP, repository, branch, dominio primario da API 1.9.0+ / Cipi 4.6.2+)apps-suspend— sospendere e riattivare appapps-basicauth— abilitare, disabilitare e ispezionare HTTP Basic Auth sulle app (API 1.10.0+)apps-delete— eliminare appdeploy-manage— deploy, rollback, unlockssl-manage— installare e gestire certificati SSLaliases-view— leggere aliasaliases-create— aggiungere aliasaliases-delete— rimuovere aliaswww-manage— controparte www/apex e redirect (API 1.12.0+ / Cipi 4.8+)dbs-view— elencare databasedbs-create— creare databasedbs-delete— eliminare databasedbs-manage— backup, restore, rigenerare passwordstatus-view— leggere snapshot stato server (GET /api/status, API 1.11.6+)mcp-access— accedere al server MCP
Da Cipi 4.6.3 / API 1.11.7+, cipi api token create legge la lista canonica delle ability dal package panel API (stesse voci di php artisan cipi:token-abilities sul server). La migration 4.6.3 aggiorna retroattivamente i server esistenti con la lista aggiornata (inclusi status-view, apps-suspend e apps-basicauth).
Endpoint REST
Tutti gli endpoint richiedono l'header Authorization: Bearer <token>. Le operazioni di scrittura (create, edit, delete, deploy, rollback, unlock, SSL, alias, www, database) sono asincrone: restituiscono 202 Accepted con un job_id da interrogare via GET /api/jobs/{id}. Gli endpoint read-only come GET /api/dbs, GET /api/dbs/engines, GET /api/status, GET /api/apps/{name}/www e GET /api/apps/{name}/logs (API 1.11.9+) sono sincroni. POST /api/apps accetta parametri opzionali custom (boolean) e docroot (string) per creare app personalizzate con deploy classico. Il campo repository è obbligatorio per app Laravel e opzionale per app custom: omettilo (o invia vuoto) per provisionare un sito solo SFTP allineato a Cipi v4.5.1+. Quando non c'è repository, branch viene omesso. Da API 1.12.0+ / Cipi 4.8+, la creazione app Laravel accetta anche engine opzionale (mariadb o pgsql) per scegliere il motore database. Da API 1.13.0+ / Cipi 5.0+, la creazione app Laravel accetta octane opzionale (true o "frankenphp") per provisionare Laravel Octane (FrankenPHP); octane viene rifiutato quando custom è impostato. Il tool MCP AppCreate segue le stesse regole. Mantieni il package API aggiornato con cipi api update / cipi api upgrade così validazione e OpenAPI corrispondono a questo comportamento.
POST /api/apps/{name}/suspend mette un'app offline sostituendo il vhost Nginx con una pagina di manutenzione generica HTTP 503 (HTTPS incluso) senza eliminarla, mentre POST /api/apps/{name}/unsuspend ripristina il vhost normale. Entrambi richiedono l'ability apps-suspend e restituiscono 409 se l'app è già nello stato target. Il flag suspended sopravvive alla rigenerazione vhost ed è esposto su GET /api/apps e GET /api/apps/{name}. Questi endpoint richiedono il package API 1.8.1+ e Cipi 4.5.8+ sul server.
PUT /api/apps/{name} accetta un campo domain opzionale per rinominare il dominio primario dell'app. L'API valida il formato in modo sincrono e restituisce 409 se il dominio è già usato da un'altra app (gli alias dell'app corrente sono consentiti, quindi promuovere un alias a primario funziona). Richiede il package API 1.9.0+ e Cipi 4.6.2+. Il tool MCP AppEdit accetta lo stesso parametro domain.
GET /api/apps e GET /api/apps/{name} espongono i flag booleani suspended e basic_auth per app (da apps.json). Da API 1.12.0+ espongono anche engine, www_redirect e force_https da apps-public.json / metadata app. Da API 1.13.0+ espongono octane e octane_port per app Octane.
Gli endpoint HTTP Basic Auth sotto /api/apps/{name}/basicauth/* avvolgono cipi basicauth in modo sincrono — non restituiscono un job_id. Enable accetta user e password opzionali (generati automaticamente se omessi; restituiti una volta nella risposta). Richiede l'ability apps-basicauth e il package API 1.10.0+. Questo è distinto dalla gestione auth.json di Composer — vedi cipi basicauth.
Gli endpoint WWW / apex sotto /api/apps/{name}/www/* avvolgono cipi www (API 1.12.0+ / Cipi 4.8+). GET …/www è sincrono e restituisce primary, apex, www e redirect. POST …/www/add, …/force-to-root, …/force-from-root e …/clear sono job asincroni. Richiede l'ability www-manage. Tool MCP: WwwStatus, WwwAdd, WwwForceToRoot, WwwForceFromRoot, WwwClear.
POST /api/apps/{name}/ssl/force riapplica il redirect HTTP → HTTPS senza emettere un nuovo certificato (cipi ssl force). Richiede ssl-manage e API 1.12.0+. Tool MCP: SslForce.
GET /api/dbs elenca i database in modo sincrono eseguendo sudo cipi db list sull'host (come la CLI server). Query opzionale engine=mariadb|pgsql filtra per motore (API 1.12.0+ / Cipi 4.8+). GET /api/dbs/engines elenca i motori installati e il default server (sync; MCP DbEngines). Le altre operazioni di scrittura /api/dbs/* sono job asincroni e accettano engine opzionale su create, delete, backup, restore e password. I comandi database richiedono Cipi 4.4.17+ sul server (voci cipi db … nella whitelist sudoers API); il supporto multi-engine richiede Cipi 4.8+.
GET /api/status restituisce lo stesso JSON strutturato di cipi status (sistema, risorse, servizi, pool PHP, conteggio app). Da API 1.11.8+ l'endpoint preferisce sudo cipi status sull'host e ricade su letture dirette host quando sudo non è disponibile. Da API 1.12.1+ il fallback host-read include postgresql quando l'unità systemd è installata (allineato a Cipi 4.8+). Richiede l'ability status-view (API 1.11.6+). Il tool MCP ServerStatus restituisce lo stesso payload e richiede solo mcp-access. Dal tuo laptop, usa cipi-cli status per una panoramica globale su tutti i profili server configurati, o il dettaglio per un profilo.
GET /api/apps/{name}/logs restituisce snapshot log sincroni e paginati per nginx, PHP-FPM, Laravel (se presente), worker e deploy — la controparte REST di cipi app logs e cipi-cli apps logs. Parametri query: type (default all), page (default 1, più recenti prima), per_page (default 50, max 1000). Richiede l'ability apps-view e il package API 1.11.9+. Il testo dei log è redatto per secret comuni (stessa policy di MCP AppLogs da API 1.11.5+).
| Metodo | Endpoint | Ability richiesta |
|---|---|---|
| GET | /api/apps |
apps-view |
| GET | /api/apps/{name} |
apps-view |
| GET | /api/apps/{name}/logs |
apps-view |
| POST | /api/apps |
apps-create |
| PUT | /api/apps/{name} |
apps-edit |
| POST | /api/apps/{name}/suspend |
apps-suspend |
| POST | /api/apps/{name}/unsuspend |
apps-suspend |
| DELETE | /api/apps/{name} |
apps-delete |
| GET | /api/apps/{name}/aliases |
aliases-view |
| POST | /api/apps/{name}/aliases |
aliases-create |
| DELETE | /api/apps/{name}/aliases |
aliases-delete |
| POST | /api/apps/{name}/deploy |
deploy-manage |
| POST | /api/apps/{name}/deploy/rollback |
deploy-manage |
| POST | /api/apps/{name}/deploy/unlock |
deploy-manage |
| POST | /api/apps/{name}/ssl |
ssl-manage |
| POST | /api/apps/{name}/ssl/force |
ssl-manage |
| GET | /api/apps/{name}/www |
www-manage |
| POST | /api/apps/{name}/www/add |
www-manage |
| POST | /api/apps/{name}/www/force-to-root |
www-manage |
| POST | /api/apps/{name}/www/force-from-root |
www-manage |
| POST | /api/apps/{name}/www/clear |
www-manage |
| GET | /api/apps/{name}/basicauth |
apps-basicauth |
| POST | /api/apps/{name}/basicauth/enable |
apps-basicauth |
| POST | /api/apps/{name}/basicauth/disable |
apps-basicauth |
| GET | /api/dbs/engines |
dbs-view |
| GET | /api/dbs |
dbs-view |
| POST | /api/dbs |
dbs-create |
| DELETE | /api/dbs/{name} |
dbs-delete |
| POST | /api/dbs/{name}/backup |
dbs-manage |
| POST | /api/dbs/{name}/restore |
dbs-manage |
| POST | /api/dbs/{name}/password |
dbs-manage |
| GET | /api/status |
status-view |
| GET | /api/jobs/{id} |
qualsiasi token autenticato |
Esempi REST (curl)
Imposta l'URL base API e il token (da cipi api token create):
export CIPI_API_URL="https://api.myserver.com" export CIPI_API_TOKEN="your-sanctum-token"
Elenca app (sync, 200):
curl -sS "${CIPI_API_URL}/api/apps" \ -H "Authorization: Bearer ${CIPI_API_TOKEN}" \ -H "Accept: application/json"
Stato server (sync, richiede status-view):
curl -sS "${CIPI_API_URL}/api/status" \ -H "Authorization: Bearer ${CIPI_API_TOKEN}"
Log app (sync, richiede apps-view, API 1.11.9+):
curl -sS "${CIPI_API_URL}/api/apps/myapp/logs?type=deploy&page=1&per_page=50" \ -H "Authorization: Bearer ${CIPI_API_TOKEN}" \ -H "Accept: application/json"
Crea un'app Laravel Octane (async, API 1.13.0+ / Cipi 5.0+; richiede apps-create):
curl -sS -X POST "${CIPI_API_URL}/api/apps" \ -H "Authorization: Bearer ${CIPI_API_TOKEN}" \ -H "Accept: application/json" \ -H "Content-Type: application/json" \ -d '{ "domain": "shop.example.com", "repository": "git@github.com:you/shop.git", "branch": "main", "octane": true, "engine": "mariadb" }'
Invia "octane": "frankenphp" per lo stesso effetto. Ometti octane per PHP-FPM classico. Usa "engine": "pgsql" quando PostgreSQL è installato (API 1.12.0+ / Cipi 4.8+).
Deploy di un'app (async, 202 + job_id):
curl -sS -X POST "${CIPI_API_URL}/api/apps/myapp/deploy" \ -H "Authorization: Bearer ${CIPI_API_TOKEN}" \ -H "Accept: application/json" # poll until completed curl -sS "${CIPI_API_URL}/api/jobs/JOB_ID" \ -H "Authorization: Bearer ${CIPI_API_TOKEN}"
Backup database (async, dbs-manage) — restituisce un percorso backup reale nel result del job, non un dump anonymizzato (vedi Agent anonymizer):
curl -sS -X POST "${CIPI_API_URL}/api/dbs/myapp_db/backup" \ -H "Authorization: Bearer ${CIPI_API_TOKEN}"
Integrazione host (sudoers)
La panel API gira come www-data ed esegue comandi CLI Cipi via sudo usando /etc/sudoers.d/cipi-api — una whitelist esplicita di sottocomandi cipi. Vault e credenziali MariaDB restano dentro Cipi, non in PHP.
GET /api/dbs— eseguesudo cipi db list(sync). Richiede Cipi 4.4.17+ (migration aggiungecipi db …a sudoers). Senza:sudo: a terminal is required. List/engines multi-engine richiedono Cipi 4.8+ / API 1.12.0+.GET /api/status/ MCPServerStatus— preferiscesudo cipi status(API 1.11.8+); fallback host-read quando sudo fallisce (includepostgresqlda API 1.12.1+).- MCP
ServiceList—sudo cipi service list - MCP
AppArtisan—sudo cipi app artisan <app> … - Job asincroni —
cipi app(inclusi--octane/--engine),deploy,alias,www,ssl/ssl force,db create|delete|backup|restore|password|engines, ecc.
Dopo cipi self-update, esegui cipi api fix-permissions se /docs o /mcp restituiscono HTTP 500 (vedi risoluzione problemi sopra).
Swagger / OpenAPI
La documentazione interattiva è disponibile su /docs (Swagger UI). La spec OpenAPI è generata da public/api-docs/openapi.json e copre app (inclusi suspend, unsuspend, rename dominio, basic auth, log paginati, redirect www, creazione Octane e engine multi-engine), alias, deploy, SSL (install + force HTTPS), database (lista engine + engine opzionale sulle mutation), stato server, polling job con tipi result strutturati e schemi tool MCP. Versione package API corrente: 1.13.0.
Server MCP
Un server MCP (Model Context Protocol) è esposto su /mcp via Streamable HTTP. Da package API 1.11.1+, un token con l'ability mcp-access è sufficiente per tutti i tool MCP — le ability REST per-endpoint (apps-view, deploy-manage, apps-basicauth, www-manage, ecc.) non vengono verificate su /mcp. Il server espone 36 tool per app, alias, www, database, deploy, SSL, HTTP Basic Auth, polling job, log, Artisan e monitoraggio server. Le operazioni di scrittura che dispatchano job async restituiscono un job_id — interroga con JobShow (API 1.11.0+). Azioni basic auth e tool read-only girano in modo sincrono.
- Applicazioni:
AppList,AppShow,AppCreate(engine,octaneopzionali),AppEdit,AppSuspend,AppUnsuspend,AppDelete,AppDeploy,AppDeployRollback,AppDeployUnlock,AppArtisan(solo app Laravel; rifiuta app custom etinker) - HTTP Basic Auth:
AppBasicAuthStatus,AppBasicAuthEnable,AppBasicAuthDisable - Alias:
AliasList,AliasAdd,AliasRemove - WWW / apex:
WwwStatus,WwwAdd,WwwForceToRoot,WwwForceFromRoot,WwwClear(API 1.12.0+) - Database:
DbEngines,DbList,DbCreate,DbDelete,DbBackup,DbRestore,DbPassword(engineopzionale su list/mutation; API 1.12.0+) - SSL:
SslInstall,SslForce(API 1.12.0+) - Job e log:
JobShow(interroga stato job async,resultparsato e output CLI),AppLogs(log app recenti per tipo:all,nginx,php,worker,deploy,laravel— comecipi app logs; equivalente REST:GET /api/apps/{name}/logsda API 1.11.9+),ApiLogShow(log Laravel recenti per l'host panel API) - Monitoraggio server:
ServerStatus(JSON strutturato allineato aGET /api/status/cipi status),ServiceList(stato servizi di sistema viacipi service list)
AppLogs, ApiLogShow) prefissano ogni risposta con un avviso contenuto produzione e redigono secret comuni prima della consegna. Output CLI sensibile da JobShow e AppArtisan è redatto; gli oggetti result strutturati del job (es. credenziali app da job create) restano intatti così gli operatori possono leggerli una volta.Da Cipi 4.6.3, il package panel API viene soft-aggiornato ogni notte alle 04:30 via /etc/cron.d/cipi-api (cipi api update), così endpoint MCP e REST restano aggiornati senza intervento manuale.
Installazione del server MCP
L'endpoint MCP è opzionale e si carica solo quando il package MCP richiesto è installato. Per usarlo da VS Code, Cursor o Claude Desktop:
- Configura l'API con
cipi api <domain>ecipi api ssl - Crea un token con
cipi api token createe seleziona almenomcp-access - Aggiungi il server MCP alla config del client (vedi sotto)
Cursor
Aggiungi a ~/.cursor/mcp.json (o Cursor → Impostazioni → MCP):
{
"mcpServers": {
"cipi-api": {
"type": "http",
"url": "https://<your-api-domain>/mcp",
"headers": {
"Authorization": "Bearer <your-token>"
}
}
}
}
Cursor si connette nativamente via HTTP — nessun bridge necessario.
VS Code
VS Code (con GitHub Copilot) supporta MCP nativamente da 1.102. Aggiungi a .vscode/mcp.json o esegui MCP: Open User Configuration per un setup globale. Usa inputs per richiedere il token una volta e salvarlo in modo sicuro:
{
"inputs": [
{
"type": "promptString",
"id": "cipi-token",
"description": "Cipi API Token",
"password": true
}
],
"servers": {
"cipi-api": {
"type": "http",
"url": "https://<your-api-domain>/mcp",
"headers": {
"Authorization": "Bearer ${input:cipi-token}"
}
}
}
}
Riavvia VS Code dopo il salvataggio. Usa MCP: Add Server dalla Command Palette per un setup guidato.
Claude Code
Aggiungi il server MCP direttamente dalla CLI:
$ claude mcp add --transport http cipi-api https://<your-api-domain>/mcp \
--header "Authorization: Bearer <your-token>"
Claude Desktop
Claude Desktop richiede il bridge mcp-remote per convertire stdio in HTTP. Aggiungi a ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) o al percorso config equivalente sul tuo OS:
{
"mcpServers": {
"cipi-api": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://<your-api-domain>/mcp",
"--header",
"Authorization: Bearer <your-token>"
]
}
}
}
Installa mcp-remote una volta con npm install -g mcp-remote.
Sostituisci <your-api-domain> con il tuo dominio API (es. api.myhosting.com) e <your-token> con il token creato al passo 2.
Modulo WHMCS
Un modulo di provisioning WHMCS ufficiale è disponibile su github.com/cipi-sh/whmcs. Collega il ciclo di vita provisioning WHMCS alla REST API Cipi — automatizzando creazione app, eliminazione, certificati SSL, deploy e modifiche di configurazione per i tuoi clienti hosting. Nessuna dipendenza Composer; il modulo è un drop-in autocontenuto.
Requisiti
- WHMCS 8.x (tipo modulo provisioning “Server”)
- Server Cipi con API abilitata:
cipi api <domain>ecipi api ssl - Token Sanctum Bearer con le ability richieste:
| Ability | Richiesta per |
|---|---|
apps-view |
Test Connection, App Info |
apps-create |
Create Account |
apps-edit |
Change Package |
apps-suspend |
Suspend / Unsuspend |
apps-delete |
Terminate Account |
deploy-manage |
Deploy, Rollback, Unlock |
ssl-manage |
Install SSL, Auto-SSL |
Installazione
- Copia
modules/servers/cipi/nella root WHMCS:your-whmcs/ └── modules/ └── servers/ └── cipi/ ├── cipi.php └── lib/ └── CipiApiClient.php - In WHMCS Admin → System Settings → Servers → Add New Server:
- Type: Cipi (Laravel hosting)
- Hostname: URL base API (es.
https://api.example.com, senza slash finale) - Password: token Bearer da
cipi api token create - Secure: Sì (consigliato — abilita verifica TLS)
- Crea un prodotto hosting collegato a questo server e configura Module Settings:
| Impostazione | Descrizione | Default |
|---|---|---|
| Versione PHP | 8.2 / 8.3 / 8.4 / 8.5 | 8.5 |
| Tipo app | laravel o custom |
laravel |
| Repository Git (SSH) | Obbligatorio per Laravel; opzionale per custom | — |
| Branch Git | Branch da deployare | main |
| SSL automatico | Installa Let’s Encrypt dopo la creazione | No |
Tipi di app
| Tipo app | Equivalente Cipi | Stack | Git / Deploy |
|---|---|---|---|
| laravel (default) | cipi app create |
Utente Linux isolato, pool PHP-FPM, vhost Nginx, MariaDB, worker Supervisor, release Deployer | URL repository SSH obbligatorio; branch dalle impostazioni |
| custom | cipi app create --custom |
Directory htdocs/, Nginx + PHP — ideale per siti statici, SPA, WordPress o app PHP generiche | Opzionale: lascia Repository Git vuoto per hosting solo SFTP, o imposta un repo per deploy Git |
Ciclo di vita provisioning
| Azione WHMCS | Chiamata API | Comportamento |
|---|---|---|
| Test Connection | GET /api/apps |
Valida token e raggiungibilità API |
| Create Account | POST /api/apps |
Provisiona un'app Cipi (Laravel o custom); attende job async; opzionalmente installa SSL |
| Suspend | POST /api/apps/{name}/suspend |
Mette l'app offline (pagina manutenzione HTTP 503) senza eliminarla; attende job async |
| Unsuspend | POST /api/apps/{name}/unsuspend |
Ripristina il vhost Nginx normale dell'app; attende job async |
| Terminate Account | DELETE /api/apps/{name} |
Rimuove l'app; attende job async |
| Change Package | PUT /api/apps/{name} |
Aggiorna versione PHP, repository Git o branch |
Suspend / Unsuspend richiedono Cipi 4.5.8+ (endpoint suspend/unsuspend), il package API 1.8.1+ e un token con l'ability apps-suspend. Sospendere sostituisce il vhost dell'app con una pagina manutenzione HTTP 503 generica; riattivare lo ripristina.
Pulsanti admin
Dalla vista servizio admin WHMCS, gli operatori possono attivare azioni one-click:
| Pulsante | Chiamata API | Descrizione |
|---|---|---|
| Install SSL | POST /api/apps/{name}/ssl |
Installa un certificato Let’s Encrypt |
| Deploy | POST /api/apps/{name}/deploy |
Attiva un deploy zero-downtime |
| Rollback Deploy | POST /api/apps/{name}/deploy/rollback |
Torna alla release precedente |
| Unlock Deploy | POST /api/apps/{name}/deploy/unlock |
Sblocca un deploy bloccato |
| App Info | GET /api/apps/{name} |
Recupera dettagli app correnti nel Module Log |
Auto-SSL alla creazione
Abilita Auto SSL nelle impostazioni modulo prodotto per installare automaticamente un certificato Let’s Encrypt subito dopo il provisioning. Se l'installazione SSL fallisce, l'app viene comunque creata con successo e un warning viene loggato.
Client API completo
Il CipiApiClient incluso copre l'intera superficie REST API Cipi. Anche se una funzionalità non è collegata a un hook WHMCS, puoi usare il client in hook o addon personalizzati:
| Area | Metodi |
|---|---|
| App | listApps, getApp, createApp, editApp, suspendApp, unsuspendApp, deleteApp |
| Deploy | deployApp, rollbackDeploy, unlockDeploy |
| SSL | installSsl |
| Alias | listAliases, addAlias, removeAlias |
| Database | listDatabases, createDatabase, deleteDatabase, backupDatabase, restoreDatabase, resetDatabasePassword |
| Job | getJob, waitForJob |
Estendere il modulo
// Example: add an alias from a WHMCS hook require_once ROOTDIR . '/modules/servers/cipi/lib/CipiApiClient.php'; $client = new CipiApiClient('https://api.example.com', $token); $client->addAlias('myapp', 'alias.example.com'); // Example: create an extra database $client->createDatabase('myapp_extra'); // Example: backup a database $client->backupDatabase('myapp');
Comportamento lato cliente
Il modulo non aggiunge una tab Client Area, pulsanti custom o stato live da Cipi. I clienti vedono la vista servizio WHMCS standard (dominio, stato, date rinnovo). Quando Cipi provisiona un'app genera secret monouso (password SSH, password DB, deploy key, URL webhook). La REST API non spinge automaticamente quei secret in WHMCS — dovresti estendere il modulo, scrivere un hook o consegnare le credenziali tramite il tuo workflow di supporto.
Log del modulo
Tutte le chiamate API sono loggate via logModuleCall() — Create, Terminate, Change Package, SSL, Deploy, Rollback, Unlock e App Info. Abilita Utilities → Logs → Module Log in WHMCS Admin per visibilità completa.
cipi sync
Trasferisci, replica e fai backup di intere applicazioni Laravel tra server Cipi — inclusi configurazione, dump database, file storage, chiavi SSH, worker e crontab. Ogni archivio è criptato con AES-256-CBC e protetto da una passphrase definita dall'utente, così credenziali e dati sensibili sono al sicuro a riposo e durante il trasferimento.
Panoramica comandi
$ cipi sync export [app ...] [--with-db] [--with-storage] [--output=<path>] [--passphrase=<secret>] $ cipi sync import <archive.tar.gz.enc> [app ...] [--update] [--deploy] [--yes] [--passphrase=<secret>] $ cipi sync push [app ...] [--host=IP] [--port=22] [--with-db] [--with-storage] [--import] [--passphrase=<secret>] $ cipi sync list <archive.tar.gz.enc> [--passphrase=<secret>] $ cipi sync pubkey # display the server's sync public key for inter-server trust $ cipi sync trust # add a remote server's public key to cipi's authorized_keys
Crittografia archivio
Tutti gli archivi sync sono criptati di default con AES-256-CBC. Durante l'export ti viene chiesta una passphrase (minimo 8 caratteri) che protegge l'archivio. La stessa passphrase è richiesta per importarlo o ispezionarlo. Questo protegge chiavi SSH, file .env, dump database e credenziali a riposo e durante il trasferimento.
# Interactive mode (default) — prompted for passphrase $ cipi sync export --with-db # Enter passphrase to encrypt the archive: ******** # Confirm passphrase: ******** # Non-interactive mode — for cron jobs and scripts $ cipi sync export --with-db --passphrase="MyStr0ngP@ss"
echo "MyStr0ngP@ss" > /etc/cipi/.sync_passphrase && chmod 400 /etc/cipi/.sync_passphrase. Poi usa --passphrase="$(cat /etc/cipi/.sync_passphrase)" nei job cron.
Export
Impacchetta le config app in un archivio .tar.gz.enc criptato. Opzionalmente include dump database e file storage.
# Export all apps (config only) $ cipi sync export # Export three specific apps with database + storage $ cipi sync export shop blog api --with-db --with-storage # Export to a custom path (non-interactive) $ cipi sync export --with-db --output=/root/backups/cipi-march.tar.gz --passphrase="MyStr0ngP@ss"
Cosa va nell'archivio
| File | Descrizione | Incluso |
|---|---|---|
env |
Il .env dell'app da /home/<app>/shared/.env |
Sempre |
auth.json |
Credenziali auth Composer (se esistono) | Sempre |
deploy.php |
Config Deployer | Sempre |
ssh/* |
Deploy key, known_hosts, authorized_keys, config SSH | Sempre |
supervisor.conf |
Config queue worker | Sempre |
crontab |
Crontab dell'app (scheduler + trigger deploy) | Sempre |
db.sql.gz |
Dump MariaDB gzippato (schema + dati + routine) | --with-db |
storage.tar.gz |
Archivio di /home/<app>/shared/storage/ |
--with-storage |
Più config globali: apps.json (filtrato alle app selezionate), databases.json, backup.json, api.json.
Import
Ripristina app da un archivio sul server corrente.
# Import all apps from archive $ cipi sync import /tmp/cipi-sync-aws01-20260306.tar.gz.enc # Import only two apps from an archive that contains ten $ cipi sync import /tmp/cipi-sync-aws01-20260306.tar.gz.enc shop blog --passphrase="MyStr0ngP@ss" # Import and deploy code from Git immediately $ cipi sync import /tmp/cipi-sync-aws01-20260306.tar.gz.enc --deploy # Non-interactive (skip all prompts) $ cipi sync import /tmp/cipi-sync-aws01-20260306.tar.gz.enc --yes --passphrase="MyStr0ngP@ss"
Cosa fa l'import per una NUOVA app
Quando un'app non esiste sul server target, l'import la crea da zero — equivalente a cipi app create con tutte le config precompilate dall'archivio:
- Utente Linux — Crea un nuovo utente con password casuale
- Directory — Crea
/home/<app>/shared/,logs/,.ssh/,.deployer/ - Deploy key SSH — Ripristina dall'archivio (la stessa chiave funziona con GitHub/GitLab senza riconfigurazione)
- Database MariaDB — Crea database + utente con una nuova password casuale
- Dati database — Importa il dump se
--with-dbera usato durante l'export .env— Copia dall'archivio, poi sovrascriveDB_PASSWORD,DB_USERNAME,DB_DATABASE,DB_HOSTcon i valori del nuovo server. Tutto il resto (APP_KEY,MAIL_*,REDIS_*, variabili custom) resta com'è- Pool PHP-FPM, vhost Nginx, worker Supervisor, Crontab, Deployer — Completamente configurati dai dati archivio
Controlli di sicurezza prima dell'import
L'import esegue controlli preliminari prima di toccare qualsiasi cosa:
- App già esistente — bloccato a meno che non venga passato
--update - Conflitto di dominio — bloccato se un'altra app usa già lo stesso dominio
- Versione PHP mancante — avviso (l'app viene saltata; installa prima la versione con
cipi php install)
Modalità update (--update)
La funzionalità chiave per la sincronizzazione ripetuta (es. replica failover). Senza --update, l'import rifiuta di toccare app già esistenti. Con --update, aggiorna le app esistenti e crea quelle nuove.
$ cipi sync import /tmp/archive.tar.gz.enc --update --passphrase="MyStr0ngP@ss"
Cosa fa l'update su un'app esistente
- Sincronizzazione
.env— Il.envdell'archivio sostituisce quello locale, maDB_PASSWORD,DB_USERNAME,DB_DATABASEeDB_HOSTvengono preservati dal server locale. Tutto il resto (APP_KEY,MAIL_*,REDIS_*, variabili personalizzate) proviene dalla sorgente. - Dati database — Se l'archivio ha un dump, elimina tutte le tabelle (con
SET FOREIGN_KEY_CHECKS=0) e reimporta. Usa le credenziali root locali. - Storage — Se l'archivio ha storage, estrae sopra la directory esistente (nuovi file aggiunti, esistenti sovrascritti).
- Migrazione versione PHP — Se la sorgente usa una versione PHP diversa, l'update migra automaticamente pool FPM, Supervisor, crontab, Deployer e
.env. - Vhost Nginx, queue worker Supervisor, config Deployer — Rigenerati dai dati dell'archivio.
- Deploy — Se viene passato
--deploy, eseguedep deployper scaricare l'ultimo codice.
Cosa l'update NON modifica
- Password utente Linux
- Chiavi deploy SSH (mantenute dal primo import)
- Credenziali utente MariaDB (il target mantiene le proprie)
- Certificati SSL (esegui
cipi ssl installseparatamente)
List (ispeziona archivio)
Visualizza il contenuto di un archivio senza importare nulla.
$ cipi sync list /tmp/cipi-sync-aws01-20260306.tar.gz.enc --passphrase="MyStr0ngP@ss" Cipi Sync Archive ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Cipi v5.0.2 Exported 2026-03-06T15:00:00Z Source aws01 (3.120.xx.xx) Database true Storage true Apps APP DOMAIN PHP DB STORAGE shop shop.example.com 8.4 yes yes blog blog.example.com 8.4 yes yes api api.example.com 8.5 yes yes ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Push (export + trasferimento + import)
Combina export, trasferimento rsync e import remoto in un solo comando. Gira interamente dal server sorgente.
# Interactive push — prompted for target IP and passphrase $ cipi sync push --with-db --with-storage --import # Non-interactive push (for cron and scripts) $ cipi sync push --host=51.195.xx.xx --port=22 --with-db --with-storage --import --passphrase="MyStr0ngP@ss" # Push specific apps only $ cipi sync push shop blog --host=51.195.xx.xx --with-db --import --passphrase="MyStr0ngP@ss" # Push without auto-import (transfer only — import manually on remote) $ cipi sync push --host=51.195.xx.xx --with-db --passphrase="MyStr0ngP@ss"
Come funziona push
- Passo 1: Esegue
cipi sync exportin locale (crittografa con passphrase) - Passo 2: Trasferisce l'archivio crittografato al target via rsync
- Passo 3: Se viene passato
--import, eseguecipi sync import --update --yessul target via SSH
Push aggiunge sempre --update e --yes quando chiama import sul remoto. Significa: la prima esecuzione crea tutte le app, le successive le aggiornano incrementalmente. È questo che rende push sicuro da eseguire ripetutamente via cron.
Setup SSH per push
Il server sorgente ha bisogno di accesso SSH al target come utente cipi. Usa il meccanismo trust integrato per autenticazione a chiave senza password tra server Cipi:
# On the SOURCE server — display its sync public key $ cipi sync pubkey # On the TARGET server — add the source's public key to cipi's authorized_keys $ cipi sync trust
Una volta trust stabilito, cipi sync push si connette automaticamente come utente cipi — nessun accesso root richiesto.
Scenari pratici
Scenario 1: migra tutte le app da AWS a OVH
Hai 20 app su AWS. Hai comprato un VPS OVH e ci hai installato Cipi.
# On AWS (source server) $ cipi sync push --host=51.195.xx.xx --with-db --with-storage --import
Sul target OVH: 20 utenti Linux, 20 database, 20 vhost Nginx, pool PHP-FPM, config Supervisor, crontab — tutto creato automaticamente. Dati DB importati, storage estratto, file .env copiati con le password DB di OVH, chiavi deploy SSH preservate (le stesse chiavi funzionano con GitHub). Dopo l'import, installa SSL e aggiorna il DNS:
# On OVH (target server) $ cipi ssl install shop $ cipi ssl install blog # ... then update DNS A records to OVH IP
Scenario 2: replica failover programmata (cron)
Ogni 6 ore, il Server 1 sincronizza tutte le app sul Server 2. Se il Server 1 cade, cambia DNS e vai live sul Server 2.
# One-time setup on Server 1 — trust Server 2 using cipi sync trust $ cipi sync pubkey # copy this key, then run "cipi sync trust" on Server 2 $ echo "YourStr0ngPassphrase!" > /etc/cipi/.sync_passphrase $ chmod 400 /etc/cipi/.sync_passphrase # First push (manual, to verify) $ cipi sync push --host=server2-ip --with-db --with-storage --import --passphrase="$(cat /etc/cipi/.sync_passphrase)" # Add to crontab for automatic replication $ crontab -e
0 */6 * * * /usr/local/bin/cipi sync push --host=51.195.xx.xx --port=22 --with-db --with-storage --import --passphrase="$(cat /etc/cipi/.sync_passphrase)" >> /var/log/cipi/sync-replica.log 2>&1
La finestra di perdita dati equivale all'intervallo cron (6 ore in questo esempio). Quando il Server 1 cade: cambia DNS verso il Server 2, esegui cipi ssl install per ogni app e sei live.
Scenario 3: replica su più server
# Stagger by 30 minutes so exports don't run simultaneously
0 */6 * * * /usr/local/bin/cipi sync push --host=51.195.xx.xx --with-db --with-storage --import --passphrase="$(cat /etc/cipi/.sync_passphrase)" >> /var/log/cipi/sync-ovh.log 2>&1
30 */6 * * * /usr/local/bin/cipi sync push --host=164.90.xx.xx --with-db --with-storage --import --passphrase="$(cat /etc/cipi/.sync_passphrase)" >> /var/log/cipi/sync-do.log 2>&1
Scenario 4: backup crittografato giornaliero (senza trasferimento)
0 3 * * * /usr/local/bin/cipi sync export --with-db --with-storage --output=/root/backups/cipi-$(date +\%Y\%m\%d).tar.gz --passphrase="$(cat /etc/cipi/.sync_passphrase)" >> /var/log/cipi/export.log 2>&1
Crea ogni notte un archivio portatile crittografato. Ripristina su qualsiasi server Cipi in qualsiasi momento con cipi sync import.
Limitazioni
- I certificati SSL non sono inclusi nell'archivio. Esegui
cipi ssl installdopo l'import su un nuovo server. - La sync DB è sostituzione completa, non incrementale. Ogni update elimina tutte le tabelle e reimporta.
- La sync storage è estrazione completa, non rsync incrementale. I file eliminati sulla sorgente restano sul target.
- Le deploy key sono le stesse su sorgente e target — nessuna riconfigurazione GitHub/GitLab necessaria.
Vault e crittografia
Cipi crittografa tutti i file di configurazione a riposo con AES-256-CBC. Il sistema Vault fornisce crittografia e decrittografia trasparenti così che i dati sensibili — password database, token API, chiavi SSH, contenuti .env — non vengono mai salvati in chiaro su disco.
Architettura
Il sistema si basa su due livelli:
- Vault — crittografia trasparente dei file di configurazione JSON su disco (
server.json,apps.json,databases.json,backup.json,smtp.json,api.json) - Crittografia sync — crittografia basata su passphrase degli archivi export per trasferimento sicuro tra server
Come funziona Vault
Una chiave master viene generata durante l'installazione con openssl rand -base64 32 e salvata in /etc/cipi/.vault_key (chmod 400, solo root). Ogni file di config JSON viene crittografato su disco con openssl enc -aes-256-cbc -salt -pbkdf2. I file mantengono l'estensione .json — il contenuto è semplicemente un blob crittografato invece di JSON leggibile.
La funzione vault_read rileva automaticamente se un file è in chiaro o crittografato (compatibilità retroattiva), così i server esistenti migrano senza interruzioni durante l'update.
Funzioni Vault
# Core functions in lib/vault.sh vault_init # Generate .vault_key if not present vault_read <file> # Decrypt and output JSON to stdout (auto-detect plain/encrypted) vault_write <file> # Read JSON from stdin, encrypt and write to disk vault_seal <file> # Encrypt an existing plaintext file in-place vault_get <file> <jq_query> # Shortcut: vault_read | jq
Proiezione pubblica
Cipi genera un file apps-public.json contenente solo campi non sensibili (dominio, alias, versione PHP, branch, repository, utente, timestamp di creazione, più i flag suspended e basic_auth). Il gruppo cipi-api legge questa proiezione in chiaro invece del file crittografato, mantenendo la chiave vault riservata a root.
Crittografia archivio sync
Quando esegui cipi sync export, le config vengono decrittografate dal vault in un'area di staging, poi l'intero archivio viene crittografato con la tua passphrase. All'import, l'archivio viene decrittografato con la passphrase e le config vengono ricrittografate con la chiave vault del server di destinazione.
chmod 400 e inclusa nei backup del server. Valuta di esportarla manualmente per maggiore sicurezza.
Notifiche email
Cipi può inviare alert email in caso di errori backup, fallimenti deploy, fallimenti job cron di sistema o eventi di autenticazione rilevanti per la sicurezza. La configurazione SMTP è salvata crittografata in /etc/cipi/smtp.json e inclusa negli export sync.
Comandi
$ cipi smtp configure # interactive setup (Gmail, SendGrid, Mailgun, custom) $ cipi smtp status # display current notification settings $ cipi smtp test # send a verification email $ cipi smtp enable # enable notifications $ cipi smtp disable # disable without losing settings $ cipi smtp delete # remove SMTP configuration entirely
Trigger di notifica granulari
Dalla v4.6.3, puoi controllare quali eventi inviano email quando SMTP è configurato. Tutti i trigger sono attivi di default; gli eventi vengono sempre loggati in /var/log/cipi/events.log comunque.
$ cipi notifications list # all triggers grouped by category $ cipi notifications enable <trigger> # turn one trigger on $ cipi notifications disable <trigger> # turn one trigger off $ cipi notifications enable-all # re-enable everything $ cipi notifications disable-all # mute all email alerts $ cipi notifications reset # restore defaults (all on)
Config: /etc/cipi/notifications.json. Esegui cipi notifications list sul server per lo stato on/off live. ID trigger per cipi notifications enable|disable <trigger>:
| ID trigger | Categoria | Evento |
|---|---|---|
app_create | App | App creata |
app_edit | App | App modificata |
app_delete | App | App eliminata |
app_suspend | App | App sospesa |
app_unsuspend | App | App riattivata |
app_ssh_password_reset | App | Reset password SSH app |
app_db_password_reset | App | Reset password DB app |
alias_add | Domini | Alias aggiunto |
alias_remove | Domini | Alias rimosso |
auth_create | Auth | auth.json Composer creato |
auth_edit | Auth | auth.json Composer modificato |
auth_delete | Auth | auth.json Composer eliminato |
basicauth_enable | Basic auth | HTTP basic auth attivato |
basicauth_disable | Basic auth | HTTP basic auth disattivato |
deploy_success | Deploy | Deploy riuscito |
deploy_fail | Deploy | Deploy fallito |
deploy_rollback | Deploy | Rollback deploy |
ssl_install | SSL | Certificato SSL installato |
ssl_renew | SSL | Certificati SSL rinnovati |
php_install | PHP | Versione PHP installata |
php_switch | PHP | PHP di sistema cambiato |
php_remove | PHP | Versione PHP rimossa |
php_upgrade | PHP | Patch di sicurezza PHP applicate |
db_create | Database | Database creato |
db_delete | Database | Database eliminato |
worker_add | Worker | Worker aggiunto |
worker_remove | Worker | Worker rimosso |
ssh_key_add | Chiavi SSH | Chiave SSH aggiunta |
ssh_key_rename | Chiavi SSH | Chiave SSH rinominata |
ssh_key_remove | Chiavi SSH | Chiave SSH rimossa |
ssh_login | Sicurezza | Login SSH (utenti cipi/root/sudo) |
sudo | Sicurezza | Elevazione sudo |
su | Sicurezza | su a root da cipi |
backup_fail | Backup | Backup fallito |
cron_fail | Cron | Job cron fallito |
reset_root_password | Reset | Reset password SSH root |
reset_db_password | Reset | Reset password root MariaDB |
reset_valkey_password | Reset | Reset password Valkey |
api_configure | API | Panel API configurata |
api_update | API | Panel API aggiornata |
api_upgrade | API | Panel API aggiornata (upgrade) |
api_ssl | API | SSL Panel API installato |
git_configure | Git | Token provider Git configurato |
sync_export | Sync | App esportate |
sync_import | Sync | App importate |
sync_push | Sync | App inviate al remoto |
service_restart | Servizi | Servizio riavviato |
service_start | Servizi | Servizio avviato |
service_stop | Servizi | Servizio fermato |
Alert automatici
Una volta configurato, Cipi invia notifiche email per:
- Errori backup (fallimenti upload S3, errori dump)
- Fallimenti deploy (errori Deployer, trigger rollback)
- Fallimenti job cron di sistema (via wrapper
cipi-cron-notify) - Eventi ciclo di vita app — notifica quando un'app viene creata, modificata o eliminata, inclusi hostname server, nome app, dominio e versione PHP
- Elevazione sudo e su — notifica quando un utente eleva con successo via
sudoosu, inclusi chi ha eseguito, utente target (persu), chiave SSH, IP client e TTY - Login SSH privilegiato — notifica quando
rooto un sudoer accede via SSH, inclusi IP sorgente, fingerprint chiave SSH e commento chiave - Cambi chiavi SSH — notifica quando una chiave SSH viene aggiunta, rimossa o rinominata sull'utente
cipi, inclusi hostname, IP, fingerprint, commento chiave, timestamp e conteggio chiavi rimanenti. Gli alert di rename includono anche il vecchio e il nuovo nome chiave.
Ogni notifica email include un footer con l'IP client (SSH_CLIENT) e il nome della chiave SSH usata per autenticarsi, quando applicabile. Il nome chiave viene risolto via SSH_USER_AUTH con fallback su auth.log quando necessario.
Notifiche auth di sicurezza
Cipi integra notifiche di autenticazione basate su PAM via pam_exec.so con ExposeAuthInfo attivo. Quando SMTP è configurato, il sistema invia automaticamente alert email su questi eventi rilevanti per la sicurezza:
- Elevazione sudo e su — attivata quando un utente esegue con successo
sudoosu. La notifica include username, utente target (persu), TTY, chiave SSH, IP client e timestamp. - Login SSH privilegiato — attivato quando
rooto un utente del grupposudoaccede via SSH. La notifica include username, indirizzo IP sorgente, fingerprint chiave SSH e commento chiave (risolto da/var/log/auth.logtramite matching fingerprint suauthorized_keys). - Cambi chiavi SSH — attivati quando una chiave SSH viene aggiunta, rimossa o rinominata sull'utente
cipiviacipi ssh add,cipi ssh removeocipi ssh rename. La notifica include hostname, IP server, fingerprint chiave, commento chiave, timestamp e conteggio chiavi rimanenti. Gli alert di rename includono anche il vecchio e il nuovo nome chiave. - Eventi ciclo di vita app — attivati quando un'app viene creata, modificata o eliminata. La notifica include hostname server, nome app, dominio e versione PHP.
Le notifiche girano in background in modo asincrono così non ritardano mai login o esecuzione comandi. Se SMTP non è configurato, gli hook falliscono silenziosamente senza impatto sul sistema.
Log eventi di sicurezza
Indipendentemente dalla configurazione SMTP, tutti gli eventi di notifica (cambi chiavi SSH, ciclo di vita app, reset password, sudo/su/login SSH, fallimenti cron) vengono sempre loggati in /var/log/cipi/events.log in formato compatto su una riga. Il log ruota giornalmente con retention di 1 anno via logrotate.
Wrapper cron
L'utility cipi-cron-notify avvolge i job cron di sistema e invia una notifica se il job esce con codice non-zero. Utile per monitorare task programmati critici.
Retention log (GDPR)
Cipi applica policy automatiche di rotazione log progettate per soddisfare GDPR e requisiti generali di protezione dati. I log vengono ruotati ed eliminati automaticamente — nessuna pulizia manuale necessaria.
| Categoria | Log | Retention |
|---|---|---|
| Applicativi | Laravel, PHP-FPM, worker, deploy, sistema | 12 mesi |
| Sicurezza | Fail2ban, firewall UFW, autenticazione, eventi Cipi (events.log) |
12 mesi |
| HTTP / navigazione | Log accesso ed errore Nginx | 90 giorni |
Valkey
Valkey è lo store in-memory che Cipi installa come parte dello stack predefinito. Dalla v4.5.6 Cipi provisiona Valkey al posto di redis-server. Eccelle in cache, session storage, message queue, broadcast in tempo reale e rate limiting.
Perché Valkey invece di Redis
Valkey è il fork veramente open source, con licenza BSD di Redis, curato dalla Linux Foundation. È nato nel 2024 dopo che Redis Inc. ha relicenziato Redis dalla permissiva licenza BSD alle source-available SSPL / RSALv2 — un cambiamento che non soddisfa più la definizione di open source. Supportato da AWS, Google Cloud, Oracle e una grande community, Valkey continua la stessa codebase collaudata sul campo sotto una licenza che resta gratuita per sempre. Lo rende perfetto per la filosofia MIT e nessun vendor lock-in di Cipi, e viene fornito nativamente nel repository Universe di Ubuntu 24.04 (pacchetti valkey-server + valkey-tools) — nessun PPA di terze parti da fidarsi.
Altrettanto importante, Valkey è un drop-in replacement: parla lo stesso protocollo RESP sulla stessa porta (127.0.0.1:6379), rispetta le stesse direttive requirepass / bind e legge lo stesso formato dati RDB/AOF. Le tue app non richiedono alcuna modifica — l'estensione phpredis e i valori REDIS_* nel .env continuano a funzionare esattamente come prima.
Come Cipi lo implementa
- Installazione —
setup.shinstalla e configura Valkey (/etc/valkey/valkey.conf, serviziovalkey-server), legato solo alocalhoste protetto con password. - Gestione servizio —
cipi service …gestiscevalkey-server(i nomiredis-server,redisevalkeysono ancora accettati come alias). Viene aggiunto alla blacklist unattended-upgrades, così Cipi lo gestisce invece di un upgrade automatico. - Credenziali — salvate sotto
valkey_user/valkey_passwordin/etc/cipi/server.json(le chiavi legacyredis_*vengono ancora lette come fallback). Host: 127.0.0.1, Porta: 6379. - Reset password —
cipi reset valkey-passwordrigenera la password e riavvia il servizio (cipi reset redis-passwordresta come alias).
Migrazione da Redis (4.5.6 / 4.5.7)
I server esistenti passano a Valkey automaticamente con cipi self-update — nessuna modifica al .env dell'app richiesta. La migrazione riusa la password Redis corrente (recuperata da server.json o /etc/redis/redis.conf), forza un SAVE RDB e snapshot di dump.rdb/AOF, elimina redis-server, installa valkey-server + valkey-tools sulla stessa porta con lo stesso requirepass / bind, ripristina il dataset e riscrive server.json (redis_* → valkey_*) e la blacklist unattended-upgrades — così cache, sessioni e job in queue sopravvivono al passaggio.
La v4.5.7 corregge il nome pacchetto in valkey-server (il pacchetto daemon di Ubuntu 24.04; la 4.5.6 usava inizialmente valkey) e rende la migrazione completamente self-contained e sicura. Abilita automaticamente il componente APT universe quando il pacchetto non viene trovato, esegue un health check post-avvio (PING → PONG con la password) e fa rollback a redis-server — ripristinando sia la password salvata che il dataset — se Valkey non può essere installato o non parte in salute. Lo snapshot del dataset viene mantenuto finché il passaggio non è verificato, poi pulito. La migrazione è idempotente: i server già su Valkey la saltano.
Integrazione Laravel
Aggiungi queste variabili al tuo .env via cipi app env myapp. I nomi variabile restano REDIS_* — è ciò che si aspettano phpredis e il driver redis di Laravel, e Valkey risponde sullo stesso socket:
REDIS_HOST=127.0.0.1 REDIS_PASSWORD=your-password-from-server-json REDIS_PORT=6379
Poi imposta i driver per ogni caso d'uso:
- Cache —
CACHE_STORE=redis - Session —
SESSION_DRIVER=redis - Queue —
QUEUE_CONNECTION=redis(poicipi worker restart myapp) - Broadcasting —
BROADCAST_CONNECTION=redis
Installa l'estensione PHP phpredis per le migliori performance, oppure usa predis/predis come fallback pure-PHP. Entrambi parlano con Valkey in modo trasparente.
Self-update
Cipi può aggiornare se stesso da GitHub senza toccare app, database o configurazioni.
$ cipi self-update --check # check for a new version $ cipi self-update # update to latest
Processo di update
- Scarica l'ultima versione da GitHub
- Fa backup dell'installazione corrente in
/opt/cipi.bak.YYYYMMDDHHMMSS/ - Sostituisce script CLI e lib
- Esegue eventuali script di migrazione in ordine (es. nuove direttive Nginx, nuovi pacchetti)
- Aggiorna il file versione
Gli script di migrazione vivono in lib/migrations/ e sono nominati per versione (es. 4.1.0.sh). Aggiornando dalla v4.0.0 alla v4.2.0, Cipi esegue automaticamente 4.1.0.sh e 4.2.0.sh in ordine. Le tue app, database e configurazioni non vengono mai toccati.
Ad esempio, la migrazione 4.5.5 applica retroattivamente alle app esistenti il nuovo alias shell ll='ls -al': aggiunge l'alias al ~/.bashrc di ogni app una volta (solo se mancante, preservando ownership), così le app create prima della 4.5.5 lo ottengono al prossimo cipi self-update.
Cron di manutenzione automatici
Cipi programma diversi job a livello root durante l'installazione. I crontab a livello app (scheduler, trigger deploy) sono separati — vedi Crontab utente.
| Schedule | Job |
|---|---|
| Giornaliero 02:00 | cipi backup run — backup S3 per tutte le app |
| Giornaliero 03:00 | cipi backup prune --weeks=4 |
| Domenica 03:30 | cipi php upgrade — patch di sicurezza per tutte le versioni PHP installate (avvolto da cipi-cron-notify) |
| Giornaliero 03:50 | cipi self-update (avvolto da cipi-cron-notify) |
| Domenica 04:10 | cipi ssl renew |
| Giornaliero 04:15 | Manutenzione Panel API (cipi-api-maintain — prune job/metriche) |
| Giornaliero 04:30 | cipi api update — soft-update Laravel panel + cipi/api |
Dominio wildcard
Cipi non supporta i domini wildcard (*.myapp.com) nativamente. Il blocco è duplice e architetturale — non un dettaglio di configurazione.
Perché i wildcard non sono supportati
1 — La validazione dominio rifiuta *
Ogni dominio passato a cipi alias add (e cipi app create) viene validato con una regex rigorosa che richiede che la stringa inizi con [a-zA-Z0-9]. L'asterisco fallisce subito, prima che Nginx o certbot vengano toccati.
2 — Certbot usa la challenge HTTP-01, che non può emettere cert wildcard
cipi ssl install chiama certbot --nginx, che si basa sulla challenge HTTP-01 (o TLS-ALPN-01) — posizionando un file di verifica su disco e servendolo sulla porta 80. Let's Encrypt emette certificati wildcard solo via la challenge DNS-01, che richiede accesso programmatico all'API del tuo provider DNS. Cipi non si integra con nessun provider DNS, quindi anche se la validazione fosse bypassata, certbot rifiuterebbe di emettere il cert wildcard.
Alternativa consigliata — certificato Multi-SAN
Se i tuoi subdomain sono fissi e enumerabili (es. api, admin, www, staging), l'approccio corretto è aggiungere ciascuno come alias esplicito e lasciare che Cipi emetta un singolo certificato SAN che li copre tutti:
$ cipi alias add myapp api.myapp.com $ cipi alias add myapp admin.myapp.com $ cipi alias add myapp www.myapp.com $ cipi ssl install myapp # single cert, SAN covers all domains
Il flag --expand di Certbot (usato internamente da Cipi) aggiunge i nuovi SAN al certificato esistente senza emetterne uno nuovo. L'elenco SAN non ha limiti significativi per l'uso tipico.
Certificato wildcard manuale (fuori da Cipi)
Se ti servono subdomain dinamici (es. <tenant>.saas.com), puoi ottenere un certificato wildcard manualmente usando un plugin DNS per certbot e posizionarlo sul server. Cipi non lo gestirà, rinnoverà o traccerà — ne possiedi tu l'intero ciclo di vita.
# example with the Cloudflare DNS plugin $ pip install certbot-dns-cloudflare $ certbot certonly --dns-cloudflare \ --dns-cloudflare-credentials /root/.cloudflare.ini \ -d "*.myapp.com" -d "myapp.com"
Dopo aver ottenuto il certificato, modifica direttamente il vhost Nginx dell'app (/etc/nginx/sites-available/myapp) per referenziare i percorsi del cert wildcard e aggiungi server_name *.myapp.com myapp.com;. Poi ricarica Nginx:
$ nginx -t && systemctl reload nginx
cipi ssl install myapp dopo un setup wildcard manuale sovrascriverà le tue direttive SSL Nginx personalizzate con un certificato Let's Encrypt HTTP-01. Se gestisci un cert wildcard manualmente, evita di eseguire cipi ssl install su quell'app.Modifica config Nginx
Per personalizzare il vhost Nginx di un'app, modifica direttamente la config del sito. Dopo le modifiche, testa e ricarica Nginx.
$ sudo nano /etc/nginx/sites-available/<app> $ sudo nginx -t && sudo systemctl reload nginx
Disinstalla Cipi
Cipi non fornisce un comando di disinstallazione integrato. Se devi rimuovere completamente Cipi da un server, segui i passi sotto in ordine. Questa procedura rimuove ogni componente che Cipi installa — utenti, servizi, pacchetti, config e dati.
1 — Ferma e rimuovi tutte le app
Per ogni app gestita da Cipi, rimuovi utente di sistema, home directory, database, vhost Nginx, pool PHP-FPM e config Supervisor.
# List all app users (members of cipi-apps group) $ grep cipi-apps /etc/group # For EACH app user, remove everything $ supervisorctl stop <app_user>:* $ rm -f /etc/supervisor/conf.d/<app_user>.conf $ rm -f /etc/nginx/sites-enabled/<app_user> $ rm -f /etc/nginx/sites-available/<app_user> $ rm -f /etc/php/*/fpm/pool.d/<app_user>.conf $ rm -f /etc/sudoers.d/cipi-<app_user> $ mysql -e "DROP DATABASE IF EXISTS <app_user>; DROP USER IF EXISTS '<app_user>'@'localhost'; DROP USER IF EXISTS '<app_user>'@'127.0.0.1';" $ userdel -r <app_user>
2 — Rimuovi utente e gruppi Cipi
$ userdel -r cipi $ groupdel cipi-ssh 2>/dev/null $ groupdel cipi-apps 2>/dev/null
3 — Rimuovi binari, librerie e dati Cipi
$ rm -f /usr/local/bin/cipi $ rm -f /usr/local/bin/cipi-worker $ rm -f /usr/local/bin/cipi-cron-notify $ rm -f /usr/local/bin/cipi-auth-notify $ rm -rf /opt/cipi $ rm -rf /etc/cipi $ rm -rf /var/log/cipi
4 — Rimuovi Cipi API (se installata)
$ systemctl stop cipi-queue 2>/dev/null $ systemctl disable cipi-queue 2>/dev/null $ rm -f /etc/systemd/system/cipi-queue.service $ systemctl daemon-reload
5 — Rimuovi job cron Cipi
# Edit root crontab and remove all Cipi entries $ crontab -e # Remove lines referencing: cipi self-update, certbot renewal, cache cleanup, RAM drop
6 — Rimuovi file di configurazione Cipi
# Sudoers $ rm -f /etc/sudoers.d/cipi-sudo $ rm -f /etc/sudoers.d/cipi-api # Logrotate $ rm -f /etc/logrotate.d/cipi-app-logs $ rm -f /etc/logrotate.d/cipi-http-logs $ rm -f /etc/logrotate.d/cipi-security-logs # Unattended upgrades $ rm -f /etc/apt/apt.conf.d/50cipi-unattended-upgrades $ rm -f /etc/apt/apt.conf.d/20cipi-auto-upgrades # System profile and MOTD $ rm -f /etc/profile.d/cipi-env.sh $ echo "" > /etc/motd # MariaDB custom config $ rm -f /etc/mysql/mariadb.conf.d/99-cipi.cnf # PHP custom config (all versions) $ rm -f /etc/php/*/fpm/conf.d/99-cipi.ini # Nginx default page $ rm -f /etc/nginx/sites-available/default $ rm -f /etc/nginx/sites-enabled/default
7 — Elimina pacchetti installati
Rimuovi tutti i pacchetti installati da Cipi. Salta qualsiasi pacchetto che vuoi tenere per altri scopi.
$ systemctl stop nginx mariadb valkey-server fail2ban supervisor $ systemctl stop php*-fpm $ apt purge -y nginx* mariadb-server mariadb-client valkey-server \ fail2ban supervisor certbot python3-certbot-nginx \ php8.4* php8.5* nodejs $ apt autoremove -y $ apt autoclean
8 — Rimuovi repository APT
$ add-apt-repository --remove ppa:ondrej/php -y $ rm -f /etc/apt/sources.list.d/mariadb.list $ rm -f /etc/apt/sources.list.d/nodesource.list $ rm -f /etc/apt/keyrings/mariadb-keyring.pgp $ apt update
9 — Rimuovi Composer e Deployer
$ rm -f /usr/local/bin/composer $ rm -f /usr/local/bin/dep
10 — Rimuovi file swap
$ swapoff /var/swap.1 $ rm -f /var/swap.1 # Remove the swap entry from /etc/fstab $ sed -i '/swap\.1/d' /etc/fstab
11 — Ripristina default SSH e PAM
Cipi hardening SSH (disabilita login root e auth password) e aggiunge hook PAM. Se devi ripristinare i default:
# Restore sshd_config to allow password auth (if needed) $ sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config $ sed -i 's/^PermitRootLogin no/PermitRootLogin yes/' /etc/ssh/sshd_config # Remove Cipi PAM hooks $ sed -i '/cipi-auth-notify/d' /etc/pam.d/sshd $ sed -i '/cipi-auth-notify/d' /etc/pam.d/sudo # Restore sysctl $ sed -i '/vm.swappiness/d' /etc/sysctl.conf $ sysctl -p $ systemctl restart sshd
12 — Reset firewall
$ ufw disable $ ufw reset