> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/pterodactyl/panel/llms.txt
> Use this file to discover all available pages before exploring further.

# Database Migrations

> Managing database migrations in Pterodactyl Panel

Pterodactyl uses Laravel's migration system to manage database schema changes. This guide covers running, creating, and troubleshooting migrations.

## What are Migrations?

Migrations are version control for your database schema. They allow you to:

* Define database structure changes in PHP code
* Roll back changes if needed
* Share schema changes across environments
* Track database version history

## Running Migrations

### Initial Installation

During first-time setup, run all migrations:

```bash theme={null}
php artisan migrate --seed --force
```

**Flags**:

* `--seed`: Run database seeders after migrations
* `--force`: Required in production (bypasses confirmation)

### Updating Panel

When updating Pterodactyl, run migrations to apply schema changes:

```bash theme={null}
cd /var/www/pterodactyl
php artisan down

# Update code (git pull, composer install, etc.)

php artisan migrate --force
php artisan view:clear
php artisan config:clear
php artisan up
```

### Auto-Upgrade (v1.3.0+)

Pterodactyl v1.3.0+ includes self-upgrade functionality:

```bash theme={null}
php artisan p:upgrade
```

This automatically:

1. Backs up the current installation
2. Downloads the latest release
3. Runs migrations with `--force` and `--seed`
4. Clears caches

## Migration Status

Check which migrations have been run:

```bash theme={null}
php artisan migrate:status
```

Output:

```
+------+----------------------------------------------------+-------+
| Ran? | Migration                                          | Batch |
+------+----------------------------------------------------+-------+
| Yes  | 2017_09_10_225941_CreateSchedulesTable            | 1     |
| Yes  | 2017_09_10_230309_CreateNewTasksTableForSchedules | 1     |
| Yes  | 2021_01_17_152623_add_generic_server_status_column| 1     |
| No   | 2024_07_13_091852_clear_unused_allocation_notes   |       |
+------+----------------------------------------------------+-------+
```

## Common Migrations

### Server State Management

**2021\_01\_17\_152623\_add\_generic\_server\_status\_column**

Added unified `status` column to replace multiple state columns:

```php theme={null}
Schema::table('servers', function (Blueprint $table) {
    $table->string('status')->default('installing')->after('suspended');
});
```

Possible statuses:

* `installing`
* `install_failed`
* `reinstall_failed`
* `suspended`
* `restoring_backup`
* `null` (normal operation)

### API Key Enhancements

**2023\_02\_23\_191004\_add\_expires\_at\_column\_to\_api\_keys\_table**

Added expiration support for API keys:

```php theme={null}
Schema::table('api_keys', function (Blueprint $table) {
    $table->timestamp('expires_at')->nullable()->after('last_used_at');
});
```

**2022\_06\_18\_112822\_track\_api\_key\_usage\_for\_activity\_events**

Links activity logs to API keys:

```php theme={null}
Schema::table('activity_logs', function (Blueprint $table) {
    $table->unsignedInteger('api_key_id')->nullable()->after('actor_id');
});
```

### Backup Features

**2021\_05\_03\_201016\_add\_support\_for\_locking\_a\_backup**

Added backup locking to prevent deletion:

```php theme={null}
Schema::table('backups', function (Blueprint $table) {
    $table->boolean('is_locked')->default(false);
});
```

**2020\_12\_26\_184914\_add\_upload\_id\_column\_to\_backups\_table**

Added support for S3 multipart uploads:

```php theme={null}
Schema::table('backups', function (Blueprint $table) {
    $table->text('upload_id')->nullable()->after('disk');
});
```

### Server Transfers

**2020\_04\_04\_131016\_add\_table\_server\_transfers**

Created table for tracking server transfers:

```php theme={null}
Schema::create('server_transfers', function (Blueprint $table) {
    $table->increments('id');
    $table->unsignedInteger('server_id');
    $table->boolean('successful')->nullable();
    $table->unsignedInteger('old_node');
    $table->unsignedInteger('new_node');
    $table->unsignedInteger('old_allocation');
    $table->unsignedInteger('new_allocation');
    $table->json('old_additional_allocations')->nullable();
    $table->json('new_additional_allocations')->nullable();
    $table->timestamps();
});
```

### Schedule Improvements

**2021\_01\_13\_013420\_add\_cron\_month**

Added month field to schedule cron:

```php theme={null}
Schema::table('schedules', function (Blueprint $table) {
    $table->string('cron_month', 191)->default('*')->after('cron_day_of_week');
});
```

**2021\_05\_01\_092523\_add\_only\_run\_when\_server\_online\_option\_to\_schedules**

Added conditional execution:

```php theme={null}
Schema::table('schedules', function (Blueprint $table) {
    $table->boolean('only_when_online')->default(false);
});
```

## Creating Custom Migrations

<Warning>
  Only create custom migrations if you're developing Panel modifications. Do not modify core migrations.
</Warning>

### Generate Migration

