When hosting your tilemaker generated maps, it is possible to use certain tileserver software such as tileserver-php. However this is not absolutely needed and the best performance for serving maps is by hosting it straight from a static webserver. In this tutorial i will explain how to build such a setup and how compression can be configured to improve hosting speed and reduce disk usage.

Please read this tutorial first before trying this approach: Generating self-hosted maps using tilemaker

Generating maps in a directory

When generating your maps using tilemaker there are two output options:

  • mbtiles The mbtiles file is a sqlite3 database which can be read by (server-side) scripting languages such as php/lua/nodejs. Tileservers such as tileserver-php open this file and read out the tile data, once the client requests them.

  • directory Using tilemaker it is also possible to generate the tile files into a directory. This is what we are going to be using in this tutorial.

Disable compression

Generating your maps into a directory is quite easy, instead of using an output filename ending in mbtiles, we give the name of the directory in which we want to generate the maps. But first first we need to edit 'resources/config-openmaptiles.json'. Open this file in an editor and change the line 'compress' in 'settings' to 'none'.

"settings": {
        "minzoom": 0,
        "maxzoom": 14,
        "basezoom": 14,
        "include_ids": false,
        "combine_below": 14,
        "name": "Tilemaker to OpenMapTiles schema",
        "version": "3.0",
        "description": "Tile config based on OpenMapTiles schema",
        "compress": "gzip",
        "filemetadata": {
            "tilejson": "2.0.0",
            "scheme": "xyz",
            "type": "baselayer",
            "format": "pbf",
            "tiles": ["https://example.com/liechtenstein/{z}/{x}/{y}.pbf"]
        }
    }
}

field 'compression' becomes:

"compress": "none"

We can now generate our tiledata:

./tilemaker --input netherlands.osm.pbf --output netherlands 
  --process resources/process-openmaptiles.lua 
  --config resources/config-openmaptiles.json 

Upload data

In this example the files will be generated into the directory 'netherlands', if we look in this directory we can see a number of directories and a file called 'metadata.json':

0  10  12  14  3  5  7  9 metadata.json
1  11  13  2   4  6  8

The numbered directories contain the tile data at different zoom levels:

./14/8347/5283.pbf
./14/8347/5386.pbf
./14/8347/5476.pbf
./14/8347/5261.pbf
./14/8347/5307.pbf
./14/8347/5379.pbf

In the end, they are nothing more than static files which are requested by the client when needed. The metadata.json file contains metadata information about the map. This is a json file that we need to edit. If we look at this file we can see at the top:

{"tilejson":"2.0.0","scheme":"xyz","type":"baselayer","format":"pbf","tiles":["https://example.com/map/netherlands/{z}/{x}/{y}.pbf"],....

You can see this file contains a url in this 'tiles' field. Depending on where you are going to upload/host the tile data, you need to change this url. In this example, we are going to upload the directory 'netherlands' with the tiledata to 'https://example.com/map/'. Change this url to where you are going to upload the tiledata and upload the pbf files and metadata.json file to your webserver.

Edit style

To actually use the map, we have to change the url to the map data in our style file. If you open the style file that is used by mapbox/maplibre, you can see at the top the url that is used for loading the map data:

"sources": {
    "openmaptiles": {
      "type": "vector",
        "url": "https://example.com/map/netherlands/metadata.json"
    }
  },

Change the url such that it points to where you uploaded the tile data directory and metadata.json file. Open your browser and see if the map is loaded correctly. If it is not, possibly some url is configured not correctly.

Note: It is also possible to change this url in the config file for tilemaker, such that the 'metadata.json' file does not have to be edited after each conversion. See the 'settings' in the 'config-openmaptiles.json'.

On the fly compression

The performance of the hosting can be improved by compressing the tiledata on the fly. In the apache webserver this can be done by adding a .htaccess file in the directory of the map data:

<IfModule mod_deflate.c>
  <FilesMatch "\\.pbf$">
    SetOutputFilter DEFLATE
  </FilesMatch>
</IfModule>

This reduces the amount of data that is going to be send to the client, but it is better to store the tile data pre-compressed on the webserver.

Pre-compressed files

Storage space can be saved by storing the tile data compressed on disk. To do so, go back to the default config file of tilemaker or change the 'compress' line back to 'gzip'. Perform the generation of the tile data again and upload it again to the webserver. Tilemaker now tells you, you have to modify your webserver configuration:

When serving compressed tiles, make sure to include 'Content-Encoding: gzip' in your webserver configuration for serving pbf files

In nginx we can add this header inside the global configuration:

location ~ /netherlands/.+pbf$ {
    # gzip Encoding and MIME type type
    add_header  Content-Encoding  gzip;
    gzip off;
    types { application/x-protobuf pbf; }
}

In apache we can add this in the .htaccess file:

<IfModule mod_headers.c>
  <FilesMatch ".pbf$">
    Header append  Content-Encoding: gzip
  </FilesMatch>
</IfModule>

In this scenario, the tile data is stored pre-compressed on disk and forwarded to the webbrowser. Because the 'Content-Encoding' header was added, the browser will perform the decompression before giving it to the mapbox/maplibre javascript client.

Multiple domains

It is possible to further improve setup multiple domains to fetch the same map data. This allows the mapbox/maplibre client to have more connections to your webserver to fetch the tile data. In the 'metadata.json' file add a list of virtual hosts all pointing to the same tile data:

"tiles":[
  "https://maps01.example.com/map/netherlands/{z}/{x}/{y}.pbf", 
  "https://maps02.example.com/map/netherlands/{z}/{x}/{y}.pbf", 
  "https://maps03.example.com/map/netherlands/{z}/{x}/{y}.pbf"]

Conclusion

You now have a completely static configuration for serving your map data. This can be hosted from a static webhosting service, possibly with compression, or if the configuration of the webserver can not be modified, without compression. The performance of the hosting should be improved, because no php/lua/javascript interpreter is involved in serving the requests.