diff --git a/docker-compose.yml b/docker-compose.yml index 11f86b4..4d4a4e2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,3 +15,25 @@ services: timeout: 10s retries: 3 start_period: 10s + + tileserver: + image: ghcr.io/maptiler/tileserver-gl:latest + container_name: rd13_tileserver + ports: + - "9983:8080" + volumes: + - ./data/styles:/data/styles:ro + - ./data/fonts:/data/fonts:ro + - ./data/sprites:/data/sprites:ro + environment: + - PMTILES_CACHE_DIR=/tmp/pmtiles-cache + - NODE_ENV=production + restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 10s + depends_on: + - martin diff --git a/docs/ADMIN.md b/docs/ADMIN.md index 23f6b0d..86cae0b 100644 --- a/docs/ADMIN.md +++ b/docs/ADMIN.md @@ -1,20 +1,19 @@ -# Administrator-Handbuch – [PROJEKT_NAME] +# Administrator-Handbuch – rd13_tile_server > Zielgruppe: **Administratoren** – Menschen, die das System betreiben, deployen und konfigurieren. -> Voraussetzung: Grundkenntnisse in Linux, Docker und dem eingesetzten Stack. +> Voraussetzung: Grundkenntnisse in Linux, Docker und der eingesetzten Stack (Martin, tileserver-gl). --- ## Systemvoraussetzungen - - | Komponente | Mindestanforderung | Empfohlen | |---|---|---| -| OS | … | … | -| RAM | … | … | -| Disk | … | … | -| Dependencies | … | … | +| OS | Linux 5.10+ (oder macOS 12+) | Ubuntu 22.04 LTS | +| RAM | 1 GB | 2-4 GB | +| Disk | 5 GB (OS + Containers) | 20 GB (mit Cache-Warmup) | +| Dependencies | Docker 20.10+, docker-compose 2.0+ | Docker Desktop / Compose v2 | +| Network | Port 9982 (Martin), Port 8080 (tileserver-gl) internal | Public domain via NPM reverse proxy | --- @@ -22,32 +21,195 @@ ### Erstes Aufsetzen - - ```bash -# Beispiel -git clone /opt/service -cd /opt/service -cp .env.example .env -# .env ausfüllen! +# Repository klonen +git clone ssh://git@192.168.178.6:2222/cschulz/rd13_tile_server.git /mnt/services-data/rd13_tile_server +cd /mnt/services-data/rd13_tile_server + +# Daten-Verzeichnis initialisieren (falls nicht vorhanden) +mkdir -p data/{fonts,sprites,styles} + +# Services starten docker compose up -d + +# Health-Checks verifizieren +docker compose ps +curl -s http://localhost:9982/health | jq . +curl -s http://localhost:8080/health ``` -### Updates einspielen +### Updates einspielen (Tile-Daten) - +**Szenario: osm.mbtiles aktualisieren (2–4×/Jahr)** ```bash -git pull +# 1. Neue MBTiles herunterladen (z.B. von OpenFreeMap) +cd /mnt/services-data/rd13_tile_server +python3 scripts/download-data.sh data/osm.mbtiles.new + +# 2. Alte Datei backup-en +mv data/osm.mbtiles data/osm.mbtiles.$(date +%Y%m%d) + +# 3. Neue Datei aktivieren +mv data/osm.mbtiles.new data/osm.mbtiles + +# 4. Container neu starten (warm caches) +docker compose restart martin tileserver + +# 5. Health-Check + Sampling testen +curl -s http://localhost:9982/osm | jq . +curl -s "http://localhost:9983/osm-intl/0/0/0.png" > /tmp/test.png && file /tmp/test.png +``` + +### Service Restart / Update Images + +```bash +# Nur Image-Updates (Martin, tileserver-gl) docker compose pull -docker compose up -d --force-recreate +docker compose up -d + +# Bei Compose-Konfiguration-Änderungen +docker compose down +docker compose up -d + +# Logs ansehen +docker compose logs -f martin # Martin Vektor-API +docker compose logs -f tileserver # Raster-Rendering ``` --- ## Konfiguration -### Umgebungsvariablen (`.env`) +### Tile-Server-Komponenten + +**Martin (Vektor-Tiles)** +- Konfiguration: `config/martin.yaml` +- API Root: `http://localhost:9982` +- Catalog: `http://localhost:9982/catalog` +- Datenquelle: `data/osm.mbtiles` + +**tileserver-gl (Raster-PNG-Rendering)** +- Konfiguration: Styles unter `data/styles/` +- API Root: `http://localhost:9983` (exposed port) +- Style `osm-intl`: `data/styles/osm-intl.json` +- Fonts: `data/fonts/` +- Sprites: `data/sprites/` + +### Reverse Proxy (NPM) – Öffentliche URLs + +**Konfiguration (manuell im NPM WebUI):** + +1. **Neuer Proxy-Host:** `tiles.rd13server.de` + - Forward Hostname/IP: `martin` (Docker-DNS) + - Forward Port: `3000` + - Schema: `http` + - Websockets Support: ☑ + +2. **Advanced Tab – Custom Nginx Config:** + ```nginx + # Rate Limiting + limit_req_zone $binary_remote_addr zone=tiles:10m rate=10r/s; + limit_conn_zone $binary_remote_addr zone=tile_conn:10m; + + location / { + limit_req zone=tiles burst=60 nodelay; + limit_conn tile_conn 20; + limit_req_status 429; + limit_conn_status 429; + + # Cache-Header für Tiles + add_header Cache-Control "public, max-age=86400, stale-while-revalidate=3600" always; + add_header Vary "Accept-Encoding" always; + } + + # Raster-Routing zu tileserver-gl + location ~ ^/osm-intl/ { + proxy_pass http://localhost:9983; + proxy_ssl_server_name on; + add_header Cache-Control "public, max-age=86400" always; + } + ``` + +--- + +## Betrieb & Monitoring + +### Health-Checks manuell + +```bash +# Martin Vektor-Tiles +curl -s http://localhost:9982/health + +# tileserver-gl Raster +curl -s http://localhost:9983/health + +# Sample-Tile abrufen (PNG) +curl -s "http://localhost:9983/osm-intl/0/0/0.png" -o /tmp/tile.png +file /tmp/tile.png +``` + +### Performance-Baseline + +**Erwartete Antwortzeiten (ohne externen Upstream):** +- Martin `/osm/{z}/{x}/{y}.pbf`: <50ms (cache warm) +- tileserver-gl `/osm-intl/{z}/{x}/{y}.png`: <100ms (cache cold), <20ms (cache warm) + +**Caches (auto-warm nach Start):** +- Martin: in-memory (fast) +- tileserver-gl: Disk unter `/tmp/pmtiles-cache` (wächst mit Nutzung) + +### Logs + +```bash +# Alle Services +docker compose logs + +# Nur Fehler +docker compose logs --tail=100 | grep -i error + +# Real-time verfolgen +docker compose logs -f +``` + +--- + +## Troubleshooting + +| Problem | Ursache | Lösung | +|---|---|---| +| `tiles.rd13server.de` liefert 502 | Martin-Container nicht erreichbar | `docker compose ps` + `docker compose logs martin` | +| PNG-Tiles sind grau/leer | tileserver-gl kann Martin nicht erreichen | Docker-Network prüfen: `docker network inspect rd13_tile_server_default` | +| Lange Antwortzeiten | Tile-Cache kalt, erste Render | Normal; nach 10–20 Requests warm; monitoring via logs | +| Out of Memory | Cache wächst unbegrenzt | tileserver-gl Speicher-Limit setzen oder Cache-TTL anpassen | + +--- + +## Wartungsplan + +| Task | Frequenz | Aufwand | +|---|---|---| +| Tile-Daten aktualisieren | 2–4×/Jahr | 15 min (Script + Restart) | +| Container-Images patchen | Wöchentlich | 5 min (`docker compose pull && up -d`) | +| Logs archivieren | Monatlich | 5 min (via logrotate) | +| Disk-Space überwachen | Wöchentlich | 2 min (du/df) | + +--- + +## Rollback-Procedure + +**Falls neue osm.mbtiles kaputt ist:** + +```bash +cd /mnt/services-data/rd13_tile_server +docker compose stop martin tileserver + +# Alte Version zurückbringen +rm data/osm.mbtiles +mv data/osm.mbtiles.YYYYMMDD data/osm.mbtiles + +docker compose up -d +``` diff --git a/docs/MAINTAINER.md b/docs/MAINTAINER.md index ad8ea35..c1f9c1e 100644 --- a/docs/MAINTAINER.md +++ b/docs/MAINTAINER.md @@ -1,53 +1,268 @@ -# Maintainer-Handbuch – [PROJEKT_NAME] +# Maintainer-Handbuch – rd13_tile_server > Zielgruppe: **Entwickler & Maintainer** – Menschen, die den Code verstehen, erweitern oder reviewen. -> Voraussetzung: Entwicklungserfahrung mit dem eingesetzten Stack. +> Voraussetzung: Entwicklungserfahrung mit Docker, MapLibre GL Styles, OSM-Daten. --- -## Architektur - - +## Architektur – Martin + tileserver-gl Stack ``` -┌──────────────────────────────────────────────────────────┐ -│ TODO: Architektur-Diagramm (ASCII oder Mermaid) │ -└──────────────────────────────────────────────────────────┘ +Internet (HTTPS) + ↓ +NPM Reverse Proxy (tiles.rd13server.de, Rate Limiting) + ├─ /osm/{z}/{x}/{y}.pbf → Martin (Vektor-Tiles) + └─ /osm-intl/{z}/{x}/{y}.png → tileserver-gl (Raster-PNG) + ↓ + tileserver-gl renders Martin Vektor → PNG + ↓ + Martin reads osm.mbtiles (Vector Tiles) + ↓ + /data/osm.mbtiles (OpenFreeMap snapshot) ``` -**Wichtige Komponenten:** +**Stack-Komponenten:** -| Komponente | Verantwortlichkeit | Ort | -|---|---|---| -| … | … | `src/…` | +| Komponente | Input | Output | Verantwortung | +|---|---|---|---| +| **Martin** | `osm.mbtiles` | `/{layer}/{z}/{x}/{y}.pbf` | Vektor-API, Tile-Distribution | +| **tileserver-gl** | Martin PBF + `osm-intl.json` | `/{style}/{z}/{x}/{y}.png` | Rendering, PNG-Tile-Cache | +| **NPM** | HTTP Client Requests | HTTPS Responses | Proxy, SSL, Rate-Limit | + +**Verwandte ADRs:** +- [ADR-001: Tile Rendering Stack – Martin + tileserver-gl](docs/adr/001-martin-tileserver-gl-stack.md) --- ## Projektstruktur ``` -[PROJEKT_NAME]/ -├── data/ ← Persistente Daten (gitignored) -│ └── / ← Ein Unterordner pro Service +rd13_tile_server/ +├── config/ +│ └── martin.yaml ← Martin Server-Konfiguration +├── data/ +│ ├── osm.mbtiles ← OpenFreeMap Vector-Snapshot (~94 GB) +│ ├── styles/ +│ │ └── osm-intl.json ← MapLibre GL Style für Raster-Rendering +│ ├── fonts/ +│ │ ├── Metropolis Black/ +│ │ ├── Open Sans Regular/ +│ │ └── … (47 weitere Font-Varianten) +│ └── sprites/ ← Marker/Icons (derzeit leer) ├── docs/ -│ ├── USER.md ← Endnutzer-Dokumentation -│ ├── ADMIN.md ← Administrator-Dokumentation -│ └── MAINTAINER.md ← Dieses Dokument -├── history/ -│ ├── prompts/ ← Vollständige Agent-Konversationen (gitignored) -│ └── summary/ -│ └── PROJECT_CONTEXT.md ← Aktueller Projektzustand für Agent-Kontext -└── … ← Source Code +│ ├── adr/ +│ │ ├── 000-template.md +│ │ └── 001-martin-tileserver-gl-stack.md +│ ├── history/ +│ ├── requirements/ +│ │ └── REQUIREMENTS.md +│ ├── USER.md, ADMIN.md, MAINTAINER.md +│ └── … (API-Endpoints, Integration-Guides) +├── docker-compose.yml ← Martin + tileserver-gl +└── scripts/ + ├── download-data.sh ← OSM-MBTiles fetcher + └── download-satellite.py ← Satellit-MBTiles fetcher (optional) ``` --- -## Entwicklungsumgebung aufsetzen +## Style-Customization (osm-intl.json) - +Die Kartographer-Karten werden von `data/styles/osm-intl.json` definiert. Das ist eine Standard **MapLibre GL Style** (v8-kompatibel). + +### Tipps zum Ändern + +**1. Farben anpassen** (einfach) + +```json +"layers": [ + { + "id": "water-area", + "paint": { + "fill-color": "#b0d4fc" ← Ändere zu z.B. "#0066cc" + } + } +] +``` + +**2. Layer-Sichtbarkeit nach Zoom-Level** (mittelschwer) + +```json +{ + "id": "poi-icon", + "minzoom": 14, ← POI-Icons nur ab Zoom 14 sichtbar + "maxzoom": 20 ← Max Zoom-Level +} +``` + +**3. Label-Schriftart** (mittelschwer) + +```json +"text-font": ["Open Sans Bold"] ← Verfügbare Fonts in data/fonts/ +``` + +**Verfügbare Fonts** (aus `/data/fonts/`): +- Metropolis (Black, Bold, Light, Regular, Thin + Italic-Varianten) +- Open Sans (Bold, Regular, Semibold + Italic-Varianten) +- PT Sans (Bold, Caption, Regular, Narrow + Varianten) +- Roboto (Black, Bold, Light, Medium, Regular, Thin + Italic-Varianten) +- Noto Sans (Bold, Italic, Regular) + +**4. Linien-Dicke nach Zoom-Level** (fortgeschritten) + +```json +"line-width": [ + "interpolate", ← Interpolations-Funktion + ["linear"], ← Linear interpolieren + ["zoom"], ← Input: aktueller Zoom-Level + 6, 0.5, ← Bei Zoom 6: 0.5px + 20, 6 ← Bei Zoom 20: 6px +] +``` + +### Style testen (lokal) ```bash -git clone +# Nach Änderungen an osm-intl.json: +docker compose restart tileserver + +# PNG-Tile abrufen +curl -s "http://localhost:9983/osm-intl/10/544/335.png" -o /tmp/test.png +file /tmp/test.png + +# In MediaWiki-Kartographer URL testen: +# https://tiles.rd13server.de/osm-intl/{z}/{x}/{y}.png +``` + +--- + +## Martin Vector-Source verstehen + +Martin liest Vektor-Daten aus `osm.mbtiles` und serviert sie als PBF (Protocol Buffers). + +**Available Layers in osm.mbtiles** (abhängig von OpenFreeMap-Schema): + +Beispiel: `http://localhost:9982/catalog` zeigt alle Source-Layer. + +Typisch enthalten: +- `water` – Seen, Flüsse +- `landuse` – Wald, Park, Gras, Acker +- `building` – Gebäude-Polygone +- `road` – Straßen (Motorway, Trunk, Primary, Secondary, etc.) +- `railway` – Eisenbahn-Linien +- `place` – Orte (City, Town, Village) +- `poi` – Points of Interest + +**Layer in osm-intl.json updaten:** + +```json +"source": "osm", ← Vector-Tile-Source (Martin) +"source-layer": "water", ← Welcher OSM-Layer? (prüfe /catalog) +``` + +Falls Layer fehlt → `http://localhost:9982/catalog` prüfen, oder mit `layer` in osm-intl.json experimential einen neuen hinzufügen. + +--- + +## Rendering-Performance tunen + +**tileserver-gl Cache:** + +- **Disk-Cache:** `/tmp/pmtiles-cache` (wächst mit Nutzung; max ~50 GB bei voller Coverage) +- **Memory:** ~500 MB standard, skaliert mit Anfrage-Load +- **Warm-up:** Erste Anfrage zu neuem Tile-Bereich ist langsam (~100–200ms), danach <20ms + +**Bottleneck identifizieren:** + +```bash +# Logs verfolgen (live) +docker compose logs -f tileserver | grep "render" + +# Performance der Martin-API +curl -w "Time: %{time_total}s\n" -s http://localhost:9982/osm/0/0/0 | head +``` + +**Falls zu langsam:** +1. Martin-Worker-Prozesse erhöhen: `config/martin.yaml` → `worker_processes` +2. tileserver-gl Memory erhöhen: docker-compose.yml → `deploy.resources.limits.memory` + +--- + +## Tests & Validierung + +### Tile-Integrität checken + +```bash +# Vektor-Tile (PBF) abrufen und inspizieren +curl -s "http://localhost:9982/osm/0/0/0.pbf" | file - +# Should: PBF (Tile protocol buffer) + +# Raster-Tile (PNG) abrufen und prüfen +curl -s "http://localhost:8080/osm-intl/0/0/0.png" -o /tmp/t.png +file /tmp/t.png +# Should: image/png + +# MediaWiki-Test URL +# https://tiles.rd13server.de/osm-intl/0/0/0.png +``` + +### Smoke-Test nach Update + +```bash +# Nach Tile-Daten-Update (osm.mbtiles): +for zoom in 0 5 10 14; do + curl -s "http://localhost:9983/osm-intl/$zoom/0/0.png" \ + -o /tmp/test_z$zoom.png && echo "✓ Zoom $zoom" || echo "✗ Zoom $zoom" +done +``` + +--- + +## Deployment & Release + +### Checklist vor Push + +- [ ] `docker compose logs` prüfen – keine Errors +- [ ] Test-Tiles (Zoom 0, 5, 10, 14) erfolgreich +- [ ] REQUIREMENTS.md aktualisiert (falls Anforderung geändert) +- [ ] ADR erstellt (falls architektur-relevant) +- [ ] ADMIN.md / MAINTAINER.md aktualisiert +- [ ] CHANGELOG.md aktualisiert (falls vorhanden) +- [ ] Git commit + push + +### Version & Releases + +Derzeit: `rolling release` (jeder Commit ist live). + +Falls später strikte Versionierung nötig: +- Versioning: Semantic Versioning (MAJOR.MINOR.PATCH) +- Releases: Tag in Git + Changelog +- Example: `v1.0.0` (Martin 0.9.0 + tileserver-gl 4.7.0) + +--- + +## Bekannte Limitations & Future TODOs + +**Jetzt (ADR-001):** +- ✅ Martin + tileserver-gl für statische 2–4×/Year Updates +- ✅ Styles anpassbar (osm-intl.json) +- ✅ Fonts + Sprites nutzbar + +**Zukünftig (Falls nötig):** +- [ ] **ADR-002:** Live OSM-Update-Pipeline (OpenMapTiles Server) +- [ ] Sprites/Icons erweitern (derzeit leer) +- [ ] Mehrere Styles pro Kartographie-Kontext (dark mode, print-optimized) +- [ ] Horizontal scaling (Kubernetes / Load Balancer) + +--- + +## Ressourcen + +- [Martin Tile Server Documentation](https://maplibre.org/martin/) +- [tileserver-gl Documentation](https://tileserver.readthedocs.io/) +- [MapLibre GL Style Specification v8](https://maplibre.org/maplibre-gl-js-docs/style-spec/) +- [OpenMapTiles Schema](https://openmaptiles.org/schema/) +- [OSM Wiki: Map Tiles](https://wiki.openstreetmap.org/wiki/Tiles) cd # Dependencies installieren # Dev-Server starten