How to create and manage services in CentOS 7 with systemd

Systemd is a system and service manager and like most major Linux distributions the init deamon was replaced by systemd in CentOS 7. One of the main functions of systemd is to manage the services, devices, mount points, sockets and other entities in a Linux system. Each of these entity that are managed by systemd is called a unit. Each unit is defined by a unit file (configuration file) which is located in one of the following directories.
/usr/lib/systemd/system/Unit files distributed with installed packages. Do not modify unit files in this location.
/run/systemd/system/Unit files that are dynamically created at runtime. Changes in this directory are lost when rebooted.
/etc/systemd/system/Unit files created by systemctl enable and custome unit files created by system administrators.

Any custom unit files that you create should be placed in the /etc/system/system/ directory. This directory takes precedence over other directories.

Unit files names are of the form


Unit_type can be one of the following:

Unit TypeDescription
deviceA device unit.
serviceA system service.
socketA socket for inter-process communication.
swapA swap file or device.
targetA group of units.
timerA systemd timer.
snapshotA snapshot of systemd manager.
mountA mount point.
sliceA group of unit that manage the system processes.
pathA file or directory.
automountA automount point.
scopeAn externally created process.

Creating a new service (systemd unit)

To create a custom service to be managed by systemd, you create a unit file that defines the configuration of that service. To create a service named MyService for example, you create a file named MyService.service in /etc/systemd/system/

# vim /etc/systemd/system/MyService.service

The unit file of service consists of a set of directives that are organized in to three sections – UnitService and Install. Below is an example of a very simple unit file.

 Description=Service description



Once you have created the unit file with all the necessary configuration options, save the file and set the correct file permissions.

# chmod 664 /etc/systemd/system/MyService.service

The next step is to reload all unit files to make systemd know about the new service.

# systemctl daemon-reload

Finally to start the service, run

# systemctl start MyService.service

[Unit] Section

The following are the main directives that you specify in the [Unit] section.

DescriptionA short description of the unit.
DocumentationA list of URIs pointing to the documentation for the unit.
RequiresA list of units that must be started alongside the current unit. If the any these units fail to start then current unit will not be activated.
WantsSimilar to the Requires directive but the difference is the current unit will be activated even if the depended units fail to start.
BeforeList of units that cannot be started before the current unit.
AfterThe current unit can started only after the units listed here.
ConflictsList units that cannot be run concurrently with the current unit.

[Service] Section

Some of the common directives that you’ll see in service section are.

TypeDefines the startup type of the unit which can be one of the values:

  • Simple: This is the default. The main process of the service is the process started with ExecStart.
  • Forking: The process started with ExecStart spawns a new child process which becomes the main process and the parent process is terminated when the startup is completed.
  • Onehot: Similar to simple but systemd waits for the process to exit before proceeding with other units.
  • Dbus: Similar to simple but systemd waits for the process to take a name on the dbus.
  • Notify: Similar to simple Systemd will wait for a notification from the process before continuing with other units.
  • Idle: Similar to simple but service will not run until all other jobs are finished.
ExecStartSpecifies the command to the executed to start service.
ExecStartPreSpecifies the command to be executed before the main process specified in the ExecStart is started.
ExecStartPostSpecifies the command to be executed after the main process specified in the ExecStart has finished.
ExecStopSpecifies the command to be executed when the service is stopped.
ExecReloadSpecifies the command to be executed when the service is restarted.
RestartSpecifies when to restart the service automatically. Possible values are “always”, “on-success”, “on-failure”, “on-abnormal”, “on-abort”, or “on-watchdog”.

[Install] Section

The [install] section provides information required to enable or disable the units using the systemctl command. The common options are:

RequiredByA list of units that requires unit. A symbolic link of this unit is created in the .requires directory of the listed unit.
WantedBySpecifies a list of targets under which the service should be started. A symbolic link of this unit is created in the .wants directory of the listed target.

