Mercator Cartography on Ubuntu 24.04 on Azure User Guide
Overview
This guide covers the deployment and configuration of Mercator on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. Mercator is an open source application for mapping the cartography of an information system, following the approach published by ANSSI, the French national cybersecurity agency. Security, risk and architecture teams use it as a single place to describe what a system is made of and how the parts relate: business processes and the applications that support them, application modules and services, logical and physical servers, databases and the information they hold, networks and network equipment, sites and buildings, and the security controls and risks attached to each. Mercator renders those relationships as cartography diagrams, so a complex estate becomes something a team can see, review and keep current.
The image installs Mercator 2026.06.28 from the official upstream source, nginx and PHP 8.4 FPM to serve it, MariaDB from Ubuntu 24.04 to hold the cartography data, and Graphviz to render the diagrams, and wires them all together. Unattended security upgrades are configured to keep the server patched on your running VM.
One appliance, four components. nginx and php8.4-fpm serve the application on port 80, mariadb holds every application, server, network and risk you record, and Graphviz turns the inventory into diagrams. MariaDB is bound to 127.0.0.1:3306 and PHP FPM listens on a Unix socket, so neither is ever exposed to the network. Port 80 is the only reachable surface.
A Laravel deployment done properly. Mercator is a Laravel application, and the document root is the framework's public/ directory and nothing above it. The application source, its vendored dependencies, the database migrations and above all .env — which holds this VM's application key and database password — live outside any URL the web server can address. On top of that, only the framework front controller is permitted to execute PHP, so a file placed anywhere else in the web root is refused rather than run.
Security by design — no shared administrator credential ships in the image. Mercator's database seeder normally creates a documented default administrator (admin@admin.com / password). Rather than shipping that live and hoping you change it, this image ships no .env, no application key and no database schema at all — so that default account does not exist anywhere in the image. On the very first boot of every VM a one shot service generates a unique Laravel APP_KEY, a unique database password and a unique administrator password, creates the database schema, rotates the seeded administrator to your per instance password, and then proves the new password signs in through the real login form and that admin@admin.com/password and other common guesses do not, before writing /root/mercator-credentials.txt (mode 0600, root only).
Why the per instance application key matters. APP_KEY is Laravel's session, cookie and encryption signing material. If it were baked into the image, every customer of that image would share it, and anyone holding the image could forge a signed session for anyone else's instance. Here it is generated on your VM, for your VM.
The instance cannot serve an unprovisioned VM. nginx and php8.4-fpm are each gated on a bootstrap marker that first boot writes only after every credential is in place and the seeded administrator has been rotated. Until that marker exists systemd skips those units entirely, so there is no window in which a half provisioned instance — or the seeded default login — is reachable. The units are still enabled, so the application comes straight back after a reboot.
What is included:
-
Mercator 2026.06.28 served by nginx and PHP 8.4 FPM, with the Laravel
public/directory as the only web root -
MariaDB (
mariadb.service) holding the cartography data, bound to loopback, and Graphviz rendering the diagrams -
An inventory covering processes, applications, modules, services, logical and physical servers, databases, information, networks, VLANs, sites and buildings, with relationships modelled between them
-
Automatic cartography diagram generation, a data protection (GDPR) view, a security controls and maturity model with reports, a documents library, and a REST API with configurable rate limiting
-
Local accounts with roles and fine grained permissions, and optional LDAP or Keycloak single sign on against your own directory
-
A per instance application key, database password and administrator password generated on first boot and documented in
/root/mercator-credentials.txt(0600), with the seeded default administrator rotated and proven dead
Prerequisites
-
Active Azure subscription, SSH public key, VNet and subnet in the target region
-
Subscription to the Mercator listing on Azure Marketplace
-
Network Security Group rules allowing TCP 22 (administration) and TCP 80 (the application) from the networks that need them
-
A registered domain if you want your team to reach the instance by name rather than by IP address, plus access to your DNS provider
Step 1: Deploy from the Azure Portal
Search Mercator in Marketplace, select the cloudimg publisher, and click Create. Choose Standard_B2s or larger. Configure the Network Security Group to allow TCP 80 for the application from your own networks and TCP 22 for administration from your administrative networks only. The database and the PHP runtime stay on loopback and are never exposed.
Step 2: Deploy from the Azure CLI
RG="mercator-prod"; LOCATION="eastus"; VM_NAME="mercator"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/mercator-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az vm create \
--resource-group "$RG" --name "$VM_NAME" \
--image "$GALLERY_IMAGE_ID" \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values "$SSH_KEY" \
--public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 80 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1002
Step 3: First boot and your credentials
On first boot the image generates this VM's application key, database password and administrator password, creates the database schema, rotates the seeded administrator to your per instance password, opens the bootstrap gate, starts the web server, verifies the new credentials work and the defaults are rejected, and writes /root/mercator-credentials.txt. This completes within a minute or two. SSH in as azureuser and read the details:
sudo cat /root/mercator-credentials.txt
The file is mode 0600 and owned by root, so only a privileged user can read it. It contains the instance URL, the administrator login and password, and the database name, user and password.
Step 4: Confirm the appliance is running
All three services should report active. ss confirms the application is on port 80 while MariaDB is bound to loopback only, and the response headers carry no server version banner.
systemctl is-active mariadb.service php8.4-fpm.service nginx.service
php -r 'echo "PHP ".PHP_VERSION."\n";'
mysql --version
nginx -v
dot -V
ss -tlnp | grep -E ':(80|3306) ' | sed 's/users:.*//' | sort
curl -sI http://127.0.0.1/login | head -4

