Es gibt Infrastrukturprobleme, die von außen fast lächerlich trivial wirken.
„Trag doch einfach einen DNS-Eintrag ein.“
„Mach eben eine Firewall-Regel.“
„Nimm einfach den DNS-Resolver des Routers.“
Und technisch stimmt das zunächst sogar. Es funktioniert – bis das Netzwerk ein wenig wächst, bis VLANs hinzukommen, bis Dienste auf mehreren Interfaces leben, bis Reproduzierbarkeit wichtig wird und bis aus jedem „nur noch schnell ein Override“ ein weiteres kleines Stück versteckter, nicht-idempotenter Infrastrukturzustand in einer Firewall-Weboberfläche wird.
Das hier ist die Geschichte eines solchen Problems, das kleiner aussieht, als es ist: lokales DNS in einem segmentierten LAN.
Genauer gesagt:
Wie betreibt man sauberes, schnelles und deterministisches DNS für interne Dienste über mehrere VLANs hinweg, ohne pfSense Host Overrides bis in alle Ewigkeit manuell zu pflegen?
Die endgültige Lösung war nicht exotisch. Kein Kubernetes, kein Consul, keine Enterprise-Appliance, kein Service Mesh. Nur ein Debian-Server, CoreDNS, pfSense/Unbound, Ansible – und etwas sorgfältige Denkarbeit darüber, wie DNS-Auflösung tatsächlich abläuft.
Denn wie so oft in der Infrastruktur lag die Schwierigkeit nicht darin, Software zu installieren. Die Schwierigkeit lag darin, den Kontrollfluss wirklich zu verstehen.
Der Ausgangspunkt: pfSense-DNS funktionierte – aber nicht mehr gut genug
Das Netzwerk nutzte bereits pfSense als zentrale Firewall und DNS-Resolver. Das ist ein verbreitetes und grundsätzlich sehr vernünftiges Setup.
pfSense betreibt Unbound als DNS Resolver, und für viele Umgebungen reicht das vollkommen aus:
- DHCP-Integration
- lokale Host Overrides
- Domain Overrides
- Forwarding oder rekursive Auflösung
- Unterstützung für DNS over TLS
- eine hinreichend zugängliche Weboberfläche
Für ein kleines LAN ist das absolut in Ordnung.
Doch mit der Zeit war das lokale DNS-Setup deutlich über „ein paar Host Overrides“ hinausgewachsen.
Es gab zahlreiche interne Dienste:
prometheus.myhost.lan
grafana.myhost.lan
git.myhost.lan
dev.myhost.lan
vpn.myhost.lan
Einige Einträge waren ausschließlich intern. Andere gehörten zu einer öffentlichen Domain, die innerhalb des Netzes anders aufgelöst werden sollte. Wieder andere mussten je nach Client-VLAN unterschiedliche Antworten liefern. Und all das wurde über die pfSense-Oberfläche verwaltet.
Das erzeugte mehrere Probleme:
- manuelle Änderungen
- keine saubere Versionskontrolle
- kein unkompliziertes Rollback
- keine Idempotenz
- keine wiederverwendbare Deployment-Logik
- kein echtes Infrastructure-as-Code-Arbeitsmodell
Das war also nicht primär ein DNS-Performance-Problem. Es war ein DNS-Control-Plane-Problem.
pfSense blieb hervorragend als Firewall und als zentraler Resolver beziehungsweise Cache. Aber es war nicht der richtige Ort, um eine wachsende, strukturierte lokale DNS-Autorität dauerhaft zu pflegen.
Die architektonische Entscheidung: Resolver und Authority trennen
Der entscheidende gedankliche Schritt war dieser:
Die Firewall muss nicht zwangsläufig die Quelle der Wahrheit für sämtliche internen DNS-Einträge sein.
Sauberer ist es, Verantwortlichkeiten zu trennen:
Clients
↓
CoreDNS / pfSense DNS Resolver
↓
Lokale autoritative Einträge
↓
pfSense / Unbound
↓
Öffentliche Upstream-DNS-Server
Oder etwas präziser:
CoreDNS = lokale DNS-Autorität / Overlay / VLAN-bewusste Logik
pfSense Unbound = rekursiver Resolver, Cache, Upstream-Forwarding, Firewall-Integration
Public DNS = globale Namensauflösung
Daraus ergibt sich ein geschichtetes Modell:
| Ebene | Verantwortung |
|---|---|
| CoreDNS | Interne Einträge, lokale Overlays, VLAN-bewusste Antworten |
| pfSense / Unbound | Allgemeine DNS-Auflösung, Cache, Upstream-Forwarding |
| Öffentliche Resolver | Externe DNS-Auflösung |
Wichtig ist: CoreDNS muss pfSense nicht vollständig ersetzen.
Es kann schlicht der Teil des Systems werden, der lokale DNS-Logik deklarativ und nachvollziehbar abbildet.
Warum CoreDNS?
CoreDNS ist klein, schnell, pluginbasiert und wird über eine einfache Textdatei namens Corefile konfiguriert.
Genau das macht es für diesen Zweck attraktiv:
- unkompliziert auf Debian zu betreiben
- gut mit Ansible zu templaten
- sauber in Git versionierbar
- Unterstützung für statische Host-Einträge
- Unterstützung für Forwarding
- Prometheus-Metriken
- clientabhängige Views
- insgesamt einfach genug, um den Ablauf wirklich zu verstehen
Das Ziel war nicht, eine überkomplexe interne DNS-Plattform zu konstruieren. Das Ziel war, versteckten UI-Zustand durch ein sauberes, reproduzierbares System zu ersetzen.
Das grundlegende CoreDNS-Modell
Ein minimales CoreDNS-Setup für lokale Records sieht etwa so aus:
myhost.lan:53 {
errors
cache 300
hosts {
192.168.10.20 prometheus.myhost.lan
192.168.10.21 grafana.myhost.lan
fallthrough
}
forward . 192.168.10.1
}
Die Logik dahinter:
- Kennt CoreDNS den Hostnamen, liefert es die lokale IP zurück.
- Falls nicht, greift
fallthrough. - Die noch nicht aufgelöste Anfrage wird an pfSense/Unbound weitergereicht.
Für eine öffentliche Domain, die intern teilweise anders beantwortet werden soll, funktioniert derselbe Ansatz:
example.org:53 {
errors
cache 300
hosts {
192.168.10.30 internal-api.example.org
192.168.10.31 dev-only.example.org
fallthrough
}
forward . 192.168.10.1
}
Das eignet sich für Split-Horizon-artiges DNS:
internal-api.example.org → lokale IP im LAN
www.example.org → öffentliche DNS-Auflösung über Upstream
Bis hierhin ist alles recht geradlinig.
Das eigentliche Problem war jedoch interessanter.
Das Multi-VLAN-Problem
Ein interner Dienst, git.myhost.lan, war aus vier VLANs erreichbar.
Der Server selbst verfügte über Interfaces in allen vier VLANs:
VLAN 10 → 192.168.10.50
VLAN 20 → 192.168.20.50
VLAN 30 → 192.168.30.50
VLAN 40 → 192.168.40.50
Das Ziel war schlicht:
Client in VLAN 10 → git.myhost.lan → 192.168.10.50
Client in VLAN 20 → git.myhost.lan → 192.168.20.50
Client in VLAN 30 → git.myhost.lan → 192.168.30.50
Client in VLAN 40 → git.myhost.lan → 192.168.40.50
Warum?
Weil der Traffic dann lokal im jeweiligen VLAN bleibt.
Ohne diese Logik könnte ein Client in VLAN 20 git.myhost.lan beispielsweise auf die VLAN-10-IP auflösen. Der Datenverkehr müsste dann unnötig durch die Firewall laufen. Da das Netzwerk zu diesem Zeitpunkt noch keine Switches mit sauberer Inter-VLAN-Routing-Fähigkeit nutzte, bedeutete das unnötige Firewall-Traversierung – und eine unschöne Topologie-Leakage.
Der bisherige Workaround sah ungefähr so aus:
git1.myhost.lan → VLAN-10-IP
git2.myhost.lan → VLAN-20-IP
git3.myhost.lan → VLAN-30-IP
git4.myhost.lan → VLAN-40-IP
Funktional, aber nicht elegant.
Ein Hostname sollte den Dienst beschreiben, nicht die Netzwerktopologie.
Die eigentliche Anforderung lautete daher:
Derselbe Hostname soll abhängig vom abfragenden Client-Subnetz unterschiedliche Antworten liefern.
Das ist Split-Horizon-DNS – oder genauer: client-subnetzabhängiges DNS.
CoreDNS Views: der vielversprechende Mechanismus
CoreDNS besitzt ein view-Plugin, das Anfragen anhand von Client-Informationen filtern kann.
Konzeptionell lässt sich damit etwa Folgendes umsetzen:
myhost.lan:53 {
view vlan10 {
expr incidr(client_ip(), '192.168.10.0/24')
}
hosts {
192.168.10.50 git.myhost.lan
fallthrough
}
forward . 192.168.10.1
}
Und für VLAN 20:
myhost.lan:53 {
view vlan20 {
expr incidr(client_ip(), '192.168.20.0/24')
}
hosts {
192.168.20.50 git.myhost.lan
fallthrough
}
forward . 192.168.10.1
}
Das war genau das richtige Konzept.
Bis der tatsächliche Kontrollfluss in CoreDNS korrekt funktionierte, brauchte es allerdings mehrere Iterationen.
Wichtige Erkenntnis 1: CoreDNS muss die echte Client-IP sehen
Damit VLAN-abhängiges DNS funktioniert, muss CoreDNS die ursprüngliche Client-IP erkennen.
Das klingt offensichtlich, hat aber eine entscheidende Konsequenz.
Wenn Clients pfSense befragen und pfSense die Anfrage anschließend an CoreDNS weiterleitet, sieht CoreDNS womöglich nur pfSense als Quelle:
Client → pfSense/Unbound → CoreDNS
Aus CoreDNS-Sicht ist der Client dann nicht 192.168.20.123, sondern die Firewall.
Damit bricht das View-Matching.
Für dieses Setup sollten Clients, die VLAN-abhängige DNS-Antworten benötigen, CoreDNS deshalb direkt befragen – typischerweise über die DHCP-DNS-Server-Einstellungen je VLAN.
Alternativ müsste die Split-Horizon-Logik vollständig in Unbound beziehungsweise pfSense selbst abgebildet werden.
Für dieses Setup war der saubere Pfad daher:
Clients → CoreDNS → pfSense/Unbound → Upstream
CoreDNS wird zum ersten Resolver für LAN-Clients. Es verarbeitet die lokale Logik und reicht alles andere an pfSense weiter.
Wichtige Erkenntnis 2: CoreDNS korrekt an Interfaces binden
Auf dem Debian-Server liefen bereits weitere DNS-nahe Dienste, unter anderem dnsmasq auf einem Docker-/libvirt-artigen Subnetz.
Der erste CoreDNS-Startversuch scheiterte mit:
listen tcp :53: bind: address already in use
Zunächst wirkte es, als würde CoreDNS explizit gesetzte IP-Adressen ignorieren. Tatsächlich war das Problem eine Grammatikbesonderheit in CoreDNS.
Das hier bedeutet nicht intuitiv „binde ausschließlich an 127.0.0.1“:
127.0.0.1:53 {
...
}
Der korrekte Weg, Listener-Interfaces einzuschränken, ist das bind-Plugin innerhalb des Server-Blocks:
.:53 {
bind 192.168.10.53 192.168.20.53 192.168.30.53 192.168.40.53
errors
cache 300
forward . 192.168.10.1
}
Und entscheidend: Jeder relevante Server-Block muss dieselbe Bind-Einschränkung enthalten.
Andernfalls versucht CoreDNS unter Umständen weiterhin, breit auf Port 53 zu lauschen.
Das resultierende Muster:
myhost.lan:53 {
bind 192.168.10.53 192.168.20.53 192.168.30.53 192.168.40.53
...
}
Damit lassen sich Konflikte mit dnsmasq oder anderen Diensten vermeiden, die auf anderen lokalen Interfaces gebunden sind.
Wichtige Erkenntnis 3: CoreDNS kaskadiert nicht zwischen Server-Blöcken
Das war die wichtigste logische Falle.
Die erste Struktur sah ungefähr so aus:
VLAN-spezifischer Block für myhost.lan
Generischer/globaler Block für myhost.lan
Die Erwartung war:
1. VLAN-spezifische Hosts prüfen
2. Wenn nicht gefunden, zu globalen Hosts durchfallen
3. Wenn weiterhin nicht gefunden, upstream weiterleiten
CoreDNS funktioniert jedoch nicht so.
Sobald eine Anfrage in einem passenden Server-Block beziehungsweise View landet, wird dessen Plugin-Kette abgearbeitet. Danach springt CoreDNS nicht in einen späteren, allgemeineren Server-Block weiter.
Diese Variante schlug also fehl:
myhost.lan:53 {
view vlan10 {
expr incidr(client_ip(), '192.168.10.0/24')
}
hosts {
192.168.10.50 git.myhost.lan
fallthrough
}
forward . 192.168.10.1
}
myhost.lan:53 {
hosts {
192.168.10.20 prometheus.myhost.lan
192.168.10.21 grafana.myhost.lan
fallthrough
}
forward . 192.168.10.1
}
Ein Client aus VLAN 10, der prometheus.myhost.lan abfragt, landet im VLAN-10-Block, findet dort keinen Eintrag und wird anschließend upstream weitergereicht. Der spätere globale Hosts-Block wird nicht mehr betrachtet.
Damit war auch klar, warum das vermeintliche „globale Overlay“ ignoriert zu werden schien.
Wichtige Erkenntnis 4: hosts lässt sich pro Zone-Block nicht beliebig wiederholen
Die nächste Idee war, mehrere hosts-Sektionen innerhalb desselben Blocks zu platzieren:
myhost.lan:53 {
view vlan10 { ... }
hosts {
192.168.10.50 git.myhost.lan
fallthrough
}
hosts {
192.168.10.20 prometheus.myhost.lan
fallthrough
}
forward . 192.168.10.1
}
Doch auch das scheiterte, weil sich das hosts-Plugin innerhalb desselben Zone-Blocks nicht einfach mehrfach auf diese Weise verwenden lässt.
Die finale Lösung war deutlich simpler – und robuster:
Die globalen Zone-Records werden in jeden passenden VLAN-spezifischen Block hineingeneriert.
Anders gesagt: Jeder VLAN-spezifische Block enthält:
VLAN-spezifische Records
+ globale Records derselben Zone
+ fallthrough
+ forward
Das hält die Plugin-Kette einfach, explizit und deterministisch.
Das funktionierende CoreDNS-Muster
Eine vereinfachte finale CoreDNS-Struktur sieht so aus:
.:53 {
bind 192.168.10.53 192.168.20.53 192.168.30.53 192.168.40.53
errors
cache 300
prometheus 192.168.10.53:9153
forward . 192.168.10.1
}
myhost.lan:53 {
bind 192.168.10.53 192.168.20.53 192.168.30.53 192.168.40.53
view vlan10 {
expr incidr(client_ip(), '192.168.10.0/24')
}
errors
cache 300
hosts {
192.168.10.50 git.myhost.lan
# Globale Records, in die VLAN-View injiziert
192.168.10.20 prometheus.myhost.lan
192.168.10.21 grafana.myhost.lan
192.168.10.22 alertmanager.myhost.lan
fallthrough
}
forward . 192.168.10.1
}
myhost.lan:53 {
bind 192.168.10.53 192.168.20.53 192.168.30.53 192.168.40.53
view vlan20 {
expr incidr(client_ip(), '192.168.20.0/24')
}
errors
cache 300
hosts {
192.168.20.50 git.myhost.lan
# Dieselben globalen Records
192.168.10.20 prometheus.myhost.lan
192.168.10.21 grafana.myhost.lan
192.168.10.22 alertmanager.myhost.lan
fallthrough
}
forward . 192.168.10.1
}
Nun verhält sich das System exakt wie gewünscht:
VLAN-10-Client:
git.myhost.lan → 192.168.10.50
prometheus.myhost.lan → 192.168.10.20
google.com → Weiterleitung an pfSense
VLAN-20-Client:
git.myhost.lan → 192.168.20.50
prometheus.myhost.lan → 192.168.10.20
google.com → Weiterleitung an pfSense
Dienstspezifische Topologie wird lokal behandelt, während allgemeine Records gemeinsam verfügbar bleiben.
Idempotent machen mit Ansible
Der Punkt war nicht, DNS ein einziges Mal zum Laufen zu bringen. Der Punkt war, es reproduzierbar zu machen.
Die Rolle arbeitet mit Variablen wie diesen:
coredns_upstreams:
- "192.168.10.1"
coredns_bind_ips:
- "192.168.10.53"
- "192.168.20.53"
- "192.168.30.53"
- "192.168.40.53"
coredns_prometheus_enabled: true
coredns_prometheus_listen: "192.168.10.53:9153"
coredns_global_zones:
- name: "myhost.lan"
records:
- "192.168.10.20 prometheus.myhost.lan"
- "192.168.10.21 grafana.myhost.lan"
- "192.168.10.22 alertmanager.myhost.lan"
- name: "example.org"
records:
- "192.168.10.30 internal-api.example.org"
- "192.168.10.31 dev-only.example.org"
coredns_views:
- name: "vlan10"
client_cidrs:
- "192.168.10.0/24"
zones:
- name: "myhost.lan"
records:
- "192.168.10.50 git.myhost.lan"
- name: "vlan20"
client_cidrs:
- "192.168.20.0/24"
zones:
- name: "myhost.lan"
records:
- "192.168.20.50 git.myhost.lan"
Der entscheidende Teil im Jinja-Template ist die Stelle, an der globale Records in passende View-spezifische Zonen injiziert werden:
hosts {
{% for record in zone.records %}
{{ record }}
{% endfor %}
{# Globale Zone-Einträge ergänzen, sofern dieselbe Domain betroffen ist #}
{% for gzone in coredns_global_zones %}
{% if gzone.name == zone.name %}
# Globale Records für {{ gzone.name }}
{% for grecord in gzone.records %}
{{ grecord }}
{% endfor %}
{% endif %}
{% endfor %}
fallthrough
}
Damit erhält jede VLAN-View eine vollständige lokale Sicht auf die betreffende Zone.
Das ist nicht die theoretisch eleganteste Modellierung, aber sie ist explizit, robust und sehr leicht zu durchdenken – und genau das ist in Infrastruktur häufig der bessere Maßstab.
Docker: die Loopback-Falle
Nach der DNS-Umstellung auf dem Debian-Host selbst tauchte noch ein zusätzliches Problem auf.
Der Host nutzte eine neue /etc/resolv.conf, unter anderem mit:
nameserver 127.0.0.1
nameserver 192.168.10.1
Für den Host funktionierte das.
Docker-Container haben jedoch ihren eigenen Network Namespace. Innerhalb eines Containers bedeutet:
127.0.0.1
nicht der Debian-Host, sondern der Container selbst.
Container konnten das Loopback-DNS des Hosts daher nicht nutzen.
Die Lösung bestand darin, Docker explizit einen DNS-Server zuzuweisen, der aus Containern erreichbar ist:
{
"dns": [
"192.168.10.53",
"192.168.10.1"
]
}
in:
/etc/docker/daemon.json
Danach:
sudo systemctl restart docker
Und testen:
docker run --rm alpine nslookup git.myhost.lan
docker run --rm alpine nslookup google.com
Damit funktionierte Namensauflösung auch innerhalb der Container wieder sauber.
Erst testen, dann produktiv umstellen
Das ist der Teil, der in realer Infrastrukturarbeit zählt: Niemals blind alles umschalten.
Der sichere Testablauf war:
dig @192.168.10.53 git.myhost.lan +short
dig @192.168.10.53 prometheus.myhost.lan +short
dig @192.168.10.53 google.com +short
Von Clients in unterschiedlichen VLANs:
dig @192.168.10.53 git.myhost.lan +short
dig @192.168.20.53 git.myhost.lan +short
dig @192.168.30.53 git.myhost.lan +short
dig @192.168.40.53 git.myhost.lan +short
Erwartet:
VLAN 10 → 192.168.10.50
VLAN 20 → 192.168.20.50
VLAN 30 → 192.168.30.50
VLAN 40 → 192.168.40.50
Während des Rollouts waren CoreDNS-Logs hilfreich:
log
errors
Und natürlich die Systemlogs:
journalctl -u coredns -f
Der kritische Punkt war zu verifizieren, dass CoreDNS tatsächlich die realen Client-IPs sieht – und nicht nur die Firewall.
Observability: Prometheus-Metriken
CoreDNS kann mit einer einzigen Zeile Prometheus-Metriken bereitstellen:
prometheus 192.168.10.53:9153
Prometheus kann diese anschließend scrapen:
scrape_configs:
- job_name: "coredns"
static_configs:
- targets:
- "192.168.10.53:9153"
Nützliche Metriken sind unter anderem:
coredns_dns_requests_total
coredns_dns_responses_total
coredns_cache_hits_total
coredns_cache_misses_total
coredns_dns_request_duration_seconds
Das ist nicht bloß ein nettes Extra. DNS ist grundlegend genug, dass Sichtbarkeit wirklich zählt.
Hohe NXDOMAIN-Raten, langsame Upstream-Antworten, fehlerhafte Clients, übermäßige Lookups – all das wird damit sichtbar.
Die finale Architektur
Das resultierende Setup sieht so aus:
LAN-Clients
↓
CoreDNS auf zentralem Debian-Server
↓
lokale Records / VLAN-bewusste Views
↓
pfSense Unbound
↓
öffentliche Upstream-DNS-Server
Für reguläre interne Dienste:
prometheus.myhost.lan → gemeinsame lokale IP
grafana.myhost.lan → gemeinsame lokale IP
Für topologiebewusste Dienste:
git.myhost.lan → VLAN-lokale IP abhängig vom Client-Subnetz
Für alles andere:
externe Domains → pfSense/Unbound → Upstream-DNS
Und all das wird über Ansible ausgerollt.
Das bedeutet:
- keine manuelle Pflege von pfSense Host Overrides mehr
- kein versteckter Zustand
- keine einmaligen UI-Änderungen
- keine Topologie verratenden Hostnamen wie
git1,git2,git3 - vorhersehbares lokales DNS-Verhalten
- beobachtbare DNS-Metriken
- reproduzierbares Deployment
Das ist genau die Art von Infrastrukturverbesserung, die auf den ersten Blick nicht glamourös wirkt – aber ein Netzwerk sofort kohärenter und ruhiger macht.
Warum das über DNS hinaus relevant ist
Das ist ein lokales LAN-Thema. Das zugrunde liegende Muster ist jedoch deutlich allgemeiner.
Viele IT-Probleme entstehen nicht, weil Werkzeuge fehlen. Sie entstehen, weil Verantwortlichkeiten unscharf ineinanderlaufen.
In diesem Fall waren:
Firewall-UI
+ DNS-Resolver
+ lokale Autorität
+ Topologie-Routing
+ manuelle Records
zu sehr an einem Ort zusammengezogen.
Die Lösung lautete nicht: „Nimm einfach einen cooleren DNS-Server.“
Die Lösung lautete: Verantwortlichkeiten trennen.
pfSense = Firewall und Resolver/Cache
CoreDNS = lokale Autorität und DNS-Logik
Ansible = gewünschter Zielzustand
Prometheus = Sichtbarkeit
Das ist der Unterschied zwischen etwas, das bloß funktioniert, und etwas, das sich tatsächlich betreiben lässt.
Eine kleine Notiz aus der Beratungsperspektive
Genau solche Arbeiten mache ich auch beruflich ausgesprochen gern: ein System, das organisch gewachsen ist, auf seine versteckten strukturellen Reibungen hin untersuchen – und es anschließend sauberer, reproduzierbarer und leichter betreibbar machen.
Bei Neoground arbeiten wir meist an größeren digitalen Systemen – AI Consulting, Webplattformen, Automatisierung, SaaS-Architekturen, Infrastruktur und Strategie. Doch das Grundprinzip bleibt überall dasselbe:
Gute Technologiearbeit ist nicht bloß Implementierung. Sie ist strukturelle Klärung.
Manchmal bedeutet das, ein digitales Produkt zu entwerfen. Manchmal, einen internen Workflow zu entwirren. Und manchmal eben, DNS in einem segmentierten LAN so zu ordnen, dass die gesamte Infrastruktur endlich so funktioniert, wie sie gedanklich längst funktionieren sollte.
Wenn ein System grundsätzlich läuft, sich aber zunehmend manuell, fragil oder schwer durchdringbar anfühlt, ist das meist ein Zeichen dafür, dass es seiner ursprünglichen Steuerungsebene entwachsen ist.
Genau an diesem Punkt wird strategische Beratung wertvoll.
Das Ergebnis
Nach der Migration ist DNS nun:
- schnell
- lokal
- VLAN-bewusst
- reproduzierbar
- beobachtbar
- nicht länger in der pfSense-Oberfläche gefangen
Das Befriedigende ist nicht nur, dass git.myhost.lan nun aus jedem VLAN korrekt auflöst.
Das Befriedigende ist, dass das System jetzt wieder zum mentalen Modell passt.
Und in der Infrastruktur ist genau das meist der Moment, in dem wieder Ruhe einkehrt.
Dieser Blogbeitrag wurde von mir mit Unterstützung von KI (GPT 5.5 Thinking) auf Grundlage meiner langen Troubleshooting-Sessions, Notizen und zahlreichen Iterationen verfasst.
No Comments Yet
Add a comment