Laravel Octane on FrankenPHP — the framework stays in memory, next to classic FPM apps. Reverb for WebSockets. PostgreSQL beside MariaDB, chosen per app. 5.2 adds opt-in CrowdSec: engine and a registered firewall bouncer, no WAF. 5.3 puts Cloudflare Zero Trust one opt-in command away — tunnel, Access, a dark origin — watches the server itself every five minutes, and sends every alert to Slack, Discord, Telegram or ntfy as well as email. 5.3.1 hands your auditor a read-only evidence bundle, and moves sites or hands a path to another service without touching a vhost. 5.4 deploys Next.js, Nuxt, SvelteKit, Astro and Vite apps next to Laravel — blue/green for SSR — and writes every deploy, however it started, into a hash-chained ledger. Same one-command server. Everything Cipi 5, tagged by release.
Everything Cipi 5 adds, at a glance. Tiles tagged since 5.0 shipped with Cipi 5; since 5.2, since 5.3 and since 5.4 are new in this line. Tap any tile to jump into the docs.
Boot the framework once and keep it in memory. Octane apps and classic PHP-FPM apps run side by side on the same server — Nginx proxies to the Octane process, Supervisor keeps it alive, every deploy reloads it cleanly.
Two engines on one box. Pick per app or set a server-wide default — env, backups and restores follow.
Supervised, and restarted on every release.
WebSockets done properly since 5.1.2: generated credentials, wss:// from the certificate, a
proxy that no longer swallows /appointments.
Run the build inside the release, right after dependencies. Fail-closed, so broken assets never reach production — and compiled files never reach your repository.
Cron on or off per app, from the CLI.
Switch runtime on a live app, both ways.
Opt in per app or per deploy and Cipi dumps the database before the release goes out. A bad migration becomes recoverable instead of fatal.
Clone a production app onto a new domain.
No app can starve the box any more.
Issue and renew through a Cloudflare DNS-01 challenge when a public HTTP endpoint isn't an option. HTTP-01 stays the default.
Every 5 minutes. Email after 3 failures.
www or apex, aliased and 301'd for you.
Restore the redirect without reissuing.
Scope, schedule, destination and retention per profile. A 30-minute local database copy next to an encrypted nightly full copy on S3. Files and databases stored separately; tenant databases discovered from the engine. Retention is mandatory.
See every tunable and which layer set it. Writes FPM and CLI together, server-wide or
--app=. Whitelist only.
Aliases, PHP, extra databases, workers, healthcheck and backups — in the repo.
plan, apply, auto after every deploy. Fail-closed:
it never creates an app and never runs a shell command.
A request matching no app used to land on a random vhost. Now :80 and
:443 close it with an empty reply.
The release that just went live is probed immediately — not after three five-minute failures. Opt in to roll it back automatically. Migrations are not undone; the email says so.
Multi-tenant apps need *.example.com. Nginx already could; Cipi now accepts
it.
Opt-in IP reputation that reads the logs your vhosts actually write. The engine ships with a registered firewall bouncer, because decisions without one ban nothing at all. It refuses to start behind an unconfigured reverse proxy, and it allowlists the SSH session you enable it from. There is no WAF.
A high-port TLS listener and a one-shot token. One GET allowlists your IP and unbans it in CrowdSec and fail2ban. Not a login, not an SSH key.
sha256 of the live release against the manifest written at deploy, then ClamAV over the upload directories only. 04:40, every night.
bash and zsh, written by setup.sh and every self-update. Verbs, sub-commands, flags and your app names. No dotfile to edit.
A single Rust binary next to Nginx — not a container. Listens on 127.0.0.1. Cipi writes the index prefix so two apps cannot share a key. Opt-in: nothing installs until you ask.
Image optimisers, ffmpeg, convert, pdftotext — from Ubuntu's repos, and only those. The allowlist is the feature. Chromium is refused on purpose.
Cursor Origin, AWS CodeCommit, Bitbucket Cloud and Azure DevOps — recognised from the clone URL, the same way GitHub always was. Save the credentials, create the app, and Cipi registers the deploy key and the webhook where the forge has one.
Declare deploy.post and the steps run from the live release after every deploy — cipi deploy and the webhook alike. Allowlisted runners only: artisan, npm, composer, one php or node script. No free shell, and no yml auto required.
Nginx, MariaDB, PostgreSQL and Valkey stay off unattended-upgrades on purpose — a database restart is not a 4am surprise. Now you have the switch: patch-level, scoped, and never on a cron.
cipi.yml is not a public URLA custom app serves htdocs/, so a committed cipi.yml answered over HTTP. Every vhost now denies it at any path, Laravel included — applied on update, without touching certbot's block.
A locally-managed Cloudflare Tunnel, Nginx that logs the real visitor, fail2ban taught the edge ranges — and not a single port closed. Route an app, put Access in front of staging or the GUI, carry SSH over the tunnel. Opt-in, like CrowdSec.
lock http refuses while an app still renews over HTTP-01, then closes 80/443 — or lets only Cloudflare in. lock ssh refuses unless the tunnel already carries SSH. The way back is one command.
Disk, certificate expiry, services, queue workers, 5xx spikes, read-only filesystems, load — every five minutes. One alert when it breaks, one when it recovers, a reminder while it stays broken. No dashboards.
Slack, Discord, Telegram, ntfy or a JSON webhook, for every trigger Cipi already had — deploys, backups, scans, logins, the monitor. A five-second timeout, so a dead webhook never stalls a deploy.
Seventeen read-only controls mapped to ISO/IEC 27001:2022 and SOC 2 — SSH, firewall, patching, TLS, accounts, API tokens, deploys, backups, logging. A root-only bundle with the raw output behind every finding, checksummed. No secrets inside, and the gaps stated up front.
Every name of the app, www included, to the new home — path and query kept, certificate still renewing. Or redirect single paths and prefixes. Stored in apps.json, so no vhost rebuild ever drops them.
/api/ to a Node service, /events/ unbuffered for SSE — WebSocket and forwarded headers included. Ports Cipi already uses are refused, and if nginx -t fails, everything is put back.
Node apps are a real app type now. A Vite SPA with client routes that survive reload, a pre-rendered site with real 404s, or an SSR server that switches blue/green only after the new release answers its health path. Releases, rollback, webhook and SSL, same as Laravel.
Official builds checked against SHASUMS256.txt, one server-wide default for
Laravel asset builds, and per-app pins. Node 20 is end of life — servers move to 22.
CLI, panel, webhook, dep over SSH or an MCP client inside the app — root reads
the origin, operator and commit from /proc, keeps the app's claims apart, and
chains each line to the one before it. Mirrored to syslog.
www redirect, basic auth by hash, redirects and proxies, Meilisearch, recipe options, limits,
forced HTTPS, required .env names, crons and a Node app's build — and the panel
API 1.31 plus the GUI drive the same features from the browser.
The honest before-and-after. Left is what running these things used to cost you. Right is Cipi 5, tagged by release.
cipi ini for both SAPIs, server-wide or per app
cipi.yml in git, applied on deploy
*.example.com wildcards
convert
→
An allowlisted cipi package — Chromium refused
deploy.post in the repo, allowlisted runners only
apt upgrade and hope MariaDB comes back
→
Scoped, patch-level, one service at a time
cipi.yml since 5.2.3
Downloadable from a custom app's own domain
→
Denied at any path, on every vhost
notifications disable kept sending
→
An explicit false stays false
apps.json, rolled back if nginx -t fails
/index.html fallback
The complete Cipi 5 addition to the CLI. Same syntax you already know, same one binary. Tagged since 5.0, since 5.1, since 5.2, since 5.3 or since 5.4 — down to the 5.4.1 patch.
cipi app create --octaneCreate a Laravel app served by Octane
on FrankenPHP since 5.0cipi app convert <app> --to=octane|fpmMove an existing app
between runtimes since 5.0cipi app reverb enable|disable|statusRealtime websockets for an
app since 5.0cipi worker horizon enable|disable|statusHorizon instead of
plain queue workers since 5.0cipi schedule on|off|status <app>Toggle the Laravel
scheduler per app since 5.0cipi app edit --node-build='…'Run a frontend build on every
deploy since 5.0cipi app edit --no-node-buildRemove the build step
again since 5.0cipi app clone <app> --domain=…Instant staging copy of a
production app since 5.0cipi deploy --snapshotDump the database before the release goes
out since 5.0cipi app limits <app>Cap FPM children, memory, Octane and
queue workers since 5.0cipi db install|uninstall pgsqlAdd or remove PostgreSQL next to
MariaDB since 5.0cipi db default mariadb|pgsqlChoose the engine used when you
omit the flag since 5.0cipi db enginesInstalled engines, ports and current
default since 5.0cipi ssl dns set --provider=cloudflareStore the credentials for
DNS-01 challenges since 5.0cipi ssl install --dns=cloudflare --wildcardIssue wildcard
certificates via DNS since 5.0cipi ssl force <app>Re-apply the HTTP to HTTPS
redirect since 5.0cipi www add|force-to-root|force-from-rootCanonical host and
permanent redirects since 5.0cipi health set|unset|check|list [--json]Built-in HTTP monitoring and
alerts since 5.0cipi api ip-whitelist show|add|set|allow-allRestrict panel API / MCP by IP since 5.0cipi app webhook recreate [--rotate-secret]Recreate GitHub/GitLab deploy webhook since 5.0cipi smtp configure --host=… --port=…Non-interactive SMTP for API/scripts since 5.0cipi app env|run|deploy-configNon-interactive app tooling for API/GUI since 5.0cipi backup profile add|edit|listBackup strategies: what, how often, where, how long since 5.1cipi backup verify|status|fetch --encryptIntegrity check, overdue watchdog, client-side AES-256 since 5.1cipi ini list|set|unsetphp.ini for FPM and CLI, server-wide or per app since 5.1cipi yml generate|plan|apply|autoPer-project cipi.yml that travels with the code since 5.1cipi nginx default-server on|offClose unmatched Host requests with 444 since 5.1cipi health set --rollback-on-unhealthyUndo a release that fails its post-deploy check since 5.1cipi health postdeploy <app>Run the post-deploy probe on demand since 5.1cipi deploy --log[=N]Show the timestamped deploy log since 5.1cipi alias add <app> '*.example.com'Wildcard domain aliases since 5.1cipi crowdsec enable|disable|statusOpt-in IP reputation: engine plus a registered firewall bouncer since 5.2cipi crowdsec allow|unallow <ip|cidr>Never ban an address, or drop an extra allow since 5.2cipi crowdsec rescue token|rotateBreak-glass TLS listener and its one-shot token since 5.2cipi scan enable|disable|statusNightly integrity check plus ClamAV on upload dirs since 5.2cipi scan [<app>] | report | manifestRun now, read the last report, re-baseline a manifest since 5.2cipi completion bash|zsh [--print]Shell tab-completion — already installed for you since 5.2cipi git refresh [app]Re-sync GitHub/GitLab deploy keys and webhooks since 5.2.1cipi app fix-permissions [app]Restore an app home to the permission model Cipi created it with since 5.2.1cipi search install|enable|disable|statusMeilisearch for Laravel Scout — native binary, 127.0.0.1 only since 5.2.2cipi search key show|rotateApp key or master key; rotating the master rewrites every .env since 5.2.2cipi search upgrade|removeIn-place store upgrade, or put the old binary back since 5.2.2cipi package list|install|removeAllowlisted host binaries from Ubuntu's repos since 5.2.2cipi git origin-token|bitbucket-token|azure-tokenCredentials for Cursor Origin, Bitbucket Cloud and Azure DevOps since 5.2.3cipi git codecommit-token <key> <secret> <iam-user>AWS IAM credentials — the deploy key goes up via UploadSSHPublicKey since 5.2.3cipi yml post-deploy <app>Run the repo's declared deploy.post steps now, against current/ since 5.2.3cipi nginx upgrade [--yes]Patch installed nginx packages, nginx -t, then reload since 5.2.3cipi db upgrade [mariadb|pgsql] [--yes]Patch one database engine, or every installed one since 5.2.3cipi service upgrade [name] [--yes]The generic entry, and the home for Valkey — all is refused since 5.2.3cipi zt token set --token= --account=Cloudflare API token, root-only — not the DNS-01 file since 5.3cipi zt enable|disable|status|refreshTunnel and Nginx real_ip, ports left open; disable restores UFW since 5.3cipi zt hostname add|remove <app|--gui>Route an app or the panel through the tunnel since 5.3cipi zt access enable|disable <app|--gui>Cloudflare Access in front, Git webhook path bypassed since 5.3cipi zt ssh enable --hostname=SSH over the tunnel — port 22 stays open since 5.3cipi zt lock http|ssh [--yes]Close the origin, with refusals that keep you in since 5.3cipi zt unlock http | cipi zt ssh unlockReopen 80/443 or port 22 since 5.3cipi zt origin-cert <app>Optional 15-year Cloudflare Origin CA certificate since 5.3cipi monitor [--json] | list | testRun the server checks now, see their state, send a sample alert since 5.3cipi monitor enable|disable|set <check>Toggle a check or change its thresholds since 5.3cipi notifications channel add <type> <id>Slack, Discord, Telegram, ntfy or webhook since 5.3cipi notifications channel list|test|enable|disable|removeMasked secrets; test one channel or all since 5.3cipi compliance [check] [--days=90] [--json]17 read-only controls; exits 1 on any fail since 5.3.1cipi compliance report [--out=] [--no-archive]Evidence bundle, SHA256SUMS and a checksummed archive since 5.3.1cipi compliance list|controlsPast reports, and the ISO 27001 / SOC 2 mapping since 5.3.1cipi redirect set <app> --to=<url>Every name of the app in one hop; enable|disable|unset since 5.3.1cipi redirect add|remove|list <app>Exact or prefix path redirects, 301/302/307/308 since 5.3.1cipi proxy add|remove|list <app>A URL prefix to another upstream, WebSocket included since 5.3.1cipi app create --node=spa|static|ssrNode frontends; --framework=next|nuxt|sveltekit|astro|remix|vite since 5.4cipi app edit <app> --node-version=24|defaultPin one app's Node major, or follow the server since 5.4cipi node install|list|upgrade|removeChecksum-verified official Node builds, LTS majors since 5.4cipi node default <major>|systemServer-wide Node for Laravel builds, app run, deploy.post since 5.4cipi node status|restart|logs <app>Slots, zero-downtime restart, serving-slot log since 5.4cipi deploy <app> --audit [--days=90] [--json]The app's records from the deploy ledger since 5.4Server management from the REST API and optional web GUI — plus non-interactive flags for scripts.
The newest rows need cipi self-update to 5.4.1 and panel API
1.31.
GET /api/php and install; remove and default stay on the CLI
cipi user keys
GET /api/services and restart from the panel
cipi smtp configure --host=…
--json on CLI
api/* and /mcp
cipi app webhook recreate [--rotate-secret]
open_basedir
cipi redirect / cipi proxy as root only
→
REST, MCP and GUI — same validation, never --force
GET /api/apps/{name}/deploy/audit + a GUI view
tools/list page
Run the updater and Cipi rebuilds vhosts, pools, Deployer templates and app metadata in place — without touching your code or your data.
cipi.yml auto and post-deploy rollback, CrowdSec, the nightly scan, Meilisearch, cipi package, Cloudflare Zero Trust, chat
channels and Node apps stay off until you ask. cipi compliance only reads. The server monitor is on, and quiet until something
breaks.