ZOO-Project 2.1.0 on Ubuntu 24.04 on Azure User Guide
Overview
This guide covers the deployment and use of ZOO-Project 2.1.0 on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. ZOO-Project is the OSGeo OGC Web Processing Service (WPS) and OGC API - Processes server: the ZOO-Kernel C server runs geospatial processing services and exposes them over the open OGC standards so any client can submit a processing request over HTTP and retrieve the result.
The cloudimg image compiles ZOO-Kernel 2.1.0 from a pinned upstream release with FastCGI, Python, and the GDAL / GEOS / PROJ geospatial libraries, and serves it behind nginx on port 80 through an always-on fcgiwrap FastCGI gateway. It ships the safe built-in demonstration services — a Python HelloPy service, the OGR/GEOS vector operations (Buffer, Centroid, ConvexHull, Intersection, Union, Simplify, Distance, GetArea, and more), OGR Ogr2Ogr, and the GDAL raster tools — so the server does real geospatial work the moment it boots. No external database is required for the base WPS.
What is included:
- ZOO-Project 2.1.0 (ZOO-Kernel, compiled from the pinned upstream
rel-2.1.0source) - Both interfaces served on port 80: classic OGC WPS 1.0.0 / 2.0.0 at
/cgi-bin/zoo_loader.cgiand OGC API - Processes at/ogc-api/ - GDAL, GEOS and PROJ geospatial libraries; the OGR/GEOS vector-processing services and GDAL raster services
zoo-fcgiwrap.service(FastCGI gateway, runs aswww-data) andnginx.service, both auto-starting on bootzoo-project-firstboot.servicesystemd oneshot that resolves the VM public IP and writes endpoint info on first customer boot- Unauthenticated
/healthzendpoint for load-balancer probes - Ubuntu 24.04 LTS base with the latest security patches applied at build time
- Azure Linux Agent for seamless cloud integration and SSH key injection
- 24/7 cloudimg support with a guaranteed 24 hour response SLA
Prerequisites
- An active Azure subscription
- A subscription to the ZOO-Project 2.1.0 on Ubuntu 24.04 listing on Azure Marketplace
- An SSH public key for VM authentication
- A virtual network and subnet in the target region
Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) for evaluation and light processing workloads. Scale up for larger geometries, raster operations, or higher request concurrency.
A note on security: the base ZOO-Project WPS server is a public processing API with no login — this matches upstream, and the cloudimg image never invents a credential. Only the fixed, safe built-in demo services are enabled; the arbitrary process-deployment (Deploy/Replace/Undeploy) endpoints are deliberately excluded. Restrict inbound access to port 80 with a network security group so that only your client networks can reach the processing endpoints.
Step 1: Deploy from the Azure Portal
Navigate to Marketplace in the Azure Portal, search for ZOO-Project, select the cloudimg publisher entry, and click Create.
On the Networking tab attach a network security group that allows inbound TCP 22 from your management IP range and TCP 80 from your client networks (the WPS and OGC API endpoints). Click Review + create, wait for validation, then Create. Deployment takes around two minutes.
Step 2: Deploy from the Azure CLI
az vm create \
--resource-group my-geo-rg \
--name zoo-project \
--image <cloudimg-zoo-project-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
# Open port 80 to your client network:
az vm open-port --resource-group my-geo-rg --name zoo-project --port 80 --priority 900
Step 3: Confirm the service is healthy
SSH in as azureuser and confirm the FastCGI gateway and nginx are both active and the health endpoint responds:
systemctl is-active nginx zoo-fcgiwrap
curl -s -o /dev/null -w 'health: HTTP %{http_code}\n' http://localhost/healthz
Expected output:
active
active
health: HTTP 200

The per-VM endpoint URLs (resolved to this VM's public IP on first boot) are recorded at /root/zoo-project-info.txt.
Step 4: WPS GetCapabilities
Ask the server which processing services it offers, using the classic OGC WPS 1.0.0 interface:
curl -s "http://localhost/cgi-bin/zoo_loader.cgi?service=WPS&version=1.0.0&request=GetCapabilities" -o /tmp/wps-capabilities.xml
head -8 /tmp/wps-capabilities.xml
The response is a wps:Capabilities XML document. List the advertised process identifiers:
curl -s "http://localhost/cgi-bin/zoo_loader.cgi?service=WPS&version=1.0.0&request=GetCapabilities" \
| grep -oE '<ows:Identifier>[^<]+' | sed 's/<ows:Identifier>/ - /'

Step 5: Execute a process
HelloPy is the simplest process — a Python service that takes a literal string input and returns a welcome message. It proves the Execute pipeline end to end:
curl -s "http://localhost/cgi-bin/zoo_loader.cgi?service=WPS&version=1.0.0&request=Execute&Identifier=HelloPy&DataInputs=a=cloudimg&RawDataOutput=Result"
Expected output:
Hello cloudimg from Python World !
Buffer is a real geospatial process built on GDAL and GEOS. Give it a GeoJSON polygon and a buffer distance and it returns the buffered geometry as GML. Here a 10×10 square is buffered outward by 1 unit (note the resulting bounding box -1,-1 to 11,11):
curl -s -G "http://localhost/cgi-bin/zoo_loader.cgi" \
--data-urlencode 'service=WPS' \
--data-urlencode 'version=1.0.0' \
--data-urlencode 'request=Execute' \
--data-urlencode 'Identifier=Buffer' \
--data-urlencode 'DataInputs=InputPolygon={"type":"Polygon","coordinates":[[[0,0],[0,10],[10,10],[10,0],[0,0]]]}@mimeType=application/json;BufferDistance=1' \
--data-urlencode 'RawDataOutput=Result' -o /tmp/buffer-result.gml
head -12 /tmp/buffer-result.gml

Step 6: OGC API - Processes (JSON REST)
ZOO-Project also serves the modern OGC API - Processes interface at /ogc-api/. List the processes collection as JSON:
curl -s http://localhost/ogc-api/processes \
| python3 -c 'import sys,json; d=json.load(sys.stdin); print("numberTotal:", d["numberTotal"]); [print(" -", p["id"]) for p in d["processes"][:12]]'
Retrieve a single process description:
curl -s http://localhost/ogc-api/processes/Buffer \
| python3 -c 'import sys,json; d=json.load(sys.stdin); print(d["id"], "-", d["title"])'

The OGC API landing document (http://localhost/ogc-api/) links the conformance, processes and jobs resources, and each process is also available as HTML at /ogc-api/processes/<id>.html.
Step 7: Configuration and customisation
- Server configuration:
/usr/lib/cgi-bin/main.cfg— the ZOO-Kernel main configuration (server metadata, temp paths, GDAL/PROJ environment). On first boot the advertised server host is set to this VM's public IP. - Services directory:
/usr/lib/cgi-bin/— each process is a.zcfgdescriptor plus its service implementation (.zoshared object for the compiled OGR/GDAL services,.pyfor Python services). Add your own services here by dropping in a.zcfgand its implementation. - FastCGI gateway:
zoo-fcgiwrap.servicerunsfcgiwrapaswww-dataonunix:/run/zoo-project/fcgiwrap.sock; nginx proxies to it. Restart withsudo systemctl restart zoo-fcgiwrap nginxafter changing services. - Web server:
/etc/nginx/sites-available/zoo-projectroutes/cgi-bin/,/ogc-api/,/healthzand the static landing page.
Support
cloudimg images come with 24/7 support and a guaranteed 24 hour response SLA. Contact support@cloudimg.co.uk for assistance. For ZOO-Project itself, see the upstream documentation at zoo-project.org.