rd13_tile_server/docs/requirements/REQUIREMENTS.md
Conrad Schulz 315914a355 docs(satellite): complete analysis & decision log – enhancement on hold
- REQ-006 rewritten with provider matrix, cost comparison, integration sketch
- MapTiler On-Prem identified as cost-optimal private self-hosting solution
- Sentinel Hub free tier analysis: Germany z14 = 1,333 years (not viable)
- Session history: 6-prompt analysis with tables & findings
- Status: On hold pending z11 feasibility validation
- Next: Test z11 in MediaWiki/HA/Nextcloud (2-4 weeks)
2026-06-22 14:40:54 +00:00

241 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Anforderungen rd13_tile_server
Letzte Aktualisierung: 2026-06-22
---
## Architektur-Entscheidung
**Stack:** Martin (Vektor-API) + tileserver-gl (Raster-Renderer)
Rationale: [siehe ADR-001](../adr/001-martin-tileserver-gl-stack.md)
- Martin: Vektor-Tiles (PBF) API-Foundation für zukünftige MapLibre GL Integration
- tileserver-gl: PNG-Rendering Kartographer + externe Clients (Home Assistant, Nextcloud)
- Tile-Updates: manuell 24×/Jahr (nicht live)
- Styles: Anpassbar über JSON-Style-Definitionen in `config/styles/`
**⛔ Hardware-Einschränkung (dauerhaft):**
Kein Planetiler-Self-Build auf dieser Hardware. Kein Pre-Built für Europa/DE z16 verfügbar.
→ Begründung: [ADR-002](../adr/002-no-highzoom-no-satellite-build.md)
---
## REQ-001 Tile Server öffentlich erreichbar
**Status:** ✅ umgesetzt
Der Tile Server muss über HTTPS unter einer öffentlichen Domain erreichbar sein,
damit externe Dienste (MediaWiki, Home Assistant, Nextcloud) Karten laden können.
**Akzeptanzkriterien:**
- Erreichbar unter `https://tiles.rd13server.de`
- SSL-Terminierung via NPM
- Health-Endpunkt antwortet mit HTTP 200
---
## REQ-002 Rate Limiting für den öffentlichen Tile-Endpunkt
**Status:** 🔴 offen Implementierung erforderlich vor Live-Gang
Da der Server unter `https://tiles.rd13server.de` öffentlich erreichbar ist, muss
er gegen unautorisierten Massenkonsum und DoS-Angriffe geschützt werden.
### Anforderungen
| ID | Anforderung | Priorität |
|---|---|---|
| REQ-002.1 | Rate Limiting: max. 10 Tile-Requests/Sekunde pro IP, Burst 60 | hoch |
| REQ-002.2 | Verbindungslimit: max. 20 gleichzeitige Verbindungen pro IP | hoch |
| REQ-002.3 | WebUI (`/`) nur aus LAN (192.168.178.0/24) erreichbar | mittel |
| REQ-002.4 | `/health` und `/catalog` nur aus LAN erreichbar | mittel |
| REQ-002.5 | HTTP-Antwort 429 bei Überschreitung mit Retry-After-Header | mittel |
| REQ-002.6 | Caching-Header für Tiles (max-age 24h) zur Lastreduzierung | mittel |
### Implementierungsplan
**Schicht 1 NPM Advanced Config (primärer Schutz)**
Rate Limiting passiert im Nginx Proxy Manager auf Proxy-Host-Ebene.
NPM erlaubt freie nginx-Direktiven im Feld „Advanced".
```nginx
# -- Rate Limiting --
# Speicher: 10 MB reicht fuer ~160.000 IP-Adressen
limit_req_zone $binary_remote_addr zone=tiles:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=tile_conn:10m;
# Burst von 60 erlaubt schnellen Kartenaufbau beim ersten Laden
limit_req zone=tiles burst=60 nodelay;
limit_conn tile_conn 20;
# 429 statt 503 zurueckgeben
limit_req_status 429;
limit_conn_status 429;
# -- Caching-Header fuer Tile-Endpunkte --
add_header Cache-Control "public, max-age=86400, stale-while-revalidate=3600" always;
add_header Vary "Accept-Encoding" always;
# -- Sicherheits-Header --
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
```
**Schicht 2 Interne Endpunkte abschirmen (im selben NPM Advanced Block)**
WebUI, Health und Catalog sollen von außen nicht erreichbar sein.
Da NPM keinen bedingten Block pro Location direkt unterstuetzt, wird ein
zweiter Proxy-Host fuer interne Endpunkte empfohlen:
```
Oeffentlicher Proxy-Host: tiles.rd13server.de -> http://HOST:9982
→ nur Tile-Pfade freigeben, alle anderen 403
→ Rate Limiting aktiv
Interner Proxy-Host (kein SSL nötig):
tiles-internal.lan -> http://192.168.178.5:9982
→ kein Rate Limiting
→ nur aus LAN erreichbar (Firewall / Access List im NPM)
```
Alternativ: Einzelner Proxy-Host mit NPM Access List „LAN only" fuer `/` und `/catalog`.
**Schicht 3 fail2ban (optionaler zweiter Layer)**
```ini
# /etc/fail2ban/filter.d/nginx-tile-ratelimit.conf
[Definition]
failregex = limiting requests, excess.* by zone "tiles".* client: <HOST>
ignoreregex =
# /etc/fail2ban/jail.local
[nginx-tile-ratelimit]
enabled = true
port = http,https
filter = nginx-tile-ratelimit
logpath = /var/log/nginx/access.log
maxretry = 10
findtime = 60
bantime = 3600
```
### Reihenfolge der Umsetzung
1. NPM Proxy-Host fuer `tiles.rd13server.de` anlegen (falls noch nicht vorhanden)
2. Rate-Limiting-Block in NPM Advanced Config eintragen
3. NPM Access List „LAN" anlegen und auf `/` + `/catalog` anwenden
4. Test: `ab -n 200 -c 10 https://tiles.rd13server.de/osm/10/0/0` → 429 nach Burst
5. fail2ban optional installieren und konfigurieren
---
## REQ-003 Caching (nicht-funktional)
**Status:** 🔴 offen
Tiles sollen gecacht werden, um wiederholte Requests zu vermeiden und
die Last auf den Server zu reduzieren.
**Akzeptanzkriterien:**
- Cache-Control-Header auf allen Tile-Responses: `public, max-age=86400`
- NPM leitet Header durch (keine Überschreibung)
---
## REQ-004 MediaWiki Integration
**Status:** ✅ umgesetzt (LocalSettings konfiguriert)
Kartographer nutzt `https://tiles.rd13server.de` als Tile-Server.
---
## REQ-005 Home Assistant Integration
**Status:** 📋 dokumentiert, nicht getestet
Satellit-Tiles als Raster-Layer in HA-Map-Card einbindbar.
**Satellit-Download-Entscheidung (2026-06-13):**
- Kein Pre-Built Planet-Satellit-MBTiles verfügbar → [ADR-002](../adr/002-no-highzoom-no-satellite-build.md)
- Download z011 (~38 GB, ~24h) via `scripts/download-satellite.py` möglich wenn gewünscht
- z12+ auf dieser Hardware nicht praktikabel (140 GB+, 35 Tage)
```bash
# Satellit z0-11 starten (optional, bei Bedarf):
SAT_MAX_ZOOM=11 python3 scripts/download-satellite.py data/satellite.mbtiles
```
---
## REQ-006 Satellit-Hybrid und Luftbild-Detailtiefe
**Status:** 🧊 **AUF EIS** Entscheidung getroffen, Implementierung folgt bei Bedarf
**Dezision:** 2026-06-22 umfangreiche Provider-Analyse durchgeführt. Feststellung: Mit freien Datenquellen ist Vollabdeckung z13/z14+ nicht praktikabel; empfohlen wird MapTiler On-Prem für Private Nutzung.
### Aktuelle Situation (z11 Sentinel-2)
Der aktuelle Satelliten-Datensatz (`data/satellite.mbtiles`) basiert auf
Sentinel-2 cloudless 2021 und endet real bei `maxzoom=11` (20 GB, 5.6 Mio Tiles).
Bei `z=14` oder `z=16` wird das Raster nur hochskaliert. Häuser, kleine Straßen
und Luftbilddetails sind nicht vorhanden.
```text
satellite.mbtiles
format: jpg
minzoom: 0
maxzoom: 11
size: ~20 GB (JPEG)
quality: 1060m Pixel (Sentinel-2)
description: Sentinel-2 cloudless 2021 (EOX CC BY 4.0)
```
### Provider-Matrix (Private Offline-Nutzung)
| **Quelle** | **Qualität** | **Lizenz** | **Kosten** | **Self-Hosting** | **Speicher z16** |
|---|---|---|---|---|---|
| **MapTiler On-Prem** | ⭐⭐⭐⭐⭐ (z1617) | ✅ Explizit erlaubt | €1.500 (One-Time) | ✅ JA | 200500 GB |
| **Sentinel-2 (EOX)** | ⭐⭐⭐ (z011) | ✅ CC BY 4.0 | Kostenlos | ✅ JA | N/A |
| **Google Maps API** | ⭐⭐⭐⭐⭐ | ❌ Offline verboten | €6001.200/Mo | ❌ NEIN | N/A |
| **Mapbox** | ⭐⭐⭐⭐ | ❌ Bulk-DL verboten | $600800/Mo | ❌ NEIN | N/A |
| **Sentinel Hub Free** | ⭐⭐⭐ | ✅ Kostenlos | Kostenlos | ⚠️ Script | 1.333+ Jahre¹ |
¹ Kostenlos: 100 PU/Mo = 100 z14-Tiles/Mo. Deutschland z14 = 1,6 Mio Tiles = 16.000 Monate = **1.333 Jahre Betrieb**.
### Kostenvergleich (3 Jahre, Private Nutzung)
| Szenario | **Jahr 1** | **Jahr 2+** | **Speicher** | **Gesamt** |
|---|---|---|---|---|
| Status Quo (z11) | €0 | €0 | 20 GB | ✅ **€0** |
| **MapTiler z14** | €500800 | €0 | 3050 GB | ✅ **€500800** |
| **MapTiler z16** | €1.2001.500 | €0 | 200300 GB | ✅ **€1.2001.500** |
| Sentinel Hub Free | €0 | €0 | 20 GB | ❌ **1.333 Jahre Betrieb** |
### Technische Integration (Option: MapTiler On-Prem)
Falls Upgrade beschlossen:
| Datei | Änderung | Impact |
|---|---|---|
| `docker-compose.yml` | Volume `/data/satellite-hq.mbtiles` | 1 Zeile |
| `config/tileserver.json` | Source `satellite-hq` eintragen | 3 Zeilen |
| `config/styles/satelite-world.json` | Layer hinzufügen | 5 Zeilen |
**Aufwand:** Niedrig (~2 Std Setup + Testing).
### Next Steps
1. **Phase 1 (Jetzt):** z11 Sentinel-2 in Produktion testen (24 Wochen)
- Frage: Reicht z11 für MediaWiki/HA/Nextcloud aus?
2. **Phase 2 (Falls nötig):** MapTiler On-Prem kaufen
- Kontakt: sales@maptiler.com
- Budget: €5001.500 (One-Time)
- Lieferzeit: 15 Tage
3. **Phase 3 (Integration):** 4 Dateien anpassen, `docker compose up -d`
4. **Phase 4 (Doku):** ADR-003 erstellen (Satellite-Entscheidungslog)