Skip to content

Building From Source

If pre-built binaries are not provided for your system of choice, of if you'd like try your hand at extending KumoMTA, you'll need to build it from source.

If you are on Ubuntu or Rocky Linux and just want to try KumoMTA, rather than build from source we recommend that you follow the instructions in the Installing on Linux section.

Prepare your environment

Read the Environmental considerations before proceeding. You will need a suitably sized server with all of the prerequisites in order to be successful.

In addition, you will need to install some development packages.

Obtain The Code

You will need git:

$ sudo dnf install -y git
$ sudo apt install -y git curl

Then clone the repo:

$ git clone https://github.com/KumoCorp/kumomta.git
$ cd kumomta

Install Dependencies

The get-deps.sh script in the repo knows how to install dependencies for various systems; you should run it the first time you clone the repo, and may need to run it after running a pull to update the repo in the future:

$ ./get-deps.sh

Note

get-deps.sh will install the various deps, but will complain that rust is not installed the first time that you run it. You can ignore that error as the very next step is to install rust.

Install Rust

You will need the Rust compiler to build KumoMTA.

We strongly recommend using rustup to install and manage your Rust compiler. While some distributions offer a version of the Rust compiler, it is often outdated.

If you are using a priviledged user, drop back to your non-priviledged user first:

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
$ source ~/.cargo/env

Building KumoMTA

With all the dependencies available, the actual build process is very simple:

$ cargo build --release

This will build everything, leaving the binaries in the target/release directory in the repo.

Building your own package

There are scripts to build out packages in either RPM or DEB format. If you're running on such a system, we recommend building and installing from a package built by our scripts, as those packages will best encapsulate how we intend for KumoMTA to be installed and operated.

These scripts will produce a package file that you are then free to install either locally or on a target system elsewhere.

$ assets/build-rpm.sh

You can find the generated rpm in a directory maintained by rpmbuild; that is usually ~/rpmbuild/RPMS/x86_64, but some environments use a different location, so the example below uses rpm --eval to obtain the correct location:

$ rpm --eval '%{_rpmdir}/%{_arch}'
/home/USER/rpmbuild/RPMS/x86_64
$ ls $(rpm --eval '%{_rpmdir}/%{_arch}')/kumo*.rpm
/home/USER/rpmbuild/RPMS/x86_64/kumomta-dev-2023.10.24.112314_f8aaa6f1-1.fedora38.x86_64.rpm

You can install it directly if you wish:

$ sudo rpm -Uvh $(ls $(rpm --eval '%{_rpmdir}/%{_arch}')/kumo*.rpm | tail -1)
$ assets/build-deb.sh
$ ls *.deb
kumomta-dev.2023.10.24.112314.f8aaa6f1.Ubuntu22.04.deb

You can install it directly if you wish:

$ sudo apt-get install -y ./kumomta*.deb

Installing from source

If RPM or DEB is not suitable for your environment for some reason, you can install the various components "by hand". We recommend installing to /opt/kumomta so that various product defaults continue to operate as intended.

Pre-req: service account

The default service account assumed by the kumod process is the kumod user.

You can create the account manually like this:

$ sudo useradd --system -g kumod -d /var/spool/kumod -s /sbin/nologin \
    -c "Service account for kumomta" kumod

Directory Structure

Take care with the ownership and permissions on the various directories, in order to avoid deploying with an insecure configuration:

$ sudo install -d --mode 755 --owner kumod --group kumod /opt/kumomta/sbin
$ sudo install -d --mode 755 --owner kumod --group kumod /opt/kumomta/etc
$ sudo install -d --mode 755 --owner kumod --group kumod /opt/kumomta/etc/policy
$ sudo install -d --mode 2770 --owner kumod --group kumod /opt/kumomta/etc/dkim
$ sudo install -d --mode 2770 --owner kumod --group kumod /var/spool/kumomta
$ sudo install -d --mode 2770 --owner kumod --group kumod /var/log/kumomta

The executables:

$ for bin in validate-shaping tsa-daemon \
    proxy-server kumod kcli traffic-gen tailer ; do
  install -Dsm755 target/release/$bin -t /opt/kumomta/sbin
done

The helpers and other assets:

