diff --git a/app/Livewire/Project/Shared/Terminal.php b/app/Livewire/Project/Shared/Terminal.php index a3d1aa10f..fce4b0cd2 100644 --- a/app/Livewire/Project/Shared/Terminal.php +++ b/app/Livewire/Project/Shared/Terminal.php @@ -43,7 +43,7 @@ class Terminal extends Component #[On('send-terminal-command')] public function sendTerminalCommand($isContainer, $identifier, $serverUuid) { - $server = Server::ownedByCurrentTeam()->whereUuid($serverUuid)->firstOrFail(); + $server = Server::ownedByCurrentTeam()->whereUuid($serverUuid)->where('settings.is_terminal_enabled', true)->firstOrFail(); if ($isContainer) { // Validate container identifier format (alphanumeric, dashes, and underscores only) diff --git a/app/Livewire/Server/Advanced.php b/app/Livewire/Server/Advanced.php index a420a38d7..1bf8cf4c9 100644 --- a/app/Livewire/Server/Advanced.php +++ b/app/Livewire/Server/Advanced.php @@ -2,12 +2,8 @@ namespace App\Livewire\Server; -use App\Helpers\SslHelper; -use App\Jobs\RegenerateSslCertJob; use App\Models\InstanceSettings; use App\Models\Server; -use App\Models\SslCertificate; -use Carbon\Carbon; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Livewire\Attributes\Validate; @@ -17,14 +13,6 @@ class Advanced extends Component { public Server $server; - public ?SslCertificate $caCertificate = null; - - public $showCertificate = false; - - public $certificateContent = ''; - - public ?Carbon $certificateValidUntil = null; - public array $parameters = []; #[Validate(['string'])] @@ -48,27 +36,12 @@ class Advanced extends Component $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); $this->parameters = get_route_parameters(); $this->syncData(); - $this->loadCaCertificate(); + } catch (\Throwable) { return redirect()->route('server.index'); } } - public function loadCaCertificate() - { - $this->caCertificate = SslCertificate::where('server_id', $this->server->id)->where('is_ca_certificate', true)->first(); - - if ($this->caCertificate) { - $this->certificateContent = $this->caCertificate->ssl_certificate; - $this->certificateValidUntil = $this->caCertificate->valid_until; - } - } - - public function toggleCertificate() - { - $this->showCertificate = ! $this->showCertificate; - } - public function toggleTerminal($password) { try { @@ -100,78 +73,6 @@ class Advanced extends Component } } - public function saveCaCertificate() - { - try { - if (! $this->certificateContent) { - throw new \Exception('Certificate content cannot be empty.'); - } - - if (! openssl_x509_read($this->certificateContent)) { - throw new \Exception('Invalid certificate format.'); - } - - if ($this->caCertificate) { - $this->caCertificate->ssl_certificate = $this->certificateContent; - $this->caCertificate->save(); - - $this->loadCaCertificate(); - - $this->writeCertificateToServer(); - - dispatch(new RegenerateSslCertJob( - server_id: $this->server->id, - force_regeneration: true - )); - } - $this->dispatch('success', 'CA Certificate saved successfully.'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function regenerateCaCertificate() - { - try { - SslHelper::generateSslCertificate( - commonName: 'Coolify CA Certificate', - serverId: $this->server->id, - isCaCertificate: true, - validityDays: 10 * 365 - ); - - $this->loadCaCertificate(); - - $this->writeCertificateToServer(); - - dispatch(new RegenerateSslCertJob( - server_id: $this->server->id, - force_regeneration: true - )); - - $this->loadCaCertificate(); - $this->dispatch('success', 'CA Certificate regenerated successfully.'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - private function writeCertificateToServer() - { - $caCertPath = config('constants.coolify.base_config_path').'/ssl/'; - - $commands = collect([ - "mkdir -p $caCertPath", - "chown -R 9999:root $caCertPath", - "chmod -R 700 $caCertPath", - "rm -rf $caCertPath/coolify-ca.crt", - "echo '{$this->certificateContent}' > $caCertPath/coolify-ca.crt", - "chmod 644 $caCertPath/coolify-ca.crt", - ]); - - remote_process($commands, $this->server); - } - public function syncData(bool $toModel = false) { if ($toModel) { diff --git a/app/Livewire/Server/CaCertificate/Show.php b/app/Livewire/Server/CaCertificate/Show.php new file mode 100644 index 000000000..750ed9f81 --- /dev/null +++ b/app/Livewire/Server/CaCertificate/Show.php @@ -0,0 +1,128 @@ +server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); + $this->loadCaCertificate(); + } catch (\Throwable $e) { + return redirect()->route('server.index'); + } + + } + + public function loadCaCertificate() + { + $this->caCertificate = SslCertificate::where('server_id', $this->server->id)->where('is_ca_certificate', true)->first(); + + if ($this->caCertificate) { + $this->certificateContent = $this->caCertificate->ssl_certificate; + $this->certificateValidUntil = $this->caCertificate->valid_until; + } + } + + public function toggleCertificate() + { + $this->showCertificate = ! $this->showCertificate; + } + + public function saveCaCertificate() + { + try { + if (! $this->certificateContent) { + throw new \Exception('Certificate content cannot be empty.'); + } + + if (! openssl_x509_read($this->certificateContent)) { + throw new \Exception('Invalid certificate format.'); + } + + if ($this->caCertificate) { + $this->caCertificate->ssl_certificate = $this->certificateContent; + $this->caCertificate->save(); + + $this->loadCaCertificate(); + + $this->writeCertificateToServer(); + + dispatch(new RegenerateSslCertJob( + server_id: $this->server->id, + force_regeneration: true + )); + } + $this->dispatch('success', 'CA Certificate saved successfully.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function regenerateCaCertificate() + { + try { + SslHelper::generateSslCertificate( + commonName: 'Coolify CA Certificate', + serverId: $this->server->id, + isCaCertificate: true, + validityDays: 10 * 365 + ); + + $this->loadCaCertificate(); + + $this->writeCertificateToServer(); + + dispatch(new RegenerateSslCertJob( + server_id: $this->server->id, + force_regeneration: true + )); + + $this->loadCaCertificate(); + $this->dispatch('success', 'CA Certificate regenerated successfully.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + private function writeCertificateToServer() + { + $caCertPath = config('constants.coolify.base_config_path').'/ssl/'; + + $commands = collect([ + "mkdir -p $caCertPath", + "chown -R 9999:root $caCertPath", + "chmod -R 700 $caCertPath", + "rm -rf $caCertPath/coolify-ca.crt", + "echo '{$this->certificateContent}' > $caCertPath/coolify-ca.crt", + "chmod 644 $caCertPath/coolify-ca.crt", + ]); + + remote_process($commands, $this->server); + } + + public function render() + { + return view('livewire.server.ca-certificate.show'); + } +} diff --git a/resources/views/components/server/sidebar.blade.php b/resources/views/components/server/sidebar.blade.php index 9de567fb2..7ec8699f8 100644 --- a/resources/views/components/server/sidebar.blade.php +++ b/resources/views/components/server/sidebar.blade.php @@ -9,6 +9,9 @@ Private Key + CA Certificate + @if (!$server->isLocalhost()) Cloudflare diff --git a/resources/views/livewire/server/advanced.blade.php b/resources/views/livewire/server/advanced.blade.php index ee78695f5..78ae93463 100644 --- a/resources/views/livewire/server/advanced.blade.php +++ b/resources/views/livewire/server/advanced.blade.php @@ -69,7 +69,6 @@

