114 lines
4.4 KiB
PHP
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';
|
|
}
|
|
}
|