Nginx Snippets & Advanced Techniques
Memcached config
Nginx configuration that reads from memcached (populated by WP-FFPC plugin), and if not found, then from HHVM, and lastly from PHP-FPM. The only thing not working is if you stop HHVM, it does not failover to PHP-FPM as it should be. Also, responces from memcached does not contain original headers.
I decided not to use such advanced configuration as I detected that speed directly reading memcached from PHP is not that slower than from nginx - and there are far less complications involved.
# Force www
#
if ($host !~* ^(www)) {
return 301 $scheme://www.$host$request_uri;
}
# Force SSL
#
if ($scheme = http) {
return 301 https://$host$request_uri;
}
# Fix for Wordpress permalinks 404 problems
#
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
try_files /dummy_nonexistant_file @memcached;
}
# memcached with failover to hhvm
#
location @memcached {
error_page 404 405 502 504 = @hhvm;
# avoid cache serve of any URL with query strings
if ($args) {
return 405;
}
# avoid cache serve of POST requests
if ($request_method = POST) {
return 405;
}
# avoid cache serve of wp-admin-like pages, starting with "wp-"
if ($uri ~ "/wp-" ) {
return 405;
}
if ($http_cookie ~ (wp-postpass|wordpress_logged_in|comment_author|wordpressuser)_ ) {
return 405;
}
default_type text/html;
add_header X-Powered-By "Memcached";
set $memcached_raw_key $scheme://$host$request_uri;
set $memcached_key data-$memcached_raw_key;
memcached_pass 127.0.0.1:11211;
}
# Also needed to increase upload max size
#
client_max_body_size 32M;
# Web Fonts - CORS & expires
#
location ~* \.(?:ttf|ttc|otf|eot|woff|woff2)$ {
add_header "Access-Control-Allow-Origin" "*";
# Only one location match is ever executed - therefore the relevant
# location match must contain all relevant rules. The first regular
# expression to match the query will stop the search.
#
expires 1M;
access_log off;
add_header Cache-Control "public";
}
# OCSP stapling
#
ssl_stapling on;
ssl_stapling_verify on;
#
# Trusted cert must be made up of your intermediate certificate followed by root certificate
# ssl_trusted_certificate /path/to/ca.crt;
#
# Using Google DNS & OpenDNS
resolver 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
resolver_timeout 2s;
# Speed up SSL handshake
#
# SSL Session Cache
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 10m;
#
# Use only fast ciphers
# ssl_ciphers ALL:!ADH:!EXP:!LOW:!RC2:!3DES:!SEED:!RC4:+HIGH:+MEDIUM
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK;
# Cache static content
# Note: webpagetest.org needs a expire period of one week for a A grade
#
location ~* \.(?:css|js|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1w;
access_log off;
add_header Cache-Control "public";
# add missing vary header in SPDY to please GTmetrix and such
add_header Vary "Accept-Encoding";
}
This is a compiled idea from the following sources:
- High-performance WordPress mit WP-FFPC, memcached, nginx und ISPConfig
- Mehr Performance in Wordpress mit Cachify & Memcached
- Nginx Wordpress + WP-FFPC Plugin Setup + ngx_pagespeed
About some nginx variables:
$request_uri
is full original request URI, with arguments, and it does not contain a host or domain name (always starts with a “/” character).
Cookie based authentication with nginx?
I want to protect a site from public eyes, but also give access only to specific users - cookies seem perfect for this.
Just add this:
if ($http_cookie !~* 'etk-private') {
return 401;
}
Simplest way to set a cookie is to go to any domain page and in JS console type:
document.cookie = 'cookie=etk-private;max-age=3153600000;path=/';
Or you can do this automatically by visiting specific URL. To set this up, enter:
if ($uri = "/etk-set-private-cookie/") {
rewrite ^ /etk-set-private-cookie/ last;
}
location = /etk-set-private-cookie/ {
add_header Set-Cookie "etk-private=1;Path=/;Max-Age=31536000";
empty_gif;
}
Done.
something like:
if ($uri = "/private/") { rewrite ^ /private/ last; }
location = /private/ { add_header Set-Cookie "private=1;Path=/;Max-Age=31536000"; empty_gif; }
if ($http_cookie !~* 'private') { return 401; }
Even better cookie based authentication (latest)
# Cookie Based Protect
#
if ($uri = "/svko/") { rewrite ^ /svko/ last; }
location = /svko/ {
default_type text/html;
add_header Set-Cookie "svko=1;Path=/;Max-Age=31536000";
return 200 '<!DOCTYPE html>\n<h2>Hooray ;)</h2>\n<p>... now you can <a href="/">access the site</a></p>';
}
# Pass through certificate checks
if ($uri !~* "^/.well-known/acme-challenge/(.*)") { set $condition BO; }
if ($http_cookie !~* 'svko') { set $condition "${condition}TH"; }
if ($condition = "BOTH") { rewrite ^ /401-error/ last; }
location = /401-error/ { default_type text/html; return 401 '<!DOCTYPE html>\n<pre> 401 | Restricted Access</pre>'; }
We can test if it’s working.
|
|
Do note that if
statements in nginx are evaluated on every request, so that could have some performance implications.
Serve WebP or AVIF images
# serve webp if web browser supports webp and webp file exists on disk
# just like on raidbox.de
# add mime tyle for avif here or in /etc/nginx/mime.types
# How to configure your web server to deliver AVIF images: https://shortpixel.com/blog/avif-mime-type-delivery-apache-nginx/
#
types {
image/avif avif;
image/avif-sequence avifs;
}
# conditional variables based on headers
# usualy there is both avif and webp support
#
# explained:
# https://vincent.bernat.ch/en/blog/2021-webp-avif-nginx#serving-webp-avif-with-nginx
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
map $http_accept $avif_suffix {
default "";
"~*avif" ".avif";
}
server {
# webp rewrite rules for jpg and png images
# try to load alternative image.png.webp before image.png
#
location /wp-content/uploads {
location ~ \.(png|jpe?g)$ {
add_header Vary "Accept-Encoding";
add_header "Access-Control-Allow-Origin" "*";
add_header Cache-Control "public, no-transform";
access_log off;
log_not_found off;
expires max;
# trick: .jpg.webp.avif actualy never exist
try_files $uri$avif_suffix$webp_suffix $uri$avif_suffix $uri$webp_suffix $uri =404;
}
}
Telephone Nginx Watch is an shell script that serves as the nearest equivalent to Nginx’s .htaccess file.