OpenStreetMap Karten selbst hosten

Veröffentlicht von am

Dieser Artikel ist veraltet. Die neueste Version ist hier zu finden.

Im diesem Artikel will ich zeigen, wie man interaktive OpenStreetmaps-Karten einfach komplett selbst hosten kann, ohne Code von Drittanbietern (z.B. MapBox, GoogleMaps) einzubinden, oder Requsests an sie zu senden.

Selbstgehostete OpenStreetMap Karte

Bitte beachten: Diese Beschreibung beschränkt sich auf die Erstellung eines kleinen Kartenausschnitts in vielen Zoomstufen, um Datenmengen und Rechenzeiten gering zu halten. Die Erstellung einer Welt- oder Europakarte funktioniert technisch genauso, benötigt allerdings ein vielfaches von Rechenzeit und Speicherplatz.

Weiterhin beschreibt dieser Artikel auf das Erstellen der Vector Tiles auf MacOS, sowie das Hosting via Apache + PHP.

Funktionsumfang

Welchen Funktionsumfang haben die hier beschriebenen selbst erstellten und gehosteten Karten?

  • Interaktive Kartenansicht mit Zoom und Pan
  • Kleine Kartenausschnitte: Eine detaillierte Karte (mit vielen Zoomstufen) von Europa oder der Welt ist (je nach Budget) wahrscheinlich viel zu groß zum selberhosten
  • Kartenoverlays und Pins setzen
  • Generell der Funktionsumfang von MaplibreGL
  • Hosting ist enweder per PHP + Apache (hier beschrieben) oder per Node.js möglich

Was können diese selbst gehosteten Karten nicht?

  • Navigation und Routing
  • Geocoding: also eine Adresse in Geokoordinaten konvertieren oder Koordinaten in Adresse umwandeln
  • weitere Komplexe Berechnungen, die auf einen Backend-Server angewiesen sind
  • Generell alles, was nicht dem Funktionsumfang von MaplibreGL entspricht :-)

Notwendige Schritte

Zum Erstellen und Anzeigen der Karte sind zwei Schritte notwendig:

  1. Kartendaten im Vector-Tile Dateiformat werden aus Openstreetmap-Daten erzeugt
  2. Die Vector-Tile-Dateien werden gehostet und via Web-Anwendung angezeigt
Ein Diagramm, dass das die Schritte für die Erstellung und das selbsthosten von OpenStreetMap Karten zeigt

Schritt 1: Erstellung von Vector-Tile Dateien

Vector Tiles ermöglichen eine skalierbare Kartendarstellung: Die Karten "verpixeln" nicht beim zoomen.

Die Vector-Tiles-Dateien werden aus Open Steet Map-Karteninformationen generiert. Dazu kann man folgende Kommandozeilenwerkzeuge verwenden:

Karteninformationen herunterladen

Die OpenStreetMap-Karteninformationen können von der OpenStreetmap-Webseite heruntergeladen werden: unter dem Menüpunkt Export:

Export von Daten auf der OpenStreetMap Webseite

Kartendaten im osm-Format können auf der OpenStreetmap Webseite heruntergeladen werden.

Die Kommandozeilenwerkzeuge in den den nächsten Schritten können mit .osm-Dateien nichts anfangen, sie benötigen die Kartendaten im .osm.pbf-Dateiformat.

Das osmium Kommandozeilenwerkzeug erledigt diese Aufgabe. Der folgende Befehl wandelt die .osm-Datei in eine .osm.pbf-Datei um:

$ osmium cat my_test_map.osm -o my_test_map.osm.pbf

Wer seine Karten direkt im .osm.pbf-Format herunterlädt, zum Beispiel von Geofabrik.de, kann sich die Installation von osmium und das Umwandeln sparen.

Vector-Tiles erzeugen