Step 5: Sign in to your instance
Browse to http://<your-vm-public-ip>/ and you are redirected to the sign in page. Enter the login admin@admin.com and the password from the credentials file.

You can prove the same sign in from the command line. This uses the per instance password from the credentials file to complete a real login through the form, then checks that the seeded default and other common passwords are refused:
sudo /usr/local/sbin/mercator-login-check.sh admin@admin.com '<MERCATOR_ADMIN_PASSWORD>' && echo "per-VM password: ACCEPTED (correct)"
sudo /usr/local/sbin/mercator-login-check.sh admin@admin.com 'password' || echo "admin@admin.com/password: REJECTED (correct)"
sudo /usr/local/sbin/mercator-login-check.sh admin@admin.com '' || echo "blank password: REJECTED (correct)"

Step 6: The cartography dashboard
Once signed in you land on the dashboard. Down the left is the whole cartography model, grouped into views: the GDPR view, the Ecosystem view, the Business view of the information system, the Applications view, the Administration view, and the views of logical and physical infrastructure. The main panel shows the maturity levels of your cartography and a breakdown by domain — both zero on a fresh instance, and both filling in as you record your estate.

Step 7: Change the administrator password
The first thing to do after signing in is set your own password. Open Preferences in the top bar and choose your profile, then use the change password form. Enter the per instance password from the credentials file as the current password and choose a new one.
Mercator stores passwords as bcrypt hashes, so the new password is never recoverable from the database. Once you have changed it, the copy in /root/mercator-credentials.txt is stale — keep the file for the database password, or remove the administrator password line from it.
Step 8: Map your first application
Cartography starts with the inventory. Open Applications view → Applications and click the add button. Give the application a name and, when you have them, link the entities, processes, application services, databases and logical servers it depends on. Save it and it appears in the application inventory.

The same objects are available for every layer of the model: record your entities and processes in the business view, your logical and physical servers in the infrastructure views, and your networks and equipment in the ecosystem view. Each object can be linked to the others, and those links are what the diagrams draw.
Step 9: Generate a cartography diagram
This is what Mercator is for. Open Applications view → Applications cartography and Mercator renders the applications you have recorded as a diagram, drawn by Graphviz, with the relationships between them as edges. The Rendu selector switches between the Graphviz layout engines (dot, fdp, osage, circo) so you can pick the layout that reads best for your estate, and the diagram can be exported.

