Update Mechanism in XC_VM¶
The XC_VM update system is implemented as a multi-layered process, from the web interface to system-level scripts. This approach ensures reliability, automation, and data integrity during panel updates.
📋 For a step-by-step guide with screenshots, see Updating a Server.
1. Update Initiation¶
The process begins when the administrator clicks the "Update" button in the web interface.
- A signal named
updateis inserted into thesignalstable in the database. - This signal acts as a trigger for the entire update procedure.
2. CRON Trigger¶
Every minute, the following CRON job runs:
The root_signals cron job checks for new signals.
When it detects an update signal, it launches:
3. Update Management (PHP Layer)¶
Core logic resides in the UpdateCommand class:
At this stage the following actions are performed:
- Detect the current panel type (
MAINorLB). - Fetch update metadata from GitHub:
- Direct link to the update archive.
- SHA checksum for integrity verification.
- Download the archive to a temporary directory.
- Verify the downloaded file matches the expected hash.
- Hand over control to the system-level updater (Python):
💡 After the Python updater finishes, it calls
console.php update post-updatewhich triggers database migrations and post-update cleanup.
4. System-Level Update (Python Layer)¶
Control is transferred to the Python script:
It performs privileged system operations:
- Re-verify the archive checksum.
- Stop the panel to prevent conflicts during update.
- Extract the archive into a temporary directory:
- Remove excluded directories from the temp copy — binaries, configs, and user data that must not be overwritten:
bin/ffmpeg_bin, bin/nginx, bin/nginx_rtmp, bin/php, bin/redis, bin/install, bin/maxmind, bin/certbot, content, backups, tmp, config, signals
- Copy remaining files over the live installation:
- Fix ownership:
- Run post-update tasks:
- Restart the panel in normal operating mode.
- Cleanup the temporary directory and delete the archive.
ℹ️ The same archive is used for both installation and update. Filtering happens on the server at update time — the exclude list is defined directly in
src/update.
5. Update Completion¶
Final steps are executed in the post-update phase of UpdateCommand:
- If LB auto-update is enabled and the main node (
MAIN) was updated → createupdatesignals for all Load Balancers. - Update the panel version in the database.
- Remove obsolete files.
- Re-apply correct permissions:
- Reload systemd daemons:
- Verify panel status:
- Mark the update process as complete.
6. Full Workflow Diagram¶
[ Web Interface ]
│
▼
[ DB: "update" signal ]
│
▼
[ CRON → console.php cron:root_signals ]
│
▼
[ UpdateCommand (PHP): download + verify hash ]
│
▼
[ update (Python): extract to /tmp → remove excluded → copy over ]
│
▼
[ post-update → UpdateCommand ]
│
▼
[ Finalize, restart daemons, update version in DB ]
Rollback (Downgrade)¶
A server can also be rolled back to an earlier release. This mirrors the update flow above but targets a chosen version instead of the latest — the same signal → CRON → PHP → Python pipeline and the same src/update applier are reused. Rollback is per-server, so MAIN and each LB can be downgraded independently.
-
Initiation. In Servers → Manage Servers, the per-server actions menu has a Rollback Version item. It opens a dialog listing earlier releases (pre-releases tagged
(beta)), fetched via therollback_versionsAPI action (GitHubReleases::getPreviousVersions()). Choosing a version inserts a signal —{"action":"rollback","version":"X.Y.Z"}— for that server. -
CRON trigger.
cron:root_signalshandles therollbacksignal by launching:
- PHP layer (
UpdateCommand,rollbackcase). - Validate the target (
X.Y.Z, strictly older than the current version). - On MAIN only: take an automatic database backup to
backups/pre_rollback_<from>_to_<to>_<timestamp>.sql, aborting if it fails. LB nodes have no database and skip this. - Resolve the exact version's archive via
GitHubReleases::getVersionFile()(MAIN →xc_vm.tar.gz, LB →loadbalancer.tar.gz), download it, and verify the MD5. -
Hand over to the same Python updater (
src/update). -
System + completion. Identical to an update: the Python script stops the panel, replaces the tree (preserving binaries/config/data), and
post-updatesets the version in the database to the rolled-back release and restarts the panel.
The version list is channel-aware: the stable channel offers only stable releases, unstable also offers (beta) pre-releases.
⚠️ A downgrade does not undo database migrations (they are forward-only). The schema is kept backward-compatible, and the automatic MAIN backup is the recovery path. The Python applier copies over the tree (
cp -a) without deleting files, so files added by a newer release remain until a subsequent update.
Key Features¶
- Double integrity check (both PHP and Python layers verify the hash).
- Automatic propagation of updates from MAIN to all Load Balancers.
- Cleanup of deprecated files and permission normalization.
- Safe panel restart after installation.
- Flexibility & autonomy thanks to CRON + signal-based triggering.