CRS-7 / Spx-7

Nginx and Mapserver on Gentoo
Simple Demo Install

Nginx

These instructions assume using Gentoo and Nginx 1.9.4 is being installed. Note, pretty much installs itself.

  1. Log into gentoo as root level user, or use sudo.
  2. If Apache is installed, uninstall it or at least disable it to avoid conflicts with nginx.
  3. Do a pretend install to verify what will be installed. emerge -vDuNtp www-servers/nginx
  4. If fastcgi is not included ("-fastcgi"), then edit your package.use file to add fastcgi, possibly found at /etc/portage/package.use, and verify again.
    /etc/portage/package.usewww-servers/nginx +fastcgi
  5. If everything looks good, then install nginx. emerge -vDuN www-servers/nginx
  6. Make a backup copy of the configuration file, likely /etc/nginx/nginx.conf. cd /etc/nginx
    cp nginx.conf nginx.conf.original
  7. Edit the nginx configuration file. The default has "listen 127.0.0.1" so only requests from the server machine itself will be responded to. To make nginx accessible by other computers, comment out the line limiting to a specific IP and add a line so it only listens to all requests on port 80. Also enter an appropriate sever_name or two, if desired.
    /etc/nginx/nginx.conf# listen 127.0.0.1;
    listen      80;
    server_name example.org www.example.org;
    Note two log files will be created for the server.
    The "root" is where your documents to be served to clients are located. Ensure this location exists, or edit the path to your desired location.
    /etc/nginx/nginx.confroot /var/www/localhost/htdocs;
    Create a simple file, or elaborate if desired, named "index.html" and place it in the server's documents' root directory echo "Hello World, from nginx!" > /var/www/localhost/htdocs/index.html
  8. To start nginx: /etc/init.d/nginx start To restart nginx after a configuration change: /etc/init.d/nginx restart To run nginx as a daemon with openrc: rc-update add nginx default
  9. To test the server, open your favourite webbrowser and go to localhost. If there is a domain assigned to the computer, your domain name maybe substituted for "localhost". links http://localhost

Mapserver

