Cipi 5.4.1 · Now available

Your server just got
a serious promotion.

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.

root@vps — cipi
$ cipi self-update
release 5 fetched
migrations applied
vhosts, pools & templates regenerated
$ cipi app create myapp --domain=myapp.com --octane
FrankenPHP · Octane port 8100
PostgreSQL · Reverb
# --node=ssr · cipi node · deploy --audit
$
The headlines
01 — The headlines

Forty-one reasons to
update tonight.

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.

Headline feature
01 since 5.0

Laravel Octane
on FrankenPHP.

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.

cipi app create myapp --domain=myapp.com --octane
02 since 5.0

PostgreSQL, alongside MariaDB.

Two engines on one box. Pick per app or set a server-wide default — env, backups and restores follow.

cipi db install pgsql
03 since 5.0

Laravel Horizon

Supervised, and restarted on every release.

cipi worker horizon enable
04 since 5.0

Laravel Reverb

WebSockets done properly since 5.1.2: generated credentials, wss:// from the certificate, a proxy that no longer swallows /appointments.

cipi app reverb enable
05 since 5.0

Your frontend builds on the server

Run the build inside the release, right after dependencies. Fail-closed, so broken assets never reach production — and compiled files never reach your repository.

cipi app edit myapp --node-build='npm ci && npm run build'
06 since 5.0

Scheduler switch

Cron on or off per app, from the CLI.

cipi schedule on myapp
07 since 5.0

Convert FPM ⇄ Octane

Switch runtime on a live app, both ways.

cipi app convert myapp --to=octane
08 since 5.0

A snapshot before every risky migration

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.

cipi deploy myapp --snapshot-required
09 since 5.0

Instant staging

Clone a production app onto a new domain.

cipi app clone myapp --domain=stage.myapp.com
10 since 5.0

Resource limits

No app can starve the box any more.

cipi app limits myapp --memory-limit=256M
11 since 5.0

Wildcard certificates, without the HTTP dance

Issue and renew through a Cloudflare DNS-01 challenge when a public HTTP endpoint isn't an option. HTTP-01 stays the default.

cipi ssl install myapp --dns=cloudflare --wildcard
12 since 5.0

Health checks

Every 5 minutes. Email after 3 failures.

cipi health set myapp --url=…
13 since 5.0

One canonical host

www or apex, aliased and 301'd for you.

cipi www force-to-root myapp
14 since 5.0

Re-force HTTPS

Restore the redirect without reissuing.

cipi ssl force myapp
15 since 5.1

Backup profiles, not one hardcoded job

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.

cipi backup profile add
16 since 5.1

Guided php.ini

See every tunable and which layer set it. Writes FPM and CLI together, server-wide or --app=. Whitelist only.

cipi ini set upload_max_filesize=50M
17 since 5.1

cipi.yml travels with the code

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.

cipi yml generate myapp
18 since 5.1

Unknown Host → 444

A request matching no app used to land on a random vhost. Now :80 and :443 close it with an empty reply.

cipi nginx default-server on
19 since 5.1

Post-deploy health, optional rollback

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.

cipi health set myapp --rollback-on-unhealthy
20 since 5.1

Wildcard aliases

Multi-tenant apps need *.example.com. Nginx already could; Cipi now accepts it.

cipi alias add myapp '*.example.com'
Security release
21 since 5.2

CrowdSec, engine
and bouncer.

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.

cipi crowdsec enable
22 since 5.2

A way back in

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.

cipi crowdsec rescue rotate
23 since 5.2

Nightly integrity check

sha256 of the live release against the manifest written at deploy, then ClamAV over the upload directories only. 04:40, every night.

cipi scan enable
24 since 5.2

Tab-completion, installed for you

bash and zsh, written by setup.sh and every self-update. Verbs, sub-commands, flags and your app names. No dotfile to edit.

cipi app <TAB>
Scout, on the box
25 since 5.2.2

Meilisearch for
Laravel Scout.

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.

cipi search enable myapp
26 since 5.2.2

An allowlisted apt

Image optimisers, ffmpeg, convert, pdftotext — from Ubuntu's repos, and only those. The allowlist is the feature. Chromium is refused on purpose.

cipi package install imagemagick
Six forges
27 since 5.2.3

Git beyond GitHub
and GitLab.

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.

cipi git bitbucket-token <token>
cipi.yml
28 since 5.2.3

Post-deploy steps
that live in the repo.

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.

cipi yml post-deploy myapp
29 since 5.2.3

The upgrade switch for the rest of the stack

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 db upgrade mariadb
30 since 5.2.3

Your cipi.yml is not a public URL

A 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.

cipi self-update
Cloudflare
31 since 5.3

Zero Trust,
one step at a time.

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.

