This commit is contained in:
Andras Bacsai
2024-10-17 22:08:23 +02:00
parent 9044c655b8
commit b75c2dc604
18 changed files with 62 additions and 51 deletions

View File

@@ -12,6 +12,7 @@ class GenerateConfig
public function handle(Application $application, bool $is_json = false) public function handle(Application $application, bool $is_json = false)
{ {
ray()->clearAll(); ray()->clearAll();
return $application->generateConfig(is_json: $is_json); return $application->generateConfig(is_json: $is_json);
} }
} }

View File

@@ -2,7 +2,6 @@
namespace App\Actions\Server; namespace App\Actions\Server;
use App\Models\InstanceSettings;
use App\Models\Server; use App\Models\Server;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
@@ -38,7 +37,7 @@ class StartSentinel
$mount_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/sentinel'; $mount_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/sentinel';
// $image = 'sentinel'; // $image = 'sentinel';
} }
$docker_environments = '-e "' . implode('" -e "', array_map(fn($key, $value) => "$key=$value", array_keys($environments), $environments)) . '"'; $docker_environments = '-e "'.implode('" -e "', array_map(fn ($key, $value) => "$key=$value", array_keys($environments), $environments)).'"';
$docker_command = "docker run -d $docker_environments --name coolify-sentinel -v /var/run/docker.sock:/var/run/docker.sock -v $mount_dir:/app/db --pid host --health-cmd \"curl --fail http://127.0.0.1:8888/api/health || exit 1\" --health-interval 10s --health-retries 3 --add-host=host.docker.internal:host-gateway $image"; $docker_command = "docker run -d $docker_environments --name coolify-sentinel -v /var/run/docker.sock:/var/run/docker.sock -v $mount_dir:/app/db --pid host --health-cmd \"curl --fail http://127.0.0.1:8888/api/health || exit 1\" --health-interval 10s --health-retries 3 --add-host=host.docker.internal:host-gateway $image";

View File

@@ -3,7 +3,6 @@
namespace App\Actions\Server; namespace App\Actions\Server;
use App\Models\Server; use App\Models\Server;
use Carbon\Carbon;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
class StopSentinel class StopSentinel

View File

@@ -241,7 +241,6 @@ class General extends Component
} }
} }
public function updatedApplicationBuildPack() public function updatedApplicationBuildPack()
{ {
if ($this->application->build_pack !== 'nixpacks') { if ($this->application->build_pack !== 'nixpacks') {
@@ -314,7 +313,7 @@ class General extends Component
public function set_redirect() public function set_redirect()
{ {
try { try {
$has_www = collect($this->application->fqdns)->filter(fn($fqdn) => str($fqdn)->contains('www.'))->count(); $has_www = collect($this->application->fqdns)->filter(fn ($fqdn) => str($fqdn)->contains('www.'))->count();
if ($has_www === 0 && $this->application->redirect === 'www') { if ($has_www === 0 && $this->application->redirect === 'www') {
$this->dispatch('error', 'You want to redirect to www, but you do not have a www domain set.<br><br>Please add www to your domain list and as an A DNS record (if applicable).'); $this->dispatch('error', 'You want to redirect to www, but you do not have a www domain set.<br><br>Please add www to your domain list and as an A DNS record (if applicable).');
@@ -335,6 +334,7 @@ class General extends Component
$this->application->fqdn = str($this->application->fqdn)->replaceStart(',', '')->trim(); $this->application->fqdn = str($this->application->fqdn)->replaceStart(',', '')->trim();
$this->application->fqdn = str($this->application->fqdn)->trim()->explode(',')->map(function ($domain) { $this->application->fqdn = str($this->application->fqdn)->trim()->explode(',')->map(function ($domain) {
Url::fromString($domain, ['http', 'https']); Url::fromString($domain, ['http', 'https']);
return str($domain)->trim()->lower(); return str($domain)->trim()->lower();
}); });
$this->application->fqdn = $this->application->fqdn->unique()->implode(','); $this->application->fqdn = $this->application->fqdn->unique()->implode(',');
@@ -409,11 +409,13 @@ class General extends Component
if ($originalFqdn !== $this->application->fqdn) { if ($originalFqdn !== $this->application->fqdn) {
$this->application->fqdn = $originalFqdn; $this->application->fqdn = $originalFqdn;
} }
return handleError($e, $this); return handleError($e, $this);
} finally { } finally {
$this->dispatch('configurationChanged'); $this->dispatch('configurationChanged');
} }
} }
public function downloadConfig() public function downloadConfig()
{ {
$config = GenerateConfig::run($this->application, true); $config = GenerateConfig::run($this->application, true);
@@ -423,7 +425,7 @@ class General extends Component
echo $config; echo $config;
}, $fileName, [ }, $fileName, [
'Content-Type' => 'application/json', 'Content-Type' => 'application/json',
'Content-Disposition' => 'attachment; filename=' . $fileName, 'Content-Disposition' => 'attachment; filename='.$fileName,
]); ]);
} }
} }

