> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xorlab.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Pages under /latest/ document the current release. Paths that begin with a version number, for example /10.0/, are frozen snapshots of superseded releases kept for reference only — never present their instructions as current. If the reader's version is unknown, answer from /latest/ and say which version the answer describes.
> xorlab is deployed on-premises, hybrid, or as a cloud service, and integrates with either Microsoft 365 or on-premises mail infrastructure. Configuration steps often differ between these. State which deployment and integration mode an instruction applies to instead of presenting one as universal.
> Distinguish inline mode from monitoring mode when describing anything that acts on email. Monitoring mode observes a copy and cannot block or quarantine; inline mode routes mail through xorlab and can.
> Write the product name as lowercase 'xorlab'. Use the documented component names: xorlab Control Center (XCC), xorlab MTA, xorlab Sandbox (DANA), xorlab Natural Language Understanding (NLU). After the first mention, use the short forms XCC, MTA, Sandbox, and NLU. Do not use DANA as a standalone name for the Sandbox, but keep it where it is a literal string in configuration keys, container names, and hostnames.
> Do not invent configuration keys, rule parameters, list names, log properties, or API fields. If a value is not present in this documentation, say that it is not documented rather than guessing.

# VM Setup Guide

> Provision the XCC and one or more MTAs on your own virtual infrastructure.

xorlab consists of two on-premises components: XCC and MTA. MTAs are email processing nodes that can be operated redundantly, depending on the expected load and availability requirements. XCC consolidates the analysis results from the MTAs and hosts the web interface.

The optional setup of on-premises Sandbox (DANA) hardware is not covered by this page.

## Preparation

### Hardware requirements

XCC and the MTAs are provided as images in the OVF format. Our [Sizing Guide](/latest/sizing-guide) will help you determine the right configuration for the resulting VMs. Download credentials can be requested [via email](<mailto:support@xorlab.com?subject=xorlab download request>).

### Network requirements

Prepare your firewall and/or proxy such that the connections described in [xorlab Network Guide](/latest/network-guide) are supported.

<Note>
  **Unfiltered DNS**

  Make sure your DNS service for xorlab is unfiltered. Otherwise, xorlab requests for malicious domains/IPs will not be answered and processed messages will be stuck in a queue because of DNS timeouts.
</Note>

### Register required DNS records

