How to Set Up OpenStreetMap Tile Server on Ubuntu 18.04

OpenStreetMap, aka OSM, is a user contributed world map that is freely editable. You can think of it as an open-source and self-hosted alternative to Google Maps. This tutorial will show you how to build your own OpenStreetMap tile server on Ubuntu 18.04 so you don’t have to use a proprietary map service.

OpenStreetMap Features

  • OpenStreetMap data covers the whole world, making it easy to support users in any country, or every country.
  • OpenStreetMap is updated every minute of every hour of every day, and these updates are available to you in real-time.
  • OpenStreetMap data is free and open – there is no subscription fee and no page-view fee.
  • OpenStreetMap data is rich and detailed, containing huge amounts of data which is relevant to people on the ground – the people who collected it.

Prerequisites/Hardware Requirements

The required RAM and disk space depends on which country’s map you are going to use. For example,

  • The UK map requires at least 4G RAM and 60GB disk space.
  • The whole planet map requires at least 32G RAM and 1TB SSD disk. It’s not viable to use a spinning hard disk for the whole planet map.

You will need more disk space if you are going to pre-render tiles to speed up map loading in web browser, which is highly recommended. Check this page to see how much disk space are required for pre-rendering tiles. Another thing to note is that importing large map data, like the whole planet, to PostgreSQL database takes a long time. Consider adding more RAM and especially using SSD instead of spinning hard disk to speed up the import process.

Step 1: Upgrade Software

It’s always a good idea to update server software before doing any major work on your server. Log into your server via SSH and run the following command.

sudo apt update; sudo apt upgrade

Step 2: Install PostgreSQL Database Server and the PostGIS Extension

We will use PostgreSQL to store map data. PostGIS is a geospatial extenstion to PostgreSQL. Run the following commands to install them.

sudo apt install postgresql postgresql-contrib postgis postgresql-10-postgis-2.4

PostgreSQL database server will automatically start and listens on The postgres user will be created on the OS during the installation process. It’s the super user for PostgreSQL database server. By default, this user has no password and there’s no need to set one because you can use sudo to switch to the postgres user and log into PostgreSQL server.

sudo -u postgres -i

Now you can create a PostgreSQL database user osm.

createuser osm

Then create a database named gis and at the same time make osm as the owner of the database. -E UTF8 specifies the character encoding scheme to be used in the database is UTF8.

createdb -E UTF8 -O osm gis

Next, create the postgis and hstore extension for the gis database.

psql -c "CREATE EXTENSION postgis;" -d gis

psql -c "CREATE EXTENSION hstore;" -d gis

Set osm as the table owner.

psql -c "ALTER TABLE spatial_ref_sys OWNER TO osm;" -d gis

Exit from the postgres user.


Create osm user on your operating system so the tile server can run as osm user.

sudo adduser osm

Step 3: Download Map Stylesheet and Map Data

Switch to osm user.

su - osm

Download the latest CartoCSS map stylesheets to the osm user’s home directory. You can check the latest version here. You can always use the following link to download, simply replace the version number.


Extract it.

tar xvf v4.20.0.tar.gz

Next, run the following command to download the map data of the whole planet (44G) in PBF (ProtoBufBinary) format.

wget -c

If you want a map of individual country/state/province/city, go to Also, provides extracts of more than 200 cities and regions world-wide in different formats. For example, download the map data of Great Britain (985M) with the following command.

wget -c

Exit from osm user.


Recommendations before Importing Map Data

Importing map data takes a lot of RAM. If your physical memory is small, you can easily add a swap file to prevent out-of-memory problem. First we use fallocate command to create a file. For example, create a file named swapfile with 2G capacity in root file system. (Increase the size of swapfile if you are going to import a large map.)

sudo fallocate -l 2G /swapfile

Then make sure only root can read and write to it.

sudo chmod 600 /swapfile

Format it to swap:

sudo mkswap /swapfile


Setting up swapspace version 1, size = 2097148 KiB
no label, UUID=h32b3e10-0779-4865-9ea0-6e2af8f3kea9

Enable the swap file

sudo swapon /swapfile

The import process can take some time. It’s recommended to configure SSH keepalive so that you don’t lose the SSH connection. It’s very easy to do. Just open the SSH client configuration file on your local Linux machine.

sudo nano /etc/ssh/ssh_config

And paste the following text at the end of the file.

ServerAliveInterval 60

Then save the file and connect to your Ubuntu server. You can also access the remote server via VNC to prevent flaky connection interrupting the import process.

