├── README ├── drop ├── default.conf ├── nginx-caching ├── default.conf └── nginx.conf └── default.vcl /README: -------------------------------------------------------------------------------- 1 | These files are the basis for a high performance wordpress blog, using Varnish caching, Nginx, and the W3 Total Cache Wordpress plugin. 2 | 3 | The instructions for using them are on my blog, at http://www.ewanleith.com/blog/900/10-million-hits-a-day-with-wordpress-using-a-15-server 4 | -------------------------------------------------------------------------------- /drop: -------------------------------------------------------------------------------- 1 | 2 | # Most sites won't have configured favicon or robots.txt 3 | # and since its always grabbed, turn it off in access log 4 | # and turn off it's not-found error in the error log 5 | location = /favicon.ico { access_log off; log_not_found off; } 6 | location = /robots.txt { access_log off; log_not_found off; } 7 | location = /apple-touch-icon.png { access_log off; log_not_found off; } 8 | location = /apple-touch-icon-precomposed.png { access_log off; log_not_found off; } 9 | 10 | # Rather than just denying .ht* in the config, why not deny 11 | # access to all .invisible files 12 | location ~ /\. { deny all; access_log off; log_not_found off; } 13 | -------------------------------------------------------------------------------- /default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | ## Your website name goes here. 3 | server_name domainname.com www.domainname.com; 4 | ## Your only path reference. 5 | root /var/www/; 6 | listen 80; 7 | ## This should be in your http block and if it is, it's not needed here. 8 | index index.html index.htm index.php; 9 | 10 | include conf.d/drop; 11 | 12 | location / { 13 | # This is cool because no php is touched for static content 14 | try_files $uri $uri/ /index.php?q=$uri&$args; 15 | } 16 | 17 | location ~ \.php$ { 18 | fastcgi_buffers 8 256k; 19 | fastcgi_buffer_size 128k; 20 | fastcgi_intercept_errors on; 21 | include fastcgi_params; 22 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 23 | fastcgi_pass unix:/dev/shm/php-fpm-www.sock; 24 | 25 | 26 | } 27 | 28 | location ~* \.(css|js|png|jpg|jpeg|gif|ico)$ { 29 | expires 1d; 30 | } 31 | 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /nginx-caching/default.conf: -------------------------------------------------------------------------------- 1 | 2 | server { 3 | server_name arm.nutmegdata.co.uk; 4 | 5 | location / { 6 | proxy_pass http://backend:8080; 7 | proxy_set_header X-Real-IP $remote_addr; 8 | proxy_cache czone; 9 | } 10 | 11 | } 12 | 13 | 14 | 15 | server { 16 | ## Your website name goes here. 17 | server_name backend; 18 | ## Your only path reference. 19 | root /var/www/; 20 | listen 8080; 21 | ## This should be in your http block and if it is, it's not needed here. 22 | index index.html index.htm index.php; 23 | 24 | 25 | location / { 26 | # This is cool because no php is touched for static content 27 | try_files $uri $uri/ /index.php?q=$uri&$args; 28 | } 29 | 30 | location ~ \.php$ { 31 | fastcgi_buffers 8 256k; 32 | fastcgi_buffer_size 128k; 33 | fastcgi_intercept_errors on; 34 | include fastcgi_params; 35 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 36 | fastcgi_pass unix:/dev/shm/php-fpm-www.sock; 37 | 38 | } 39 | 40 | 41 | } 42 | 43 | -------------------------------------------------------------------------------- /nginx-caching/nginx.conf: -------------------------------------------------------------------------------- 1 | # This file is only for the nginx caching configuration only, not for use with Varnish and probably not production ready 2 | 3 | user www-data; 4 | worker_processes 1; 5 | pid /var/run/nginx.pid; 6 | 7 | events { 8 | worker_connections 768; 9 | # multi_accept on; 10 | } 11 | 12 | http { 13 | 14 | ## 15 | # Basic Settings 16 | ## 17 | 18 | sendfile on; 19 | tcp_nopush on; 20 | tcp_nodelay on; 21 | keepalive_timeout 65; 22 | types_hash_max_size 2048; 23 | # server_tokens off; 24 | 25 | # server_names_hash_bucket_size 64; 26 | # server_name_in_redirect on; 27 | 28 | include /etc/nginx/mime.types; 29 | default_type application/octet-stream; 30 | 31 | ## 32 | # Logging Settings 33 | ## 34 | 35 | access_log /var/log/nginx/access.log; 36 | error_log /var/log/nginx/error.log crit; 37 | 38 | ## 39 | # Gzip Settings 40 | ## 41 | 42 | gzip on; 43 | gzip_disable "msie6"; 44 | 45 | # Proxy Settings 46 | port_in_redirect off; 47 | proxy_cache_path /dev/shm/nginx levels=1:2 keys_zone=czone:16m max_size=32m inactive=10m; 48 | proxy_temp_path /dev/shm/nginx/tmp; 49 | proxy_cache_key "$scheme$host$request_uri"; 50 | proxy_cache_valid 200 302 10m; 51 | 52 | 53 | # gzip_vary on; 54 | # gzip_proxied any; 55 | # gzip_comp_level 6; 56 | # gzip_buffers 16 8k; 57 | # gzip_http_version 1.1; 58 | # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; 59 | 60 | ## 61 | # Virtual Host Configs 62 | ## 63 | 64 | include /etc/nginx/conf.d/*.conf; 65 | include /etc/nginx/sites-enabled/*; 66 | } 67 | 68 | 69 | -------------------------------------------------------------------------------- /default.vcl: -------------------------------------------------------------------------------- 1 | # This is a basic VCL configuration file for varnish. See the vcl(7) 2 | # man page for details on VCL syntax and semantics. 3 | # 4 | # Default backend definition. Set this to point to your content 5 | # server. 6 | # 7 | backend default { 8 | .host = "127.0.0.1"; 9 | .port = "8080"; 10 | .connect_timeout = 600s; 11 | .first_byte_timeout = 600s; 12 | .between_bytes_timeout = 600s; 13 | .max_connections = 800; 14 | } 15 | 16 | 17 | acl purge { 18 | "localhost"; 19 | } 20 | 21 | sub vcl_recv { 22 | set req.grace = 2m; 23 | 24 | # Set X-Forwarded-For header for logging in nginx 25 | remove req.http.X-Forwarded-For; 26 | set req.http.X-Forwarded-For = client.ip; 27 | 28 | 29 | # Remove has_js and CloudFlare/Google Analytics __* cookies. 30 | set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js)=[^;]*", ""); 31 | # Remove a ";" prefix, if present. 32 | set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", ""); 33 | 34 | 35 | 36 | # Either the admin pages or the login 37 | if (req.url ~ "/wp-(login|admin|cron)") { 38 | # Don't cache, pass to backend 39 | return (pass); 40 | } 41 | 42 | 43 | # Remove the wp-settings-1 cookie 44 | set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-1=[^;]+(; )?", ""); 45 | 46 | # Remove the wp-settings-time-1 cookie 47 | set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-time-1=[^;]+(; )?", ""); 48 | 49 | # Remove the wp test cookie 50 | set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie=[^;]+(; )?", ""); 51 | 52 | # Static content unique to the theme can be cached (so no user uploaded images) 53 | # The reason I don't take the wp-content/uploads is because of cache size on bigger blogs 54 | # that would fill up with all those files getting pushed into cache 55 | if (req.url ~ "wp-content/themes/" && req.url ~ "\.(css|js|png|gif|jp(e)?g)") { 56 | unset req.http.cookie; 57 | } 58 | 59 | # Even if no cookies are present, I don't want my "uploads" to be cached due to their potential size 60 | if (req.url ~ "/wp-content/uploads/") { 61 | return (pass); 62 | } 63 | 64 | # Check the cookies for wordpress-specific items 65 | if (req.http.Cookie ~ "wordpress_" || req.http.Cookie ~ "comment_") { 66 | # A wordpress specific cookie has been set 67 | return (pass); 68 | } 69 | 70 | 71 | 72 | # allow PURGE from localhost 73 | if (req.request == "PURGE") { 74 | if (!client.ip ~ purge) { 75 | error 405 "Not allowed."; 76 | } 77 | return (lookup); 78 | } 79 | 80 | 81 | # Force lookup if the request is a no-cache request from the client 82 | if (req.http.Cache-Control ~ "no-cache") { 83 | return (pass); 84 | } 85 | 86 | 87 | # Try a cache-lookup 88 | return (lookup); 89 | 90 | } 91 | 92 | sub vcl_fetch { 93 | #set obj.grace = 5m; 94 | set beresp.grace = 2m; 95 | 96 | } 97 | 98 | sub vcl_hit { 99 | if (req.request == "PURGE") { 100 | purge; 101 | error 200 "Purged."; 102 | } 103 | } 104 | 105 | sub vcl_miss { 106 | if (req.request == "PURGE") { 107 | purge; 108 | error 200 "Purged."; 109 | } 110 | } 111 | --------------------------------------------------------------------------------