View File

@@ -317,6 +317,7 @@ class PublicGitRepository extends Component
// $application->setConfig($config); // $application->setConfig($config);
// } // }
} }
return redirect()->route('project.application.configuration', [ return redirect()->route('project.application.configuration', [
'application_uuid' => $application->uuid, 'application_uuid' => $application->uuid,
'environment_name' => $environment->name, 'environment_name' => $environment->name,

View File

@@ -21,6 +21,7 @@ class EditDomain extends Component
{ {
$this->application = ServiceApplication::find($this->applicationId); $this->application = ServiceApplication::find($this->applicationId);
} }
public function submit() public function submit()
{ {
try { try {
@@ -28,6 +29,7 @@ class EditDomain extends Component
$this->application->fqdn = str($this->application->fqdn)->replaceStart(',', '')->trim(); $this->application->fqdn = str($this->application->fqdn)->replaceStart(',', '')->trim();
$this->application->fqdn = str($this->application->fqdn)->trim()->explode(',')->map(function ($domain) { $this->application->fqdn = str($this->application->fqdn)->trim()->explode(',')->map(function ($domain) {
Url::fromString($domain, ['http', 'https']); Url::fromString($domain, ['http', 'https']);
return str($domain)->trim()->lower(); return str($domain)->trim()->lower();
}); });
$this->application->fqdn = $this->application->fqdn->unique()->implode(','); $this->application->fqdn = $this->application->fqdn->unique()->implode(',');
@@ -48,6 +50,7 @@ class EditDomain extends Component
if ($originalFqdn !== $this->application->fqdn) { if ($originalFqdn !== $this->application->fqdn) {
$this->application->fqdn = $originalFqdn; $this->application->fqdn = $originalFqdn;
} }
return handleError($e, $this); return handleError($e, $this);
} }
} }

View File

@@ -39,7 +39,7 @@ class Navbar extends Component
return [ return [
"echo-private:user.{$userId},ServiceStatusChanged" => 'serviceStarted', "echo-private:user.{$userId},ServiceStatusChanged" => 'serviceStarted',
"envsUpdated" => '$refresh', 'envsUpdated' => '$refresh',
]; ];
} }

View File

@@ -30,10 +30,7 @@ class ServiceApplicationView extends Component
'application.is_stripprefix_enabled' => 'nullable|boolean', 'application.is_stripprefix_enabled' => 'nullable|boolean',
]; ];
public function updatedApplicationFqdn() public function updatedApplicationFqdn() {}
{
}
public function instantSave() public function instantSave()
{ {
@@ -82,6 +79,7 @@ class ServiceApplicationView extends Component
$this->application->fqdn = str($this->application->fqdn)->replaceStart(',', '')->trim(); $this->application->fqdn = str($this->application->fqdn)->replaceStart(',', '')->trim();
$this->application->fqdn = str($this->application->fqdn)->trim()->explode(',')->map(function ($domain) { $this->application->fqdn = str($this->application->fqdn)->trim()->explode(',')->map(function ($domain) {
Url::fromString($domain, ['http', 'https']); Url::fromString($domain, ['http', 'https']);
return str($domain)->trim()->lower(); return str($domain)->trim()->lower();
}); });
$this->application->fqdn = $this->application->fqdn->unique()->implode(','); $this->application->fqdn = $this->application->fqdn->unique()->implode(',');
@@ -101,6 +99,7 @@ class ServiceApplicationView extends Component
if ($originalFqdn !== $this->application->fqdn) { if ($originalFqdn !== $this->application->fqdn) {
$this->application->fqdn = $originalFqdn; $this->application->fqdn = $originalFqdn;
} }
return handleError($e, $this); return handleError($e, $this);
} }
} }

