2. Installation
2.1. Linux
The programs are installed using a Linux distribution package manager
according to the corresponding instructions, or by manually copying the files to the
/opt/halon
directory.
In the examples below with #
prompts, steps will require elevated (root) privilege, e.g. sudo su -
before running them.
In preparation; if you have another MTA running on the same host (eg. Exim, Sendmail or Postfix), you should in most installations stop it. To stop Postfix for example:
# systemctl disable postfix
# systemctl stop postfix
Note
Some of the software provided from Halon Security AB are subject to export control restrictions listed in category 5D002 of the Annex I of the European Union dual use regulations, Regulation (EU) 2021/821. The software downloaded may not be re-exported or re-transferred without the expressed approval from concerned authority or legislation.
2.1.1. Ubuntu
To install the .deb package use the following commands, replacing the username and password with the provided credentials.
# HALON_REPO_USER=<username>
# HALON_REPO_PASS=<password>
# wget -O- https://raw.githubusercontent.com/halon/pgp-keys/master/pgp-keys/7F0A73B5.gpg > /usr/share/keyrings/halon-archive-keyring.gpg
# . /etc/lsb-release && echo "deb [arch=`dpkg --print-architecture` signed-by=/usr/share/keyrings/halon-archive-keyring.gpg] https://repo.halon.io/ $DISTRIB_CODENAME stable" > /etc/apt/sources.list.d/halon.list
# echo "machine repo.halon.io login $HALON_REPO_USER password $HALON_REPO_PASS" > /etc/apt/auth.conf
# apt-get update
# apt-get install halon
# halonctl license fetch --username $HALON_REPO_USER --password $HALON_REPO_PASS
# echo "$(($RANDOM % 60)) $(($RANDOM % 24)) * * * root /opt/halon/bin/halonctl license fetch --username $HALON_REPO_USER --password $HALON_REPO_PASS --syslog" > /etc/cron.d/halon-license
2.1.1.1. Version pinning
To pin the .deb package to a specific minor version, use the following commands
# cat <<'EOF' > /etc/apt/preferences.d/halon
Package: halon
Pin: version 1:6.6.*
Pin-Priority: 1000
EOF
# apt-get update
Now any future apt-get upgrade
will not upgrade the package beyond the 6.6 minor version.
2.1.2. RHEL
To install the .rpm package use the following commands, replacing the username and password with the provided credentials.
Note
The RHEL repository can also be used when installing Halon on CentOS, Rocky Linux or AlmaLinux.
# HALON_REPO_USER=<username>
# HALON_REPO_PASS=<password>
# yum install epel-release
# REPO="/etc/yum.repos.d/Halon.repo"
# DIST="rhel$(cat /etc/redhat-release | sed 's/.*release \([0-9]\+\).*/\1/')"
# echo "[halon]" > $REPO
# echo "name=Halon repository" >> $REPO
# echo "baseurl=https://$HALON_REPO_USER:$HALON_REPO_PASS@repo.halon.io/dists/$DIST/amd64/stable" >> $REPO
# echo "gpgcheck=1" >> $REPO
# echo "gpgkey=https://raw.githubusercontent.com/halon/pgp-keys/master/pgp-keys/7F0A73B5.asc" >> $REPO
# echo "enabled=1" >> $REPO
# yum install halon
# halonctl license fetch --username $HALON_REPO_USER --password $HALON_REPO_PASS
# echo "$(($RANDOM % 60)) $(($RANDOM % 24)) * * * root /opt/halon/bin/halonctl license fetch --username $HALON_REPO_USER --password $HALON_REPO_PASS --syslog" > /etc/cron.d/halon-license
The default configuration allows users in the staff group to manage the MTA
# groupadd staff
2.1.2.1. Version locking
To lock the .rpm package to a specific version, use the following commands
Note
Install the yum-plugin-versionlock
package instead if you’re using RHEL 7.
# yum install python3-dnf-plugin-versionlock
# yum versionlock add halon
Now any future yum update
or yum upgrade
will not upgrade the package.
2.2. Docker & K8s
For instructions on how to build container images of the programs as well as deploying them on K8s (Kubernetes), see our halon-docker GitHub repository.
2.3. Upgrade
In order to upgrade the package, install the new package over the previous installed one (see the installation chapter). After the upgrade the service will be stopped and requires to be manually started. Important upgrades notes will be published in the release notes documents. Those may include
Configuration version compatibility
Protobuf API compatibility
C plugin API compatibility
2.3.1. Versioning scheme
All packages provided both the base software packages and halon-extras plugins follow the standard format of semantic versioning often referred to as “SemVer”. This allows you to do version pinning on both major.*
and major.minor.*
releases to safely move between feature and patch releases.
2.3.2. Lifecycle compatibility
The lifecycle of our software releases will follow the lifecycle of the currently supported Linux distributions. For this reason we choose support the LTS (Long Term Support) versions of a specific Linux distribution if possible. For an additional yearly fee the support term may be extended during the Linux distribution extended paid support term.
Distribution |
End-of-Life |
Final supported version |
---|---|---|
RHEL 9.x |
— 2032 |
|
RHEL 8.x |
— 2029 |
|
RHEL 7.x |
Jun 2024 |
|
Ubuntu 24.04 |
Apr 2029 |
|
Ubuntu 22.04 |
Apr 2027 |
|
Ubuntu 20.04 |
Apr 2025 |
|
Ubuntu 18.04 |
Oct 2023 |
6.0.2 |
2.4. License
In order for Halon to operate it needs to have a valid non-expired license environment.licensekey
.
This license can be obtained once with the following command.
# halonctl license fetch --username $HALON_REPO_USER --password $HALON_REPO_PASS
Importantly, the license needs to be updated before the end of the license period as the system will not operate without a valid non-expired license. It can easily be done using eg. a cron job. This fetches your license once per day at a random minute and hour.
# echo "$(($RANDOM % 60)) $(($RANDOM % 24)) * * * root /opt/halon/bin/halonctl license fetch --username $HALON_REPO_USER --password $HALON_REPO_PASS --syslog" > /etc/cron.d/halon-license
If running in a container or if you have other ways of deploying Halon where you don’t have cron available, another method needs to be used.
The current license status and expiration can be shown either using the halonctl license show
or halonctl process-stats
command or using the Web UI.
2.5. Configuration
Each program has a small startup configuration,
which contains settings such as
control socket paths and user privilege drop. Most importantly,
they point at the running configuration load path via environment.appconf
.
There are multiple sample configuration files in /opt/halon/share/examples directory.
The running configuration contains the bulk of the configuration data,
including all the Halon script.
The following sample configuration are available.
/opt/halon/share/examples/minimal
listen on localhost, port 25
deliver messages by lookup mx
contains only necessary configuration
To quickly get started, follow the steps below.
$ mkdir -p test/dist
$ cd test
$ cp -r /opt/halon/share/examples/minimal src
$ halonconfig
# cp dist/* /etc/halon/
A sample configuration in /opt/halon/share/examples/minimal is copied to a working directory
The
halonconfig
script prepares the configuration filesIt validates the configuration files in src/config against the JSON schemas
It “packs” the script in src/hooks and src/files into the smtpd-app.yaml running configuration
It writes the result to the dist directory
The prepared configuration is copied from dist/ to /etc/halon/
When the initial configuration is in place, the program can be enabled on system boot and started with:
# systemctl enable halon-smtpd.service
# systemctl start halon
The default minimal configuration allows you to relay email on port 25 from localhost, so you can send a test email using for example swaks:
$ swaks --server 127.0.0.1 --port 25 --to [email protected]
2.6. Programs
This section describes the programs. These are:
smtpd which is main MTA server process, and what runs the connect, HELO, AUTH, MAIL, RCPT, EOD, disconnect, pre- and post delivery, and proxy script hooks.
hsh that can be used to run standard library functions.
hqfeml is used to convert
.hqf
files to.eml
.hqfcat is used to impect
.hqf
.halonctl is used to control the MTA.
halontop is used to view statistics from the MTA.
halonconfig is used to verify and compile the configuration.
2.6.1. Default paths
Each of the programs have default paths for configurations, Unix domain sockets, temporary directories, and the queue. Those are specified in the JSON schemas, but repeated below for your convenience.
smtpd loads its startup configuration from /etc/halon/smtpd.yaml, which have the following defaults:
Setting |
Default |
Description |
---|---|---|
/etc/halon/smtpd-app.yaml |
||
/etc/halon/smtpd-policy.yaml |
||
/etc/halon/smtpd-suspend.yaml |
||
/etc/halon/smtpd-delivery.yaml |
||
|
/var/spool/halon/queue |
Queued messages |
Used by DMARC functions |
||
/var/run/halon/smtpd.ctl |
2.6.2. File permissions
Each of the programs are compiled with default paths for Unix domain sockets, temporary directories, and the queue.
The permissions and user/group settings need to be configured however, but the default configuration files comes
with recommended settings as you can see in the /opt/halon/share/examples directory. This default configuration gives
users of group staff
the privilege of administration via the control sockets.
Below is a description of why those permissions were chosen:
smtpd runs as user “halon” with umask 0027. This leaves messages on disk with read/write for user “halon”, and read for group “halon”. The control socket is owned by group “staff” with chmod 0660 which makes it read/writeable by both “staff”.
2.6.3. Troubleshooting
If the program doesn’t start, this is usually due to an erroneous configuration change. To avoid this, checking the script and configuration with halonconfig (and doing a test deploy with live stage) before configuration deployment is recommended. Certain types of errors can however not be detected by the syntax checker. By default, errors are logged to syslog (which with systemd is managed by journald):
# journalctl -xe -u halon-smtpd
...
Dec 12 03:12:47 mta1 smtpd[57556]: - listen on 192.0.2.5:25
Dec 12 03:12:47 mta1 smtpd[57556]: Could not load configuration: bind: Cannot assign requested address
...
If you want to see startup errors directly on the console you can start smtpd with log sent to foreground (stderr) using the -f flag:
# LD_LIBRARY_PATH=/opt/halon/lib /opt/halon/sbin/smtpd -f
smtpd: Starting Halon (5.3.0)
smtpd: serverid: inbound
smtpd: - listen on 192.0.2.5:25
smtpd: Could not load configuration: bind: Cannot assign requested address