1. Register DNS A records for the XCC and MTA VMs with your internal DNS server(s). For XCC, you can also use a CNAME record instead of an A record. For the MTA VMs, A records are required; see also [RFC 2181](https://datatracker.ietf.org/doc/html/rfc2181#section-10.3). The table below shows an example setup for example.com:

   | Component | Record             | Type       |
   | :-------- | :----------------- | :--------- |
   | XCC       | `xcc.example.com`  | A or CNAME |
   | MTA1      | `mta1.example.com` | A          |
   | MTA2      | `mta2.example.com` | A          |

2. Add an MX record for every MTA in your setup. Use the same priority for all MTAs to achieve automatic load-balancing. In our example, we use `mx.example.com` and the DNS query result is:

   ```shell theme={null}
   dig MX mx.example.com
   [...]
   ;; ANSWER SECTION:
   mx.example.com. 3600    IN  MX  10 mta1.example.com.
   mx.example.com. 3600    IN  MX  10 mta2.example.com.
   ```

### Prepare the VMs

1. Download the XCC and MTA images (OVF format). The link and credentials will be provided by us.
2. Decompress the zip files and instantiate the XCC and MTA virtual machines using your Hypervisor.

## Setup

### Configure the network

The XCC and MTA VM images have DHCP configured on all network interfaces, which names match `en*`.

If your environment requires static addresses, proceed with the steps below:

1. Open a shell on the VM using your hypervisor, log in and open the `/etc/netplan/00-xorlab-config.yaml` file with elevated privileges (`sudo`). Comment the dynamic configuration out, uncomment the static configuration, and set the appropriate values. In this example, for the `ens192` interface, the config file should look like this:

   ```yaml theme={null}
   network:
     version: 2
     renderer: networkd
     ethernets:
       ens192:
         dhcp4: false
         dhcp6: false
         addresses:
           - 192.168.0.1/16
         routes:
           - to: default
             via: 192.168.0.254
         nameservers:
           search:
             - "example.com"
           addresses:
             - 192.168.0.254
             - 192.168.0.253
   ```

   <Warning>
     **Avoid using certain special-use domain names**

     Some special-use domain names can cause issues. For example, `.local` is reserved for [multicast DNS](https://en.wikipedia.org/wiki/Multicast_DNS) (mDNS) and should not be used for private networks, since it can lead to name resolution conflicts. Instead, if you need a dedicated naming space for a local network, better use a subdomain under `.home.arpa.`, which is specifically [reserved](https://en.wikipedia.org/wiki/.arpa) for that purpose.
   </Warning>

2. In case you want to add a second interface (or more) to your VM, you need to add a configuration for each:

   <Accordion title="Static IP configuration example for more interfaces">
     `nameservers` block can have either `search` or `addresses`, or both defined.

     ```yaml theme={null}
       version: 2
       renderer: networkd
       ethernets:
         ens192:
           dhcp4: false
           dhcp6: false
           addresses:
             - 192.168.0.1/16
           routes:
             - to: default
               via: 192.168.0.254
           nameservers:
             search:
               - "example.com"
             addresses:
               - 192.168.0.254
               - 192.168.0.253
         ens224:
           dhcp4: false
           dhcp6: false
           addresses:
             - 192.168.0.2/16
           routes:
             - to: default
               via: 192.168.0.254
           nameservers:
             search:
               - "example.com"
             addresses:
               - 192.168.0.254
               - 192.168.0.253
     ```
   </Accordion>

3. Apply the configuration by executing `sudo netplan apply`.

4. Restart all docker containers.

After changing the configuration on all your destination VMs, you should be able to connect to them using SSH.

### Connect via SSH

All our virtual machines are running Ubuntu Linux. The OS comes with a pre-configured admin account. Use the credentials provided to you by xorlab to open an SSH connection.

### Resize the disk

Now, resize the disks of the VMs so that they meet the requirements from the [Sizing Guide](/latest/sizing-guide):

1. Configure your hypervisor to provide the correct amount of storage to the VMs. This step is not described any further here since it depends on your hypervisor.

2. Execute the following steps on every xorlab VM (XCC and MTAs)

3. Run `lsblk` to show the current structure of the disks and partitions.
   ```shell theme={null}
   lsblk
   NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
   sda      8:0    0  100G  0 disk 
   ├─sda1   8:1    0    1M  0 part 
   └─sda2   8:2    0  100G  0 part /
   ```

4. Run `sudo fdisk /dev/<disk>` - replace `<disk>` with the desired disk as shown before. Then follow the highlighted instructions below. The partition number might be different.

   <Note>
     **fdisk**

     No changes will be written to the disk before you execute the `w` command. You can accept the defaults by pressing the <kbd>Enter</kbd> key.
   </Note>

   ```shell {1,2,16,17,21,22,23,24,29,31} theme={null}
   sudo fdisk /dev/sda
   Command (m for help): p

   Disk /dev/sda: 100 GiB, 107374182400 bytes, 209715200 sectors
   Disk model: Virtual disk    
   Units: sectors of 1 * 512 = 512 bytes
   Sector size (logical/physical): 512 bytes / 512 bytes
   I/O size (minimum/optimal): 512 bytes / 512 bytes
   Disklabel type: gpt
   Disk identifier: 0E4A82CF-8961-476F-B565-F53F562FD9CE

   Device     Start       End   Sectors  Size Type
   /dev/sda1   2048      4095      2048    1M BIOS boot
   /dev/sda2   4096 209713151 209709056  100G Linux filesystem

   Command (m for help): d
   Partition number (1,2, default 2): 

   Partition 2 has been deleted.

   Command (m for help): n
   Partition number (2-128, default 2): 
   First sector (4096-209715166, default 4096): 
   Last sector, +/-sectors or +/-size{K,M,G,T,P} (4096-209715166, default 209715166): 

   Created a new partition 2 of type 'Linux filesystem' and of size 100 GiB.
   Partition #2 contains a ext4 signature.

   Do you want to remove the signature? [Y]es/[N]o: n

   Command (m for help): w

   The partition table has been altered.
   Syncing disks.
   ```

5. Resize the file system with:
   ```shell theme={null}
   sudo resize2fs /dev/sda2
   ```

6. Verify that the partition has the correct size with `df -h`.

### Run the Setup Script

`xorlab-setup` will first determine the VM type it's running on.

1. Connect to the XCC VM via SSH and run `xorlab-setup`.
2. Connect to the MTA VM via SSH and run `xorlab-setup`.

The script can be safely run multiple times. It logs additional information to `/var/log/xorlab/host/host_bootstrap.log`.

When you invoke it without arguments, it offers to update to the newest wrapper-managed setup script version before starting the interactive set-up. Direct invocation with arguments such as `--help`, `--restart-services`, or `--reachability-test` omits the update prompt and forwards the arguments directly to the local role-specific script.

Here you can find more information about the script:

* [Script Breakdown](/latest/vm-setup-script-breakdown#script-breakdown): Step-by-step instruction on what the script does. Use this in case you need to manually apply certain steps.
* [Script Coverage Overview](/latest/vm-setup-script-breakdown#script-coverage): Overview of all config files changed by the script.
* [Script Usage](/latest/vm-setup-script-breakdown#using-the-script): Save and re-use inputs to the setup script.

### EHLO configuration

Set the hostnames used by the MTAs for the `EHLO` when the SMTP connection is established. For every xorlab MTA, you will see one `main.cf.vmx.<id>` file: `main.cf.vmx.1` will be applied on MTA 1, `main.cf.vmx.2` on MTA 2, and so on. If there is only one MTA, you will only find the `main.cf` file.

1. Open [Expert Editor](/latest/expert-editor).
2. Navigate to the `activeguard/mta/startup_cfg/postfix_custom/`.
3. Edit each `main.cf*` file and set the `myhostname` parameter to the hostname that points to this MTA in your DNS (A record).

A sample `activeguard/mta/startup_cfg/postfix_custom/main.cf` file should look like this:

```shell main.cf theme={null}
# This hostname will be used by xorlab for SMTP, e.g. in the EHLO message
myhostname = mta1.example.com
```

Click **Publish**. The `main.cf*` changes become active within about one minute.

### Set local NTP servers

xorlab uses the time provided by the OS. In order to configure the OS settings set the `NTP` line in `/etc/systemd/timesyncd.conf`:

```text theme={null}
[Time]
NTP=ntp.example.com ntp.ubuntu.com ...
```

Then restart the NTP service by executing:

```shell theme={null}
sudo systemctl restart systemd-timesyncd.service
```

### Configure performance resources

This is informational only: The VMs are normally already pre-configured according to your expected email load.

However if you expect that your load is different from the ordered VM, adjust the performance configuration according to [VM Resource Configuration](/latest/vm-resource-configuration).

## Optional settings

### Add host mapping for XCC

This is only required if **the MTAs cannot resolve the domain of the XCC via DNS**:

1. SSH connect to each MTA
2. Edit `/etc/hosts`, e.g. `sudo nano /etc/hosts`
3. Add a line with the IP and domain of the XCC:
   ```bash hosts theme={null}
   1.2.3.4 xcc.example.com
   ```

### Change Docker IP range

This is only required if **your local network uses the `172.16.0.0/12` IP address range.** As xorlab uses the same IP range internally, this can lead to routing problems.

Follow these instructions to change the xorlab internal Docker network. This must be done for every xorlab VM (MTA and XCC).

1. To verify that xorlab actually uses 172.16.0.0/12 internally, you can execute `ip r` on the command line. The output usually looks like this:

   ```shell theme={null}
   ip r
   ...
   172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
   172.18.0.0/16 dev br-74362b0b174e proto kernel scope link src 172.18.0.1
   ...
   ```

2. Open the `daemon.json` file:

   ```shell daemon.json theme={null}
   sudo vi /etc/docker/daemon.json
   ```

3. Specify the new IP range that xorlab should use internally. You have to set a subnet for `bip` and a different one for `default-address-pools`. Make sure you don’t use those subnets in your network. More information can be found on the official Docker documentation: [Networking overview](https://docs.docker.com/network/) and [dockerd](https://docs.docker.com/engine/reference/commandline/dockerd/).

   ```json theme={null}
   {
   ...
     "bip": "10.200.0.1/24",
     "default-address-pools":[
       {"base":"10.201.0.0/16","size":24}
     ]
   }
   ```

4. To activate the changes, stop all running containers by executing `docker compose down` in the following directories:

   * MTA: `/etc/xorlab/activeguard`, and `/etc/xorlab/monitored_mta`
   * XCC: `/etc/xorlab/xcc`, `/etc/xorlab/auth`, `/etc/xorlab/elastic`, and `/etc/xorlab/monitoring`

5. Restart the Docker service with:

   ```shell theme={null}
   service docker restart
   ```

6. Recreate the existing networks by executing `docker network rm <network> && docker network create <network>` for the following `<network>`:

   * MTA: `activeguard.xor` and `monitored_mta.xor`. You can display existing networks with `docker network ls`.
   * XCC: `xcc.xor`, `auth.xor`, and `monitoring.xor`

7. Restart the VM:

   ```shell theme={null}
   sudo reboot
   ```

### Replace built-in certificates

This is only applicable if **you want to replace the pre-installed dummy certificates**.

These certificates allow for encryption of traffic but not for authentication. To install new TLS certificates, you have to:

1. Replace the dummy certificate files on both the XCC and MTAs in `/etc/xorlab/tls` with your certificate files in [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) format:
   1. [Replace MTA SMTP Certificate](/latest/tls-certificates-for-mta-smtp)
   2. [Replace MTA GUI Certificate](/latest/tls-certificates-for-mta-proxy)
   3. [Replace XCC Certificate](/latest/tls-certificates-for-xcc)

2. If certificates are used that are not signed by a generally trusted CA, i.e. self-issued / locally trusted certificates, you need to configure XCC and MTA VMs to trust all certificates:

   <Tabs>
     <Tab title="XCC">
       * `/etc/xorlab/<stack>/bootstrap.env` (`auth`, `monitoring` and `xcc` stacks)

         ```yaml {4} theme={null}
         ## xorlab bootstrap configuration
         (...)
         # If an untrusted certificate is used on xcc, set 'trustAll' to 'True'
         configServiceProvider_ag_local={'serviceProvider': {'hosts': ['http://backend.xcc.xor:9080'], 'ssl': {'trustAll': True}}}
         ```

       * `/activeguard/core/active_guard.yml` (using [Expert Editor](/latest/expert-editor))

         ```yaml {6,7} theme={null}
         serviceProviders:
         (...)
           xcc:
             hosts:
               - https://xcc.example.com:9080
             ssl:
               trustAll: true
         ```

       * `/monitored_mta/promtail/config.yml` (using [Expert Editor](/latest/expert-editor))

         ```yaml {3,4} theme={null}
         clients:
           - url: https://xcc.example.com:3100/loki/api/v1/push
             tls_config:
               insecure_skip_verify: true
         ```

       * `/activeguard/mta/audit/audit.yml` (using [Expert Editor](/latest/expert-editor))

         ```yaml {6,7} theme={null}
         serviceProviders:
         (...)
           xcc:
             hosts:
               - https://xcc.example.com:9080
             ssl:
               trustAll: true
         ```
     </Tab>

     <Tab title="MTA">
       * `/etc/xorlab/<stack>/bootstrap.env` (`activeguard`, `monitored_mta`, `rproxy_mta` stacks)

         ```yaml {4} theme={null}
         ## xorlab bootstrap configuration
         (...)
         # If an untrusted certificate is used on xcc, set 'trustAll' to 'True'
         configServiceProvider_ag_local={'serviceProvider': {'hosts': ['https://xcc.example.com:9080'], 'ssl': {'trustAll': True}}}
         ```
     </Tab>
   </Tabs>

3. Click **Publish** for the files edited in Expert Editor, then restart all containers on the XCC and MTAs to activate the changes. The `active_guard.yml`, audit, Promtail, and Grafana settings listed above include entries that require component restarts; see [How to Activate the Configuration](/latest/activate-configuration).

### Activate the firewall

This is only applicable if **you want to manage a host firewall on the xorlab hosts**.

By default, new MTA and XCC VMs have their firewalls disabled, although the necessary iptables config files are present. To enable the firewalls, for XCC and each MTA VM, execute the following command:

```shell theme={null}
sudo systemctl enable --now /etc/xorlab/firewall/iptables.service
```

## Post-installation checks

1. Log in to the xorlab MTA admin interface on port 8443.
2. Go to **Health Check** and confirm that the status is `RUNNING`.
3. Go to **Configuration → System Tests** and confirm that all System Tests are green.

## Further steps

1. When the VM setup is finished, proceed to configuring [monitoring tools](/latest/monitoring-guide).
2. Start integrating xorlab into your environment: [On-prem Integration](/latest/on-prem-integration-overview).
