This is install a LAMP stack on CentOS 8 with virtual host support, PHP, fail2ban, SSH security, letsencrypt, auto updates.
Install CentOS 8 minimal with 2 CPU, 512MB+ RAM, 20GB+ storage, set FQDN, set static IP, enable NTP.
3.) After install if finished reboot → login → perform a “dnf update”.
useradd example_user && passwd example_user usermod -aG wheel example_user
dnf install unzip wget vim tar
Logout of root and login using sudo user
sudo vim /etc/ssh/sshd_config
then set
PermitRootLogin no
To help keep things organized we'll create a keypair that is specific to the user and the remote sudo user+host.
https://www.ssh.com/ssh/keygen/
ssh-keygen -C "your_email@example.com" -f ~/.ssh/your_email@example.com-remote_sudo_username_@remote_hostname -t ed25519
Record the private and public keys in a secure document for the webserver.
Copy the public key to the remote webserver.
ssh-copy-id -i ~/.ssh/your_email@example.com-remote_sudo_username_@remote_hostname.pub sudo_username@remote_hostname
sudo vim /etc/ssh/sshd_config
then set
PasswordAuthentication no
Restart sshd
sudo systemctl restart sshd
Login using SSH key
ssh -i deployment_key.txt demo@192.237.248.66
https://www.tecmint.com/install-lamp-on-centos-8/ https://linuxize.com/post/how-to-install-php-on-centos-8/ https://www.linode.com/docs/web-servers/lamp/how-to-install-a-lamp-stack-on-centos-8/ https://www.linode.com/docs/web-servers/apache/how-to-install-and-configure-fastcgi-and-php-fpm-on-centos-8/ https://www.digitalocean.com/community/tutorials/how-to-run-multiple-php-versions-on-one-server-using-apache-and-php-fpm-on-ubuntu-18-04 https://certbot.eff.org/lets-encrypt/centosrhel8-apache.html
sudo vim /etc/hosts
Add a line for your FQDN
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.10.30 websrv01.domainname.com websrv01
sudo dnf install httpd httpd-tools sudo systemctl enable httpd sudo systemctl start httpd sudo firewall-cmd --permanent --zone=public --add-service=http sudo firewall-cmd --permanent --zone=public --add-service=https sudo firewall-cmd --reload
sudo dnf install mariadb-server mariadb sudo systemctl enable mariadb sudo systemctl start mariadb sudo mysql_secure_installation
sudo dnf install dnf-utils http://rpms.remirepo.net/enterprise/remi-release-8.rpm sudo dnf module reset php sudo dnf module enable php:remi-8.2 sudo dnf install php php-opcache php-gd php-curl php-mysqlnd mod_fcgid sudo systemctl enable php-fpm sudo systemctl start php-fpm
Increase upload and post size limit for PHP
sudo vim /etc/php.ini
Modify the following lines to meet your requirements
upload_max_filesize = 50M ; post_max_size = 50M ;
Note: isn't taking full advantage of the feature, feel free to research more if needed.
sudo cp /etc/php-fpm.d/www.conf /etc/php-fpm.d/example.com.conf
Edit the file to change the socket name, user and group, and socket listen address. Ensure that the listen address is different from the listen address that you set in the main PHP pool configuration file. You can append the name of your site as part of the file name, for example, listen = /var/run/php-fpm/example.com.sock. Also, ensure that you comment out or replace any existing user and group and add your own user and group settings as shown in the example.
sudo vim /etc/php-fpm.d/example.com.conf
; Start a new pool named 'www'. ; the variable $pool can be used in any directive and will be replaced by the ; pool name ('www' here) [www] ... ; Unix user/group of processes ; Note: The user is mandatory. If the group is not set, the default user's group ; will be used. user = apache group = apache ... listen = /var/run/php-fpm/www.sock
Note: you can replace each instance of www with example.domain.com by using the following in vim:
:g/www/s//example\.domain\.com/g
The $s searches through the whole file, the \. is needed because . is a special regex pattern and the \ escapes it… though I'm still not entirely sure what escapes is; regex to me is like cooking or playing music, magic.
sudo mkdir -p /var/www/html/site1.your_domain/public_html sudo mkdir -p /var/www/html/site2.your_domain/public_html
sudo chown -R apache:apache /var/www/html/site1.your_domain/public_html sudo chown -R apache:apache /var/www/html/site2.your_domain/public_html sudo chmod -R 755 /var/www/html/site1.your_domain/public_html sudo chmod -R 755 /var/www/html/site2.your_domain/public_html
Create a file in each site to test webserver and show php version
sudo vim /var/www/html/site1.your_domain/public_html/info.php
Add
<?php phpinfo(); ?>
sudo vim /etc/httpd/conf.d/site1.your_domain.conf
Add the following content. Make sure the website directory path, server name, and PHP version match your setup:
<Directory /var/www/html/example.com/public_html> Require all granted Options -Indexes -MultiViews -Includes -FollowSymLinks </Directory> <VirtualHost *:80> ServerAdmin webmaster@example.com ServerName example.com ServerAlias www.example.com DocumentRoot /var/www/html/example.com/public_html ErrorLog /var/log/httpd/example.com_error.log CustomLog /var/log/httpd/example.com_access.log combined DirectoryIndex index.php <IfModule mod_fcgid.c> Options +ExecCGI FcgidConnectTimeout 20 AddType application/x-httpd-php .php AddHandler application/x-httpd-php .php Alias /php7-fcgi /usr/lib/cgi-bin/php7-fcgi ProxyPassMatch " ^/(.*\.php(/.*)?)$" "unix:/run/php-fpm/example.com.sock|fcgi://localhost/var/www/html/example.com/public_html/" </IfModule> </VirtualHost>
Save and close the file when you are finished. Then check the Apache configuration file for any syntax errors:
sudo httpd -t
You’ll see the following output:
Output Syntax OK
https://www.if-not-true-then-false.com/2009/howto-hide-and-modify-apache-server-information-serversignature-and-servertokens-and-hide-php-version-x-powered-by/
This will help to prevent being the target of a an attack if you're running an out of date or vunerable release
sudo vim /etc/httpd/conf/httpd.conf
Add the following:
ServerSignature Off ServerTokens Prod
And add your timezone…
sudo vim /etc/php.ini
Change the following:
expose_php = Off date.timezone = America/Los_Angeles
Finally, restart the Apache service and PHP-FPM to implement your changes:
sudo systemctl restart httpd sudo systemctl restart php-fpm
Now that you have configured Apache to serve each site, you will test them to make sure the proper PHP versions are running.
test.example.com/info.php
delete the info.php after your'e done.
delete the welconf.conf to disable the default apache welcome page.
sudo rm /etc/httpd/conf.d/welcome.conf
This is important as it would allow access to the /var/www/html path via HTTP.
sudo vim /etc/httpd/conf/httpd.conf
Modify the following statements to mirror the examples below:
DocumentRoot "/var/www/html" <Directory "/var/www"> AllowOverride None Require all denied Options None </Directory> <Directory "/var/www/html"> AllowOverride None Require all denied Options None </Directory> <Directory "/var/www/cgi-bin"> AllowOverride None Require all denied Options None </Directory>
wget https://dl.eff.org/certbot-auto sudo mv certbot-auto /usr/local/bin/certbot-auto sudo chown root /usr/local/bin/certbot-auto sudo chmod 0755 /usr/local/bin/certbot-auto
Generate local certificates
sudo /usr/libexec/httpd-ssl-gencerts
Request and install certificates for virtual hosts
sudo /usr/local/bin/certbot-auto --apache
When prompted enabled Redirect so all requests go over https
Enable autorenew via crontab
echo "0 0,12 * * * root python3 -c 'import random; import time; time.sleep(random.random() * 3600)' && /usr/local/bin/certbot-auto renew -q" | sudo tee -a /etc/crontab > /dev/null
Enable SSL Apache
https://www.thesslstore.com/knowledgebase/ssl-generate/generate-csr-apache-web-server-using-openssl-v-2/ https://forums.centos.org/viewtopic.php?t=43230 https://www.getpagespeed.com/server-setup/ssl-directory
Install Mod SSL
sudo dnf install mod_ssl sudo /usr/libexec/httpd-ssl-gencerts
sudo openssl req -new -newkey rsa:4096 -nodes -keyout site1.domain.com.key -out site1.domain.com.csr
Move the files to your PKI folder
sudo mv site1.domain.com.key /etc/pki/tls/private/
Set permissions on private key
sudo chown root:root /etc/pki/tls/private/site1.domain.com.key sudo chmod 600 /etc/pki/tls/private/site1.domain.com.key sudo restorecon -RvF /etc/pki/tls/private/
Submit the CSR to your CA (public or private)
Copy the BASE64 certificate from your CA to your cert folder
sudo vim /etc/pki/tls/certs/site1.domain.com.crt
Create the CA bundle associated with your certificate
sudo vim /etc/pki/tls/certs/site1.domain.com.ca-bundle
Paste the subordinate followed by the root BASE64 certificates
Edit the conf file for you website and change
<VirtualHost *:443> DocumentRoot /var/www/html/site1.domain.com/public_html ServerName site1.domain.com SSLEngine on SSLCertificateFile /etc/pki/tls/certs/site1.domain.com.crt SSLCertificateKeyFile /etc/pki/tls/private/site1.domain.com.key SSLCertificateChainFile /etc/pki/tls/certs/site1.domain.com.ca-bundle .... .... .... </VirtualHost>
Do this only if you aren't using Letsencrypt for SSL/TLS
sudo firewall-cmd --remove-service=http --permanent sudo firewall-cmd --reload
Or…. if you want to leave http open and have the client automatically redirected to https add this to your website.conf file, below the existing Virtual Host block (add a new one):
<VirtualHost *:80> ServerName site1.domain.com RewriteEngine on RewriteCond %{SERVER_NAME} =site1.domain.com RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] </VirtualHost>
Restart Apache
sudo systemctl restart httpd
Note: if you are using your own internal CA you'll need to import the root and any intermediate certificates into your browsers/etc.
This is a send only SMTP server, create your public DNS records first. Then setup a virtual host for the domain of the mail server as this will allow us to use Letsencrypt certificates on the mail server. So if your smtp server is going to be mail.subdomain.domain.com then setup a virtual host to match that first then use certbot to get a letsencrypt certificate for that virtual host. We don't open any firewall rules to allow smtp traffic in as this will only send out messages from the host it runs on or the private subnets it's attached to.
sudo dnf install postfix mailx sudo systemctl enable postfix sudo systemctl start postfix sudo systemctl status postfix
This will configure it as a send only SMTP server
http://www.postfix.org/STANDARD_CONFIGURATION_README.html#local_network
sudo vim /etc/postfix/main.cf
Modify the following lines to match your domain/subnet
mydomain = subdomain.domain.com myorigin = $mydomain mynetworks = 127.0.0.0/8, 10.0.0.0/24, localhost
Restart Postfix
sudo systemctl restart postfix
Test sending an E-Mail
echo "Test Message" | mailx -s "Test Subject" recipient@somewhere.com
https://www.geekyramblings.net/2019/04/12/lets-encrypt-and-postfix/
sudo vim /etc/postfix/main.cf
Set the following variables
smtp_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem smtp_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem #smtp_tls_CApath = /etc/ssl/certs #smtp_tls_CAfile = /etc/ssl/certs/ca-bundle.crt 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_CApath = /etc/ssl/certs #smtpd_tls_CAfile = /etc/ssl/certs/ca-bundle.crt
Restart postfix
sudo systemctl restart postfix
Test sending an E-Mail again
echo "Test Message 2" | mailx -s "Test Subject 2" recipient@somewhere.com
I haven't validated the TLS certificates but everything appears to be working. For a full test you'll likely need to have a working reply to email to have the results sent back.
sudo vim /etc/letsencrypt/renewal-hooks/reload_postfix
Add the following
!/bin/sh for domain in $RENEWED_DOMAINS; do case $domain in subdomain.domain.com) cd /etc/letsencrypt/live/$domain chgrp letsencrypt *.pem chmod 640 *.pem /sbin/service postfix reload > /dev/null ;; esac done
Set permissions
sudo chmod 755 /etc/letsencrypt/renewal-hooks/reload_postfix
Setup a dedicated user for sending E-mail, use no_reply or similar so people get the picture. Use this info for SMTP authentication for your sending applications.
useradd no_reply && passwd no_reply
https://www.tecmint.com/dnf-automatic-install-security-updates-automatically-in-centos-8/
sudo dnf install dnf-automatic sudo vim /etc/dnf/automatic.conf
Set:
upgrade_type = security download_updates = yes apply_updates = yes system_name = (your system name) emit_via = motd
Enable the auto-update timer
sudo systemctl enable --now dnf-automatic.timer
https://idroot.us/install-fail2ban-centos-8/ https://www.digitalocean.com/community/tutorials/how-to-protect-an-apache-server-with-fail2ban-on-ubuntu-14-04
sudo dnf install fail2ban
sudo vim /etc/fail2ban/jail.d/sshd.local
Add the following:
[sshd] enabled = true port = ssh logpath = %(sshd_log)s backend = %(sshd_backend)s [selinux-ssh] enabled = true port = ssh logpath = %(auditd_log)s
sudo vim /etc/fail2ban/jail.d/apache.local
Add the following:
[apache-auth] enabled = true port = http,https logpath = %(apache_error_log)s [apache-badbots] enabled = true port = http,https logpath = %(apache_access_log)s bantime = 48h maxretry = 1 [apache-noscript] enabled = true port = http,https logpath = %(apache_error_log)s [apache-overflows] enabled = true port = http,https logpath = %(apache_error_log)s maxretry = 2 [apache-nohome] enabled = true port = http,https logpath = %(apache_error_log)s maxretry = 2 [apache-botsearch] enabled = true port = http,https logpath = %(apache_error_log)s maxretry = 2 [apache-modsecurity] enabled = true port = http,https logpath = %(apache_error_log)s maxretry = 2 [apache-shellshock] enabled = true port = http,https logpath = %(apache_error_log)s maxretry = 1
sudo systemctl start fail2ban sudo systemctl enable fail2ban sudo fail2ban-client status sshd