mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
- Regenerate SSL Certificates now writes server.crt/server.key for every engine except MongoDB, which keeps the combined server.pem. Before, the button always wrote server.pem, so Postgres, MySQL, MariaDB, Redis, KeyDB and Dragonfly failed to start after a regenerate. - The certificate renewal job uses the same rule, so MongoDB no longer switches to server.crt/server.key on renewal and fails on restart. - Starting an SSL database writes the CA that signs its certificate to /data/coolify/ssl/coolify-ca.crt, so a stale CA file (for example one written by another server entry for the same host) no longer causes "certificate signature failure". - Saving a custom CA certificate that does not match the stored CA private key is rejected. - The CA file write commands live in SslHelper::caCertificateFileCommands(). Fixes #10388 Fixes #6771 Fixes #11926
84 lines
2.7 KiB
PHP
84 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace App\Jobs;
|
|
|
|
use App\Helpers\SslHelper;
|
|
use App\Models\SslCertificate;
|
|
use App\Models\Team;
|
|
use App\Notifications\SslExpirationNotification;
|
|
use Illuminate\Bus\Queueable;
|
|
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
use Illuminate\Foundation\Bus\Dispatchable;
|
|
use Illuminate\Queue\InteractsWithQueue;
|
|
use Illuminate\Queue\SerializesModels;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class RegenerateSslCertJob implements ShouldBeEncrypted, ShouldQueue
|
|
{
|
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
|
|
public $tries = 3;
|
|
|
|
public $backoff = 60;
|
|
|
|
public function __construct(
|
|
protected ?Team $team = null,
|
|
protected ?int $server_id = null,
|
|
protected bool $force_regeneration = false,
|
|
) {}
|
|
|
|
public function handle()
|
|
{
|
|
$query = SslCertificate::query();
|
|
|
|
if ($this->server_id) {
|
|
$query->where('server_id', $this->server_id);
|
|
}
|
|
|
|
if (! $this->force_regeneration) {
|
|
$query->where('valid_until', '<=', now()->addDays(14));
|
|
}
|
|
|
|
$query->where('is_ca_certificate', false);
|
|
|
|
$regenerated = collect();
|
|
|
|
$query->cursor()->each(function ($certificate) use ($regenerated) {
|
|
try {
|
|
$caCert = $certificate->server->sslCertificates()
|
|
->where('is_ca_certificate', true)
|
|
->first();
|
|
|
|
if (! $caCert) {
|
|
Log::error("No CA certificate found for server_id: {$certificate->server_id}");
|
|
|
|
return;
|
|
}
|
|
SslHelper::generateSslCertificate(
|
|
commonName: $certificate->common_name,
|
|
subjectAlternativeNames: $certificate->subject_alternative_names,
|
|
resourceType: $certificate->resource_type,
|
|
resourceId: $certificate->resource_id,
|
|
serverId: $certificate->server_id,
|
|
configurationDir: $certificate->configuration_dir,
|
|
mountPath: $certificate->mount_path,
|
|
caCert: $caCert->ssl_certificate,
|
|
caKey: $caCert->ssl_private_key,
|
|
isPemKeyFileRequired: $certificate->requiresPemKeyFile(),
|
|
);
|
|
$resource = $certificate->database;
|
|
if ($resource) {
|
|
$regenerated->push($resource);
|
|
}
|
|
} catch (\Exception $e) {
|
|
Log::error('Failed to regenerate SSL certificate: '.$e->getMessage());
|
|
}
|
|
});
|
|
|
|
if ($regenerated->isNotEmpty()) {
|
|
$this->team?->notify(new SslExpirationNotification($regenerated));
|
|
}
|
|
}
|
|
}
|