Skip to content

XMS Installation Manual

1. Introduction

This guide covers installation and initial configuration of XMS, plus optional advanced configuration and troubleshooting.

2. Prerequisites

2.1 System Requirements

  • Hardware: Minimum 2 CPU cores, 8 GB RAM, 40 GB storage (60 GB recommended for production)
  • Architecture: amd64 / x86_64
  • OS: Ubuntu 22.04 LTS recommended (modern Debian-based systems with systemd are typically suitable)

Required software:

  • If you install using the official XMS OVA, these are already preinstalled.
  • Docker Engine (docker)
  • Docker Compose (docker compose)
  • jq
  • certbot (only if you plan to use Let's Encrypt)

2.2 Network and DNS Requirements

  • Two static IPv4 addresses on the XMS host:
  • One for XMS HTTPS/UI/API
  • One for MQTT TLS
  • Two DNS records:
  • XMS_FQDN (for example xms.example.com)
  • MQTT_FQDN (for example mqtt.example.com)
  • Firewall:
  • 443/TCP open to XMS IP
  • 443/TCP open to MQTT IP
  • 80/TCP open to XMS IP only if using Let's Encrypt
  • 22/TCP for SSH administration

2.3 External Database (Optional)

If using external database instead of internal PostgreSQL container:

  • Use a PostgreSQL version supported by your XMS release
  • Enable extension:
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
  • Ensure XMS host can reach the database host

2.4 Acquiring and Installing XMS

Retrieve and run the installer script:

wget https://share.xertified.net/install/xms_install_ubuntu_release.sh
chmod 750 xms_install_ubuntu_release.sh
./xms_install_ubuntu_release.sh

You will be prompted for your account key. After successful validation, package repository access is configured and XMS package installation starts.

3. Installation and Setup

3.1 Run the Setup Tool

If you use the XMS OVA image, first configure networking:

sudo xms-network-setup

Then run setup:

cd /usr/share/xms
./xms-setup.sh

For unattended setup (when configuration is already saved):

./xms-setup.sh --setup

3.2 Configure XMS

From the menu, select Configure XMS. The script walks you through each setting:

  1. XMS FQDN — The domain name for the XMS web UI and API (for example xms.example.com). Must resolve to the XMS IP in DNS.
  2. XMS IP — The local IP address on this host for the XMS interface. Verify with ip addr.
  3. MQTT FQDN — The domain name for the MQTT service (for example mqtt.example.com). Must resolve to the MQTT IP.
  4. MQTT IP — The local IP for MQTT. Must be a different IP than XMS.
  5. Database typeInternal uses a bundled PostgreSQL container (recommended for most deployments). External connects to your own PostgreSQL instance (see 2.3).
  6. Database FQDN — Only prompted if you selected External.
  7. TLS source — How the HTTPS certificate for Nginx is obtained. Options: Let's Encrypt (automatic, requires the XMS FQDN to be publicly reachable on port 80), Generate self-signed (quick for lab/testing, causes browser warnings), Issue via XMS CA (uses the built-in CA, requires CA_TYPE to be configured), or File (provide paths to your own certificate and key files).
  8. User sourceKeycloak manages users locally (recommended for first install). Microsoft Entra ID requires additional Azure configuration (see 4.4).
  9. Create initial XMS userYes creates an xmsadmin account with a generated password. Choose No only if you plan to bootstrap users manually.

After confirming the summary, configuration is written to .env/.config and related templates are updated.

3.3 Start Setup

Back in the menu, select Start setup.

The setup process will:

  1. Validate external DB credentials (if external DB)
  2. Apply required file permissions
  3. Verify database access
  4. Configure Keycloak realm (if needed)
  5. Issue internal service certificates (if needed)
  6. Configure/import TLS certificate according to selected TLS source
  7. Optionally create xmsadmin, enable group sync, and assign superadmin
  8. Apply final permissions
  9. Enable and restart xms service

3.4 Validate Installation

Run:

systemctl status xms
cd /usr/share/xms
docker compose ps

Then verify:

  1. Core services are running/healthy (nginx, auth-api, xot-api, directory-sync, mqtt, dashboard, plus postgres if internal DB)
  2. Open https://<XMS_FQDN>
  3. Log in using created credentials (or external IdP login)

3.5 Main Menu Reference

Menu options are state-dependent:

  • Configure XMS: Save/update installation settings
  • Start setup: Run setup with saved settings
  • Configure Entra ID Sync: Appears when user source is Entra ID/Azure
  • Print full system status: Runs scripts/get-status.sh

4. Advanced Configuration (Optional)

4.1 OVA First-Login Hardening

If you deployed from OVA, complete these hardening steps after initial setup:

  1. Change the default password.
  2. Add your SSH public key to ~/.ssh/authorized_keys.
  3. Remove temporary password-auth override and restart SSH:
sudo rm /etc/ssh/sshd_config.d/99-ova-default-password.conf
sudo systemctl restart ssh
  1. Remove /etc/motd setup banner if no longer needed.

For package updates on OVA deployments, configure APR repository access:

sudo xertified-repo-setup

4.2 Release vs Testing Package Track (Automation)

If you install via Ansible automation, you can choose repository track:

  • Release track:
ansible-playbook -K playbook_setup_xms.yml
  • Testing track:
ansible-playbook -K playbook_setup_xms.yml -e testing=true

Testing mode switches repository key/component/distribution to testing variants.

4.3 External CA

Default is integrated CA. If needed, configure external CA after base setup.

  • Telia Cygate (CA_TYPE=CYGATE)

  • Set CA_TYPE=CYGATE, CYGATE_URL, CYGATE_ISSUER in /etc/xms/config/env

  • Place in /etc/xms/secrets/ca-manager/:

    • cygate-issuer.pem
    • cygate-issuer-ca.pem
    • cygate-ra.pem
    • cygate-ra-key.pem
  • Net iD Portal (CA_TYPE=NIP)

  • Set CA_TYPE=NIP, NIP_FQDN in /etc/xms/config/env

  • Set SECMAKER_PW for the Net iD Portal API certificate .pfx

4.4 Identity Source and Synchronization

External Identity Providers (OIDC)

If you want users to authenticate via an external provider (for example Microsoft Entra ID) instead of local Keycloak users, configure an OIDC Identity Provider in Keycloak:

  1. Open the Keycloak Administration Console (https://<XMS_FQDN>/idp), select the xms realm, and navigate to Identity ProvidersOpenID Connect v1.0.
  2. Fill in Client ID, Client Secret, and Discovery endpoint from your provider's app registration.
  3. Under Advanced, set Scopes to openid profile.
  4. Go to the Mappers tab, click Add mapper, and create a mapper with:
  5. Name: oid
  6. Sync mode override: Force
  7. Mapper type: Attribute Importer
  8. Claim: oid
  9. User Attribute Name: oid

For Azure-specific app registration setup, see Microsoft Entra ID Integration for XMS.

Keycloak Login Theme

When using an external identity provider, change the login theme so users are redirected to the provider instead of seeing a username/password form (which could cause them to enter external credentials into Keycloak).

In the Keycloak Administration Console, select the xms realm → Realm settingsThemes tab, and set the login theme to xertified.

Do not change the login theme for the master realm — this will break admin access.

If you are authenticating users directly in Keycloak (no external provider), leave the theme at its default value keycloak.

4.5 User and Role Bootstrapping

If you are not relying on the auto-created xmsadmin, you need to create users and assign roles manually.

Creating Users via Keycloak UI

  1. Retrieve Keycloak admin credentials:
cat /etc/xms/secrets/keycloak/admin-credentials
  1. Navigate to https://<XMS_FQDN>/idpAdministration Console and log in as xadmin.

  2. Switch to the xms realm (top-left dropdown). All XMS user management must be done in this realm.

  3. Create groups via the Groups menu (create groups first so you can assign membership during user creation).

  4. Navigate to UsersAdd user. Assign at least one group — users without group membership are not synchronized by directory-sync.

  5. Go to the Credentials tab and set the password. Set Temporary to off for a permanent password.

Creating Users via Script

cd /usr/share/xms/scripts
./keycloak-create-user.sh --username 'operator1' --group 'Operators' --password 'ComplexP@ss!' --email 'op1@domain.tld'

This creates the user in Keycloak but does not assign an XMS role — see below.

Setting User Roles

Users synced from Keycloak initially receive the role none, which prevents login. You must assign a role for the user to have access.

If you already have a working superadmin account, change roles in the XMS UI: Users → select user → XMS Access dropdown.

Otherwise, use the script:

cd /usr/share/xms
scripts/xms-set-user-role.sh --email admin@example.com --role superadmin
scripts/xms-set-user-role.sh --userid f4a5b1c2-d3e4-f5a6-b7c8-d9e0f1a2b3c4 --role admin

Available roles: none, admin, superadmin. The script handles starting directory-sync if needed and waits for the user to appear in the database. For external databases, ensure psql is installed on the XMS host.

4.6 Ticket Lifetime Tuning (LEASE_SETTINGS)

If your deployment uses customized ticket lifetimes, tune your lease/ticket settings in your XMS runtime configuration (commonly exposed as LEASE_SETTINGS in XMS configuration).

Guidelines:

  • Shorter lifetimes improve revocation responsiveness
  • Longer lifetimes improve resilience during temporary control-plane outages
  • Validate changes in a staging environment before production

After changing ticket/lease settings, restart XMS services and verify policy/ticket behavior from a test client.

4.7 Keycloak with LDAPS (Certificate Trust)

When Keycloak federates against LDAPS, Keycloak must trust the LDAP server certificate chain.

Typical approach:

  1. Export LDAP server root/intermediate certificates
  2. Import them into the trust store used by auth-api/Keycloak runtime
  3. Restart auth-api and test LDAP bind/search

If LDAPS bind fails, check docker compose logs auth-api for trust-chain and hostname verification errors.

4.8 TLS Operations Notes

  • Let's Encrypt (scripts/setup-letsencrypt.sh) requires:
  • XMS_FQDN resolving publicly to the XMS host
  • TCP 80 reachable during ACME challenge
  • certbot installed
  • File-based TLS requires valid existing certificate/key paths during configuration.
  • Issue via XMS CA is only available when CA_TYPE is configured.

4.9 Nginx IP Access Control

Restrict access to sensitive XMS endpoints by editing files in /usr/share/xms/config/nginx/:

  • access-admin.conf: Controls access to the Keycloak admin console (/idp/admin/*). Add allow <IP>; lines for trusted administrator IPs, then uncomment deny all; to enforce.
  • access-restricted.conf: Controls other restricted application paths. IPs from access-admin.conf are automatically included. Uncomment deny all; to enforce.

After modifying, reload Nginx:

cd /usr/share/xms
docker compose exec nginx nginx -s reload

4.10 Benthos Configuration

The benthos service processes or forwards MQTT messages. If enabled, ensure its configuration (/usr/share/xms/config/benthos/benthos.yaml) has the correct MQTT password — it must match MQTT_XMS_PASSWORD in your .env file.

4.11 Removing Stored Keycloak Credentials

Setup stores Keycloak admin and user credentials in /etc/xms/secrets/keycloak. These are used by helper scripts (keycloak-create-user.sh, xms-set-user-role.sh, etc.) for post-setup configuration. Once setup is complete, copy these credentials to a secure credential management system and remove them from the host. The files are not needed during normal operation, but removing them will prevent the helper scripts from functioning.

4.12 NTP

XMS has NTP enabled by default and can act as a time server for connected XoT devices. This is useful in air-gapped or restricted environments where external NTP servers are not reachable. XoT-Locks can be configured in the XMS to use the XMS as their NTP source.

4.13 Upgrading XMS

sudo apt update
sudo apt upgrade xms

The upgrade stops the XMS service, loads new Docker images, preserves configuration in /etc/xms/config/ and /etc/xms/secrets/, applies database migrations on service start, and restarts XMS.

Verify after upgrading:

systemctl status xms
docker compose ps

Check the Release Notes for version-specific upgrade notes.

5. Troubleshooting

5.1 Installation Issues

  • If Start setup is missing in the menu:

  • Run Configure XMS first and save configuration

  • Ensure both XMS and MQTT IPs are configured on local interfaces
  • For OVA deployments, run sudo xms-network-setup

  • Run status snapshot:

cd /usr/share/xms/scripts
./get-status.sh --all
  • Review setup logs (/var/log/xms-setup/, fallback /tmp)
  • Re-run setup in debug mode:
XMS_SETUP_DEBUG=1 ./xms-setup.sh --setup
  • If auto user creation fails, bootstrap manually with:
  • ./scripts/keycloak-create-user.sh
  • ./scripts/xms-set-user-role.sh --email <user_email> --role superadmin

5.2 Operational Issues

  • Check service/container state:
systemctl status xms
cd /usr/share/xms
docker compose ps
  • Check logs:
journalctl -u xms
cd /usr/share/xms
docker compose logs auth-api
docker compose logs xot-api
docker compose logs directory-sync
docker compose logs postgres
  • Re-apply permissions if file access errors appear:
/usr/share/xms/scripts/set-permissions.sh
  • Verify .env and .config for IP/FQDN/credential mismatches
  • For sync/login issues, verify group membership and assigned XMS role

6. Reference: XMS Services Overview

XMS is composed of multiple Docker services managed by systemd service xms.

Key components:

  • nginx: HTTPS entrypoint and reverse proxy
  • dashboard: Admin web interface
  • xot-api: Core backend API and business logic
  • mqtt: Mosquitto broker for device communication
  • auth-api: Keycloak-based identity/authentication
  • ca-manager: Certificate issuance and management
  • directory-sync: User/group synchronization into XMS DB
  • local-discovery (optional): Local discovery for isolated setups

Additional optional/supporting services can include postgres, mqtt-metrics-collector, and benthos.

XoT-WebAccess is a separate component deployed independently. See the XoT-WebAccess Installation Guide for details.