View File

@@ -8,8 +8,11 @@ use Livewire\Component;
class UploadConfig extends Component class UploadConfig extends Component
{ {
public $config; public $config;
public $applicationId; public $applicationId;
public function mount() {
public function mount()
{
if (isDev()) { if (isDev()) {
$this->config = '{ $this->config = '{
"build_pack": "nixpacks", "build_pack": "nixpacks",
@@ -22,6 +25,7 @@ class UploadConfig extends Component
}'; }';
} }
} }
public function uploadConfig() public function uploadConfig()
{ {
try { try {
@@ -30,10 +34,12 @@ class UploadConfig extends Component
$this->dispatch('success', 'Application settings updated'); $this->dispatch('success', 'Application settings updated');
} catch (\Exception $e) { } catch (\Exception $e) {
$this->dispatch('error', $e->getMessage()); $this->dispatch('error', $e->getMessage());
return; return;
} }
} }
public function render() public function render()
{ {
return view('livewire.project.shared.upload-config'); return view('livewire.project.shared.upload-config');

View File

@@ -29,7 +29,6 @@ class CloudflareTunnels extends Component
} }
} }
public function manualCloudflareConfig() public function manualCloudflareConfig()
{ {
$this->server->settings->is_cloudflare_tunnel = true; $this->server->settings->is_cloudflare_tunnel = true;

View File

@@ -30,6 +30,7 @@ class Delete extends Component
} }
$this->server->delete(); $this->server->delete();
DeleteServer::dispatch($this->server); DeleteServer::dispatch($this->server);
return redirect()->route('server.index'); return redirect()->route('server.index');
} catch (\Throwable $e) { } catch (\Throwable $e) {
return handleError($e, $this); return handleError($e, $this);

View File

@@ -47,6 +47,7 @@ class ShowPrivateKey extends Component
$this->dispatch('success', 'Server is reachable.'); $this->dispatch('success', 'Server is reachable.');
} else { } else {
$this->dispatch('error', 'Server is not reachable.<br><br>Check this <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a> for further help.<br><br>Error: '.$error); $this->dispatch('error', 'Server is not reachable.<br><br>Check this <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a> for further help.<br><br>Error: '.$error);
return; return;
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
@@ -56,6 +57,4 @@ class ShowPrivateKey extends Component
$this->server->refresh(); $this->server->refresh();
} }
} }
} }

View File

@@ -28,6 +28,7 @@ class Index extends Component
protected string $dynamic_config_path = '/data/coolify/proxy/dynamic'; protected string $dynamic_config_path = '/data/coolify/proxy/dynamic';
protected Server $server; protected Server $server;
public $timezones; public $timezones;
protected $rules = [ protected $rules = [
@@ -57,7 +58,6 @@ class Index extends Component
'settings.instance_timezone' => 'Instance Timezone', 'settings.instance_timezone' => 'Instance Timezone',
]; ];
public function mount() public function mount()
{ {
if (isInstanceAdmin()) { if (isInstanceAdmin()) {
@@ -171,7 +171,6 @@ class Index extends Component
} }
} }
public function render() public function render()
{ {
return view('livewire.settings.index'); return view('livewire.settings.index');

View File

@@ -51,7 +51,6 @@ class ScheduledDatabaseBackup extends BaseModel
} }
} }
return null; return null;
} }
} }

View File

