Offline/off-grid mapserver tutorial
Setting up your own WMS map server isn’t overly hard. There’s various open source server platforms for that. For simplicity and performance reasons, this tutorial is about setting up a WMS server with MapServer.
Please note that this tutorial is specifically for topographical maps of Finland.
This tutorial presumes that you have basic Linux command line knowledge and know how to install software on your system.
First, let’s start with some requirements. You will need at least 45GB of storage space, preferably of the solid-state type. Hardware-wise, almost everything goes. However, the more users you have, the more CPU and RAM you will need to prevent the map server from getting painfully slow. You can later also look into mapcache but that is not part of this tutorial. Software-wise, you will need to install
Once you have everything in place, create a directory of your choosing and create the subdirectories config
and maps
.
Go to the maps
subdirectory and run the Download script. That is going to take a while, depending on your internet connection. It will download about 42GB of map data.
download.sh
#!/bin/bash
WGET="wget -r -N -np -nH -nd -A png,pgw"
BASEURL="http://kartat.kapsi.fi/files"
PERUS="peruskarttarasteri_jhs180/painovari/1m/etrs89/png/"
TOPO50k="maastokarttarasteri_50k_jhs180/painovari/4m/etrs89/png/"
TOPO100k="maastokarttarasteri_100k_jhs180/kaikki/etrs89/png/"
TOPO250k="maastokarttarasteri_250k_jhs180/kaikki/etrs89/png/"
TOPO500k="maastokarttarasteri_500k_jhs180/kaikki/etrs89/png/"
YLEIS1000k="yleiskarttarasteri_1000k_jhs180/kaikki/etrs89/png/"
YLEIS2000k="yleiskarttarasteri_2000k_jhs180/kaikki/etrs89/png/"
YLEIS4500k="yleiskarttarasteri_4500k_jhs180/kaikki/etrs89/png/"
YLEIS8000k="yleiskarttarasteri_8000k_jhs180/kaikki/etrs89/png/"
${WGET} -P PERUS ${BASEURL}/${PERUS}
${WGET} -P TOPO50k ${BASEURL}/${TOPO50k}
${WGET} -P TOPO100k ${BASEURL}/${TOPO100k}
${WGET} -P TOPO250k ${BASEURL}/${TOPO250k}
${WGET} -P TOPO500k ${BASEURL}/${TOPO500k}
${WGET} -P YLEIS1000k ${BASEURL}/${YLEIS1000k}
${WGET} -P YLEIS2000k ${BASEURL}/${YLEIS2000k}
${WGET} -P YLEIS4500k ${BASEURL}/${YLEIS4500k}
${WGET} -P YLEIS8000k ${BASEURL}/${YLEIS8000k}
gdaltindex PERUS.shp PERUS/*.png
gdaltindex TOPO50k.shp TOPO50k/*.png
gdaltindex TOPO100k.shp TOPO100k/*.png
gdaltindex TOPO250k.shp TOPO250k/*.png
gdaltindex TOPO500k.shp TOPO500k/*.png
gdaltindex YLEIS1000k.shp YLEIS1000k/*.png
gdaltindex YLEIS2000k.shp YLEIS2000k/*.png
gdaltindex YLEIS4500k.shp YLEIS2000k/*.png
gdaltindex YLEIS8000k.shp YLEIS8000k/*.png
Relevant documentation
Next, go to the config
subdirectory and create the wms.map
file.
Notes:
- You have to change “wms_onlineresource” in the METADATA section to whatever fits your server.
- The source maps from the Finnish Land Survey are published in EPSG:3067. Please check your source material and change the map file if necessary
wms.map
MAP
NAME "TOPO_FIN"
IMAGETYPE PNG8
EXTENT 20000.000000 6570000.000000 788000.000000 7818000.000000
SIZE 256 256
MAXSIZE 4096
SHAPEPATH "/maps/maastokartta"
IMAGECOLOR 255 255 255
PROJECTION
"init=epsg:3067"
END
WEB
METADATA
"wms_title" "Finland - topographical map"
"wms_onlineresource" "http://<server-ip>/?service=WMS"
"wms_srs" "EPSG:3067 EPSG:3857"
"wms_getmap_formatlist" "PNG,PNG8,JPEG"
"wms_enable_request" "* !GetLegendGraphic"
END
END
LAYER
NAME "Basemap"
METADATA
"wms_title" "Basemap"
END
STATUS ON
TILEINDEX "/maps/maastokartta/index_peruskartta.shp"
TILEITEM "Location"
TYPE RASTER
EXTENT 56000.000000 6594000.000000 740000.000000 7782000.000000
MINSCALEDENOM 0
MAXSCALEDENOM 25000
PROJECTION
"init=epsg:3067"
END
PROCESSING "RESAMPLE=BILINEAR"
END
LAYER
NAME "Topo_50k"
METADATA
"wms_title" "Topo_50k"
END
STATUS ON
TILEINDEX "/maps/maastokartta/index_50000.shp"
TILEITEM "Location"
TYPE RASTER
EXTENT 20000.000000 6594000.000000 740000.000000 7794000.000000
MINSCALEDENOM 25000
MAXSCALEDENOM 50000
PROJECTION
"init=epsg:3067"
END
PROCESSING "RESAMPLE=BILINEAR"
END
LAYER
NAME "Topo_100k"
METADATA
"wms_title" "Topo_100k"
END
STATUS ON
TILEINDEX "/maps/maastokartta/index_100000.shp"
TILEITEM "Location"
TYPE RASTER
EXTENT 20000.000000 6570000.000000 740000.000000 7818000.000000
MINSCALEDENOM 50000
MAXSCALEDENOM 100000
PROJECTION
"init=epsg:3067"
END
PROCESSING "RESAMPLE=BILINEAR"
END
LAYER
NAME "Topo_250k"
METADATA
"wms_title" "Topo_250k"
END
STATUS ON
TILEINDEX "/maps/maastokartta/index_250000.shp"
TILEITEM "Location"
TYPE RASTER
EXTENT 20000.000000 6570000.000000 788000.000000 7818000.000000
MINSCALEDENOM 100000
MAXSCALEDENOM 250000
PROJECTION
"init=epsg:3067"
END
PROCESSING "RESAMPLE=BILINEAR"
END
LAYER
NAME "Topo_500k"
METADATA
"wms_title" "Topo_500k"
END
STATUS ON
TILEINDEX "/maps/maastokartta/index_500000.shp"
TILEITEM "Location"
TYPE RASTER
EXTENT 76000.000000 6570000.000000 884000.000000 7818000.000000
MINSCALEDENOM 250000
MAXSCALEDENOM 500000
PROJECTION
"init=epsg:3067"
END
PROCESSING "RESAMPLE=BILINEAR"
END
LAYER
NAME "Overview_1000k"
METADATA
"wms_title" "Overview_1000k"
END
STATUS ON
TILEINDEX "/maps/maastokartta/index_yk1000k.shp"
TILEITEM "Location"
TYPE RASTER
EXTENT 20000.000000 6570000.000000 740896.000000 7819280.000000
MINSCALEDENOM 500000
MAXSCALEDENOM 1000000
PROJECTION
"init=epsg:3067"
END
PROCESSING "RESAMPLE=BILINEAR"
END
LAYER
NAME "Overview_2000k"
METADATA
"wms_title" "Overview_2000k"
END
STATUS ON
TILEINDEX "/maps/maastokartta/index_yk2000k.shp"
TILEITEM "Location"
TYPE RASTER
EXTENT 20000.000000 6570000.000000 740896.000000 7819280.000000
MINSCALEDENOM 1000000
MAXSCALEDENOM 2000000
PROJECTION
"init=epsg:3067"
END
PROCESSING "RESAMPLE=BILINEAR"
END
LAYER
NAME "Overview_4500k"
METADATA
"wms_title" "Overview_4500k"
END
STATUS ON
TILEINDEX "/maps/maastokartta/index_yk4500k.shp"
TILEITEM "Location"
TYPE RASTER
EXTENT 20000.000000 6570000.000000 740896.000000 7819280.000000
MINSCALEDENOM 2000000
MAXSCALEDENOM 4500000
PROJECTION
"init=epsg:3067"
END
PROCESSING "RESAMPLE=BILINEAR"
END
LAYER
NAME "Overview_8000k"
METADATA
"wms_title" "Overview_8000k"
END
STATUS ON
TILEINDEX "/maps/maastokartta/index_yk8000k.shp"
TILEITEM "Location"
TYPE RASTER
EXTENT 20000.000000 6570000.000000 740896.000000 7819280.000000
MINSCALEDENOM 4500000
PROJECTION
"init=epsg:3067"
END
PROCESSING "RESAMPLE=BILINEAR"
END
END
Relevant documentation
When wms.map
is in place, go to your directory - not the config
or maps
subdir - and create the mapserver.conf
file. The file doesn’t actually contain any active instructions but we don’t want the default configuration which comes with the container.
mapserver.conf
CONFIG
ENV
#
# Default Map
#
# MS_MAPFILE "/etc/mapserver/mapserver.map"
END
#
# Map Aliases
#
# MAPS
# wfs "/etc/mapserver/wfs.map"
# END
END
Relevant documentation
Finally, when everything else in in place, create docker-compose.yaml
in your directory.
Please change the paths in the volumes section to fit your directory’s path!
In the compose file, we pass 2 important environment variables to MapServer:
-
MS_MAP_NO_PATH=1
blocks the use of explicit paths in the map=… URL parameter. -
MS_MAPFILE=/etc/mapserver/wms.map
setswms.map
as our default mapfile
docker-compose.yaml
services:
mapserver:
image: camptocamp/mapserver
container_name: mapserver
volumes:
- <your dir>/config:/etc/mapserver:rw
- <your dir>/mapserver.conf:/etc/mapserver.conf:ro
- <your dir>/maps:/maps:rw
networks:
- default
ports:
- 80:80
environment:
- MS_MAP_NO_PATH=1
- MS_MAPFILE=/etc/mapserver/wms.map
restart: unless-stopped
networks:
default:
external: true
name: web_services
Relevant documentation
If everything is set up properly, you should be able to start your MapServer instance with
-
docker compose up
if you want to watch the log output or -
docker compose up -d
if you want your MapServer to run in the background