cipi zt enable
Origin dark
32 since 5.3

Close the ports
only when it is safe.

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.

cipi zt lock ssh --yes
33 since 5.3

A monitor that only speaks when it matters

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.

cipi monitor list
34 since 5.3

Every alert, in the chat you already read

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.

cipi notifications channel add slack ops
Audit
35 since 5.3.1

Evidence your auditor
will actually accept.

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.

cipi compliance report
36 since 5.3.1

Move a site in one hop

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.

cipi redirect set old --to=https://new.com
Nginx
37 since 5.3.1

Hand a path
to another service.

/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.

cipi proxy add myapp /api/ http://127.0.0.1:3000
Headline feature
38 since 5.4

Next.js, Nuxt, SvelteKit
and Astro — deployed.

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.

cipi app create --node=ssr --framework=next
39 since 5.4

Node runtimes, verified.

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.

cipi node default 22
Audit
40 since 5.4

Every deploy on the record.

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.

cipi deploy myapp --audit
cipi.yml
41 since 5.4

The whole app,
in one committed file.

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.

cipi yml plan myapp
02 — The shift

What used to be work,
is now a flag.

The honest before-and-after. Left is what running these things used to cost you. Right is Cipi 5, tagged by release.

Runtime since 5.0 PHP-FPM for everything FPM or Octane on FrankenPHP, chosen per app
Queues since 5.0 Bare queue workers, restarted by hand Horizon under Supervisor, deploy-aware
Websockets since 5.0 Roll your own port, proxy and service Reverb enabled in one command, SSL included
Databases since 5.0 MariaDB, take it or leave it MariaDB and PostgreSQL, per app
Frontend since 5.0 Commit compiled assets, or build in CI Node build runs inside the release, fail-closed
Migrations since 5.0 Deploy and hope Automatic snapshot before the release goes out
Staging since 5.0 Rebuild a second app by hand One clone command, database optional
Wildcards since 5.0 Manual DNS challenge every renewal DNS-01 with Cloudflare, automated
Monitoring since 5.0 A third-party service and its invoice Health checks every five minutes, built in
Noisy apps since 5.0 One app could take the server down Hard caps on workers, children and memory
Backups since 5.1 One hardcoded nightly job Profiles, client-side AES-256, verify, managed cron
php.ini since 5.1 Hand-edit FPM files; CLI ignored cipi ini for both SAPIs, server-wide or per app
App config since 5.1 Recreate by SSH on every server cipi.yml in git, applied on deploy
Unknown Host since 5.1 Landed on a random vhost Empty 444 default server
Broken deploy since 5.1 Wait fifteen minutes for a health email Immediate post-deploy probe, optional rollback
Aliases since 5.1 Exact names only *.example.com wildcards
Attackers since 5.2 fail2ban, and only after the fact CrowdSec decisions dropped by a registered bouncer
Locked out since 5.2 The provider's rescue console One-shot token on a rescue TLS port
Tampering since 5.2 Notice it when something looks odd Nightly sha256 against the deploy manifest
The CLI since 5.2 Remember every verb TAB completes verbs, flags and app names
Search since 5.2.2 An Algolia account, or Scout's database driver Meilisearch on 127.0.0.1, prefix written by Cipi
Host binaries since 5.2.2 apt as root, and hope php-imagick pulled convert An allowlisted cipi package — Chromium refused
Git forges since 5.2.3 Auto-setup on GitHub and GitLab, manual everywhere else Origin, CodeCommit, Bitbucket and Azure DevOps too
After the deploy since 5.2.3 Patch the deploy script on every server deploy.post in the repo, allowlisted runners only
Stack patches since 5.2.3 apt upgrade and hope MariaDB comes back Scoped, patch-level, one service at a time
Committed cipi.yml since 5.2.3 Downloadable from a custom app's own domain Denied at any path, on every vhost
Origin IP since 5.3 Anyone who finds it can skip the CDN Tunnel-only — 80/443 closed, or Cloudflare IPs only
Port 22 since 5.3 Open to the internet, guarded by fail2ban Behind Cloudflare Access, closed once the tunnel works
Server health since 5.3 A customer tells you the disk is full One alert on the change, one on recovery
Alerts since 5.3 Email, or a CI step you wrote yourself Slack, Discord, Telegram, ntfy or a webhook
Muted triggers since 5.3 notifications disable kept sending An explicit false stays false
Audits since 5.3.1 Screenshots and shell history pasted into a spreadsheet One command, a checksummed evidence bundle
Redirects since 5.3.1 Hand-edited vhosts, lost on the next rebuild In apps.json, rolled back if nginx -t fails
React / Vue SPA since 5.4 A committed build, 404 on every reload Built on deploy, /index.html fallback
Next.js / Nuxt since 5.4 No way to run an SSR server Blue/green, health-checked before the switch
Who deployed? since 5.4 Only CLI and webhook deploys left a banner Every deploy in a hash-chained, root-only ledger
Old backups since 5.4 Pre-5.1 archives kept forever, S3 errors swallowed Orphans pruned, retention failures alert
03 — The new vocabulary

