Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 88d0d19239 | |||
| 8f9ca5e1c4 | |||
| 08605ab422 |
@@ -6,7 +6,7 @@ on:
|
||||
|
||||
jobs:
|
||||
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
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -26,6 +26,16 @@ jobs:
|
||||
- name: Update option reference
|
||||
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
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
@@ -36,6 +46,6 @@ jobs:
|
||||
git remote set-url origin "${REPO_URL/https:\/\//https:\/\/oauth2:${GITEA_TOKEN}@}"
|
||||
git add docs/
|
||||
if ! git diff --cached --quiet; then
|
||||
git commit -m "docs: update generated tables"
|
||||
git commit -m "docs: Update generated references"
|
||||
git push
|
||||
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.
|
||||
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
|
||||
workflow (`.gitea/workflows/update-docs.yaml`) regenerates the network-assignment tables and NixOS
|
||||
option reference via `nix run .#update-docs-{assignments,options}`.
|
||||
workflow (`.gitea/workflows/update-docs.yaml`) regenerates the network assignments, NixOS option
|
||||
reference and live DNS reference under `docs/`.
|
||||
|
||||
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`.
|
||||
@@ -212,10 +212,12 @@ physical box share a name, the site keeps the `README.md` and the box page stays
|
||||
example `sites/colony/README.md` and `sites/colony/colony.md`).
|
||||
|
||||
**Box page layout** (match the existing pages): H1 + a one-line intro; a short bullet list of
|
||||
`Source` / `Host` / `nixpkgs`; `## Role`; `## Network assignments` that **links** to
|
||||
`Source` / `Host` / `nixpkgs`; an optional hardware inventory or VPS resource-allocation section;
|
||||
`## Role`; `## Network assignments` that **links** to
|
||||
[`networking.md#box-assignments`](docs/networking.md#box-assignments) (never inline the table); one
|
||||
`##` section per topic; `## Notable config files` last. A box without static assignments still gets
|
||||
the section with a short explanation instead of a generated-table link.
|
||||
`##` section per topic; `## Notable config files` last. Keep non-hardware platform details in their
|
||||
topical sections rather than moving them with the inventory. A box without static assignments still
|
||||
gets the section with a short explanation instead of a generated-table link.
|
||||
|
||||
**Structure and layout:**
|
||||
- Use **tables** for lists of structured items (BGP peers, forwarded ports, vhosts, containers,
|
||||
@@ -247,10 +249,12 @@ 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
|
||||
topic that owns them.
|
||||
|
||||
**Generated content:** the network-assignment tables in `networking.md` and the option reference
|
||||
(`docs/reference/nixos-options.md`) are CI-generated (`nix run .#update-docs-{assignments,options}`)
|
||||
— don't hand-edit between the `<!-- ... -->` markers; write the prose and let the updater refresh
|
||||
the tables.
|
||||
**Generated content:** the network-assignment tables in `networking.md`, the option reference
|
||||
(`docs/reference/nixos-options.md`) and the live DNS tables (`docs/reference/dns.md`) are
|
||||
CI-generated by the corresponding `update-docs-*` packages; the workflow supplies the DNS zones.
|
||||
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
|
||||
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,
|
||||
the AS211024 L2 mesh, BGP, WireGuard, Tailscale.
|
||||
- [`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
|
||||
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`
|
||||
|
||||
On pushes to the docs branch, excluding its own commits, this runs
|
||||
`nix run .#update-docs-assignments` and `nix run .#update-docs-options` and commits changed outputs
|
||||
as `docs: update generated tables`.
|
||||
On pushes to `master`, excluding its own commits, this runs the assignment, option and DNS
|
||||
reference generators and commits changed outputs as `docs: Update generated references`.
|
||||
|
||||
### The docs generators
|
||||
|
||||
Both are registered in [`pkgs/default.nix`](../pkgs/default.nix) (`writeShellScriptBin`s wrapping
|
||||
Python scripts under [`ci/`](../ci)). They leave the worktree unchanged when their output is current;
|
||||
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;
|
||||
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))
|
||||
@@ -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
|
||||
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.
|
||||
|
||||
`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.
|
||||
|
||||
+11
-11
@@ -6,17 +6,6 @@ Portable workstation — a Framework Laptop 13 (Intel), running the full GUI env
|
||||
- **Host:** physical (laptop)
|
||||
- **nixpkgs:** `mine`
|
||||
|
||||
## Role
|
||||
|
||||
- Personal portable workstation: `my.gui.enable`, with Sway managed by home-manager.
|
||||
- Joins the tailnet through the headscale on [`britway`](../remote/britway.md) (fish abbr
|
||||
`tsup` = `doas tailscale up --login-server=https://hs.nul.ie --accept-routes`).
|
||||
|
||||
## Network assignments
|
||||
|
||||
`tower` has no static assignment; it uses DHCP through NetworkManager and reaches the other boxes
|
||||
over Tailscale.
|
||||
|
||||
## Hardware / platform
|
||||
|
||||
| Component | Inventory |
|
||||
@@ -32,6 +21,17 @@ The configuration enables Intel microcode updates, `kvm-intel`, `intel_iommu=on`
|
||||
`intel-media-driver` and the latest kernel (`lib.my.c.kernel.latest`). Thunderbolt security
|
||||
(`bolt`), the fingerprint reader (`fprintd`) and `tlp` power management are also enabled.
|
||||
|
||||
## Role
|
||||
|
||||
- Personal portable workstation: `my.gui.enable`, with Sway managed by home-manager.
|
||||
- Joins the tailnet through the headscale on [`britway`](../remote/britway.md) (fish abbr
|
||||
`tsup` = `doas tailscale up --login-server=https://hs.nul.ie --accept-routes`).
|
||||
|
||||
## Network assignments
|
||||
|
||||
`tower` has no static assignment; it uses DHCP through NetworkManager and reaches the other boxes
|
||||
over Tailscale.
|
||||
|
||||
## Storage
|
||||
|
||||
- Two LUKS-encrypted partitions, `persist` and `home` (both `allowDiscards`); `/nix` is a
|
||||
|
||||
+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
|
||||
`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
|
||||
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`
|
||||
|
||||
|
||||
@@ -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 -->
|
||||
@@ -7,6 +7,14 @@ narrower gateway role than [`britway`](britway.md) (no control plane, no BGP).
|
||||
- **Host:** VPS (Birmingham, `bhx1`; provider uplink assignment `allhost`)
|
||||
- **nixpkgs:** `mine`
|
||||
|
||||
## Platform
|
||||
|
||||
| Component | Allocation |
|
||||
|---|---|
|
||||
| Virtualisation | KVM/QEMU guest |
|
||||
| Compute | 2 vCPUs and 2 GiB RAM |
|
||||
| Storage | 32 GiB virtio disk with separate ext4 filesystems for `/boot`, `/nix` and `/persist`; root is tmpfs |
|
||||
|
||||
## Role
|
||||
|
||||
- **Tailscale exit node** — logs into the headscale on [`britway`](britway.md)
|
||||
@@ -20,14 +28,6 @@ narrower gateway role than [`britway`](britway.md) (no control plane, no BGP).
|
||||
|
||||
See the consolidated [network assignments](../networking.md#box-assignments) table (this box: `britnet`).
|
||||
|
||||
## Platform
|
||||
|
||||
| Component | Allocation |
|
||||
|---|---|
|
||||
| Virtualisation | KVM/QEMU guest |
|
||||
| Compute | 2 vCPUs and 2 GiB RAM |
|
||||
| Storage | 32 GiB virtio disk with separate ext4 filesystems for `/boot`, `/nix` and `/persist`; root is tmpfs |
|
||||
|
||||
## Networking
|
||||
|
||||
- The provider interface is renamed to `veth0` by MAC. Its IPv6 default gateway sits off-subnet, so
|
||||
|
||||
@@ -7,6 +7,14 @@ control plane, a tailnet exit node, and the BGP speaker for AS211024.
|
||||
- **Host:** VPS at Vultr (London, `lon1`)
|
||||
- **nixpkgs:** `mine`
|
||||
|
||||
## Platform
|
||||
|
||||
| Component | Allocation |
|
||||
|---|---|
|
||||
| Virtualisation | Vultr VC2 virtual guest on a QEMU-compatible platform |
|
||||
| Compute | 2 vCPUs and 2 GiB RAM |
|
||||
| Storage | 65 GiB virtio disk with separate ext4 filesystems for `/boot`, `/nix` and `/persist`; root is tmpfs |
|
||||
|
||||
## Role
|
||||
|
||||
- **Headscale** — the self-hosted Tailscale control plane at `hs.nul.ie`; every other box's
|
||||
@@ -27,14 +35,6 @@ control plane, a tailnet exit node, and the BGP speaker for AS211024.
|
||||
|
||||
See the consolidated [network assignments](../networking.md#box-assignments) table (this box: `britway`).
|
||||
|
||||
## Platform
|
||||
|
||||
| Component | Allocation |
|
||||
|---|---|
|
||||
| Virtualisation | Vultr VC2 virtual guest on a QEMU-compatible platform |
|
||||
| Compute | 2 vCPUs and 2 GiB RAM |
|
||||
| Storage | 65 GiB virtio disk with separate ext4 filesystems for `/boot`, `/nix` and `/persist`; root is tmpfs |
|
||||
|
||||
## Networking
|
||||
|
||||
- Two assignments: `vultr` on the provider interface `veth0` (renamed by MAC), and `as211024`
|
||||
|
||||
+12
-12
@@ -8,6 +8,18 @@ everything at the colony site.
|
||||
- **Host:** bare metal (this *is* the physical box)
|
||||
- **nixpkgs:** `mine-stable`
|
||||
|
||||
## Hardware
|
||||
|
||||
| Component | Inventory |
|
||||
|---|---|
|
||||
| Platform | ASRock Rack X570D4U server board |
|
||||
| CPU | AMD Ryzen 9 5950X (16 cores / 32 threads) |
|
||||
| Memory | 128 GiB |
|
||||
| NVMe storage | Three 2 TB Samsung SSD 980 PRO devices providing the NVMe-backed LVM thin pool and data LVs |
|
||||
| Bulk storage | Three 12 TB WD120EDBZ disks and one 18 TB WD180EDGZ disk for the bulk LVM volumes |
|
||||
| Boot | SanDisk USB device holding the EFI system partition |
|
||||
| Network / management | Two Intel I210 Gigabit Ethernet controllers, one passed through to `estuary`; ASPEED BMC graphics and console |
|
||||
|
||||
## Role
|
||||
|
||||
Bare-metal AMD host. It does little application work itself — its job is to run
|
||||
@@ -55,18 +67,6 @@ Netdata uses FreeIPMI while ignoring the VCCM sensor. The box also runs `smartd`
|
||||
|
||||
See the consolidated [network assignments](../../networking.md#box-assignments) table (this box: `colony`).
|
||||
|
||||
## Hardware
|
||||
|
||||
| Component | Inventory |
|
||||
|---|---|
|
||||
| Platform | ASRock Rack X570D4U server board |
|
||||
| CPU | AMD Ryzen 9 5950X (16 cores / 32 threads) |
|
||||
| Memory | 128 GiB |
|
||||
| NVMe storage | Three 2 TB Samsung SSD 980 PRO devices providing the NVMe-backed LVM thin pool and data LVs |
|
||||
| Bulk storage | Three 12 TB WD120EDBZ disks and one 18 TB WD180EDGZ disk for the bulk LVM volumes |
|
||||
| Boot | SanDisk USB device holding the EFI system partition |
|
||||
| Network / management | Two Intel I210 Gigabit Ethernet controllers, one passed through to `estuary`; ASPEED BMC graphics and console |
|
||||
|
||||
## Networking
|
||||
|
||||
- Two bridges: `base` (the colony base network, shared with `estuary`) and
|
||||
|
||||
@@ -75,7 +75,8 @@ Besides the forwards, `extraRules` defines:
|
||||
|
||||
## 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
|
||||
|
||||
@@ -86,7 +87,8 @@ zone.
|
||||
- Zone contents are largely generated from `allAssignments`
|
||||
(`lib.my.dns.fwdRecords` / `ptrRecords` / `ptr6Records`); `ALIAS` records
|
||||
(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).
|
||||
- Reached publicly via the NAT redirect of port 53 → 5353; the `base` side also
|
||||
accepts DNS directly.
|
||||
|
||||
+11
-11
@@ -7,6 +7,17 @@ root storage on NVMe-oF volumes from `cellar`.
|
||||
- **Host:** physical
|
||||
- **nixpkgs:** `mine`
|
||||
|
||||
## Hardware
|
||||
|
||||
| Component | Inventory |
|
||||
|---|---|
|
||||
| Platform | ASUS ProArt X670E-CREATOR WIFI |
|
||||
| CPU | AMD Ryzen 9 7950X (16 cores / 32 threads) |
|
||||
| Memory | 64 GiB |
|
||||
| Graphics | Integrated AMD Radeon graphics |
|
||||
| Network | Mellanox ConnectX-4 100G, Aquantia AQC113CS 10G, Intel I225-V 2.5G and MediaTek MT7922 Wi-Fi 6E controllers |
|
||||
| System storage | No local root disk; the box netboots and uses the SPDK NVMe-oF namespace exported by `cellar` |
|
||||
|
||||
## Role
|
||||
|
||||
### Desktop
|
||||
@@ -38,17 +49,6 @@ a `drm-amd-display` flicker patch remains commented out.
|
||||
|
||||
See the consolidated [network assignments](../../networking.md#box-assignments) table (this box: `castle`).
|
||||
|
||||
## Hardware
|
||||
|
||||
| Component | Inventory |
|
||||
|---|---|
|
||||
| Platform | ASUS ProArt X670E-CREATOR WIFI |
|
||||
| CPU | AMD Ryzen 9 7950X (16 cores / 32 threads) |
|
||||
| Memory | 64 GiB |
|
||||
| Graphics | Integrated AMD Radeon graphics |
|
||||
| Network | Mellanox ConnectX-4 100G, Aquantia AQC113CS 10G, Intel I225-V 2.5G and MediaTek MT7922 Wi-Fi 6E controllers |
|
||||
| System storage | No local root disk; the box netboots and uses the SPDK NVMe-oF namespace exported by `cellar` |
|
||||
|
||||
## Networking
|
||||
|
||||
- `et100g` (100G, MTU 9000) carries `lan-hi` (the `hi` assignment, also pinned by a kea
|
||||
|
||||
+12
-12
@@ -8,18 +8,6 @@ SR-IOV VFs, PCI NVMe drives and LVM disks.
|
||||
- **Host:** physical
|
||||
- **nixpkgs:** `mine-stable`
|
||||
|
||||
## Role
|
||||
|
||||
- Home hypervisor: VMs are declared in `my.vms.instances`
|
||||
([`palace/vms/default.nix`](../../../nixos/boxes/home/palace/vms/default.nix)); disks are LVs in
|
||||
the `main` thin pool (`services.lvm.boot.thin.enable`).
|
||||
- AMD box (`kvm-amd`, `amd_iommu=on`, microcode updates); the kernel is built with
|
||||
`ACPI_APEI_PCIEAER`/`PCIEAER` for the PCIe passthrough work below.
|
||||
|
||||
## Network assignments
|
||||
|
||||
See the consolidated [network assignments](../../networking.md#box-assignments) table (this box: `palace`).
|
||||
|
||||
## Hardware
|
||||
|
||||
| Component | Inventory |
|
||||
@@ -32,6 +20,18 @@ See the consolidated [network assignments](../../networking.md#box-assignments)
|
||||
| NVMe storage | Three 2 TB Samsung NVMe devices passed through to `cellar`; SPDK combines them as the `NVMeRaid` RAID 0 device |
|
||||
| Network / graphics | Mellanox ConnectX-4 100G adapter with four SR-IOV VFs, two Intel I211 Gigabit Ethernet controllers, and an AMD Radeon RX 550/560-family GPU |
|
||||
|
||||
## Role
|
||||
|
||||
- Home hypervisor: VMs are declared in `my.vms.instances`
|
||||
([`palace/vms/default.nix`](../../../nixos/boxes/home/palace/vms/default.nix)); disks are LVs in
|
||||
the `main` thin pool (`services.lvm.boot.thin.enable`).
|
||||
- AMD box (`kvm-amd`, `amd_iommu=on`, microcode updates); the kernel is built with
|
||||
`ACPI_APEI_PCIEAER`/`PCIEAER` for the PCIe passthrough work below.
|
||||
|
||||
## Network assignments
|
||||
|
||||
See the consolidated [network assignments](../../networking.md#box-assignments) table (this box: `palace`).
|
||||
|
||||
## Networking
|
||||
|
||||
100G `et100g` (mlx5, MTU 9000) uplinks to the `dave` switch and carries `lan-hi` (VLAN 100, the
|
||||
|
||||
+14
-16
@@ -8,6 +8,18 @@ redundant router pair with [`river`](river.md) and is dual-homed to both switche
|
||||
- **Host:** physical
|
||||
- **nixpkgs:** `mine`
|
||||
|
||||
## Hardware
|
||||
|
||||
| Component | Inventory |
|
||||
|---|---|
|
||||
| Platform | BROUNION R86S |
|
||||
| CPU | Intel Celeron N5105 (4 cores / 4 threads) |
|
||||
| Memory | 16 GiB |
|
||||
| Storage | 512 GB Samsung SSD 970 PRO NVMe containing `/boot`, `/nix` and `/persist`; integrated 128 GB eMMC is present but is not used by the declared filesystems |
|
||||
| Network | Three Intel `igc` interfaces and a dual-port Mellanox `mlx4_en` adapter; `wan`, `lan-jim` and `lan-dave` use three of these ports |
|
||||
|
||||
The platform configuration enables `kvm-intel`, `intel_iommu=on` and Intel microcode updates.
|
||||
|
||||
## Role
|
||||
|
||||
At `routing-common` index 1, `stream` normally holds the secondary position in the router pair.
|
||||
@@ -61,28 +73,14 @@ box sets:
|
||||
reaching the modem subnet (needed only because it shares `wan`; WAN egress is otherwise
|
||||
accepted).
|
||||
|
||||
## Platform
|
||||
|
||||
### Hardware
|
||||
|
||||
| Component | Inventory |
|
||||
|---|---|
|
||||
| Platform | BROUNION R86S |
|
||||
| CPU | Intel Celeron N5105 (4 cores / 4 threads) |
|
||||
| Memory | 16 GiB |
|
||||
| Storage | 512 GB Samsung SSD 970 PRO NVMe containing `/boot`, `/nix` and `/persist`; integrated 128 GB eMMC is present but is not used by the declared filesystems |
|
||||
| Network | Three Intel `igc` interfaces and a dual-port Mellanox `mlx4_en` adapter; `wan`, `lan-jim` and `lan-dave` use three of these ports |
|
||||
|
||||
The platform configuration enables `kvm-intel`, `intel_iommu=on` and Intel microcode updates.
|
||||
|
||||
### Switching (RSTP)
|
||||
## Switching (RSTP)
|
||||
|
||||
`stream` is dual-homed to both switches: `lan-jim` (igc) and `lan-dave` (mlx4_en), both MTU 9000,
|
||||
are enslaved to the `lan` bridge with `STP=true`. [`routing-common/mstpd.nix`](../../../nixos/boxes/home/routing-common/mstpd.nix)
|
||||
runs a patched `mstpd` and forces RSTP on `lan` once it's routable, so exactly one uplink carries
|
||||
traffic at a time. (The remaining NICs are renamed `et2`/`et5` and left unconfigured.)
|
||||
|
||||
### Deployment
|
||||
## Deployment
|
||||
|
||||
`my.deploy.node.hostname` is currently commented out.
|
||||
|
||||
|
||||
@@ -114,8 +114,12 @@ in
|
||||
];
|
||||
also-notify = [ "127.0.0.1" ];
|
||||
allow-axfr-ips = [
|
||||
"127.0.0.0/8" "::1/128"
|
||||
"216.218.133.2" "2001:470:600::2"
|
||||
];
|
||||
]
|
||||
++ lib.my.c.home.routersPubV4
|
||||
++ lib.my.c.as211024.trusted.v4
|
||||
++ lib.my.c.as211024.trusted.v6;
|
||||
enable-lua-records = true;
|
||||
#loglevel = 7;
|
||||
#log-dns-queries = true;
|
||||
|
||||
@@ -170,6 +170,12 @@ in
|
||||
"0.0.0.0:5353" "[::]:5353"
|
||||
];
|
||||
also-notify = [ "127.0.0.1" ];
|
||||
allow-axfr-ips = [
|
||||
"127.0.0.0/8" "::1/128"
|
||||
allAssignments.estuary.internal.ipv4.address
|
||||
]
|
||||
++ lib.my.c.as211024.trusted.v4
|
||||
++ lib.my.c.as211024.trusted.v6;
|
||||
enable-lua-records = true;
|
||||
# loglevel = 7;
|
||||
# log-dns-queries = true;
|
||||
|
||||
@@ -19,4 +19,12 @@ in
|
||||
update-docs-options = pkgs.writeShellScriptBin "update-docs-options" ''
|
||||
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