Install and Configure Latest Redis Cache for WordPress

redis-cacheRedis-server is a caching system that speeds up WordPress using object cache. Benchmarks show ridiculous speed increases with the PECL Redis extension for PHP. I use Redis caching and Varnish caching for this site and have found it to be the best combination on my 512 MB Digital Ocean droplet for $5 a month.

This guide is for Ubuntu and Debian based systems (Wheezy 7, Jessie 8, Trusty 14.x and Vivid 15.x and later) but should work on CentOS, Fedora and others by making small adjustments to package managers and paths. It provides a secure Redis installation for WordPress in light of recent telnet exploits – no easy root access can be gained from hackers if you follow this configuration tutorial.

Note: If you are on Ubuntu 16.04 please follow my new Redis guide.

Install and Configure Latest Redis Cache for WordPress

Using Redis object cache with WordPress requires two components speed boost your site

  • Redis Server which stores the WordPress object cache
  • Redis PHP extension (phpredis or predis) for php to communicate with the redis-server for storing and retrieving cache

phpredis is the the native c extension so is the fastest and obvious choice, the instructions for compiling from source follow the Redis server installation section.

If you prefer to use predis (redis extension written in php – (read slower)) then you do not need to install phpredis as the WordPress Redis cache plugin will default to predis.

Install Redis Server

This block of code installs the compilation tools, grabs the latest stable redis, builds and installs it. The latest version number can be found here

sudo apt-get install build-essential -y
wget http://download.redis.io/redis-stable.tar.gz
tar xzf redis*
cd redis*
sudo make
sudo make install PREFIX=/usr
sudo mkdir /etc/redis
sudo cp redis.conf /etc/redis/
cd ..
rm -R redis*

Create a non-privileged Redis user for maximum security which has no login, valid shell and limited home directory to its PID

sudo adduser --system --group --disabled-login redis --no-create-home --shell /bin/nologin --quiet

Ensure the redis user is there by checking the shadow file

cat /etc/passwd | grep redis

If it isn't there use the add user command again

Make some changes to the redis configuration

sudo mv /etc/redis/redis.conf /etc/redis/redis.conf.bak
sudo nano /etc/redis/redis.conf

Set daemonize to yes for init.d and systemd services

Change bind to only listen on localhost: 127.0.0.1 to prevent serious security issues

Set maxmemory to 50M so Redis doesn't use more than 50 MB of RAM. Even with 40 plugins I have never seen Redis use more than 20-30 MB for WordPress object caching.

Change the policy to allkeys-lru which forces redis-server to delete old cache (least recently used objects) when the Redis server starts to run out of memory

bind 127.0.0.1
port 6379
daemonize yes
stop-writes-on-bgsave-error no
rdbcompression yes
maxmemory 50M
maxmemory-policy allkeys-lru

Ctrl+X, Y and Enter to save

Create a folder for the pid file

sudo mkdir -p /var/run/redis

Change permissions so the redis user owns it

sudo chown -R redis /var/run/redis

Time to start Redis server on boot, only use the init.d script or the systemd script

If you are in doubt which to choose run this command, if it doesn't say systemd use the init.d script

sudo stat /proc/1/exe

Redis Server Systemd Script

Create the redis-server systemd script

sudo nano /etc/systemd/system/redis-server.service

Paste the Redis server systemd script

[Unit]
Description=Redis Datastore Server
After=network.target

[Service]
Type=forking
Restart=always
User=redis
ExecStart=/sbin/start-stop-daemon --start --pidfile /var/run/redis/redis.pid --umask 007 --exec /usr/bin/redis-server -- /etc/redis/redis.conf
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target

Enable the redis-server systemd script

sudo systemctl enable redis-server

Start the redis-server systemd script

sudo service redis-server start

Redis-server init.d Script

Create the Redis server init.d script which may already exist

sudo nano /etc/init.d/redis-server

Paste the redis server init.d script unless it already exists

#! /bin/sh
### BEGIN INIT INFO
# Provides:		redis-server
# Required-Start:	$syslog $remote_fs
# Required-Stop:	$syslog $remote_fs
# Should-Start:		$local_fs
# Should-Stop:		$local_fs
# Default-Start:	2 3 4 5
# Default-Stop:		0 1 6
# Short-Description:	redis-server - Persistent key-value db
# Description:		redis-server - Persistent key-value db
### END INIT INFO


PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/bin/redis-server
DAEMON_ARGS=/etc/redis/redis.conf
NAME=redis-server
DESC=redis-server

RUNDIR=/var/run/redis
PIDFILE=$RUNDIR/redis-server.pid

test -x $DAEMON || exit 0

if [ -r /etc/default/$NAME ]
then
	. /etc/default/$NAME
fi

. /lib/lsb/init-functions

set -e

case "$1" in
  start)
	echo -n "Starting $DESC: "
	mkdir -p $RUNDIR
	touch $PIDFILE
	chown redis:redis $RUNDIR $PIDFILE
	chmod 755 $RUNDIR

	if [ -n "$ULIMIT" ]
	then
		ulimit -n $ULIMIT
	fi

	if start-stop-daemon --start --quiet --umask 007 --pidfile $PIDFILE --chuid redis:redis --exec $DAEMON -- $DAEMON_ARGS
	then
		echo "$NAME."
	else
		echo "failed"
	fi
	;;
  stop)
	echo -n "Stopping $DESC: "
	if start-stop-daemon --stop --retry forever/TERM/1 --quiet --oknodo --pidfile $PIDFILE --exec $DAEMON
	then
		echo "$NAME."
	else
		echo "failed"
	fi
	rm -f $PIDFILE
	sleep 1
	;;

  restart|force-reload)
	${0} stop
	${0} start
	;;

  status)
	status_of_proc -p ${PIDFILE} ${DAEMON} ${NAME}
	;;

  *)
	echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload|status}" >&2
	exit 1
	;;
esac

exit 0

Make sure the redis-server init.d script is executable

sudo chmod +x /etc/init.d/redis-server

Update the system to use Redis server init.d script

sudo update-rc.d redis-server defaults

Start the Redis server service

sudo service redis-server restart

Confirm Redis-server is Secure

These are a few checks to make sure Redis is running securely, first use netstat

netstat -antp

Make sure it listening on 127.0.0.1

tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      10561/redis-server

You can also make sure the redis process is running as the redis user we specified

ps aux | grep redis

If redis says root instead that would be bad, even though it's listening on the loopback interface

redis     10561  0.0  0.4  38020  2160 pts/0    Tl   19:03   0:00 /usr/bin/redis-server 127.0.0.1:6379

Install phpredis

Install php5-development tools and git, clone the latest phpredis, build and install it.

If you are using php7 you will need the php7.0-dev package for the development tools. You will also need to add -b php7 at the end of the git clone line (not on its own new line) to use the php7 branch of the github repository.

sudo apt-get install php5-dev git -y
git clone https://github.com/phpredis/phpredis
cd phpredis
phpize
./configure
sudo make
make install

Add the redis extension to php5-fpm for nginx or apache2

For Apache2 add Redis to its php file

echo "extension=redis.so" >> /etc/php5/apache2/php.ini
sudo service apache2 restart

For nginx with php5-fpm enable Redis like this

echo "extension=redis.so" >> /etc/php5/fpm/php.ini
sudo service php5-fpm restart

For nginx with php7.0-fpm

echo "extension=redis.so" >> /etc/php/7.0/fpm/php.ini
sudo service php7.0-fpm restart

Install the WordPress Redis plugin and enable it and enjoy the speed!

You can monitor Redis cached objects with this tool and monitor phpredis too.