fix: proxy check, reduce jobs, etc

This commit is contained in:
Andras Bacsai
2023-09-11 22:29:34 +02:00
parent 42daae10c6
commit 8a39a4469a
19 changed files with 146 additions and 214 deletions

View File

@@ -2,8 +2,6 @@
namespace App\Actions\Proxy;
use App\Enums\ProxyStatus;
use App\Enums\ProxyTypes;
use App\Models\Server;
use Illuminate\Support\Str;
use Spatie\Activitylog\Models\Activity;
@@ -36,11 +34,14 @@ class StartProxy
"echo '####### Creating Docker Compose file...'",
"echo '####### Pulling docker image...'",
'docker compose pull',
"echo '####### Stopping existing proxy...'",
"echo '####### Stopping existing coolify-proxy...'",
'docker compose down -v --remove-orphans',
"lsof -nt -i:80 | xargs -r kill -9",
"lsof -nt -i:443 | xargs -r kill -9",
"echo '####### Starting proxy...'",
"systemctl disable nginx > /dev/null 2>&1 || true",
"systemctl disable apache2 > /dev/null 2>&1 || true",
"systemctl disable apache > /dev/null 2>&1 || true",
"echo '####### Starting coolify-proxy...'",
'docker compose up -d --remove-orphans',
"echo '####### Proxy installed successfully...'"
], $server);

View File

@@ -21,7 +21,6 @@ use Exception;
use Illuminate\Console\Command;
use Illuminate\Mail\Message;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Process;
use Mail;
use Str;

View File

