forgelab-me / ci4-updater
Self-update system for CodeIgniter 4 apps: an admin panel that checks a remote update server for new releases, downloads, diffs, backs up, and applies them, with automatic DB migrations. No SSH/git pull required.
Requires
- php: ^8.2
- ext-zip: *
- codeigniter4/framework: ^4.4
Requires (Dev)
- phpunit/phpunit: ^10.5 || ^11.0
Suggests
- codeigniter4/shield: To protect the admin routes with group/permission-based authorization if you don't already have an auth system in place — see the Security section in the README.
README
A drop-in self-update system for CodeIgniter 4 apps: an admin panel that checks a remote update server (or GitHub releases) for new versions, downloads the release ZIP, diffs it against the live install (SHA-256 manifest), backs up changed files, applies the update, and runs pending DB migrations — all from the browser, no SSH/git pull required.
Every update leaves a backup the panel restores in one click, and releases can be signed so a compromised update server can't publish code to your apps.
Current version, PHP/CI/DB info, migration status |
A new release was found |
File-level diff, before anything is written |
Applied, with the DB migration run automatically |
Requirements
PHP 8.2+ · ext-zip · CodeIgniter 4.4+
Install
composer require forgelab-me/ci4-updater php spark updater:setup
updater:setup is a one-time step per app. It publishes an editable
app/Config/Updater.php and adds service('updater')->routes($routes); to
app/Config/Routes.php. Re-running it is safe: existing files are only
replaced after confirmation (or with -f), and the routes line is added once.
The panel itself is rendered from the package, so its improvements arrive with
composer update; point $layout at your admin layout and set $appName.
Pass --views if you'd rather own the markup.
Then, at minimum:
- Set
VERSION,DATEandUSER_AGENTinapp/Config/Updater.php. - Set
$layoutto your admin layout and$appNamein the same file. - Make sure the route filter really restricts access — read Security first.
- Point
update_server_urlat a feed — see Update server.
Full details: Configuration.
Security
These routes can overwrite any file under app//public/ and run DB
migrations. Treat them as deploy access, not as an ordinary admin page: the
filter you pass to routes() is the entire boundary, so gate it on an
admin-only group or permission rather than "is logged in", and serve
update_server_url over HTTPS only — everything it returns gets written over
your application files.
The manifest's SHA-256 check catches a corrupted download, not a
malicious server — it comes from that same server. To close that gap, sign
your releases: set Config\Updater::$publicKeys and unsigned releases are
refused from then on. See Signing releases and
Security.
How it works
- Before cutting a release you run
php spark update:manifest. It hashes every file inSCAN_DIRS(SHA-256), writesmanifest.json— recording which directories the release covers — and bundles arelease_X.Y.Z_*.zipwith the manifest embedded. - You publish that ZIP and a
latest.jsondescribing it —ci4-update-serveris a ready-made server for this, or use GitHub Releases. - In the app,
/admin/updateschecks the feed, downloads and diffs the release, and applies it on confirmation — backing up every changed file towritable/backups/and running pending migrations. - If it goes wrong, the same panel restores that backup: files go back as
they were and files the update added are removed. Older backups are pruned
automatically (
$keepBackups, five by default). A restore reverts code and never the database — the panel flags backups whose update shipped migrations.
A release covers app/ and public/ by default and says so in its manifest,
so an app only ever touches what a release actually declares. Dependencies can
be shipped too — see
Shipping vendor/.
Step by step: Releasing an update.
Documentation
- Configuration — config reference, routes, custom settings storage, permissions
- Update server — the
latest.jsoncontract, your own server or GitHub Releases - Security — trust model, filters, recovery
- Signing releases — optional signature verification, off by default
- Releasing an update — release workflow and the full update pipeline
Contributing
Issues and PRs are welcome.
composer install
composer test
composer validate --strict
Keep changes focused, add or update tests for behavior changes, and note anything user-facing in CHANGELOG.md.
License
MIT — see LICENSE.



