Difference between revisions of ""Secure" Word Press on Amazon Linux"

From Michael's Information Zone
Jump to navigation Jump to search
 
(8 intermediate revisions by the same user not shown)
Line 1: Line 1:
WORK IN PROGRESS<br>
+
WORK IN PROGRESS: Amazon only allows ssh access without a console, you can easily get yourself locked out.<br>
These instructions follow my attempts for a generally "locked down" instance for running Word Press without losing sleep.<br>
+
==Purpose==
<br>
+
To run a simple wordpress site as "securely" as possible from the server side.
Version I am working with before updates<br>
+
==Process==
Linux ip-172-26-9-250 4.9.51-10.52.amzn1.x86_64 #1 SMP Fri Sep 29 01:16:19 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
+
==Non SELinux==
<br>
+
When this was written, we started using PHP 7 and needed Apache 2.4. Neither of these are standard installs for Amazon Linux.
<br>
+
===OS Prep===
<ref>https://www.tecmint.com/hide-apache-web-server-version-information/</ref><ref>https://www.tecmint.com/hide-php-version-http-header/</ref>
+
====Create SWAP====
 +
*Create SWAP file (Cloud hosted instances lack these). The following will create a 6GB swap file.<ref>https://www.centos.org/docs/5/html/5.2/Deployment_Guide/s2-swap-creating-file.html</ref>
 +
<pre>
 +
sudo dd if=/dev/zero of=/SWAP bs=1024 count=6291453
 +
sudo chmod 0600 /SWAP
 +
sudo mkswap /SWAP
 +
sudo swapon /SWAP
 +
</pre>
 +
*Add the swap file to FSTAB
 +
<pre>
 +
/SWAP swap swap defaults 0 0
 +
</pre>
 +
 
 +
====Install packages====
 +
Feel free to install updated php, this section will be updated as further testing is done. Also note the time zone if you are on the east coast.
 
<pre>
 
<pre>
 
sudo yum -y update
 
sudo yum -y update
sudo yum -y install libselinux libselinux-utils selinux-policy-minimum selinux-policy-mls selinux-policy-targeted policycoreutils fail2ban httpd24 mysql mysql-server php70 php70-mysqlnd mod24_ssl yum-cron
+
sudo yum -y install fail2ban httpd24 mysql mysql-server php70 php70-mysqlnd mod24_ssl yum-cron php70-mbstring php70-zip php-xml htop
 +
sudo yum -y install https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_x86_64.rpm
 
sudo ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime
 
sudo ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime
sudo sed -i 's/selinux=/selinux=1\ security=selinux\ enforcing=1/' /etc/grub.conf
+
sudo sed -i 's/update_cmd\ =\ default/update_cmd\ =\ security/' /etc/yum/yum-cron.conf
sudo sed -i 's/selinux=/selinux=1\ security=selinux\ enforcing=1/' /boot/grub/menu.lst
+
</pre>
sudo echo -e "ServerTokens Prod\nServerSignature Off" >> /etc/httpd/conf/httpd.conf
+
 
 +
====Hide Apache\PHP====
 +
<pre>
 
sudo rm -f /etc/httpd/conf.d/welcome.conf
 
sudo rm -f /etc/httpd/conf.d/welcome.conf
sudo sed -i 's/expose_php\ =\ On/expose_php\ =\ off/' /etc/php.ini
+
sudo sed -i 's/expose_php\ =\ On/expose_php\ =\ off/; s/upload_max_filesize\ =\ 2M/upload_max_filesize\ =\ 128M/; s/post_max_size\ =\ 8M/post_max_size\ =\ 64M/; s/max_execution_time\ =\ 30/max_execuion_time\ =\ 60/' /etc/php.ini
 +
</pre>
 +
*Append /etc/httpd/conf/httpd.conf with
 +
<pre>
 +
ServerTokens Prod
 +
ServerSignature Off
 +
LoadModule deflate_module modules/mod_deflate.so
 
</pre>
 
</pre>
*<ref>https://premium.wpmudev.org/blog/increase-memory-limit/</ref>Loosen PHP for the admins. Need to confirm if post and memory sizes really need to be that high (I doubt it)
+
====Startup Services====
upload_max_filesize = 256M<br>
+
*Make sure services are set to start at boot, then reboot.
post_max_size = 128M<br>
 
