Wednesday, January 16, 2069

Intro

My main website is https://bradsmithcpa.com. In addition to being a CPA, I am a self-taught programmer.  My programming experience includes Javascript, VBA, Visual Basic, Google Apps Script, HTML, and PHP. This blog  is targeted primarily for beginners to those with moderate levels of experience. 

Thursday, June 15, 2023

Oracle Free Tier VPN with Debian 12

I successfully installed Debian 12 on an Oracle Free Tier VPN with 4 CPU, 24GB memory, and 50 storage. 

Debian is not one of the images available, so I started off with Canonical Ubuntu 22.04 Minimal aarch64 for the image and VM.Standard.A1.Flex for the shape. I used PuttyGen to generate public and private keys and pasted the public key into the Oracle Create Compute Instance screen. After the instance was up and running I connected to the server using Putty with the private key attached.

After connecting, getting the GUI installed was my first priority.  I made a mistake in the installation with the lightdm desktop manager and was unable to connect with Windows Remote Desktop.  I made several attempts to fix the error to no avail.  

Oracle does not give the option to reinstall the OS to an existing instance for Free Tier customers. The only official option available was to destroy the instance and create a new one.  This is not an attractive option because available shapes are limited.  After trying to find a workaround I found a git that provided a script to reinstall a minimal Debian 10,11, or 12 remotely on a VPN.

https://github.com/bohanyang/debi

I was skeptical but had nothing to lose.  To my pleasant surprise, the reinstallation was fast and flawless.  The script provides a fresh Debian 12 install with a user named debian.  I rebooted the server and logged back in with putty.  Since the ssh public key was destroyed after reinstallation, I logged in with password credentials and manually added the public key as follows:

Create a text file with the public ssh keys in the user's root directory:
$ sudo mkdir ~/.ssh/  
$ sudo nano ~/.ssh/authorized_keys Copy and paste the public key in the above file, save, and exit.
$ sudo reboot

With that task accomplished I was off to the races.

Here are the steps I followed to create a GUI XRDP environment:

$ sudo apt update && sudo apt upgrade

$ sudo apt install whiptail

$ sudo apt install accountsservice

$ sudo apt install lightdm

$ sudo dpkg-reconfigure lightdm

$ sudo apt install xfce4

$ sudo apt install xrdp
After a reboot, I was able to access the server with Windows Remote Desktop. 

If I've learned anything it's that I need to take periodic snapshots in case I incur another unrecoverable error.  The best software I found to accomplish this task is called Timeshift.
$ sudo apt install timeshift
After installation, the GUI version of Timeshift is available in the menu.  The first couple of times I used timeshift on an Oracle cloud VPN, I destroyed to bootloader and was forced to create new instances.  The problem is, Timeshift tries to overwrite Oracle's BlockVolume drive rendering the instance unusable and unrecoverable.  

When restoring a snapshot, make sure /boot and /boot/efi are both set to "Keep on Root Device" using the drop-down menu (by default, the program selects sda1 to restore grub2 which is incorrect) AND also click Bootloader Options (Advanced) and change the option for (re)install Grub2 on: to sda2.

Timeshift doesn't provide a way to change restoration defaults.  Timeshift's website says the program was designed for grub2 bootloader-type systems.  The risk of getting this wrong is pretty nerve-racking.  A better option for VPN on Oracle Cloud may be BackInTime, a snapshot utility that gives more control over the backup and restoration process. 

Wednesday, November 6, 2019

Modoboa Mail Server with Apache2 as Web Server on Ubuntu 18.04

Modoboa is an excellent way to simplify the installation, configuration, and ongoing maintenance of an email server.  The easiest way is to install Modoboa is by using an installation script available on GitHub.

The Modoboa install script installs the Nginx web server by default.  Nginx is best for static content and Apache is better for dynamic content (like php). The key advantage to using Nginx is it commands less system resources due to its architecture.  Still, if  your web traffic is low, the performance gains by using Nginx is negligible. I decided my website would be best served with Apache alone, though I still wanted to use Modoboa as my email server.

