docs/dns: Add live record reference
Generate forward and reverse record tables from authoritative AXFRs while preserving handwritten Markdown outside per-zone markers. Run the generator in CI and link the reference from the relevant docs.
This commit is contained in:
@@ -6,7 +6,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
update:
|
update:
|
||||||
if: "!contains(github.event.head_commit.message, 'docs: update generated tables')"
|
if: "!contains(github.event.head_commit.message, 'docs: Update generated references')"
|
||||||
runs-on: ubuntu-26.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -26,6 +26,16 @@ jobs:
|
|||||||
- name: Update option reference
|
- name: Update option reference
|
||||||
run: nix run .#update-docs-options
|
run: nix run .#update-docs-options
|
||||||
|
|
||||||
|
- name: Update DNS reference
|
||||||
|
run: >
|
||||||
|
nix run .#update-docs-dns --
|
||||||
|
ams1.int.nul.ie
|
||||||
|
100.10.in-addr.arpa
|
||||||
|
2.d.4.0.0.c.7.9.e.0.a.2.ip6.arpa
|
||||||
|
h.nul.ie
|
||||||
|
168.192.in-addr.arpa
|
||||||
|
0.d.4.0.0.c.7.9.e.0.a.2.ip6.arpa
|
||||||
|
|
||||||
- name: Commit and push if changed
|
- name: Commit and push if changed
|
||||||
env:
|
env:
|
||||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
@@ -36,6 +46,6 @@ jobs:
|
|||||||
git remote set-url origin "${REPO_URL/https:\/\//https:\/\/oauth2:${GITEA_TOKEN}@}"
|
git remote set-url origin "${REPO_URL/https:\/\//https:\/\/oauth2:${GITEA_TOKEN}@}"
|
||||||
git add docs/
|
git add docs/
|
||||||
if ! git diff --cached --quiet; then
|
if ! git diff --cached --quiet; then
|
||||||
git commit -m "docs: update generated tables"
|
git commit -m "docs: Update generated references"
|
||||||
git push
|
git push
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -66,8 +66,8 @@ Use the narrowest relevant evaluation while iterating: `check-system <host>` for
|
|||||||
`nix flake check --no-build` for final broad validation or reproducing CI.
|
`nix flake check --no-build` for final broad validation or reproducing CI.
|
||||||
CI builds each attr of `.#ci.x86_64-linux` (systems, homes, packages, shell) and pushes to the
|
CI builds each attr of `.#ci.x86_64-linux` (systems, homes, packages, shell) and pushes to the
|
||||||
Harmonia binary cache; see `.gitea/workflows/ci.yaml` and `ci/push-to-cache.sh`. A separate
|
Harmonia binary cache; see `.gitea/workflows/ci.yaml` and `ci/push-to-cache.sh`. A separate
|
||||||
workflow (`.gitea/workflows/update-docs.yaml`) regenerates the network-assignment tables and NixOS
|
workflow (`.gitea/workflows/update-docs.yaml`) regenerates the network assignments, NixOS option
|
||||||
option reference via `nix run .#update-docs-{assignments,options}`.
|
reference and live DNS reference under `docs/`.
|
||||||
|
|
||||||
For DNS lookups use **`drill`** (ldns) — `dig` isn't installed in this environment (it fails with
|
For DNS lookups use **`drill`** (ldns) — `dig` isn't installed in this environment (it fails with
|
||||||
exit 127, which is easy to miss if stderr is redirected). E.g. `drill -Q @<resolver> <name> A`.
|
exit 127, which is easy to miss if stderr is redirected). E.g. `drill -Q @<resolver> <name> A`.
|
||||||
@@ -249,10 +249,12 @@ gets the section with a short explanation instead of a generated-table link.
|
|||||||
Addresses outside that data model (such as external peers or service endpoints) stay with the
|
Addresses outside that data model (such as external peers or service endpoints) stay with the
|
||||||
topic that owns them.
|
topic that owns them.
|
||||||
|
|
||||||
**Generated content:** the network-assignment tables in `networking.md` and the option reference
|
**Generated content:** the network-assignment tables in `networking.md`, the option reference
|
||||||
(`docs/reference/nixos-options.md`) are CI-generated (`nix run .#update-docs-{assignments,options}`)
|
(`docs/reference/nixos-options.md`) and the live DNS tables (`docs/reference/dns.md`) are
|
||||||
— don't hand-edit between the `<!-- ... -->` markers; write the prose and let the updater refresh
|
CI-generated by the corresponding `update-docs-*` packages; the workflow supplies the DNS zones.
|
||||||
the tables.
|
Don't hand-edit content between `<!-- ... -->` markers; write the surrounding prose or source
|
||||||
|
configuration and let the updater refresh the tables. The option-reference file is generated in
|
||||||
|
full.
|
||||||
|
|
||||||
**Keep docs current:** when you add, remove or repurpose a box or service, update its box page, the
|
**Keep docs current:** when you add, remove or repurpose a box or service, update its box page, the
|
||||||
relevant site-index `README.md`, and any affected prose in `networking.md` (the assignment/option
|
relevant site-index `README.md`, and any affected prose in `networking.md` (the assignment/option
|
||||||
|
|||||||
@@ -0,0 +1,347 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Render docs/reference/dns.md from live authoritative DNS zone transfers.
|
||||||
|
|
||||||
|
The authoritative servers are queried directly over AXFR. Records owned by Kea are
|
||||||
|
identified by DHCID records and omitted together with their forward and reverse data.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import ipaddress
|
||||||
|
import re
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import dns.exception
|
||||||
|
import dns.name
|
||||||
|
import dns.query
|
||||||
|
import dns.resolver
|
||||||
|
import dns.rdatatype
|
||||||
|
|
||||||
|
|
||||||
|
OUT = Path("docs/reference/dns.md")
|
||||||
|
DEFAULT_PORT = 53
|
||||||
|
IGNORED_TYPES = {"DHCID", "SOA"}
|
||||||
|
POWERDNS_ALIAS = 65401
|
||||||
|
POWERDNS_LUA = 65402
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class Record:
|
||||||
|
zone: str
|
||||||
|
owner: str
|
||||||
|
type: str
|
||||||
|
value: str
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_name(name: str) -> str:
|
||||||
|
return name.rstrip(".").lower()
|
||||||
|
|
||||||
|
|
||||||
|
def record_data(rdtype: int, rdata) -> tuple[str, str]:
|
||||||
|
if rdtype == POWERDNS_ALIAS:
|
||||||
|
target, _used = dns.name.from_wire(rdata.data, 0)
|
||||||
|
return "ALIAS", target.to_text()
|
||||||
|
if rdtype == POWERDNS_LUA:
|
||||||
|
logical_type = int.from_bytes(rdata.data[:2], byteorder="big")
|
||||||
|
return "LUA", dns.rdatatype.to_text(logical_type)
|
||||||
|
return dns.rdatatype.to_text(rdtype), rdata.to_text()
|
||||||
|
|
||||||
|
|
||||||
|
def server_addresses(server: str, port: int) -> list[str]:
|
||||||
|
addresses = []
|
||||||
|
try:
|
||||||
|
for result in socket.getaddrinfo(server, port, type=socket.SOCK_STREAM):
|
||||||
|
address = result[4][0]
|
||||||
|
if address not in addresses:
|
||||||
|
addresses.append(address)
|
||||||
|
except socket.gaierror as error:
|
||||||
|
raise RuntimeError(f"cannot resolve nameserver {server}: {error}") from error
|
||||||
|
return addresses
|
||||||
|
|
||||||
|
|
||||||
|
def transfer(server: str, port: int, zone: str) -> list[Record]:
|
||||||
|
addresses = server_addresses(server, port)
|
||||||
|
|
||||||
|
errors = []
|
||||||
|
for address in addresses:
|
||||||
|
try:
|
||||||
|
records = []
|
||||||
|
for message in dns.query.xfr(
|
||||||
|
address, zone, port=port, lifetime=60, relativize=False
|
||||||
|
):
|
||||||
|
for rrset in message.answer:
|
||||||
|
for rdata in rrset:
|
||||||
|
record_type, value = record_data(rrset.rdtype, rdata)
|
||||||
|
records.append(
|
||||||
|
Record(
|
||||||
|
zone=normalize_name(zone),
|
||||||
|
owner=normalize_name(rrset.name.to_text()),
|
||||||
|
type=record_type,
|
||||||
|
value=value,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if not any(record.type == "SOA" for record in records):
|
||||||
|
raise RuntimeError("transfer returned no SOA record")
|
||||||
|
return records
|
||||||
|
except (dns.exception.DNSException, OSError, RuntimeError) as error:
|
||||||
|
errors.append(f"{address}: {error}")
|
||||||
|
raise RuntimeError(f"AXFR of {zone} from {server} failed ({'; '.join(errors)})")
|
||||||
|
|
||||||
|
|
||||||
|
def system_nameservers(domain: str) -> list[str]:
|
||||||
|
try:
|
||||||
|
answer = dns.resolver.resolve(domain, "NS", lifetime=30)
|
||||||
|
except dns.exception.DNSException as error:
|
||||||
|
message = f"cannot discover authoritative servers for {domain}: {error}"
|
||||||
|
raise RuntimeError(message) from error
|
||||||
|
return [rdata.target.to_text() for rdata in answer]
|
||||||
|
|
||||||
|
|
||||||
|
def nameservers_via(server: str, port: int, domain: str) -> list[str]:
|
||||||
|
errors = []
|
||||||
|
for address in server_addresses(server, port):
|
||||||
|
resolver = dns.resolver.Resolver(configure=False)
|
||||||
|
resolver.nameservers = [address]
|
||||||
|
resolver.port = port
|
||||||
|
try:
|
||||||
|
answer = resolver.resolve(domain, "NS", lifetime=15, search=False)
|
||||||
|
return [rdata.target.to_text() for rdata in answer]
|
||||||
|
except dns.exception.DNSException as error:
|
||||||
|
errors.append(f"{address}: {error}")
|
||||||
|
raise RuntimeError(f"NS query for {domain} via {server} failed ({'; '.join(errors)})")
|
||||||
|
|
||||||
|
|
||||||
|
def discover_nameservers(domains: list[str], port: int) -> dict[str, list[str]]:
|
||||||
|
discovered = {}
|
||||||
|
unresolved = {}
|
||||||
|
candidates = []
|
||||||
|
for domain in domains:
|
||||||
|
try:
|
||||||
|
servers = system_nameservers(domain)
|
||||||
|
discovered[domain] = servers
|
||||||
|
for server in servers:
|
||||||
|
if server not in candidates:
|
||||||
|
candidates.append(server)
|
||||||
|
except RuntimeError as error:
|
||||||
|
unresolved[domain] = [str(error)]
|
||||||
|
|
||||||
|
for domain, errors in list(unresolved.items()):
|
||||||
|
for server in candidates:
|
||||||
|
try:
|
||||||
|
discovered[domain] = nameservers_via(server, port, domain)
|
||||||
|
del unresolved[domain]
|
||||||
|
break
|
||||||
|
except RuntimeError as error:
|
||||||
|
errors.append(str(error))
|
||||||
|
|
||||||
|
if unresolved:
|
||||||
|
details = "; ".join(
|
||||||
|
f"{domain}: {'; '.join(errors)}" for domain, errors in unresolved.items()
|
||||||
|
)
|
||||||
|
raise RuntimeError(details)
|
||||||
|
return discovered
|
||||||
|
|
||||||
|
|
||||||
|
def transfer_domain(port: int, domain: str, servers: list[str]) -> list[Record]:
|
||||||
|
errors = []
|
||||||
|
for server in servers:
|
||||||
|
try:
|
||||||
|
return transfer(server, port, domain)
|
||||||
|
except RuntimeError as error:
|
||||||
|
errors.append(str(error))
|
||||||
|
raise RuntimeError(f"no authoritative server allowed AXFR for {domain} ({'; '.join(errors)})")
|
||||||
|
|
||||||
|
|
||||||
|
def dynamic_names(records: list[Record]) -> set[str]:
|
||||||
|
return {record.owner for record in records if record.type == "DHCID"}
|
||||||
|
|
||||||
|
|
||||||
|
def dynamic_addresses(records: list[Record], names: set[str]) -> set[str]:
|
||||||
|
return {
|
||||||
|
record.value.rstrip(".").lower()
|
||||||
|
for record in records
|
||||||
|
if record.owner in names and record.type in {"A", "AAAA"}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def reverse_address(owner: str) -> str | None:
|
||||||
|
if owner.endswith(".in-addr.arpa"):
|
||||||
|
labels = owner.removesuffix(".in-addr.arpa").split(".")
|
||||||
|
if len(labels) != 4:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return str(ipaddress.IPv4Address(".".join(reversed(labels))))
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if owner.endswith(".ip6.arpa"):
|
||||||
|
labels = owner.removesuffix(".ip6.arpa").split(".")
|
||||||
|
if len(labels) != 32:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
value = int("".join(reversed(labels)), 16)
|
||||||
|
return str(ipaddress.IPv6Address(value))
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def static_records(records: list[Record]) -> list[Record]:
|
||||||
|
names = dynamic_names(records)
|
||||||
|
addresses = dynamic_addresses(records, names)
|
||||||
|
static = []
|
||||||
|
for record in records:
|
||||||
|
if record.type in IGNORED_TYPES or record.owner in names:
|
||||||
|
continue
|
||||||
|
if record.type == "PTR":
|
||||||
|
target = normalize_name(record.value.split()[0])
|
||||||
|
address = reverse_address(record.owner)
|
||||||
|
if target in names or address in addresses:
|
||||||
|
continue
|
||||||
|
static.append(record)
|
||||||
|
return static
|
||||||
|
|
||||||
|
|
||||||
|
def relative_name(owner: str, zone: str) -> str:
|
||||||
|
if owner == zone:
|
||||||
|
return "@"
|
||||||
|
suffix = f".{zone}"
|
||||||
|
return owner[: -len(suffix)] if owner.endswith(suffix) else owner
|
||||||
|
|
||||||
|
|
||||||
|
def markdown_code(value: str) -> str:
|
||||||
|
escaped = value.replace("|", "\\|")
|
||||||
|
return f"`{escaped}`"
|
||||||
|
|
||||||
|
|
||||||
|
def display_record(record: Record) -> tuple[str, str]:
|
||||||
|
if record.type != "LUA":
|
||||||
|
return record.type, record.value
|
||||||
|
return f"{record.value} (LUA)", "generated at query time"
|
||||||
|
|
||||||
|
|
||||||
|
def render_forward(domain: str, records: list[Record]) -> list[str]:
|
||||||
|
domain = normalize_name(domain)
|
||||||
|
rows = []
|
||||||
|
for record in records:
|
||||||
|
if record.zone != domain or record.type == "PTR":
|
||||||
|
continue
|
||||||
|
record_type, value = display_record(record)
|
||||||
|
rows.append((relative_name(record.owner, record.zone), record_type, value))
|
||||||
|
rows.sort(key=lambda row: (row[0] != "@", row[0], row[1], row[2]))
|
||||||
|
|
||||||
|
lines = ["| Name | Type | Value |", "|---|---|---|"]
|
||||||
|
lines.extend(
|
||||||
|
f"| {markdown_code(name)} | {markdown_code(record_type)} | {markdown_code(value)} |"
|
||||||
|
for name, record_type, value in rows
|
||||||
|
)
|
||||||
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
def render_reverse(domain: str, records: list[Record]) -> list[str]:
|
||||||
|
domain = normalize_name(domain)
|
||||||
|
rows = []
|
||||||
|
for record in records:
|
||||||
|
if record.zone != domain or record.type != "PTR":
|
||||||
|
continue
|
||||||
|
rows.append((reverse_address(record.owner) or record.owner, record.value))
|
||||||
|
rows.sort(key=lambda row: ipaddress.ip_address(row[0]))
|
||||||
|
|
||||||
|
lines = ["| Address | Name |", "|---|---|"]
|
||||||
|
lines.extend(
|
||||||
|
f"| {markdown_code(address)} | {markdown_code(name)} |" for address, name in rows
|
||||||
|
)
|
||||||
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
def is_reverse(domain: str) -> bool:
|
||||||
|
domain = normalize_name(domain)
|
||||||
|
return domain.endswith(".in-addr.arpa") or domain.endswith(".ip6.arpa")
|
||||||
|
|
||||||
|
|
||||||
|
def rendered_zones(transferred: list[tuple[str, list[Record]]]) -> dict[str, list[str]]:
|
||||||
|
records = static_records([record for _domain, zone in transferred for record in zone])
|
||||||
|
rendered = {}
|
||||||
|
for domain, _raw_records in transferred:
|
||||||
|
if is_reverse(domain):
|
||||||
|
rendered[normalize_name(domain)] = render_reverse(domain, records)
|
||||||
|
else:
|
||||||
|
rendered[normalize_name(domain)] = render_forward(domain, records)
|
||||||
|
return rendered
|
||||||
|
|
||||||
|
|
||||||
|
def update_target(transferred: list[tuple[str, list[Record]]], target: Path) -> bool:
|
||||||
|
rendered = rendered_zones(transferred)
|
||||||
|
text = target.read_text()
|
||||||
|
lines = text.splitlines()
|
||||||
|
marker_re = re.compile(r"^<!--\s*dns:\s*(\S+)\s*-->$")
|
||||||
|
found = set()
|
||||||
|
output = []
|
||||||
|
i = 0
|
||||||
|
while i < len(lines):
|
||||||
|
match = marker_re.match(lines[i].strip())
|
||||||
|
if not match or normalize_name(match.group(1)) not in rendered:
|
||||||
|
output.append(lines[i])
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
domain = normalize_name(match.group(1))
|
||||||
|
end = i + 1
|
||||||
|
while end < len(lines) and lines[end].strip() != "<!-- dns-end -->":
|
||||||
|
end += 1
|
||||||
|
if end >= len(lines):
|
||||||
|
raise RuntimeError(f"missing <!-- dns-end --> for {domain}")
|
||||||
|
|
||||||
|
output.extend(
|
||||||
|
[
|
||||||
|
lines[i],
|
||||||
|
"<!-- dns-start -->",
|
||||||
|
*rendered[domain],
|
||||||
|
"<!-- dns-end -->",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
found.add(domain)
|
||||||
|
i = end + 1
|
||||||
|
|
||||||
|
missing = rendered.keys() - found
|
||||||
|
if missing:
|
||||||
|
raise RuntimeError(f"missing DNS markers for: {', '.join(sorted(missing))}")
|
||||||
|
|
||||||
|
new = "\n".join(output) + "\n"
|
||||||
|
if new == text:
|
||||||
|
return False
|
||||||
|
target.write_text(new)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
parser = argparse.ArgumentParser(prog="update-docs-dns", description=__doc__)
|
||||||
|
parser.add_argument("domain", nargs="+", help="DNS zone to transfer")
|
||||||
|
parser.add_argument("--port", type=int, default=DEFAULT_PORT)
|
||||||
|
parser.add_argument("--output", type=Path, default=OUT)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
nameservers = discover_nameservers(args.domain, args.port)
|
||||||
|
transferred = [
|
||||||
|
(domain, transfer_domain(args.port, domain, nameservers[domain]))
|
||||||
|
for domain in args.domain
|
||||||
|
]
|
||||||
|
except RuntimeError as error:
|
||||||
|
print(f"update-docs-dns: {error}", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
try:
|
||||||
|
changed = update_target(transferred, args.output)
|
||||||
|
except (OSError, RuntimeError) as error:
|
||||||
|
print(f"update-docs-dns: {error}", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
if changed:
|
||||||
|
print(f"updated {args.output}")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
@@ -25,6 +25,7 @@ Not every box fits this pattern, but **colony** and **home** are organised this
|
|||||||
- [`networking.md`](networking.md) — network assignments, domains, site topologies, router HA,
|
- [`networking.md`](networking.md) — network assignments, domains, site topologies, router HA,
|
||||||
the AS211024 L2 mesh, BGP, WireGuard, Tailscale.
|
the AS211024 L2 mesh, BGP, WireGuard, Tailscale.
|
||||||
- [`deployment.md`](deployment.md) — deploy-rs, devshell commands, secrets workflow, CI.
|
- [`deployment.md`](deployment.md) — deploy-rs, devshell commands, secrets workflow, CI.
|
||||||
|
- [`reference/dns.md`](reference/dns.md) — generated forward and reverse DNS record reference.
|
||||||
- [`reference/nixos-options.md`](reference/nixos-options.md) — generated per-option reference for
|
- [`reference/nixos-options.md`](reference/nixos-options.md) — generated per-option reference for
|
||||||
the custom `my.*` NixOS modules.
|
the custom `my.*` NixOS modules.
|
||||||
|
|
||||||
|
|||||||
+12
-5
@@ -170,14 +170,13 @@ Pushing the `installer` tag (refreshed by `update-installer`) builds `my.buildAs
|
|||||||
|
|
||||||
### `update-docs.yaml`
|
### `update-docs.yaml`
|
||||||
|
|
||||||
On pushes to the docs branch, excluding its own commits, this runs
|
On pushes to `master`, excluding its own commits, this runs the assignment, option and DNS
|
||||||
`nix run .#update-docs-assignments` and `nix run .#update-docs-options` and commits changed outputs
|
reference generators and commits changed outputs as `docs: Update generated references`.
|
||||||
as `docs: update generated tables`.
|
|
||||||
|
|
||||||
### The docs generators
|
### The docs generators
|
||||||
|
|
||||||
Both are registered in [`pkgs/default.nix`](../pkgs/default.nix) (`writeShellScriptBin`s wrapping
|
The generators are registered in [`pkgs/default.nix`](../pkgs/default.nix) as wrappers around
|
||||||
Python scripts under [`ci/`](../ci)). They leave the worktree unchanged when their output is current;
|
Python scripts under [`ci/`](../ci). They leave the worktree unchanged when their output is current;
|
||||||
the workflow stages `docs/` and uses `git diff --cached --quiet` to decide whether to commit.
|
the workflow stages `docs/` and uses `git diff --cached --quiet` to decide whether to commit.
|
||||||
|
|
||||||
`update-docs-assignments` ([`ci/update-docs-assignments.py`](../ci/update-docs-assignments.py))
|
`update-docs-assignments` ([`ci/update-docs-assignments.py`](../ci/update-docs-assignments.py))
|
||||||
@@ -197,3 +196,11 @@ apply to every box, so defaults don't pick up a real host's values. The renderer
|
|||||||
[`docs/reference/nixos-options.md`](reference/nixos-options.md), one table per module file. The
|
[`docs/reference/nixos-options.md`](reference/nixos-options.md), one table per module file. The
|
||||||
whole file is generated; edit the option descriptions in the modules, not the reference. The
|
whole file is generated; edit the option descriptions in the modules, not the reference. The
|
||||||
internal `asX` build-target options are marked `internal = true` so they're excluded.
|
internal `asX` build-target options are marked `internal = true` so they're excluded.
|
||||||
|
|
||||||
|
`update-docs-dns` ([`ci/update-docs-dns.py`](../ci/update-docs-dns.py)) accepts forward and reverse
|
||||||
|
zone names, discovers their authoritative nameservers through NS queries, and transfers each zone
|
||||||
|
over AXFR. If a private reverse zone is not visible through the configured recursive resolver, it
|
||||||
|
asks the authoritative servers discovered for the other requested zones. It updates only the
|
||||||
|
matching `<!-- dns: <zone> -->` blocks in the [`DNS records`](reference/dns.md) reference; the page's
|
||||||
|
headings and prose remain handwritten. Kea-managed owners are identified by `DHCID` records and
|
||||||
|
removed together with their A, AAAA and PTR records; SOA records and TTLs are also omitted.
|
||||||
|
|||||||
+3
-1
@@ -327,7 +327,9 @@ and keepalived's `notify_master`/`notify_backup` hooks ensure that only the mast
|
|||||||
[`routing-common/dns.nix`](../nixos/boxes/home/routing-common/dns.nix). The
|
[`routing-common/dns.nix`](../nixos/boxes/home/routing-common/dns.nix). The
|
||||||
`net.ipv4.ip_nonlocal_bind` / `net.ipv6.ip_nonlocal_bind` settings let the backup listen before it
|
`net.ipv4.ip_nonlocal_bind` / `net.ipv6.ip_nonlocal_bind` settings let the backup listen before it
|
||||||
owns the addresses, so failover does not depend on client resolver timeouts. The recursor forwards
|
owns the addresses, so failover does not depend on client resolver timeouts. The recursor forwards
|
||||||
the site's zones to authoritative PowerDNS on `127.0.0.1:5353`.
|
the site's zones to authoritative PowerDNS on `127.0.0.1:5353`. The generated
|
||||||
|
[DNS reference](reference/dns.md) lists the live forward and reverse records; the authoritative
|
||||||
|
servers allow its AXFRs from the shared internal prefixes and the colony site's egress address.
|
||||||
|
|
||||||
#### `wan-online.target`
|
#### `wan-online.target`
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,319 @@
|
|||||||
|
# DNS records
|
||||||
|
|
||||||
|
The tables on this page are generated from live authoritative zone transfers by
|
||||||
|
`nix run .#update-docs-dns -- <zones...>`; CI keeps them current. The Nix DNS configuration is
|
||||||
|
the source of truth. Edit the prose and headings here, but not content between the DNS markers.
|
||||||
|
|
||||||
|
DHCP-managed records are excluded. The generator identifies them by `DHCID` and removes the
|
||||||
|
corresponding forward and reverse records. SOA records and TTLs are also omitted because they are
|
||||||
|
operational metadata rather than useful inventory.
|
||||||
|
|
||||||
|
## Colony
|
||||||
|
|
||||||
|
These zones are served by [`estuary`](../sites/colony/estuary.md); their source configuration is
|
||||||
|
[`estuary/dns.nix`](../../nixos/boxes/colony/vms/estuary/dns.nix).
|
||||||
|
|
||||||
|
### Forward zone: `ams1.int.nul.ie`
|
||||||
|
|
||||||
|
<!-- dns: ams1.int.nul.ie -->
|
||||||
|
<!-- dns-start -->
|
||||||
|
| Name | Type | Value |
|
||||||
|
|---|---|---|
|
||||||
|
| `@` | `ALIAS` | `estuary-vm.ams1.int.nul.ie.` |
|
||||||
|
| `@` | `NS` | `ns.ams1.int.nul.ie.` |
|
||||||
|
| `_acme-challenge` | `TXT (LUA)` | `generated at query time` |
|
||||||
|
| `andrey-cust` | `A` | `94.142.242.254` |
|
||||||
|
| `chatterbox-ctr` | `A` | `10.100.2.5` |
|
||||||
|
| `chatterbox-ctr` | `AAAA` | `2a0e:97c0:4d2:12::5` |
|
||||||
|
| `colony` | `A` | `94.142.241.224` |
|
||||||
|
| `colony` | `AAAA` | `2a0e:97c0:4d2:10::2` |
|
||||||
|
| `colony-psql` | `CNAME` | `colony-psql-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `colony-psql-ctr` | `A` | `10.100.2.4` |
|
||||||
|
| `colony-psql-ctr` | `AAAA` | `2a0e:97c0:4d2:12::4` |
|
||||||
|
| `colony-routing` | `A` | `10.100.0.2` |
|
||||||
|
| `colony-vms` | `A` | `10.100.1.1` |
|
||||||
|
| `colony-vms` | `AAAA` | `2a0e:97c0:4d2:11::1` |
|
||||||
|
| `ctr` | `CNAME` | `shill-vm.ams1.int.nul.ie.` |
|
||||||
|
| `darts-cust` | `A` | `94.142.242.255` |
|
||||||
|
| `darts-cust` | `AAAA` | `2a0e:97c0:4d2:2001::1` |
|
||||||
|
| `enshrouded` | `A` | `94.142.240.44` |
|
||||||
|
| `enshrouded-oci` | `A` | `10.100.3.5` |
|
||||||
|
| `enshrouded-oci` | `AAAA` | `2a0e:97c0:4d2:13::5` |
|
||||||
|
| `estuary-vm` | `A` | `94.142.240.44` |
|
||||||
|
| `estuary-vm` | `AAAA` | `2a02:898:0:20::329:1` |
|
||||||
|
| `estuary-vm-base` | `A` | `10.100.0.1` |
|
||||||
|
| `estuary-vm-base` | `AAAA` | `2a0e:97c0:4d2:10::1` |
|
||||||
|
| `fw` | `CNAME` | `estuary-vm.ams1.int.nul.ie.` |
|
||||||
|
| `gam-ctr` | `A` | `10.100.2.11` |
|
||||||
|
| `gam-ctr` | `AAAA` | `2a0e:97c0:4d2:12::b` |
|
||||||
|
| `git-vm` | `A` | `94.142.241.117` |
|
||||||
|
| `git-vm` | `AAAA` | `2a0e:97c0:4d2:11::4` |
|
||||||
|
| `git-vm-routing` | `A` | `10.100.1.4` |
|
||||||
|
| `graeme` | `A` | `94.142.240.44` |
|
||||||
|
| `graeme` | `AAAA` | `2a0e:97c0:4d2:13::8` |
|
||||||
|
| `graeme-oci` | `A` | `10.100.3.8` |
|
||||||
|
| `graeme-oci` | `AAAA` | `2a0e:97c0:4d2:13::8` |
|
||||||
|
| `hillcrest-tun` | `A` | `10.100.5.2` |
|
||||||
|
| `http` | `A` | `94.142.240.44` |
|
||||||
|
| `http` | `AAAA` | `2a0e:97c0:4d2:12::2` |
|
||||||
|
| `jackflix-ctr` | `A` | `10.100.2.6` |
|
||||||
|
| `jackflix-ctr` | `AAAA` | `2a0e:97c0:4d2:12::6` |
|
||||||
|
| `jam-cust` | `A` | `10.100.100.4` |
|
||||||
|
| `jam-cust` | `AAAA` | `2a0e:97c0:4d2:2002::1` |
|
||||||
|
| `jam-fwd` | `A` | `94.142.241.225` |
|
||||||
|
| `john-valorant-tun` | `A` | `10.100.5.6` |
|
||||||
|
| `kevcraft` | `A` | `94.142.240.44` |
|
||||||
|
| `kevcraft` | `AAAA` | `2a0e:97c0:4d2:13::6` |
|
||||||
|
| `kevcraft-oci` | `A` | `10.100.3.6` |
|
||||||
|
| `kevcraft-oci` | `AAAA` | `2a0e:97c0:4d2:13::6` |
|
||||||
|
| `kinkcraft` | `A` | `94.142.240.44` |
|
||||||
|
| `kinkcraft` | `AAAA` | `2a0e:97c0:4d2:13::7` |
|
||||||
|
| `kinkcraft-oci` | `A` | `10.100.3.7` |
|
||||||
|
| `kinkcraft-oci` | `AAAA` | `2a0e:97c0:4d2:13::7` |
|
||||||
|
| `librespeed` | `CNAME` | `http.ams1.int.nul.ie.` |
|
||||||
|
| `mail-vm` | `A` | `94.142.241.227` |
|
||||||
|
| `mail-vm` | `AAAA` | `2a0e:97c0:4d2:2000::1` |
|
||||||
|
| `middleman-ctr` | `A` | `10.100.2.2` |
|
||||||
|
| `middleman-ctr` | `AAAA` | `2a0e:97c0:4d2:12::2` |
|
||||||
|
| `ns` | `ALIAS` | `estuary-vm.ams1.int.nul.ie.` |
|
||||||
|
| `object-ctr` | `A` | `10.100.2.7` |
|
||||||
|
| `object-ctr` | `AAAA` | `2a0e:97c0:4d2:12::7` |
|
||||||
|
| `oci` | `CNAME` | `whale-vm.ams1.int.nul.ie.` |
|
||||||
|
| `qclk-ctr` | `A` | `10.100.2.10` |
|
||||||
|
| `qclk-ctr` | `AAAA` | `2a0e:97c0:4d2:12::a` |
|
||||||
|
| `shill-vm` | `A` | `94.142.241.225` |
|
||||||
|
| `shill-vm` | `AAAA` | `2a0e:97c0:4d2:11::2` |
|
||||||
|
| `shill-vm-ctrs` | `A` | `10.100.2.1` |
|
||||||
|
| `shill-vm-ctrs` | `AAAA` | `2a0e:97c0:4d2:12::1` |
|
||||||
|
| `shill-vm-routing` | `A` | `10.100.1.2` |
|
||||||
|
| `simpcraft` | `A` | `94.142.240.44` |
|
||||||
|
| `simpcraft` | `AAAA` | `2a0e:97c0:4d2:13::3` |
|
||||||
|
| `simpcraft-oci` | `A` | `10.100.3.3` |
|
||||||
|
| `simpcraft-oci` | `AAAA` | `2a0e:97c0:4d2:13::3` |
|
||||||
|
| `simpcraft-staging` | `A` | `94.142.240.44` |
|
||||||
|
| `simpcraft-staging` | `AAAA` | `2a0e:97c0:4d2:13::4` |
|
||||||
|
| `simpcraft-staging-oci` | `A` | `10.100.3.4` |
|
||||||
|
| `simpcraft-staging-oci` | `AAAA` | `2a0e:97c0:4d2:13::4` |
|
||||||
|
| `terraria` | `A` | `94.142.240.44` |
|
||||||
|
| `terraria` | `AAAA` | `2a0e:97c0:4d2:12::b` |
|
||||||
|
| `toot-ctr` | `A` | `10.100.2.8` |
|
||||||
|
| `toot-ctr` | `AAAA` | `2a0e:97c0:4d2:12::8` |
|
||||||
|
| `valheim` | `A` | `94.142.240.44` |
|
||||||
|
| `valheim` | `AAAA` | `2a0e:97c0:4d2:13::2` |
|
||||||
|
| `valheim-oci` | `A` | `10.100.3.2` |
|
||||||
|
| `valheim-oci` | `AAAA` | `2a0e:97c0:4d2:13::2` |
|
||||||
|
| `vaultwarden-ctr` | `A` | `10.100.2.3` |
|
||||||
|
| `vaultwarden-ctr` | `AAAA` | `2a0e:97c0:4d2:12::3` |
|
||||||
|
| `vm` | `CNAME` | `colony.ams1.int.nul.ie.` |
|
||||||
|
| `waffletail-ctr` | `A` | `10.100.2.9` |
|
||||||
|
| `waffletail-ctr` | `AAAA` | `2a0e:97c0:4d2:12::9` |
|
||||||
|
| `whale-vm` | `A` | `94.142.241.226` |
|
||||||
|
| `whale-vm` | `AAAA` | `2a0e:97c0:4d2:11::3` |
|
||||||
|
| `whale-vm-routing` | `A` | `10.100.1.3` |
|
||||||
|
<!-- dns-end -->
|
||||||
|
|
||||||
|
### IPv4 reverse zone: `100.10.in-addr.arpa`
|
||||||
|
|
||||||
|
<!-- dns: 100.10.in-addr.arpa -->
|
||||||
|
<!-- dns-start -->
|
||||||
|
| Address | Name |
|
||||||
|
|---|---|
|
||||||
|
| `10.100.0.1` | `estuary-vm-base.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.0.2` | `colony-routing.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.1.1` | `colony-vms.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.1.2` | `shill-vm-routing.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.1.3` | `whale-vm-routing.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.1.4` | `git-vm-routing.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.2.1` | `shill-vm-ctrs.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.2.2` | `middleman-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.2.3` | `vaultwarden-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.2.4` | `colony-psql-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.2.5` | `chatterbox-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.2.6` | `jackflix-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.2.7` | `object-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.2.8` | `toot-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.2.9` | `waffletail-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.2.10` | `qclk-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.2.11` | `gam-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.3.2` | `valheim-oci.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.3.3` | `simpcraft-oci.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.3.4` | `simpcraft-staging-oci.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.3.5` | `enshrouded-oci.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.3.6` | `kevcraft-oci.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.3.7` | `kinkcraft-oci.ams1.int.nul.ie.` |
|
||||||
|
| `10.100.3.8` | `graeme-oci.ams1.int.nul.ie.` |
|
||||||
|
<!-- dns-end -->
|
||||||
|
|
||||||
|
### IPv6 reverse zone: `2.d.4.0.0.c.7.9.e.0.a.2.ip6.arpa`
|
||||||
|
|
||||||
|
<!-- dns: 2.d.4.0.0.c.7.9.e.0.a.2.ip6.arpa -->
|
||||||
|
<!-- dns-start -->
|
||||||
|
| Address | Name |
|
||||||
|
|---|---|
|
||||||
|
| `2a0e:97c0:4d2:10::1` | `estuary-vm-base.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:10::2` | `colony.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:11::1` | `colony-vms.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:11::2` | `shill-vm.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:11::3` | `whale-vm.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:11::4` | `git-vm.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:12::1` | `shill-vm-ctrs.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:12::2` | `middleman-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:12::3` | `vaultwarden-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:12::4` | `colony-psql-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:12::5` | `chatterbox-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:12::6` | `jackflix-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:12::7` | `object-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:12::8` | `toot-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:12::9` | `waffletail-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:12::a` | `qclk-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:12::b` | `gam-ctr.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:13::2` | `valheim-oci.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:13::3` | `simpcraft-oci.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:13::4` | `simpcraft-staging-oci.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:13::5` | `enshrouded-oci.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:13::6` | `kevcraft-oci.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:13::7` | `kinkcraft-oci.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:13::8` | `graeme-oci.ams1.int.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:2000::1` | `mail.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d2:2001::1` | `darts-cust.ams1.int.nul.ie.` |
|
||||||
|
<!-- dns-end -->
|
||||||
|
|
||||||
|
## Home
|
||||||
|
|
||||||
|
These zones are served by [`river`](../sites/home/river.md) and
|
||||||
|
[`stream`](../sites/home/stream.md); their shared source configuration is
|
||||||
|
[`routing-common/dns.nix`](../../nixos/boxes/home/routing-common/dns.nix).
|
||||||
|
|
||||||
|
### Forward zone: `h.nul.ie`
|
||||||
|
|
||||||
|
<!-- dns: h.nul.ie -->
|
||||||
|
<!-- dns-start -->
|
||||||
|
| Name | Type | Value |
|
||||||
|
|---|---|---|
|
||||||
|
| `@` | `NS` | `ns1.h.nul.ie.` |
|
||||||
|
| `@` | `NS` | `ns2.h.nul.ie.` |
|
||||||
|
| `boot` | `CNAME` | `river-hi.h.nul.ie.` |
|
||||||
|
| `brian` | `A` | `192.168.64.13` |
|
||||||
|
| `castle` | `A` | `192.168.68.40` |
|
||||||
|
| `castle` | `AAAA` | `2a0e:97c0:4d0:1::3:1` |
|
||||||
|
| `cellar` | `A` | `192.168.68.80` |
|
||||||
|
| `cellar` | `AAAA` | `2a0e:97c0:4d0:1::4:1` |
|
||||||
|
| `dave` | `A` | `192.168.68.11` |
|
||||||
|
| `dave` | `AAAA` | `2a0e:97c0:4d0:1::1:2` |
|
||||||
|
| `dave-core` | `A` | `192.168.64.11` |
|
||||||
|
| `dave-lo` | `A` | `192.168.72.11` |
|
||||||
|
| `dave-lo` | `AAAA` | `2a0e:97c0:4d0:2::1:2` |
|
||||||
|
| `dyn` | `NS` | `ns1.dyn.h.nul.ie.` |
|
||||||
|
| `dyn` | `NS` | `ns2.dyn.h.nul.ie.` |
|
||||||
|
| `frigate` | `CNAME` | `hass-ctr.h.nul.ie.` |
|
||||||
|
| `hass-ctr` | `A` | `192.168.68.103` |
|
||||||
|
| `hass-ctr` | `AAAA` | `2a0e:97c0:4d0:1::5:3` |
|
||||||
|
| `hass-ctr-lo` | `A` | `192.168.72.103` |
|
||||||
|
| `hass-ctr-lo` | `AAAA` | `2a0e:97c0:4d0:2::5:3` |
|
||||||
|
| `jim` | `A` | `192.168.68.10` |
|
||||||
|
| `jim` | `AAAA` | `2a0e:97c0:4d0:1::1:1` |
|
||||||
|
| `jim-core` | `A` | `192.168.64.10` |
|
||||||
|
| `jim-lo` | `A` | `192.168.72.10` |
|
||||||
|
| `jim-lo` | `AAAA` | `2a0e:97c0:4d0:2::1:1` |
|
||||||
|
| `nixlight` | `A` | `192.168.72.46` |
|
||||||
|
| `ns1` | `ALIAS` | `river.h.nul.ie.` |
|
||||||
|
| `ns1.dyn` | `ALIAS` | `river.h.nul.ie.` |
|
||||||
|
| `ns2` | `ALIAS` | `stream.h.nul.ie.` |
|
||||||
|
| `ns2.dyn` | `ALIAS` | `stream.h.nul.ie.` |
|
||||||
|
| `palace` | `A` | `192.168.68.22` |
|
||||||
|
| `palace` | `AAAA` | `2a0e:97c0:4d0:1::2:1` |
|
||||||
|
| `palace-core` | `A` | `192.168.64.20` |
|
||||||
|
| `palace-kvm` | `A` | `192.168.72.21` |
|
||||||
|
| `reolink-living-room` | `A` | `192.168.72.45` |
|
||||||
|
| `river` | `A (LUA)` | `generated at query time` |
|
||||||
|
| `river` | `AAAA` | `2a0e:97c0:4df:0:1::1` |
|
||||||
|
| `river-core` | `A` | `192.168.64.1` |
|
||||||
|
| `river-hi` | `A` | `192.168.68.1` |
|
||||||
|
| `river-hi` | `AAAA` | `2a0e:97c0:4d0:1::1` |
|
||||||
|
| `river-lo` | `A` | `192.168.72.1` |
|
||||||
|
| `river-lo` | `AAAA` | `2a0e:97c0:4d0:2::1` |
|
||||||
|
| `river-ut` | `A` | `192.168.80.1` |
|
||||||
|
| `river-ut` | `AAAA` | `2a0e:97c0:4d0:3::1` |
|
||||||
|
| `router-hi` | `A` | `192.168.71.254` |
|
||||||
|
| `router-hi` | `AAAA` | `2a0e:97c0:4d0:1::ffff` |
|
||||||
|
| `router-lo` | `A` | `192.168.79.254` |
|
||||||
|
| `router-lo` | `AAAA` | `2a0e:97c0:4d0:2::ffff` |
|
||||||
|
| `router-ut` | `A` | `192.168.80.254` |
|
||||||
|
| `router-ut` | `AAAA` | `2a0e:97c0:4d0:3::ffff` |
|
||||||
|
| `sfh` | `A` | `192.168.68.81` |
|
||||||
|
| `sfh` | `AAAA` | `2a0e:97c0:4d0:1::4:2` |
|
||||||
|
| `shytzel` | `A` | `192.168.64.12` |
|
||||||
|
| `stream` | `A (LUA)` | `generated at query time` |
|
||||||
|
| `stream` | `AAAA` | `2a0e:97c0:4df:0:1::2` |
|
||||||
|
| `stream-core` | `A` | `192.168.64.2` |
|
||||||
|
| `stream-hi` | `A` | `192.168.68.2` |
|
||||||
|
| `stream-hi` | `AAAA` | `2a0e:97c0:4d0:1::2` |
|
||||||
|
| `stream-lo` | `A` | `192.168.72.2` |
|
||||||
|
| `stream-lo` | `AAAA` | `2a0e:97c0:4d0:2::2` |
|
||||||
|
| `stream-ut` | `A` | `192.168.80.2` |
|
||||||
|
| `stream-ut` | `AAAA` | `2a0e:97c0:4d0:3::2` |
|
||||||
|
| `unifi-ctr` | `A` | `192.168.68.100` |
|
||||||
|
| `unifi-ctr` | `AAAA` | `2a0e:97c0:4d0:1::5:1` |
|
||||||
|
| `unifi-ctr-core` | `A` | `192.168.64.21` |
|
||||||
|
| `ups` | `A` | `192.168.72.20` |
|
||||||
|
| `vibe` | `A` | `192.168.68.15` |
|
||||||
|
| `vibe` | `AAAA` | `2a0e:97c0:4d0:1::1:6` |
|
||||||
|
| `vibe-core` | `A` | `192.168.64.15` |
|
||||||
|
| `vibe-lo` | `A` | `192.168.72.15` |
|
||||||
|
| `vibe-lo` | `AAAA` | `2a0e:97c0:4d0:2::1:6` |
|
||||||
|
| `wave` | `A` | `192.168.72.14` |
|
||||||
|
| `wave` | `AAAA` | `2a0e:97c0:4d0:2::1:5` |
|
||||||
|
| `wave-core` | `A` | `192.168.64.14` |
|
||||||
|
<!-- dns-end -->
|
||||||
|
|
||||||
|
### IPv4 reverse zone: `168.192.in-addr.arpa`
|
||||||
|
|
||||||
|
<!-- dns: 168.192.in-addr.arpa -->
|
||||||
|
<!-- dns-start -->
|
||||||
|
| Address | Name |
|
||||||
|
|---|---|
|
||||||
|
| `192.168.64.1` | `river-core.h.nul.ie.` |
|
||||||
|
| `192.168.64.2` | `stream-core.h.nul.ie.` |
|
||||||
|
| `192.168.64.20` | `palace-core.h.nul.ie.` |
|
||||||
|
| `192.168.64.21` | `unifi-ctr-core.h.nul.ie.` |
|
||||||
|
| `192.168.68.1` | `river-hi.h.nul.ie.` |
|
||||||
|
| `192.168.68.2` | `stream-hi.h.nul.ie.` |
|
||||||
|
| `192.168.68.22` | `palace.h.nul.ie.` |
|
||||||
|
| `192.168.68.40` | `castle.h.nul.ie.` |
|
||||||
|
| `192.168.68.80` | `cellar.h.nul.ie.` |
|
||||||
|
| `192.168.68.81` | `sfh.h.nul.ie.` |
|
||||||
|
| `192.168.68.100` | `unifi-ctr.h.nul.ie.` |
|
||||||
|
| `192.168.68.103` | `hass-ctr.h.nul.ie.` |
|
||||||
|
| `192.168.71.254` | `router-hi.h.nul.ie.` |
|
||||||
|
| `192.168.72.1` | `river-lo.h.nul.ie.` |
|
||||||
|
| `192.168.72.2` | `stream-lo.h.nul.ie.` |
|
||||||
|
| `192.168.72.103` | `hass-ctr-lo.h.nul.ie.` |
|
||||||
|
| `192.168.79.254` | `router-lo.h.nul.ie.` |
|
||||||
|
| `192.168.80.1` | `river-ut.h.nul.ie.` |
|
||||||
|
| `192.168.80.2` | `stream-ut.h.nul.ie.` |
|
||||||
|
| `192.168.80.254` | `router-ut.h.nul.ie.` |
|
||||||
|
<!-- dns-end -->
|
||||||
|
|
||||||
|
### IPv6 reverse zone: `0.d.4.0.0.c.7.9.e.0.a.2.ip6.arpa`
|
||||||
|
|
||||||
|
<!-- dns: 0.d.4.0.0.c.7.9.e.0.a.2.ip6.arpa -->
|
||||||
|
<!-- dns-start -->
|
||||||
|
| Address | Name |
|
||||||
|
|---|---|
|
||||||
|
| `2a0e:97c0:4d0:1::1` | `river-hi.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:1::2` | `stream-hi.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:1::ffff` | `router-hi.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:1::2:1` | `palace.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:1::3:1` | `castle.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:1::4:1` | `cellar.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:1::4:2` | `sfh.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:1::5:1` | `unifi-ctr.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:1::5:3` | `hass-ctr.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:2::1` | `river-lo.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:2::2` | `stream-lo.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:2::ffff` | `router-lo.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:2::5:3` | `hass-ctr-lo.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:3::1` | `river-ut.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:3::2` | `stream-ut.h.nul.ie.` |
|
||||||
|
| `2a0e:97c0:4d0:3::ffff` | `router-ut.h.nul.ie.` |
|
||||||
|
<!-- dns-end -->
|
||||||
@@ -75,7 +75,8 @@ Besides the forwards, `extraRules` defines:
|
|||||||
|
|
||||||
## DNS
|
## DNS
|
||||||
|
|
||||||
Both halves are PowerDNS ([`dns.nix`](../../../nixos/boxes/colony/vms/estuary/dns.nix)).
|
Both halves are PowerDNS ([`dns.nix`](../../../nixos/boxes/colony/vms/estuary/dns.nix)). The live
|
||||||
|
forward and reverse records are listed in the generated [DNS reference](../../reference/dns.md).
|
||||||
|
|
||||||
### Authoritative
|
### Authoritative
|
||||||
|
|
||||||
@@ -86,7 +87,8 @@ zone.
|
|||||||
- Zone contents are largely generated from `allAssignments`
|
- Zone contents are largely generated from `allAssignments`
|
||||||
(`lib.my.dns.fwdRecords` / `ptrRecords` / `ptr6Records`); `ALIAS` records
|
(`lib.my.dns.fwdRecords` / `ptrRecords` / `ptr6Records`); `ALIAS` records
|
||||||
(with `expand-alias`) point the zone apex at estuary itself.
|
(with `expand-alias`) point the zone apex at estuary itself.
|
||||||
- AXFR is allowed to HE.net's secondary (`216.218.133.2` / `2001:470:600::2`).
|
- AXFR is allowed to HE.net's secondary and the trusted internal/site-egress sources used by the
|
||||||
|
generated DNS reference.
|
||||||
- `_acme-challenge` is a LUA `TXT` record answered from a file (DNS-01 issuance).
|
- `_acme-challenge` is a LUA `TXT` record answered from a file (DNS-01 issuance).
|
||||||
- Reached publicly via the NAT redirect of port 53 → 5353; the `base` side also
|
- Reached publicly via the NAT redirect of port 53 → 5353; the `base` side also
|
||||||
accepts DNS directly.
|
accepts DNS directly.
|
||||||
|
|||||||
@@ -19,4 +19,12 @@ in
|
|||||||
update-docs-options = pkgs.writeShellScriptBin "update-docs-options" ''
|
update-docs-options = pkgs.writeShellScriptBin "update-docs-options" ''
|
||||||
exec ${pkgs.python3}/bin/python3 ${../ci/update-docs-options.py} "$@"
|
exec ${pkgs.python3}/bin/python3 ${../ci/update-docs-options.py} "$@"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
update-docs-dns =
|
||||||
|
let
|
||||||
|
python = pkgs.python3.withPackages (ps: [ ps.dnspython ]);
|
||||||
|
in
|
||||||
|
pkgs.writeShellScriptBin "update-docs-dns" ''
|
||||||
|
exec ${python}/bin/python3 ${../ci/update-docs-dns.py} "$@"
|
||||||
|
'';
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user