feat: initial tile server setup
- TileServer-GL + nginx reverse proxy (docker-compose) - CORS-Konfiguration für MediaWiki, Nextcloud & weitere Dienste - Rate-Limiting & Tile-Caching-Header via nginx - config/config.json: OSM + Satellitenkacheln - scripts/download-data.sh: Planetiler (OSM), Sentinel-2 Hinweise - docs: API-Endpoints, MediaWiki Kartographer, Nextcloud Maps - .gitignore: MBTiles/PMTiles und .env ausgeschlossen
This commit is contained in:
commit
bfd8dfdf96
11 changed files with 383 additions and 0 deletions
2
.env.example
Normal file
2
.env.example
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
# Beispiel – in .env kopieren und anpassen
|
||||
TILE_PORT=8080
|
||||
12
.gitignore
vendored
Normal file
12
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Datendateien – nicht im Repo (können mehrere GB groß sein)
|
||||
data/*.mbtiles
|
||||
data/*.pmtiles
|
||||
data/fonts/
|
||||
data/sprites/
|
||||
data/styles/
|
||||
|
||||
# Laufzeit
|
||||
.env
|
||||
|
||||
# Docker
|
||||
*.log
|
||||
29
config/config.json
Normal file
29
config/config.json
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"options": {
|
||||
"paths": {
|
||||
"root": "",
|
||||
"fonts": "fonts",
|
||||
"sprites": "sprites",
|
||||
"styles": "styles",
|
||||
"mbtiles": ""
|
||||
},
|
||||
"serveAllFonts": true,
|
||||
"serveAllStyles": true
|
||||
},
|
||||
"data": {
|
||||
"osm-openmaptiles": {
|
||||
"mbtiles": "osm.mbtiles"
|
||||
},
|
||||
"satellite": {
|
||||
"mbtiles": "satellite.mbtiles"
|
||||
}
|
||||
},
|
||||
"styles": {
|
||||
"osm-bright": {
|
||||
"style": "styles/osm-bright/style.json"
|
||||
},
|
||||
"satellite-hybrid": {
|
||||
"style": "styles/satellite-hybrid/style.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
7
data/.gitkeep
Normal file
7
data/.gitkeep
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# MBTiles-Dateien hier ablegen
|
||||
#
|
||||
# Benötigte Dateien (nicht im Git, da zu groß):
|
||||
# osm.mbtiles – OpenStreetMap Vektorkacheln (via Planetiler)
|
||||
# satellite.mbtiles – Satellitenkacheln
|
||||
#
|
||||
# Download-Skript: ../scripts/download-data.sh
|
||||
30
docker-compose.yml
Normal file
30
docker-compose.yml
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
services:
|
||||
tileserver:
|
||||
image: maptiler/tileserver-gl:latest
|
||||
container_name: rd13_tileserver
|
||||
expose:
|
||||
- "8080"
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- ./config/config.json:/data/config.json:ro
|
||||
command: ["--config", "/data/config.json", "--port", "8080", "--verbose"]
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 20s
|
||||
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: rd13_tileserver_proxy
|
||||
ports:
|
||||
- "${TILE_PORT:-8080}:80"
|
||||
volumes:
|
||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- ./nginx/cors.conf:/etc/nginx/cors.conf:ro
|
||||
depends_on:
|
||||
tileserver:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
34
docs/api-endpoints.md
Normal file
34
docs/api-endpoints.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Allgemeine Tile-Server Endpunkte
|
||||
#
|
||||
# Sobald der Server läuft, sind folgende Endpoints verfügbar:
|
||||
#
|
||||
# Web-Interface:
|
||||
# http://SERVER:PORT/
|
||||
#
|
||||
# Styles (Raster-Tiles, PNG):
|
||||
# http://SERVER:PORT/styles/osm-bright/{z}/{x}/{y}.png ← OSM
|
||||
# http://SERVER:PORT/styles/satellite-hybrid/{z}/{x}/{y}.png ← Satellit
|
||||
# http://SERVER:PORT/styles/osm-bright/{z}/{x}/{y}@2x.png ← Retina
|
||||
#
|
||||
# Daten (Vektor-Tiles, PBF):
|
||||
# http://SERVER:PORT/data/osm-openmaptiles/{z}/{x}/{y}.pbf
|
||||
# http://SERVER:PORT/data/satellite/{z}/{x}/{y}.png
|
||||
#
|
||||
# TileJSON (Metadaten für Leaflet, MapLibre, etc.):
|
||||
# http://SERVER:PORT/styles/osm-bright.json
|
||||
# http://SERVER:PORT/data/osm-openmaptiles.json
|
||||
#
|
||||
# WMTS (für QGIS, ArcGIS, etc.):
|
||||
# http://SERVER:PORT/styles/osm-bright/wmts
|
||||
#
|
||||
# Leaflet.js Beispiel:
|
||||
# L.tileLayer('http://SERVER:PORT/styles/osm-bright/{z}/{x}/{y}.png', {
|
||||
# attribution: '© OpenMapTiles © OpenStreetMap contributors',
|
||||
# maxZoom: 20
|
||||
# }).addTo(map);
|
||||
#
|
||||
# MapLibre GL Beispiel:
|
||||
# new maplibregl.Map({
|
||||
# style: 'http://SERVER:PORT/styles/osm-bright.json',
|
||||
# container: 'map'
|
||||
# });
|
||||
35
docs/mediawiki-config.php
Normal file
35
docs/mediawiki-config.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# MediaWiki Kartographer – Konfiguration für LocalSettings.php
|
||||
#
|
||||
# Füge diese Zeilen in deine LocalSettings.php ein.
|
||||
# Ersetze TILE_SERVER_URL mit der tatsächlichen URL deines Servers.
|
||||
#
|
||||
# Dokumentation: https://www.mediawiki.org/wiki/Extension:Kartographer
|
||||
|
||||
# Kartographer aktivieren
|
||||
wfLoadExtension( 'Kartographer' );
|
||||
|
||||
# Tile-Server URL (dein selbst gehosteter Server)
|
||||
$wgKartographerMapServer = 'http://TILE_SERVER_URL:8080';
|
||||
|
||||
# Welche Kartenstile stehen zur Verfügung?
|
||||
# Die Namen entsprechen den Keys in config/config.json → "styles"
|
||||
$wgKartographerStyles = [
|
||||
'osm-bright', # OpenStreetMap Vektorkarte
|
||||
'satellite-hybrid', # Satellitenkarte
|
||||
];
|
||||
|
||||
# Standard-Stil
|
||||
$wgKartographerDfltStyle = 'osm-bright';
|
||||
|
||||
# Tile-URL-Muster für Raster-Tiles (XYZ)
|
||||
# TileServer-GL stellt Tiles unter /styles/{style}/{z}/{x}/{y}.png bereit
|
||||
$wgKartographerSrcsetScales = [ 1, 1.5, 2 ];
|
||||
|
||||
# Optional: statische Kartenbilder für Vorschau (Mapshot)
|
||||
# $wgKartographerStaticFullWidth = true;
|
||||
|
||||
# Beispiel-Verwendung in einem Wiki-Artikel:
|
||||
# <maplink zoom="12" latitude="48.137" longitude="11.576">
|
||||
# {"type":"Feature","geometry":{"type":"Point","coordinates":[11.576,48.137]},
|
||||
# "properties":{"title":"München","description":"Landeshauptstadt"}}
|
||||
# </maplink>
|
||||
27
docs/nextcloud-config.md
Normal file
27
docs/nextcloud-config.md
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Nextcloud Maps – eigenen Tile-Server verwenden
|
||||
#
|
||||
# Nextcloud Maps App: https://apps.nextcloud.com/apps/maps
|
||||
#
|
||||
# Konfiguration in Nextcloud Admin-Panel:
|
||||
# Einstellungen → Verwaltung → Maps → Tile server URL
|
||||
#
|
||||
# Tile-Server-URLs (TileServer-GL XYZ-Format):
|
||||
#
|
||||
# OSM Vektorkarte (als Rasterbild gerendert):
|
||||
# http://TILE_SERVER_URL:8080/styles/osm-bright/{z}/{x}/{y}.png
|
||||
#
|
||||
# Satellitenkarte:
|
||||
# http://TILE_SERVER_URL:8080/styles/satellite-hybrid/{z}/{x}/{y}.png
|
||||
#
|
||||
# Rohe Vektorkacheln (OpenMapTiles Schema):
|
||||
# http://TILE_SERVER_URL:8080/data/osm-openmaptiles/{z}/{x}/{y}.pbf
|
||||
#
|
||||
# Über occ (Kommandozeile) setzen:
|
||||
# php occ config:app:set maps tileserverUrl \
|
||||
# --value="http://TILE_SERVER_URL:8080/styles/osm-bright/{z}/{x}/{y}.png"
|
||||
|
||||
# Beispiel für docker-compose override wenn Nextcloud im selben Stack läuft:
|
||||
#
|
||||
# nextcloud:
|
||||
# environment:
|
||||
# MAPS_TILE_SERVER: "http://rd13_tileserver_proxy/styles/osm-bright/{z}/{x}/{y}.png"
|
||||
4
nginx/cors.conf
Normal file
4
nginx/cors.conf
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# Shared CORS headers – included by nginx.conf
|
||||
# Wird automatisch auf alle Responses angewendet.
|
||||
# Für produktiven Betrieb kann Origin auf deine Domains eingeschränkt werden:
|
||||
# add_header Access-Control-Allow-Origin "https://wiki.example.com" always;
|
||||
53
nginx/nginx.conf
Normal file
53
nginx/nginx.conf
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
worker_processes auto;
|
||||
events { worker_connections 1024; }
|
||||
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
|
||||
# Rate limiting – schützt vor Missbrauch durch externe Dienste
|
||||
limit_req_zone $binary_remote_addr zone=tiles:10m rate=100r/s;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
# CORS für alle Clients (MediaWiki, Nextcloud, etc.)
|
||||
include /etc/nginx/cors.conf;
|
||||
|
||||
location / {
|
||||
limit_req zone=tiles burst=200 nodelay;
|
||||
|
||||
proxy_pass http://tileserver:8080;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# Tile-Caching-Header
|
||||
proxy_hide_header Cache-Control;
|
||||
add_header Cache-Control "public, max-age=86400, stale-while-revalidate=3600";
|
||||
|
||||
# CORS-Header (aus cors.conf)
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
|
||||
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept" always;
|
||||
}
|
||||
|
||||
# CORS Preflight
|
||||
location ~* \.(pbf|png|jpg|json)$ {
|
||||
if ($request_method = OPTIONS) {
|
||||
add_header Access-Control-Allow-Origin "*";
|
||||
add_header Access-Control-Allow-Methods "GET, OPTIONS";
|
||||
add_header Access-Control-Max-Age 86400;
|
||||
return 204;
|
||||
}
|
||||
|
||||
proxy_pass http://tileserver:8080;
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
add_header Cache-Control "public, max-age=86400";
|
||||
}
|
||||
}
|
||||
}
|
||||
150
scripts/download-data.sh
Normal file
150
scripts/download-data.sh
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# download-data.sh – Kartendaten für den rd13 Tile Server herunterladen
|
||||
#
|
||||
# Verwendung:
|
||||
# ./scripts/download-data.sh [region]
|
||||
#
|
||||
# Regionen:
|
||||
# europe-dach – Deutschland, Österreich, Schweiz (Standard)
|
||||
# germany – nur Deutschland
|
||||
# planet – gesamter Planet (groß!)
|
||||
# satellite – Sentinel-2 cloudless Satellitenkacheln (niedrig/mittel Zoom)
|
||||
# =============================================================================
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
DATA_DIR="$SCRIPT_DIR/../data"
|
||||
mkdir -p "$DATA_DIR"
|
||||
|
||||
REGION="${1:-europe-dach}"
|
||||
|
||||
# ---- OSM-Vektorkacheln via Planetiler ------------------------------------
|
||||
download_osm() {
|
||||
local region="$1"
|
||||
local jar="$DATA_DIR/planetiler.jar"
|
||||
|
||||
# Planetiler herunterladen falls nicht vorhanden
|
||||
if [[ ! -f "$jar" ]]; then
|
||||
echo "[OSM] Lade Planetiler herunter..."
|
||||
curl -L -o "$jar" \
|
||||
"https://github.com/onthegomap/planetiler/releases/latest/download/planetiler.jar"
|
||||
fi
|
||||
|
||||
case "$region" in
|
||||
germany)
|
||||
AREA="germany"
|
||||
DOWNLOAD="https://download.geofabrik.de/europe/germany-latest.osm.pbf"
|
||||
;;
|
||||
europe-dach)
|
||||
# DACH als Extrakt
|
||||
AREA="dach"
|
||||
DOWNLOAD="https://download.geofabrik.de/europe/dach-latest.osm.pbf"
|
||||
;;
|
||||
planet)
|
||||
AREA="planet"
|
||||
DOWNLOAD="" # Planetiler lädt selbst herunter
|
||||
;;
|
||||
*)
|
||||
echo "Unbekannte Region: $region"; exit 1 ;;
|
||||
esac
|
||||
|
||||
echo "[OSM] Erzeuge osm.mbtiles für Region: $region"
|
||||
if [[ "$region" == "planet" ]]; then
|
||||
java -Xmx8g -jar "$jar" \
|
||||
--download \
|
||||
--output="$DATA_DIR/osm.mbtiles"
|
||||
else
|
||||
# OSM-PBF herunterladen
|
||||
local pbf="$DATA_DIR/${AREA}.osm.pbf"
|
||||
if [[ ! -f "$pbf" ]]; then
|
||||
echo "[OSM] Lade PBF-Datei: $DOWNLOAD"
|
||||
curl -L -o "$pbf" "$DOWNLOAD"
|
||||
fi
|
||||
java -Xmx4g -jar "$jar" \
|
||||
--area="$AREA" \
|
||||
--osm-path="$pbf" \
|
||||
--output="$DATA_DIR/osm.mbtiles"
|
||||
fi
|
||||
echo "[OSM] Fertig: $DATA_DIR/osm.mbtiles"
|
||||
}
|
||||
|
||||
# ---- Satellit: Sentinel-2 cloudless (OpenMapTiles / maptiler) ------------
|
||||
download_satellite() {
|
||||
echo ""
|
||||
echo "[Satellit] Hinweis:"
|
||||
echo " Kostenlose Satelliten-MBTiles sind nur für niedrige Zoomstufen (0-10)"
|
||||
echo " verfügbar. Für höhere Auflösung gibt es zwei Optionen:"
|
||||
echo ""
|
||||
echo " 1) NASA GIBS (kostenlos, TMS/WMTS, kein Download nötig):"
|
||||
echo " https://gibs.earthdata.nasa.gov/wmts/"
|
||||
echo " → Einfach in config.json als 'tilejson'-Source eintragen."
|
||||
echo ""
|
||||
echo " 2) Sentinel-2 cloudless (maptiler.com, kostenloser Account für self-hosted):"
|
||||
echo " https://www.maptiler.com/data/satellite-mediumres/"
|
||||
echo " → MBTiles manuell herunterladen und als data/satellite.mbtiles ablegen."
|
||||
echo ""
|
||||
echo " 3) Eigene GeoTIFFs → MBTiles mit gdal2tiles:"
|
||||
echo " gdal2tiles.py --zoom=0-14 input.tif data/satellite/"
|
||||
echo " mb-util data/satellite/ data/satellite.mbtiles"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ---- Fonts & Sprites für OSM Bright Style --------------------------------
|
||||
download_assets() {
|
||||
local fonts_dir="$DATA_DIR/fonts"
|
||||
local sprites_dir="$DATA_DIR/sprites"
|
||||
local styles_dir="$DATA_DIR/styles"
|
||||
|
||||
mkdir -p "$fonts_dir" "$sprites_dir" "$styles_dir"
|
||||
|
||||
if [[ ! -d "$fonts_dir/Open Sans Regular" ]]; then
|
||||
echo "[Assets] Lade OpenMapTiles Fonts herunter..."
|
||||
TMP=$(mktemp -d)
|
||||
curl -L -o "$TMP/fonts.zip" \
|
||||
"https://github.com/openmaptiles/fonts/releases/latest/download/v3.0.zip" \
|
||||
|| { echo "[Assets] Font-Download fehlgeschlagen – bitte manuell von"; \
|
||||
echo " https://github.com/openmaptiles/fonts/releases herunterladen"; \
|
||||
rm -rf "$TMP"; }
|
||||
if [[ -f "$TMP/fonts.zip" ]]; then
|
||||
unzip -q "$TMP/fonts.zip" -d "$fonts_dir"
|
||||
rm -rf "$TMP"
|
||||
echo "[Assets] Fonts installiert."
|
||||
fi
|
||||
else
|
||||
echo "[Assets] Fonts bereits vorhanden."
|
||||
fi
|
||||
|
||||
if [[ ! -d "$styles_dir/osm-bright" ]]; then
|
||||
echo "[Assets] Lade OSM Bright GL Style herunter..."
|
||||
TMP=$(mktemp -d)
|
||||
curl -L -o "$TMP/style.zip" \
|
||||
"https://github.com/openmaptiles/osm-bright-gl-style/releases/latest/download/v1.9.zip" \
|
||||
|| { echo "[Assets] Style-Download fehlgeschlagen."; rm -rf "$TMP"; }
|
||||
if [[ -f "$TMP/style.zip" ]]; then
|
||||
unzip -q "$TMP/style.zip" -d "$TMP/extracted"
|
||||
mv "$TMP/extracted/"*/ "$styles_dir/osm-bright"
|
||||
rm -rf "$TMP"
|
||||
echo "[Assets] OSM Bright Style installiert."
|
||||
fi
|
||||
else
|
||||
echo "[Assets] OSM Bright Style bereits vorhanden."
|
||||
fi
|
||||
}
|
||||
|
||||
# ---- Hauptlogik ----------------------------------------------------------
|
||||
echo "=== rd13 Tile Server – Daten-Download ==="
|
||||
echo "Region: $REGION"
|
||||
echo ""
|
||||
|
||||
if [[ "$REGION" == "satellite" ]]; then
|
||||
download_satellite
|
||||
else
|
||||
download_osm "$REGION"
|
||||
download_assets
|
||||
download_satellite
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Abgeschlossen ==="
|
||||
echo "Starte den Server mit: docker compose up -d"
|
||||
Loading…
Add table
Reference in a new issue