rd13_tile_server/docs/ADMIN.md

451 lines
14 KiB
Markdown
Raw Normal View History

# Administrator-Handbuch rd13_tile_server
> Zielgruppe: **Administratoren** Menschen, die das System betreiben, deployen und konfigurieren.
> Voraussetzung: Grundkenntnisse in Linux, Docker und der eingesetzten Stack (Martin, tileserver-gl).
---
## Systemvoraussetzungen
| Komponente | Mindestanforderung | Empfohlen |
|---|---|---|
| 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 |
---
## Deployment
### Erstes Aufsetzen
```bash
# 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 (Tile-Daten)
**Szenario: osm.mbtiles aktualisieren (24×/Jahr)**
```bash
# 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
```
### Höhere Zoom-Level bauen (auf Host-Rechner, nicht auf dem Server)
Planetiler läuft in einem eigenen Container auf dem **Host-Rechner** (MacBook, Desktop-PC
etc.) mit genug RAM. Das Ergebnis wird per `rsync` auf den Server übertragen.
**Europa z16 (empfohlen):** ~280 GB Host-Disk, ~812h, 12 CPUs / 28 GB RAM
```bash
# Auf dem HOST-RECHNER ausführen (im geklonten Repo-Verzeichnis):
# Europa z0-16 (~80 GB Output, ~8-12h, ~280 GB Disk nötig)
AREA=europe MAX_ZOOM=16 RAM=28g BUILD_CPUS=12 BUILD_MEM=30g \
docker compose -f docker-compose.build.yml up
# Germany z0-16 (kleiner Test: ~12 GB Output, ~2h, ~50 GB Disk)
AREA=germany MAX_ZOOM=16 RAM=8g \
docker compose -f docker-compose.build.yml up
# Fertiges MBTiles auf Server übertragen (resume-fähig):
rsync -avh --progress --partial \
./build/output/europe.mbtiles \
rd13server@192.168.178.6:/mnt/services-data/rd13_tile_server/data/osm-europe.mbtiles
# Martin auf dem Server neu starten:
ssh rd13server@192.168.178.6 \
"cd /mnt/services-data/rd13_tile_server && docker compose restart martin"
# Neue Source prüfen:
curl https://tiles.rd13server.de/catalog | python3 -m json.tool | grep osm-europe
```
Build-Output liegt lokal unter `./build/output/<AREA>.mbtiles` (gitignored).
Sources-Cache unter `./build/sources/` bei Rebuild nicht löschen (spart Re-Download).
### Planetiler Build-Steuerung (Cleanup/Resume)
Der Build trennt jetzt bewusst in kurzlebige und wiederverwendbare Daten:
- `build/output/` fertige MBTiles
- `build/sources/` Download-Cache (OSM + Zusatzdaten)
- `build/tmp/work/` laufzeitbezogene Temp-Daten (wegwerfbar)
- `build/tmp/reuse/` wiederverwendbare Feature-DB fuer `--reuse_featuredb`
Steuerung ueber Script:
```bash
# Status + Reuse-Readiness anzeigen
./scripts/planetiler-build-control.sh status
# Resume-Build: work leeren, reuse/sources behalten, dann starten
./scripts/planetiler-build-control.sh resume
# Fresh-Build: output+work+reuse leeren, sources behalten, dann starten
./scripts/planetiler-build-control.sh fresh
# Vollstaendig neu: output+sources+work+reuse leeren, dann starten
./scripts/planetiler-build-control.sh fresh-all
```
Hinweis: `reuse` ist nur aktiv, wenn diese Artefakte existieren:
- `build/tmp/reuse/feature.db/`
- `build/tmp/reuse/feature.db/feature.db.strings`
- `build/tmp/reuse/feature.db/feature.db.manifest`
### Satellit-Tiles herunterladen (einmalig, ~38 GB, ~24h)
Der Download läuft in einem eigenen Container vollständig unabhängig von
SSH-Sessions und VS Code. Resume-fähig: bei Unterbrechung einfach neu starten.
**Ressourcen:** 16 Threads, 1 GB RAM-Limit (~40 MB effektiv), 4 CPUs. `restart: on-failure`.
**Robustheit:** Schreibt in `satellite.mbtiles.part`, Umbenennung nach Abschluss. Resume-fähig.
EOX liefert trotz `.jpg`-URL einzelne PNG-Tiles. Der Download-Container konvertiert
PNG-Antworten direkt zu JPEG, damit Martin die fertige MBTiles-Datei als einheitliche
Rasterquelle laden kann. Wichtige Tuning-Variablen: `SAT_CHUNK` und `SAT_DB_BATCH`
begrenzen RAM/SQLite-Transaktionsgröße, `SAT_JPEG_QUALITY` steuert die JPEG-Qualität.
Falls eine bereits fertige Satellit-MBTiles-Datei gemischte JPEG/PNG-Tiles enthält,
erst eine vollständige Sicherung erstellen und dann nur die PNG-Tiles konvertieren.
Das Script ist resume-fähig: bereits konvertierte JPEG-Tiles werden bei erneutem Start
übersprungen, maximal der letzte nicht committete Batch wird wiederholt.
```bash
cd /mnt/services-data/rd13_tile_server
docker compose stop martin
cp data/satellite.mbtiles data/satellite.mbtiles.backup-$(date +%Y%m%d-%H%M%S)
docker run --rm \
-v ./data:/data \
-v ./scripts/convert-satellite-to-jpeg.py:/convert.py:ro \
-e SAT_CONVERT_BATCH=500 \
-e SAT_CONVERT_SLEEP=0.02 \
-e SAT_JPEG_QUALITY=90 \
python:3.12-slim \
sh -c "pip install --no-cache-dir Pillow && python3 /convert.py /data/satellite.mbtiles"
# Nach Konvertierung verifizieren
docker run --rm -v ./data:/data python:3.12-slim python3 -c \
"import sqlite3; conn=sqlite3.connect('/data/satellite.mbtiles'); \
fmt=conn.execute('SELECT value FROM metadata WHERE name=\"format\"').fetchone()[0]; \
total=conn.execute('SELECT COUNT(*) FROM tiles').fetchone()[0]; \
quick=conn.execute('PRAGMA quick_check').fetchone()[0]; \
conn.close(); print(f'✓ format={fmt} tiles={total} quick_check={quick}')"
# Martin neu starten
docker compose up -d martin
curl -s http://localhost:9982/health
```
**Download-Szenario (normal, neu empfohlen):**
```bash
cd /mnt/services-data/rd13_tile_server
# Starten (läuft im Hintergrund, résumé-fähig, konvertiert PNG→JPEG on-the-fly)
docker compose -f docker-compose.download.yml up -d
# Status verfolgen
docker compose -f docker-compose.download.yml logs -f
# Pausieren
docker compose -f docker-compose.download.yml stop
# Fortsetzen (bereits heruntergeladene und konvertierte Tiles werden übersprungen)
docker compose -f docker-compose.download.yml up -d
# Nach Fertigstellung (check für ~5.6M Tiles, nur JPEG)
docker compose -f docker-compose.download.yml logs | tail -5
docker compose ps
curl -s http://localhost:9982/catalog | jq '.[] | select(.id == "satellite")'
```
Wenn fertig: `data/satellite.mbtiles` (~20 GB nach PNG→JPEG-Konvertierung) ist bereit.
Martin lädt sie automatisch beim nächsten Restart als Source `satellite`.
### Service Restart / Update Images
```bash
# Nur Image-Updates (Martin, tileserver-gl)
docker compose pull
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
### 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/`
**marker-api (Marker-PNG-Generierung)**
- Code: `services/marker-api/` (Go, 0 externe Dependencies)
- Image: `cr.rd13server.de/cschulz/rd13_tile_server-marker-api:latest` (Forgejo Registry)
- API Root: `http://localhost:9984`
- Endpunkt: `/styles/v4/marker/{type}+{hexcolor}(@{scale}x).png`
- Typen: `pin-s` (20×50px), `pin-m` (30×70px), `pin-l` (35×90px) @1x exakte Kartographer-Maße (mapbox-lib.js `sizes`); weißer Rand + Innenpunkt, 85% opak
- Ankerpunkt: Nadelspitze liegt bei Pixel (w/2, h/2) = `iconAnchor` in mapbox-lib.js → geografische Koordinate zeigt exakt auf Spitze
- Image neu bauen: `docker compose build marker-api && docker compose up -d marker-api`
- CI: Forgejo baut + pusht automatisch bei Änderungen in `services/marker-api/`
### 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
```
### Nextcloud + Home Assistant Integration (Quick Rollout)
1. Endpunkte lokal pruefen:
```bash
curl -I "http://localhost:9983/styles/osm-intl/14/8802/5373.png"
curl -I "http://localhost:9983/styles/europa-detail/16/35210/21493.png"
curl -I "http://localhost:9983/styles/satelite-world/13/4401/2686.png"
```
2. Nextcloud Maps setzen:
```bash
# Im Nextcloud-Container ausfuehren
php occ config:app:set maps tileserverUrl \
--value="https://tiles.rd13server.de/styles/europa-detail/{z}/{x}/{y}.png"
```
3. Home Assistant Lovelace Tile-Layer auf einen der verifizierten Endpunkte setzen:
- `https://tiles.rd13server.de/styles/osm-intl/{z}/{x}/{y}.png`
- `https://tiles.rd13server.de/styles/europa-detail/{z}/{x}/{y}.png`
- `https://tiles.rd13server.de/styles/satelite-world/{z}/{x}/{y}.png`
4. Externen Test aus Browser oder HA/Nextcloud Host:
```bash
curl -I "https://tiles.rd13server.de/styles/europa-detail/16/35210/21493.png"
```
---
## 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 1020 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 | 24×/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
```
<!-- TODO: Alle relevanten Env-Vars dokumentieren -->
| Variable | Pflicht | Default | Beschreibung |
|---|---|---|---|
| `EXAMPLE_VAR` | ✓ | | Beschreibung |
### Persistente Daten (`/data/`)
Alle persistenten Daten liegen unter `/data/<service>/` im Repo-Root:
<!-- TODO: Alle Service-Unterordner und was drin liegt -->
| Pfad | Inhalt | Backup-Priorität |
|---|---|---|
| `data/<service>/` | … | hoch/mittel/niedrig |
**Backup-Hinweise:**
- `/data/` komplett sichern vor jedem Update
- Empfehlung: tägliches Backup via Cron / Restic / rsync
---
## Monitoring & Logs
<!-- TODO: Wie überwacht man das System? Wo sind die Logs? -->
```bash
# Logs ansehen
docker compose logs -f <service>
# Status prüfen
docker compose ps
```
---
## Sicherheit
<!-- TODO: Firewall-Regeln, Portfreigaben, TLS-Setup etc. -->
- Offene Ports: …
- TLS: …
- Zugriffskontrolle: …
---
## Troubleshooting
| Symptom | Ursache | Lösung |
|---|---|---|
| … | … | … |
---
## Disaster Recovery
<!-- TODO: Was tun wenn es brennt? -->
1. Dienst stoppen: `docker compose down`
2. Backup einspielen: …
3. Dienst neu starten: `docker compose up -d`