Since the installation script installs Nginx by default, a few modifications to the script file are needed.  The following instructions assume a fresh Ubuntu 18.04 with Apache already installed.  Also, make sure DNS MX record is already configured with mail.your-domain.com.


Modoboa Installer


First install mod_wsgi then restart Apache
$ sudo apt-get install libapache2-mod-wsgi
$ sudo systemctl restart apache2
The installation script is available from GitHub.
$ git clone https://github.com/modoboa/modoboa-installer
Install the necessary perl scripts
$ sudo apt-get install python-virtualenv python-pip
Navigate to the installer directory
$ cd modoboa-installer
Run the following command.
$ sudo ./run.py --stop-after-configfile-check your-domain.com
You'll get a warning that the installer.cfg file was not found so a new one was created.  installer.cfg file allows you to customize certain elements of the installation. The default contents include the following:
$ [general]
hostname = mail.%(domain)s

[certificate]
generate = true
type = self-signed

[letsencrypt]
email = admin@your-domain.com

[database]
engine = postgres
host = 127.0.0.1
install = true

[postgres]
user = postgres
password =
Leave the certificate type to self-signed.  We will install a Let's Encrypt certificate manually later.
If you want to use MariaDB instead of postgres, change the engine type under database to mysql. Scroll down and change the instruction to install nginx to false.
[nginx]
enabled = false
Make the desired changes and save the file.  Next we'll re-run the installation routine using --interactive.
$ sudo ./run.py --interactive your-domain.com
If you have problems with the installation, rerun the script with the debug option:
$ sudo ./run.py --interactive --debug your-domain.com
If all goes well, the completed installation should look similar to the following:
Welcome to Modoboa installer!

Warning:
Before you start the installation, please make sure the following DNS records exist for domain 'microsmith.net':
  mail IN A   <IP ADDRESS OF YOUR SERVER>
       IN MX  mail.your-domain.com

Your mail server will be installed with the following components:
modoboa automx amavis clamav dovecot razor postfix postwhite spamassassin uwsgi radicale opendkim
Do you confirm? (Y/n)
The process can be long, feel free to take a coffee and come back later ;)
Starting...
Generating new self-signed certificate
Installing amavis
Installing spamassassin
Installing razor
Installing clamav
Installing modoboa
Installing automx
Installing radicale
Installing uwsgi
Installing opendkim
Installing postfix
Installing postwhite
Installing dovecot
Congratulations! You can enjoy Modoboa at https://mail.your-domain.com (admin:password)


Apache Configuration


Next we need to create an Apache config file for mail.your-domain.com  Here is the file I created in the /etc/apache2/sites-available directory and named mail.your-domain.com.conf :
<VirtualHost *:80>
ServerName mail.microsmith.net
  DocumentRoot /srv/modoboa/instance/


  Alias /media/ /srv/modoboa/instance/media/
  <Directory /srv/modoboa/instance/media>
    Order deny,allow
    Allow from all
  </Directory>

  Alias /sitestatic/ /srv/modoboa/instance/sitestatic/
  <Directory /srv/modoboa/instance/sitestatic>
    Order deny,allow
    Allow from all
  </Directory>

