diff --git a/.github/workflows/coolify-builder.yml b/.github/workflows/coolify-builder.yml deleted file mode 100644 index f69ba64f3..000000000 --- a/.github/workflows/coolify-builder.yml +++ /dev/null @@ -1,80 +0,0 @@ -name: Coolify Builder (v4) - -on: - push: - branches: ["main", "next"] - paths: - - .github/workflows/coolify-builder.yml - - docker/coolify-builder/Dockerfile - -env: - REGISTRY: ghcr.io - IMAGE_NAME: "coollabsio/coolify-builder" - -jobs: - amd64: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - steps: - - uses: actions/checkout@v3 - - name: Login to ghcr.io - uses: docker/login-action@v2 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Build image and push to registry - uses: docker/build-push-action@v3 - with: - no-cache: true - context: . - file: docker/coolify-builder/Dockerfile - platforms: linux/amd64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest - aarch64: - runs-on: [self-hosted, arm64] - permissions: - contents: read - packages: write - steps: - - uses: actions/checkout@v3 - - name: Login to ghcr.io - uses: docker/login-action@v2 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Build image and push to registry - uses: docker/build-push-action@v3 - with: - no-cache: true - context: . - file: docker/coolify-builder/Dockerfile - platforms: linux/aarch64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:aarch64 - merge-manifest: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - needs: [amd64, aarch64] - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - name: Login to ghcr.io - uses: docker/login-action@v2 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Create & publish manifest - run: | - docker buildx imagetools create --append ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:aarch64 --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index a2ed0f2f9..deced9de9 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -6,6 +6,7 @@ use App\Models\Project; use App\Models\S3Storage; use App\Models\Server; +use App\Models\StandalonePostgresql; use App\Models\TeamInvitation; use App\Models\User; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; @@ -60,20 +61,16 @@ public function settings() { if (auth()->user()->isInstanceAdmin()) { $settings = InstanceSettings::get(); + $database = StandalonePostgresql::whereName('coolify-db')->first(); + if ($database) { + $backup = $database->scheduledBackups->first(); + $s3s = S3Storage::whereTeamId(0)->get(); + } return view('settings.configuration', [ - 'settings' => $settings - ]); - } else { - return redirect()->route('dashboard'); - } - } - - public function emails() - { - if (auth()->user()->isInstanceAdmin()) { - $settings = InstanceSettings::get(); - return view('settings.emails', [ - 'settings' => $settings + 'settings' => $settings, + 'database' => $database, + 'backup' => $backup ?? null, + 's3s' => $s3s ?? [], ]); } else { return redirect()->route('dashboard'); diff --git a/app/Http/Controllers/DatabaseController.php b/app/Http/Controllers/DatabaseController.php index bddc7ffe6..650051f06 100644 --- a/app/Http/Controllers/DatabaseController.php +++ b/app/Http/Controllers/DatabaseController.php @@ -46,7 +46,12 @@ public function executions() return redirect()->route('dashboard'); } $executions = collect($backup->executions)->sortByDesc('created_at'); - return view('project.database.backups.executions', ['database' => $database, 'backup' => $backup, 'executions' => $executions]); + return view('project.database.backups.executions', [ + 'database' => $database, + 'backup' => $backup, + 'executions' => $executions, + 's3s' => auth()->user()->currentTeam()->s3s, + ]); } public function backups() @@ -63,6 +68,9 @@ public function backups() if (!$database) { return redirect()->route('dashboard'); } - return view('project.database.backups.all', ['database' => $database]); + return view('project.database.backups.all', [ + 'database' => $database, + 's3s' => auth()->user()->currentTeam()->s3s, + ]); } } diff --git a/app/Http/Livewire/Project/Database/BackupEdit.php b/app/Http/Livewire/Project/Database/BackupEdit.php index b73682943..56d472672 100644 --- a/app/Http/Livewire/Project/Database/BackupEdit.php +++ b/app/Http/Livewire/Project/Database/BackupEdit.php @@ -7,6 +7,7 @@ class BackupEdit extends Component { public $backup; + public $s3s; public array $parameters; protected $rules = [ @@ -14,17 +15,25 @@ class BackupEdit extends Component 'backup.frequency' => 'required|string', 'backup.number_of_backups_locally' => 'required|integer|min:1', 'backup.save_s3' => 'required|boolean', + 'backup.s3_storage_id' => 'nullable|integer', ]; protected $validationAttributes = [ 'backup.enabled' => 'Enabled', 'backup.frequency' => 'Frequency', 'backup.number_of_backups_locally' => 'Number of Backups Locally', 'backup.save_s3' => 'Save to S3', + 'backup.s3_storage_id' => 'S3 Storage', + ]; + protected $messages = [ + 'backup.s3_storage_id' => 'Select a S3 Storage', ]; public function mount() { $this->parameters = get_route_parameters(); + if (is_null($this->backup->s3_storage_id)) { + $this->backup->s3_storage_id = 'default'; + } } @@ -37,21 +46,43 @@ public function delete() public function instantSave() { - $this->backup->save(); - $this->backup->refresh(); - $this->emit('success', 'Backup updated successfully'); + try { + $this->custom_validate(); + $this->backup->save(); + $this->backup->refresh(); + $this->emit('success', 'Backup updated successfully'); + } catch (\Exception $e) { + $this->emit('error', $e->getMessage()); + } + + } + + private function custom_validate() + { +// if ($this->backup->save_s3) { +// if (!is_numeric($this->selected_storage_id)) { +// throw new \Exception('Invalid S3 Storage'); +// } else { +// $this->backup->s3_storage_id = $this->selected_storage_id; +// } +// } + $isValid = validate_cron_expression($this->backup->frequency); + if (!$isValid) { + throw new \Exception('Invalid Cron / Human expression'); + } + $this->validate(); } public function submit() { - $isValid = validate_cron_expression($this->backup->frequency); - if (!$isValid) { - $this->emit('error', 'Invalid Cron / Human expression'); - return; + ray($this->backup->s3_storage_id); + try { + $this->custom_validate(); + $this->backup->save(); + $this->backup->refresh(); + $this->emit('success', 'Backup updated successfully'); + } catch (\Exception $e) { + $this->emit('error', $e->getMessage()); } - $this->validate(); - $this->backup->save(); - $this->backup->refresh(); - $this->emit('success', 'Backup updated successfully'); } } diff --git a/app/Http/Livewire/Project/Database/CreateScheduledBackup.php b/app/Http/Livewire/Project/Database/CreateScheduledBackup.php index c2334ca2d..e3ea97735 100644 --- a/app/Http/Livewire/Project/Database/CreateScheduledBackup.php +++ b/app/Http/Livewire/Project/Database/CreateScheduledBackup.php @@ -11,6 +11,8 @@ class CreateScheduledBackup extends Component public $frequency; public bool $enabled = true; public bool $save_s3 = true; + public $s3_storage_id; + public $s3s; protected $rules = [ 'frequency' => 'required|string', @@ -27,13 +29,14 @@ public function submit(): void $this->validate(); $isValid = validate_cron_expression($this->frequency); if (!$isValid) { - $this->emit('error', 'Invalid Cron / Human expression'); + $this->emit('error', 'Invalid Cron / Human expression.'); return; } ScheduledDatabaseBackup::create([ 'enabled' => true, 'frequency' => $this->frequency, 'save_s3' => $this->save_s3, + 's3_storage_id' => $this->s3_storage_id, 'database_id' => $this->database->id, 'database_type' => $this->database->getMorphClass(), 'team_id' => auth()->user()->currentTeam()->id, diff --git a/app/Http/Livewire/Settings/Backup.php b/app/Http/Livewire/Settings/Backup.php new file mode 100644 index 000000000..99ca1d731 --- /dev/null +++ b/app/Http/Livewire/Settings/Backup.php @@ -0,0 +1,75 @@ + 'required', + 'database.name' => 'required', + 'database.description' => 'nullable', + 'database.postgres_user' => 'required', + 'database.postgres_password' => 'required', + + ]; + protected $validationAttributes = [ + 'database.uuid' => 'uuid', + 'database.name' => 'name', + 'database.description' => 'description', + 'database.postgres_user' => 'postgres user', + 'database.postgres_password' => 'postgres password', + ]; + + public function add_coolify_database() + { + ray('add_coolify_database'); + $server = Server::find(0); + $out = instant_remote_process(['docker inspect coolify-db'], $server); + $envs = format_docker_envs_to_json($out); + $postgres_password = $envs['POSTGRES_PASSWORD']; + $postgres_user = $envs['POSTGRES_USER']; + $postgres_db = $envs['POSTGRES_DB']; + $this->database = StandalonePostgresql::create([ + 'id' => 0, + 'name' => 'coolify-db', + 'description' => 'Coolify database', + 'postgres_user' => $postgres_user, + 'postgres_password' => $postgres_password, + 'postgres_db' => $postgres_db, + 'status' => 'running', + 'destination_type' => 'App\Models\StandaloneDocker', + 'destination_id' => 0, + ]); + $this->backup = ScheduledDatabaseBackup::create([ + 'id' => 0, + 'enabled' => true, + 'save_s3' => false, + 'frequency' => '0 0 * * *', + 'database_id' => $this->database->id, + 'database_type' => 'App\Models\StandalonePostgresql', + 'team_id' => auth()->user()->currentTeam()->id, + ]); + $this->database->refresh(); + $this->backup->refresh(); + ray($this->backup); + $this->s3s = S3Storage::whereTeamId(0)->get(); + } + + public function submit() + { + $this->emit('success', 'Backup updated successfully'); + } + +} diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index c5695804b..bed7e0a11 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -176,10 +176,10 @@ private function prepare_builder_image() { $this->execute_remote_command( [ - "echo -n 'Pulling latest version of the builder image (ghcr.io/coollabsio/coolify-builder).'", + "echo -n 'Pulling latest version of the builder image (ghcr.io/coollabsio/coolify-helper).'", ], [ - "docker run --pull=always -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/coollabsio/coolify-builder", + "docker run --pull=always -d --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/coollabsio/coolify-helper", "hidden" => true, ], [ diff --git a/app/Jobs/DatabaseBackupJob.php b/app/Jobs/DatabaseBackupJob.php index 644b5978c..7879e31a0 100644 --- a/app/Jobs/DatabaseBackupJob.php +++ b/app/Jobs/DatabaseBackupJob.php @@ -30,22 +30,25 @@ class DatabaseBackupJob implements ShouldQueue public StandalonePostgresql $database; public string $database_status; + public string|null $container_name = null; public ScheduledDatabaseBackupExecution|null $backup_log = null; public string $backup_status; - public string|null $backup_filename = null; + public string|null $backup_location = null; + public string $backup_dir; + public string $backup_file; public int $size = 0; public string|null $backup_output = null; - public S3Storage $s3; + public S3Storage|null $s3 = null; public function __construct($backup) { $this->backup = $backup; $this->team = Team::find($backup->team_id); - $this->database = $this->backup->database->first(); + $this->database = $this->backup->database; $this->database_type = $this->database->type(); $this->server = $this->database->destination->server; $this->database_status = $this->database->status; - $this->s3 = $this->team->s3; + $this->s3 = $this->backup->s3; } public function middleware(): array @@ -58,16 +61,23 @@ public function uniqueId(): int return $this->backup->id; } - public function handle() + public function handle(): void { if ($this->database_status !== 'running') { ray('database not running'); return; } - $this->backup_filename = backup_dir() . "/{$this->database->uuid}/dumpall-" . Carbon::now()->timestamp . ".sql"; + $this->container_name = $this->database->uuid; + if ($this->database->name === 'coolify-db') { + $this->container_name = "coolify-db"; + } + + $this->backup_dir = backup_dir() . "/" . $this->container_name; + $this->backup_file = "/dumpall-" . Carbon::now()->timestamp . ".sql"; + $this->backup_location = $this->backup_dir . $this->backup_file; $this->backup_log = ScheduledDatabaseBackupExecution::create([ - 'filename' => $this->backup_filename, + 'filename' => $this->backup_location, 'scheduled_database_backup_id' => $this->backup->id, ]); if ($this->database_type === 'standalone-postgresql') { @@ -76,18 +86,17 @@ public function handle() $this->calculate_size(); $this->remove_old_backups(); if ($this->backup->save_s3) { -// $this->upload_to_s3(); + $this->upload_to_s3(); } $this->save_backup_logs(); // TODO: Notify user } - private function backup_standalone_postgresql() + private function backup_standalone_postgresql(): void { try { - $commands[] = "mkdir -p " . backup_dir(); - $commands[] = "mkdir -p " . backup_dir() . "/{$this->database->uuid}"; - $commands[] = "docker exec {$this->database->uuid} pg_dumpall -U {$this->database->postgres_user} > $this->backup_filename"; + $commands[] = "mkdir -p " . $this->backup_dir; + $commands[] = "docker exec $this->container_name pg_dumpall -U {$this->database->postgres_user} > $this->backup_location"; $this->backup_output = instant_remote_process($commands, $this->server); @@ -97,14 +106,14 @@ private function backup_standalone_postgresql() $this->backup_output = null; } - ray('Backup done for ' . $this->database->uuid . ' at ' . $this->server->name . ':' . $this->backup_filename); + ray('Backup done for ' . $this->container_name . ' at ' . $this->server->name . ':' . $this->backup_location); $this->backup_status = 'success'; $this->team->notify(new BackupSuccess($this->backup, $this->database)); } catch (Throwable $th) { $this->backup_status = 'failed'; $this->add_to_backup_output($th->getMessage()); - ray('Backup failed for ' . $this->database->uuid . ' at ' . $this->server->name . ':' . $this->backup_filename . '\n\nError:' . $th->getMessage()); + ray('Backup failed for ' . $this->container_name . ' at ' . $this->server->name . ':' . $this->backup_location . '\n\nError:' . $th->getMessage()); $this->team->notify(new BackupFailed($this->backup, $this->database, $this->backup_output)); } finally { $this->backup_log->update([ @@ -113,7 +122,7 @@ private function backup_standalone_postgresql() } } - private function add_to_backup_output($output) + private function add_to_backup_output($output): void { if ($this->backup_output) { $this->backup_output = $this->backup_output . "\n" . $output; @@ -122,12 +131,12 @@ private function add_to_backup_output($output) } } - private function calculate_size() + private function calculate_size(): void { - $this->size = instant_remote_process(["du -b $this->backup_filename | cut -f1"], $this->server); + $this->size = instant_remote_process(["du -b $this->backup_location | cut -f1"], $this->server); } - private function remove_old_backups() + private function remove_old_backups(): void { if ($this->backup->number_of_backups_locally === 0) { $deletable = $this->backup->executions()->where('status', 'success'); @@ -140,17 +149,7 @@ private function remove_old_backups() } } - private function save_backup_logs() - { - $this->backup_log->update([ - 'status' => $this->backup_status, - 'message' => $this->backup_output, - 'size' => $this->size, - ]); - - } - - private function upload_to_s3() + private function upload_to_s3(): void { try { if (is_null($this->s3)) { @@ -161,16 +160,29 @@ private function upload_to_s3() // $region = $this->s3->region; $bucket = $this->s3->bucket; $endpoint = $this->s3->endpoint; - $backup_dir = backup_dir() . "/{$this->database->uuid}"; - - $base_command = "docker run -t --network {$this->database->destination->network} -v {$this->backup_filename}:{$this->backup_filename}:ro --rm --entrypoint=/bin/sh minio/mc -c \"mc config host add temporary {$endpoint} $key $secret && mc cp $this->backup_filename temporary/$bucket/$backup_dir/ \""; - - instant_remote_process([$base_command], $this->server); + $commands[] = "docker run --pull=always -d --network {$this->database->destination->network} --name backup-of-{$this->backup->uuid} --rm -v $this->backup_location:$this->backup_location:ro ghcr.io/coollabsio/coolify-helper"; + $commands[] = "docker exec backup-of-{$this->backup->uuid} mc config host add temporary {$endpoint} $key $secret"; + $commands[] = "docker exec backup-of-{$this->backup->uuid} mc cp $this->backup_location temporary/$bucket{$this->backup_dir}/"; + instant_remote_process($commands, $this->server); $this->add_to_backup_output('Uploaded to S3.'); + ray('Uploaded to S3. ' . $this->backup_location . ' to s3://' . $bucket . $this->backup_dir); } catch (\Throwable $th) { $this->add_to_backup_output($th->getMessage()); ray($th->getMessage()); + } finally { + $command = "docker rm -f backup-of-{$this->backup->uuid}"; + instant_remote_process([$command], $this->server); } } + + private function save_backup_logs(): void + { + $this->backup_log->update([ + 'status' => $this->backup_status, + 'message' => $this->backup_output, + 'size' => $this->size, + ]); + + } } diff --git a/app/Models/Application.php b/app/Models/Application.php index 664b695b6..bc4d48b1a 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -8,25 +8,7 @@ class Application extends BaseModel { - protected $fillable = [ - 'name', - 'repository_project_id', - 'project_id', - 'description', - 'git_repository', - 'git_branch', - 'git_full_url', - 'build_pack', - 'environment_id', - 'destination_id', - 'destination_type', - 'source_id', - 'source_type', - 'ports_mappings', - 'ports_exposes', - 'publish_directory', - 'private_key_id' - ]; + protected $guarded = []; protected static function booted() { diff --git a/app/Models/Database.php b/app/Models/Database.php deleted file mode 100644 index 85434feea..000000000 --- a/app/Models/Database.php +++ /dev/null @@ -1,16 +0,0 @@ -belongsTo(Environment::class); - } - - public function destination() - { - return $this->morphTo(); - } -} diff --git a/app/Models/ScheduledDatabaseBackup.php b/app/Models/ScheduledDatabaseBackup.php index 795d4b9c8..5c41fc4dc 100644 --- a/app/Models/ScheduledDatabaseBackup.php +++ b/app/Models/ScheduledDatabaseBackup.php @@ -25,4 +25,9 @@ public function executions(): HasMany { return $this->hasMany(ScheduledDatabaseBackupExecution::class); } + + public function s3() + { + return $this->belongsTo(S3Storage::class, 's3_storage_id'); + } } diff --git a/app/Models/Service.php b/app/Models/Service.php deleted file mode 100644 index fab754360..000000000 --- a/app/Models/Service.php +++ /dev/null @@ -1,17 +0,0 @@ -belongsTo(Environment::class); - } - - public function destination() - { - return $this->morphTo(); - } -} diff --git a/app/Models/StandaloneDocker.php b/app/Models/StandaloneDocker.php index 9d9f44454..6ecc46a97 100644 --- a/app/Models/StandaloneDocker.php +++ b/app/Models/StandaloneDocker.php @@ -4,11 +4,7 @@ class StandaloneDocker extends BaseModel { - protected $fillable = [ - 'name', - 'network', - 'server_id', - ]; + protected $guarded = []; public function applications() { diff --git a/app/Models/Team.php b/app/Models/Team.php index 30b3980d5..d8d486fec 100644 --- a/app/Models/Team.php +++ b/app/Models/Team.php @@ -84,8 +84,8 @@ public function sources() return $sources; } - public function s3() + public function s3s() { - return $this->hasOne(S3Storage::class); + return $this->hasMany(S3Storage::class); } } diff --git a/app/Notifications/Database/BackupSuccess.php b/app/Notifications/Database/BackupSuccess.php index 36c8961ba..82b521019 100644 --- a/app/Notifications/Database/BackupSuccess.php +++ b/app/Notifications/Database/BackupSuccess.php @@ -36,7 +36,6 @@ public function via(object $notifiable): array if ($isDiscordEnabled && $isSubscribedToDiscordEvent) { $channels[] = DiscordChannel::class; } - ray($channels); return $channels; } diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 18882647b..21c72ebf6 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -30,6 +30,19 @@ function format_docker_labels_to_json($rawOutput): Collection })[0]; } +function format_docker_envs_to_json($rawOutput) +{ + try { + $outputLines = json_decode($rawOutput, true, flags: JSON_THROW_ON_ERROR); + return collect(data_get($outputLines[0], 'Config.Env', []))->mapWithKeys(function ($env) { + $env = explode('=', $env); + return [$env[0] => $env[1]]; + }); + } catch (\Throwable $th) { + return collect([]); + } +} + function get_container_status(Server $server, string $container_id, bool $all_data = false, bool $throwError = false) { $container = instant_remote_process(["docker inspect --format '{{json .}}' {$container_id}"], $server, $throwError); diff --git a/database/migrations/2023_08_07_142950_create_standalone_postgresqls_table.php b/database/migrations/2023_08_07_142950_create_standalone_postgresqls_table.php index 25f65e660..00f367de0 100644 --- a/database/migrations/2023_08_07_142950_create_standalone_postgresqls_table.php +++ b/database/migrations/2023_08_07_142950_create_standalone_postgresqls_table.php @@ -42,7 +42,7 @@ public function up(): void $table->timestamp('started_at')->nullable(); $table->morphs('destination'); - $table->foreignId('environment_id'); + $table->foreignId('environment_id')->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2023_08_08_150103_create_scheduled_database_backups_table.php b/database/migrations/2023_08_08_150103_create_scheduled_database_backups_table.php index 8eb76cd72..035f8a174 100644 --- a/database/migrations/2023_08_08_150103_create_scheduled_database_backups_table.php +++ b/database/migrations/2023_08_08_150103_create_scheduled_database_backups_table.php @@ -9,12 +9,14 @@ public function up(): void { Schema::create('scheduled_database_backups', function (Blueprint $table) { $table->id(); + $table->text('description')->nullable(); $table->string('uuid')->unique(); $table->boolean('enabled')->default(true); - $table->string('save_s3')->default(true); + $table->boolean('save_s3')->default(true); $table->string('frequency'); $table->integer('number_of_backups_locally')->default(7); $table->morphs('database'); + $table->foreignId('s3_storage_id')->nullable(); $table->foreignId('team_id'); $table->timestamps(); }); diff --git a/database/seeders/ApplicationSeeder.php b/database/seeders/ApplicationSeeder.php index 42997a708..f5b000662 100644 --- a/database/seeders/ApplicationSeeder.php +++ b/database/seeders/ApplicationSeeder.php @@ -2,7 +2,6 @@ namespace Database\Seeders; -use App\Data\ApplicationPreview; use App\Models\Application; use App\Models\GithubApp; use App\Models\StandaloneDocker; @@ -15,8 +14,6 @@ class ApplicationSeeder extends Seeder */ public function run(): void { - $github_public_source = GithubApp::where('name', 'Public GitHub')->first(); - Application::create([ 'name' => 'coollabsio/coolify-examples:nodejs-fastify', 'description' => 'NodeJS Fastify Example', @@ -28,9 +25,9 @@ public function run(): void 'ports_exposes' => '3000', 'ports_mappings' => '3000:3000', 'environment_id' => 1, - 'destination_id' => 1, + 'destination_id' => 0, 'destination_type' => StandaloneDocker::class, - 'source_id' => $github_public_source->id, + 'source_id' => 1, 'source_type' => GithubApp::class ]); } diff --git a/database/seeders/DBSeeder.php b/database/seeders/DBSeeder.php deleted file mode 100644 index 1e88129f8..000000000 --- a/database/seeders/DBSeeder.php +++ /dev/null @@ -1,23 +0,0 @@ - 1, - // 'name'=> "My first database", - // 'environment_id' => $environment_1->id, - // 'destination_id' => $standalone_docker_1->id, - // 'destination_type' => StandaloneDocker::class, - // ]); - } -} diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 135b749bc..2a2767d78 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -26,8 +26,6 @@ public function run(): void ApplicationSeeder::class, ApplicationSettingsSeeder::class, ApplicationPreviewSeeder::class, - DBSeeder::class, - ServiceSeeder::class, EnvironmentVariableSeeder::class, LocalPersistentVolumeSeeder::class, S3StorageSeeder::class, diff --git a/database/seeders/EnvironmentVariableSeeder.php b/database/seeders/EnvironmentVariableSeeder.php index d49e97fc2..a6e04a33b 100644 --- a/database/seeders/EnvironmentVariableSeeder.php +++ b/database/seeders/EnvironmentVariableSeeder.php @@ -2,7 +2,6 @@ namespace Database\Seeders; -use App\Models\EnvironmentVariable; use Illuminate\Database\Seeder; class EnvironmentVariableSeeder extends Seeder @@ -12,11 +11,11 @@ class EnvironmentVariableSeeder extends Seeder */ public function run(): void { - EnvironmentVariable::create([ - 'key' => 'NODE_ENV', - 'value' => 'production', - 'is_build_time' => true, - 'application_id' => 1, - ]); +// EnvironmentVariable::create([ +// 'key' => 'NODE_ENV', +// 'value' => 'production', +// 'is_build_time' => true, +// 'application_id' => 1, +// ]); } } diff --git a/database/seeders/GithubAppSeeder.php b/database/seeders/GithubAppSeeder.php index 681017e6e..1b5143988 100644 --- a/database/seeders/GithubAppSeeder.php +++ b/database/seeders/GithubAppSeeder.php @@ -3,8 +3,6 @@ namespace Database\Seeders; use App\Models\GithubApp; -use App\Models\PrivateKey; -use App\Models\Team; use Illuminate\Database\Seeder; class GithubAppSeeder extends Seeder @@ -14,14 +12,12 @@ class GithubAppSeeder extends Seeder */ public function run(): void { - $root_team = Team::find(0); - $private_key_2 = PrivateKey::find(1); GithubApp::create([ 'name' => 'Public GitHub', 'api_url' => 'https://api.github.com', 'html_url' => 'https://github.com', 'is_public' => true, - 'team_id' => $root_team->id, + 'team_id' => 0, ]); GithubApp::create([ 'name' => 'coolify-laravel-development-public', @@ -34,8 +30,8 @@ public function run(): void 'client_id' => 'Iv1.220e564d2b0abd8c', 'client_secret' => '116d1d80289f378410dd70ab4e4b81dd8d2c52b6', 'webhook_secret' => '326a47b49054f03288f800d81247ec9414d0abf3', - 'private_key_id' => $private_key_2->id, - 'team_id' => $root_team->id, + 'private_key_id' => 1, + 'team_id' => 0, ]); } } diff --git a/database/seeders/GitlabAppSeeder.php b/database/seeders/GitlabAppSeeder.php index 9a7165844..340e7d44f 100644 --- a/database/seeders/GitlabAppSeeder.php +++ b/database/seeders/GitlabAppSeeder.php @@ -3,8 +3,6 @@ namespace Database\Seeders; use App\Models\GitlabApp; -use App\Models\PrivateKey; -use App\Models\Team; use Illuminate\Database\Seeder; class GitlabAppSeeder extends Seeder @@ -14,15 +12,13 @@ class GitlabAppSeeder extends Seeder */ public function run(): void { - $root_team = Team::find(0); - $private_key_2 = PrivateKey::find(2); GitlabApp::create([ 'id' => 1, 'name' => 'Public GitLab', 'api_url' => 'https://gitlab.com/api/v4', 'html_url' => 'https://gitlab.com', 'is_public' => true, - 'team_id' => $root_team->id, + 'team_id' => 0, ]); GitlabApp::create([ 'id' => 2, @@ -35,8 +31,8 @@ public function run(): void 'deploy_key_id' => '1234', 'public_key' => 'dfjasiourj', 'webhook_token' => '4u3928u4y392', - 'private_key_id' => $private_key_2->id, - 'team_id' => $root_team->id, + 'private_key_id' => 2, + 'team_id' => 0 ]); } } diff --git a/database/seeders/PrivateKeySeeder.php b/database/seeders/PrivateKeySeeder.php index d86f25fbc..d0c9a4570 100644 --- a/database/seeders/PrivateKeySeeder.php +++ b/database/seeders/PrivateKeySeeder.php @@ -3,7 +3,6 @@ namespace Database\Seeders; use App\Models\PrivateKey; -use App\Models\Team; use Illuminate\Database\Seeder; class PrivateKeySeeder extends Seeder @@ -13,10 +12,9 @@ class PrivateKeySeeder extends Seeder */ public function run(): void { - $team_1 = Team::find(0); PrivateKey::create([ "id" => 0, - "team_id" => $team_1->id, + "team_id" => 0, "name" => "Testing-host", "description" => "This is a test docker container", "private_key" => "-----BEGIN OPENSSH PRIVATE KEY----- @@ -30,7 +28,7 @@ public function run(): void ]); PrivateKey::create([ - "team_id" => $team_1->id, + "team_id" => 0, "name" => "development-github-app", "description" => "This is the key for using the development GitHub app", "private_key" => "-----BEGIN RSA PRIVATE KEY----- @@ -63,7 +61,7 @@ public function run(): void "is_git_related" => true ]); PrivateKey::create([ - "team_id" => $team_1->id, + "team_id" => 0, "name" => "development-gitlab-app", "description" => "This is the key for using the development Gitlab app", "private_key" => "asdf" diff --git a/database/seeders/ProjectSeeder.php b/database/seeders/ProjectSeeder.php index 6aaca3833..304417ed5 100644 --- a/database/seeders/ProjectSeeder.php +++ b/database/seeders/ProjectSeeder.php @@ -3,18 +3,16 @@ namespace Database\Seeders; use App\Models\Project; -use App\Models\Team; use Illuminate\Database\Seeder; class ProjectSeeder extends Seeder { public function run(): void { - $root_team = Team::find(0); Project::create([ 'name' => "My first project", 'description' => "This is a test project in development", - 'team_id' => $root_team->id, + 'team_id' => 0, ]); } } diff --git a/database/seeders/ProjectSettingSeeder.php b/database/seeders/ProjectSettingSeeder.php index 2fe41976f..d0a837335 100644 --- a/database/seeders/ProjectSettingSeeder.php +++ b/database/seeders/ProjectSettingSeeder.php @@ -2,15 +2,14 @@ namespace Database\Seeders; -use App\Models\Project; use Illuminate\Database\Seeder; class ProjectSettingSeeder extends Seeder { public function run(): void { - $first_project = Project::find(1); +// $first_project = Project::find(1); // $first_project->settings->wildcard_domain = 'wildcard.example.com'; - $first_project->settings->save(); +// $first_project->settings->save(); } } diff --git a/database/seeders/ScheduledDatabaseBackupSeeder.php b/database/seeders/ScheduledDatabaseBackupSeeder.php index a6fa6d820..96ca0c012 100644 --- a/database/seeders/ScheduledDatabaseBackupSeeder.php +++ b/database/seeders/ScheduledDatabaseBackupSeeder.php @@ -18,6 +18,15 @@ public function run(): void 'number_of_backups_locally' => 2, 'database_id' => 1, 'database_type' => 'App\Models\StandalonePostgresql', + 's3_storage_id' => 1, + 'team_id' => 0, + ]); + ScheduledDatabaseBackup::create([ + 'enabled' => true, + 'frequency' => '* * * * *', + 'number_of_backups_locally' => 3, + 'database_id' => 1, + 'database_type' => 'App\Models\StandalonePostgresql', 'team_id' => 0, ]); } diff --git a/database/seeders/ServerSeeder.php b/database/seeders/ServerSeeder.php index a781ca1de..77a4516e5 100644 --- a/database/seeders/ServerSeeder.php +++ b/database/seeders/ServerSeeder.php @@ -2,36 +2,24 @@ namespace Database\Seeders; -use App\Models\PrivateKey; use App\Models\Server; -use App\Models\Team; use Illuminate\Database\Seeder; class ServerSeeder extends Seeder { public function run(): void { - $root_team = Team::find(0); - $private_key_1 = PrivateKey::find(0); - Server::create([ 'id' => 0, 'name' => "testing-local-docker-container", 'description' => "This is a test docker container", 'ip' => "coolify-testing-host", - 'team_id' => $root_team->id, - 'private_key_id' => $private_key_1->id, + 'team_id' => 0, + 'private_key_id' => 0, // 'proxy' => ServerMetadata::from([ // 'type' => ProxyTypes::TRAEFIK_V2->value, // 'status' => ProxyStatus::EXITED->value // ]), ]); - Server::create([ - 'name' => "testing-local-docker-container-2", - 'description' => "This is a test docker container", - 'ip' => "coolify-testing-host-2", - 'team_id' => $root_team->id, - 'private_key_id' => $private_key_1->id - ]); } } diff --git a/database/seeders/ServerSettingSeeder.php b/database/seeders/ServerSettingSeeder.php index 59fe07c99..6d8c68188 100644 --- a/database/seeders/ServerSettingSeeder.php +++ b/database/seeders/ServerSettingSeeder.php @@ -18,11 +18,5 @@ public function run(): void $server_2->settings->is_usable = true; $server_2->settings->is_reachable = true; $server_2->settings->save(); - - $server_3 = Server::find(1)->load(['settings']); - $server_3->settings->is_part_of_swarm = false; - $server_2->settings->is_usable = false; - $server_3->settings->is_reachable = false; - $server_3->settings->save(); } } diff --git a/database/seeders/ServiceSeeder.php b/database/seeders/ServiceSeeder.php deleted file mode 100644 index c016d89e6..000000000 --- a/database/seeders/ServiceSeeder.php +++ /dev/null @@ -1,26 +0,0 @@ - 1, - // 'name'=> "My first service", - // 'environment_id' => $environment_1->id, - // 'destination_id' => $standalone_docker_1->id, - // 'destination_type' => StandaloneDocker::class, - // ]); - } -} diff --git a/database/seeders/StandaloneDockerSeeder.php b/database/seeders/StandaloneDockerSeeder.php index 8b1bfa76a..9f67de710 100644 --- a/database/seeders/StandaloneDockerSeeder.php +++ b/database/seeders/StandaloneDockerSeeder.php @@ -3,7 +3,6 @@ namespace Database\Seeders; use App\Models\Destination; -use App\Models\Server; use App\Models\StandaloneDocker; use Illuminate\Database\Seeder; @@ -14,11 +13,11 @@ class StandaloneDockerSeeder extends Seeder */ public function run(): void { - $server_1 = Server::find(0); StandaloneDocker::create([ + 'id' => 0, 'name' => 'Standalone Docker 1', 'network' => 'coolify', - 'server_id' => $server_1->id, + 'server_id' => 0, ]); } } diff --git a/database/seeders/StandalonePostgresqlSeeder.php b/database/seeders/StandalonePostgresqlSeeder.php index fefeee38e..1fc96a610 100644 --- a/database/seeders/StandalonePostgresqlSeeder.php +++ b/database/seeders/StandalonePostgresqlSeeder.php @@ -15,7 +15,7 @@ public function run(): void 'description' => 'Local PostgreSQL for testing', 'postgres_password' => 'postgres', 'environment_id' => 1, - 'destination_id' => 1, + 'destination_id' => 0, 'destination_type' => StandaloneDocker::class, ]); } diff --git a/database/seeders/SwarmDockerSeeder.php b/database/seeders/SwarmDockerSeeder.php index dc2934ead..906e1bccc 100644 --- a/database/seeders/SwarmDockerSeeder.php +++ b/database/seeders/SwarmDockerSeeder.php @@ -3,7 +3,6 @@ namespace Database\Seeders; use App\Models\Destination; -use App\Models\Server; use App\Models\SwarmDocker; use Illuminate\Database\Seeder; @@ -14,10 +13,9 @@ class SwarmDockerSeeder extends Seeder */ public function run(): void { - $server_2 = Server::find(1); SwarmDocker::create([ 'name' => 'Swarm Docker 1', - 'server_id' => $server_2->id, + 'server_id' => 1, ]); } } diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 75320e374..df1beff70 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -33,14 +33,14 @@ services: POSTGRES_DB: "${DB_DATABASE:-coolify}" POSTGRES_HOST_AUTH_METHOD: "trust" volumes: - - ./_data/_volumes/database/:/var/lib/postgresql/data + - /data/coolify/_volumes/database/:/var/lib/postgresql/data redis: ports: - "${FORWARD_REDIS_PORT:-6379}:6379" env_file: - .env volumes: - - ./_data/_volumes/redis/:/data + - /data/coolify/_volumes/redis/:/data vite: image: node:19 working_dir: /var/www/html @@ -54,13 +54,7 @@ services: container_name: coolify-testing-host volumes: - /var/run/docker.sock:/var/run/docker.sock - - "./_data/_servers/testing-local-docker-container:/data/coolify" - testing-host-2: - <<: *testing-host-base - container_name: coolify-testing-host-2 - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - "./_data/_servers/testing-local-docker-container-2:/data/coolify" + - /data/coolify/:/data/coolify mailpit: image: "axllent/mailpit:latest" container_name: coolify-mail @@ -80,13 +74,6 @@ services: MINIO_ACCESS_KEY: "${MINIO_ACCESS_KEY:-minioadmin}" MINIO_SECRET_KEY: "${MINIO_SECRET_KEY:-minioadmin}" volumes: - - ./_data/_volumes/minio/:/data + - /data/coolify/_volumes/minio/:/data networks: - coolify - # buggregator: - # image: ghcr.io/buggregator/server:latest - # container_name: coolify-debug - # ports: - # - 8001:8000 - # networks: - # - coolify diff --git a/docker/coolify-builder/Dockerfile b/docker/coolify-builder/Dockerfile deleted file mode 100644 index e1cdbe8cd..000000000 --- a/docker/coolify-builder/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -FROM alpine:3.17 - -ARG TARGETPLATFORM -# https://download.docker.com/linux/static/stable/ -ARG DOCKER_VERSION=23.0.6 -# https://github.com/docker/compose/releases -ARG DOCKER_COMPOSE_VERSION=2.18.1 -# https://github.com/docker/buildx/releases -ARG DOCKER_BUILDX_VERSION=0.10.5 -# https://github.com/buildpacks/pack/releases -ARG PACK_VERSION=0.29.0 -# https://github.com/railwayapp/nixpacks/releases -ARG NIXPACKS_VERSION=1.12.0 - -USER root -WORKDIR /artifacts -RUN apk add --no-cache bash curl git git-lfs openssh-client tar tini -RUN mkdir -p ~/.docker/cli-plugins -RUN if [[ ${TARGETPLATFORM} == 'linux/amd64' ]]; then \ - curl -sSL https://github.com/docker/buildx/releases/download/v${DOCKER_BUILDX_VERSION}/buildx-v${DOCKER_BUILDX_VERSION}.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx && \ - curl -sSL https://github.com/docker/compose/releases/download/v${DOCKER_COMPOSE_VERSION}/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose && \ - (curl -sSL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz | tar -C /usr/bin/ --no-same-owner -xzv --strip-components=1 docker/docker) && \ - (curl -sSL https://github.com/buildpacks/pack/releases/download/v${PACK_VERSION}/pack-v${PACK_VERSION}-linux.tgz | tar -C /usr/local/bin/ --no-same-owner -xzv pack) && \ - curl -sSL https://nixpacks.com/install.sh | bash && \ - chmod +x ~/.docker/cli-plugins/docker-compose /usr/bin/docker /usr/local/bin/pack /root/.docker/cli-plugins/docker-buildx \ - ;fi - -RUN if [[ ${TARGETPLATFORM} == 'linux/arm64' ]]; then \ - curl -sSL https://github.com/docker/buildx/releases/download/v${DOCKER_BUILDX_VERSION}/buildx-v${DOCKER_BUILDX_VERSION}.linux-arm64 -o ~/.docker/cli-plugins/docker-buildx && \ - curl -sSL https://github.com/docker/compose/releases/download/v${DOCKER_COMPOSE_VERSION}/docker-compose-linux-aarch64 -o ~/.docker/cli-plugins/docker-compose && \ - (curl -sSL https://download.docker.com/linux/static/stable/aarch64/docker-${DOCKER_VERSION}.tgz | tar -C /usr/bin/ --no-same-owner -xzv --strip-components=1 docker/docker) && \ - (curl -sSL https://github.com/buildpacks/pack/releases/download/v${PACK_VERSION}/pack-v${PACK_VERSION}-linux-arm64.tgz | tar -C /usr/local/bin/ --no-same-owner -xzv pack) && \ - curl -sSL https://nixpacks.com/install.sh | bash && \ - chmod +x ~/.docker/cli-plugins/docker-compose /usr/bin/docker /usr/local/bin/pack /root/.docker/cli-plugins/docker-buildx \ - ;fi - -ENTRYPOINT ["/sbin/tini", "--"] -CMD ["sh", "-c", "while true; do sleep 1; done"] - diff --git a/resources/views/components/forms/select.blade.php b/resources/views/components/forms/select.blade.php index a9e092936..09a9fadb0 100644 --- a/resources/views/components/forms/select.blade.php +++ b/resources/views/components/forms/select.blade.php @@ -15,4 +15,9 @@ @if ($attributes->whereStartsWith('wire:model')->first()) {{ $attributes->whereStartsWith('wire:model')->first() }} @else wire:model.defer={{ $id }} @endif> {{ $slot }} + @error($id) + + @enderror diff --git a/resources/views/components/settings/navbar.blade.php b/resources/views/components/settings/navbar.blade.php index ea3dd6c49..f7e5ebb94 100644 --- a/resources/views/components/settings/navbar.blade.php +++ b/resources/views/components/settings/navbar.blade.php @@ -1,15 +1,11 @@ -