@@ -2,6 +2,7 @@
namespace App\Console;
use App\Enums\ProxyTypes;
use App\Jobs\ApplicationContainerStatusJob;
use App\Jobs\CheckResaleLicenseJob;
use App\Jobs\CleanupInstanceStuffsJob;
@@ -9,11 +10,11 @@ use App\Jobs\DatabaseBackupJob;
use App\Jobs\DatabaseContainerStatusJob;
use App\Jobs\DockerCleanupJob;
use App\Jobs\InstanceAutoUpdateJob;
use App\Jobs\ProxyCheckJob;
use App\Jobs\ResourceStatusJob;
use App\Jobs\ProxyContainerStatusJob;
use App\Models\Application;
use App\Models\InstanceSettings;
use App\Models\ScheduledDatabaseBackup;
use App\Models\Server;
use App\Models\StandalonePostgresql;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
@@ -24,22 +25,26 @@ class Kernel extends ConsoleKernel
{
if (isDev()) {
$schedule->command('horizon:snapshot')->everyMinute();
// $schedule->job(new ResourceStatusJob)->everyMinute();
$schedule->job(new ProxyCheckJob)->everyFiveMinutes();
$schedule->job(new CleanupInstanceStuffsJob)->everyMinute();
// $schedule->job(new CheckResaleLicenseJob)->hourly();
$schedule->job(new DockerCleanupJob)->everyOddHour();
} else {
$schedule->command('horizon:snapshot')->everyFiveMinutes();
$schedule->job(new CleanupInstanceStuffsJob)->everyTenMinutes()->onOneServer();
// $schedule->job(new ResourceStatusJob)->everyMinute()->onOneServer();
$schedule->job(new CheckResaleLicenseJob)->hourly()->onOneServer();
$schedule->job(new ProxyCheckJob)->everyFiveMinutes()->onOneServer();
$schedule->job(new DockerCleanupJob)->everyTenMinutes()->onOneServer();
}
$this->instance_auto_update($schedule);
$this->check_scheduled_backups($schedule);
$this->check_resources($schedule);
$this->check_proxies($schedule);
}
private function check_proxies($schedule)
{
$servers = Server::all()->where('settings.is_usable', true)->where('settings.is_reachable', true)->whereNotNull('proxy.type')->where('proxy.type', '!=', ProxyTypes::NONE->value);
foreach ($servers as $server) {
$schedule->job(new ProxyContainerStatusJob($server))->everyMinute()->onOneServer();
}
}
private function check_resources($schedule)
{
@@ -53,7 +58,8 @@ class Kernel extends ConsoleKernel
$schedule->job(new DatabaseContainerStatusJob($postgresql))->everyMinute()->onOneServer();
}
}
private function instance_auto_update($schedule){
private function instance_auto_update($schedule)
{
if (isDev()) {
return;
}
@@ -74,7 +80,7 @@ class Kernel extends ConsoleKernel
if (!$scheduled_backup->enabled) {
continue;
}
if (is_null(data_get($scheduled_backup,'database'))) {
if (is_null(data_get($scheduled_backup, 'database'))) {
ray('database not found');
$scheduled_backup->delete();
continue;

View File

@@ -14,14 +14,14 @@ class Proxy extends Component
public ?string $selectedProxy = null;
public $proxy_settings = null;
public string|null $redirect_url = null;
public ?string $redirect_url = null;
protected $listeners = ['proxyStatusUpdated', 'saveConfiguration' => 'submit'];
public function mount()
{
$this->selectedProxy = $this->server->proxy->type;
$this->redirect_url = $this->server->proxy->redirect_url;
$this->selectedProxy = data_get($this->server, 'proxy.type');
$this->redirect_url = data_get($this->server, 'proxy.redirect_url');
}
public function proxyStatusUpdated()
@@ -69,9 +69,10 @@ class Proxy extends Component
}
}
public function load_proxy_configuration()
public function loadProxyConfiguration()
{
try {
ray('loadProxyConfiguration');
$this->proxy_settings = resolve(CheckConfigurationSync::class)($this->server);
} catch (\Throwable $e) {
return general_error_handler(err: $e);

View File

@@ -10,15 +10,20 @@ class Deploy extends Component
{
public Server $server;
public $proxy_settings = null;
protected $listeners = ['proxyStatusUpdated'];
public function start_proxy()
public function proxyStatusUpdated() {
$this->server->refresh();
}
public function startProxy()
{
if (
$this->server->proxy->last_applied_settings &&
$this->server->proxy->last_saved_settings !== $this->server->proxy->last_applied_settings
) {
$this->emit('saveConfiguration', $this->server);
resolve(SaveConfigurationSync::class)($this->server, $this->proxy_settings);
}
$activity = resolve(StartProxy::class)($this->server);
$this->emit('newMonitorActivity', $activity->id);
}

View File

@@ -2,7 +2,6 @@
namespace App\Http\Livewire\Server\Proxy;
use App\Jobs\ProxyContainerStatusJob;
use App\Models\Server;
use Livewire\Component;
@@ -10,14 +9,26 @@ class Status extends Component
{
public Server $server;
public function get_status()
protected $listeners = ['proxyStatusUpdated'];
public function proxyStatusUpdated() {
$this->server->refresh();
}
public function getProxyStatus()
{
if (data_get($this->server,'settings.is_usable')) {
dispatch_sync(new ProxyContainerStatusJob(
server: $this->server
));
$this->server->refresh();
$this->emit('proxyStatusUpdated');
try {
if (data_get($this->server, 'settings.is_usable') && data_get($this->server, 'settings.is_reachable')) {
$container = getContainerStatus(server: $this->server, container_id: 'coolify-proxy');
$this->server->proxy->status = $container;
$this->server->save();
$this->emit('proxyStatusUpdated');
}
} catch (\Throwable $e) {
return general_error_handler(err: $e);
}
}
public function getProxyStatusWithNoti() {
$this->emit('success', 'Refreshing proxy status.');
$this->getProxyStatus();
}
}

View File

@@ -2,7 +2,7 @@
namespace App\Http\Livewire\Settings;
use App\Jobs\ProxyStartJob;
use App\Jobs\ProxyContainerStatusJob;
use App\Models\InstanceSettings as ModelsInstanceSettings;
use App\Models\Server;
use Livewire\Component;
@@ -124,7 +124,7 @@ class Configuration extends Component
];
}
$this->save_configuration_to_disk($traefik_dynamic_conf, $file);
dispatch(new ProxyStartJob($this->server));
dispatch(new ProxyContainerStatusJob($this->server));
}
}

View File

@@ -135,7 +135,7 @@ class ApplicationDeploymentJob implements ShouldQueue
$this->deploy();
}
}
if ($this->application->fqdn) dispatch(new ProxyStartJob($this->server));
if ($this->application->fqdn) dispatch(new ProxyContainerStatusJob($this->server));
$this->next(ApplicationDeploymentStatus::FINISHED->value);
} catch (Exception $e) {
ray($e);

View File

@@ -1,46 +0,0 @@
<?php
namespace App\Jobs;
use App\Actions\Proxy\StartProxy;
use App\Models\Server;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ProxyCheckJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct()
{
}
public function handle()
{
try {
$container_name = 'coolify-proxy';
$servers = Server::all();
foreach ($servers as $server) {
if (
$server->settings->is_reachable === false || $server->settings->is_usable === false
) {
continue;
}
$status = getContainerStatus(server: $server, container_id: $container_name);
if ($status === 'running') {
continue;
}
if (data_get($server, 'proxy.type')) {
resolve(StartProxy::class)($server);
}
}
} catch (\Throwable $e) {
ray($e->getMessage());
send_internal_notification('ProxyCheckJob failed with: ' . $e->getMessage());
throw $e;
}
}
}

