A MapProxy configuration that groups layers by WMS endpoint/service URL for better organization and maintainability.
mapproxy-config/
├── config.yml # Main configuration (loads all source modules)
├── config_layers.yml # All layer definitions (loaded first)
├── sources/ # One file per WMS endpoint (caches & sources only)
│ ├── shared-alkis.yaml # �️ Shared ALKIS background cache
│ ├── fbinter-alkis.yaml # 🗺️ ALKIS cadastral data
│ ├── fbinter-senstadt.yaml # 🛰️ Aerial imagery (2015, 2016 CIR)
│ ├── fbinter-oeffbeleucht.yaml # 💡 Public lighting
│ ├── gdi-bdom.yaml # 🏔️ Digital elevation model
│ ├── gdi-strassenbefahrung.yaml # 🛣️ Street survey 2014
│ ├── gdi-baumbestand.yaml # 🌳 Tree inventory (all variants)
│ ├── gdi-tempolimits.yaml # 🚦 Speed limits
│ ├── gdi-fussgaengernetz.yaml # 🚶 Pedestrian network
│ ├── gdi-postleitzahlen.yaml # 📮 Postal codes
│ ├── gdi-abstell-mikromob.yaml # 🛴 Micromobility parking
│ └── gdi-fahrradreparatur.yaml # 🔧 Bicycle repair stations
├── demo_links/ # Demo URLs for all available layers
└── docker-compose.yml # Local development environment
# Start MapProxy locally with Docker
docker compose up -d
# View demo with all layers
open http://localhost:8080/demo/
# View generated demo links -- this does not really work, yet. We cannot view the demo_links/README this way.
open http://localhost:8888/
# Test tiles from demo_links/README like this
open http://localhost:8080/tiles/1.0.0/strassenbefahrung/mercator/16/35198/21494.pngApplying config changes: config.yml, config_layers.yml and sources/ are mounted into the container. After editing any of these, restart MapProxy (no image rebuild):
docker compose restart mapproxy🗺 A list of all available maps with demo and editing urls …
- luftbilder.berlin.codefor.de showcases aerial images from different years Github
- maps.berlin.codefor.de showcases all kind of maps Github
- github.com/codeforberlin/tilestache-config is the config for serving aerial imagery from file (config)
This MapProxy setup uses a modular architecture that separates concerns:
config_layers.yml: Contains ALL layer definitions (must be first in base array)sources/: Individual files per data source containing only caches & sourcesconfig.yml: Main config that includes all modules viabasedirective
layers: section, so all layers must be defined in config_layers.yml.
Automated tools for managing configurations:
bun run check-all: Run all checks (layer docs, URL validation, demo links)bun run discover-layers: Discover layers for a WMS servicebun run generate-layer-docs: Generate documentation for all servicesbun run check-urls: Validate all WMS URLs and verify layers existbun run create-demo-links: Regenerate demo links README
See docs/wms_wfs_wmts_guide.md for detailed usage.
- Add layer definition to
config_layers.yml - Add cache and source to the appropriate
sources/xxx.yamlfile - Use
bun run discover-layers <service_url>to find available layers - See docs/wms_wfs_wmts_guide.md for WMS configuration details
- Create
sources/new-service.yamlwith caches and sources - Add layer definitions to
config_layers.yml - Include the new file in
config.ymlbase section (afterconfig_layers.yml) - Run
bun run check-allto validate and generate documentation
python3 -m venv env
source env/bin/activate
pip install -r requirements.txt
mapproxy-util serve-develop config.yml
# creates the wsgi.py script
mapproxy-util create -t wsgi-app -f config.yml wsgi.py
Note: We don't use make_wsgi_app(…, reloader=True) but restart the server manually. The auto reloading would only restart if the config is valid, which would hide a broken edit. The manual reload will make the error visible.
Create a systemd service script in /etc/systemd/system/mapproxy.service.
[Unit]
Description=Mapproxy gunicorn daemon
After=network.target
[Service]
User=tiles
Group=tiles
WorkingDirectory=/srv/tiles/proxy
ExecStart=/srv/tiles/proxy/env/bin/gunicorn --access-logfile /var/log/mapproxy/access.log --error-logfile /var/log/mapproxy/error.log --bind unix:/tmp/mapproxy.sock --workers 9 wsgi:application
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl start mapproxyAdd to nginx configuration:
location /proxy/ {
proxy_pass http://unix:/tmp/mapproxy.sock;
proxy_set_header Host $http_host;
proxy_set_header X-Script-Name /proxy;
}
nginx -t
systemctl start nginx- Available layers: Use MapProxy Debug Page or
bun run discover-layers <service_url> - Layer documentation: See
layer_docs/for detailed layer information - URL validation: Run
bun run check-urlsto verify all WMS URLs - Request logging: Enable in log.ini and check
mapproxy_log/source-requests.log - Cache refresh: Delete
cache_data/folders to force cache refresh - WMS/WFS details: See docs/wms_wfs_wmts_guide.md
- WMS/WFS/WMTS Guide: docs/wms_wfs_wmts_guide.md - Protocol details and usage
- Layer Documentation:
layer_docs/- Detailed layer information (auto-generated) - Demo Links: demo_links/README.md - All available layers with previews
- MapProxy Docs: https://mapproxy.github.io/mapproxy/latest/index.html