How to proxy NGINX, Varnish, and PHP-FPM over SSL

Trying to figure out how to host a WordPress site with NGINX and PHP-FPM, but also add Varnish for caching; and, to make it worse, have this offered over SSL.

I’ve worked with NGINX, Varnish, and Gunicorn for an SSL Django site, and I thought this might be similar. I’ve also setup Varnish, Apache and WordPress before. But so far my logs have been fruitless.


Here’s what is working right now (NGINX and FPM):

NGINX port 80 forwarding to 443 (also forwarding www to non-www).

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com
    return 301 https://example.com$request_uri;
}

NGINX port 443 passing to PHP-FPM listening on port 9000

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    access_log /var/log/nginx-access.log;
    error_log /var/log/nginx-error.log;

    server_name example.com;

    location / {
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }

    location ~ .php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+.php)(/.+)$;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

So I add Varnish

I’ve set up Varnish on port 6081 (default) and point it to 8080 as a backend.

Then I add another port for NGINX to proxy to FPM (like before)

I’ve then added this config for NGINX to handle port 8080, posted here in its entirety since it’s so small (NOTE! THIS SECTION SEEMS TO BE THE PROBLEM):

server {
    listen 127.0.0.1:8080;

    access_log /var/log/nginx-access.log;
    error_log /var/log/php-fpm-error.log;

    root /var/www/example.com;

    index index.php;
    port_in_redirect off;

    location / {
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }

    location ~ .php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+.php)(/.+)$;
        include fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass 127.0.0.1:9000;
    }
}

And then I’ve altered the SSL section of NGINX to proxy_pass to Varnish (like I’ve done in my other projects):

upstream varnish_server {
    server 127.0.0.1:6081 fail_timeout=0;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    # etc. 

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header 'Access-Control-Allow-Origin' '*';

        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header HTTPS "on";
        proxy_pass http://varnish_server;
        break;
    }
}

Errors I’ve received:

varnishlog says this:

   11 ReqStart     c 127.0.0.1 39742 1007025263
   11 RxRequest    c GET
   11 RxURL        c /
   11 RxProtocol   c HTTP/1.0
   11 RxHeader     c X-Forwarded-For: 12.34.567.890
   11 RxHeader     c Host: example.com
   11 RxHeader     c Access-Control-Allow-Origin: *
   11 RxHeader     c X-Forwarded-Host: example.com
   11 RxHeader     c X-Real-IP: 12.34.567.890
   11 RxHeader     c X-Forwarded-Proto: https
   11 RxHeader     c HTTPS: on
   11 VCL_call     c pass pass
   11 FetchError   c no backend connection
   11 VCL_call     c error deliver
   11 VCL_call     c deliver deliver
   11 TxProtocol   c HTTP/1.1
   11 TxStatus     c 503
   11 TxResponse   c Service Unavailable
   11 TxHeader     c Server: Varnish

nginx-error.log says this:

[error] 7532#0: *1 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 12.34.567.890, server: example.com, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:6081/", host: "example.com"

Visually the site hangs for about a minute or two, times out; can’t see any other errors.

Also, note that I added this to wp-config.php, as recommended in WordPress Codex:

if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false)
       $_SERVER['HTTPS']='on';

Any help on this would be much appreciated! 😀

Read more here: How to proxy NGINX, Varnish, and PHP-FPM over SSL

Leave a Reply

Your email address will not be published. Required fields are marked *