diff options
Diffstat (limited to 'mail/dns')
| -rwxr-xr-x | mail/dns/setup-route53.py | 56 |
1 files changed, 51 insertions, 5 deletions
diff --git a/mail/dns/setup-route53.py b/mail/dns/setup-route53.py index a54fc91..c508235 100755 --- a/mail/dns/setup-route53.py +++ b/mail/dns/setup-route53.py @@ -29,6 +29,15 @@ SELECTOR = "mail" PRIMARY = "hetzner.yyamashita.com" ZONE_DOMAIN = "yyamashita.com" +# hetzner.yyamashita.com への CNAME を設定するサービスサブドメイン +WEB_SUBDOMAINS = [ + "golive", + "whoisband", + "code", + "git", + "hetzner-admin", +] + def get_server_ip(): if ip := os.environ.get("SERVER_IP", ""): @@ -70,6 +79,33 @@ def read_dkim_pubkey(path): return "".join(parts) +def a_record(fqdn, ip): + name = fqdn if fqdn.endswith(".") else fqdn + "." + return { + "Action": "UPSERT", + "ResourceRecordSet": { + "Name": name, + "Type": "A", + "TTL": 300, + "ResourceRecords": [{"Value": ip}], + }, + } + + +def cname_record(fqdn, target): + name = fqdn if fqdn.endswith(".") else fqdn + "." + target = target if target.endswith(".") else target + "." + return { + "Action": "UPSERT", + "ResourceRecordSet": { + "Name": name, + "Type": "CNAME", + "TTL": 300, + "ResourceRecords": [{"Value": target}], + }, + } + + def txt_record(fqdn, raw_value): chunks = [raw_value[i:i + 255] for i in range(0, len(raw_value), 255)] txt_value = " ".join(f'"{c}"' for c in chunks) @@ -117,12 +153,19 @@ def main(): changes = [] - # プライマリドメイン (IP 直指定 SPF) + # プライマリドメイン: A レコード + changes.append(a_record(PRIMARY, server_ip)) + + # Web サービス: CNAME → hetzner.yyamashita.com + for sub in WEB_SUBDOMAINS: + changes.append(cname_record(f"{sub}.{ZONE_DOMAIN}", PRIMARY)) + + # プライマリドメイン: メール認証 changes.append(txt_record(PRIMARY, f"v=spf1 ip4:{server_ip} -all")) changes.append(txt_record(f"{SELECTOR}._domainkey.{PRIMARY}", dkim_value)) changes.append(txt_record(f"_dmarc.{PRIMARY}", "v=DMARC1; p=none")) - # サービスドメイン (include SPF) + # サービスドメイン: メール認証 (include SPF) for domain in service_domains: changes.append(txt_record(domain, f"v=spf1 include:{PRIMARY} -all")) changes.append(txt_record(f"{SELECTOR}._domainkey.{domain}", dkim_value)) @@ -138,7 +181,7 @@ def main(): client.change_resource_record_sets( HostedZoneId=zone_id, ChangeBatch={ - "Comment": "Mail auth records (SPF/DKIM/DMARC) via hetzner-infra", + "Comment": "DNS records via hetzner-infra", "Changes": [c], }, ) @@ -146,8 +189,8 @@ def main(): ok += 1 except client.exceptions.InvalidChangeBatch as e: msg = str(e) - if "CNAME" in msg or "conflicting" in msg: - print(f" SKIP {rtype} {name} (既存の CNAME と競合)") + if "already exists" in msg or "conflicting" in msg: + print(f" SKIP {rtype} {name} (競合または既存レコード)") skipped += 1 else: raise @@ -156,6 +199,9 @@ def main(): print(f"完了: {ok} 件成功 / {skipped} 件スキップ") print() print("確認コマンド (数分後):") + print(f" dig A {PRIMARY} +short") + for sub in WEB_SUBDOMAINS: + print(f" dig CNAME {sub}.{ZONE_DOMAIN} +short") for domain in [PRIMARY] + service_domains: print(f" dig TXT {SELECTOR}._domainkey.{domain} +short") |