Using systemctl to manage services

systemctl is the command line tool you can use to control and manage services in systemd. Let’s now take a look at the some of the important systemctl commands for service management.

Listing Service Units and Unit files

To list all the units that are loaded

# systemctl list-units

To list only units of type service

# systemctl list-units -t service

To list all installed unit files of type service

# systemctl list-unit-files -t service

To list all installed unit files of type service

# systemctl list-unit-files -t service

You can use the --state option to filter the output by the state of the unit. The following command lists all services that are enabled.

# systemctl list-unit-files --state enabled

Note the difference between list-units and list-unit-files is that list-unit will only show units that are loaded while list-unit-files shows all unit files that are installed on the system.

Start and Stop service

This is quite straightforward, start option to start a service and stop option to stop a service

# systemctl start service_name.service
# systemctl stop service_name.service

Restart and Reload services

The restart option will restart a service that is running. If the service is not running, it will be started.

# systemctl restart service_name.service

If you want to restart the service only if its running then use the try-restart option.

# systemctl try-restart service_name.service

The reload option will try to reload the service specific configuration of a unit if it is supported.

# systemctl reload service_name.service

Enable and Disable services

Units can be enabled or disabled using the enable or disable options of systemctl command. When a unit a enabled symbolic links are created in various locations as specified in the [install] section of the unit file. Disabling a unit will remove the symbolic links that wer created when the unit was enabled.

# systemctl enable service_name.service
# systemctl disable service_name.service

Reload Unit Files

Whenever you make any changes to the unit files you need to let systemd know by executing daemon-reload which reloads all unit files.

# systemctl daemon-reload

Modifying system services

The unit files that come with installed packages are stored in /usr/lib/systemd/system/. The unit files in this directory should not be modified directly as the changes will be lost when if you update the package. The recommended method is to first copy the unit file to /etc/systemd/system/ and make the changes in that location. The unit files in /etc/systemd/system/ takes precedence over unit files in /usr/lib/systemd/system/ so the original unit file will be overridden.

How email works (MTA, MDA, MUA)

As simple as it is to use, email relies on a more complicated set of operating procedures than that of the Web. For most users, its operation is transparent, which means that it is not necessary to understand how email works in order to be able to use it.

However, the short introduction below has been provided to help you to understand its basic principles, give you an idea of how to best configure your email clients, and inform you about the underlying mechanisms of spam.

How Email Works

Email is based around the use of electronic mailboxes. When an email is sent, the message is routed from server to server, all the way to the recipient’s email server. More specifically, the message is sent to the mail server tasked with transporting emails (called the MTA, for Mail Transport Agent) to the recipient’s MTA. On the Internet, MTAs communicate with one another using the protocol SMTP, and so are logically called SMTP servers (or sometimes outgoing mail servers).

The recipient’s MTA then delivers the email to the incoming mail server (called the MDA, for Mail Delivery Agent), which stores the email as it waits for the user to accept it. There are two main protocols used for retrieving email on an MDA: POP3 (Post Office Protocol), the older of the two, which is used for retrieving email and, in certain cases, leaving a copy of it on the server; and IMAP (Internet Message Access Protocol), which is used for coordinating the status of emails (read, deleted, moved) across multiple email clients. With IMAP, a copy of every message is saved on the server, so that this synchronization task can be completed.

For this reason, incoming mail servers are called POP servers or IMAP servers, depending on which protocol is used:

Schematic diagram of MTA-MDA-MUA
To use a real-world analogy, MTAs act as the post office (the sorting area and mail carrier), which handle message transportation, while MDAs act as mailboxes, which store messages (as much as their volume will allow) until the recipients check the box. This means that it is not necessary for recipients to be connected in order for them to be sent email.

To keep everyone from checking other users’ emails, MDA is protected by a user name called a login and by a password.

