diff --git a/app/Actions/Server/CleanupDocker.php b/app/Actions/Server/CleanupDocker.php
index ad663de8b..a24ac6b29 100644
--- a/app/Actions/Server/CleanupDocker.php
+++ b/app/Actions/Server/CleanupDocker.php
@@ -12,29 +12,21 @@ class CleanupDocker
public function handle(Server $server)
{
- $commands = $this->getCommands($force);
+ $commands = $this->getCommands();
foreach ($commands as $command) {
instant_remote_process([$command], $server, false);
}
}
- private function getCommands(bool $force): array
+ private function getCommands(): array
{
$commonCommands = [
'docker container prune -f --filter "label=coolify.managed=true"',
- 'docker image prune -f',
- 'docker builder prune -f',
+ 'docker image prune -af',
+ '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;
}
}
diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php
index 12b514c6a..fd4c508a0 100644
--- a/app/Console/Kernel.php
+++ b/app/Console/Kernel.php
@@ -106,7 +106,11 @@ class Kernel extends ConsoleKernel
//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();
+ 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;
}
foreach ($scheduled_backups as $scheduled_backup) {
- if (!$scheduled_backup->enabled) {
+ if (! $scheduled_backup->enabled) {
continue;
}
if (is_null(data_get($scheduled_backup, 'database'))) {
@@ -150,7 +154,7 @@ class Kernel extends ConsoleKernel
$service = $scheduled_task->service;
$application = $scheduled_task->application;
- if (!$application && !$service) {
+ if (! $application && ! $service) {
ray('application/service attached to scheduled task does not exist');
$scheduled_task->delete();
@@ -177,7 +181,7 @@ class Kernel extends ConsoleKernel
protected function commands(): void
{
- $this->load(__DIR__ . '/Commands');
+ $this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
diff --git a/app/Jobs/DockerCleanupJob.php b/app/Jobs/DockerCleanupJob.php
index e53b54f5b..f95cd2920 100644
--- a/app/Jobs/DockerCleanupJob.php
+++ b/app/Jobs/DockerCleanupJob.php
@@ -10,6 +10,7 @@ use Illuminate\Contracts\Queue\ShouldBeEncrypted;
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\Facades\Log;
@@ -17,14 +18,24 @@ class DockerCleanupJob implements ShouldBeEncrypted, ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
- public $timeout = 300;
+ public $timeout = 600;
- public $tries = 2;
+ public $tries = 1;
public ?string $usageBefore = null;
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
{
try {
@@ -32,34 +43,30 @@ class DockerCleanupJob implements ShouldBeEncrypted, ShouldQueue
return;
}
if ($this->server->settings->force_docker_cleanup) {
- Log::info('DockerCleanupJob force cleanup on ' . $this->server->name);
- CleanupDocker::run(server: $this->server, force: true);
+ Log::info('DockerCleanupJob force cleanup on '.$this->server->name);
+ CleanupDocker::run(server: $this->server);
return;
}
-
- return;
- }
- try {
$this->usageBefore = $this->server->getDiskUsage();
if (str($this->usageBefore)->isEmpty() || $this->usageBefore === null || $this->usageBefore === 0) {
- Log::info('DockerCleanupJob force cleanup on ' . $this->server->name);
- CleanupDocker::run(server: $this->server, force: true);
+ Log::info('DockerCleanupJob force cleanup on '.$this->server->name);
+ CleanupDocker::run(server: $this->server);
return;
}
- if ($this->usageBefore >= $this->server->settings->cleanup_after_percentage) {
+ if ($this->usageBefore >= $this->server->settings->docker_cleanup_threshold) {
CleanupDocker::run(server: $this->server);
$usageAfter = $this->server->getDiskUsage();
if ($usageAfter < $this->usageBefore) {
- $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);
+ $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);
} 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 {
- Log::info('No need to clean up ' . $this->server->name);
+ Log::info('No need to clean up '.$this->server->name);
}
} catch (\Throwable $e) {
CleanupDocker::run(server: $this->server);
@@ -67,4 +74,4 @@ class DockerCleanupJob implements ShouldBeEncrypted, ShouldQueue
throw $e;
}
}
-}
\ No newline at end of file
+}
diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php
index 7c176c952..1ab70c004 100644
--- a/app/Livewire/Server/Form.php
+++ b/app/Livewire/Server/Form.php
@@ -18,8 +18,6 @@ class Form extends Component
public ?string $wildcard_domain = null;
- public int $cleanup_after_percentage;
-
public bool $dockerInstallationStarted = false;
public bool $revalidate = false;
@@ -81,7 +79,7 @@ class Form extends Component
{
if ($field === '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->server->settings->docker_cleanup_frequency = '*/10 * * * *';
}
@@ -169,7 +167,7 @@ class Form extends Component
$this->server->settings->save();
$this->dispatch('proxyStatusUpdated');
} else {
- $this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.
Check this documentation for further help.
Error: ' . $error);
+ $this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.
Check this documentation for further help.
Error: '.$error);
return;
}
@@ -185,31 +183,35 @@ class Form extends Component
public function submit()
{
- if (isCloud() && !isDev()) {
- $this->validate();
- $this->validate([
- 'server.ip' => 'required',
- ]);
- } else {
- $this->validate();
- }
- $uniqueIPs = Server::all()->reject(function (Server $server) {
- return $server->id === $this->server->id;
- })->pluck('ip')->toArray();
- if (in_array($this->server->ip, $uniqueIPs)) {
- $this->dispatch('error', 'IP address is already in use by another team.');
+ try {
+ if (isCloud() && ! isDev()) {
+ $this->validate();
+ $this->validate([
+ 'server.ip' => 'required',
+ ]);
+ } else {
+ $this->validate();
+ }
+ $uniqueIPs = Server::all()->reject(function (Server $server) {
+ return $server->id === $this->server->id;
+ })->pluck('ip')->toArray();
+ 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.');
}
-}
\ No newline at end of file
+}
diff --git a/app/Models/Service.php b/app/Models/Service.php
index 091516144..3d19b067b 100644
--- a/app/Models/Service.php
+++ b/app/Models/Service.php
@@ -2,13 +2,11 @@
namespace App\Models;
-use App\Enums\ProxyTypes;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Collection;
-use Illuminate\Support\Str;
use OpenApi\Attributes as OA;
use Spatie\Url\Url;
use Symfony\Component\Yaml\Yaml;
@@ -25,7 +23,7 @@ use Symfony\Component\Yaml\Yaml;
'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' => ['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.'],
'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.'],
diff --git a/app/Notifications/Server/DockerCleanup.php b/app/Notifications/Server/DockerCleanup.php
index f8195ec1d..682ed7a1a 100644
--- a/app/Notifications/Server/DockerCleanup.php
+++ b/app/Notifications/Server/DockerCleanup.php
@@ -44,7 +44,7 @@ class DockerCleanup extends Notification implements ShouldQueue
// $mail->view('emails.high-disk-usage', [
// 'name' => $this->server->name,
// 'disk_usage' => $this->disk_usage,
- // 'threshold' => $this->cleanup_after_percentage,
+ // 'threshold' => $this->docker_cleanup_threshold,
// ]);
// return $mail;
// }
diff --git a/app/Notifications/Server/HighDiskUsage.php b/app/Notifications/Server/HighDiskUsage.php
index 3c68afe7b..34cb22091 100644
--- a/app/Notifications/Server/HighDiskUsage.php
+++ b/app/Notifications/Server/HighDiskUsage.php
@@ -17,7 +17,7 @@ class HighDiskUsage extends Notification implements ShouldQueue
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
{
@@ -46,7 +46,7 @@ class HighDiskUsage extends Notification implements ShouldQueue
$mail->view('emails.high-disk-usage', [
'name' => $this->server->name,
'disk_usage' => $this->disk_usage,
- 'threshold' => $this->cleanup_after_percentage,
+ 'threshold' => $this->docker_cleanup_threshold,
]);
return $mail;
@@ -54,7 +54,7 @@ class HighDiskUsage extends Notification implements ShouldQueue
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;
}
@@ -62,7 +62,7 @@ class HighDiskUsage extends Notification implements ShouldQueue
public function toTelegram(): array
{
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.",
];
}
}
diff --git a/database/migrations/2024_08_09_215659_add_server_cleanup_fields_to_server_settings_table.php b/database/migrations/2024_08_09_215659_add_server_cleanup_fields_to_server_settings_table.php
index 4e1bfb357..b5300c905 100644
--- a/database/migrations/2024_08_09_215659_add_server_cleanup_fields_to_server_settings_table.php
+++ b/database/migrations/2024_08_09_215659_add_server_cleanup_fields_to_server_settings_table.php
@@ -1,5 +1,6 @@
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');
});
+ 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()
{
+ $serverSettings = ServerSetting::all();
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);
+ $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();
+ }
}
}
diff --git a/openapi.yaml b/openapi.yaml
index 9f6bc3889..482ff6f05 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -4523,14 +4523,14 @@ components:
properties:
id:
type: integer
- cleanup_after_percentage:
- type: integer
concurrent_builds:
type: integer
dynamic_timeout:
type: integer
force_disabled:
type: boolean
+ force_server_cleanup:
+ type: boolean
is_build_server:
type: boolean
is_cloudflare_tunnel:
@@ -4577,6 +4577,10 @@ components:
type: integer
metrics_token:
type: string
+ docker_cleanup_frequency:
+ type: string
+ docker_cleanup_threshold:
+ type: integer
server_id:
type: integer
wildcard_domain:
@@ -4613,6 +4617,9 @@ components:
docker_compose:
type: string
description: 'The docker-compose.yml file that is parsed and modified by Coolify.'
+ destination_type:
+ type: string
+ description: 'Destination type.'
destination_id:
type: integer
description: 'The unique identifier of the destination where the service is running.'
diff --git a/resources/views/livewire/server/form.blade.php b/resources/views/livewire/server/form.blade.php
index ee8855321..474521c9c 100644
--- a/resources/views/livewire/server/form.blade.php
+++ b/resources/views/livewire/server/form.blade.php
@@ -3,68 +3,73 @@