Als Nächstes werden aus den .osm.pbf-Dateien Vector-Tiles im .mbtiles Format erstellt, die im Browser angezeigt werden können. Hierbei kommt das Open Map Tiles Projekt zum Einsatz, das per Git heruntergeladen und installiert wird:

$ git clone git@github.com:openmaptiles/openmaptiles.git
$ cd openmaptiles

Für openmaptiles kann man jetzt noch einige Einstellungen anpassen, bevor die Vector Tiles erzeugt werden: In der .env-Datei im opemaptiles/ Ordner kann man dazu zum Beispiel den minimalen und maximalen Zoomlevel der Karte anpassen:

MIN_ZOOM=0
MAX_ZOOM=7

Je höher der Maximale Zoomlevel, desto detailreicher die Karte, und desto länger dauert der Render-Prozess. Für die oben eingebunde Karte habe ich beispielsweise Zoomlevel von 2-18 eingestellt.

Jetzt können die Vector-Tile-Dateien erzeugt werden. Dies geschieht mit dem Befehl:

$ ./quickstart.sh my_test_map

Dieser Prozess kann sehr lange dauern. Je nach eingestelltem Zoomlevel und Kartengebiet auch mehrere Stunden.

Die erzeugten Vector-Tiles-Dateien werden im Anschluss unter openmaptiles/data/tiles.mbtiles abgelegt.

Schritt 2: Karte Anzeigen

Die Karte wird mithilfe der MapLibreGL-Bibliothek in eine Seite eingebettet. Zusätzlich werden (je nach gewünschtem Kartenstil) noch einige weitere NodeJS-Tools eingesetzt.

Styles erstellen

Nachdem im Browser Anzeigbare Karteninformationen nun in Form von Vector-Tiles-Dateien vorliegen, geht es als Nächstes darum, sie in eine gut lesbare Form zu bringen, mithilfe von Kartenstilen (oder Mapstyles):

Diese sind in einer Datei namens styles.json enthalten und beschreiben Aussehen Farbgebung und Anmutung verschiedener Kartenelemente.

Eine Spezifikation des Mapstyles-Formats ist auf der Webseite von maplibre einsehbar.

Wer kein Interesse hat, eigene Karten-Styles zu schreiben, der kann auch die vorgefertigten Styles von OpenMapTiles übernehmen. In diesem Beispiel verwende ich die Styles von OSM Bright

Dafür lade ich die Styles per git clone herunter:

$ git clone git@github.com:openmaptiles/osm-bright-gl-style.git

Sprites erstellen

Für viele Kartenstyles werden auch Icons und Symbole benötigt, um zum Beispiel Autobahnen richtig zu kennzeichnen. Diese Symbole sind im Bright-OSM Theme im icons-Ordner im svg-Format hinterlegt.

Das Command-Line Tool spritezero-cli kann die einzelnen SVG-Dateien zu einem Spritesheet zusammenfügen, um Ladezeiten zu optimieren.

Dieses kann man global via npm installieren:

$ npm install -g @elastic/spritezero-cli

Per

$ spritezero sprite@2x icons --retina && spritezero sprite icons

wird aus dem "icons" Ordner ein neues Spritesheet mit dem namen "sprite" erstellt: Es besteht aus den Dateien sprite.png und sprite.json

.
├── icons
│   ├── ... (svg icons)
│   └── ...
├── sprite.png
└── sprite.json

Schritt 4: Schriftdateien erzeugen

Neben den Vector-Tiles und Style-Dateien werden für die richtige Anzeige der Karten in der Regel auch Schriften benötigt. Die Schriftdateien werden im .pbf-Dateiformat benötigt. Bei der Umwandlung von Schriftdateien in anderen Formaten (z.B. .ttf) hilft das Paket openmaptiles/fonts, das netterweise auch schon einige Standartschriftarten mitbringt:

Dazu das Paket per git clone herunterladen und dann per npm install die Abhängigkeiten installieren:

$ git clone git@github.com:openmaptiles/fonts.git
$ cd fonts
$ npm install

