Home | Send Feedback | Share on Bluesky |

TileServerGL, a self-hosted map tile server with OpenStreetMap data

Published: 10. July 2018  •  Updated: 6. March 2026  •  selfhost

When you want to add interactive maps to your web application, you need some JavaScript and a server that hosts the map data. A popular solution is Google Maps, which provides an all-in-one package, including a JavaScript library and the map data.

Google Maps isn't the only map provider. You can choose others, like Apple Maps and Bing Maps.

Then, there are providers that host maps generated with data from the OpenStreetMap project. The OpenStreetMap data is publicly available, and anyone can use it. On this wiki page, you can find a list of commercial companies that provide services related to OpenStreetMap data: https://wiki.openstreetmap.org/wiki/Commercial_OSM_Software_and_Services

The server that sends the map data to a web application is called a tile server. A tile server either serves vector tiles or pre-rendered tiles in PNG format, or it can support both.

OpenStreetMap itself also runs a tile server (tile.openstreetmap.org) that is used for the map you find on the homepage: https://www.openstreetmap.org. You can use this tile server in your application, but you have to comply with the usage policy: https://operations.osmfoundation.org/policies/tiles/

A better solution is to use one of the commercial providers mentioned above or host your own tile server. Fortunately, it is not too complicated to do that. All you need is a server on your intranet or a server connected to the Internet, plus enough disk space. Depending on the extract you want to host, that can range from a few gigabytes for a small country to far more for larger regions.

In this tutorial, I will install a tile server on a VPS. For this demo installation, I used a VPS server from Hetzner (referral link). I chose the smallest server offering: CX23 with 4GB of RAM. For the operating system, I selected Debian 13.

The tile server we will install is called TileServer GL, an open-source tile server maintained by the MapTiler team. TileServer GL is written in JavaScript and Node.js. The source code is hosted on GitHub: https://github.com/maptiler/tileserver-gl

The server comes in two versions: TileServer GL, which serves vector and raster tiles, and TileServer GL Light, which, without the rasterization component, can only serve vector tiles. The server-side rasterization depends on native code that might not run on every platform. TileServer GL Light is pure JavaScript and runs on any Node.js-supported platform.

The difference between raster tiles and vector tiles is the location where the map is drawn. When using vector data, the server only sends the raw data to the client, and the client "draws" the map. Another benefit is that the data transfer is significantly reduced because vector data is much smaller than rendered images. It is also easy to provide interactivity with map features, and a user can zoom and rotate the map very easily. Raster tiles are rendered on the server and then transferred to the client as images, usually PNG. This can be beneficial for mobile devices with slow CPU/GPU, where rendering data on the client is slow. The drawback is that rasterization requires more processing power on the server.

Data

OpenStreetMap data is free to use, and you can download it from different locations. The data is quite large, so make sure you have enough space on your disk. Unfortunately, my VPS only has a drive with 20 GB of capacity, so I can't download the map data for the whole world. Instead, I'm downloading only the data for Andorra, a small European country between Spain and France.

The data you download from the OpenStreetMap project is stored in a format that TileServer GL cannot read directly. For this tutorial, we need the map data stored in an mbtiles file. MBTiles is a specification for storing arbitrary tiled map data in SQLite databases.

Current TileServer GL versions can also serve pmtiles files, but mbtiles is still a common format for OpenMapTiles downloads, so I will use that here.

The conversion from the raw OpenStreetMap data into an mbtiles file is time-consuming. Fortunately, we don't have to do that ourselves, and we can download preprocessed mbtiles files from https://data.maptiler.com/downloads/planet/

You may have to create an account before downloading the map data. On the download page, you can search for a region and then download the OpenStreetMap vector tiles extract that you need.

Availability, file names, and license terms can change over time, so always check the current information on the download page before using the data in production.

You can either download the file in the browser and transfer it to your server or download it directly on the server. You will find a wget command on the download page to execute on the server. The URL is usually signed and specific to your download session.

I will run all the following commands as a root user. If you are not logged in as root, prepend sudo to the commands or switch to root with sudo -i.

mkdir /opt/maps
cd /opt/maps
wget -c -O europe_andorra.mbtiles "https://data.maptiler.com/download/<signed-download-url>"

In the last section of this blog post, I'll show you how to create mbtiles files on your computer.

DNS

For this demo installation, I created the maps.rasc.ch domain. This is optional. You can connect to the server using just the IP address, but you need a domain name if you want to secure the connection with a TLS certificate. And a name is easier to remember than an IP address.

In the web console of my DNS provider, I inserted an A record. Also, add an AAAA record if the server has a public IPv6 address.

maps.rasc.ch.        86400   IN      A       51.38.124.133

