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 that is relevant to people on the ground – the people who collected it.

Prerequisites/Hardware Requirements

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

  • The UK map requires at least 12G 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 the web browser, which is highly recommended. Check this page to see how much disk space are required for pre-rendering tiles. For example, if you are going to pre-render tiles from zoom level 0 to zoom level 15 for the planet map, an extra 460 GB disk space is required.

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.

If you are going to host the entire world map, I recommend you buy the extra-large VPS from Contabo, which boasts

  • A 10 core CPU
  • 60 GB RAM
  • 1.6 TB Intel Optane SSD

It costs just 26.99 €/month.

Step 1: Upgrade Software

It’s always a good practice 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 extension 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 127.0.0.1:5432. 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.

exit

Create osm user on your operating system so the tile server can run as osm user. The following command will create a system user without password.

sudo adduser --system osm

Step 3: Download Map Stylesheet and Map Data

Change to osm’s home directory.

cd /home/osm/

Download the latest CartoCSS map stylesheets to the osm user’s home directory with git.

sudo apt install git

git clone https://github.com/gravitystorm/openstreetmap-carto.git

If you see “permission denied” error while running the above command, then you can grant permissions with the following command. Replace username with your real username.

sudo setfacl -R -m u:username:rwx /home/osm/

Then run one of the following commands to download the map data in PBF (ProtoBufBinary) format.

Britain and Ireland (1.7G)

wget -c http://download.geofabrik.de/europe/britain-and-ireland-latest.osm.pbf

Europe (25.8G)

wget -c http://download.geofabrik.de/europe-latest.osm.pbf

North America (11.8G)

wget -c http://download.geofabrik.de/north-america-latest.osm.pbf

South America (2.9G)

wget -c http://download.geofabrik.de/south-america-latest.osm.pbf

Central America (570MB)

wget -c http://download.geofabrik.de/central-america-latest.osm.pbf

Asia (11.2G)

wget -c http://download.geofabrik.de/asia-latest.osm.pbf

Africa (5.5G)

wget -c http://download.geofabrik.de/africa-latest.osm.pbf

Whole planet (66G). Note: I recommend only downloading the whole plant map when you really need to display the map of the whole world, or you will waste time waiting for the tile server to process unnecessary data.

wget -c http://planet.openstreetmap.org/pbf/planet-latest.osm.pbf

or

wget -c https://download.bbbike.org/osm/planet/planet-latest.osm.pbf

If you want other map of individual country/state/province/city, go to http://download.geofabrik.de. Also, BBBike.org provides extracts of more than 200 cities and regions worldwide in different formats.

Step 4: Optimize PostgreSQL Server Performance

The import process can take some time. To speed up this process, we can tune some PostgreSQL server settings to improve performance. Edit PostgreSQL main configuration file.

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

First, we should change the value of shared_buffers. The default setting is:

shared_buffers = 128MB

This is too small. The rule of thumb is to set it to 25% of your total RAM (excluding swap space). For example, my VPS has 60G RAM, so I set it to:

shared_buffers = 15GB

Find the following line.

#work_mem = 4MB
#maintenance_work_mem = 64MB

Again, the value is too small.

work_mem = 1GB
maintenance_work_mem = 8GB

Then find the following line.

#effective_cache_size = 4GB

If you have lots of RAM like I do, you can set a higher value for the effective_cache_size like 20G.

effective_cache_size = 20GB

Save and close the file. Restart PostgreSQL for the changes to take effect.

sudo systemctl restart postgresql

By default, PostgreSQL would try use huge pages in RAM. However, Linux by default does not allocate huge pages. Check the process ID of PostgreSQL.

sudo head -1 /var/lib/postgresql/10/main/postmaster.pid

Sample output:

7031

Then check the VmPeak value of this process ID.

grep ^VmPeak /proc/7031/status

Sample output:

VmPeak: 16282784 kB

This is the peak memory size that will be used by PostgreSQL. Now check the size of huge page in Linux.

cat /proc/meminfo | grep -i huge

Sample output:

AnonHugePages:         0 kB
ShmemHugePages:        0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB

We can calculate how many huge pages we need. Divide the VmPeak value by the size of huge page: 16282784 kB / 2048 kB = 7950. Edit /etc/sysctl.conf file.

sudo nano /etc/sysctl.conf

Add the following line at the end of this file allocate 7950 huge pages.

vm.nr_hugepages = 7950

postgresql hugepages

Save and close the file. Then apply the changes.

sudo sysctl -p

If you check the meminfo again,

cat /proc/meminfo | grep -i huge

We can see there are 7950 huge pages available.

AnonHugePages:         0 kB
ShmemHugePages:        0 kB
HugePages_Total:    7950
HugePages_Free:     7950
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB

Restart PostgreSQL to use huge pages.

sudo systemctl restart postgresql

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 5: 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

Grant permissions to the postgres user.

sudo setfacl -R -m u:postgres:rwx /home/osm/

Switch to the postgres user.

sudo -u postgres -i

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 10 --tag-transform-script /home/osm/openstreetmap-carto/openstreetmap-carto.lua --style /home/osm/openstreetmap-carto/openstreetmap-carto.style -C 32000 /home/osm/great-britain-latest.osm.pbf

where

  • --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. I have 10.
  • -C flag specifies the cache size in MegaBytes. It should be around 70% of the free RAM on your machine. Bigger cache size results in faster import speed. For example, my server has 60GB RAM, so I can specify -C 32000. Be aware that PostgreSQL will need RAM for shared_buffers. Use this formula to calculate how big the cache size should be: (Total RAM - PostgreSQL shared_buffers) * 70%
  • Finally, you need to specify the location of map data file.

Command Output:

openstreetmap osm2pgsql import great britain map

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 10 --tag-transform-script /home/osm/openstreetmap-carto/openstreetmap-carto.lua --style /home/osm/openstreetmap-carto/openstreetmap-carto.style -C 32000 /home/osm/planet-latest.osm.pbf

RAM usage will gradually increase during the importing process. Once the import is complete, grant all privileges of the gis database to the osm user.

psql -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO osm;" -d gis

Exit from the postgres user.

exit

Step 6: 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 apt install software-properties-common

sudo add-apt-repository ppa:osmadmins/ppa

sudo apt install libapache2-mod-tile renderd

During the installation, it will install Apache web server and ask if you want to enable mod_tile in the Apache config. Select Yes and press Enter. This will create an Apache config file for mod_tile (/etc/apache2/sites-available/tileserver_site.conf).

apache mod_tile

The render daemon will automatically start, as can be seen with:

systemctl status renderd

Step 7: Generate Mapnik Stylesheet

Install the required packages.

sudo apt install curl unzip gdal-bin mapnik-utils libmapnik-dev python3-pip

We also need to install nodejs and npm from the upstream repository with the following commands.

curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt-get install -y nodejs

Then install the carto package with npm.

sudo npm install -g carto

Install the psycopg2 Python module.

sudo -H pip3 install psycopg2==2.8.5

Switch to the postgres user.

sudo -u postgres -i

Cd into the carto style directory.

cd /home/osm/openstreetmap-carto/

Get shapefiles.

scripts/get-external-data.py

If you encounter the following error message while running the above command, then you have DNS issues. Simply wait for several minutes and run the Python script again.

Failed to establish a new connection: [Errno -3] Temporary failure in name resolution

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

carto project.mml > style.xml

Grant all privileges of the gis database to the osm user.

