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
xmsDebian 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
systemdare typically suitable)
Required software (already preinstalled if you use the XMS image):
- Docker Engine (
docker) - Docker Compose (
docker compose) jqcertbot(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 examplexms.example.com)MQTT_FQDN(for examplemqtt.example.com)
Firewall ports:
443/TCPopen to XMS IP443/TCPopen to MQTT IP80/TCPopen to XMS IP only if using Let's Encrypt22/TCPfor 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
3. Deploying from the XMS Image (Recommended)
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
- Obtain the XMS image (qcow2 or OVA) from Xertified.
- 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).
- 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:
-
Log in as
xertifiedusing the default password listed on the Xertified support site, support.xertified.net. -
Change the default password:
passwd
- Add your SSH public key:
nano ~/.ssh/authorized_keys
- 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
- 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-setupis provided only by the image. It is not part of thexmspackage — 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:
- Prompts for your Xertified APR Account Key.
- Exchanges the key for an APT client certificate/key and configures repository access.
- Installs Docker and its dependencies.
- Installs the
xmspackage.
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.shlater reportsNo usable env configuration file found, the package post-install step did not complete — for example because a.debwas installed manually withdpkg -iinstead of through the installer/APT. Reinstall via the installer above, or runsudo 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
--setupflag (sudo ./xms-setup.sh --setup) runs an unattended setup using a previously saved configuration. It requires an existing.configfile 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:
- 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. - 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).
- MQTT FQDN — The domain name for the MQTT service (for example
mqtt.example.com). Must resolve to the MQTT IP. - MQTT IP — The local IP for MQTT. Must be a different IP than XMS.
- Database type —
Internaluses a bundled PostgreSQL container (recommended for most deployments).Externalconnects to your own PostgreSQL instance (see 2.4). - Database FQDN — Only prompted if you selected
External. - 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, requiresCA_TYPEto be configured), orFile(provide paths to your own certificate and key files). - User source —
Keycloakmanages users locally (recommended for first install).Microsoft Entra IDrequires additional Azure configuration (see 6.3). - Create initial XMS user —
Yescreates anxmsadminaccount with a generated password. ChooseNoonly 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:
- Validate external DB credentials (if external DB)
- Apply required file permissions
- Verify database access
- Configure Keycloak realm (if needed)
- Issue internal service certificates (if needed)
- Configure/import TLS certificate according to selected TLS source
- Optionally create
xmsadmin, enable group sync, and assignsuperadmin - Apply final permissions
- Enable and restart the
xmsservice
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:
- Core services are
running/healthy(nginx,auth-api,xot-api,directory-sync,mqtt,dashboard, pluspostgresif internal DB) - Open
https://<XMS_FQDN> - Log in using created credentials (or external IdP login)
5.5 Main Menu Reference
Menu options are state-dependent:
Configure XMS: Save/update installation settingsStart 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/AzurePrint full system status: Runsscripts/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_ISSUERin/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_FQDNin/etc/xms/config/env - Set
SECMAKER_PWfor the Net iD Portal API certificate.pfx
6.3 Identity Source and Synchronization
- For Entra ID authentication/synchronization, see Microsoft Entra ID Integration for XMS.
- In setup, selecting Entra ID enables
Configure Entra ID Syncin the menu.
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:
- Open the Keycloak Administration Console (
https://<XMS_FQDN>/idp), select thexmsrealm, and navigate to Identity Providers → OpenID Connect v1.0. - Fill in Client ID, Client Secret, and Discovery endpoint from your provider's app registration.
- Under Advanced, set Scopes to
openid profile. - Go to the Mappers tab, click Add mapper, and create an Attribute Importer mapper named
oidwith Sync mode overrideForce, Claimoid, and User Attribute Nameoid.
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 settings → Themes 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
- Retrieve Keycloak admin credentials:
cat /etc/xms/secrets/keycloak/admin-credentials
-
Navigate to
https://<XMS_FQDN>/idp→ Administration Console and log in asxadmin. -
Switch to the
xmsrealm (top-left dropdown). All XMS user management must be done in this realm. -
Create groups via the Groups menu (create groups first so you can assign membership during user creation).
-
Navigate to Users → Add user. Assign at least one group — users without group membership are not synchronized by
directory-sync. -
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.
- Export the LDAP server's root (and any intermediate) CA certificate in PEM format.
- Copy the certificate(s) into
/etc/xms/secrets/keycloak/truststores/on the XMS host. - 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) requiresXMS_FQDNresolving publicly to the XMS host, TCP80reachable during the ACME challenge, andcertbotinstalled. - File-based TLS requires valid existing certificate/key paths during configuration.
- Issue via XMS CA is only available when
CA_TYPEis 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/*). Addallow <IP>;lines for trusted administrator IPs, then uncommentdeny all;to enforce.access-restricted.conf: Controls other restricted application paths. IPs fromaccess-admin.confare automatically included. Uncommentdeny 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 foundwhen runningxms-setup.sh— The package post-install step did not create/etc/xms/config/env. This usually means a.debwas installed manually withdpkg -iinstead of via the installer/APT. Reinstall with the installer orsudo apt-get install --reinstall xms. -
xms-setup.shfails to write files or change services — Run it withsudo; it writes to/etc/xmsand manages thexmssystemd 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 setupis missing in the menu — RunConfigure XMSfirst and save the configuration, ensure both XMS and MQTT IPs are configured on local interfaces, and on the image runsudo 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
.envand.configfor 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 proxydashboard: Admin web interfacexot-api: Core backend API and business logicmqtt: Mosquitto broker for device communicationauth-api: Keycloak-based identity/authenticationca-manager: Certificate issuance and managementdirectory-sync: User/group synchronization into XMS DBlocal-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.