If you plan to install a TLS certificate, I recommend adding a CAA record, either for the whole domain if you get all your certificates from one CA or just for the subdomain if you use multiple certificate authorities.

ralscha.ch.             86400   IN      CAA     0 issue "letsencrypt.org"
; OR
maps.rasc.ch.        86400   IN      CAA     0 issue "letsencrypt.org"

TileServer GL

In this section, we install the tile server. But first, make sure that the system is up to date.

apt update
apt full-upgrade

I will run TileServer GL as a Docker container, which is the easiest way to install the service on a server. Alternatively, you could install the software directly on Linux.

Install Docker following the installation instructions on this web page: https://docs.docker.com/engine/install/debian/

Test the Docker installation with docker run hello-world. You should see the Hello from Docker! message if everything is set up correctly.


cd /opt/maps
docker run --name tileserver-gl --restart unless-stopped -d \
  -v $(pwd):/data \
  -p 127.0.0.1:8080:8080 \
  maptiler/tileserver-gl:latest \
  --public_url https://maps.rasc.ch/ \
  --file europe_andorra.mbtiles

With --restart unless-stopped, we ensure that the container always runs after a reboot of the server. To stop it, we have to stop it explicitly.

Make sure that you mount the local directory where the mbtiles files are stored to the /data folder inside the container (-v).

The service listens on local port 8080 and is only reachable from localhost in this setup. Expose the service through Caddy on ports 80/443 instead of opening port 8080 publicly.

The --public_url option is recommended for production deployments behind a reverse proxy. Current TileServer GL documentation also warns about Host header poisoning if you expose the service without a fixed public URL or an allowed host list.

Caddy

A web server in front of TileServer GL lets you enable HTTPS and hide the internal port. You can do this with any web server. A simple solution is Caddy because it automatically manages TLS certificates.

To install Caddy, follow the installation instructions on this page: https://caddyserver.com/docs/install#debian-ubuntu-raspbian

Open the Caddy configuration file.

nano /etc/caddy/Caddyfile

Insert the following configuration. Change the domain accordingly.

{
  email <valid_email_address_for_lets_encrypt>
}
maps.rasc.ch {
   reverse_proxy localhost:8080
}

Restart Caddy:

systemctl restart caddy

If everything is set up correctly, you should now be able to connect to the tile server over HTTPS. In my example, that is https://maps.rasc.ch.

Access map from a web application

You can now start developing web applications and use the map data from the tile server.

For this example, I will use the MapLibre GL JS library. Check out the documentation page for more information. The source code of the library is hosted on GitHub.

Here is a simple HTML page that displays the map of Andorra. Change the center option accordingly if you have downloaded a different region.

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8' />
    <title>Map Example</title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
    <script src="https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.js"></script>
    <link href="https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.css" rel="stylesheet" />
    <style>
        body { margin:0; padding:0; }
        #map { position:absolute; top:0; bottom:0; width:100%; }
    </style>
</head>
<body>

<div id='map'></div>
<script>
  const map = new maplibregl.Map({
       container: 'map',
       style: 'https://maps.rasc.ch/styles/basic-preview/style.json',
       center: [1.5813, 42.5341],
       zoom: 15.65
  });
</script>

</body>
</html>

You don't need to host this file on a server. Instead, you can create it locally and open it in a browser. Make sure that you change the URL of the tile server.

Convert OpenStreetMap data

The data we can download from OpenStreetMap is stored in a raw format that TileServer GL cannot read directly; we have to convert it first. In the previous steps, we downloaded the converted data from https://data.maptiler.com/downloads/planet/, but you can convert the data on your computer if you want.

The developers behind TileServer GL and OpenMapTiles released the necessary conversion tools on GitHub.

Here is an example of how you can convert the OpenStreetMap data of Andorra. I had to install make, git, and Docker Compose first.

apt install make git docker-compose-plugin
git clone https://github.com/openmaptiles/openmaptiles.git
cd openmaptiles
make
./quickstart.sh andorra

The script runs for a few minutes, depending on the size of the map and the computer's performance, and it can take significantly longer for larger extracts. After the script ends successfully, you will find the mbtiles file in the data directory (data/tiles.mbtiles).

If you need higher zoom levels, open the .env file and adjust the zoom settings before running the build again.

MIN_ZOOM=0
MAX_ZOOM=9

Then run ./quickstart.sh again. Note that higher zoom levels require more time, memory, and disk space.

TileServer GL documentation:
https://tileserver.readthedocs.io/en/latest/index.html

OpenMapTiles Homepage:
https://openmaptiles.org/

TileServer GL source code:
https://github.com/maptiler/tileserver-gl