```bash theme={null}
php artisan make:migration add_custom_field_to_servers_table
```

### Migration Structure

```php theme={null}
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::table('servers', function (Blueprint $table) {
            $table->string('custom_field')->nullable();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::table('servers', function (Blueprint $table) {
            $table->dropColumn('custom_field');
        });
    }
};
```

### Common Schema Operations

**Add Column**:

```php theme={null}
$table->string('column_name')->nullable();
$table->integer('count')->default(0);
$table->text('description')->after('name');
```

**Modify Column**:

```php theme={null}
$table->string('name', 500)->change();
$table->integer('value')->unsigned()->change();
```

**Drop Column**:

```php theme={null}
$table->dropColumn('column_name');
$table->dropColumn(['col1', 'col2']);
```

**Add Index**:

```php theme={null}
$table->index('email');
$table->unique('username');
$table->foreign('user_id')->references('id')->on('users');
```

**Drop Index**:

```php theme={null}
$table->dropIndex('users_email_index');
$table->dropUnique('users_username_unique');
$table->dropForeign('servers_user_id_foreign');
```

## Rollback Migrations

<Warning>
  Rolling back migrations can cause data loss. Always backup your database first.
</Warning>

### Rollback Last Batch

```bash theme={null}
php artisan migrate:rollback
```

### Rollback Specific Steps

```bash theme={null}
# Rollback last 3 migration batches
php artisan migrate:rollback --step=3
```

### Rollback All

```bash theme={null}
php artisan migrate:reset
```

### Rollback and Re-run

```bash theme={null}
php artisan migrate:refresh

# With seeding
php artisan migrate:refresh --seed
```

## Migration Best Practices

### 1. Always Backup First

```bash theme={null}
mysqldump -u root -p panel > backup_$(date +%Y%m%d_%H%M%S).sql
```

### 2. Test in Development

Never run untested migrations in production:

```bash theme={null}
# In development
php artisan migrate
php artisan migrate:rollback
php artisan migrate
```

### 3. Use Transactions

For complex migrations:

```php theme={null}
DB::transaction(function () {
    // Migration operations
});
```

### 4. Handle Data Migration

When changing column types, migrate existing data:

```php theme={null}
public function up(): void
{
    // Add new column
    Schema::table('servers', function (Blueprint $table) {
        $table->string('status_new')->nullable();
    });
    
    // Migrate data
    DB::table('servers')->where('installing', true)
        ->update(['status_new' => 'installing']);
    
    // Drop old column
    Schema::table('servers', function (Blueprint $table) {
        $table->dropColumn('installing');
    });
    
    // Rename new column
    Schema::table('servers', function (Blueprint $table) {
        $table->renameColumn('status_new', 'status');
    });
}
```

## Troubleshooting

### "Nothing to migrate"

All migrations are already run. Check status:

```bash theme={null}
php artisan migrate:status
```

### "Syntax error or access violation"

Database user lacks required permissions:

```sql theme={null}
GRANT ALL PRIVILEGES ON panel.* TO 'pterodactyl'@'localhost';
FLUSH PRIVILEGES;
```

### "SQLSTATE\[42S01]: Base table or view already exists"

Migration already partially applied. Options:

1. Rollback and retry
2. Manually mark as run:

```bash theme={null}
php artisan migrate:rollback --step=1
php artisan migrate
```

### "Class not found" errors

Clear autoload cache:

```bash theme={null}
composer dump-autoload
php artisan config:clear
```

### "Migration table not found"

Database not initialized. Run:

```bash theme={null}
php artisan migrate:install
php artisan migrate
```

### MySQL 8 Compatibility

If encountering errors with MySQL 8:

```sql theme={null}
-- Use native password authentication
ALTER USER 'pterodactyl'@'localhost' 
    IDENTIFIED WITH mysql_native_password BY 'password';
```

### MariaDB Compatibility

Some migrations may fail on MariaDB \< 10.5. Upgrade to 10.5+ or use MySQL 8.

## Database Maintenance

### Optimize Tables

```bash theme={null}
php artisan db:optimize
```

### Repair Tables

```sql theme={null}
REPAIR TABLE servers;
REPAIR TABLE allocations;
```

### Check Table Status

```sql theme={null}
CHECK TABLE servers;
CHECK TABLE api_keys;
```

## Migration History

Key migration milestones:

* **v1.11.0**: Added activity logging tables
* **v1.8.0**: Changed egg format to PTDL\_v2
* **v1.6.0**: Added server transfer support
* **v1.3.0**: Unified server status column
* **v1.0.0**: Complete database restructure
* **v0.7.x**: Legacy structure (pre-1.0)

## Further Reading

* [Laravel Migrations Documentation](https://laravel.com/docs/migrations)
* [Pterodactyl Changelog](https://github.com/pterodactyl/panel/blob/1.0-develop/CHANGELOG.md)
* [Database Schema Reference](https://github.com/pterodactyl/panel/tree/develop/database/migrations)