@@ -169,7 +169,7 @@ class Server extends BaseModel
public function setupDefault404Redirect() public function setupDefault404Redirect()
{ {
$dynamic_conf_path = $this->proxyPath() . '/dynamic'; $dynamic_conf_path = $this->proxyPath().'/dynamic';
$proxy_type = $this->proxyType(); $proxy_type = $this->proxyType();
$redirect_url = $this->proxy->redirect_url; $redirect_url = $this->proxy->redirect_url;
if ($proxy_type === ProxyTypes::TRAEFIK->value) { if ($proxy_type === ProxyTypes::TRAEFIK->value) {
@@ -183,8 +183,8 @@ class Server extends BaseModel
respond 404 respond 404
}'; }';
$conf = $conf =
"# This file is automatically generated by Coolify.\n" . "# This file is automatically generated by Coolify.\n".
"# Do not edit it manually (only if you know what are you doing).\n\n" . "# Do not edit it manually (only if you know what are you doing).\n\n".
$conf; $conf;
$base64 = base64_encode($conf); $base64 = base64_encode($conf);
instant_remote_process([ instant_remote_process([
@@ -246,8 +246,8 @@ respond 404
]; ];
$conf = Yaml::dump($dynamic_conf, 12, 2); $conf = Yaml::dump($dynamic_conf, 12, 2);
$conf = $conf =
"# This file is automatically generated by Coolify.\n" . "# This file is automatically generated by Coolify.\n".
"# Do not edit it manually (only if you know what are you doing).\n\n" . "# Do not edit it manually (only if you know what are you doing).\n\n".
$conf; $conf;
$base64 = base64_encode($conf); $base64 = base64_encode($conf);
@@ -256,8 +256,8 @@ respond 404
redir $redirect_url redir $redirect_url
}"; }";
$conf = $conf =
"# This file is automatically generated by Coolify.\n" . "# This file is automatically generated by Coolify.\n".
"# Do not edit it manually (only if you know what are you doing).\n\n" . "# Do not edit it manually (only if you know what are you doing).\n\n".
$conf; $conf;
$base64 = base64_encode($conf); $base64 = base64_encode($conf);
} }
@@ -275,7 +275,7 @@ respond 404
public function setupDynamicProxyConfiguration() public function setupDynamicProxyConfiguration()
{ {
$settings = instanceSettings(); $settings = instanceSettings();
$dynamic_config_path = $this->proxyPath() . '/dynamic'; $dynamic_config_path = $this->proxyPath().'/dynamic';
if ($this->proxyType() === ProxyTypes::TRAEFIK->value) { if ($this->proxyType() === ProxyTypes::TRAEFIK->value) {
$file = "$dynamic_config_path/coolify.yaml"; $file = "$dynamic_config_path/coolify.yaml";
if (empty($settings->fqdn) || (isCloud() && $this->id !== 0) || ! $this->isLocalhost()) { if (empty($settings->fqdn) || (isCloud() && $this->id !== 0) || ! $this->isLocalhost()) {
@@ -394,8 +394,8 @@ respond 404
} }
$yaml = Yaml::dump($traefik_dynamic_conf, 12, 2); $yaml = Yaml::dump($traefik_dynamic_conf, 12, 2);
$yaml = $yaml =
"# This file is automatically generated by Coolify.\n" . "# This file is automatically generated by Coolify.\n".
"# Do not edit it manually (only if you know what are you doing).\n\n" . "# Do not edit it manually (only if you know what are you doing).\n\n".
$yaml; $yaml;
$base64 = base64_encode($yaml); $base64 = base64_encode($yaml);
@@ -459,13 +459,13 @@ $schema://$host {
if (isDev()) { if (isDev()) {
$proxy_path = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/proxy/caddy'; $proxy_path = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/proxy/caddy';
} else { } else {
$proxy_path = $proxy_path . '/caddy'; $proxy_path = $proxy_path.'/caddy';
} }
} elseif ($proxyType === ProxyTypes::NGINX->value) { } elseif ($proxyType === ProxyTypes::NGINX->value) {
if (isDev()) { if (isDev()) {
$proxy_path = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/proxy/nginx'; $proxy_path = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/proxy/nginx';
} else { } else {
$proxy_path = $proxy_path . '/nginx'; $proxy_path = $proxy_path.'/nginx';
} }
} }
@@ -528,12 +528,12 @@ $schema://$host {
Storage::disk('ssh-mux')->delete($this->muxFilename()); Storage::disk('ssh-mux')->delete($this->muxFilename());
} }
public function sentinelHeartbeat(bool $isReset = false) public function sentinelHeartbeat(bool $isReset = false)
{ {
$this->sentinel_updated_at = $isReset ? now()->subMinutes(6000) : now(); $this->sentinel_updated_at = $isReset ? now()->subMinutes(6000) : now();
$this->save(); $this->save();
} }
public function isSentinelLive() public function isSentinelLive()
{ {
return Carbon::parse($this->sentinel_updated_at)->isAfter(now()->subMinutes(4)); return Carbon::parse($this->sentinel_updated_at)->isAfter(now()->subMinutes(4));
@@ -541,7 +541,7 @@ $schema://$host {
public function isSentinelEnabled() public function isSentinelEnabled()
{ {
return ($this->isMetricsEnabled() || $this->isServerApiEnabled()) && !$this->isBuildServer(); return ($this->isMetricsEnabled() || $this->isServerApiEnabled()) && ! $this->isBuildServer();
} }
public function isMetricsEnabled() public function isMetricsEnabled()
@@ -611,8 +611,9 @@ $schema://$host {
} }
$cpu = json_decode($cpu, true); $cpu = json_decode($cpu, true);
$parsedCollection = collect($cpu)->map(function ($metric) { $parsedCollection = collect($cpu)->map(function ($metric) {
return [(int)$metric['time'], (float)$metric['percent']]; return [(int) $metric['time'], (float) $metric['percent']];
}); });
return $parsedCollection; return $parsedCollection;
} }
@@ -640,8 +641,8 @@ $schema://$host {
throw new \Exception($error); throw new \Exception($error);
} }
$memory = json_decode($memory, true); $memory = json_decode($memory, true);
$parsedCollection = collect($memory)->map(function ($metric) { $parsedCollection = collect($memory)->map(function ($metric) {
return [(int)$metric['time'], (float)$metric['usedPercent']]; return [(int) $metric['time'], (float) $metric['usedPercent']];
}); });
return $parsedCollection->toArray(); return $parsedCollection->toArray();
@@ -1092,6 +1093,7 @@ $schema://$host {
return true; return true;
} }
public function validateConnection($isManualCheck = true) public function validateConnection($isManualCheck = true)
{ {
config()->set('constants.ssh.mux_enabled', ! $isManualCheck); config()->set('constants.ssh.mux_enabled', ! $isManualCheck);

View File

@@ -72,7 +72,7 @@ class ServerSetting extends Model
} }
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
loggy('Error creating server setting: ' . $e->getMessage()); loggy('Error creating server setting: '.$e->getMessage());
} }
}); });
} }
@@ -98,17 +98,18 @@ class ServerSetting extends Model
$settings = InstanceSettings::get(); $settings = InstanceSettings::get();
if ($this->server->isLocalhost()) { if ($this->server->isLocalhost()) {
$domain = 'http://host.docker.internal:8000'; $domain = 'http://host.docker.internal:8000';
} else if ($settings->fqdn) { } elseif ($settings->fqdn) {
$domain = $settings->fqdn; $domain = $settings->fqdn;
} else if ($settings->ipv4) { } elseif ($settings->ipv4) {
$domain = $settings->ipv4 . ':8000'; $domain = $settings->ipv4.':8000';
} else if ($settings->ipv6) { } elseif ($settings->ipv6) {
$domain = $settings->ipv6 . ':8000'; $domain = $settings->ipv6.':8000';
} }
$this->sentinel_custom_url = $domain; $this->sentinel_custom_url = $domain;
if ($save) { if ($save) {
$this->save(); $this->save();
} }
return $domain; return $domain;
} }

