fix: proxy check for ports, do not kill anything listening on port 80/443
This commit is contained in:
parent
5aa8ccfcf4
commit
59eae3a44e
42
app/Actions/Proxy/CheckProxy.php
Normal file
42
app/Actions/Proxy/CheckProxy.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions\Proxy;
|
||||||
|
|
||||||
|
use App\Enums\ProxyTypes;
|
||||||
|
use App\Models\Server;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Lorisleiva\Actions\Concerns\AsAction;
|
||||||
|
use Spatie\Activitylog\Models\Activity;
|
||||||
|
|
||||||
|
class CheckProxy
|
||||||
|
{
|
||||||
|
use AsAction;
|
||||||
|
public function handle(Server $server)
|
||||||
|
{
|
||||||
|
if (!$server->isProxyShouldRun()) {
|
||||||
|
throw new \Exception("Proxy should not run");
|
||||||
|
}
|
||||||
|
$status = getContainerStatus($server, 'coolify-proxy');
|
||||||
|
if ($status === 'running') {
|
||||||
|
$server->proxy->set('status', 'running');
|
||||||
|
$server->save();
|
||||||
|
return 'OK';
|
||||||
|
}
|
||||||
|
$ip = $server->ip;
|
||||||
|
if ($server->id === 0) {
|
||||||
|
$ip = 'host.docker.internal';
|
||||||
|
}
|
||||||
|
|
||||||
|
$connection = @fsockopen($ip, '80');
|
||||||
|
$connection = @fsockopen($ip, '443');
|
||||||
|
$port80 = is_resource($connection) && fclose($connection);
|
||||||
|
$port443 = is_resource($connection) && fclose($connection);
|
||||||
|
ray($ip);
|
||||||
|
if ($port80) {
|
||||||
|
throw new \Exception("Port 80 is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a> <br> Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>");
|
||||||
|
}
|
||||||
|
if ($port443) {
|
||||||
|
throw new \Exception("Port 443 is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a> <br> Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace App\Actions\Proxy;
|
namespace App\Actions\Proxy;
|
||||||
|
|
||||||
use App\Enums\ProxyTypes;
|
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Lorisleiva\Actions\Concerns\AsAction;
|
use Lorisleiva\Actions\Concerns\AsAction;
|
||||||
@ -11,56 +10,49 @@
|
|||||||
class StartProxy
|
class StartProxy
|
||||||
{
|
{
|
||||||
use AsAction;
|
use AsAction;
|
||||||
public function handle(Server $server, bool $async = true): Activity|string
|
public function handle(Server $server, bool $async = true): string|Activity
|
||||||
{
|
{
|
||||||
$commands = collect([]);
|
try {
|
||||||
$proxyType = $server->proxyType();
|
CheckProxy::run($server);
|
||||||
if ($proxyType === ProxyTypes::NONE->value) {
|
|
||||||
return 'OK';
|
|
||||||
}
|
|
||||||
$proxy_path = get_proxy_path();
|
|
||||||
$configuration = CheckConfiguration::run($server);
|
|
||||||
if (!$configuration) {
|
|
||||||
throw new \Exception("Configuration is not synced");
|
|
||||||
}
|
|
||||||
SaveConfiguration::run($server, $configuration);
|
|
||||||
$docker_compose_yml_base64 = base64_encode($configuration);
|
|
||||||
$server->proxy->last_applied_settings = Str::of($docker_compose_yml_base64)->pipe('md5')->value;
|
|
||||||
$server->save();
|
|
||||||
|
|
||||||
$commands = $commands->merge([
|
$proxyType = $server->proxyType();
|
||||||
"apt-get update > /dev/null 2>&1 || true",
|
$commands = collect([]);
|
||||||
"command -v lsof >/dev/null || echo '####### Installing lsof.'",
|
$proxy_path = get_proxy_path();
|
||||||
"command -v lsof >/dev/null || apt install -y lsof",
|
$configuration = CheckConfiguration::run($server);
|
||||||
"command -v lsof >/dev/null || command -v fuser >/dev/null || apt install -y psmisc",
|
if (!$configuration) {
|
||||||
"mkdir -p $proxy_path && cd $proxy_path",
|
throw new \Exception("Configuration is not synced");
|
||||||
"echo '####### Creating Docker Compose file.'",
|
}
|
||||||
"echo '####### Pulling docker image.'",
|
SaveConfiguration::run($server, $configuration);
|
||||||
'docker compose pull',
|
$docker_compose_yml_base64 = base64_encode($configuration);
|
||||||
"echo '####### Stopping existing coolify-proxy.'",
|
$server->proxy->last_applied_settings = Str::of($docker_compose_yml_base64)->pipe('md5')->value;
|
||||||
"docker compose down -v --remove-orphans > /dev/null 2>&1",
|
|
||||||
"command -v fuser >/dev/null || command -v lsof >/dev/null || echo '####### Could not kill existing processes listening on port 80 & 443. Please stop the process holding these ports...'",
|
|
||||||
"command -v lsof >/dev/null && lsof -nt -i:80 | xargs -r kill -9 || true",
|
|
||||||
"command -v lsof >/dev/null && lsof -nt -i:443 | xargs -r kill -9 || true",
|
|
||||||
"command -v fuser >/dev/null && fuser -k 80/tcp || true",
|
|
||||||
"command -v fuser >/dev/null && fuser -k 443/tcp || true",
|
|
||||||
"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.'"
|
|
||||||
]);
|
|
||||||
$commands = $commands->merge(connectProxyToNetworks($server));
|
|
||||||
if ($async) {
|
|
||||||
$activity = remote_process($commands, $server);
|
|
||||||
return $activity;
|
|
||||||
} else {
|
|
||||||
instant_remote_process($commands, $server);
|
|
||||||
$server->proxy->set('status', 'running');
|
|
||||||
$server->proxy->set('type', $proxyType);
|
|
||||||
$server->save();
|
$server->save();
|
||||||
return 'OK';
|
$commands = $commands->merge([
|
||||||
|
"mkdir -p $proxy_path && cd $proxy_path",
|
||||||
|
"echo 'Creating required Docker Compose file.'",
|
||||||
|
"echo 'Pulling docker image.'",
|
||||||
|
'docker compose pull',
|
||||||
|
"echo 'Stopping existing coolify-proxy.'",
|
||||||
|
"docker compose down -v --remove-orphans > /dev/null 2>&1",
|
||||||
|
"echo 'Starting coolify-proxy.'",
|
||||||
|
'docker compose up -d --remove-orphans',
|
||||||
|
"echo 'Proxy started successfully.'"
|
||||||
|
]);
|
||||||
|
$commands = $commands->merge(connectProxyToNetworks($server));
|
||||||
|
if ($async) {
|
||||||
|
$activity = remote_process($commands, $server);
|
||||||
|
return $activity;
|
||||||
|
} else {
|
||||||
|
instant_remote_process($commands, $server);
|
||||||
|
$server->proxy->set('status', 'running');
|
||||||
|
$server->proxy->set('type', $proxyType);
|
||||||
|
$server->save();
|
||||||
|
return 'OK';
|
||||||
|
}
|
||||||
|
} catch(\Throwable $e) {
|
||||||
|
ray($e);
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire\Server\Proxy;
|
namespace App\Http\Livewire\Server\Proxy;
|
||||||
|
|
||||||
|
use App\Actions\Proxy\CheckProxy;
|
||||||
use App\Actions\Proxy\StartProxy;
|
use App\Actions\Proxy\StartProxy;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
@ -11,18 +12,29 @@ class Deploy extends Component
|
|||||||
public Server $server;
|
public Server $server;
|
||||||
public bool $traefikDashboardAvailable = false;
|
public bool $traefikDashboardAvailable = false;
|
||||||
public ?string $currentRoute = null;
|
public ?string $currentRoute = null;
|
||||||
protected $listeners = ['proxyStatusUpdated', 'traefikDashboardAvailable', 'serverRefresh' => 'proxyStatusUpdated'];
|
protected $listeners = ['proxyStatusUpdated', 'traefikDashboardAvailable', 'serverRefresh' => 'proxyStatusUpdated', "checkProxy", "startProxy"];
|
||||||
|
|
||||||
public function mount() {
|
public function mount()
|
||||||
|
{
|
||||||
$this->currentRoute = request()->route()->getName();
|
$this->currentRoute = request()->route()->getName();
|
||||||
}
|
}
|
||||||
public function traefikDashboardAvailable(bool $data) {
|
public function traefikDashboardAvailable(bool $data)
|
||||||
|
{
|
||||||
$this->traefikDashboardAvailable = $data;
|
$this->traefikDashboardAvailable = $data;
|
||||||
}
|
}
|
||||||
public function proxyStatusUpdated()
|
public function proxyStatusUpdated()
|
||||||
{
|
{
|
||||||
$this->server->refresh();
|
$this->server->refresh();
|
||||||
}
|
}
|
||||||
|
public function checkProxy() {
|
||||||
|
try {
|
||||||
|
CheckProxy::run($this->server);
|
||||||
|
$this->emit('startProxyPolling');
|
||||||
|
$this->emit('proxyChecked');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
public function startProxy()
|
public function startProxy()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
@ -11,8 +11,6 @@ class Modal extends Component
|
|||||||
|
|
||||||
public function proxyStatusUpdated()
|
public function proxyStatusUpdated()
|
||||||
{
|
{
|
||||||
$this->server->proxy->set('status', 'running');
|
|
||||||
$this->server->save();
|
|
||||||
$this->emit('proxyStatusUpdated');
|
$this->emit('proxyStatusUpdated');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire\Server\Proxy;
|
namespace App\Http\Livewire\Server\Proxy;
|
||||||
|
|
||||||
|
use App\Actions\Proxy\CheckProxy;
|
||||||
use App\Jobs\ContainerStatusJob;
|
use App\Jobs\ContainerStatusJob;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
@ -9,12 +10,42 @@
|
|||||||
class Status extends Component
|
class Status extends Component
|
||||||
{
|
{
|
||||||
public Server $server;
|
public Server $server;
|
||||||
|
public bool $polling = false;
|
||||||
|
public int $numberOfPolls = 0;
|
||||||
|
|
||||||
protected $listeners = ['proxyStatusUpdated'];
|
protected $listeners = ['proxyStatusUpdated', 'startProxyPolling'];
|
||||||
|
public function startProxyPolling()
|
||||||
|
{
|
||||||
|
$this->polling = true;
|
||||||
|
}
|
||||||
public function proxyStatusUpdated()
|
public function proxyStatusUpdated()
|
||||||
{
|
{
|
||||||
$this->server->refresh();
|
$this->server->refresh();
|
||||||
}
|
}
|
||||||
|
public function checkProxy(bool $notification = false)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if ($this->polling) {
|
||||||
|
if ($this->numberOfPolls >= 10) {
|
||||||
|
$this->polling = false;
|
||||||
|
$this->numberOfPolls = 0;
|
||||||
|
$notification && $this->emit('error', 'Proxy is not running.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->numberOfPolls++;
|
||||||
|
}
|
||||||
|
CheckProxy::run($this->server);
|
||||||
|
$this->emit('proxyStatusUpdated');
|
||||||
|
if ($this->server->proxy->status === 'running') {
|
||||||
|
$this->polling = false;
|
||||||
|
$notification && $this->emit('success', 'Proxy is running.');
|
||||||
|
} else {
|
||||||
|
$notification && $this->emit('error', 'Proxy is not running.');
|
||||||
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
public function getProxyStatus()
|
public function getProxyStatus()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@ -24,11 +55,4 @@ public function getProxyStatus()
|
|||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public function getProxyStatusWithNoti()
|
|
||||||
{
|
|
||||||
if ($this->server->isFunctional()) {
|
|
||||||
$this->emit('success', 'Refreshed proxy status.');
|
|
||||||
$this->getProxyStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -27,11 +27,6 @@ class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
public $tries = 1;
|
public $tries = 1;
|
||||||
public $timeout = 120;
|
public $timeout = 120;
|
||||||
|
|
||||||
public function __construct(public Server $server)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function middleware(): array
|
public function middleware(): array
|
||||||
{
|
{
|
||||||
return [(new WithoutOverlapping($this->server->uuid))->dontRelease()];
|
return [(new WithoutOverlapping($this->server->uuid))->dontRelease()];
|
||||||
@ -41,6 +36,11 @@ public function uniqueId(): string
|
|||||||
{
|
{
|
||||||
return $this->server->uuid;
|
return $this->server->uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function __construct(public Server $server)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
@ -22,7 +22,7 @@ function connectProxyToNetworks(Server $server)
|
|||||||
}
|
}
|
||||||
$commands = $networks->map(function ($network) {
|
$commands = $networks->map(function ($network) {
|
||||||
return [
|
return [
|
||||||
"echo '####### Connecting coolify-proxy to $network network...'",
|
"echo 'Connecting coolify-proxy to $network network...'",
|
||||||
"docker network ls --format '{{.Name}}' | grep '^$network$' >/dev/null || docker network create --attachable $network >/dev/null",
|
"docker network ls --format '{{.Name}}' | grep '^$network$' >/dev/null || docker network create --attachable $network >/dev/null",
|
||||||
"docker network connect $network coolify-proxy >/dev/null 2>&1 || true",
|
"docker network connect $network coolify-proxy >/dev/null 2>&1 || true",
|
||||||
];
|
];
|
||||||
|
@ -20,8 +20,9 @@
|
|||||||
@endif
|
@endif
|
||||||
<x-forms.button isModal noStyle modalId="stopProxy"
|
<x-forms.button isModal noStyle modalId="stopProxy"
|
||||||
class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
|
class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-error" viewBox="0 0 24 24" stroke-width="2"
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-error" viewBox="0 0 24 24"
|
||||||
stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||||
|
stroke-linejoin="round">
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||||
<path d="M6 5m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"></path>
|
<path d="M6 5m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"></path>
|
||||||
<path d="M14 5m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"></path>
|
<path d="M14 5m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"></path>
|
||||||
@ -30,7 +31,7 @@ class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400"
|
|||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<button wire:click='startProxy' onclick="startProxy.showModal()"
|
<button onclick="checkProxy()"
|
||||||
class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
|
class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-warning" viewBox="0 0 24 24"
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-warning" viewBox="0 0 24 24"
|
||||||
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||||
@ -42,4 +43,13 @@ class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400"
|
|||||||
</button>
|
</button>
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
|
<script>
|
||||||
|
function checkProxy() {
|
||||||
|
Livewire.emit('checkProxy')
|
||||||
|
}
|
||||||
|
Livewire.on('proxyChecked', () => {
|
||||||
|
startProxy.showModal();
|
||||||
|
Livewire.emit('startProxy');
|
||||||
|
})
|
||||||
|
</script>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<div>
|
<div>
|
||||||
@if ($server->isFunctional())
|
@if ($server->isFunctional())
|
||||||
<div class="flex gap-2" x-init="$wire.getProxyStatus">
|
<div class="flex gap-2" @if ($polling) wire:poll.2000ms='checkProxy' @endif>
|
||||||
@if (data_get($server, 'proxy.status') === 'running')
|
@if (data_get($server, 'proxy.status') === 'running')
|
||||||
<x-status.running status="Proxy Running" />
|
<x-status.running status="Proxy Running" />
|
||||||
@elseif (data_get($server, 'proxy.status') === 'restarting')
|
@elseif (data_get($server, 'proxy.status') === 'restarting')
|
||||||
@ -8,7 +8,9 @@
|
|||||||
@else
|
@else
|
||||||
<x-status.stopped status="Proxy Stopped" />
|
<x-status.stopped status="Proxy Stopped" />
|
||||||
@endif
|
@endif
|
||||||
<x-forms.button wire:click='getProxyStatusWithNoti'>Refresh </x-forms.button>
|
@if (data_get($server, 'proxy.status') === 'running')
|
||||||
|
<x-forms.button wire:click='checkProxy(true)'>Refresh</x-forms.button>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user