Speeding Up WordPress on Synology

Out of the box, WordPress running on a Synology is very slow (search Synology.com forums or Google if you don’t believe me). This article explains how to optimize your Synology and your WordPress website for speed.

Disclaimer

The below are tweaks I’ve implemented with success. I don’t know the complete extent of their validity; they just seems to bring extremely noticeable positive performance gains to my Synology. Besides these changes not working as expected on your Synology, they are risky. Before making any changes, backup your data and your Synology configuration off the Synology incase the worst happens. By implementing any of the suggestions below, you are proceeding at your own risk without any expectation of responsibility and or support from me. I only take credit if the changes bring you positive results

I also expect you to have moderate technical skills – able to modify your Synology through the DSM console, install and configure plugins, use telnet, run executables and edit/save text files in linux, etc.

Synology Tuning

Synology produces some pretty powerful network storage devices. These are basically tiny computers optimized to store/serve data and able to run programs to stream music, videos, photos, websites, and more. By default, WordPress will run relatively slow on a Synology since it is configured to minimize disk, CPU, and memory utilization. By simply making a few changes, you can make WordPress on your Synology run faster than average website without compromising its ability to run other functions.

Enable PHP Caching

By default, the Synology is configured to enable PHP caching. Ensure “Enable PHP cache” is still checked under Control Panel | Web Services | PHP Settings.

Synology-DSM-5-PHP-Caching

 

Tuning Configurations

Tuning the following configurations will give you the largest performance gain of any of the other recommendations listed in this article. It is also the most dangerous as you can easily cause an over consumption of resources slowing down parts of all of your Synology or worse yet can break WordPress or your entire Synology. Before proceeding, ensure you have everything backed up OFF your Synology in case you need to perform a full Synology restore. Now that we have that gloom and doom over with, on with the tuning… To perform any of the changes below, you will first need to enable Telnet by checking “Enable Telnet service” under Control Panel | Terminal & SNMP | Terminal.

Synology-DSM-5-Enable-Telnet

Note: Enabling telnet allows remote command line access to your Synology. You should only enable it when needed and if your network is adequately secured.

OPCache

OPCode is caching mechanism preinstalled on Synology to cache running PHP code into memory and to recall the code from memory instead of from disk. To configure the OPCode engine to consume more resources and thus speed up WordPress:

  1. Telnet to your Synology with the root account
  2. Edit and save /etc/php/conf.d/opcache.ini with your desired changes
  3. Restart Apache by running /usr/syno/etc/rc.d/S97apache-sys.sh restart

Below are some of the change I have implemented with positive results:

PHP Configuration

PHP is the language WordPress is written in. Synology has the PHP engine preinstalled and preconfigured to consume minimal resources such as memory and CPU. To configure the PHP engine to consume more resources and thus speed up WordPress:

  1. Telnet to your Synology with the root account
  2. Edit and save /etc/php/php.ini with your desired changes
  3. Restart Apache by running /usr/syno/etc/rc.d/S97apache-sys.sh restart

Below are some of the change I have implemented with positive results:

memory_limit = 512M
max_execution_time = 2000

Apache is the web server preinstalled on the Synology for all web applications (like WordPress). The Apache configuration is preconfigured to consume minimal resources such as memory and CPU. To configure Apache to consume more resources and thus speed up WordPress:

  1. Telnet to your Synology with the root account
  2. Edit and save /etc/httpd/conf/extra/httpd-mpm.conf-user with your desired changes
  3. Restart Apache by running /usr/syno/etc/rc.d/S97apache-sys.sh restart

Below are some of the change I have implemented with positive results:

MariaDB is the database server you can install to run with Wordpress. The MariaDB configuration is preconfigured to consume minimal resources such as memory and CPU. To configure MariaDB to consume more resources and thus speed up WordPress:

  1. Telnet to your Synology with the root account
  2. Edit and save /volume1/@appstore/MariaDB/etc/mysql/my.cnf with your desired changes (note: you may have to change “volume1″ to the location where you installed MariaDB).
  3. Restart MariaDB by running /usr/share/mysql/mysql.server restart

