Repository navigation
Conversation
added 5 commits
September 5, 2026 02:34
… on render.com to noisegarden-root k8s cluster (Hetzner VPS). Also removes a number of dead services.
…M key
The committed noisebridge.io zone had drifted from what the nameservers
actually serve, in the dangerous direction: live carries records this
file does not. Because roles/cloudalchemy.coredns templates every zone
file via with_fileglob, the next run of that play -- for any unrelated
reason -- would have rewritten the live zone from this file and silently
dropped what was missing.
Three changes:
- Add the apex MX (10 mail.noisegarden.nexus.). This is LIVE today and
was absent here, so a deploy would have stopped all @noisebridge.io
mail. The target is deliberately mail.noisegarden.nexus rather than a
name in this zone: Stalwart's mounted certificate carries that single
SAN, so an in-zone name would break strict-TLS senders.
- Remove the v1-rsa-20260706._domainkey TXT. It is noisegarden.nexus's
own public key, published here under noisebridge.io. Verified
byte-identical to the record served for noisegarden.nexus. This domain
is an ALIAS of noisegarden.nexus in Stalwart and DKIM keys are
per-Domain, so nothing signs with d=noisebridge.io. Publishing it makes
the domain look DKIM-protected, which invites tightening DMARC to
p=quarantine and hard-failing real mail. Live serves nothing here, so
this only ever existed in the file.
- Remove the self-referential `mail._domainkey IN CNAME mail._domainkey`.
An unqualified RHS takes the origin, so it pointed at itself and could
never resolve. Live serves nothing here either.
Serial 2026080400 -> 2026090500, which must exceed the live 2026080500.
NOTE ON SCOPE: this makes the .io zone safe to deploy, but does NOT make
a deploy safe. The play globs all five zone files, so noisebridge.net
goes out at the same time -- and that file currently repoints library,
parts and matrix at noisegarden-root, which serves none of them. See the
accompanying discussion before running the play.
TESTED:
Zone parsed before and after; the record delta is exactly the three
intended changes (32 -> 31 records: -2 +1), with no collateral edits:
```sh
# -mail._domainkey CNAME, -v1-rsa-20260706._domainkey TXT, +apex MX
```
Live state confirmed against ns1 (216.252.162.220):
```sh
dig +short MX noisebridge.io # 10 mail.noisegarden.nexus.
dig +short TXT v1-rsa-20260706._domainkey.noisebridge.io # empty
dig +short TXT mail._domainkey.noisebridge.io # empty
dig +short SOA noisebridge.io | awk '{print $3}' # 2026080500
```
The repo now covers every live mail record for this zone. Not deployed.
The spf.noisebridge.net record carried two mechanisms that were not
doing what they appear to do.
`mx` authorised ZERO hosts. The apex is "v=spf1 redirect=spf.noisebridge.net",
and a redirect resets the evaluated <domain> to spf.noisebridge.net --
which has no MX records at all -- so the mechanism resolved against an
empty set on every evaluation. m3 has been authorised the whole time by
a:m3.noisebridge.net alone. Removing `mx` changes no outcome, and stops
the record implying a relationship to the domain's real MX that it does
not have.
`a:m5.noiesbridge.net` is a typo for m5, so m5 has never actually been
SPF-authorised. The misspelling matters more than the missing
authorisation: noiesbridge.net is UNREGISTERED -- NXDOMAIN for SOA, NS
and A -- which makes it a squattable authorisation vector. Anyone could
register the domain, point an A record at a host they control, and pass
SPF as @noisebridge.net under the record's ~all.
It is deleted rather than corrected. Mail has been working without m5
authorised, which is the evidence that m5 sends none; adding a
previously-unauthorised host to an SPF record is a change with its own
risk, and there is nothing asking for it.
Remaining: a:lists, a:m3, a:m6 -- 3 DNS lookups plus the redirect, well
inside the RFC 7208 limit of 10.
Serial 2026073100 -> 2026090500, which must exceed the live 2026073101.
NOTE ON SCOPE: this serial bump also finally deploys the commit beneath it on this branch, which
repoints library, parts and matrix at noisegarden-root. That cluster does
not serve those names yet -- 1 of 31 HTTPRoute hostnames on root is a
.noisebridge.net name. Confirmed as intended: the apps have no users, and
the ingress work is tracked as follow-ups.
TESTED:
Record set unchanged -- 92 records before and after, byte-identical apart
from the SPF value and the serial:
```sh
# zone parsed both sides; diff of (name,type) pairs is empty
```
Pre-deploy drift check against ns1 (216.252.162.220), to confirm the file
would not drop anything live serves:
```sh
# 92 repo records probed live -> 1 apparent diff, confirmed a formatting
# equivalence (2604:a880:1:20:0:0:c3:a001 == 2604:a880:1:20::c3:a001)
# 24 plausible undeclared names x 4 types probed -> 0 live-only records
```
Both claims verified live:
```sh
dig +short MX spf.noisebridge.net # empty -> `mx` matched nothing
dig SOA noiesbridge.net | grep status # NXDOMAIN
```
Not deployed.
The commit beneath this one removes stuff.noisebridge.net along with the
other m6 records, on the grounds that it was dead. It is not quite dead:
it resolves (CNAME -> m6) and answers HTTP 308, redirecting to its own
HTTPS, which then answers nothing. So it is a redirect loop into a dead
endpoint rather than a name nobody uses, and anything still linking to it
would go from broken-with-a-redirect to NXDOMAIN.
Restore it pointed at the new home instead, as an explicitly temporary
alias while the old name drains.
It targets `parts` rather than noisegarden-root directly, so it follows
parts wherever that goes rather than needing a second edit. The zone
already uses this shape (cycletrailer -> biketrailer, 2169 ->
biketrailer), so it is not a new idiom here.
Restoring it as a separate commit rather than amending the removal: the
removal is not mine to rewrite, and "this was removed as dead, then
deliberately brought back" is worth keeping legible.
The CNAME alone does not serve anything. A request still carries
Host: stuff.noisebridge.net, so the root cluster's HTTPRoute has to list
that hostname or it answers 404 -- the same readiness-before-DNS ordering
that library and matrix are waiting on. That hostname is added alongside
parts.noisebridge.{net,io} in the noisegarden repo, and the two should be
retired together.
No further serial bump: the file is already at 2026090500 in this branch,
ahead of the live 2026073101, and has not been deployed at that serial.
TESTED:
Zone parses; the record set grows by exactly one and the new entry is
seen as a record rather than a comment:
```sh
# 92 -> 93 records; stuff.noisebridge.net CNAME present
```
Current live behaviour that motivates keeping it:
```sh
dig +short CNAME stuff.noisebridge.net # m6.noisebridge.net.
curl -sI http://stuff.noisebridge.net/ # 308 -> https://stuff.noisebridge.net/
curl -s -o /dev/null -w '%{http_code}' https://stuff.noisebridge.net/ # 000
```
Not deployed.
Nothing the NoiseGarden Stalwart server sends as `@noisebridge.net` can currently be authenticated: it is absent from the domain's SPF, its DKIM public keys are unpublished, and there is no DMARC record. All three land here. No MX change -- that is a separate step. SPF. Adds `a:mail.noisegarden.nexus`. `a:` rather than `ip4:` so the record follows the host; the redirect keeps the mechanism count at 5, inside the RFC 7208 limit of 10. The address outbound mail actually leaves from was established by observation rather than assumed, because it need not be the one that binds :25 and under `~all` a wrong answer fails silently. Stalwart logs `localIp = 0.0.0.0` on a real outbound delivery, i.e. it binds no source address and takes the default route; the pod has no working IPv6 egress, so mail can only leave over IPv4; and that pod's observed IPv4 egress is 204.168.192.161, which is `mail.noisegarden.nexus`'s A record and the node's only address. DKIM. Both selectors, read out of the running server at publish time rather than transcribed -- they are per-domain and auto-generated, so noisegarden.nexus's `v1-*-20260706` keys are the wrong ones, which is the bug 533f0e7 removed from the .io zone. DMARC. `_dmarc.noisebridge.net` did not exist (NXDOMAIN on both nameservers). Introduced at `p=none` with `rua` at `postmaster@` -- one of the 28 role aliases -- since a cross-domain `rua` needs a `_report._dmarc` opt-in reporters otherwise silently decline. `p=none` is load-bearing rather than a first step. Stalwart forwards for this domain, forwarding breaks SPF on the second hop, and nothing signs an aligned DKIM signature for it. Stalwart's own suggested zone file offers `p=reject`, which would turn that forwarded mail into lost mail; its suggested `v=spf1 mx -all` and `MX 10 stalwart-0.` are wrong here too, so only its DKIM records were taken. SOA serial bumped. Note ns1 and ns2 both still served 2026073101 when this was written -- this branch has never been deployed. #dns #mail TESTED: Every zone in the directory parses -- the coredns role templates all five through one `with_fileglob`, so a syntax error here would take out the other four: ```sh # dnspython 2.8.0, dns.zone.from_file(check_origin=True) noisebridge.com PARSE OK names=2 rrsets=6 noisebridge.io PARSE OK names=26 rrsets=31 noisebridge.net PARSE OK names=75 rrsets=99 noisebridge.org PARSE OK names=2 rrsets=6 noisetor.net PARSE OK names=1 rrsets=4 ``` Shown to fail first: the same run against a copy with the SPF record's type replaced by `BOGUSTYPE` exits 1 with `unknown rdatatype`. Both DKIM records were compared, after zone parsing, against the key material the server holds -- concatenating each record's character-strings on both sides so the two representations are compared on one surface: ``` v1-ed25519-20260905: MATCH len=76 (server 76) v1-rsa-20260905: MATCH len=420 (server 420) selectors compared: 2 ``` Shown to fail first: flipping a single base64 character in a copy of the zone reports `MISMATCH` for that selector and exits 1. `postmaster` confirmed present in `group_vars/noisebridge_net/postfix.yml` (1 of 28 localparts), so the `rua` target delivers. `derive_plan.py` re-derives `roles=10 aliases=15 lists=3 TOTAL=28` from that file, and its vault audit decrypts and reports `1 of 10` role chains (`press` -> `root`, unprovisioned). NOT tested: no deploy, so no `dig` against ns1/ns2 yet, and no end-to-end send-as showing dkim/spf/dmarc=pass.
ElanHR
requested review from
Daniel-Alnasir,
Doty1154,
SuperQ,
danthedaniel,
lxpk,
mcint and
nthmost
September 8, 2026 20:47
danthedaniel
approved these changes
Sep 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
mail.noisegarden.nexuswhich aims to be a fallback email server for{secretary,treasurer}@noisebridge.netas the current mailbox has apparently been having trouble (dropping emails).Moves
{library,parts,stuff,matrix}.noisebridge.{net,io}to NoisegardenRemoves a typo (
m5.noiesbridge.net)