This project provides multiple deployment methods for a QGIS Server-based web mapping application. It offers flexible options to deploy both the server backend and various client applications, allowing users to select the approach that best fits their infrastructure and complexity requirements.
The project consists of:
- A QGIS Server backend to serve geospatial data via WMS
- Multiple frontend implementations (Angular and simple HTML/JS)
- Multiple deployment methods (Kubernetes and Docker Compose)
| Directory | Purpose |
|---|---|
| projects | QGIS project files (.qgs) and related styling/templates |
| data | Geographic data files (Natural Earth shapefiles) |
| deployment-k8s | Kubernetes deployment configurations and scripts |
| deployment-docker | Docker Compose deployment configurations |
| frontend-angular | Angular-based web mapping application |
| frontend-simple | Simple HTML/JS/CSS web mapping application |
| config | Configuration files used across deployments |
Deploys both QGIS Server and a sophisticated Angular-based web mapping client in a Kubernetes cluster.
Key Characteristics:
- Full-featured reactive UI using Angular
- Containerized deployment of both backend and frontend
- More sophisticated UI capabilities
- Better code organization for complex features
- Uses pre-built Docker images
Deploys QGIS Server alongside a lightweight HTML/JS/CSS web client in a Kubernetes cluster.
Key Characteristics:
- Uses ConfigMaps to deploy the frontend directly
- Same QGIS Server configuration as the Angular option
- Simpler implementation with vanilla JavaScript
- No need to build Docker images for the frontend
- Easier to make quick changes to the frontend
Deploys both QGIS Server and the lightweight web client using Docker Compose.
Key Characteristics:
- Simplest deployment option
- Suitable for local development or simple production environments
- No Kubernetes requirements
- Uses the same frontend as the "Kubernetes Simple" option
- Configured entirely through Docker Compose
cd deployment-k8s
./deploy.shThis script:
- Creates namespace
qgis-systemin your Kubernetes cluster - Checks and installs ingress-nginx controller if needed
- Creates ConfigMaps for NGINX config, entrypoint script, etc.
- Creates ConfigMap from the QGIS project file
- Deploys QGIS Server using the specified Docker image
- Deploys Angular viewer using its Docker image
- Applies services and ingress configurations
- Waits for pods to be ready
The deployment can be accessed at http://qgis.local/ once complete.
cd deployment-k8s
./deploy.simple.shThis script:
- Creates namespace
qgis-systemin your Kubernetes cluster - Checks and installs ingress-nginx controller if needed
- Creates ConfigMaps for NGINX config, entrypoint script, etc.
- Creates ConfigMap from the QGIS project file
- Creates ConfigMaps from the HTML, JS, and CSS files in frontend-simple
- Deploys QGIS Server using the specified Docker image
- Deploys viewer using deployment.simple.yaml that mounts the ConfigMaps
- Applies services and ingress configurations
- Waits for pods to be ready
The deployment can be accessed at http://qgis.local/ once complete.
cd deployment-docker
docker compose up -dThis command:
- Starts the QGIS Server container with appropriate environment variables
- Mounts volumes for projects and data
- Sets up an Apache container to serve the simple frontend
- Configures network connections between services
The deployment can be accessed at:
- Frontend:
http://localhost:8081/ - QGIS Server direct access:
http://localhost:8080/qgis/qgis_mapserv.fcgi
When using the Kubernetes deployments, you'll need to configure your local system to resolve qgis.local to your machine. This is done by modifying your hosts file:
-
Linux/Mac users: Edit
/etc/hostswith sudo privileges:sudo nano /etc/hosts
Add the following line:
127.0.0.1 qgis.local -
Windows users: Edit
C:\Windows\System32\drivers\etc\hostswith administrative privileges:- Open Notepad as Administrator
- Open the file at
C:\Windows\System32\drivers\etc\hosts - Add the following line:
127.0.0.1 qgis.local
Once configured, you can access the application at http://qgis.local/ in your browser after deployment.
A sophisticated web mapping application built using Angular.
Features:
- Reactive UI updates through Angular signals
- Component-based architecture
- Modern build pipeline with Angular CLI
- TypeScript for improved code safety and tooling
- Advanced state management capabilities
A lightweight web mapping application built using vanilla JavaScript, HTML, and CSS.
Features:
- Minimal dependencies
- Simple codebase
- Easy to modify and extend
- Direct inclusion in deployments via ConfigMaps (K8s) or volume mounts (Docker Compose)
- OpenLayers for map rendering
| Variable | Description | Default |
|---|---|---|
QGIS_PROJECT_FILE |
Path to the QGIS project file | /etc/qgisserver/world_map.qgs |
QGIS_SERVER_LOG_LEVEL |
Logging verbosity (0-3) | 2 |
QGIS_SERVER_ENABLE_GETMAP |
Enable GetMap requests | true |
QGIS_SERVER_TRUST_LAYER_METADATA |
Trust layer metadata | true |
QGIS_SERVER_WMS_ENABLED |
Enable WMS service | true |
QGIS_SERVER_ALLOW_GETMAP |
Allow GetMap requests | true |
QGIS_SERVER_IGNORE_BAD_LAYERS |
Ignore problematic layers | true |
The QGIS Server container runs with an NGINX server configured to proxy requests to the QGIS Fast CGI application:
location ~ ^/qgis/qgis_mapserv\.fcgi {
include fastcgi_params;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_param SCRIPT_FILENAME /usr/lib/cgi-bin/qgis_mapserv.fcgi;
# QGIS Server configurations
fastcgi_param QGIS_PROJECT_FILE /etc/qgisserver/world_map.qgs;
fastcgi_param QGIS_SERVER_LOG_LEVEL 2;
fastcgi_param QGIS_DEBUG 1;
# Further configuration...
}In the Docker Compose deployment, Apache proxies requests to the QGIS Server:
<IfModule mod_proxy.c>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass "/qgis/qgis_mapserv.fcgi" "http://qgis-server:80/qgis/qgis_mapserv.fcgi?"
ProxyPassReverse "/qgis/qgis_mapserv.fcgi" "http://qgis-server:80/qgis/qgis_mapserv.fcgi"
</IfModule>The project includes several map layers from Natural Earth data:
| Layer | Description | Short Name |
|---|---|---|
| Countries | World countries | Countries |
| Places | Populated places | Places |
| Urban Areas | Urban areas | Urban |
| Disputed Areas | Disputed territories | Disputed |
These are defined in the QGIS project file (world_map.qgs) and can be selected from the dropdown in the web interface.
| Feature | K8s Angular | K8s Simple | Docker Compose |
|---|---|---|---|
| Frontend | Angular | HTML/JS | HTML/JS |
| Backend | QGIS Server | QGIS Server | QGIS Server |
| Complexity | Highest | Medium | Lowest |
| Infrastructure Required | Kubernetes cluster | Kubernetes cluster | Docker only |
| Frontend Packaging | Docker image | ConfigMaps | Volume mounts |
| Development Experience | Angular workflow | Simple file edits | Simple file edits |
| Scaling Capabilities | High | Medium | Limited |
| Update Process | Rebuild image | Update ConfigMaps | Update files |
| URL Structure | http://qgis.local/ |
http://qgis.local/ |
http://localhost:8081/ |
-
Proxy Error 500
- Ensure the question mark is present in the Apache proxy configuration
- Check that all QGIS Server environment variables are properly set
- Verify the data paths in the QGIS project file
-
NGINX Configuration Errors
- If you see "Device or resource busy" errors, ensure volumes are properly mounted
- Check that nginx-qgis.conf is properly configured and accessible
-
Pod Startup Issues
- Check pod logs:
kubectl logs -n qgis-system <pod-name> - Verify ConfigMap contents:
kubectl describe configmap -n qgis-system <configmap-name>
- Check pod logs:
-
Ingress Issues
- Ensure ingress-nginx controller is running
- Verify
qgis.localis in your /etc/hosts file pointing to 127.0.0.1