Below are some of the change I have implemented with positive results:

WordPress Tuning

WordPress by default is also not optimized for speed but thankfully there are some great plugins and changes your can make to make your site scream.

Enable Site Caching

Download, activate, and configure the W3 Total Cache plugin.

W3-Total-Cache

Basically this plugin caches all the dynamic content on your website while also shrinking down code where possible. The performance gained because of this plugin is like night and day. If you are skittish about implementing any of the suggestions within this article, this is the one NOT to skip.

There are tons of settings and tons of articles already on the web on how to optimally configure this plugin. Here are some quick tips:

  • Enable page, minify, database, object, and browser cache
  • Select “OpCode: Alternative PHP Cache (APC)” as your cache method (if not “Disk: Enhanced”, “Disk: Basic” or just “Disk”)
  • Uncheck all items within the “Debug” section
  • Enable “Late Initialization” on the “Page Cache” options page
  • Update “Pages Per Interval” to 15 on the “Page Cache” options page

Shrink Your Images

Download, activate, and use the WP Smush.it plugin.

Smush-It

Basically this plugin performs operations to shrink the size of your website’s images without a loss in quality.

To “smush” images, simply go to your WordPress “Media” section on the admin dashboard and click “Smish.it Now!” or “Remush” next to the desired image.

Or to “smush” a bunch of images at once, go to your WordPress “Media | Bulk Smush.it” section on the admin dashboard.

Deactivate unneeded plugins

Plugins may add additional code that run every time a page or image is loaded. That additional code will cause the page to display slower. Deactivate all plugins that are not needed.

Choose a fast theme

Not all themes are created equal. Experiment by activating several themes and noting the time each takes to load. Select the theme that fills your need while also loading the fastest.

Optimize the Database

Download, activate, and use the WP-Optimize plugin.

Basically this plugin performs a bunch of database optimizes and cleanup routines to speed up your database calls. Faster database calls means faster web page loading.

To optimize your database, click “WP-Optimize” in the admin dashboard, check everything, and click “Process”.

Conclusion

While the changes above bring huge performance gains, I still have 2 things that quirk me from being completely satisfied. First, I don’t really know which parts of the configuration changes are truly essential, which are not required, and if they are fine tuned to bring optimal performance. Second, I don’t see my Synology utilizing noticeable memory despite calling for more memory consumptions in the configuration files. This causes me to question the value they bring.

But with that aside, I know WordPress on my Synology now runs substantially faster having implemented the changes above. And in fact, any web application on your Synology should run faster as well (ex. the DSM console). Let me know if they work well for you too by liking or sharing this page on Facebook. Feel free as well to send me any performance enhancing tips to make WordPress on Synology run even faster.

Create a Public Key Infrastructure Using the easy-rsa Scripts

The first step when setting up OpenVPN is to create a Public Key Infrastructure (PKI). The PKI consists of:

  • A public master Certificate Authority (CA) certificate and a private key.
  • A separate public certificate and private key pair (hereafter referred to as a certificate) for each server and each client.

To facilitate the certificate creation process, OpenVPN comes with a collection of RSA key manangement scripts (based on the openssl command line tool) known as easy-rsa.

Note: Only .key files need to be kept secret, .crt and .csr files can be sent over insecure channels such as plaintext email.

In this article the needed certificates are created by root in root’s home directory. This ensures that the generated files have the right ownership and permissions, and are safe from other users.

Note: The certificates can be created on any machine. For the highest security, generate the certificates on a physically secure machine disconnected from any network, and make sure that the generated ca.key private key is backed up and never accessible to anyone.
Warning: Make sure that the generated files are backed up, especially the ca.key and ca.crt files, since if lost you will not be able to create any new, nor revoke any compromised certificates, thus requiring the generation of a new Certificate Authority (CA) certificate, invalidating the entire PKI infrastructure.

Installing the easy-rsa scripts

Install the scripts by doing the following:

# pacman -S easy-rsa
# cp -r /usr/share/easy-rsa /root

Creating certificates

Change to the directory where you installed the scripts.

# cd /root/easy-rsa