Builds

-
Customize the build process.
@@ -78,85 +77,6 @@
- -
-

CA SSL Certificate

-
- - - - -
-
- -
- -
-
-
-
-
- CA Certificate - @if ($certificateValidUntil) - (Valid until: - @if (now()->gt($certificateValidUntil)) - {{ $certificateValidUntil->format('d.m.Y H:i:s') }} - - Expired) - @elseif(now()->addDays(30)->gt($certificateValidUntil)) - {{ $certificateValidUntil->format('d.m.Y H:i:s') }} - - Expiring soon) - @else - {{ $certificateValidUntil->format('d.m.Y H:i:s') }}) - @endif - - @endif -
- - {{ $showCertificate ? 'Hide' : 'Show' }} - -
- @if ($showCertificate) - - @else -
-
-
- ━━━━━━━━ CERTIFICATE CONTENT ━━━━━━━━ -
-
- Click "Show" to view or edit -
-
-
- @endif -
-
diff --git a/resources/views/livewire/server/ca-certificate/show.blade.php b/resources/views/livewire/server/ca-certificate/show.blade.php new file mode 100644 index 000000000..a1fc8620e --- /dev/null +++ b/resources/views/livewire/server/ca-certificate/show.blade.php @@ -0,0 +1,88 @@ +
+ + {{ data_get_str($server, 'name')->limit(10) }} > CA Certificate | Coolify + + +
+ +
+
+

CA SSL Certificate

+
+ + + + +
+
+
+
+

Recommended Configuration:

+
    +
  • Mount this CA certificate of Coolify into all containers that need to connect to one of + your databases over SSL. You can see and copy the bind mount below.
  • +
  • Read more when and why this is needed here.
  • +
+
+
+ +
+
+
+
+
+ CA Certificate + @if ($certificateValidUntil) + (Valid until: + @if (now()->gt($certificateValidUntil)) + {{ $certificateValidUntil->format('d.m.Y H:i:s') }} - + Expired) + @elseif(now()->addDays(30)->gt($certificateValidUntil)) + {{ $certificateValidUntil->format('d.m.Y H:i:s') }} - + Expiring soon) + @else + {{ $certificateValidUntil->format('d.m.Y H:i:s') }}) + @endif + + @endif +
+ + {{ $showCertificate ? 'Hide' : 'Show' }} + +
+ @if ($showCertificate) + + @else +
+
+
+ ━━━━━━━━ CERTIFICATE CONTENT ━━━━━━━━ +
+
+ Click "Show" to view or edit +
+
+
+ @endif +
+
+
+
diff --git a/routes/web.php b/routes/web.php index c0368c3d9..948e828b1 100644 --- a/routes/web.php +++ b/routes/web.php @@ -37,6 +37,7 @@ use App\Livewire\Security\ApiTokens; use App\Livewire\Security\PrivateKey\Index as SecurityPrivateKeyIndex; use App\Livewire\Security\PrivateKey\Show as SecurityPrivateKeyShow; use App\Livewire\Server\Advanced as ServerAdvanced; +use App\Livewire\Server\CaCertificate\Show as CaCertificateShow; use App\Livewire\Server\Charts as ServerCharts; use App\Livewire\Server\CloudflareTunnels; use App\Livewire\Server\Delete as DeleteServer; @@ -242,6 +243,7 @@ Route::middleware(['auth', 'verified'])->group(function () { Route::get('/', ServerShow::class)->name('server.show'); Route::get('/advanced', ServerAdvanced::class)->name('server.advanced'); Route::get('/private-key', PrivateKeyShow::class)->name('server.private-key'); + Route::get('/ca-certificate', CaCertificateShow::class)->name('server.ca-certificate'); Route::get('/resources', ResourcesShow::class)->name('server.resources'); Route::get('/cloudflare-tunnels', CloudflareTunnels::class)->name('server.cloudflare-tunnels'); Route::get('/destinations', ServerDestinations::class)->name('server.destinations');