Retrieving mail is done using a software program called an MUA (Mail User Agent). When the MUA is a program installed on the user’s system, it is called an email client (such as Mozilla Thunderbird, Microsoft Outlook, Eudora Mail, Incredimail or Lotus Notes).

When it is a web interface used for interacting with the incoming mail server, it is called webmail.

Open Relay

By default, it is not necessary to authenticate oneself to send email, which means that it is very easy to falsify one’s own address when sending mail. For this reason, nearly all Internet service providers lock down their SMTP servers so that only their subscribers can use them, or more precisely, only machines whose IP address belongs to the ISP’s domain. This explains why users must modify the outgoing server settings in their email clients each time they move to a new home or business.

When an organization’s email server is improperly configured and allows third-party users on any network to send emails, this is called an open relay. Open relays are generally used by spammers, as using them hides the true origins of their messages. As a result, many ISPs keep an up-to-date blacklist of open relays to keep subscribers from receiving messages from such servers.

Enigma plugin (PGP encryption) Roundcube signature

You have to set up enigma plugin :

cp /……../roundcubemail/plugins/enigma/ /……../roundcubemail/plugins/enigma/


// Enigma Plugin options
// --------------------

// A driver to use for PGP. Default: "gnupg".
$config['enigma_pgp_driver'] = 'gnupg';

// A driver to use for S/MIME. Default: "phpssl".
$config['enigma_smime_driver'] = 'phpssl';

// Enables logging of enigma operations (including Crypt_GPG debug info)
$config['enigma_debug'] = true;

// Keys directory for all users. Default 'enigma/home'.
// Must be writeable by PHP process
$config['enigma_pgp_homedir'] = enigma/home;

// Location of gpg binary. By default it will be auto-detected.
// This is also a way to force gpg2 use if there are both 1.x and 2.x on the system.
$config['enigma_pgp_binary'] = '/usr/bin/gpg';

// Location of gpg-agent binary. By default it will be auto-detected.
// It's used with GnuPG 2.x.
$config['enigma_pgp_agent'] = '';

// Location of gpgconf binary. By default it will be auto-detected.
// It's used with GnuPG >= 2.1.
$config['enigma_pgp_gpgconf'] = '';

// Enables signatures verification feature.
$config['enigma_signatures'] = true;

// Enables messages decryption feature.
$config['enigma_decryption'] = true;

// Enables messages encryption and signing feature.
$config['enigma_encryption'] = true;

// Enable signing all messages by default
$config['enigma_sign_all'] = false;

// Enable encrypting all messages by default
$config['enigma_encrypt_all'] = false;

// Enable attaching a public key to all messages by default
$config['enigma_attach_pubkey'] = false;

// Default for how long to store private key passwords (in minutes).
// When set to 0 passwords will be stored for the whole session.
$config['enigma_password_time'] = 0;

// With this option you can lock composing options
// of the plugin forcing the user to use configured settings.
// The array accepts: 'sign', 'encrypt', 'pubkey'.
// For example, to force your users to sign every email,
// you should set:
//     - enigma_sign_all     = true
//     - enigma_options_lock = array('sign')
//     - dont_override       = array('enigma_sign_all')
$config['enigma_options_lock'] = array();

from here

In this article I described how we implemented client-side encryption in Roundcube using Mailvelope. There’s another approach for encryption, it is the Enigma plugin. It implements all the functionality using server-side GNUPG software. So, the big difference in these is that: Mailvelope keeps your keys in the browser, Enigma stores them on the server. In the current state Enigma however, has a lot more features.

Installation and settings

To use Enigma just enable it as any other plugin. Then in Preferences > Settings > Encryption you’ll see a set of options that will give you possibility to enable/disable encryption-related features.

NOTE: As keys are stored on the server, make sure the directory used as a storage has proper permissions, and it’s good to move it somewhere out of the location accessible from the web (even if secured by .htaccess rules).

Figure 1. Encryption preferences section.

Keys management