Every new command
you didn't have before.

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.0
cipi app convert <app> --to=octane|fpmMove an existing app between runtimes since 5.0
cipi app reverb enable|disable|statusRealtime websockets for an app since 5.0
cipi worker horizon enable|disable|statusHorizon instead of plain queue workers since 5.0
cipi schedule on|off|status <app>Toggle the Laravel scheduler per app since 5.0
cipi app edit --node-build='…'Run a frontend build on every deploy since 5.0
cipi app edit --no-node-buildRemove the build step again since 5.0
cipi app clone <app> --domain=…Instant staging copy of a production app since 5.0
cipi deploy --snapshotDump the database before the release goes out since 5.0
cipi app limits <app>Cap FPM children, memory, Octane and queue workers since 5.0
cipi db install|uninstall pgsqlAdd or remove PostgreSQL next to MariaDB since 5.0
cipi db default mariadb|pgsqlChoose the engine used when you omit the flag since 5.0
cipi db enginesInstalled engines, ports and current default since 5.0
cipi ssl dns set --provider=cloudflareStore the credentials for DNS-01 challenges since 5.0
cipi ssl install --dns=cloudflare --wildcardIssue wildcard certificates via DNS since 5.0
cipi ssl force <app>Re-apply the HTTP to HTTPS redirect since 5.0
cipi www add|force-to-root|force-from-rootCanonical host and permanent redirects since 5.0
cipi health set|unset|check|list [--json]Built-in HTTP monitoring and alerts since 5.0
cipi api ip-whitelist show|add|set|allow-allRestrict panel API / MCP by IP since 5.0
cipi app webhook recreate [--rotate-secret]Recreate GitHub/GitLab deploy webhook since 5.0
cipi smtp configure --host=… --port=…Non-interactive SMTP for API/scripts since 5.0
cipi app env|run|deploy-configNon-interactive app tooling for API/GUI since 5.0
cipi backup profile add|edit|listBackup strategies: what, how often, where, how long since 5.1
cipi backup verify|status|fetch --encryptIntegrity check, overdue watchdog, client-side AES-256 since 5.1
cipi ini list|set|unsetphp.ini for FPM and CLI, server-wide or per app since 5.1
cipi yml generate|plan|apply|autoPer-project cipi.yml that travels with the code since 5.1
cipi nginx default-server on|offClose unmatched Host requests with 444 since 5.1
cipi health set --rollback-on-unhealthyUndo a release that fails its post-deploy check since 5.1
cipi health postdeploy <app>Run the post-deploy probe on demand since 5.1
cipi deploy --log[=N]Show the timestamped deploy log since 5.1
cipi alias add <app> '*.example.com'Wildcard domain aliases since 5.1
cipi crowdsec enable|disable|statusOpt-in IP reputation: engine plus a registered firewall bouncer since 5.2
cipi crowdsec allow|unallow <ip|cidr>Never ban an address, or drop an extra allow since 5.2
cipi crowdsec rescue token|rotateBreak-glass TLS listener and its one-shot token since 5.2
cipi scan enable|disable|statusNightly integrity check plus ClamAV on upload dirs since 5.2
cipi scan [<app>] | report | manifestRun now, read the last report, re-baseline a manifest since 5.2
cipi completion bash|zsh [--print]Shell tab-completion — already installed for you since 5.2
cipi git refresh [app]Re-sync GitHub/GitLab deploy keys and webhooks since 5.2.1
cipi app fix-permissions [app]Restore an app home to the permission model Cipi created it with since 5.2.1
cipi search install|enable|disable|statusMeilisearch for Laravel Scout — native binary, 127.0.0.1 only since 5.2.2
cipi search key show|rotateApp key or master key; rotating the master rewrites every .env since 5.2.2
cipi search upgrade|removeIn-place store upgrade, or put the old binary back since 5.2.2
cipi package list|install|removeAllowlisted host binaries from Ubuntu's repos since 5.2.2
cipi git origin-token|bitbucket-token|azure-tokenCredentials for Cursor Origin, Bitbucket Cloud and Azure DevOps since 5.2.3
cipi git codecommit-token <key> <secret> <iam-user>AWS IAM credentials — the deploy key goes up via UploadSSHPublicKey since 5.2.3
cipi yml post-deploy <app>Run the repo's declared deploy.post steps now, against current/ since 5.2.3
cipi nginx upgrade [--yes]Patch installed nginx packages, nginx -t, then reload since 5.2.3
cipi db upgrade [mariadb|pgsql] [--yes]Patch one database engine, or every installed one since 5.2.3
cipi service upgrade [name] [--yes]The generic entry, and the home for Valkey — all is refused since 5.2.3
cipi zt token set --token= --account=Cloudflare API token, root-only — not the DNS-01 file since 5.3
cipi zt enable|disable|status|refreshTunnel and Nginx real_ip, ports left open; disable restores UFW since 5.3
cipi zt hostname add|remove <app|--gui>Route an app or the panel through the tunnel since 5.3
cipi zt access enable|disable <app|--gui>Cloudflare Access in front, Git webhook path bypassed since 5.3
cipi zt ssh enable --hostname=SSH over the tunnel — port 22 stays open since 5.3
cipi zt lock http|ssh [--yes]Close the origin, with refusals that keep you in since 5.3
cipi zt unlock http | cipi zt ssh unlockReopen 80/443 or port 22 since 5.3
cipi zt origin-cert <app>Optional 15-year Cloudflare Origin CA certificate since 5.3
cipi monitor [--json] | list | testRun the server checks now, see their state, send a sample alert since 5.3
cipi monitor enable|disable|set <check>Toggle a check or change its thresholds since 5.3
cipi notifications channel add <type> <id>Slack, Discord, Telegram, ntfy or webhook since 5.3
cipi notifications channel list|test|enable|disable|removeMasked secrets; test one channel or all since 5.3
cipi compliance [check] [--days=90] [--json]17 read-only controls; exits 1 on any fail since 5.3.1
cipi compliance report [--out=] [--no-archive]Evidence bundle, SHA256SUMS and a checksummed archive since 5.3.1
cipi compliance list|controlsPast reports, and the ISO 27001 / SOC 2 mapping since 5.3.1
cipi redirect set <app> --to=<url>Every name of the app in one hop; enable|disable|unset since 5.3.1
cipi redirect add|remove|list <app>Exact or prefix path redirects, 301/302/307/308 since 5.3.1
cipi proxy add|remove|list <app>A URL prefix to another upstream, WebSocket included since 5.3.1
cipi app create --node=spa|static|ssrNode frontends; --framework=next|nuxt|sveltekit|astro|remix|vite since 5.4
cipi app edit <app> --node-version=24|defaultPin one app's Node major, or follow the server since 5.4
cipi node install|list|upgrade|removeChecksum-verified official Node builds, LTS majors since 5.4
cipi node default <major>|systemServer-wide Node for Laravel builds, app run, deploy.post since 5.4
cipi node status|restart|logs <app>Slots, zero-downtime restart, serving-slot log since 5.4
cipi deploy <app> --audit [--days=90] [--json]The app's records from the deploy ledger since 5.4
04 — Since 5.0.6, bigger in 5.4.1

Panel API, GUI
and automation.

Server 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.

PHP SSH-only version management GET /api/php and install; remove and default stay on the CLI
SSH keys Terminal-only key admin REST + GUI for cipi user keys
Services Manual systemctl GET /api/services and restart from the panel
SMTP Interactive wizard only REST + cipi smtp configure --host=…
Health CLI-only checks REST per app + --json on CLI
API access Any IP with a token Optional IP whitelist on api/* and /mcp
Webhooks Recreate by re-editing the repo cipi app webhook recreate [--rotate-secret]
Self-update Could hang on API/GUI Composer step 5.0.14–5.0.17 — timed Packagist/tarball panel updates
Panel GUI HTTP 500 after upgrade/soft update 5.0.18 — no Composer symlink outside open_basedir
Routing since 5.4.1 cipi redirect / cipi proxy as root only REST, MCP and GUI — same validation, never --force
Node apps since 5.4.1 CLI-only create and restart Create, edit, blue/green restart from the panel
Deploy audit API 1.31 SSH in and read the ledger GET /api/apps/{name}/deploy/audit + a GUI view
Host insight API 1.31 Search, packages, monitor, Zero Trust: SSH only Read-only in the panel; installs stay CLI-root
MCP 46 tools 68 tools, one tools/list page

One line stands between
you and all of it.

Run the updater and Cipi rebuilds vhosts, pools, Deployer templates and app metadata in place — without touching your code or your data.

  • Everything new is opt-in — Octane, Horizon, Reverb, PostgreSQL, snapshots, health checks, backup profiles, 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.
  • Your PHP-FPM apps keep running exactly as they are, next to any new Octane neighbours.
  • Fresh servers get all of it out of the box with the usual installer.
upgrade
$ cipi self-update # On a fresh Ubuntu 24.04 or 26.04 VPS:
$ wget -O - https://cipi.sh/setup.sh | bash