Initial Ladill Hosting app with Gitea deploy pipeline.
Deploy Ladill Hosting / deploy (push) Failing after 17s
Deploy Ladill Hosting / deploy (push) Failing after 17s
Shared web hosting extracted from the platform monolith, with CI deploy to /var/www/ladill-hosting matching Bird/Domains/Email. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\Domain;
|
||||
use App\Models\DomainDkimKey;
|
||||
use App\Models\DomainNsCheck;
|
||||
use App\Jobs\ProvisionDomainSlaveZoneJob;
|
||||
use App\Services\Dns\PowerDnsClient;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Http\Client\RequestException;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ProvisionDomainZoneJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable;
|
||||
use InteractsWithQueue;
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
public int $tries = 5;
|
||||
|
||||
public int $backoff = 60;
|
||||
|
||||
public function __construct(public int $domainId)
|
||||
{
|
||||
}
|
||||
|
||||
public function handle(PowerDnsClient $client): void
|
||||
{
|
||||
$domain = Domain::query()->find($this->domainId);
|
||||
if (! $domain) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure DKIM keys exist before provisioning zone
|
||||
$this->ensureDkimKeys($domain);
|
||||
|
||||
try {
|
||||
$client->ensureZone($domain);
|
||||
$this->logCheck($domain, 'success', 'PDNS zone provisioned successfully.');
|
||||
ProvisionDomainSlaveZoneJob::dispatch($domain->id);
|
||||
} catch (RequestException $exception) {
|
||||
$this->logCheck($domain, 'failed', $exception->getMessage());
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
private function ensureDkimKeys(Domain $domain): void
|
||||
{
|
||||
$existing = DomainDkimKey::query()
|
||||
->where('domain_id', $domain->id)
|
||||
->where('status', 'active')
|
||||
->latest('id')
|
||||
->first();
|
||||
|
||||
if ($existing) {
|
||||
return;
|
||||
}
|
||||
|
||||
$prefix = (string) config('mailinfra.dkim_selector_prefix', 'ladill');
|
||||
$selector = Str::lower(trim($prefix)) ?: 'ladill';
|
||||
$selector .= '1';
|
||||
|
||||
$config = [
|
||||
'digest_alg' => 'sha512',
|
||||
'private_key_bits' => 2048,
|
||||
'private_key_type' => OPENSSL_KEYTYPE_RSA,
|
||||
];
|
||||
|
||||
$res = openssl_pkey_new($config);
|
||||
openssl_pkey_export($res, $privateKey);
|
||||
$details = openssl_pkey_get_details($res);
|
||||
$publicKey = $details['key'] ?? '';
|
||||
|
||||
$publicKey = preg_replace('/-----BEGIN PUBLIC KEY-----|-----END PUBLIC KEY-----|\s/', '', $publicKey);
|
||||
|
||||
$privatePath = null;
|
||||
if (is_string($privateKey) && trim($privateKey) !== '') {
|
||||
$safeHost = Str::slug($domain->host, '_');
|
||||
$directory = storage_path('app/mail/dkim');
|
||||
File::ensureDirectoryExists($directory);
|
||||
$privatePath = $directory.'/'.$safeHost.'_'.$selector.'.key';
|
||||
File::put($privatePath, $privateKey);
|
||||
}
|
||||
|
||||
DomainDkimKey::query()->create([
|
||||
'domain_id' => $domain->id,
|
||||
'selector' => $selector,
|
||||
'public_key_txt' => $publicKey,
|
||||
'private_key_path' => $privatePath,
|
||||
'status' => 'active',
|
||||
]);
|
||||
}
|
||||
|
||||
private function logCheck(Domain $domain, string $result, string $notes): void
|
||||
{
|
||||
DomainNsCheck::create([
|
||||
'domain_id' => $domain->id,
|
||||
'check_type' => 'pdns_provision',
|
||||
'result' => $result,
|
||||
'status_before' => (string) $domain->status,
|
||||
'status_after' => (string) $domain->status,
|
||||
'state_before' => (string) ($domain->onboarding_state ?? ''),
|
||||
'state_after' => (string) ($domain->onboarding_state ?? ''),
|
||||
'notes' => $notes,
|
||||
'checked_at' => now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user