Here i want to describe how i set up my own little Maps-Server just like openstreetmap.org or maps.google.com based on OpenStreetMap.
It is running on an average notebook (8GB RAM, i7, 1TB HDD, no SSD), without any fancy optimization and even in a chroot. It is not very fast and i just use it with Austria (the whole Planet would be way too big, there is no chance that this would work on this ordinary Notebook).
Ovarall i am very pleased and it is fast enough for one user to use it.
This HowTo is based on switchosm and debianwiki. I think that about 90% will be the same.
First, lets take a look at the result:
This whole map here is running offline, without the need of any internet connection. You will realize that there is no search field and no navigation option. This is because it basically just displays tiles. Maybe i will look into adding navigation and a search bar in the future (there are Leaflet PlugIns for that or projects like nominatim).
Whats needed:
- Mapnik to render tiles
- Postgresql with postgis for the map data (it will be importet with osm2pgsql from some .osm.pbf file)
- openstreetmap-carto, a Carto Style for Mapnik, which is basically like a CSS and tells Mapnik how it should render the map
There are other styles like OSM Bright too. - Apache2 with mod_tile and renderd to serve the tiles
- Leaflet to create a map out of tiles
Install some requirements
We will take as much as possible from the package manager, but we still have to compile things like mod_tile from source, so we need seome dev packages.
apt-get install libboost-all-dev subversion git-core tar unzip wget bzip2 build-essential autoconf libtool libxml2-dev libgeos-dev libgeos++-dev libpq-dev libbz2-dev libproj-dev munin-node munin libprotobuf-c-dev protobuf-c-compiler libfreetype6-dev libpng12-dev libtiff5-dev libicu-dev libgdal-dev libcairo-dev libcairomm-1.0-dev apache2 apache2-dev libagg-dev liblua5.2-dev ttf-unifont lua5.1 liblua5.1-0-dev
Install postgresql
apt-get install postgresql postgresql-contrib postgis postgresql-9.3-postgis-2.1 osm2pgsql
Install mapnik and node-carto
apt-get install python-mapnik libmapnik-dev maptnik-utils node-carto curl
Install basic OpenStreetMap tools (it’s needed for the openstreetmap-carto style)
apt-get install osmosis gdal-bin
Setup Database
Start postgresql if it’s not already running:
/etc/init.d/postgresql start
First we have to change the postgresql tamplate to use UTF8.
su - postgres psql -U postgres postgres=# update pg_database set datallowconn = TRUE where datname = 'template0'; UPDATE 1 postgres=# \c template0 You are now connected to database "template0". template0=# update pg_database set datistemplate = FALSE where datname = 'template1'; UPDATE 1 template0=# drop database template1; DROP DATABASE template0=# create database template1 with template = template0 encoding = 'UTF8'; CREATE DATABASE template0=# update pg_database set datistemplate = TRUE where datname = 'template1'; UPDATE 1 template0=# \c template1 You are now connected to database "template1". template1=# update pg_database set datallowconn = FALSE where datname = 'template0'; UPDATE 1 exit
Now we can create the Database. Our username will be tilesrv
su - postgres createuser tilesrv createdb -E UTF8 -O tilesrv gis exit
Create the unix user:
sudo useradd -m tiesrv sudo passwd tilesrv
Setup postgis in postgresql
su - postgres psql \c gis CREATE EXTENSION postgis; ALTER TABLE geometry_columns OWNER TO username; ALTER TABLE spatial_ref_sys OWNER TO username; \q exit
Install mod_tile and rendr
There is no Debian Package for mod_tile, so we have to compile it from source
su - root cd /usr/local/src git clone git://github.com/openstreetmap/mod_tile.git cd mod_tile ./autogen.sh ./configure make make install make install-mod_tile ldconfig exit
Install openstreetmap-carto Style
We will download openstreetmap-carto from git (this needs to be done before importing the data with osm2pgsql because the style-file describes what data goes where into the database).
su - root cd /usr/local/src wget https://github.com/gravitystorm/openstreetmap-carto/archive/v2.29.1.tar.gz tar -xzf v2.29.1.tar.gz
Now we need to build a style for mapnik out of openstreetmap-carto
cd ~/openstreetmap-carto-2.29.1/ ./get-shapefiles.sh #if your database is not named gis, you need to change it in ./project.mml before doing the next step carto project.mml > style.xml exit
Import OpenStreetMap Data to postgresql
We need to download OpenStreetMap data, don’t pick the whole planet.osm.pbf. Pick something smaller from geofabrik.de, like Austria.
mkdir /usr/local/share/maps/austria chown tilesrv /usr/local/share/maps/austria cd /usr/local/share/maps/austria wget http://download.geofabrik.de/europe/austria-latest.osm.pbf
Now we can import this data to the postgresql database.
This will take some time. On my 8GB RAM Notebook without SSD it took 5 hours to import Austria! There are some pages and articles on how to tune your system on the OpenStreetMap wiki, so that it will take not as much time, like changing buffer sizes in /etc/postgresql/9.4/main/postgresql.conf.
You will need to adjust the -C value according to your RAM size.
su - tilesrv osm2pgsql --slim -d gis -C 8000 --hstore -S /usr/local/srv/openstreetmap-carto-2.29.1/openstreetmap-carto.style /usr/local/share/maps/austria/austria-latest.osm.pbf
This is how osm2pgsql is beheaving when everything is fine:
$ time osm2pgsql --slim -d gis -C 8000 --number-processes 3 S /usr/local/srv/openstreetmap-carto-2.29.1/openstreetmap-carto.style /usr/local/share/maps/austria/austria-latest.osm.pbf osm2pgsql SVN version 0.86.0 (64bit id space) Using projection SRS 900913 (Spherical Mercator) Setting up table: planet_osm_point NOTICE: table "planet_osm_point" does not exist, skipping NOTICE: table "planet_osm_point_tmp" does not exist, skipping Setting up table: planet_osm_line NOTICE: table "planet_osm_line" does not exist, skipping NOTICE: table "planet_osm_line_tmp" does not exist, skipping Setting up table: planet_osm_polygon NOTICE: table "planet_osm_polygon" does not exist, skipping NOTICE: table "planet_osm_polygon_tmp" does not exist, skipping Setting up table: planet_osm_roads NOTICE: table "planet_osm_roads" does not exist, skipping NOTICE: table "planet_osm_roads_tmp" does not exist, skipping Using built-in tag processing pipeline 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=8000MB, maxblocks=1024000*8192, allocation method=11 Mid: pgsql, scale=100 cache=8000 Setting up table: planet_osm_nodes NOTICE: table "planet_osm_nodes" does not exist, skipping Setting up table: planet_osm_ways NOTICE: table "planet_osm_ways" does not exist, skipping Setting up table: planet_osm_rels NOTICE: table "planet_osm_rels" does not exist, skipping Reading in file: /usr/local/share/maps/austria/austria-latest.osm.pbf Processing: Node(50300k 118.9k/s) Way(5427k 24.90k/s) Relation(99170 8.95/s) parse time: 11722s Node stats: total(50300269), max(4449627239) in 423s Way stats: total(5427806), max(447905198) in 218s Relation stats: total(99178), max(6648485) in 11081s Committing transaction for planet_osm_point Committing transaction for planet_osm_line Committing transaction for planet_osm_polygon Committing transaction for planet_osm_roads Going over pending ways... 3675813 ways are pending Using 3 helper-processes Helper process 1 out of 3 initialised Helper process 2 out of 3 initialised Helper process 0 out of 3 initialised Process 0 finished processing 1225271 ways in 829 sec Process 2 finished processing 1225271 ways in 831 sec Process 1 finished processing 1225271 ways in 831 sec All child processes exited 3675813 Pending ways took 836s at a rate of 4396.91/s Committing transaction for planet_osm_point Committing transaction for planet_osm_line Committing transaction for planet_osm_polygon Committing transaction for planet_osm_roads Going over pending relations... 0 relations are pending Using 3 helper-processes Process 2 finished processing 0 relations in 4 sec Process 1 finished processing 0 relations in 4 sec Process 0 finished processing 0 relations in 4 sec All child processes exited 0 Pending relations took 4s at a rate of 0.00/s Sorting data and creating indexes for planet_osm_point node cache: stored: 50300269(100.00%), storage efficiency: 52.02% (dense blocks: 12150, sparse nodes: 42121688), hit rate: 100.00% Sorting data and creating indexes for planet_osm_line Sorting data and creating indexes for planet_osm_polygon Sorting data and creating indexes for planet_osm_roads Stopping table: planet_osm_nodes Stopped table: planet_osm_nodes in 0s Stopping table: planet_osm_ways Building index on table: planet_osm_ways (fastupdate=off) Stopping table: planet_osm_rels Building index on table: planet_osm_rels (fastupdate=off) Analyzing planet_osm_point finished Analyzing planet_osm_roads finished Analyzing planet_osm_line finished Copying planet_osm_point to cluster by geometry finished Creating geometry index on planet_osm_point Stopped table: planet_osm_rels in 77s Copying planet_osm_roads to cluster by geometry finished Creating geometry index on planet_osm_roads Creating osm_id index on planet_osm_roads Creating indexes on planet_osm_roads finished All indexes on planet_osm_roads created in 353s Completed planet_osm_roads Creating osm_id index on planet_osm_point Creating indexes on planet_osm_point finished All indexes on planet_osm_point created in 399s Completed planet_osm_point Analyzing planet_osm_polygon finished Copying planet_osm_line to cluster by geometry finished Creating geometry index on planet_osm_line Creating osm_id index on planet_osm_line Creating indexes on planet_osm_line finished All indexes on planet_osm_line created in 734s Completed planet_osm_line Copying planet_osm_polygon to cluster by geometry finished Creating geometry index on planet_osm_polygon Creating osm_id index on planet_osm_polygon Creating indexes on planet_osm_polygon finished All indexes on planet_osm_polygon created in 1715s Completed planet_osm_polygon Stopped table: planet_osm_ways in 5640s Osm2pgsql took 18205s overall 816.43user 65.39system 5:03:25elapsed 4%CPU (0avgtext+0avgdata 1029488maxresident)k 1009456inputs+0outputs (35major+452435minor)pagefaults 0swaps
Configure renderd
The renderd settings are in /usr/local/etc/renderd.conf, you need to check at least the following lines:
socketname=/var/run/renderd/renderd.sock plugins_dir=/usr/lib/mapnik/2.2/input font_dir=/usr/share/fonts/truetype TILEDIR=/var/lib/mod_tile XML=/usr/local/src/openstreetmap-carto-2.29.1/style.xml HOST=localhost
And we need to create the directories for renderd
mkdir /var/run/renderd chown tilesrv /var/run/renderd mkdir /var/lib/mod_tile chown tilesrv /var/lib/mod_tile
Configure Apache (mod_tile)
Now we have to configure Apache2.
Create a file /etc/apache2/conf-available/mod_tile.conf which contains:
LoadModule tile_module /usr/lib/apache2/modules/mod_tile.so
And add following lines to the section of /etc/apache2/sites-available/000-default.conf
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 30
Enable the mod_tile configuration and restart Apache:
a2enconf mod_tile /etc/init.d/apache2 restart
First test
Run renderd as user tilesrv:
su - tilesrv renderd -f -c /usr/local/etc/renderd.conf
In a second console, reload apache2
service apache2 reload
Browse to http://localhost/osm_tiles/0/0/0.png and you should see a small picture of the world.
Install init-file for renderd
We want to autosrat renderd, so we need to install the init-script
cp /usr/local/src/mod_tile/debian/renderd.init /etc/init.d/renderd chmod +x /etc/init.d/renderd
The init file /etc/init.d/renderd needs to be configured, change following lines:
DAEMON=/usr/local/bin/$NAME DAEMON_ARGS=" -c /usr/local/etc/renderd.conf" RUNASUSER=tilesrv
Start renderd:
/etc/init.d/renderd start
Install Leaflet
Last but not least we need install some fancy slippy map on our webserver. We choose Leaflet.
It should be usable without internet, so we download it.
cd /var/www/html wget https://unpkg.com/leaflet@1.0.1/dist/leaflet.js wget https://unpkg.com/leaflet@1.0.1/dist/leaflet.css
Now we create our /var/www/html/index.html file which will display a leaflet map in fullscreen:
Full Screen Leaflet Map <div id="map"></div>
Be sure to set the location in .setView, which is displayed first when visiting the site, to some tile with high zoomlevel which is available in your Map-Data.
Start everything
Restart all necessary services
/etc/init.d/postgresql restart /etc/init.d/renderd restart /etc/init.d/apache2 restart
Now everything is ready and you can browse to http://localhost
Be aware that the map will be very slow and you have to wait a few minutes for tiles with low zoomlevels. Don’t get impatient. Keep it open and wait. It will get faster over time when the server already rendered some tiles.