Skip to content

XMS Installation Manual

1. Introduction

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

There are two ways to deploy XMS:

  • From the XMS image (recommended). A pre-built qcow2/OVA virtual machine image with Docker, the XMS stack, and all dependencies preinstalled. This is how almost all XMS deployments are made — see Section 3.
  • Manual package installation (advanced). Installing the xms Debian package onto your own Ubuntu host. Use this only when the image cannot be used (for example, a hardware install or a managed-OS environment) — see Section 4.

Both methods converge on the same configuration step, xms-setup.sh, described in Section 5.

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 (already preinstalled if you use the XMS image):

  • 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 ports:

  • 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

Both IP addresses are configured on the XMS host. On the image, xms-network-setup sets them up for you. For a manual install you configure them yourself (for example via netplan). Nginx and the MQTT broker each bind to port 443 on different IPs — the two addresses must not be the same.

2.3 Xertified APR Account Key

Access to Xertified's package repository (APR) requires an account key, provided by your Xertified contact. You need it when:

  • Installing manually from the package repository (Section 4), or
  • Enabling package updates on any deployment (including the image — see xertified-repo-setup).

Have the account key ready before you start a manual install. The key is exchanged once for a client certificate/key pair that APT uses to authenticate to the repository.

2.4 External Database (Optional)

If using an external database instead of the internal PostgreSQL container:

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

The XMS image ships as a qcow2 or OVA virtual machine with Docker, the XMS Docker Compose stack (/usr/share/xms), and all dependencies preinstalled. Because the network addresses and FQDNs depend on your environment, you provide them during a short first-boot configuration.

3.1 Obtain and Import the Image

  1. Obtain the XMS image (qcow2 or OVA) from Xertified.
  2. Import it into your hypervisor. For qcow2 (libvirt/KVM), define a new VM using the qcow2 as its disk; for OVA, use your virtualization platform's "Import appliance" function (for example VMware or VirtualBox).
  3. Size the VM to meet the system requirements and attach it to the network where the two XMS IP addresses will live.

Note: Download links for the XMS image are available on the Xertified support site, support.xertified.net.

3.2 First Login and Hardening

The image includes a default user xertified with sudo privileges and temporary password authentication enabled for first login. After booting the VM:

  1. Log in as xertified using the default password listed on the Xertified support site, support.xertified.net.

  2. Change the default password:

passwd
  1. Add your SSH public key:
nano ~/.ssh/authorized_keys
  1. Remove the temporary password-auth override and restart SSH:
sudo rm /etc/ssh/sshd_config.d/99-ova-default-password.conf
sudo systemctl restart ssh
  1. Optionally remove the setup banner once you no longer need it:
rm -f /etc/motd

3.3 Configure Networking

XMS requires two static IP addresses (one for the web interface, one for the MQTT broker). The image provides a helper to configure them:

sudo xms-network-setup

This prompts for the interface, the two IPs (CIDR), gateway, and DNS servers, then writes and applies a netplan configuration. Verify with ip addr.

xms-network-setup is provided only by the image. It is not part of the xms package — on a manual install you configure host networking yourself (see Section 4).

3.4 Run Setup

With networking in place, continue to Section 5: Initial Setup:

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

4. Manual Package Installation (Advanced)

Use the image for normal deployments. The manual package path is intended for advanced scenarios (hardware installs, managed-OS environments) and assumes you are comfortable administering Ubuntu, Docker, and netplan.

4.1 Configure Host Networking

Before installing, configure the two static IP addresses on the host yourself (the xms-network-setup helper is image-only). Both must be on interfaces this host owns, and they must be different addresses — nginx and MQTT each bind port 443 on their own IP. Verify with ip addr.

4.2 Install the XMS Package

You need a Xertified APR account key for this step.

Retrieve and run the installer as root:

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

The installer:

  1. Prompts for your Xertified APR Account Key.
  2. Exchanges the key for an APT client certificate/key and configures repository access.
  3. Installs Docker and its dependencies.
  4. Installs the xms package.

When the xms package finishes installing, its post-install step creates the base configuration at /etc/xms/config/env (generating random service passwords) and prints the command to start configuration. Continue to Section 5: Initial Setup.