To ensure the consistent use of values when generating the PKI, set default values to be used by the PKI generating scripts. Edit /root/easy-rsa/vars and at a minimum set the KEY_COUNTRY, KEY_PROVINCE, KEY_CITY, KEY_ORG, and KEY_EMAIL parameters (do not leave any of these parameters blank). Change the KEY_SIZE parameter to 2048 for the SSL/TLS to use 2048bit RSA keys for authentication.

/root/easy-rsa/vars
# easy-rsa parameter settings

# NOTE: If you installed from an RPM,
# do not edit this file in place in
# /usr/share/openvpn/easy-rsa --
# instead, you should copy the whole
# easy-rsa directory to another location
# (such as /etc/openvpn) so that your
# edits will not be wiped out by a future
# OpenVPN package upgrade.

# This variable should point to
# the top level of the easy-rsa
# tree.
export EASY_RSA="`pwd`"

#
# This variable should point to
# the requested executables
#
export OPENSSL="openssl"
export PKCS11TOOL="pkcs11-tool"
export GREP="grep"

# This variable should point to
# the openssl.cnf file included
# with easy-rsa.
export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA`

# Edit this variable to point to
# your soon-to-be-created key
# directory.
#
# WARNING: clean-all will do
# a rm -rf on this directory
# so make sure you define
# it correctly!
export KEY_DIR="$EASY_RSA/keys"

# Issue rm -rf warning
echo NOTE: If you run ./clean-all, I will be doing a rm -rf on $KEY_DIR

# PKCS11 fixes
export PKCS11_MODULE_PATH="dummy"
export PKCS11_PIN="dummy"

# Increase this to 2048 if you
# are paranoid.  This will slow
# down TLS negotiation performance
# as well as the one-time DH parms
# generation process.
export KEY_SIZE=2048

# In how many days should the root CA key expire?
export CA_EXPIRE=3650

# In how many days should certificates expire?
export KEY_EXPIRE=3650

# These are the default values for fields
# which will be placed in the certificate.
# Do not leave any of these fields blank.


export KEY_COUNTRY="US"
export KEY_PROVINCE="CA"
export KEY_CITY="Acme Acres"
export KEY_ORG="Acme"
export KEY_EMAIL="roadrunner@acmecorp.org"
#export KEY_EMAIL=mail@host.domain
export KEY_CN=Acme-CA
export KEY_NAME=Acme-CA
export KEY_OU=""
export PKCS11_MODULE_PATH=changeme
export PKCS11_PIN=1234

Export the environment variables.

# source ./vars

Delete any previously created certificates.

# ./clean-all
Note: Entering a . (dot) when prompted for a value, blanks out the parameter.

The build-ca script generates the Certificate Authority (CA) certificate.

# ./build-ca
Generating a 2048 bit RSA private key
..............++++++
...++++++
writing new private key to 'ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [CA]:
Locality Name (eg, city) [Acme Acres]:
Organization Name (eg, company) [Acme]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [Acme-CA]:
Name [Acme-CA]:
Email Address [roadrunner@acmecorp.org]:

The build-key-server script # ./build-key-server <server name> generates a server certificate. Make sure that the server name (Common Name when running the script) is unique.

Note: Do not enter a challenge password or company name when the script prompts you for one.
# ./build-key-server elmer
Generating a 2048 bit RSA private key
.....................++++++
.......................................................++++++
writing new private key to 'elmer.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [CA]:
Locality Name (eg, city) [Acme Acres]:
Organization Name (eg, company) [Acme]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [elmer]:
Name [Acme-CA]:
Email Address [roadrunner@acmecorp.org]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /root/easy-rsa/openssl-1.0.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'CA'
localityName          :PRINTABLE:'Acme Acres'
organizationName      :PRINTABLE:'Acme'
commonName            :PRINTABLE:'elmer'
name                  :PRINTABLE:'Acme-CA'
emailAddress          :IA5STRING:'roadrunner@acmecorp.org'
Certificate is to be certified until Dec 27 19:11:59 2021 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

The build-dh script generates the Diffie-Hellman parameters .pem file needed by the server.

Note: It would be better to generate a new one for each server, but you can use the same one if you want to.
# ./build-dh
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
..+.............................................................................
.
.
.
............+...............+...................................................
..................................................................++*++*

The build-key script # ./build-key <client name> generates a client certificate. Make sure that the client name (Common Name when running the script) is unique.

Note: Do not enter a challenge password or company name when the script prompts you for one.
# ./build-key bugs
Generating a 2048 bit RSA private key
....++++++
.............................................................++++++
writing new private key to 'bugs.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
State or Province Name (full name) [CA]:
Locality Name (eg, city) [Acme Acres]:
Organization Name (eg, company) [Acme]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [bugs]:
Name [Acme-CA]:
Email Address [roadrunner@acmecorp.org]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /root/easy-rsa/openssl-1.0.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'CA'
localityName          :PRINTABLE:'Acme Acres'
organizationName      :PRINTABLE:'Acme'
commonName            :PRINTABLE:'bugs'
name                  :PRINTABLE:'Acme-CA'
emailAddress          :IA5STRING:'roadrunner@acmecorp.org'
Certificate is to be certified until Dec 27 19:18:27 2021 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

Generate a secret Hash-based Message Authentication Code (HMAC) by running: # openvpn --genkey --secret /root/easy-rsa/keys/ta.key

This will be used to add an additional HMAC signature to all SSL/TLS handshake packets. In addition any UDP packet not having the correct HMAC signature will be immediately dropped, protecting against:

  • Portscanning.
  • DOS attacks on the OpenVPN UDP port.
  • SSL/TLS handshake initiations from unauthorized machines.
  • Any eventual buffer overflow vulnerabilities in the SSL/TLS implementation.

All the created keys and certificates have been stored in /root/easy-rsa/keys. If you make a mistake, you can start over by running the clean-all script again.

Warning: This will delete any previously generated certificates stored in /root/easy-rsa/keys, including the Certificate Authority (CA) certificate.

Converting certificates to encrypted .p12 format

Some software (such as Android) will only read VPN certificates that are stored in a password-encrypted .p12 file. These can be generated with the following command:

# openssl pkcs12 -export -inkey keys/bugs.key -in keys/bugs.crt -certfile keys/ca.crt -out keys/bugs.p12

Checking Using OpenSSL

If you need to check the information within a Certificate, CSR or Private Key, use these commands. You can also check CSRs and check certificates using our online tools.

  • Check a Certificate Signing Request (CSR)
    openssl req -text -noout -verify -in CSR.csr
  • Check a private key
    openssl rsa -in privateKey.key -check
  • Check a certificate
    openssl x509 -in certificate.crt -text -noout
  • Check a PKCS#12 file (.pfx or .p12)
    openssl pkcs12 -info -in keyStore.p12

Contact the parcel service

The DHL customer service for standard packages is under 0228/28609898 accessible (Every day 7:00 – 22:00 Clock). The DHL Customer Service for National Express packages can be reached at 0180 6 345 300-1 (20 ct per call from a German landline, max. 60 ct from a German mobile network). DHL also provides direct customer service on the DHL packet Facebook page and the DHL-Twitter-Account.

Deutsche Post Hotline: 0180 2 3333 (0,06 Euro per call from landline deutschm; mobile max. 0,42 EUR/Min.)

DPD-Hotline: 01806 373 200 (0,20 Euro per call from a German landline, max. 0,60 Euro per call from a German mobile network). accessible Mo. Fr. from 8 to 18 Clock. Find the DPD customer service on Twitter

GLS parcel service hotline at the normal rate: 06677-646907000

UPS-Hotline: 01806 882 663 (20 Cent / Call from the German. landline; mobile max. 60 Cent / Call) the English UPS Support can be reached also on Twitter.

Hermes Package-Hotline: 01806-311211 (landline 20 Cent / call, mobile max. 60 Cent / call).
Hotline of Hermes Einrichtungs Service (Sperrgutlieferungen z.B. furniture): 05732 103-0 The Hermes-Service available here also on Twitter.

TNT-Hotline: 01805 900 900 (0,14 EUR /Min. from the landline, mobile max. 0,42 EUR/Min.)