To manage your keys goto Settings > PGP Keys. There you can generate a new key pair or import keys. See the following screenshots for more details.

Figure 2. Key generation form.

Figure 3. Key information frame.

Composing messages

In message compose screen a new toolbar button is added with popup where you can decide if the message have to be signed and/or encrypted. The behaviour and the icon is slightly different than the one used for Mailvelope functionality. Also, note that we did not change the compose screen in any way, so all standard features like responses and spellchecking actually work.

Figure 4. Encryption options in compose.


You can find the Enigma plugin code in Roundcube 1.0 and 1.1, but only the version in Roundcube 1.2 (current git-master) is usable. I put a lot of work into this plugin and I hope there will be users that will use it. It depends on you if that solution will be extended with S/MIME or other features in future versions. Current state is described in the plugin README file .


Install Milter Manager on Centos 7

from here 

Install packages

Postfix is used as MTA because it’s installed by default.

Spamass-milter, clamav-milter and milter-greylist are used as milters. Milter packages registered in EPEL are used.

Register EPEL like the following:

% sudo yum install -y epel-release

Now, you install milters:

% sudo yum install -y spamass-milter-postfix clamav-scanner-systemd clamav-update clamav-milter clamav-milter-systemd milter-greylist

And you install RRDtool for generating graphs:

% sudo yum install -y rrdtool

Build and Install

milter manager can be installed by yum.

Register milter manager yum repository like the following:

% curl -s | sudo bash

See also: <URL:>

Now, you install milter manager:

% sudo yum install -y milter-manager


Here is a basic configuration policy.

milter-greylist should be applied only if S25R condition is matched to reduce needless delivery delay. But the configuration is automatically done by milter manager. You need to do nothing for it.

It’s difficult that milter manager runs on SELinux. Disable SELinux policy module for Postfix and Milter.

% sudo semodule -d postfix
% sudo semodule -d milter

Configure spamass-milter

At first, you configure spamd.

spamd adds “[SPAM]” to spam mail’s subject by default. If you don’t like the behavior, edit /etc/mail/spamassassin/


rewrite_header Subject [SPAM]


# rewrite_header Subject [SPAM]

Add the following configuration to /etc/mail/spamassassin/ This configuration is for adding headers only if spam detected.

remove_header ham Status
remove_header ham Level

Start spamd on startup:

% sudo systemctl enable spamassassin

Start spamd:

% sudo systemctl start spamassassin

Here are spamass-milter’s configuration items:

  • Disable needless body change feature.
  • Reject if score is larger than or equal to 15.

Change /etc/sysconfig/spamass-milter:


#EXTRA_FLAGS="-m -r 15"


EXTRA_FLAGS="-m -r 15"

Start spamass-milter on startup:

% sudo systemctl enable spamass-milter

Start spamass-milter:

% sudo systemctl start spamass-milter

Configure clamav-milter

Update ClamAV virus database and start clamd.

Edit /etc/freshclam.conf like the following. It comments out “Example”, changes “NotifyClamd” value and uncomments other items.


#LogFacility LOG_MAIL
#NotifyClamd /path/to/clamd.conf


LogFacility LOG_MAIL
NotifyClamd /etc/clamd.d/scan.conf

Run freshclam by hand at the first time:

% sudo freshclam

Configure clamd.

Edit /etc/clamd.d/scan.conf like the following. It comments out “Example” and uncomments other items:


#LogFacility LOG_MAIL
#LocalSocket /run/clamd.scan/clamd.sock


LogFacility LOG_MAIL
LocalSocket /run/clamd.scan/clamd.sock

Start clamd on startup:

% sudo systemctl enable [email protected]

Start clamd:

% sudo systemctl start [email protected]

Configure clamav-milter.

Edit /etc/mail/clamav-milter.conf like the following. It comments out “Example”, change “ClamdSocket” value and uncomments other items:


