From 661092e184bd8db5ec4266268350ae0b5bf7c491 Mon Sep 17 00:00:00 2001 From: John Coffey Date: Wed, 4 Nov 2026 21:36:46 -0700 Subject: [PATCH] DNS guide: leave CAA off by default and say why A CAA record covers every name under the domain and ties it to this server's ACME account, so another ACME client there is refused at its next renewal. The guide no longer switches it on by itself, and the switch now carries a warning. Part of inbuxa/inbuxa-server#292 --- src/features/dns/records.test.ts | 22 ++++++++++++++++++++++ src/features/dns/records.ts | 16 +++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 src/features/dns/records.test.ts diff --git a/src/features/dns/records.test.ts b/src/features/dns/records.test.ts new file mode 100644 index 0000000..1ddd8ca --- /dev/null +++ b/src/features/dns/records.test.ts @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2026 Coffey Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { describe, expect, it } from 'vitest'; +import { DEFAULT_KINDS, RECORD_GROUPS } from './records'; + +describe('DEFAULT_KINDS', () => { + it('leaves off the records that can break something else', () => { + expect(DEFAULT_KINDS).not.toContain('tlsa'); + expect(DEFAULT_KINDS).not.toContain('caa'); + expect(DEFAULT_KINDS).toContain('dkim'); + expect(DEFAULT_KINDS).toContain('mx'); + }); + + it('warns before CAA is switched on', () => { + const caa = RECORD_GROUPS.flatMap((g) => g.kinds).find((k) => k.kind === 'caa'); + expect(caa?.caution).toMatch(/refused at its next renewal/); + }); +}); diff --git a/src/features/dns/records.ts b/src/features/dns/records.ts index 7937852..658fb26 100644 --- a/src/features/dns/records.ts +++ b/src/features/dns/records.ts @@ -63,11 +63,21 @@ export const RECORD_GROUPS: RecordGroup[] = [ id: 'certs', title: 'Limit who can issue certificates', why: 'Names the certificate authorities allowed to issue for this domain.', - kinds: [{ kind: 'caa', label: 'Certificate authorities (CAA)' }], + kinds: [ + { + kind: 'caa', + label: 'Certificate authorities (CAA)', + caution: + "Covers every name under this domain and ties it to this server's ACME account. Another ACME client under this domain, like certbot on a web server, is refused at its next renewal.", + }, + ], }, ]; -/** The guided default: everything but TLSA, which needs DNSSEC to mean anything. */ +/** + * The guided default: everything but TLSA, which needs DNSSEC to mean anything, + * and CAA, which can stop other ACME clients under the domain from renewing. + */ export const DEFAULT_KINDS: RecordKind[] = RECORD_GROUPS.flatMap((g) => g.kinds.map((k) => k.kind)).filter( - (k) => k !== 'tlsa', + (k) => k !== 'tlsa' && k !== 'caa', ); -- 2.54.0