$ sudo mkdir -p /opt/kumomta/share/bounce_classifier /opt/kumomta/share/policy-extras
$ sudo install -Dm644 assets/bounce_classifier/* -t /opt/kumomta/share/bounce_classifier
$ sudo install -Dm644 assets/policy-extras/*.lua -t /opt/kumomta/share/policy-extras
$ sudo install -Dm644 assets/policy-extras/*.toml -t /opt/kumomta/share/policy-extras

The example/starter configuration files can be installed like this; you may wish to skip this set and just deploy your own configuration, as discussed in the section below:

$ sudo install -Dm644 assets/init.lua -T /opt/kumomta/etc/policy/init.lua
$ sudo install -Dm644 assets/tsa_init.lua -T /opt/kumomta/etc/policy/tsa_init.lua

Systemd Service

If you wish to use systemd to manage kumod and/or tsa-daemon, you can find the .service files in the assets directory. Precisely where these files are deployed varies a little depending on your distribution, so copyable instructions for that are not currently provided here.

Creating the initial config

KumoMTA is now installed, but it requires a policy configuration script so it knows how to behave. The policy config is written in Lua and should live in /opt/kumomta/etc/policy/init.lua in order to work with the systemd service definition.

Both the from-package and from-source instructions above will pre-populate that file with the basic configuration that is reproduced below. Alternately, there is a more substantial config sample HERE, but you must save it as /opt/kumomta/etc/policy/init.lua.

/opt/kumomta/etc/policy/init.lua
--[[
########################################################
  KumoMTA minimal Send Policy
  (Save this as /opt/kumomta/etc/policy/init.lua for systemd automation)
  This config policy defines KumoMTA with a minimal
  set of modifications from default.
  Please read the docs at https://docs.kumomta.com/
  For detailed configuration instructions.
########################################################
]]
--
local kumo = require 'kumo'
--[[ Start of INIT section ]]
--

kumo.on('init', function()
  kumo.start_esmtp_listener {
    listen = '0.0.0.0:25',
  }

  kumo.start_http_listener {
    listen = '127.0.0.1:8000',
  }

  kumo.define_spool {
    name = 'data',
    path = '/var/spool/kumomta/data',
  }

  kumo.define_spool {
    name = 'meta',
    path = '/var/spool/kumomta/meta',
  }

  kumo.configure_local_logs {
    log_dir = '/var/log/kumomta',
    -- Flush logs every 10 seconds.
    -- You may wish to set a larger value in your production
    -- configuration; this lower value makes it quicker to see
    -- logs while you are first getting set up.
    max_segment_duration = '10s',
  }
end)
--[[ End of INIT Section ]]

--[[ Start of Non-INIT level config ]]
--
-- PLEASE read https://docs.kumomta.com/ for extensive documentation on customizing this config.
--[[ End of Non-INIT level config ]]

Running kumod

If you are not using systemd to manage the service, then you will need to use some other way to launch kumod. This section shows how you might launch it manually, so that you understand how to automatate/manage this for yourself in your chosen environment:

$ sudo /opt/kumomta/sbin/kumod \
   --policy /opt/kumomta/etc/policy/init.lua \
   --user kumod

Using sudo (or otherwise spawning as root) to launch the process allows binding to privileged ports, such as port 25, so that you can accept incoming mail on the standard port.

When launched with root privileges, kumod requires a service account to switch to after it has bound privileged ports, in order to avoid running in a dangerously insecure mode: you do not want public internet traffic connecting directly to a privileged process!

The --policy argument specifies the path to your init.lua configuration.

The --user argument specifies the name of the service account to use instead of running as root.

Running from your source directory

Note

This section is intended for people that are developing kumomta itself, rather than people that just want to install and use kumomta

This command will bring kumod up to date (in case you made changes), and then try to launch it:

$ cargo run --release -p kumod -- --policy /opt/kumomta/etc/policy/init.lua

You can run as root using port 25, in the foreground, with this:

$ cargo build --release -p kumod && \
  sudo target/release/kumod \
     --policy /opt/kumomta/etc/policy/init.lua \
     --user kumod

Keeping the source up to date

To synchronize your repo with the latest changes in the main branch:

$ cd kumomta
$ git pull --rebase
$ ./get-deps.sh
$ cargo build --release
Note that this builds the new files in target/release/. If you installed binaries to /opt/kumomta/sbin then you will want to follow the instructions above to build your own package and update the files in /opt/kumomta/.