#MilterSocket /run/clamav-milter/clamav-milter.socket
#MilterSocketMode 660
#ClamdSocket tcp:scanner.mydomain:7357
#LogFacility LOG_MAIL


MilterSocket /run/clamav-milter/clamav-milter.socket
MilterSocketMode 660 
ClamdSocket unix:/run/clamd.scan/clamd.sock 
LogFacility LOG_MAIL

Add “clamilt” user to “clamscan” group to access clamd’s socket:

% sudo usermod -G clamscan -a clamilt

Start clamav-milter on startup:

% sudo systemctl enable clamav-milter

Start clamav-milter:

% sudo systemctl start clamav-milter

Configure milter-greylist

Change /etc/mail/greylist.conf for the following configurations:

  • use the leading 24bits for IP address match to avoid Greylist adverse effect for sender uses some MTA case.
  • decrease retransmit check time to 10 minutes from 30 minutes (default value) to avoid Greylist adverse effect.
  • increase auto whitelist period to a week from 1 day (default value) to avoid Greylist adverse effect.
  • don’t use Greylist when trusted domain passes SPF. (Trusted domains are configured in milter manager)
  • use Greylist by default.

The configuration relaxes Greylist check to avoid Greylist adverse effect. It increases received spam mails but you should give priority to avoid false positive rather than false negative. You should not consider that you blocks all spam mails by Greylist. You can blocks spam mails that isn’t blocked by Greylist by other anti-spam technique such as SpamAssassin. milter manager helps constructing mail system that combines some anti-spam techniques.


socket "/run/milter-greylist/milter-greylist.sock"
# ...
racl whitelist default


socket "/run/milter-greylist/milter-greylist.sock" 660
# ...
subnetmatch /24
greylist 10m
autowhite 1w
sm_macro "trusted_domain" "{trusted_domain}" "yes"
racl whitelist sm_macro "trusted_domain" spf pass
racl greylist sm_macro "trusted_domain" not spf pass
racl greylist default

Start milter-greylist on startup:

% sudo systemctl enable milter-greylist

Start milter-greylist:

% sudo systemctl start milter-greylist

Configure milter manager

Add “milter-manager” user to “clamilt” group to access clamav-milter’s socket:

% sudo usermod -G clamilt -a milter-manager

Add “milter-manager” user to “mail” group and “grmilter” group to access milter-greylist’s socket:

% sudo usermod -G mail -a milter-manager
% sudo usermod -G grmilter -a milter-manager

Add “milter-manager” user to “postfix”” group to access spamass-milter’s socket:

% sudo usermod -G postfix -a milter-manager

milter manager detects milters that installed in system. You can confirm spamass-milter, clamav-milter and milter-greylist are detected:

% sudo /usr/sbin/milter-manager -u milter-manager -g milter-manager --show-config

The following output shows milters are detected:

define_milter("milter-greylist") do |milter|
  milter.connection_spec = "unix:/run/milter-greylist/milter-greylist.sock"
  milter.enabled = true
define_milter("clamav-milter") do |milter|
  milter.connection_spec = "unix:/var/run/clamav-milter/clamav-milter.socket"
  milter.enabled = true
define_milter("spamass-milter") do |milter|
  milter.connection_spec = "unix:/run/spamass-milter/postfix/sock"
  milter.enabled = true

You should confirm that milter’s name, socket path and “enabled = true”. If the values are unexpected, you need to change /etc/milter-manager/milter-manager.local.conf. See Configuration for details of milter-manager.local.conf.

But if we can, we want to use milter manager without editing miter-manager.local.conf. If you report your environment to the milter manager project, the milter manager project may improve detect method.

milter manager’s configuration is finished.

Start to milter manager on startup:

% sudo systemctl enable milter-manager

Start to milter manager:

% sudo systemctl start milter-manager

milter-test-server is usuful to confirm milter manager was ran:

% sudo -u milter-manager milter-test-server -s unix:/var/run/milter-manager/milter-manager.sock