Per node ./generate.js werden die pbf-Dateien im _output Ordner erzeugt.

Tileserver einrichten

Nachdem alle Vorarbeiten abgeschlossen sind, geht es schließelich darum, eine Interaktive Karte im Browser anzuzeigen: Dabei kommt serverseitig ein Tileserver zum Einsatz: Der Tileserver gibt auf HTTP-Anfragen den angefragtem Kartenausschnitt zurück. Dabei das Projekt https://github.com/maptiler/tileserver-php verwendet.

Für die Installation des Tileservers sind folgende Dateien aus dem Projekt herunterzuladen und in einen öffentlich erreichbaren Ordner eines Webservers zu kopieren (also z.B. in den htdocs-Ordnervon Apache):

  • .htaccess
  • tileserver.php

Als nächstes noch die erzeugte Datei mit den Vector-Tiles tiles.mbtiles in den gleichen Ordner kopieren.

Um zu testen ob alles funktioniert hat kann man als nächstes die Adresse von tileserver.php im Browser aufrufen, also z.B: http://localhost/tileserver.php.

Wenn alles geklappt hat, sollte das Tileserver-Interface erscheinen:

die tileserver-benutzerobefläche im browser

Das Tileserver.php Interface

Um eine Vorschau der erstellten Vector Tiles zu sehen, kann man im Menü auf der rechten Seite unter Open Layers 3 auf Preview klicken und dann links unten den Haken bei "Show OSM" setzen. Das erleichtert das Heranzoomen in der Karte auf den gerenderten Bereich:

Die Tileserver-Oberfläche mit einem befüllten Kartenausschnitt

Tileserver.php Interface mit Kartendaten

Als nächstes geht es daran, die Kartenstile, Icons und die erzeugten Schriftdateien ebenfalls auf den Webserver hochzuladen. In welchem Ordner die Dateien abgelegt werden ist nicht relevant, wichtig ist nur, dass die hochgeladenen Dateien über eine URL abrufbar sind.

Sind Kartenstile, Icons und Schriftdateien hochgeladen, müssen diese mit in der Kartenstil-Datei styles.json richtig verlinkt werden, und zwar jeweils mit der richtigen URL.

Dazu müssen in der JSON-Datei folgende Einträge angepasst werden:

  • Unter sources.openmaptiles.url wird die URL zu den Karteninformationen auf dem Tileserver eingetragen, also z.B: "http://localhost/tileserver/wuerzburg2.json".
  • Unter glyphs wird die URL zu den Schriftdateien eingetragen, also z.B: http://localhost/fonts/{fontstack}/{range}.pbf. Die Werte {fontstack} und {range} werden später programmatisch ersetzt.
  • Unter sprite: wird die Ordner-URL der Icons eingetragen, also z.B: http://localhost/icons

Insgesamt sollte die Ordnerstruktur auf dem Server jetzt in etwa so aussehen:

.
├── fonts
│   ├── ...
│   └── ...
├── mapstyle.php
├── styles
│   ├── sprite.json
│   ├── sprite.png
│   ├── sprite@2x.json
│   ├── sprite@2x.png
│   └── style.json
└── tiles
    ├── tileserver.php
    └── tiles.mbtiles

Einbettung per MapLibreGL

Als letzter Schritt bleibt schließlich nur noch, die Interaktive Karte anzuzeigen. Dabei verwende ich die maplibre-gl-js Javascript Bibliothek:

<!doctype html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>Self hosted OSM-Widget</title>
		<style>
			#map { width: 100%; height: 90vh; }
		</style>
	</head>
	<body>
		<div id="map"></div>
	<script src="maplibre-gl.js"></script>
	<script>
const map = new maplibregl.Map( {
	container: '#map',
	style: 'assets/styles.json',
	center: new maplibregl.LngLat( 9.928392619016336, 49.79308196069323 ),
	zoom: 16
} );

