18.2.1. Getting Started

18.2.1.1. Installation on Debian-based systems

We will give a short and simple installation how-to for a minimal working configuration on Debian based systems (including Ubuntu and derivatives). However, many other distributions and OSs provide packages for QGIS Server.

Requirements and steps to add official QGIS repositories to install current QGIS Server on a Debian based system are provided in QGIS installers page.

Note

In Ubuntu you can use your regular user, prepending sudo to commands requiring admin permissions. In Debian you can work as admin (root), without using sudo.

We strongly suggest installing the LTR version.

Once the chosen repository is configured, installation is simply done with:

apt install qgis-server
# if you want to install server plugins, also:
apt install python-qgis

You can test the installation by running:

/usr/lib/cgi-bin/qgis_mapserv.fcgi

If you get the following output, the server is correctly installed:

QFSFileEngine::open: No file name specified
Warning 1: Unable to find driver ECW to unload from GDAL_SKIP environment variable.
Warning 1: Unable to find driver ECW to unload from GDAL_SKIP environment variable.
Warning 1: Unable to find driver JP2ECW to unload from GDAL_SKIP environment variable.
Warning 1: Unable to find driver ECW to unload from GDAL_SKIP environment variable.
Warning 1: Unable to find driver JP2ECW to unload from GDAL_SKIP environment variable.
Content-Length: 206
Content-Type: text/xml; charset=utf-8

<ServiceExceptionReport version="1.3.0" xmlns="https://www.opengis.net/ogc">
 <ServiceException code="Service configuration error">Service unknown or unsupported</ServiceException>
</ServiceExceptionReport>

Let’s add a sample project. You can use your own, or one from Training demo data:

mkdir /home/qgis/projects/
cd /home/qgis/projects/
wget https://github.com/qgis/QGIS-Training-Data/archive/v2.0.zip
unzip v2.0.zip
mv QGIS-Training-Data-2.0/exercise_data/qgis-server-tutorial-data/world.qgs .
mv QGIS-Training-Data-2.0/exercise_data/qgis-server-tutorial-data/naturalearth.sqlite .

Of course, you can use your favorite GIS software to open this file and take a look on the configuration and available layers.

18.2.1.1.1. HTTP Server configuration

To run QGIS server you need a web server. Recommended choices are Apache or Nginx.

Note

In the following, please replace localhost with the name or IP address of your server.

18.2.1.1.1.1. Apache

Install Apache and mod_fcgid:

apt install apache2 libapache2-mod-fcgid
a2enmod cgi

QGIS Server is now available at http://localhost/. To check, type in a browser:

http://localhost/cgi-bin/qgis_mapserv.fcgi?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities

If you get something like:

<WMS_Capabilities version="1.3.0" xsi:schemaLocation="http://www.opengis.net/wms http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd http://www.qgis.org/wms http://localhost/cgi-bin/qgis_mapserv.fcgi?SERVICE=WMS&REQUEST=GetSchemaExtension">
...

the server is correctly installed and responds through Apache.

Let’s now add mod_fcgid configuration directives for QGIS Server:

# Tell QGIS Server instances to use a specific display number for xvfb
# necessary for printing, see below
FcgidInitialEnv DISPLAY ":99"
# Activate QGIS log (different from apache logs)
FcgidInitialEnv QGIS_SERVER_LOG_FILE /var/log/qgis/qgisserver.log
FcgidInitialEnv QGIS_SERVER_LOG_LEVEL "0"
FcgidInitialEnv QGIS_SERVER_LOG_STDERR "1"
FcgidInitialEnv QGIS_DEBUG 1
# Add a default QGIS project
SetEnv QGIS_PROJECT_FILE /home/qgis/projects/world.qgs
# QGIS_AUTH_DB_DIR_PATH must lead to a directory writeable by www-data
FcgidInitialEnv QGIS_AUTH_DB_DIR_PATH "/var/www/qgis-server/qgisserverdb/"
FcgidInitialEnv QGIS_AUTH_PASSWORD_FILE "/var/www/qgis-server/qgisserverdb/qgis-auth.db"

<IfModule mod_fcgid.c>
# Longer timeout for WPS... default = 40
FcgidIOTimeout 120
FcgidMaxRequestLen 26214400
FcgidConnectTimeout 60
</IfModule>

Note

See the mod_fcgid documentation for more information on the Fcgid parameters used. And see below (xvfb) to understand when and why the DISPLAY environment variable needs to be set.

