MaxKey on Ubuntu 24.04 on Azure User Guide
Overview
MaxKey is a leading, enterprise-grade IAM / IDaaS (Identity and Access Management) and single sign-on server. It gives your organisation one central place to authenticate people and to control which applications they can reach: a user signs in once to MaxKey and then moves between connected applications without signing in again. It speaks the standard protocols the rest of your estate already understands, including OAuth 2.x / OpenID Connect, SAML 2.0, CAS, JWT and SCIM 2.0.
The cloudimg image runs the official MaxKey topology as a Docker Compose stack: a MySQL identity datastore, the SSO/authentication backend and the management backend (two Spring Boot services), the end-user SSO portal and the management console (two Angular front ends), and an nginx reverse proxy that presents everything on a single HTTP port. Every secret is generated uniquely on the first boot of every VM - the administrator password, the MySQL database password and the JSON Web Token signing key are each rotated per instance, and every seeded demo account is disabled - so no shared or default credential is ever live. Backed by 24/7 cloudimg support.
What is included:
- The official MaxKey 4.1.12 stack running under Docker (
maxkey-mysql,maxkey,maxkey-mgt,maxkey-frontend,maxkey-mgt-frontend,maxkey-nginx), every image pinned so it never silently upgrades - A single reverse proxy on port
80: the management console at/maxkey-mgt/and the end-user SSO portal at/maxkey/ - A per-VM
adminaccount generated on first boot, its password recorded in a root-only file, so every VM is secured independently - The MaxKey JWT signing key and MySQL password regenerated per VM on first boot, replacing the shipped defaults
- MySQL bound to the internal Docker network only - just
22/tcp(SSH) and80/tcp(MaxKey) are exposed - The whole stack managed as one
maxkey.servicesystemd unit, plusdocker.service, both enabled - 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a comfortable starting size for the full stack. NSG inbound: allow 22/tcp from your management network and 80/tcp from the clients and applications that will use MaxKey. The appliance serves plain HTTP; for production put it behind your own domain and TLS.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for MaxKey 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), then add 80 after deployment. Review + create -> Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name maxkey \
--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 maxkey --port 80 --priority 1010
Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 - Confirm the stack is running
MaxKey runs as a Docker Compose stack managed by a single systemd unit. On first boot the stack rotates every secret, re-seeds a fresh identity database, seeds the per-VM admin account and points its URLs at your VM's address; the multi-container stack can take a couple of minutes to become fully healthy after the VM is first created.
systemctl is-active maxkey.service docker.service
docker compose -f /var/lib/maxkey/docker-compose.yml ps --format '{{.Name}}\t{{.Status}}'
All six containers should report Up.

Step 5 - Retrieve your per-VM admin credentials
The first boot writes a unique administrator password to a root-only file. Read it over SSH:
sudo cat /root/maxkey-credentials.txt
The file records the console URL, the admin username and the generated password. It is mode 0600, owned by root.

Step 6 - Verify the login and that no default credential survives
The first boot rotates the built-in admin password away from MaxKey's shipped default and neutralises every seeded demo account, so no known credential is ever live. You can prove this from the shell: the per-VM password authenticates and returns a Bearer token, while the shipped default admin / maxkey is rejected.
B=http://127.0.0.1/maxkey-mgt-api
STATE=$(curl -s $B/login/get | python3 -c 'import sys,json;print(json.load(sys.stdin)["data"]["state"])')
curl -s -X POST "$B/login/signin?_allow_anonymous=true" -H 'Content-Type: application/json' \
-d "{\"username\":\"admin\",\"password\":\"<MAXKEY_ADMIN_PASSWORD>\",\"authType\":\"normal\",\"state\":\"$STATE\",\"code\":\"\",\"otpCaptcha\":\"\"}"
A response with "code":0 and a token means the per-VM admin authenticated.

Step 7 - Confirm the pinned images and exposed ports
The stack images are pinned to 4.1.12, and only SSH and HTTP are exposed on the VM - MySQL listens on the internal Docker network only, never on the host.
docker compose -f /var/lib/maxkey/docker-compose.yml images --format '{{.Repository}}:{{.Tag}}' | sort -u
sudo ss -tlnp '( sport = :80 or sport = :22 )'

Step 8 - Sign in to the management console
Browse to http://<vm-public-ip>/maxkey-mgt/ and sign in as admin with the password from Step 5.

About the CAPTCHA field: this image ships with console CAPTCHA validation disabled so the console is usable out of the box, but the sign-in form still shows a CAPTCHA box - you may type any characters into it. To enforce a real CAPTCHA in production, set
LOGIN_CAPTCHA=truein themaxkeyandmaxkey-mgtservice environments in/var/lib/maxkey/docker-compose.ymland runsudo systemctl restart maxkey.service.
After signing in you land on the dashboard, which summarises your directory - organisations, users and registered applications - and recent access activity.

Step 9 - Register a single sign-on application
The Applications section is where you connect the apps your users log in to. MaxKey supports OAuth 2.0 / OIDC, SAML 2.0, CAS, JWT and form-based sign-on; choose Add, pick the protocol your application speaks, and fill in its redirect URI or metadata. Your users then reach that application from the end-user portal without signing in again.

Step 10 - Manage identities
Under Identities you manage the organisations, users and groups that make up your directory. Create your own users here (the seeded demo accounts ship with their passwords disabled), organise them into departments and groups, and assign application access. MaxKey can also synchronise identities from LDAP or Active Directory and over SCIM 2.0.

Step 11 - Production hardening
- TLS: the appliance serves plain HTTP on port 80. For production, place it behind your own domain and a TLS-terminating load balancer or reverse proxy, and update
SERVER_DOMAINin/var/lib/maxkey/.envto that host name, then runsudo systemctl restart maxkey.serviceso single sign-on redirect URLs use it. - CAPTCHA: re-enable console CAPTCHA validation as described in Step 8 for internet-facing deployments.
- SAML signing keystore: MaxKey ships a default SAML IdP keystore. Before you enable any SAML relying-party integrations, replace the keystore and its password with your own so SAML assertions are signed with a key unique to you.
- Backups: the identity database lives in the
maxkey_mysql_dataDocker volume. Include it (and/var/lib/maxkey/.env, which holds your per-VM secrets) in your backup routine.
Managing the service
# Restart the whole stack
sudo systemctl restart maxkey.service
# Stop / start
sudo systemctl stop maxkey.service
sudo systemctl start maxkey.service
# Follow logs for a component
docker compose -f /var/lib/maxkey/docker-compose.yml logs -f maxkey-mgt
Support
Every cloudimg image is backed by 24/7 support. If you have any questions about this MaxKey image, contact us at support@cloudimg.co.uk.