Deployment guide

NextGIS Web 5.5

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. The resource tree, the users and permissions, and the geometry sit together in a single system you administer. This image is secure by default and ships with a working demo project.

What you get:

  • NextGIS Web 5.5.0 (GPL-3.0), a Pyramid application. It runs as a single Python worker bound to 127.0.0.1 only, served by its own single-worker WSGI server behind nginx on port 80. The version is recorded at /var/lib/sac/config/sac-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. The lightweight MapServer extension, rather than a full QGIS stack, lets the whole server fit the recommended Standard_B2s (2 vCPU / 4 GiB) with no swap.
  • PostgreSQL 16 with PostGIS 3.4, tuned for 4 GiB and listening on localhost only. NextGIS Web reads and writes the database over a local socket, and the application role authenticates by operating-system identity, so there is no database password anywhere in the image to leak.
  • No default password. NextGIS Web ships a built-in administrator account whose upstream default password is admin, and on this image that default never exists in any window. The build seeds a random build-only secret, and the capture rotates it away. The first boot of your VM then creates a unique 28-character per-VM administrator password, writes it to /root/nextgisweb-credentials.txt, and only then opens nginx.
  • 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 SecureAnyCloud 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 the tiers are tuned for it. 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 SecureAnyCloud, 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 select Review + create, followed by Create.

Step 2 - Deploy from the Azure CLI

Deploy the image from the Azure CLI. Replace the values in angle brackets with your own:

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:nextgis-web-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name nextgis-web \
  --image sac1647283583153:nextgis-web-ubuntu-24-04:default:latest \
  --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

Connect to the VM over SSH:

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. Check that all three report active:

systemctl is-active postgresql nextgisweb nginx
cat /var/lib/sac/config/sac-nextgisweb-version /var/lib/sac/config/sac-nextgisweb-mapserver-version /var/lib/sac/config/sac-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()'

Run the second command block to print the versions. They 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 comes from the distribution's own packages, inside upstream's required envelope of Python 3.12, GDAL 3.8 and PostgreSQL/PostGIS.

Step 5 - Confirm first boot completed

First boot generates the per-VM administrator password and verifies that the demo map renders end to end. Only then does it write its sentinel and open nginx. If the sentinel is present, all of that succeeded.

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

nginx itself carries ConditionPathExists=/var/lib/sac/data/nextgisweb-bootstrap-ready. First boot writes this marker only after the per-VM administrator password has been set. NextGIS Web is therefore never 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.

Read it from the credentials file:

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.

Step 7 - Confirm the health endpoint

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

curl -s http://127.0.0.1/healthz

The endpoint 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. They cannot be reached from the network, so nginx cannot be bypassed.

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

Port 80 listens on all interfaces. Ports 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 does not necessarily draw anything, because a blank tile is still a valid PNG. The image ships a self-test that checks the content, not the status code. The self-test does the following:

  • Signs in with the per-VM password
  • Renders the demo layer server-side and asserts that 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
  • Confirms that the service is still alive afterwards

On success, it prints OK and nothing else:

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"

You can see the same evidence by hand. NextGIS Web accepts HTTP Basic Auth, so the following block does three things. It reads the per-VM password from the credentials file. It counts the demo features through the feature API. It 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 these results:

  • unauth : 403: the anonymous visitor is refused, because the demo map requires signing in.
  • wrongpw : 401: Basic Auth rejects a bad password.
  • authed : 200: the correct password reaches the resource.

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 repeat 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. This proves that the pixels vary, so 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. That is what a genuinely blank render looks like.

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.

Step 11 - Open the bundled demo web map

After you sign in, open the SecureAnyCloud demo web map (resource 6). NextGIS Web draws the map with a layer tree on the left, holding 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. The MapServer extension renders them server-side through the web map's image layer adapter. The OpenStreetMap basemap is a default background layer that the viewer fetches live from OpenStreetMap. It is not data stored in the image.

Toggle layers with the checkboxes. Pan and zoom with the controls or the scroll wheel. Each movement re-renders the vector layers server-side at the new scale.

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. It holds the SecureAnyCloud 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. Choose Create resource to add layers, styles, web maps and OGC services.

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.

Select a row to open that feature. The toolbar lets you search, filter, add, edit and delete features, and export the layer.

Step 14 - Publish WMS and WFS services for desktop GIS

NextGIS Web serves OGC WMS and WFS through service resources that you create. Each one points at the layers you want to expose, so you publish exactly what you intend, not 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.

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

To replace the demo with your own data, use the same three-resource pattern that the demo is built from:

  • 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.
  • 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.
  • 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 are kept on the image as a worked example. You can adapt them to script your own resources. /usr/local/lib/sac/make-demo.py writes the demo GeoJSON. /usr/local/lib/sac/seed-demo.py loads it through the REST API and assembles the web map.

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. Choose Groups to place the account 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 lives on a dedicated Azure data disk at /srv/nextgisweb, not on the OS disk. This covers the NextGIS Web file store and the entire PostgreSQL cluster. You can snapshot and grow the disk 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. This confirms that the database sits on the data disk alongside the file store.

To grow the disk, resize it 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. Without TLS, sessions and credentials cross the network in clear text.

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. 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. Preview the pending updates with:

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. To upgrade, follow these steps:

  • Follow the project's upgrade notes for the target release.
  • Upgrade the package inside that environment.
  • Run the database migrations with nextgisweb migration.
  • 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

SecureAnyCloud provides 24/7 support for this image. For questions about the image, contact SecureAnyCloud support. For questions about NextGIS Web itself, see the NextGIS documentation.

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. SecureAnyCloud is not affiliated with, endorsed by or sponsored by any of them.

Deploy on Azure

Launch NextGIS Web 5.5 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure