su - xc_vm -c '/home/xc_vm/bin/php/bin/php /home/xc_vm/console.php tools images'
# Remove duplicate VOD entries (xc_vm)
su - xc_vm -c '/home/xc_vm/bin/php/bin/php /home/xc_vm/console.php tools duplicates'
# Clean orphaned bouquet references (xc_vm)
su - xc_vm -c '/home/xc_vm/bin/php/bin/php /home/xc_vm/console.php tools bouquets'
```
> ⚠️ **Warning:** `duplicates` permanently deletes streams and all associated data (logs, stats, episodes, recordings). Always back up before running.
> ⚠️ **Warning:** `database --confirm` erases the entire database and replaces it with a blank schema. This is irreversible.
> 💡 **Tip:** After running `rescue`, always delete the code through the admin panel or by running `tools access` once you have regained access.
> 💡 **Tip:** After running `user`, change the password immediately and delete the rescue user when done.
---
## 🗃 Database Migrations
XC_VM uses a file-based migration system to manage database schema changes between versions. Migrations are executed automatically during updates and system status checks.
### How It Works
1. Migration files are stored as `.sql` files in:
```
/home/xc_vm/migrations/
```
2. Each file is named with a sequential number prefix:
```
001_drop_watch_folders_plex_token.sql
002_panel_logs_add_file_env.sql
003_drop_settings_segment_type.sql
```
3. Applied migrations are tracked in the `migrations` database table. Each migration runs **exactly once** — if a migration has already been applied, it is skipped.
4. Migrations are executed automatically by:
- `console.php update post-update` — after a panel update
- `console.php status` — during system status check (MAIN server only)
### Migration Execution Flow
```text
[ MigrationRunner::run() ]
│
▼
[ CREATE TABLE IF NOT EXISTS `migrations` ]
│
▼
[ Read all *.sql files from migrations/ ]
│
▼
[ For each file not in `migrations` table: ]
├── Execute SQL statements
├── Record in `migrations` table
└── Output [OK] or [WARN]
```
---
## 📝 Creating a New Migration
When you need to modify the database schema (add columns, create tables, insert data, etc.), create a new SQL migration file.
### Step 1. Choose a File Name
Use the next sequential number and a descriptive name:
```
NNN_short_description.sql
```
**Format rules:**
- Number prefix: 3 digits, zero-padded (e.g., `006`, `007`)
- Separator: underscore `_`
- Name: lowercase, underscores, describing what the migration does
- Extension: `.sql`
**Examples:**
```
006_add_user_timezone.sql
007_create_audit_log_table.sql
008_insert_default_codec_settings.sql
```
### Step 2. Write the SQL
Place raw SQL statements in the file. Multiple statements are separated by `;`.
**Rules for migration SQL:**
1. **Use `IF EXISTS` / `IF NOT EXISTS`** to make migrations idempotent:
```sql
-- Adding a column (safe)
ALTER TABLE `settings` ADD COLUMN IF NOT EXISTS `timezone` VARCHAR(64) DEFAULT 'UTC';
-- Dropping a column (safe)
ALTER TABLE `settings` DROP COLUMN IF EXISTS `old_column`;
-- Creating a table (safe)
CREATE TABLE IF NOT EXISTS `audit_log` (
`id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`action` VARCHAR(255) NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```
2. **Use conditional `INSERT`** to avoid duplicates:
```sql
INSERT INTO `streams_arguments` (argument_key, argument_name, argument_cmd)
SELECT 'my_key', 'My Argument', '-my_flag %s'
FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `streams_arguments` WHERE argument_key = 'my_key');
```
3. **Do not mix DDL and DML** that depend on each other in the same file. If you need to add a column and then populate it — use two migration files.
4. **Comments** are supported with `--` prefix (they are skipped during execution).
### Step 3. Place the File
Copy the migration file to:
```
/home/xc_vm/migrations/
```
> 💡 In the source repository, this is `src/migrations/`.
### Step 4. Test
Run the status command to apply pending migrations:
```bash
sudo /home/xc_vm/bin/php/bin/php /home/xc_vm/console.php status first-run
```
Expected output:
```
Migrations
------------------------------
[OK] 006_add_user_timezone.sql
```
If a statement fails, the migration will still be recorded but show `[WARN]` — review the SQL and fix any issues.
---
## ⚙️ Common CLI Operations
### Status Check
```bash
sudo /home/xc_vm/bin/php/bin/php /home/xc_vm/console.php status
```
Checks if XC_VM is running, connects to the database, runs pending migrations, fixes permissions, and validates nginx configuration. Required after installation or recovery.
With `first-run` argument, skips the running check — used for initial setup:
```bash
sudo /home/xc_vm/bin/php/bin/php /home/xc_vm/console.php status first-run
```
### Service Management
```bash
sudo /home/xc_vm/bin/php/bin/php /home/xc_vm/console.php service start|stop|restart|reload