Files
jabali-panel/app/Observers/DomainObserver.php
2026-01-24 19:36:46 +02:00

114 lines
4.4 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Observers;
use App\Jobs\IssueSslCertificate;
use App\Models\DnsRecord;
use App\Models\DnsSetting;
use App\Models\Domain;
use App\Services\Agent\AgentClient;
use Exception;
use Illuminate\Support\Facades\Log;
class DomainObserver
{
public function created(Domain $domain): void
{
$this->createDefaultDnsRecords($domain);
$this->createDnsZone($domain);
$this->scheduleSSLIssuance($domain);
}
protected function scheduleSSLIssuance(Domain $domain): void
{
// Dispatch SSL issuance job with a 30 second delay
// This gives time for DNS to propagate and web server to be configured
IssueSslCertificate::dispatch($domain->id)->delay(now()->addSeconds(30));
Log::info("Scheduled SSL certificate issuance for {$domain->domain}");
}
public function deleted(Domain $domain): void
{
try {
$agent = new AgentClient;
$agent->send('dns.delete_zone', ['domain' => $domain->domain]);
} catch (Exception $e) {
Log::warning("Failed to delete DNS zone for {$domain->domain}: ".$e->getMessage());
}
}
protected function createDefaultDnsRecords(Domain $domain): void
{
$settings = DnsSetting::getAll();
$defaultIp = $domain->ip_address ?: ($settings['default_ip'] ?? $this->getServerIp());
$defaultIpv6 = $domain->ipv6_address ?: ($settings['default_ipv6'] ?? null);
$defaultTtl = (int) ($settings['default_ttl'] ?? 3600);
$hostname = $this->getServerHostname();
$ns1 = $settings['ns1'] ?? "ns1.{$hostname}";
$ns2 = $settings['ns2'] ?? "ns2.{$hostname}";
$defaultRecords = [
// NS records
['name' => '@', 'type' => 'NS', 'content' => $ns1, 'ttl' => $defaultTtl],
['name' => '@', 'type' => 'NS', 'content' => $ns2, 'ttl' => $defaultTtl],
// A records
['name' => '@', 'type' => 'A', 'content' => $defaultIp, 'ttl' => $defaultTtl],
['name' => 'www', 'type' => 'A', 'content' => $defaultIp, 'ttl' => $defaultTtl],
['name' => 'mail', 'type' => 'A', 'content' => $defaultIp, 'ttl' => $defaultTtl],
// MX record
['name' => '@', 'type' => 'MX', 'content' => "mail.{$domain->domain}", 'ttl' => $defaultTtl, 'priority' => 10],
// SPF record - allows mail from this server
['name' => '@', 'type' => 'TXT', 'content' => 'v=spf1 mx a ~all', 'ttl' => $defaultTtl],
// DMARC record - basic policy
['name' => '_dmarc', 'type' => 'TXT', 'content' => 'v=DMARC1; p=none; rua=mailto:postmaster@'.$domain->domain, 'ttl' => $defaultTtl],
];
if (! empty($defaultIpv6)) {
$defaultRecords[] = ['name' => '@', 'type' => 'AAAA', 'content' => $defaultIpv6, 'ttl' => $defaultTtl];
$defaultRecords[] = ['name' => 'www', 'type' => 'AAAA', 'content' => $defaultIpv6, 'ttl' => $defaultTtl];
$defaultRecords[] = ['name' => 'mail', 'type' => 'AAAA', 'content' => $defaultIpv6, 'ttl' => $defaultTtl];
}
foreach ($defaultRecords as $record) {
DnsRecord::create(array_merge(['domain_id' => $domain->id], $record));
}
}
protected function createDnsZone(Domain $domain): void
{
try {
$settings = DnsSetting::getAll();
$records = DnsRecord::where('domain_id', $domain->id)->get()->toArray();
$hostname = $this->getServerHostname();
$serverIp = $this->getServerIp();
$agent = new AgentClient;
$agent->send('dns.sync_zone', [
'domain' => $domain->domain,
'records' => $records,
'ns1' => $settings['ns1'] ?? "ns1.{$hostname}",
'ns2' => $settings['ns2'] ?? "ns2.{$hostname}",
'admin_email' => $settings['admin_email'] ?? "admin.{$hostname}",
'default_ip' => $settings['default_ip'] ?? $serverIp,
'default_ttl' => $settings['default_ttl'] ?? 3600,
]);
} catch (Exception $e) {
Log::warning("Failed to create DNS zone for {$domain->domain}: ".$e->getMessage());
}
}
protected function getServerHostname(): string
{
return gethostname() ?: 'localhost';
}
protected function getServerIp(): string
{
$ip = trim(shell_exec("hostname -I | awk '{print $1}'") ?? '');
return $ip ?: '127.0.0.1';
}
}