Merge pull request #3042 from peaklabs-dev/auto-cleanup-improvements

Feat: Cron input for docker cleanup job and docker cleanup improvements
This commit is contained in:
Andras Bacsai 2024-08-26 11:17:33 +02:00 committed by GitHub
commit e52f762cf9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 246 additions and 187 deletions

View File

@ -11,9 +11,30 @@ class CleanupDocker
public function handle(Server $server) public function handle(Server $server)
{ {
// cleanup docker images, containers, and builder caches
instant_remote_process(['docker image prune -af'], $server, false); $commands = $this->getCommands($force);
instant_remote_process(['docker container prune -f --filter "label=coolify.managed=true"'], $server, false);
instant_remote_process(['docker builder prune -af'], $server, false); foreach ($commands as $command) {
instant_remote_process([$command], $server, false);
}
}
private function getCommands(bool $force): array
{
$commonCommands = [
'docker container prune -f --filter "label=coolify.managed=true"',
'docker image prune -f',
'docker builder prune -f',
];
if ($force) {
return array_merge([
'docker container prune -f --filter "label=coolify.managed=true"',
'docker image prune -af',
'docker builder prune -af',
], $commonCommands);
}
return $commonCommands;
} }
} }

View File

@ -35,7 +35,6 @@ protected function schedule(Schedule $schedule): void
// Instance Jobs // Instance Jobs
$schedule->command('horizon:snapshot')->everyMinute(); $schedule->command('horizon:snapshot')->everyMinute();
$schedule->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer(); $schedule->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer();
// Server Jobs // Server Jobs
$this->check_scheduled_backups($schedule); $this->check_scheduled_backups($schedule);
$this->check_resources($schedule); $this->check_resources($schedule);
@ -44,7 +43,7 @@ protected function schedule(Schedule $schedule): void
} else { } else {
// Instance Jobs // Instance Jobs
$schedule->command('horizon:snapshot')->everyFiveMinutes(); $schedule->command('horizon:snapshot')->everyFiveMinutes();
$schedule->command('cleanup:unreachable-servers')->daily(); $schedule->command('cleanup:unreachable-servers')->daily()->onOneServer();
$schedule->job(new PullCoolifyImageJob)->cron($settings->update_check_frequency)->onOneServer(); $schedule->job(new PullCoolifyImageJob)->cron($settings->update_check_frequency)->onOneServer();
$schedule->job(new PullTemplatesFromCDN)->cron($settings->update_check_frequency)->onOneServer(); $schedule->job(new PullTemplatesFromCDN)->cron($settings->update_check_frequency)->onOneServer();
$schedule->job(new CleanupInstanceStuffsJob)->everyTwoMinutes()->onOneServer(); $schedule->job(new CleanupInstanceStuffsJob)->everyTwoMinutes()->onOneServer();
@ -67,7 +66,14 @@ private function pull_images($schedule)
$servers = $this->all_servers->where('settings.is_usable', true)->where('settings.is_reachable', true)->where('ip', '!=', '1.2.3.4'); $servers = $this->all_servers->where('settings.is_usable', true)->where('settings.is_reachable', true)->where('ip', '!=', '1.2.3.4');
foreach ($servers as $server) { foreach ($servers as $server) {
if ($server->isSentinelEnabled()) { if ($server->isSentinelEnabled()) {
$schedule->job(new PullSentinelImageJob($server))->cron($settings->update_check_frequency)->onOneServer(); $schedule->job(function () use ($server) {
$sentinel_found = instant_remote_process(['docker inspect coolify-sentinel'], $server, false);
$sentinel_found = json_decode($sentinel_found, true);
$status = data_get($sentinel_found, '0.State.Status', 'exited');
if ($status !== 'running') {
PullSentinelImageJob::dispatch($server);
}
})->cron($settings->update_check_frequency)->onOneServer();
} }
$schedule->job(new PullHelperImageJob($server))->cron($settings->update_check_frequency)->onOneServer(); $schedule->job(new PullHelperImageJob($server))->cron($settings->update_check_frequency)->onOneServer();
} }
@ -97,7 +103,11 @@ private function check_resources($schedule)
} }
foreach ($servers as $server) { foreach ($servers as $server) {
$schedule->job(new ServerCheckJob($server))->everyMinute()->onOneServer(); $schedule->job(new ServerCheckJob($server))->everyMinute()->onOneServer();
$schedule->job(new DockerCleanupJob($server))->everyTenMinutes()->onOneServer(); //The lines below need to be added as soon as timzone is merged!!
//$serverTimezone = $server->settings->server_timezone;
//$schedule->job(new DockerCleanupJob($server))->cron($server->settings->docker_cleanup_frequency)->timezone($serverTimezone)->onOneServer();
$schedule->job(new DockerCleanupJob($server))->cron($server->settings->docker_cleanup_frequency)->onOneServer();
} }
} }
@ -108,7 +118,7 @@ private function check_scheduled_backups($schedule)
return; return;
} }
foreach ($scheduled_backups as $scheduled_backup) { foreach ($scheduled_backups as $scheduled_backup) {
if (! $scheduled_backup->enabled) { if (!$scheduled_backup->enabled) {
continue; continue;
} }
if (is_null(data_get($scheduled_backup, 'database'))) { if (is_null(data_get($scheduled_backup, 'database'))) {
@ -140,7 +150,7 @@ private function check_scheduled_tasks($schedule)
$service = $scheduled_task->service; $service = $scheduled_task->service;
$application = $scheduled_task->application; $application = $scheduled_task->application;
if (! $application && ! $service) { if (!$application && !$service) {
ray('application/service attached to scheduled task does not exist'); ray('application/service attached to scheduled task does not exist');
$scheduled_task->delete(); $scheduled_task->delete();
@ -167,7 +177,7 @@ private function check_scheduled_tasks($schedule)
protected function commands(): void protected function commands(): void
{ {
$this->load(__DIR__.'/Commands'); $this->load(__DIR__ . '/Commands');
require base_path('routes/console.php'); require base_path('routes/console.php');
} }

View File

@ -27,20 +27,25 @@ public function __construct(public Server $server) {}
public function handle(): void public function handle(): void
{ {
if (! $this->server->isFunctional()) { try {
return; if (! $this->server->isFunctional()) {
} return;
if ($this->server->settings->is_force_cleanup_enabled) { }
Log::info('DockerCleanupJob force cleanup on '.$this->server->name); if ($this->server->settings->force_docker_cleanup) {
CleanupDocker::run(server: $this->server); Log::info('DockerCleanupJob force cleanup on ' . $this->server->name);
CleanupDocker::run(server: $this->server, force: true);
return;
}
return; return;
} }
try { try {
$this->usageBefore = $this->server->getDiskUsage(); $this->usageBefore = $this->server->getDiskUsage();
if (str($this->usageBefore)->trim()->isEmpty()) { if (str($this->usageBefore)->isEmpty() || $this->usageBefore === null || $this->usageBefore === 0) {
Log::info('DockerCleanupJob force cleanup on '.$this->server->name); Log::info('DockerCleanupJob force cleanup on ' . $this->server->name);
CleanupDocker::run(server: $this->server); CleanupDocker::run(server: $this->server, force: true);
return; return;
} }
@ -48,13 +53,13 @@ public function handle(): void
CleanupDocker::run(server: $this->server); CleanupDocker::run(server: $this->server);
$usageAfter = $this->server->getDiskUsage(); $usageAfter = $this->server->getDiskUsage();
if ($usageAfter < $this->usageBefore) { if ($usageAfter < $this->usageBefore) {
$this->server->team?->notify(new DockerCleanup($this->server, 'Saved '.($this->usageBefore - $usageAfter).'% disk space.')); $this->server->team?->notify(new DockerCleanup($this->server, 'Saved ' . ($this->usageBefore - $usageAfter) . '% disk space.'));
Log::info('DockerCleanupJob done: Saved '.($this->usageBefore - $usageAfter).'% disk space on '.$this->server->name); Log::info('DockerCleanupJob done: Saved ' . ($this->usageBefore - $usageAfter) . '% disk space on ' . $this->server->name);
} else { } else {
Log::info('DockerCleanupJob failed to save disk space on '.$this->server->name); Log::info('DockerCleanupJob failed to save disk space on ' . $this->server->name);
} }
} else { } else {
Log::info('No need to clean up '.$this->server->name); Log::info('No need to clean up ' . $this->server->name);
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
CleanupDocker::run(server: $this->server); CleanupDocker::run(server: $this->server);
@ -62,4 +67,4 @@ public function handle(): void
throw $e; throw $e;
} }
} }
} }

View File

@ -79,7 +79,6 @@ public function handle()
} }
GetContainersStatus::run($this->server, $this->containers, $containerReplicates); GetContainersStatus::run($this->server, $this->containers, $containerReplicates);
$this->checkLogDrainContainer(); $this->checkLogDrainContainer();
$this->checkSentinel();
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
@ -90,21 +89,6 @@ public function handle()
} }
private function checkSentinel()
{
if ($this->server->isSentinelEnabled()) {
$sentinelContainerFound = $this->containers->filter(function ($value, $key) {
return data_get($value, 'Name') === '/coolify-sentinel';
})->first();
if ($sentinelContainerFound) {
$status = data_get($sentinelContainerFound, 'State.Status');
if ($status !== 'running') {
PullSentinelImageJob::dispatch($this);
}
}
}
}
private function serverStatus() private function serverStatus()
{ {
['uptime' => $uptime] = $this->server->validateConnection(); ['uptime' => $uptime] = $this->server->validateConnection();

View File

@ -37,7 +37,6 @@ class Form extends Component
'server.settings.is_swarm_manager' => 'required|boolean', 'server.settings.is_swarm_manager' => 'required|boolean',
'server.settings.is_swarm_worker' => 'required|boolean', 'server.settings.is_swarm_worker' => 'required|boolean',
'server.settings.is_build_server' => 'required|boolean', 'server.settings.is_build_server' => 'required|boolean',
'server.settings.is_force_cleanup_enabled' => 'required|boolean',
'server.settings.concurrent_builds' => 'required|integer|min:1', 'server.settings.concurrent_builds' => 'required|integer|min:1',
'server.settings.dynamic_timeout' => 'required|integer|min:1', 'server.settings.dynamic_timeout' => 'required|integer|min:1',
'server.settings.is_metrics_enabled' => 'required|boolean', 'server.settings.is_metrics_enabled' => 'required|boolean',
@ -46,6 +45,9 @@ class Form extends Component
'server.settings.metrics_history_days' => 'required|integer|min:1', 'server.settings.metrics_history_days' => 'required|integer|min:1',
'wildcard_domain' => 'nullable|url', 'wildcard_domain' => 'nullable|url',
'server.settings.is_server_api_enabled' => 'required|boolean', 'server.settings.is_server_api_enabled' => 'required|boolean',
'server.settings.force_docker_cleanup' => 'required|boolean',
'server.settings.docker_cleanup_frequency' => 'required_if:server.settings.force_docker_cleanup,true|string',
'server.settings.docker_cleanup_threshold' => 'required_if:server.settings.force_docker_cleanup,false|integer|min:1|max:100',
]; ];
protected $validationAttributes = [ protected $validationAttributes = [
@ -71,7 +73,19 @@ class Form extends Component
public function mount() public function mount()
{ {
$this->wildcard_domain = $this->server->settings->wildcard_domain; $this->wildcard_domain = $this->server->settings->wildcard_domain;
$this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage; $this->server->settings->docker_cleanup_threshold = $this->server->settings->docker_cleanup_threshold;
$this->server->settings->docker_cleanup_frequency = $this->server->settings->docker_cleanup_frequency;
}
public function updated($field)
{
if ($field === 'server.settings.docker_cleanup_frequency') {
$frequency = $this->server->settings->docker_cleanup_frequency;
if (empty($frequency) || !validate_cron_expression($frequency)) {
$this->dispatch('error', 'Invalid Cron / Human expression for Docker Cleanup Frequency. Resetting to default 10 minutes.');
$this->server->settings->docker_cleanup_frequency = '*/10 * * * *';
}
}
} }
public function serverInstalled() public function serverInstalled()
@ -116,7 +130,6 @@ public function instantSave()
} }
if ($this->server->settings->isDirty('is_server_api_enabled') && $this->server->settings->is_server_api_enabled === true) { if ($this->server->settings->isDirty('is_server_api_enabled') && $this->server->settings->is_server_api_enabled === true) {
ray('Starting sentinel'); ray('Starting sentinel');
} }
} else { } else {
ray('Sentinel is not enabled'); ray('Sentinel is not enabled');
@ -156,7 +169,7 @@ public function checkLocalhostConnection()
$this->server->settings->save(); $this->server->settings->save();
$this->dispatch('proxyStatusUpdated'); $this->dispatch('proxyStatusUpdated');
} else { } else {
$this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.<br><br>Check this <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a> for further help. <br><br>Error: '.$error); $this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.<br><br>Check this <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a> for further help. <br><br>Error: ' . $error);
return; return;
} }
@ -172,7 +185,7 @@ public function validateServer($install = true)
public function submit() public function submit()
{ {
if (isCloud() && ! isDev()) { if (isCloud() && !isDev()) {
$this->validate(); $this->validate();
$this->validate([ $this->validate([
'server.ip' => 'required', 'server.ip' => 'required',
@ -190,9 +203,13 @@ public function submit()
} }
refresh_server_connection($this->server->privateKey); refresh_server_connection($this->server->privateKey);
$this->server->settings->wildcard_domain = $this->wildcard_domain; $this->server->settings->wildcard_domain = $this->wildcard_domain;
$this->server->settings->cleanup_after_percentage = $this->cleanup_after_percentage; if ($this->server->settings->force_docker_cleanup) {
$this->server->settings->docker_cleanup_frequency = $this->server->settings->docker_cleanup_frequency;
} else {
$this->server->settings->docker_cleanup_threshold = $this->server->settings->docker_cleanup_threshold;
}
$this->server->settings->save(); $this->server->settings->save();
$this->server->save(); $this->server->save();
$this->dispatch('success', 'Server updated.'); $this->dispatch('success', 'Server updated.');
} }
} }

View File

@ -10,10 +10,10 @@
type: 'object', type: 'object',
properties: [ properties: [
'id' => ['type' => 'integer'], 'id' => ['type' => 'integer'],
'cleanup_after_percentage' => ['type' => 'integer'],
'concurrent_builds' => ['type' => 'integer'], 'concurrent_builds' => ['type' => 'integer'],
'dynamic_timeout' => ['type' => 'integer'], 'dynamic_timeout' => ['type' => 'integer'],
'force_disabled' => ['type' => 'boolean'], 'force_disabled' => ['type' => 'boolean'],
'force_server_cleanup' => ['type' => 'boolean'],
'is_build_server' => ['type' => 'boolean'], 'is_build_server' => ['type' => 'boolean'],
'is_cloudflare_tunnel' => ['type' => 'boolean'], 'is_cloudflare_tunnel' => ['type' => 'boolean'],
'is_jump_server' => ['type' => 'boolean'], 'is_jump_server' => ['type' => 'boolean'],
@ -37,6 +37,8 @@
'metrics_history_days' => ['type' => 'integer'], 'metrics_history_days' => ['type' => 'integer'],
'metrics_refresh_rate_seconds' => ['type' => 'integer'], 'metrics_refresh_rate_seconds' => ['type' => 'integer'],
'metrics_token' => ['type' => 'string'], 'metrics_token' => ['type' => 'string'],
'docker_cleanup_frequency' => ['type' => 'string'],
'docker_cleanup_threshold' => ['type' => 'integer'],
'server_id' => ['type' => 'integer'], 'server_id' => ['type' => 'integer'],
'wildcard_domain' => ['type' => 'string'], 'wildcard_domain' => ['type' => 'string'],
'created_at' => ['type' => 'string'], 'created_at' => ['type' => 'string'],
@ -47,8 +49,13 @@ class ServerSetting extends Model
{ {
protected $guarded = []; protected $guarded = [];
protected $casts = [
'force_docker_cleanup' => 'boolean',
'docker_cleanup_threshold' => 'integer',
];
public function server() public function server()
{ {
return $this->belongsTo(Server::class); return $this->belongsTo(Server::class);
} }
} }

View File

@ -0,0 +1,46 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddServerCleanupFieldsToServerSettingsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('server_settings', function (Blueprint $table) {
$table->boolean('force_docker_cleanup')->default(false);
$table->string('docker_cleanup_frequency')->default('*/10 * * * *');
$table->integer('docker_cleanup_threshold')->default(80);
// Remove old columns
$table->dropColumn('cleanup_after_percentage');
$table->dropColumn('is_force_cleanup_enabled');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('server_settings', function (Blueprint $table) {
$table->dropColumn('force_docker_cleanup');
$table->dropColumn('docker_cleanup_frequency');
$table->dropColumn('docker_cleanup_threshold');
// Add back old columns
$table->integer('cleanup_after_percentage')->default(80);
$table->boolean('force_server_cleanup')->default(false);
});
}
}

View File

@ -3,73 +3,68 @@
<div class="flex gap-2"> <div class="flex gap-2">
<h2>General</h2> <h2>General</h2>
@if ($server->id === 0) @if ($server->id === 0)
<x-modal-confirmation buttonTitle="Save" title="Change Localhost" action="submit"> <x-modal-confirmation buttonTitle="Save" title="Change Localhost" action="submit">
You could lose a lot of functionalities if you change the server details of the server where Coolify You could lose a lot of functionalities if you change the server details of the server where Coolify
is is
running on.<br>Please think again. running on.<br>Please think again.
</x-modal-confirmation> </x-modal-confirmation>
@else @else
<x-forms.button type="submit">Save</x-forms.button> <x-forms.button type="submit">Save</x-forms.button>
@if ($server->isFunctional()) @if ($server->isFunctional())
<x-slide-over closeWithX fullScreen>
<x-slot:title>Validate & configure</x-slot:title>
<x-slot:content>
<livewire:server.validate-and-install :server="$server" ask />
</x-slot:content>
<x-forms.button @click="slideOverOpen=true" wire:click.prevent='validateServer' isHighlighted>
Revalidate server
</x-forms.button>
</x-slide-over>
@endif
@endif
</div>
@if ($server->isFunctional())
Server is reachable and validated.
@else
You can't use this server until it is validated.
@endif
@if ((!$server->settings->is_reachable || !$server->settings->is_usable) && $server->id !== 0)
<x-slide-over closeWithX fullScreen> <x-slide-over closeWithX fullScreen>
<x-slot:title>Validate & configure</x-slot:title> <x-slot:title>Validate & configure</x-slot:title>
<x-slot:content> <x-slot:content>
<livewire:server.validate-and-install :server="$server" /> <livewire:server.validate-and-install :server="$server" ask />
</x-slot:content> </x-slot:content>
<x-forms.button @click="slideOverOpen=true" <x-forms.button @click="slideOverOpen=true" wire:click.prevent='validateServer' isHighlighted>
class="w-full mt-8 mb-4 font-bold box-without-bg bg-coollabs hover:bg-coollabs-100" Revalidate server
wire:click.prevent='validateServer' isHighlighted>
Validate Server & Install Docker Engine
</x-forms.button> </x-forms.button>
</x-slide-over> </x-slide-over>
@if ($server->validation_logs)
<h4>Previous Validation Logs</h4>
<div class="pb-8">
{!! $server->validation_logs !!}
</div>
@endif @endif
@endif
</div>
@if ($server->isFunctional())
Server is reachable and validated.
@else
You can't use this server until it is validated.
@endif
@if ((!$server->settings->is_reachable || !$server->settings->is_usable) && $server->id !== 0)
<x-slide-over closeWithX fullScreen>
<x-slot:title>Validate & configure</x-slot:title>
<x-slot:content>
<livewire:server.validate-and-install :server="$server" />
</x-slot:content>
<x-forms.button @click="slideOverOpen=true" class="w-full mt-8 mb-4 font-bold box-without-bg bg-coollabs hover:bg-coollabs-100" wire:click.prevent='validateServer' isHighlighted>
Validate Server & Install Docker Engine
</x-forms.button>
</x-slide-over>
@if ($server->validation_logs)
<h4>Previous Validation Logs</h4>
<div class="pb-8">
{!! $server->validation_logs !!}
</div>
@endif
@endif @endif
@if ((!$server->settings->is_reachable || !$server->settings->is_usable) && $server->id === 0) @if ((!$server->settings->is_reachable || !$server->settings->is_usable) && $server->id === 0)
<x-forms.button class="mt-8 mb-4 font-bold box-without-bg bg-coollabs hover:bg-coollabs-100" <x-forms.button class="mt-8 mb-4 font-bold box-without-bg bg-coollabs hover:bg-coollabs-100" wire:click.prevent='checkLocalhostConnection' isHighlighted>
wire:click.prevent='checkLocalhostConnection' isHighlighted> Validate Server
Validate Server </x-forms.button>
</x-forms.button>
@endif @endif
@if ($server->isForceDisabled() && isCloud()) @if ($server->isForceDisabled() && isCloud())
<div class="pt-4 font-bold text-red-500">The system has disabled the server because you have exceeded the <div class="pt-4 font-bold text-red-500">The system has disabled the server because you have exceeded the
number of servers for which you have paid.</div> number of servers for which you have paid.</div>
@endif @endif
<div class="flex flex-col gap-2 pt-4"> <div class="flex flex-col gap-2 pt-4">
<div class="flex flex-col w-full gap-2 lg:flex-row"> <div class="flex flex-col w-full gap-2 lg:flex-row">
<x-forms.input id="server.name" label="Name" required /> <x-forms.input id="server.name" label="Name" required />
<x-forms.input id="server.description" label="Description" /> <x-forms.input id="server.description" label="Description" />
@if (!$server->settings->is_swarm_worker && !$server->settings->is_build_server) @if (!$server->settings->is_swarm_worker && !$server->settings->is_build_server)
<x-forms.input placeholder="https://example.com" id="wildcard_domain" label="Wildcard Domain" <x-forms.input placeholder="https://example.com" id="wildcard_domain" label="Wildcard Domain" helper='A wildcard domain allows you to receive a randomly generated domain for your new applications. <br><br>For instance, if you set "https://example.com" as your wildcard domain, your applications will receive domains like "https://randomId.example.com".' />
helper='A wildcard domain allows you to receive a randomly generated domain for your new applications. <br><br>For instance, if you set "https://example.com" as your wildcard domain, your applications will receive domains like "https://randomId.example.com".' />
@endif @endif
</div> </div>
<div class="flex flex-col w-full gap-2 lg:flex-row"> <div class="flex flex-col w-full gap-2 lg:flex-row">
<x-forms.input type="password" id="server.ip" label="IP Address/Domain" <x-forms.input type="password" id="server.ip" label="IP Address/Domain" helper="An IP Address (127.0.0.1) or domain (example.com)." required />
helper="An IP Address (127.0.0.1) or domain (example.com)." required />
<div class="flex gap-2"> <div class="flex gap-2">
<x-forms.input id="server.user" label="User" required /> <x-forms.input id="server.user" label="User" required />
<x-forms.input type="number" id="server.port" label="Port" required /> <x-forms.input type="number" id="server.port" label="Port" required />
@ -77,106 +72,80 @@ class="w-full mt-8 mb-4 font-bold box-without-bg bg-coollabs hover:bg-coollabs-1
</div> </div>
<div class="w-64"> <div class="w-64">
@if ($server->isFunctional()) @if ($server->isFunctional())
@if (!$server->isLocalhost()) @if (!$server->isLocalhost())
<x-forms.checkbox instantSave id="server.settings.is_build_server" <x-forms.checkbox instantSave id="server.settings.is_build_server" label="Use it as a build server?" />
label="Use it as a build server?" /> <div class="flex items-center gap-1 pt-6">
<div class="flex items-center gap-1 pt-6"> <h3 class="">Cloudflare Tunnels
<h3 class="">Cloudflare Tunnels </h3>
</h3> <x-helper class="inline-flex" helper="If you are using Cloudflare Tunnels, enable this. It will proxy all SSH requests to your server through Cloudflare.<br><span class='dark:text-warning'>Coolify does not install or set up Cloudflare (cloudflared) on your server.</span>" />
<x-helper class="inline-flex" </div>
helper="If you are using Cloudflare Tunnels, enable this. It will proxy all SSH requests to your server through Cloudflare.<br><span class='dark:text-warning'>Coolify does not install or set up Cloudflare (cloudflared) on your server.</span>" /> @if ($server->settings->is_cloudflare_tunnel)
</div> <x-forms.checkbox instantSave id="server.settings.is_cloudflare_tunnel" label="Enabled" />
@if ($server->settings->is_cloudflare_tunnel)
<x-forms.checkbox instantSave id="server.settings.is_cloudflare_tunnel" label="Enabled" />
@else
<x-modal-input buttonTitle="Configure" title="Cloudflare Tunnels">
<livewire:server.configure-cloudflare-tunnels :server_id="$server->id" />
</x-modal-input>
@endif
@if (!$server->isBuildServer())
<h3 class="pt-6">Swarm <span class="text-xs text-neutral-500">(experimental)</span></h3>
<div class="pb-4">Read the docs <a class='underline dark:text-white'
href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>.
</div>
@if ($server->settings->is_swarm_worker)
<x-forms.checkbox disabled instantSave type="checkbox"
id="server.settings.is_swarm_manager"
helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>."
label="Is it a Swarm Manager?" />
@else
<x-forms.checkbox instantSave type="checkbox" id="server.settings.is_swarm_manager"
helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>."
label="Is it a Swarm Manager?" />
@endif
@if ($server->settings->is_swarm_manager)
<x-forms.checkbox disabled instantSave type="checkbox"
id="server.settings.is_swarm_worker"
helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>."
label="Is it a Swarm Worker?" />
@else
<x-forms.checkbox instantSave type="checkbox" id="server.settings.is_swarm_worker"
helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>."
label="Is it a Swarm Worker?" />
@endif
@endif
@endif
@else @else
<div class="flex items-center gap-1 pt-6"> <x-modal-input buttonTitle="Configure" title="Cloudflare Tunnels">
<h3 class="">Cloudflare Tunnels <livewire:server.configure-cloudflare-tunnels :server_id="$server->id" />
</h3> </x-modal-input>
<x-helper class="inline-flex" @endif
helper="If you are using Cloudflare Tunnels, enable this. It will proxy all SSH requests to your server through Cloudflare.<br><span class='dark:text-warning'>Coolify does not install or set up Cloudflare (cloudflared) on your server.</span>" /> @if (!$server->isBuildServer())
</div> <h3 class="pt-6">Swarm <span class="text-xs text-neutral-500">(experimental)</span></h3>
@if ($server->settings->is_cloudflare_tunnel) <div class="pb-4">Read the docs <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>.
<x-forms.checkbox instantSave id="server.settings.is_cloudflare_tunnel" label="Enabled" /> </div>
@else @if ($server->settings->is_swarm_worker)
<x-modal-input buttonTitle="Configure" title="Cloudflare Tunnels"> <x-forms.checkbox disabled instantSave type="checkbox" id="server.settings.is_swarm_manager" helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>." label="Is it a Swarm Manager?" />
<livewire:server.configure-cloudflare-tunnels :server_id="$server->id" /> @else
</x-modal-input> <x-forms.checkbox instantSave type="checkbox" id="server.settings.is_swarm_manager" helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>." label="Is it a Swarm Manager?" />
@endif @endif
@if ($server->settings->is_swarm_manager)
<x-forms.checkbox disabled instantSave type="checkbox" id="server.settings.is_swarm_worker" helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>." label="Is it a Swarm Worker?" />
@else
<x-forms.checkbox instantSave type="checkbox" id="server.settings.is_swarm_worker" helper="For more information, please read the documentation <a class='dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>." label="Is it a Swarm Worker?" />
@endif
@endif
@endif
@else
<div class="flex items-center gap-1 pt-6">
<h3 class="">Cloudflare Tunnels
</h3>
<x-helper class="inline-flex" helper="If you are using Cloudflare Tunnels, enable this. It will proxy all SSH requests to your server through Cloudflare.<br><span class='dark:text-warning'>Coolify does not install or set up Cloudflare (cloudflared) on your server.</span>" />
</div>
@if ($server->settings->is_cloudflare_tunnel)
<x-forms.checkbox instantSave id="server.settings.is_cloudflare_tunnel" label="Enabled" />
@else
<x-modal-input buttonTitle="Configure" title="Cloudflare Tunnels">
<livewire:server.configure-cloudflare-tunnels :server_id="$server->id" />
</x-modal-input>
@endif
@endif @endif
</div> </div>
</div> </div>
@if ($server->isFunctional()) @if ($server->isFunctional())
<h3 class="pt-4">Settings</h3> <h3 class="pt-4">Settings</h3>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<div class="flex flex-col flex-wrap gap-2 sm:flex-nowrap"> <div class="flex flex-col flex-wrap gap-2 sm:flex-nowrap">
@if ($server->settings->is_force_cleanup_enabled) <div class="w-64">
<div class="w-64"> <x-forms.checkbox helper="Enable force Docker Cleanup. This will cleanup build caches / unused images / etc." instantSave id="server.settings.force_docker_cleanup" label="Force Docker Cleanup" /> </div>
<x-forms.checkbox @if ($server->settings->force_docker_cleanup)
helper="This will cleanup build caches / unused images / etc every 10 minutes." <x-forms.input placeholder="*/10 * * * *" id="server.settings.docker_cleanup_frequency" label="Docker Cleanup Frequency" required helper="Cron expression for Docker Cleanup.<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every 10 minutes." />
instantSave id="server.settings.is_force_cleanup_enabled" @else
label="Force Cleanup Docker Engine" /> <x-forms.input id="server.settings.docker_cleanup_threshold" label="Docker cleanup threshold (%)" required helper="The Docker cleanup tasks will run when the disk usage exceeds this threshold." />
</div> @endif
@else
<x-forms.input id="cleanup_after_percentage" label="Disk cleanup threshold (%)" required
helper="The disk cleanup task will run when the disk usage exceeds this threshold." />
<div class="w-64">
<x-forms.checkbox
helper="This will cleanup build caches / unused images / etc every 10 minutes."
instantSave id="server.settings.is_force_cleanup_enabled"
label="Force Cleanup Docker Engine" />
</div>
@endif
</div>
<div class="flex flex-wrap gap-2 sm:flex-nowrap">
<x-forms.input id="server.settings.concurrent_builds" label="Number of concurrent builds" required
helper="You can specify the number of simultaneous build processes/deployments that should run concurrently." />
<x-forms.input id="server.settings.dynamic_timeout" label="Deployment timeout (seconds)" required
helper="You can define the maximum duration for a deployment to run before timing it out." />
</div>
</div> </div>
<div class="flex items-center gap-2 pt-4 pb-2"> <div class="flex flex-wrap gap-2 sm:flex-nowrap">
<h3>Sentinel</h3> <x-forms.input id="server.settings.concurrent_builds" label="Number of concurrent builds" required helper="You can specify the number of simultaneous build processes/deployments that should run concurrently." />
{{-- @if ($server->isSentinelEnabled()) --}} <x-forms.input id="server.settings.dynamic_timeout" label="Deployment timeout (seconds)" required helper="You can define the maximum duration for a deployment to run before timing it out." />
{{-- <x-forms.button wire:click='restartSentinel'>Restart</x-forms.button> --}}
{{-- @endif --}}
</div> </div>
<div>Metrics are disabled until a few bugs are fixed.</div> </div>
{{-- <div class="w-64"> <div class="flex items-center gap-2 pt-4 pb-2">
<h3>Sentinel</h3>
{{-- @if ($server->isSentinelEnabled()) --}}
{{-- <x-forms.button wire:click='restartSentinel'>Restart</x-forms.button> --}}
{{-- @endif --}}
</div>
<div>Metrics are disabled until a few bugs are fixed.</div>
{{-- <div class="w-64">
<x-forms.checkbox instantSave id="server.settings.is_metrics_enabled" label="Enable Metrics" /> <x-forms.checkbox instantSave id="server.settings.is_metrics_enabled" label="Enable Metrics" />
</div> </div>
<div class="pt-4"> <div class="pt-4">
@ -192,4 +161,4 @@ class="w-full mt-8 mb-4 font-bold box-without-bg bg-coollabs hover:bg-coollabs-1
</div> --}} </div> --}}
@endif @endif
</form> </form>
</div> </div>