fix: docker cleanup job
This commit is contained in:
@@ -12,29 +12,21 @@ class CleanupDocker
|
|||||||
public function handle(Server $server)
|
public function handle(Server $server)
|
||||||
{
|
{
|
||||||
|
|
||||||
$commands = $this->getCommands($force);
|
$commands = $this->getCommands();
|
||||||
|
|
||||||
foreach ($commands as $command) {
|
foreach ($commands as $command) {
|
||||||
instant_remote_process([$command], $server, false);
|
instant_remote_process([$command], $server, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getCommands(bool $force): array
|
private function getCommands(): array
|
||||||
{
|
{
|
||||||
$commonCommands = [
|
$commonCommands = [
|
||||||
'docker container prune -f --filter "label=coolify.managed=true"',
|
'docker container prune -f --filter "label=coolify.managed=true"',
|
||||||
'docker image prune -f',
|
'docker image prune -af',
|
||||||
'docker builder prune -f',
|
'docker builder prune -af',
|
||||||
];
|
];
|
||||||
|
|
||||||
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;
|
return $commonCommands;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -106,7 +106,11 @@ class Kernel extends ConsoleKernel
|
|||||||
//The lines below need to be added as soon as timzone is merged!!
|
//The lines below need to be added as soon as timzone is merged!!
|
||||||
//$serverTimezone = $server->settings->server_timezone;
|
//$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)->timezone($serverTimezone)->onOneServer();
|
||||||
$schedule->job(new DockerCleanupJob($server))->cron($server->settings->docker_cleanup_frequency)->onOneServer();
|
if ($server->settings->force_docker_cleanup) {
|
||||||
|
$schedule->job(new DockerCleanupJob($server))->cron($server->settings->docker_cleanup_frequency)->onOneServer();
|
||||||
|
} else {
|
||||||
|
$schedule->job(new DockerCleanupJob($server))->everyTenMinutes()->onOneServer();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,7 +122,7 @@ class Kernel extends ConsoleKernel
|
|||||||
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'))) {
|
||||||
@@ -150,7 +154,7 @@ class Kernel extends ConsoleKernel
|
|||||||
$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();
|
||||||
|
|
||||||
@@ -177,7 +181,7 @@ class Kernel extends ConsoleKernel
|
|||||||
|
|
||||||
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');
|
||||||
}
|
}
|
||||||
|
@@ -10,6 +10,7 @@ use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
|||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
@@ -17,14 +18,24 @@ class DockerCleanupJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
public $timeout = 300;
|
public $timeout = 600;
|
||||||
|
|
||||||
public $tries = 2;
|
public $tries = 1;
|
||||||
|
|
||||||
public ?string $usageBefore = null;
|
public ?string $usageBefore = null;
|
||||||
|
|
||||||
public function __construct(public Server $server) {}
|
public function __construct(public Server $server) {}
|
||||||
|
|
||||||
|
public function middleware(): array
|
||||||
|
{
|
||||||
|
return [new WithoutOverlapping($this->server->id)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function uniqueId(): int
|
||||||
|
{
|
||||||
|
return $this->server->id;
|
||||||
|
}
|
||||||
|
|
||||||
public function handle(): void
|
public function handle(): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@@ -32,34 +43,30 @@ class DockerCleanupJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($this->server->settings->force_docker_cleanup) {
|
if ($this->server->settings->force_docker_cleanup) {
|
||||||
Log::info('DockerCleanupJob force cleanup on ' . $this->server->name);
|
Log::info('DockerCleanupJob force cleanup on '.$this->server->name);
|
||||||
CleanupDocker::run(server: $this->server, force: true);
|
CleanupDocker::run(server: $this->server);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
$this->usageBefore = $this->server->getDiskUsage();
|
$this->usageBefore = $this->server->getDiskUsage();
|
||||||
if (str($this->usageBefore)->isEmpty() || $this->usageBefore === null || $this->usageBefore === 0) {
|
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, force: true);
|
CleanupDocker::run(server: $this->server);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($this->usageBefore >= $this->server->settings->cleanup_after_percentage) {
|
if ($this->usageBefore >= $this->server->settings->docker_cleanup_threshold) {
|
||||||
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);
|
||||||
|
@@ -18,8 +18,6 @@ class Form extends Component
|
|||||||
|
|
||||||
public ?string $wildcard_domain = null;
|
public ?string $wildcard_domain = null;
|
||||||
|
|
||||||
public int $cleanup_after_percentage;
|
|
||||||
|
|
||||||
public bool $dockerInstallationStarted = false;
|
public bool $dockerInstallationStarted = false;
|
||||||
|
|
||||||
public bool $revalidate = false;
|
public bool $revalidate = false;
|
||||||
@@ -81,7 +79,7 @@ class Form extends Component
|
|||||||
{
|
{
|
||||||
if ($field === 'server.settings.docker_cleanup_frequency') {
|
if ($field === 'server.settings.docker_cleanup_frequency') {
|
||||||
$frequency = $this->server->settings->docker_cleanup_frequency;
|
$frequency = $this->server->settings->docker_cleanup_frequency;
|
||||||
if (empty($frequency) || !validate_cron_expression($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->dispatch('error', 'Invalid Cron / Human expression for Docker Cleanup Frequency. Resetting to default 10 minutes.');
|
||||||
$this->server->settings->docker_cleanup_frequency = '*/10 * * * *';
|
$this->server->settings->docker_cleanup_frequency = '*/10 * * * *';
|
||||||
}
|
}
|
||||||
@@ -169,7 +167,7 @@ class Form extends Component
|
|||||||
$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;
|
||||||
}
|
}
|
||||||
@@ -185,31 +183,35 @@ class Form extends Component
|
|||||||
|
|
||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
if (isCloud() && !isDev()) {
|
try {
|
||||||
$this->validate();
|
if (isCloud() && ! isDev()) {
|
||||||
$this->validate([
|
$this->validate();
|
||||||
'server.ip' => 'required',
|
$this->validate([
|
||||||
]);
|
'server.ip' => 'required',
|
||||||
} else {
|
]);
|
||||||
$this->validate();
|
} else {
|
||||||
}
|
$this->validate();
|
||||||
$uniqueIPs = Server::all()->reject(function (Server $server) {
|
}
|
||||||
return $server->id === $this->server->id;
|
$uniqueIPs = Server::all()->reject(function (Server $server) {
|
||||||
})->pluck('ip')->toArray();
|
return $server->id === $this->server->id;
|
||||||
if (in_array($this->server->ip, $uniqueIPs)) {
|
})->pluck('ip')->toArray();
|
||||||
$this->dispatch('error', 'IP address is already in use by another team.');
|
if (in_array($this->server->ip, $uniqueIPs)) {
|
||||||
|
$this->dispatch('error', 'IP address is already in use by another team.');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
refresh_server_connection($this->server->privateKey);
|
||||||
|
$this->server->settings->wildcard_domain = $this->wildcard_domain;
|
||||||
|
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->save();
|
||||||
|
$this->dispatch('success', 'Server updated.');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
}
|
}
|
||||||
refresh_server_connection($this->server->privateKey);
|
|
||||||
$this->server->settings->wildcard_domain = $this->wildcard_domain;
|
|
||||||
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->save();
|
|
||||||
$this->dispatch('success', 'Server updated.');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -2,13 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Enums\ProxyTypes;
|
|
||||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use OpenApi\Attributes as OA;
|
use OpenApi\Attributes as OA;
|
||||||
use Spatie\Url\Url;
|
use Spatie\Url\Url;
|
||||||
use Symfony\Component\Yaml\Yaml;
|
use Symfony\Component\Yaml\Yaml;
|
||||||
@@ -25,7 +23,7 @@ use Symfony\Component\Yaml\Yaml;
|
|||||||
'description' => ['type' => 'string', 'description' => 'The description of the service.'],
|
'description' => ['type' => 'string', 'description' => 'The description of the service.'],
|
||||||
'docker_compose_raw' => ['type' => 'string', 'description' => 'The raw docker-compose.yml file of the service.'],
|
'docker_compose_raw' => ['type' => 'string', 'description' => 'The raw docker-compose.yml file of the service.'],
|
||||||
'docker_compose' => ['type' => 'string', 'description' => 'The docker-compose.yml file that is parsed and modified by Coolify.'],
|
'docker_compose' => ['type' => 'string', 'description' => 'The docker-compose.yml file that is parsed and modified by Coolify.'],
|
||||||
'destination_type' => ['type' => 'integer', 'description' => 'The unique identifier of the destination where the service is running.'],
|
'destination_type' => ['type' => 'string', 'description' => 'Destination type.'],
|
||||||
'destination_id' => ['type' => 'integer', 'description' => 'The unique identifier of the destination where the service is running.'],
|
'destination_id' => ['type' => 'integer', 'description' => 'The unique identifier of the destination where the service is running.'],
|
||||||
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
||||||
'is_container_label_escape_enabled' => ['type' => 'boolean', 'description' => 'The flag to enable the container label escape.'],
|
'is_container_label_escape_enabled' => ['type' => 'boolean', 'description' => 'The flag to enable the container label escape.'],
|
||||||
|
@@ -44,7 +44,7 @@ class DockerCleanup extends Notification implements ShouldQueue
|
|||||||
// $mail->view('emails.high-disk-usage', [
|
// $mail->view('emails.high-disk-usage', [
|
||||||
// 'name' => $this->server->name,
|
// 'name' => $this->server->name,
|
||||||
// 'disk_usage' => $this->disk_usage,
|
// 'disk_usage' => $this->disk_usage,
|
||||||
// 'threshold' => $this->cleanup_after_percentage,
|
// 'threshold' => $this->docker_cleanup_threshold,
|
||||||
// ]);
|
// ]);
|
||||||
// return $mail;
|
// return $mail;
|
||||||
// }
|
// }
|
||||||
|
@@ -17,7 +17,7 @@ class HighDiskUsage extends Notification implements ShouldQueue
|
|||||||
|
|
||||||
public $tries = 1;
|
public $tries = 1;
|
||||||
|
|
||||||
public function __construct(public Server $server, public int $disk_usage, public int $cleanup_after_percentage) {}
|
public function __construct(public Server $server, public int $disk_usage, public int $docker_cleanup_threshold) {}
|
||||||
|
|
||||||
public function via(object $notifiable): array
|
public function via(object $notifiable): array
|
||||||
{
|
{
|
||||||
@@ -46,7 +46,7 @@ class HighDiskUsage extends Notification implements ShouldQueue
|
|||||||
$mail->view('emails.high-disk-usage', [
|
$mail->view('emails.high-disk-usage', [
|
||||||
'name' => $this->server->name,
|
'name' => $this->server->name,
|
||||||
'disk_usage' => $this->disk_usage,
|
'disk_usage' => $this->disk_usage,
|
||||||
'threshold' => $this->cleanup_after_percentage,
|
'threshold' => $this->docker_cleanup_threshold,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $mail;
|
return $mail;
|
||||||
@@ -54,7 +54,7 @@ class HighDiskUsage extends Notification implements ShouldQueue
|
|||||||
|
|
||||||
public function toDiscord(): string
|
public function toDiscord(): string
|
||||||
{
|
{
|
||||||
$message = "Coolify: Server '{$this->server->name}' high disk usage detected!\nDisk usage: {$this->disk_usage}%. Threshold: {$this->cleanup_after_percentage}%.\nPlease cleanup your disk to prevent data-loss.\nHere are some tips: https://coolify.io/docs/knowledge-base/server/automated-cleanup.";
|
$message = "Coolify: Server '{$this->server->name}' high disk usage detected!\nDisk usage: {$this->disk_usage}%. Threshold: {$this->docker_cleanup_threshold}%.\nPlease cleanup your disk to prevent data-loss.\nHere are some tips: https://coolify.io/docs/knowledge-base/server/automated-cleanup.";
|
||||||
|
|
||||||
return $message;
|
return $message;
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ class HighDiskUsage extends Notification implements ShouldQueue
|
|||||||
public function toTelegram(): array
|
public function toTelegram(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'message' => "Coolify: Server '{$this->server->name}' high disk usage detected!\nDisk usage: {$this->disk_usage}%. Threshold: {$this->cleanup_after_percentage}%.\nPlease cleanup your disk to prevent data-loss.\nHere are some tips: https://coolify.io/docs/knowledge-base/server/automated-cleanup.",
|
'message' => "Coolify: Server '{$this->server->name}' high disk usage detected!\nDisk usage: {$this->disk_usage}%. Threshold: {$this->docker_cleanup_threshold}%.\nPlease cleanup your disk to prevent data-loss.\nHere are some tips: https://coolify.io/docs/knowledge-base/server/automated-cleanup.",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Models\ServerSetting;
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
@@ -13,16 +14,23 @@ class AddServerCleanupFieldsToServerSettingsTable extends Migration
|
|||||||
*/
|
*/
|
||||||
public function up()
|
public function up()
|
||||||
{
|
{
|
||||||
|
$serverSettings = ServerSetting::all();
|
||||||
|
|
||||||
Schema::table('server_settings', function (Blueprint $table) {
|
Schema::table('server_settings', function (Blueprint $table) {
|
||||||
$table->boolean('force_docker_cleanup')->default(false);
|
$table->boolean('force_docker_cleanup')->default(false);
|
||||||
$table->string('docker_cleanup_frequency')->default('*/10 * * * *');
|
$table->string('docker_cleanup_frequency')->default('*/10 * * * *');
|
||||||
$table->integer('docker_cleanup_threshold')->default(80);
|
$table->integer('docker_cleanup_threshold')->default(80);
|
||||||
|
|
||||||
|
|
||||||
// Remove old columns
|
// Remove old columns
|
||||||
$table->dropColumn('cleanup_after_percentage');
|
$table->dropColumn('cleanup_after_percentage');
|
||||||
$table->dropColumn('is_force_cleanup_enabled');
|
$table->dropColumn('is_force_cleanup_enabled');
|
||||||
});
|
});
|
||||||
|
foreach ($serverSettings as $serverSetting) {
|
||||||
|
$serverSetting->force_docker_cleanup = $serverSetting->is_force_cleanup_enabled;
|
||||||
|
$serverSetting->docker_cleanup_threshold = $serverSetting->cleanup_after_percentage;
|
||||||
|
$serverSetting->save();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,15 +40,21 @@ class AddServerCleanupFieldsToServerSettingsTable extends Migration
|
|||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
|
$serverSettings = ServerSetting::all();
|
||||||
Schema::table('server_settings', function (Blueprint $table) {
|
Schema::table('server_settings', function (Blueprint $table) {
|
||||||
$table->dropColumn('force_docker_cleanup');
|
$table->dropColumn('force_docker_cleanup');
|
||||||
$table->dropColumn('docker_cleanup_frequency');
|
$table->dropColumn('docker_cleanup_frequency');
|
||||||
$table->dropColumn('docker_cleanup_threshold');
|
$table->dropColumn('docker_cleanup_threshold');
|
||||||
|
|
||||||
|
|
||||||
// Add back old columns
|
// Add back old columns
|
||||||
$table->integer('cleanup_after_percentage')->default(80);
|
$table->integer('cleanup_after_percentage')->default(80);
|
||||||
$table->boolean('force_server_cleanup')->default(false);
|
$table->boolean('force_server_cleanup')->default(false);
|
||||||
|
$table->boolean('is_force_cleanup_enabled')->default(false);
|
||||||
});
|
});
|
||||||
|
foreach ($serverSettings as $serverSetting) {
|
||||||
|
$serverSetting->is_force_cleanup_enabled = $serverSetting->force_docker_cleanup;
|
||||||
|
$serverSetting->cleanup_after_percentage = $serverSetting->docker_cleanup_threshold;
|
||||||
|
$serverSetting->save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
openapi.yaml
11
openapi.yaml
@@ -4523,14 +4523,14 @@ components:
|
|||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
type: integer
|
type: integer
|
||||||
cleanup_after_percentage:
|
|
||||||
type: integer
|
|
||||||
concurrent_builds:
|
concurrent_builds:
|
||||||
type: integer
|
type: integer
|
||||||
dynamic_timeout:
|
dynamic_timeout:
|
||||||
type: integer
|
type: integer
|
||||||
force_disabled:
|
force_disabled:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
force_server_cleanup:
|
||||||
|
type: boolean
|
||||||
is_build_server:
|
is_build_server:
|
||||||
type: boolean
|
type: boolean
|
||||||
is_cloudflare_tunnel:
|
is_cloudflare_tunnel:
|
||||||
@@ -4577,6 +4577,10 @@ components:
|
|||||||
type: integer
|
type: integer
|
||||||
metrics_token:
|
metrics_token:
|
||||||
type: string
|
type: string
|
||||||
|
docker_cleanup_frequency:
|
||||||
|
type: string
|
||||||
|
docker_cleanup_threshold:
|
||||||
|
type: integer
|
||||||
server_id:
|
server_id:
|
||||||
type: integer
|
type: integer
|
||||||
wildcard_domain:
|
wildcard_domain:
|
||||||
@@ -4613,6 +4617,9 @@ components:
|
|||||||
docker_compose:
|
docker_compose:
|
||||||
type: string
|
type: string
|
||||||
description: 'The docker-compose.yml file that is parsed and modified by Coolify.'
|
description: 'The docker-compose.yml file that is parsed and modified by Coolify.'
|
||||||
|
destination_type:
|
||||||
|
type: string
|
||||||
|
description: 'Destination type.'
|
||||||
destination_id:
|
destination_id:
|
||||||
type: integer
|
type: integer
|
||||||
description: 'The unique identifier of the destination where the service is running.'
|
description: 'The unique identifier of the destination where the service is running.'
|
||||||
|
@@ -3,68 +3,73 @@
|
|||||||
<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-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" ask />
|
<livewire:server.validate-and-install :server="$server" ask />
|
||||||
</x-slot:content>
|
</x-slot:content>
|
||||||
<x-forms.button @click="slideOverOpen=true" wire:click.prevent='validateServer' isHighlighted>
|
<x-forms.button @click="slideOverOpen=true" wire:click.prevent='validateServer' isHighlighted>
|
||||||
Revalidate server
|
Revalidate server
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</x-slide-over>
|
</x-slide-over>
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@if ($server->isFunctional())
|
@if ($server->isFunctional())
|
||||||
Server is reachable and validated.
|
Server is reachable and validated.
|
||||||
@else
|
@else
|
||||||
You can't use this server until it is validated.
|
You can't use this server until it is validated.
|
||||||
@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-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" />
|
||||||
</x-slot:content>
|
</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>
|
<x-forms.button @click="slideOverOpen=true"
|
||||||
Validate Server & Install Docker Engine
|
class="w-full mt-8 mb-4 font-bold box-without-bg bg-coollabs hover:bg-coollabs-100"
|
||||||
</x-forms.button>
|
wire:click.prevent='validateServer' isHighlighted>
|
||||||
</x-slide-over>
|
Validate Server & Install Docker Engine
|
||||||
@if ($server->validation_logs)
|
</x-forms.button>
|
||||||
<h4>Previous Validation Logs</h4>
|
</x-slide-over>
|
||||||
<div class="pb-8">
|
@if ($server->validation_logs)
|
||||||
{!! $server->validation_logs !!}
|
<h4>Previous Validation Logs</h4>
|
||||||
</div>
|
<div class="pb-8">
|
||||||
@endif
|
{!! $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" wire:click.prevent='checkLocalhostConnection' isHighlighted>
|
<x-forms.button class="mt-8 mb-4 font-bold box-without-bg bg-coollabs hover:bg-coollabs-100"
|
||||||
Validate Server
|
wire:click.prevent='checkLocalhostConnection' isHighlighted>
|
||||||
</x-forms.button>
|
Validate Server
|
||||||
|
</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" 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".' />
|
<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".' />
|
||||||
@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" helper="An IP Address (127.0.0.1) or domain (example.com)." required />
|
<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 />
|
||||||
<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 />
|
||||||
@@ -72,80 +77,103 @@
|
|||||||
</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" label="Use it as a build server?" />
|
<x-forms.checkbox instantSave id="server.settings.is_build_server"
|
||||||
<div class="flex items-center gap-1 pt-6">
|
label="Use it as a build server?" />
|
||||||
<h3 class="">Cloudflare Tunnels
|
<div class="flex items-center gap-1 pt-6">
|
||||||
</h3>
|
<h3 class="">Cloudflare Tunnels
|
||||||
<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>" />
|
</h3>
|
||||||
</div>
|
<x-helper class="inline-flex"
|
||||||
@if ($server->settings->is_cloudflare_tunnel)
|
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-forms.checkbox instantSave id="server.settings.is_cloudflare_tunnel" label="Enabled" />
|
</div>
|
||||||
@else
|
@if ($server->settings->is_cloudflare_tunnel)
|
||||||
<x-modal-input buttonTitle="Configure" title="Cloudflare Tunnels">
|
<x-forms.checkbox instantSave id="server.settings.is_cloudflare_tunnel" label="Enabled" />
|
||||||
<livewire:server.configure-cloudflare-tunnels :server_id="$server->id" />
|
@else
|
||||||
</x-modal-input>
|
<x-modal-input buttonTitle="Configure" title="Cloudflare Tunnels">
|
||||||
@endif
|
<livewire:server.configure-cloudflare-tunnels :server_id="$server->id" />
|
||||||
@if (!$server->isBuildServer())
|
</x-modal-input>
|
||||||
<h3 class="pt-6">Swarm <span class="text-xs text-neutral-500">(experimental)</span></h3>
|
@endif
|
||||||
<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>.
|
@if (!$server->isBuildServer())
|
||||||
</div>
|
<h3 class="pt-6">Swarm <span class="text-xs text-neutral-500">(experimental)</span></h3>
|
||||||
@if ($server->settings->is_swarm_worker)
|
<div class="pb-4">Read the docs <a class='underline dark:text-white'
|
||||||
<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?" />
|
href='https://coolify.io/docs/knowledge-base/docker/swarm' target='_blank'>here</a>.
|
||||||
@else
|
</div>
|
||||||
<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?" />
|
@if ($server->settings->is_swarm_worker)
|
||||||
@endif
|
<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)
|
@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?" />
|
<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
|
||||||
<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?" />
|
<div class="flex items-center gap-1 pt-6">
|
||||||
@endif
|
<h3 class="">Cloudflare Tunnels
|
||||||
@endif
|
</h3>
|
||||||
@endif
|
<x-helper class="inline-flex"
|
||||||
@else
|
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 class="flex items-center gap-1 pt-6">
|
</div>
|
||||||
<h3 class="">Cloudflare Tunnels
|
@if ($server->settings->is_cloudflare_tunnel)
|
||||||
</h3>
|
<x-forms.checkbox instantSave id="server.settings.is_cloudflare_tunnel" label="Enabled" />
|
||||||
<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>" />
|
@else
|
||||||
</div>
|
<x-modal-input buttonTitle="Configure" title="Cloudflare Tunnels">
|
||||||
@if ($server->settings->is_cloudflare_tunnel)
|
<livewire:server.configure-cloudflare-tunnels :server_id="$server->id" />
|
||||||
<x-forms.checkbox instantSave id="server.settings.is_cloudflare_tunnel" label="Enabled" />
|
</x-modal-input>
|
||||||
@else
|
@endif
|
||||||
<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">
|
||||||
<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="Enable force Docker Cleanup. This will cleanup build caches / unused images / etc."
|
||||||
<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.force_docker_cleanup" label="Force Docker Cleanup" />
|
||||||
@else
|
</div>
|
||||||
<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." />
|
@if ($server->settings->force_docker_cleanup)
|
||||||
@endif
|
<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." />
|
||||||
|
@else
|
||||||
|
<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." />
|
||||||
|
@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 flex-wrap gap-2 sm:flex-nowrap">
|
<div class="flex items-center gap-2 pt-4 pb-2">
|
||||||
<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." />
|
<h3>Sentinel</h3>
|
||||||
<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." />
|
{{-- @if ($server->isSentinelEnabled()) --}}
|
||||||
|
{{-- <x-forms.button wire:click='restartSentinel'>Restart</x-forms.button> --}}
|
||||||
|
{{-- @endif --}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div>Metrics are disabled until a few bugs are fixed.</div>
|
||||||
<div class="flex items-center gap-2 pt-4 pb-2">
|
{{-- <div class="w-64">
|
||||||
<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">
|
||||||
|
Reference in New Issue
Block a user