From 3fb2b9563d9b58a9683808c6620832dc71f76b20 Mon Sep 17 00:00:00 2001
From: Sam Chudnick FreeIPA is a centralized idenity management solution developed
+ by Redhat. It is in my opinion the most functional libre alternative
+ to Microsoft's Active Directory. Like AD, FreeIPA integrates all of
+ the pieces needed to setup a domain including LDAP, Kerberos,
+ a Certificate Authority, and much more. I will be using Fedora 35 in this tutorial. As of Debian 11, the
+ FreeIPA server is still not in the Debian repos. You will need either
+ a Fedora or a RHEL machine. A CentOS fork may work also but I have not
+ tested that. For readers exploring the use of FreeIPA in a business
+ environment, note that FreeIPA documentation explicitly states that
+ it is not a replacement for Active Directory. I have not personally
+ tried to join a Windows computer to a FreeIPA domain, and so I can't
+ speak to how well that would work. FreeIPA would also not be able to push
+ out policy to Windows machines as is done with Group Policy. FreeIPA
+ is though able to create inter-domain trusts with an existing AD
+ infrastructure. Using a full Kerberos and LDAP identity management server may
+ seem like overkill at home. And if you only have a single computer
+ then it probably is. But scaling up even slightly, to perhaps a small
+ family each with their own computer, will make having FreeIPA
+ advantageous (your family is all using Linux, right?). This
+ will be especially apparent if you are hosting your own services.
+ If you are for instance hosting a Jellyfin media server that everyone
+ in your family accesses, you won't want them to juggle separate
+ passwords for Jellyfin when you could just have them use the same
+ password they do on the computer. This single/same sign-on capability is
+ one of the most practically useful aspects of FreeIPA. We start as usual by installing the required packages. The server will need to have a fully qualified hostname
+ before setting up IPA. You will need both a hostname for the server
+ itself and the domain name you will want for the FreeIPA domain. I
+ will be using ipaserver.myhome.local, where
+ ipaserver is the hostname and myhome.local is the
+ domain name. We'll also need to add a hosts file entry to
+ /etc/hosts. Open that file in an editor and add a new
+ line with the IP of the server, the fully qualified name, and the
+ hostname. Make sure to reboot the server before continuing to complete
+ the hostname change. We'll need to allow several ports for FreeIPA to function properly.
+ Fedora 35 uses firewalld by default but I am going to disable that
+ in favor of UFW here. Now we can run the FreeIPA setup script. This is an interactive but mostly
+ automatic process that will configure all of the IPA components. The
+ --mkhomedir flag will configure the server to create home
+ directories for IPA users on their first login and would otherwise have to be
+ done manually. That command will bring you into the install script. You will be prompted
+ several times before the bulk of the configuration happens. Default values
+ are show in brackets after the prompt. Let's run through those prompts. The install script will now run through configuration. This process usually
+ takes several minutes. When finished you should get a message saying
+ The ipa-server-install command was successful. To finish, run this command to receive a Kerberos TGT. Provide the
+ password for the admin user when prompted. You are now able to manage FreeIPA through the web interface. You can
+ browse either to the IP or the hostname if your DNS is configured correctly.
+ You should see a screen similar to this. Login with the username admin and the password you set during the
+ insallation. You are now ready to begin configuring your IPA domain.
+About Me
FreeIPA Server Setup
FreeIPA in an Enterprise
+
+ The Case for FreeIPA at Home
+ Install Packages
+
+
+ dnf install freeipa-server freeipa-dnsSet Hostname
+
+
+ hostnamectl set-hostname ipaserver.home.local
+
+
+ 192.168.1.10 ipaserver.myhome.local ipaserverFirewall Configuration
+
+
+ #Install UFW
+dnf install ufw
+# Stop and disable firewalld
+systemctl disable --now firewalld
+# Configure UFW
+ufw enable
+ufw allow ssh
+ufw allow dns
+ufw allow 88 comment kerberos
+ufw allow 389 comment ldap
+ufw allow 443 comment webui
+ufw allow 636 comment ldaps
+ufw default deny incoming
+ufw reloadConfigure FreeIPA
+
+
+ ipa-server-install --mkhomedir
+ Do you want to configure integrated DNS (BIND)?:
+ yes
+ Sever host name: the default value should be showing
+ ipaserver.myhome.local which is what we want. Simply hit enter to acecpt
+ the default.
+ Please confirm the domain name: The default here should be
+ correct myhome.local so hit enter to accept that.
+ Please provide a realm name: This should just be the domain
+ name in all uppercase. If the default looks correct just hit enter.
+ Directory Manager password: This is the password for an
+ administrator account used by system services. You will not need this for daily
+ use so I recommend setting it to a long randomly generated string. I have found
+ myself that using an extremely long password here will cause the installation to
+ fail. A password under 40 characters should be safe.
+ IPA admin password: This is the password for your initial admin
+ user. Make this a strong password as this user has full admin rights for the
+ entire domain.
+ Do you want to configure DNS forwarders: This allows you to
+ configure the IPA server to forward DNS requests to another DNS server for
+ zones it is not authoratitve for. The DNS server is configured by default as
+ a recursive DNS server so answering no does not prevent internet access. If you
+ have another DNS server that should be used instead then answer yes and provide
+ the IP address when prompted.
+
+ Do you want to configure chrony with NTP server or pool address?
+ : Here you can configure a custom NTP server or pool for the NTP daemon chrony.
+ If you already have an NTP server on your network answer yes and provide its IP.
+ If you want to leave the deafult chrony configuration then answer no. Time
+ synchronization is very important in Kerberos so you should consider how you
+ want to achieve that on your network. If you do not have an NTP server you may
+ want to configure the IPA server as one later.
+
+ Continue to configure the system with these values?: This is a
+ final confirmation before the script takes over and configures the IPA
+ components. Review the information printed and enter yes if it all looks correct.
+
+
+ kinit adminAccessing the Web Interface
+
+
+
+
+Consider donating if this article was useful.
+[BTC]
+
With the Icinga master node configured, the servers we want + to monitor can now be added as agent nodes. As the names suggest, + the Icinga master node pushes the desired configuration to agent + nodes, while agent nodes report the configured status checks back + to the master. Communication between the master and agent nodes is + encrypted via TLS, with the master node acting as a certificate + authority.
+ +You can find my script to automate this process + + here.
+ +Start by installing the required packages on the server to be + monitored.
+ +apt install icinga2 monitoring-plugins
+monitoring-plugins-contrib
+
+ Now we need to setup the PKI that will be used for the communication + with the master node. The first step is to generate a certificate + signing request. Replace hostname with the FQDN of the server.
+ +icinga2 pki new-cert --cn "hostname" --cert "/etc/icinga2/pki/hostname.crt" --csr "/etc/icinga2/pki/hostname.csr" --key "/etc/icinga2/pki/hostname.key"
+
+ Next we save the master node's public key certificate. Replace + master with the FQDN of your master node.
+ +icinga2 pki save-cert --host "master" --port 5665 --key "/etc/icinga2/pki/hostname.key" --trustedcert "/etc/icinga2/pki/trusted-master.crt"
+
+ Receive signed certificate from the master node.
+ +icinga2 pki request --host "master" --port 5665 --key "/etc/icinga2/pki/hostname.key" --cert "/etc/icinga2/pki/hostname.crt" --trustedcert "/etc/icinga2/pki/trusted-master.crt" --ca "/etc/icinga2/pki/ca.crt"
+
+ Write Icinga configuration.
+ +/etc/icinga2/icinga2.conf
+include "constants.conf"
+const NodeName = "$nodename"
+include "zones.conf"
+include "features-enabled/*.conf"
+include <itl>
+include <plugins>
+include <plugins-contrib>
+include <manubulon>
+include <windows-plugins>
+include <nscp>"
+
+ Write zones configuration.
+ +/etc/icinga2/zones.conf
+echo "object Endpoint "hostname" {}
+object Zone "hostname" {
+ parent = "master"
+ endpoints = [ "hostname" ]
+}
+object Zone "master" {
+ endpoints = [ "master" ]
+}
+object Endpoint "master" {
+ host = "master"
+}
+object Zone "director-global" {
+ global = true
+}
+
+ Write API configuration file.
+ +/etc/icinga2/features-available/api.conf
+echo "object ApiListener \"api\" {
+ accept_commands = true
+ accept_config = true
+}
+
+ Next, we need to enable the API on the agent.
+ +icinga2 feature enable api
+
+mkdir -p /var/lib/icinga2/certs
+
+cp /etc/icinga2/pki/hostname.crt /etc/icinga2/pki/hostname.key /etc/icinga2/pki/ca.crt /var/lib/icinga2/certs/
+
+chown -R nagios: /var/lib/icinga2/certs/
+
+ The only action needed on the master node is to sign the agent's + CSR. Logon to your master node and run the following:
+ +fpr="$(icinga2 ca list | tail -1 | cut -d '|' -f 1)"
+icinga2 ca sign $fpr
+
+ Before finishing we need to open the proper firewall port. + I will use UFW in the example here and allow traffic only only + from the master node for best security.
+ +ufw allow proto tcp from master-ip to any port 5665
+
+ Finally, restart the icinga service on the agent node.
+ +systemctl restart icinga2
+
+ The Icinga agent node will now pull down configuration from the master. + You will know that this worked if /var/lib/icinga2/api/zones + begins to populate with new files.
++
Icinga Director is the web-based configuration tool for Icinga2. + Director provides a simple interface for configuring the various parts + of your monitoring environment. Even if you would rather do all of + the configuration from a terminal, I still recommend using Director for + its self-service API which allows new nodes to register with no interaction + required on the node (i.e. via a script).
+ +Start by logging into your Icinga instance. If you followed the + master installation guide you should have + a tab labeled Icinga Director. Click on that, and you should + see something similar to this:
+
+
+ Let's start by looking at the hosts section. Clicking on the hosts + button from the Director menu will present you with several options. + Click on host templates, and then click add to define our first host + template. Host templates are the building blocks of Icinga, they allow + for your nodes to be structured however you see fit, and then to have + monitoring checks automatically applied to them based on that structure.
+I like to structure my host templates by operating system. For example, + I have a template called Linux Server, which is designed + to encompass all of the Linux servers in my environment. I then get more + specific, creating templates based on distro. These templates are children + of the Linux Server template, so they inherit whatever is applied to the + parent, but then can have distro-specific checks applied to themselves.
+Start by giving your template a name - I will use Linux Server + here. Groups can be left empty for now, but you may want to + add groups and apply them to templates later. The check command should + be set to hostalive. Expand Icinga Agent and zone settings + and set Icinga2 Agent, Establish connection, + and Accepts config to Yes. Click store to save the template. + Your template should look like this:
+ +
+
+ Let's turn to services now. Return to the Director menu and select + Services. The services menu is structured similar to hosts, and we will + start with the service templates section. The idea behind service templates + is very similar to host templates. Typically, a service template corresponds + to a single monitoring command.
+As an example, we'll create a service template for a monitoring + command that checks the status of a web server. Give the template a + name, set the check command to http, and finally expand Icinga + Agent and zone settings and set Run on agent + to no. We set this to no because we want Icinga to query + the web server externally instead of from the web server itself.
+ +
+
+ Service sets are simply groups of service templates. They can be + structured however you see fit. Service sets can then be applied to + hosts/host templates to have the checks be automatically applied.
+ +Add a new service set and give it a name. Then click on the services + tab and add all of the services you want to group into that set. + Here is an example of a service set Linux Standard + that has service checks that should be applied to all Linux servers.
+ +
+
+ To bring service sets and host templates together, return to your host + templates, select Linux Server, select the services tab, and then select + add service set and choose your desired set from the dropdown menu.
+ +
+
+ When you have made all of the changes you need you will need to + render the Director configuration. Return to the Director menu, + select Config Deployment, and then select Render config.
+ +In this last section we will look at what I think is the best feature + of Director which is the self service API. To enroll a host template + in the self service API, select the host template, select the agent + tab, and select generate self service api key. That's it! + The string of letters and numbers is the API key associated with this + host template. Hosts can be enrolled with this API key and Icinga + will automatically assign the host to this template. With proper + structuring, you can have hosts be completely provisioned without + touching Director. In the next article, we will use this to enroll + a host in Icinga with a shell script.
++
Icinga2 has built-in support for writing monitoring data to InfluxDB. + This makes Icinga quite extensible as it allows for other programs to read + the gathered data from InfluxDB. For example, Icinga does not have built-in + graphing support. But monitoring data can be written to InfluxDB and then + consumed by a dedicated graphing tool like Grafana.
+ +Let's install a few necessary packages
+ +apt install influxdb influxdb-client ssl-cert
+
+ Now generate a self-signed certificate for accessing InfluxDB over TLS
+ +make-ssl-cert generate-default-snakeoil
+usermod -aG ssl-cert influxdb
+
+ Start and enable the InfluxDB service
+ +systemctl enable --now influxdb
+
+ Now we'll create our database and users. We'll be creating 3 users with + different access rights. An admin user with full control over the database, a + user with write access that Icinga will use to write data to the database, and + a read-only user to allow external programs to read data from the database.
+ +influx -ssl -unsafeSsl -execute "create database icinga2; create user admin with password 'changeme'; create user icingauser with password 'changeme'; create user readonly with password 'changeme'; grant all to admin; grant write on icinga2 to icingauser; grant read on icinga2 to readonly;"
+
+
+Then write InfluxDB's configuration file at + /etc/influxdb/influxdb.conf
+ +reporting-enabled = false
+[meta]
+ dir = "/var/lib/influxdb/meta"
+[data]
+ dir = "/var/lib/influxdb/data"
+ wal-dir = "/var/lib/influxdb/wal"
+[coordinator]
+[retention]
+[shard-precreation]
+[monitor]
+[http]
+ enabled = true
+ bind-address = ":8086"
+ auth-enabled = true
+ https-enabled = true
+ https-certificate = "/etc/ssl/certs/ssl-cert-snakeoil.pem"
+ https-private-key = "/etc/ssl/private/ssl-cert-snakeoil.key"
+[ifql]
+[logging]
+[subscriber]
+[[graphite]]
+[[collectd]]
+[[opentsdb]]
+[[udp]]
+[continuous_queries]
+[tls]
+ min-version = "tls1.2"
+
+ And restart InfluxDB to pickup the changes
+ +systemctl restart influxdb
+
+ Then we need to configure Icinga to write data to our database. Start by + enabling the influxdb feature in Icinga
+ +icinga2 feature enable influxdb
+
+ Now we tell Icinga how to write to our database. Open the configuration + file at /etc/icinga2/features-available/influxdb.conf and replace + with the following
+ +object InfluxdbWriter \"influxdb\" {
+ host = "127.0.0.1"
+ port = 8086
+ username = "icingauser"
+ password = "icinga_password"
+ ssl_enable = true
+ database = "icinga2"
+ flush_threshold = 1024
+ flush_interval = 10s
+ host_template = {
+ measurement = "$host.check_command$"
+ tags = {
+ hostname = "$host.name$"
+ }
+ }
+ service_template = {
+ measurement = "$service.check_command$"
+ tags = {
+ hostname = "$host.name$"
+ service = "$service.name$"
+ }
+ }
+}
+
+ And finally restart Icinga to make those changes live.
+ +systemctl restart icinga2
+
+ Icinga2 will now be writing the data it collects to your InfluxDB instance.
+ ++
+This tutorial will cover the installation of the Icinga2 +monitoring application master node. This includes the base +program, the web frontend, and the web-based configuration tool. +This guide was made for Debian but should be similar +on other distributions. +
++I have a script available to automate the steps described in this +tutorial available +from my git repo. +
Here we will install the required packages. Icinga can use either MySQL +or PostgreSQL, however this tutorial will use MySQL/MariaDB.
+apt install icinga2 icingaweb2 icinga2-ido-mysql icingaweb2-module-director monitoring-plugins monitoring-plugins-contrib default-mysql-server
+This step is optional but strongly recommended. +The mysql_secure_installation script will harden your MySQL instance.
+mysql_secure_installation
+I recommend the following responses: +
The next several sections will cover creating databases for the various +parts of Icinga. We'll start with the monitoring database. +The following command creates a MySQL database named icinga2 +and grants permissions to a user named ido_admin. These values +are arbitrary, but I use them throughout the tutorial so I recommend leaving them +as is. You should definitely change the password though, which in the command +is change me. You will need this password and the passwords for the +other databases later, so make sure you save them.
+mysql -u root -e "CREATE DATABASE icinga2; GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON icinga2.* TO ido_admin@'localhost' IDENTIFIED BY 'change me'; FLUSH PRIVILEGES;
+
+We then need to import the ido schema into the database.
+ +mysql -u root icinga2 </usr/share/icinga2-ido-mysql/schema/mysql.sql
+
+After importing the schema, we then write the configuration file that tells +the monitoring module how to connect to the database.
+/etc/icinga2/features-available/ido-mysql.conf
+library "db_ido_mysql"
+object IdoMysqlConnection "ido-mysql" {
+ user = "ido_admin",
+ password = "ido_password",
+ host = "localhost",
+ database = "icinga2"
+}"
+
+And finally we enable the monitoring module in Icinga.
+icinga2 feature enable ido-mysql
+
+This step is nearly identical to the last. This time we create a database +named icingaweb2 and grant permissions to the user named +icingaweb2_admin.
+mysql -u root -e "CREATE DATABASE icingaweb2;GRANT ALL ON icingaweb2.* TO 'icingaweb2_admin'@'localhost' IDENTIFIED BY 'changeme'; FLUSH PRIVILEGES;
+
+Again we will need to import required schema into the database.
+mysql -u root icingaweb2 </usr/share/icingawbe2/etc/schema/mysql.schema.sql
+
+
+In this step we create the initial admin user that will be used to login +to the web interface. As is, this would create a user named admin +with the password changme. You should at least change the password.
+passhash="$(php -r "echo password_hash(\"changeme\", PASSWORD_DEFAULT);")"
+mysql -u root -e "USE icingaweb2; INSERT INTO icingaweb_user (name, active, password_hash) VALUES (\"admin\", 1, \"$passhash\"); FLUSH PRIVILEGES;"
+
+Here we create the database for Director. Director will require more +configuration later, so for now we will just be creating the database.
+mysql -u root -e "CREATE DATABASE director CHARACTER SET 'utf8'; GRANT ALL on director.* TO 'director'@'localhost' IDENTIFIED BY '$director_password';FLUSH PRIVILEGES;"
+
+Run the following command to initialize the Icinga API.
+icinga2 api setup
+And then restart Icinga to apply the changes.
+systemctl restart icinga2
+
+In this section we will configure the web server for accessing +Icinga's web interface and Director configuration tool. +This tutorial will use nginx but apache could be used as well. +We'll start by installing the necessary packages.
+apt install nginx php-fpm
+Then we need to create the site configuration file.
+
/etc/nginx/sites-available/icingaweb2.conf
+server {
+ listen 80;
+ server_name monitoring.example.com
+ location ~ ^/icingaweb2/index\.php(.*)$ {
+ fastcgi_pass unix:/var/run/php/php-fpm.sock;
+ fastcgi_index index.php;
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME /usr/share/icingaweb2/public/index.php;
+ fastcgi_param ICINGAWEB_CONFIGDIR /etc/icingaweb2;
+ fastcgi_param REMOTE_USER $remote_user;
+ }
+
+ location ~ ^/icingaweb2(.+)? {
+ alias /usr/share/icingaweb2/public;
+ index index.php;
+ try_files $1 $uri $uri/ /icingaweb2/index.php$is_args$args;
+ }
+
+ # Not strictly necessary but allows you to get to icinga without
+ # specifying /icingaweb2 in the URL.
+ location = / {
+ return 302 http://$host/icingaweb2;
+ }
+
+}
+And then restart nginx to pick up the changes.
+systemctl restart nginx
+
+At this point we are done with the Icinga setup module and so we +can disable it.
+icingacli module disable setup
+
+In this section we will write several configuration files. Icinga uses +the INI format for its web interface configuration files.
+In this first file we tell Icinga about the various resources it should have +access to. These resources are the three databases created previously. +Replace the password in each section with the corresponding password you set +for that database earlier.
+/etc/icingaweb2/resources.ini
+[icinga2]
+type = "db"
+db = "mysql"
+host = "localhost"
+port = ""
+dbname = "icinga2"
+username = "ido_admin"
+password = "ido password"
+charset = ""
+use_ssl = "0"
+
+[icingaweb2]
+type = "db"
+db = "mysql"
+host = "localhost"
+port = ""
+dbname = "icingaweb2"
+username = "icingaweb2_admin"
+password = "ido password"
+charset = ""
+use_ssl = "0"
+
+
+[director]
+type = "db"
+db = "mysql"
+host = "localhost"
+port = ""
+dbname = "director"
+username = "director"
+password = "director password"
+charset = "utf8"
+use_ssl = "0"
+
+
+This file controls the authentication settings for the web interface. +Here we tell Icinga to look at the icingaweb2 database for +authentication purposes.
+/etc/icingaweb2/authentication.ini
+[icingaweb2]
+backend = "db"
+resource = "icingaweb2"
+
+Now we tell icinga which users should have admin permissions. +If you changed the username value from admin previously, be sure to update +it here.
+/etc/icingaweb2/roles.ini
+[admins]
+users = "admin"
+resource = "icingaweb2"
+
+Enable the web interface monitoring module.
+icingacli module enable monitoring
+Then write the configuration file pointing the monitoring module to the +monitoring database.
+/etc/icingaweb2/modules/monitoring/backends.ini
+[icinga]
+type = "ido"
+resource = "icinga2"
+
+Here we configure Icinga to use the API for communication. +You will need to get your unique API password generated during the API setup from +from /etc/icinga2/conf.d/api-users.conf. +hostname should be the FQDN of the server.
+/etc/icingaweb2/modules/monitoring/commandtransports.ini
+[icinga2]
+transport = "api"
+host = hostname
+port = "5665"
+username = "root"
+password = "api password"
+
+Lastly, tell Icinga to protect variables with potentially sensitive values.
+/etc/icingaweb2/modules/monitoring/config.ini
+[security]
+protected_customvars = "*pw*,*pass*,*community*"
+
+
+This section will cover configuring Director configuration tool.
+Create Director module configuration directory.
+mkdir -p /etc/icingaweb2/modules/director
+
+Write the Director configuration file.
+/etc/icingaweb2/modules/director/config.ini
+[db]
+resource = "director"
+
+Enable Director module and run the initial migration.
+icingacli module enable director
+icingacli director migration run
+
+Write Director kickstart configuration file.
+/etc/icingaweb2/modules/director/kickstart.ini
+[config]
+endpoint = "hostname"
+username = "root"
+password = "api password"
+
+Kickstart Director, then render and deploy the configuration.
+icingacli director kickstart run
+icingacli director config render
+icingacli director config deploy
+
+Director is setup at this point so we will shred the unneeded configuration +file containing sensitive information.
+shred -uz /etc/icingaweb2/modules/director/kickstart.ini
+
+You are now ready to login to your monitoring instance with the admin +user created previously. Open a web browser and go to +http://hostname/icingaweb2. You should see a screen similar to this:
+
+
+In the following articles we will go through setting up Icinga2 agents on servers, and configure your monitoring instance through Icinga Director.
++
Linux Unified Key Setup (LUKS) is a method for encrypting + block devices that is built-in to the Linux Kernel. In this tutorial + I will be showing how to create an encrypted USB drive with LUKS, but + this process is applicable to other types of storage. + This process will wipe all data on the device that you + encrypt so make backups beforehand if needed.
+ +Install cryptsetup and its dependencies
+ +apt install cryptsetup
+
+ If the device you are encrypting was previously used, you will + want to completely overwrite any data on it before encryption. This + can be done using dd as shown below. This could take + a very long time depending on the size and type of your drive. + Be sure that you enter the correct path to your drive as the + argument to of, and do not specify a partition: + /dev/sdb is correct, /dev/sdb1 is + wrong. Obviously this will destroy any data on the device so be + absolutely sure you specify the correct device in the command + and have backups of data previously stored if needed.
+ +dd if=/dev/zero of=/dev/sdX status=progress
+
+ cryptsetup is the main command used to perform + LUKS-related tasks. This main command is followed by a subcommand + that specifies which action to perform. To create a LUKS partition + on a drive we need to use the subcommand luksFormat. + We also use the type option to explicitly say to use LUKS version 2 + encryption. Run the command and then enter and confirm the + encryption password.
+ +cryptsetup --type luks2 luksFormat /dev/sdX
+
+ Now we need to open and map the encrypted LUKS device. This is done + by using the luksOpen subcommand. This subcommand takes + the device as the first argument and then a map target as the second. The + map target can be any string as long as a map does not already exist with + that name. In the example I will use crypt. + +
cryptsetup luksOpen /dev/sdX crypt
+
+ And then we just need to create a filesystem on the device; I will + be making an ext4 filesystem in the example. To + interact with an encrypted drive after it has been opened you need + to refer to its device mapper target, which is found under /dev/mapper. + Since we used crypt as the map target, our encrypted drive + is /dev/mapper/crypt.
+ +mkfs.ext4 /dev/mapper/crypt
+
+ After creating the filesystem created the encrypted drive + can now be mounted and used like any other device. Remember that + when mounting the device you refer to the device mapper target + (mount /dev/mapper/crypt /mnt/crypt).
+ +In addition to unmounting the filesystem you should always close + the device mapping before removing your encrypted drive. This is + done with the luksClose subcommand and takes + the device mapping as the argument.
+ +cryptsetup luksClose /dev/mapper/crypt
+
+ The LUKS header sits at the front of your encrypted drive and is + responsible for managing access to the device. If the header is + damaged accessing your encrypted data will not be possible. Because of + this, you may want to make backups of the header, but before doing so + you need to weigh the risks and benefits.
+ +The obvious benefit is that + in the event of damage to the LUKS header, you can easily restore a + backup and regain access to the data. However, having a backup of the + header makes it harder to wipe the LUKS device. Without a header + backup, overwriting the LUKS header on the device is enough to securely + wipe the drive. With backups, you need to either destroy all header + backups or overwrite all encrypted data on the device. The other main risk + is that an encryption password that is valid at the time you make a + backup will always be valid for that backup. For example, say you change + the encryption password on your device after making a backup because it + has been compromised. An attacker would be able to restore the header + backup and then use the compromised password to access the data.
+ +The cryptsetup documentation refers to creating header backups + as making a trade-off between safety and security. You need to make a + decision based on your individual use-case. It's a good idea to + routinely update your header backups if you do choose to make them
+ +When creating or restoring a header backup you always refer to the + block device in the command, not the device mapper taget. To create + a header backup:
+ +cryptsetup luksHeaderBackup /dev/sdX --header-backup-file path/to/backup
+
+ To restore a header from a backup:
+ +cryptsetup luksHeaderRestore /dev/sdX --header-backup-file path/to/backup
+
+ Note that is not necessary to store header backups on an encrypted + device. I would recommend storing backups on at least one non-encrypted + drive in case of an emergency.
+ ++
Postfix and dovecot will be the two primary pieces of our mail sever. +Postfix is the mail transport agent that handles the sending and +receiving of mail and dovecot is the IMAP server that will allow us to +access our mail from a mail client such as mutt. The server will also +have several other supporting components, a complete list of which is:
+ +You can use +this script I have written to automate this process, but I would +recommend that you run through the tutorial first to understand +what is being done.
+ +Please note that this tutorial is loosely intended for small personal mail +servers. Using PAM for authentication, as is done here, is not a scalable solution +for working with a large number of users. I do plan on covering Dovecot LDAP +authentication at some point which would be a better solution in an enterprise +setting.
+ +Let's start by installing the required packages. Note that if you already +have Apache installed on the server, replace python3-certbot-nginx +with python3-certbot-apache.
+apt install postfix dovecot-imapd dovecot-sieve opendkim opendkim-tools spamassassin gnupg postgrey postfix-policyd-spf-python opendmarc dbconfig-no-thanks certbot python3-certbot-nginx
+During the installation of Postfix you will get a Debconf prompt in which +you need to select "Internet Site" and then provide your domain name, +example.com.
+ +Now we'll use Certbot to get a certificate for our server. If you are +using Apache replace nginx with apache2.
+ +systemctl stop nginx
+certbot certonly --standalone -d mail.example.com
+systemctl start nginx
+
+In this section we will be doing the bulk of the postfix configuration. +The postconf command used throughout appends (or changes) +the specified configuration item in /etc/postfix/main.cf
+ +Let's start by configuring some network and domain information.
+ +postconf -e "myorigin = example.com"
+postconf -e "mydestination = \$myhostname, \$mydomain, localhost"
+postconf -e "mynetworks = 127.0.0.0/8 [::1]/128"
+postconf -e "myhostname = mail.example.com"
+
+
+Next, point postfix to the cerbot key and certificate, as well as the distro's +CA certificates.
+ +postconf -e "smtpd_tls_key_file=/etc/letsencrypt/live/mail.example.com/privkey.pem"
+postconf -e "smtpd_tls_cert_file=/etc/letsencrypt/live/mail.example.com/fullchain.pem"
+postconf -e "smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt"
+
+
+Harden the TLS configuration by forcing strong +protocols and ciphers, and requiring that authentication occur only over an +encrypted session.
+# Require authentication over TLS and optionally use it for sending and receiving mail
+postconf -e "smtpd_tls_auth_only = yes"
+postconf -e "smtpd_tls_security_level = may"
+postconf -e "smtp_tls_security_level = may"
+
+# Force the use of TLSv1.2 or TLSv1.3
+postconf -e 'smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1'
+postconf -e 'smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1'
+postconf -e 'smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1'
+postconf -e 'smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1'
+
+# Prefer server ciphers
+postconf -e "tls_preempt_cipherlist = yes"
+
+# Force strong ciphers
+postconf -e "smtpd_tls_ciphers = high"
+postconf -e "smtpd_tls_mandatory_ciphers = high"
+postconf -e "smtp_tls_ciphers = high"
+postconf -e "smtp_tls_mandatory_ciphers = high"
+postconf -e "smtpd_tls_exclude_ciphers = aNULL, eNULL, EXP, LOW, MEDIUM, PSK, SRP, SHA1, kRSA, CAMELLIA, ARIA, DSS, RSA+AES, ADH, AECDH"
+postconf -e "smtp_tls_exclude_ciphers = aNULL, eNULL, EXP, LOW, MEDIUM, PSK, SRP, SHA1, kRSA, CAMELLIA, ARIA, DSS, RSA+AES, ADH, AECDH"
+
+
+Here we configure the bulk of the postfix built-in security settings which are +structured as a series of access restrictions. Do not edit these settings without +first reading the Postfix documentation as an incorrect change could inadvertently +make your server an open relay.
+ +postconf -e "smtpd_helo_required = yes"
+postconf -e "smtpd_sender_login_maps = proxy:hash:/etc/postfix/login_maps"
+postconf -e "smtpd_helo_restrictions = reject_unknown_helo_hostname, reject_non_fqdn_helo_hostname"
+postconf -e "smtpd_sender_restrictions = reject_sender_login_mismatch, reject_non_fqdn_sender, reject_unknown_sender_domain"
+postconf -e "smtpd_recipient_restrictions = reject_non_fqdn_recipient, reject_unknown_recipient_domain, permit_sasl_authenticated, reject_unauth_destination, check_policy_service unix:private/postgrey, check_policy_service unix:private/policyd-spf, reject_rbl_client zen.spamhaus.org"
+postconf -e "smtpd_relay_restrictions = permit_sasl_authenticated, reject_unauth_destination"
+postconf -e "smtpd_data_restrictions = reject_unauth_pipelining"
+
+# Disable VRFY command to prevent harvesting of user accounts on system
+postconf -e "disable_vrfy_command = yes"
+
+# Change smptd banner (hide distribution)
+postconf -e "smtpd_banner = \$myhostname ESMTP \$mail_name"
+
+Now, configure the local mail recipients and some aliases. We'll create +an account called mailadmin to receive mail addressed to +several other accounts. This is to keep administrative mail separate, but +you can certainly alias these to your main account later if you would prefer to see +it there.
+ +# Set a custom local_recipient_maps here in order to avoid accepting mail for all local accounts
+postconf -e "local_recipient_maps = proxy:hash:/etc/postfix/local_maps \$alias_maps"
+
+# You will need to manually set a password later to login as mailadmin
+adduser --disabled-login --shell /usr/sbin/nologin --gecos "" mailadmin
+echo "# postfix aliases
+postmaster: mailadmin
+root: mailadmin
+dmarc: mailadmin
+" > /etc/aliases
+
+# Update address databases
+echo "mailadmin@mail.example.com mailadmin" > /etc/postfix/login_maps
+echo "mailadmin mailadmin" > /etc/postfix/local_maps
+newaliases
+postmap /etc/postfix/login_maps
+postmap /etc/postfix/local_maps
+
+
+These commands configure our mail delivery preferences. Mail will be +delivered inside a user's home folder with a maildir-style mailbox using +dovecot.
+ +# Maildir delivery to $HOME/Mail/Inbox/
+postconf -e "home_mailbox = Mail/Inbox/"
+# Deliver mail with Dovecot
+postconf -e "mailbox_command = /usr/lib/dovecot/deliver"
+
+Header and body checks allow for some simple content filtering within Postfix. +This is done by scanning a message line by line for a configured regex string, +nothing more. For example, the first header check listed will reject a message +with an attachment of ransomware.exe but will not block it if sent with +no extension. This is mostly a protection against uneducated users and poorly +written mail clients. Other checks block vulnerabilities and improve privacy.
+ +Create a new file /etc/postfix/header_checks, then open it in a +text editor and add the following
+# Block files with common executable extensions
+/name=[^>]*\.(exe|pif|com|dll|vbs|bat|sh|bash|so|zip|tar|gz|cpio)/ REJECT
+
+# Block message/partial vulnerability
+/message\/partial/ REJECT
+
+# Remove Received string that is created when spamassassin reinjects message into postfix
+# This is to prevent leaking the userid of the spamassassin user
+/^Received:.*userid.*/ IGNORE
+
+# Remove User-Agent strings from headers
+/^User-Agent: .*/ IGNORE
+
+Create another new file /etc/postfix/body_checks, and add this
+# Block messages with iframes
+/<iframe/ REJECT" > /etc/postfix/body_checks
+
+And then run these commands to point postfix to the check files.
+postconf -e "header_checks = regexp:/etc/postfix/header_checks"
+postconf -e "body_checks = regexp:/etc/postfix/body_checks"
+
+This simple command configures the SMTP client process that is responsible +for sending your mail to other mail servers.
+ +postconf -M "smtp/unix=smtp unix - - y - - smtp"
+
+Postscreen is a kind of firewall that sits in front of the Postfix SMTPD +process and receives all incoming traffic. Postscreen will drop connections +from IPs on a DNS blacklst, or from clients that violate the SMTP protocol by +speaking out of turn or sending non-SMTP commands. This adds up to less spam +connections and therefore a much lighter workload for your server.
+ +postconf -M "smtp/inet=smtp inet n - y - 1 postscreen"
+postconf -M "smtpd/pass=smtpd pass - - y - - smtpd"
+postconf -P "smtpd/pass/content_filter=spamassassin"
+postconf -M "tlsproxy/unix=tlsproxy unix - - y - 0 tlsproxy"
+postconf -M "dnsblog/unix=dnsblog unix - - y - 0 dnsblog"
+postconf -e "postscreen_dnsbl_sites = zen.spamhaus.org"
+postconf -e "postscreen_dnsbl_action = enforce"
+postconf -e "postscreen_greet_action = enforce"
+
+
+Submission over TLS (aka submissions) is the process you will use to submit +mail to your server from a mail client. These commands configure submissions to +use a fully-encrypted session, as opposed to STARTTLS, and to only allow access +to authenticated clients.
+ +postconf -M "submissions/inet=submissions inet n - y - - smtpd"
+postconf -P "submissions/inet/smtpd_tls_wrappermode=yes"
+postconf -P "submissions/inet/smtpd_tls_security_level=encrypt"
+postconf -P "submissions/inet/smtpd_tls_auth_only=yes"
+postconf -P "submissions/inet/smtpd_sasl_auth_enable=yes"
+postconf -P "submissions/inet/smtpd_client_restrictions=permit_sasl_authenticated,reject"
+postconf -P "submissions/inet/smtpd_helo_restrictions="
+postconf -P "submissions/inet/smtpd_sender_restrictions=reject_sender_login_mismatch"
+postconf -P "submissions/inet/smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject"
+postconf -P "submissions/inet/syslog_name=postfix/submissions"
+postconf -P 'submissions/inet/smtpd_tls_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1'
+postconf -P 'submissions/inet/smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1'
+
+Having configured submission over TLS on port 465 this step is optional. +STARTTLS is considered by some to be less secure than full-session TLS and +may be vulnerable to exploitation.
+ +postconf -M "submission/inet=submission inet n - y - - smtpd"
+postconf -P "submission/inet/smtpd_tls_security_level=encrypt"
+postconf -P 'submission/inet/smtpd_tls_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1'
+postconf -P 'submission/inet/smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1'
+postconf -P "submission/inet/smtpd_sasl_auth_enable=yes"
+postconf -P "submission/inet/smtpd_tls_auth_only=yes"
+postconf -P "submission/inet/syslog_name=postfix/submission"
+postconf -P "submission/inet/smtpd_helo_restrictions="
+postconf -P "submission/inet/smtpd_client_restrictions=permit_sasl_authenticated,reject"
+postconf -P "submission/inet/smtpd_helo_restrictions="
+postconf -P "submission/inet/smtpd_sender_restrictions=reject_sender_login_mismatch"
+postconf -P "submission/inet/smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject"
+
+
+Finally, this command tells Postfix how to interact with SpamAssassin.
+ +postconf -M "spamassassin/unix=spamassassin unix - n n - - pipe user=debian-spamd argv=/usr/bin/spamc --socket=/var/run/spamd.sock -e /usr/sbin/sendmail -oi -f \${sender} \${recipient}"
+
+Dovecot configuration is usually split up into many different files under +/etc/dovecot/conf.d/ but here will be doing all of the +configuration in the primary config file +/etc/dovecot/dovecot.conf. Open that file with your editor +of choice, clear all of its contents, and then replace it with the following.
+ +# /etc/dovecot/conf.d/10-auth.conf
+disable_plaintext_auth = yes
+auth_username_format = %n
+auth_mechanisms = plain
+userdb {
+ driver = passwd
+}
+passdb {
+ driver = pam
+}
+
+# /etc/dovecot/conf.d/10-mail.conf
+mail_location = maildir:~/Mail:INBOX=~/Mail/Inbox:LAYOUT=fs
+namespace inbox {
+ type = private
+ prefix =
+ separator = /
+ inbox = yes
+ subscriptions = yes
+ list = yes
+}
+
+# /etc/dovecot/conf.d/10-master.conf
+service imap-login {
+# Run login processes in high-security mode (see: LoginProcess.txt in dovecot docs)
+service_count = 1
+# Disable unencrypted IMAP by setting port for plain IMAP to 0
+ inet_listener imap {
+ port = 0
+ }
+ inet_listener imaps {
+ port = 993
+ ssl = yes
+ }
+}
+
+# Allow postfix to use dovecot SASL
+service auth {
+ unix_listener /var/spool/postfix/private/auth {
+ mode = 0660
+ user = postfix
+ group = postfix
+ }
+}
+
+# /etc/dovecot/conf.d/10-ssl.conf
+ssl = required
+ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem
+ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem
+ssl_client_ca_dir = /etc/ssl/certs
+ssl_dh = </usr/share/dovecot/dh.pem
+
+# Mozilla intermediate compatibility
+ssl_min_protocol = TLSv1.2
+ssl_cipher_list = ECDHE+ECDSA+AESGCM:ECDHE+aRSA+AESGCM:ECDHE+ECDSA+CHACHA20:ECDHE+aRSA+CHACHA20:DHE+aRSA+AESGCM:!aNULL:!eNULL
+
+ssl_prefer_server_ciphers = yes
+ssl_client_require_valid_cert = yes
+
+
+# /etc/dovecot/conf.d/15-lda.conf
+protocol lda {
+ mail_plugins = \$mail_plugins sieve
+}
+
+# /etc/dovecot/conf.d/15-mailboxes.conf
+namespace inbox {
+ mailbox Sent {
+ special_use = \Sent
+ auto = subscribe
+ }
+ mailbox Trash {
+ special_use = \Trash
+ auto = create
+ autoexpunge = 30d
+ }
+ mailbox Drafts {
+ special_use = \Drafts
+ auto = subscribe
+ }
+ mailbox Spam {
+ special_use = \Junk
+ auto = create
+ autoexpunge = 30d
+ }
+ mailbox Archive {
+ special_use = \Archive
+ auto = create
+ }
+}
+
+# /etc/dovecot/conf.d/20-imap.conf
+imap_capability = +SPECIAL-USE
+
+# /etc/dovecot/conf.d/90-sieve.conf
+plugin {
+ sieve = ~/.dovecot.sieve
+ sieve_default = /var/lib/dovecot/sieve/default.sieve
+ sieve_global = /var/lib/dovecot/sieve/
+}
+
+Then create the default sieve filtering script at +/var/lib/dovecot/sieve/default.sieve
+require ["fileinto", "mailbox"];
+/*
+* Discard mail that has a spam score greater than or equal to 10
+*/
+if header :contains "X-Spam-Level" "**********" {
+ discard;
+ stop;
+}
+/*
+* Discard messages marked as infected by a virus scanner
+*/
+if header :contains "X-Virus-Scan" "infected" {
+ discard;
+ stop;
+}
+/*
+* If message is marked as spam (and falls below discard threshold) put into spam mailbox
+*/
+if header :contains "X-Spam-Flag" "YES" {
+ fileinto "Spam";
+}
+
+And compile the script
+ +sievec /var/lib/dovecot/sieve/default.sieve
+
+
+Finally, configure PAM authentication for dovecot at +/etc/pam.d/dovecot. Append these changes leaving any include +statements intact.
+auth required pam_unix.so
+account required pam_unix.so
+
+DKIM is a mail-verification method that cryptographically signs mail +to allow receivers to verify the authenticity of the sender. Our mail server +will use DKIM to validate signatures on incoming mail and sign outgoing mail. DKIM +requires a public key to be published via DNS, which will be done near the end of +the guide.
+ +Start by generating the DKIM key
+ +opendkim-genkey -D /etc/dkimkeys -d example.com -s mail
+chown opendkim: /etc/dkimkeys/*
+chmod 600 /etc/dkimkeys/*
+mv /etc/dkimkeys/mail.private /etc/dkimkeys/mail.pem
+
+Here we make a directory for the opendkim socket inside the postfix chroot and +make it accessible to the postfix user.
+ +mkdir /var/spool/postfix/opendkim
+chmod 770 /var/spool/postfix/opendkim
+chown opendkim:opendkim /var/spool/postfix/opendkim
+usermod -aG opendkim postfix
+
+Edit the configuration file at /etc/opendkim.conf +to be as follows:
+ +On-BadSignature reject
+On-Security reject
+Syslog yes
+SyslogSuccess yes
+LogResults yes
+Canonicalization simple
+Mode sv
+OversignHeaders From
+Domain example.com
+Selector mail
+KeyFile /etc/dkimkeys/mail.pem
+UserID opendkim
+UMask 007
+Socket local:/var/spool/postfix/opendkim/opendkim.sock
+PidFile /run/opendkim/opendkim.pid
+TemporaryDirectory /run/opendkim
+InternalHosts 127.0.0.1
+TrustAnchorFile /usr/share/dns/root.key
+RequireSafeKeys True
+AlwaysAddARHeader True
+
+
+DMARC is another mail-verification technology that provides verification of the +address seen by end-users and either or both of SPF and DKIM. + +
Like with OpenDKIM, we need to make a directory inside the postfix chroot +for the socket and assign proper permissions.
+mkdir /var/spool/postfix/opendmarc
+chmod 770 /var/spool/postfix/opendmarc
+chown opendmarc:opendmarc /var/spool/postfix/opendmarc
+usermod -aG opendmarc postfix
+
+
+Now we write the configuration file at /etc/opendmarc.conf
+ +PidFile /run/opendmarc/opendmarc.pid
+PublicSuffixList /usr/share/publicsuffix/public_suffix_list.dat
+RejectFailures True
+Socket local:/var/spool/postfix/opendmarc/opendmarc.sock
+Syslog True
+SyslogFacility mail
+UMask 002
+UserID opendmarc
+HistoryFile /var/run/opendmarc/opendmarc.hist
+SPFIgnoreResults True
+SPFSelfValidate True
+
+
+Then create the history file and set permissions.
+ +touch /var/run/opendmarc/opendmarc.hist
+chown opendmarc:opendmarc /var/run/opendmarc/opendmarc.hist
+chmod 664 /var/run/opendmarc/opendmarc.hist
+
+
+Now that both OpenDKIM and OpenDMARC are configured we can define them as milters +in postfix. This will tell postfix to route mail through one or both of these milters +depending on whether it is incoming or outgoing.
+ +postconf -P "smtpd/pass/smtpd_milters=unix:opendkim/opendkim.sock,unix:opendmarc/opendmarc.sock"
+postconf -P "submissions/inet/smtpd_milters=unix:opendkim/opendkim.sock"
+# If you enabled submission on port 587 run this too
+postconf -P "submission/inet/smtpd_milters=unix:opendkim/opendkim.sock"
+
+
+Postgrey implements a spam-filter technique known as greylisting, which +always rejects mail on the first try and for a period of time afterwards known +as the greylist period. The idea behind this being that legitimate senders will +send the mail again later, while spammers, in a rush to send as many messages as +possible before being blacklisted, will not.
+ +Postgrey ships with an extensive whitelist domains that are known +to cause issues (mainly large providers that constantly send from different +addresses). This whitelist file is located at +/etc/postgrey/whitelist_clients and can be appended to include +any domain you do not wish to be subject to greylisting.
+ +The configuration needed here is minimal, just open +/etc/default/postgrey and make these changes
+ +POSTGREY_OPTS="--unix=/var/spool/postfix/private/postgrey --privacy"
+POSTGREY_TEXT="Greylisted - see https://www.greylisting.org"
+
+And then enable the service
+ +systemctl enable --now postgrey
+
+SPF is yet another mail-verification technology that uses DNS records to +delegate specific servers as being authorized to send mail for the domain +(and implicitly all other servers as unauthorized). Policyd-SPF will perform +SPF checking of received mail and reject mail that fails SPF verfication.
+ +First, tell postfix how to access Policyd-SPF
+ +postconf -e "policyd-spf_time_limit = 3600"
+postconf -M "policyd-spf/unix=policyd-spf unix - n n - 0 spawn user=policyd-spf argv=/usr/bin/policyd-spf"
+
+And then edit the configuration file at +/etc/postfix-policyd-spf-python/policyd-spf.conf
+ +debugLevel = 1
+TestOnly = 1
+HELO_reject = Fail
+Mail_From_reject = Fail
+Header_Type = AR
+# These settings increase false-positive risk
+# Comment them if you want to reduce that risk
+PermError_reject = True
+TempError_Defer = True
+
+
+SpamAssassin is a spam-filter that will scan all received mail and assign +a spam score based on configured rules. SpamAssassin is much heavier and more +resource-intensive than any of the previous spam-filtering/verification programs +we have configured. The postfix spam-filtering philosophy emphasizes the use +of lightweight checks before passing to an external content filter such as +SpamAssassin. Ideally, non-legitimate mail will have already been caught by one +of the previous methods, and SpamAssassin will only have to operate on a much +smaller subset of the mail that is sent to our server.
+ +We have actually already told postfix to use SpamAssassin as a content filter +so in this section we just need to edit the configuration file +/etc/spamassassin/local.cf.
+ +# Clearly indicate message is spam to user
+rewrite_header Subject *****SPAM*****
+rewrite_header From *****SPAM*****
+
+# Set required score to be marked as spam, 5.0 is default.
+# Lower to make policy more strict or raise to be more lenient.
+required_score 5.0
+
+# Attach original messages as text/plain instead of message/rfc822 to spam reports
+report_safe 2
+
+Do not implicitly trust mail based on IP address except localhost
+trusted_networks 127.0.0.1/32
+
+
+And finally make a few changes to the defaults file at +/etc/default/spamassassin
+ +OPTIONS="--listen /var/run/spamd.sock --max-children 5"
+PIDFILE=/var/run/spamd.pid
+CRON=1
+
+At this point we have done all of the necessary configuration of the mail +server programs. We have just a few more minor tasks before your mail server +is operational.
+ +We need to open the proper ports in the firewall. This example uses UFW.
+ +ufw allow 25 comment "smtp"
+ufw allow 465 comment "submission over TLS"
+# Run this next command only if you enabled submission on port 587
+ufw allow 587 comment "mail submission"
+ufw allow 993 comment "IMAP over TLS"
+ufw reload
+
+Now let's restart the services to pick up any configuration changes.
+ +systemctl restart postfix
+systemctl restart dovecot
+systemctl restart opendkim
+systemctl restart opendmarc
+systemctl enable --now spamassassin
+systemctl restart spamassassin
+systemctl restart postgrey
+
+Finally, we needs to set some required DNS records to enable mail flow and +verification. Begin by logging into your registrar or DNS host and editing +your DNS records.
+ +If you did not set a wildcard A record earlier, you will need to set one now +for mail. +Alternatively, if you are running the mail server on the same server as your +website, you may want to instead make a CNAME record pointing mail to www.
+ +MX records tell servers attempting to send you mail where to send it. Open the +MX records section on your registrar and add a new record. An MX +record consists of a priority and a destination. Set the priority to 10 and the +destination to mail, or whatever your subdomain for this mail +server is. The host value can be left blank or may need to be set to "@" +depending on your registrar.
+ +Now we will set the three TXT records we need. Open the TXT records tab on +your registrar.
+ +We'll set the DKIM record first. The command we ran to +generate our DKIM keys also generates a DNS record for us which will be helpful +here. Print that to the screen with:
+ +cat /etc/dkimkeys/mail.txt
+
+You should get a lengthy output that looks something like the following. The +bolded portion is the value.
+ +mail._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; "
+ "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz50PSYL0Ob+OlF/0B77rwlzLe7zF6JKnxQNtMqcOCZ0Dar2FPhSUSz1FR0YmNuoShjMogdgKeojIzgRUqwK5GZ5Lz456qiXWkfAtLPc6UQ/WPoyEBGbJpRBYPGWdN4VoNcHkk/I4csvXW6MOI55ghPOwDmootPkCzNPR6gmNAXMe0duS4Lb+bIjy9QMOxGYVUaQ/b+7xar+fWw"
+ "bA3DjQa3jTLCydzzJpjEMfVaKqNhQ4N+ve7O2Mb3LF5k5B977mtok/6POjVG5HY8g6Pba+GzMFItR6nJO5EE2fyfv6cNbRLsZiM+WQmqvDBst5ejaeapy86F5PdJFlX/TUgXjtuwIDAQAB" ) ; ----- DKIM key mail for example.com
+
+You can cleanup the spacing of the value as your registrar should automatically +handle any needed splitting of the record. The parts you need to paste into your +registrar's web interface should then look like this.
+ +# Name/Host
+mail._domainkey
+# TXT Value
+"v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz50PSYL0Ob+OlF/0B77rwlzLe7zF6JKnxQNtMqcOCZ0Dar2FPhSUSz1FR0YmNuoShjMogdgKeojIzgRUqwK5GZ5Lz456qiXWkfAtLPc6UQ/WPoyEBGbJpRBYPGWdN4VoNcHkk/I4csvXW6MOI55ghPOwDmootPkCzNPR6gmNAXMe0duS4Lb+bIjy9QMOxGYVUaQ/b+7xar+fWwbA3DjQa3jTLCydzzJpjEMfVaKqNhQ4N+ve7O2Mb3LF5k5B977mtok/6POjVG5HY8g6Pba+GzMFItR6nJO5EE2fyfv6cNbRLsZiM+WQmqvDBst5ejaeapy86F5PdJFlX/TUgXjtuwIDAQAB"
+
+The DMARC record should be as follows:
+ +# Name/Host
+_dmarc
+# Value
+"v=DMARC1; p=reject; rua=mailto:dmarc@example.com; fo=1"
+
+
+Your SPF record will look like this. Remember to replace +mail.example.com with your server name.
+ +# Name/Host
+@
+# Value
+"v=spf1 a:mail.example.com -all"
+
+
+Many mail servers rely on PTR records for verification purposes so we need +to make sure our server's IP address resolves to the proper domain name. If +your mail server is residing on a VPS, you will need to add this record on your +VPS provider's interface, consult their documentation for details.
+ +Your mail server is now up and running. Let's create an email for you to +receive mail.
+ +useradd --shell /usr/sbin/nologin --create-home --user-group user
+echo "user@example.com user" >> /etc/postfix/login_maps
+echo "user user" >> /etc/postfix/local_maps
+postmap /etc/postfix/login_maps
+postmap /etc/postfix/local_maps
+postfix reload
+
+
+I have a script available for adding and removing users that you can find +here. + +
When connecting your account to a mail client you need to use these settings.
+ ++
mdadm is a tool that allows for creation and + management of software RAID arrays on Linux. Creating an array + is a rather straightforward process.
+ +The only package needed is mdadm itself
+apt install mdadm
+
+ We'll need to parition the disks to be used in the array before + creating it. This isn't anything complicated, we will just be + creating a single partition using all the space on each disk.
+ +Use lsblk to get a list of disks attached to your system.
+ +
+
+ Then use fdisk to edit the partition table of the + first disk. In my case this would be /dev/sdb. + Be sure that you are selecting the correct disk as selecting the + wrong one can result in data being lost.
+ +fdisk /dev/sdb
+
+ Use g to create a new GUID partition table. + Use n to create a new partition, and then just press + enter at all of the prompts to accept the defaults. Finally use + w to write the changes. You can use lsblk again + to verify the change and you should see that /dev/sdb now has a + partition /dev/sdb1.
+ +
+
+ Repeat this process for your other disks before continuing.
+ + +Creating the array is done with a single command, but takes just a + bit of planning.
+mdadm --create /dev/md0 --level=5 --raid-devices=3 /dev/sdb1 /dev/sdc1 /dev/sdd1 --spare-devices=1 /dev/sde1
+
+ After creating the array run the following command to get details + and the status of the array. It will take a bit to initialize the + array, you will know this is done when the state is clean. You do not + need to wait for the array to completely intialize to continue.
+ +mdadm --detail /dev/md0
+
+ Take note of the UUID and name values as we will need them in the + next step.
+ +Before moving on we need to make a filesystem on the array. I'm + going to make a simple EXT4 filesystem here.
+ +mkfs.ext4 /dev/md0
+
+
+ Open the mdadm configuration file at + /etc/mdadm/mdadm.conf and append this line. Replace + uuid and name with the values you got when running + mdadm --detail, replace 0 whatever ID you chose.
+ +ARRAY /dev/md0 metadata=1.2 UUID=uuid name=name
+
+ Optionally, create an /etc/fstab entry for + automounting of the array. Replace /mnt/raid with the directory + where you want to mount the array. If you made a filesystem other than + ext4 make sure to change that value.
+ +/dev/md0 /mnt/raid ext4 defaults 0 1
+
++
+
In this article we are going to look at configuring two factor + authentication via PAM using OATH. This is a simple and private way + to increase the security of your systems. Even if you are not familiar + with the term, it is likely that you + have used OATH before. OATH (specifically TOTP) is the rotating 6 + digit code that you get from scanning a QR code when setting up 2FA + on an account.
+ +This example will show how to configure 2FA for SSH logins to a + server, but can easily be generalized to cover other programs or + even all authentication on a system. The two factors here will be + public key authentication and then the OATH/TOTP code. + It is highly recommended that you remain SSHd into your server + until after testing to avoid locking yourself out in the event + of a configuration error.
+ +You only need to install a single package on the server side.
+ +apt install libpam-oath
+
+ On the client machine that will be SSHing to the server install + these two packages.
+ +apt install oathtool qrencode
+
+ Create the OATH configuration file /etc/users.oath. + This file will contain the OATH secret keys so permissions need to be + set to only allow the root user to view it.
+ +touch /etc/users.oath
+chown root: /etc/users.oath
+chmod 600 /etc/users.oath
+
+ Generate a secret key for the TOTP. Treat this secret key as you + would your SSH or GPG private key. Anyone who has this key will be able + to generate the code needed to authenticate.
+ +openssl rand -hex 10
+
+ Now we define the TOTP configuration for our user. If you were + setting this up for multiple users you would make one entry per line. + Open /etc/users.oath and add this line. + user is the username of the account you will SSH into. + Replace the long string of numbers and letters with the secret key + you just generated.
+ +HOTP/T30/6 user - 00112233445566aabbcc
+
+
+ Now we need to tell PAM to use OATH to authenticate sshd. Do that + by opening /etc/pam.d/sshd and adding the following + line to the top of the file.
+ +auth sufficient pam_oath.so usersfile=/etc/users.oath window=30 digits=6
+
+ This tells PAM to consider a valid 6 digit code as fully authenticated + and to skip any other processing that may normally occur, such as + requesting a password.
+ +We need to make a few changes to the sshd configuration to allow + OATH to work properly. Open the sshd configuration file at + /etc/ssh/sshd_config and make the following changes.
+ +AuthenticationMethods publickey,keyboard-interactive
+PubkeyAuthentication yes
+PasswordAuthentication no
+ChallengeResponseAuthentication yes
+UsePAM yes
+
+ The AuthenticationMethods line specifically tells + sshd that a user needs to both have an authorized SSH key and know + the proper 6 digit code to login.
+ +Restart sshd to apply the changes
+ +systemctl restart sshd
+
+ From your client ssh into your server as normal. Instead of + connecting as you have been, you should now see a prompt for your + one time password. You can use oathtool to get + the code. Again, replace the long string of numbers and letters + with the secret key you generated on the server.
+ +oathtool --totp -d6 00112233445566aabbcc
+
+ Enter that 6 digit code into the prompt and you will be logged + into your server.
+ +Now, in the unlikely event that your SSH private key is stolen, + an attacker still won't be able to access your server!
+ +You probably don't want to run the oathtool command everytime you + need your code, and while you could make an alias, that would require + storing your secret key in plaintext. Here are some better options.
+ +You may also want to generate a QR code for easy setup on another + device. Rerun the same oathtool command as before with the -v flag + to get the base32 version of your secret key.
+ +oathtool --totp -v -d6 00112233445566aabbcc
+--------------------------------
+Hex secret: 00112233445566aabbcc
+Base32 secret: AAISEM2EKVTKVO6M
+Digits: 6
+Window size: 0
+TOTP mode: SHA1
+Step size (seconds): 30
+
+
+ Then use qrencode to generate the QR code image.
+ +qrencode -o totp.png 'otpauth://totp/user@server?secret=AAISEM2EKVTKVO6M'
+
+ +
+
bc1qzmpetsvyteku76cdv7qz2ngmxtxvyfuql973yd
+ +
+ This page contains various articles on technology topics of interest, + typically structured as how-to or tutorial documents. + Items without links indicate future topics I intend to cover. All articles + are intended for Debian 11 unless otherwise stated, but should be similar + if tried on other distros.
+Check out the source code here - + git.chudnick.com/mfa
+ +mfa is a system for out-of-band multi-factor + authentication with PAM. + My original reason for working on this was to get MFA functionality for + a Postfix/Dovecot mail server that uses PAM for authentication. + Solutions such as pam_oath are not feasible + for this purpose because a mail client has no way of exposing an + interface for the oath challenge-response. + Therefore a way to circumvent the original application to get the request + to the user is needed, which is what mfa does.
+ +The design of mfa is not novel, it works the same way as Cisco's Duo. + Duo does have open source modules for achieving this objective, but all + the authentication requests are + sent back to their proprietary "cloud" service. I'm sure that most + free software + enthusiasts see this as a major red flag, especially for small personal + use cases.
+ +mfa is primarily composed of three parts - the server, the client, + and the PAM module. + The server listens for connections from both clients and PAM + modules. The server receives a + request from a PAM module that includes the username of the user + attempting to authenticate, + the hostname of the computer, and the service being accessed. The + server then correlates the + combination of user, host, and service to a particular client, and + attempts to push a request. + The server will then evaluate the client's response, and either + return to the PAM module that + the user is authenticated or denied.
+ +The server itself consists of two parts that I've called + mfad and + mfac. mfad is the program responsible for doing + what I've described above. + mfac is a command line utility that the administrator uses to + configure the server. mfac is used + to enroll clients in the system and to provision applications. A + client is enrolled by using the + --add-client option and providing an alias for that user. The + server then assigns that user an + identifying key that is used to connect and a TOTP secret key. With + the client enrolled, the + administrator can then assign applications to that client. With the + --add-app command, the + administrator ties a username, hostname, and service combination to + a client alias, so that + when that combination is seen the server knows who to ask for + authentication. The administrator + also identifies which MFA methods are valid for this combination + (currently either or both of + push and/or totp). The example below shows the process of + enrolling a new client called + 'tux' and then provisioning MFA for SSH attempts to + tux@linux.example.org.
+ +# Enroll a client named tux
+mfac --add-client tux
+alias: tux
+client key: VA32LB3SF2HG2FDWJS5XIOFVWTMBQYRSQ3PK3OOPA3FBIQMSMJZCXYJQCYKYUWUU
+totp secret: TGGG3QCXA4MR2S2X6B33GSYN
+uri: otpauth://totp/tux%40mfad?secret=TGGG3QCXA4MR2S2X6B33GSYN
+
+# Provision MFA for SSH tux@linux.example.org allowing for both push
+authentication or TOTP
+mfac --add-app --user tux --host linux.example.org --service sshd --alias tux
+--methods push totp
+
+
+ The PAM module of mfa also consists of two parts: the actual PAM + module + pam_mfa.so that gets called in the PAM stack and a + helper + program that interacts with mfad. The job of pam_mfa.so is to + retrieve the + necessary information (user and service) from PAM and then invoke + the helper + program with that data. It then waits for the MFA process to + complete, retrieves + the result, and returns either success or failure to the PAM stack. + The helper + program initiates a connetion to mfad when run and then passes + username, hostname, + and service information to the server. It too receives a success + or failure response + and then relays that information to the PAM module. Here is an + example of using + pam_mfa.so in the PAM stack for sshd.
+ +/etc/pam.d/sshd
+auth requisite pam_mfa.so
+
+ The client program is what the end user interacts with to + provide authentication responses. + Currently it is only a very simple terminal program but expanding + on this is high on the + TODO list. The client opens a connection to the server and + identifies itself with the client + key that was generated during enrollment. The client waits for a + prompt from the server, and + when it receives one, informs the user. The client receives the + users input and sends it back + to the server. The client performs this loop continuously until it + is closed.
+ +Check out the source code here - + git.chudnick.com/clibrary
+ ++ git.chudnick.com/mail-tools +
+ ++ + git.chudnick.com/deploy-scripts +
+ +Check out the source code here - + git.chudnick.com/mfa
+ +mfa is a system for out-of-band multi-factor authentication with PAM. + My original reason for working on this was to get MFA functionality for a Postfix/Dovecot + mail server that uses PAM for authentication. Solutions such as pam_oath are not feasible + for this purpose because a mail client has no way of exposing an interface for the oath + challenge-response. Therefore a way to circumvent the original application to get the request + to the user is needed, which is what mfa does.
+ +The design of mfa is not novel, it works the same way as Cisco's Duo. Duo does have open + source modules for achieving this objective, but all the authentication requests are + sent back to their proprietary "cloud" service. I'm sure that most free software + enthusiasts see this as a major red flag, especially for small personal use cases.
+ +mfa is primarily composed of three parts - the server, the client, and the PAM module. + The server listens for connections from both clients and PAM modules. The server receives a + request from a PAM module that includes the username of the user attempting to authenticate, + the hostname of the computer, and the service being accessed. The server then correlates the + combination of user, host, and service to a particular client, and attempts to push a request. + The server will then evaluate the client's response, and either return to the PAM module that + the user is authenticated or denied.
+ +The server itself consists of two parts that I've called mfad and + mfac. mfad is the program responsible for doing what I've described above. + mfac is a command line utility that the administrator uses to configure the server. mfac is used + to enroll clients in the system and to provision applications. A client is enrolled by using the + --add-client option and providing an alias for that user. The server then assigns that user an + identifying key that is used to connect and a TOTP secret key. With the client enrolled, the + administrator can then assign applications to that client. With the --add-app command, the + administrator ties a username, hostname, and service combination to a client alias, so that + when that combination is seen the server knows who to ask for authentication. The administrator + also identifies which MFA methods are valid for this combination (currently either or both of + push and/or totp). The example below shows the process of enrolling a new client called + 'tux' and then provisioning MFA for SSH attempts to tux@linux.example.org.
+ +# Enroll a client named tux
+mfac --add-client tux
+alias: tux
+client key: VA32LB3SF2HG2FDWJS5XIOFVWTMBQYRSQ3PK3OOPA3FBIQMSMJZCXYJQCYKYUWUU
+totp secret: TGGG3QCXA4MR2S2X6B33GSYN
+uri: otpauth://totp/tux%40mfad?secret=TGGG3QCXA4MR2S2X6B33GSYN
+
+# Provision MFA for SSH tux@linux.example.org allowing for both push authentication or TOTP
+mfac --add-app --user tux --host linux.example.org --service sshd --alias tux --methods push totp
+
+
+ The PAM module of mfa also consists of two parts: the actual PAM module + pam_mfa.so that gets called in the PAM stack and a helper + program that interacts with mfad. The job of pam_mfa.so is to retrieve the + necessary information (user and service) from PAM and then invoke the helper + program with that data. It then waits for the MFA process to complete, retrieves + the result, and returns either success or failure to the PAM stack. The helper + program initiates a connetion to mfad when run and then passes username, hostname, + and service information to the server. It too receives a success or failure response + and then relays that information to the PAM module. Here is an example of using + pam_mfa.so in the PAM stack for sshd.
+ +/etc/pam.d/sshd
+auth requisite pam_mfa.so
+
+ The client program is what the end user interacts with to provide authentication responses. + Currently it is only a very simple terminal program but expanding on this is high on the + TODO list. The client opens a connection to the server and identifies itself with the client + key that was generated during enrollment. The client waits for a prompt from the server, and + when it receives one, informs the user. The client receives the users input and sends it back + to the server. The client performs this loop continuously until it is closed.
+ +Check out the source code here - + git.chudnick.com/clibrary
+ ++ git.chudnick.com/mail-tools +
+ ++ git.chudnick.com/deploy-scripts +
+ +Linux Unified Key Setup (LUKS) is a method for encrypting + block devices that is built-in to the Linux Kernel. In this tutorial + I will be showing how to create an encrypted USB drive with LUKS, but + this process is applicable to other types of storage. + This process will wipe all data on the device that you + encrypt so make backups beforehand if needed.
+ +Install cryptsetup and its dependencies
+ +apt install cryptsetup
+
+ If the device you are encrypting was previously used, you will + want to completely overwrite any data on it before encryption. This + can be done using dd as shown below. This could take + a very long time depending on the size and type of your drive. + Be sure that you enter the correct path to your drive as the + argument to of, and do not specify a partition: + /dev/sdb is correct, /dev/sdb1 is + wrong. Obviously this will destroy any data on the device so be + absolutely sure you specify the correct device in the command + and have backups of data previously stored if needed.
+ +dd if=/dev/zero of=/dev/sdX status=progress
+
+ cryptsetup is the main command used to perform + LUKS-related tasks. This main command is followed by a subcommand + that specifies which action to perform. To create a LUKS partition + on a drive we need to use the subcommand luksFormat. + We also use the type option to explicitly say to use LUKS version 2 + encryption. Run the command and then enter and confirm the + encryption password.
+ +cryptsetup --type luks2 luksFormat /dev/sdX
+
+ Now we need to open and map the encrypted LUKS device. This is done + by using the luksOpen subcommand. This subcommand takes + the device as the first argument and then a map target as the second. The + map target can be any string as long as a map does not already exist with + that name. In the example I will use crypt. + +
cryptsetup luksOpen /dev/sdX crypt
+
+ And then we just need to create a filesystem on the device; I will + be making an ext4 filesystem in the example. To + interact with an encrypted drive after it has been opened you need + to refer to its device mapper target, which is found under /dev/mapper. + Since we used crypt as the map target, our encrypted drive + is /dev/mapper/crypt.
+ +mkfs.ext4 /dev/mapper/crypt
+
+ After creating the filesystem created the encrypted drive + can now be mounted and used like any other device. Remember that + when mounting the device you refer to the device mapper target + (mount /dev/mapper/crypt /mnt/crypt).
+ +In addition to unmounting the filesystem you should always close + the device mapping before removing your encrypted drive. This is + done with the luksClose subcommand and takes + the device mapping as the argument.
+ +cryptsetup luksClose /dev/mapper/crypt
+
+ The LUKS header sits at the front of your encrypted drive and is + responsible for managing access to the device. If the header is + damaged accessing your encrypted data will not be possible. Because of + this, you may want to make backups of the header, but before doing so + you need to weigh the risks and benefits.
+ +The obvious benefit is that + in the event of damage to the LUKS header, you can easily restore a + backup and regain access to the data. However, having a backup of the + header makes it harder to wipe the LUKS device. Without a header + backup, overwriting the LUKS header on the device is enough to securely + wipe the drive. With backups, you need to either destroy all header + backups or overwrite all encrypted data on the device. The other main risk + is that an encryption password that is valid at the time you make a + backup will always be valid for that backup. For example, say you change + the encryption password on your device after making a backup because it + has been compromised. An attacker would be able to restore the header + backup and then use the compromised password to access the data.
+ +The cryptsetup documentation refers to creating header backups + as making a trade-off between safety and security. You need to make a + decision based on your individual use-case. It's a good idea to + routinely update your header backups if you do choose to make them
+ +When creating or restoring a header backup you always refer to the + block device in the command, not the device mapper taget. To create + a header backup:
+ +cryptsetup luksHeaderBackup /dev/sdX --header-backup-file path/to/backup
+
+ To restore a header from a backup:
+ +cryptsetup luksHeaderRestore /dev/sdX --header-backup-file path/to/backup
+
+ Note that is not necessary to store header backups on an encrypted + device. I would recommend storing backups on at least one non-encrypted + drive in case of an emergency.
+ ++
In this article we are going to look at configuring two factor + authentication via PAM using OATH. This is a simple and private way + to increase the security of your systems. Even if you are not familiar + with the term, it is likely that you + have used OATH before. OATH (specifically TOTP) is the rotating 6 + digit code that you get from scanning a QR code when setting up 2FA + on an account.
+ +This example will show how to configure 2FA for SSH logins to a + server, but can easily be generalized to cover other programs or + even all authentication on a system. The two factors here will be + public key authentication and then the OATH/TOTP code. + It is highly recommended that you remain SSHd into your server + until after testing to avoid locking yourself out in the event + of a configuration error.
+ +You only need to install a single package on the server side.
+ +apt install libpam-oath
+
+ On the client machine that will be SSHing to the server install + these two packages.
+ +apt install oathtool qrencode
+
+ Create the OATH configuration file /etc/users.oath. + This file will contain the OATH secret keys so permissions need to be + set to only allow the root user to view it.
+ +touch /etc/users.oath
+chown root: /etc/users.oath
+chmod 600 /etc/users.oath
+
+ Generate a secret key for the TOTP. Treat this secret key as you + would your SSH or GPG private key. Anyone who has this key will be able + to generate the code needed to authenticate.
+ +openssl rand -hex 10
+
+ Now we define the TOTP configuration for our user. If you were + setting this up for multiple users you would make one entry per line. + Open /etc/users.oath and add this line. + user is the username of the account you will SSH into. + Replace the long string of numbers and letters with the secret key + you just generated.
+ +HOTP/T30/6 user - 00112233445566aabbcc
+
+
+ Now we need to tell PAM to use OATH to authenticate sshd. Do that + by opening /etc/pam.d/sshd and adding the following + line to the top of the file.
+ +auth sufficient pam_oath.so usersfile=/etc/users.oath window=30 digits=6
+
+ This tells PAM to consider a valid 6 digit code as fully authenticated + and to skip any other processing that may normally occur, such as + requesting a password.
+ +We need to make a few changes to the sshd configuration to allow + OATH to work properly. Open the sshd configuration file at + /etc/ssh/sshd_config and make the following changes.
+ +AuthenticationMethods publickey,keyboard-interactive
+PubkeyAuthentication yes
+PasswordAuthentication no
+ChallengeResponseAuthentication yes
+UsePAM yes
+
+ The AuthenticationMethods line specifically tells + sshd that a user needs to both have an authorized SSH key and know + the proper 6 digit code to login.
+ +Restart sshd to apply the changes
+ +systemctl restart sshd
+
+ From your client ssh into your server as normal. Instead of + connecting as you have been, you should now see a prompt for your + one time password. You can use oathtool to get + the code. Again, replace the long string of numbers and letters + with the secret key you generated on the server.
+ +oathtool --totp -d6 00112233445566aabbcc
+
+ Enter that 6 digit code into the prompt and you will be logged + into your server.
+ +Now, in the unlikely event that your SSH private key is stolen, + an attacker still won't be able to access your server!
+ +You probably don't want to run the oathtool command everytime you + need your code, and while you could make an alias, that would require + storing your secret key in plaintext. Here are some better options.
+ +You may also want to generate a QR code for easy setup on another + device. Rerun the same oathtool command as before with the -v flag + to get the base32 version of your secret key.
+ +oathtool --totp -v -d6 00112233445566aabbcc
+--------------------------------
+Hex secret: 00112233445566aabbcc
+Base32 secret: AAISEM2EKVTKVO6M
+Digits: 6
+Window size: 0
+TOTP mode: SHA1
+Step size (seconds): 30
+
+
+ Then use qrencode to generate the QR code image.
+ +qrencode -o totp.png 'otpauth://totp/user@server?secret=AAISEM2EKVTKVO6M'
+
+ +
FreeIPA is a centralized idenity management solution developed + by Redhat. It is in my opinion the most functional libre alternative + to Microsoft's Active Directory. Like AD, FreeIPA integrates all of + the pieces needed to setup a domain including LDAP, Kerberos, + a Certificate Authority, and much more.
+ +I will be using Fedora 35 in this tutorial. As of Debian 11, the + FreeIPA server is still not in the Debian repos. You will need either + a Fedora or a RHEL machine. A CentOS fork may work also but I have not + tested that.
+ +For readers exploring the use of FreeIPA in a business + environment, note that FreeIPA documentation explicitly states that + it is not a replacement for Active Directory. I have not personally + tried to join a Windows computer to a FreeIPA domain, and so I can't + speak to how well that would work. FreeIPA would also not be able to push + out policy to Windows machines as is done with Group Policy. FreeIPA + is though able to create inter-domain trusts with an existing AD + infrastructure.
+ +Using a full Kerberos and LDAP identity management server may + seem like overkill at home. And if you only have a single computer + then it probably is. But scaling up even slightly, to perhaps a small + family each with their own computer, will make having FreeIPA + advantageous (your family is all using Linux, right?). This + will be especially apparent if you are hosting your own services. + If you are for instance hosting a Jellyfin media server that everyone + in your family accesses, you won't want them to juggle separate + passwords for Jellyfin when you could just have them use the same + password they do on the computer. This single/same sign-on capability is + one of the most practically useful aspects of FreeIPA.
+ +We start as usual by installing the required packages.
+ +dnf install freeipa-server freeipa-dns
+
+ The server will need to have a fully qualified hostname + before setting up IPA. You will need both a hostname for the server + itself and the domain name you will want for the FreeIPA domain. I + will be using ipaserver.myhome.local, where + ipaserver is the hostname and myhome.local is the + domain name.
+ +hostnamectl set-hostname ipaserver.home.local
+
+ We'll also need to add a hosts file entry to + /etc/hosts. Open that file in an editor and add a new + line with the IP of the server, the fully qualified name, and the + hostname.
+ +192.168.1.10 ipaserver.myhome.local ipaserver
+
+
+ Make sure to reboot the server before continuing to complete + the hostname change.
+ +We'll need to allow several ports for FreeIPA to function properly. + Fedora 35 uses firewalld by default but I am going to disable that + in favor of UFW here.
+ +#Install UFW
+dnf install ufw
+# Stop and disable firewalld
+systemctl disable --now firewalld
+# Configure UFW
+ufw enable
+ufw allow ssh
+ufw allow dns
+ufw allow 88 comment kerberos
+ufw allow 389 comment ldap
+ufw allow 443 comment webui
+ufw allow 636 comment ldaps
+ufw default deny incoming
+ufw reload
+
+ Now we can run the FreeIPA setup script. This is an interactive but mostly + automatic process that will configure all of the IPA components. The + --mkhomedir flag will configure the server to create home + directories for IPA users on their first login and would otherwise have to be + done manually.
+ +ipa-server-install --mkhomedir
+
+ That command will bring you into the install script. You will be prompted
+ several times before the bulk of the configuration happens. Default values
+ are show in brackets after the prompt. Let's run through those prompts.
+ Do you want to configure integrated DNS (BIND)?:
+ yes
+ Sever host name: the default value should be showing
+ ipaserver.myhome.local which is what we want. Simply hit enter to acecpt
+ the default.
+ Please confirm the domain name: The default here should be
+ correct myhome.local so hit enter to accept that.
+ Please provide a realm name: This should just be the domain
+ name in all uppercase. If the default looks correct just hit enter.
+ Directory Manager password: This is the password for an
+ administrator account used by system services. You will not need this for daily
+ use so I recommend setting it to a long randomly generated string. I have found
+ myself that using an extremely long password here will cause the installation to
+ fail. A password under 40 characters should be safe.
+ IPA admin password: This is the password for your initial admin
+ user. Make this a strong password as this user has full admin rights for the
+ entire domain.
+ Do you want to configure DNS forwarders: This allows you to
+ configure the IPA server to forward DNS requests to another DNS server for
+ zones it is not authoratitve for. The DNS server is configured by default as
+ a recursive DNS server so answering no does not prevent internet access. If you
+ have another DNS server that should be used instead then answer yes and provide
+ the IP address when prompted.
+
+ Do you want to configure chrony with NTP server or pool address?
+ : Here you can configure a custom NTP server or pool for the NTP daemon chrony.
+ If you already have an NTP server on your network answer yes and provide its IP.
+ If you want to leave the deafult chrony configuration then answer no. Time
+ synchronization is very important in Kerberos so you should consider how you
+ want to achieve that on your network. If you do not have an NTP server you may
+ want to configure the IPA server as one later.
+
+ Continue to configure the system with these values?: This is a
+ final confirmation before the script takes over and configures the IPA
+ components. Review the information printed and enter yes if it all looks correct.
+
The install script will now run through configuration. This process usually + takes several minutes. When finished you should get a message saying + The ipa-server-install command was successful.
+ +To finish, run this command to receive a Kerberos TGT. Provide the + password for the admin user when prompted.
+ +kinit admin
+
+ You are now able to manage FreeIPA through the web interface. You can + browse either to the IP or the hostname if your DNS is configured correctly. + You should see a screen similar to this.
+ +
+
+ Login with the username admin and the password you set during the + insallation. You are now ready to begin configuring your IPA domain.
++
mdadm is a tool that allows for creation and + management of software RAID arrays on Linux. Creating an array + is a rather straightforward process.
+ +The only package needed is mdadm itself
+apt install mdadm
+
+ We'll need to parition the disks to be used in the array before + creating it. This isn't anything complicated, we will just be + creating a single partition using all the space on each disk.
+ +Use lsblk to get a list of disks attached to your system.
+ +
+
+ Then use fdisk to edit the partition table of the + first disk. In my case this would be /dev/sdb. + Be sure that you are selecting the correct disk as selecting the + wrong one can result in data being lost.
+ +fdisk /dev/sdb
+
+ Use g to create a new GUID partition table. + Use n to create a new partition, and then just press + enter at all of the prompts to accept the defaults. Finally use + w to write the changes. You can use lsblk again + to verify the change and you should see that /dev/sdb now has a + partition /dev/sdb1.
+ +
+
+ Repeat this process for your other disks before continuing.
+ + +Creating the array is done with a single command, but takes just a + bit of planning.
+mdadm --create /dev/md0 --level=5 --raid-devices=3 /dev/sdb1 /dev/sdc1 /dev/sdd1 --spare-devices=1 /dev/sde1
+
+ After creating the array run the following command to get details + and the status of the array. It will take a bit to initialize the + array, you will know this is done when the state is clean. You do not + need to wait for the array to completely intialize to continue.
+ +mdadm --detail /dev/md0
+
+ Take note of the UUID and name values as we will need them in the + next step.
+ +Before moving on we need to make a filesystem on the array. I'm + going to make a simple EXT4 filesystem here.
+ +mkfs.ext4 /dev/md0
+
+
+ Open the mdadm configuration file at + /etc/mdadm/mdadm.conf and append this line. Replace + uuid and name with the values you got when running + mdadm --detail, replace 0 whatever ID you chose.
+ +ARRAY /dev/md0 metadata=1.2 UUID=uuid name=name
+
+ Optionally, create an /etc/fstab entry for + automounting of the array. Replace /mnt/raid with the directory + where you want to mount the array. If you made a filesystem other than + ext4 make sure to change that value.
+ +/dev/md0 /mnt/raid ext4 defaults 0 1
+
++
Icinga2 has built-in support for writing monitoring data to InfluxDB. + This makes Icinga quite extensible as it allows for other programs to read + the gathered data from InfluxDB. For example, Icinga does not have built-in + graphing support. But monitoring data can be written to InfluxDB and then + consumed by a dedicated graphing tool like Grafana.
+ +Let's install a few necessary packages
+ +apt install influxdb influxdb-client ssl-cert
+
+ Now generate a self-signed certificate for accessing InfluxDB over TLS
+ +make-ssl-cert generate-default-snakeoil
+usermod -aG ssl-cert influxdb
+
+ Start and enable the InfluxDB service
+ +systemctl enable --now influxdb
+
+ Now we'll create our database and users. We'll be creating 3 users with + different access rights. An admin user with full control over the database, a + user with write access that Icinga will use to write data to the database, and + a read-only user to allow external programs to read data from the database.
+ +influx -ssl -unsafeSsl -execute "create database icinga2; create user admin with password 'changeme'; create user icingauser with password 'changeme'; create user readonly with password 'changeme'; grant all to admin; grant write on icinga2 to icingauser; grant read on icinga2 to readonly;"
+
+
+Then right InfluxDB's configuration file at + /etc/influxdb/influxdb.conf
+ +reporting-enabled = false
+[meta]
+ dir = "/var/lib/influxdb/meta"
+[data]
+ dir = "/var/lib/influxdb/data"
+ wal-dir = "/var/lib/influxdb/wal"
+[coordinator]
+[retention]
+[shard-precreation]
+[monitor]
+[http]
+ enabled = true
+ bind-address = ":8086"
+ auth-enabled = true
+ https-enabled = true
+ https-certificate = "/etc/ssl/certs/ssl-cert-snakeoil.pem"
+ https-private-key = "/etc/ssl/private/ssl-cert-snakeoil.key"
+[ifql]
+[logging]
+[subscriber]
+[[graphite]]
+[[collectd]]
+[[opentsdb]]
+[[udp]]
+[continuous_queries]
+[tls]
+ min-version = "tls1.2"
+
+ And restart InfluxDB to pickup the changes
+ +systemctl restart influxdb
+
+ Then we need to configure Icinga to write data to our database. Start by + enabling the influxdb feature in Icinga
+ +icinga2 feature enable influxdb
+
+ Now we tell Icinga how to write to our database. Open the configuration + file at /etc/icinga2/features-available/influxdb.conf and replace + with the following
+ +object InfluxdbWriter \"influxdb\" {
+ host = "127.0.0.1"
+ port = 8086
+ username = "icingauser"
+ password = "icinga_password"
+ ssl_enable = true
+ database = "icinga2"
+ flush_threshold = 1024
+ flush_interval = 10s
+ host_template = {
+ measurement = "$host.check_command$"
+ tags = {
+ hostname = "$host.name$"
+ }
+ }
+ service_template = {
+ measurement = "$service.check_command$"
+ tags = {
+ hostname = "$host.name$"
+ service = "$service.name$"
+ }
+ }
+}
+
+ And finally restart Icinga to make those changes live.
+ +systemctl restart icinga2
+
+ Icinga2 will now be writing the data it collects to your InfluxDB instance.
+ ++
Postfix and dovecot will be the two primary pieces of our mail sever. +Postfix is the mail transport agent that handles the sending and +receiving of mail and dovecot is the IMAP server that will allow us to +access our mail from a mail client such as mutt. The server will also +have several other supporting components, a complete list of which is:
+ +You can use +this script I have written to automate this process, but I would +recommend that you run through the tutorial first to understand +what is being done.
+ +Please note that this tutorial is loosely intended for small personal mail +servers. Using PAM for authentication, as is done here, is not a scalable solution +for working with a large number of users. I do plan on covering Dovecot LDAP +authentication at some point which would be a better solution in an enterprise +setting.
+ +Let's start by installing the required packages. Note that if you already +have Apache installed on the server, replace python3-certbot-nginx +with python3-certbot-apache.
+apt install postfix dovecot-imapd dovecot-sieve opendkim opendkim-tools spamassassin gnupg postgrey postfix-policyd-spf-python opendmarc dbconfig-no-thanks certbot python3-certbot-nginx
+During the installation of Postfix you will get a Debconf prompt in which +you need to select "Internet Site" and then provide your domain name, +example.com.
+ +Now we'll use Certbot to get a certificate for our server. If you are +using Apache replace nginx with apache2.
+ +systemctl stop nginx
+certbot certonly --standalone -d mail.example.com
+systemctl start nginx
+
+In this section we will be doing the bulk of the postfix configuration. +The postconf command used throughout appends (or changes) +the specified configuration item in /etc/postfix/main.cf
+ +Let's start by configuring some network and domain information.
+ +postconf -e "myorigin = example.com"
+postconf -e "mydestination = \$myhostname, \$mydomain, localhost"
+postconf -e "mynetworks = 127.0.0.0/8 [::1]/128"
+postconf -e "myhostname = mail.example.com"
+
+
+Next, point postfix to the cerbot key and certificate, as well as the distro's +CA certificates.
+ +postconf -e "smtpd_tls_key_file=/etc/letsencrypt/live/mail.example.com/privkey.pem"
+postconf -e "smtpd_tls_cert_file=/etc/letsencrypt/live/mail.example.com/fullchain.pem"
+postconf -e "smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt"
+
+
+Harden the TLS configuration by forcing strong +protocols and ciphers, and requiring that authentication occur only over an +encrypted session.
+# Require authentication over TLS and optionally use it for sending and receiving mail
+postconf -e "smtpd_tls_auth_only = yes"
+postconf -e "smtpd_tls_security_level = may"
+postconf -e "smtp_tls_security_level = may"
+
+# Force the use of TLSv1.2 or TLSv1.3
+postconf -e 'smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1'
+postconf -e 'smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1'
+postconf -e 'smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1'
+postconf -e 'smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1'
+
+# Prefer server ciphers
+postconf -e "tls_preempt_cipherlist = yes"
+
+# Force strong ciphers
+postconf -e "smtpd_tls_ciphers = high"
+postconf -e "smtpd_tls_mandatory_ciphers = high"
+postconf -e "smtp_tls_ciphers = high"
+postconf -e "smtp_tls_mandatory_ciphers = high"
+postconf -e "smtpd_tls_exclude_ciphers = aNULL, eNULL, EXP, LOW, MEDIUM, PSK, SRP, SHA1, kRSA, CAMELLIA, ARIA, DSS, RSA+AES, ADH, AECDH"
+postconf -e "smtp_tls_exclude_ciphers = aNULL, eNULL, EXP, LOW, MEDIUM, PSK, SRP, SHA1, kRSA, CAMELLIA, ARIA, DSS, RSA+AES, ADH, AECDH"
+
+
+Here we configure the bulk of the postfix built-in security settings which are +structured as a series of access restrictions. Do not edit these settings without +first reading the Postfix documentation as an incorrect change could inadvertently +make your server an open relay.
+ +postconf -e "smtpd_helo_required = yes"
+postconf -e "smtpd_sender_login_maps = proxy:hash:/etc/postfix/login_maps"
+postconf -e "smtpd_helo_restrictions = reject_unknown_helo_hostname, reject_non_fqdn_helo_hostname"
+postconf -e "smtpd_sender_restrictions = reject_sender_login_mismatch, reject_non_fqdn_sender, reject_unknown_sender_domain"
+postconf -e "smtpd_recipient_restrictions = reject_non_fqdn_recipient, reject_unknown_recipient_domain, permit_sasl_authenticated, reject_unauth_destination, check_policy_service unix:private/postgrey, check_policy_service unix:private/policyd-spf, reject_rbl_client zen.spamhaus.org"
+postconf -e "smtpd_relay_restrictions = permit_sasl_authenticated, reject_unauth_destination"
+postconf -e "smtpd_data_restrictions = reject_unauth_pipelining"
+
+# Disable VRFY command to prevent harvesting of user accounts on system
+postconf -e "disable_vrfy_command = yes"
+
+# Change smptd banner (hide distribution)
+postconf -e "smtpd_banner = \$myhostname ESMTP \$mail_name"
+
+Now, configure the local mail recipients and some aliases. We'll create +an account called mailadmin to receive mail addressed to +several other accounts. This is to keep administrative mail separate, but +you can certainly alias these to your main account later if you would prefer to see +it there.
+ +# Set a custom local_recipient_maps here in order to avoid accepting mail for all local accounts
+postconf -e "local_recipient_maps = proxy:hash:/etc/postfix/local_maps \$alias_maps"
+
+# You will need to manually set a password later to login as mailadmin
+adduser --disabled-login --shell /usr/sbin/nologin --gecos "" mailadmin
+echo "# postfix aliases
+postmaster: mailadmin
+root: mailadmin
+dmarc: mailadmin
+" > /etc/aliases
+
+# Update address databases
+echo "mailadmin@mail.example.com mailadmin" > /etc/postfix/login_maps
+echo "mailadmin mailadmin" > /etc/postfix/local_maps
+newaliases
+postmap /etc/postfix/login_maps
+postmap /etc/postfix/local_maps
+
+
+These commands configure our mail delivery preferences. Mail will be +delivered inside a user's home folder with a maildir-style mailbox using +dovecot.
+ +# Maildir delivery to $HOME/Mail/Inbox/
+postconf -e "home_mailbox = Mail/Inbox/"
+# Deliver mail with Dovecot
+postconf -e "mailbox_command = /usr/lib/dovecot/deliver"
+
+Header and body checks allow for some simple content filtering within Postfix. +This is done by scanning a message line by line for a configured regex string, +nothing more. For example, the first header check listed will reject a message +with an attachment of ransomware.exe but will not block it if sent with +no extension. This is mostly a protection against uneducated users and poorly +written mail clients. Other checks block vulnerabilities and improve privacy.
+ +Create a new file /etc/postfix/header_checks, then open it in a +text editor and add the following
+# Block files with common executable extensions
+/name=[^>]*\.(exe|pif|com|dll|vbs|bat|sh|bash|so|zip|tar|gz|cpio)/ REJECT
+
+# Block message/partial vulnerability
+/message\/partial/ REJECT
+
+# Remove Received string that is created when spamassassin reinjects message into postfix
+# This is to prevent leaking the userid of the spamassassin user
+/^Received:.*userid.*/ IGNORE
+
+# Remove User-Agent strings from headers
+/^User-Agent: .*/ IGNORE
+
+Create another new file /etc/postfix/body_checks, and add this
+# Block messages with iframes
+/<iframe/ REJECT" > /etc/postfix/body_checks
+
+And then run these commands to point postfix to the check files.
+postconf -e "header_checks = regexp:/etc/postfix/header_checks"
+postconf -e "body_checks = regexp:/etc/postfix/body_checks"
+
+This simple command configures the SMTP client process that is responsible +for sending your mail to other mail servers.
+ +postconf -M "smtp/unix=smtp unix - - y - - smtp"
+
+Postscreen is a kind of firewall that sits in front of the Postfix SMTPD +process and receives all incoming traffic. Postscreen will drop connections +from IPs on a DNS blacklst, or from clients that violate the SMTP protocol by +speaking out of turn or sending non-SMTP commands. This adds up to less spam +connections and therefore a much lighter workload for your server.
+ +postconf -M "smtp/inet=smtp inet n - y - 1 postscreen"
+postconf -M "smtpd/pass=smtpd pass - - y - - smtpd"
+postconf -P "smtpd/pass/content_filter=spamassassin"
+postconf -M "tlsproxy/unix=tlsproxy unix - - y - 0 tlsproxy"
+postconf -M "dnsblog/unix=dnsblog unix - - y - 0 dnsblog"
+postconf -e "postscreen_dnsbl_sites = zen.spamhaus.org"
+postconf -e "postscreen_dnsbl_action = enforce"
+postconf -e "postscreen_greet_action = enforce"
+
+
+Submission over TLS (aka submissions) is the process you will use to submit +mail to your server from a mail client. These commands configure submissions to +use a fully-encrypted session, as opposed to STARTTLS, and to only allow access +to authenticated clients.
+ +postconf -M "submissions/inet=submissions inet n - y - - smtpd"
+postconf -P "submissions/inet/smtpd_tls_wrappermode=yes"
+postconf -P "submissions/inet/smtpd_tls_security_level=encrypt"
+postconf -P "submissions/inet/smtpd_tls_auth_only=yes"
+postconf -P "submissions/inet/smtpd_sasl_auth_enable=yes"
+postconf -P "submissions/inet/smtpd_client_restrictions=permit_sasl_authenticated,reject"
+postconf -P "submissions/inet/smtpd_helo_restrictions="
+postconf -P "submissions/inet/smtpd_sender_restrictions=reject_sender_login_mismatch"
+postconf -P "submissions/inet/smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject"
+postconf -P "submissions/inet/syslog_name=postfix/submissions"
+postconf -P 'submissions/inet/smtpd_tls_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1'
+postconf -P 'submissions/inet/smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1'
+
+Having configured submission over TLS on port 465 this step is optional. +STARTTLS is considered by some to be less secure than full-session TLS and +may be vulnerable to exploitation.
+ +postconf -M "submission/inet=submission inet n - y - - smtpd"
+postconf -P "submission/inet/smtpd_tls_security_level=encrypt"
+postconf -P 'submission/inet/smtpd_tls_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1'
+postconf -P 'submission/inet/smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3,!TLSv1,!TLSv1.1'
+postconf -P "submission/inet/smtpd_sasl_auth_enable=yes"
+postconf -P "submission/inet/smtpd_tls_auth_only=yes"
+postconf -P "submission/inet/syslog_name=postfix/submission"
+postconf -P "submission/inet/smtpd_helo_restrictions="
+postconf -P "submission/inet/smtpd_client_restrictions=permit_sasl_authenticated,reject"
+postconf -P "submission/inet/smtpd_helo_restrictions="
+postconf -P "submission/inet/smtpd_sender_restrictions=reject_sender_login_mismatch"
+postconf -P "submission/inet/smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject"
+
+
+Finally, this command tells Postfix how to interact with SpamAssassin.
+ +postconf -M "spamassassin/unix=spamassassin unix - n n - - pipe user=debian-spamd argv=/usr/bin/spamc --socket=/var/run/spamd.sock -e /usr/sbin/sendmail -oi -f \${sender} \${recipient}"
+
+Dovecot configuration is usually split up into many different files under +/etc/dovecot/conf.d/ but here will be doing all of the +configuration in the primary config file +/etc/dovecot/dovecot.conf. Open that file with your editor +of choice, clear all of its contents, and then replace it with the following.
+ +# /etc/dovecot/conf.d/10-auth.conf
+disable_plaintext_auth = yes
+auth_username_format = %n
+auth_mechanisms = plain
+userdb {
+ driver = passwd
+}
+passdb {
+ driver = pam
+}
+
+# /etc/dovecot/conf.d/10-mail.conf
+mail_location = maildir:~/Mail:INBOX=~/Mail/Inbox:LAYOUT=fs
+namespace inbox {
+ type = private
+ prefix =
+ separator = /
+ inbox = yes
+ subscriptions = yes
+ list = yes
+}
+
+# /etc/dovecot/conf.d/10-master.conf
+service imap-login {
+# Run login processes in high-security mode (see: LoginProcess.txt in dovecot docs)
+service_count = 1
+# Disable unencrypted IMAP by setting port for plain IMAP to 0
+ inet_listener imap {
+ port = 0
+ }
+ inet_listener imaps {
+ port = 993
+ ssl = yes
+ }
+}
+
+# Allow postfix to use dovecot SASL
+service auth {
+ unix_listener /var/spool/postfix/private/auth {
+ mode = 0660
+ user = postfix
+ group = postfix
+ }
+}
+
+# /etc/dovecot/conf.d/10-ssl.conf
+ssl = required
+ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem
+ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem
+ssl_client_ca_dir = /etc/ssl/certs
+ssl_dh = </usr/share/dovecot/dh.pem
+
+# Mozilla intermediate compatibility
+ssl_min_protocol = TLSv1.2
+ssl_cipher_list = ECDHE+ECDSA+AESGCM:ECDHE+aRSA+AESGCM:ECDHE+ECDSA+CHACHA20:ECDHE+aRSA+CHACHA20:DHE+aRSA+AESGCM:!aNULL:!eNULL
+
+ssl_prefer_server_ciphers = yes
+ssl_client_require_valid_cert = yes
+
+
+# /etc/dovecot/conf.d/15-lda.conf
+protocol lda {
+ mail_plugins = \$mail_plugins sieve
+}
+
+# /etc/dovecot/conf.d/15-mailboxes.conf
+namespace inbox {
+ mailbox Sent {
+ special_use = \Sent
+ auto = subscribe
+ }
+ mailbox Trash {
+ special_use = \Trash
+ auto = create
+ autoexpunge = 30d
+ }
+ mailbox Drafts {
+ special_use = \Drafts
+ auto = subscribe
+ }
+ mailbox Spam {
+ special_use = \Junk
+ auto = create
+ autoexpunge = 30d
+ }
+ mailbox Archive {
+ special_use = \Archive
+ auto = create
+ }
+}
+
+# /etc/dovecot/conf.d/20-imap.conf
+imap_capability = +SPECIAL-USE
+
+# /etc/dovecot/conf.d/90-sieve.conf
+plugin {
+ sieve = ~/.dovecot.sieve
+ sieve_default = /var/lib/dovecot/sieve/default.sieve
+ sieve_global = /var/lib/dovecot/sieve/
+}
+
+Then create the default sieve filtering script at +/var/lib/dovecot/sieve/default.sieve
+require ["fileinto", "mailbox"];
+/*
+* Discard mail that has a spam score greater than or equal to 10
+*/
+if header :contains "X-Spam-Level" "**********" {
+ discard;
+ stop;
+}
+/*
+* Discard messages marked as infected by a virus scanner
+*/
+if header :contains "X-Virus-Scan" "infected" {
+ discard;
+ stop;
+}
+/*
+* If message is marked as spam (and falls below discard threshold) put into spam mailbox
+*/
+if header :contains "X-Spam-Flag" "YES" {
+ fileinto "Spam";
+}
+
+And compile the script
+ +sievec /var/lib/dovecot/sieve/default.sieve
+
+
+Finally, configure PAM authentication for dovecot at +/etc/pam.d/dovecot. Append these changes leaving any include +statements intact.
+auth required pam_unix.so
+account required pam_unix.so
+
+DKIM is a mail-verification method that cryptographically signs mail +to allow receivers to verify the authenticity of the sender. Our mail server +will use DKIM to validate signatures on incoming mail and sign outgoing mail. DKIM +requires a public key to be published via DNS, which will be done near the end of +the guide.
+ +Start by generating the DKIM key
+ +opendkim-genkey -D /etc/dkimkeys -d example.com -s mail
+chown opendkim: /etc/dkimkeys/*
+chmod 600 /etc/dkimkeys/*
+mv /etc/dkimkeys/mail.private /etc/dkimkeys/mail.pem
+
+Here we make a directory for the opendkim socket inside the postfix chroot and +make it accessible to the postfix user.
+ +mkdir /var/spool/postfix/opendkim
+chmod 770 /var/spool/postfix/opendkim
+chown opendkim:opendkim /var/spool/postfix/opendkim
+usermod -aG opendkim postfix
+
+Edit the configuration file at /etc/opendkim.conf +to be as follows:
+ +On-BadSignature reject
+On-Security reject
+Syslog yes
+SyslogSuccess yes
+LogResults yes
+Canonicalization simple
+Mode sv
+OversignHeaders From
+Domain example.com
+Selector mail
+KeyFile /etc/dkimkeys/mail.pem
+UserID opendkim
+UMask 007
+Socket local:/var/spool/postfix/opendkim/opendkim.sock
+PidFile /run/opendkim/opendkim.pid
+TemporaryDirectory /run/opendkim
+InternalHosts 127.0.0.1
+TrustAnchorFile /usr/share/dns/root.key
+RequireSafeKeys True
+AlwaysAddARHeader True
+
+
+DMARC is another mail-verification technology that provides verification of the +address seen by end-users and either or both of SPF and DKIM. + +
Like with OpenDKIM, we need to make a directory inside the postfix chroot +for the socket and assign proper permissions.
+mkdir /var/spool/postfix/opendmarc
+chmod 770 /var/spool/postfix/opendmarc
+chown opendmarc:opendmarc /var/spool/postfix/opendmarc
+usermod -aG opendmarc postfix
+
+
+Now we write the configuration file at /etc/opendmarc.conf
+ +PidFile /run/opendmarc/opendmarc.pid
+PublicSuffixList /usr/share/publicsuffix/public_suffix_list.dat
+RejectFailures True
+Socket local:/var/spool/postfix/opendmarc/opendmarc.sock
+Syslog True
+SyslogFacility mail
+UMask 002
+UserID opendmarc
+HistoryFile /var/run/opendmarc/opendmarc.hist
+SPFIgnoreResults True
+SPFSelfValidate True
+
+
+Then create the history file and set permissions.
+ +touch /var/run/opendmarc/opendmarc.hist
+chown opendmarc:opendmarc /var/run/opendmarc/opendmarc.hist
+chmod 664 /var/run/opendmarc/opendmarc.hist
+
+
+Now that both OpenDKIM and OpenDMARC are configured we can define them as milters +in postfix. This will tell postfix to route mail through one or both of these milters +depending on whether it is incoming or outgoing.
+ +postconf -P "smtpd/pass/smtpd_milters=unix:opendkim/opendkim.sock,unix:opendmarc/opendmarc.sock"
+postconf -P "submissions/inet/smtpd_milters=unix:opendkim/opendkim.sock"
+# If you enabled submission on port 587 run this too
+postconf -P "submission/inet/smtpd_milters=unix:opendkim/opendkim.sock"
+
+
+Postgrey implements a spam-filter technique known as greylisting, which +always rejects mail on the first try and for a period of time afterwards known +as the greylist period. The idea behind this being that legitimate senders will +send the mail again later, while spammers, in a rush to send as many messages as +possible before being blacklisted, will not.
+ +Postgrey ships with an extensive whitelist domains that are known +to cause issues (mainly large providers that constantly send from different +addresses). This whitelist file is located at +/etc/postgrey/whitelist_clients and can be appended to include +any domain you do not wish to be subject to greylisting.
+ +The configuration needed here is minimal, just open +/etc/default/postgrey and make these changes
+ +POSTGREY_OPTS="--unix=/var/spool/postfix/private/postgrey --privacy"
+POSTGREY_TEXT="Greylisted - see https://www.greylisting.org"
+
+And then enable the service
+ +systemctl enable --now postgrey
+
+SPF is yet another mail-verification technology that uses DNS records to +delegate specific servers as being authorized to send mail for the domain +(and implicitly all other servers as unauthorized). Policyd-SPF will perform +SPF checking of received mail and reject mail that fails SPF verfication.
+ +First, tell postfix how to access Policyd-SPF
+ +postconf -e "policyd-spf_time_limit = 3600"
+postconf -M "policyd-spf/unix=policyd-spf unix - n n - 0 spawn user=policyd-spf argv=/usr/bin/policyd-spf"
+
+And then edit the configuration file at +/etc/postfix-policyd-spf-python/policyd-spf.conf
+ +debugLevel = 1
+TestOnly = 1
+HELO_reject = Fail
+Mail_From_reject = Fail
+Header_Type = AR
+# These settings increase false-positive risk
+# Comment them if you want to reduce that risk
+PermError_reject = True
+TempError_Defer = True
+
+
+SpamAssassin is a spam-filter that will scan all received mail and assign +a spam score based on configured rules. SpamAssassin is much heavier and more +resource-intensive than any of the previous spam-filtering/verification programs +we have configured. The postfix spam-filtering philosophy emphasizes the use +of lightweight checks before passing to an external content filter such as +SpamAssassin. Ideally, non-legitimate mail will have already been caught by one +of the previous methods, and SpamAssassin will only have to operate on a much +smaller subset of the mail that is sent to our server.
+ +We have actually already told postfix to use SpamAssassin as a content filter +so in this section we just need to edit the configuration file +/etc/spamassassin/local.cf.
+ +# Clearly indicate message is spam to user
+rewrite_header Subject *****SPAM*****
+rewrite_header From *****SPAM*****
+
+# Set required score to be marked as spam, 5.0 is default.
+# Lower to make policy more strict or raise to be more lenient.
+required_score 5.0
+
+# Attach original messages as text/plain instead of message/rfc822 to spam reports
+report_safe 2
+
+Do not implicitly trust mail based on IP address except localhost
+trusted_networks 127.0.0.1/32
+
+
+And finally make a few changes to the defaults file at +/etc/default/spamassassin
+ +OPTIONS="--listen /var/run/spamd.sock --max-children 5"
+PIDFILE=/var/run/spamd.pid
+CRON=1
+
+At this point we have done all of the necessary configuration of the mail +server programs. We have just a few more minor tasks before your mail server +is operational.
+ +We need to open the proper ports in the firewall. This example uses UFW.
+ +ufw allow 25 comment "smtp"
+ufw allow 465 comment "submission over TLS"
+# Run this next command only if you enabled submission on port 587
+ufw allow 587 comment "mail submission"
+ufw allow 993 comment "IMAP over TLS"
+ufw reload
+
+Now let's restart the services to pick up any configuration changes.
+ +systemctl restart postfix
+systemctl restart dovecot
+systemctl restart opendkim
+systemctl restart opendmarc
+systemctl enable --now spamassassin
+systemctl restart spamassassin
+systemctl restart postgrey
+
+Finally, we needs to set some required DNS records to enable mail flow and +verification. Begin by logging into your registrar or DNS host and editing +your DNS records.
+ +If you did not set a wildcard A record earlier, you will need to set one now +for mail. +Alternatively, if you are running the mail server on the same server as your +website, you may want to instead make a CNAME record pointing mail to www.
+ +MX records tell servers attempting to send you mail where to send it. Open the +MX records section on your registrar and add a new record. An MX +record consists of a priority and a destination. Set the priority to 10 and the +destination to mail, or whatever your subdomain for this mail +server is. The host value can be left blank or may need to be set to "@" +depending on your registrar.
+ +Now we will set the three TXT records we need. Open the TXT records tab on +your registrar.
+ +We'll set the DKIM record first. The command we ran to +generate our DKIM keys also generates a DNS record for us which will be helpful +here. Print that to the screen with:
+ +cat /etc/dkimkeys/mail.txt
+
+You should get a lengthy output that looks something like the following. The +bolded portion is the value.
+ +mail._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; "
+ "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz50PSYL0Ob+OlF/0B77rwlzLe7zF6JKnxQNtMqcOCZ0Dar2FPhSUSz1FR0YmNuoShjMogdgKeojIzgRUqwK5GZ5Lz456qiXWkfAtLPc6UQ/WPoyEBGbJpRBYPGWdN4VoNcHkk/I4csvXW6MOI55ghPOwDmootPkCzNPR6gmNAXMe0duS4Lb+bIjy9QMOxGYVUaQ/b+7xar+fWw"
+ "bA3DjQa3jTLCydzzJpjEMfVaKqNhQ4N+ve7O2Mb3LF5k5B977mtok/6POjVG5HY8g6Pba+GzMFItR6nJO5EE2fyfv6cNbRLsZiM+WQmqvDBst5ejaeapy86F5PdJFlX/TUgXjtuwIDAQAB" ) ; ----- DKIM key mail for example.com
+
+You can cleanup the spacing of the value as your registrar should automatically +handle any needed splitting of the record. The parts you need to paste into your +registrar's web interface should then look like this.
+ +# Name/Host
+mail._domainkey
+# TXT Value
+"v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz50PSYL0Ob+OlF/0B77rwlzLe7zF6JKnxQNtMqcOCZ0Dar2FPhSUSz1FR0YmNuoShjMogdgKeojIzgRUqwK5GZ5Lz456qiXWkfAtLPc6UQ/WPoyEBGbJpRBYPGWdN4VoNcHkk/I4csvXW6MOI55ghPOwDmootPkCzNPR6gmNAXMe0duS4Lb+bIjy9QMOxGYVUaQ/b+7xar+fWwbA3DjQa3jTLCydzzJpjEMfVaKqNhQ4N+ve7O2Mb3LF5k5B977mtok/6POjVG5HY8g6Pba+GzMFItR6nJO5EE2fyfv6cNbRLsZiM+WQmqvDBst5ejaeapy86F5PdJFlX/TUgXjtuwIDAQAB"
+
+The DMARC record should be as follows:
+ +# Name/Host
+_dmarc
+# Value
+"v=DMARC1; p=reject; rua=mailto:dmarc@example.com; fo=1"
+
+
+Your SPF record will look like this. Remember to replace +mail.example.com with your server name.
+ +# Name/Host
+@
+# Value
+"v=spf1 a:mail.example.com -all"
+
+
+Many mail servers rely on PTR records for verification purposes so we need +to make sure our server's IP address resolves to the proper domain name. If +your mail server is residing on a VPS, you will need to add this record on your +VPS provider's interface, consult their documentation for details.
+ +Your mail server is now up and running. Let's create an email for you to +receive mail.
+ +useradd --shell /usr/sbin/nologin --create-home --user-group user
+echo "user@example.com user" >> /etc/postfix/login_maps
+echo "user user" >> /etc/postfix/local_maps
+postmap /etc/postfix/login_maps
+postmap /etc/postfix/local_maps
+postfix reload
+
+
+I have a script available for adding and removing users that you can find +here. + +
When connecting your account to a mail client you need to use these settings.
+ ++
With the Icinga master node configured, the servers we want + to monitor can now be added as agent nodes. As the names suggest, + the Icinga master node pushes the desired configuration to agent + nodes, while agent nodes report the configured status checks back + to the master. Communication between the master and agent nodes is + encrypted via TLS, with the master node acting as a certificate + authority.
+ +You can find my script to automate this process + + here.
+ +Start by installing the required packages on the server to be + monitored.
+ +apt install icinga2 monitoring-plugins
+monitoring-plugins-contrib
+
+ Now we need to setup the PKI that will be used for the communication + with the master node. The first step is to generate a certificate + signing request. Replace hostname with the FQDN of the server.
+ +icinga2 pki new-cert --cn "hostname" --cert "/etc/icinga2/pki/hostname.crt" --csr "/etc/icinga2/pki/hostname.csr" --key "/etc/icinga2/pki/hostname.key"
+
+ Next we save the master node's public key certificate. Replace + master with the FQDN of your master node.
+ +icinga2 pki save-cert --host "master" --port 5665 --key "/etc/icinga2/pki/hostname.key" --trustedcert "/etc/icinga2/pki/trusted-master.crt"
+
+ Receive signed certificate from the master node.
+ +icinga2 pki request --host "master" --port 5665 --key "/etc/icinga2/pki/hostname.key" --cert "/etc/icinga2/pki/hostname.crt" --trustedcert "/etc/icinga2/pki/trusted-master.crt" --ca "/etc/icinga2/pki/ca.crt"
+
+ Write Icinga configuration.
+ +/etc/icinga2/icinga2.conf
+include "constants.conf"
+const NodeName = "$nodename"
+include "zones.conf"
+include "features-enabled/*.conf"
+include <itl>
+include <plugins>
+include <plugins-contrib>
+include <manubulon>
+include <windows-plugins>
+include <nscp>"
+
+ Write zones configuration.
+ +/etc/icinga2/zones.conf
+echo "object Endpoint "hostname" {}
+object Zone "hostname" {
+ parent = "master"
+ endpoints = [ "hostname" ]
+}
+object Zone "master" {
+ endpoints = [ "master" ]
+}
+object Endpoint "master" {
+ host = "master"
+}
+object Zone "director-global" {
+ global = true
+}
+
+ Write API configuration file.
+ +/etc/icinga2/features-available/api.conf
+echo "object ApiListener \"api\" {
+ accept_commands = true
+ accept_config = true
+}
+
+ Next, we need to enable the API on the agent.
+ +icinga2 feature enable api
+
+mkdir -p /var/lib/icinga2/certs
+
+cp /etc/icinga2/pki/hostname.crt /etc/icinga2/pki/hostname.key /etc/icinga2/pki/ca.crt /var/lib/icinga2/certs/
+
+chown -R nagios: /var/lib/icinga2/certs/
+
+ The only action needed on the master node is to sign the agent's + CSR. Logon to your master node and run the following:
+ +fpr="$(icinga2 ca list | tail -1 | cut -d '|' -f 1)"
+icinga2 ca sign $fpr
+
+ Before finishing we need to open the proper firewall port. + I will use UFW in the example here and allow traffic only only + from the master node for best security.
+ +ufw allow proto tcp from master-ip to any port 5665
+
+ Finally, restart the icinga service on the agent node.
+ +systemctl restart icinga2
+
+ The Icinga agent node will now pull down configuration from the master. + You will know that this worked if /var/lib/icinga2/api/zones + begins to populate with new files.
++
Icinga Director is the web-based configuration tool for Icinga2. + Director provides a simple interface for configuring the various parts + of your monitoring environment. Even if you would rather do all of + the configuration from a terminal, I still recommend using Director for + its self-service API which allows new nodes to register with no interaction + required on the node (i.e. via a script).
+ +Start by logging into your Icinga instance. If you followed the + master installation guide you should have + a tab labeled Icinga Director. Click on that, and you should + see something similar to this:
+
+
+ Let's start by looking at the hosts section. Clicking on the hosts + button from the Director menu will present you with several options. + Click on host templates, and then click add to define our first host + template. Host templates are the building blocks of Icinga, they allow + for your nodes to be structured however you see fit, and then to have + monitoring checks automatically applied to them based on that structure.
+I like to structure my host templates by operating system. For example, + I have a template called Linux Server, which is designed + to encompass all of the Linux servers in my environment. I then get more + specific, creating templates based on distro. These templates are children + of the Linux Server template, so they inherit whatever is applied to the + parent, but then can have distro-specific checks applied to themselves.
+Start by giving your template a name - I will use Linux Server + here. Groups can be left empty for now, but you may want to + add groups and apply them to templates later. The check command should + be set to hostalive. Expand Icinga Agent and zone settings + and set Icinga2 Agent, Establish connection, + and Accepts config to Yes. Click store to save the template. + Your template should look like this:
+ +
+
+ Let's turn to services now. Return to the Director menu and select + Services. The services menu is structured similar to hosts, and we will + start with the service templates section. The idea behind service templates + is very similar to host templates. Typically, a service template corresponds + to a single monitoring command.
+As an example, we'll create a service template for a monitoring + command that checks the status of a web server. Give the template a + name, set the check command to http, and finally expand Icinga + Agent and zone settings and set Run on agent + to no. We set this to no because we want Icinga to query + the web server externally instead of from the web server itself.
+ +
+
+ Service sets are simply groups of service templates. They can be + structured however you see fit. Service sets can then be applied to + hosts/host templates to have the checks be automatically applied.
+ +Add a new service set and give it a name. Then click on the services + tab and add all of the services you want to group into that set. + Here is an example of a service set Linux Standard + that has service checks that should be applied to all Linux servers.
+ +
+
+ To bring service sets and host templates together, return to your host + templates, select Linux Server, select the services tab, and then select + add service set and choose your desired set from the dropdown menu.
+ +
+
+ When you have made all of the changes you need you will need to + render the Director configuration. Return to the Director menu, + select Config Deployment, and then select Render config.
+ +In this last section we will look at what I think is the best feature + of Director which is the self service API. To enroll a host template + in the self service API, select the host template, select the agent + tab, and select generate self service api key. That's it! + The string of letters and numbers is the API key associated with this + host template. Hosts can be enrolled with this API key and Icinga + will automatically assign the host to this template. With proper + structuring, you can have hosts be completely provisioned without + touching Director. In the next article, we will use this to enroll + a host in Icinga with a shell script.
++
+This tutorial will cover the installation of the Icinga2 +monitoring application master node. This includes the base +program, the web frontend, and the web-based configuration tool. +This guide was made for Debian but should be similar +on other distributions. +
++I have a script available to automate the steps described in this +tutorial available +from my git repo. +
Here we will install the required packages. Icinga can use either MySQL +or PostgreSQL, however this tutorial will use MySQL/MariaDB.
+apt install icinga2 icingaweb2 icinga2-ido-mysql icingaweb2-module-director monitoring-plugins monitoring-plugins-contrib default-mysql-server
+This step is optional but strongly recommended. +The mysql_secure_installation script will harden your MySQL instance.
+mysql_secure_installation
+I recommend the following responses: +
The next several sections will cover creating databases for the various +parts of Icinga. We'll start with the monitoring database. +The following command creates a MySQL database named icinga2 +and grants permissions to a user named ido_admin. These values +are arbitrary, but I use them throughout the tutorial so I recommend leaving them +as is. You should definitely change the password though, which in the command +is change me. You will need this password and the passwords for the +other databases later, so make sure you save them.
+mysql -u root -e "CREATE DATABASE icinga2; GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON icinga2.* TO ido_admin@'localhost' IDENTIFIED BY 'change me'; FLUSH PRIVILEGES;
+
+We then need to import the ido schema into the database.
+ +mysql -u root icinga2 </usr/share/icinga2-ido-mysql/schema/mysql.sql
+
+After importing the schema, we then write the configuration file that tells +the monitoring module how to connect to the database.
+/etc/icinga2/features-available/ido-mysql.conf
+library "db_ido_mysql"
+object IdoMysqlConnection "ido-mysql" {
+ user = "ido_admin",
+ password = "ido_password",
+ host = "localhost",
+ database = "icinga2"
+}"
+
+And finally we enable the monitoring module in Icinga.
+icinga2 feature enable ido-mysql
+
+This step is nearly identical to the last. This time we create a database +named icingaweb2 and grant permissions to the user named +icingaweb2_admin.
+mysql -u root -e "CREATE DATABASE icingaweb2;GRANT ALL ON icingaweb2.* TO 'icingaweb2_admin'@'localhost' IDENTIFIED BY 'changeme'; FLUSH PRIVILEGES;
+
+Again we will need to import required schema into the database.
+mysql -u root icingaweb2 </usr/share/icingawbe2/etc/schema/mysql.schema.sql
+
+
+In this step we create the initial admin user that will be used to login +to the web interface. As is, this would create a user named admin +with the password changme. You should at least change the password.
+passhash="$(php -r "echo password_hash(\"changeme\", PASSWORD_DEFAULT);")"
+mysql -u root -e "USE icingaweb2; INSERT INTO icingaweb_user (name, active, password_hash) VALUES (\"admin\", 1, \"$passhash\"); FLUSH PRIVILEGES;"
+
+Here we create the database for Director. Director will require more +configuration later, so for now we will just be creating the database.
+mysql -u root -e "CREATE DATABASE director CHARACTER SET 'utf8'; GRANT ALL on director.* TO 'director'@'localhost' IDENTIFIED BY '$director_password';FLUSH PRIVILEGES;"
+
+Run the following command to initialize the Icinga API.
+icinga2 api setup
+And then restart Icinga to apply the changes.
+systemctl restart icinga2
+
+In this section we will configure the web server for accessing +Icinga's web interface and Director configuration tool. +This tutorial will use nginx but apache could be used as well. +We'll start by installing the necessary packages.
+apt install nginx php-fpm
+Then we need to create the site configuration file.
+
/etc/nginx/sites-available/icingaweb2.conf
+server {
+ listen 80;
+ server_name monitoring.example.com
+ location ~ ^/icingaweb2/index\.php(.*)$ {
+ fastcgi_pass unix:/var/run/php/php-fpm.sock;
+ fastcgi_index index.php;
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME /usr/share/icingaweb2/public/index.php;
+ fastcgi_param ICINGAWEB_CONFIGDIR /etc/icingaweb2;
+ fastcgi_param REMOTE_USER $remote_user;
+ }
+
+ location ~ ^/icingaweb2(.+)? {
+ alias /usr/share/icingaweb2/public;
+ index index.php;
+ try_files $1 $uri $uri/ /icingaweb2/index.php$is_args$args;
+ }
+
+ # Not strictly necessary but allows you to get to icinga without
+ # specifying /icingaweb2 in the URL.
+ location = / {
+ return 302 http://$host/icingaweb2;
+ }
+
+}
+And then restart nginx to pick up the changes.
+systemctl restart nginx
+
+At this point we are done with the Icinga setup module and so we +can disable it.
+icingacli module disable setup
+
+In this section we will write several configuration files. Icinga uses +the INI format for its web interface configuration files.
+In this first file we tell Icinga about the various resources it should have +access to. These resources are the three databases created previously. +Replace the password in each section with the corresponding password you set +for that database earlier.
+/etc/icingaweb2/resources.ini
+[icinga2]
+type = "db"
+db = "mysql"
+host = "localhost"
+port = ""
+dbname = "icinga2"
+username = "ido_admin"
+password = "ido password"
+charset = ""
+use_ssl = "0"
+
+[icingaweb2]
+type = "db"
+db = "mysql"
+host = "localhost"
+port = ""
+dbname = "icingaweb2"
+username = "icingaweb2_admin"
+password = "ido password"
+charset = ""
+use_ssl = "0"
+
+
+[director]
+type = "db"
+db = "mysql"
+host = "localhost"
+port = ""
+dbname = "director"
+username = "director"
+password = "director password"
+charset = "utf8"
+use_ssl = "0"
+
+
+This file controls the authentication settings for the web interface. +Here we tell Icinga to look at the icingaweb2 database for +authentication purposes.
+/etc/icingaweb2/authentication.ini
+[icingaweb2]
+backend = "db"
+resource = "icingaweb2"
+
+Now we tell icinga which users should have admin permissions. +If you changed the username value from admin previously, be sure to update +it here.
+/etc/icingaweb2/roles.ini
+[admins]
+users = "admin"
+resource = "icingaweb2"
+
+Enable the web interface monitoring module.
+icingacli module enable monitoring
+Then write the configuration file pointing the monitoring module to the +monitoring database.
+/etc/icingaweb2/modules/monitoring/backends.ini
+[icinga]
+type = "ido"
+resource = "icinga2"
+
+Here we configure Icinga to use the API for communication. +You will need to get your unique API password generated during the API setup from +from /etc/icinga2/conf.d/api-users.conf. +hostname should be the FQDN of the server.
+/etc/icingaweb2/modules/monitoring/commandtransports.ini
+[icinga2]
+transport = "api"
+host = hostname
+port = "5665"
+username = "root"
+password = "api password"
+
+Lastly, tell Icinga to protect variables with potentially sensitive values.
+/etc/icingaweb2/modules/monitoring/config.ini
+[security]
+protected_customvars = "*pw*,*pass*,*community*"
+
+
+This section will cover configuring Director configuration tool.
+Create Director module configuration directory.
+mkdir -p /etc/icingaweb2/modules/director
+
+Write the Director configuration file.
+/etc/icingaweb2/modules/director/config.ini
+[db]
+resource = "director"
+
+Enable Director module and run the initial migration.
+icingacli module enable director
+icingacli director migration run
+
+Write Director kickstart configuration file.
+/etc/icingaweb2/modules/director/kickstart.ini
+[config]
+endpoint = "hostname"
+username = "root"
+password = "api password"
+
+Kickstart Director, then render and deploy the configuration.
+icingacli director kickstart run
+icingacli director config render
+icingacli director config deploy
+
+Director is setup at this point so we will shred the unneeded configuration +file containing sensitive information.
+shred -uz /etc/icingaweb2/modules/director/kickstart.ini
+
+You are now ready to login to your monitoring instance with the admin +user created previously. Open a web browser and go to +http://hostname/icingaweb2. You should see a screen similar to this:
+
+
+In the following articles we will go through setting up Icinga2 agents on servers, and configure your monitoring instance through Icinga Director.
++
This is some of the software that I use and recommend. + It goes without saying, but all of this software is free as in freedom, + libre, open source.
+ +Window Manager - dwm + [git]
+Shell - zsh
+Terminal Emulator - urxvt
+Statusbar - dwmblocks + [git]
+Text Editor - vim
+Music Player - cmus
+Process Monitor - htop
+Media Player - mpv
+Email - neomutt, isync, msmtp + [kb]
+RSS - newsboat
+PDF Reader - zathura
+Sandbox - firejail
+Virtualization - qemu/kvm + libvirt
+Firewall - ufw
+ +This is some server oriented software that I use.
+Mail Server - postfix + dovecot + [kb]
+ +Media Server - jellyfin
+ +Server Monitoring - icinga2 + [kb]
+ +Configuration Management - ansible
+ +Identity Management - FreeIPA + [kb]
+ + + +