memory_limit = 256M<br>
 
 
<pre>
 
<pre>
 
sudo chkconfig fail2ban on
 
sudo chkconfig fail2ban on
 
sudo chkconfig mysqld on
 
sudo chkconfig mysqld on
 
sudo chkconfig httpd on
 
sudo chkconfig httpd on
sudo touch /.autorelabel
+
sudo chkconfig yum-cron on
 
sudo reboot
 
sudo reboot
 
</pre>
 
</pre>
*After logging back in make sure services are started.
+
====Configure Database====
 +
*After reboot prep the database. Start with the standard secure installation. Password does not need to be super secure as this is not a shared database, or remotely accessible.  
 
<pre>
 
<pre>
sudo service httpd status
+
sudo mysql_secure_installation
sudo service mysqld status
+
[ec2-user@ip-172-26-8-112 ~]$ sudo mysql_secure_installation
sudo service fail2ban status
+
 
 +
Set root password? [Y/n] Y
 +
New password:
 +
Re-enter new 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
 
</pre>
 
</pre>
*Prepare MySQL for Word Press by creating a database.
+
*Create the databse
 
<pre>
 
<pre>
sudo mysql_secure_installation
 
 
mysql -uroot -p
 
mysql -uroot -p
 +
create database wordpress;
 +
grant all privileges on wordpress.* to 'wordpress'@'localhost' identified by 'password';
 +
exit
 
</pre>
 
</pre>
*Grab Word Press and install in the appropriate location
+
Append  the following to /etc/my.cnf in the mysqld section.
<pre>
+
<pre>max_allowed_packet=32M</pre>
wget https://wordpress.org/latest.tar.gz
+
 
mkdir build
+
====vhost Config====
cd build
+
We do not want to use htaccess as this would allow bad modifications to be made if compromised. Instead we stick to vhost config files (It also performs better).
tar -xf ../latest.tar.gz
+
*Prep for using SSL. The following will provide a self signed cert that can be used for initial configuration of the site. When the URL is known, you will want to replace with a trusted cert. LetsEncrypt is a good resource for this.
sudo mv wordpress /var/www/html/wordpress
+
*In the following example we have the Google Analytics modules commented out. Make sure to have your Analytics ID ready before enabling.<ref>https://www.modpagespeed.com/doc/filter-insert-ga</ref>
</pre>
 
*There are many ways to make this work, I prefer vhosts and sub directories. This will get us up and running with a self signed cert for initial configuration. Afterwards the cert should be updated.
 
 
<pre>
 
<pre>
 
sudo mv /etc/httpd/conf.d/ssl.conf ./
 
sudo mv /etc/httpd/conf.d/ssl.conf ./
echo -e "LoadModule ssl_module modules/mod_ssl.so\nListen 443\nSSLPassPhraseDialog  builtin\nSSLSessionCache        shmcb:/var/cache/mod_ssl/scache(512000)\nSSLSessionCacheTimeout  300\nSSLMutex default\nSSLRandomSeed startup file:/dev/urandom  256\nSSLRandomSeed connect builtin\nSSLCryptoDevice builtin\n\n<VirtualHost *:80>\nRewriteEngine On\nRewriteCond %{HTTPS} off\nRewriteRule (.*) https://%{HTTP_HOST}:443%{REQUEST_URI}\n</VirtualHost>\n\n<VirtualHost _default_:443>\nDocumentRoot /var/www/html/wordpress\nErrorLog logs/ssl_error_log\nTransferLog logs/ssl_access_log\nLogLevel warn\nSSLEngine on\nSSLCertificateFile /etc/pki/tls/certs/localhost.crt\nSSLCertificateKeyFile /etc/pki/tls/private/localhost.key\n</VirtualHost>" > /etc/httpd/conf.d/vhost.conf
+
sudo nano /etc/httpd/conf.d/vhost.conf
</pre>
+
 
Since echo can not write to the destination file, here is the entry formatted for copy and past into a conf file
 
<pre>
 
 
LoadModule ssl_module modules/mod_ssl.so
 
LoadModule ssl_module modules/mod_ssl.so
 
Listen 443
 
Listen 443
Line 59: Line 90:
 
SSLSessionCache        shmcb:/var/cache/mod_ssl/scache(512000)
 
SSLSessionCache        shmcb:/var/cache/mod_ssl/scache(512000)
 
SSLSessionCacheTimeout  300
 
SSLSessionCacheTimeout  300
SSLMutex default
 
 
SSLRandomSeed startup file:/dev/urandom  256
 
SSLRandomSeed startup file:/dev/urandom  256
 
SSLRandomSeed connect builtin
 
SSLRandomSeed connect builtin
 
SSLCryptoDevice builtin
 
SSLCryptoDevice builtin
  
 +
SSLStaplingCache shmcb:/var/cache/httpd/stapling_cache(128000)
 
<VirtualHost *:80>
 
<VirtualHost *:80>
 
RewriteEngine On
 
RewriteEngine On
 
RewriteCond %{HTTPS} off
 
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}:443%{REQUEST_URI}
+
RewriteRule (.*) https://host.tld:443%{REQUEST_URI}
 
</VirtualHost>
 
</VirtualHost>
 +
 +
#ModPagespeedEnableFilters insert_ga
 +
#ModPagespeedAnalyticsID <Analytics ID>
  
 
<VirtualHost _default_:443>
 
<VirtualHost _default_:443>
 +
<If "%{HTTP_HOST} != 'host.tld'">
 +
Redirect "/" "https://host.tld"
 +
</If>
 +
<Files wp-config.php>
 +
Order allow,deny
 +
Deny from all
 +
</Files>
 
DocumentRoot /var/www/html/wordpress
 
DocumentRoot /var/www/html/wordpress
 
ErrorLog logs/ssl_error_log
 
ErrorLog logs/ssl_error_log
Line 76: Line 117:
 
LogLevel warn
 
LogLevel warn
 
SSLEngine on
 
SSLEngine on
 +
SSLProtocol +TLSv1.2
 +
SSLHonorCipherOrder on
 +
SSLCipherSuite EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:HIGH:!MEDIUM:!aNULL:!MD5:!SEED:!IDEA
 
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
 
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
 
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
 
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
 +
SSLUseStapling on
 +
Header always set Strict-Transport-Security "max-age=15638400;"
 +
 +
AddOutputFilterByType DEFLATE text/plain
 +
AddOutputFilterByType DEFLATE text/html
 +
AddOutputFilterByType DEFLATE text/xml
 +
AddOutputFilterByType DEFLATE text/css
 +
AddOutputFilterByType DEFLATE text/javascript
 +
AddOutputFilterByType DEFLATE application/xml
 +
AddOutputFilterByType DEFLATE application/xhtml+xml
 +
AddOutputFilterByType DEFLATE application/rss+xml
 +
AddOutputFilterByType DEFLATE application/javascript
 +
AddOutputFilterByType DEFLATE application/x-javascript
 +
 +
<Directory "/var/www/html/wordpress">
 +
RewriteEngine On
 +
RewriteBase /
 +
 +
RewriteRule ^index\.php$ - [L]
 +
RewriteCond %{REQUEST_FILENAME} !-f
 +
RewriteCond %{REQUEST_FILENAME} !-d
 +
RewriteRule . /index.php [L]
 +
</Directory>
 +
 +
<filesmatch ".svg$">
 +
SetOutputFilter DEFLATE
 +
</filesmatch>
 +
 +
ExpiresActive On
 +
<filesMatch ".(svg|css|jpg|jpeg|png|gif|js|ico)$">
 +
ExpiresDefault A604800
 +
Header unset Cache-Control
 +
Header unset Vary
 +
</filesMatch>
 +
 
</VirtualHost>
 
</VirtualHost>
 
</pre>
 
</pre>
*Restart Apache
+
*Update settings with correct url.
 +
sudo sed -i 's/host\.tld/<yourdomainhere>/g' /etc/httpd/conf.d/vhost.conf
 +
*Restart Apache and start the WordPress Installation
 
  sudo apachectl graceful
 
  sudo apachectl graceful
*Allow the web server to write to the uploads directory for automatic updates. This first chown command shouldn't be needed, I will be doing further testing to ensure it can be removed.
+
 
 +
====IPTABLES====
 +
*Change default input to drop, allow new and established ssh and web connections.
 
<pre>
 
