mirror of
https://github.com/tiennm99/coolify.git
synced 2026-08-06 18:22:31 +00:00
Merge remote-tracking branch 'origin/next' into jean/port-exposes-improvement
This commit is contained in:
+31
@@ -0,0 +1,31 @@
|
||||
<?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('application_settings', function (Blueprint $table) {
|
||||
$table->integer('stop_grace_period')
|
||||
->nullable()
|
||||
->after('use_build_secrets')
|
||||
->comment('Seconds to wait for graceful shutdown before forcing container stop (1-3600). Null uses default of 30 seconds.');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('application_settings', function (Blueprint $table) {
|
||||
$table->dropColumn('stop_grace_period');
|
||||
});
|
||||
}
|
||||
};
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
DB::transaction(function () {
|
||||
if (DB::getDriverName() !== 'sqlite') {
|
||||
DB::statement('ALTER TABLE shared_environment_variables DROP CONSTRAINT IF EXISTS shared_environment_variables_type_check');
|
||||
DB::statement("ALTER TABLE shared_environment_variables ADD CONSTRAINT shared_environment_variables_type_check CHECK (type IN ('team', 'project', 'environment', 'server'))");
|
||||
}
|
||||
Schema::table('shared_environment_variables', function (Blueprint $table) {
|
||||
$table->foreignId('server_id')->nullable()->constrained()->onDelete('cascade');
|
||||
// NULL != NULL in PostgreSQL unique indexes, so this only enforces uniqueness
|
||||
// for server-scoped rows (where server_id is non-null). Other scopes are covered
|
||||
// by existing unique constraints on ['key', 'project_id', 'team_id'] and ['key', 'environment_id', 'team_id'].
|
||||
$table->unique(['key', 'server_id', 'team_id']);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
DB::transaction(function () {
|
||||
Schema::table('shared_environment_variables', function (Blueprint $table) {
|
||||
$table->dropUnique(['key', 'server_id', 'team_id']);
|
||||
$table->dropForeign(['server_id']);
|
||||
$table->dropColumn('server_id');
|
||||
});
|
||||
if (DB::getDriverName() !== 'sqlite') {
|
||||
DB::statement('ALTER TABLE shared_environment_variables DROP CONSTRAINT IF EXISTS shared_environment_variables_type_check');
|
||||
DB::statement("ALTER TABLE shared_environment_variables ADD CONSTRAINT shared_environment_variables_type_check CHECK (type IN ('team', 'project', 'environment'))");
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Server;
|
||||
use App\Models\SharedEnvironmentVariable;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Server::query()->whereHas('team')->chunk(100, function ($servers) {
|
||||
foreach ($servers as $server) {
|
||||
$existingKeys = SharedEnvironmentVariable::where('type', 'server')
|
||||
->where('server_id', $server->id)
|
||||
->whereIn('key', ['COOLIFY_SERVER_UUID', 'COOLIFY_SERVER_NAME'])
|
||||
->pluck('key')
|
||||
->toArray();
|
||||
|
||||
if (! in_array('COOLIFY_SERVER_UUID', $existingKeys)) {
|
||||
SharedEnvironmentVariable::create([
|
||||
'key' => 'COOLIFY_SERVER_UUID',
|
||||
'value' => $server->uuid,
|
||||
'type' => 'server',
|
||||
'server_id' => $server->id,
|
||||
'team_id' => $server->team_id,
|
||||
'is_literal' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
if (! in_array('COOLIFY_SERVER_NAME', $existingKeys)) {
|
||||
SharedEnvironmentVariable::create([
|
||||
'key' => 'COOLIFY_SERVER_NAME',
|
||||
'value' => $server->name,
|
||||
'type' => 'server',
|
||||
'server_id' => $server->id,
|
||||
'team_id' => $server->team_id,
|
||||
'is_literal' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
SharedEnvironmentVariable::where('type', 'server')
|
||||
->whereIn('key', ['COOLIFY_SERVER_UUID', 'COOLIFY_SERVER_NAME'])
|
||||
->delete();
|
||||
}
|
||||
};
|
||||
+6
-5
@@ -10,14 +10,15 @@ return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('local_persistent_volumes', function (Blueprint $table) {
|
||||
$table->string('uuid')->nullable()->after('id');
|
||||
});
|
||||
if (! Schema::hasColumn('local_persistent_volumes', 'uuid')) {
|
||||
Schema::table('local_persistent_volumes', function (Blueprint $table) {
|
||||
$table->string('uuid')->nullable()->after('id');
|
||||
});
|
||||
}
|
||||
|
||||
DB::table('local_persistent_volumes')
|
||||
->whereNull('uuid')
|
||||
->orderBy('id')
|
||||
->chunk(1000, function ($volumes) {
|
||||
->chunkById(1000, function ($volumes) {
|
||||
foreach ($volumes as $volume) {
|
||||
DB::table('local_persistent_volumes')
|
||||
->where('id', $volume->id)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class EncryptExistingClickhouseAdminPasswords extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
try {
|
||||
DB::table('standalone_clickhouses')->chunkById(100, function ($clickhouses) {
|
||||
foreach ($clickhouses as $clickhouse) {
|
||||
$password = $clickhouse->clickhouse_admin_password;
|
||||
|
||||
if (empty($password)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if already encrypted (idempotent)
|
||||
try {
|
||||
Crypt::decryptString($password);
|
||||
|
||||
continue;
|
||||
} catch (Exception) {
|
||||
// Not encrypted yet — encrypt it
|
||||
}
|
||||
|
||||
DB::table('standalone_clickhouses')
|
||||
->where('id', $clickhouse->id)
|
||||
->update(['clickhouse_admin_password' => Crypt::encryptString($password)]);
|
||||
}
|
||||
});
|
||||
} catch (Exception $e) {
|
||||
echo 'Encrypting ClickHouse admin passwords failed.';
|
||||
echo $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('application_previews', function (Blueprint $table) {
|
||||
$table->string('docker_registry_image_tag')->nullable()->after('docker_compose_domains');
|
||||
});
|
||||
|
||||
Schema::table('application_deployment_queues', function (Blueprint $table) {
|
||||
$table->string('docker_registry_image_tag')->nullable()->after('pull_request_id');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('application_previews', function (Blueprint $table) {
|
||||
$table->dropColumn('docker_registry_image_tag');
|
||||
});
|
||||
|
||||
Schema::table('application_deployment_queues', function (Blueprint $table) {
|
||||
$table->dropColumn('docker_registry_image_tag');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class BackfillAndEncryptWebhookSecrets extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$columns = [
|
||||
'manual_webhook_secret_github',
|
||||
'manual_webhook_secret_gitlab',
|
||||
'manual_webhook_secret_bitbucket',
|
||||
'manual_webhook_secret_gitea',
|
||||
];
|
||||
|
||||
Schema::table('applications', function ($table) use ($columns) {
|
||||
foreach ($columns as $col) {
|
||||
$table->text($col)->nullable()->change();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
DB::table('applications')->chunkById(100, function ($apps) use ($columns) {
|
||||
foreach ($apps as $app) {
|
||||
$updates = [];
|
||||
foreach ($columns as $col) {
|
||||
$current = $app->{$col};
|
||||
|
||||
if (empty($current)) {
|
||||
$updates[$col] = Crypt::encryptString(Str::random(40));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
Crypt::decryptString($current);
|
||||
|
||||
continue;
|
||||
} catch (Exception) {
|
||||
// Not encrypted yet
|
||||
}
|
||||
|
||||
$updates[$col] = Crypt::encryptString($current);
|
||||
}
|
||||
if ($updates !== []) {
|
||||
DB::table('applications')->where('id', $app->id)->update($updates);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception $e) {
|
||||
echo 'Backfilling and encrypting webhook secrets failed.';
|
||||
echo $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
<?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('instance_settings', function (Blueprint $table) {
|
||||
$table->boolean('is_mcp_server_enabled')->default(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('instance_settings', function (Blueprint $table) {
|
||||
$table->dropColumn('is_mcp_server_enabled');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('server_settings', function (Blueprint $table) {
|
||||
$table->integer('connection_timeout')->default(10)->after('deployment_queue_limit');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('server_settings', function (Blueprint $table) {
|
||||
$table->dropColumn('connection_timeout');
|
||||
});
|
||||
}
|
||||
};
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('application_deployment_queues', function (Blueprint $table) {
|
||||
$table->string('configuration_hash')->nullable()->after('docker_registry_image_tag');
|
||||
$table->json('configuration_snapshot')->nullable()->after('configuration_hash');
|
||||
$table->json('configuration_diff')->nullable()->after('configuration_snapshot');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('application_deployment_queues', function (Blueprint $table) {
|
||||
$table->dropColumn([
|
||||
'configuration_hash',
|
||||
'configuration_snapshot',
|
||||
'configuration_diff',
|
||||
]);
|
||||
});
|
||||
}
|
||||
};
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?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('personal_access_tokens', function (Blueprint $table) {
|
||||
$table->timestamp('api_token_expiration_warning_sent_at')->nullable()->after('expires_at');
|
||||
$table->index(['expires_at', 'api_token_expiration_warning_sent_at'], 'personal_access_tokens_expiration_warning_index');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('personal_access_tokens', function (Blueprint $table) {
|
||||
$table->dropIndex('personal_access_tokens_expiration_warning_index');
|
||||
$table->dropColumn('api_token_expiration_warning_sent_at');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
DB::statement('CREATE INDEX IF NOT EXISTS swarm_dockers_server_id_index ON swarm_dockers (server_id)');
|
||||
DB::statement('CREATE INDEX IF NOT EXISTS services_server_id_index ON services (server_id)');
|
||||
DB::statement('CREATE INDEX IF NOT EXISTS application_previews_application_id_index ON application_previews (application_id)');
|
||||
DB::statement('CREATE INDEX IF NOT EXISTS service_applications_service_id_index ON service_applications (service_id)');
|
||||
DB::statement('CREATE INDEX IF NOT EXISTS service_databases_service_id_index ON service_databases (service_id)');
|
||||
DB::statement('CREATE INDEX IF NOT EXISTS servers_sentinel_updated_at_index ON servers (sentinel_updated_at)');
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
DB::statement('DROP INDEX IF EXISTS swarm_dockers_server_id_index');
|
||||
DB::statement('DROP INDEX IF EXISTS services_server_id_index');
|
||||
DB::statement('DROP INDEX IF EXISTS application_previews_application_id_index');
|
||||
DB::statement('DROP INDEX IF EXISTS service_applications_service_id_index');
|
||||
DB::statement('DROP INDEX IF EXISTS service_databases_service_id_index');
|
||||
DB::statement('DROP INDEX IF EXISTS servers_sentinel_updated_at_index');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
if (DB::connection()->getDriverName() !== 'pgsql') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fillfactor < 100 leaves free space per page so Postgres can do HOT
|
||||
// (Heap-Only Tuple) in-place updates instead of allocating a new tuple
|
||||
// elsewhere. Coolify's hot-update tables churn rows on every Sentinel
|
||||
// push / status change; without page-local headroom, non-HOT updates
|
||||
// accumulate dead tuples and bloat the heap (we've seen up to 50× on
|
||||
// cloud). Lower fillfactor on hot-update tables, default on the rest.
|
||||
DB::statement('ALTER TABLE applications SET (fillfactor = 70)');
|
||||
DB::statement('ALTER TABLE servers SET (fillfactor = 85)');
|
||||
DB::statement('ALTER TABLE services SET (fillfactor = 85)');
|
||||
DB::statement('ALTER TABLE service_applications SET (fillfactor = 85)');
|
||||
DB::statement('ALTER TABLE service_databases SET (fillfactor = 85)');
|
||||
DB::statement('ALTER TABLE standalone_postgresqls SET (fillfactor = 85)');
|
||||
DB::statement('ALTER TABLE standalone_redis SET (fillfactor = 85)');
|
||||
DB::statement('ALTER TABLE standalone_mongodbs SET (fillfactor = 85)');
|
||||
DB::statement('ALTER TABLE standalone_mysqls SET (fillfactor = 85)');
|
||||
DB::statement('ALTER TABLE standalone_mariadbs SET (fillfactor = 85)');
|
||||
DB::statement('ALTER TABLE standalone_keydbs SET (fillfactor = 85)');
|
||||
DB::statement('ALTER TABLE standalone_dragonflies SET (fillfactor = 85)');
|
||||
DB::statement('ALTER TABLE standalone_clickhouses SET (fillfactor = 85)');
|
||||
DB::statement('ALTER TABLE application_deployment_queues SET (fillfactor = 90)');
|
||||
|
||||
// Autovacuum default kicks in at 20% dead tuples — too lazy for our
|
||||
// churn rate. Trigger at 5% on the highest-write tables to keep heap
|
||||
// pages tidy and prevent visibility-map gaps that hurt scan plans.
|
||||
DB::statement('ALTER TABLE applications SET (autovacuum_vacuum_scale_factor = 0.05)');
|
||||
DB::statement('ALTER TABLE servers SET (autovacuum_vacuum_scale_factor = 0.05)');
|
||||
DB::statement('ALTER TABLE service_applications SET (autovacuum_vacuum_scale_factor = 0.05)');
|
||||
DB::statement('ALTER TABLE service_databases SET (autovacuum_vacuum_scale_factor = 0.05)');
|
||||
DB::statement('ALTER TABLE standalone_postgresqls SET (autovacuum_vacuum_scale_factor = 0.05)');
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
if (DB::connection()->getDriverName() !== 'pgsql') {
|
||||
return;
|
||||
}
|
||||
|
||||
DB::statement('ALTER TABLE applications RESET (fillfactor, autovacuum_vacuum_scale_factor)');
|
||||
DB::statement('ALTER TABLE servers RESET (fillfactor, autovacuum_vacuum_scale_factor)');
|
||||
DB::statement('ALTER TABLE services RESET (fillfactor)');
|
||||
DB::statement('ALTER TABLE service_applications RESET (fillfactor, autovacuum_vacuum_scale_factor)');
|
||||
DB::statement('ALTER TABLE service_databases RESET (fillfactor, autovacuum_vacuum_scale_factor)');
|
||||
DB::statement('ALTER TABLE standalone_postgresqls RESET (fillfactor, autovacuum_vacuum_scale_factor)');
|
||||
DB::statement('ALTER TABLE standalone_redis RESET (fillfactor)');
|
||||
DB::statement('ALTER TABLE standalone_mongodbs RESET (fillfactor)');
|
||||
DB::statement('ALTER TABLE standalone_mysqls RESET (fillfactor)');
|
||||
DB::statement('ALTER TABLE standalone_mariadbs RESET (fillfactor)');
|
||||
DB::statement('ALTER TABLE standalone_keydbs RESET (fillfactor)');
|
||||
DB::statement('ALTER TABLE standalone_dragonflies RESET (fillfactor)');
|
||||
DB::statement('ALTER TABLE standalone_clickhouses RESET (fillfactor)');
|
||||
DB::statement('ALTER TABLE application_deployment_queues RESET (fillfactor)');
|
||||
}
|
||||
};
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* The configuration snapshot/diff now store an encrypted blob (not valid
|
||||
* JSON), so the columns must hold arbitrary text instead of json.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
DB::statement('ALTER TABLE application_deployment_queues ALTER COLUMN configuration_snapshot TYPE text USING configuration_snapshot::text');
|
||||
DB::statement('ALTER TABLE application_deployment_queues ALTER COLUMN configuration_diff TYPE text USING configuration_diff::text');
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
DB::statement('ALTER TABLE application_deployment_queues ALTER COLUMN configuration_snapshot TYPE json USING configuration_snapshot::json');
|
||||
DB::statement('ALTER TABLE application_deployment_queues ALTER COLUMN configuration_diff TYPE json USING configuration_diff::json');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
private array $tables = [
|
||||
'standalone_postgresqls',
|
||||
'standalone_mysqls',
|
||||
'standalone_mariadbs',
|
||||
'standalone_redis',
|
||||
'standalone_clickhouses',
|
||||
'standalone_dragonflies',
|
||||
'standalone_keydbs',
|
||||
'standalone_mongodbs',
|
||||
];
|
||||
|
||||
public function up(): void
|
||||
{
|
||||
foreach ($this->tables as $table) {
|
||||
Schema::table($table, function (Blueprint $table) {
|
||||
$table->boolean('health_check_enabled')->default(true);
|
||||
$table->integer('health_check_interval')->default(15);
|
||||
$table->integer('health_check_timeout')->default(5);
|
||||
$table->integer('health_check_retries')->default(5);
|
||||
$table->integer('health_check_start_period')->default(5);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
foreach ($this->tables as $table) {
|
||||
Schema::table($table, function (Blueprint $table) {
|
||||
$table->dropColumn([
|
||||
'health_check_enabled',
|
||||
'health_check_interval',
|
||||
'health_check_timeout',
|
||||
'health_check_retries',
|
||||
'health_check_start_period',
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -31,5 +31,11 @@ class DatabaseSeeder extends Seeder
|
||||
CaSslCertSeeder::class,
|
||||
PersonalAccessTokenSeeder::class,
|
||||
]);
|
||||
|
||||
if (in_array(config('app.env'), ['local', 'development', 'dev'], true)) {
|
||||
$this->call([
|
||||
DevelopmentRailpackExamplesSeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,513 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Enums\ProxyStatus;
|
||||
use App\Enums\ProxyTypes;
|
||||
use App\Models\Application;
|
||||
use App\Models\Environment;
|
||||
use App\Models\GithubApp;
|
||||
use App\Models\PrivateKey;
|
||||
use App\Models\Project;
|
||||
use App\Models\Server;
|
||||
use App\Models\StandaloneDocker;
|
||||
use App\Models\Team;
|
||||
use Illuminate\Database\Seeder;
|
||||
use RuntimeException;
|
||||
|
||||
class DevelopmentRailpackExamplesSeeder extends Seeder
|
||||
{
|
||||
public const PROJECT_UUID = 'railpack-examples';
|
||||
|
||||
public const ENVIRONMENT_UUID = 'railpack-examples-production';
|
||||
|
||||
public const GIT_REPOSITORY = 'coollabsio/coolify-examples';
|
||||
|
||||
public const GIT_BRANCH = 'next';
|
||||
|
||||
public const REPOSITORY_PROJECT_ID = 603035348;
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
if (! $this->isDevelopmentEnvironment()) {
|
||||
$this->command?->warn('Skipping DevelopmentRailpackExamplesSeeder outside development mode.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->ensureDevelopmentPrerequisitesExist();
|
||||
$destination = StandaloneDocker::query()->find(0);
|
||||
|
||||
if (! $destination) {
|
||||
throw new RuntimeException('StandaloneDocker with id=0 is required before running DevelopmentRailpackExamplesSeeder.');
|
||||
}
|
||||
|
||||
$environment = $this->prepareEnvironment();
|
||||
|
||||
foreach (self::examples() as $example) {
|
||||
$this->upsertApplication($environment, $destination, $example);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
public static function examples(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'uuid' => 'railpack-simple-webserver',
|
||||
'name' => 'Railpack Simple Webserver Example',
|
||||
'base_directory' => '/node/simple-webserver',
|
||||
'ports_exposes' => '3000',
|
||||
'start_command' => 'npm run start',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-expressjs',
|
||||
'name' => 'Railpack Express.js Example',
|
||||
'base_directory' => '/node/expressjs',
|
||||
'ports_exposes' => '3000',
|
||||
'start_command' => 'npm run start',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-fastify',
|
||||
'name' => 'Railpack Fastify Example',
|
||||
'base_directory' => '/node/fastify',
|
||||
'ports_exposes' => '3000',
|
||||
'start_command' => 'npm run start',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-nestjs',
|
||||
'name' => 'Railpack NestJS Example',
|
||||
'base_directory' => '/node/nestjs',
|
||||
'ports_exposes' => '3000',
|
||||
'build_command' => 'npm run build',
|
||||
'start_command' => 'npm run start:prod',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-adonisjs',
|
||||
'name' => 'Railpack AdonisJS Example',
|
||||
'base_directory' => '/node/adonisjs',
|
||||
'ports_exposes' => '3333',
|
||||
'build_command' => 'npm run build',
|
||||
'start_command' => 'npm run start',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-hono',
|
||||
'name' => 'Railpack Hono Example',
|
||||
'base_directory' => '/node/hono',
|
||||
'ports_exposes' => '3000',
|
||||
'build_command' => 'npm run build',
|
||||
'start_command' => 'npm run start',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-koa',
|
||||
'name' => 'Railpack Koa Example',
|
||||
'base_directory' => '/node/koa',
|
||||
'ports_exposes' => '3000',
|
||||
'start_command' => 'npm run start',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-nextjs-ssr',
|
||||
'name' => 'Railpack Next.js SSR Example',
|
||||
'base_directory' => '/node/nextjs/ssr',
|
||||
'ports_exposes' => '3000',
|
||||
'build_command' => 'npm run build',
|
||||
'start_command' => 'npm run start',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-nuxtjs-ssr',
|
||||
'name' => 'Railpack NuxtJS SSR Example',
|
||||
'base_directory' => '/node/nuxtjs/ssr',
|
||||
'ports_exposes' => '3000',
|
||||
'build_command' => 'npm run build',
|
||||
'start_command' => 'npm run preview -- --host 0.0.0.0 --port 3000',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-astro-ssr',
|
||||
'name' => 'Railpack Astro SSR Example',
|
||||
'base_directory' => '/node/astro/ssr',
|
||||
'ports_exposes' => '4321',
|
||||
'build_command' => 'npm run build',
|
||||
'start_command' => 'npm run start',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-sveltekit-ssr',
|
||||
'name' => 'Railpack SvelteKit SSR Example',
|
||||
'base_directory' => '/node/sveltekit/ssr',
|
||||
'ports_exposes' => '3000',
|
||||
'build_command' => 'npm run build',
|
||||
'start_command' => 'npm run start',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-tanstack-start-ssr',
|
||||
'name' => 'Railpack TanStack Start SSR Example',
|
||||
'base_directory' => '/node/tanstack-start/ssr',
|
||||
'ports_exposes' => '3000',
|
||||
'build_command' => 'npm run build',
|
||||
'start_command' => 'npm run start',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-angular-ssr',
|
||||
'name' => 'Railpack Angular SSR Example',
|
||||
'base_directory' => '/node/angular/ssr',
|
||||
'ports_exposes' => '4000',
|
||||
'build_command' => 'npm run build',
|
||||
'start_command' => 'npm run start',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-vue-ssr',
|
||||
'name' => 'Railpack Vue SSR Example',
|
||||
'base_directory' => '/node/vue/ssr',
|
||||
'ports_exposes' => '3000',
|
||||
'build_command' => 'npm run build',
|
||||
'start_command' => 'npm run start',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-qwik-ssr',
|
||||
'name' => 'Railpack Qwik SSR Example',
|
||||
'base_directory' => '/node/qwik/ssr',
|
||||
'ports_exposes' => '3000',
|
||||
'build_command' => 'npm run build',
|
||||
'start_command' => 'npm run serve',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-react-static',
|
||||
'name' => 'Railpack React Static Example',
|
||||
'base_directory' => '/node/react',
|
||||
'ports_exposes' => '80',
|
||||
'build_command' => 'npm run build',
|
||||
'publish_directory' => '/dist',
|
||||
'is_static' => true,
|
||||
'is_spa' => true,
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-vite-static',
|
||||
'name' => 'Railpack Vite Static Example',
|
||||
'base_directory' => '/node/vite',
|
||||
'ports_exposes' => '80',
|
||||
'build_command' => 'npm run build',
|
||||
'publish_directory' => '/dist',
|
||||
'is_static' => true,
|
||||
'is_spa' => true,
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-eleventy-static',
|
||||
'name' => 'Railpack Eleventy Static Example',
|
||||
'base_directory' => '/node/eleventy',
|
||||
'ports_exposes' => '80',
|
||||
'build_command' => 'npm run build',
|
||||
'publish_directory' => '/_site',
|
||||
'is_static' => true,
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-gatsby-static',
|
||||
'name' => 'Railpack Gatsby Static Example',
|
||||
'base_directory' => '/node/gatsby',
|
||||
'ports_exposes' => '80',
|
||||
'build_command' => 'npm run build',
|
||||
'publish_directory' => '/public',
|
||||
'is_static' => true,
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-nextjs-static',
|
||||
'name' => 'Railpack Next.js Static Example',
|
||||
'base_directory' => '/node/nextjs/static',
|
||||
'ports_exposes' => '80',
|
||||
'build_command' => 'npm run build',
|
||||
'publish_directory' => '/out',
|
||||
'is_static' => true,
|
||||
'is_spa' => true,
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-nuxtjs-static',
|
||||
'name' => 'Railpack NuxtJS Static Example',
|
||||
'base_directory' => '/node/nuxtjs/static',
|
||||
'ports_exposes' => '80',
|
||||
'build_command' => 'npm run build',
|
||||
'publish_directory' => '/.output/public',
|
||||
'is_static' => true,
|
||||
'is_spa' => true,
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-astro-static',
|
||||
'name' => 'Railpack Astro Static Example',
|
||||
'base_directory' => '/node/astro/static',
|
||||
'ports_exposes' => '80',
|
||||
'build_command' => 'npm run build',
|
||||
'publish_directory' => '/dist',
|
||||
'is_static' => true,
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-sveltekit-static',
|
||||
'name' => 'Railpack SvelteKit Static Example',
|
||||
'base_directory' => '/node/sveltekit/static',
|
||||
'ports_exposes' => '80',
|
||||
'build_command' => 'npm run build',
|
||||
'publish_directory' => '/build',
|
||||
'is_static' => true,
|
||||
'is_spa' => true,
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-tanstack-start-static',
|
||||
'name' => 'Railpack TanStack Start Static Example',
|
||||
'base_directory' => '/node/tanstack-start/static',
|
||||
'ports_exposes' => '80',
|
||||
'build_command' => 'npm run build',
|
||||
'publish_directory' => '/.output/public',
|
||||
'is_static' => true,
|
||||
'is_spa' => true,
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-angular-static',
|
||||
'name' => 'Railpack Angular Static Example',
|
||||
'base_directory' => '/node/angular/static',
|
||||
'ports_exposes' => '80',
|
||||
'build_command' => 'npm run build',
|
||||
'publish_directory' => '/dist/static/browser',
|
||||
'is_static' => true,
|
||||
'is_spa' => true,
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-vue-static',
|
||||
'name' => 'Railpack Vue Static Example',
|
||||
'base_directory' => '/node/vue/static',
|
||||
'ports_exposes' => '80',
|
||||
'build_command' => 'npm run build',
|
||||
'publish_directory' => '/dist',
|
||||
'is_static' => true,
|
||||
'is_spa' => true,
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-qwik-static',
|
||||
'name' => 'Railpack Qwik Static Example',
|
||||
'base_directory' => '/node/qwik/static',
|
||||
'ports_exposes' => '80',
|
||||
'build_command' => 'npm run build',
|
||||
'publish_directory' => '/dist',
|
||||
'is_static' => true,
|
||||
'is_spa' => true,
|
||||
],
|
||||
// Multi-language examples (only available on v4.x branch).
|
||||
[
|
||||
'uuid' => 'railpack-python-flask',
|
||||
'name' => 'Railpack Python Flask Example',
|
||||
'base_directory' => '/flask',
|
||||
'ports_exposes' => '5000',
|
||||
'git_branch' => 'v4.x',
|
||||
'start_command' => 'flask run --host=0.0.0.0 --port=5000',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-go-gin',
|
||||
'name' => 'Railpack Go Gin Example',
|
||||
'base_directory' => '/go/gin',
|
||||
'ports_exposes' => '3000',
|
||||
'git_branch' => 'v4.x',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-rust',
|
||||
'name' => 'Railpack Rust Example',
|
||||
'base_directory' => '/rust',
|
||||
'ports_exposes' => '8000',
|
||||
'git_branch' => 'v4.x',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-laravel',
|
||||
'name' => 'Railpack Laravel Example',
|
||||
'base_directory' => '/laravel',
|
||||
'ports_exposes' => '80',
|
||||
'git_branch' => 'v4.x',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-laravel-pure',
|
||||
'name' => 'Railpack Laravel Pure Example',
|
||||
'base_directory' => '/laravel-pure',
|
||||
'ports_exposes' => '80',
|
||||
'git_branch' => 'v4.x',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-laravel-inertia',
|
||||
'name' => 'Railpack Laravel Inertia Example',
|
||||
'base_directory' => '/laravel-inertia',
|
||||
'ports_exposes' => '80',
|
||||
'git_branch' => 'v4.x',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-symfony',
|
||||
'name' => 'Railpack Symfony Example',
|
||||
'base_directory' => '/symfony',
|
||||
'ports_exposes' => '80',
|
||||
'git_branch' => 'v4.x',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-rails',
|
||||
'name' => 'Railpack Ruby on Rails Example',
|
||||
'base_directory' => '/rails-example',
|
||||
'ports_exposes' => '3000',
|
||||
'git_branch' => 'v4.x',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-elixir-phoenix',
|
||||
'name' => 'Railpack Elixir Phoenix Example',
|
||||
'base_directory' => '/elixir-phoenix',
|
||||
'ports_exposes' => '4000',
|
||||
'git_branch' => 'v4.x',
|
||||
],
|
||||
[
|
||||
'uuid' => 'railpack-bun',
|
||||
'name' => 'Railpack Bun Example',
|
||||
'base_directory' => '/bun',
|
||||
'ports_exposes' => '3000',
|
||||
'git_branch' => 'v4.x',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
private function ensureDevelopmentPrerequisitesExist(): void
|
||||
{
|
||||
Team::query()->firstOrCreate(
|
||||
['id' => 0],
|
||||
[
|
||||
'name' => 'Root Team',
|
||||
'description' => 'The root team',
|
||||
'personal_team' => true,
|
||||
],
|
||||
);
|
||||
|
||||
PrivateKey::query()->firstOrCreate(
|
||||
['id' => 1],
|
||||
[
|
||||
'uuid' => 'ssh',
|
||||
'team_id' => 0,
|
||||
'name' => 'Testing Host Key',
|
||||
'description' => 'This is a test docker container',
|
||||
'private_key' => <<<'KEY'
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevAAAAJi/QySHv0Mk
|
||||
hwAAAAtzc2gtZWQyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevA
|
||||
AAAECBQw4jg1WRT2IGHMncCiZhURCts2s24HoDS0thHnnRKVuGmoeGq/pojrsyP1pszcNV
|
||||
uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
KEY,
|
||||
],
|
||||
);
|
||||
|
||||
Server::query()->firstOrCreate(
|
||||
['id' => 0],
|
||||
[
|
||||
'uuid' => 'localhost',
|
||||
'name' => 'localhost',
|
||||
'description' => 'This is a test docker container in development mode',
|
||||
'ip' => 'coolify-testing-host',
|
||||
'team_id' => 0,
|
||||
'private_key_id' => 1,
|
||||
'proxy' => [
|
||||
'type' => ProxyTypes::TRAEFIK->value,
|
||||
'status' => ProxyStatus::EXITED->value,
|
||||
],
|
||||
],
|
||||
);
|
||||
|
||||
StandaloneDocker::query()->firstOrCreate(
|
||||
['id' => 0],
|
||||
[
|
||||
'uuid' => 'docker',
|
||||
'name' => 'Standalone Docker 1',
|
||||
'network' => 'coolify',
|
||||
'server_id' => 0,
|
||||
],
|
||||
);
|
||||
|
||||
$this->ensurePublicGithubSourceExists();
|
||||
}
|
||||
|
||||
private function ensurePublicGithubSourceExists(): void
|
||||
{
|
||||
GithubApp::query()->firstOrCreate(
|
||||
['id' => 0],
|
||||
[
|
||||
'uuid' => 'github-public',
|
||||
'name' => 'Public GitHub',
|
||||
'api_url' => 'https://api.github.com',
|
||||
'html_url' => 'https://github.com',
|
||||
'is_public' => true,
|
||||
'team_id' => 0,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
private function isDevelopmentEnvironment(): bool
|
||||
{
|
||||
return in_array(config('app.env'), ['local', 'development', 'dev'], true);
|
||||
}
|
||||
|
||||
private function prepareEnvironment(): Environment
|
||||
{
|
||||
$project = Project::query()->firstOrNew(['uuid' => self::PROJECT_UUID]);
|
||||
$project->fill([
|
||||
'name' => 'Railpack Examples',
|
||||
'description' => 'Development-only Railpack examples from coollabsio/coolify-examples@next.',
|
||||
'team_id' => 0,
|
||||
]);
|
||||
$project->save();
|
||||
|
||||
$environment = $project->environments()->first();
|
||||
|
||||
if (! $environment) {
|
||||
$environment = $project->environments()->create([
|
||||
'name' => 'production',
|
||||
'uuid' => self::ENVIRONMENT_UUID,
|
||||
]);
|
||||
} else {
|
||||
$environment->update([
|
||||
'name' => 'production',
|
||||
'uuid' => self::ENVIRONMENT_UUID,
|
||||
]);
|
||||
}
|
||||
|
||||
return $environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $example
|
||||
*/
|
||||
private function upsertApplication(Environment $environment, StandaloneDocker $destination, array $example): void
|
||||
{
|
||||
$application = Application::withTrashed()->firstOrNew(['uuid' => $example['uuid']]);
|
||||
$application->fill([
|
||||
'name' => $example['name'],
|
||||
'description' => $example['name'],
|
||||
'fqdn' => "http://{$example['uuid']}.127.0.0.1.sslip.io",
|
||||
'repository_project_id' => self::REPOSITORY_PROJECT_ID,
|
||||
'git_repository' => self::GIT_REPOSITORY,
|
||||
'git_branch' => $example['git_branch'] ?? self::GIT_BRANCH,
|
||||
'build_pack' => 'railpack',
|
||||
'ports_exposes' => $example['ports_exposes'],
|
||||
'base_directory' => $example['base_directory'],
|
||||
'publish_directory' => $example['publish_directory'] ?? null,
|
||||
'static_image' => 'nginx:alpine',
|
||||
'install_command' => $example['install_command'] ?? null,
|
||||
'build_command' => $example['build_command'] ?? null,
|
||||
'start_command' => $example['start_command'] ?? null,
|
||||
'environment_id' => $environment->id,
|
||||
'destination_id' => $destination->id,
|
||||
'destination_type' => StandaloneDocker::class,
|
||||
'source_id' => 0,
|
||||
'source_type' => GithubApp::class,
|
||||
]);
|
||||
$application->save();
|
||||
|
||||
if ($application->trashed()) {
|
||||
$application->restore();
|
||||
}
|
||||
|
||||
$application->settings()->updateOrCreate(
|
||||
['application_id' => $application->id],
|
||||
[
|
||||
'is_static' => $example['is_static'] ?? false,
|
||||
'is_spa' => $example['is_spa'] ?? false,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -23,23 +23,25 @@ class InstanceSettingsSeeder extends Seeder
|
||||
'smtp_from_address' => 'hi@localhost.com',
|
||||
'smtp_from_name' => 'Coolify',
|
||||
]);
|
||||
try {
|
||||
$ipv4 = Process::run('curl -4s https://ifconfig.io')->output();
|
||||
$ipv4 = trim($ipv4);
|
||||
$ipv4 = filter_var($ipv4, FILTER_VALIDATE_IP);
|
||||
$settings = instanceSettings();
|
||||
if (is_null($settings->public_ipv4) && $ipv4) {
|
||||
$settings->update(['public_ipv4' => $ipv4]);
|
||||
if (! isDev()) {
|
||||
try {
|
||||
$ipv4 = Process::run('curl -4s https://ifconfig.io')->output();
|
||||
$ipv4 = trim($ipv4);
|
||||
$ipv4 = filter_var($ipv4, FILTER_VALIDATE_IP);
|
||||
$settings = instanceSettings();
|
||||
if (is_null($settings->public_ipv4) && $ipv4) {
|
||||
$settings->update(['public_ipv4' => $ipv4]);
|
||||
}
|
||||
$ipv6 = Process::run('curl -6s https://ifconfig.io')->output();
|
||||
$ipv6 = trim($ipv6);
|
||||
$ipv6 = filter_var($ipv6, FILTER_VALIDATE_IP);
|
||||
$settings = instanceSettings();
|
||||
if (is_null($settings->public_ipv6) && $ipv6) {
|
||||
$settings->update(['public_ipv6' => $ipv6]);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error: {$e->getMessage()}\n";
|
||||
}
|
||||
$ipv6 = Process::run('curl -6s https://ifconfig.io')->output();
|
||||
$ipv6 = trim($ipv6);
|
||||
$ipv6 = filter_var($ipv6, FILTER_VALIDATE_IP);
|
||||
$settings = instanceSettings();
|
||||
if (is_null($settings->public_ipv6) && $ipv6) {
|
||||
$settings->update(['public_ipv6' => $ipv6]);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error: {$e->getMessage()}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,16 @@ class ProductionSeeder extends Seeder
|
||||
echo " Running in self-hosted mode.\n";
|
||||
}
|
||||
|
||||
if (Team::find(0) === null) {
|
||||
(new Team)->forceFill([
|
||||
'id' => 0,
|
||||
'name' => 'Root Team',
|
||||
'description' => 'The root team',
|
||||
'personal_team' => true,
|
||||
'show_boarding' => true,
|
||||
])->save();
|
||||
}
|
||||
|
||||
if (User::find(0) !== null && Team::find(0) !== null) {
|
||||
if (DB::table('team_user')->where('user_id', 0)->first() === null) {
|
||||
DB::table('team_user')->insert([
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
@@ -45,12 +46,19 @@ class RootUserSeeder extends Seeder
|
||||
}
|
||||
|
||||
try {
|
||||
User::create([
|
||||
$user = (new User)->forceFill([
|
||||
'id' => 0,
|
||||
'name' => env('ROOT_USERNAME', 'Root User'),
|
||||
'email' => env('ROOT_USER_EMAIL'),
|
||||
'password' => Hash::make(env('ROOT_USER_PASSWORD')),
|
||||
]);
|
||||
$user->save();
|
||||
|
||||
$team = Team::find(0);
|
||||
if ($team !== null && ! $user->teams()->where('team_id', 0)->exists()) {
|
||||
$user->teams()->attach($team, ['role' => 'owner']);
|
||||
}
|
||||
|
||||
echo "\n SUCCESS Root user created successfully.\n\n";
|
||||
} catch (\Exception $e) {
|
||||
echo "\n ERROR Failed to create root user: {$e->getMessage()}\n\n";
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Server;
|
||||
use App\Models\SharedEnvironmentVariable;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
@@ -32,5 +33,29 @@ class SharedEnvironmentVariableSeeder extends Seeder
|
||||
'project_id' => 1,
|
||||
'team_id' => 0,
|
||||
]);
|
||||
|
||||
// Add predefined server variables to all existing servers
|
||||
$servers = Server::all();
|
||||
foreach ($servers as $server) {
|
||||
SharedEnvironmentVariable::firstOrCreate([
|
||||
'key' => 'COOLIFY_SERVER_UUID',
|
||||
'type' => 'server',
|
||||
'server_id' => $server->id,
|
||||
'team_id' => $server->team_id,
|
||||
], [
|
||||
'value' => $server->uuid,
|
||||
'is_literal' => true,
|
||||
]);
|
||||
|
||||
SharedEnvironmentVariable::firstOrCreate([
|
||||
'key' => 'COOLIFY_SERVER_NAME',
|
||||
'type' => 'server',
|
||||
'server_id' => $server->id,
|
||||
'team_id' => $server->team_id,
|
||||
], [
|
||||
'value' => $server->name,
|
||||
'is_literal' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user