This Old Blog

WordPress Renovation – WordPress Server Setup

The renovation of my WordPress blog, http://byronpate.com continues this week with the setup of my new cloud server. In my last article, I benchmarked several cloud servers and ended up selecting Vultr as the server I want to use for hosting WordPress. The following steps are what I will use to perform the core WordPress Server Setup. This includes the Nginx, PHP, and Percona installs.

I have a 1 CPU Core, 768MB of memory, 15GB SSD drive server from Vultr. The server is running Ubuntu 16.04 (Xenial). I’m ready to start installing components and getting this ready to run WordPress.

Setup Anturis Server Monitoring

WordPress Server Setup Anturis MonitoringAnturis provides a cloud monitoring solution. I use Anturis to monitor my server CPU, Memory, and Disk for alerts. From the Anturis web console, you can view a dashboard of historic utilization and alerts. Anturis will also send email alerts if any thresholds are passed on my server. There are a number of server monitoring solutions available, but Anturis offers monitoring of 5 servers for free.

Installing the Anturis Agent on the server is pretty simple. Inside the Anturis account you select adding a new server and you’ll be given the command line to execute on the server that will download the agent, install it, and link to your account.

Once installed you’ll see your server metrics showing up within a few minutes.

Install ODrive Agent

WordPress Server Setup ODriveI use a number of Cloud Storage providers. Dropbox for Themes and Plugin installs. Google Drive for Backups. Yandisk for storing Management scripts. Instead of having to connect to each cloud provider individually I use ODrive. ODrive aggregates multiple cloud providers into one interface. I set up an ODrive account that’s connected to three different cloud storage accounts. In my ODrive account, I created an authentication key and then I’m ready to install the ODrive Agent on my server. From the server command line, I ran the following commands to install and then authenticate to my ODrive account.

od="$HOME/.odrive-agent/bin" && curl -L "http://dl.odrive.com/odrive-py" --create-dirs -o "$od/odrive.py" && curl -L "http://dl.odrive.com/odriveagent-lnx-64" | tar -xvzf- -C "$od/" && curl -L "http://dl.odrive.com/odrivecli-lnx-64" | tar -xvzf- -C "$od/"

nohup "$HOME/.odrive-agent/bin/odriveagent" >/dev/null&

"$HOME/.odrive-agent/bin/odrive" authenticate 00000000-0000-0000-0000-000000000000-00000000

After installing the Agent and Authenticating to my account. I’m going to sync my drives on the server. By default the ODrive Agent does not sync files to the file system, it creates pointers to directories and files. So I’m going to sync down the Management directory that has my scripts in it. The following commands create a top level directory in /opt, mount ODrive into it, Sync one of my top level folders, and then recursively sync all files in that folder.

mkdir /opt/odrive/

"$HOME/.odrive-agent/bin/odrive" mount "/opt/odrive" /

"$HOME/.odrive-agent/bin/odrive" sync "/opt/odrive/manage.cloudf

output="go"; while [ "$output" ]; do output=$(find "/opt/odrive/manage/" -name "*.cloud*" -exec "$HOME/.odrive-agent/bin/odrive" sync "{}" \;); echo $output; done

 Install Nginx

The primary function of this server is to run Nginx, so this is the primary part of my WordPress Server Setup. I’m going to install the latest version of Nginx, which is currently 1.10. Running nginx -v after the install to verify the installation. I’ll come back and tune the configuration more later.

apt-get update
apt-get install Nginx
nginx -v

Install PHP 7

I’m going to install the latest version of PHP, which is currently PHP7.  Upgrading from PHP5 to PHP7 will offer a performance boost. But it does require testing to ensure all of WordPress Plugins and themes I’m using are compatible.

apt-get install php-fpm php-mysql

I’m going to install a number of PHP 7 Modules that are requirements for some of my WordPress plugins. These modules may not be needed by your WordPress site, but these are commonly used modules for PHP Curl, XML handling, and Image Manipulation.

apt install php7.0-mbstring 

apt install php7.0-zip 

apt install php7.0-xml

apt install php-imagick

apt install imagemagick

apt install php7.0-gd

apt install php7.0-curl

After installing PHP I need to edit /etc/php/php7.0-fpm/php.ini and make 2 tweaks. First I’m going to change cgi.fix_pathinfo from 1 to 0, this is a known security hardening. Second I’m going to change theupload_max_filesize to 15MB to handle some of the larger Plugins.

cgi.fix_pathinfo=0
upload_max_filesize = 15M