These instructions assume Debian 7.0 is used, Nginx 1.2.1 was installed following above instructions, and Mapserver 6.0.1 is being installed.

  1. Check what will be installed to install via portage: emerge -vDuNtp mapserver Edit your package.use file for desired USE flags(unnecessary for demo), and then complete install: emerge -vDuN mapserver
  2. If emerging mapserver via portage is unsuccessful (or undesired), download the source from mapserver.org, extract the contents, and try to make the application. tar -xvzf mapserver-7-0-0.tar.gz
    cd mapserver-7.0
    mkdir build
    cd build
    cmake ..
    make
    There may be errors requiring adjustments, like including where your local glib 2 files are.
    Clear the build directory and open the CMakeLists.txt file. cd ..
    rm -r build/*
    nano CMakeLists.txt
    To add the missing glib 2 paths, near the top of CMakeLists.txt just below the "include_directories" lines, add the following with adjustments for the paths on your system.
    CMakeLists.txtinclude_directories(/usr/include/glib-2.0)
    include_directories(/usr/lib64/glib-2.0/include)
    Try making mapserver again: cd build
    cmake ..
    make
    If it works this time, then install (default to /usr/local/). make install
  3. Verify the mapserv executable/cgi is installed, and which options. mapserv -v
  4. With the executable/cgi installed, it is time to test it with a simple map. First try a shapefile, then a raster (png) file.

Mapserver Shapefile CGI

  1. Download a shapefile for the world. A "shapefile" consists of at least the 3 files with the same "name" and ending with the extensions ".dbf",".shp", and ".shx". The Natural Earth datasets come in various sizes and are free to use, downloadable from www.naturalearthdata.com/downloads/. The "Small scale data, 1:110m" files are small, so use one of them for the test. ( eg, Admin 0 – Boundary Lines : country boundaries ) If a different shapefile is used, be careful to adjust the names accordingly.
  2. Extract the files to a directory("shapefile directory") which nginx will have permissions to access and read, but is not under the nginx document "root" (see nginx.conf) for clients to directly request. For example, if nginx "root" is "/var/www/localhost/htdocs" , then "/var/www/localhost/mapserver/" could be used.
  3. In the shapefile directory, create and open a file with the extension ".map" to tell mapserver about the shapefile. Edit the configuration file (eg, "shapefile.map") as below, adjusting for your specific configuration. See a version with line-by-line details further below.
    /var/www/localhost/mapserver/shapefile.mapMAP
    	NAME "world"
    	STATUS ON
    	SIZE 600 400
    	EXTENT -180 -90 180 90
    	IMAGECOLOR 255 255 255
    	#
    	# Start of layer definitions
    	#
    	LAYER
    		NAME "world_nations"
    		DATA ne_110m_admin_0_boundary_lines_land
    		STATUS DEFAULT
    		TYPE LINE
    		CLASS
    			NAME 'The World'
    			STYLE
    				OUTLINECOLOR 0 0 0
    			END # STYLE
    		END # CLASS
    	END # LAYER
    END # MAP
    
    With line-by-line commenting:
    /var/www/localhost/mapserver/shapefile.mapMAP
    	NAME "world" # unimportant for now
    	STATUS ON # do show map
    	SIZE 600 400 # size of image to output
    	EXTENT -180 -90 180 90 # bounaries of source data. For this shapefile it is in degrees
    	IMAGECOLOR 255 255 255 # colour of image, excluding lines
    	#
    	# Start of layer definitions
    	#
    	LAYER
    		NAME "world_nations" # unimportant for now
    		DATA ne_110m_admin_0_boundary_lines_land # filename shared by the 3 shapefile files, without the extensions
    		STATUS DEFAULT # "DEFAULT" outputs image, "ON" and "OFF" tend to give blank image
    		TYPE LINE # !!!! shape type used in shapefile. For Polygon type, TYPE POLYGON. Using a less complex shape TYPE than used will work, like using LINE instead of POLYGON
    		CLASS
    			NAME 'The World' # unimportant for now
    			STYLE
    				OUTLINECOLOR 0 0 0 # colour of lines on the map, like national borders
    			END # STYLE
    		END # CLASS
    	END # LAYER
    END # MAP
    
  4. Test using the command line to validate the map file and its dependencies. Edit the path/filename for your setup. mapserv -nh "QUERY_STRING=map=/var/www/localhost/mapserver/shapefile.map&mode=map" > maptest.png Open the maptest.png file to verify the map lines are visible. If the national land borders shapefile suggested was used, then all land borders should be visible, but no coastlines.
  5. Now a daemon is needed for creating a mapserv-fastcgi process, since nginx does not handle this itself. Spawn FCGI v1.6.4 is used for this guide. To verify what will be installed, run: emerge -vDuNtp spawn-fcgi And then to install: emerge -vDuN spawn-fcgi
  6. Create a symbolic link to the new spawn-fcgi daemon script for a mapserv daemon. cd /etc/init.d
    ln -s spawn-fcgi spawn-fcgi.mapserv
  7. Create a copy of the default spawn-fcgi configuration file for the mapserv daemon configuration. cd /etc/conf.d
    cp spawn-fcgi spawn-fcgi.mapserv
    Open the configuration file and change the socket to a path where the socket can reside and be used. The actual socket will have a dash and number automatically appended.
    /etc/conf.d/spawn-fcgi.mapserv# FCGI_SOCKET=
    FCGI_SOCKET=/var/run/mapserv.sock
    The address and port must be disabled by setting them to blank/empty so the socket can be used.
    /etc/conf.d/spawn-fcgi.mapserv# FCGI_ADDRESS=127.0.0.1
    FCGI_ADDRESS=
    
    # FCGI_PORT=1234
    FCGI_PORT=
    Set the fgci program path to the full path of the mapserv cgi/executable file on your system. If installed from source code, this may be /usr/local/bin/mapserv .
    /etc/conf.d/spawn-fcgi.mapserv#FCGI_PROGRAM=/usr/bin/php-cgi
    FCGI_PROGRAM=/usr/bin/mapserv
    Set the fast-cgi user/group to the same as the webserver.
    /etc/conf.d/spawn-fcgi.mapservFCGI_USER=nginx
    FCGI_GROUP=nginx
  8. Start up the mapserv daemon and verify it is ready for use. Use "*" with "ls" because "-1" is appended to the name for the first socket. /etc/init.d/spawn-fcgi.mapserv start
    ls -la /var/run/mapserv.sock*
    If you want to always start the daemon at boot, add to openrc (or your system's daemon manager). rc-update add spawn-fcgi.mapserv default
  9. Edit the ngninx configuration file. Add the following location to your "server {" "}" section, being careful to set the "root" directory to your mapserv executable's directory, and "fastcgi_pass" to "unix:"+[path_of_socket].
    /etc/nginx/nginx.conf		location ~ ^/mapserv$ {
    			gzip           off;
    			root           /usr/bin; # path to directory with mapserv cgi/executable
    			fastcgi_pass   unix:/var/run/mapserv.sock-1; # path of mapserv fcgi socket
    			# include      fastcgi_params;
    			fastcgi_param  QUERY_STRING       $query_string;
    			fastcgi_param  REQUEST_METHOD     $request_method;
    			fastcgi_param  CONTENT_TYPE       $content_type;
    			fastcgi_param  CONTENT_LENGTH     $content_length;
    
    			fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
    			fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
    			fastcgi_param  REQUEST_URI        $request_uri;
    			fastcgi_param  DOCUMENT_URI       $document_uri;
    			fastcgi_param  DOCUMENT_ROOT      $document_root;
    			fastcgi_param  SERVER_PROTOCOL    $server_protocol;
    
    			fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
    			fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
    
    			fastcgi_param  REMOTE_ADDR        $remote_addr;
    			fastcgi_param  REMOTE_PORT        $remote_port;
    			fastcgi_param  SERVER_ADDR        $server_addr;
    			fastcgi_param  SERVER_PORT        $server_port;
    
    			# According to RFC3875 (https://tools.ietf.org/html/rfc3875#section-4.1.14) in SERVER_NAME
    			# we should put actual hostname user came to. For nginx it is in $host
    			# This will allow to run multihost instances
    			fastcgi_param  SERVER_NAME        $host;
    		}
    The "~ ^/mapserv$" regex comparison catches all page requests ending with "/mapserv", excluding GET parameters. If the executable is "mapserv.cgi", change the comparison here to "~ ^/mapserv.cgi$ {" and future http requests to "/mapserv.cgi?".
  10. Test the cgi functionality. Ensure the mapserv fcgi daemon is running. /etc/init.d/spawn-fcgi.mapserv restart Ensure nginx gets the new configuration loaded. /etc/init.d/nginx restart Go to your favourite gui webbrowser and try to view the map. Edit "localhost" to your domain if not accessing via localhost. links http://localhost/mapserv This will give an error (ie, "No query information to decode. QUERY_STRING is set, but empty.") because, like running mapserv from the command line, it needs to know which map to use and the mode. Add GET parameters for "map" to match the location of your shapefile mapfile, and "mode" to be "map". And edit the first "localhost" to you domain, if needed. links http://localhost/mapserv?map=/var/www/localhost/mapserver/shapefile.map&mode=map The map should now be visible. If using the land borders map, it will show black lines for the land borders between nations on a white background.
* NOTE: this is just to get something visible, not a finished or secure product.

Mapserver Raster (PNG) CGI

To host a simple raster(image) source for mapserver requires the same process as in the Mapserver Shapefile CGI section, but with the following changes.

  1. Instead of downloading shapefile files, get a large image file of the whole Earth, such as the Blue Marble images with topography and bathymetry available from NASA. For simplicity, this guide uses the smallest Blue Marble image consisting of the whole Earth in a single png file: world.topo.bathy.200401.3x5400x2700.png . Download a copy to your mapserver directory.
  2. Instead of "shapefile.map", create a "raster.map" similar to below. A more detailed raster.map is further below.
    /var/www/localhost/mapserver/raster.mapMAP
    	NAME "World"
    	STATUS ON
    	SIZE 800 400
    	EXTENT -180 -90 180 90
    	SHAPEPATH "."
    	#
    	# Start of layer definitions
    	#
    	LAYER
    		NAME "topo-bath"
    		TYPE RASTER
    		EXTENT -180 -90 180 90
    		STATUS DEFAULT
    		DATA "world.topo.bathy.200401.3x5400x2700.png"
    	END # LAYER
    END # MAP
    
    With line by line comments:
    /var/www/localhost/mapserver/raster.mapMAP
    	NAME "World" # Name used to refer to aggregate map layer sent to client
    	STATUS ON # show this map, but client can turn off.
    	SIZE 800 400 # size of image to send to requesting clients
    	EXTENT -180 -90 180 90 # dimensions source data represents, need for MAP and LAYER
    	SHAPEPATH "." # relative path to directory containing the raster/image file from this mapfile's directory
    	#
    	# Start of layer definitions
    	#
    	LAYER
    		NAME "topo-bath" # name of layer in map, topography-bathymetry image raster layer
    		TYPE RASTER # type of data is raster/image
    		EXTENT -180 -90 180 90 # dimensions source data represents, need for MAP and LAYER
    		STATUS DEFAULT # always display this layer when this MAP is requested
    		DATA "world.topo.bathy.200401.3x5400x2700.png" # name of the raster/image file
    	END # LAYER
    END # MAP
    
  3. Test the raster mapfile from the commandline with the following command modified for your raster.map path. mapserv -nh "QUERY_STRING=map=/var/www/localhost/mapserver/raster.map&mode=map" > rastertest.png The rastertest.png file will contain a smaller, lower-resolution copy of the original Blue Marble image.
  4. Start the mapserv fastcgi and nginx, if not already started. /etc/init.d/spawn-fcgi.mapserv start
    /etc/init.d/nginx start
    Test the raster mapfile with your server by going to the link below, changing the (first) localhost to your domain and the mapfile path for your system. links http://localhost/mapserv?map=/var/www/localhost/mapserver/raster.map&mode=map
* NOTE: this is just to get something visible, not a finished or secure product.

Mapserver PostGIS

This guide assumes use of PostgreSQL 9.4 and PostGIS 2.1.

  1. Verify what will be installed for PostGIS, then install PostgreSQL and PostGIS, if not already installed. A default database will be installed in /var/lib/postgres-9.4/data/. emerge -vDuNtp postgis
    emerge -vDuN postgis
  2. To start postgresql/postgis as a foreground process with the installed default database. Running in the foreground displays error messages to the screen for fast identification. su postgres
    postgres -D /var/lib/postgres-9.4/data
    To start postgresql/postgis as a background server. /etc/init.d/postgresql-9.4 start To add a daemon so postgresql/postgis is always available. rc-update add postgresql-9.4 default The default configuration for PostgreSQL may allow all local connections to require no password. To secure the system, edit the /etc/postgresql-9.4/pg_hba.conf file so METHOD for connections requires passwords, as described in the file. Note: set the "postgres" ROLE password to avoid getting locked out of PostgreSQL after passwords are required.
  3. After starting the database server, switch to the "postgres" user, create a database "mapdb", connect to the database, and add the PostGIS extension to it. su postgres
    psql
    CREATE DATABASE mapdb;
    \c mapdb
    CREATE EXTENSION postgis;
  4. While still in psql as postgres and connected to "mapdb" database, create a new role/user "mapuser" for accessing and controlling the database "mapdb", and then exit "postgres". CREATE USER mapuser;
    ALTER ROLE mapuser WITH PASSWORD 'secretpassword';
    ALTER DATABASE mapdb OWNER TO mapuser;
    \q
    exit
  5. Log into the "mapdb" database using the "mapuser" role. psql mapdb mapuser Create a new table for storing points on Earth. CREATE TABLE global_points (
    id SERIAL PRIMARY KEY,
    name VARCHAR(64),
    location GEOGRAPHY(POINT,4326)
    );
    Add some locations to the table, using the "4326" spheroid model of Earth's shape and each (longitude latitude) in decimal degrees. INSERT INTO global_points (name, location)
    VALUES ('Panama', STraphyFromText('SRID=4326;POINT(-79.5 9)') );
    INSERT INTO global_points (name, location)
    VALUES ('Forest', STraphyFromText('SRID=4326;POINT(-79.5 51.5)') );
    INSERT INTO global_points (name, location)
    VALUES ('London', STraphyFromText('SRID=4326;POINT(-0.1 51.5)') );
    Create an index for each location's position. CREATE INDEX global_points_gix ON global_points USING GIST ( location ); Now simple queries of the data can be executed.
  6. WARNING: the "GEOGRAPHY" type has much fewer functions implemented for it than "GEOMETRY" type, and PostGIS does not automatically convert GEOGRAPHY to GEOMETRY.

    This will cause Mapserver to fail when it tries to use "location". Since Mapserver puts double quotes around the DATA field selected, a simple type cast or function can not be used to work around the problem.

    A simple solution is to make a VIEW in the database with everything from the original table plus a new GEOMETRY field type casting from the GEOGRAPHY field. CREATE VIEW global_points_geom AS
    SELECT *, location::geometry AS location_geom
    FROM global_points;
  7. Now create a new mapfile, "postgis.map", in the same directory as the other mapfiles. This mapfile will be adding the locations in PostGIS to the raster map used earlier.

    Below is the new mapfile, with a commented version further below.
    /var/www/localhost/mapserver/postgis.mapMAP
    	NAME "World"
    	STATUS ON
    	SIZE 800 400
    	EXTENT -180 -90 180 90
    	UNITS DD
    	SHAPEPATH "."
    	FONTSET ./fonts.txt
    	SYMBOLSET "./symbols.txt"
    	#
    	# Start of layer definitions
    	#
    	# raster/image layer of world, flattened
    	LAYER
    		EXTENT -180 -90 180 90
    		NAME "topo-bath"
    		TYPE RASTER
    		STATUS DEFAULT
    		DATA "world.topo.bathy.200401.3x5400x2700.png"
    	END # LAYER
    	#
    	# points to add to map, taken from postgis database
    	LAYER
    		EXTENT -180 -90 180 90
    		CONNECTIONTYPE POSTGIS
    		NAME "worldpoints"
    		CONNECTION "host=127.0.0.1 dbname=mapdb user=mapuser password=secretpassword"
    		PROCESSING "CLOSE_CONNECTION=DEFER"
    		DATA "location_geom from global_points_geom using srid=4326 using unique id"
    		LABELITEM "name"
    		STATUS DEFAULT
    		TYPE POINT
    		CLASS
    			NAME "placedot"
    			STYLE
    				SYMBOL 'circle'
    				OUTLINECOLOR 255 0 0
    				SIZE 10
    				COLOR 0 255 0
    			END # STYLE
    			LABEL
    				FONT "arial"
    				TYPE truetype
    				SIZE 12
    				POSITION LC
    				COLOR  255 0 0
    				OUTLINECOLOR 0 0 0
    			END # LABEL
     		END # CLASS
    	END # LAYER
    END # MAP
    
    With comments explaining each line
    /var/www/localhost/mapserver/postgis.mapMAP
    	NAME "World" # Name used to refer to aggregate map layer sent to client
    	STATUS ON # show this map, but client can turn off.
    	SIZE 800 400 # size of image to send to requesting clients
    	EXTENT -180 -90 180 90 # dimensions source data represents, need for MAP and LAYER
    	UNITS DD # units used for scale bar and scaling/zoom
    	SHAPEPATH "." # path to directory containing the raster/image file
    	FONTSET "./fonts.txt" # path to fonts file, needed for drawing labels onto map
    	SYMBOLSET "./symbols.txt" # path to symbols file, needed for drawing points or pictures onto map
    	#
    	# Start of layer definitions
    	#
    	# raster/image layer of world, flattened
    	LAYER
    		EXTENT -180 -90 180 90 # dimensions source data represents, need for MAP and LAYER
    		NAME "topo-bath" # name of layer in map, topography-bathymetry image raster layer
    		TYPE RASTER # type of data is raster/image
    		STATUS DEFAULT # "always display" when this MAP is requested
    		DATA "world.topo.bathy.200401.3x5400x2700.png" # name of the raster/image file
    	END # LAYER
    	#
    	# points to add to map, taken from postgis database
    	LAYER
    		EXTENT -180 -90 180 90 # dimensions source data represents, need for MAP and LAYER
    		CONNECTIONTYPE POSTGIS # connect to PostgreSQL/PostGIS database
    		NAME "worldpoints" # name of layer in map
    		CONNECTION "host=127.0.0.1 dbname=mapdb user=mapuser password=secretpassword" # Connect to a local (or remote) spatial database, edit user, dbname and host as needed
    		PROCESSING "CLOSE_CONNECTION=DEFER" # keep connection alive for this mapfile, instead of slow reconnection for each layer
    		DATA "location_geom from global_points_geom using srid=4326 using unique id" # Get the points from the ’location_geom’ field of the ’global_points_geom’ VIEW (type casts table 'global_points' field 'location' to "GEOMETRY" type). "srid=4326" means use 4326 spheroid shape of Earth. PRIMARY KEY (unique) is "id".
    		LABELITEM "name" # name of field for displaying as label on the map/layer with each point
    		STATUS DEFAULT # "always display"
    		TYPE POINT # layer displays points (name labels are extras with points)
    		CLASS
    			NAME "placedot" # unimportant
    			STYLE # style for dot/line/polygon to display
    				SYMBOL 'circle' # name of symbol, find SYMBOL with this NAME
    				OUTLINECOLOR 255 0 0 # outer line/border RGB colour for circle
    				SIZE 10 # size of circle
    				COLOR 0 255 0 # inner RGB color for circle
    			END # STYLE
    			LABEL # style for label/name to display near point
    				FONT "arial" # font used for label, MUST exist in FONT file included above and the font must exist in the system
    				TYPE truetype # truetype or bitmap. Truetype is prettier
    				SIZE 12 # size of label letters
    				POSITION LC # position of label relative to dot/point. "POSITION [upper-lower][left-right]" where "LC" = "lower,center"
    				COLOR  255 0 0 # main colour of letters
    				OUTLINECOLOR 0 0 0 # colour of outline around each letter
    			END # LABEL
     		END # CLASS
    	END # LAYER
    END # MAP
    
    This map has two layers, a picture of Earth layer overlayed with points of interest. The points of interest rely on FONTSET and SYMBOLSET files. An error in those files will prevent the mapfile from working. See below for samples of these files.
  8. Create a symbols file to tell mapserver how to draw a 'circle' SYMBOL. This file draws a simple circle at the location. A SYMBOL can be a simple shape or a picture.
    /var/www/localhost/mapserver/symbols.txtSYMBOLSET
    	SYMBOL
    		NAME "circle" # name used to refer to this symbol in a mapfile
    		TYPE ellipse # ellipsde shape
    		FILLED true # middle/most of circle is opaque and not transparent
    		POINTS # reference points for shape/rotation/position of ellipse
    			1 1 # x y of radius, make equal for a circle. Actual size of circle determined in mapfile's STYLE's SIZE.
    		END # POINTS
    	END # SYMBOL
    END # SYMBOLSET
    
  9. Create a fonts file to tell mapserver where to get the data for how to draw a FONT in the mapfile. The file is list of each line containing a font name then whitespace then full path to the font file.
    /var/www/localhost/mapserver/fonts.txtverdana	/usr/share/fonts/corefonts/verdana.ttf
    times	/usr/share/fonts/corefonts/times.ttf
    arial	/usr/share/fonts/corefonts/arial.ttf
    
    To look up what fonts are available on your system and where, use "find" or another file search tool. find / -name *.ttf
  10. Start nginx, spawn-fcgi.mapserv and postgresql, if not already running.
  11. Test the PostGIS mapfile with your server by going to the link below, changing the (first) localhost to your domain and the mapfile path for your system. links http://localhost/mapserv?map=/var/www/localhost/mapserver/postgis.map&mode=map
* NOTE: this is just to get something visible, not a finished or secure product.

Mapserver WMS (Shapefile)

To make a shapefile map available via WMS requires several additions to the mapfile and a minor addition to the nginx configuration file.

  1. Create a new mapfile file (eg, wms.map) in the same shapefile directory as earlier. Add the configuration, as below, making adjustments as needed for names, paths, etc. See the further below file for line-by-line comments on making these edits.
    /var/www/localhost/mapserver/wms.mapMAP
    	NAME "Nations"
    	PROJECTION # All Natural Earth data use the Geographic coordinate system (projection), WGS84 datum +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs # Natural Earth data seems to be EPSG:4326
    		"init=epsg:4326" # Natural Earth data seems to be EPSG:4326
    	END # PROJECTION
    	STATUS ON
    	EXTENT -180 -90 180 90
    	UNITS DD
    	SHAPEPATH "." # where the spapefile or raster data is located
    	IMAGECOLOR 255 255 255
    	#
    	# Start of web interface definition
    	#
    	WEB
    		METADATA
    			wms_title "Word Borders"
    			wms_onlineresource "http://localhost/mapserv?map=/var/www/localhost/mapserver/wms.map&"
    			# wms_srs (unless PROJECTION object is defined using “init=epsg:...”)
    			wms_enable_request "GetCapabilities GetMap GetLegendGraphic"
    		END # METADATA
    		IMAGEPATH "/var/www/localhost/mapserver_tmp/"
    		IMAGEURL "/wmst/"
    	END # WEB
    	#
    	# Start of layer definitions
    	#
    	LAYER
    		NAME "ne_110m_admin_0_boundary_lines_land"
    		PROJECTION
    			"init=epsg:4326"
    		END # PROJECTION
    		METADATA
    			"wms_srs" "EPSG:4326" # optional tag since inherits MAP level's wms_srs
    			"wms_name" "land boundaries"
    			"wms_server_version" "1.1.1"
    			"wms_format" "image/png"
    		END # METADATA
    		STATUS ON
    		DATA ne_110m_admin_0_boundary_lines_land
    		TYPE LINE # TYPE POLYGON
    		CLASS
    			NAME 'provinceboundaries'
    			STYLE
    				OUTLINECOLOR 0 0 0
    				SIZE       1
    			END # STYLE
    		END # CLASS
    	END # LAYER
    END # MAP
    
    With comments explaining each line
    /var/www/localhost/mapserver/wms.mapMAP
    	NAME "Nations" # name for the aggregate layer output to the client as images/tiles
    	PROJECTION # All Natural Earth data use the Geographic coordinate system (projection), WGS84 datum +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs
    		"init=epsg:4326" # Natural Earth data coresponds to "EPSG:4326" projection type, using "init=" means allows skipping "wms_srs" below
    	END # PROJECTION
    	STATUS ON # show lines of this map
    	EXTENT -180 -90 180 90 # range of coordinates of WMS requests allowed.
    	UNITS DD # units for scalebar and scaling/zoom, eg "DD" decimal degrees, not visible in this simple demo, maybe visible with Cesium
    	SHAPEPATH "." # where directory with the spapefile or raster data is located, relative to this file
    	IMAGECOLOR 255 255 255 # background color of images/tiles output
    	#
    	# Start of web interface definition
    	#
    	WEB
    		METADATA
    			wms_title "Word Borders" # name for the map, can have spaces
    			wms_onlineresource "http://localhost/mapserv?map=/var/www/localhost/mapserver/wms.map&" # link/url to your mapserver cgi with "map=" to your wms mapfile and MUST end with "&", OR can end at "?" if your "map=" part is hidden and carefully appended by nginx or a cgi wrapper
    			# wms_srs is unneeded unless PROJECTION object is defined using “init=epsg:...”
    			wms_enable_request "GetCapabilities GetMap GetLegendGraphic" # default is nothing enabled. Must enable some to make wms mapserver usable # possibilities: {GetCapabilities GetMap GetFeatureInfo GetLegendGraphic}
    		END # METADATA
    		IMAGEPATH "/var/www/localhost/mapserver_tmp/" # full path of directory on server to place the images/tiles to be sent to client (eg, /var/www/localhost/mapserver_tmp/nameofimage)
    		IMAGEURL "/wmst/" # url / path within the domain for client to use to get images/tiles from IMAGEPATH (eg, http://domain.com/wmst/nameofimage)
    	END # WEB
    	#
    	# Start of layer definitions
    	#
    	LAYER
    		NAME "ne_110m_admin_0_boundary_lines_land" # name (no spaces) for specific layer within this mapfile. Can be multiple layers per mapfile.p
    		PROJECTION # All Natural Earth data use the Geographic coordinate system (projection), WGS84 datum +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs
    			"init=epsg:4326" # Natural Earth data coresponds to "EPSG:4326" projection type, using "init=" means allows skipping "wms_srs" below
    		END # PROJECTION
    		METADATA
    			"wms_srs" "EPSG:4326" # optional tag since inherits MAP level's wms_srs
    			"wms_name" "land boundaries" # name for the map layer, can have spaces
    			"wms_server_version" "1.1.1" # This is the older standard. Could use "wms_server_version" "1.3.0"
    			"wms_format" "image/png" # Image file type. eg, "image/jpeg"
    		END # METADATA
    		STATUS DEFAULT # DEFAULT always sent to client, STATUS ON or OFF can be requested by client. Relevant if multiple layers in mapfile.
    		DATA ne_110m_admin_0_boundary_lines_land
    		TYPE LINE # Kind of shapes data represents. A more simple shape type can be specified than data is stored in. eg, "TYPE LINE" if data is "TYPE POLYGON"
    		CLASS
    			NAME 'provinceboundaries' # name of "CLASS"/style for this layer
    			STYLE # layer drawing characteristics
    				OUTLINECOLOR 0 0 0 # colour of border lines drawn
    				SIZE       1 # width of border lines drawn
    			END # STYLE
    		END # CLASS
    	END # LAYER
    END # MAP
    
  2. To enable access to the temporary image directory by the client, add the following to the nginx.conf file, inside the "server{" "}", after the mapserv "location {" "}" block. The location (/wmst/) and alias must match the IMAGEURL and IMAGEPATH in your wms.map file, respectively, and must end with slash "/".
    /etc/nginx/nginx.cfg		# for wms mapserver temporary files/tiles
    		location /wmst/ {
    			alias /var/www/localhost/mapserver_tmp/;
    			# using "root" postfixes the location name to end of path. eg, /var/www/localhost/mapserver_tmp/wmst/
    		}
    
    The "alias" directory must exist and have permission for read and write by the webserver and fast-cgi daemons' user (nginx). mkdir /var/www/localhost/mapserver_tmp
    chown nginx:nginx /var/www/localhost/mapserver_tmp
    chmod 755 /var/www/localhost/mapserver_tmp
  3. Restart nginx to use new configuration. /etc/init.d/nginx restart
  4. Test if WMS is working by going to following url with webbrowser, changing (first) "localhost" to your domain if needed, adjusting "map=" parameter's path for your wms mapfile. links http://localhost/mapserv?map=/var/www/localhost/mapserver/wms.map&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetCapabilities This should give an xml file with information about the wms server, similar to below. It may include ERROR tag messages if there is a configuration issue.
    <?xml version='1.0' encoding="UTF-8" standalone="no" ?>
    <!DOCTYPE WMT_MS_Capabilities SYSTEM "http://schemas.opengis.net/wms/1.1.1/WMS_MS_Capabilities.dtd"
     [
     <!ELEMENT VendorSpecificCapabilities EMPTY>
     ]>  <!-- end of DOCTYPE declaration -->
    
    <WMT_MS_Capabilities version="1.1.1">
    
    <!-- MapServer version 7.0.0 OUTPUT=PNG OUTPUT=JPEG SUPPORTS=PROJ SUPPORTS=AGG SUPPORTS=FREETYPE SUPPORTS=CAIRO SUPPORTS=ICONV SUPPORTS=FRIBIDI SUPPORTS=WMS_SERVER SUPPORTS=WFS_SERVER SUPPORTS=WCS_SERVER SUPPORTS=FASTCGI SUPPORTS=GEOS INPUT=JPEG INPUT=POSTGIS INPUT=OGR INPUT=GDAL INPUT=SHAPEFILE -->
    
    <Service>
      <Name>OGC:WMS</Name>
      <Title>WMS NE2 Provinces</Title>
      <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://localhost/mapserv?map=/var/www/localhost/mapserver/wms.map&amp;"/>
      <ContactInformation>
      </ContactInformation>
    </Service>
    
    <Capability>
      <Request>
        <GetCapabilities>
          <Format>application/vnd.ogc.wms_xml</Format>
          <DCPType>
            <HTTP>
              <Get><OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://localhost/mapserv?map=/var/www/localhost/mapserver/wms.map&amp;"/></Get>
              <Post><OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://localhost/mapserv?map=/var/www/localhost/mapserver/wms.map&amp;"/></Post>
            </HTTP>
          </DCPType>
        </GetCapabilities>
        <GetMap>
          <Format>image/png</Format>
          <Format>image/jpeg</Format>
          <Format>image/png; mode=8bit</Format>
          <Format>application/x-pdf</Format>
          <Format>image/svg+xml</Format>
          <Format>image/tiff</Format>
          <DCPType>
            <HTTP>
              <Get><OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://localhost/mapserv?map=/var/www/localhost/mapserver/wms.map&amp;"/></Get>
              <Post><OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://localhost/mapserv?map=/var/www/localhost/mapserver/wms.map&amp;"/></Post>
            </HTTP>
          </DCPType>
        </GetMap>
        <GetLegendGraphic>
          <Format>image/png</Format>
          <Format>image/jpeg</Format>
          <Format>image/png; mode=8bit</Format>
          <DCPType>
            <HTTP>
              <Get><OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://localhost/mapserv?map=/var/www/localhost/mapserver/wms.map&amp;"/></Get>
              <Post><OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://localhost/mapserv?map=/var/www/localhost/mapserver/wms.map&amp;"/></Post>
            </HTTP>
          </DCPType>
        </GetLegendGraphic>
      </Request>
      <Exception>
        <Format>application/vnd.ogc.se_xml</Format>
        <Format>application/vnd.ogc.se_inimage</Format>
        <Format>application/vnd.ogc.se_blank</Format>
      </Exception>
      <VendorSpecificCapabilities />
      <UserDefinedSymbolization SupportSLD="1" UserLayer="0" UserStyle="1" RemoteWFS="0"/>
      <Layer>
        <Name>nations</Name>
        <Title>WMS NE2 Provinces</Title>
        <Abstract>nations</Abstract>
        <SRS>EPSG:4326</SRS>
        <LatLonBoundingBox minx="-180" miny="-90" maxx="180" maxy="90" />
        <BoundingBox SRS="EPSG:4326"
                    minx="-180" miny="-90" maxx="180" maxy="90" />
        <Layer queryable="0" opaque="0" cascaded="0">
            <Name>ne_110m_admin_0_boundary_lines_land</Name>
            <Title>ne_110m_admin_0_boundary_lines_land</Title>
            <SRS>EPSG:4326</SRS>
            <LatLonBoundingBox minx="-140.998" miny="-54.8968" maxx="141.034" maxy="70.1642" />
            <BoundingBox SRS="EPSG:4326"
                        minx="-140.998" miny="-54.8968" maxx="141.034" maxy="70.1642" />
            <Style>
              <Name>default</Name>
              <Title>default</Title>
              <LegendURL width="151" height="23">
                 <Format>image/png</Format>
                 <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://localhost/mapserv?map=/var/www/localhost/mapserver/wms.map&amp;version=1.1.1&amp;service=WMS&amp;request=GetLegendGraphic&amp;layer=ne_110m_admin_0_boundary_lines_land&amp;format=image/png&amp;STYLE=default"/>
              </LegendURL>
            </Style>
        </Layer>
      </Layer>
    </Capability>
    </WMT_MS_Capabilities>
    
    To get a test map image/tile from the wms, try the following, making adjustments to names/paths as needed.
    Change the (first) "localhost" to your domain if not accessed from same computer.
    Adust the "map=" path to absolute path for your wms file.
    Change the "LAYERS=" parameter to the "MAP"'s highest-level "NAME" in the wms.map file. (eg, Nations) links http://localhost/mapserv?map=/var/www/localhost/mapserver/wms.map&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=Nations&STYLES=&SRS=EPSG:4326&BBOX=-173.537,35.8775,-11.9603,83.8009&WIDTH=400&HEIGHT=300&FORMAT=image/png You should now see a partial map of North America.
  5. The WMS server should now be usable to display your maps in apps, like Cesium. Cesium is a free html5 based 3D map veiwer. To use it with your WMS server, download it, extract it to your nginx's root document directory, and edit the HelloWorld.html file as below. Comment out original viewer creation line, and add relacement.
    		//comment out the original viewer
    		//var viewer = new Cesium.Viewer('cesiumContainer');
    		
    		// Add a new WMS type viewer connecting to your WMS server
    		// need baseLayerPicker and geocoder as false to prevent pulling in default map layers (Bing)
    		var viewer = new Cesium.Viewer('cesiumContainer',{
    			imageryProvider : new Cesium.WebMapServiceImageryProvider({
    				url : '/mapserv?map=/var/www/localhost/mapserver/wms.map',
    				layers : 'Nations'
    			}),
    			baseLayerPicker : false,
    			geocoder : false
    		});
    
    Then go to the link via your browser, editing localhost and the path as appropriate. Note, do not open the file directly via a file manager, it needs to come through your web server (nginx). links http://localhost/Cesium/Apps/HelloWorld.html

Basic Improvements

  1. A lot of the information for this guide(s) is based on the doumentation on mapserver.org. For further information on using mapserver.org, see their website and documentation.
  2. Edit nginx configuration file to convert alias for map, instead of using including full path in GET parameter.
  3. NOTE: having "&mode=map" will break wms requests to mapserv, giving map (or bad gateway error)
* NOTE: this is just to get something visible, not a finished or secure product.


© 2014 Eric Marvin. All rights reserved.