Merge remote-tracking branch 'origin/next' into pr-7764-shadow/add-shared-server-env

This commit is contained in:
Andras Bacsai committed 2026-03-31 10:52:31 +02:00
commit cb97a18a78
767 files changed
+61894 -15664

No files matched your search

+16
View File
@@ -0,0 +1,16 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class EnvironmentFactory extends Factory
{
public function definition(): array
{
return [
'name' => fake()->unique()->word(),
'project_id' => 1,
];
}
}
+16
View File
@@ -0,0 +1,16 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class ProjectFactory extends Factory
{
public function definition(): array
{
return [
'name' => fake()->unique()->company(),
'team_id' => 1,
];
}
}
@@ -0,0 +1,21 @@
<?php
namespace Database\Factories;
use App\Models\Team;
use Illuminate\Database\Eloquent\Factories\Factory;
class ScheduledTaskFactory extends Factory
{
public function definition(): array
{
return [
'name' => fake()->word(),
'command' => 'echo hello',
'frequency' => '* * * * *',
'timeout' => 300,
'enabled' => true,
'team_id' => Team::factory(),
];
}
}
+19
View File
@@ -0,0 +1,19 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class ServiceFactory extends Factory
{
public function definition(): array
{
return [
'name' => fake()->unique()->word(),
'destination_type' => \App\Models\StandaloneDocker::class,
'destination_id' => 1,
'environment_id' => 1,
'docker_compose_raw' => 'version: "3"',
];
}
}
@@ -0,0 +1,18 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class StandaloneDockerFactory extends Factory
{
public function definition(): array
{
return [
'uuid' => fake()->uuid(),
'name' => fake()->unique()->word(),
'network' => 'coolify',
'server_id' => 1,
];
}
}
@@ -8,6 +8,10 @@ class AddIndexToActivityLog extends Migration
{
public function up()
{
if (DB::connection()->getDriverName() !== 'pgsql') {
return;
}
try {
DB::statement('ALTER TABLE activity_log ALTER COLUMN properties TYPE jsonb USING properties::jsonb');
DB::statement('CREATE INDEX idx_activity_type_uuid ON activity_log USING GIN (properties jsonb_path_ops)');
@@ -18,6 +22,10 @@ class AddIndexToActivityLog extends Migration
public function down()
{
if (DB::connection()->getDriverName() !== 'pgsql') {
return;
}
try {
DB::statement('DROP INDEX IF EXISTS idx_activity_type_uuid');
DB::statement('ALTER TABLE activity_log ALTER COLUMN properties TYPE json USING properties::json');
@@ -0,0 +1,36 @@
<?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('environment_variables', function (Blueprint $table) {
$table->string('comment', 256)->nullable();
});
Schema::table('shared_environment_variables', function (Blueprint $table) {
$table->string('comment', 256)->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('environment_variables', function (Blueprint $table) {
$table->dropColumn('comment');
});
Schema::table('shared_environment_variables', function (Blueprint $table) {
$table->dropColumn('comment');
});
}
};
@@ -22,6 +22,10 @@ return new class extends Migration
public function up(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
return;
}
foreach ($this->indexes as [$table, $columns, $indexName]) {
if (! $this->indexExists($indexName)) {
$columnList = implode(', ', array_map(fn ($col) => "\"$col\"", $columns));
@@ -32,6 +36,10 @@ return new class extends Migration
public function down(): void
{
if (DB::connection()->getDriverName() !== 'pgsql') {
return;
}
foreach ($this->indexes as [, , $indexName]) {
DB::statement("DROP INDEX IF EXISTS \"{$indexName}\"");
}
@@ -0,0 +1,44 @@
<?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
{
if (! Schema::hasColumn('applications', 'health_check_type')) {
Schema::table('applications', function (Blueprint $table) {
$table->text('health_check_type')->default('http')->after('health_check_enabled');
});
}
if (! Schema::hasColumn('applications', 'health_check_command')) {
Schema::table('applications', function (Blueprint $table) {
$table->text('health_check_command')->nullable()->after('health_check_type');
});
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
if (Schema::hasColumn('applications', 'health_check_type')) {
Schema::table('applications', function (Blueprint $table) {
$table->dropColumn('health_check_type');
});
}
if (Schema::hasColumn('applications', 'health_check_command')) {
Schema::table('applications', function (Blueprint $table) {
$table->dropColumn('health_check_command');
});
}
}
};
@@ -0,0 +1,25 @@
<?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('subscriptions', function (Blueprint $table) {
$table->timestamp('stripe_refunded_at')->nullable()->after('stripe_past_due');
});
}
public function down(): void
{
Schema::table('subscriptions', function (Blueprint $table) {
$table->dropColumn('stripe_refunded_at');
});
}
};
@@ -0,0 +1,60 @@
<?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
{
$tables = [
'standalone_postgresqls',
'standalone_mysqls',
'standalone_mariadbs',
'standalone_redis',
'standalone_mongodbs',
'standalone_clickhouses',
'standalone_keydbs',
'standalone_dragonflies',
'service_databases',
];
foreach ($tables as $table) {
if (Schema::hasTable($table) && !Schema::hasColumn($table, 'public_port_timeout')) {
Schema::table($table, function (Blueprint $table) {
$table->integer('public_port_timeout')->nullable()->default(3600)->after('public_port');
});
}
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
$tables = [
'standalone_postgresqls',
'standalone_mysqls',
'standalone_mariadbs',
'standalone_redis',
'standalone_mongodbs',
'standalone_clickhouses',
'standalone_keydbs',
'standalone_dragonflies',
'service_databases',
];
foreach ($tables as $table) {
if (Schema::hasTable($table) && Schema::hasColumn($table, 'public_port_timeout')) {
Schema::table($table, function (Blueprint $table) {
$table->dropColumn('public_port_timeout');
});
}
}
}
};
@@ -0,0 +1,32 @@
<?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
{
if (! Schema::hasColumn('servers', 'server_metadata')) {
Schema::table('servers', function (Blueprint $table) {
$table->json('server_metadata')->nullable();
});
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
if (Schema::hasColumn('servers', 'server_metadata')) {
Schema::table('servers', function (Blueprint $table) {
$table->dropColumn('server_metadata');
});
}
}
};
@@ -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('local_file_volumes', function (Blueprint $table) {
$table->boolean('is_preview_suffix_enabled')->default(true)->after('is_based_on_git');
});
Schema::table('local_persistent_volumes', function (Blueprint $table) {
$table->boolean('is_preview_suffix_enabled')->default(true)->after('host_path');
});
}
public function down(): void
{
Schema::table('local_file_volumes', function (Blueprint $table) {
$table->dropColumn('is_preview_suffix_enabled');
});
Schema::table('local_persistent_volumes', function (Blueprint $table) {
$table->dropColumn('is_preview_suffix_enabled');
});
}
};
@@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Visus\Cuid2\Cuid2;
return new class extends Migration
{
public function up(): void
{
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) {
foreach ($volumes as $volume) {
DB::table('local_persistent_volumes')
->where('id', $volume->id)
->update(['uuid' => (string) new Cuid2]);
}
});
Schema::table('local_persistent_volumes', function (Blueprint $table) {
$table->string('uuid')->nullable(false)->unique()->change();
});
}
public function down(): void
{
Schema::table('local_persistent_volumes', function (Blueprint $table) {
$table->dropColumn('uuid');
});
}
};
@@ -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();
}
}
}
@@ -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');
});
}
};
File diff suppressed because it is too large. Load diff
+48 -1
View File
@@ -4,6 +4,7 @@ namespace Database\Seeders;
use App\Models\Application;
use App\Models\GithubApp;
use App\Models\GitlabApp;
use App\Models\StandaloneDocker;
use Illuminate\Database\Seeder;
@@ -21,7 +22,7 @@ class ApplicationSeeder extends Seeder
'git_repository' => 'coollabsio/coolify-examples',
'git_branch' => 'v4.x',
'base_directory' => '/docker-compose',
'docker_compose_location' => 'docker-compose-test.yaml',
'docker_compose_location' => '/docker-compose-test.yaml',
'build_pack' => 'dockercompose',
'ports_exposes' => '80',
'environment_id' => 1,
@@ -98,5 +99,51 @@ CMD ["nginx", "-g", "daemon off;"]
CMD ["sh", "-c", "echo Crashing in 5 seconds... && sleep 5 && exit 1"]
',
]);
Application::create([
'uuid' => 'github-deploy-key',
'name' => 'GitHub Deploy Key Example',
'fqdn' => 'http://github-deploy-key.127.0.0.1.sslip.io',
'git_repository' => 'git@github.com:coollabsio/coolify-examples-deploy-key.git',
'git_branch' => 'main',
'build_pack' => 'nixpacks',
'ports_exposes' => '80',
'environment_id' => 1,
'destination_id' => 0,
'destination_type' => StandaloneDocker::class,
'source_id' => 0,
'source_type' => GithubApp::class,
'private_key_id' => 1,
]);
Application::create([
'uuid' => 'gitlab-deploy-key',
'name' => 'GitLab Deploy Key Example',
'fqdn' => 'http://gitlab-deploy-key.127.0.0.1.sslip.io',
'git_repository' => 'git@gitlab.com:coollabsio/php-example.git',
'git_branch' => 'main',
'build_pack' => 'nixpacks',
'ports_exposes' => '80',
'environment_id' => 1,
'destination_id' => 0,
'destination_type' => StandaloneDocker::class,
'source_id' => 1,
'source_type' => GitlabApp::class,
'private_key_id' => 1,
]);
Application::create([
'uuid' => 'gitlab-public-example',
'name' => 'GitLab Public Example',
'fqdn' => 'http://gitlab-public.127.0.0.1.sslip.io',
'git_repository' => 'https://gitlab.com/andrasbacsai/coolify-examples.git',
'base_directory' => '/astro/static',
'publish_directory' => '/dist',
'git_branch' => 'main',
'build_pack' => 'nixpacks',
'ports_exposes' => '80',
'environment_id' => 1,
'destination_id' => 0,
'destination_type' => StandaloneDocker::class,
'source_id' => 1,
'source_type' => GitlabApp::class,
]);
}
}
@@ -15,5 +15,12 @@ class ApplicationSettingsSeeder extends Seeder
$application_1 = Application::find(1)->load(['settings']);
$application_1->settings->is_debug_enabled = false;
$application_1->settings->save();
$gitlabPublic = Application::where('uuid', 'gitlab-public-example')->first();
if ($gitlabPublic) {
$gitlabPublic->load(['settings']);
$gitlabPublic->settings->is_static = true;
$gitlabPublic->settings->save();
}
}
}
+3 -1
View File
@@ -26,12 +26,14 @@ class CaSslCertSeeder extends Seeder
}
$caCertPath = config('constants.coolify.base_config_path').'/ssl/';
$base64Cert = base64_encode($caCert->ssl_certificate);
$commands = collect([
"mkdir -p $caCertPath",
"chown -R 9999:root $caCertPath",
"chmod -R 700 $caCertPath",
"rm -rf $caCertPath/coolify-ca.crt",
"echo '{$caCert->ssl_certificate}' > $caCertPath/coolify-ca.crt",
"echo '{$base64Cert}' | base64 -d | tee $caCertPath/coolify-ca.crt > /dev/null",
"chmod 644 $caCertPath/coolify-ca.crt",
]);
+2 -1
View File
@@ -45,12 +45,13 @@ 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();
echo "\n SUCCESS Root user created successfully.\n\n";
} catch (\Exception $e) {
echo "\n ERROR Failed to create root user: {$e->getMessage()}\n\n";