Applications Azure

NextGIS Web 5.5 on Ubuntu 24.04 on Azure User Guide

| Product: NextGIS Web 5.5 on Ubuntu 24.04 LTS on Azure

Overview

NextGIS Web is an open-source Web GIS server. You upload vector and raster data, style it, and assemble web maps that render in the browser with a layer tree, feature identification, attribute tables and search. The same data is served as standard OGC endpoints - WMS and WFS - so desktop GIS clients such as QGIS and ArcGIS read straight from the server. Everything lives in one PostgreSQL and PostGIS database plus a file store, so the resource tree, the users and permissions, and the geometry sit together in a single system you administer.

NextGIS Web is a Pyramid application. On this image it runs as a single Python worker bound to 127.0.0.1 only, behind nginx on port 80, and reads and writes a PostgreSQL 16 / PostGIS 3.4 database over a local socket. It renders a vector layer to a map image with the lightweight MapServer render extension rather than a full QGIS stack, which is what lets the whole server fit the recommended Standard_B2s (2 vCPU / 4 GiB) with no swap.

Security is designed in rather than bolted on. NextGIS Web ships a built-in administrator account whose upstream default password is admin; on this image that default never exists in any window. The build seeds a random build-only secret, the capture rotates it away, and the first boot of your VM mints a unique 28-character administrator password, writes it to a root-only file, and only then opens nginx. The PostgreSQL role authenticates by operating-system identity over a local socket, so there is no database password anywhere in the image to leak. Backed by 24/7 cloudimg support.

The bundled cloudimg demo web map rendered in the NextGIS Web viewer: a 3x3 graticule of named region polygons with depot points, drawn server-side by the MapServer extension

What is included:

  • NextGIS Web 5.5.0 (GPL-3.0) served by its own single-worker WSGI server behind nginx, with the version recorded at /etc/cloudimg-nextgisweb-version
  • The nextgisweb_mapserver 3.1.0 render extension (MapServer / mapscript 8.0.1), so a demo vector layer renders server-side without a resident QGIS process
  • PostgreSQL 16 with PostGIS 3.4, tuned for 4 GiB, listening on localhost only and authenticating the application role by operating-system identity (no password)
  • A per-VM administrator password generated on the first boot of your VM and written to /root/nextgisweb-credentials.txt
  • A working demo project - two vector layers (nine named region polygons, nine depot points), a MapServer style each, and a web map framed on them - rendering out of the box
  • /usr/local/sbin/nextgisweb-selftest.sh, an end-to-end check that asserts the map genuinely renders, not just that a request returned 200
  • A dedicated Azure data disk mounted at /srv/nextgisweb carrying both the NextGIS Web file store and the PostgreSQL cluster
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is the recommended size and is what the tiers are tuned for; scale up if you load large raster datasets, expect heavy concurrent traffic, or add the QGIS renderer (see Maintenance). NSG inbound: allow 22/tcp from your management network, 80/tcp for NextGIS Web, and 443/tcp if you add TLS. The appliance serves plain HTTP on port 80; for production, terminate TLS with your own domain and restrict access to trusted IP ranges (see Maintenance).

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for NextGIS Web by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Review the dedicated data disk on the Disks tab, then Review + create followed by Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name nextgis-web \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard

az vm open-port --resource-group <your-rg> --name nextgis-web --port 80 --priority 1010

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm every tier is running

NextGIS Web is a three-tier appliance: PostgreSQL, the NextGIS Web application worker, and nginx. All three should report active.

systemctl is-active postgresql nextgisweb nginx
cat /etc/cloudimg-nextgisweb-version /etc/cloudimg-nextgisweb-mapserver-version /etc/cloudimg-mapserver-version
. /etc/os-release && echo "$PRETTY_NAME"
sudo -u postgres psql -tAc 'SHOW server_version'
sudo -u postgres psql -d nextgisweb -tAc 'SELECT postgis_lib_version()'

The version files record exactly what shipped: NextGIS Web 5.5.0, the nextgisweb_mapserver extension 3.1.0 and mapscript 8.0.1, on Ubuntu 24.04.4 LTS with PostgreSQL 16.14 and PostGIS 3.4.2 - every runtime component from the distribution's own packages, inside upstream's required envelope of Python 3.12, GDAL 3.8 and PostgreSQL/PostGIS.