psql -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO osm;" -d gis

Exit from the postgres user.

exit

Step 8: 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 9: Configure renderd

Edit renderd config file.

sudo nano /etc/renderd.conf

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

num_threads=10

In the [default] section, change the value of XML and HOST to the following. Note that lines beginning with semicolons (;) are comments.

XML=/home/osm/openstreetmap-carto/style.xml
HOST=map.your-domain.com

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

plugins_dir=/usr/lib/mapnik/3.0/input/

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.

font_dir=/usr/share/fonts/truetype
font_dir_recurse=true

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

sudo nano /etc/init.d/renderd

Find the following line.

RUNASUSER=www-data

Change the user to osm. This is needed to load map data from PostgreSQL database.

RUNASUSER=osm

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

sudo chown 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 10: 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 map.yourdomain.com. You also need to create DNS A record for this sub-domain.

ServerName map.yourdomain.com

Save and close the file. Restart Apache.

sudo systemctl restart apache2

Then in your web browser address bar, type

map.your-domain.com/osm/0/0/0.png

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

osm-tile-for-world-map

If you have enabled the UFW firewall, be sure to open port 80 and 443 with the following command.

sudo ufw allow 80,443/tcp

Step 11: 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.

OpenLayer

To display your slippy map with OpenLayer, download JavaScript and CSS from openlayer.org and extract it to the webroot folder.

cd /var/www/

sudo wget https://github.com/openlayers/openlayers/releases/download/v5.3.0/v5.3.0.zip

sudo unzip v5.3.0.zip

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>
<html>
<head>
<meta charset="UTF-8">
<title>Accessible Map</title>
<link rel="stylesheet" href="http://map.yourdomain.com/v5.3.0/css/ol.css" type="text/css">
<script src="http://map.yourdomain.com/v5.3.0/build/ol.js"></script>
<style>
  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;
  }
