Security Azure

MaxKey on Ubuntu 24.04 on Azure User Guide

| Product: MaxKey on Ubuntu 24.04 LTS on Azure

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 admin account 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) and 80/tcp (MaxKey) are exposed
  • The whole stack managed as one maxkey.service systemd unit, plus docker.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.

MaxKey systemd unit active and all six containers running

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.

The per-VM admin credentials written on first boot, root-only

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.

The per-VM admin authenticates while the shipped default is rejected

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 )'

The MaxKey images pinned to 4.1.12 with only SSH and HTTP exposed

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.

The MaxKey management console sign-in page

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=true in the maxkey and maxkey-mgt service environments in /var/lib/maxkey/docker-compose.yml and run sudo 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.

The MaxKey management dashboard

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.

Registered single sign-on applications across OAuth, SAML, CAS and JWT

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.

Identity and user management in the MaxKey console

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_DOMAIN in /var/lib/maxkey/.env to that host name, then run sudo systemctl restart maxkey.service so 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_data Docker 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.