Step 4: Import the Map Data to PostgreSQL

To import map data, we need to install osm2pgsql which converts OpenStreetMap data to postGIS-enabled PostgreSQL databases.

sudo apt install osm2pgsql

Next, swith to osm user.

su - osm

Run the following command to load map stylesheet and map data into the gis database. Replace great-britain-latest.osm.pbf with your own map data file.

osm2pgsql --slim -d gis --hstore --multi-geometry --number-processes 8 --tag-transform-script /home/osm/openstreetmap-carto-4.20.0/openstreetmap-carto.lua --style /home/osm/openstreetmap-carto-4.20.0/ -C 12000 /home/osm/great-britain-latest.osm.pbf


  • --slim: run in slim mode rather than normal mode. This option is needed if you want to update the map data using OSM change files (OSC) in the future.
  • -d gis: select database.
  • --hstore: add tags without column to an additional hstore (key/value) column to PostgreSQL tables
  • --multi-geometry: generate multi-geometry features in postgresql tables.
  • --style: specify the location of style file
  • --number-processes: number of CPU cores on your server
  • -C flag specify the cache size in MegaBytes. It should be around 80% of the free RAM on your machine. Bigger cache size results in faster import speed. For example, my server has 16GB free RAM, so I can specify -C 12000.
  • Finally, you need to specify the location of map data file.

If you are going to import the full planet map data, then use the --drop option and the --flat-nodes option to increase the import speed. Note that the --flat-nodes option isn’t suitable for small maps.

osm2pgsql --slim -d gis --drop --flat-nodes nodes.cache --hstore --multi-geometry --number-processes 8 --tag-transform-script /home/osm/openstreetmap-carto-4.20.0/openstreetmap-carto.lua --style /home/osm/openstreetmap-carto-4.20.0/ -C 12000 /home/osm/great-britain-latest.osm.pbf

RAM usage will gradually increase during the importing process. Once finished, exit from osm user.


Step 5: Install mod_tile and Renderd

mod_tile is an Apache module that is required to serve tiles and renderd is the rendering daemon for rendering OpenStreetMap tiles. The default Ubuntu repository does not include mod_tile and renderd, but we can install them from the OSM PPA.

sudo add-apt-repository ppa:osmadmins/ppa

sudo apt install libapache2-mod-tile renderd

During the installation, it will install Apache web server and create an Apache config for mod_tile (/etc/apache2/sites-available/tileserver_site.conf). The render daemon will automatically start, as can be seen with:

systemctl status renderd

Step 6: Generate Mapnik Stylesheet

Install required packages.

sudo apt install curl unzip gdal-bin mapnik-utils libmapnik-dev nodejs npm 
sudo npm install -g carto

Switch to osm user.

su - osm

Cd into the carto style directory.

cd /home/osm/openstreetmap-carto-4.20.0/

Get shapefiles.


Now build the Mapnik xml stylesheet with the carto map stylesheet compiler.

carto project.mml > style.xml

Exit from the osm user.


Step 7: Install Fonts

You need to install the ttf-dejavu package.

sudo apt install ttf-dejavu

To display non-Latin characters, install the following packages.

sudo apt install fonts-noto-cjk fonts-noto-hinted fonts-noto-unhinted ttf-unifont

Step 8: Configure renderd

Edit renderd config file.

sudo nano /etc/renderd.conf

In the [renderd] section, change to the number of threads according to the number of CPU cores on your server.


In the [default] section, change the value of XML and HOST to the following.


In [mapnik] section, change the value of plugins_dir to the following.


You can print the default input plugins directory with the following command.

mapnik-config --input-plugins

If you want to display non-Latin characters, it’s better to change the font settings to the following.


Save and close the file. Then edit the init script file

sudo nano /etc/init.d/renderd

Change the following variable. This is needed to load map data from PostgreSQL database.


Save the file. Set osm as the owner of /var/lib/mod_tile/ directory, which will hold the rendered tile files.

sudo chown osm:osm /var/lib/mod_tile/ -R

Then restart renderd service.

sudo systemctl daemon-reload

sudo systemctl restart renderd

You need to check the log of renderd.

sudo journalctl -eu renderd

Make sure renderd does not produce any error in the log, or the map won’t be displayed.

Step 9: Configure Apache

Edit the OSM virtual host file.

sudo nano /etc/apache2/sites-available/tileserver_site.conf

