2. Installation

2.1. Linux

The Halon 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 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

2.1.1. Ubuntu

To install the .deb package use the following commands, replacing the username and password with the provided credentials.

$ wget -qO - https://raw.githubusercontent.com/halon/changelog/master/pgp-keys/7F0A73B5.asc | sudo apt-key add -
$ . /etc/lsb-release && echo "deb [arch=amd64] https://repo.halon.io/ $DISTRIB_CODENAME stable" | sudo tee /etc/apt/sources.list.d/halon.list
$ echo "machine repo.halon.io login <username> password <password>" | sudo tee /etc/apt/auth.conf
$ sudo apt-get update
$ sudo apt-get install halon

To install the optional packages mentioned in the programs section use the following commands

$ sudo apt-get install halon-rated
$ sudo apt-get install halon-dlpd

2.1.1.1. Version pinning

To pin the .deb package to a specific minor version, use the following commands

cat <<'EOF' | sudo tee /etc/apt/preferences.d/halon
Package: halon
Pin: version 1:5.8.*
Pin-Priority: 1000
EOF
$ sudo apt-get update

Now any future apt-get upgrade will not upgrade the package beyond the 5.8 minor version.

2.1.2. CentOS

To install the .rpm package use the following commands, replacing the username and password with the provided credentials.

Note

Use rhel7 instead of rhel8 in the URL if you’re using CentOS 7.

$ yum install epel-release
$ cat <<'EOF' | sudo tee /etc/yum.repos.d/Halon.repo
[halon]
name=Halon repository
baseurl=https://<username>:<password>@repo.halon.io/dists/rhel8/amd64/stable
gpgcheck=1
gpgkey=https://raw.githubusercontent.com/halon/changelog/master/pgp-keys/7F0A73B5.asc
enabled=1
EOF
$ sudo yum install halon

The default configuration allows users in the staff group to manage the MTA

$ sudo groupadd staff

To install the optional packages mentioned in the programs section use the following commands

$ sudo yum install halon-rated
$ sudo yum install halon-dlpd

2.1.2.1. Version locking

To lock the .rpm package to a specific version, use the following commands

$ sudo yum install python3-dnf-plugin-versionlock
$ sudo yum versionlock add halon

Now any future yum update or yum upgrade will not upgrade the package.

2.2. Docker and K8s

For instructions on how to build container images of the Halon 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.4. 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

  • /opt/halon/share/examples/standard

    • listen on all addresses, port 25 and 587

    • port 25: forward messages to a local server

    • port 587: deliver messages by lookup mx

    • contains a lot of example configuration

To quickly get started, follow the steps below.

$ mkdir -p test/dist
$ cd test
$ cp -r /opt/halon/share/examples/minimal src
$ halonconfig
$ sudo cp dist/* /etc/halon/
  • A sample configuration in /opt/halon/share/examples/{minimal,standard} is copied to a working directory

  • The halonconfig script prepares the configuration files

    • It 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 programs can be enabled on system boot and started with:

$ sudo systemctl enable halon.service
$ sudo systemctl start halon

The default minimal configuration allows you to relay email on port 25 from localhost (port 587 when using the default standard configuration), so you can send a test email using for example swaks:

$ swaks --server 127.0.0.1 --port 25 --to [email protected]

2.5. Programs

This section describes the Halon 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.

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

These packages can be optionally installed as separate packages:

  • rated that manages operations from the rate() function and synchronise this information in the cluster. A ratectl tool is provided to control the rated daemon.

  • dlpd that manages operations from the dlp() function. A dlpctl tool is provided to control the dlpd daemon.

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

environment.appconf

/etc/halon/smtpd-app.yaml

Running configuration

environment.policyconf

/etc/halon/smtpd-policy.yaml

Active queue policies

environment.suspendconf

/etc/halon/smtpd-suspend.yaml

Active queue suspends

environment.deliveryconf

/etc/halon/smtpd-delivery.yaml

Active queue delivery settings

environment.spool.path

/var/spool/halon/queue

Queued messages

environment.publicsuffix

Used by DMARC functions

environment.controlsocket.path

/var/run/halon/smtpd.ctl

Control socket

rated loads its startup configuration from /etc/halon/rated.yaml, which have the following defaults:

Setting

Default

Description

environment.appconf

/etc/halon/rated-app.yaml

Running configuration

environment.controlsocket.path

/var/run/halon/rated.ctl

Control socket

environment.socket.path

/var/run/halon/rated.sock

IPC socket

dlpd loads its startup configuration from /etc/halon/dlpd.yaml, which have the following defaults:

Setting

Default

Description

environment.appconf

/etc/halon/dlpd-app.yaml

Running configuration

environment.tmpdir

/var/spool/halon/tmp

Extracted messages

environment.controlsocket.path

/var/run/halon/dlpd.ctl

Control socket

environment.socket.path

/var/run/halon/dlpd.sock

IPC socket

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

  • rated runs as “nobody”, and its IPC socket is owned by user/group “halon” with chmod 0660 so that smtpd can communicate with it. Like above, its control socket is owned by group “staff” with chmod 0660.

  • dlpd runs as “halon” with umask 0027 so that it can read the message files and write extracted message parts. Its IPC socket is owned by user/group “halon” with chmod 0600 so that smtpd can communicate with it. Like the others, its control socket is owned by group “staff” with chmod 0660.

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