</style>
</head>
<body>
  <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>
  <script>
    var map = new ol.Map({
      layers: [
        new ol.layer.Tile({
          source: new ol.source.OSM({
             url: 'http://map.yourdomain.com/osm/{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],
       zoom:5
    })
 });

  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);
  };
</script>
</body>
</html>

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

map.yourdomain.com

or

map.yourdomain.com/index.html

Leaflet

To display your slippy map with Leftlet, download JavaScript and CSS from leftletjs.com and extract it to the webroot folder.

cd /var/www/

sudo wget http://cdn.leafletjs.com/leaflet/v1.6.0/leaflet.zip

sudo unzip leaflet.zip

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.

<html>
<head>
<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>
<style>
   #map{width:100%;height:100%}
</style>
</head>

<body>
  <div id="map"></div>
  <script>
    var map = L.map('map').setView([53.555,9.899],5);
    L.tileLayer('http://map.yourdomain.com/osm/{z}/{x}/{y}.png',{maxZoom:18}).addTo(map);
</script>
</body>
</html>

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

map.yourdomain.com

or

map.yourdomain.com/index.html

openstreetmap tile server setup

Step 12: 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 19 --num-threads=10

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 19 --num-threads=10 --force

To render map tiles in the background, add the & symbol at the end.

render_list -m default -a -z 0 -Z 19 --num-threads=10 &

Now you can close the terminal window. To check the rendering progress, open another SSH session, and run the following command.

sudo journalctl -eu renderd

The above command will show the latest log of the renderd service. The following lines show that my OSM server is now rendering map tiles at zoom level 12.

 renderd[20838]: DEBUG: START TILE default 12 1008-1015 4056-4063, new metatile
 renderd[20838]: Rendering projected coordinates 12 1008 4056 -> -10175297.205328|-19724422.274944 -10097025.688364|-19646150.757980 to a 8 x 8 tile
 renderd[20838]: DEBUG: DONE TILE default 12 1008-1015 3984-3991 in 0.799 seconds
 renderd[20838]: DEBUG: Sending render cmd(3 default 12/1008/3984) with protocol version 2 to fd 18
 renderd[20838]: DEBUG: Got incoming request with protocol version 2
 renderd[20838]: DEBUG: Got command RenderBulk fd(18) xml(default), z(12), x(1008), y(4064), mime(image/png), options()
 renderd[20838]: DEBUG: START TILE default 12 1008-1015 4064-4071, new metatile
 renderd[20838]: Rendering projected coordinates 12 1008 4064 -> -10175297.205328|-19802693.791908 -10097025.688364|-19724422.274944 to a 8 x 8 tile

Step 13: Enable 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 map.yourdomain.com

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 with the following command.

sudo sed -i 's/http/https/g' /var/www/index.html

Step 14: Enable HTTP2

To further improve map loading performance, 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

Restrict Access to Your OSM Tile Server

By default, anyone can use OpenLayer or Leaflet to create a slippy map with the URL of your tile server. To restrict access to your tile server, edit the Apache virtual host file.

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

Add the following lines in the <VirtualHost> tags.

    <Location /osm>
        SetEnvIf Referer example\.com trusted_referer
        Order deny,allow
        Deny from all
        Allow from env=trusted_referer
    </Location>

The above code checks if the HTTP referer header includes your own domain. If not, access to the /osm directory will be denied. The backslash is used to escape the dot character. To add multiple hostnames as trusted refererrs, use the following syntax.

SetEnvIf Referer (example\.com|www\.example\.com|map\.example\.com) trusted_referer

Save and close the file. Then test the syntax.

sudo apache2ctl -t

If the syntax is Ok, reload Apache for the changes to take effect.

sudo systemctl reload apache2

Auto-Renew TLS Certificate

You can create Cron job to automatically renew TLS certificate. Simply open root user’s crontab file.

sudo crontab -e

Add the following line at the bottom of the file.

@daily certbot renew --quiet && systemctl reload 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: "10.0.0.2"
  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 to 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 10.0.0.1 with the IP address of Apache host.

host   gis   osm   10.0.0.1/32   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 10.0.0.1 to any port 5432

How to Upgrade PostgreSQL Database Server

When a new version of PostgreSQL comes out, you can upgrade to take advantage of performance improvements. Simply run the following command, and the apt package manager will install the latest version of PostgreSQL from the apt.postgresql.org repository.

sudo apt update; sudo apt upgrade -y

After that, you also need to upgrade existing PostgreSQL clusters. Pro Tip: You should open a GNU Screen session to prevent connection drop because the upgrade will take sometime.

screen

Then list current clusters.

sudo pg_lsclusters

Sample output:

Ver Cluster Port Status Owner    Data directory              Log file
10  main    5432 online postgres /var/lib/postgresql/10/main /var/log/postgresql/postgresql-10-main.log
12  main    5433 online postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log
14  main    5434 online postgres /var/lib/postgresql/14/main /var/log/postgresql/postgresql-14-main.log

As you can see, PostgreSQL 10 is using the default 5432 port. PostgreSQL 12 is using port 5433 and PostgreSQL 14 is using port 5434. Stop PostgreSQL server.

sudo systemctl stop postgresql

Let’s check the cluster status again with: sudo pg_lsclusters. They are all down.

Ver Cluster Port Status Owner    Data directory              Log file
10  main    5432 down   postgres /var/lib/postgresql/10/main /var/log/postgresql/postgresql-10-main.log
12  main    5433 down   postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log
14  main    5434 down   postgres /var/lib/postgresql/14/main /var/log/postgresql/postgresql-14-main.log

Rename the cluster name of  PostgreSQL 14 from main to latest_stable.

sudo pg_renamecluster 14 main latest_stable

Then we need to shrink the PostgreSQL shared_buffer.

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

Decrease the value to prevent out-of-memory problem during upgrade. For example, I reduce the value from 15GB to 5GB.

shared_buffers = 5GB

Save and close the file.

Next, upgrade the old PostgreSQL 10 cluster.

sudo pg_upgradecluster 10 main

Start PostgreSQL  server.

sudo systemctl start postgresql

Now check if your application is working. If it’s working well, then drop the old cluster.

sudo pg_dropcluster 10 main

Check cluster status again:

sudo pg_lsclusters

If the upgrade is successful, you can change the shared_buffer back to the original value in the /etc/postgresql/14/main/postgresql.conf file. Don’t forget to restart PostgreSQL.

If the upgrade procedure can’t stop PostgreSQL,

pg_ctl: server does not shut down
Error: Could not stop target cluster

then you need to run the following command to stop PostgreSQL.

pkill postgres

Then edit PostgreSQL 10 config file.

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

Set the listen port to 5432.

port = 5432

Save and close the file. Then start PostgreSQL 14.

sudo systemctl restart postgresql@14-main

Run the following command to make sure you can log into PostgreSQL console.

sudo -u postgres -i psql

Press Ctrl+D to log out.

Also restart renderd, or you might encounter the “Received request for map layer ‘default’ which failed to load” error in renderd.

sudo systemctl restart renderd

Conclusion

I hope this tutorial 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: 16 Average: 4.8]

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

  • Phil Rack
    5 years 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
    5 years ago

    hi.. I am trying to follow this but am getting an error when i do the
    scripts/get-shapefiles.py

    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..

    • Xiao Guo An (Admin)
      5 years ago

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

      • John Silver
        5 years 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

        • Bogdan
          5 years ago

          the links moved and are now under osmdata.openstreetmap.de

          I have replaced the four problem links in the file with the following

          https://osmdata.openstreetmap.de/download/simplified-land-polygons-complete-3857.zip
          https://osmdata.openstreetmap.de/download/land-polygons-split-3857.zip
          https://osmdata.openstreetmap.de/download/antarctica-icesheet-polygons-3857.zip
          https://osmdata.openstreetmap.de/download/antarctica-icesheet-outlines-3857.zip

  • Christian
    5 years ago

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

  • Marco S.
    5 years 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 mydomain.com/osm/0/0/0.png
    Did I miss any important steps? Thank you for help.

    • Xiao Guo An (Admin)
      5 years ago

      The tile files are stored in /var/lib/mod_tile/default/ directory, not in the web root directory.

  • Ilia Lev
    5 years ago

    sudo add-apt-repository ppa:osmadmins/ppa
    Not working…
    Returns error:
    E: The repository ‘http://ppa.launchpad.net/osmadmins/ppa/ubuntu 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.

    • Xiao Guo An (Admin)
      5 years ago

      This PPA doesn’t support Ubuntu 18.10.

      • Ilia Lev
        5 years ago

        Thank you!
        For some kind of reason I was sure that I installed the 18.04…

  • Noel Dixon
    5 years ago

    This tutorial worked! Even over the official git, etc. Many thanks – 178.128.53.65/mobile.html

  • Ali Kılıç
    5 years ago

    search engine api with open street map, prepare tutorial?

  • Issa Hammoud
    5 years ago

    Hi. Thank you for the great tutorial.

    I just have a small question. Can I use this server with Nominatim (https://geopy.readthedocs.io/en/stable/#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

    • Xiao Guo An (Admin)
      5 years ago

      This tutorial doesn’t cover installing Nominatim.

  • Ilia Lev
    5 years ago

    Hi.
    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 http://xxx.xxx.xxx.xxx:5000/
    I get the: “This site can’t be reached xxx.xxx.xxx.xxx refused to connect.”

    While on opening http://xxx.xxx.xxx.xxx/
    The map is shown as needed

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

    • Xiao Guo An (Admin)
      5 years ago

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

      • Ilia Lev
        5 years 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
        5 years ago

        This is the result of firewall test:

        PORT STATE SERVICE
        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

    • Xiao Guo An (Admin)
      5 years ago

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

  • John Silver
    5 years 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?

    • Xiao Guo An (Admin)
      5 years ago

      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.

        • Anant Tyagi
          4 years ago

          Hi,
          Its an amazing tutorial. But i am facing one issue.
          I want to setup the map server for personal use, so instead of domain name i entered one ip address and the same ip address I gave it to my server.
          But i get “unable to connect” error when i open the link http://xx.xx.xx.x/osm/0/0/0.png
          Have i done some mistake? Pls suggest

    • Xiao Guo An (Admin)
      5 years ago

      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: http://192.168.12.10/
        [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: http://192.168.12.10/
        [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: http://192.168.12.10/ 

        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 
    • Xiao Guo An (Admin)
      5 years ago

      I can’t find any problem either.

      • Maybe

        --socket=/var/run/renderd/renderd.sock

        attribute in renderd command ?

  • For the “map.yourdomain.com” what does it refer to ? for example great-britain and the server IP ? “great-britain.ip” for example ?

    • Xiao Guo An (Admin)
      5 years ago

      To make your map publicly accessible, you need to have a domain name like map.google.com. I registered my domain name from NameCheap because the price is low and they give whois privacy protection free for life.

  • Hi, do you have an example of what to fill in “map.yourdomain.com” ? i have really no idea of what to put there
    thanks

    • Xiao Guo An (Admin)
      5 years ago

      To make your map publicly accessible, you need to have a domain name like map.google.com. I registered my domain name from NameCheap because the price is low and they give whois privacy protection free for life.

      • And do I must make it publicly accessible? I mean can’t I just use privatly for a personal project

    • Xiao Guo An (Admin)
      5 years ago

      You can enter your server’s IP address instead of a domain name, if you just use it for a personal project, but you won’t be able to enable HTTPS with certbot for an IP address.

  • Hi again, thanks for the tutorial worked for me, do you know some good websites or articles that help us fill our map with precise mapping, itinerary and other features ?

  • Thanks for your tutorial … amazing job !

    Just a question : If I want to add new data after I follow this tutorial, what must I do ?

    Thanks again

    • Hi, that’s also my next step. I would like to manually update the data once a month. This tutorial here is great 🙂

  • coderplus
    5 years ago

    Error: you need shapeindex (or shapeindex is not in the
    PATH). Otherwise, use ‘-s’ option to skip shapeindex
    (indexing shapes is suggested for performance improvement)
    I am getting this error please help me to solve this!

  • Thank you very much for this tutorial. It was very detailed and helpful. I have setup my own server thanks to you!

  • clap clap clap. straightforward… SIMPLY AMAZING.

    THANK YOU VERY MUCH FOR SHARING THIS TUTORIAL

  • Hi Xiao
    thanks for this awesome tutorial!

    I am considering using the VPS you suggested, but do you know any reliable alternatives?
    Thanks for your time!

  • Yes, I came upon Hetzner just yesterday in my search, and it seems a very good alternative.
    Did you have direct experience in working with Contabo? Would you recommend it?

    Thanks for your reply, have a nice day!

    • Xiao Guoan (Admin)
      5 years ago

      I came across Contabo in September 2019 and bought the small VPS in October 31, 2019 for another project. So far so good.

      I don’t have experience in running OpenStreetMap on the Contabo XL VPS, but I’m considering giving it a test in the near future.

      The most important factor for hosting the world map are CPU power, enough RAM, fast read and write speed. I once tried to use spinning hard disk, but it took 2 hours to generate a single map tile.

  • Hi,
    I thank you for this tutorial..
    I have a problem with the step 9.
    I get a 404 error when I try to launch my.domain.com/osm/0/0/0.png
    As Marco, my /var/lib/mod_tile/ folder is empty (I have not default folder within this directory).
    FYI, I have downloaded the full planet.
    Any help?

    • Xiao Guoan (Admin)
      5 years ago

      There’s not much I can do except if you are willing to allow me to access the server and pay me to fix the error.

      • Thanks for your reply.. it finally works.. I had to restart the renderd service..(don’t know why).

        • Zafer Gokhan Unal
          5 years ago

          I get the same error.
          Is there a solution?

  • I am a Product Owner reading about this topic. I am wondering if it would be a benefit if the tiles itself would be hosted on Amazon S3 + Cloudfront?

    • Xiao Guoan (Admin)
      5 years ago

      Yes, it would be better to cache the tiles on a CDN after they are rendered.

      • What is the best way to cache the tiles in S3?
        Is there a way to pre-render tiles directly to S3 and configure renderd to point to that S3 bucket?

  • SK ASIF RAJA
    5 years ago

    I have already deployed the map server and it is working for now But how to update new locations/data in my stand-alone openstreetmap -server?

  • Sharma Nadakuditi
    5 years ago

    This worked really well. Saved me a ton of time with OSM not working intermittently and also as PoC etc.
    1. If I need to add different pbf files (after first one), do you know how to append? (use –append to the “osm2pgsql –slim” command?)
    2. Can you share how to append the changes (.osc.gz) files ?

  • where can i find other stylesheets?

  • How to put a watermark at render?

  • On step 6 at line “sudo apt install curl unzip gdal-bin mapnik-utils libmapnik-dev nodejs npm” i’ve got error about broken packeges. Solved this by installing aptitude (sudo apt install aptitude). Then instead of apt ran aptitude (sudo aptitude install curl unzip gdal-bin mapnik-utils libmapnik-dev nodejs npm). After that choosed a variant with downgrade of packages (on request “[Y/n/q/?]” type “.” and press Enter to see next variant of installation. That all. Sorry for me English. Hope its useful. Ubuntu server 18.04.4 VirtualBox.

  • podunlami
    4 years ago

    on request “[Y/n/q/?]” type “.”
    There is no dot

  • podunlami
    4 years ago

    Oh i see. Thx @Bohdan

  • Nicolai
    4 years ago

    I get the error:

    E: Unable to locate package libapache2-mod-tile
    E: Unable to locate package renderd

    after I did sudo apt install libapache2-mod-tile renderd

    I already did sudo add-apt-repository ppa:osmadmins/ppa succesfully.

    Is it because I’m using ARM?

    • Xiao Guoan (Admin)
      4 years ago

      Yes. This PPA doesn’t provide ARM packages.

  • Hi. Thank you for this great tutorial. I am trying it, but get an error at the ‘ git clone https://github.com/gravitystorm/openstreetmap-carto.git ‘ it says: ‘fatal: could not create work tree dir ‘openstreetmap-carto’: Permission denied’. I know it has to do with permissions for the /home/osm folder, but don’t know how to fix it without deviating from your installation instructions, which might cause me issues later on?

    • Xiao Guoan (Admin)
      4 years ago

      You can use sudo, or switch to root user, or you can grant permissions with the following command. Replace username with your real username.

      sudo setfacl -R -m u:username:rwx /home/osm/
      • Thank you! That worked? Am I the only one with this issue? Because wondering what I did wrong then. Btw it solved it for me it seems. Thank you again!

  • Patrick
    4 years ago

    Anyone knows how to update the map data?

  • blaster
    4 years ago

    Hello Xiao Guoan.
    thanks for the article How to Set Up OpenStreetMap Tile Server on Ubuntu 18.04
    Based on the article, I set up an offline map server
    while routing does not work
    C # language example:
    gmap.MapProvider = GMap.NET.MapProviders.OpenStreetMapProvider.Instance;
    GMap.NET.GMaps.Instance.Mode = GMap.NET.AccessMode.ServerAndCache;
    // gmap.SetPositionByKeywords (“Paris, France”);
    // gmap.ShowCenter = false;

    PointLatLng start = new PointLatLng (41.3109325, 69.2826225);
    PointLatLng end = new PointLatLng (41.3109325, 69.3826225);
    MapRoute route = GMap.NET.MapProviders.OpenStreetMapProvider.Instance.GetRoute (start, end, false, false, 15);
    GMapRoute r = new GMapRoute (route.Points, “My route”);
    //MessageBox.Show ();
    GMapOverlay routesOverlay = new GMapOverlay (“routes”);
    routesOverlay.Routes.Add (r);
    gmap.Overlays.Add (routesOverlay);

    javascript example

    window.onload = function(){
    alert(‘Click on the map it set Start and End waypoints’);
    }

    var mbAttr = ‘Map data © OpenStreetMap contributors, ‘ +
    CC-BY-SA, ‘ +
    ‘Imagery © Mapbox‘,
    mbUrl = ‘http://192.168.2.4/osm/{z}/{x}/{y}.png’;

    var street = L.tileLayer(mbUrl, {id: ‘mapbox.streets’, maxZoom:18, attribution: mbAttr}),
    satellite = L.tileLayer(mbUrl, {id: ‘mapbox.streets-satellite’, maxZoom:18, attribution: mbAttr});

    var map = L.map(‘map’, {
    layers:[street]}).setView([47.25, -122.44], 11);

    var baseLayers = {
    “Street”: street,
    “Satellite”: satellite
    };
    L.control.layers(baseLayers).addTo(map);

    var easyButton = L.easyButton(‘fas fa-crosshairs’, function(btn, map){
    map.locate({setView: true, maxZoom: 18});
    }).addTo(map); //not passing latlng to geocoder/routing machine

    var control = L.Routing.control({
    waypoints: [
    null
    ],
    routeWhileDragging: true,
    units: ‘imperial’,
    router: L.Routing.mapbox(‘pk.eyJ1IjoicnlhbmptaXRjaCIsImEiOiJjamhhdDBjaXgwcmZlMzBxZ2t1cnZ4bnFnIn0.4tXv0Yvk06rDbYp7ZLSdAw’),
    geocoder: L.Control.Geocoder.nominatim(),
    }).addTo(map);

    function createButton(label, container) {
    var btn = L.DomUtil.create(‘button’, ”, container);
    btn.setAttribute(‘type’, ‘button’);
    btn.innerHTML = label;
    return btn;
    }
    map.on(‘click’, function(e) {

    var container = L.DomUtil.create(‘div’),
    startBtn = createButton(‘Start from this location’, container),
    destBtn = createButton(‘End at this location’, container);

    L.DomEvent.on(startBtn, ‘click’, function() {
    control.spliceWaypoints(0, 1, e.latlng);
    map.closePopup();
    });

    L.DomEvent.on(destBtn, ‘click’, function() {
    control.spliceWaypoints(control.getWaypoints().length – 1, 1, e.latlng);
    map.closePopup();
    });

    L.popup()
    .setContent(container)
    .setLatLng(e.latlng)
    .openOn(map);
    });

    //locate user
    function onLocationError(e) {
    alert(e.message);
    }

    map.on(‘locationfound’, onLocationFound);
    map.on(‘locationerror’, onLocationError);
    map.locate({
    setView: false,
    maxZoom: 16,
    timeout: 15000,
    watch: false,
    });

  • amaziiiiiiing post. thank you very much.

  • Parmjit Singh
    4 years ago

    when i import data to postgresql it gets killed after sometime. ways and nodes got processsed whenit was processing relations . It got killed . Just displsying killed and nothing else

  • Parmjit Singh
    4 years ago

    Server specs are ok. I have 32 gb ram 16 cores 500gb hard drive space and i am trying to import northamerica-latest-osm

    postgres@tile-ProLiant-DL380-G6:~$ osm2pgsql –slim -d gis –hstore –multi-geometry –number-processes 16 –tag-transform-script /home/osm/openstreetmap-carto/openstreetmap-carto.lua –style /home/osm/openstreetmap-carto/openstreetmap-carto.style -C 16000 /home/osm/north-america-latest.osm.pbf
    osm2pgsql version 0.94.0 (64 bit id space)

    Using lua based tag processing pipeline with script /home/osm/openstreetmap-carto/openstreetmap-carto.lua
    Using projection SRS 3857 (Spherical Mercator)
    Setting up table: planet_osm_point
    Setting up table: planet_osm_line
    Setting up table: planet_osm_polygon
    Setting up table: planet_osm_roads
    Allocating memory for dense node cache
    Allocating dense node cache in one big chunk
    Allocating memory for sparse node cache
    Sharing dense sparse
    Node-cache: cache=16000MB, maxblocks=256000*65536, allocation method=11
    Mid: pgsql, cache=16000
    Setting up table: planet_osm_nodes
    Setting up table: planet_osm_ways
    Setting up table: planet_osm_rels

    Reading in file: /home/osm/north-america-latest.osm.pbf
    Using PBF parser.
    Processing: Node(1205745k 189.7k/s) Way(99995k 9.53k/s) Relation(91140 55.74/s)Killed

    • Xiao Guoan (Admin)
      4 years ago

      When importing the map data, open another terminal session and monitor how much RAM is being used.

      You can also check your syslog (/var/log/syslog), you will probably find something like:

      Out of memory: Killed process 32580 (osm2pgsql)

      Which indicates your server is out of memory and the osm2pgsql process is killed.

  • Yury Tkachuk
    4 years ago

    When the repository ppa: osmadmins / ppa branch appears under Ubuntu 20.04?

  • weiiiii
    4 years ago

    Get shapefiles.

    scripts/get-shapefiles.py.

    I followed all the steps here but i not sure why i receive this error when i ran the steps above.
    “bash: scripts/get-shapefiles.py: No such file or directory”

    Where can i get this file ? Thank you. Would appreciate if anyone can help me with this.

    • Xiao Guoan (Admin)
      4 years ago

      This script was renamed to get-external-data.py about 20 days ago. I just updated the instructions in step 7.

  • “scripts/get-shapefiles.py ”

    Same problem here. It’s missing.

    • Xiao Guoan (Admin)
      4 years ago

      This script was renamed to get-external-data.py about 20 days ago. I just updated the instructions in step 7.

  • hi
    tnx for your tutorial. how we can update tiles automatically??

  • how can i set up offline routing in ubuntu ??

  • Aleksei
    4 years ago

    Hey. This is a very helpful post! Many thanks!
    But I have a problem:
    I start to pre-render the tiles, and after about a few hours, rendering stops. Then I reboot the server, start pre-rendering again and see the same problem after a few hours or a few minutes. Each time, rendering continues from where it stopped. I’m now at 12th zoom.
    This is my log:

    Aug 19 05:54:40 ubuntu_server renderd[1676]: DEBUG: Sending render cmd(3 default 12/1176/2464) with protocol version 2 to fd 10
    Aug 19 05:54:40 ubuntu_server renderd[1676]: DEBUG: Got incoming request with protocol version 2
    Aug 19 05:54:40 ubuntu_server renderd[1676]: DEBUG: Got command RenderBulk fd(10) xml(default), z(12), x(1176), y(2496), mime(image/png), options()
    Aug 19 05:54:40 ubuntu_server renderd[1676]: DEBUG: START TILE default 12 1176-1183 2496-2503, new metatile
    Aug 19 05:54:40 ubuntu_server renderd[1676]: Rendering projected coordinates 12 1176 2496 -> -8531595.349083|-4461476.466952 -8453323.832119|-4383204.949988 to a 8 x 8 tile
    Aug 19 05:54:40 ubuntu_server renderd[1676]: DEBUG: DONE TILE default 12 1176-1183 2472-2479 in 0.409 seconds
    Aug 19 05:54:40 ubuntu_server renderd[1676]: DEBUG: Sending render cmd(3 default 12/1176/2472) with protocol version 2 to fd 7
    Aug 19 05:54:40 ubuntu_server renderd[1676]: DEBUG: Got incoming request with protocol version 2
    Aug 19 05:54:40 ubuntu_server renderd[1676]: DEBUG: Got command RenderBulk fd(7) xml(default), z(12), x(1176), y(2504), mime(image/png), options()
    Aug 19 05:54:40 ubuntu_server renderd[1676]: DEBUG: START TILE default 12 1176-1183 2504-2511, new metatile
    Aug 19 05:54:40 ubuntu_server renderd[1676]: Rendering projected coordinates 12 1176 2504 -> -8531595.349083|-4539747.983916 -8453323.832119|-4461476.466952 to a 8 x 8 tile
    Aug 19 05:54:40 ubuntu_server renderd[1676]: DEBUG: DONE TILE default 12 1176-1183 2480-2487 in 0.393 seconds
    Aug 19 05:54:40 ubuntu_server renderd[1676]: DEBUG: Sending render cmd(3 default 12/1176/2480) with protocol version 2 to fd 9
    Aug 19 05:54:40 ubuntu_server renderd[1676]: DEBUG: Got incoming request with protocol version 2
    Aug 19 05:54:40 ubuntu_server renderd[1676]: DEBUG: Got command RenderBulk fd(9) xml(default), z(12), x(1176), y(2512), mime(image/png), options()
    Aug 19 05:54:40 ubuntu_server renderd[1676]: DEBUG: START TILE default 12 1176-1183 2512-2519, new metatile
    Aug 19 05:54:40 ubuntu_server renderd[1676]: Rendering projected coordinates 12 1176 2512 -> -8531595.349083|-4618019.500880 -8453323.832119|-4539747.983916 to a 8 x 8 tile
    Aug 19 05:54:41 ubuntu_server renderd[1676]: DEBUG: Failed to read cmd on fd 8
    Aug 19 05:54:41 ubuntu_server renderd[1676]: DEBUG: Connection 1, fd 8 closed, now 3 left
    Aug 19 05:54:41 ubuntu_server renderd[1676]: DEBUG: Failed to read cmd on fd 10
    Aug 19 05:54:41 ubuntu_server renderd[1676]: DEBUG: Connection 2, fd 10 closed, now 2 left
    Aug 19 05:54:41 ubuntu_server renderd[1676]: DEBUG: Failed to read cmd on fd 7
    Aug 19 05:54:41 ubuntu_server renderd[1676]: DEBUG: Connection 0, fd 7 closed, now 1 left
    Aug 19 05:54:41 ubuntu_server renderd[1676]: DEBUG: Failed to read cmd on fd 9
    Aug 19 05:54:41 ubuntu_server renderd[1676]: DEBUG: Connection 0, fd 9 closed, now 0 left
    Aug 19 05:54:41 ubuntu_server renderd[1676]: DEBUG: DONE TILE default 12 1176-1183 2496-2503 in 0.441 seconds
    Aug 19 05:54:41 ubuntu_server renderd[1676]: DEBUG: DONE TILE default 12 1176-1183 2488-2495 in 0.453 seconds
    Aug 19 05:54:41 ubuntu_server renderd[1676]: DEBUG: DONE TILE default 12 1176-1183 2504-2511 in 0.422 seconds
    Aug 19 05:54:41 ubuntu_server renderd[1676]: DEBUG: DONE TILE default 12 1176-1183 2512-2519 in 0.403 seconds
    
  • Hi, this tut worked great, can you tell me the command to update the map using the change files as suggested?

    Thanks

  • Hey there,
    i have a problem with my own tile server. I tested it with https://download.geofabrik.de/europe/germany/bayern-latest.osm.pbf and everything works fine. At the begin it took about 200 seconds to render the first tile but then it worked quite good. After this i load up another set https://download.geofabrik.de/europe/germany/saarland-latest.osm.pbf with –create and it worked still. Then i wanted to try the same with a bigger set (germany, switzerland, austria) http://download.geofabrik.de/europe/dach-latest.osm.pbf. It took about 12 hours to process the osm2pgsql. Now i started the tile server again and it seems not to work. Other possibility is that it is very slow.
    Here ist the grep renderd:

    Mar 24 10:36:47 h2929534 renderd[8445]: DEBUG: Loading font: /usr/share/fonts/truetype/unifont/unifont_sample.ttf
    Mar 24 10:36:47 h2929534 renderd[8445]: DEBUG: Loading font: /usr/share/fonts/truetype/unifont/unifont_csur.ttf
    Mar 24 10:36:47 h2929534 renderd[8445]: DEBUG: Loading font: /usr/share/fonts/truetype/unifont/unifont.ttf
    Mar 24 10:36:47 h2929534 renderd[8445]: Loading parameterization function for
    Mar 24 10:36:47 h2929534 renderd[8445]: Starting stats thread
    Mar 24 10:36:47 h2929534 renderd[8445]: Loading parameterization function for
    Mar 24 10:36:47 h2929534 renderd[8445]: message repeated 5 times: [ Loading parameterization function for]
    Mar 24 10:36:54 h2929534 renderd[8445]: DEBUG: Got incoming connection, fd 8, number 1
    Mar 24 10:36:54 h2929534 renderd[8445]: DEBUG: Got incoming request with protocol version 2
    Mar 24 10:36:54 h2929534 renderd[8445]: DEBUG: Got command RenderPrio fd(8) xml(ajt), z(19), x(247506), y(167636), mime(image/png), options()
    Mar 24 10:36:56 h2929534 renderd[8445]: Using web mercator projection settings
    Mar 24 10:36:56 h2929534 renderd[8445]: DEBUG: START TILE ajt 19 247504-247511 167632-167639, new metatile
    Mar 24 10:36:56 h2929534 renderd[8445]: Rendering projected coordinates 19 247504 167632 -> -1119038.094096|7223604.921066 -1118426.597869|7224216.417292 to a 8 x 8 tile
    Mar 24 10:36:57 h2929534 renderd[8445]: Using web mercator projection settings
    Mar 24 10:36:57 h2929534 renderd[8445]: message repeated 5 times: [ Using web mercator projection settings]
    Mar 24 10:37:24 h2929534 renderd[8445]: DEBUG: Connection 0, fd 8 closed, now 0 left
    Mar 24 10:37:45 h2929534 renderd[8445]: DEBUG: Got incoming connection, fd 7, number 1
    Mar 24 10:37:45 h2929534 renderd[8445]: DEBUG: Got incoming request with protocol version 2
    Mar 24 10:37:45 h2929534 renderd[8445]: DEBUG: Got command RenderPrio fd(7) xml(ajt), z(19), x(247506), y(167636), mime(image/png), options()
    Mar 24 10:38:15 h2929534 renderd[8445]: DEBUG: Connection 0, fd 7 closed, now 0 left
    Mar 24 10:39:21 h2929534 renderd[8445]: DEBUG: Got incoming connection, fd 7, number 1
    Mar 24 10:39:21 h2929534 renderd[8445]: DEBUG: Got incoming request with protocol version 2
    Mar 24 10:39:21 h2929534 renderd[8445]: DEBUG: Got command RenderPrio fd(7) xml(ajt), z(19), x(247506), y(167636), mime(image/png), options()
    Mar 24 10:39:51 h2929534 renderd[8445]: DEBUG: Connection 0, fd 7 closed, now 0 left
    Mar 24 10:43:44 h2929534 renderd[8445]: DEBUG: Got incoming connection, fd 7, number 1
    Mar 24 10:43:44 h2929534 renderd[8445]: DEBUG: Got incoming request with protocol version 2
    Mar 24 10:43:44 h2929534 renderd[8445]: DEBUG: Got command RenderPrio fd(7) xml(ajt), z(19), x(247506), y(167636), mime(image/png), options()
    Mar 24 10:44:14 h2929534 renderd[8445]: DEBUG: Connection 0, fd 7 closed, now 0 left
    Mar 24 10:59:42 h2929534 renderd[8445]: DEBUG: Got incoming connection, fd 7, number 1
    Mar 24 10:59:42 h2929534 renderd[8445]: DEBUG: Got incoming request with protocol version 2
    Mar 24 10:59:42 h2929534 renderd[8445]: DEBUG: Got command RenderPrio fd(7) xml(ajt), z(19), x(247506), y(167636), mime(image/png), options()
    Mar 24 11:00:12 h2929534 renderd[8445]: DEBUG: Connection 0, fd 7 closed, now 0 left
    Mar 24 11:00:56 h2929534 renderd[8445]: DEBUG: Got incoming connection, fd 7, number 1
    Mar 24 11:00:57 h2929534 renderd[8445]: DEBUG: Got incoming request with protocol version 2
    Mar 24 11:00:57 h2929534 renderd[8445]: DEBUG: Got command RenderPrio fd(7) xml(ajt), z(19), x(247506), y(167636), mime(image/png), options()
    Mar 24 11:01:26 h2929534 renderd[8445]: DEBUG: Connection 0, fd 7 closed, now 0 left
    Mar 24 11:11:53 h2929534 renderd[8445]: DEBUG: Got incoming connection, fd 7, number 1
    Mar 24 11:11:53 h2929534 renderd[8445]: DEBUG: Got incoming request with protocol version 2
    Mar 24 11:11:53 h2929534 renderd[8445]: DEBUG: Got command RenderPrio fd(7) xml(ajt), z(19), x(247506), y(167636), mime(image/png), options()
    Mar 24 11:12:23 h2929534 renderd[8445]: DEBUG: Connection 0, fd 7 closed, now 0 left
    Mar 24 11:13:48 h2929534 renderd[8445]: DEBUG: Got incoming connection, fd 7, number 1
    Mar 24 11:13:48 h2929534 renderd[8445]: DEBUG: Got incoming request with protocol version 2
    Mar 24 11:13:48 h2929534 renderd[8445]: DEBUG: Got command RenderPrio fd(7) xml(ajt), z(19), x(247506), y(167636), mime(image/png), options()
    Mar 24 11:14:18 h2929534 renderd[8445]: DEBUG: Connection 0, fd 7 closed, now 0 left
    Mar 24 11:16:09 h2929534 renderd[8445]: DEBUG: Got incoming connection, fd 7, number 1
    Mar 24 11:16:09 h2929534 renderd[8445]: DEBUG: Got incoming request with protocol version 2
    Mar 24 11:16:09 h2929534 renderd[8445]: DEBUG: Got command RenderPrio fd(7) xml(ajt), z(19), x(247506), y(167636), mime(image/png), options()
    Mar 24 11:16:39 h2929534 renderd[8445]: DEBUG: Connection 0, fd 7 closed, now 0 left
    Mar 24 11:21:53 h2929534 renderd[8445]: DEBUG: Got incoming connection, fd 7, number 1
    Mar 24 11:21:53 h2929534 renderd[8445]: DEBUG: Got incoming request with protocol version 2
    Mar 24 11:21:53 h2929534 renderd[8445]: DEBUG: Got command RenderPrio fd(7) xml(ajt), z(19), x(247506), y(167636), mime(image/png), options()
    Mar 24 11:22:23 h2929534 renderd[8445]: DEBUG: Connection 0, fd 7 closed, now 0 left

    I tried to render the /hot/19/247506/167636.png

    Thanks in advance

  • enoldis maceo
    3 years ago

    when I run carto project.mml> style.xml I get the following error Warning: style / admin.mss: 18: 6 Styles do not match layer selector

  • Hi. I followed your article, but I get this:

     osm2pgsql --slim -d gis --hstore --multi-geometry --number-processes 2 --tag-transform-script /home/osm/openstreetmap-carto/openstreetmap-carto.lua --style /home/osm/openstreetmap-carto/openstreetmap-carto.style -C 6451 /home/osm/italy-latest.osm.pbf
    osm2pgsql version 0.94.0 (64 bit id space)
    
    Using lua based tag processing pipeline with script /home/osm/openstreetmap-carto/openstreetmap-carto.lua
    Using projection SRS 3857 (Spherical Mercator)
    Setting up table: planet_osm_point
    Osm2pgsql failed due to ERROR: CREATE UNLOGGED TABLE planet_osm_point (osm_id int8,"access" text,"addr:housename" text,"addr:housenumber" text,"admin_level" text,"aerialway" text,"aeroway" text,"amenity" text,"barrier" text,"boundary" text,"building" text,"highway" text,"historic" text,"junction" text,"landuse" text,"layer" int4,"leisure" text,"lock" text,"man_made" text,"military" text,"name" text,"natural" text,"oneway" text,"place" text,"power" text,"railway" text,"ref" text,"religion" text,"shop" text,"tourism" text,"water" text,"waterway" text,"tags" hstore,way geometry(POINT,3857) ) WITH ( autovacuum_enabled = FALSE ) failed: ERROR:  type "hstore" does not exist
    LINE 1: ...tourism" text,"water" text,"waterway" text,"tags" hstore,way...
    
    • Xiao Guoan (Admin)
      3 years ago

      You need to enable the postgis and hstore extension for the gis database as described in step 2.

  • rosario
    3 years ago

    Hi Xiao Guoan.
    Your article is very accurate. Everything worked fine.
    I ask you: if I have my own tls certificate, what operations should I do to use it?

  • Hello Xiao Guoan, before all — thanks for good guide!
    Is it possible to hire you?

  • rosario
    3 years ago

    I haven’t had a problem up to this point in the guide: scripts/get-external-data.py (Step 7)
    Can someone help me?
    Thanks

    INFO:root:Checking table simplified_water_polygons
    Traceback (most recent call last):
      File "scripts/get-external-data.py", line 109, in index
        .format(name=self._name, temp_schema=self._temp_schema))
    psycopg2.errors.ActiveSqlTransaction: VACUUM cannot run inside a transaction block
    
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "scripts/get-external-data.py", line 294, in 
        main()
      File "scripts/get-external-data.py", line 284, in main
        this_table.index()
      File "scripts/get-external-data.py", line 111, in index
        self._conn.autocommit = old_autocommit
    psycopg2.ProgrammingError: set_session cannot be used inside a transaction
    
    • I also need help on this, getting the same error message

    • tooneamelt
      3 years ago

      Not sure if this is the correct way to go about this but this is an error with psycopg2. I did:
      pip3 uninstall psycopg2
      Then installed an older version of psycopg2. I chose 2.8.2
      pip3 install psycopg2==2.8.2

      I’m not sure which version actually broke this but 2.8.2 works for me

  • Hi! Thanks for great article.
    I have problem with renderd – when I send sudo journalctl -eu renderd it returnes “fail”:
    renderd[76032]: * Starting Mapnik rendering daemon renderd
    renderd[76032]: /usr/bin/renderd: symbol lookup error: /usr/bin/renderd: undefined symbol: _ZN6mapnik16datasource_cache20register_datasourcesERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb
    renderd[76032]: …fail!

    Hope, that you can help.
    Thanks.

  • Rosario
    3 years ago

    I have followed everything up to step 11.
    1) But if with the browser I try:

    http://localhost/osm/0/0/0.png

    i don’t get png file display. I also looked for the file in the osm folder and it is not there.
    2)I created the index.html file, but I can’t navigate the map with it. I can only navigate if:
    http://localhost/osm/slippymap.html
    Any suggestions are appreciated.
    Thanks

    • Rosario
      3 years ago

      I have solved. I was wrong in editing the file:/etc/apache2/sites-available/tileserver_site.conf.
      Thanks

      • lolotux
        2 years ago

        Hi

        What was wrong!
        Have details could be important! No ?

        Tks

  • khadija shaban
    3 years ago

    vm.nr_hugepages = 795
    where exactly do you add this..
    tried it but no changes

  • PRITAM RAJPUT
    3 years ago

    Hello ,
    I also try in my local system for downlod openstreetmap server i completed 5 step successfully but in 5th step i got some warning when i fire command to load map stylesheet & map data into the GIS Database of India map purpose then i get some WARNING : there is no transaction in progress. but i think this is not big issue. for india map i use this command please check once correct or not ??

    osm2pgsql –slim -d gis –hstore –multi-geometry –number-processes 4 –tag-transform-script /home/osm/openstreetmap-carto/openstreetmap-carto.lua –style /home/osm/openstreetmap-carto/openstreetmap-carto.style -C 200 /home/osm/india-latest.osm.pbf

    & when i try to check osm2pgsql -v command for checking osm2pgsql version then
    osm2pgsql -v
    osm2pgsql version 0.94.0 (64 bit id space)

    Osm2pgsql failed due to ERROR: Usage error. For further information see:
    osm2pgsql -h|–help

  • Sheik manayil
    2 years ago

    Wow ! great tutorials
    is it possible to install OSM transport layer feature also in Ubuntu ? in that case how do we access that
    Thanks

  • Moses Karani
    2 years ago

    This is a great tutorial but I’m having issues with getting my Aussie map to center. I’m instead getting middle of the ocean near Africa (0,0). Using ubuntu 18.4

    view: new ol.view ({
    center: [-25, 133],
    zoom:3.5
    })

  • rosario
    2 years ago

    Hi, at the point 7), when I launch the get-external-data.py script I get this error

    Traceback (most recent call last):
      File "scripts/get-external-data.py", line 25, in 
        from requests_file import FileAdapter

    . Some idea?

    • Rosario
      2 years ago

      Hi. I solved. Need:

      sudo apt-get install python3-requests-file
  • For anyone wondering how long this takes (7+ days) and space it needs (361G) wanting to monitor progress here’s my output (from 16 core E5-2698 VM with 32G ram on SSDs with input over NFS) :-

    [postgres@vmosm:~]$ df;now;osm2pgsql --slim -d gis --drop --flat-nodes /home/osm/nodes.cache --hstore --multi-geometry --number-processes 16 --tag-transform-script /home/osm/openstreetmap-carto/openstreetmap-carto.lua --style /home/osm/openstreetmap-carto/openstreetmap-carto.style -C 10000 /nfs/planet-220926.osm.pbf ;nowl;df
    Filesystem     Type              Size  Used Avail Use% Mounted on
    tmpfs          tmpfs             3.0G  1.7M  3.0G   1% /run
    /dev/sda4      ext4              967G   19G  900G   2% /
    tmpfs          tmpfs              15G   28K   15G   1% /dev/shm
    tmpfs          tmpfs             5.0M     0  5.0M   0% /run/lock
    /dev/sda2      ext4              974M  127M  780M  14% /boot
    tmpfs          tmpfs             3.0G  4.0K  3.0G   1% /run/user/1000
    vmhgfs-fuse    fuse.vmhgfs-fuse  5.5T  1.2T  4.4T  21% /nfs
    2022_10_10_03h43m42
    2022-10-10 03:43:42  osm2pgsql version 1.7.0
    2022-10-10 03:43:42  Database version: 14.5 (Ubuntu 14.5-1.pgdg22.04+1)
    2022-10-10 03:43:42  PostGIS version: 3.3
    2022-10-10 03:43:42  Setting up table 'planet_osm_point'
    2022-10-10 03:43:42  Setting up table 'planet_osm_line'
    2022-10-10 03:43:42  Setting up table 'planet_osm_polygon'
    2022-10-10 03:43:42  Setting up table 'planet_osm_roads'
    2022-10-17 01:15:09  Reading input files done in 595887s (165h 31m 27s).
    2022-10-17 01:15:09    Processed 7936251920 nodes in 6069s (1h 41m 9s) - 1308k/s
    2022-10-17 01:15:09    Processed 889663922 ways in 281332s (78h 8m 52s) - 3k/s
    2022-10-17 01:15:09    Processed 10264462 relations in 308486s (85h 41m 26s) - 33/s
    2022-10-17 01:15:38  Dropping table 'planet_osm_nodes'
    2022-10-17 01:15:38  Table 'planet_osm_nodes' dropped in 0s
    2022-10-17 01:15:38  Dropping table 'planet_osm_ways'
    2022-10-17 01:15:52  Table 'planet_osm_ways' dropped in 14s
    2022-10-17 01:15:52  Dropping table 'planet_osm_rels'
    2022-10-17 01:15:54  Table 'planet_osm_rels' dropped in 2s
    2022-10-17 01:15:54  Done postprocessing on table 'planet_osm_nodes' in 0s
    2022-10-17 01:15:54  Done postprocessing on table 'planet_osm_ways' in 0s
    2022-10-17 01:15:54  Done postprocessing on table 'planet_osm_rels' in 0s
    2022-10-17 01:15:55  Clustering table 'planet_osm_point' by geometry...
    2022-10-17 01:15:57  Clustering table 'planet_osm_line' by geometry...
    2022-10-17 01:15:57  Clustering table 'planet_osm_roads' by geometry...
    2022-10-17 01:15:57  Clustering table 'planet_osm_polygon' by geometry...
    2022-10-17 02:32:23  Creating geometry index on table 'planet_osm_roads'...
    2022-10-17 02:32:45  Creating geometry index on table 'planet_osm_point'...
    2022-10-17 02:57:41  Analyzing table 'planet_osm_roads'...
    2022-10-17 04:23:09  Analyzing table 'planet_osm_point'...
    2022-10-17 04:24:01  All postprocessing on table 'planet_osm_point' done in 11287s (3h 8m 7s).
    
    2022-10-17 06:40:10  Creating geometry index on table 'planet_osm_line'...
    2022-10-17 07:58:46  Creating geometry index on table 'planet_osm_polygon'...
    2022-10-17 09:00:32  Analyzing table 'planet_osm_line'...
    2022-10-17 09:03:02  All postprocessing on table 'planet_osm_line' done in 28028s (7h 47m 8s).
    2022-10-17 13:24:26  Analyzing table 'planet_osm_polygon'...
    2022-10-17 13:26:40  All postprocessing on table 'planet_osm_polygon' done in 43845s (12h 10m 45s).
    2022-10-17 13:26:40  All postprocessing on table 'planet_osm_roads' done in 6195s (1h 43m 15s).
    2022-10-17 13:26:41  osm2pgsql took 639779s (177h 42m 59s) overall.
    639780.297515869 elapsed
    2022_10_17_13h26m42
    Filesystem     Type              Size  Used Avail Use% Mounted on
    tmpfs          tmpfs             3.0G  1.7M  3.0G   1% /run
    /dev/sda4      ext4              967G  382G  536G  42% /
    tmpfs          tmpfs              15G   28K   15G   1% /dev/shm
    tmpfs          tmpfs             5.0M     0  5.0M   0% /run/lock
    /dev/sda2      ext4              974M  247M  661M  28% /boot
    tmpfs          tmpfs             3.0G  4.0K  3.0G   1% /run/user/1000
    vmhgfs-fuse    fuse.vmhgfs-fuse  5.5T  2.0T  3.5T  36% /nfs
    
    [postgres@vmosm:~]$ perl -e 'print 639780/60/60/24 . " days"'
    7.40486111111111 days
    
    
  • Thanks a lot for this tutorial! It inspired me (again) to set up my own tile server. Do you think the Contablo “CLOUD VPS L” package with 800GB SSL would be enough for Europe? Or would be the “CLOUD VPS M” with additional SSD (max. 600GB SSD possible in this package) also be fine if I would limit zoom level to 14/15?

  • Thanks for the great tutorial! But I got errors installing libapache2-mod-tile

    E: Unable to locate package libapache2-mod-tile
    E: Unable to locate package renderd
    

    What should I do?

    • Xiao Guoan (Admin)
      2 years ago

      Upgrade to Ubuntu 20.04.

      do-release-upgrade
      • I upgraded to Ubuntu22.04,but package ttf-dejavu does not work on it, is there any solution?

  • charismeki
    2 years ago

    I get error with script

    postgress@xyz:/home/osm/openstreetmap-carto$ scripts/get-external-data.py
    INFO:root:Starting load of external data into database
    Traceback (most recent call last):
    File “scripts/get-external-data.py”, line 405, in
    main()
    File “scripts/get-external-data.py”, line 291, in main
    os.makedirs(data_dir, exist_ok=True)
    File “/usr/lib/python3.6/os.py”, line 220, in makedirs
    mkdir(name, mode)
    PermissionError: [Errno 13] Permission denied: ‘data’

    Any ideas?

  • If I upgrade Ubuntu to 20.xx will this all continue working? (Ubuntu 18.XX is now out of support)

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 (https://community.linuxbabe.com) for questions unrelated to this article.
  • I don't have time to answer every question. Making a donation would incentivize me to spend more time answering questions.

The maximum upload file size: 2 MB. You can upload: image. Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded. Drop file here