Installing LEMP with Nginx Security and Intrusion Prevention – Complete WordPress Hardening Guide – Part 2
In this tutorial we will install nginx , mariadb, php, and WordPress. We will also secure nginx from DoS and brute force attacks. Nginx security is already pretty good out of the box, and our CIS compliance hardening in step one has done a decent job have hardening the box. However we will add some addition nginx security, using fail2ban.
Also thanks to these sites for Nginx and fail2ban configuration
2.2 – Install Nginx
sudo apt install -y nginx
Install and Configure Maria DB to start at boot
sudo apt install -y mariadb-server sudo systemctl enable mariadb sudo systemctl start mariadb
Setup WP Database
sudo mysql_secure_installation
mysql -u root -p
After logging into mysql run these commands. (changing user/pass of course}
CREATE DATABASE wp_db; CREATE USER wpuser IDENTIFIED BY 'Passw0rd2'; GRANT ALL ON wp_db.* TO `wpuser`; exit
Install Cerbot for SSL Certificate
sudo apt install python-certbot-nginx -y
Install PHP
sudo apt install -y php sudo apt install -y php-pear php-fpm php-dev php-zip php-curl php-xmlrpc php-gd php-mysql php-mbstring php-xml libapache2-mod-php
Configure PHP for nginx
sudo sh -c "sed -i '/cgi.fix_pathinfo=1/c\cgi.fix_pathinfo=0' /etc/php/7.2/fpm/php.ini" sudo sh -c "echo '' >> /etc/php/7.2/fpm/php.ini" sudo sh -c "echo '' >> /etc/php/7.2/fpm/php.ini" sudo sh -c "echo ';***********************************************************' >> /etc/php/7.2/fpm/php.ini" sudo sh -c "echo '; WordPress Settings ' >> /etc/php/7.2/fpm/php.ini" sudo sh -c "echo ';***********************************************************' >> /etc/php/7.2/fpm/php.ini" sudo sh -c "echo 'upload_max_filesize = 500M' >> /etc/php/7.2/fpm/php.ini" sudo sh -c "echo 'post_max_size = 2000M' >> /etc/php/7.2/fpm/php.ini" sudo sh -c "echo 'memory_limit = 2000M' >> /etc/php/7.2/fpm/php.ini" sudo sh -c "echo 'max_execution_time = 120' >> /etc/php/7.2/fpm/php.ini"
Create nginx site file. Change mydomain.com
to your domain
sudo sh -c "cat > /etc/nginx/sites-available/mydomain.com <<\EOF server { listen 80; listen [::]:80; root /var/www/html; index index.php index.html index.htm; server_name mydomain.com www.mydomain.com; client_max_body_size 500M; location / { try_files \$uri \$uri/ /index.php?\$args; } location = /favicon.ico { log_not_found off; access_log off; } location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires max; log_not_found off; } location = /robots.txt { allow all; log_not_found off; access_log off; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php7.2-fpm.sock; fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name; include fastcgi_params; } } EOF "
Configure Site as Enabled and link the configuration file
sudo sh -c "ln -s /etc/nginx/sites-available/mydomain.com /etc/nginx/sites-enabled/" sudo sh -c "rm -f /etc/nginx/sites-available/default" sudo sh -c "rm -f /etc/nginx/sites-enabled/default" sudo systemctl restart nginx
Install WordPress
sudo sh -c "wget https://wordpress.org/latest.tar.gz -o /var/www/html/latest.tar.gz" sudo sh -c "tar -zxvf latest.tar.gz -C /var/www/html/ --strip-components=1" sudo sh -c "rm -rf /var/www/html/latest.tar.gz" sudo sh -c "cp /var/www/html/wp-config-sample.php /var/www/html/wp-config.php"
Set Permissions for /var/www/html/
sudo chown -R www-data:www-data /var/www/html/* sudo chmod -R 755 /var/www/html/*
Set WP Config (change username and password to match ones you created in mysql step)
sudo sh -c "sed -i '/database_name_here/c\define\( '\''DB_USER'\'', '\''wpuser'\'' \);' /var/www/html/wp-config.php" sudo sh -c "sed -i '/username_here/c\define\( '\''DB_NAME'\'', '\''wp_db'\'' \);' /var/www/html/wp-config.php" sudo sh -c "sed -i '/password_here/c\define\( '\''DB_PASSWORD'\'', '\''Passw0rd2'\'' \);' /var/www/html/wp-config.php"
Configure SSL
Follow prompts. Select 2 to route ALL traffic through through your website. Other settings can be default.
note: make sure you have your DNS pointed to your domain at this point if you cannot ping mydomain.com
and return your servers IP address, this step will fail and you will need to wait for DNS replication.
sudo certbot --nginx -m info@mydomain.com -d mydomain.com -d www.mydomain.com
Configure NGINX Security and SSH Intrusion Prevention by using Fail2ban
This configuration will mitigate brute forces and denial of service attacks.
Install Fail2ban for NGINX security
sudo apt install -y fail2ban
Configure Fail2ban to be enabled at boot
sudo systemctl enable fail2ban sudo systemctl start fail2ban
Create new Fail2ban config file
sudo sh -c "touch /etc/fail2ban/jail.local"
Configure SSH Jail
sudo sh -c "echo "" >> /etc/fail2ban/jail.local" sudo sh -c "echo "" >> /etc/fail2ban/jail.local" sudo sh -c "echo "#***********************************************************" >> /etc/fail2ban/jail.local" sudo sh -c "echo "# # SSH Jail Settings" >> /etc/fail2ban/jail.local" sudo sh -c "echo "#***********************************************************" >> /etc/fail2ban/jail.local" sudo sh -c "echo "" >> /etc/fail2ban/jail.local" sudo sh -c "echo "" >> /etc/fail2ban/jail.local" sudo sh -c "echo "[ssh]" >> /etc/fail2ban/jail.local" sudo sh -c "echo "enabled = true" >> /etc/fail2ban/jail.local" sudo sh -c "echo "port = ssh" >> /etc/fail2ban/jail.local" sudo sh -c "echo "filter = sshd" >> /etc/fail2ban/jail.local" sudo sh -c "echo "maxretry = 3 " >> /etc/fail2ban/jail.local" sudo sh -c "echo "bantime = 600 " >> /etc/fail2ban/jail.local" sudo sh -c "echo "ignoreip = 192.168.122.1" >> /etc/fail2ban/jail.local"
Configure NGINX Authentication Jail
sudo sh -c "echo "" >> /etc/fail2ban/jail.local" sudo sh -c "echo "" >> /etc/fail2ban/jail.local" sudo sh -c "echo "#***********************************************************" >> /etc/fail2ban/jail.local" sudo sh -c "echo "# # Nginx Auth Jail Settings" >> /etc/fail2ban/jail.local" sudo sh -c "echo "#***********************************************************" >> /etc/fail2ban/jail.local" sudo sh -c "echo "" >> /etc/fail2ban/jail.local" sudo sh -c "echo "" >> /etc/fail2ban/jail.local" sudo sh -c "echo "[nginx-auth]" >> /etc/fail2ban/jail.local" sudo sh -c "echo "enabled = true" >> /etc/fail2ban/jail.local" sudo sh -c "echo "filter = nginx-auth" >> /etc/fail2ban/jail.local" sudo sh -c "echo "action = iptables-multiport[name=NoAuthFailures, port="http,https"]" >> /etc/fail2ban/jail.local" sudo sh -c "echo "logpath = /var/log/nginx*/*error*.log" >> /etc/fail2ban/jail.local" sudo sh -c "echo "bantime = 600 " >> /etc/fail2ban/jail.local" sudo sh -c "echo "maxretry = 6" >> /etc/fail2ban/jail.local" sudo sh -c "echo "ignoreip = 192.168.122.1" >> /etc/fail2ban/jail.local"
Add NGINX login jail
sudo sh -c"echo "" >> /etc/fail2ban/jail.local" sudo sh -c"echo "" >> /etc/fail2ban/jail.local" sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local" sudo sh -c"echo "# # Nginx Login Jail Settings" >> /etc/fail2ban/jail.local" sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local" sudo sh -c"echo "" >> /etc/fail2ban/jail.local" sudo sh -c"echo "" >> /etc/fail2ban/jail.local" sudo sh -c"echo "[nginx-login]" >> /etc/fail2ban/jail.local" sudo sh -c"echo "enabled = true" >> /etc/fail2ban/jail.local" sudo sh -c"echo "filter = nginx-login" >> /etc/fail2ban/jail.local" sudo sh -c"echo "action = iptables-multiport[name=NoLoginFailures, port="http,https"]" >> /etc/fail2ban/jail.local" sudo sh -c"echo "logpath = /var/log/nginx*/*access*.log" >> /etc/fail2ban/jail.local" sudo sh -c"echo "bantime = 600 " >> /etc/fail2ban/jail.local" sudo sh -c"echo "maxretry = 6" >> /etc/fail2ban/jail.local" sudo sh -c"echo "ignoreip = 192.168.122.1" >> /etc/fail2ban/jail.local"
Add NGINX Jail for Bad Bots
sudo sh -c"echo "" >> /etc/fail2ban/jail.local" sudo sh -c"echo "" >> /etc/fail2ban/jail.local" sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local" sudo sh -c"echo "# # Nginx Bad Bots Jail Settings" >> /etc/fail2ban/jail.local" sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local" sudo sh -c"echo "" >> /etc/fail2ban/jail.local" sudo sh -c"echo "" >> /etc/fail2ban/jail.local" sudo sh -c"echo "[nginx-badbots]" >> /etc/fail2ban/jail.local" sudo sh -c"echo "enabled = true" >> /etc/fail2ban/jail.local" sudo sh -c"echo "filter = apache-badbots" >> /etc/fail2ban/jail.local" sudo sh -c"echo "action = iptables-multiport[name=BadBots, port="http,https"]" >> /etc/fail2ban/jail.local" sudo sh -c"echo "logpath = /var/log/nginx*/*access*.log" >> /etc/fail2ban/jail.local" sudo sh -c"echo "bantime = 86400 # 1 day" >> /etc/fail2ban/jail.local" sudo sh -c"echo "maxretry = 1" >> /etc/fail2ban/jail.local" sudo sh -c"echo "ignoreip = 192.168.122.1" >> /etc/fail2ban/jail.local"
Add NGINX Script Jail
sudo sh -c"echo "" >> /etc/fail2ban/jail.local sudo sh -c"echo "" >> /etc/fail2ban/jail.local sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local" sudo sh -c"echo "# # Nginx No Script Jail Settings" >> /etc/fail2ban/jail.local" sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local" sudo sh -c"echo "" >> /etc/fail2ban/jail.local sudo sh -c"echo "" >> /etc/fail2ban/jail.local sudo sh -c"echo "[nginx-noscript]" >> /etc/fail2ban/jail.local" sudo sh -c"echo "enabled = true" >> /etc/fail2ban/jail.local" sudo sh -c"echo "filter = nginx-noscript" >> /etc/fail2ban/jail.local" sudo sh -c"echo "action = iptables-multiport[name=NoScript, port="http,https"]" >> /etc/fail2ban/jail.local" sudo sh -c"echo "logpath = /var/log/nginx*/*access*.log" >> /etc/fail2ban/jail.local" sudo sh -c"echo "bantime = 86400 # 1 day" >> /etc/fail2ban/jail.local" sudo sh -c"echo "maxretry = 6" >> /etc/fail2ban/jail.local" sudo sh -c"echo "ignoreip = 192.168.122.1" >> /etc/fail2ban/jail.local"
Add NGINX Proxy Jail
sudo sh -c"echo "" >> /etc/fail2ban/jail.local" sudo sh -c"echo "" >> /etc/fail2ban/jail.local" sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local" sudo sh -c"echo "# # Nginx No Proxy Jail Settings" >> /etc/fail2ban/jail.local" sudo sh -c"echo "#***********************************************************" >> /etc/fail2ban/jail.local" sudo sh -c"echo "" >> /etc/fail2ban/jail.local" sudo sh -c"echo "" >> /etc/fail2ban/jail.local" sudo sh -c"echo "[nginx-noproxy]" >> /etc/fail2ban/jail.local" sudo sh -c"echo "enabled = true" >> /etc/fail2ban/jail.local" sudo sh -c"echo "filter = nginx-noproxy" >> /etc/fail2ban/jail.local" sudo sh -c"echo "action = iptables-multiport[name=NoProxy, port="http,https"]" >> /etc/fail2ban/jail.local" sudo sh -c"echo "logpath = /var/log/nginx*/*access*.log" >> /etc/fail2ban/jail.local" sudo sh -c"echo "bantime = 86400 " >> /etc/fail2ban/jail.local" sudo sh -c"echo "maxretry = 0" >> /etc/fail2ban/jail.local" sudo sh -c"echo "ignoreip = 192.168.122.1" >> /etc/fail2ban/jail.local"
Create Proxy config file for jail
sudo sh -c "cat > /etc/fail2ban/filter.d/nginx-proxy.conf <<EOF # Proxy filter /etc/fail2ban/filter.d/nginx-proxy.conf: # # Block IPs trying to use server as proxy. # # Matches e.g. # 192.168.1.1 - - GET http://www.something.com/ [Definition] failregex = ^<HOST> -.*GET http.* ignoreregex = EOF "
Create NoScript config file for jail
sudo sh -c "cat > /etc/fail2ban/filter.d/nginx-noscript.conf <<EOF # Noscript filter /etc/fail2ban/filter.d/nginx-noscript.conf: # # Block IPs trying to execute scripts such as .php, .pl, .exe and other funny scripts. # # Matches e.g. # 192.168.1.1 - - GET /something.php # [Definition] failregex = ^<HOST> -.*GET.*(\.php|\.asp|\.exe|\.pl|\.cgi|\scgi) ignoreregex = EOF "
Create Authentication config file for jail
sudo sh -c "cat > /etc/fail2ban/filter.d/nginx-auth.conf <<EOF # Auth filter /etc/fail2ban/filter.d/nginx-auth.conf: # # Blocks IPs that fail to authenticate using basic authentication # [Definition] failregex = no user/password was provided for basic authentication.*client: <HOST> user .* was not found in.*client: <HOST> user .* password mismatch.*client: <HOST> ignoreregex = EOF "
Create Login config file for jail
sudo sh -c "cat > /etc/fail2ban/filter.d/nginx-login.conf <<EOF # Login filter /etc/fail2ban/filter.d/nginx-login.conf: # # Blocks IPs that fail to authenticate using web application's log in page # # Scan access log for HTTP 200 + POST /sessions => failed log in [Definition] failregex = ^<HOST> -.*POST /sessions HTTP/1\..\" 200 ignoreregex = EOF "
Restart Fail2ban
sudo systemctl restart fail2ban
All Done , but Stay Tuned!!
That’s it! LEMP and WordPress are now configured on the server. We have also setup fail2ban jail for SSH, NGINX auth, login, proxy, scripts, and bad bots.
Stay tuned for Part 3 where we add server side caching and compression. This will really improve the speed of your website! You will be surprised how much performance we can get!
For Baseline hardening and configuration please see Part 1 of this guide.

2 thoughts on “Installing LEMP with Nginx Security and Intrusion Prevention – Complete WordPress Hardening Guide – Part 2”