Indico Tile Server (CERN)
This is a simple tile server microservice that we are publishing in hopes of being helpful to others who want to use the map functionality in Indico 2.2 without a commercial provider.
Introduction
The Indico Tile Server is based on the TileServer GL application. Tiles are the map pieces that are served to the client through HTTP. They are stored in a file that can be built with the tilemaker application.
tilemaker
is using OpenStreetMap (OSM) maps as input and
applies some rendering instructions (style) to the input map, using the Lua
scripting language. The rendering definition can be based on shapes, typically polygons, that
define areas of the map that must be rendered specifically (for example to highlight the
buildings of your laboratory in a campus). Shapes must be built with a tool like
QGIS and stored in a shapefile.
Even though it is not mandatory, the tile server as provided in this repository is intended to
be run as a Docker container. For this reason, this repository provides, in
addition to configuration files for tileserver
and tilemaker
, a Dockerfile to build
the container.
All these files are based on CERN configuration and can be used as templates to build your own
configuration. The documentation below describes the main parameters that need to be customized.
Building the tileserver container
Dockerfile
The Dockerfile is made up of two stages: each stage produces a different container.
- the first one downloads the OpenStreetMap data, crops it to a bounding box and generates an
*.mbtiles
file containing relevant data;- Relies on osmconvert tool to extract the region of interest from an OSM map.
- the second one sets up a lightweight tileserver-gl using the data generated above;
The Dockerfile must be customized to use the proper GPS coordinates and the configuration files you will create in the next steps, in particular:
- the shapefile passed as a
tilemaker
argument - the tile file name you want to use for your site, used as the output for the
osmconvert
command and as an argument totilemaker
Shapefile
To build a shapefile, you need to use QGIS or a similar tool. See links below for the QGIS documentation.
The basic steps to create a shapefile are (based on QGIS 3.8):
- Extract the OSM map of your site. Look at the Dockerfile to see how to do it: it typically involves downloading your OSM region
map from Geofabrik and running
osmconvert
to extract the region of interest. Be aware that loading a region map into QGIS generally doesn't work because it is too big. - Open QGIS and create a new project if one was already open
- Use menu
Layer
->Add a layer
->Add a vector layer...
. In theSource
pane, select the file containing your OSM site map (extracted during first step) and click theAdd
button: the new layer should appear in the bottom left pane of the QGIS window. Click theClose
button. - Use menu
Layer
->Create a layer
->Create a new shapefile...
. Enter the shapefile file name (it must match the parameter passed totilemaker
in the Dockerfile) and for the geometry type, selectPolygon
. Accept all other defaults. Click theAdd
button: the shapefile layer should appear in the bottom left pane of the QGIS window. ClickClose
button. - With the shapefile layer selected in the bottom left pane of the QGIS window, click on the pencil icon and then
on the
Add a polygon
button, to the right of the pencil button. - On your map, draw a polygon around your site or laboratory buildings, clicking at the position of each vertex. Once
you are done with the polygon, do a right click and accept the default ID (
null
). - Repeating the previous step, draw a polygon around each set of buildings you want to identify as part of your site/laboratory.
- Once you are done, click again on the pencil button: you should be asked a confirmation that you want to save your shapefile modifications.
- Copy the files with
.shq
,.shx
and.dbf
extensions to theshapes
directory of the repository checkout.
tilemaker configuration
tilemaker
is using 2 files to drive the tile file creation, located in the tilemaker
directory:
- tiles.json: defines the different layers (building, roads, waterway...) to add to the tile file. It is important
that each type of object in the map is associated with the proper layer for the rendering customization (styles) to work
as it is based on layers rather than object types. In the CERN
tiles.json
, a layer called "cern_buildings" is created where all the buildings inside the shapefile polygons are placed. In thesettings
part of this file, you need to customize thename
anddescription
. - process.lua: a Lua script with a function,
way function()
called for each object in the map. This function is responsible for defining the attributes of the object that must be displayed. Its main feature is the selection of whether a building belongs to the site (e.g. CERN) or not. Site-specific buildings are added to a specific layer ("cern_buildings" in the CERN configuration) and others to the layer "buildings". Also, in the CERN configuration, only the CERN buildings have their names displayed: it can be easily changed by moving the following lines out of the "if way:Intersects("cern_sites") then":
if name ~= "" then
way:LayerAsCentroid("building_names")
way:Attribute("name", name)
end
You need to ensure that the name of the site-specific layer is the same in the tiles.json
file and in the
process.lua
file.
Styles
Styles define the rendering applied to the various elements. They are defined in a JSON file stored in the styles
directory of the repository. To create your own style, start from the CERN style (styles/cern.json
) and edit what
is relevant. One of the CERN style features is that buildings are rendered differently depending on whether they
are CERN buildings (buildings located inside the polygons that are part of the shapefile created before) or not.
Normal buildings are rendered in grey whereas CERN buildings are rendered in green.
tileserver configuration
The tileserver
configuration file is located in tileserver/config.json
in the repository.
It contains 2 dictionaries which have normally one key each. The key must be the same in both
dictionaries and will be your site name (used in the tile server URL configured in Indico).
The 2 dictionaries are:
data
: it contains an entrymbtiles
which is the name of the file that contains the map tiles. It must match the name of the file produced bytilemaker
.styles
: this dictionary has 2 entries:styles
: must reflect your style configuration, i.e. the JSON file relative path in the repository (e.g.styles/cern.json
).tilejson/bounds
: an array of GPS coordinates of your site OSM map (processed by tilemaker) for the south-west and the north-east corners withlatitude
thelongitude
for each one.
Build the container image
As for any Docker container image that you want to build from a Dockerfile, go into the directory containing the Dockerfile and run the following command:
$ docker build . -t indico-maps
''Note: indico-maps
will be the tag of (name referring to) the image. You can use any
name you prefer: nothing in the configuration refers to this name.`
Running the tile server
Starting the tileserver
The typical command to run the tileserver container built previously is:
$ docker run -dit --restart unless-stopped -p 8080:8080 indico-maps
Note: if you used an image tag different from indico-maps
when you built the container,
use it when starting the container.
The command above runs the container as a daemon (-d
) and ensures it is restarted when Docker
starts (for example after a reboot). If you want to see the tileserver output (logs), you must
use the command docker attach
with the container ID returned by the run
command. Type CTRL+C
to exit docker attach
.
Testing the tile server
To test your tile server, the easiest way is to use a browser and connect to http://yourhost:8080
.
Configuring httpS access to the server
Since your production Indico instance is running on HTTPS, you
need to use HTTPS for the tile server as well but tileserver
doesn't support HTTPS
natively.
To allow access to the tileserver through HTTPS,
you need to put a reverse proxy in front of it. In the proxy configuration, you need
to ensure that you pass Host
, X-Forward-Host
and X-Forwarded-Scheme
headers to the tileserver.
With nginx, this is done by adding the following lines to the host configuration:
proxy_pass_request_headers on;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
Note: HTTPS
is considered as a requirement otherwise otherwise you will have a mix of HTTP and HTTPS, which
will trigger a browser warning in the best-case scenario.
Using from Indico
To use the tile server in Indico room booking, go to the room booking administration panel and in the tileserver URL field, enter something similar to:
https://your.tileserver.dom.ain/styles/<sitename>/{z}/{x}/{y}.png
<sitename>
must be replaced by the key you used in the dictionaries of your tileserver
configuration.
Useful documentation
- tilemaker: see project home page
- tileserver: documentation
- QGIS: documentation and tutorial
Credits
This was possible thanks to the OpenStreetMap project.