This updater provides a simple, production‑ready way to update your PHP app from GitHub Releases. It creates a ZIP backup, downloads the latest release asset, extracts it to a temp directory, copies files over your app (skipping the updater and backups dir), and updates version.json.
- Author: Fattain Naime
- GitHub: https://github.com/fattain-naime/automatic-update-via-github
- License: GPLv3 or later
- Version: 1.0.0
- PHP 7.4+ (PHP 8.x recommended)
- Extensions:
curl,zip - Write permissions for:
- The application root (to copy files)
- The backup directory (defaults to
backups/next toupdate.php) - Log file (defaults to
update.lognext toupdate.php)
- A GitHub repository with Releases and a downloadable ZIP asset
- Optional: GitHub token (recommended in production for higher API limits/private assets)
update.php— The updater UI and logicversion.json— Stores current version, e.g.{ "version": "v1.2.3" }
- Copy
update.phpandversion.jsoninto your app (ideally in an admin‑only area). - Open
update.phpand set:GITHUB_REPOto your repo inowner/repoformat.GITHUB_TOKENto your PAT (optional but recommended).- Optionally change
CURRENT_VERSION_JSONandBACKUP_DIRpaths.
- Ensure the web user (Apache/IIS/PHP‑FPM) can write to your app directory and backup directory.
- Visit
update.phpwhile logged in to your app’s admin; click “Update Now”.
By default, only logged‑in users can access the updater UI.
- Constants at the top of
update.php:ACCESS_REQUIRE_LOGIN(default:true)ACCESS_REQUIRE_ADMIN(default:false)HOME_URL(default:..) — where unauthenticated/unauthorized users are redirected
If your app distinguishes admins, set ACCESS_REQUIRE_ADMIN to true.
The default guard checks typical session keys:
$_SESSION['user_id']or$_SESSION['logged_in']or$_SESSION['user']$_SESSION['is_admin']or arolevalue equal toadmin/administrator
When access is denied (not logged in or not admin when required), the script redirects to HOME_URL with a 302.
Customize the guard to match your app’s session/role model. For example:
// Replace the guard with your own app’s checks
if (!myAppIsLoggedIn() || !myAppIsAdmin()) {
header('Location: ..');
exit;
}Tip: You can also place update.php inside an existing admin route that already enforces authentication.
- Checks GitHub Releases API for the latest release.
- Selects the first ZIP asset (or falls back to the source zipball).
- Creates a ZIP backup of the current app into
backups/. - Downloads the release ZIP using cURL.
- Extracts to a temp folder and copies files into the app directory.
- Skips the updater script and the
backups/folder.
- Skips the updater script and the
- Writes the new version to
version.jsonand resets opcache. - Logs errors to
update.log(errors are not displayed to users in production).
Version comparison uses semantic comparison with optional v/V prefix stripping (e.g., v1.2.3). The updater won’t downgrade if the remote tag is older.
GITHUB_REPO: GitHub repo inowner/repoformat.GITHUB_TOKEN: Personal Access Token string. For public repos, no scopes are required; for private releases, add appropriate scopes.CURRENT_VERSION_JSON: Path to the version JSON file to update.BACKUP_DIR: Directory for ZIP backups.ACCESS_REQUIRE_LOGIN: Require authenticated user to access the updater page.ACCESS_REQUIRE_ADMIN: Require admin role in addition to login.
- Keep
update.phpin an authenticated admin area. - Ensure backups and logs are not web‑accessible (or use server rules to deny direct access to
backups/andupdate.log). - Use a GitHub token in production to avoid rate limits and to support private assets.
- Only allow downloads from GitHub hosts (enforced by the script).
- “Could not create backup” — check write permissions and that the
zipextension is enabled. - “Download failed” — verify network access, token (if needed), and that the asset URL is valid.
- “ZIP extraction failed” — ensure
zipextension is enabled and disk has space. - “Up to date” but you expect an update — verify your tags are semantic and prefixed consistently (e.g.,
v1.2.3).
If your app doesn’t already set login session flags, a very simple approach is:
// During login in your app
$_SESSION['user_id'] = $userId; // or any truthy value
$_SESSION['role'] = 'admin'; // optional, for admin‑only accessThen the updater’s default guard will allow access when logged in.
For questions or improvements, feel free to extend update.php — it’s a single self‑contained file.