Deploying QGIS Server with Systemd

By Friday November 23rd, 2018GIS

QGIS Server, like other map engines such as MapServer, is a FastCGI application. FastCGI itself is a binary protocol for interfacing interactive programs – QGIS Server is our case — with a web/HTTP server.

There are many ways to deploying a FastCGI application. The QGIS Server documentation shows a number of ways to deploying QGIS Server.

It shows how to use Apache with its mod_fcgid module. It also shows how to use NGINX with its ngx_http_fastcgi_module module, and using either fcgiwrap or spawn-fcgi as the FastCGI Server responsible for setting up the listening socket and actually spawning the QGIS Server process(es).

This blog presents yet another way to deploying QGIS Server. The method presented here is based 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 than Systemd. It’s meant to be simple, yet robust and efficient for production deployments.

How it works

Systemd is much more than an init process. It provides a full-featured init system, with unique capabilities. Our method to deploying QGIS Server relies on two Systemd units: a Socket unit and a Service unit.

Our QGIS Server Socket unit defines and creates a file system socket, a.k.a. a Unix socket, which will be used by the web server, NGINX in our case, to start and communicate with QGIS Server. The Socket unit is configured with Accept=false, meaning that the calls to the accept() system call are delegated to the process created by the Service unit.

The QGIS Server Socket unit is associated with a Service unit, the QGIS Server Service unit. That 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 is configured using StandardInput=socket in the Service unit configuration.

So, using a Socket unit, combined with the StandardInput=socket setting in the Service unit configuration, we have everything we need for deploying QGIS Server, with “just” Systemd!

But there’s one little problem though. With just one Socket unit and one Service unit we just have one QGIS Server process. In production, for performance reasons, you will want to have multiple QGIS Server processes running, at least one per CPU core. Again, we can count on Systemd: Service Templates to the rescue! See the examples in the following section for more detail.

The Systemd files

The Socket unit configuration is located in /etc/systemd/system/qgis-server@.socket, which is actually a template. Its content looks like this:

[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

The Service unit configuration is located in /etc/systemd/system/qgis-server@.service. Its content looks like this:

[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

Note that the QGIS Server environment variables are defined in a separate file, /etc/qgis-server/env. This is what it looks like in my case:

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

The NGINX configuration

And finally, the missing piece of the puzzle, the NGINX configuration:

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;
    }
}

See the NGINX upstream documentation for more information.

Conclusion

There are multiple ways to deploying QGIS Server as a FastCGI application. At Oslandia we often use Docker, but Docker is not always an option. For cases where Docker cannot be used relying on Systemd as described in this blog post provides for a simple, robust and high-performance technique!

Feel free to contact us at infos+data@oslandia.com if you want to know more about QGIS and QGIS Server. And please have a look at our support offering for QGIS: http://qgis.oslandia.com/.