Lesson 0002 · groupdir-infra

DNS-Optionen

scope, target und wo du welche Records pflegst: Lab in net/lab/hosts/, Rest in der Zone.

Einleitung

In Lesson 0001 war die Landkarte klar: Lab-Namen kommen aus net/lab/hosts/, die Zone net/dns/groupdir.de.nix merged sie mit öffentlichen und VPN-Records. Jetzt lernst du die Felder. Danach solltest du einen neuen Lab-Namen in einer Host-Datei skizzieren und erklären, warum du welche Option gewählt hast.

Grundlage: docs/lab-ipam.md und docs/dns-records.md.

Zwei Orte, eine Semantik

  • Lab LAN (*.lab): net/lab/hosts/<name>.nix mit ipv4 und dns = { … }. Daraus erzeugt net/lab/dns-records.nix die A-Records (Default scope = "internal").
  • Öffentlich / VPN / SRV / TXT: weiterhin direkt in net/dns/groupdir.de.nix (staticRecords).

Dieselbe Record-Liste speist zwei Ableitungen:

  • öffentlich: Hetzner (tofu/dns), wenn scope public oder both
  • intern: lab-gateway-DNS, wenn internal oder both

Deshalb trägst du Namen nicht direkt in tofu/dns ein — und Lab-*.lab-A-Records nicht noch einmal manuell in die Zone.

scope: wo existiert der Name?

  • public: nur im öffentlichen DNS (aktuell Hetzner), z. B. vpn.groupdir.de
  • internal: nur im internen DNS (Lab/VPN), z. B. grafana.lab.groupdir.de (Lab-Default)
  • both: beides (manchmal mit unterschiedlichen Antworten; siehe dns-records.md)

target: wohin zeigt ein interner A-Record?

Für interne A-Records entscheidet target, was aufgelöst wird und ob Caddy mitspielt — in der Zone als target, in Host-Dateien unter dns.target:

  • direct (Default bei Hosts): Antwort ist die Host-IP (ipv4 bzw. Zone-value). Typisch für LDAP, DB, …
  • reverse-proxy: Antwort ist die Gateway-IP; zusätzlich Caddy-Route zu upstream. Typisch für HTTP(S) im Lab.

Faustregel aus operations.md: HTTP(S) hinter Caddy → reverse-proxy; alles andere → direct.

Schablone: Lab-Host

# net/lab/hosts/mein-dienst.nix
{
  name = "mein-dienst";
  ipv4 = "192.168.200.40";
  dns = {
    name = "mein-dienst.lab";
    target = "reverse-proxy";
    upstream = "http://192.168.200.40:8080";
  };
}

Ohne Proxy reicht dns = { name = "…"; } (oder nur dns = { }; → Default-Name ${name}.lab). Nur IP reservieren: dns = false. Freie Adresse: just lab-ipam.

Mindestfelder je Fall

Mehrere IPs für einen Namen: in Hosts dns.values = [ ... ] (Beispiel: rancher.lab).

Lesen am echten Repo

Öffne die Dateien und vergleiche:

  1. net/lab/hosts/grafana.nix: reverse-proxy + upstream
  2. net/lab/hosts/dc1.nix: direct, mehrere Namen (dc1.lab, ldap.lab)
  3. In net/dns/groupdir.de.nix einen öffentlichen Record (z. B. vpn) — nicht unter Lab-Hosts

Das ist die Leseübung, nichts deployen.

Üben: Optionen wählen

Retrieval

Neuer Hostname nur im Lab sichtbar, nicht bei Hetzner. Welcher scope?

Web-UI im Lab hinter Caddy (reverse-proxy). Was brauchst du außer Name/IP?

Neuer Lab-Name app.lab. Wo trägst du ihn ein?

Nach dem Eintrag (Später im Alltag): interne Änderungen wirken nach Deploy von lab-gateway; öffentliche nach Terraform generate → plan → apply unter tofu/dns. Für diese Lesson reicht die Datei zu verstehen.

Primärquelle

docs/lab-ipam.md, docs/dns-records.md, Praxis: docs/operations.md („Add a lab service“).

Kompakt: Referenz: DNS-Records.