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>
177 lines
5.8 KiB
PHP
177 lines
5.8 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Domain;
|
|
|
|
use App\Models\Domain;
|
|
|
|
class DomainDnsBlueprintService
|
|
{
|
|
public function expectedNameservers(): array
|
|
{
|
|
$nameservers = (array) config('mailinfra.nameservers', ['ns1.ladill.com', 'ns2.ladill.com']);
|
|
|
|
return collect($nameservers)
|
|
->map(fn ($value) => strtolower(trim((string) $value, ". \t\n\r\0\x0B")))
|
|
->filter()
|
|
->unique()
|
|
->values()
|
|
->all();
|
|
}
|
|
|
|
public function mailSetupInstructions(): array
|
|
{
|
|
return [
|
|
'imap' => [
|
|
'server' => (string) config('mailinfra.mail_host', 'mail.ladill.com'),
|
|
'port' => (int) config('mailinfra.imap_port', 993),
|
|
'security' => 'SSL/TLS',
|
|
'username' => 'full_email',
|
|
],
|
|
'smtp' => [
|
|
'server' => (string) config('mailinfra.mail_host', 'mail.ladill.com'),
|
|
'port' => (int) config('mailinfra.smtp_port', 587),
|
|
'security' => 'STARTTLS',
|
|
'authentication' => true,
|
|
'username' => 'full_email',
|
|
],
|
|
'smtp_ssl' => [
|
|
'server' => (string) config('mailinfra.mail_host', 'mail.ladill.com'),
|
|
'port' => (int) config('mailinfra.smtp_ssl_port', 465),
|
|
'security' => 'SSL/TLS',
|
|
],
|
|
];
|
|
}
|
|
|
|
public function managedRecords(Domain $domain, string $selector, string $publicKey): array
|
|
{
|
|
$mailHost = strtolower(trim((string) config('mailinfra.mail_host', 'mail.ladill.com')));
|
|
$autodiscoverHost = strtolower(trim((string) config('mailinfra.autodiscover_host', 'autodiscover.ladill.com')));
|
|
$autoconfigHost = strtolower(trim((string) config('mailinfra.autoconfig_host', 'autoconfig.ladill.com')));
|
|
$ttl = (int) config('mailinfra.default_ttl', 3600);
|
|
$websiteIp = trim((string) config('mailinfra.website_a_record', ''));
|
|
$wwwTarget = trim((string) config('mailinfra.website_www_cname', '@'));
|
|
$rua = trim((string) config('mailinfra.dmarc_rua', 'mailto:dmarc@ladill.com'));
|
|
|
|
$records = [];
|
|
|
|
// Always include A record for apex domain (use configured IP or placeholder)
|
|
$records[] = [
|
|
'name' => '@',
|
|
'type' => 'A',
|
|
'value' => $websiteIp !== '' ? $websiteIp : '161.97.138.149',
|
|
'ttl' => $ttl,
|
|
'priority' => null,
|
|
'source' => 'managed',
|
|
'status' => 'active',
|
|
'notes' => 'Website apex record',
|
|
];
|
|
|
|
// Always include www record (CNAME to @ or A record to same IP)
|
|
if ($wwwTarget !== '' && $wwwTarget !== '@') {
|
|
$records[] = [
|
|
'name' => 'www',
|
|
'type' => 'CNAME',
|
|
'value' => $wwwTarget,
|
|
'ttl' => $ttl,
|
|
'priority' => null,
|
|
'source' => 'managed',
|
|
'status' => 'active',
|
|
'notes' => 'Website www record',
|
|
];
|
|
} else {
|
|
// Default: www points to same IP as apex
|
|
$records[] = [
|
|
'name' => 'www',
|
|
'type' => 'A',
|
|
'value' => $websiteIp !== '' ? $websiteIp : '161.97.138.149',
|
|
'ttl' => $ttl,
|
|
'priority' => null,
|
|
'source' => 'managed',
|
|
'status' => 'active',
|
|
'notes' => 'Website www record',
|
|
];
|
|
}
|
|
|
|
$records[] = [
|
|
'name' => '@',
|
|
'type' => 'MX',
|
|
'value' => $mailHost.'.',
|
|
'ttl' => $ttl,
|
|
'priority' => 10,
|
|
'source' => 'managed',
|
|
'status' => 'active',
|
|
'notes' => 'Primary mail exchanger',
|
|
];
|
|
|
|
$records[] = [
|
|
'name' => '@',
|
|
'type' => 'TXT',
|
|
'value' => (string) config('mailinfra.spf_customer_txt'),
|
|
'ttl' => $ttl,
|
|
'priority' => null,
|
|
'source' => 'managed',
|
|
'status' => 'active',
|
|
'notes' => 'SPF policy',
|
|
];
|
|
|
|
$records[] = [
|
|
'name' => $selector.'._domainkey',
|
|
'type' => 'TXT',
|
|
'value' => sprintf('v=DKIM1; k=rsa; p=%s', $publicKey),
|
|
'ttl' => $ttl,
|
|
'priority' => null,
|
|
'source' => 'managed',
|
|
'status' => 'active',
|
|
'notes' => 'DKIM public key',
|
|
];
|
|
|
|
$records[] = [
|
|
'name' => '_dmarc',
|
|
'type' => 'TXT',
|
|
'value' => sprintf('v=DMARC1; p=none; rua=%s; adkim=s; aspf=s', $rua),
|
|
'ttl' => $ttl,
|
|
'priority' => null,
|
|
'source' => 'managed',
|
|
'status' => 'active',
|
|
'notes' => 'DMARC policy',
|
|
];
|
|
|
|
$records[] = [
|
|
'name' => 'autodiscover',
|
|
'type' => 'CNAME',
|
|
'value' => $autodiscoverHost.'.',
|
|
'ttl' => $ttl,
|
|
'priority' => null,
|
|
'source' => 'managed',
|
|
'status' => 'active',
|
|
'notes' => 'Autodiscover helper',
|
|
];
|
|
|
|
$records[] = [
|
|
'name' => 'autoconfig',
|
|
'type' => 'CNAME',
|
|
'value' => $autoconfigHost.'.',
|
|
'ttl' => $ttl,
|
|
'priority' => null,
|
|
'source' => 'managed',
|
|
'status' => 'active',
|
|
'notes' => 'Autoconfig helper',
|
|
];
|
|
|
|
return $records;
|
|
}
|
|
|
|
public function manualDnsPack(Domain $domain, string $selector, string $publicKey): array
|
|
{
|
|
return collect($this->managedRecords($domain, $selector, $publicKey))
|
|
->map(function (array $record) {
|
|
$record['source'] = 'required_manual';
|
|
$record['status'] = 'pending';
|
|
|
|
return $record;
|
|
})
|
|
->values()
|
|
->all();
|
|
}
|
|
}
|