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