Skip to content

Self-host map tiles

Diadem uses MapLibre GL JS to render maps. Unlike traditional raster maps, tile data is downloaded as vector data and rendered on the client. There are great public-facing tile sources available as defaults for Diadem, but you might want to host your own sources.

If you’re already running your own tile server, like Rampardos, this is basically free. If not, it will take about 100 GB of disk space for tiles covering the entire globe.

Rampardos is not capable of serving the required data on its own, so you need to set up Martin. Below is a quick guide on how to do that. You can also refer to the documentation for more exhaustive instructions.

Terminal window
mkdir martin && cd martin
curl -L -O https://github.com/maplibre/martin/releases/latest/download/martin-x86_64-unknown-linux-musl.tar.gz
tar -xzf martin-x86_64-unknown-linux-musl.tar.gz
chmod +x ./martin

Check if you can run the Martin binary.

Terminal window
./martin --help

Create a symlink to your existing MBTiles file.

Terminal window
ln -s /path/to/rampardos/TileServer/Datasets/Combined.mbtiles world.mbtiles

You can search for an MBTiles dump for your desired region. If you want to provide tiles for the entire globe, you can use this (the download is about 90 GB).

Terminal window
wget https://btrfs.openfreemap.com/areas/planet/20260422_001001_pt/tiles.mbtiles
mv tiles.mbtiles world.mbtiles

You should already be able to start Martin. Try opening it in your browser.

Terminal window
./martin world.mbtiles

Martin will have to be available on the internet. As with all your other public-facing services, you should set it up behind a reverse proxy.

Sample config using Caddy:

example.com {
reverse_proxy 127.0.0.1:3000
# or behind a path
# reverse_proxy /tiles* 127.0.0.1:3000
}

Now restart Martin while binding it to 127.0.0.1, and you should be able to reach it through your reverse proxy.

Terminal window
./martin world.mbtiles -l 127.0.0.1:3000
Terminal window
touch config.yml
mkdir data && mkdir data/fonts && mkdir data/styles && mkdir data/sprites

Then paste the basic config from below. Refer to Martin’s documentation for further configuration options.

You can now start Martin with the config. Note that it will throw an error since no styles are defined yet.

Terminal window
./martin -c config.yml

This is what your directory will look like, and where your style definitions will go. You will learn how to set up a style in the next section.

  • Directoryfonts
    • Directorynoto Example font
      • NotoSans-Regular.ttf
  • Directorysprites
    • Directoryosm_liberty Example sprites
      • airfield_1.svg
  • Directorystyles
    • osm_liberty.json Example style
  • config.yml
  • martin
  • world.mbtiles
# refer to https://maplibre.org/martin/config-file/ for all options
listen_addresses: "127.0.0.1:3000"
# can be enabled-for-all or disable
# make sure to not expose this in production
web_ui: disable
# Set the URL path prefix for all API routes.
# When set, Martin will serve all endpoints under this path prefix.
# This allows Martin to be served under a subpath when behind a reverse proxy.
# Must begin with a `/`.
# Examples: `/tiles`, `/api/v1/tiles`
route_prefix: null
mbtiles:
paths:
- ./
fonts:
paths:
- ./data/fonts
styles:
paths:
- ./data/styles
sprites:
paths:
# - ./data/sprites/osm_liberty

A style is defined via a JSON file, and it might require sprites and fonts.

You can use Maputnik to find premade styles, edit them, and export them.

To import a pre-existing style, click Open and select a style you like. Let’s go with OSM Liberty. Now click on Export and then Download.

To make sure a Maputnik export works with your Martin installation, some additional steps need to be taken. world is the name of your mbtiles file. . Copy the downloaded JSON file to data/styles and set the name to its ID, for example osm_liberty.json 2. Point sources to your own server

"sources": {
"openmaptiles": {
"type": "vector",
"url": "https://yourmartinurl.com/world"
}
},
  1. Point sprite and glyphs to your own server. {yourspritename} needs to be replaced with the sprite name you will choose in step 4. Usually, you can set it to the style ID, for example osm_liberty

    "sprite": "https://yourmartinurl.com/sprite/{yourspritename}",
    "glyphs": "https://yourmartinurl.com/font/{fontstack}/{range}",
  2. Prepare the sprites

    • Find the SVGs used in your map style. Maputnik’s styles are open source, for example, you can find the icons used by OSM Liberty in its GitHub repo
    • Create a subdirectory in data/sprites and call it the same as your style ID, for example osm_liberty
    • Copy the SVGs into that directory
    • Add this new directory to config.yml. The example config already has it, just commented out
  3. Prepare the fonts

    • Search style.json for text-font to check which fonts it uses. You can also change the font name to one that you already have installed
    • Your goal is to find ttf, otf, or ttc files for that font
    • For example, OSM Liberty uses Roboto, which you can download as TTF files from Google Fonts
    • Create a new directory under data/fonts, name it whatever you like, then copy the downloaded files there

The style should now be set up and ready for use.

Add the following example to your config and restart Diadem.

[[client.mapStyles]]
id = "osm_liberty"
name = "OSM Liberty"
url = "https://yourmartinurl.com/tiles/style/osm_liberty"

It’s recommended to set up a cache layer in front of your Martin instance. Refer to Set up Cloudflare Cache Rules for more information.

All your tile data is very static, so you can choose very long TTLs.