# DNS-Mapping -- Canonical Source of Truth

**Stand:** 2026-04-15
**Scope:** Beide Cloudflare-Zonen (bahn.business, bahn.services) + 5 mTLS-Cluster-Server + 2 Fixed-IP-Colocation-Server.
**Zweck:** Diese Datei ist die **einzige verbindliche Referenz** fuer DNS-Mappings, Routing-Regeln und Cluster-Apache-Konsistenz. Andere Doku-Dateien die DNS-/Routing-Details beschreiben (ARCHITECTURE.md, APACHE-VHOSTS.md, APACHE_CONFIG.md, QUICK-REFERENCE.md, TEST-BACKEND.md, TESTING.md, CLOUDFLARE_CONFIG.md, INFRASTRUCTURE.md) verweisen hierher. Wenn etwas dort der hier dokumentierten Wahrheit widerspricht, gilt **diese** Datei.

---

## 1. Server-Inventar

### 5 mTLS-Cluster-Server (Hetzner Cloud, VLAN 10.0.0.0/16)

| Kuerzel | Hostname | IPv4 (public) | IPv6 | VLAN-IP | Standort |
|---|---|---|---|---|---|
| **S1-NBG1** | Cert-Server-1-NBG | 188.245.157.241 | 2a01:4f8:c0c:af60::1 | 10.0.0.2 | Nuernberg |
| **S2-NBG0** | Cert-Server-0-NBG | 116.203.243.240 | 2a01:4f8:1c1a:b9f1::1 | 10.0.0.3 | Nuernberg |
| **S3-FSN0** | Cert-Server-0-FSN | 49.12.76.141 | 2a01:4f8:c17:7411::1 | 10.0.0.4 | Falkenstein |
| **S4-FSN1** | Cert-Server-1-FSN | 91.98.147.79 | 2a01:4f8:c012:e96c::1 | 10.0.0.5 | Falkenstein |
| **S5-HEL** | Cert-Server-HEL | 46.62.131.226 | 2a01:4f9:c012:4f8f::1 | 10.0.0.6 | Helsinki |

Reference-Server fuer Config-Verteilung (rsync/lsyncd): **S1-NBG1 (10.0.0.2)**.

### 2 Fixed-IP-Server (Hetzner Colocation, DC4-NBG)

| Kuerzel | IPv4 | Funktion |
|---|---|---|
| **FIX-B** | 49.12.179.109 | `-b` Variante (Bund) |
| **FIX-BW** | 49.12.179.110 | `-bw` Variante (Bundeswehr) |

### CA-Gen-Server (separat)

| Rolle | IP | Hinweis |
|---|---|---|
| `db-cert-generate` | 49.12.179.94 | Einziger Server mit privaten CA-Keys. Zugang nur via Cloudflare Tunnel. Nicht im mTLS-Cluster. |

### Non-Cluster API-Server

| FQDN | Ziel-IP | Bemerkung |
|---|---|---|
| `apis.bahn.services`, `apis-test.bahn.services` | **49.12.179.70** | Eigener API-Server, NICHT im Cluster, NICHT Fixed-IP |

---

## 2. Cloudflare Zonen

| Zone | Account | Plan | Zone-ID | Token-Env | Record-Count (2026-04-15) |
|---|---|---|---|---|---|
| `bahn.business` | BLUEITS GmbH | **Enterprise** | `36e79a0dc1c69628fa1e23aae9d5e9b8` | `CF_TOKEN_BUSINESS` | 464 (201 A, 218 AAAA, 24 CNAME, 10 MX, 11 TXT) |
| `bahn.services` | REDITS by BLUEITS GmbH | **Pro** | `ada86c619846d0486e721dd85381ad00` | `CF_TOKEN_SERVICES` | 514 (257 A, 257 AAAA) |

### API-Zugriff (Pflicht: Vollpaginierung)
```bash
curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE/dns_records?per_page=100&page=$N" \
  -H "Authorization: Bearer $CF_TOKEN_..."
```
Iteriere ueber alle Seiten bis `result` leer -- niemals feste Seitenzahl annehmen (Zonen wachsen).

---

## 3. Fixed-IP-Regel (NUR bahn.business)

