Gravitee Access Management on Ubuntu 24.04 on Azure User Guide
Overview
Gravitee Access Management (AM) is an open source Identity & Access Management server: an OAuth 2.0 authorization server and OpenID Connect provider with single sign-on, multi-factor and passwordless authentication, a web management console and a REST API. You define security domains, register applications (OAuth2/OIDC clients), manage users and identity providers, and issue and introspect access and ID tokens through a dedicated security-token gateway. The cloudimg image runs the official open source Docker images (management API, security-token gateway and management console), pinned to Gravitee AM 4.12.4, on a PostgreSQL backend and fronted by TLS.
This appliance ships the open source edition only - no Enterprise-Edition plugins and no licence key are used or required. It deliberately uses the fully-supported PostgreSQL (JDBC/R2DBC) backend rather than the MongoDB default. Every secret - the admin password, the database password and the token-signing secrets - is generated uniquely on the first boot of each VM, and the stock admin/adminadmin default is never shipped.
What is included:
- The official Gravitee AM 4.12.4 open source stack under Docker:
management-api(console API),gateway(OAuth2/OIDC token endpoints),management-ui(console) and PostgreSQL 16, pinned so it never silently upgrades - A PostgreSQL backend (JDBC/R2DBC) - the MongoDB default is not used; no MongoDB, Redis or Elasticsearch is present
- An nginx TLS terminator: the management console + API on
https://<vm>/(port 443) and the OAuth2/OIDC gateway onhttps://<vm>:8443/- port 80 redirects to 443 - A per-VM
adminconsole account generated on first boot - a unique password recorded in a root-only file - so every VM is secured independently;admin/adminadmindoes not work - Docker's data-root and the Compose project relocated onto a dedicated 40 GiB Azure data disk at
/var/lib/gravitee-am, so the PostgreSQL volume and certificates survive OS changes and can be resized independently - The stack managed as one
gravitee-am.servicesystemd unit, plusdocker.service, both enabled - PostgreSQL bound to the internal Docker network only - just
22/tcp(SSH),443/tcp(console) and8443/tcp(gateway) are exposed (80/tcpredirects to 443) - 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2ms (2 vCPU / 8 GiB RAM) is the recommended starting size - the two JVM services plus PostgreSQL fit comfortably; choose Standard_B4ms for heavier production use. NSG inbound: allow 22/tcp from your management network, and 443/tcp + 8443/tcp from your users. The image serves a self-signed TLS certificate generated per VM; for production, install your own certificate or front the VM with your own domain and certificate.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Gravitee Access Management 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), HTTPS (443) and custom 8443. Review the dedicated data disk on the Disks tab, then Review + create then Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name gravitee-am \
--image <marketplace-image-urn> \
--size Standard_B2ms \
--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 gravitee-am --port 443 --priority 1010
az vm open-port --resource-group <your-rg> --name gravitee-am --port 8443 --priority 1020
Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 - Confirm the stack is running
The Gravitee AM containers run under Docker as a Compose stack managed by a single systemd unit. On first boot the stack rotates every secret, recreates itself on a fresh PostgreSQL database and seeds a per-VM admin console account; the multi-container stack can take a couple of minutes to become fully healthy after the VM is created.
systemctl is-active gravitee-am.service docker.service
Both report active. List the running containers with:
sudo docker compose -f /var/lib/gravitee-am/docker-compose.yml ps

Step 5 - Retrieve your per-VM admin credentials
First boot writes a unique console admin password to a root-only file. Retrieve it:
sudo cat /root/gravitee-am-credentials.txt

Step 6 - Confirm the console is reachable over TLS
The management console is served over HTTPS on port 443 (the certificate is self-signed per VM, so -k is used here):
curl -sk -o /dev/null -w 'console: HTTP %{http_code}\n' https://localhost/
It returns HTTP 200.
Step 7 - Confirm the stock default credential is rejected
This image never ships the Gravitee admin/adminadmin default. Prove that only your per-VM password authenticates against the management API - the placeholder below is substituted with the real per-VM password from the credentials file:
echo -n 'per-VM admin password accepted: '
curl -sk -o /dev/null -w 'HTTP %{http_code}\n' -X POST -u 'admin:<GRAVITEE_ADMIN_PASSWORD>' https://localhost/management/auth/token
echo -n 'stock admin/adminadmin default: '
curl -sk -o /dev/null -w 'HTTP %{http_code}\n' -X POST -u 'admin:adminadmin' https://localhost/management/auth/token
The per-VM password returns HTTP 200; admin/adminadmin returns HTTP 401.

