130 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| namespace App\Actions\Proxy;
 | |
| 
 | |
| use App\Enums\ProxyTypes;
 | |
| use App\Models\Server;
 | |
| use Illuminate\Support\Facades\Log;
 | |
| use Lorisleiva\Actions\Concerns\AsAction;
 | |
| use Symfony\Component\Yaml\Yaml;
 | |
| 
 | |
| class CheckProxy
 | |
| {
 | |
|     use AsAction;
 | |
| 
 | |
|     // It should return if the proxy should be started (true) or not (false)
 | |
|     public function handle(Server $server, $fromUI = false): bool
 | |
|     {
 | |
|         if (! $server->isFunctional()) {
 | |
|             return false;
 | |
|         }
 | |
|         if ($server->isBuildServer()) {
 | |
|             if ($server->proxy) {
 | |
|                 $server->proxy = null;
 | |
|                 $server->save();
 | |
|             }
 | |
| 
 | |
|             return false;
 | |
|         }
 | |
|         $proxyType = $server->proxyType();
 | |
|         if (is_null($proxyType) || $proxyType === 'NONE' || $server->proxy->force_stop) {
 | |
|             return false;
 | |
|         }
 | |
|         if (! $server->isProxyShouldRun()) {
 | |
|             if ($fromUI) {
 | |
|                 throw new \Exception('Proxy should not run. You selected the Custom Proxy.');
 | |
|             } else {
 | |
|                 return false;
 | |
|             }
 | |
|         }
 | |
|         if ($server->isSwarm()) {
 | |
|             $status = getContainerStatus($server, 'coolify-proxy_traefik');
 | |
|             $server->proxy->set('status', $status);
 | |
|             $server->save();
 | |
|             if ($status === 'running') {
 | |
|                 return false;
 | |
|             }
 | |
| 
 | |
|             return true;
 | |
|         } else {
 | |
|             $status = getContainerStatus($server, 'coolify-proxy');
 | |
|             if ($status === 'running') {
 | |
|                 $server->proxy->set('status', 'running');
 | |
|                 $server->save();
 | |
| 
 | |
|                 return false;
 | |
|             }
 | |
|             if ($server->settings->is_cloudflare_tunnel) {
 | |
|                 return false;
 | |
|             }
 | |
|             $ip = $server->ip;
 | |
|             if ($server->id === 0) {
 | |
|                 $ip = 'host.docker.internal';
 | |
|             }
 | |
| 
 | |
|             $portsToCheck = ['80', '443'];
 | |
| 
 | |
|             foreach ($portsToCheck as $port) {
 | |
|                 // Try multiple methods to check port availability
 | |
|                 $commands = [
 | |
|                     // Method 1: Check /proc/net/tcp directly (convert port to hex)
 | |
|                     "cat /proc/net/tcp | grep -q '00000000:".str_pad(dechex($port), 4, '0', STR_PAD_LEFT)."'",
 | |
|                     // Method 2: Use ss command (modern alternative to netstat)
 | |
|                     "ss -tuln | grep -q ':$port '",
 | |
|                     // Method 3: Use lsof if available
 | |
|                     "lsof -i :$port >/dev/null 2>&1",
 | |
|                     // Method 4: Use fuser if available
 | |
|                     "fuser $port/tcp >/dev/null 2>&1",
 | |
|                 ];
 | |
| 
 | |
|                 $portInUse = false;
 | |
|                 foreach ($commands as $command) {
 | |
|                     try {
 | |
|                         instant_remote_process([$command], $server);
 | |
|                         $portInUse = true;
 | |
|                         break;
 | |
|                     } catch (\Throwable $e) {
 | |
| 
 | |
|                         continue;
 | |
|                     }
 | |
|                 }
 | |
|                 if ($portInUse) {
 | |
|                     if ($fromUI) {
 | |
|                         throw new \Exception("Port $port is in use.<br>You must stop the process using this port.<br><br>Docs: <a target='_blank' class='dark:text-white hover:underline' href='https://coolify.io/docs'>https://coolify.io/docs</a><br>Discord: <a target='_blank' class='dark:text-white hover:underline' href='https://coolify.io/discord'>https://coolify.io/discord</a>");
 | |
|                     } else {
 | |
|                         return false;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             try {
 | |
|                 if ($server->proxyType() !== ProxyTypes::NONE->value) {
 | |
|                     $proxyCompose = CheckConfiguration::run($server);
 | |
|                     if (isset($proxyCompose)) {
 | |
|                         $yaml = Yaml::parse($proxyCompose);
 | |
|                         $portsToCheck = [];
 | |
|                         if ($server->proxyType() === ProxyTypes::TRAEFIK->value) {
 | |
|                             $ports = data_get($yaml, 'services.traefik.ports');
 | |
|                         } elseif ($server->proxyType() === ProxyTypes::CADDY->value) {
 | |
|                             $ports = data_get($yaml, 'services.caddy.ports');
 | |
|                         }
 | |
|                         if (isset($ports)) {
 | |
|                             foreach ($ports as $port) {
 | |
|                                 $portsToCheck[] = str($port)->before(':')->value();
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                 } else {
 | |
|                     $portsToCheck = [];
 | |
|                 }
 | |
|             } catch (\Exception $e) {
 | |
|                 Log::error('Error checking proxy: '.$e->getMessage());
 | |
|             }
 | |
|             if (count($portsToCheck) === 0) {
 | |
|                 return false;
 | |
|             }
 | |
| 
 | |
|             return true;
 | |
|         }
 | |
|     }
 | |
| }
 | 
