Resolver modules: one that serves, and two ways of deciding what a machine asks

Three manifests and the rule that keeps them apart. Serving and asking are
genuinely different roles, and systemd-resolved can only do the second — it
cannot answer a wildcard, it routes the mesh's suffix to something that can. A
module that treated them as one role could not work, which is the mistake worth
naming rather than discovering.

So `the-dns-port` and `the-resolver-configuration` are two claims. A machine
gets one of each, and two of either is refused by the mesh rather than fought
over on the machine — which is what ADR 0009's table meant by listing resolvers
beside the seat and pid 1. That table names the resource `/etc/resolv.conf`,
which is what it is; a claim is a name in the catalogue's own form, and the
catalogue refuses the path as one.

Neither module knows anything about the machine it is on, which is what lets
them be static manifests: they name `mesh0` and `127.0.0.54`, both chosen by
the mesh, rather than an address only that machine has. Not 127.0.0.1 and not
127.0.0.53 — taking either would be a module claiming something it did not say
it claims.

A service can now reflect a file another module put on the machine, written
`<module>.<id>`. The resolver has to restart when the mesh rewrites the names;
without it, it would serve the names it started with for ever, with every
machine that joined afterwards unreachable and every check passing.
This commit is contained in:
2026-08-31 12:21:58 +02:00
parent 3954157555
commit bff893f8af
7 changed files with 310 additions and 1 deletions
+18
View File
@@ -0,0 +1,18 @@
{
"module": "resolved-split-dns",
"version": "1",
"requires": ["wildcard-resolution"],
"claims": [{"name": "the-resolver-configuration", "scope": "node"}],
"resources": [
{"id": "drop-in", "type": "directory", "path": "/etc/systemd/resolved.conf.d", "mode": "0755"},
{"id": "route", "type": "file",
"path": "/etc/systemd/resolved.conf.d/mesh.conf", "mode": "0644",
"content": "# Managed by the mesh.\n#\n# **Only the mesh's names.** The tilde makes this a routing domain rather than a\n# search domain: queries under it go to the resolver below, and everything else\n# keeps going wherever this machine already sent it. A resolver that took over\n# all of DNS would be this module claiming the machine's whole network, which\n# is not what it says it claims.\n#\n# 127.0.0.54 is where the mesh's resolver answers on every machine — a name the\n# mesh chose, so this file needs to know nothing about this particular one.\n[Resolve]\nDNS=127.0.0.54\nDomains=~internal\n"},
{"id": "resolved", "type": "service", "unit": "systemd-resolved.service",
"state": "running", "boot": "enabled", "restart-on": ["route"]}
]
}