Every tier of the NextGIS Web appliance reported active, and the exact shipped versions of NextGIS Web, the MapServer extension, the OS, PostgreSQL and PostGIS

Step 5 - Confirm first boot completed

First boot generates the per-VM administrator password, verifies the demo map renders end to end, and only then writes its sentinel and opens nginx. If the sentinel is present, all of that succeeded.

test -f /var/lib/cloudimg/nextgisweb-firstboot.done && echo "first boot complete"

nginx itself carries ConditionPathExists=/var/lib/cloudimg/nextgisweb-bootstrap-ready, a marker that first boot writes only after the per-VM administrator password has been set - so there is no boot in which NextGIS Web is reachable on port 80 before a unique credential exists.

Step 6 - Retrieve your per-VM administrator password

The image contains no usable account: the upstream default administrator/admin never exists in it. Your administrator password was generated on this VM, on its first boot, and exists nowhere else.

sudo cat /root/nextgisweb-credentials.txt

The file is 0600 root:root and lists NGW_ADMIN_USERNAME (administrator), NGW_ADMIN_PASSWORD (a 28-character random string) and NGW_URL. Store the password somewhere safe. NextGIS Web accepts this credential both at the web sign-in form and as HTTP Basic Auth for the REST and OGC APIs.

The per-VM administrator credentials generated at first boot, root-only at 0600, and the unauthenticated health endpoint returning ok

Step 7 - Confirm the health endpoint

/healthz is static, unauthenticated and served by nginx, which makes it a safe Azure Load Balancer probe target - it exposes no map data.

curl -s http://127.0.0.1/healthz

It returns ok.

Step 8 - Confirm the application is bound to loopback

nginx on port 80 is the sole network listener and the security boundary. The NextGIS Web worker and PostgreSQL are bound to 127.0.0.1 only, so they cannot be reached from the network and nginx cannot be bypassed.

sudo ss -lnt | grep -E ':(80|8080|5432) '

Port 80 listens on all interfaces; 8080 (the NextGIS Web worker) and 5432 (PostgreSQL) show 127.0.0.1 only.

Step 9 - Prove the demo map really renders

A Web GIS that returns HTTP 200 is not necessarily one that draws anything: a blank tile is still a valid PNG. The image ships a self-test that checks the content, not the status code. It signs in with the per-VM password, renders the demo layer server-side and asserts the returned image is genuinely not blank, requires the same render over an empty extent to come back blank (the honesty control), refuses a wrong password, and confirms the service is still alive afterwards. It prints OK and nothing else on success.

sudo /usr/local/sbin/nextgisweb-selftest.sh

The data behind the map lives in PostGIS. Each vector layer is a PostGIS table (plus a history table); the demo has one polygon layer and one point layer, both in EPSG:3857.

sudo -u postgres psql -d nextgisweb -c "SELECT f_table_name, type, srid FROM geometry_columns ORDER BY 1"

The end-to-end self-test printing OK, and the PostGIS geometry tables that back the demo vector layers

You can see the same evidence by hand. NextGIS Web accepts HTTP Basic Auth, so the following reads the per-VM password from the credentials file, counts the demo features through the feature API, and proves the access gate - anonymous is refused, a wrong password is refused, and only the correct password reaches the resource:

PW=$(sudo grep '^NGW_ADMIN_PASSWORD=' /root/nextgisweb-credentials.txt | cut -d= -f2-)
echo "regions : $(curl -s -u administrator:"$PW" http://127.0.0.1/api/resource/2/feature_count)"
echo "depots  : $(curl -s -u administrator:"$PW" http://127.0.0.1/api/resource/3/feature_count)"
echo "unauth  : $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/resource/6/display)"
echo "wrongpw : $(curl -s -o /dev/null -w '%{http_code}' -u administrator:wrong-pw http://127.0.0.1/resource/6/display)"
echo "authed  : $(curl -s -o /dev/null -w '%{http_code}' -u administrator:"$PW" http://127.0.0.1/resource/6/display)"

Each demo layer reports {"total_count":9}. The gate prints unauth : 403 (the anonymous visitor is refused - the demo map requires signing in), wrongpw : 401 (Basic Auth rejects a bad password) and authed : 200.

To watch a real render, ask NextGIS Web for a server-side image of the demo regions style over the extent that frames the data, then over an empty extent as a control:

