From fb34eb53945fbf1455c2132b3d02fc076bd3557e Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sun, 27 Aug 2023 15:49:35 +0200 Subject: [PATCH 01/44] new version --- config/version.php | 2 +- versions.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/version.php b/config/version.php index 7ea9c5731..06255e53e 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ Date: Sun, 27 Aug 2023 16:23:02 +0200 Subject: [PATCH 02/44] disable docker cleanup job --- app/Console/Kernel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 0dc99ba8a..48478aced 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -33,7 +33,7 @@ class Kernel extends ConsoleKernel $schedule->job(new ResourceStatusJob)->everyMinute(); $schedule->job(new CheckResaleLicenseJob)->hourly(); $schedule->job(new ProxyCheckJob)->everyFiveMinutes(); - $schedule->job(new DockerCleanupJob)->everyTenMinutes(); + // $schedule->job(new DockerCleanupJob)->everyTenMinutes(); $schedule->job(new InstanceAutoUpdateJob)->everyTenMinutes(); } $this->check_scheduled_backups($schedule); From ab1207e461614ad8ef7b2d9c74c018c28117c5e5 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sun, 27 Aug 2023 21:36:11 +0200 Subject: [PATCH 03/44] fix:dockerCleanupjob --- app/Console/Kernel.php | 2 +- app/Jobs/DockerCleanupJob.php | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 48478aced..0dc99ba8a 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -33,7 +33,7 @@ class Kernel extends ConsoleKernel $schedule->job(new ResourceStatusJob)->everyMinute(); $schedule->job(new CheckResaleLicenseJob)->hourly(); $schedule->job(new ProxyCheckJob)->everyFiveMinutes(); - // $schedule->job(new DockerCleanupJob)->everyTenMinutes(); + $schedule->job(new DockerCleanupJob)->everyTenMinutes(); $schedule->job(new InstanceAutoUpdateJob)->everyTenMinutes(); } $this->check_scheduled_backups($schedule); diff --git a/app/Jobs/DockerCleanupJob.php b/app/Jobs/DockerCleanupJob.php index 7a8571c00..a03ba409c 100644 --- a/app/Jobs/DockerCleanupJob.php +++ b/app/Jobs/DockerCleanupJob.php @@ -32,6 +32,11 @@ class DockerCleanupJob implements ShouldQueue try { $servers = Server::all(); foreach ($servers as $server) { + if ( + !$server->settings->is_reachable && !$server->settings->is_usable + ) { + continue; + } if (isDev()) { $docker_root_filesystem = "/"; } else { From 5ca0237e346c53c5264bd5279a2dd1e3ba784bba Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sun, 27 Aug 2023 22:05:37 +0200 Subject: [PATCH 04/44] fix logging on ui --- app/Traits/ExecuteRemoteCommand.php | 1 + .../livewire/project/application/deployment-logs.blade.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Traits/ExecuteRemoteCommand.php b/app/Traits/ExecuteRemoteCommand.php index 24e17a73d..fd20c3764 100644 --- a/app/Traits/ExecuteRemoteCommand.php +++ b/app/Traits/ExecuteRemoteCommand.php @@ -41,6 +41,7 @@ trait ExecuteRemoteCommand $remote_command = generate_ssh_command($private_key_location, $ip, $user, $port, $command); $process = Process::timeout(3600)->idleTimeout(3600)->start($remote_command, function (string $type, string $output) use ($command, $hidden) { + $output = Str::of($output)->trim(); $new_log_entry = [ 'command' => $command, 'output' => $output, diff --git a/resources/views/livewire/project/application/deployment-logs.blade.php b/resources/views/livewire/project/application/deployment-logs.blade.php index 1a0c5116f..f354083b3 100644 --- a/resources/views/livewire/project/application/deployment-logs.blade.php +++ b/resources/views/livewire/project/application/deployment-logs.blade.php @@ -18,12 +18,12 @@ @if (decode_remote_command_output($application_deployment_queue)->count() > 0) @foreach (decode_remote_command_output($application_deployment_queue) as $line)
$line['type'] == 'stdout', 'text-error' => $line['type'] == 'stderr', 'text-warning' => $line['hidden'], ])>[{{ $line['timestamp'] }}] @if ($line['hidden']) -
Command: {{ $line['command'] }}
Output: +
COMMAND:
{{ $line['command'] }}