Fuer die 4 Subdomain-Familien `ccc-b`, `ccc-bw`, `cs-b`, `cs-bw` in **bahn.business**:

- **`.abn` und `.prd`**: Ausschliesslich FIX-B (49.12.179.109) bzw. FIX-BW (49.12.179.110). Keine Cluster-IP.
- **Stages drunter (dev/tst/int/lup/pen/pres)**: muessen mindestens S1-NBG1 enthalten ("auch auf NBG-1"). Aktuell: `.dev` exklusiv S1-NBG1; `.tst/int/lup/pen/pres` volles 5-RR.

**bahn.services hat KEIN Fixed-IP-Konzept.** Dort sind die gleichen Subdomains cluster-basiert (Details in Abschnitt 5).

---

## 4. bahn.business -- Vollstaendige Routing-Matrix

### 4.1 `-b/-bw` Varianten (Fixed-IP-Regel)

| Stage | ccc-b | ccc-bw | cs-b | cs-bw |
|---|---|---|---|---|
| dev | S1-NBG1 only | S1-NBG1 only | S1-NBG1 only | S1-NBG1 only |
| tst | 5-RR | 5-RR | 5-RR | 5-RR |
| int | 5-RR | 5-RR | 5-RR | 5-RR |
| lup | 5-RR | 5-RR | 5-RR | 5-RR |
| pen | 5-RR | 5-RR | 5-RR | 5-RR |
| pres | 5-RR | 5-RR | 5-RR | 5-RR |
| **prd** | **FIX-B** | **FIX-BW** | **FIX-B** | **FIX-BW** |
| **abn** | **FIX-B** | **FIX-BW** | **FIX-B** | **FIX-BW** |

### 4.2 `ccc` / `cs` plain (ohne -b/-bw)

| Stage | ccc | cs |
|---|---|---|
| @ (Apex/ohne Stage) | S1-NBG1 only | S1-NBG1 only |
| dev | 5-RR | 5-RR |
| tst | 5-RR | 5-RR |
| int | 5-RR | 5-RR |
| lup | 5-RR | 5-RR |
| pen | 5-RR | 5-RR |
| pres | 5-RR | 5-RR |
| prd | 5-RR | 5-RR |
| abn | 5-RR | 5-RR |

### 4.3 `cert.*` (bahn.business) -- CNAME zu Cloudflare Pages

**KRITISCH:** `cert.*` auf bahn.business zeigt **NICHT auf den Cluster** (Ausnahme: `cert.dev`). Alle anderen Stages sind **CNAMEs zu Cloudflare Pages**:

| FQDN | Ziel | Typ | Proxied |
|---|---|---|---|
| `cert.bahn.business` (Apex) | `db-cert-prd.pages.dev` | CNAME | yes |
| `cert.abn.bahn.business` | `db-cert-abn.pages.dev` | CNAME | yes |
| `cert.int.bahn.business` | `db-cert-int.pages.dev` | CNAME | yes |
| `cert.lup.bahn.business` | `db-cert-lup.pages.dev` | CNAME | yes |
| `cert.pen.bahn.business` | `db-cert-pen.pages.dev` | CNAME | yes |
| `cert.pres.bahn.business` | `db-cert-pres.pages.dev` | CNAME | yes |
| `cert.prd.bahn.business` | `db-cert-prd.pages.dev` | CNAME | yes |
| `cert.tst.bahn.business` | `db-cert-tst.pages.dev` | CNAME | yes |
| **`cert.dev.bahn.business`** | **5-RR Cluster** | A+AAAA | no (DNS-only) |

Apache-vhosts fuer die 8 CNAME-Varianten existieren im Cluster (Ghost-Vhosts, siehe Abschnitt 7).

### 4.4 Andere Subdomains auf bahn.business

| Pattern | Beispiele | Ziel |
|---|---|---|
| `b`, `bw` (Single-Letter) | `b.bahn.business`, `bw.bahn.business` | FIX-B / FIX-BW (A only) |
| Cloudflare Pages/Tunnel | `cert.download`, `cert.log`, `cert-next.tst`, `cert-status.tst`, `ccc-fixip.*`, `cs-fixip.*`, `pst.*`, `web.*`, `www`, `@`, `bcbp`, `btm.tst`, `support` | CNAME/AAAA auf `100::` (proxied) |

---

## 5. bahn.services -- Vollstaendige Routing-Matrix

### 5.1 `-b/-bw` Varianten (KEIN Fixed-IP -- cluster-basiert)

| Stage | ccc-b | ccc-bw | cs-b | cs-bw |
|---|---|---|---|---|
| dev | 5-RR | 5-RR | 5-RR | 5-RR |
| tst | 5-RR | 5-RR | 5-RR | 5-RR |
| int | 5-RR | 5-RR | 5-RR | 5-RR |
| lup | 5-RR | 5-RR | 5-RR | 5-RR |
| pen | 5-RR | 5-RR | 5-RR | 5-RR |
| pres | 5-RR | 5-RR | 5-RR | 5-RR |
| **prd** | **S1-NBG1 only** | **S1-NBG1 only** | **S1-NBG1 only** | **S1-NBG1 only** |
| abn | 5-RR | 5-RR | 5-RR | 5-RR |

### 5.2 `ccc` / `cs` plain (ohne -b/-bw)

| Stage | ccc | cs |
|---|---|---|
| @ (Apex/ohne Stage) | S1-NBG1 only | S1-NBG1 only |
| dev | 5-RR | 5-RR |
| **tst** | **S1-NBG1 only** | **S1-NBG1 only** |
| int | 5-RR | 5-RR |
| lup | 5-RR | 5-RR |
| pen | 5-RR | 5-RR |
| pres | 5-RR | 5-RR |
| prd | 5-RR | 5-RR |
| abn | 5-RR | 5-RR |

**Unterschied zu business:** `ccc.tst` / `cs.tst` sind hier S1-NBG1 only (business = 5-RR). Gewollt.

### 5.3 `cert.*` (bahn.services) -- Cluster + Apache-Proxy zum Worker

Im Gegensatz zu business **zeigen diese auf den Cluster** (A/AAAA DNS-only). Apache terminiert mTLS und proxied zum Cloudflare Worker:

| FQDN | DNS | Apache-vhost |
|---|---|---|
| `cert.bahn.services` (Apex) | S1-NBG1 only | ServerName (mit Alias `cert.prd.bahn.services`) |
| `cert.abn.bahn.services` | 5-RR | eigener vhost |
| `cert.dev.bahn.services` | 5-RR | eigener vhost |
| `cert.int.bahn.services` | 5-RR | eigener vhost |
| `cert.lup.bahn.services` | 5-RR | eigener vhost |
| `cert.pen.bahn.services` | 5-RR | eigener vhost |
| `cert.pres.bahn.services` | 5-RR | eigener vhost |
| `cert.prd.bahn.services` | 5-RR | Alias zum Apex-vhost |
| `cert.tst.bahn.services` | S1-NBG1 only | eigener vhost |

**Apache-Flow fuer services cert.*:**
```
Client (mTLS-Cert) → Apache ssl:443 → SSLVerifyClient optional_no_ca
  → strip mTLS, inject X-CC-* Request-Header
  → ProxyPass https://cert-server-{stage}.db-app.workers.dev/
```
Worker-Auth via `X-CC-Access-Id` / `X-CC-Access-Secret` Headern.

---

## 6. Record-Verteilung pro Server

| Server | bahn.business A | bahn.business AAAA | bahn.services A | bahn.services AAAA | **Total** |
|---|---:|---:|---:|---:|---:|
| **S1-NBG1** | 43 | 43 | 59 | 59 | **204** |
| S2-NBG0 | 37 | 37 | 49 | 49 | 172 |
| S3-FSN0 | 37 | 37 | 49 | 49 | 172 |
| S4-FSN1 | 37 | 37 | 49 | 49 | 172 |
| S5-HEL | 37 | 37 | 49 | 49 | 172 |

**S1-NBG1 traegt +32 Records** gegenueber den anderen. Grund: S1 bedient zusaetzlich alle Apex-/Base-Subdomains (ccc, cs, cert ohne Stage) und die Single-Server-Stages (DEV-Varianten auf business, TST-plain + PRD `-b/-bw` auf services).

---

## 7. Apache Ghost-Vhosts -- Migrations-Vorbereitung

Apache `cert-pki.conf` auf allen 5 Cluster-Servern enthaelt ServerName/ServerAlias-Eintraege fuer **16 FQDNs, die DNS-seitig heute nicht auf den Cluster zeigen**:

### 8x `cert.*.bahn.business` (CNAME zu Pages)

```
cert.bahn.business, cert.abn, cert.int, cert.lup,
cert.pen, cert.pres, cert.prd, cert.tst   (alle .bahn.business)
```
Heute: DNS-CNAME zu `db-cert-{stage}.pages.dev`. Apache-vhost ist vorbereitet fuer den zukuenftigen DNS-Swap (CNAME → A/AAAA Cluster-IPs), damit mTLS-Proxy zum Worker direkt aktivierbar ist **ohne Deployment**.

### 8x `ccc-b/-bw.prd|abn` + `cs-b/-bw.prd|abn` (Fixed-IP heute)

```
ccc-b.prd, ccc-b.abn, ccc-bw.prd, ccc-bw.abn,
cs-b.prd,  cs-b.abn,  cs-bw.prd,  cs-bw.abn    (alle .bahn.business)
```
Heute: DNS zeigt auf FIX-B / FIX-BW. Apache-vhost ist vorbereitet fuer Failover bzw. spaeteren Umzug auf den Cluster.

### Konsistenz-Regel

**Diese 16 vhosts NIEMALS als "dead code" entfernen.** Sie sind absichtlich ueberdimensioniert, damit ein einziger DNS-Swap genuegt, um die jeweilige FQDN vom Cluster bedienen zu lassen. Doku-Quellen die "Backend-Routing" fuer `cert.*.bahn.business` via Apache-cluster behaupten, sind veraltet -- Realitaet ist CNAME auf Pages, Apache-vhost ist Standby.

---

## 8. TTL-Policy

- Alle A/AAAA Cluster-Records nutzen **TTL=Auto** (Cloudflare-managed).
- dns-maintenance.sh setzt waehrend Drain-Operation temporaer per-Zone-TTL:
  - bahn.business: 60s (Enterprise-Plan erlaubt Minimum 1s)
  - bahn.services: 60s (Pro-Plan Minimum)
- Am 2026-04-14 wurden 758 Records von festem TTL=60s auf Auto korrigiert.

---

## 9. Konsistenz-Cross-Check (verifiziert 2026-04-15)

| Check | Ergebnis |
|---|---|
| Apache-vhost-Config auf allen 5 Servern identisch | ✓ (1:1 via rsync) |
| Alle 102 DNS-Cluster-FQDNs haben Apache-vhost | ✓ (keine Routing-Leaks) |
| Apache-Superset = DNS-Cluster-Set + 16 Ghost-Vhosts | ✓ (Migrations-Vorbereitung) |
| bahn.business Fixed-IP-Regel (abn/prd → FIX only) | ✓ (alle 8 Records konform) |
| bahn.business Stages drunter enthalten S1-NBG1 | ✓ |
| cert.* business via CNAME zu Pages (ausser cert.dev) | ✓ |
| cert.* services Apache→Worker ProxyPass | ✓ |

---

## 10. Referenzen

- `scripts/dns-maintenance.sh` -- Cluster-Drain fuer Wartung/Reboot
- `scripts/verify-deployment.sh` -- 28-Check Cluster-Audit (SSH, Scripts, systemd-Units, Certs, Kernel, DNS, Apache, Cloudflared-Tunnel, Disk/Memory/CPU, Webhook-Env; seit 2026-04-21 P6-Konsolidierung)
- [docs/INFRASTRUCTURE.md](INFRASTRUCTURE.md) -- Server-Inventar (primaer, hier gespiegelt)
- [docs/DNS-MAINTENANCE.md](DNS-MAINTENANCE.md) -- Drain-/Restore-Flow
- [docs/FIPS.md](FIPS.md) -- FIPS-Policy (auf Cluster deaktiviert)
- Cloudflare API: siehe Abschnitt 2