<pre>
sudo chown -R apache:apache /var/www/html/wordpress/*
+
sudo /sbin/iptables -A INPUT -p tcp --dport 80 -m state --state  NEW -j ACCEPT
sudo chcon -R -t httpd_sys_rw_content_t /var/www/html/wordpress/wp-content/uploads/*
+
sudo /sbin/iptables -A INPUT -p tcp --dport 443 -m state --state  NEW -j ACCEPT
sudo setsebool -P httpd_read_user_content on
+
sudo /sbin/iptables -A INPUT -p tcp --dport 22 -m state --state  NEW -j ACCEPT
sudo setsebool -P httpd_can_network_connect_db on
+
sudo /sbin/iptables -A INPUT -m state --state  ESTABLISHED -j ACCEPT
 +
sudo /sbin/iptables -P INPUT DROP
 +
sudo /sbin/iptables save
 
</pre>
 
</pre>
*Make sure that you use 172.0.0.1 for the database server, instead of localhost (it gets complicated otherwise)
+
 
*Add various contextual permissions (need to research this. Optionally you could enable httpd_unified, but this is not the best idea)
+
===WordPress Server Config===
 +
*<b>NOTE</b>: Lightsail/EC2 instances do not have static IPs by default. When creating the wordpress site it likes to create database entries based on the current url. You will want to make sure to provide a static IP to the instance before continuing.
 +
*Grab latest WordPress files and place in web directory
 
<pre>
 
<pre>
allow httpd_t etc_mail_t:dir { search getattr };
+
wget https://wordpress.org/latest.tar.gz
allow httpd_t http_port_t:tcp_socket name_connect;
+
mkdir build
allow httpd_t httpd_sys_content_t:dir write;
+
cd build
allow httpd_t initrc_t:unix_stream_socket connectto;
+
tar -xf ../latest.tar.gz
allow httpd_t user_home_t:file read;
+
sudo mv wordpress /var/www/html/wordpress
</pre>
+
 
*Fail2ban policy
 
<pre>
 
sudo setsebool -P authlogin_nsswitch_use_ldap on
 
sudo semodule -i fail2ban.pp
 
 
</pre>
 
</pre>
*Make sure Amazon has the access it needs
+
*Fix permissions
 
<pre>
 
<pre>
sudo sudo setsebool -P authlogin_nsswitch_use_ldap on
+
sudo find /var/www/html/wordpress/ -type d -exec chmod 755 {} \;
sudo grep shutdown /var/log/audit/audit.log | audit2allow -M shutdown
+
sudo find /var/www/html/wordpress/ -type f -exec chmod 644 {} \;
sudo semodule -i shutdown.pp
+
sudo find /var/www/html/wordpress/ -maxdepth 1 -type f -exec chmod 444 {} \;
 +
sudo chown -R apache:apache /var/www/html/wordpress
 
</pre>
 
</pre>
*Reboot again just for the fun of it.
 
*Install Wordfence Security plugin. Modify settings to fit your needs.
 
==SELinux Notes==
 
*From before making any changes.
 
<pre>
 
#============= httpd_t ==============
 
#!!!! This avc can be allowed using one of the these booleans:
 
#    httpd_can_network_relay, httpd_graceful_shutdown, allow_ypbind, httpd_can_network_connect
 
 
allow httpd_t http_port_t:tcp_socket name_connect;
 
#!!!! This avc can be allowed using one of the these booleans:
 
#    httpd_read_user_content, httpd_enable_homedirs
 
  
allow httpd_t user_home_t:dir getattr;
+
===WordPress Site Setup===
 
+
*In your browser, open your site using the IP provided by Amazon. "https://xxx.xxx.xxx.xxx"
</pre>
+
*Enter the database information from before and hit connect. If it fails, make sure you did not have any typos. You can always go back to the server and look at the MySQL history for what you entered.
*sudo semanage fcontext -a -t httpd_sys_rw_content_t "/path(/.*)?"
+
*Apache does not have write access based on the permissions we set earlier, so you will need to create the /var/www/html/wordpress/wp-config.php file with the contents displayed in the browser.
 +
sudo nano /var/www/html/wordpress/wp-config.php
 +
Paste into file, then save/exit
 +
sudo chmod 640 /var/www/html/wordpress/wp-config.php
 +
*Enter site Title, admin username (admin), admin password, set email.
 +
*When finished, log in with the credentials you just entered. Make sure to check for updates and that word press can install them.
 +
====Plugins====
 +
*Go to "Plugins" -> "Add New". Search for wordfence and install.
 +
=====Wordfence Config=====
 +
*It is important to have this plugin installed, especially if you have third parties managing things.
 +
#Go to "Firewall", "Manage WAF", and under "Web Application Firewall Status" change to "Enabled and Protecting.
 +
#Go to "Firewall", "Manage Brute Force Protection", and change the following
 +
##Lock out after how many login failures : 5
 +
##Lock out after how many forgot passwords attempts : 5
 +
##Count failures over what time period : 30 minutes
 +
##Amount of time a user is locked out : 30 minutes
 +
##Immediately lock out invalid usernames : Check this box

Latest revision as of 18:01, 15 February 2019

WORK IN PROGRESS: Amazon only allows ssh access without a console, you can easily get yourself locked out.

Purpose

To run a simple wordpress site as "securely" as possible from the server side.

Process

Non SELinux

When this was written, we started using PHP 7 and needed Apache 2.4. Neither of these are standard installs for Amazon Linux.

OS Prep

Create SWAP

  • Create SWAP file (Cloud hosted instances lack these). The following will create a 6GB swap file.[1]
sudo dd if=/dev/zero of=/SWAP bs=1024 count=6291453
sudo chmod 0600 /SWAP
sudo mkswap /SWAP
sudo swapon /SWAP
  • Add the swap file to FSTAB
/SWAP swap swap defaults 0 0

Install packages

Feel free to install updated php, this section will be updated as further testing is done. Also note the time zone if you are on the east coast.

sudo yum -y update
sudo yum -y install fail2ban httpd24 mysql mysql-server php70 php70-mysqlnd mod24_ssl yum-cron php70-mbstring php70-zip php-xml htop
sudo yum -y install https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_x86_64.rpm
sudo ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime
sudo sed -i 's/update_cmd\ =\ default/update_cmd\ =\ security/' /etc/yum/yum-cron.conf

Hide Apache\PHP

sudo rm -f /etc/httpd/conf.d/welcome.conf
sudo sed -i 's/expose_php\ =\ On/expose_php\ =\ off/; s/upload_max_filesize\ =\ 2M/upload_max_filesize\ =\ 128M/; s/post_max_size\ =\ 8M/post_max_size\ =\ 64M/; s/max_execution_time\ =\ 30/max_execuion_time\ =\ 60/' /etc/php.ini
  • Append /etc/httpd/conf/httpd.conf with
ServerTokens Prod
ServerSignature Off
LoadModule deflate_module modules/mod_deflate.so

Startup Services

  • Make sure services are set to start at boot, then reboot.
sudo chkconfig fail2ban on
sudo chkconfig mysqld on
sudo chkconfig httpd on
sudo chkconfig yum-cron on
sudo reboot

Configure Database

  • After reboot prep the database. Start with the standard secure installation. Password does not need to be super secure as this is not a shared database, or remotely accessible.
sudo mysql_secure_installation
[ec2-user@ip-172-26-8-112 ~]$ sudo mysql_secure_installation

Set root password? [Y/n] Y 
New password: 
Re-enter new 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
  • Create the databse
mysql -uroot -p
create database wordpress;
grant all privileges on wordpress.* to 'wordpress'@'localhost' identified by 'password';
exit

Append the following to /etc/my.cnf in the mysqld section.

max_allowed_packet=32M

vhost Config

We do not want to use htaccess as this would allow bad modifications to be made if compromised. Instead we stick to vhost config files (It also performs better).

  • Prep for using SSL. The following will provide a self signed cert that can be used for initial configuration of the site. When the URL is known, you will want to replace with a trusted cert. LetsEncrypt is a good resource for this.
  • In the following example we have the Google Analytics modules commented out. Make sure to have your Analytics ID ready before enabling.[2]
sudo mv /etc/httpd/conf.d/ssl.conf ./
sudo nano /etc/httpd/conf.d/vhost.conf

LoadModule ssl_module modules/mod_ssl.so
Listen 443
SSLPassPhraseDialog  builtin
SSLSessionCache         shmcb:/var/cache/mod_ssl/scache(512000)
SSLSessionCacheTimeout  300
SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin

SSLStaplingCache shmcb:/var/cache/httpd/stapling_cache(128000)
<VirtualHost *:80>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://host.tld:443%{REQUEST_URI}
</VirtualHost>

#ModPagespeedEnableFilters insert_ga
#ModPagespeedAnalyticsID <Analytics ID>

<VirtualHost _default_:443>
<If "%{HTTP_HOST} != 'host.tld'">
Redirect "/" "https://host.tld"
</If>
<Files wp-config.php>
Order allow,deny
Deny from all
</Files>
DocumentRoot /var/www/html/wordpress
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn
SSLEngine on
SSLProtocol +TLSv1.2
SSLHonorCipherOrder on
SSLCipherSuite EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:HIGH:!MEDIUM:!aNULL:!MD5:!SEED:!IDEA
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
SSLUseStapling on
Header always set Strict-Transport-Security "max-age=15638400;"

AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript

<Directory "/var/www/html/wordpress">
RewriteEngine On
RewriteBase /

RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</Directory>

<filesmatch ".svg$">
SetOutputFilter DEFLATE
</filesmatch>

ExpiresActive On
<filesMatch ".(svg|css|jpg|jpeg|png|gif|js|ico)$">
ExpiresDefault A604800
Header unset Cache-Control
Header unset Vary
</filesMatch>

</VirtualHost>
  • Update settings with correct url.
sudo sed -i 's/host\.tld/<yourdomainhere>/g' /etc/httpd/conf.d/vhost.conf
  • Restart Apache and start the WordPress Installation
sudo apachectl graceful

IPTABLES

  • Change default input to drop, allow new and established ssh and web connections.
sudo /sbin/iptables -A INPUT -p tcp --dport 80 -m state --state  NEW -j ACCEPT
sudo /sbin/iptables -A INPUT -p tcp --dport 443 -m state --state  NEW -j ACCEPT
sudo /sbin/iptables -A INPUT -p tcp --dport 22 -m state --state  NEW -j ACCEPT
sudo /sbin/iptables -A INPUT -m state --state  ESTABLISHED -j ACCEPT
sudo /sbin/iptables -P INPUT DROP
sudo /sbin/iptables save

WordPress Server Config

  • NOTE: Lightsail/EC2 instances do not have static IPs by default. When creating the wordpress site it likes to create database entries based on the current url. You will want to make sure to provide a static IP to the instance before continuing.
  • Grab latest WordPress files and place in web directory
wget https://wordpress.org/latest.tar.gz
mkdir build
cd build
tar -xf ../latest.tar.gz
sudo mv wordpress /var/www/html/wordpress

  • Fix permissions
sudo find /var/www/html/wordpress/ -type d -exec chmod 755 {} \;
sudo find /var/www/html/wordpress/ -type f -exec chmod 644 {} \;
sudo find /var/www/html/wordpress/ -maxdepth 1 -type f -exec chmod 444 {} \;
sudo chown -R apache:apache /var/www/html/wordpress

WordPress Site Setup

  • In your browser, open your site using the IP provided by Amazon. "https://xxx.xxx.xxx.xxx"
  • Enter the database information from before and hit connect. If it fails, make sure you did not have any typos. You can always go back to the server and look at the MySQL history for what you entered.
  • Apache does not have write access based on the permissions we set earlier, so you will need to create the /var/www/html/wordpress/wp-config.php file with the contents displayed in the browser.
sudo nano /var/www/html/wordpress/wp-config.php
Paste into file, then save/exit
sudo chmod 640 /var/www/html/wordpress/wp-config.php
  • Enter site Title, admin username (admin), admin password, set email.
  • When finished, log in with the credentials you just entered. Make sure to check for updates and that word press can install them.

Plugins

  • Go to "Plugins" -> "Add New". Search for wordfence and install.
Wordfence Config
  • It is important to have this plugin installed, especially if you have third parties managing things.
  1. Go to "Firewall", "Manage WAF", and under "Web Application Firewall Status" change to "Enabled and Protecting.
  2. Go to "Firewall", "Manage Brute Force Protection", and change the following
    1. Lock out after how many login failures : 5
    2. Lock out after how many forgot passwords attempts : 5
    3. Count failures over what time period : 30 minutes
    4. Amount of time a user is locked out : 30 minutes
    5. Immediately lock out invalid usernames : Check this box
    6. https://www.centos.org/docs/5/html/5.2/Deployment_Guide/s2-swap-creating-file.html
    7. https://www.modpagespeed.com/doc/filter-insert-ga