Change the ServerName to your own domain name like You alos need to create DNS A record for this sub-domain.


Save and close the file. Restart Apache.

sudo systemctl restart apache2

Then in your web browser address bar, type

You should see the tile of world map. Congrats! You just successfully built your own OSM tile server.


Display Your Tiled Web Map

Tiled web map is also known as slippy map in OpenStreetMap terminology. There are two free and open source JavaScript map libraries you can use for your tile server: OpenLayer and Leaflet. The advantage of Leaflet is that it is simple to use and your map will be mobile-friendly.


To display your slippy map with OpenLayer, download JavaScript and CSS from and extract it to the web root folder.

cd /var/www/

sudo wget

sudo unzip

Next, create the index.html file.

sudo nano /var/www/index.html

Paste the following HTML code in the file. Replace red-colored text and adjust the longitude, latitude and zoom level according to your needs.

<!DOCTYPE html>
<meta charset="UTF-8">
<title>Accessible Map</title>
<link rel="stylesheet" href="" type="text/css">
<script src=""></script>
  a.skiplink {
    position: absolute;
    clip: rect(1px, 1px, 1px, 1px);
    padding: 0;
    border: 0;
    height: 1px;
    width: 1px;
    overflow: hidden;
  a.skiplink:focus {
    clip: auto;
    height: auto;
    width: auto;
    background-color: #fff;
    padding: 0.3em;
  #map:focus {
    outline: #4A74A8 solid 0.15em;
  <a class="skiplink" href="#map">Go to map</a>
  <div id="map" class="map" tabindex="0"></div>
  <button id="zoom-out">Zoom out</button>
  <button id="zoom-in">Zoom in</button>
    var map = new ol.Map({
      layers: [
        new ol.layer.Tile({
          source: new ol.source.OSM({
             url: '{z}/{x}/{y}.png'
     target: 'map',
     controls: ol.control.defaults({
        attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
          collapsible: false
    view: new ol.View({
       center: [244780.24508882355, 7386452.183179816],

  document.getElementById('zoom-out').onclick = function() {
    var view = map.getView();
    var zoom = view.getZoom();
    view.setZoom(zoom - 1);

  document.getElementById('zoom-in').onclick = function() {
     var view = map.getView();
     var zoom = view.getZoom();
     view.setZoom(zoom + 1);

Save and close the file. Now you can view your slippy map by typing your sub-domain in browser address bar.



To display your slippy map with Leftlet, download JavaScript and CSS from and extract it to the web root folder.

cd /var/www/

sudo wget

sudo unzip

Next, create the index.html file.

sudo nano /var/www/index.html

Paste the following HTML code in the file. Replace red-colored text and adjust the longitude, latitude and zoom level according to your needs.

<meta charset="UTF-8">
<title>My first osm</title>
<link rel="stylesheet" type="text/css" href="leaflet.css"/>
<script type="text/javascript" src="leaflet.js"></script>

  <div id="map"></div>
    var map ='map').setView([53.555,9.899],5);

Save and close the file. Now you can view your slippy map by typing your server IP address in browser.


openstreetmap tile server setup

Pre-render Tiles

Rendering tiles on-the-fly will increase the map loading time in web browser. To pre-render tiles instead of rendering on the fly, use the following render_list command. Use -z and -Z flag specify the zoom level and replace the number of threads according to the number of CPU cores on your server. Render_list renders a list of map tiles by sending requests to the rendering daemon. Pre-rendered tiles will be cached in /var/lib/mod_tile directory.

render_list -m default -a -z 0 -Z 15 --num-threads=8

If later you updated the map data, you can pre-render all tiles again by using the --force option.

render_list -m default -a -z 0 -Z 15 --num-threads=8 --force

Enabling HTTPS

To encrypt HTTP traffic, we can obtain and install a free TLS certificate from Let’s Encrypt. First, install the Let’s Encrypt client (certbot) on Ubuntu 18.04.

sudo add-apt-repository ppa:certbot/certbot

sudo apt install certbot

Since we are using Apache web server, we also need to install the Apache plugin.

sudo apt install python3-certbot-apache

Then run the following command to obtain and install TLS certificate.

sudo certbot --apache --agree-tos --redirect --hsts --staple-ocsp --must-staple --email [email protected] -d

Once the certificate is installed, refresh the web page and you will see a lock in the address bar.

osm tile server ubuntu 18.04 install

If you see a yellow triangle in Firefox address bar, that means the tile URLs are still using HTTP. You need to edit the index.html file and replace all HTTP protocol with HTTPS.

Enable HTTP2

To furthur improve map loading peformance, you can enable HTTP2 protocol. First, you need to enable the HTTP2 module.

sudo a2enmod http2

Then open the SSL virtual host file.

sudo nano /etc/apache2/sites-enabled/tileserver_site-le-ssl.conf

Put the following directive after the opening <VirtualHost *:443> tag.

Protocols h2 http/1.1

Save and close the file. Then restart Apache for the changes to take effect.

sudo systemctl restart apache2

PostgreSQL Database and Web Server on Different Hosts

If your PostgreSQL and Apache web server reside on different hosts, then you need to edit the project.mml file on the Apache host.

nano /home/osm/openstreetmap-carto-4.20.0/project.mml

Find the following lines:

osm2pgsql: &osm2pgsql
  type: "postgis"
  dbname: "gis"
  key_field: ""
  geometry_field: "way"
  extent: "-20037508,-20037508,20037508,20037508"

Specify the IP address of PostgreSQL database server.

osm2pgsql: &osm2pgsql
  type: "postgis"
  host: ""
  dbname: "gis"
  key_field: ""
  geometry_field: "way"
  extent: "-20037508,-20037508,20037508,20037508"

Save and close the file. Then build the Mapnik xml stylesheet with the carto map stylesheet compiler.

carto project.mml > style.xml

On the PostgreSQL database server, edit the main configuration file.

sudo nano /etc/postgresql/10/main/postgresql.conf

Add the following line to set PostgreSQL listen on all interfaces.

listen_addresses = '*'

Save and close the file. Then edit the PostgreSQL client authentication configuration file.

sudo nano /etc/postgresql/10/main/pg_hba.conf

Add the following line at the end of the file to allow the osm user to login from the Apache host. Replace with the IP address of Apache host.

host   gis   osm   trust

Save and close the file. Then restart PostgreSQL.

sudo systemctl restart postgresql

Restart the render daemon on the Apache host.

sudo systemctl restart renderd

You need to check the log of renderd. Make sure renderd does not produce any error in the log, or the map won’t be displayed.

sudo journalctl -eu renderd

You should also restrict access to port 5432 of the PostgreSQL database server. For example, you can use the following UFW command to allow the IP address of Apache host only.

sudo ufw allow in from to any port 5432


I hope this turorial helped you set up OpenStreetMap tile server on Ubuntu 18.04. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care 🙂

Rate this tutorial
[Total: 7 Average: 4.6]

29 Responses to “How to Set Up OpenStreetMap Tile Server on Ubuntu 18.04

  • Phil Rack
    2 months ago

    This is so timely! Since Google maps now requires an API key to use their services, this tutorial allows businesses and other organizations to use maps without having to pay a toll to Google. One other great tutorial (please?) would be how to install Nominatim for geocoding. I’ve looked at this in the past and the tutorials are just not up to the quality one would get from Linuxbabe.

    Thanks for the great tutorials. They are very helpful.

  • Luke Guild
    2 months ago

    hi.. I am trying to follow this but am getting an error when i do the

    3-1. Downloading ‘ne_110m_admin_0_boundary_lines_land’…
    % Total % Received % Xferd Average Speed Time Time Time Current
    Dload Upload Total Spent Left Speed
    0 0 0 0 0 0 0 0 –:–:– 0:00:01 –:–:– 0
    100 295 100 295 0 0 193 0 0:00:01 0:00:01 –:–:– 193
    0 0 0 0 0 0 0 0 –:–:– 0:01:00 –:–:– 0
    curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number

    ‘curl’ error: download failed.

    somehelp please..

    • It seems the curl program on your server is trying to use SSLv3, which is insecure.

      • John Silver
        4 days ago

        I received this error message when I tried to connect proxy and the proxy was not set up properly.
        http_proxy = http: //your.proxy.server: port / good
        https_proxy = https: //your.proxy.server: port / bad doesn’t need https just http
        https_proxy = http: //your.proxy.server: port / good

  • Christian
    2 months ago

    Thank you for the very good tutorial.
    Can you recommend a good tutorial to synchronize the Tilserver with OSM?

  • Marco S.
    1 month ago

    Hi and thanks for the tutorial that I really appreciated. I have only one problem I can’t solve. I don’t have the dir and the 0.png file in my path
    Did I miss any important steps? Thank you for help.

  • Ilia Lev
    1 month ago

    sudo add-apt-repository ppa:osmadmins/ppa
    Not working…
    Returns error:
    E: The repository ‘ cosmic Release’ does not have a Release file.
    N: Updating from such a repository can’t be done securely, and is therefore disabled by default.
    N: See apt-secure(8) manpage for repository creation and user configuration details.

  • Ali Kılıç
    1 month ago
    cannot add PPA: 'ppa:~somadmins/ubuntu/pps'

    what is it happen?

  • Noel Dixon
    1 month ago

    This tutorial worked! Even over the official git, etc. Many thanks –

  • Ali Kılıç
    1 month ago

    search engine api with open street map, prepare tutorial?

  • Issa Hammoud
    4 weeks ago

    Hi. Thank you for the great tutorial.

    I just have a small question. Can I use this server with Nominatim ( in order to send requests about places?
    I tried to use it using my server IP address as “domain” argument of Nominatim constructor but it didn’t work, so should I buy a domain name to be associated with that IP, or this tutorial doesn’t cover Nominatim at all?

    Thanks in advance

  • Ilia Lev
    4 weeks ago

    Thank you again for the great tutorial!
    I followed all the flow and successfully ran the basic view – it shows the map as needed, but there is one problem – for some kind of reason I can’t use the 5000 port…

    On opening url
    I get the: “This site can’t be reached refused to connect.”

    While on opening
    The map is shown as needed

    What can I do?…
    I have digitalocean server with ubuntu 18.04 and apache

    • What service is using the port 5000 on your server? Maybe your firewall is blocking inbound connection to port 5000.

      • Ilia Lev
        4 weeks ago

        I checked it with netstat -na | grep 5000
        but got an empty response…
        So is it possible that there is nothing listening on port 5000?

      • Ilia Lev
        4 weeks ago

        This is the result of firewall test:

        21/tcp closed ftp
        22/tcp open ssh
        23/tcp closed telnet
        80/tcp open http
        110/tcp closed pop3
        143/tcp closed imap
        443/tcp closed https
        3389/tcp closed ms-wbt-server

    • This article only shows setting up the OSM tile server. You need to install OSRM (open source routing machine).

  • John Silver
    4 days ago

    Thanks for the article, it works perfectly.

  • Hey,
    first of all thanks for the instructions. It works great.
    But I’ve got one problem: I don’t see any streets in any zoomlevel higher than 9 (at 9 it works). How to fix this?

    • Have you tried to pre-render tiles with render_list command?

      • Yes. I’m rendering zoomlevel 13 or 14 right now. That’s why it’s confusing me.

    • Check the Apache log file under /var/log/apache/ directory or the renderd log (sudo journalctl -eu renderd) to see if you can find any clue.

      • I can’t seem to find any problems.
        Maybe you or anyone else can ->
        That’s how my whole Apache error.log looks like:

         [Wed Jun 05 14:52:18.948012 2019] [tile:info] [pid 1369:tid 140564926285568] [client x.x.x.x:51638] tile_storage_hook: handler(tile_serve), uri(/osm/13/4293/2667.png), referer:
        [Wed Jun 05 14:52:18.949376 2019] [tile:info] [pid 1368:tid 140565840631552] [client x.x.x.x:51640] tile_storage_hook: handler(tile_serve), uri(/osm/13/4292/2670.png), referer:
        [Wed Jun 05 14:52:18.950560 2019] [tile:info] [pid 1369:tid 140566444611328] [client x.x.x.x:51639] tile_storage_hook: handler(tile_serve), uri(/osm/13/4298/2667.png), referer: 

        And that’s what my journalctl says:

         Jun 05 14:56:17 osm renderd[13665]: DEBUG: DONE TILE default 13 3400-3407 4000-4007 in 0.467 seconds
        Jun 05 14:56:17 osm renderd[13665]: DEBUG: START TILE default 13 3400-3407 4032-4039, new metatile
        Jun 05 14:56:17 osm renderd[13665]: Rendering projected coordinates 13 3400 4032 -> -3404810.987937|273950.309374 -3365675.229455|313086.067856 to a 8 x 8 tile 
    • I can’t find any problem either.

Leave a Comment

  • Comments with links are moderated by admin before published.
  • Your email address will not be published.
  • Use <pre> ... </pre> HTML tag to quote the output from your terminal/console.
  • Please use the community ( for questions unrelated to this article.
  • If my answer helped you, please consider supporting this site. Thanks :)