Configure NginX, PHP-FPM, APC & Varnish For WordPress
This guide will show you how to
configure varnish for WordPress along with APC, NginX and PHP-FPM.
Wordpress has gained massive popularity and currently accounts for a
decent slice of the internets webpages. In the recent years, the makers
of WordPress have seen a massive surge in its community, bringing new plugins
and themes to the table. It is incredibly extensive and the api vast, but
with this expansion also comes a problem. Wordpress is not known for vetting
plugins, so whenever you install a free plugin, or even some paid plugins, you
run the risk of introducing poor code into your site. Perhaps code that
will either break functionality, or slow your site’s speed down to a halt. This
guide assumes that you have knowledge of WordPress and that you are proficient
using command line in a server environment. Enough talk, Lets dive into a
setup that I personally use on all my WordPress blogs to keep content flowing
smoothly and most of all, fast!
1.
Install NginX, Varnish, PHP-FPM & APC.
Using your preferred method, install
NginX. If you are unaware how to install this there is a post on installation process here.
Essentially it is just adding the RPM and using yum to install NginX.
The same goes for PHP-FPM & APC. Both of these are available in
the CentOS repository, simply yum install them. Varnish
installation can be found on post “Installing Varnish on CentOS“, again
fairly straight forward stuff.
2.
Optimize NginX for WordPress
We now the have the correct software
installed. Lets open up the NginX configuration file located at /etc/nginx/nginx.conf
and input the following into it.
user www-data;
worker_processes 2;
pid /var/run/nginx.pid;
events {
worker_connections
768;
multi_accept
on;
use epoll;
}
http {
# Let NGINX
get the real client IP for its access logs
set_real_ip_from
127.0.0.1;
real_ip_header
X-Forwarded-For;
# Basic
Settings
sendfile on;
tcp_nopush
on;
tcp_nodelay
on;
keepalive_timeout
20;
client_max_body_size
15m;
client_body_timeout
60;
client_header_timeout
60;
client_body_buffer_size 1K;
client_header_buffer_size
1k;
large_client_header_buffers
4 8k;
send_timeout
60;
reset_timedout_connection
on;
types_hash_max_size
2048;
server_tokens
off;
#
server_names_hash_bucket_size 64;
#
server_name_in_redirect off;
include
/etc/nginx/mime.types;
default_type
application/octet-stream;
# Logging
Settings
# access_log
/var/log/nginx/access.log;
error_log
/var/log/nginx/error.log;
# Log Format
log_format
main '$remote_addr - $remote_user [$time_local] '
'"$request"
$status $body_bytes_sent "$http_referer" '
'"$http_user_agent"
"$http_x_forwarded_for"';
# Gzip
Settings
gzip on;
gzip_static
on;
gzip_disable
"msie6";
gzip_vary
on;
gzip_proxied
any;
gzip_comp_level
6;
gzip_min_length
512;
gzip_buffers
16 8k;
gzip_http_version
1.1;
gzip_types
text/css text/javascript text/xml text/plain text/x-component
application/javascript
application/x-javascript application/json
application/xml application/rss+xml
font/truetype application/x-font-ttf
font/opentype
application/vnd.ms-fontobject image/svg+xml;
# Virtual
Host Configs
include
/etc/nginx/conf.d/*.conf;
include
/etc/nginx/sites-enabled/*;
}
Now that we have NginX primed and ready to go, we need to
make changes to our virtual host. Create your vhost file at /etc/nginx/conf.d/yourdomain.conf
and input the following text:
server {
listen
127.0.0.1:8080;
server_name syntaxheaven.com;
port_in_redirect
off;
server_tokens
off;
autoindex
off;
client_max_body_size
15m;
client_body_buffer_size
128k;
access_log /home/syntax/logs/access_log main;
error_log
/home/syntax/logs/error_log;
root
/home/syntax/public_html;
index
index.php index.html index.htm;
try_files
$uri $uri/ /index.php;
error_page 404 /404.html;
location =
/404.html {
root
/usr/share/nginx/html;
}
# Define
default caching of 24h
expires
86400s;
add_header
Pragma public;
add_header
Cache-Control "max-age=86400, public, must-revalidate,
proxy-revalidate";
# Redirect
server error pages to static 50x.html
error_page
500 502 503 504 /50x.html;
location =
/50x.html {
root
/usr/share/nginx/html;
}
# Don't log
robots.txt requests
location =
/robots.txt {
allow
all;
log_not_found
off;
access_log
off;
}
# Rewrite
for versioned CSS+JS via filemtime
location ~*
^.+\.(css|js) {
rewrite
^(.+)\.(\d+)\.(css|js)$ $1.$3 last;
expires
31536000s;
access_log
off;
log_not_found
off;
add_header
Pragma public;
add_header
Cache-Control "max-age=31536000, public";
}
# Aggressive
caching for static files
# If you
alter static files often, please use
# add_header
Cache-Control "max-age=31536000, public, must-revalidate,
proxy-revalidate";
location ~*
\.(asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|ogv|otf|pdf|png|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|t?gz|tif|tiff|ttf|wav|webm|wma|woff|wri|xla|xls|xlsx|xlt|xlw|zip)$
{
expires
31536000s;
access_log
off;
log_not_found
off;
add_header
Pragma public;
add_header
Cache-Control "max-age=31536000, public";
}
location ~*
(^(?!(?:(?!(php|inc)).)*/uploads/).*?(php)) {
try_files
$uri = 404;
fastcgi_split_path_info
^(.+.php)(.*)$;
fastcgi_pass
unix:/var/run/php-fpm.socket;
fastcgi_index
index.php;
fastcgi_param
SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param
SCRIPT_NAME $fastcgi_script_name;
include
/etc/nginx/fastcgi_params;
fastcgi_intercept_errors
on;
fastcgi_ignore_client_abort
off;
fastcgi_connect_timeout
60;
fastcgi_send_timeout
180;
fastcgi_read_timeout
180;
fastcgi_buffer_size
128k;
fastcgi_buffers
4 256k;
fastcgi_busy_buffers_size
256k;
fastcgi_temp_file_write_size
256k;
}
}
3. Configure PHP-FPM
OK, we are making magic here folks. Let’s keep the process rolling with the configuration of PHP-FPM ( PHP FastCGI Process Manager ) will act as your PHP handler. The definition of php-fpm is noted as the following.PHP is a server-side scripting language designed for web development but also used as a general-purpose programming language. PHP is now installed on more than 244 million websites and 2.1 million web servers worldwide.
OK, you should already have PHP-FPM installed. If not, just grab it from the repositories as it should be standard in later version of RHEL & CentOS. The same goes for APC as well. Open up your php.ini for editing using your favorite editor. This file is fairly big so I will not be showing you it’s entire contents. Instead just make sure the following values are set in the configuration file.
ignore_user_abort = Off
post_max_size = 15M
upload_max_filesize = 15M
default_charset = "UTF-8"
allow_url_fopen = Off
default_socket_timeout = 30
mysql.allow_persistent = Off
Now at the very end of your php.ini file drop this
immediately following the last line.
[apc]
apc.stat = "0"
apc.max_file_size = "1M"
apc.localcache = "1"
apc.localcache.size =
"256"
apc.shm_segments = "1"
apc.ttl = "3600"
apc.user_ttl = "7200"
apc.gc_ttl = "3600"
apc.cache_by_default = "1"
apc.filters = ""
apc.write_lock = "1"
apc.num_files_hint= "512"
apc.user_entries_hint="4096"
apc.shm_size = "256M"
apc.mmap_file_mask=/tmp/apc.XXXXXX
apc.include_once_override =
"0"
apc.file_update_protection="2"
apc.canonicalize = "1"
apc.report_autofilter="0"
apc.stat_ctime="0"
;This should be used when you are
finished with PHP file changes.
;As you must clear the APC cache to
recompile already cached files.
;If you are still developing, set
this to 1.
apc.stat="0"
This serve as the configuration settings for APC. Next
we need to locate the php-fpm.conf file. On my machine this was located
just inside /etc at /etc/php-fpm.conf . Set the following lines
to these values.
pid = /var/run/php5-fpm.pid
error_log = /var/log/php5-fpm.log
emergency_restart_threshold = 5
emergency_restart_interval = 2
events.mechanism = epoll
Take note: Double
check that the error and access log files actually exist at the location
defined. Finally, in the www.conf file located
at /etc/php-fpm.d/www.conf make the following adjustments.
user = www-data
group = www-data
listen = /var/run/php-fpm.socket
listen.owner = www-data
listen.group = www-data
listen.mode = 0666
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 50
pm.start_servers = 15
pm.min_spare_servers = 5
pm.max_spare_servers = 25
pm.process_idle_timeout = 60s
request_terminate_timeout = 30
security.limit_extensions = .php
Then, amend the following to the end of the file
php_flag[display_errors] = off
php_admin_value[error_reporting] = 0
php_admin_value[error_log] =
/var/log/php5-fpm.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 128M
php_admin_value[session.save_path] =
/tmp/
4. Add A Layer of Varnish
Quick recap, so far we have installed NginX, setup PHP-FPM with APC to boot. But wait, NginX is on port 8080! That isn’t the port that browsers look to for content, you broke my site! Hold it now, we aren’t finished yet. This is where Varnish comes in. We will now proceed to set Varnish up on port 80 so when someone navigates to your site, Varnish will handle the request, process its VCL rule set to determine whether to pull from cache, or serve fresh content from NginX. If you followed instructions, you should have Varnish installed. Lets open /etc/sysconfig/varnish , or on some servers /etc/default/varnish for editing. Once open, amend this somewhere in the file.
DAEMON_OPTS="-a :80 \
-T
localhost:6082 \
-f
/etc/varnish/default.vcl \
-u www-data
-g www-data \
-S
/etc/varnish/secret \
-p
thread_pools=2 \
-p
thread_pool_min=25 \
-p
thread_pool_max=250 \
-p
thread_pool_add_delay=2 \
-p
session_linger=50 \
-p
sess_workspace=262144 \
-p
cli_timeout=40 \
-s
malloc,768m"
This will server as the default start up options for
Varnish on startup, otherwise you would probably need to type out a giant one
liner containing all the above on every start. Finally, we need to open
the default VCL file located at /etc/varnish/default.vcl.
Go ahead and replace its content with the following.
backend default {
.host =
"127.0.0.1";
.port =
"8080";
}
acl purge {
"127.0.0.1";
}
sub vcl_recv {
# Allow purge requests
if (req.request ==
"PURGE") {
if
(!client.ip ~ purge) {
error
405 "Not allowed.";
}
ban("req.url
~ ^" + req.url + " && req.http.host == " +
req.http.host);
return(lookup);
}
# Add header for sending client ip
to backend
set req.http.X-Forwarded-For =
client.ip;
# Normalize content-encoding
if (req.http.Accept-Encoding) {
if
(req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|lzma|tbz)(\?.*|)$") {
remove
req.http.Accept-Encoding;
}
elsif (req.http.Accept-Encoding ~ "gzip") {
set
req.http.Accept-Encoding = "gzip";
}
elsif (req.http.Accept-Encoding ~ "deflate") {
set
req.http.Accept-Encoding = "deflate";
}
else {
remove
req.http.Accept-Encoding;
}
}
# Remove
cookies and query string for real static files
if (req.url
~
"^/[^?]+\.(gif|jpg|jpeg|swf|css|js|txt|flv|mp3|mp4|pdf|ico|png|gz|zip|lzma|bz2|tgz|tbz)(\?.*|)$")
{
unset req.http.cookie;
set req.url = regsub(req.url, "\?.*$", "");
}
# Don't
cache admin
if (req.url
~
"((wp-(login|admin|comments-post.php|cron.php))|login|timthumb|wrdp_files)"
|| req.url ~ "preview=true" || req.url ~ "xmlrpc.php") {
return
(pass);
} else {
if (
!(req.http.cookie ~ "wpoven-no-cache") ) {
unset req.http.cookie;
}
}
}
sub vcl_hit {
# purge cached objects from memory
if (req.request ==
"PURGE") {
purge;
error 200 "Purged";
}
}
sub vcl_miss {
# purge cached objects variants from
memory
if
(req.request == "PURGE") {
if
(!client.ip ~ purge) {
error 405 "Not allowed.";
}
ban("req.url
~ "+req.url);
error 200
"Purged";
}
if (req.request ==
"PURGE") {
purge;
error 404 "Purged
varients";
}
}
sub vcl_fetch {
# Dont cache admin
if (req.url ~
"(wp-(login|admin|comments-post.php|cron.php))|login" || req.url ~
"preview=true" || req.url ~ "xmlrpc.php") {
return
(deliver);
} else {
if (
beresp.ttl > 0s && !(beresp.http.set-cookie ~
"wpoven-no-cache") ) {
unset beresp.http.set-cookie;
}
}
}
sub vcl_deliver {
# Remove
unwanted headers
unset
resp.http.Server;
unset
resp.http.X-Powered-By;
unset
resp.http.x-backend;
unset
resp.http.Via;
unset
resp.http.X-Varnish;
}
5. WordPress Plugins
To make sure you take advantage of your new configuration and to avoid problems, I recommend the following WordPress plug-ins:APC Object Cache Backend
Nginx Helper
WordPress Varnish
There you have it! You should now have Varnish for WordPress setup along with PHP-FPM, NginX and PHP-FPM. Drop me a line in the comments if you have any thing to add!
Nhận xét
Đăng nhận xét