View File

@@ -297,7 +297,7 @@ class Service extends BaseModel
'key' => 'CP_DISABLE_HTTPS', 'key' => 'CP_DISABLE_HTTPS',
'value' => data_get($disable_https, 'value'), 'value' => data_get($disable_https, 'value'),
'rules' => 'required', 'rules' => 'required',
'customHelper' => "If you want to use https, set this to 0. Variable name: CP_DISABLE_HTTPS", 'customHelper' => 'If you want to use https, set this to 0. Variable name: CP_DISABLE_HTTPS',
], ],
]); ]);
} }
@@ -997,8 +997,8 @@ class Service extends BaseModel
break; break;
case $image->contains('mysql'): case $image->contains('mysql'):
$userVariables = ['SERVICE_USER_MYSQL', 'SERVICE_USER_WORDPRESS', 'MYSQL_USER']; $userVariables = ['SERVICE_USER_MYSQL', 'SERVICE_USER_WORDPRESS', 'MYSQL_USER'];
$passwordVariables = ['SERVICE_PASSWORD_MYSQL', 'SERVICE_PASSWORD_WORDPRESS', 'MYSQL_PASSWORD','SERVICE_PASSWORD_64_MYSQL']; $passwordVariables = ['SERVICE_PASSWORD_MYSQL', 'SERVICE_PASSWORD_WORDPRESS', 'MYSQL_PASSWORD', 'SERVICE_PASSWORD_64_MYSQL'];
$rootPasswordVariables = ['SERVICE_PASSWORD_MYSQLROOT', 'SERVICE_PASSWORD_ROOT','SERVICE_PASSWORD_64_MYSQLROOT']; $rootPasswordVariables = ['SERVICE_PASSWORD_MYSQLROOT', 'SERVICE_PASSWORD_ROOT', 'SERVICE_PASSWORD_64_MYSQLROOT'];
$dbNameVariables = ['MYSQL_DATABASE']; $dbNameVariables = ['MYSQL_DATABASE'];
$mysql_user = $this->environment_variables()->whereIn('key', $userVariables)->first(); $mysql_user = $this->environment_variables()->whereIn('key', $userVariables)->first();
$mysql_password = $this->environment_variables()->whereIn('key', $passwordVariables)->first(); $mysql_password = $this->environment_variables()->whereIn('key', $passwordVariables)->first();
@@ -1326,9 +1326,9 @@ class Service extends BaseModel
return false; return false;
} }
} }
return true; return true;
} }
); );
} }
} }