Step 8 - Issue and validate a real OAuth2 token
This end-to-end example authenticates to the management API, creates a security domain and a client_credentials application, waits for the gateway to publish the domain, then requests and validates a real access token. It is self-contained:
ADMIN_PASS='<GRAVITEE_ADMIN_PASSWORD>'
MGMT=https://localhost/management
GW=https://localhost:8443
TOKEN=$(curl -sk -X POST -u "admin:${ADMIN_PASS}" "$MGMT/auth/token" | jq -r .access_token)
if [ -z "$TOKEN" ] || [ "$TOKEN" = "null" ]; then
echo "Sign in first with your per-VM admin password (Step 5), then re-run this step."
exit 0
fi
OE="$MGMT/organizations/DEFAULT/environments/DEFAULT"
DID=$(curl -sk -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"quickstart","description":"quickstart demo","dataPlaneId":"default"}' "$OE/domains" | jq -r .id)
curl -sk -X PATCH -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"enabled":true}' "$OE/domains/$DID" -o /dev/null
DPATH=$(curl -sk -H "Authorization: Bearer $TOKEN" "$OE/domains/$DID" | jq -r .path)
APP=$(curl -sk -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"quickstart-service","type":"SERVICE"}' "$OE/domains/$DID/applications")
CID=$(echo "$APP" | jq -r .settings.oauth.clientId)
CSEC=$(echo "$APP" | jq -r .settings.oauth.clientSecret)
for i in $(seq 1 40); do
[ "$(curl -sk -o /dev/null -w '%{http_code}' "${GW}${DPATH}/oidc/.well-known/openid-configuration")" = "200" ] && break
sleep 3
done
curl -sk -X POST -u "${CID}:${CSEC}" -d grant_type=client_credentials "${GW}${DPATH}/oauth/token" \
| jq '{token_type, expires_in, access_token: (.access_token[0:40] + "...")}'
The gateway returns a signed JWT access token with token_type: bearer. The screenshot below shows the same flow returning a token and the introspection endpoint confirming it is active.

Step 9 - Sign in to the management console
Browse to https://<vm-public-ip>/ (accept the self-signed certificate warning, or install your own certificate). Sign in as admin with the password from Step 5.

The console opens on your security domain's dashboard, showing users and registered applications at a glance.

Open Applications to see your registered OAuth2/OIDC clients, create new ones, and manage their grant types, scopes, redirect URIs and client credentials.

Step 10 - Confirm data lives on the dedicated disk
The PostgreSQL database, the Compose project and the per-VM TLS certificate all live on a dedicated 40 GiB Azure data disk mounted at /var/lib/gravitee-am:
df -h /var/lib/gravitee-am
Creating your first application
In the console, create a security domain (Settings then General), then under Applications click Create application and pick the type that matches your client: Web for a server-side app using the authorization-code flow, Single-Page App for a browser app with PKCE, Native for mobile, or Service for machine-to-machine (client_credentials). Configure its redirect URIs, grant types and scopes, then use the OpenID Connect discovery document at https://<vm>:8443/<domain-path>/oidc/.well-known/openid-configuration to wire up your application.
Maintenance
- Logs:
sudo docker compose -f /var/lib/gravitee-am/docker-compose.yml logs -f management-api gateway - Restart:
sudo systemctl restart gravitee-am.service - OS updates: unattended-upgrades is enabled for security patches; reboot to apply kernel updates.
- Backups: snapshot the
/var/lib/gravitee-amdata disk, orpg_dumpthegraviteeamdatabase from the PostgreSQL container.
Support
This image is maintained by cloudimg with 24/7 support. For help, contact cloudimg support via the Azure Marketplace listing.