PW=$(sudo grep '^NGW_ADMIN_PASSWORD=' /root/nextgisweb-credentials.txt | cut -d= -f2-)
curl -s -u administrator:"$PW" -o /tmp/ngw-map.png \
  'http://127.0.0.1/api/component/render/image?resource=4&extent=2700000,5500000,4550000,8500000&size=512,512'
file /tmp/ngw-map.png
gdalinfo -stats --config GDAL_PAM_ENABLED NO /tmp/ngw-map.png 2>/dev/null | grep -E 'Size is|StdDev'

file reports a 512x512 PNG and gdalinfo reports a non-zero standard deviation on each band - that is proof the pixels vary, i.e. a map was drawn. The same request over an extent where the layer has no features returns a fully transparent image with StdDev=0.000, which is what a genuinely blank render looks like.

The Basic Auth gate returning 403 unauthenticated, 401 for a wrong password and 200 with the per-VM password, the server-side render reporting non-zero per-band standard deviation, the empty-extent blank control at StdDev 0, and the dedicated data volume

Step 10 - Sign in to NextGIS Web

Open http://<vm-public-ip>/ in a browser and choose Sign in. Enter administrator and the password from Step 6.

The NextGIS Web sign-in page

Step 11 - Open the bundled demo web map

Signed in, open the cloudimg demo web map (resource 6). NextGIS Web draws the map with a layer tree on the left - Regions and Depots - over an OpenStreetMap basemap. The green graticule of nine named regions and the depot points are the demo's own vector features, rendered server-side by the MapServer extension through the web map's image layer adapter; the OpenStreetMap basemap is a default background layer the viewer fetches live from OpenStreetMap, not data stored in the image. Toggle layers with the checkboxes, and pan and zoom with the controls or the scroll wheel; each movement re-renders the vector layers server-side at the new scale.

The cloudimg demo web map open in the NextGIS Web viewer: the Regions and Depots layer tree, and the nine region polygons rendered server-side over an OpenStreetMap basemap

Step 12 - Browse the resource tree

Everything in NextGIS Web is a resource in a tree, and the tree is where you administer the server. Choose Resources (or open /resource/0) to see the Main resource group and its contents: the cloudimg demo web map, the default Main web map, and the Demo depots and Demo regions vector layers. Each row's action icons open the resource, its feature table, or its settings, and Create resource is how you add layers, styles, web maps and OGC services.

The NextGIS Web resource tree showing the Main resource group with the demo web map and the Demo regions and Demo depots vector layers

Step 13 - View a layer's feature data

Open Demo regions and choose Feature table to read the attributes straight from PostGIS. The nine regions - North West, North, North East, West, Central, East, South West, South and South East - each carry a name and a kind field. Selecting a row opens that feature; the toolbar lets you search, filter, add, edit and delete features, and export the layer.

The feature table of the Demo regions vector layer, listing the nine named regions read live from PostGIS

Step 14 - Publish WMS and WFS services for desktop GIS

NextGIS Web serves OGC WMS and WFS through service resources you create, each pointing at the layers you want to expose - so you publish exactly what you intend, rather than exposing every layer by default. In the resource tree, choose Create resource -> WMS service (or WFS service) inside the Main resource group, add your vector layer and its style as a service layer with a short keyname, and save. NextGIS Web assigns the new service a resource id; its OGC endpoint is then:

# WMS GetCapabilities (replace <service-id> with the WMS service's resource id)
http://<vm-public-ip>/api/resource/<service-id>/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities

# WFS GetCapabilities (replace <service-id> with the WFS service's resource id)
http://<vm-public-ip>/api/resource/<service-id>/wfs?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetCapabilities

In QGIS Desktop, choose Layer -> Add Layer -> Add WMS/WMTS Layer, create a new connection with the WMS URL above, set the authentication to Basic with username administrator and your per-VM password, then connect and add the layers. The same pattern works for Add WFS Layer with the WFS URL. Because the appliance serves plain HTTP and Basic Auth sends the credential with every request, publish OGC services only over TLS on any network you do not fully control (see Maintenance).

Step 15 - Create your own vector layer, style and web map