OUTPUT: @endif{{ $line['output'] }}@if ($line['hidden']) @endif
From 61a54f48c528cf4153319cd6cfb8a8a6496e98f4 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 28 Aug 2023 10:44:11 +0200 Subject: [PATCH 05/44] update --- bootstrap/helpers/docker.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 8ee0765a5..1094fb06f 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -58,9 +58,11 @@ function format_docker_envs_to_json($rawOutput) } function getApplicationContainerStatus(Application $application) { - $server = $application->destination->server; + $server = data_get($application,'destination.server'); $id = $application->id; - + if (!$server) { + return 'exited'; + } $containers = getCurrentApplicationContainerStatus($server, $id); if ($containers->count() > 0) { $status = data_get($containers[0], 'State', 'exited'); From 0dfd3a5b0e87268f08829c687613cecc56935ca6 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 28 Aug 2023 11:43:01 +0200 Subject: [PATCH 06/44] run scheduled jobs on one server --- app/Console/Kernel.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 0dc99ba8a..ffedc6e72 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -29,11 +29,11 @@ class Kernel extends ConsoleKernel // $schedule->job(new InstanceAutoUpdateJob(true))->everyMinute(); } else { $schedule->command('horizon:snapshot')->everyFiveMinutes(); - $schedule->job(new CleanupInstanceStuffsJob)->everyMinute(); - $schedule->job(new ResourceStatusJob)->everyMinute(); - $schedule->job(new CheckResaleLicenseJob)->hourly(); - $schedule->job(new ProxyCheckJob)->everyFiveMinutes(); - $schedule->job(new DockerCleanupJob)->everyTenMinutes(); + $schedule->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer(); + $schedule->job(new ResourceStatusJob)->everyMinute()->onOneServer(); + $schedule->job(new CheckResaleLicenseJob)->hourly()->onOneServer(); + $schedule->job(new ProxyCheckJob)->everyFiveMinutes()->onOneServer(); + $schedule->job(new DockerCleanupJob)->everyTenMinutes()->onOneServer(); $schedule->job(new InstanceAutoUpdateJob)->everyTenMinutes(); } $this->check_scheduled_backups($schedule); From 761775657662085b2c30fe57e1cb7c292e2f9e69 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 28 Aug 2023 13:32:36 +0200 Subject: [PATCH 07/44] remove dynamic sentry version checker --- config/sentry.php | 2 +- docker-compose.cloud.yml | 84 ++++++++++++++++++++++++++++++++++++++++ docker-compose.prod.yml | 2 +- 3 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 docker-compose.cloud.yml diff --git a/config/sentry.php b/config/sentry.php index 12c418325..3a4d999a5 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -7,7 +7,7 @@ return [ // The release version of your application // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) - 'release' => trim(exec('jq -r .coolify.v4.version versions.json 2>/dev/null')) ?? 'unknown', + 'release' => '4.0.0-beta.21', 'server_name' => env('APP_ID', 'coolify'), // When left empty or `null` the Laravel environment will be used 'environment' => config('app.env'), diff --git a/docker-compose.cloud.yml b/docker-compose.cloud.yml new file mode 100644 index 000000000..f85a4c7fa --- /dev/null +++ b/docker-compose.cloud.yml @@ -0,0 +1,84 @@ +version: "3.8" +services: + coolify: + image: "ghcr.io/coollabsio/coolify:${LATEST_IMAGE:-next}" + container_name: coolify + restart: always + working_dir: /var/www/html + extra_hosts: + - "host.docker.internal:host-gateway" + networks: + - coolify + volumes: + - type: bind + source: /data/coolify/source/.env + target: /var/www/html/.env + read_only: true + - /data/coolify/ssh:/var/www/html/storage/app/ssh + - /data/coolify/applications:/var/www/html/storage/app/applications + - /data/coolify/databases:/var/www/html/storage/app/databases + - /data/coolify/backups:/var/www/html/storage/app/backups + environment: + - APP_ID + - APP_ENV=production + - APP_DEBUG + - APP_NAME + - APP_KEY + - APP_URL + - DB_CONNECTION + - DB_HOST + - DB_PORT + - DB_DATABASE + - DB_USERNAME + - DB_PASSWORD + - QUEUE_CONNECTION + - REDIS_HOST + - REDIS_PASSWORD + - SSL_MODE=off + - PHP_PM_CONTROL=dynamic + - PHP_PM_START_SERVERS=1 + - PHP_PM_MIN_SPARE_SERVERS=1 + - PHP_PM_MAX_SPARE_SERVERS=10 + - SELF_HOSTED + - WAITLIST + - SUBSCRIPTION_PROVIDER + - STRIPE_API_KEY + - STRIPE_WEBHOOK_SECRET + - STRIPE_PRICE_ID_BASIC_MONTHLY + - STRIPE_PRICE_ID_BASIC_YEARLY + - STRIPE_PRICE_ID_PRO_MONTHLY + - STRIPE_PRICE_ID_PRO_YEARLY + - STRIPE_PRICE_ID_ULTIMATE_MONTHLY + - STRIPE_PRICE_ID_ULTIMATE_YEARLY + - PADDLE_VENDOR_ID + - PADDLE_WEBHOOK_SECRET + - PADDLE_VENDOR_AUTH_CODE + - PADDLE_PUBLIC_KEY + - PADDLE_PRICE_ID_BASIC_MONTHLY + - PADDLE_PRICE_ID_BASIC_YEARLY + - PADDLE_PRICE_ID_PRO_MONTHLY + - PADDLE_PRICE_ID_PRO_YEARLY + - PADDLE_PRICE_ID_ULTIMATE_MONTHLY + - PADDLE_PRICE_ID_ULTIMATE_YEARLY + - LEMON_SQUEEZY_API_KEY + - LEMON_SQUEEZY_WEBHOOK_SECRET + - LEMON_SQUEEZY_CHECKOUT_ID_BASIC_MONTHLY + - LEMON_SQUEEZY_CHECKOUT_ID_BASIC_YEARLY + - LEMON_SQUEEZY_CHECKOUT_ID_PRO_MONTHLY + - LEMON_SQUEEZY_CHECKOUT_ID_PRO_YEARLY + - LEMON_SQUEEZY_CHECKOUT_ID_ULTIMATE_MONTHLY + - LEMON_SQUEEZY_CHECKOUT_ID_ULTIMATE_YEARLY + - LEMON_SQUEEZY_BASIC_PLAN_IDS + - LEMON_SQUEEZY_PRO_PLAN_IDS + - LEMON_SQUEEZY_ULTIMATE_PLAN_IDS + ports: + - ":8000:80" + healthcheck: + test: curl --fail http://localhost:80/api/health || exit 1 + interval: 4s + retries: 5 + timeout: 2s +networks: + coolify: + name: coolify + driver: bridge diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 710f44f2c..6268f9963 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -1,7 +1,7 @@ version: '3.8' services: coolify: - image: "ghcr.io/coollabsio/coolify:${LATEST_IMAGE:-4.0.0-nightly.0}" + image: "ghcr.io/coollabsio/coolify:${LATEST_IMAGE:-4.0.0-beta.20}" volumes: - type: bind source: /data/coolify/source/.env From a5ce191e4dccd0bf9633a99cb970c06d7e9ccf57 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 28 Aug 2023 13:33:20 +0200 Subject: [PATCH 08/44] add example cloud --- .env.cloud | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .env.cloud diff --git a/.env.cloud b/.env.cloud new file mode 100644 index 000000000..fd4892cc8 --- /dev/null +++ b/.env.cloud @@ -0,0 +1,7 @@ +APP_ID= +APP_NAME=coolify-cloud +APP_KEY= +DB_HOST= +DB_PASSWORD= +REDIS_HOST= +REDIS_PASSWORD= From 2bb778834bcb2389f42fd19b385e9bbd4efce554 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 28 Aug 2023 14:40:18 +0200 Subject: [PATCH 09/44] remove cloud configs --- .env.cloud | 7 ---- docker-compose.cloud.yml | 84 ---------------------------------------- 2 files changed, 91 deletions(-) delete mode 100644 .env.cloud delete mode 100644 docker-compose.cloud.yml diff --git a/.env.cloud b/.env.cloud deleted file mode 100644 index fd4892cc8..000000000 --- a/.env.cloud +++ /dev/null @@ -1,7 +0,0 @@ -APP_ID= -APP_NAME=coolify-cloud -APP_KEY= -DB_HOST= -DB_PASSWORD= -REDIS_HOST= -REDIS_PASSWORD= diff --git a/docker-compose.cloud.yml b/docker-compose.cloud.yml deleted file mode 100644 index f85a4c7fa..000000000 --- a/docker-compose.cloud.yml +++ /dev/null @@ -1,84 +0,0 @@ -version: "3.8" -services: - coolify: - image: "ghcr.io/coollabsio/coolify:${LATEST_IMAGE:-next}" - container_name: coolify - restart: always - working_dir: /var/www/html - extra_hosts: - - "host.docker.internal:host-gateway" - networks: - - coolify - volumes: - - type: bind - source: /data/coolify/source/.env - target: /var/www/html/.env - read_only: true - - /data/coolify/ssh:/var/www/html/storage/app/ssh - - /data/coolify/applications:/var/www/html/storage/app/applications - - /data/coolify/databases:/var/www/html/storage/app/databases - - /data/coolify/backups:/var/www/html/storage/app/backups - environment: - - APP_ID - - APP_ENV=production - - APP_DEBUG - - APP_NAME - - APP_KEY - - APP_URL - - DB_CONNECTION - - DB_HOST - - DB_PORT - - DB_DATABASE - - DB_USERNAME - - DB_PASSWORD - - QUEUE_CONNECTION - - REDIS_HOST - - REDIS_PASSWORD - - SSL_MODE=off - - PHP_PM_CONTROL=dynamic - - PHP_PM_START_SERVERS=1 - - PHP_PM_MIN_SPARE_SERVERS=1 - - PHP_PM_MAX_SPARE_SERVERS=10 - - SELF_HOSTED - - WAITLIST - - SUBSCRIPTION_PROVIDER - - STRIPE_API_KEY - - STRIPE_WEBHOOK_SECRET - - STRIPE_PRICE_ID_BASIC_MONTHLY - - STRIPE_PRICE_ID_BASIC_YEARLY - - STRIPE_PRICE_ID_PRO_MONTHLY - - STRIPE_PRICE_ID_PRO_YEARLY - - STRIPE_PRICE_ID_ULTIMATE_MONTHLY - - STRIPE_PRICE_ID_ULTIMATE_YEARLY - - PADDLE_VENDOR_ID - - PADDLE_WEBHOOK_SECRET - - PADDLE_VENDOR_AUTH_CODE - - PADDLE_PUBLIC_KEY - - PADDLE_PRICE_ID_BASIC_MONTHLY - - PADDLE_PRICE_ID_BASIC_YEARLY - - PADDLE_PRICE_ID_PRO_MONTHLY - - PADDLE_PRICE_ID_PRO_YEARLY - - PADDLE_PRICE_ID_ULTIMATE_MONTHLY - - PADDLE_PRICE_ID_ULTIMATE_YEARLY - - LEMON_SQUEEZY_API_KEY - - LEMON_SQUEEZY_WEBHOOK_SECRET - - LEMON_SQUEEZY_CHECKOUT_ID_BASIC_MONTHLY - - LEMON_SQUEEZY_CHECKOUT_ID_BASIC_YEARLY - - LEMON_SQUEEZY_CHECKOUT_ID_PRO_MONTHLY - - LEMON_SQUEEZY_CHECKOUT_ID_PRO_YEARLY - - LEMON_SQUEEZY_CHECKOUT_ID_ULTIMATE_MONTHLY - - LEMON_SQUEEZY_CHECKOUT_ID_ULTIMATE_YEARLY - - LEMON_SQUEEZY_BASIC_PLAN_IDS - - LEMON_SQUEEZY_PRO_PLAN_IDS - - LEMON_SQUEEZY_ULTIMATE_PLAN_IDS - ports: - - ":8000:80" - healthcheck: - test: curl --fail http://localhost:80/api/health || exit 1 - interval: 4s - retries: 5 - timeout: 2s -networks: - coolify: - name: coolify - driver: bridge From 5989eb8f6ec3f3226c904ce8b8489b3ed295c1b6 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 28 Aug 2023 15:02:03 +0200 Subject: [PATCH 10/44] rename license server --- config/coolify.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/coolify.php b/config/coolify.php index f3485f0da..bb9e67364 100644 --- a/config/coolify.php +++ b/config/coolify.php @@ -3,7 +3,7 @@ return [ 'self_hosted' => env('SELF_HOSTED', true), 'waitlist' => env('WAITLIST', false), - 'license_url' => 'https://license.coolify.io', + 'license_url' => 'https://licenses.coollabs.io', 'mux_enabled' => env('MUX_ENABLED', true), 'dev_webhook' => env('SERVEO_URL'), 'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'), From af30d0831d68788836510eb30ccad262abbf43eb Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 28 Aug 2023 15:03:44 +0200 Subject: [PATCH 11/44] do not seed in coolify cloud --- database/seeders/ProductionSeeder.php | 100 +++++++++++++------------- 1 file changed, 51 insertions(+), 49 deletions(-) diff --git a/database/seeders/ProductionSeeder.php b/database/seeders/ProductionSeeder.php index 09a420504..8b6ee3141 100644 --- a/database/seeders/ProductionSeeder.php +++ b/database/seeders/ProductionSeeder.php @@ -45,60 +45,62 @@ class ProductionSeeder extends Seeder ]); } - // Save SSH Keys for the Coolify Host - $coolify_key_name = "id.root@host.docker.internal"; - $coolify_key = Storage::disk('ssh-keys')->get("{$coolify_key_name}"); + if (config('app.name') !== 'coolify-cloud') { + // Save SSH Keys for the Coolify Host + $coolify_key_name = "id.root@host.docker.internal"; + $coolify_key = Storage::disk('ssh-keys')->get("{$coolify_key_name}"); - if ($coolify_key) { - PrivateKey::updateOrCreate( - [ + if ($coolify_key) { + PrivateKey::updateOrCreate( + [ + 'id' => 0, + 'name' => 'localhost\'s key', + 'description' => 'The private key for the Coolify host machine (localhost).', + 'team_id' => 0, + ], + ['private_key' => $coolify_key] + ); + } else { + echo "No SSH key found for the Coolify host machine (localhost).\n"; + echo "Please generate one and save it in /data/coolify/ssh/keys/{$coolify_key_name}\n"; + echo "Then try to install again.\n"; + exit(1); + } + // Add Coolify host (localhost) as Server if it doesn't exist + if (Server::find(0) == null) { + $server_details = [ 'id' => 0, - 'name' => 'localhost\'s key', - 'description' => 'The private key for the Coolify host machine (localhost).', + 'name' => "localhost", + 'description' => "This is the server where Coolify is running on. Don't delete this!", + 'user' => 'root', + 'ip' => "host.docker.internal", 'team_id' => 0, - ], - ['private_key' => $coolify_key] - ); - } else { - echo "No SSH key found for the Coolify host machine (localhost).\n"; - echo "Please generate one and save it in /data/coolify/ssh/keys/{$coolify_key_name}\n"; - echo "Then try to install again.\n"; - exit(1); + 'private_key_id' => 0 + ]; + $server_details['proxy'] = ServerMetadata::from([ + 'type' => ProxyTypes::TRAEFIK_V2->value, + 'status' => ProxyStatus::EXITED->value + ]); + $server = Server::create($server_details); + $server->settings->is_reachable = true; + $server->settings->is_usable = true; + $server->settings->save(); + } else { + $server = Server::find(0); + $server->settings->is_reachable = true; + $server->settings->is_usable = true; + $server->settings->save(); + } + if (StandaloneDocker::find(0) == null) { + StandaloneDocker::create([ + 'id' => 0, + 'name' => 'localhost-coolify', + 'network' => 'coolify', + 'server_id' => 0, + ]); + } } - // Add Coolify host (localhost) as Server if it doesn't exist - if (Server::find(0) == null) { - $server_details = [ - 'id' => 0, - 'name' => "localhost", - 'description' => "This is the server where Coolify is running on. Don't delete this!", - 'user' => 'root', - 'ip' => "host.docker.internal", - 'team_id' => 0, - 'private_key_id' => 0 - ]; - $server_details['proxy'] = ServerMetadata::from([ - 'type' => ProxyTypes::TRAEFIK_V2->value, - 'status' => ProxyStatus::EXITED->value - ]); - $server = Server::create($server_details); - $server->settings->is_reachable = true; - $server->settings->is_usable = true; - $server->settings->save(); - } else { - $server = Server::find(0); - $server->settings->is_reachable = true; - $server->settings->is_usable = true; - $server->settings->save(); - } - if (StandaloneDocker::find(0) == null) { - StandaloneDocker::create([ - 'id' => 0, - 'name' => 'localhost-coolify', - 'network' => 'coolify', - 'server_id' => 0, - ]); - } try { $settings = InstanceSettings::get(); if (is_null($settings->public_ipv4)) { From f48a9122872dd3fc77958326c897f9f88c52fbcf Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 28 Aug 2023 18:02:31 +0200 Subject: [PATCH 12/44] update cloud no localhost server --- app/Actions/Server/UpdateCoolify.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/Actions/Server/UpdateCoolify.php b/app/Actions/Server/UpdateCoolify.php index 0be05894f..e988965ec 100644 --- a/app/Actions/Server/UpdateCoolify.php +++ b/app/Actions/Server/UpdateCoolify.php @@ -17,7 +17,11 @@ class UpdateCoolify $settings = InstanceSettings::get(); ray('Running InstanceAutoUpdateJob'); $localhost_name = 'localhost'; - $this->server = Server::where('name', $localhost_name)->firstOrFail(); + $this->server = Server::where('name', $localhost_name)->first(); + if (!$this->server) { + // No server found, so we are running on local docker container + return; + } $this->latest_version = get_latest_version_of_coolify(); $this->current_version = config('version'); ray('latest version:' . $this->latest_version . " current version: " . $this->current_version . ' force: ' . $force); From 77667be570f5d83ddad87e782cc6ebede4987a51 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 28 Aug 2023 20:29:44 +0200 Subject: [PATCH 13/44] fix: validation --- app/Http/Livewire/Server/Proxy/Status.php | 12 +++++++----- bootstrap/helpers/remoteProcess.php | 21 +++++++++++---------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/app/Http/Livewire/Server/Proxy/Status.php b/app/Http/Livewire/Server/Proxy/Status.php index a4a29b7c2..352a1df52 100644 --- a/app/Http/Livewire/Server/Proxy/Status.php +++ b/app/Http/Livewire/Server/Proxy/Status.php @@ -12,10 +12,12 @@ class Status extends Component public function get_status() { - dispatch_sync(new ProxyContainerStatusJob( - server: $this->server - )); - $this->server->refresh(); - $this->emit('proxyStatusUpdated'); + if (data_get($this->server,'settings.is_usable')) { + dispatch_sync(new ProxyContainerStatusJob( + server: $this->server + )); + $this->server->refresh(); + $this->emit('proxyStatusUpdated'); + } } } diff --git a/bootstrap/helpers/remoteProcess.php b/bootstrap/helpers/remoteProcess.php index 86e11bcf3..b99dc3a9d 100644 --- a/bootstrap/helpers/remoteProcess.php +++ b/bootstrap/helpers/remoteProcess.php @@ -16,11 +16,6 @@ use Illuminate\Support\Facades\Storage; use Illuminate\Support\Sleep; use Spatie\Activitylog\Models\Activity; -/** - * Run a Remote Process, which SSH's asynchronously into a machine to run the command(s). - * @TODO Change 'root' to 'coolify' when it's able to run Docker commands without sudo - * - */ function remote_process( array $command, Server $server, @@ -167,17 +162,23 @@ function validateServer(Server $server) { try { refresh_server_connection($server->privateKey); - $uptime = instant_remote_process(['uptime'], $server); + $uptime = instant_remote_process(['uptime'], $server, false); if (!$uptime) { - $uptime = 'Server not reachable.'; - throw new \Exception('Server not reachable.'); + $server->settings->is_reachable = false; + return [ + "uptime" => null, + "dockerVersion" => null, + ]; } $server->settings->is_reachable = true; $dockerVersion = instant_remote_process(['docker version|head -2|grep -i version'], $server, false); if (!$dockerVersion) { - $dockerVersion = 'Not installed.'; - throw new \Exception('Docker not installed.'); + $dockerVersion = null; + return [ + "uptime" => $uptime, + "dockerVersion" => null, + ]; } $server->settings->is_usable = true; return [ From 556168892d144823cc09aac48eb35a80f164b82f Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 28 Aug 2023 20:45:53 +0200 Subject: [PATCH 14/44] fix job --- app/Jobs/ProxyContainerStatusJob.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Jobs/ProxyContainerStatusJob.php b/app/Jobs/ProxyContainerStatusJob.php index aa6056434..24ad24be0 100644 --- a/app/Jobs/ProxyContainerStatusJob.php +++ b/app/Jobs/ProxyContainerStatusJob.php @@ -39,9 +39,9 @@ class ProxyContainerStatusJob implements ShouldQueue, ShouldBeUnique public function handle(): void { try { - $container = getContainerStatus(server: $this->server, all_data: true, container_id: 'coolify-proxy', throwError: true); + $container = getContainerStatus(server: $this->server, all_data: true, container_id: 'coolify-proxy', throwError: false); $status = data_get($container, 'State.Status'); - if (data_get($this->server,'proxy.status') !== $status) { + if ($status && data_get($this->server, 'proxy.status') !== $status) { $this->server->proxy->status = $status; if ($this->server->proxy->status === 'running') { $traefik = $container['Config']['Labels']['org.opencontainers.image.title']; From b4a32362841c38727a541b6cf929c1664d5f28fe Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 28 Aug 2023 20:52:45 +0200 Subject: [PATCH 15/44] fix --- app/Actions/Server/InstallDocker.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/Actions/Server/InstallDocker.php b/app/Actions/Server/InstallDocker.php index a26fadc05..a7408b2cc 100644 --- a/app/Actions/Server/InstallDocker.php +++ b/app/Actions/Server/InstallDocker.php @@ -37,11 +37,14 @@ class InstallDocker "docker network create --attachable coolify", "echo ####### Done!" ], $server); - StandaloneDocker::create([ - 'name' => 'coolify', - 'network' => 'coolify', - 'server_id' => $server->id, - ]); + $found = StandaloneDocker::where('server_id', $server->id); + if ($found->count() == 0) { + StandaloneDocker::create([ + 'name' => 'coolify', + 'network' => 'coolify', + 'server_id' => $server->id, + ]); + } } From d28cf0b76d2e1177bed65e3e7f4d6170878c332e Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 28 Aug 2023 21:03:07 +0200 Subject: [PATCH 16/44] fix: webhook endpoint in cloud and no system wide gh app --- app/Http/Livewire/Source/Github/Change.php | 8 +++- .../livewire/source/github/change.blade.php | 38 ++++++++++--------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/app/Http/Livewire/Source/Github/Change.php b/app/Http/Livewire/Source/Github/Change.php index e2be4e0ab..859e94f79 100644 --- a/app/Http/Livewire/Source/Github/Change.php +++ b/app/Http/Livewire/Source/Github/Change.php @@ -37,9 +37,13 @@ class Change extends Component public function mount() { - $this->webhook_endpoint = $this->ipv4; + if (is_cloud()) { + $this->webhook_endpoint = config('app.url'); + } else { + $this->webhook_endpoint = $this->ipv4; + $this->is_system_wide = $this->github_app->is_system_wide; + } $this->parameters = get_route_parameters(); - $this->is_system_wide = $this->github_app->is_system_wide; } public function submit() diff --git a/resources/views/livewire/source/github/change.blade.php b/resources/views/livewire/source/github/change.blade.php index 1fc17d985..737bdac42 100644 --- a/resources/views/livewire/source/github/change.blade.php +++ b/resources/views/livewire/source/github/change.blade.php @@ -77,20 +77,22 @@
You need to register a GitHub App before using this source.
-
- - @if ($ipv4) - - @endif - @if ($ipv6) - - @endif - @if ($fqdn) - - @endif - -
+ @if (!is_cloud()) +
+ + @if ($ipv4) + + @endif + @if ($ipv6) + + @endif + @if ($fqdn) + + @endif + +
+ @endif
@@ -118,9 +120,11 @@ @endif
- + @if (!is_cloud()) + + @endif + @endauth + @guest + {{ $slot }} + @endguest + + + diff --git a/resources/views/dashboard.blade.php b/resources/views/livewire/dashboard.blade.php similarity index 84% rename from resources/views/dashboard.blade.php rename to resources/views/livewire/dashboard.blade.php index 4e83f41b3..44e9452a1 100644 --- a/resources/views/dashboard.blade.php +++ b/resources/views/livewire/dashboard.blade.php @@ -1,4 +1,4 @@ - +

Dashboard

Something useful will be here.
@@ -19,10 +19,7 @@
S3 Storages
-
{{ $s3s->count() }}
+
{{ $s3s }}
- @if (isDev()) - {{-- --}} - @endif -
+
diff --git a/resources/views/livewire/server/all.blade.php b/resources/views/livewire/server/all.blade.php new file mode 100644 index 000000000..8ad9c82a3 --- /dev/null +++ b/resources/views/livewire/server/all.blade.php @@ -0,0 +1,54 @@ +
+
+

Servers

+ + + Add + +
+
All Servers
+ +
diff --git a/resources/views/livewire/server/show.blade.php b/resources/views/livewire/server/show.blade.php new file mode 100644 index 000000000..59f6868a4 --- /dev/null +++ b/resources/views/livewire/server/show.blade.php @@ -0,0 +1,4 @@ +
+ + +
diff --git a/resources/views/server/all.blade.php b/resources/views/server/all.blade.php index 048fb311c..a9b0a4a1f 100644 --- a/resources/views/server/all.blade.php +++ b/resources/views/server/all.blade.php @@ -1,53 +1,3 @@ -
-

Servers

- + Add - -
-
All Servers
-
- @forelse ($servers as $server) -
$server->settings->is_reachable, - 'border-red-500' => !$server->settings->is_reachable, - ])> -
-
- {{ $server->name }} -
-
- {{ $server->description }}
-
- @if (!$server->settings->is_reachable) - Not reachable - @endif - @if (!$server->settings->is_reachable && !$server->settings->is_usable) - & - @endif - @if (!$server->settings->is_usable) - Not usable by Coolify - @endif -
-
-
-
- @empty -
-
No servers found. Without a server, you won't be able to do much.
- -
- @endforelse - @isset($error) -
- {{ $error }} -
- @endisset - -
+
diff --git a/routes/web.php b/routes/web.php index ce98b65b7..2824a0be1 100644 --- a/routes/web.php +++ b/routes/web.php @@ -6,6 +6,9 @@ use App\Http\Controllers\DatabaseController; use App\Http\Controllers\MagicController; use App\Http\Controllers\ProjectController; use App\Http\Controllers\ServerController; +use App\Http\Livewire\Dashboard; +use App\Http\Livewire\Server\All; +use App\Http\Livewire\Server\Show; use App\Models\GithubApp; use App\Models\GitlabApp; use App\Models\InstanceSettings; @@ -71,13 +74,9 @@ Route::middleware(['auth'])->group(function () { }); Route::middleware(['auth'])->group(function () { - Route::get('/servers', fn () => view('server.all', [ - 'servers' => Server::ownedByCurrentTeam()->get() - ]))->name('server.all'); + Route::get('/servers', All::class)->name('server.all'); Route::get('/server/new', [ServerController::class, 'new_server'])->name('server.create'); - Route::get('/server/{server_uuid}', fn () => view('server.show', [ - 'server' => Server::ownedByCurrentTeam(['name', 'description', 'ip', 'port', 'user', 'proxy'])->whereUuid(request()->server_uuid)->firstOrFail(), - ]))->name('server.show'); + Route::get('/server/{server_uuid}', Show::class)->name('server.show'); Route::get('/server/{server_uuid}/proxy', fn () => view('server.proxy', [ 'server' => Server::ownedByCurrentTeam(['name', 'proxy'])->whereUuid(request()->server_uuid)->firstOrFail(), ]))->name('server.proxy'); @@ -92,9 +91,9 @@ Route::middleware(['auth'])->group(function () { Route::middleware(['auth'])->group(function () { - Route::get('/', [Controller::class, 'dashboard'])->name('dashboard'); + Route::get('/', Dashboard::class)->name('dashboard'); Route::get('/boarding', [Controller::class, 'boarding'])->name('boarding'); - Route::middleware(['throttle:force-password-reset'])->group(function() { + Route::middleware(['throttle:force-password-reset'])->group(function () { Route::get('/force-password-reset', [Controller::class, 'force_passoword_reset'])->name('auth.force-password-reset'); }); Route::get('/subscription', [Controller::class, 'subscription'])->name('subscription.show'); diff --git a/tests/Feature/DockerCommandsTest.php b/tests/Feature/DockerCommandsTest.phpold similarity index 100% rename from tests/Feature/DockerCommandsTest.php rename to tests/Feature/DockerCommandsTest.phpold diff --git a/tests/Feature/ExampleTest.php b/tests/Feature/ExampleTest.php new file mode 100644 index 000000000..e07cdfb06 --- /dev/null +++ b/tests/Feature/ExampleTest.php @@ -0,0 +1,7 @@ +get('/api/health'); + + $response->assertStatus(200); +}); diff --git a/tests/Feature/RemoteProcessTest.php b/tests/Feature/RemoteProcessTest.phpold similarity index 100% rename from tests/Feature/RemoteProcessTest.php rename to tests/Feature/RemoteProcessTest.phpold diff --git a/tests/Unit/ExampleTest.php b/tests/Unit/ExampleTest.php new file mode 100644 index 000000000..44a4f337a --- /dev/null +++ b/tests/Unit/ExampleTest.php @@ -0,0 +1,5 @@ +toBeTrue(); +}); diff --git a/tests/Unit/RulesTest.php b/tests/Unit/RulesTest.php index 02e14ba48..585e7126c 100644 --- a/tests/Unit/RulesTest.php +++ b/tests/Unit/RulesTest.php @@ -1,5 +1,5 @@ expect(['dd', 'dump', 'ray']) + ->expect(['dd', 'dump']) ->not->toBeUsed(); From fe68e45609fd24b3b38c0a51aea9c6f33dfecda4 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 29 Aug 2023 15:51:30 +0200 Subject: [PATCH 24/44] refactor --- app/Http/Livewire/Server/Form.php | 20 ++++-- app/Http/Livewire/Server/Show.php | 8 ++- app/Models/Server.php | 15 ++++- app/Policies/ServerPolicy.php | 66 ++++++++++++++++++++ bootstrap/helpers/shared.php | 4 ++ resources/views/livewire/dashboard.blade.php | 5 +- 6 files changed, 107 insertions(+), 11 deletions(-) create mode 100644 app/Policies/ServerPolicy.php diff --git a/app/Http/Livewire/Server/Form.php b/app/Http/Livewire/Server/Form.php index 290c06dd7..0546c0007 100644 --- a/app/Http/Livewire/Server/Form.php +++ b/app/Http/Livewire/Server/Form.php @@ -4,10 +4,12 @@ namespace App\Http\Livewire\Server; use App\Actions\Server\InstallDocker; use App\Models\Server; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Livewire\Component; class Form extends Component { + use AuthorizesRequests; public Server $server; public $uptime; public $dockerVersion; @@ -64,14 +66,20 @@ class Form extends Component public function delete() { - if (!$this->server->isEmpty()) { - $this->emit('error', 'Server has defined resources. Please delete them first.'); - return; + try { + $this->authorize('delete', $this->server); + if (!$this->server->isEmpty()) { + $this->emit('error', 'Server has defined resources. Please delete them first.'); + return; + } + $this->server->delete(); + return redirect()->route('server.all'); + } catch (\Exception $e) { + return general_error_handler(err: $e, that: $this); } - $this->server->delete(); - redirect()->route('server.all'); - } + + } public function submit() { $this->validate(); diff --git a/app/Http/Livewire/Server/Show.php b/app/Http/Livewire/Server/Show.php index b54b98fea..75053cc1a 100644 --- a/app/Http/Livewire/Server/Show.php +++ b/app/Http/Livewire/Server/Show.php @@ -3,14 +3,20 @@ namespace App\Http\Livewire\Server; use App\Models\Server; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Livewire\Component; class Show extends Component { + use AuthorizesRequests; public ?Server $server = null; public function mount() { - $this->server = Server::ownedByCurrentTeam(['name', 'description', 'ip', 'port', 'user', 'proxy'])->whereUuid(request()->server_uuid)->firstOrFail(); + try { + $this->server = Server::ownedByCurrentTeam(['name', 'description', 'ip', 'port', 'user', 'proxy'])->whereUuid(request()->server_uuid)->firstOrFail(); + } catch (\Throwable $e) { + return general_error_handler(err: $e, that: $this); + } } public function render() { diff --git a/app/Models/Server.php b/app/Models/Server.php index 764c58246..f3d9090a0 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -33,6 +33,9 @@ class Server extends BaseModel }); static::deleting(function ($server) { + $server->destinations()->each(function ($destination) { + $destination->delete(); + }); $server->settings()->delete(); }); } @@ -70,8 +73,6 @@ class Server extends BaseModel return $standaloneDocker->concat($swarmDocker); } - - public function settings() { return $this->hasOne(ServerSetting::class); @@ -84,12 +85,20 @@ class Server extends BaseModel public function isEmpty() { - if ($this->applications()->count() === 0) { + $applications = $this->applications()->count() === 0; + $databases = $this->databases()->count() === 0; + if ($applications && $databases) { return true; } return false; } + public function databases() { + return $this->destinations()->map(function ($standaloneDocker) { + $postgresqls = $standaloneDocker->postgresqls; + return $postgresqls?->concat([]) ?? collect([]); + })->flatten(); + } public function applications() { return $this->destinations()->map(function ($standaloneDocker) { diff --git a/app/Policies/ServerPolicy.php b/app/Policies/ServerPolicy.php new file mode 100644 index 000000000..08ee5e64d --- /dev/null +++ b/app/Policies/ServerPolicy.php @@ -0,0 +1,66 @@ +teams()->get()->firstWhere('id', $server->team_id) !== null; + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + return true; + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, Server $server): bool + { + return $user->teams()->get()->firstWhere('id', $server->team_id) !== null; + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, Server $server): bool + { + return $user->teams()->get()->firstWhere('id', $server->team_id) !== null; + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, Server $server): bool + { + return false; + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, Server $server): bool + { + return false; + } +} diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index f1670723e..378bfae47 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -58,6 +58,7 @@ function refreshSession(): void function general_error_handler(Throwable | null $err = null, $that = null, $isJson = false, $customErrorMessage = null): mixed { try { + ray($err); ray('ERROR OCCURRED: ' . $err->getMessage()); if ($err instanceof QueryException) { if ($err->errorInfo[0] === '23505') { @@ -70,6 +71,9 @@ function general_error_handler(Throwable | null $err = null, $that = null, $isJs } elseif ($err instanceof TooManyRequestsException) { throw new Exception($customErrorMessage ?? "Too many requests. Please try again in {$err->secondsUntilAvailable} seconds."); } else { + if ($err->getMessage() === 'This action is unauthorized.') { + return redirect()->route('dashboard')->with('error', $customErrorMessage ?? $err->getMessage()); + } throw new Exception($customErrorMessage ?? $err->getMessage()); } } catch (Throwable $error) { diff --git a/resources/views/livewire/dashboard.blade.php b/resources/views/livewire/dashboard.blade.php index 44e9452a1..ed814ffa9 100644 --- a/resources/views/livewire/dashboard.blade.php +++ b/resources/views/livewire/dashboard.blade.php @@ -1,6 +1,9 @@
+ @if (session('error')) + + @endif

Dashboard

-
Something useful will be here.
+
Something useful will be here.
Servers
From 4ad72fab7b5b1f335007970c53029292e0c1eb0d Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 29 Aug 2023 16:31:46 +0200 Subject: [PATCH 25/44] refactor --- app/Http/Controllers/Controller.php | 17 -- app/Http/Livewire/Boarding/Index.php | 183 ++++++++++++++++ resources/views/boarding.blade.php | 13 -- .../views/components/layout-simple.blade.php | 69 +------ .../components/layout-subscription.blade.php | 87 +------- resources/views/components/layout.blade.php | 134 +----------- resources/views/layouts/app.blade.php | 142 +------------ resources/views/layouts/base.blade.php | 88 ++++++++ resources/views/layouts/boarding.blade.php | 9 + resources/views/layouts/simple.blade.php | 7 + .../views/layouts/subscription.blade.php | 16 ++ resources/views/livewire/boarding.blade.php | 195 ------------------ .../views/livewire/boarding/index.blade.php | 192 +++++++++++++++++ routes/web.php | 4 +- 14 files changed, 511 insertions(+), 645 deletions(-) create mode 100644 app/Http/Livewire/Boarding/Index.php delete mode 100644 resources/views/boarding.blade.php create mode 100644 resources/views/layouts/base.blade.php create mode 100644 resources/views/layouts/boarding.blade.php create mode 100644 resources/views/layouts/simple.blade.php create mode 100644 resources/views/layouts/subscription.blade.php delete mode 100644 resources/views/livewire/boarding.blade.php create mode 100644 resources/views/livewire/boarding/index.blade.php diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index e92a29fc2..e3d8420ab 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -48,23 +48,6 @@ class Controller extends BaseController public function force_passoword_reset() { return view('auth.force-password-reset'); } - // public function dashboard() - // { - // $projects = Project::ownedByCurrentTeam()->get(); - // $servers = Server::ownedByCurrentTeam()->get(); - // $s3s = S3Storage::ownedByCurrentTeam()->get(); - // $resources = 0; - // foreach ($projects as $project) { - // $resources += $project->applications->count(); - // $resources += $project->postgresqls->count(); - // } - // return view('dashboard', [ - // 'servers' => $servers->count(), - // 'projects' => $projects->count(), - // 'resources' => $resources, - // 's3s' => $s3s, - // ]); - // } public function boarding() { if (currentTeam()->boarding || isDev()) { return view('boarding'); diff --git a/app/Http/Livewire/Boarding/Index.php b/app/Http/Livewire/Boarding/Index.php new file mode 100644 index 000000000..d704f4f02 --- /dev/null +++ b/app/Http/Livewire/Boarding/Index.php @@ -0,0 +1,183 @@ +privateKeyName = generate_random_name(); + $this->remoteServerName = generate_random_name(); + if (isDev()) { + $this->privateKey = '-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevAAAAJi/QySHv0Mk +hwAAAAtzc2gtZWQyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevA +AAAECBQw4jg1WRT2IGHMncCiZhURCts2s24HoDS0thHnnRKVuGmoeGq/pojrsyP1pszcNV +uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== +-----END OPENSSH PRIVATE KEY-----'; + $this->privateKeyDescription = 'Created by Coolify'; + $this->remoteServerDescription = 'Created by Coolify'; + $this->remoteServerHost = 'coolify-testing-host'; + } + } + public function restartBoarding() + { + if ($this->createdServer) { + $this->createdServer->delete(); + } + if ($this->createdPrivateKey) { + $this->createdPrivateKey->delete(); + } + return redirect()->route('boarding'); + } + public function skipBoarding() + { + currentTeam()->update([ + 'show_boarding' => false + ]); + refreshSession(); + return redirect()->route('dashboard'); + } + public function setServer(string $type) + { + if ($type === 'localhost') { + $this->createdServer = Server::find(0); + if (!$this->createdServer) { + return $this->emit('error', 'Localhost server is not found. Something went wrong during installation. Please try to reinstall or contact support.'); + } + $this->currentState = 'select-proxy'; + } elseif ($type === 'remote') { + $this->currentState = 'private-key'; + } + } + public function setPrivateKey(string $type) + { + $this->privateKeyType = $type; + if ($type === 'create' && !isDev()) { + $this->createNewPrivateKey(); + } + $this->currentState = 'create-private-key'; + } + public function savePrivateKey() + { + $this->validate([ + 'privateKeyName' => 'required', + 'privateKey' => 'required', + ]); + $this->currentState = 'create-server'; + } + public function saveServer() + { + $this->validate([ + 'remoteServerName' => 'required', + 'remoteServerHost' => 'required', + 'remoteServerPort' => 'required', + 'remoteServerUser' => 'required', + ]); + $this->privateKey = formatPrivateKey($this->privateKey); + $this->createdPrivateKey = PrivateKey::create([ + 'name' => $this->privateKeyName, + 'description' => $this->privateKeyDescription, + 'private_key' => $this->privateKey, + 'team_id' => currentTeam()->id + ]); + $this->createdServer = Server::create([ + 'name' => $this->remoteServerName, + 'ip' => $this->remoteServerHost, + 'port' => $this->remoteServerPort, + 'user' => $this->remoteServerUser, + 'description' => $this->remoteServerDescription, + 'private_key_id' => $this->createdPrivateKey->id, + 'team_id' => currentTeam()->id + ]); + try { + ['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->createdServer); + if (!$uptime) { + $this->createdServer->delete(); + $this->createdPrivateKey->delete(); + throw new \Exception('Server is not reachable.'); + } else { + $this->createdServer->settings->update([ + 'is_reachable' => true, + ]); + $this->emit('success', 'Server is reachable.'); + } + if ($dockerVersion) { + $this->emit('error', 'Docker is not installed on the server.'); + $this->currentState = 'install-docker'; + return; + } + } catch (\Exception $e) { + return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this); + } + } + public function installDocker() + { + $activity = resolve(InstallDocker::class)($this->createdServer, currentTeam()); + $this->emit('newMonitorActivity', $activity->id); + $this->currentState = 'select-proxy'; + } + public function selectProxy(string|null $proxyType = null) + { + if (!$proxyType) { + return $this->currentState = 'create-project'; + } + $this->createdServer->proxy->type = $proxyType; + $this->createdServer->proxy->status = 'exited'; + $this->createdServer->save(); + $this->currentState = 'create-project'; + } + public function createNewProject() + { + $this->createdProject = Project::create([ + 'name' => "My first project", + 'team_id' => currentTeam()->id + ]); + $this->currentState = 'create-resource'; + } + public function showNewResource() + { + $this->skipBoarding(); + return redirect()->route( + 'project.resources.new', + [ + 'project_uuid' => $this->createdProject->uuid, + 'environment_name' => 'production', + + ] + ); + } + private function createNewPrivateKey() + { + $this->privateKeyName = generate_random_name(); + $this->privateKeyDescription = 'Created by Coolify'; + ['private' => $this->privateKey, 'public'=> $this->publicKey] = generateSSHKey(); + } + public function render() + { + return view('livewire.boarding.index')->layout('layouts.boarding'); + } +} diff --git a/resources/views/boarding.blade.php b/resources/views/boarding.blade.php deleted file mode 100644 index bdf229935..000000000 --- a/resources/views/boarding.blade.php +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - Close - - - - diff --git a/resources/views/components/layout-simple.blade.php b/resources/views/components/layout-simple.blade.php index cf1328b32..538b357f0 100644 --- a/resources/views/components/layout-simple.blade.php +++ b/resources/views/components/layout-simple.blade.php @@ -1,68 +1 @@ - - - - - - - - - @env('local') - Coolify - localhost - - @else - {{ $title ?? 'Coolify' }} - - @endenv - - @vite(['resources/js/app.js', 'resources/css/app.css']) - - @livewireStyles - - - - @livewireScripts - -
- {{ $slot }} -
- - - - - - +@extends('layouts.simple') diff --git a/resources/views/components/layout-subscription.blade.php b/resources/views/components/layout-subscription.blade.php index a3b0bf806..5fdd838af 100644 --- a/resources/views/components/layout-subscription.blade.php +++ b/resources/views/components/layout-subscription.blade.php @@ -1,86 +1 @@ - - - - - - - - - @env('local') - Coolify - localhost - -@else - {{ $title ?? 'Coolify' }} - - @endenv - - @vite(['resources/js/app.js', 'resources/css/app.css']) - - @livewireStyles - - - - @livewireScripts - - @if (isSubscriptionOnGracePeriod()) -
- -
- - @else - - @endif - -
- {{ $slot }} -
- - - - - +@extends('layouts.subscription') diff --git a/resources/views/components/layout.blade.php b/resources/views/components/layout.blade.php index 32fc1c73f..f16b07f50 100644 --- a/resources/views/components/layout.blade.php +++ b/resources/views/components/layout.blade.php @@ -1,133 +1 @@ - - - - - - - - - @env('local') - Coolify - localhost - -@else - {{ $title ?? 'Coolify' }} - - @endenv - - @vite(['resources/js/app.js', 'resources/css/app.css']) - - @livewireStyles - - - - @livewireScripts - @auth - - -
- -
-
- {{ $slot }} -
- - - @endauth - @guest - {{ $slot }} - @endguest - - - +@extends('layouts.app') diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 32fc1c73f..e825b5493 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -1,133 +1,11 @@ - - - - - - - - - @env('local') - Coolify - localhost - -@else - {{ $title ?? 'Coolify' }} - - @endenv - - @vite(['resources/js/app.js', 'resources/css/app.css']) - - @livewireStyles - - - - @livewireScripts - @auth - - -
- -
-
- {{ $slot }} -
- - - @endauth - @guest +@extends('layouts.base') +@section('body') + @parent + +
+ +
+
{{ $slot }} - @endguest - - - +
+@endsection diff --git a/resources/views/layouts/base.blade.php b/resources/views/layouts/base.blade.php new file mode 100644 index 000000000..a8e2f941d --- /dev/null +++ b/resources/views/layouts/base.blade.php @@ -0,0 +1,88 @@ + + + + + + + + + Coolify + @env('local') + +@else + + @endenv + + @vite(['resources/js/app.js', 'resources/css/app.css']) + + @livewireStyles + +@section('body') + + + @livewireScripts + @auth + + + + @endauth + @guest + {{ $slot }} + @endguest + +@show + + diff --git a/resources/views/layouts/boarding.blade.php b/resources/views/layouts/boarding.blade.php new file mode 100644 index 000000000..a63d26a41 --- /dev/null +++ b/resources/views/layouts/boarding.blade.php @@ -0,0 +1,9 @@ +@extends('layouts.base') +@section('body') +
+
+ {{ $slot }} +
+
+@parent +@endsection diff --git a/resources/views/layouts/simple.blade.php b/resources/views/layouts/simple.blade.php new file mode 100644 index 000000000..c3a25cda8 --- /dev/null +++ b/resources/views/layouts/simple.blade.php @@ -0,0 +1,7 @@ +@extends('layouts.base') +@section('body') + @parent +
+ {{ $slot }} +
+@endsection diff --git a/resources/views/layouts/subscription.blade.php b/resources/views/layouts/subscription.blade.php new file mode 100644 index 000000000..2feb5199b --- /dev/null +++ b/resources/views/layouts/subscription.blade.php @@ -0,0 +1,16 @@ +@extends('layouts.base') +@section('body') + @parent + @if (isSubscriptionOnGracePeriod()) +
+ +
+ + @else + + @endif + +
+ {{ $slot }} +
+@endsection diff --git a/resources/views/livewire/boarding.blade.php b/resources/views/livewire/boarding.blade.php deleted file mode 100644 index c6482cbeb..000000000 --- a/resources/views/livewire/boarding.blade.php +++ /dev/null @@ -1,195 +0,0 @@ -@php use App\Enums\ProxyTypes; @endphp -
-
-
- @if ($currentState === 'welcome') -

Welcome to Coolify

-

Let me help you to set the basics.

-
-
Get Started -
-
- @endif - @if ($currentState === 'select-server') - - - Do you want to deploy your resources on your - or on a ? - - -
Localhost -
-
Remote Server -
-
- -

Servers are the main building blocks, as they will host your applications, databases, - services, called resources. Any CPU intensive process will use the server's CPU where you - are deploying your resources.

-

Localhost is the server where Coolify is running on. It is not recommended to use one server - for everyting.

-

Remote Server is a server reachable through SSH. It can be hosted at home, or from any cloud - provider.

-
-
- @endif - @if ($currentState === 'private-key') - - - Do you have your own SSH Private Key? - - -
Yes -
-
No (create one for me) -
-
- -

SSH Keys are used to connect to a remote server through a secure shell, called SSH.

-

You can use your own ssh private key, or you can let Coolify to create one for you.

-

In both ways, you need to add the public version of your ssh private key to the remote - server's - ~/.ssh/authorized_keys file. -

-
-
- @endif - @if ($currentState === 'create-private-key') - - - Please let me know your key details. - - -
- - - - @if ($privateKeyType === 'create' && !isDev()) - Copy this to your server's ~/.ssh/authorized_keys file. - - @endif - Save - -
- -

Private Keys are used to connect to a remote server through a secure shell, called SSH.

-

You can use your own private key, or you can let Coolify to create one for you.

-

In both ways, you need to add the public version of your private key to the remote server's - ~/.ssh/authorized_keys file. -

-
-
- @endif - @if ($currentState === 'create-server') - - - Please let me know your server details. - - -
-
- - -
-
- - - -
- Save -
-
- -

Username should be for now. We are working on to use - non-root users.

-
-
- @endif - @if ($currentState === 'install-docker') - - - Could not find Docker Engine on your server. Do you want me to install it for you? - - -
- Let's do - it!
-
- -

This will install the latest Docker Engine on your server, configure a few things to be able - to run optimal.

-
-
- @endif - @if ($currentState === 'select-proxy') - - - If you would like to attach any kind of domain to your resources, you need a proxy. - - - - Decide later - - - Traefik - v2 - - - Nginx - - - Caddy - - - -

This will install the latest Docker Engine on your server, configure a few things to be able - to run optimal.

-
-
- @endif - @if ($currentState === 'create-project') - - - I will create an initial project for you. You can change all the details later on. - - -
Let's do it!
-
- -

Projects are bound together several resources into one virtual group. There are no - limitations on the number of projects you could have.

-

Each project should have at least one environment. This helps you to create a production & - staging version of the same application, but grouped separately.

-
-
- @endif - @if ($currentState === 'create-resource') - - - I will redirect you to the new resource page, where you can create your first resource. - - -
Let's do - it!
-
- -

A resource could be an application, a database or a service (like WordPress).

-
-
- @endif - -
-
-
diff --git a/resources/views/livewire/boarding/index.blade.php b/resources/views/livewire/boarding/index.blade.php new file mode 100644 index 000000000..4bda0e4dc --- /dev/null +++ b/resources/views/livewire/boarding/index.blade.php @@ -0,0 +1,192 @@ +@php use App\Enums\ProxyTypes; @endphp +
+ @if ($currentState === 'welcome') +

Welcome to Coolify

+

Let me help you to set the basics.

+
+
Get Started +
+
+ @endif + @if ($currentState === 'select-server') + + + Do you want to deploy your resources on your + or on a ? + + +
Localhost +
+
Remote Server +
+
+ +

Servers are the main building blocks, as they will host your applications, databases, + services, called resources. Any CPU intensive process will use the server's CPU where you + are deploying your resources.

+

Localhost is the server where Coolify is running on. It is not recommended to use one server + for everyting.

+

Remote Server is a server reachable through SSH. It can be hosted at home, or from any cloud + provider.

+
+
+ @endif + @if ($currentState === 'private-key') + + + Do you have your own SSH Private Key? + + +
Yes +
+
No (create one for me) +
+
+ +

SSH Keys are used to connect to a remote server through a secure shell, called SSH.

+

You can use your own ssh private key, or you can let Coolify to create one for you.

+

In both ways, you need to add the public version of your ssh private key to the remote + server's + ~/.ssh/authorized_keys file. +

+
+
+ @endif + @if ($currentState === 'create-private-key') + + + Please let me know your key details. + + +
+ + + + @if ($privateKeyType === 'create' && !isDev()) + Copy this to your server's ~/.ssh/authorized_keys + file. + + @endif + Save + +
+ +

Private Keys are used to connect to a remote server through a secure shell, called SSH.

+

You can use your own private key, or you can let Coolify to create one for you.

+

In both ways, you need to add the public version of your private key to the remote server's + ~/.ssh/authorized_keys file. +

+
+
+ @endif + @if ($currentState === 'create-server') + + + Please let me know your server details. + + +
+
+ + +
+
+ + + +
+ Save +
+
+ +

Username should be for now. We are working on to use + non-root users.

+
+
+ @endif + @if ($currentState === 'install-docker') + + + Could not find Docker Engine on your server. Do you want me to install it for you? + + +
+ Let's do + it!
+
+ +

This will install the latest Docker Engine on your server, configure a few things to be able + to run optimal.

+
+
+ @endif + @if ($currentState === 'select-proxy') + + + If you would like to attach any kind of domain to your resources, you need a proxy. + + + + Decide later + + + Traefik + v2 + + + Nginx + + + Caddy + + + +

This will install the latest Docker Engine on your server, configure a few things to be able + to run optimal.

+
+
+ @endif + @if ($currentState === 'create-project') + + + I will create an initial project for you. You can change all the details later on. + + +
Let's do it!
+
+ +

Projects are bound together several resources into one virtual group. There are no + limitations on the number of projects you could have.

+

Each project should have at least one environment. This helps you to create a production & + staging version of the same application, but grouped separately.

+
+
+ @endif + @if ($currentState === 'create-resource') + + + I will redirect you to the new resource page, where you can create your first resource. + + +
Let's do + it!
+
+ +

A resource could be an application, a database or a service (like WordPress).

+
+
+ @endif + +
diff --git a/routes/web.php b/routes/web.php index 2824a0be1..839786385 100644 --- a/routes/web.php +++ b/routes/web.php @@ -6,6 +6,8 @@ use App\Http\Controllers\DatabaseController; use App\Http\Controllers\MagicController; use App\Http\Controllers\ProjectController; use App\Http\Controllers\ServerController; +use App\Http\Livewire\Boarding\Index; +use App\Http\Livewire\Boarding\Server as BoardingServer; use App\Http\Livewire\Dashboard; use App\Http\Livewire\Server\All; use App\Http\Livewire\Server\Show; @@ -92,7 +94,7 @@ Route::middleware(['auth'])->group(function () { Route::middleware(['auth'])->group(function () { Route::get('/', Dashboard::class)->name('dashboard'); - Route::get('/boarding', [Controller::class, 'boarding'])->name('boarding'); + Route::get('/boarding', Index::class)->name('boarding'); Route::middleware(['throttle:force-password-reset'])->group(function () { Route::get('/force-password-reset', [Controller::class, 'force_passoword_reset'])->name('auth.force-password-reset'); }); From 4a4837d9f5b18186ade80f400d8c1c900a91c3cd Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 29 Aug 2023 20:25:42 +0200 Subject: [PATCH 26/44] fix --- resources/views/layouts/base.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/layouts/base.blade.php b/resources/views/layouts/base.blade.php index a8e2f941d..9ea6c6e7c 100644 --- a/resources/views/layouts/base.blade.php +++ b/resources/views/layouts/base.blade.php @@ -1,5 +1,5 @@ - + From 5eb41e1a1527aed4095d50134ee4772fa03c9981 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 29 Aug 2023 20:34:01 +0200 Subject: [PATCH 27/44] fix boarding --- app/Http/Livewire/Boarding/Index.php | 14 ++++++++++++-- resources/views/livewire/boarding/index.blade.php | 8 ++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/app/Http/Livewire/Boarding/Index.php b/app/Http/Livewire/Boarding/Index.php index d704f4f02..539751ceb 100644 --- a/app/Http/Livewire/Boarding/Index.php +++ b/app/Http/Livewire/Boarding/Index.php @@ -1,15 +1,20 @@ currentState = 'select-proxy'; } elseif ($type === 'remote') { + $this->privateKeys = PrivateKey::ownedByCurrentTeam(['name'])->get(); $this->currentState = 'private-key'; } } + public function selectExistingPrivateKey() + { + ray($this->selectedExistingPrivateKey); + } public function setPrivateKey(string $type) { $this->privateKeyType = $type; @@ -174,7 +184,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== { $this->privateKeyName = generate_random_name(); $this->privateKeyDescription = 'Created by Coolify'; - ['private' => $this->privateKey, 'public'=> $this->publicKey] = generateSSHKey(); + ['private' => $this->privateKey, 'public' => $this->publicKey] = generateSSHKey(); } public function render() { diff --git a/resources/views/livewire/boarding/index.blade.php b/resources/views/livewire/boarding/index.blade.php index 4bda0e4dc..06ff5661b 100644 --- a/resources/views/livewire/boarding/index.blade.php +++ b/resources/views/livewire/boarding/index.blade.php @@ -41,6 +41,14 @@
No (create one for me)
+
+ + @foreach ($privateKeys as $privateKey) + + @endforeach + + Select this +

SSH Keys are used to connect to a remote server through a secure shell, called SSH.

From 97d48823dd3d7454ebb79b171bb88ab759df0378 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 30 Aug 2023 11:06:44 +0200 Subject: [PATCH 28/44] improve boarding --- app/Http/Controllers/ProjectController.php | 4 + app/Http/Livewire/Boarding/Index.php | 75 ++- app/Http/Livewire/Project/New/Select.php | 11 + .../{PrivateKey.php => ShowPrivateKey.php} | 2 +- .../views/livewire/boarding/index.blade.php | 459 ++++++++++-------- ...y.blade.php => show-private-key.blade.php} | 0 resources/views/server/private-key.blade.php | 2 +- 7 files changed, 353 insertions(+), 200 deletions(-) rename app/Http/Livewire/Server/{PrivateKey.php => ShowPrivateKey.php} (96%) rename resources/views/livewire/server/{private-key.blade.php => show-private-key.blade.php} (100%) diff --git a/app/Http/Controllers/ProjectController.php b/app/Http/Controllers/ProjectController.php index 476d54437..07e4a2a0f 100644 --- a/app/Http/Controllers/ProjectController.php +++ b/app/Http/Controllers/ProjectController.php @@ -43,6 +43,7 @@ class ProjectController extends Controller { $type = request()->query('type'); $destination_uuid = request()->query('destination'); + $server = requesT()->query('server'); $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); if (!$project) { @@ -59,6 +60,9 @@ class ProjectController extends Controller 'environment_name' => $environment->name, 'database_uuid' => $standalone_postgresql->uuid, ]); + } + if ($server) { + } return view('project.new', [ 'type' => $type diff --git a/app/Http/Livewire/Boarding/Index.php b/app/Http/Livewire/Boarding/Index.php index 539751ceb..8cc1cd50d 100644 --- a/app/Http/Livewire/Boarding/Index.php +++ b/app/Http/Livewire/Boarding/Index.php @@ -6,7 +6,7 @@ use App\Actions\Server\InstallDocker; use App\Models\PrivateKey; use App\Models\Project; use App\Models\Server; -use Illuminate\Database\Eloquent\Collection; +use Illuminate\Support\Collection; use Livewire\Component; class Index extends Component @@ -22,6 +22,8 @@ class Index extends Component public ?string $privateKeyDescription = null; public ?PrivateKey $createdPrivateKey = null; + public ?Collection $servers = null; + public ?int $selectedExistingServer = null; public ?string $remoteServerName = null; public ?string $remoteServerDescription = null; public ?string $remoteServerHost = null; @@ -29,6 +31,8 @@ class Index extends Component public ?string $remoteServerUser = 'root'; public ?Server $createdServer = null; + public Collection|array $projects = []; + public ?int $selectedExistingProject = null; public ?Project $createdProject = null; public function mount() @@ -66,25 +70,62 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== refreshSession(); return redirect()->route('dashboard'); } - public function setServer(string $type) + + public function setServerType(string $type) { if ($type === 'localhost') { $this->createdServer = Server::find(0); if (!$this->createdServer) { return $this->emit('error', 'Localhost server is not found. Something went wrong during installation. Please try to reinstall or contact support.'); } - $this->currentState = 'select-proxy'; + return $this->validateServer(); } elseif ($type === 'remote') { - $this->privateKeys = PrivateKey::ownedByCurrentTeam(['name'])->get(); + $this->privateKeys = PrivateKey::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get(); + if ($this->privateKeys->count() > 0) { + $this->selectedExistingPrivateKey = $this->privateKeys->first()->id; + } + $this->servers = Server::ownedByCurrentTeam(['name'])->where('id', '!=', 0)->get(); + if ($this->servers->count() > 0) { + $this->selectedExistingServer = $this->servers->first()->id; + $this->currentState = 'select-existing-server'; + return; + } $this->currentState = 'private-key'; } } + public function selectExistingServer() + { + $this->createdServer = Server::find($this->selectedExistingServer); + if (!$this->createdServer) { + $this->emit('error', 'Server is not found.'); + $this->currentState = 'private-key'; + return; + } + $this->selectedExistingPrivateKey = $this->createdServer->privateKey->id; + $this->validateServer(); + $this->getProxyType(); + $this->getProjects(); + } + public function getProxyType() { + $proxyTypeSet = $this->createdServer->proxy->type; + if (!$proxyTypeSet) { + $this->currentState = 'select-proxy'; + return; + } + $this->getProjects(); + } public function selectExistingPrivateKey() { - ray($this->selectedExistingPrivateKey); + $this->currentState = 'create-server'; + } + public function createNewServer() + { + $this->selectedExistingServer = null; + $this->currentState = 'private-key'; } public function setPrivateKey(string $type) { + $this->selectedExistingPrivateKey = null; $this->privateKeyType = $type; if ($type === 'create' && !isDev()) { $this->createNewPrivateKey(); @@ -123,11 +164,12 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== 'private_key_id' => $this->createdPrivateKey->id, 'team_id' => currentTeam()->id ]); + $this->validateServer(); + } + public function validateServer() { try { ['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->createdServer); if (!$uptime) { - $this->createdServer->delete(); - $this->createdPrivateKey->delete(); throw new \Exception('Server is not reachable.'); } else { $this->createdServer->settings->update([ @@ -135,11 +177,14 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== ]); $this->emit('success', 'Server is reachable.'); } - if ($dockerVersion) { + ray($dockerVersion, $uptime); + if (!$dockerVersion) { $this->emit('error', 'Docker is not installed on the server.'); $this->currentState = 'install-docker'; return; } + $this->getProxyType(); + } catch (\Exception $e) { return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this); } @@ -153,13 +198,25 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== public function selectProxy(string|null $proxyType = null) { if (!$proxyType) { - return $this->currentState = 'create-project'; + return $this->getProjects(); } $this->createdServer->proxy->type = $proxyType; $this->createdServer->proxy->status = 'exited'; $this->createdServer->save(); + $this->getProjects(); + } + + public function getProjects() { + $this->projects = Project::ownedByCurrentTeam(['name'])->get(); + if ($this->projects->count() > 0) { + $this->selectedExistingProject = $this->projects->first()->id; + } $this->currentState = 'create-project'; } + public function selectExistingProject() { + $this->createdProject = Project::find($this->selectedExistingProject); + $this->currentState = 'create-resource'; + } public function createNewProject() { $this->createdProject = Project::create([ diff --git a/app/Http/Livewire/Project/New/Select.php b/app/Http/Livewire/Project/New/Select.php index b3109ef8c..e48ebf9cf 100644 --- a/app/Http/Livewire/Project/New/Select.php +++ b/app/Http/Livewire/Project/New/Select.php @@ -5,10 +5,12 @@ namespace App\Http\Livewire\Project\New; use App\Models\Server; use Countable; use Livewire\Component; +use Route; class Select extends Component { public $current_step = 'type'; + public ?int $server = null; public string $type; public string $server_id; public string $destination_uuid; @@ -16,6 +18,9 @@ class Select extends Component public $destinations = []; public array $parameters; + protected $queryString = [ + 'server', + ]; public function mount() { $this->parameters = get_route_parameters(); @@ -31,6 +36,12 @@ class Select extends Component $this->set_destination($server->destinations()->first()->uuid); } } + if (!is_null($this->server )) { + $foundServer = $this->servers->where('id', $this->server)->first(); + if ($foundServer) { + return $this->set_server($foundServer); + } + } $this->current_step = 'servers'; } diff --git a/app/Http/Livewire/Server/PrivateKey.php b/app/Http/Livewire/Server/ShowPrivateKey.php similarity index 96% rename from app/Http/Livewire/Server/PrivateKey.php rename to app/Http/Livewire/Server/ShowPrivateKey.php index 8f433f73d..4f77014cb 100644 --- a/app/Http/Livewire/Server/PrivateKey.php +++ b/app/Http/Livewire/Server/ShowPrivateKey.php @@ -6,7 +6,7 @@ use App\Models\Server; use Livewire\Component; use Masmerise\Toaster\Toaster; -class PrivateKey extends Component +class ShowPrivateKey extends Component { public Server $server; public $privateKeys; diff --git a/resources/views/livewire/boarding/index.blade.php b/resources/views/livewire/boarding/index.blade.php index 06ff5661b..d38aa0190 100644 --- a/resources/views/livewire/boarding/index.blade.php +++ b/resources/views/livewire/boarding/index.blade.php @@ -1,198 +1,279 @@ @php use App\Enums\ProxyTypes; @endphp
- @if ($currentState === 'welcome') -

Welcome to Coolify

-

Let me help you to set the basics.

-
-
Get Started +
+ @if ($currentState === 'welcome') +

Welcome to Coolify

+

Let me help you to set the basics.

+
+
Get Started +
-
- @endif - @if ($currentState === 'select-server') - - - Do you want to deploy your resources on your - or on a ? - - -
Localhost -
-
Remote Server -
-
- -

Servers are the main building blocks, as they will host your applications, databases, - services, called resources. Any CPU intensive process will use the server's CPU where you - are deploying your resources.

-

Localhost is the server where Coolify is running on. It is not recommended to use one server - for everyting.

-

Remote Server is a server reachable through SSH. It can be hosted at home, or from any cloud - provider.

-
-
- @endif - @if ($currentState === 'private-key') - - - Do you have your own SSH Private Key? - - -
Yes -
-
No (create one for me) -
-
- - @foreach ($privateKeys as $privateKey) - - @endforeach - - Select this -
-
- -

SSH Keys are used to connect to a remote server through a secure shell, called SSH.

-

You can use your own ssh private key, or you can let Coolify to create one for you.

-

In both ways, you need to add the public version of your ssh private key to the remote - server's - ~/.ssh/authorized_keys file. -

-
-
- @endif - @if ($currentState === 'create-private-key') - - - Please let me know your key details. - - -
- - - - @if ($privateKeyType === 'create' && !isDev()) - Copy this to your server's ~/.ssh/authorized_keys - file. - + @endif +
+
+ @if ($currentState === 'select-server-type') + + + Do you want to deploy your resources on your + or on a ? + + +
Localhost +
+
Remote Server +
+
+ +

Servers are the main building blocks, as they will host your applications, databases, + services, called resources. Any CPU intensive process will use the server's CPU where you + are deploying your resources.

+

Localhost is the server where Coolify is running on. It is not recommended to use one server + for everyting.

+

Remote Server is a server reachable through SSH. It can be hosted at home, or from any cloud + provider.

+
+
+ @endif +
+
+ @if ($currentState === 'private-key') + + + Do you have your own SSH Private Key? + + +
Yes +
+
No (create one for me) +
+ @if (count($privateKeys) > 0) + + + @foreach ($privateKeys as $privateKey) + + @endforeach + + Use this SSH Key + @endif - Save - -
- -

Private Keys are used to connect to a remote server through a secure shell, called SSH.

-

You can use your own private key, or you can let Coolify to create one for you.

-

In both ways, you need to add the public version of your private key to the remote server's - ~/.ssh/authorized_keys file. -

-
-
- @endif - @if ($currentState === 'create-server') - - - Please let me know your server details. - - -
-
- + + +

SSH Keys are used to connect to a remote server through a secure shell, called SSH.

+

You can use your own ssh private key, or you can let Coolify to create one for you.

+

In both ways, you need to add the public version of your ssh private key to the remote + server's + ~/.ssh/authorized_keys file. +

+
+ + @endif +
+
+ @if ($currentState === 'select-existing-server') + + + There are already servers available for your Team. Do you want to use one of them? + + +
No (create a new one) +
+
+ + + @foreach ($servers as $server) + + @endforeach + + Use this Server + +
+
+ +

Private Keys are used to connect to a remote server through a secure shell, called SSH.

+

You can use your own private key, or you can let Coolify to create one for you.

+

In both ways, you need to add the public version of your private key to the remote server's + ~/.ssh/authorized_keys file. +

+
+
+ @endif +
+
+ @if ($currentState === 'create-private-key') + + + Please let me know your key details. + + +
+ + label="Description" id="privateKeyDescription" /> + + @if ($privateKeyType === 'create' && !isDev()) + Copy this to your server's ~/.ssh/authorized_keys + file. + + @endif + Save + +
+ +

Private Keys are used to connect to a remote server through a secure shell, called SSH.

+

You can use your own private key, or you can let Coolify to create one for you.

+

In both ways, you need to add the public version of your private key to the remote server's + ~/.ssh/authorized_keys file. +

+
+
+ @endif +
+
+ @if ($currentState === 'create-server') + + + Please let me know your server details. + + +
+
+ + +
+
+ + + +
+ Save +
+
+ +

Username should be for now. We are working on to use + non-root users.

+
+
+ @endif +
+
+ @if ($currentState === 'install-docker') + + + + + + + Close + + + + + + Could not find Docker Engine on your server. Do you want me to install it for you? + + +
+ Let's do + it!
+
+ +

This will install the latest Docker Engine on your server, configure a few things to be able + to run optimal.

+
+
+ @endif +
+
+ @if ($currentState === 'select-proxy') + + + If you would like to attach any kind of domain to your resources, you need a proxy. + + + + Decide later + + + Traefik + v2 + + + Nginx + + + Caddy + + + +

This will install the latest Docker Engine on your server, configure a few things to be able + to run optimal.

+
+
+ @endif +
+
+ @if ($currentState === 'create-project') + + + @if (count($projects) > 0) + You already have some projects. Do you want to use one of them or should I create a new one for + you? + @else + I will create an initial project for you. You can change all the details later on. + @endif + + +
Let's create a new one!
+
+ @if (count($projects) > 0) +
+ + @foreach ($projects as $project) + + @endforeach + + Use this Project +
+ @endif
-
- - - -
- Save - -
- -

Username should be for now. We are working on to use - non-root users.

-
-
- @endif - @if ($currentState === 'install-docker') - - - Could not find Docker Engine on your server. Do you want me to install it for you? - - -
- Let's do - it!
-
- -

This will install the latest Docker Engine on your server, configure a few things to be able - to run optimal.

-
-
- @endif - @if ($currentState === 'select-proxy') - - - If you would like to attach any kind of domain to your resources, you need a proxy. - - - - Decide later - - - Traefik - v2 - - - Nginx - - - Caddy - - - -

This will install the latest Docker Engine on your server, configure a few things to be able - to run optimal.

-
-
- @endif - @if ($currentState === 'create-project') - - - I will create an initial project for you. You can change all the details later on. - - -
Let's do it!
-
- -

Projects are bound together several resources into one virtual group. There are no - limitations on the number of projects you could have.

-

Each project should have at least one environment. This helps you to create a production & - staging version of the same application, but grouped separately.

-
-
- @endif - @if ($currentState === 'create-resource') - - - I will redirect you to the new resource page, where you can create your first resource. - - -
Let's do - it!
-
- -

A resource could be an application, a database or a service (like WordPress).

-
-
- @endif + + +

Projects are bound together several resources into one virtual group. There are no + limitations on the number of projects you could have.

+

Each project should have at least one environment. This helps you to create a production & + staging version of the same application, but grouped separately.

+
+ + @endif +
+
+ @if ($currentState === 'create-resource') + + + I will redirect you to the new resource page, where you can create your first resource. + + +
Let's do + it!
+
+ +

A resource could be an application, a database or a service (like WordPress).

+
+
+ @endif +
Skip boarding process Restart boarding process diff --git a/resources/views/livewire/server/private-key.blade.php b/resources/views/livewire/server/show-private-key.blade.php similarity index 100% rename from resources/views/livewire/server/private-key.blade.php rename to resources/views/livewire/server/show-private-key.blade.php diff --git a/resources/views/server/private-key.blade.php b/resources/views/server/private-key.blade.php index 3c42f98f0..d1b22b16c 100644 --- a/resources/views/server/private-key.blade.php +++ b/resources/views/server/private-key.blade.php @@ -1,4 +1,4 @@ - + From 248863cf16ef4dc59ca2c07a5b0715c57d7445f6 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 30 Aug 2023 11:26:46 +0200 Subject: [PATCH 29/44] update boarding process --- app/Http/Livewire/Boarding.php | 181 ------------------ app/Http/Livewire/Boarding/Index.php | 2 +- app/Http/Livewire/Project/New/Select.php | 11 +- .../livewire/project/new/select.blade.php | 20 +- 4 files changed, 24 insertions(+), 190 deletions(-) delete mode 100644 app/Http/Livewire/Boarding.php diff --git a/app/Http/Livewire/Boarding.php b/app/Http/Livewire/Boarding.php deleted file mode 100644 index 7ec11a3bc..000000000 --- a/app/Http/Livewire/Boarding.php +++ /dev/null @@ -1,181 +0,0 @@ -privateKeyName = generate_random_name(); - $this->remoteServerName = generate_random_name(); - if (isDev()) { - $this->privateKey = '-----BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW -QyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevAAAAJi/QySHv0Mk -hwAAAAtzc2gtZWQyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevA -AAAECBQw4jg1WRT2IGHMncCiZhURCts2s24HoDS0thHnnRKVuGmoeGq/pojrsyP1pszcNV -uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== ------END OPENSSH PRIVATE KEY-----'; - $this->privateKeyDescription = 'Created by Coolify'; - $this->remoteServerDescription = 'Created by Coolify'; - $this->remoteServerHost = 'coolify-testing-host'; - } - } - public function restartBoarding() - { - if ($this->createdServer) { - $this->createdServer->delete(); - } - if ($this->createdPrivateKey) { - $this->createdPrivateKey->delete(); - } - return redirect()->route('boarding'); - } - public function skipBoarding() - { - currentTeam()->update([ - 'show_boarding' => false - ]); - refreshSession(); - return redirect()->route('dashboard'); - } - public function setServer(string $type) - { - if ($type === 'localhost') { - $this->createdServer = Server::find(0); - if (!$this->createdServer) { - return $this->emit('error', 'Localhost server is not found. Something went wrong during installation. Please try to reinstall or contact support.'); - } - $this->currentState = 'select-proxy'; - } elseif ($type === 'remote') { - $this->currentState = 'private-key'; - } - } - public function setPrivateKey(string $type) - { - $this->privateKeyType = $type; - if ($type === 'create' && !isDev()) { - $this->createNewPrivateKey(); - } - $this->currentState = 'create-private-key'; - } - public function savePrivateKey() - { - $this->validate([ - 'privateKeyName' => 'required', - 'privateKey' => 'required', - ]); - $this->currentState = 'create-server'; - } - public function saveServer() - { - $this->validate([ - 'remoteServerName' => 'required', - 'remoteServerHost' => 'required', - 'remoteServerPort' => 'required', - 'remoteServerUser' => 'required', - ]); - $this->privateKey = formatPrivateKey($this->privateKey); - $this->createdPrivateKey = PrivateKey::create([ - 'name' => $this->privateKeyName, - 'description' => $this->privateKeyDescription, - 'private_key' => $this->privateKey, - 'team_id' => currentTeam()->id - ]); - $this->createdServer = Server::create([ - 'name' => $this->remoteServerName, - 'ip' => $this->remoteServerHost, - 'port' => $this->remoteServerPort, - 'user' => $this->remoteServerUser, - 'description' => $this->remoteServerDescription, - 'private_key_id' => $this->createdPrivateKey->id, - 'team_id' => currentTeam()->id - ]); - try { - ['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->createdServer); - if (!$uptime) { - $this->createdServer->delete(); - $this->createdPrivateKey->delete(); - throw new \Exception('Server is not reachable.'); - } else { - $this->createdServer->settings->update([ - 'is_reachable' => true, - ]); - $this->emit('success', 'Server is reachable.'); - } - if ($dockerVersion) { - $this->emit('error', 'Docker is not installed on the server.'); - $this->currentState = 'install-docker'; - return; - } - } catch (\Exception $e) { - return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this); - } - } - public function installDocker() - { - $activity = resolve(InstallDocker::class)($this->createdServer, currentTeam()); - $this->emit('newMonitorActivity', $activity->id); - $this->currentState = 'select-proxy'; - } - public function selectProxy(string|null $proxyType = null) - { - if (!$proxyType) { - return $this->currentState = 'create-project'; - } - $this->createdServer->proxy->type = $proxyType; - $this->createdServer->proxy->status = 'exited'; - $this->createdServer->save(); - $this->currentState = 'create-project'; - } - public function createNewProject() - { - $this->createdProject = Project::create([ - 'name' => "My first project", - 'team_id' => currentTeam()->id - ]); - $this->currentState = 'create-resource'; - } - public function showNewResource() - { - $this->skipBoarding(); - return redirect()->route( - 'project.resources.new', - [ - 'project_uuid' => $this->createdProject->uuid, - 'environment_name' => 'production', - - ] - ); - } - private function createNewPrivateKey() - { - $this->privateKeyName = generate_random_name(); - $this->privateKeyDescription = 'Created by Coolify'; - ['private' => $this->privateKey, 'public'=> $this->publicKey] = generateSSHKey(); - } -} diff --git a/app/Http/Livewire/Boarding/Index.php b/app/Http/Livewire/Boarding/Index.php index 8cc1cd50d..e543af17a 100644 --- a/app/Http/Livewire/Boarding/Index.php +++ b/app/Http/Livewire/Boarding/Index.php @@ -233,7 +233,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== [ 'project_uuid' => $this->createdProject->uuid, 'environment_name' => 'production', - + 'server'=> $this->createdServer->id, ] ); } diff --git a/app/Http/Livewire/Project/New/Select.php b/app/Http/Livewire/Project/New/Select.php index e48ebf9cf..c6ec91bb3 100644 --- a/app/Http/Livewire/Project/New/Select.php +++ b/app/Http/Livewire/Project/New/Select.php @@ -3,7 +3,10 @@ namespace App\Http\Livewire\Project\New; use App\Models\Server; +use App\Models\StandaloneDocker; +use App\Models\SwarmDocker; use Countable; +use Illuminate\Support\Collection; use Livewire\Component; use Route; @@ -15,7 +18,8 @@ class Select extends Component public string $server_id; public string $destination_uuid; public Countable|array|Server $servers; - public $destinations = []; + public Collection|array $standaloneDockers = []; + public Collection|array $swarmDockers = []; public array $parameters; protected $queryString = [ @@ -36,7 +40,7 @@ class Select extends Component $this->set_destination($server->destinations()->first()->uuid); } } - if (!is_null($this->server )) { + if (!is_null($this->server)) { $foundServer = $this->servers->where('id', $this->server)->first(); if ($foundServer) { return $this->set_server($foundServer); @@ -48,7 +52,8 @@ class Select extends Component public function set_server(Server $server) { $this->server_id = $server->id; - $this->destinations = $server->destinations(); + $this->standaloneDockers = $server->standaloneDockers; + $this->swarmDockers = $server->swarmDockers; $this->current_step = 'destinations'; } diff --git a/resources/views/livewire/project/new/select.blade.php b/resources/views/livewire/project/new/select.blade.php index bdb6ac4ad..9cdfe515f 100644 --- a/resources/views/livewire/project/new/select.blade.php +++ b/resources/views/livewire/project/new/select.blade.php @@ -109,18 +109,28 @@
  • Select a Destination
  • - @foreach ($destinations as $destination) + @foreach ($standaloneDockers as $standaloneDocker)
    + wire:click="set_destination('{{ $standaloneDocker->uuid }}')">
    -
    - {{ $destination->name }} +
    + Standalone Docker ({{ $standaloneDocker->name }})
    - {{ $destination->network }}
    + network: {{ $standaloneDocker->network }}
    @endforeach + @foreach ($swarmDockers as $swarmDocker) +
    +
    +
    + Swarm Docker ({{ $swarmDocker->name }}) +
    +
    +
    + @endforeach
    @endif
    From 6f00740f6755e9a462108e1f52d56479383a5512 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 30 Aug 2023 14:46:51 +0200 Subject: [PATCH 30/44] better boarding flow --- .../Project/New/GithubPrivateRepository.php | 22 ++++- app/Http/Livewire/Source/Github/Change.php | 1 - app/Http/Livewire/Source/Github/Create.php | 3 + app/Traits/SaveFromRedirect.php | 25 ++++++ app/View/Components/Forms/Button.php | 5 +- bootstrap/helpers/shared.php | 5 +- resources/js/components/MagicBar.vue | 9 ++ .../views/livewire/boarding/index.blade.php | 30 +++---- .../new/github-private-repository.blade.php | 11 ++- .../livewire/project/new/select.blade.php | 5 +- .../livewire/source/github/change.blade.php | 88 ++++++++++--------- resources/views/source/all.blade.php | 9 +- routes/web.php | 20 +++++ 13 files changed, 153 insertions(+), 80 deletions(-) create mode 100644 app/Traits/SaveFromRedirect.php diff --git a/app/Http/Livewire/Project/New/GithubPrivateRepository.php b/app/Http/Livewire/Project/New/GithubPrivateRepository.php index 77b2b2dab..dec4e80e8 100644 --- a/app/Http/Livewire/Project/New/GithubPrivateRepository.php +++ b/app/Http/Livewire/Project/New/GithubPrivateRepository.php @@ -7,15 +7,19 @@ use App\Models\GithubApp; use App\Models\Project; use App\Models\StandaloneDocker; use App\Models\SwarmDocker; +use App\Traits\SaveFromRedirect; use Illuminate\Support\Facades\Http; use Livewire\Component; +use Route; class GithubPrivateRepository extends Component { + use SaveFromRedirect; public $current_step = 'github_apps'; public $github_apps; public GithubApp $github_app; public $parameters; + public $currentRoute; public $query; public $type; @@ -36,14 +40,30 @@ class GithubPrivateRepository extends Component public string|null $publish_directory = null; protected int $page = 1; + // public function saveFromRedirect(string $route, ?Collection $parameters = null){ + // session()->forget('from'); + // if (!$parameters || $parameters->count() === 0) { + // $parameters = $this->parameters; + // } + // $parameters = collect($parameters) ?? collect([]); + // $queries = collect($this->query) ?? collect([]); + // $parameters = $parameters->merge($queries); + // session(['from'=> [ + // 'back'=> $this->currentRoute, + // 'route' => $route, + // 'parameters' => $parameters + // ]]); + // return redirect()->route($route); + // } + public function mount() { + $this->currentRoute = Route::currentRouteName(); $this->parameters = get_route_parameters(); $this->query = request()->query(); $this->repositories = $this->branches = collect(); $this->github_apps = GithubApp::private(); } - public function loadRepositories($github_app_id) { $this->repositories = collect(); diff --git a/app/Http/Livewire/Source/Github/Change.php b/app/Http/Livewire/Source/Github/Change.php index f4ab49c1a..4012386ae 100644 --- a/app/Http/Livewire/Source/Github/Change.php +++ b/app/Http/Livewire/Source/Github/Change.php @@ -39,7 +39,6 @@ class Change extends Component { if (is_cloud() && !isDev()) { $this->webhook_endpoint = config('app.url'); - ray($this->webhook_endpoint); } else { $this->webhook_endpoint = $this->ipv4; $this->is_system_wide = $this->github_app->is_system_wide; diff --git a/app/Http/Livewire/Source/Github/Create.php b/app/Http/Livewire/Source/Github/Create.php index 4d6f8b26b..b5487bcc8 100644 --- a/app/Http/Livewire/Source/Github/Create.php +++ b/app/Http/Livewire/Source/Github/Create.php @@ -42,6 +42,9 @@ class Create extends Component 'is_system_wide' => $this->is_system_wide, 'team_id' => currentTeam()->id, ]); + if (session('from')) { + session(['from' => session('from') + ['source_id' => $github_app->id]]); + } redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]); } catch (\Exception $e) { return general_error_handler(err: $e, that: $this); diff --git a/app/Traits/SaveFromRedirect.php b/app/Traits/SaveFromRedirect.php new file mode 100644 index 000000000..83013a857 --- /dev/null +++ b/app/Traits/SaveFromRedirect.php @@ -0,0 +1,25 @@ +forget('from'); + if (!$parameters || $parameters->count() === 0) { + $parameters = $this->parameters; + } + $parameters = collect($parameters) ?? collect([]); + $queries = collect($this->query) ?? collect([]); + $parameters = $parameters->merge($queries); + session(['from' => [ + 'back' => $this->currentRoute, + 'route' => $route, + 'parameters' => $parameters + ]]); + return redirect()->route($route); + } +} diff --git a/app/View/Components/Forms/Button.php b/app/View/Components/Forms/Button.php index 2b67c6915..c9f4ebdc0 100644 --- a/app/View/Components/Forms/Button.php +++ b/app/View/Components/Forms/Button.php @@ -15,7 +15,7 @@ class Button extends Component public bool $disabled = false, public bool $isModal = false, public bool $noStyle = false, - public string|null $modalId = null, + public ?string $modalId = null, public string $defaultClass = "btn btn-primary btn-sm font-normal text-white normal-case no-animation rounded border-none" ) { if ($this->noStyle) { @@ -23,9 +23,6 @@ class Button extends Component } } - /** - * Get the view / contents that represent the component. - */ public function render(): View|Closure|string { return view('components.forms.button'); diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 378bfae47..da8eaebdf 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -7,6 +7,7 @@ use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException; use Illuminate\Database\QueryException; use Illuminate\Mail\Message; use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Route; @@ -52,8 +53,7 @@ function showBoarding(): bool } function refreshSession(): void { - $team = currentTeam(); - session(['currentTeam' => $team]); + session(['currentTeam' => currentTeam()]); } function general_error_handler(Throwable | null $err = null, $that = null, $isJson = false, $customErrorMessage = null): mixed { @@ -259,3 +259,4 @@ function send_user_an_email(MailMessage $mail, string $email): void ->html((string) $mail->render()) ); } + diff --git a/resources/js/components/MagicBar.vue b/resources/js/components/MagicBar.vue index a0e8f762c..5719bc1d6 100644 --- a/resources/js/components/MagicBar.vue +++ b/resources/js/components/MagicBar.vue @@ -408,6 +408,12 @@ const magicActions = [{ name: 'Goto: Switch Teams', icon: 'goto', sequence: ['main', 'redirect'] +}, +{ + id: 23, + name: 'Goto: Boarding process', + icon: 'goto', + sequence: ['main', 'redirect'] } ] const initialState = { @@ -635,6 +641,9 @@ async function redirect() { case 22: targetUrl.pathname = `/team` break; + case 23: + targetUrl.pathname = `/boarding` + break; } window.location.href = targetUrl; } diff --git a/resources/views/livewire/boarding/index.blade.php b/resources/views/livewire/boarding/index.blade.php index d38aa0190..a62b0c705 100644 --- a/resources/views/livewire/boarding/index.blade.php +++ b/resources/views/livewire/boarding/index.blade.php @@ -5,8 +5,8 @@

    Welcome to Coolify

    Let me help you to set the basics.

    -
    Get Started -
    + Get Started +
    @endif
    @@ -18,10 +18,10 @@ or on a ? -
    Localhost -
    -
    Remote Server -
    + Localhost + + Remote Server +

    Servers are the main building blocks, as they will host your applications, databases, @@ -42,10 +42,10 @@ Do you have your own SSH Private Key? -

    Yes -
    -
    No (create one for me) -
    + Yes + + No (create one for me) + @if (count($privateKeys) > 0)
    @@ -76,8 +76,8 @@ There are already servers available for your Team. Do you want to use one of them? -
    No (create a new one) -
    + No (create one for me) +
    @@ -182,9 +182,9 @@ Could not find Docker Engine on your server. Do you want me to install it for you? -
    + Let's do - it!
    + it!

    This will install the latest Docker Engine on your server, configure a few things to be able @@ -233,7 +233,7 @@ @endif -

    Let's create a new one!
    + Let's create a new one!
    @if (count($projects) > 0)

    Create a new Application

    - - + Add New GitHub App - - + + + Add New GitHub App +
    Deploy any public or private git repositories through a GitHub App.
    @if ($github_apps->count() !== 0) @@ -25,7 +24,7 @@ {{ $ghapp->name }}
    {{ $ghapp->http_url }}
    -
    @@ -39,7 +38,7 @@
    {{ data_get($ghapp, 'html_url') }}
    - Loading...
    diff --git a/resources/views/livewire/project/new/select.blade.php b/resources/views/livewire/project/new/select.blade.php index 9cdfe515f..be76d5e66 100644 --- a/resources/views/livewire/project/new/select.blade.php +++ b/resources/views/livewire/project/new/select.blade.php @@ -70,7 +70,6 @@ - @endif @if ($current_step === 'servers') @@ -79,7 +78,7 @@
  • Select a Server
  • Select a Destination
  • -
    +
    @forelse($servers as $server)
    @@ -108,7 +107,7 @@
  • Select a Server
  • Select a Destination
  • -
    +
    @foreach ($standaloneDockers as $standaloneDocker)
    diff --git a/resources/views/livewire/source/github/change.blade.php b/resources/views/livewire/source/github/change.blade.php index 632791b9f..8f987db70 100644 --- a/resources/views/livewire/source/github/change.blade.php +++ b/resources/views/livewire/source/github/change.blade.php @@ -11,17 +11,15 @@ @if ($github_app->app_id) Save - - - @if ($github_app->installation_id) + @if (data_get($github_app, 'installation_id')) + + + Update Repositories - @else - Install Repositories - - @endif - - + + + @endif @else Save @endif @@ -30,8 +28,21 @@
    -
    Your Private GitHub App for private repositories.
    - @if ($github_app->app_id) +
    Your Private GitHub App for private repositories.
    + @if (data_get($github_app, 'app_id')) + @if (!data_get($github_app, 'installation_id')) +
    + + + + You must complete this step before you can use this source! +
    + + Install Repositories on GitHub + + @else
    + @endif + @else +
    + + + + You must complete this step before you can use this source! +
    -
    -

    Register a GitHub App

    - - Register a - GitHub - Application - -
    +

    Register a GitHub App

    You need to register a GitHub App before using this source.
    @if (!is_cloud() || isDev()) @@ -90,8 +103,20 @@ @if ($fqdn) @endif + @if (config('app.url')) + + @endif + + Register +
    + @else + + Register Now + @endif
    -
    - - -
    -
    - - -
    -
    - @if ($github_app->html_url === 'https://github.com') - - - @else - - - @endif -
    - @if (!is_cloud() || isDev()) - - @endif @endauth - @guest - {{ $slot }} - @endguest @show From 472ed0753d77da66ecf6035c26cce36c78526e95 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 31 Aug 2023 21:51:05 +0200 Subject: [PATCH 39/44] update --- app/Jobs/SendConfirmationForWaitlistJob.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Jobs/SendConfirmationForWaitlistJob.php b/app/Jobs/SendConfirmationForWaitlistJob.php index 3ff4982d9..041b418ec 100755 --- a/app/Jobs/SendConfirmationForWaitlistJob.php +++ b/app/Jobs/SendConfirmationForWaitlistJob.php @@ -37,7 +37,7 @@ class SendConfirmationForWaitlistJob implements ShouldQueue $mail->subject('You are on the waitlist!'); send_user_an_email($mail, $this->email); } catch (\Throwable $th) { - send_internal_notification('SendConfirmationForWaitlistJob failed with error: ' . $th->getMessage()); + send_internal_notification("SendConfirmationForWaitlistJob failed for {$mail} with error: " . $th->getMessage()); ray($th->getMessage()); throw $th; } From e74efc4e76ca9cab3369708f49a77d169b8a75bc Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 31 Aug 2023 21:56:53 +0200 Subject: [PATCH 40/44] fix --- resources/views/layouts/base.blade.php | 96 +++++++++++++------------- 1 file changed, 47 insertions(+), 49 deletions(-) diff --git a/resources/views/layouts/base.blade.php b/resources/views/layouts/base.blade.php index e44235ccd..6302eddeb 100644 --- a/resources/views/layouts/base.blade.php +++ b/resources/views/layouts/base.blade.php @@ -25,60 +25,58 @@ @livewireScripts - @auth - - - - @endauth + } + } + + function copyToClipboard(text) { + navigator.clipboard.writeText(text); + Livewire.emit('success', 'Copied to clipboard.'); + } + + Livewire.on('reloadWindow', (timeout) => { + if (timeout) { + setTimeout(() => { + window.location.reload(); + }, timeout); + return; + } else { + window.location.reload(); + } + }) + Livewire.on('info', (message) => { + if (message) Toaster.info(message) + }) + Livewire.on('error', (message) => { + if (message) Toaster.error(message) + }) + Livewire.on('warning', (message) => { + if (message) Toaster.warning(message) + }) + Livewire.on('success', (message) => { + if (message) Toaster.success(message) + }) + @show From 3fabff93f65197c72869ba4701d914c8b39adffa Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 1 Sep 2023 09:34:25 +0200 Subject: [PATCH 41/44] fix a few things --- app/Http/Controllers/Controller.php | 8 -------- app/Http/Livewire/Dashboard.php | 1 - .../{Waitlist.php => Waitlist/Index.php} | 17 +++++++++++------ app/Providers/FortifyServiceProvider.php | 10 ++-------- resources/views/auth/waitlist.blade.php | 3 --- .../views/components/pricing-plans.blade.php | 18 ++++++++++++++++++ .../index.blade.php} | 2 +- routes/web.php | 3 ++- 8 files changed, 34 insertions(+), 28 deletions(-) rename app/Http/Livewire/{Waitlist.php => Waitlist/Index.php} (77%) delete mode 100644 resources/views/auth/waitlist.blade.php rename resources/views/livewire/{waitlist.blade.php => waitlist/index.blade.php} (98%) diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 72893f974..39b0881e3 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -5,11 +5,9 @@ namespace App\Http\Controllers; use App\Models\InstanceSettings; 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 App\Models\Waitlist; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Routing\Controller as BaseController; @@ -19,12 +17,6 @@ class Controller extends BaseController { use AuthorizesRequests, ValidatesRequests; - public function waitlist() { - $waiting_in_line = Waitlist::whereVerified(true)->count(); - return view('auth.waitlist', [ - 'waiting_in_line' => $waiting_in_line, - ]); - } public function subscription() { if (!isCloud()) { diff --git a/app/Http/Livewire/Dashboard.php b/app/Http/Livewire/Dashboard.php index 98c330847..874e389e0 100644 --- a/app/Http/Livewire/Dashboard.php +++ b/app/Http/Livewire/Dashboard.php @@ -6,7 +6,6 @@ use App\Models\Project; use App\Models\S3Storage; use App\Models\Server; use Livewire\Component; -use Log; class Dashboard extends Component { diff --git a/app/Http/Livewire/Waitlist.php b/app/Http/Livewire/Waitlist/Index.php similarity index 77% rename from app/Http/Livewire/Waitlist.php rename to app/Http/Livewire/Waitlist/Index.php index d9b3b92ab..06d224afe 100644 --- a/app/Http/Livewire/Waitlist.php +++ b/app/Http/Livewire/Waitlist/Index.php @@ -1,22 +1,27 @@ 'required|email', ]; + public function render() + { + return view('livewire.waitlist.index')->layout('layouts.simple'); + } public function mount() { + $this->waitingInLine = Waitlist::whereVerified(true)->count(); if (isDev()) { $this->email = 'waitlist@example.com'; } @@ -29,7 +34,7 @@ class Waitlist extends Component if ($already_registered) { throw new \Exception('You are already on the waitlist or registered.
    Please check your email to verify your email address or contact support.'); } - $found = ModelsWaitlist::where('email', $this->email)->first(); + $found = Waitlist::where('email', $this->email)->first(); if ($found) { if (!$found->verified) { $this->emit('error', 'You are already on the waitlist.
    Please check your email to verify your email address.'); @@ -38,7 +43,7 @@ class Waitlist extends Component $this->emit('error', 'You are already on the waitlist.
    You will be notified when your turn comes.
    Thank you.'); return; } - $waitlist = ModelsWaitlist::create([ + $waitlist = Waitlist::create([ 'email' => $this->email, 'type' => 'registration', ]); diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php index eee442390..a5fce4858 100644 --- a/app/Providers/FortifyServiceProvider.php +++ b/app/Providers/FortifyServiceProvider.php @@ -43,22 +43,16 @@ class FortifyServiceProvider extends ServiceProvider */ public function boot(): void { - Fortify::createUsersUsing(CreateNewUser::class); Fortify::registerView(function () { $settings = InstanceSettings::get(); - $waiting_in_line = Waitlist::whereVerified(true)->count(); if (!$settings->is_registration_enabled) { return redirect()->route('login'); } if (config('coolify.waitlist')) { - return view('auth.waitlist',[ - 'waiting_in_line' => $waiting_in_line, - ]); + return redirect()->route('waitlist.index'); } else { - return view('auth.register',[ - 'waiting_in_line' => $waiting_in_line, - ]); + return view('auth.register'); } }); diff --git a/resources/views/auth/waitlist.blade.php b/resources/views/auth/waitlist.blade.php deleted file mode 100644 index 497bb0868..000000000 --- a/resources/views/auth/waitlist.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/resources/views/components/pricing-plans.blade.php b/resources/views/components/pricing-plans.blade.php index 95a9ee4d3..c231f1d21 100644 --- a/resources/views/components/pricing-plans.blade.php +++ b/resources/views/components/pricing-plans.blade.php @@ -192,6 +192,15 @@ Basic Support +
  • + + Included Email System +
  • @@ -250,6 +259,15 @@ Priority Support
  • +
  • + + Included Email System +
  • diff --git a/resources/views/livewire/waitlist.blade.php b/resources/views/livewire/waitlist/index.blade.php similarity index 98% rename from resources/views/livewire/waitlist.blade.php rename to resources/views/livewire/waitlist/index.blade.php index 60b807872..06c5f9d5a 100644 --- a/resources/views/livewire/waitlist.blade.php +++ b/resources/views/livewire/waitlist/index.blade.php @@ -23,7 +23,7 @@ Join Waitlist - Waiting in the line: {{ $waiting_in_line }} + Waiting in the line: {{ $waitingInLine }}
    See the pricing here.
    diff --git a/routes/web.php b/routes/web.php index 8c4734a82..d59b9a48d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -11,6 +11,7 @@ use App\Http\Livewire\Boarding\Server as BoardingServer; use App\Http\Livewire\Dashboard; use App\Http\Livewire\Server\All; use App\Http\Livewire\Server\Show; +use App\Http\Livewire\Waitlist\Index as WaitlistIndex; use App\Models\GithubApp; use App\Models\GitlabApp; use App\Models\InstanceSettings; @@ -46,7 +47,7 @@ Route::post('/forgot-password', function (Request $request) { } return response()->json(['message' => 'Transactional emails are not active'], 400); })->name('password.forgot'); -Route::get('/waitlist', [Controller::class, 'waitlist'])->name('auth.waitlist'); +Route::get('/waitlist', WaitlistIndex::class)->name('waitlist.index'); Route::prefix('magic')->middleware(['auth'])->group(function () { Route::get('/servers', [MagicController::class, 'servers']); From f75a324030f39e11619450e62ae7326f3ea21bd9 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 1 Sep 2023 10:02:24 +0200 Subject: [PATCH 42/44] fix: proxy start job --- app/Actions/Proxy/SaveConfigurationSync.php | 21 +++++++++++++-------- app/Actions/Proxy/StartProxy.php | 6 ------ app/Jobs/DockerCleanupJob.php | 14 ++++++++++---- app/Jobs/ProxyCheckJob.php | 5 +++-- app/Jobs/ProxyStartJob.php | 7 +++++++ 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/app/Actions/Proxy/SaveConfigurationSync.php b/app/Actions/Proxy/SaveConfigurationSync.php index c17607516..b35b4375b 100644 --- a/app/Actions/Proxy/SaveConfigurationSync.php +++ b/app/Actions/Proxy/SaveConfigurationSync.php @@ -9,15 +9,20 @@ class SaveConfigurationSync { public function __invoke(Server $server, string $configuration) { - $proxy_path = get_proxy_path(); - $docker_compose_yml_base64 = base64_encode($configuration); + try { + $proxy_path = get_proxy_path(); + $docker_compose_yml_base64 = base64_encode($configuration); - $server->proxy->last_saved_settings = Str::of($docker_compose_yml_base64)->pipe('md5')->value; - $server->save(); + $server->proxy->last_saved_settings = Str::of($docker_compose_yml_base64)->pipe('md5')->value; + $server->save(); + + instant_remote_process([ + "mkdir -p $proxy_path", + "echo '$docker_compose_yml_base64' | base64 -d > $proxy_path/docker-compose.yml", + ], $server); + } catch (\Throwable $th) { + ray($th); + } - instant_remote_process([ - "mkdir -p $proxy_path", - "echo '$docker_compose_yml_base64' | base64 -d > $proxy_path/docker-compose.yml", - ], $server); } } diff --git a/app/Actions/Proxy/StartProxy.php b/app/Actions/Proxy/StartProxy.php index b9d9ab02b..d541921be 100644 --- a/app/Actions/Proxy/StartProxy.php +++ b/app/Actions/Proxy/StartProxy.php @@ -12,12 +12,6 @@ class StartProxy { public function __invoke(Server $server): Activity { - // TODO: check for other proxies - if (is_null(data_get($server, 'proxy.type'))) { - $server->proxy->type = ProxyTypes::TRAEFIK_V2->value; - $server->proxy->status = ProxyStatus::EXITED->value; - $server->save(); - } $proxy_path = get_proxy_path(); $networks = collect($server->standaloneDockers)->map(function ($docker) { return $docker['network']; diff --git a/app/Jobs/DockerCleanupJob.php b/app/Jobs/DockerCleanupJob.php index 071846fe6..6ac00bc4b 100644 --- a/app/Jobs/DockerCleanupJob.php +++ b/app/Jobs/DockerCleanupJob.php @@ -34,7 +34,13 @@ class DockerCleanupJob implements ShouldQueue if (isDev()) { $this->dockerRootFilesystem = "/"; } else { - $this->dockerRootFilesystem = instant_remote_process(["stat --printf=%m $(docker info --format '{{json .DockerRootDir}}'' |sed 's/\"//g')"], $server, false); + $this->dockerRootFilesystem = instant_remote_process( + [ + "stat --printf=%m $(docker info --format '{{json .DockerRootDir}}'' |sed 's/\"//g')" + ], + $server, + false + ); } if (!$this->dockerRootFilesystem) { continue; @@ -47,9 +53,9 @@ class DockerCleanupJob implements ShouldQueue instant_remote_process(['docker builder prune -af'], $server); $usageAfter = $this->getFilesystemUsage($server); if ($usageAfter < $this->usageBefore) { - ray('Saved ' . ( $this->usageBefore - $usageAfter) . '% disk space on ' . $server->name)->color('orange'); - send_internal_notification('DockerCleanupJob done: Saved ' . ( $this->usageBefore - $usageAfter) . '% disk space on ' . $server->name); - }else { + ray('Saved ' . ($this->usageBefore - $usageAfter) . '% disk space on ' . $server->name)->color('orange'); + send_internal_notification('DockerCleanupJob done: Saved ' . ($this->usageBefore - $usageAfter) . '% disk space on ' . $server->name); + } else { ray('DockerCleanupJob failed to save disk space on ' . $server->name)->color('orange'); } } else { diff --git a/app/Jobs/ProxyCheckJob.php b/app/Jobs/ProxyCheckJob.php index 9d5559053..720dd2ea1 100755 --- a/app/Jobs/ProxyCheckJob.php +++ b/app/Jobs/ProxyCheckJob.php @@ -33,8 +33,9 @@ class ProxyCheckJob implements ShouldQueue if ($status === 'running') { continue; } - // $server->team->notify(new ProxyStoppedNotification($server)); - resolve(StartProxy::class)($server); + if (data_get($server, 'proxy.type')) { + resolve(StartProxy::class)($server); + } } } catch (\Throwable $th) { ray($th->getMessage()); diff --git a/app/Jobs/ProxyStartJob.php b/app/Jobs/ProxyStartJob.php index 4e2331a68..91932a48c 100755 --- a/app/Jobs/ProxyStartJob.php +++ b/app/Jobs/ProxyStartJob.php @@ -3,6 +3,8 @@ namespace App\Jobs; use App\Actions\Proxy\StartProxy; +use App\Enums\ProxyStatus; +use App\Enums\ProxyTypes; use App\Models\Server; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; @@ -27,6 +29,11 @@ class ProxyStartJob implements ShouldQueue if ($status === 'running') { return; } + if (is_null(data_get($this->server, 'proxy.type'))) { + $this->server->proxy->type = ProxyTypes::TRAEFIK_V2->value; + $this->server->proxy->status = ProxyStatus::EXITED->value; + $this->server->save(); + } resolve(StartProxy::class)($this->server); } catch (\Throwable $th) { send_internal_notification('ProxyStartJob failed with: ' . $th->getMessage()); From 8e86ce671cab712573edc4231799cf097d992151 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 1 Sep 2023 10:11:00 +0200 Subject: [PATCH 43/44] fix: dockerimage jobs are not overlapping --- app/Actions/Server/UpdateCoolify.php | 25 ++++++++++++------------- app/Console/Kernel.php | 2 +- app/Jobs/ApplicationDeploymentJob.php | 7 +++++++ app/Jobs/DockerCleanupJob.php | 8 ++++++++ 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/app/Actions/Server/UpdateCoolify.php b/app/Actions/Server/UpdateCoolify.php index e988965ec..de4700b75 100644 --- a/app/Actions/Server/UpdateCoolify.php +++ b/app/Actions/Server/UpdateCoolify.php @@ -7,9 +7,9 @@ use App\Models\Server; class UpdateCoolify { - public Server $server; - public string $latest_version; - public string $current_version; + public ?Server $server = null; + public ?string $latestVersion = null; + public ?string $currentVersion = null; public function __invoke(bool $force) { @@ -19,15 +19,14 @@ class UpdateCoolify $localhost_name = 'localhost'; $this->server = Server::where('name', $localhost_name)->first(); if (!$this->server) { - // No server found, so we are running on local docker container return; } - $this->latest_version = get_latest_version_of_coolify(); - $this->current_version = config('version'); - ray('latest version:' . $this->latest_version . " current version: " . $this->current_version . ' force: ' . $force); + $this->latestVersion = get_latest_version_of_coolify(); + $this->currentVersion = config('version'); + ray('latest version:' . $this->latestVersion . " current version: " . $this->currentVersion . ' force: ' . $force); if ($settings->next_channel) { ray('next channel enabled'); - $this->latest_version = 'next'; + $this->latestVersion = 'next'; } if ($force) { $this->update(); @@ -35,15 +34,15 @@ class UpdateCoolify if (!$settings->is_auto_update_enabled) { return 'Auto update is disabled'; } - if ($this->latest_version === $this->current_version) { + if ($this->latestVersion === $this->currentVersion) { return 'Already on latest version'; } - if (version_compare($this->latest_version, $this->current_version, '<')) { + if (version_compare($this->latestVersion, $this->currentVersion, '<')) { return 'Latest version is lower than current version?!'; } $this->update(); } - send_internal_notification('InstanceAutoUpdateJob done to version: ' . $this->latest_version . ' from version: ' . $this->current_version); + send_internal_notification('InstanceAutoUpdateJob done to version: ' . $this->latestVersion . ' from version: ' . $this->currentVersion); } catch (\Exception $th) { ray('InstanceAutoUpdateJob failed'); ray($th->getMessage()); @@ -55,7 +54,7 @@ class UpdateCoolify private function update() { if (isDev()) { - ray("Running update on local docker container. Updating to $this->latest_version"); + ray("Running update on local docker container. Updating to $this->latestVersion"); remote_process([ "sleep 10" ], $this->server); @@ -65,7 +64,7 @@ class UpdateCoolify ray('Running update on production server'); remote_process([ "curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh -o /data/coolify/source/upgrade.sh", - "bash /data/coolify/source/upgrade.sh $this->latest_version" + "bash /data/coolify/source/upgrade.sh $this->latestVersion" ], $this->server); return; } diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index ffedc6e72..07032e1a1 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -25,7 +25,7 @@ class Kernel extends ConsoleKernel $schedule->job(new CleanupInstanceStuffsJob)->everyMinute(); // $schedule->job(new CheckResaleLicenseJob)->hourly(); - // $schedule->job(new DockerCleanupJob)->everyOddHour(); + $schedule->job(new DockerCleanupJob)->everyOddHour(); // $schedule->job(new InstanceAutoUpdateJob(true))->everyMinute(); } else { $schedule->command('horizon:snapshot')->everyFiveMinutes(); diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 5f24d4ab8..715b22b91 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -20,6 +20,7 @@ use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Collection; use Illuminate\Support\Str; @@ -65,6 +66,12 @@ class ApplicationDeploymentJob implements ShouldQueue private $log_model; private Collection $saved_outputs; + public function middleware(): array + { + return [ + (new WithoutOverlapping("dockerimagejobs"))->shared(), + ]; + } public function __construct(int $application_deployment_queue_id) { ray()->clearScreen(); diff --git a/app/Jobs/DockerCleanupJob.php b/app/Jobs/DockerCleanupJob.php index 6ac00bc4b..4456eee5e 100644 --- a/app/Jobs/DockerCleanupJob.php +++ b/app/Jobs/DockerCleanupJob.php @@ -7,6 +7,7 @@ use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Str; @@ -17,6 +18,13 @@ class DockerCleanupJob implements ShouldQueue public $timeout = 500; public ?string $dockerRootFilesystem = null; public ?int $usageBefore = null; + + public function middleware(): array + { + return [ + (new WithoutOverlapping("dockerimagejobs"))->shared(), + ]; + } public function __construct() { } From 3e1120182c10c825060d557fe7fbe73071f3804b Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 1 Sep 2023 10:21:35 +0200 Subject: [PATCH 44/44] update --- resources/views/livewire/server/proxy/deploy.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/server/proxy/deploy.blade.php b/resources/views/livewire/server/proxy/deploy.blade.php index 685cddbdf..9e46ce0cc 100644 --- a/resources/views/livewire/server/proxy/deploy.blade.php +++ b/resources/views/livewire/server/proxy/deploy.blade.php @@ -20,7 +20,7 @@ @if (data_get($server, 'proxy.status') === 'running')