Here is a sample success output:

status: accept
elapsed-time: 0.128 seconds

If milter manager fails to run, the following message will be shown:

Failed to connect to unix:/var/run/milter-manager/milter-manager.sock

In this case, you can use log to solve the problem. milter manager is verbosily if –verbose option is specified. milter manager outputs logs to standard output if milter manager isn’t daemon process.

You can add the following configuration to /etc/sysconfig/milter-manager to output verbose log to standard output:

OPTION_ARGS="--verbose --no-daemon"

Restart milter manager:

% sudo systemctl restart milter-manager

Some logs are output if there is a problem. Running milter manager can be exitted by Ctrl+c.

OPTION_ARGS configuration in /etc/sysconfig/milter-manager should be commented out after the problem is solved to run milter manager as daemon process. And you should restart milter manager.

Configure Postfix

Enables Postfix:

% sudo systemctl enable postfix
% sudo systemctl start postfix

Configure Postfix for milters. Append following lines to /etc/postfix/

milter_protocol = 6
milter_default_action = accept
milter_mail_macros = {auth_author} {auth_type} {auth_authen}

For details for each lines.

milter_protocol = 6Use milter protocol version 6.
milter_default_action = acceptMTA receives mails when MTA cannot access milter. Although there are problems between MTA and milter, MTA can deliver mails to clients. But until you recover milter, perhaps MTA receives spam mails and virus mails.

If you can recover the system quickly, you can specify ‘tempfail’ instead of ‘accept’. Default value is ‘tempfail’.

milter_mail_macros = {auth_author} {auth_type} {auth_authen}MTA gives information related SMTP Auth to milters. milter-greylist etc. uses it.

Register milter manager to Postfix. It’s important that spamass-milter, clamav-milter and milter-greylist aren’t needed to be registered because they are used via milter manager.

Append following lines to /etc/postfix/

smtpd_milters = unix:/var/run/milter-manager/milter-manager.sock

Reload Postfix’s configuration.

% sudo systemctl reload postfix

milter manager logs to syslog. If milter manager works well, some logs can be shown in /var/log/maillog. You need to send a test mail for confirming.


There are many configurations to work milter and Postfix together. They can be reduced by introducing milter manager.

Without milter manager, you need to specify sockets of spamass-milter, clamav-milter and milter-greylist to /etc/postfix/ With milter manager, you don’t need to specify sockets of them, just specify a socket of milter manager. They are detected automatically. You don’t need to take care some small mistakes like typo.

milter manager also detects which ‘/sbin/chkconfig -add’ is done or not. If you disable a milter, you use the following steps:

% sudo systemctl stop milter-greylist
% sudo systemctl disable milter-greylist

You need to reload milter manager after you disable a milter.

% sudo systemctl reload milter-manager

milter manager detects a milter is disabled and doesn’t use it. You don’t need to change /etc/postfix/

You can reduce maintainance cost by introducing milter manager if you use some milters on CentOS.

milter manager also provides tools to help operation. Installing them is optional but you can reduce operation cost too. If you also install them, you will go to Install to CentOS (optional) .


after the installation i saw this error in the maillog file

warning: connect to Milter service unix:/run/milter-manager/milter-manager.sock: Permission denied

One solution is :

chown milter-manager:postfix /run/milter-manager/milter-manager.sock

but if you restart milter-manager you return back with the error because the permission over the file is reset.


vim /etc/sysconfig/milter-manager




Incorrect definition of table mysql.event: expected column ‘sql_mode’

[ERROR] Incorrect definition of table mysql.event: expected column ‘sql_mode’ at position 14








Apr 26 04:22:08 mail mysqld: 2020-04-26  4:22:07 0 [ERROR] mysqld: Event Scheduler: An error occurred when initializing system tables. Disabling the Event Scheduler.

i solved copying from the log file how the column has to be set and run this in the mysql db: