OpenStreetMap Carto Tutorials - Unofficial documentation     Site map    

Installing an OpenStreetMap Tile Server on Ubuntu

Installing an OpenStreetMap Tile Server on Ubuntu


The following step-by-step procedure can be used to install and configure all the necessary software to operate your own OpenStreetMap tile server on Ubuntu 16.4 or 14.4.1

The OSM tile server stack is a collection of programs and libraries chained together to create a tile server. As so often with OpenStreetMap, there are many ways to achieve this goal and nearly all of the components have alternatives that have various specific advantages and disadvantages. This tutorial describes the most standard version that is also used on the main tile server.

It consists of the following main components:

  • Mapnik
  • Apache
  • Mod_tile
  • renderd
  • osm2pgsql
  • PostgreSQL/PostGIS database, to be installed locally (suggested) or remotely (might be slow, depending on the network).
  • carto
  • openstreetmap-carto

Mod_tile is an apache module that serves cached tiles and decides which tiles need re-rendering either because they are not yet cached or because they are outdated. Renderd provides a priority queueing system for rendering requests to manage and smooth out the load from rendering requests. Mapnik is the software library that does the actual rendering and is used by renderd.

A description of the rendering process of OpenStreetMap can be found at OSM architecture, including general components and tools, populating the PostGIS instance, converting the CartoCSS style sources to Mapnik XML and the Mapnik rendering process.

The process to generate tiles is the following:

    client browser web    
Disk Cache (tiles)png   Apache Web Server prg Web page html
renderd prg mod_tile prg tiles png
Mapnik XML xml Mapnik prg    
PostgreSQL PostGIS db   shapefiles data directory shape    

Even if different operating system versions have been tested, Ubuntu 16.4 is strongly suggested.

We consider using Ubuntu 16.04.1 LTS Xenial Xerus, Ubuntu 15.4 Vivid Vervet or Ubuntu 14.04.3 LTS Trusty Tahr (other versions should work). All should be 64-bit computing architecture.

General setup for Ubuntu

Update Ubuntu

Make sure your Ubuntu system is fully up-to-date:

lsb_release -a # to get the Ubuntu version
sudo apt-get update
sudo apt-get -y upgrade

Install essential tools

sudo apt-get -y install curl unzip gdal-bin tar wget bzip2

For the subsequent installation steps, we suppose that cd defaults to your home directory.

Configure a swap

Importing and managing map data takes a lot of RAM and a swap is generally needed.

To check whether a swap partition is already configured on your system, use one of the following two commands:

  • Reports the swap usage summary (no output means missing swap):

    swapon -s
  • Display amount of free and used memory in the system (check the line specifying Swap):

    free -h

If you do not have an active swap partition, especially if your physical memory is small, you should add a swap file. First we use fallocate command to create a file. For example, create a file named swapfile with 2G capacity in root file system:

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

Enable the swap file

sudo swapon /swapfile

Creating a UNIX user

We suppose that you have already created a login user during the installation of Ubuntu, to be used to run the tile server. Let’s suppose that your selected user name is tileserver. Within this document, all times tileserver is mentioned, change it with your actual user name.

If you need to create a new user:

sudo useradd -m tileserver
sudo passwd tileserver

Set a password when prompted.

Install Git

Git should be already installed on Ubuntu 16.04.

git --version # to verify whether git is already installed
sudo apt-get install -y git

Install Mapnik library

We need to install the Mapnik library. Mapnik is used to render the OpenStreetMap data into the tiles managed by the Apache web server through renderd and mod_tile.

We report some alternative procedures to install Mapnik (in the consideration to run an updated version of Ubuntu).

Install Mapnik library from package

Tested with Ubuntu 16.04 and Ubuntu 14.04; suggested as the preferred option to install Mapnik.

sudo apt-get install -y git autoconf libtool libxml2-dev libbz2-dev \
  libgeos-dev libgeos++-dev libproj-dev gdal-bin libgdal1-dev g++ \
  libmapnik-dev mapnik-utils python-mapnik

This will most probably install Mapnik 2.2 on Ubuntu 14.04.3 LTS and Mapnik 3.0.9 on Ubuntu 16.04.1 LTS.

Go to check Mapnik installation.

Alternatively, install Mapnik from sources

Refer to Mapnik Ubuntu Installation to for specific documentation.

Refer to Mapnik Releases for the latest version and changelog.

This procedure to install Mapnik from sources has been tested with Ubuntu 16.4 only. Refer to the above links for other O.S. versions.

Remove any other old Mapnik packages:

sudo apt-get purge -y libmapnik* mapnik-* python-mapnik
sudo add-apt-repository --remove -y ppa:mapnik/nightly-trunk

Install prerequisites; first create a directory to load the sources:

test -d ~/src || mkdir  ~/src ; cd ~/src

sudo apt-get install -y libxml2-dev libfreetype6-dev \
  libjpeg-dev libpng-dev libproj-dev libtiff-dev \
  libcairo2 libcairo2-dev python-cairo python-cairo-dev \
  libgdal1-dev git

sudo apt-get install -y build-essential python-dev libbz2-dev libicu-dev

We need to install Boost either from package or from source.

Install Boost from package

sudo apt-get install -y libboost-all-dev

Alternatively, install the latest version of Boost from source

sudo apt-get purge -y libboost-all-dev # remove installation from package
cd ~/src
wget -O boost.tar.bz2
tar xjf boost.tar.bz2
rm boost.tar.bz2
cd boost_*
./b2 stage toolset=gcc --with-thread --with-filesystem --with-python --with-regex -sHAVE_ICU=1 -sICU_PATH=/usr/ --with-program_options --with-system link=shared
sudo ./b2 install toolset=gcc --with-thread --with-filesystem --with-python --with-regex -sHAVE_ICU=1 -sICU_PATH=/usr/ --with-program_options --with-system link=shared -d0
sudo ldconfig && cd ~/

Install HarfBuzz from source

HarfBuzz is an OpenType text shaping engine.

Check the lastest version here

cd ~/src
tar xf harfbuzz-1.3.2.tar.bz2
rm harfbuzz-1.3.2.tar.bz2
cd harfbuzz-1.3.2
./configure && make && sudo make install
sudo ldconfig
cd ~/

Build the Mapnik library from source

cd ~/src
git clone --depth 10
cd mapnik
git submodule update --init
./configure && make

Test Mapnik (without needing to install):

make test # some test might not pass

Install Mapnik:

sudo make install
cd ~/

Python bindings are not included by default. You’ll need to add those separately.

cd ~/src
git clone
cd python-mapnik
sudo apt-get install -y python-setuptools python3-setuptools libboost-python-dev
sudo python develop
sudo python install

Verify that Mapnik has been correctly installed

Report Mapnik version number:

mapnik-config -v

Check then with Python:

python -c "import mapnik;print mapnik.__file__"

It should return the path to the python bindings. If python replies without errors, then Mapnik library was found by Python.

Configure the firewall

If you are preparing a remote virtual machine, configure the firewall to allow remote access to the local port 80 and local port 443.

If you run a cloud based VM, also the VM itself shall be set to open this port.

Install Apache HTTP Server

The Apache free open source HTTP Server is among the most popular web servers in the world. It’s well-documented, and has been in wide use for much of the history of the web, which makes it a great default choice for hosting a website.

To install apache:

sudo apt-get install -y apache2 apache2-dev

To check if Apache is installed, direct your browser to the IP address of your server (eg. http://localhost). The page should display the default Apache home page. Also this command allows checking correct working:

curl localhost| grep 'It works!'

How to Find the IP address of your server

You can run the following command to reveal the public IP address of your server:

wget -qO -

You can test Apache by accessing it through a browser at http://your-server-ip.

Install Mod_tile

Mod_tile is an Apache module to efficiently render and serve map tiles for map using Mapnik. We can compile it from Github repository.

test -d ~/src || mkdir  ~/src ; cd ~/src
git clone
cd mod_tile
./ && ./configure && make && sudo make install && sudo make install-mod_tile && sudo ldconfig
cd ~/

The rendering process implemented by mod_tile and renderd is well explained here.

Python installation

Check that Python is installed:

python -V
python3 -V

Otherwise Python needs to be installed.

Install Yaml and Package Manager for Python

This is necessary in order to run OpenStreetMap-Carto scripts/indexes.

sudo apt-get install -y python-yaml

pip -V # to verify whether pip is already installed
sudo apt-get install -y python-pip

Install Mapnik Utilities

The Mapnik Utilities package includes shapeindex.

sudo apt-get install -y mapnik-utils

Install openstreetmap-carto

cd ~/src
git clone
cd openstreetmap-carto

Read installation notes for further information.

Install the fonts needed by openstreetmap-carto

Currently Noto Sans font is used and DejaVu Sans is used as an optional fallback:

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

DejaVu is packaged as fonts-dejavu-core.

Old fonts:

sudo apt-get install -y fonts-dejavu-core fonts-droid-fallback ttf-unifont \
  fonts-sipa-arundina fonts-sil-padauk fonts-khmeros \
  fonts-beng-extra fonts-gargi fonts-taml-tscu fonts-tibetan-machine

If fonts-droid-fallback fails installing, replace it with with fonts-droid.

Read font notes for further information.

Create the data folder

cd ~/src
cd openstreetmap-carto

Read scripted download for further information.

Install carto and build the Mapnik xml stylesheet

Notice that the carto feature able to natively process project.mml in YAML format (currently adopted for openstreetmap-carto) is recent.

Install node-carto:

sudo apt-get install -y node-carto

Ensure that the latest carto version is installed (at least version >= 0.16.0, using YAML):

carto -v
carto 0.16.3 (Carto map stylesheet compiler)

Test carto and produce style.xml from the openstreetmap-carto style:

cd ~/src
cd openstreetmap-carto
carto -a "3.0.0" project.mml > style.xml

The option -a "3.0.0" is needed when using Mapnik 3 functions 2.

Set the environment variables

export PGHOST=localhost
export PGPORT=5432
export PGUSER=postgres
export PGPASSWORD=postgres_007%

Install PostgreSQL and PostGIS

PostgreSQL is a relational database, and PostGIS is its spatial extender, which allow you to store geographic objects like map data in it. PostgreSQL + PostGIS are used for a wide variety of uses such as rendering maps, geocoding, and analysis. It serves a similar function to ESRI’s SDE or Oracle’s Spatial extension.

Currently the tested versions are PostgreSQL 9.5 and PostGIS 2.2:

Also older PostgreSQL version should be suitable.

On Ubuntu there are pre-packaged versions of both postgis and postgresql, so these can simply be installed via the Ubuntu package manager.

sudo apt-get update
sudo apt-get install -y postgresql postgis pgadmin3 postgresql-contrib

Note: used PostgeSQL port is 5432 (default).

A user named postgres will be created during the installation process.

Set the password for the postgres user

sudo -u postgres psql postgres
\password postgres

Alternative procedure (useful if you get authentication issues with the previous one):

sudo su -
sudo -i -u postgres
psql postgres
\password postgres

Enter the following password twice: postgres_007%

This is just an example of password, you can use the one you prefer.

After entering the password, exit from psql with:


With the second procedure, also isssue:

exit # from 'sudo -i -u postgres'
exit # from 'sudo su -'

Create the PostGIS instance

Now you need to create a postgis database. The defaults of various programs including openstreetmap-carto (ref. project.mml) assume the database is called gis. You need to set up PostGIS on the PostgreSQL database.

export PGPASSWORD=postgres_007%
HOSTNAME=localhost # set it to the actual ip address or host name
psql -U postgres -h $HOSTNAME -c "create database gis" # alternative command: createdb -E UTF8 -O postgres gis
psql -U postgres -h $HOSTNAME -c "\connect gis"
psql -U postgres -h $HOSTNAME -d gis -c "CREATE EXTENSION postgis"
psql -U postgres -h $HOSTNAME -d gis -c "CREATE EXTENSION hstore"

The character encoding scheme to be used in the database is UTF8.

If you get the following error

ERROR:  could not open extension control file "/usr/share/postgresql/9.3/extension/postgis.control": No such file or directory

then you might be installing PostgreSQL 9.3, for which you should also need:

sudo apt-get install postgis postgresql-9.3-postgis-scripts

Install it and repeat the create extension commands.

Add a user and grant access to gis DB

In order for the application to access the gis database, a DB user with the same name of your UNIX user is needed. Let’s suppose your UNIX ue is tileserver.

sudo su -
sudo -i -u postgres
createuser tileserver
grant all privileges on database gis to tileserver;

Enabling remote access to PostgreSQL

To remotely access PostgreSQL, you need to edit pg_hba.conf:

sudo vi /etc/postgresql/9.5/main/pg_hba.conf

and add the following line:

host    all             all             <your IP set>/<your netmask>             md5

host all all md5 is an access control rule that let anybody login in from any address if providing a valid password (md5 keyword).

Then edit postgresql.conf:

sudo vi /etc/postgresql/9.5/main/postgresql.conf

and change the following line:

set `listen_addresses = '*'`

Finally, the DB shall be restarted:

sudo /etc/init.d/postgresql restart

Tuning the database

The PostgreSQL wiki has a page on database tuning. The important settings are shared_buffers, checkpoint_segments, and the write-ahead-log settings. There are also some settings you want to change specifically for the import.

The default PostgreSQL settings aren’t great for very large databases like OSM databases. Proper tuning can just about double the performance you’re getting. The most important PostgreSQL settings to change are maintenance_work_mem and work_mem, both which should be increased for faster data loading and faster queries while rendering respectively. Conservative settings for a 2GB VM are work_mem=16MB and maintenance_work_mem=128MB. On a machine with enough memory you could set them as high as work_mem=128MB and maintenance_work_mem=1GB. An overview to tuning PostgreSQL can be found on the PostgreSQL Wiki, but adjusting maintenance_work_mem and work_mem are probably enough on a development or testing machine.3

To edit the PostgreSQL configuration file with vi editor:

sudo vi /etc/postgresql/9.5/main/postgresql.conf

and if you are running PostgreSQL 9.3:

sudo vi /etc/postgresql/9.3/main/postgresql.conf

Suggested settings:

shared_buffers = 128MB
checkpoint_segments = 20
maintenance_work_mem = 256MB
autovacuum = off
fsync = off

The latter two ones allow a faster import.

The first turns off auto-vacuum during the import and allows you to run a vacuum at the end. The second will introduce data corruption in case of a power outage and is dangerous. If you have a power outage while importing the data you will have to drop the data from the database and re-import, but it’s faster. Just remember to change these settings back after importing. fsync has no effect on query times once the data is loaded.

Suggested settings for a system with 16GB of RAM:

shared_buffers = 2GB
work_mem = 128MB
maintenance_work_mem = 1GB
wal_level = minimal
synchronous_commit = off
checkpoint_segments = 64
checkpoint_timeout = 15min
checkpoint_completion_target = 0.9
default_statistics_target = 1000
autovacuum = off
fsync = off

To stop and start the database:

sudo /etc/init.d/postgresql stop

sudo /etc/init.d/postgresql start

You may get an error and need to increase the shared memory size. Edit /etc/sysctl.d/30-postgresql-shm.conf and run sudo sysctl -p /etc/sysctl.d/30-postgresql-shm.conf. A parameter like kernel.shmmax=17179869184 and kernel.shmall=4194304 could be appropriate for a 16GB segment size.4

Install Osm2pgsql

Osm2pgsql is an OpenStreetMap specific software used to load the OSM data into the PostGIS database.

To install osm2pgsql:

sudo apt-get install -y osm2pgsql

Go to Get an OpenStreetMap data extract.

Alternative installation procedure

This alternative installation procedure generates the most updated executable by compiling the sources.

# Needed dependencies
sudo apt-get install -y make cmake g++ libboost-dev libboost-system-dev \
  libboost-filesystem-dev libexpat1-dev zlib1g-dev \
  libbz2-dev libpq-dev libgeos-dev libgeos++-dev libproj-dev lua5.2 \

# Download osm2pgsql
cd /tmp
git clone git:// 

# Prepare for compiling
cd osm2pgsql
mkdir build && cd build
cmake ..

# Compile

# Install
sudo make install

# Clean-out temporary files
cd ../..
rm -rf osm2pgsql

Get an OpenStreetMap data extract

You need to download an appropriate .osm or .pbf file to be subsequently loaded into the previously created PostGIS instance via osm2pgsql.

There are many ways to download the OSM data.

The reference is Planet OSM.

It’s probably easiest to grab an PBF of OSM data from Mapzen or geofabrik.

Also, provides extracts of more than 200 cities and regions world-wide in different formats.


One method is directly with your browser. Check this page.

Alternatively, JOSM can be used (Select the area to download the OSM data: JOSM menu, File, Download From OSM; tab Slippy map; drag the map with the right mouse button, zoom with the mouse wheel or Ctrl + arrow keys; drag a box with the left mouse button to select an area to download. The Continuous Download plugin is also suggested. When the desired region is locally available, select File, Save As, <filename>.osm. Give it a valid file name and check also the appropriate directory where this file is saved.

Load data to PostGIS

cd ~/src
cd openstreetmap-carto
HOSTNAME=localhost # set it to the actual ip address or host name
osm2pgsql -s -C 300 -c -G -d gis --style -H $HOSTNAME -U postgres [.osm or .pbf file]

Note: if you get the following error:

node_changed_mark failed: ERROR:  prepared statement "node_changed_mark" does not exist

do the following command on your original.osm:

sed "s/action='modify' //" < original.osm | > fixedfile.osm

Then process fixedfile.osm.

If you get the following error:

Error reading style file line 79 (fields=4)
flag 'phstore' is invalid in non-hstore mode
Error occurred, cleaning up

then you need to add the hstore flag to osm2pgsql:

osm2pgsql -s -C 300 -c -G -d gis --style --hstore -H $HOSTNAME -U postgres [.osm or .pbf file]

Create indexes

Add the indexes indicated by openstreetmap-carto:

HOSTNAME=localhost # set it to the actual ip address or host name
cd ~/src
cd openstreetmap-carto
scripts/ | psql -U postgres -h $HOSTNAME -d gis

Read custom indexes for further information.

Configure renderd

Next we need to plug renderd and mod_tile into the Apache webserver, ready to receive tile requests.

Edit renderd configuration file with your preferite editor:

sudo vi /usr/local/etc/renderd.conf

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


We suppose in the above example that your home directory is /home/tileserver. Change it to your actual home directory.

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


Pay attention to the mapnik version: if it is at version 2.2 (Ubuntu 14.4):


Save the file.

Install renderd init script by copying the sample init script included in its package.

sudo cp ~/src/mod_tile/debian/renderd.init /etc/init.d/renderd

Grant execute permission.

sudo chmod a+x /etc/init.d/renderd

Edit the init script file

sudo vi /etc/init.d/renderd

Change the following variables:

DAEMON_ARGS="-c /usr/local/etc/renderd.conf"

In RUNASUSER=tileserver we suppose that your user is tileserver. Change it to your actual user name.

Save the file.

Create the following file and set tileserver (your actual user) the owner.

sudo mkdir -p /var/lib/mod_tile

sudo chown tileserver:tileserver /var/lib/mod_tile

Again change it to your actual user name.

Then start renderd service

sudo systemctl daemon-reload

sudo systemctl start renderd

sudo systemctl enable renderd

The following output is regular:

renderd.service is not a native service, redirecting to systemd-sysv-install
Executing /lib/systemd/systemd-sysv-install enable renderd

If systemctl is not installed (e.g., Ubuntu 14.4) use these commands respectively:

sudo update-rc.d renderd defaults

sudo service renderd start

Configure Apache

Create a module load file.

sudo vi /etc/apache2/mods-available/mod_tile.load

Paste the following line into the file.

LoadModule tile_module /usr/lib/apache2/modules/

Create a symlink.

sudo ln -s /etc/apache2/mods-available/mod_tile.load /etc/apache2/mods-enabled/

Then edit the default virtual host file.

sudo vi /etc/apache2/sites-enabled/000-default.conf

Past the following lines after the line <VirtualHost *:80>

LoadTileConfigFile /usr/local/etc/renderd.conf
ModTileRenderdSocketName /var/run/renderd/renderd.sock
# Timeout before giving up for a tile to be rendered
ModTileRequestTimeout 0
# Timeout before giving up for a tile to be rendered that is otherwise missing
ModTileMissingRequestTimeout 2000

Note: the default settings, which are the following, should already be a good tuning:

ModTileRequestTimeout 3
ModTileMissingRequestTimeout 30

Save and close the file. Restart Apache.

sudo systemctl restart apache2

If systemctl is not installed (e.g., Ubuntu 14.4):

sudo service apache2 restart

Test access to tiles locally:

wget --spider http://localhost/osm_tiles/0/0/0.png

You should get Remote file exists. if everything is correctly configured.

Then in your web browser address bar, type


where you need to change your-server-ip with the actual IP address of the installed map server.

You should see the tile of world map.

Congratulations! You just successfully built your own OSM tile server.

Pre-rendering tiles

To pre-render tiles instead of rendering on the fly, use render_list command. Pre-rendered tiles will be cached in /var/lib/mod_tile directory.

To show all command line option of render_list:

render_list --help

Example usage:

render_list -a

Debugging Apache, mod_tile and renderd

To clear all osm tiles cache, remove /var/lib/mod_tile/default (using rm -rf if you dare) and restart renderd daemon:

rm -rf /var/lib/mod_tile/default
sudo systemctl restart renderd

If systemctl is not installed (e.g., Ubuntu 14.4):

sudo service renderd restart

Show Apache loaded modules:

apache2ctl -M

You should find tile_module (shared)

Show Apache configuration:

apache2ctl -S

You should get the following messages within the log:

Loading tile config default at /osm_tiles/ for zooms 0 - 20 from tile directory /var/lib/mod_tile with extension .png and mime type image/png

Tail log:

tail -f /var/log/apache2/error.log

Most of the configuration issues can discovered by analyzing the debug log of renderd; we need to stop the daemon and start renderd in foreground:

sudo systemctl stop renderd

If systemctl is not installed (e.g., Ubuntu 14.4):

sudo service renderd stop


/usr/local/bin/renderd -fc /usr/local/etc/renderd.conf

Ignore the five errors related to iniparser: syntax error in /usr/local/etc/renderd.conf when referring to commented out variables (e.g., beginning with ;).

Press Control-C to kill the program. After fixing the error, the daemon can be restarted with:

sudo systemctl start renderd

If systemctl is not installed (e.g., Ubuntu 14.4):

sudo service renderd start

If everything in the configuration looks fine, but the map is still not rendered without any particular message produced by renderd, try performing a system restart:

sudo shutdown -r now

If the problem persists, you might have a problem with your UNIX user. Try debugging again, after setting these variables:

export PGHOST=localhost
export PGPORT=5432
export PGUSER=postgres
export PGPASSWORD=postgres_007%

As exceptional case, the following commands allow to fully remove Apache, mod_tile and renderd and reinstall the service:

sudo rm -r ~/src/mod_tile/
sudo apt-get purge apache2 apache2-dev
sudo rm -r /etc/apache2/mods-available
sudo rm /usr/local/etc/renderd.conf
sudo rm  /etc/init.d/renderd
sudo rm -rf /var/lib/mod_tile
sudo rm -rf /usr/lib/apache2
sudo rm -rf /etc/apache2/
sudo rm -rf /var/run/renderd
sudo apt-get --reinstall install apache2-bin
sudo apt-get install apache2 apache2-dev

Tile names format of OpenStreetMap tile server

The file naming and image format used by mod_tile is described at Slippy map tilenames. Similar format is also used by Google Maps and many other map providers.

TMS and WMS are other protocols for serving maps as tiles, managed by different rendering backends.

Deploying your own Slippy Map

Tiled web map is also known as slippy map in OpenStreetMap terminology.

OpenStreetMap does not provide an “official” JavaScript library which you are required to use. Rather, you can use any library that meets your needs. The two most popular are OpenLayers and Leaflet. Both are open source.

Page Deploying your own Slippy Map illustrates how to embed the previously installed map server into a website. A number of possible map libraries are mentioned, including some relevant ones (Leaflet, OpenLayers, Google Maps API) as well as many alternatives.


To display your slippy map with OpenLayers, create a file named ol.html under /var/www/html.

sudo vi /var/www/html/ol.html

Paste the following HTML code into the file.

You might wish to adjust the longitude, latitude and zoom level according to your needs. Check var zoom = 2, center = [0, 0];.

<!DOCTYPE html>
<title>OpenStreetMap with OpenLayers</title>
<link rel="stylesheet" href="" type="text/css">
<script src=""></script>
<script src=""></script>
  #map {
    height: 100%;
    margin: 0;
    padding: 0;
  .ol-custom-overviewmap.ol-uncollapsible {
    bottom: auto;
    left: auto;
    right: 0;
    top: 85px;
  .ol-zoom {
    top: 50px;
  .ol-zoom-extent {
      top: 110px;
  .ol-zoomslider {
      top: 140px;
  .ol-custom-fullscreen {
    bottom: auto;
    left: auto;
    right: 0;
    top: 50px;
  .ol-custom-mouse-positionXY {
    top: auto;
    bottom: 3em;
    font-family: "Arial";
    font-size: 12px;
    text-shadow: 0 0 0.5em #FFE, 0 0 0.5em #FFE, 0 0 0.5em #FFE;
  .ol-custom-mouse-positionHDMS {
    top: auto;
    bottom: 4em;
    font-family: "Arial";
    font-size: 12px;
    text-shadow: 0 0 0.5em #FFE, 0 0 0.5em #FFE, 0 0 0.5em #FFE;
  .ol-custom-mouse-position3857 {
    top: auto;
    bottom: 5em;
    font-family: "Arial";
    font-size: 12px;
    text-shadow: 0 0 0.5em #FFE, 0 0 0.5em #FFE, 0 0 0.5em #FFE;
  #ZoomElement {
    position: absolute;
    top: auto;
    left: 10px;
    bottom: 2.5em;
    text-decoration: none;
    font-family: "Arial";
    font-size: 10pt;
    text-shadow: 0 0 0.5em #FFE, 0 0 0.5em #FFE, 0 0 0.5em #FFE;
    z-index: 30;
  #TSLabel {
    position: absolute;
    top: 21px;
    right: 0;
    font-family: "Arial";
    font-size: 12px;
    z-index: 30;
  #osmLabel {
    position: absolute;
    top: 21px;
    left: 0;
    font-family: "Arial";
    font-size: 12px;
    z-index: 30;
  #swipe {
    position: absolute;
    top: 0;
    left: -4px;
    z-index: 20;
  <div class="ol-viewport">
  <input class="ol-unselectable ol-control" id="swipe" type="range" style="width: 100%">
  <div class="ol-unselectable ol-control" id="TSLabel"> Tile Server &#9658;</div>
  <div class="ol-unselectable ol-control" id="osmLabel">&#9668; OpenStreetMap </div>
  <a class="ol-unselectable ol-control" id="ZoomElement"></a>
  <div tabindex="0" id="map" class="map"></div>
    var zoom = 2, center = [0, 0];

    // Set up the Tile Server layer
    var myTileServer = new ol.layer.Tile({
      preload: Infinity,
      source: new ol.source.OSM({
        crossOrigin: null,
        url: 'osm_tiles/{z}/{x}/{y}.png'
    // Set up the OSM layer
    var openStreetMap = new ol.layer.Tile({
      preload: Infinity,
      source: new ol.source.OSM({
        crossOrigin: null,
        url: 'http://{a-c}{z}/{x}/{y}.png'

    if (window.location.hash !== '') {
      var hash = window.location.hash.replace('#', '');
      var parts = hash.split(';');
      if (parts.length === 3) {
        zoom = parseInt(parts[0], 10);
        center = [

    // Set up the default view
    var myTileView = new ol.View({
      center: ol.proj.transform(center, 'EPSG:4326', 'EPSG:3857'),
      zoom: zoom
    // Create the map
    var map = new ol.Map({
      layers: [myTileServer, openStreetMap],
      loadTilesWhileInteracting: true,
      target: 'map',
      controls: ol.control.defaults().extend([
        new ol.control.ScaleLine(),
        new ol.control.Zoom(),
        new ol.control.ZoomSlider(),
        new ol.control.ZoomToExtent(),
        new ol.control.FullScreen({
          className: 'ol-fullscreen ol-custom-fullscreen'
        new ol.control.OverviewMap({
          className: 'ol-overviewmap ol-custom-overviewmap'
        new ol.control.MousePosition({
          className: 'ol-mouse-position ol-custom-mouse-position3857',
          coordinateFormat: ol.coordinate.createStringXY(4),
          projection: 'EPSG:3857',
          undefinedHTML: '&nbsp;'
        new ol.control.MousePosition({
          coordinateFormat: function(coord) {
            return ol.coordinate.toStringHDMS(coord);
          projection: 'EPSG:4326',
          className: 'ol-mouse-position ol-custom-mouse-positionHDMS',
          target: document.getElementById('mouse-position'),
          undefinedHTML: '&nbsp;'
        new ol.control.MousePosition({
          className: 'ol-mouse-position ol-custom-mouse-positionXY',
          coordinateFormat: ol.coordinate.createStringXY(4),
          projection: 'EPSG:4326',
          undefinedHTML: '&nbsp;'
      view: myTileView
    map.on("moveend", function() {
      var view = map.getView();
      var center = ol.proj.transform(view.getCenter(), 'EPSG:3857', 'EPSG:4326');
      var zoom = view.getZoom();
      var zoomInfo = 'Zoom level = ' + zoom;
      document.getElementById('ZoomElement').innerHTML = zoomInfo;
      window.location.hash =
        view.getZoom() + ';' +
          Math.round(center[1]*1000000)/1000000 + ';' +

    var swipe = document.getElementById('swipe');
    openStreetMap.on('precompose', function(event) {
        var ctx = event.context;
        var width = ctx.canvas.width * (swipe.value / 100);;
        ctx.rect(width, 0, ctx.canvas.width - width, ctx.canvas.height);

    openStreetMap.on('postcompose', function(event) {
        var ctx = event.context;
    swipe.addEventListener('input', function() {
    }, false);

Save and close the file. Now you can view your slippy map by typing the following URL in browser.



Leaflet is a JavaScript library for embedding maps. It is simpler and smaller than OpenLayers.

The easiest example to display your slippy map with Leaflet consists in creating a file named lf.html under /var/www/html.

sudo vi /var/www/html/lf.html

Paste the following HTML code in the file. Replace your-server-ip with your IP Address and adjust the longitude, latitude and zoom level according to your needs.

<!DOCTYPE html>
<title>OpenStreetMap with Leaflet</title>
<link rel="stylesheet" href="" type="text/css">
<script src=""></script>
  #map {
    height: 100%;
    margin: 0;
    padding: 0;
  <div id="map" class="map"></div>
    // Create the map
    var map ='map').setView([45, 10], 3);
    // Set up the OSM layer

Save and close the file. Now you can view your slippy map by typing the following URL in the browser.


A rapid way to test the slippy map is through an online source code playground like this JSFiddle template.

The following example exploits Leaflet to show OpenStreetMap data.

Default tiles can be replaced with your tile server ones by changing


to http://your-server-ip/osm_tiles/{z}/{x}/{y}.png.

To edit the sample, click on Edit in JSFiddle. Then in the Javascript panel modify the string inside quotes as descripted above. Press Run.


Please, create a GitHub issue to notify errors or suggestions. This is the most effective way to track problems.
comments powered by Disqus