View File

@@ -2,6 +2,8 @@
namespace App\Jobs;
use App\Actions\Proxy\StartProxy;
use App\Enums\ProxyStatus;
use App\Enums\ProxyTypes;
use App\Models\Server;
use Illuminate\Bus\Queueable;
@@ -11,7 +13,6 @@ use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Str;
class ProxyContainerStatusJob implements ShouldQueue, ShouldBeUnique
{
@@ -28,29 +29,49 @@ class ProxyContainerStatusJob implements ShouldQueue, ShouldBeUnique
public function middleware(): array
{
return [new WithoutOverlapping($this->server->id)];
return [new WithoutOverlapping($this->server->uuid)];
}
public function uniqueId(): int
public function uniqueId(): string
{
return $this->server->id;
ray($this->server->uuid);
return $this->server->uuid;
}
public function handle(): void
{
try {
$container = getContainerStatus(server: $this->server, all_data: true, container_id: 'coolify-proxy', throwError: false);
$status = data_get($container, 'State.Status');
if ($status && data_get($this->server, 'proxy.status') !== $status) {
$this->server->proxy->status = $status;
if ($this->server->proxy->status === 'running') {
$traefik = $container['Config']['Labels']['org.opencontainers.image.title'];
$version = $container['Config']['Labels']['org.opencontainers.image.version'];
if (isset($version) && isset($traefik) && $traefik === 'Traefik' && Str::of($version)->startsWith('v2')) {
$this->server->proxy->type = ProxyTypes::TRAEFIK_V2->value;
}
$proxyType = data_get($this->server, 'proxy.type');
if ($proxyType === ProxyTypes::NONE->value) {
return;
}
if (is_null($proxyType)) {
if ($this->server->isProxyShouldRun()) {
$this->server->proxy->type = ProxyTypes::TRAEFIK_V2->value;
$this->server->proxy->status = ProxyStatus::EXITED->value;
$this->server->save();
resolve(StartProxy::class)($this->server);
return;
}
}
$container = getContainerStatus(server: $this->server, all_data: true, container_id: 'coolify-proxy', throwError: false);
$containerStatus = data_get($container, 'State.Status');
$databaseContainerStatus = data_get($this->server, 'proxy.status', 'exited');
if ($proxyType !== ProxyTypes::NONE->value) {
if ($containerStatus === 'running') {
$this->server->proxy->status = $containerStatus;
$this->server->save();
return;
}
if ((is_null($containerStatus) ||$containerStatus !== 'running' || $databaseContainerStatus !== 'running' || ($containerStatus && $databaseContainerStatus !== $containerStatus)) && $this->server->isProxyShouldRun()) {
$this->server->proxy->status = $containerStatus;
$this->server->save();
resolve(StartProxy::class)($this->server);
return;
}
$this->server->save();
}
} catch (\Throwable $e) {
if ($e->getCode() === 1) {

View File

@@ -1,44 +0,0 @@
<?php
namespace App\Jobs;
use App\Actions\Proxy\StartProxy;
use App\Enums\ProxyStatus;
use App\Enums\ProxyTypes;
use App\Models\Server;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ProxyStartJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(protected Server $server)
{
}
public function handle()
{
try {
$container_name = 'coolify-proxy';
ray('Starting proxy for server: ' . $this->server->name);
$status = getContainerStatus(server: $this->server, container_id: $container_name);
if ($status === 'running') {
return;
}
if (is_null(data_get($this->server, 'proxy.type'))) {
$this->server->proxy->type = ProxyTypes::TRAEFIK_V2->value;
$this->server->proxy->status = ProxyStatus::EXITED->value;
$this->server->save();
}
resolve(StartProxy::class)($this->server);
} catch (\Throwable $e) {
send_internal_notification('ProxyStartJob failed with: ' . $e->getMessage());
ray($e->getMessage());
throw $e;
}
}
}

View File

@@ -1,46 +0,0 @@
<?php
namespace App\Jobs;
use App\Models\Application;
use App\Models\StandalonePostgresql;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ResourceStatusJob implements ShouldQueue, ShouldBeUnique
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $applications;
public $postgresqls;
public function __construct()
{
$this->applications = Application::all();
$this->postgresqls = StandalonePostgresql::all();
}
public function handle(): void
{
try {
foreach ($this->applications as $application) {
dispatch(new ApplicationContainerStatusJob(
application: $application,
));
}
foreach ($this->postgresqls as $postgresql) {
dispatch(new DatabaseContainerStatusJob(
database: $postgresql,
));
}
} catch (\Throwable $e) {
send_internal_notification('ResourceStatusJob failed with: ' . $e->getMessage());
ray($e);
throw $e;
}
}
}

View File

@@ -30,7 +30,6 @@ class Server extends BaseModel
'server_id' => $server->id,
]);
}
});
static::deleting(function ($server) {
$server->destinations()->each(function ($destination) {
@@ -72,7 +71,6 @@ class Server extends BaseModel
$swarmDocker = collect($server->swarmDockers->all());
return $standaloneDocker->concat($swarmDocker);
}
public function settings()
{
return $this->hasOne(ServerSetting::class);
@@ -93,7 +91,8 @@ class Server extends BaseModel
return false;
}
public function databases() {
public function databases()
{
return $this->destinations()->map(function ($standaloneDocker) {
$postgresqls = $standaloneDocker->postgresqls;
return $postgresqls?->concat([]) ?? collect([]);
@@ -137,4 +136,21 @@ class Server extends BaseModel
{
return $this->belongsTo(Team::class);
}
public function isProxyShouldRun()
{
$shouldRun = false;
foreach ($this->applications() as $application) {
if (data_get($application, 'fqdn')) {
$shouldRun = true;
break;
}
}
if ($this->id === 0) {
$settings = InstanceSettings::get();
if (data_get($settings, 'fqdn')) {
$shouldRun = true;
}
}
return $shouldRun;
}
}

View File

@@ -13,9 +13,10 @@ class Modal extends Component
*/
public function __construct(
public string $modalId,
public string|null $modalTitle = null,
public string|null $modalBody = null,
public string|null $modalSubmit = null,
public ?string $submitWireAction = null,
public ?string $modalTitle = null,
public ?string $modalBody = null,
public ?string $modalSubmit = null,
public bool $noSubmit = false,
public bool $yesOrNo = false,
public string $action = 'delete'