Replacing the demo with your own data is the same three-resource pattern the demo is built from:

  1. Create resource -> Vector layer in the Main resource group, and upload your data - a GeoJSON file, or a zipped Shapefile or GeoPackage. NextGIS Web loads it into a new PostGIS table and detects the geometry type.
  2. Create resource -> MapServer style as a child of that layer to control how it draws (fill, outline, marker), or add a raster style for imagery.
  3. Create resource -> Web map, then add your styled layer to its layer tree and set the initial extent.

Your web map is then live at /resource/<webmap-id>/display with no restart. The scripts that generate the demo - /usr/local/lib/cloudimg/make-demo.py (which writes the demo GeoJSON) and /usr/local/lib/cloudimg/seed-demo.py (which loads it through the REST API and assembles the web map) - are kept on the image as a worked example you can adapt to script your own resources.

Step 16 - Add users

NextGIS Web has its own users, groups and per-resource permissions. Open the Control panel and choose Users to add an account, then Groups to place it in a group; grant that principal access on a resource from the resource's User permissions page (the demo restricts the map to signed-in administrators, which is why the anonymous request in Step 9 was refused). The built-in guest identity represents anonymous visitors - grant it read on a resource only when you deliberately want that resource to be public. Accounts can also be created over the REST API for automation.

Step 17 - Confirm the dedicated data volume

Everything that is yours - the NextGIS Web file store and the entire PostgreSQL cluster - lives on a dedicated Azure data disk at /srv/nextgisweb, not on the OS disk, so you can snapshot and grow it independently.

df -h /srv/nextgisweb
findmnt -no SOURCE,TARGET,FSTYPE,SIZE /srv/nextgisweb
sudo -u postgres psql -tAc 'SHOW data_directory'

The 32 GiB ext4 volume mounts at /srv/nextgisweb, and PostgreSQL's data_directory is /srv/nextgisweb/postgresql/16/main - confirming the database sits on the data disk alongside the file store. To grow it, resize the disk in the Azure Portal (the VM must be deallocated), then extend the filesystem online:

sudo resize2fs /dev/disk/azure/scsi1/lun0

Maintenance

Add TLS before exposing this VM on the public internet. NextGIS Web serves plain HTTP on port 80, and HTTP Basic Auth sends the password with every request, so sessions and credentials cross the network in clear text otherwise. Point a DNS record at the VM, allow 443/tcp in the NSG, and issue a certificate.

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d gis.example.com --redirect --agree-tos -m you@example.com

Reset the administrator password. If you lose it, set a new one from the command line - this is also how you rotate it periodically.

sudo -u ngw NEXTGISWEB_CONFIG=/opt/ngw/config/config.ini \
  /opt/ngw/env/bin/nextgisweb change_password administrator 'YourNewPassword'

Back up your data. Both the resource metadata and the geometry are in PostgreSQL, and the file store (attachments, rasters, styles) is under /srv/nextgisweb/data. Dump the database and archive the file store together.

sudo -u postgres pg_dump -Fc nextgisweb > /tmp/nextgisweb.dump
sudo tar czf /tmp/nextgisweb-sdir.tgz -C /srv/nextgisweb data

Patching. Every component except NextGIS Web itself is package-managed, so ordinary updates cover PostgreSQL, PostGIS, nginx and the OS. Unattended security upgrades are enabled by default.

sudo apt-get update && sudo apt-get -s dist-upgrade | tail -3

Upgrading NextGIS Web. NextGIS Web is installed into a dedicated Python virtual environment at /opt/ngw. Follow the project's upgrade notes for the target release, upgrade the package inside that environment, run the database migrations with nextgisweb migration, and restart the worker with sudo systemctl restart nextgisweb.

Higher-quality rendering. This image renders vectors with the lightweight MapServer extension to fit Standard_B2s. If you need QGIS-quality raster WMS or web-map-to-PDF printing, add the nextgisweb_qgis extension and move to a larger VM (4 vCPU / 8 GiB or more) - the QGIS renderer pulls in the full QGIS library and needs the extra headroom.

Logs. The application worker and nginx log to the journal.

sudo journalctl -u nextgisweb -u nginx --no-pager -n 20

Support

cloudimg provides 24/7 support for this image. NextGIS Web and NextGIS are products of NextGIS; PostgreSQL and PostGIS are products of their respective projects; MapServer is a product of the MapServer project; QGIS is a product of the QGIS project. cloudimg is not affiliated with, endorsed by or sponsored by any of them. For questions about the image, contact cloudimg support. For questions about NextGIS Web itself, see the NextGIS documentation.