View File

@@ -335,10 +335,11 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
if (preg_match('/coolify\.traefik\.middlewares=(.*)/', $item, $matches)) { if (preg_match('/coolify\.traefik\.middlewares=(.*)/', $item, $matches)) {
return explode(',', $matches[1]); return explode(',', $matches[1]);
} }
return null; return null;
})->flatten() })->flatten()
->filter() ->filter()
->unique(); ->unique();
} }
foreach ($domains as $loop => $domain) { foreach ($domains as $loop => $domain) {
try { try {
@@ -388,7 +389,7 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
if ($path !== '/') { if ($path !== '/') {
// Middleware handling // Middleware handling
$middlewares = collect([]); $middlewares = collect([]);
if ($is_stripprefix_enabled && !str($image)->contains('ghost')) { if ($is_stripprefix_enabled && ! str($image)->contains('ghost')) {
$labels->push("traefik.http.middlewares.{$https_label}-stripprefix.stripprefix.prefixes={$path}"); $labels->push("traefik.http.middlewares.{$https_label}-stripprefix.stripprefix.prefixes={$path}");
$middlewares->push("{$https_label}-stripprefix"); $middlewares->push("{$https_label}-stripprefix");
} }
@@ -402,7 +403,7 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
$labels = $labels->merge($redirect_to_non_www); $labels = $labels->merge($redirect_to_non_www);
$middlewares->push($to_non_www_name); $middlewares->push($to_non_www_name);
} }
if ($redirect_direction === 'www' && !str($host)->startsWith('www.')) { if ($redirect_direction === 'www' && ! str($host)->startsWith('www.')) {
$labels = $labels->merge($redirect_to_www); $labels = $labels->merge($redirect_to_www);
$middlewares->push($to_www_name); $middlewares->push($to_www_name);
} }