Install Let’s Encrypt

As part of this WordPress Server Setup I want to enable HTTPS for my website. So now I’m going to install the Let’s Encrypt plugin for generating TLS HTTPS certificates in Nginx. The first thing I need to do is enable requests to the /.well-known directory under your web site root. This goes into your default Nginx server block by editing /etc/nginx/sites-available/default.

location ~ /.well-known {
  allow all;
}

Next run the Let’s Encrypt install and restart Nginx.

apt install letsencrypt

systemctl restart nginx

Now we need to generate a 2048-bit Diffie-Hellman group that we’ll use in our Nginx SSL configuration. To generate the 2048-bit group, I’ll run this command:

openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Inside the Nginx Snippets directory create the following SSL Parameters file. These configurations are based on Raymii’s Nginx SSL Tutorial.

/etc/nginx/snippets/ssl-params.conf

# from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

I can’t create my certificate until the website is active on my server. So I’ll do that after the migration. But at this point the server is ready to go with Let’s Encrypt.

Install Percona

Instead of using standard MySQL in this WordPress server setup, I’m going to be using Percona Server. I’m installing the current version which is Percona Server 5.7. During the install it will prompt you to enter the MySQL Root password. Provide a root password and be sure to save the password.

wget https://repo.percona.com/apt/percona-release_0.1-4.$(lsb_release -sc)_all.deb

dpkg -i percona-release_0.1-4.$(lsb_release -sc)_all.deb

sudo apt-get update

sudo apt-get install percona-server-server-5.7

Tune Linux

I’m going to update the server’s /etc/sysctl.conf to tune it for hosting a Nginx web server. I’ll add the following to the end of the config file, save the config, and run sysctl -p to load the parameters.

### IMPROVE SYSTEM MEMORY MANAGEMENT ###

# Increase size of file handles and inode cache
fs.file-max = 2097152

# Do less swapping
vm.swappiness = 10
vm.dirty_ratio = 60
vm.dirty_background_ratio = 2

### GENERAL NETWORK SECURITY OPTIONS ###

# Number of times SYNACKs for passive TCP connection.
net.ipv4.tcp_synack_retries = 2

# Allowed local port range
net.ipv4.ip_local_port_range = 2000 65535

# Protect Against TCP Time-Wait
net.ipv4.tcp_rfc1337 = 1

# Decrease the time default value for tcp_fin_timeout connection
net.ipv4.tcp_fin_timeout = 15

# Decrease the time default value for connections to keep alive
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15

### TUNING NETWORK PERFORMANCE ###

# Default Socket Receive Buffer
net.core.rmem_default = 31457280

# Maximum Socket Receive Buffer
net.core.rmem_max = 12582912

# Default Socket Send Buffer
net.core.wmem_default = 31457280

# Maximum Socket Send Buffer
net.core.wmem_max = 12582912

# Increase number of incoming connections
net.core.somaxconn = 4096

# Increase number of incoming connections backlog
net.core.netdev_max_backlog = 65536

# Increase the maximum amount of option memory buffers
net.core.optmem_max = 25165824

# Increase the maximum total buffer-space allocatable
# This is measured in units of pages (4096 bytes)
net.ipv4.tcp_mem = 65536 131072 262144
net.ipv4.udp_mem = 65536 131072 262144

# Increase the read-buffer space allocatable
net.ipv4.tcp_rmem = 8192 87380 16777216
net.ipv4.udp_rmem_min = 16384

# Increase the write-buffer-space allocatable
net.ipv4.tcp_wmem = 8192 65536 16777216
net.ipv4.udp_wmem_min = 16384

# Increase the tcp-time-wait buckets pool size to prevent simple DOS attacks
net.ipv4.tcp_max_tw_buckets = 1440000
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1

Credits for this configuration go to the following sites:

  • http://klaver.it/linux/sysctl.conf
  • https://github.com/GoTux/Configs/blob/master/99-sysctl.conf

WordPress Server Setup Next Steps

At this point, I have a solid WordPress server setup to work with. My next steps will be to further tune the server, making the necessary updates to the configurations. After that is completed I can begin migrating my websites from the old server to the Vultr server.

Update - 2016.09.07Be sure to read the other articles in the This Old Blog series:

Byron Pate
I am Byron Pate, and I’m a technology enthusiast. I work in Atlanta, Georgia as a Solution Architect. I write about technology, troubleshooting, and infrastructure.
We will be happy to hear your thoughts

      Leave a reply