Created
August 4, 2022 18:06
-
-
Save valiantboymaksud/3d75658bde4e8f74480fcb789a976b9d to your computer and use it in GitHub Desktop.
Full Installation and Configuration of Apache2, Multiple PHP, MariaDB, phpMyAdmin, LetsEncrypt, HTTP/2, IonCube, Postfix, Dovecot, SPF, DKIM, Roundcube Webmail and Files Permission Commands on Ubuntu 18.04 and 18.10 Web Server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Complete Installation and Configuration of Apache2, Multiple PHP, MariaDB, phpMyAdmin, LetsEncrypt, | |
HTTP/2, IonCube, Postfix, Dovecot, SPF, DKIM, Roundcube Webmail and | |
Files Permission Commands on Ubuntu 18.04 and 18.10 Web Server | |
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | |
This is a complete Ubuntu Linux based web server for Website, PHP, SSL, TLS, Database and Email hosting purpose. | |
Built with the below components for good performance. Also, I tried to make it as secure as possible. | |
DISCLAIMER: I'm making this guide just for my own purpose and needs. But, If it meets your requirements, | |
please feel free to use those commands below. Remember, I'm not liable if any bad thing happens to your server. | |
My recommendation is to you that use this on a testing server before using it on a production server. | |
Just kidding; do whatever you like, at your own risk. | |
Please contact me: If you need Linux server maintenance and installation help. | |
MY CONTACT: | |
EMAIL: [email protected] | |
SKYPE: maksud.masum5 | |
MOBILE: +8801875958005 (Bangladesh) | |
FACEBOOK: www.fb.me/valiantboymaksud | |
Software Lists: | |
01. Apache2 | |
02. PHP | |
03. HTTP/2 [OPTIONAL] | |
04. MariaDB | |
05. phpMyAdmin [OPTIONAL] | |
06. LetsEncrypt [OPTIONAL] | |
07. IonCube [OPTIONAL] | |
08. Postfix | |
09. Dovecot | |
10. SPF | |
11. DKIM | |
12. Roundcube [OPTIONAL] | |
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # | |
## Lets Update The Ubuntu Linux Server before creating the web serevr | |
sudo apt update && sudo apt upgrade -y && sudo apt dist-upgrade && sudo apt autoremove && sudo apt update | |
01. Apache2 | |
------------------- | |
## Lets Install Apache2 Web Server | |
sudo apt install apache2 libapache2-mod-fcgid -y | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Commands below can be used to stop, start and enable Apache2 service | |
sudo systemctl stop apache2.service | |
sudo systemctl start apache2.service | |
sudo systemctl enable apache2.service | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Let's add a domain .conf file with PHP7.2-FPM enabled | |
sudo nano /etc/apache2/sites-available/example.com.conf | |
## Add below lines into the example.com.conf file and save it. | |
# # # # # # # # # # # # # # # # # # # # # # | |
<VirtualHost *:80> | |
ServerAdmin [email protected] | |
DocumentRoot /var/www/html/example.com | |
ServerName example.com | |
ServerAlias www.example.com | |
<Directory /var/www/html/example.com/> | |
Options +FollowSymlinks | |
AllowOverride All | |
Require all granted | |
</Directory> | |
<FilesMatch \.php$> | |
SetHandler "proxy:unix:/var/run/php/php7.2-fpm.sock|fcgi://localhost/" | |
</FilesMatch> | |
ErrorLog ${APACHE_LOG_DIR}/error.log | |
CustomLog ${APACHE_LOG_DIR}/access.log combined | |
</VirtualHost> | |
# # # # # # # # # # # # # # # # # # # # # # | |
sudo mkdir /var/www/html/example.com | |
sudo ln -s /etc/apache2/sites-available/example.com.conf /etc/apache2/sites-enabled/ | |
sudo systemctl restart apache2.service | |
02. PHP | |
------------------- | |
## Add Extra Repository for PHP | |
sudo apt-get install software-properties-common | |
sudo add-apt-repository ppa:ondrej/php | |
sudo apt update | |
### Lets Install Multiple PHP or Install Just One Version!!! | |
## Install PHP based modules that are not found in various versions! [OPTIONAL] | |
sudo apt install php-common php-cgi php-mbstring php-xmlrpc php-soap php-gd php-xml php-intl php-mysql php-cli php-zip php-curl php-imap php-memcached php-memcache php-ldap php-redis php-tidy php-ssh2 php-oauth php-imagick php-bz2 php-apcu php-geoip | |
## Install PHP 5.6 and FPM and it's modules | |
sudo apt install php5.6 php5.6-fpm php5.6-common php5.6-cgi php5.6-mbstring php5.6-xmlrpc php5.6-soap php5.6-gd php5.6-xml php5.6-intl php5.6-mysql php5.6-cli php5.6-zip php5.6-curl php5.6-imap php5.6-opcache php5.6-memcached php5.6-memcache php5.6-ldap php5.6-redis php5.6-tidy php5.6-ssh2 php5.6-oauth php5.6-imagick php5.6-bz2 php5.6-apcu php5.6-geoip php5.6-gettext | |
## Install PHP 7.0 and FPM and it's modules | |
sudo apt install php7.0 php7.0-fpm php7.0-common php7.0-cgi php7.0-mbstring php7.0-xmlrpc php7.0-soap php7.0-gd php7.0-xml php7.0-intl php7.0-mysql php7.0-cli php7.0-zip php7.0-curl php7.0-imap php7.0-opcache php7.0-memcached php7.0-memcache php7.0-ldap php7.0-redis php7.0-tidy php7.0-ssh2 php7.0-oauth php7.0-imagick php7.0-bz2 php7.0-apcu php7.0-geoip php7.0-gettext | |
## Install PHP 7.1 and FPM and it's modules | |
sudo apt install php7.1 php7.1-fpm php7.1-common php7.1-cgi php7.1-mbstring php7.1-xmlrpc php7.1-soap php7.1-gd php7.1-xml php7.1-intl php7.1-mysql php7.1-cli php7.1-zip php7.1-curl php7.1-imap php7.1-opcache php7.1-memcached php7.1-memcache php7.1-ldap php7.1-redis php7.1-tidy php7.1-ssh2 php7.1-oauth php7.1-imagick php7.1-bz2 php7.1-apcu php7.1-geoip php7.1-gettext | |
## Install PHP 7.2 and FPM and it's modules | |
sudo apt install php7.2 php7.2-fpm php7.2-common php7.2-cgi php7.2-mbstring php7.2-xmlrpc php7.2-soap php7.2-gd php7.2-xml php7.2-intl php7.2-mysql php7.2-cli php7.2-zip php7.2-curl php7.2-imap php7.2-opcache php7.2-memcached php7.2-memcache php7.2-ldap php7.2-redis php7.2-tidy php7.2-ssh2 php7.2-oauth php7.2-imagick php7.2-bz2 php7.2-apcu php7.2-geoip php7.2-gettext | |
## Install PHP 7.3 and FPM and it's modules | |
sudo apt install php7.3 php7.3-fpm php7.3-common php7.3-cgi php7.3-mbstring php7.3-xmlrpc php7.3-soap php7.3-gd php7.3-xml php7.3-intl php7.3-mysql php7.3-cli php7.3-zip php7.3-curl php7.3-imap php7.3-opcache php7.3-memcached php7.3-memcache php7.3-ldap php7.3-redis php7.3-tidy php7.3-ssh2 php7.3-oauth php7.3-imagick php7.3-bz2 php7.3-apcu php7.3-geoip php7.3-gettext | |
## Install PHP 7.4 and FPM and it's modules | |
sudo apt install php7.4 php7.4-fpm php7.4-common php7.4-cgi php7.4-mbstring php7.4-xmlrpc php7.4-soap php7.4-gd php7.4-xml php7.4-intl php7.4-mysql php7.4-cli php7.4-zip php7.4-curl php7.4-imap php7.4-opcache php7.4-memcached php7.4-memcache php7.4-ldap php7.4-redis php7.4-tidy php7.4-ssh2 php7.4-oauth php7.4-imagick php7.4-bz2 php7.4-apcu php7.4-geoip php7.4-gettext | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Check Avaliable PHP7.2 Extensions / Modules [OPTIONAL] | |
sudo apt-cache search php7.2 | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Let's Configure PHP7.2-FPM with Apache2 | |
sudo a2enmod actions fcgid alias proxy_fcgi | |
sudo a2enconf php5.6-fpm php7.0-fpm php7.1-fpm php7.2-fpm php7.3-fpm | |
sudo a2dismod mpm_prefork | |
## Below Commands is only for just to make sure that php7.2 is disables. May show errors that php7.2 is not exist... | |
sudo a2dismod php7.2 | |
sudo a2enmod mpm_event | |
sudo systemctl restart apache2.service | |
sudo systemctl restart php5.6-fpm.service | |
sudo systemctl restart php7.0-fpm.service | |
sudo systemctl restart php7.1-fpm.service | |
sudo systemctl restart php7.3-fpm.service | |
sudo systemctl restart php7.3-fpm.service | |
## Configure PHP.ini file | |
sudo nano /etc/php/7.2/fpm/php.ini | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Make the changes on the following lines below in the file and save... | |
cgi.fix_pathinfo=0 | |
file_uploads = On | |
allow_url_fopen = On | |
date.timezone = Asia/Dhaka | |
upload_tmp_dir = /var/tmp | |
post_max_size = 4096M | |
upload_max_filesize = 4096M | |
max_execution_time = 5000 | |
max_input_time = 5000 | |
memory_limit = 1024M | |
max_input_vars = 5000 | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Check installed php extensions | |
php -m | |
## Lets restart the service | |
sudo systemctl restart php7.2-fpm.service | |
03. HTTP/2 [OPTIONAL] | |
---------------------- | |
## Prerequisites | |
### Enable HTTPS on your server. All major browsers allow using of HTTP/2 only over HTTPS. | |
### TLS protocol version >= 1.2 with modern cipher suites is required. | |
### Ensure that you are running Apache 2.4.17 or above because HTTP/2 is supported from this version and upwards. | |
### If you run PHP in Apache via mod_php, you need to switch to FPM. That is not a bad thing. FPM is newer and faster. | |
## Switching Apache’s PHP Module from MPM Prefork to Event | |
sudo apt-get install php7.2-fpm (not required if already installed) | |
sudo a2enmod proxy_fcgi | |
sudo a2enconf php7.2-fpm | |
sudo a2dismod php7.2 (not required if not installed) | |
sudo a2dismod mpm_prefork | |
sudo a2enmod mpm_event | |
sudo systemctl restart apache2.service | |
## Lets enable the module mod_http2 | |
sudo a2enmod http2 | |
sudo systemctl restart apache2.service | |
sudo systemctl restart php7.2-fpm.service | |
## Enable the HTTP/2 protocol by adding the following to /etc/apache2/apache2.conf: | |
Protocols h2 http/1.1 | |
sudo nano /etc/apache2/sites-available/example.com.conf | |
## Examples of adding apache2.conf file Protocols h2 http/1.1 | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Don not forget to put the below code inside the both SSL and HTTP conf for the domain | |
<VirtualHost *:443> | |
Protocols h2 http/1.1 | |
... | |
... | |
... | |
</VirtualHost> | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Lets restart few services | |
sudo systemctl restart apache2.service | |
sudo systemctl restart php7.2-fpm.service | |
## Verify that HTTP/2 is Working from here: https://tools.keycdn.com/http2-test | |
04. MariaDB | |
------------------- | |
## Lets Install MariaDB Database Server | |
sudo apt-get install mariadb-server mariadb-client -y | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Commands below can be used to stop, start and enable MariaDB service | |
sudo systemctl stop mariadb.service | |
sudo systemctl start mariadb.service | |
sudo systemctl enable mariadb.service | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Secure MariaDB server | |
sudo mysql_secure_installation | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Answer the questions below by following the guide. | |
Enter current password for root (enter for none): Just press the Enter | |
Set root password? [Y/n]: Y | |
New password: Enter password | |
Re-enter new password: Repeat password | |
Remove anonymous users? [Y/n]: Y | |
Disallow root login remotely? [Y/n]: Y | |
Remove test database and access to it? [Y/n]: Y | |
Reload privilege tables now? [Y/n]: Y | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Let's restart MariaDB server | |
sudo systemctl restart mariadb.service | |
05. phpMyAdmin [OPTIONAL] | |
--------------------------- | |
## Lets Install phpMyAdmin | |
sudo apt install phpmyadmin -y | |
# # # # # # # # # # # # # # # # # # # # # # | |
## When prompted to choose "Configuring phpmyadmin" | |
Web server to reconfigure automatically: select apache2 and continue. | |
Configure database for phpmyadmin with dbconfig-common: Yes | |
Create a password for phpMyAdmin: Please provide a password for phpmyadmin to register with the database… | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Lets restart | |
sudo systemctl restart apache2.service | |
## Now browse yourdomain.com/phpmyadmin and try to use (root) user login and password. | |
## Can't login there? Because, (root) user login is not permitted! Lets fix it below... | |
sudo mysql -u root | |
use mysql; | |
update user set plugin='' where User='root'; | |
flush privileges; | |
exit | |
sudo systemctl restart mariadb.service | |
06. LetsEncrypt [OPTIONAL] | |
--------------------------- | |
## Let's make sure that the apache2 domain conf is avaliable | |
sudo nano /etc/apache2/sites-available/example.com.conf | |
sudo ln -s /etc/apache2/sites-available/example.com.conf /etc/apache2/sites-enabled/ | |
# # # # # # # # # # # # # # # # # # # # # # | |
<VirtualHost *:80> | |
... | |
... | |
ServerName example.com | |
ServerAlias www.example.com | |
... | |
... | |
<VirtualHost> | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Let's Install Let’s Encrypt Apache Client | |
sudo apt-get install python-certbot-apache -y | |
## Please repleace the below example.com text with your own domain name. | |
sudo certbot --apache --agree-tos --email [email protected] --redirect --hsts -d example.com -d www.example.com | |
# # # # # # # # # # # # # # # # # # # # # # | |
## The commands options above are explained below: | |
### –apache: Use the Apache2 Let’s Encrypt installer | |
### –agree-tos: Agree to Let’s Encrypt terms of service | |
### –redirect: Adds 301 redirect. | |
### –email: Contact email address. | |
### –hsts: Adds the Strict-Transport-Security header to every HTTP response. | |
### – d flag is followed by domains you want to secure. | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Now, the SSL client should install the cert and configure your website to redirect all traffic over HTTPS. | |
## A new configuration file for the domain should also be created named /etc/apache2/sites-available/example.com-le-ssl.conf. | |
## The below highlighted code block should be added to your website configuration file automatically by Let’s Encrypt certbot. | |
## Your site should be ready to be used over HTTPS. | |
# # # # # # # # # # # # # # # # # # # # # # | |
<VirtualHost *:80> | |
... | |
... | |
ServerName example.com | |
ServerAlias www.example.com | |
... | |
... | |
RewriteEngine on | |
RewriteCond %{SERVER_NAME} =example.com [OR] | |
RewriteCond %{SERVER_NAME} =www.example.com | |
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] | |
... | |
... | |
<VirtualHost> | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Let's add Let’s Encrypt certificate auto renewal process using crontab | |
sudo crontab -e | |
## Add the line below and save | |
# # # # # # # # # # # # # # # # # # # # # # | |
# Lets Encrypt Monthly Domain Auto Renewal | |
0 1 * * * /usr/bin/certbot renew & > /dev/null | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Manual Let's Encrypt Renewal command is below | |
sudo certbot renew --dry-run | |
07. IonCube [OPTIONAL] | |
------------------------ | |
## Create a php info file in html folder and use your IP to browse it. | |
## http://your_server_ip/info.php | |
sudo nano /var/www/html/info.php | |
## Then paste the below lines from the box without hashes and save and exit. | |
# # # # # # # # # # # # # # # # # # # # # # | |
<?php | |
phpinfo(); | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Lets Download and unzip IonCube Loader Zip file inside /tmp directory | |
cd /tmp && wget http://downloads3.ioncube.com/loader_downloads/ioncube_loaders_lin_x86-64.tar.gz && tar xfz ioncube_loaders_lin_*.gz | |
## Then paste the below lines from the box without hashes and save and exit. | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Lets find the PHP extensions directory on the system | |
php -i | grep extension_dir | |
## example below of the result and remember the directory | |
extension_dir => /usr/lib/php/20180731 => /usr/lib/php/20180731 | |
# # # # # # # # # # # # # # # # # # # # # # | |
## Now copy the ioncube loader inside the above extension_dir | |
sudo cp /tmp/ioncube/ioncube_loader_lin_5.6.so /usr/lib/php/20180731 | |
sudo cp /tmp/ioncube/ioncube_loader_lin_7.0.so /usr/lib/php/20180731 | |
sudo cp /tmp/ioncube/ioncube_loader_lin_7.1.so /usr/lib/php/20180731 | |
sudo cp /tmp/ioncube/ioncube_loader_lin_7.2.so /usr/lib/php/20180731 | |
sudo cp /tmp/ioncube/ioncube_loader_lin_7.3.so /usr/lib/php/20180731 | |
## Lets create a file inside /etc/php/5.6/fpm/conf.d/ for php front end version | |
sudo nano /etc/php/5.6/fpm/conf.d/00-ioncube.ini | |
## Then paste the below lines and save. For PHP 5.6 | |
zend_extension = /usr/lib/php/20180731/ioncube_loader_lin_5.6.so | |
## Lets create a file inside /etc/php/7.0/fpm/conf.d/ for php front end version | |
sudo nano /etc/php/7.0/fpm/conf.d/00-ioncube.ini | |
## Then paste the below lines and save. For PHP 7.0 | |
zend_extension = /usr/lib/php/20180731/ioncube_loader_lin_7.0.so | |
## Lets create a file inside /etc/php/7.1/fpm/conf.d/ for php front end version | |
sudo nano /etc/php/7.1/fpm/conf.d/00-ioncube.ini | |
## Then paste the below lines and save. For PHP 7.1 | |
zend_extension = /usr/lib/php/20180731/ioncube_loader_lin_7.1.so | |
## Lets create a file inside /etc/php/7.2/fpm/conf.d/ for php front end version | |
sudo nano /etc/php/7.2/fpm/conf.d/00-ioncube.ini | |
## Then paste the below lines and save. For PHP 7.2 | |
zend_extension = /usr/lib/php/20180731/ioncube_loader_lin_7.2.so | |
## Lets create a file inside /etc/php/7.3/fpm/conf.d/ for php front end version | |
sudo nano /etc/php/7.3/fpm/conf.d/00-ioncube.ini | |
## Then paste the below lines and save. For PHP 7.3 | |
zend_extension = /usr/lib/php/20180731/ioncube_loader_lin_7.3.so | |
## Lets create a symlink, inside the server (CLI) encryptrd files with ioncube will not work inside server if not created... | |
sudo ln -s /etc/php/5.6/fpm/conf.d/00-ioncube.ini /etc/php/5.6/cli/conf.d/ | |
sudo ln -s /etc/php/7.0/fpm/conf.d/00-ioncube.ini /etc/php/7.0/cli/conf.d/ | |
sudo ln -s /etc/php/7.1/fpm/conf.d/00-ioncube.ini /etc/php/7.1/cli/conf.d/ | |
sudo ln -s /etc/php/7.2/fpm/conf.d/00-ioncube.ini /etc/php/7.2/cli/conf.d/ | |
sudo ln -s /etc/php/7.3/fpm/conf.d/00-ioncube.ini /etc/php/7.3/cli/conf.d/ | |
## Lets restart the web server to take effect. | |
sudo systemctl restart apache2.service | |
sudo systemctl restart php5.6-fpm.service | |
sudo systemctl restart php7.0-fpm.service | |
sudo systemctl restart php7.1-fpm.service | |
sudo systemctl restart php7.2-fpm.service | |
sudo systemctl restart php7.3-fpm.service | |
## Lets Verify the ionCube Installation on browser | |
# Go Back on the http://your_server_ip/info.php page, refresh the page and search for the "ionCube" keyword. | |
## Use the below command to see is it working or not. | |
php -v | |
08. Postfix | |
---------------------- | |
# Set A Correct Hostname for Ubuntu Server | |
hostname -f | |
sudo hostnamectl set-hostname example.com | |
# Set System Time | |
sudo dpkg-reconfigure tzdata | |
# To let your system read RTC time in UTC standard | |
timedatectl set-local-rtc 0 | |
# To let your system read RTC time in local time zone | |
timedatectl set-local-rtc 1 | |
# Now check status | |
timedatectl status | |
# Set up DNS Records for Your Mail Server | |
## EXAMPLE: MX record | |
MX record @ mail.example.com | |
## EXAMPLE: A record | |
mail.example.com <IP-address> | |
# Lety's check PTR record | |
dig -x <IP> +short | |
# Lets Install Postfix | |
sudo apt-get update | |
sudo apt-get install postfix -y | |
############################################################# | |
##You will be asked | |
### General type of mail configuration: Internet Site | |
### System mail name: example.com | |
############################################################# | |
# Let's check postfix version | |
sudo postconf mail_version | |
# Let's check the port | |
sudo netstat -lnpt | |
# Lety's check your server open Port | |
sudo apt install nmap | |
sudo nmap your-server-ip | |
# Send Test Email | |
echo "test email" | sendmail [email protected] | |
# The inbox for each user is located at | |
postconf mail_spool_directory | |
# Using the mail program to Send and Read Email | |
sudo apt-get install mailutils | |
# To send email | |
mail [email protected] | |
############################################################### | |
user@mail:~$ mail [email protected] | |
Cc: | |
Subject: 2nd test email | |
I'm sending this email using the mail program. | |
### Enter subject line and the body text. | |
### Press Ctrl+D and mail will send this email message for you. | |
### To read incoming emails, just type "mail" | |
### To read the first email message, type 1. | |
### If only parts of the message is displayed, press Enter to show the remaining part of the message. | |
### To display message headers starting from message 1, type h. | |
### To show the last screenful of messages, type h$ or z. | |
### To read the next email message, type n. | |
### To delete message 1, type d 1. | |
### To delete message 1, 2 and 3, type d 1 2 3. | |
### To delete messages from 1 to 10, type d 1-10. | |
### To replay to message 1, type reply 1. | |
### To exit out of mail, type q. | |
############################################################### | |
## EXTRAS : Setting up Postfix as a Forward Only Mail Host | |
# Forward every incoming email to another email service like Gmail | |
nano ~/.forward | |
############################################################### | |
### and add an email address in the file. | |
[email protected] | |
### Save and close the file. That’s all you have to do. | |
############################################################### | |
09. Dovecot | |
---------------------- | |
# Install Dovecot IMAP server and Enable TLS Encryption | |
sudo apt install software-properties-common | |
sudo add-apt-repository ppa:certbot/certbot | |
sudo apt update | |
sudo apt install certbot | |
sudo apt install python3-certbot-apache | |
sudo apt install python3-certbot-nginx | |
# Obtaining TLS Certificate with Apache Web Server | |
sudo nano /etc/apache2/sites-available/mail.example.com.conf | |
########################################################### | |
### Then paste the following text into the file. | |
<VirtualHost *:80> | |
ServerName mail.example.com | |
DocumentRoot /var/www/html/mail.example.com | |
</VirtualHost> | |
### Save and close the file | |
########################################################### | |
# Create the web root directory | |
sudo mkdir /var/www/html/mail.example.com | |
sudo chown www-data:www-data /var/www/html/mail.example.com -R | |
# Enable this virtual host | |
sudo a2ensite mail.example.com.conf | |
# Reload Apache | |
sudo systemctl reload apache2 | |
# Obtain and install Let’s Encrypt TLS certificate | |
sudo certbot --apache --agree-tos --redirect --hsts --email your-email-address -d mail.example.com | |
# Configuring Postfix | |
# Enable the submission service of Postfix | |
sudo nano /etc/postfix/master.cf | |
########################################################### | |
### In submission section, uncomment or add the following lines. | |
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 | |
### The above configuration enables the submission daemon of Postfix and requires TLS encryption. | |
### The submission daemon listens on TCP port 587. | |
### STARTTLS is used to encrypt communications between email client and the submission daemon. | |
########################################################### | |
# Let's Postfix know where TLS certificate and private key are. | |
sudo nano /etc/postfix/main.cf | |
########################################################### | |
### Edit the TLS parameter as follows: change the example.com with your domain | |
smtpd_tls_cert_file=/etc/letsencrypt/live/mail.example.com/fullchain.pem | |
smtpd_tls_key_file=/etc/letsencrypt/live/mail.example.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 | |
########################################################### | |
# Reload Postfix | |
sudo postfix reload | |
# See port 587 is now open | |
sudo netstat -lnpt | |
# Installing Dovecot IMAP Server | |
sudo apt install dovecot-core dovecot-imapd | |
# Check Dovecot version | |
sudo dovecot --version | |
# Configuring Dovecot | |
# Edit main config file. | |
sudo nano /etc/dovecot/dovecot.conf | |
########################################################### | |
### Add the following line to enable IMAP protocol. | |
protocols = imap | |
########################################################### | |
# Configuring Mailbox Location | |
## By default, Postfix uses mbox format to store emails. | |
## Each user’s emails is stored in a single file /var/mail/username | |
## Find the mail spool directory | |
postconf mail_spool_directory | |
########################################################### | |
### Sample output: | |
mail_spool_directory = /var/mail | |
########################################################### | |
# The config file for mailbox location is /etc/dovecot/conf.d/10-mail.conf | |
sudo nano /etc/dovecot/conf.d/10-mail.conf | |
########################################################### | |
### The default configuration is as follows, which is fine for a small email server. | |
mail_location = mbox:~/mail:INBOX=/var/mail/%u | |
### Add the following line in the file. (On Ubuntu 18.04, this line is already in the file.) | |
mail_privileged_group = mail | |
########################################################### | |
# Add dovecot to the mail group so that Dovecot can read the INBOX | |
sudo gpasswd -a dovecot mail | |
# Configuring Authentication Mechanism | |
# Edit the authentication config file. | |
sudo nano /etc/dovecot/conf.d/10-auth.conf | |
########################################################### | |
### Uncomment the following line. | |
disable_plaintext_auth = yes | |
### It will disable plaintext authentication when there’s no SSL/TLS encryption. | |
### And if you want to use full email address ([email protected]) to login, add the following line in the file. | |
auth_username_format = %n | |
### Find the following line. and add "login" after "plain" as follows | |
auth_mechanisms = plain login | |
########################################################### | |
# Configuring SSL/TLS Encryption | |
# Edit SSL/TLS config file. | |
sudo nano /etc/dovecot/conf.d/10-ssl.conf | |
########################################################### | |
### Change ssl = no/yes to ssl = required. | |
ssl = required | |
### Specify the location of your SSL/TLS cert and private key. | |
### Don’t leave out < character. It’s necessary. | |
ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem | |
ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem | |
########################################################### | |
# SASL Authentication Between Postfix and Dovecot | |
# Edit the following file. | |
sudo nano /etc/dovecot/conf.d/10-master.conf | |
########################################################### | |
### Change "service auth" section to the following so that Postfix can find the Dovecot authentication server. | |
service auth { | |
unix_listener /var/spool/postfix/private/auth { | |
mode = 0660 | |
user = postfix | |
group = postfix | |
} | |
} | |
########################################################### | |
# Auto-create Sent and Trash Folder | |
# Edit the below config file. | |
sudo nano /etc/dovecot/conf.d/15-mailboxes.conf | |
########################################################### | |
### To auto create a folder, simply add the following line in the mailbox section. | |
auto = create | |
### Example: | |
mailbox Trash { | |
auto = create | |
special_use = \Trash | |
} | |
########################################################### | |
# Dovecot will be listening on port 143 (IMAP) and 993 (IMAPS). | |
# If there’s a configuration error, dovecot will fail to restart. | |
# We also need to restart Postfix to allow the LOGIN authentication mechanism. | |
# Restart Dovecot and Postfix | |
sudo systemctl restart dovecot | |
sudo systemctl restart postfix | |
# The Final Step: Configure Desktop Email Client | |
# Now open up your desktop email client such as Mozilla Thunderbird and add a mail account. | |
########################################################### | |
### In the incoming server section, select IMAP protocol, enter mail.example.com as the server name, | |
### choose port 993 and SSL/TLS. Choose normal password as the authentication method. | |
### In the outgoing section, select SMTP protocol, enter mail.example.com as the server name, | |
###choose port 587 and STARTTLS. Choose normal password as the authentication method. | |
### Note: Linux matchine username and password will be used as user email and password | |
### Example: Username: [email protected] | |
########################################################### | |
10. SPF | |
---------------------- | |
# Create an SPF Record in DNS | |
# Create a new TXT record like below. | |
TXT @ v=spf1 mx ~all | |
# Check if your SPF record is propagated to the public Internet, | |
# Use the dig utility on your Linux machine like below: | |
dig example.com txt | |
# Configuring SPF Policy Agent | |
sudo apt install postfix-policyd-spf-python | |
# Edit the Postfix master process configuration file. | |
sudo nano /etc/postfix/master.cf | |
########################################################### | |
### Add the following lines at the end of the file. | |
policyd-spf unix - n n - 0 spawn | |
user=policyd-spf argv=/usr/bin/policyd-spf | |
########################################################### | |
# Edit Postfix main configuration file. | |
sudo nano /etc/postfix/main.cf | |
########################################################### | |
### Append the following lines at the end of the file. | |
### The first line specifies the Postfix policy agent timeout setting. | |
### The following lines will impose restriction on incoming emails by rejecting unauthorized email and checking SPF record. | |
policyd-spf_time_limit = 3600 | |
smtpd_recipient_restrictions = | |
reject_unauth_destination, | |
check_policy_service unix:private/policyd-spf | |
########################################################### | |
# Restart Postfix. | |
sudo systemctl restart postfix | |
11. DKIM | |
---------------------- | |
# Setting up DKIM | |
sudo apt install opendkim opendkim-tools | |
sudo gpasswd -a postfix opendkim | |
# Edit OpenDKIM main configuration file. | |
sudo nano /etc/opendkim.conf | |
########################################################### | |
### Uncomment the following lines. Replace simple with relaxed/simple. | |
Canonicalization simple | |
Mode sv | |
SubDomains no | |
### Then add the following lines below #ADSPAction continue line. | |
### If your file doesn’t have #ADSPAction continue line, then just add them below SubDomains no. | |
AutoRestart yes | |
AutoRestartRate 10/1M | |
Background yes | |
DNSTimeout 5 | |
SignatureAlgorithm rsa-sha256 | |
### Add the following lines at the end of this file. | |
### On Ubuntu 18.04, the UserID is already set to opendkim. | |
#OpenDKIM user | |
# Remember to add user postfix to group opendkim | |
UserID opendkim | |
# Map domains in From addresses to keys used to sign messages | |
KeyTable /etc/opendkim/key.table | |
SigningTable refile:/etc/opendkim/signing.table | |
# Hosts to ignore when verifying signatures | |
ExternalIgnoreList /etc/opendkim/trusted.hosts | |
InternalHosts /etc/opendkim/trusted.hosts | |
########################################################### | |
# Create Signing table, key table and trusted hosts file | |
# Create a directory structure for OpenDKIM | |
sudo mkdir /etc/opendkim | |
sudo mkdir /etc/opendkim/keys | |
# Change owner from root to opendkim and make sure only opendkim user can read and write to the keys directory. | |
sudo chown -R opendkim:opendkim /etc/opendkim | |
sudo chmod go-rw /etc/opendkim/keys | |
# Create the signing table. | |
sudo nano /etc/opendkim/signing.table | |
########################################################### | |
### Add this line to the file. | |
### Note that "example.com" and "example" is different. | |
### The latter should not contain the top-level domain. | |
*@example.com default._domainkey.example | |
########################################################### | |
# Create the key table. | |
sudo nano /etc/opendkim/key.table | |
########################################################### | |
### Add the following line. | |
default._domainkey.example example.com:default:/etc/opendkim/keys/example.com/default.private | |
########################################################### | |
# Configure Trusted Hosts | |
# Create the file. | |
sudo nano /etc/opendkim/trusted.hosts | |
########################################################### | |
### Add the following lines to the newly created file. | |
127.0.0.1 | |
localhost | |
*.example.com | |
########################################################### | |
# Generate Private/Public Keypair | |
# Create a separate folder for the domain. | |
sudo mkdir /etc/opendkim/keys/your-domain.com | |
# Generate keys using opendkim-genkey tool. | |
sudo opendkim-genkey -b 2048 -d example.com -D /etc/opendkim/keys/example.com -s default -v | |
# Make opendkim as the owner of the private key. | |
sudo chown opendkim:opendkim /etc/opendkim/keys/example.com/default.private | |
# Add Public Key in DNS Records | |
# Display the public key | |
# The string after the p parameter is the public key. | |
sudo cat /etc/opendkim/keys/example.com/default.txt | |
########################################################### | |
### In you DNS manager, create a TXT record, enter default._domainkey in the name field. | |
### Then copy everything in the parentheses and paste it into the value field. | |
### Delete all double quotes and white spaces. If you don’t delete them, then the key test in the next step will fail. | |
TXT default._domainkey v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApFNEbyADBeibEJw0/0YKXFdMRd0xoekp0VWFJUvY6DokBfPhiuPHY6vzt5Q5TkbXLI1PJgWF6S4mIiLwZgyijkSRx8lIVrJSHNxR0GU2HYNQMnOzYjcznQHhZXYA4SB2FKnxaURP+LzkesGSkunf11dMlSm7+ZvkZLE8+f1nCAXNL4BppgLhI1WOM12SEYefl4XND269kGVBM2 fnW96aMC3/uYbr0+20WbfcVWx7U9o93NpUvIA/JGxfibF/hbKBcVNyCPnWnyFfjaSJapI4mXG0GfSRTDxuZfINLPmjckaw1SDEGIuOD2hOSYKHJZImfAFPVGGAVk/4Et+bqsuAwwIDAQAB | |
########################################################### | |
# Test your configuration | |
sudo opendkim-testkey -d example.com -s default -vvv | |
########################################################### | |
### If everything is OK, you will see | |
key OK | |
########################################################### | |
# Connect Postfix to OpenDKIM | |
# Create a directory to hold the OpenDKIM socket file and only allow opendkim user and postfix group to access it. | |
sudo mkdir /var/spool/postfix/opendkim | |
sudo chown opendkim:postfix /var/spool/postfix/opendkim | |
# Edit the socket configuration file. | |
# Note: On Ubuntu 18.04, the opendkim systemd service doesn’t use "/etc/default/opendkim" file. | |
# You need to change the socket file in "/etc/opendkim.conf" file. | |
sudo nano /etc/default/opendkim | |
########################################################### | |
### Find the following line: | |
SOCKET="local:/var/run/opendkim/opendkim.sock" | |
### Replace it with: | |
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock" | |
########################################################### | |
# Edit Postfix main configuration file. | |
sudo nano /etc/postfix/main.cf | |
########################################################### | |
### Add the following lines after "smtpd_recipient_restriction" section. | |
# Milter configuration | |
milter_default_action = accept | |
milter_protocol = 6 | |
smtpd_milters = local:/opendkim/opendkim.sock | |
non_smtpd_milters = $smtpd_milters | |
########################################################### | |
# Restart opendkim and postfix service. | |
sudo systemctl restart opendkim | |
sudo systemctl restart postfix | |
# SPF and DKIM Check | |
# use your desktop email client or webmail client to send a test email to "[email protected]" | |
12. Roundcube [OPTIONAL] | |
-------------------------- | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment