SystemD

Running EmailEngine as a SystemD service.

In most cases, you probably do not want to run EmailEngine as a regular application but as a background service. Under Linux, the easiest way to create such services would be with SystemD. EmailEngine does not fork itself and sends all its logs to standard output, so it's not a good match with the SysV Init kind of system, but it runs well with SystemD.

Prepare the App

First, we need the application to be present. In this example, we download the executable and place it under /opt directory. Why /opt, you say? Well, it's just as good as any other place; you could store it somewhere else.

$ wget https://github.com/postalsys/emailengine/releases/latest/download/emailengine.tar.gz
$ tar xzf emailengine.tar.gz
$ rm -rf emailengine.tar.gz
$ sudo mv emailengine /opt

Create service unit

All SystemD services require to have a valid service file. We can create one via the command line.

$ sudo vim /etc/systemd/system/emailengine.service

Once the editor is open, paste the following service file content into it and save it:

[Unit]
Description=EmailEngine
# Depending on how you installed Redis, it's service name might be different
After=redis

[Service]
# Configure environment variables
Environment="EENGINE_REDIS=redis://@127.0.0.1:6379/8"
Environment="EENGINE_PORT=3000"

# Folder where EmailEngine executable is located
WorkingDirectory=/opt

# EmailEngine does not require any special privileges
User=www-data
Group=www-data

# Run the EmailEngine executable
ExecStart=/opt/emailengine

Type=simple
Restart=always

SyslogIdentifier=emailengine

[Install]
WantedBy=multi-user.target

Now we can enable and start the service. Next time when we reboot our server, the service is started automatically.

$ sudo systemctl enable emailengine
$ sudo systemctl start emailengine

Verify that the service is running either by checking the service status or connecting to EmailEngine's port.

$ sudo systemctl status emailengine
● emailengine.service - EmailEngine
     Loaded: loaded (/etc/systemd/system/emailengine.service; disabled; vendor >
     Active: active (running) since Sat 2021-10-02 11:04:29 UTC; 1h 34min ago
   Main PID: 368410 (emailengine)
      Tasks: 17 (limit: 9284)
     Memory: 416.3M
     CGroup: /system.slice/emailengine.service
             └─368410 /opt/emailengine
...

$ curl 127.0.0.1:3000/metrics
# HELP thread_starts Number of started threads
# TYPE thread_starts counter
thread_starts 7
...

Checking output logs

When EmailEngine is installed as a SystemD service, you can use standard SystemD tools for different tasks and logging.

For example, to tail output from EmailEngine, you can use the journalctl command:

$ journalctl -t emailengine -f

-- Logs begin at Tue 2021-06-01 12:53:14 UTC. --
Oct 02 12:43:43 srv-01 emailengine[369048]: {"level":30,"time":1633178623716,"pid":369048,"hostname":"srv-01","msg":"Starting EmailEngine","version":"1.14.5","node":"16.8.0"}
Oct 02 12:43:43 srv-01 emailengine[369048]: {"level":20,"time":1633178623716,"pid":369048,"hostname":"srv-01","msg":"IMAP Worker Count","workersImap":4}
Oct 02 12:43:43 srv-01 emailengine[369048]: {"level":20,"time":1633178623716,"pid":369048,"hostname":"srv-01","msg":"Webhooks Worker Count","workersWebhooks":1}
Oct 02 12:43:43 srv-01 emailengine[369048]: {"level":20,"time":1633178623717,"pid":369048,"hostname":"srv-01","msg":"Submission Worker Count","workersWebhooks":1}

This output is not very well readable, but you can't directly use the log renderers shown here because of the metadata entries in front of EmailEngine output logs. These lines are not valid JSON, so the renderers would not be able to process these.

Luckily we can modify journalctl output, so we can ask it to drop all the metadata and only show log entries from EmailEngine. This way, we can pipe that output to a log renderer of our choice.

$ journalctl -t emailengine -f -o cat | jq
{
  "level": 20,
  "time": 1633178713318,
  "pid": 369143,
  "hostname": "srv-01",
  "msg": "Webhooks Worker Count",
  "workersWebhooks": 1
}