const marker = new maplibregl.Marker( { color: '#000000' } )
	.setLngLat( [ 9.928392619016336, 49.79308196069323 ] )
	.addTo( map );
		</script>
	</body>
</html>

Eine einfache Karte mit Pin

Kommentare

  • Gerfried Sperling

    15.04.2024 11:59 Uhr

    Hallo!

    Ist es möglich auf einer so gehosteten Karte einen .gpx-track darzustellen?

    Danke und freundliche Grüße

    Gerfried

  • Georg Fischer

    15.04.2024 12:06 Uhr

    @Gerfried Sperling

    Ja, das ist möglich. MapLibre, die Bibliothek, die zum Darstellen der Karte im Browser verwendet wird, unterstützt auch die Darstellung von .gpx-Tracks.

    Eine Beispielhafte Implementierung mit Erklärungen ist hier zu finden:
    https://observablehq.com/@mcmcclur/gpx-rides-with-maplibre-and-maptiler

  • Gerfried Sperling

    17.04.2024 16:19 Uhr

    @Georg Fischer
    Danke!

  • Gerfried Sperling

    18.04.2024 17:26 Uhr

    Hallo!
    Danke für diese tolle übersichtliche Anleitung. Ich versuche Schritt für Schritt zu folgen. Beim Befehl "./quickstart.sh my_test_map" wird jedoch Docker vorausgesetzt. Hm? kann man das umgehen?

    MgG
    Gerfried

  • Georg Fischer

    18.04.2024 19:32 Uhr

    @Gerfried Sperling

    Soweit ich weiss ist es nicht möglich, diesen Schritt ohne Docker vorzunehmen.

    Dieser Artikel ist schon einige Jahre alt, inzwischen gibt es eine (meiner Meinung nach) einfachere Alternative zu dem im Artikel aufgezeigten Weg:

    Das Datenformat Protomaps ermöglicht es, die Kartendaten direkt herunterzuladen, ohne eine zeitaufwändige Konvertierung zwischen Datenformaten.

    Dazu kann man zunächst eine .mbtiles-Datei herunterladen, die alle Kartendaten für das gewünschte Gebiet enthält.

    Bevor der Download starten kann, wird zunächst eine .geojson-Datei benötigt, in welcher der gewünschte Kartenauschnitt eingezeichnet ist. Diese Datei kann man sehr einfach mit dem Editor von geojson.io erstellen.

    Hier einfach den gewünschten Kartenausschnitt mit den Bearbeitungswerkzeigen auf der Rechten Seit markieren, und dann die Datei herunterladen (am Besten in einen neuen Ordner unter REGION.geojson speichern).

    Das funktioniert am Besten mit dem go-mbtiles-Tool, das man auf Github herunterladen kann, idealerweise in den gerade neu erstellten Ordner.

    go-mbtiles ermöglicht es, einen Ausschnitt von Kartendaten herunterzuladen. Mehr zur Funktionsweise findet sich auch in der Readme-Datei.

    Als Datenquelle für den Kartenauschnitt dient eine von Protomaps erstellte weltweite Karte.
    Die neuesten Karten werden unter https://maps.protomaps.com/builds/ aufgelistet.

    Um die .mbtiles-Datei herunterzuladen kann man jetzt den eben erstellten Ordner im Terminal öffnen, und den folgenden Befehl ausführen:

    pmtiles extract https://build.protomaps.com/20240418.pmtiles OUTPUT.pmtiles --region=REGION.geojson

    Wenn das script durchgelaufen ist, sollte sich in dem Ordner eine neue Datei mit dem Name OUTPUT.pmtiles befinden.

    Diese Datei kann dann in der Javascript-Bibliothek maplibre-gl referenziert werden.

    Ein Code-Beispiel, wie man die .pmtiles-Datei in maplibre-gl referenziert, findet sich hier
    Blog-Einträge auf Englisch die sich mit dem Thema befassen,befinden sich sich hier und hier.

  • Gerfried Sperling

    19.04.2024 15:12 Uhr

    @Georg Fischer

    Herzlichen Dank!!

    Bin aktuell beim "Zusammenstöpseln" der spreets und .json und fonts - das hakt ein bissel.

    Darf ich wieder fragen wenns gar nicht weitergeht?

    den tile-server hab ich schon zum laufen gebracht :-))

    Gerfried

  • Georg Fischer

    19.04.2024 16:22 Uhr

    @Gerfried Sperling klar!

  • Gerfried Sperling

    20.04.2024 00:52 Uhr

    @Georg Fischer
    Danke!
    Ich scheitere an den fonts:
    konnte zwar die fonts als .ttf/.otf runterladen
    Umwandlung in .pbf gelingt nicht

    npm install
    und
    node ./generate.js
    (sind das terminal-befehle?)
    funktionieren nicht
    Könnte das an Mac OS Monterey liegen, oder kapier ich grundlegend etwas nicht?
    Danke für etwaige Hilfe und LG
    Gerfried

  • Georg Fischer

    23.04.2024 21:03 Uhr

    @Gerfried Sperling
    Das Script von openmaptiles scheint tatsächlich nicht mehr zu funktionieren, ich habe es gerade getestet. Bei github habe ich das Ergebnis des Scripts (die .pbf-Dateien) hier gefunden.

  • Gerfried Sperling

    24.04.2024 09:29 Uhr

    @Georg Fischer

    Vielen herzlichen Dank für die Mühe!

    Ich muss zugeben - ich bin auf diesem Gebiet Anfänger; eigentlich dürfte ich mit meinem Niveau dies gar nicht angehen. Aber ich hab mich da in was verfangen - es lässt mich nicht mehr los. Es begann damit, karten DSGVO-konform zu veröffentlichen und so bin ich auf das Thema mit dem selber hosten der karten mit OSM/Tileserver gestossen.

    Ich hab jetzt die tiles mit dem tile-server gehostet - das klappt.

    Ab da steh ich total an - mir gelingt es nicht daraus eine karte darzustellen.

    Wenn ich es richtig verstehe, braucht man einen html-code - ich hab deinen quellcode kopiert - das funktioniert natürlich nicht.

    Auch die urls in der .json datei hab ich angepasst (hoffentlich richtig).

    Es gibt auch im tile-server selbst einen source-code, wenn ich den verwende, komme ich auch nur wieder zum tile-server.

    Wenn ich iframe einbette, sehe ich auch nur die tiles.

    Ich wäre für jeden Hinsweis sehr dankbar, vor allem wie beginne ich mit diesem html-code für die Darstellung der karte.

    Übrigens - ich mache das ganze völlig umkommerziell.

    Vielen herzlichen Dank und liebe Grüße
    Gerfried

  • Georg Fischer

    01.05.2024 10:30 Uhr

    @Gerfried Sperling ich habe diesen Artikel angepasst: Die aktuelle Version befindet sich hier. Bei weiteren Fragen kann ich evtl. per E-Mail weiterhelfen: hi at snorpey . com

Hinterlasse einen Kommentar

Verfügbare Formatierungen

Benutze Markdown-Befehle oder ihre HTML-Äquivalente, um deinen Kommentar zu formatieren:

Textauszeichnungen
*kursiv*, **fett**, ~~durchgestrichen~~, `Code` und <mark>markierter Text</mark>.
Listen
- Listenpunkt 1
- Listenpunkt 1
1. Nummerierte Liste 1
2. Nummerierte Liste 2
Zitate
> Zitierter Text
Code-Blöcke
```
// Ein einfacher Code-Block
```
```php
// Etwas PHP-Code
phpinfo();
```
Verlinkungen
[Link-Text](https://example.com)
Vollständige URLs werden automatisch in Links umgewandelt.

Auf der eigenen Website geantwortet? Sende eine Webmention!