</VirtualHost>
Next we need to configure the Apache config file.
$ sudo nano /etc/apache2/apache2.conf
Scroll down the page and uncomment (or add if it's missing) the following lines.
<Directory /srv/>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>
In addition, we need to configure WSGI.  Add the following lines to the Apache config file:
WSGIScriptAlias / /srv/modoboa/instance/instance/wsgi.py
WSGIPythonHome /srv/modoboa/env/
WSGIPythonPath /srv/modoboa/instance/

<Directory /srv/modoboa/instance/instance>
<Files wsgi.py>
  Require all granted
</Files>
</Directory>
WSGIPassAuthorization On
Save the file and reboot.

Install Lets Encrypt Certificate


Make sure the https port 443 is included in your firewall configuration. See Install Firewall (ufw).

Install certbot


Add the PPA and install certbot (install software-properties-common if necessary)
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt update
Install certbot packages:
$ sudo apt install python-certbot-apache

Install certificate:


Install the certificate as shown
$ sudo certbot --apache -d mail.your-domain.com
Answer any prompts and wait for the confirmation that the certificate has been issued.  If you have problems getting the certificate issue, try visiting the website https://letsdebug.net/. The Let's Encrypt Certificate is only valid for 90 days.  However the certbot installation includes a cron script that auto renews the certificate 30 days before expiration.  The script is located at /etc/cron.d.

You can test the renewal process by running the following command again:
$ sudo certbot renew --dry-run
Manual installation of the Let's Encrypt certificate as instructed will automatically result in the creation of an ssl version of the Apache conf files for your site. Here are the contents of my site's ssl config file (mail.your-domain-le-ssl.conf) after a successful letsencrypt installation in the /etc/apache2/sites-available/ path:
<IfModule mod_ssl.c>
<VirtualHost *:443>
  ServerName mail.your-domain.com
  DocumentRoot /srv/modoboa/instance/


  Alias /media/ /srv/modoboa/instance/media/
  <Directory </srv/modoboa/instance/media>
    Order deny,allow
    Allow from all
  </Directory>

  Alias /sitestatic/ /srv/modoboa/instance/sitestatic/
  <Directory /srv/modoboa/instance/sitestatic>
    Order deny,allow
    Allow from all
  </Directory>

SSLCertificateFile /etc/letsencrypt/live/your-domain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/your-domain.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
Note your certificate file path may vary.

There are two additional lines we need to add to the Apache config file file.  Add the two following lines after the WSGIScriptAlias.
WSGIDaemonProcess your-domain.com python-path=/srv/modoboa/instance:/srv/modoboa/env/lib/python2.7/site-packages
WSGIProcessGroup your-domain.com

Modoboa Log-In Panel


Modoboa is programmed to work with IMAP.  If you want to connect to your mail server via pop3 to another email service, you need to make configuration changes.  The easiest was to do this is to install dovecot-pop3d.
$ sudo apt install dovecot-pop3d
Open firewall ports for 25, 587, 993, 995.

We're now ready to log into the Modoboa panel.  Go to https://mail.your-domain.com.  Your log-in is Admin and the password is password. Once you're logged in change your username and/or password.  Click on the user name in the top right of the menu panel, then go to settings>>profile to make the changes.

To set up domains for the server, click Domains from the top menu bar then click the Add+ button. Be sure to enable dkim signing. Once the domain is setup, you can retrieve the public key for DKIM by selecting Domains from the top menu bar, then click the domain name.  Click the Show key button in the DNS box on the top right. You will need to add the domain key to your DNS settings.

If you plan to use Modoboa's webmail (I used it for testing) you should change the IMAP and SMTP ports and enable ssl/tls.  Click Modoboa in the menu bar, then select the Webmail tab.  Under IMAP settings, click the radio button to use a secure connection and change the port to 993.  Under SMTP settings, click the radio button to enable STARTTLS, change the server port to 587, then click the "Yes" radio button to require authentication.  Click save.













Monday, November 4, 2019

Awstats setup on Apache2 Ubuntu 18.04

Helpful websites: LinuxbabeLeave No Bit Unturned.
Awstats is a useful free program that provides website statistics. The installation in this guide was performed on a Ubuntu 18.04 server running Apache2.

Install  and Configure Awstats


$ sudo apt install awstats libgeo-ip-perl libgeo-ipfree-perl
Edit domain config file
$ sudo nano /etc/apache2/sites-available/your-domain.com
Append log file names to separate stats for each website you'll track.  Edit thefollowing within the <VirtualHost> tag
ErrorLog ${APACHE_LOG_DIR}/your-domain.com_error.log
CustomLog ${APACHE_LOG_DIR}/your-domain.com_access.log combined
Add the following before the closing </VirtualHost> tag.
Alias /awstatsclasses "/usr/share/awstats/lib/"
Alias /awstats-icon/ "/usr/share/awstats/icon/"
Alias /awstatscss "/usr/share/doc/awstats/examples/css"
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
ScriptAlias /awstats/ /usr/lib/cgi-bin/
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Save file.  Enable the CGI module
$ sudo a2enmod cgi
Configure Awstats files for default website.  Back up the file
$ sudo cp /etc/awstats/awstats.conf /etc/awstats/awstat.conf.bak
Then edit
$ sudo nano /etc/awstats/awstats.conf
Edit the following lines as shown
LogFile="/var/log/apache2/your-domain.com_access.log"
LogFormat=1
SiteDomain="your-domain.com"
HostAliases="your-domain.com localhost 127.0.0.1"
DirData="/var/lib/awstats/your-domain.com"
Save file.  Give user www-data log access permissions (the following command requires "acl")
$ sudo setfacl -R -m "u:www-data:rx" /var/log/apache2/
Create directory structure to hold data and then grant permissions
$ sudo mkdir -p /var/lib/awstats/your-domain.com
$ sudo chown www-data:www-data /var/lib/awstats/your-domain.com
Restart Apache2
$ sudo systemctl restart apache2
The stats for your main (or only) domain should be accessible now at your-domain.com/cgi-bin/awstats.pl.  Cron should be set to update awstats every ten minutes by default.

Secure access to Awstats page


Now that Astats is working you'll want to restrict access.  Run the following to set a password for admin.  The password will be stored at /etc/apache2/htpasswd.
$ sudo htpasswd -c /etc/apache2/htpasswd admin
Configure the Apache virtual host file
$ sudo nano /etc/apache2/sites-available/your-domain.com.conf
Then add the following
<Directory "/usr/lib/cgi-bin/">
    AuthUserFile /etc/apache2/htpasswd
    AuthName "Please Enter Your Password" 
    AuthType Basic
    Require valid-user
</Directory>
Save the file. Restart Apache2
$ sudo systemctl restart apache2
Now when you access the awstats page you should be prompted to enter a user name and password.

Multiple Websites


Create an awstats config file for your other websites.
$ sudo nano /etc/awstats/awstats.your-other-domain.com.conf
An include statement at the top will bring over the settings from the default awstats file. We just need to change some of the directives from the default by adding the following lines
Include "/etc/awstats/awstats.conf"
SiteDomain="your-other-domain.com"
HostAliases="your-other-domain.com localhost 127.0.0.1"
DirData="/var/lib/awstats/your-other-domain.com"
LogFile="/var/log/apache2/your-other-domain.com_access_log"
Create directory structure and set permissions.
$ sudo mkdir -p /var/lib/awstats/your-other-domain.com
$ sudo chown www-data:www-data /var/lib/awstats/your-other-domain.com
Restart Apache2
$ sudo systemctl restart apache2
Cron will update the stats in ten minutes. If you want to check your configuration now run the following:
$ sudo -l -c /usr/share/awstats/tools/update.sh www-data

Log File Permissions and Rotation


Edit the Apache logrotate file to give apache read permissions to everyone.
$ sudo nano /etc/logrotate.d/apache2
Edit the following line as shown
create 644 root adm
Save the file.






Tuesday, September 24, 2019

Email Spam and Virus Filters

Note: Installation performed on a VPS KVM server
Helpful websites: Postfix Amavis NewMail Filtering.
Excellent article on spam filtering using postfix

Install mail filtering programs and utilities


$ sudo apt install amavisd-new spamassassin clamav-daemon
$ sudo apt-get install libnet-dns-perl libmail-spf-perl pyzor razor
$ sudo apt-get install arj bzip2 cabextract cpio file gzip lhasa liblz4-tool lrzip nomarch pax rar ripole rpm unrar-free lzop unzip zip
Cross add clamav and amvis to each other's group
$ sudo adduser clamav amavis
$ sudo adduser amavis clamav
Amavis is its own spamassassin-daemon (amavis uses the spamassassin libraries). There is no need to configure spamassassin.

Enable pyzor and razor
$ sudo amavis -s /bin/bash
$ sudo razor-admin -create
$ sudo razor-admin -register
Activate spam and antivirus detection in Amavis.  Edit /etc/amavis/conf.d/15-content_filter_mode
$ sudo nano /etc/amavis/conf.d/15-content_filter_mode
Uncomment lines as shown
use strict;

# You can modify this file to re-enable SPAM checking through spamassassin
# and to re-enable antivirus checking.

#
# Default antivirus checking mode
# Uncomment the two lines below to enable it
#

@bypass_virus_checks_maps = (
   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);


#
# Default SPAM checking mode
# Uncomment the two lines below to enable it
#

@bypass_spam_checks_maps = (
   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

1;  # insure a defined return
To cover multiple domains, edit the following
$ sudo nano /etc/amavis/conf.d/50-user
Edit as follows
$myhostname = 'your-mail-server-domain.com';
@local_domains_acl = ( "your-domain.com", "your-domain.org" );
or configure last line above this way
@local_domains_acl = qw(.);
Restart amavis service
$ sudo systemctl restart amavis

Postfix integration


Run the following command
$ sudo postconf -e 'content_filter = smtp-amavis:[127.0.0.1]:10024'
Edit postfix master.cf
$ sudo nano /etc/postfix/master.cf
Add the following to the end of file
smtp-amavis     unix    -       -       -       -       2       smtp
  -o smtp_data_done_timeout=1200
  -o smtp_send_xforward_command=yes
  -o disable_dns_lookups=yes
  -o max_use=20

127.0.0.1:10025 inet    n       -       -       -       -       smtpd
  -o content_filter=
  -o local_recipient_maps=
  -o relay_recipient_maps=
  -o smtpd_restriction_classes=
  -o smtpd_delay_reject=no
  -o smtpd_client_restrictions=permit_mynetworks,reject
  -o smtpd_helo_restrictions=
  -o smtpd_sender_restrictions=
  -o smtpd_recipient_restrictions=permit_mynetworks,reject
  -o smtpd_data_restrictions=reject_unauth_pipelining
  -o smtpd_end_of_data_restrictions=
  -o mynetworks=127.0.0.0/8
  -o smtpd_error_sleep_time=0
  -o smtpd_soft_error_limit=1001
  -o smtpd_hard_error_limit=1000
  -o smtpd_client_connection_count_limit=0
  -o smtpd_client_connection_rate_limit=0
  -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters
Also add the following to the postfix master.cer file immediately after the pickup transport service.
  -o content_filter=
  -o receive_override_options=no_header_body_checks
Restart postfix service
$ sudo systemctl restart postfix

Testing


Test that amavisd-new is listening
$ telnet localhost 10024
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 [127.0.0.1] ESMTP amavisd-new service ready
^] 22
Review incoming email headers for the presence of X-Virus-Scanned and X-Spam-Status entries.

Get last date clamav virus definitions were updated
$ strings /var/lib/clamav/daily.cld|head -1|cut -c1-2

Website Security with fresh Ubuntu 18.04 install

Note: Installation performed on a VPS KVM server


First update and upgrade

# apt update
# apt upgrade

Update Firewall (ufw)


Firewall needs to be enabled

# ufw enable
Verify firewall is active
# ufw status verbose
Allow access to port 22
# ufw allow 22
Configure firewall to allow the following additional ports:

  • 80
  • 8080
  • 443
Allow access to your ip address / port 3389
# sudo ufw allow from ###.###.###.### to any port 3389
Recheck ufw status
# ufw status verbose
The results should be similar to the following:
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
To                         Action      From --                         ------      ---- 22                         ALLOW IN    Anywhere 80                         ALLOW IN    Anywhere 8080                       ALLOW IN    Anywhere 443                        ALLOW IN    Anywhere
3389                       ALLOW IN    ###.###.###.### 22 (v6)                    ALLOW IN    Anywhere (v6) 80 (v6)                    ALLOW IN    Anywhere (v6) 8080 (v6)                  ALLOW IN    Anywhere (v6) 443 (v6)                   ALLOW IN    Anywhere (v6)

Set up user

Add a user

# adduser example_user

Add to sudo group (if new user needs root privileges)

# adduser example_user sudo
Exit then log-in with new credentials.

Secure SSH Log-in Using PuTTY

Enable firewall for ssh access

$ sudo ufw allow ssh

Configure the server


Backup the sshd_config file
$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
Edit the sshd_config file
$ sudo nano /etc/ssh/sshd_config
Uncomment the following lines (remove the leading #):

Port 22
PubkeyAuthentication yes
AuthorizedKeysFile      .ssh/authorized_keys .ssh/authorized_keys2

Generate keys with PuTTYgen

  1. Go to Windows Start menu → All Programs → PuTTY→ PuTTYgen
  2. Generate a public/private key pair
    • Parameters (use defaults)
      • Type of key: RSA
      • bits: 2048
    • click Generate
      • Putty uses mouse movements for randomness
      • When key generation is complete enter a passphrase
      • Save public key
      • Save private key
  3. Install public key on server
    • In the users root directory create .ssh folder
      • $ mkdir ~/.ssh
    • Create a new file as follows:
      • $ nano ~/.ssh/authorized_keys
    • Copy/paste the public key created in step 2 in the new file.  The key must be all on one line.
    •  Save the file
  4. Exit

Disable "root" user


Edit the sshd_config file
$ sudo nano /etc/ssh/sshd_config
For security purposes, change PermitRootLogin to no.  Save file. Reboot.

Monday, September 23, 2019

Ubuntu 18.04 email using postfix, dovecot, and opendkim


Most of these steps were taken from linuxbabe.com and modified for my purposes.  If you want more insight visit her website.

The following assumes you have already set up your webserver with apache2 and/or nginx, and secured the website with a Let's Encrypt certificate.

Email

Hostname


You can change your host name.  If you're using  this server as your mail server you might want to use a FQDN like mail.your-domain.com.  I used my domain name without the domain suffix.
$ sudo hostnamectl set-hostname your-domain
To verify changes relog-in and run the following
hostname -f


DNS


If you're using a mail server, set DNS records like the following:
Name: @; Type: MX; Content: mail.your-domain.com
Name:mail.your-domain.com: Type: A; Content: your-ip
Install and configure postfix
$ sudo apt update
$ sudo apt install postfix -y
You will be prompted to answer some questions.
Type:  Internet Site 
System mail name: your-domain.com
Configure postfix.  Review the postfix main config file.
$ sudo nano /etc/postfix/main.cf
Review the following and edit as needed
myhostname = your-domain.com
mydomain = your-domain.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = $mydomain, localhost.$mydomain, localhost;
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 192.168.0.0/24
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all
home_mailbox = Maildir/
Open the postfix master config file.
$ sudo nano /etc/postfix/master.cf
Add the submission section to the end of the file
submission     inet     n    -    y    -    -    smtpd
 -o syslog_name=postfix/submission
 -o smtpd_tls_security_level=encrypt
 -o smtpd_tls_wrappermode=no
 -o smtpd_sasl_auth_enable=yes
 -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
 -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
 -o smtpd_sasl_type=dovecot
 -o smtpd_sasl_path=private/auth
More edits to the postfix main config file.
$ sudo nano /etc/postfix/main.cf
Add the following to the end of the file
smtpd_tls_cert_file=/etc/letsencrypt/live/mail.your-domain.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/mail.your-domain.com/privkey.pem
smtpd_tls_security_level=may 
smtpd_tls_protocols = !SSLv2, !SSLv3 !TLSv1
smtpd_tls_loglevel = 1
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_security_level = may
smtp_tls_loglevel = 1
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

Restart postfix service.
$ sudo systemctl restart postfix

Install and configure dovecot


$ sudo apt install dovecot-core dovecot-imapd
Edit the main dovecot config file.
$ sudo nano /etc/dovecot/dovecot.conf
Add the following to enable imap
protocols = imap
Configure authentication.
$ sudo nano /etc/dovecot/conf.d/10-auth.conf
Uncomment this line to disable plaintext authentication when there’s no SSL/TLS encryption.
disable_plaintext_auth = yes
Configure TLS.
$ sudo nano /etc/dovecot/conf.d/10-ssl.conf
Edit file to require SSL
ssl = required
Provide your SSL certificate addresses.
ssl_cert = </etc/letsencrypt/live/mail.your-domain.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.your-domain.com/privkey.pem
SASL Authentication Between Postfix and Dovecot
$ sudo nano /etc/dovecot/conf.d/10-master.conf
Change service auth section.
service auth {
    unix_listener /var/spool/postfix/private/auth {
      mode = 0660
      user = postfix
      group = postfix
    }
}
Auto create folders
$ sudo nano /etc/dovecot/conf.d/15-mailboxes.conf
Add auto = create to folders as you see fit. Example:
mailbox Trash {
    auto = create
    special_use = \Trash
 }
Tell Dovecot to use Maildir.
$ sudo nano /etc/dovecot/conf.d/10-mail.conf 
Replace /etc/dovecot/conf.d/10-mail.conf with the following:
/etc/dovecot/conf.d/10-mail.conf
Restart services.
$ sudo systemctl restart dovecot
$ sudo systemctl restart postfix

Sender Policy Framework - SPF


Add a DNS record for SPF.
Name: @; Type: TXT; Content: v=spf1 mx ~all
There are several SPF tags and mechanisms.
You can invoke SPF checking for incoming email
sudo apt install postfix-policyd-spf-python
Configure.
$ sudo nano /etc/postfix/master.cf
Add to the end of file.
policyd-spf  unix  -       n       n       -       0       spawn
    user=policyd-spf argv=/usr/bin/policyd-spf
Save, then open the main config file.
$ sudo nano /etc/postfix/main.cf
Add to the end of file
policyd-spf_time_limit = 3600
smtpd_recipient_restrictions =
   permit_mynetworks,
   permit_sasl_authenticated,
   reject_unauth_destination,
   check_policy_service unix:private/policyd-spf
Save file then restart postfix service
$ sudo systemctl restart postfix

DKIM


Install opendkim.
$ sudo apt install opendkim opendkim-tools
Add postfix to opendkim user group.
$ sudo gpasswd -a postfix opendkim
Configure.
$ sudo nano /etc/opendkim.conf
Uncomment the following lines. Replace simple with relaxed/simple.
Canonicalization   relaxed/simple
Mode               sv
SubDomains         no
Add the following after Subdomains no.
AutoRestart         yes
AutoRestartRate     10/1M
Background          yes
DNSTimeout          5
SignatureAlgorithm  rsa-sha256
Add the following to the end of file. Ubuntu may already include the first section for UserID.
#OpenDKIM user
# Remember to add user postfix to group opendkim
UserID             opendkim

# Map domains in From addresses to keys used to sign messages
KeyTable           refile:/etc/opendkim/key.table
SigningTable       refile:/etc/opendkim/signing.table

# Hosts to ignore when verifying signatures
ExternalIgnoreList  /etc/opendkim/trusted.hosts

# A set of internal hosts whose mail should be signed
InternalHosts       /etc/opendkim/trusted.hosts
Save and close file.

Create Signing Table, Key Table and Trusted Hosts Files


Create directory structure.
$ sudo mkdir /etc/opendkim
$ sudo mkdir /etc/opendkim/keys
Change ownership and permissions.
$ sudo chown -R opendkim:opendkim /etc/opendkim
$ sudo chmod go-rw /etc/opendkim/keys
Create signing table.
$ sudo nano /etc/opendkim/signing.table
Add the following line.
*@your-domain.com    default._domainkey.your-domain.com
Save and close.  Create key table.
$ sudo nano /etc/opendkim/key.table
Add the following line.
$ default._domainkey.your-domain.com     your-domain.com:default:/etc/opendkim/keys/your-domain.com/default.private
Save and close.  Create trusted hosts file
$ sudo nano /etc/opendkim/trusted.hosts
Add the following lines.
127.0.0.1
localhost

*.your-domain.com
Create file structure.
$ sudo mkdir /etc/opendkim/keys/your-domain.com
Generate keys.
$ sudo opendkim-genkey -b 2048 -d your-domain.com -D /etc/opendkim/keys/your-domain.com -s default -v
Change ownership of private key.
$ sudo chown opendkim:opendkim /etc/opendkim/keys/your-domain.com/default.private
Add Public Key in DNS Records. Get the key
$ sudo cat /etc/opendkim/keys/your-domain.com/default.txt
The string after the p is the key. Add DNS record and add key string after the p:
Name: default._domainkey.your-domain.com; Type: TXT; Content: v=DKIM1; k=rsa; p=KEYSTRINGHERE
Test.
$ sudo opendkim-testkey -d your-domain.com -s default -vvv
If the setup is good the response should be key OK .

Connect opendkim to postfix


Create directory structure.
$ sudo mkdir /var/spool/postfix/opendkim
$ sudo chown opendkim:postfix /var/spool/postfix/opendkim
Open conf file.
$ sudo nano /etc/opendkim.conf
Find this line.
Socket                  local:/var/run/opendkim/opendkim.sock
Replace with this.
Socket                local:/var/spool/postfix/opendkim/opendkim.sock
Save and close file. Open postfix main config file.
$ sudo nano /etc/postfix/main.cf
Add the following after smtpd_recipient_restriction.
# Milter configuration
milter_default_action = accept
milter_protocol = 6
smtpd_milters = local:/opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters
Save and close the file then restart opendkim and postfix.
$ sudo systemctl restart opendkim
$ sudo systemctl restart postfix
Check your spf and dkim set up by sending an email to the following.
$ [email protected]
You should get a response indicating is your setup has passed the checks

DMARC


Set up a DMARC record in your DNS table similar to the following.
Name: _dmarc.your-domain.com; Type: TXT; Content: v=DMARC1; p=none; pct=100; fo=1; rua=mailto:[email protected]
The parameters are as follows:
v - DMARC version
p - policy (what to do with email that doesn't pass the dmarc test.
pct - The percentage of email the policy should be applied
fo - report preferences:     0 (default): generate reports if all underlying authentication mechanisms fail to produce a DMARC pass result
     1:  generate reports if any mechanisms fail.
     d:  generate report if DKIM signature failed to verify
     s: generate report if SPF failed
rua - the email address dmarc reports should be sent to
Check your dmarc set-up as follows
dig txt +short _dmarc.example.com

Set up aliases

Open alias file
$ sudo nano /etc/aliases
Edit file as needed.
# See man 5 aliases for format postmaster: root abuse: root webmaster: root
admin: root root: account you want root email directed to

Thunderbird

If you choose Thunderbird for email note the first time you open the Thunderbird program you need to change the default where Thunderbird looks for your inbound mail.  To do this, Enable the menu (right click at the top click box for menu bar or enter alt or F10).  Go to Edit>>Preferences>>Advanced. Find the section near the bottom where it says Message Store Type for new accounts click the down arrow and select File per message (maildir) .  Close the menu then proceed with adding new accounts.>