diff --git a/app/Actions/Proxy/StartProxy.php b/app/Actions/Proxy/StartProxy.php
index 7c93720cb..9bc506d9b 100644
--- a/app/Actions/Proxy/StartProxy.php
+++ b/app/Actions/Proxy/StartProxy.php
@@ -2,6 +2,7 @@
namespace App\Actions\Proxy;
+use App\Enums\ProxyTypes;
use App\Events\ProxyStarted;
use App\Models\Server;
use Lorisleiva\Actions\Concerns\AsAction;
@@ -37,11 +38,16 @@ public function handle(Server $server, bool $async = true, bool $force = false):
"echo 'Successfully started coolify-proxy.'",
]);
} else {
- $caddfile = 'import /dynamic/*.caddy';
+ if (isDev()) {
+ if ($proxyType === ProxyTypes::CADDY->value) {
+ $proxy_path = '/data/coolify/proxy/caddy';
+ }
+ }
+ $caddyfile = 'import /dynamic/*.caddy';
$commands = $commands->merge([
"mkdir -p $proxy_path/dynamic",
"cd $proxy_path",
- "echo '$caddfile' > $proxy_path/dynamic/Caddyfile",
+ "echo '$caddyfile' > $proxy_path/dynamic/Caddyfile",
"echo 'Creating required Docker Compose file.'",
"echo 'Pulling docker image.'",
'docker compose pull',
diff --git a/app/Listeners/ProxyStartedNotification.php b/app/Listeners/ProxyStartedNotification.php
index d0541b162..9045b1e5c 100644
--- a/app/Listeners/ProxyStartedNotification.php
+++ b/app/Listeners/ProxyStartedNotification.php
@@ -14,7 +14,7 @@ public function __construct() {}
public function handle(ProxyStarted $event): void
{
$this->server = data_get($event, 'data');
- $this->server->setupDefault404Redirect();
+ $this->server->setupDefaultRedirect();
$this->server->setupDynamicProxyConfiguration();
$this->server->proxy->force_stop = false;
$this->server->save();
diff --git a/app/Livewire/Server/Proxy.php b/app/Livewire/Server/Proxy.php
index 0b069ddb9..5d2f851db 100644
--- a/app/Livewire/Server/Proxy.php
+++ b/app/Livewire/Server/Proxy.php
@@ -15,6 +15,7 @@ class Proxy extends Component
public $proxy_settings = null;
+ public bool $redirect_enabled = true;
public ?string $redirect_url = null;
protected $listeners = ['proxyStatusUpdated', 'saveConfiguration' => 'submit'];
@@ -26,6 +27,7 @@ class Proxy extends Component
public function mount()
{
$this->selectedProxy = $this->server->proxyType();
+ $this->redirect_enabled = data_get($this->server, 'proxy.redirect_enabled', true);
$this->redirect_url = data_get($this->server, 'proxy.redirect_url');
}
@@ -63,13 +65,25 @@ public function instantSave()
}
}
+ public function instantSaveRedirect()
+ {
+ try {
+ $this->server->proxy->redirect_enabled = $this->redirect_enabled;
+ $this->server->save();
+ $this->server->setupDefaultRedirect();
+ $this->dispatch('success', 'Proxy configuration saved.');
+ } catch (\Throwable $e) {
+ return handleError($e, $this);
+ }
+ }
+
public function submit()
{
try {
SaveConfiguration::run($this->server, $this->proxy_settings);
$this->server->proxy->redirect_url = $this->redirect_url;
$this->server->save();
- $this->server->setupDefault404Redirect();
+ $this->server->setupDefaultRedirect();
$this->dispatch('success', 'Proxy configuration saved.');
} catch (\Throwable $e) {
return handleError($e, $this);
diff --git a/app/Livewire/Server/Proxy/Deploy.php b/app/Livewire/Server/Proxy/Deploy.php
index 8fcff85d6..4f9d41092 100644
--- a/app/Livewire/Server/Proxy/Deploy.php
+++ b/app/Livewire/Server/Proxy/Deploy.php
@@ -65,7 +65,7 @@ public function proxyStatusUpdated()
public function restart()
{
try {
- $this->stop(forceStop: false);
+ $this->stop();
$this->dispatch('checkProxy');
} catch (\Throwable $e) {
return handleError($e, $this);
@@ -105,6 +105,7 @@ public function stop(bool $forceStop = true)
$startTime = Carbon::now()->getTimestamp();
while ($process->running()) {
+ ray('running');
if (Carbon::now()->getTimestamp() - $startTime >= $timeout) {
$this->forceStopContainer($containerName);
break;
diff --git a/app/Models/Server.php b/app/Models/Server.php
index 77673b959..4c4ca774f 100644
--- a/app/Models/Server.php
+++ b/app/Models/Server.php
@@ -105,6 +105,14 @@ protected static function booted()
]);
}
}
+ if (! isset($server->proxy->redirect_enabled)) {
+ $server->proxy->redirect_enabled = true;
+ }
+ });
+ static::retrieved(function ($server) {
+ if (! isset($server->proxy->redirect_enabled)) {
+ $server->proxy->redirect_enabled = true;
+ }
});
static::forceDeleting(function ($server) {
@@ -184,73 +192,77 @@ public function proxySet()
return $this->proxyType() && $this->proxyType() !== 'NONE' && $this->isFunctional() && ! $this->isSwarmWorker() && ! $this->settings->is_build_server;
}
- public function setupDefault404Redirect()
+ public function setupDefaultRedirect()
{
+ $banner =
+ "# This file is generated by Coolify, do not edit it manually.\n".
+ "# Disable the default redirect to customize (only if you know what are you doing).\n\n";
$dynamic_conf_path = $this->proxyPath().'/dynamic';
$proxy_type = $this->proxyType();
+ $redirect_enabled = $this->proxy->redirect_enabled ?? true;
$redirect_url = $this->proxy->redirect_url;
- if ($proxy_type === ProxyTypes::TRAEFIK->value) {
- $default_redirect_file = "$dynamic_conf_path/default_redirect_404.yaml";
- } elseif ($proxy_type === ProxyTypes::CADDY->value) {
- $default_redirect_file = "$dynamic_conf_path/default_redirect_404.caddy";
- }
- if (empty($redirect_url)) {
+ if (isDev()) {
if ($proxy_type === ProxyTypes::CADDY->value) {
- $conf = ':80, :443 {
-respond 404
-}';
- $conf =
- "# This file is automatically generated by Coolify.\n".
- "# Do not edit it manually (only if you know what are you doing).\n\n".
- $conf;
- $base64 = base64_encode($conf);
- instant_remote_process([
- "mkdir -p $dynamic_conf_path",
- "echo '$base64' | base64 -d | tee $default_redirect_file > /dev/null",
- ], $this);
- $this->reloadCaddy();
-
- return;
+ $dynamic_conf_path = '/data/coolify/proxy/caddy/dynamic';
}
- instant_remote_process([
- "mkdir -p $dynamic_conf_path",
- "rm -f $default_redirect_file",
- ], $this);
-
- return;
}
if ($proxy_type === ProxyTypes::TRAEFIK->value) {
- $dynamic_conf = [
- 'http' => [
- 'routers' => [
- 'catchall' => [
- 'entryPoints' => [
- 0 => 'http',
- 1 => 'https',
- ],
- 'service' => 'noop',
- 'rule' => 'HostRegexp(`.+`)',
- 'tls' => [
- 'certResolver' => 'letsencrypt',
- ],
- 'priority' => 1,
- 'middlewares' => [
- 0 => 'redirect-regexp',
+ $default_redirect_file = "$dynamic_conf_path/default_redirect_503.yaml";
+ } elseif ($proxy_type === ProxyTypes::CADDY->value) {
+ $default_redirect_file = "$dynamic_conf_path/default_redirect_503.caddy";
+ }
+
+ instant_remote_process([
+ "mkdir -p $dynamic_conf_path",
+ "rm -f $dynamic_conf_path/default_redirect_404.yaml",
+ "rm -f $dynamic_conf_path/default_redirect_404.caddy",
+ ], $this);
+
+ if ($redirect_enabled === false) {
+ instant_remote_process(["rm -f $default_redirect_file"], $this);
+ } else {
+ if ($proxy_type === ProxyTypes::CADDY->value) {
+ if (filled($redirect_url)) {
+ $conf = ":80, :443 {
+ redir $redirect_url
+}";
+ } else {
+ $conf = ':80, :443 {
+ respond 503
+}';
+ }
+ } elseif ($proxy_type === ProxyTypes::TRAEFIK->value) {
+ $dynamic_conf = [
+ 'http' => [
+ 'routers' => [
+ 'catchall' => [
+ 'entryPoints' => [
+ 0 => 'http',
+ 1 => 'https',
+ ],
+ 'service' => 'noop',
+ 'rule' => 'PathPrefix(`/`)',
+ 'priority' => -1000,
],
],
- ],
- 'services' => [
- 'noop' => [
- 'loadBalancer' => [
- 'servers' => [
- 0 => [
- 'url' => '',
- ],
+ 'services' => [
+ 'noop' => [
+ 'loadBalancer' => [
+ 'servers' => [],
],
],
],
],
- 'middlewares' => [
+ ];
+ if (filled($redirect_url)) {
+ $dynamic_conf['http']['routers']['catchall']['middlewares'] = [
+ 0 => 'redirect-regexp',
+ ];
+
+ $dynamic_conf['http']['services']['noop']['loadBalancer']['servers'][0] = [
+ 'url' => '',
+ ];
+ $dynamic_conf['http']['middlewares'] = [
'redirect-regexp' => [
'redirectRegex' => [
'regex' => '(.*)',
@@ -258,32 +270,17 @@ public function setupDefault404Redirect()
'permanent' => false,
],
],
- ],
- ],
- ];
- $conf = Yaml::dump($dynamic_conf, 12, 2);
- $conf =
- "# This file is automatically generated by Coolify.\n".
- "# Do not edit it manually (only if you know what are you doing).\n\n".
- $conf;
-
- $base64 = base64_encode($conf);
- } elseif ($proxy_type === ProxyTypes::CADDY->value) {
- $conf = ":80, :443 {
- redir $redirect_url
-}";
- $conf =
- "# This file is automatically generated by Coolify.\n".
- "# Do not edit it manually (only if you know what are you doing).\n\n".
- $conf;
+ ];
+ }
+ $conf = Yaml::dump($dynamic_conf, 12, 2);
+ }
+ $conf = $banner.$conf;
$base64 = base64_encode($conf);
+ instant_remote_process([
+ "echo '$base64' | base64 -d | tee $default_redirect_file > /dev/null",
+ ], $this);
}
- instant_remote_process([
- "mkdir -p $dynamic_conf_path",
- "echo '$base64' | base64 -d | tee $default_redirect_file > /dev/null",
- ], $this);
-
if ($proxy_type === 'CADDY') {
$this->reloadCaddy();
}
@@ -612,6 +609,7 @@ public function getMemoryMetrics(int $mins = 5)
$memory = json_decode($memory, true);
$parsedCollection = collect($memory)->map(function ($metric) {
$usedPercent = $metric['usedPercent'] ?? 0.0;
+
return [(int) $metric['time'], (float) $usedPercent];
});
diff --git a/bootstrap/helpers/proxy.php b/bootstrap/helpers/proxy.php
index a8ef0fe5a..463e89b6f 100644
--- a/bootstrap/helpers/proxy.php
+++ b/bootstrap/helpers/proxy.php
@@ -173,13 +173,12 @@ function generate_default_proxy_configuration(Server $server)
],
'volumes' => [
'/var/run/docker.sock:/var/run/docker.sock:ro',
- "{$proxy_path}:/traefik",
+
],
'command' => [
'--ping=true',
'--ping.entrypoint=http',
'--api.dashboard=true',
- '--api.insecure=false',
'--entrypoints.http.address=:80',
'--entrypoints.https.address=:443',
'--entrypoints.http.http.encodequerysemicolons=true',
@@ -187,21 +186,26 @@ function generate_default_proxy_configuration(Server $server)
'--entrypoints.https.http.encodequerysemicolons=true',
'--entryPoints.https.http2.maxConcurrentStreams=50',
'--entrypoints.https.http3',
- '--providers.docker.exposedbydefault=false',
'--providers.file.directory=/traefik/dynamic/',
+ '--providers.docker.exposedbydefault=false',
'--providers.file.watch=true',
'--certificatesresolvers.letsencrypt.acme.httpchallenge=true',
- '--certificatesresolvers.letsencrypt.acme.storage=/traefik/acme.json',
'--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=http',
+ '--certificatesresolvers.letsencrypt.acme.storage=/traefik/acme.json',
],
'labels' => $labels,
],
],
];
if (isDev()) {
- // $config['services']['traefik']['command'][] = "--log.level=debug";
+ $config['services']['traefik']['command'][] = '--api.insecure=true';
+ $config['services']['traefik']['command'][] = '--log.level=debug';
$config['services']['traefik']['command'][] = '--accesslog.filepath=/traefik/access.log';
$config['services']['traefik']['command'][] = '--accesslog.bufferingsize=100';
+ $config['services']['traefik']['volumes'][] = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/proxy/:/traefik';
+ } else {
+ $config['services']['traefik']['command'][] = '--api.insecure=false';
+ $config['services']['traefik']['volumes'][] = "{$proxy_path}:/traefik";
}
if ($server->isSwarm()) {
data_forget($config, 'services.traefik.container_name');
diff --git a/resources/views/livewire/server/proxy.blade.php b/resources/views/livewire/server/proxy.blade.php
index 25c3f7acd..00e0b04b2 100644
--- a/resources/views/livewire/server/proxy.blade.php
+++ b/resources/views/livewire/server/proxy.blade.php
@@ -27,6 +27,13 @@
helper="If set, all resources will only have docker container labels for {{ str($server->proxyType())->title() }}.
For applications, labels needs to be regenerated manually.
Resources needs to be restarted."
id="server.settings.generate_exact_labels"
label="Generate labels only for {{ str($server->proxyType())->title() }}" instantSave />
+