The other views generate their own diagrams the same way — the ecosystem map, the network map, the physical infrastructure map — so as your inventory grows, the cartography grows with it.
Step 10: Run a maturity report
Under the Tools and report menus, Mercator scores the maturity of your cartography against its model and produces reports you can use in an audit or a steering committee. The maturity gauges on the dashboard (Step 6) summarise the same data. As you record more of your estate and link the objects together, the maturity levels rise, giving you a measurable picture of how complete and current your cartography is.
Step 11: Configure mail so password reset works
A fresh instance has no working mail transport, so password reset email is not delivered until you configure one. Edit the MAIL_ values in /var/www/mercator/.env — MAIL_HOST, MAIL_PORT, MAIL_USERNAME, MAIL_PASSWORD, MAIL_FROM_ADDRESS — to point at your SMTP server, then clear the cached configuration:
sudo -u www-data php /var/www/mercator/artisan config:clear
Keep the file's ownership and permissions as they are — it is root:www-data mode 0640 on purpose, because it holds this VM's application key and database password.
Step 12: Enable LDAP or Keycloak single sign on
Mercator can authenticate against your own directory. LDAP and Keycloak both ship disabled in this image. To enable LDAP, set LDAP_ENABLED=true in /var/www/mercator/.env and fill in LDAP_HOST, LDAP_PORT, the bind LDAP_USERNAME and LDAP_PASSWORD, and LDAP_USERS_BASE_DN for your directory; LDAP_FALLBACK_LOCAL=true keeps local logins working alongside it. To enable Keycloak single sign on, set KEYCLOAK_ENABLED=true and fill in KEYCLOAK_CLIENT_ID, KEYCLOAK_CLIENT_SECRET, KEYCLOAK_BASE_URL, KEYCLOAK_REALM and KEYCLOAK_REDIRECT_URI. After editing .env, clear the cached configuration:
sudo -u www-data php /var/www/mercator/artisan config:clear
Step 13: Use your own domain and add TLS
Point an A record at the VM's public IP, then set APP_URL in /var/www/mercator/.env to https://your.domain. For TLS, the simplest path is a certificate from Let's Encrypt with the nginx plugin, which edits the shipped nginx site in place and reloads it. Replace <your-domain> with your fully qualified domain:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain> --redirect --agree-tos -m admin@<your-domain> -n
After certbot has installed the certificate, set APP_FORCE_HTTPS=true in .env and clear the cache so every generated URL uses HTTPS.
Step 14: How the security model works
The image ships no .env, no application key and no database schema, so the seeded default administrator does not exist in it. nginx and php8.4-fpm are gated on a bootstrap marker that first boot writes only after your per instance secrets exist and the seeded administrator has been rotated. Until then, systemd skips the serving units and nothing is reachable.
grep -E 'ConditionPathExists|After=' /etc/systemd/system/nginx.service.d/cloudimg-bootstrap-gate.conf
ls -l /var/lib/cloudimg/
systemctl is-enabled php8.4-fpm.service nginx.service mercator-firstboot.service

The document root is the Laravel public/ directory and nothing above it, and only the front controller executes PHP. You can confirm nothing above public/ is reachable over HTTP:
grep -E '^\s+root ' /etc/nginx/sites-available/mercator
for p in /.env /config/app.php /vendor/autoload.php /artisan; do
printf '%-28s HTTP %s\n' "$p" "$(curl -s -o /dev/null -w '%{http_code}' -m 10 http://127.0.0.1$p)"
done
curl -s -o /dev/null -w '/login HTTP %{http_code}\n' http://127.0.0.1/login

Step 15: Back up your instance
The whole state of your cartography is in the MariaDB database plus the .env file. Take a consistent dump on a schedule and copy it somewhere off the VM (Azure Blob Storage, for example):
TS="$(date +%F-%H%M)"
DB_PASS="$(sudo sed -n 's/^mercator.db.password=//p' /root/mercator-credentials.txt)"
sudo mysqldump --single-transaction -u mercator_user -p"$DB_PASS" mercator > "/tmp/mercator-$TS.sql"
echo "wrote /tmp/mercator-$TS.sql"
Keep a copy of /var/www/mercator/.env with the backup: it holds the application key that signs your sessions and the database password, so restoring the database without it would invalidate existing sessions.
Step 16: Keeping Mercator up to date
The operating system keeps itself patched through unattended upgrades. For Mercator itself, cloudimg publishes refreshed images as upstream releases new versions; the supported upgrade path is to deploy the new image and restore your database into it, which keeps the appliance hardening intact. cloudimg support can help you plan and carry out an upgrade.
Troubleshooting
The site does not load. Check that first boot finished: systemctl is-active mercator-firstboot.service should report active, and /var/lib/cloudimg/mercator-firstboot.done should exist. If first boot is still running, wait a minute and retry. If it failed, sudo journalctl -u mercator-firstboot.service shows why.
The serving units are inactive. nginx and php8.4-fpm are gated on /var/lib/cloudimg/mercator-bootstrap-ready. If that marker is missing, first boot has not completed — the units are meant to stay inactive until it does.
I cannot sign in. Read the current password from /root/mercator-credentials.txt. If you have already changed it and lost the new one, reset it with sudo -u www-data php /var/www/mercator/artisan tinker and update the admin@admin.com user's password, or contact cloudimg support.
Diagrams do not render. Confirm Graphviz is installed with dot -V; the cartography views call dot to draw the diagrams.
A change to .env had no effect. Clear the cached configuration with sudo -u www-data php /var/www/mercator/artisan config:clear.
Support
cloudimg provides 24/7 technical support for this Mercator image by email (support@cloudimg.co.uk) and live chat, with a one hour average response time for critical issues. We help with first boot and credentials, rotating the administrator password, the cartography model and diagram generation, the security controls and maturity reports, LDAP and Keycloak single sign on against your own directory, mail delivery, domain and TLS setup, the REST API, database backup and restore, performance tuning and version upgrades. For billing or subscription changes, contact support@cloudimg.co.uk.
Mercator is free software licensed under the GNU General Public License version 3. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.