These directives can be added either to /etc/apache2/mods-enabled/fcgid.conf for a system-wide configuration, or to a specific Apache VirtualHost, if you want QGIS server to be available only for that address; the default one is available at /etc/apache2/sites-available/000-default.conf.

<Location /qgisserver>
 SetHandler fcgid-script
 FcgidWrapper /usr/lib/cgi-bin/qgis_mapserv.fcgi virtual
 Options +ExecCGI -MultiViews +FollowSymLinks
 Require all granted
</Location>

Then create all the needed directories with appropriate permissions:

mkdir -p /var/log/qgis/
chown www-data:www-data /var/log/qgis
mkdir -p /var/www/qgis-server/qgisserverdb/
chown www-data:www-data /var/www/qgis-server/qgisserverdb/

Now restart Apache for the new configuration to be taken into account:

systemctl restart apache2

QGIS Server is now available at http://localhost/qgisserver. To check, type in a browser, as in the simple case:

http://localhost/qgisserver/cgi-bin/qgis_mapserv.fcgi?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities

18.2.1.1.1.2. NGINX

You can also use QGIS Server with NGINX. Unlike Apache, NGINX does not automatically spawn FastCGI processes. The FastCGI processes are to be started by something else.

On Debian-based systems, you can use spawn-fcgi or fcgiwrap to start and manage the QGIS Server processes. Official Debian packages exist for both.

Warning

fcgiwrap is easier to set up than spawn-fcgi, because it’s already wrapped in a Systemd service. But it also leads to a solution that is much slower than using spawn-fcgi. With fcgiwrap a new QGIS Server process is created on each request, meaning that the QGIS Server initialization process, which includes reading and parsing the QGIS project file, is done on each request. With spawn-fcgi, the QGIS Server process remains alive between requests, resulting in much better performance. For that reason, spawn-fcgi is recommended for production use.

Another option is to rely on Systemd, the init system for GNU/Linux that most Linux distributions use today. One of the advantages of this method is that it requires no other components or processes. It’s meant to be simple, yet robust and efficient for production deployments.

Install NGINX:

apt install nginx
18.2.1.1.1.2.1. spawn-fcgi

If you want to use spawn-fcgi, the first step is to install the package:

apt install spawn-fcgi

Then, introduce the following block in your NGINX server configuration:

location /qgisserver {
    gzip           off;
    include        fastcgi_params;
    fastcgi_pass   unix:/var/run/qgisserver.socket;
}

And restart NGINX to take into account the new configuration:

service nginx restart

Finally, considering that there is no default service file for spawn-fcgi, you have to manually start QGIS Server in your terminal:

spawn-fcgi -s /var/run/qgisserver.socket \
                -U www-data -G www-data -n \
                /usr/lib/cgi-bin/qgis_mapserv.fcgi

todo: Add instructions to add a spawn-fcgi.service

QGIS Server is now available at http://localhost/qgisserver.

Note

With the above command spawn-fcgi spawns only one QGIS Server process. To use more than one QGIS Server process you can combine spawn-fcgi with the multiwatch tool, which is also packaged in Debian.

Of course, you can add an init script (like a qgis-server.service file with systemd) to start QGIS Server at boot time or whenever you want.

todo: Add instructions to add a qgis-server.service

18.2.1.1.1.2.2. fcgiwrap

Using fcgiwrap is much easier to setup than spawn-fcgi but it’s much slower. You first have to install the corresponding package:

apt install fcgiwrap

Then, introduce the following block in your NGINX server configuration:

1
2
3
4
5
6
  location /qgisserver {
      gzip           off;
      include        fastcgi_params;
      fastcgi_pass   unix:/var/run/fcgiwrap.socket;
      fastcgi_param  SCRIPT_FILENAME /usr/lib/cgi-bin/qgis_mapserv.fcgi;
  }

Finally, restart NGINX and fcgiwrap to take into account the new configuration:

service nginx restart
service fcgiwrap restart

QGIS Server is now available at http://localhost/qgisserver.

18.2.1.1.1.2.3. Configuration

The include fastcgi_params; used in previous configuration is important as it adds the parameters from /etc/nginx/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_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  REQUEST_SCHEME     $scheme;
fastcgi_param  HTTPS              $https if_not_empty;

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;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;

Of course, you may override these variables in your own configuration. For example:

include fastcgi_params;
fastcgi_param SERVER_NAME domain.name.eu;

