mirror of
https://github.com/Vateron-Media/XC_VM.git
synced 2026-10-04 04:02:30 +02:00
Make 'beta' the canonical update_channel value across the settings UI, GitHubReleases (prerelease filter + cache-file suffix + setChannel), the binary/fanout update commands, and the module channel mapping. 'unstable' is kept as a legacy alias so nothing breaks mid-upgrade: GitHubReleases::normalizeChannel() maps it to 'beta', and the binary commands still accept it. Migration 011 rewrites existing settings.update_channel 'unstable' -> 'beta', and the settings dropdown normalizes a stale 'unstable' to show Beta selected before the migration runs. Docs (en) updated.
198 lines
6.4 KiB
Markdown
198 lines
6.4 KiB
Markdown
# 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](../administration/server-update.md).
|
||
|
||
---
|
||
|
||
## 1. Update Initiation
|
||
|
||
The process begins when the administrator clicks the **"Update"** button in the web interface.
|
||
|
||
- A signal named `update` is inserted into the `signals` table in the database.
|
||
- This signal acts as a **trigger** for the entire update procedure.
|
||
|
||
---
|
||
|
||
## 2. CRON Trigger
|
||
|
||
Every **minute**, the following CRON job runs:
|
||
|
||
```bash
|
||
/home/xc_vm/console.php cron:root_signals
|
||
```
|
||
|
||
The `root_signals` cron job checks for new signals.
|
||
When it detects an `update` signal, it launches:
|
||
|
||
```bash
|
||
/home/xc_vm/console.php update update
|
||
```
|
||
|
||
---
|
||
|
||
## 3. Update Management (PHP Layer)
|
||
|
||
Core logic resides in the `UpdateCommand` class:
|
||
|
||
```text
|
||
src/Cli/Commands/UpdateCommand.php
|
||
```
|
||
|
||
At this stage the following actions are performed:
|
||
|
||
1. Detect the **current panel type** (`MAIN` or `LB`).
|
||
2. Fetch update metadata from **GitHub**:
|
||
- Direct link to the update archive.
|
||
- SHA checksum for integrity verification.
|
||
3. Download the archive to a temporary directory.
|
||
4. Verify the downloaded file matches the expected hash.
|
||
5. Hand over control to the system-level updater (Python):
|
||
|
||
```bash
|
||
sudo /usr/bin/python3 /home/xc_vm/update "/home/xc_vm/tmp/.update.tar.gz" "HASH" > /dev/null 2>&1 &
|
||
```
|
||
|
||
> 💡 After the Python updater finishes, it calls `console.php update post-update` which triggers [database migrations](../guides/database-migrations.md) and post-update cleanup.
|
||
|
||
---
|
||
|
||
## 4. System-Level Update (Python Layer)
|
||
|
||
Control is transferred to the Python script:
|
||
|
||
```text
|
||
/home/xc_vm/update
|
||
```
|
||
|
||
It performs privileged system operations:
|
||
|
||
1. **Re-verify** the archive checksum.
|
||
2. **Stop the panel** to prevent conflicts during update.
|
||
3. **Extract** the archive into a temporary directory:
|
||
|
||
```bash
|
||
/tmp/xc_vm_update_*/
|
||
```
|
||
|
||
4. **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`
|
||
|
||
5. **Copy remaining files** over the live installation:
|
||
|
||
```bash
|
||
cp -a /tmp/xc_vm_update_*/. /home/xc_vm/
|
||
```
|
||
|
||
6. **Fix ownership**:
|
||
|
||
```bash
|
||
chown -R xc_vm:xc_vm /home/xc_vm/
|
||
```
|
||
|
||
7. Run post-update tasks:
|
||
|
||
```bash
|
||
/home/xc_vm/console.php update post-update
|
||
```
|
||
|
||
8. **Restart** the panel in normal operating mode.
|
||
9. **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`:
|
||
|
||
1. If **LB auto-update** is enabled and the main node (`MAIN`) was updated → create `update` signals for all Load Balancers.
|
||
2. Update the **panel version** in the database.
|
||
3. Remove obsolete files.
|
||
4. Re-apply correct permissions:
|
||
|
||
```bash
|
||
chown -R xc_vm:xc_vm /home/xc_vm/
|
||
```
|
||
|
||
5. Reload systemd daemons:
|
||
|
||
```bash
|
||
sudo systemctl daemon-reload
|
||
```
|
||
|
||
6. Verify panel status:
|
||
|
||
```bash
|
||
sudo /home/xc_vm/console.php status
|
||
```
|
||
|
||
7. Mark the update process as complete.
|
||
|
||
---
|
||
|
||
## 6. Full Workflow Diagram
|
||
|
||
```text
|
||
[ 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.
|
||
|
||
1. **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 the `rollback_versions` API action (`GitHubReleases::getPreviousVersions()`). Choosing a version inserts a signal — `{"action":"rollback","version":"X.Y.Z"}` — for that server.
|
||
|
||
2. **CRON trigger.** `cron:root_signals` handles the `rollback` signal by launching:
|
||
|
||
```bash
|
||
/home/xc_vm/console.php update rollback X.Y.Z
|
||
```
|
||
|
||
3. **PHP layer (`UpdateCommand`, `rollback` case).**
|
||
- 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`).
|
||
|
||
4. **System + completion.** Identical to an update: the Python script stops the panel, replaces the tree (preserving binaries/config/data), and `post-update` sets 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, `beta` 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.
|
||
|
||
---
|