If xms-setup.sh later reports No usable env configuration file found, the package post-install step did not complete — for example because a .deb was installed manually with dpkg -i instead of through the installer/APT. Reinstall via the installer above, or run sudo apt-get install --reinstall xms, so the post-install step lays down /etc/xms/config/env.

5. Initial Setup with xms-setup.sh

Both deployment methods finish here. The setup tool lives at /usr/share/xms/xms-setup.sh and writes to /etc/xms, so it must be run with sudo.

5.1 Run the Setup Tool

Launch the interactive menu:

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

The --setup flag (sudo ./xms-setup.sh --setup) runs an unattended setup using a previously saved configuration. It requires an existing .config file and configured IPs, and will exit if they are absent — do not use it for a first install. Use the interactive menu below instead.

5.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. Selected from the IPs detected on the host (configured in 3.3 or 4.1).
  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.4).
  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 6.3).
  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.

5.3 Start Setup

Back in the menu, select Start setup. (This option only appears once a configuration is saved and both IPs are present on local interfaces.)

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 the xms service

On success, the script prints the XMS URL and, if you chose to create one, the xmsadmin credentials.

5.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)

5.5 Main Menu Reference

Menu options are state-dependent:

  • Configure XMS: Save/update installation settings
  • Start setup: Run setup with saved settings (appears only when configuration and both IPs are present)
  • Configure Entra ID Sync: Appears when user source is Entra ID/Azure
  • Print full system status: Runs scripts/get-status.sh

6. Advanced Configuration (Optional)

6.1 Enabling Package Updates

To receive package updates, configure APR repository access. This requires a Xertified APR account key.

  • On the image, run:
sudo xertified-repo-setup
  • On a manual install, repository access is already configured by the installer in 4.2.

Once repository access is configured, upgrade as described in 6.12.

6.2 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 these files 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

6.3 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 an Attribute Importer mapper named oid with Sync mode override Force, Claim oid, and 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.

6.4 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.

6.5 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.

6.6 Keycloak with LDAPS (Certificate Trust)

When Keycloak federates against LDAPS, Keycloak must trust the LDAP server's certificate chain. The auth-api (Keycloak) container mounts a host directory as its truststore: /etc/xms/secrets/keycloak/truststores/ on the XMS host maps to /opt/keycloak/conf/truststores in the container. Keycloak automatically loads every certificate placed in that directory into its truststore at startup, so trusting a new LDAP server is just a matter of adding a file and restarting.

  1. Export the LDAP server's root (and any intermediate) CA certificate in PEM format.
  2. Copy the certificate(s) into /etc/xms/secrets/keycloak/truststores/ on the XMS host.
  3. Restart Keycloak so it reloads the truststore:
cd /usr/share/xms
docker compose restart auth-api

Then test the LDAP bind/search from the Keycloak user-federation configuration. If the bind fails, check docker compose logs auth-api for trust-chain and hostname verification errors.

6.7 TLS Operations Notes

  • Let's Encrypt (scripts/setup-letsencrypt.sh) requires XMS_FQDN resolving publicly to the XMS host, TCP 80 reachable during the ACME challenge, and 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.

6.8 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

6.9 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.

6.10 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.

6.11 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.

6.12 Upgrading XMS

Package updates require repository access to be configured.

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.

7. Troubleshooting

7.1 Installation Issues

  • No usable env configuration file found when running xms-setup.sh — The package post-install step did not create /etc/xms/config/env. This usually means a .deb was installed manually with dpkg -i instead of via the installer/APT. Reinstall with the installer or sudo apt-get install --reinstall xms.

  • xms-setup.sh fails to write files or change services — Run it with sudo; it writes to /etc/xms and manages the xms systemd service.

  • sudo xms-network-setup: command not found — That helper exists only on the image. On a manual install, configure the two host IPs yourself (see 4.1).

  • Start setup is missing in the menu — Run Configure XMS first and save the configuration, ensure both XMS and MQTT IPs are configured on local interfaces, and on the image 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:
sudo XMS_SETUP_DEBUG=1 ./xms-setup.sh --setup
  • If auto user creation fails, bootstrap manually with ./scripts/keycloak-create-user.sh, then ./scripts/xms-set-user-role.sh --email <user_email> --role superadmin

7.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

8. 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.