Moreover, you can use some Environment variables to configure QGIS Server. With NGINX as HTTP Server, you have to use fastcgi_param to define these variables as shown below:

fastcgi_param  QGIS_DEBUG              1;
fastcgi_param  QGIS_SERVER_LOG_FILE    /var/log/qgis/qgisserver.log;
fastcgi_param  QGIS_SERVER_LOG_LEVEL   0;

Note

When using spawn-fcgi, you may directly define environment variables before running the server. For example: export QGIS_SERVER_LOG_FILE=/var/log/qgis/qgisserver.log

18.2.1.1.1.2.4. Systemd

This method to deploy QGIS Server relies on two Systemd units:

The QGIS Server Socket unit defines and creates a file system socket, used by NGINX to start and communicate with QGIS Server. The Socket unit has to be configured with Accept=false, meaning that the calls to the accept() system call are delegated to the process created by the Service unit. It is located in /etc/systemd/system/qgis-server@.socket, which is actually a template:

[Unit]
Description=QGIS Server Listen Socket (instance %i)

[Socket]
Accept=false
ListenStream=/var/run/qgis-server-%i.sock
SocketUser=www-data
SocketGroup=www-data
SocketMode=0600

[Install]
WantedBy=sockets.target

Now enable and start sockets:

systemctl enable [email protected]
systemctl start [email protected]
systemctl enable [email protected]
systemctl start [email protected]
systemctl enable [email protected]
systemctl start [email protected]
systemctl enable [email protected]
systemctl start [email protected]

The QGIS Server Service unit defines and starts the QGIS Server process. The important part is that the Service process’ standard input is connected to the socket defined by the Socket unit. This has to be configured using StandardInput=socket in the Service unit configuration located in /etc/systemd/system/qgis-server@.service:

[Unit]
Description=QGIS Server Service (instance %i)

[Service]
User=www-data
Group=www-data
StandardOutput=null
StandardError=journal
StandardInput=socket
ExecStart=/usr/lib/cgi-bin/qgis_mapserv.fcgi
EnvironmentFile=/etc/qgis-server/env

[Install]
WantedBy=multi-user.target

Now start socket service:

sudo systemctl start [email protected]

Note that the QGIS Server environment variables are defined in a separate file, /etc/qgis-server/env. It could look like this:

QGIS_PROJECT_FILE=/etc/qgis/myproject.qgs
QGIS_SERVER_LOG_STDERR=1
QGIS_SERVER_LOG_LEVEL=3

Finally, introduce the NGINX configuration for this setup:

upstream qgis-server_backend {
   server unix:/var/run/qgis-server-1.sock;
   server unix:/var/run/qgis-server-2.sock;
   server unix:/var/run/qgis-server-3.sock;
   server unix:/var/run/qgis-server-4.sock;
}

server {
   

   location /qgis {
       gzip off;
       include fastcgi_params;
       fastcgi_pass qgis-server_backend;
   }
}

Now restart NGINX for the new configuration to be taken into account:

service nginx restart

Thanks to Oslandia for sharing their tutorial.

18.2.1.1.2. Xvfb

QGIS Server needs a running X Server to be fully usable, in particular for printing. On servers it is usually recommended not to install it, so you may use xvfb to have a virtual X environment.

To install the package:

apt install xvfb

Then, according to your HTTP server, you should configure the DISPLAY parameter or directly use xvfb-run.

With Apache you just add to your Fcgi configuration (see above):

FcgidInitialEnv DISPLAY       ":99"

Create the service file:

sh -c \
"echo \
'[Unit]
Description=X Virtual Frame Buffer Service
After=network.target

[Service]
ExecStart=/usr/bin/Xvfb :99 -screen 0 1024x768x24 -ac +extension GLX +render -noreset

[Install]
WantedBy=multi-user.target' \
> /etc/systemd/system/xvfb.service"

Enable, start and check the status of the xvfb.service:

systemctl enable xvfb.service
systemctl start xvfb.service
systemctl status xvfb.service

Now restart Apache for the new configuration to be taken into account:

systemctl restart apache2

With NGINX and spawn-fcgi using xvfb-run:

xvfb-run /usr/bin/spawn-fcgi -f /usr/lib/cgi-bin/qgis_mapserv.fcgi \
                             -s /tmp/qgisserver.socket \
                             -G www-data -U www-data -n

The other option is to start a virtual X server environment with a specific display number thanks to Xvfb:

/usr/bin/Xvfb :99 -screen 0 1024x768x24 -ac +extension GLX +render -noreset

Then we just have to set the DISPLAY environment variable in the HTTP server configuration. For example with NGINX:

fastcgi_param  DISPLAY       ":99";

18.2.1.2. Installation on Windows

QGIS Server can also be installed on Windows systems. While the QGIS Server package is available in the 64 bit version of the OSGeo4W network installer (https://qgis.org/en/site/forusers/download.html) there is no Apache (or other web server) package available, so this must be installed by other means.

A simple procedure is the following:

../../../../_images/qgis_server_windows1.png
  • Download the OSGeo4W installer, follow the “Advanced Install” and install both the QGIS Desktop and QGIS Server packages

../../../../_images/qgis_server_windows2.png
  • Edit the httpd.conf file (C:\xampp\apache\httpd.conf if the default installation paths have been used) and make the following changes:

From:

ScriptAlias /cgi-bin/ "C:/xampp/cgi-bin/"

To:

ScriptAlias /cgi-bin/ "c:/OSGeo4W64/apps/qgis/bin/"

From:

<Directory "C:/xampp/cgi-bin">
AllowOverride None
Options None
Require all granted
</Directory>

To:

<Directory "c:/OSGeo4W64/apps/qgis/bin">
SetHandler cgi-script
AllowOverride None
Options ExecCGI
Order allow,deny
Allow from all
Require all granted
</Directory>

From:

AddHandler cgi-script .cgi .pl .asp

To:

AddHandler cgi-script .cgi .pl .asp .exe

Then at the bottom of httpd.conf add:

SetEnv GDAL_DATA "C:\OSGeo4W64\share\gdal"
SetEnv QGIS_AUTH_DB_DIR_PATH "C:\OSGeo4W64\apps\qgis\resources"
SetEnv PYTHONHOME "C:\OSGeo4W64\apps\Python37"
SetEnv PATH "C:\OSGeo4W64\bin;C:\OSGeo4W64\apps\qgis\bin;C:\OSGeo4W64\apps\Qt5\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem"
SetEnv QGIS_PREFIX_PATH "C:\OSGeo4W64\apps\qgis"
SetEnv QT_PLUGIN_PATH "C:\OSGeo4W64\apps\qgis\qtplugins;C:\OSGeo4W64\apps\Qt5\plugins"

Restart the Apache web server from the XAMPP Control Panel and open browser window to testing a GetCapabilities request to QGIS Server

http://localhost/cgi-bin/qgis_mapserv.fcgi.exe?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities

18.2.1.3. Serve a project

Now that QGIS Server is installed and running, we just have to use it.

Obviously, we need a QGIS project to work on. Of course, you can fully customize your project by defining contact information, precise some restrictions on CRS or even exclude some layers. Everything you need to know about that is described later in Configure your project.

But for now, we are going to use a simple project already configured and previously downloaded in /home/qgis/projects/world.qgs, as described above.

By opening the project and taking a quick look on layers, we know that 4 layers are currently available:

  • airports

  • places

  • countries

  • countries_shapeburst

You don’t have to understand the full request for now but you may retrieve a map with some of the previous layers thanks to QGIS Server by doing something like this in your web browser to retrieve the countries layer:

http://localhost/qgisserver?
  MAP=/home/qgis/projects/world.qgs&
  LAYERS=countries&
  SERVICE=WMS&
  REQUEST=GetMap&
  CRS=EPSG:4326&
  WIDTH=400&
  HEIGHT=200

If you obtain the next image, then QGIS Server is running correctly:

../../../../_images/server_basic_getmap.png

Fig. 18.6 Server response to a basic GetMap request

Note that you may define PROJECT_FILE environment variable to use a project by default instead of giving a MAP parameter (see Environment variables).

For example with spawn-fcgi:

export PROJECT_FILE=/home/qgis/projects/world.qgs
spawn-fcgi -f /usr/lib/bin/cgi-bin/qgis_mapserv.fcgi \
           -s /var/run/qgisserver.socket \
           -U www-data -G www-data -n

18.2.1.4. Configure your project

To provide a new QGIS Server WMS, WFS or WCS, you have to create a QGIS project file with some data or use one of your current project. Define the colors and styles of the layers in QGIS and the project CRS, if not already defined.

../../../../_images/ows_server_definition.png

Fig. 18.7 Definitions for a QGIS Server WMS/WFS/WCS project

Then, go to the QGIS Server menu of the Project ▶ Properties… dialog and provide some information about the OWS in the fields under Service Capabilities. This will appear in the GetCapabilities response of the WMS, WFS or WCS. If you don’t check checkbox Service capabilities, QGIS Server will use the information given in the wms_metadata.xml file located in the cgi-bin folder.

18.2.1.4.1. WMS capabilities

In the WMS capabilities section, you can define the extent advertised in the WMS GetCapabilities response by entering the minimum and maximum X and Y values in the fields under Advertised extent. Clicking Use Current Canvas Extent sets these values to the extent currently displayed in the QGIS map canvas. By checking checkbox CRS restrictions, you can restrict in which coordinate reference systems (CRS) QGIS Server will offer to render maps. It is recommended that you restrict the offered CRS as this reduces the size of the WMS GetCapabilities response. Use the signPlus button below to select those CRSs from the Coordinate Reference System Selector, or click Used to add the CRSs used in the QGIS project to the list.

If you have print layouts defined in your project, they will be listed in the GetProjectSettings response, and they can be used by the GetPrint request to create prints, using one of the print layout layouts as a template. This is a QGIS-specific extension to the WMS 1.3.0 specification. If you want to exclude any print layout from being published by the WMS, check checkbox Exclude layouts and click the signPlus button below. Then, select a print layout from the Select print layout dialog in order to add it to the excluded layouts list.

If you want to exclude any layer or layer group from being published by the WMS, check checkbox Exclude Layers and click the signPlus button below. This opens the Select restricted layers and groups dialog, which allows you to choose the layers and groups that you don’t want to be published. Use the Shift or Ctrl key if you want to select multiple entries. It is recommended that you exclude from publishing the layers that you don’t need as this reduces the size of the WMS GetCapabilities response which leads to faster loading times on the client side.

You can receive requested GetFeatureInfo as plain text, XML and GML. Default is XML, text or GML format depends the output format chosen for the GetFeatureInfo request.

If you wish, you can check checkbox Add geometry to feature response. This will include the bounding box for each feature in the GetFeatureInfo response. See also the WITH_GEOMETRY parameter.

As many web clients can’t display circular arcs in geometries you have the option to segmentize the geometry before sending it to the client in a GetFeatureInfo response. This allows such clients to still display a feature’s geometry (e.g. for highlighting the feature). You need to check the checkbox Segmentize feature info geometry to activate the option.

You can also use the GetFeatureInfo geometry precision option to set the precision of the GetFeatureInfo geometry. This enables you to save bandwidth when you don’t need the full precision.

If you want QGIS Server to advertise specific request URLs in the WMS GetCapabilities response, enter the corresponding URL in the Advertised URL field.

Furthermore, you can restrict the maximum size of the maps returned by the GetMap request by entering the maximum width and height into the respective fields under Maximums for GetMap request.

If one of your layers uses the Map Tip display (i.e. to show text using expressions) this will be listed inside the GetFeatureInfo output. If the layer uses a Value Map for one of its attributes, this information will also be shown in the GetFeatureInfo output.

18.2.1.4.2. WFS capabilities

In the WFS capabilities area you can select the layers you want to publish as WFS, and specify if they will allow update, insert and delete operations. If you enter a URL in the Advertised URL field of the WFS capabilities section, QGIS Server will advertise this specific URL in the WFS GetCapabilities response.

18.2.1.4.3. WCS capabilities

In the WCS capabilities area, you can select the layers that you want to publish as WCS. If you enter a URL in the Advertised URL field of the WCS capabilities section, QGIS Server will advertise this specific URL in the WCS GetCapabilities response.

18.2.1.4.4. Fine tuning your OWS

For vector layers, the Fields menu of the Layer ▶ Layer Properties dialog allows you to define for each attribute if it will be published or not. By default, all the attributes are published by your WMS and WFS. If you don’t want a specific attribute to be published, uncheck the corresponding checkbox in the WMS or WFS column.

You can overlay watermarks over the maps produced by your WMS by adding text annotations or SVG annotations to the project file. See the Annotation Tools section for instructions on creating annotations. For annotations to be displayed as watermarks on the WMS output, the Fixed map position checkbox in the Annotation text dialog must be unchecked. This can be accessed by double clicking the annotation while one of the annotation tools is active. For SVG annotations, you will need either to set the project to save absolute paths (in the General menu of the Project ▶ Properties… dialog) or to manually modify the path to the SVG image so that it represents a valid relative path.