From 9bdad6bb672991959237fcc8909efcb92c1d106f Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 11 Mar 2024 17:17:34 +0100 Subject: [PATCH] feat caddy dynamic configurations --- app/Actions/Proxy/StartProxy.php | 2 + app/Console/Commands/Init.php | 3 +- app/Livewire/Settings/Configuration.php | 6 +- app/Models/Server.php | 153 +++++++++++++++++++++++- bootstrap/helpers/proxy.php | 127 +------------------- 5 files changed, 159 insertions(+), 132 deletions(-) diff --git a/app/Actions/Proxy/StartProxy.php b/app/Actions/Proxy/StartProxy.php index 46ac816b4..a781ab442 100644 --- a/app/Actions/Proxy/StartProxy.php +++ b/app/Actions/Proxy/StartProxy.php @@ -37,8 +37,10 @@ public function handle(Server $server, bool $async = true): string|Activity "echo 'Proxy started successfully.'" ]); } else { + $caddfile = "import /dynamic/*.caddy"; $commands = $commands->merge([ "mkdir -p $proxy_path/dynamic && cd $proxy_path", + "echo '$caddfile' > $proxy_path/dynamic/Caddyfile", "echo 'Creating required Docker Compose file.'", "echo 'Pulling docker image.'", 'docker compose pull', diff --git a/app/Console/Commands/Init.php b/app/Console/Commands/Init.php index c69d411dd..66a4f1aff 100644 --- a/app/Console/Commands/Init.php +++ b/app/Console/Commands/Init.php @@ -35,7 +35,8 @@ public function handle() $this->call('cleanup:queue'); $this->call('cleanup:stucked-resources'); try { - setup_dynamic_configuration(); + $server = Server::find(0)->first(); + $server->setupDynamicProxyConfiguration(); } catch (\Throwable $e) { echo "Could not setup dynamic configuration: {$e->getMessage()}\n"; } diff --git a/app/Livewire/Settings/Configuration.php b/app/Livewire/Settings/Configuration.php index bafc82447..f1c732a97 100644 --- a/app/Livewire/Settings/Configuration.php +++ b/app/Livewire/Settings/Configuration.php @@ -2,12 +2,9 @@ namespace App\Livewire\Settings; -use App\Jobs\ContainerStatusJob; use App\Models\InstanceSettings as ModelsInstanceSettings; use App\Models\Server; use Livewire\Component; -use Spatie\Url\Url; -use Symfony\Component\Yaml\Yaml; class Configuration extends Component { @@ -84,7 +81,6 @@ public function submit() private function setup_instance_fqdn() { - setup_dynamic_configuration(); - + $this->server->setupDynamicProxyConfiguration(); } } diff --git a/app/Models/Server.php b/app/Models/Server.php index bc65cbdba..d2c412d9e 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -15,6 +15,8 @@ use Spatie\SchemalessAttributes\SchemalessAttributesTrait; use Illuminate\Support\Str; use Illuminate\Support\Stringable; +use Spatie\Url\Url; +use Symfony\Component\Yaml\Yaml; class Server extends BaseModel { @@ -118,7 +120,156 @@ public function addInitialNetwork() } } } - public function proxyPath() { + public function setupDynamicProxyConfiguration() + { + $settings = InstanceSettings::get(); + $dynamic_config_path = $this->proxyPath() . "/dynamic"; + if ($this) { + if ($this->proxyType() === 'TRAEFIK_V2') { + $file = "$dynamic_config_path/coolify.yaml"; + if (empty($settings->fqdn)) { + instant_remote_process([ + "rm -f $file", + ], $this); + } else { + $url = Url::fromString($settings->fqdn); + $host = $url->getHost(); + $schema = $url->getScheme(); + $traefik_dynamic_conf = [ + 'http' => + [ + 'middlewares' => [ + 'redirect-to-https' => [ + 'redirectscheme' => [ + 'scheme' => 'https', + ], + ], + 'gzip' => [ + 'compress' => true, + ], + ], + 'routers' => + [ + 'coolify-http' => + [ + 'middlewares' => [ + 0 => 'gzip', + ], + 'entryPoints' => [ + 0 => 'http', + ], + 'service' => 'coolify', + 'rule' => "Host(`{$host}`)", + ], + 'coolify-realtime-ws' => + [ + 'entryPoints' => [ + 0 => 'http', + ], + 'service' => 'coolify-realtime', + 'rule' => "Host(`{$host}`) && PathPrefix(`/app`)", + ], + ], + 'services' => + [ + 'coolify' => + [ + 'loadBalancer' => + [ + 'servers' => + [ + 0 => + [ + 'url' => 'http://coolify:80', + ], + ], + ], + ], + 'coolify-realtime' => + [ + 'loadBalancer' => + [ + 'servers' => + [ + 0 => + [ + 'url' => 'http://coolify-realtime:6001', + ], + ], + ], + ], + ], + ], + ]; + + if ($schema === 'https') { + $traefik_dynamic_conf['http']['routers']['coolify-http']['middlewares'] = [ + 0 => 'redirect-to-https', + ]; + + $traefik_dynamic_conf['http']['routers']['coolify-https'] = [ + 'entryPoints' => [ + 0 => 'https', + ], + 'service' => 'coolify', + 'rule' => "Host(`{$host}`)", + 'tls' => [ + 'certresolver' => 'letsencrypt', + ], + ]; + $traefik_dynamic_conf['http']['routers']['coolify-realtime-wss'] = [ + 'entryPoints' => [ + 0 => 'https', + ], + 'service' => 'coolify-realtime', + 'rule' => "Host(`{$host}`) && PathPrefix(`/app`)", + 'tls' => [ + 'certresolver' => 'letsencrypt', + ], + ]; + } + $yaml = Yaml::dump($traefik_dynamic_conf, 12, 2); + $yaml = + "# This file is automatically generated by Coolify.\n" . + "# Do not edit it manually (only if you know what are you doing).\n\n" . + $yaml; + + $base64 = base64_encode($yaml); + instant_remote_process([ + "mkdir -p $dynamic_config_path", + "echo '$base64' | base64 -d > $file", + ], $this); + + if (config('app.env') == 'local') { + // ray($yaml); + } + } + } else if ($this->proxyType() === 'CADDY') { + $file = "$dynamic_config_path/coolify.caddy"; + if (empty($settings->fqdn)) { + instant_remote_process([ + "rm -f $file", + "docker exec coolify-proxy caddy reload --config /dynamic/Caddyfile", + ], $this); + } else { + $url = Url::fromString($settings->fqdn); + $host = $url->getHost(); + $schema = $url->getScheme(); + $caddy_file = " +$schema://$host { + reverse_proxy coolify:80 +}"; + $base64 = base64_encode($caddy_file); + instant_remote_process([ + "echo '$base64' | base64 -d > $file", + "docker exec coolify-proxy caddy reload --config /dynamic/Caddyfile", + ], $this); + } + } + } + } + public function proxyPath() + { $base_path = config('coolify.base_config_path'); $proxyType = $this->proxyType(); $proxy_path = "$base_path/proxy"; diff --git a/bootstrap/helpers/proxy.php b/bootstrap/helpers/proxy.php index caa3e4fa0..2bdffaf63 100644 --- a/bootstrap/helpers/proxy.php +++ b/bootstrap/helpers/proxy.php @@ -188,6 +188,7 @@ function generate_default_proxy_configuration(Server $server) ], "environment" => [ "CADDY_DOCKER_POLLING_INTERVAL=5s", + "CADDY_DOCKER_CADDYFILE_PATH=/dynamic/Caddyfile", ], "networks" => $networks->toArray(), "ports" => [ @@ -202,6 +203,7 @@ function generate_default_proxy_configuration(Server $server) // ], "volumes" => [ "/var/run/docker.sock:/var/run/docker.sock:ro", + "{$proxy_path}/dynamic:/dynamic", "{$proxy_path}/config:/config", "{$proxy_path}/data:/data", ], @@ -216,132 +218,7 @@ function generate_default_proxy_configuration(Server $server) SaveConfiguration::run($server, $config); return $config; } -function setup_dynamic_configuration() -{ - $settings = InstanceSettings::get(); - $server = Server::find(0); - $dynamic_config_path = $server->proxyPath() . "/dynamic"; - if ($server) { - $file = "$dynamic_config_path/coolify.yaml"; - if (empty($settings->fqdn)) { - instant_remote_process([ - "rm -f $file", - ], $server); - } else { - $url = Url::fromString($settings->fqdn); - $host = $url->getHost(); - $schema = $url->getScheme(); - $traefik_dynamic_conf = [ - 'http' => - [ - 'middlewares' => [ - 'redirect-to-https' => [ - 'redirectscheme' => [ - 'scheme' => 'https', - ], - ], - 'gzip' => [ - 'compress' => true, - ], - ], - 'routers' => - [ - 'coolify-http' => - [ - 'middlewares' => [ - 0 => 'gzip', - ], - 'entryPoints' => [ - 0 => 'http', - ], - 'service' => 'coolify', - 'rule' => "Host(`{$host}`)", - ], - 'coolify-realtime-ws' => - [ - 'entryPoints' => [ - 0 => 'http', - ], - 'service' => 'coolify-realtime', - 'rule' => "Host(`{$host}`) && PathPrefix(`/app`)", - ], - ], - 'services' => - [ - 'coolify' => - [ - 'loadBalancer' => - [ - 'servers' => - [ - 0 => - [ - 'url' => 'http://coolify:80', - ], - ], - ], - ], - 'coolify-realtime' => - [ - 'loadBalancer' => - [ - 'servers' => - [ - 0 => - [ - 'url' => 'http://coolify-realtime:6001', - ], - ], - ], - ], - ], - ], - ]; - if ($schema === 'https') { - $traefik_dynamic_conf['http']['routers']['coolify-http']['middlewares'] = [ - 0 => 'redirect-to-https', - ]; - - $traefik_dynamic_conf['http']['routers']['coolify-https'] = [ - 'entryPoints' => [ - 0 => 'https', - ], - 'service' => 'coolify', - 'rule' => "Host(`{$host}`)", - 'tls' => [ - 'certresolver' => 'letsencrypt', - ], - ]; - $traefik_dynamic_conf['http']['routers']['coolify-realtime-wss'] = [ - 'entryPoints' => [ - 0 => 'https', - ], - 'service' => 'coolify-realtime', - 'rule' => "Host(`{$host}`) && PathPrefix(`/app`)", - 'tls' => [ - 'certresolver' => 'letsencrypt', - ], - ]; - } - $yaml = Yaml::dump($traefik_dynamic_conf, 12, 2); - $yaml = - "# This file is automatically generated by Coolify.\n" . - "# Do not edit it manually (only if you know what are you doing).\n\n" . - $yaml; - - $base64 = base64_encode($yaml); - instant_remote_process([ - "mkdir -p $dynamic_config_path", - "echo '$base64' | base64 -d > $file", - ], $server); - - if (config('app.env') == 'local') { - // ray($yaml); - } - } - } -} function setup_default_redirect_404(string|null $redirect_url, Server $server) { $traefik_dynamic_conf_path = $server->proxyPath() . "/dynamic";