I'm trying to setup a Nginx server with Lets Encrypt SSL and Varnish for cacheing but I've hit a brick wall. For some reason the website just keeps returning ERR_TOO_MANY_REDIRECTS and I'm can't track down why.

I'm running Ubuntu 16.04

Extra Info: Not sure if this will make a difference but I'm trying to set it up for a sub-domain


Server Config

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

    server_name dev.domain.co.uk;
    set $base /var/www/dev.domain.co.uk;
    root $base;

    # SSL
    ssl_certificate /etc/letsencrypt/live/dev.domain.co.uk/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/dev.domain.co.uk/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/dev.domain.co.uk/fullchain.pem;

    # index.php
    index index.php;

    # reverse proxy
    location / {
        include nginxconfig.io/proxy.conf;

    # handle .php
    location ~ \.php$ {
        include nginxconfig.io/php_fastcgi.conf;

    include nginxconfig.io/general.conf;
    include nginxconfig.io/wordpress.conf;

# subdomains redirect
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name *.dev.domain.co.uk;

    # SSL
    ssl_certificate /etc/letsencrypt/live/dev.domain.co.uk/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/dev.domain.co.uk/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/dev.domain.co.uk/fullchain.pem;

    return 301 https://dev.domain.co.uk$request_uri;

# HTTP redirect
server {
    listen 8080;
    listen [::]:8080;

    server_name .dev.domain.co.uk;

    include nginxconfig.io/letsencrypt.conf;

    location / {
        return 301 https://dev.domain.co.uk$request_uri;

/etc/nginx/nginxconfig.io/proxy.conf file

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_cache_bypass $http_upgrade;

/etc/varnish/default.vcl file

# It does not do anything by default, delegating control to the
# builtin VCL. The builtin VCL is called when there is no explicit
# return statement.
# See the VCL chapters in the Users Guide at https://www.varnish-cache.org/docs/
# and https://www.varnish-cache.org/trac/wiki/VCLExamples for more examples.

# Marker to tell the VCL compiler that this VCL has been adapted to the
# new 4.0 format.
vcl 4.0;

# Default backend definition. Set this to point to your content server.
backend default {
    .host = "";
    .port = "8080";

sub vcl_recv {
    # Happens before we check if we have this in cache already.
    # Typically you clean up the request here, removing cookies you don't need,
    # rewriting the request, etc.

sub vcl_backend_response {
    # Happens after we have read the response headers from the backend.
    # Here you clean the response headers, removing silly Set-Cookie headers
    # and other mistakes your backend does.
    set beresp.ttl = 10s;
    set beresp.grace = 1h;

sub vcl_deliver {
    # Happens when we have all the pieces we need, and are about to send the
    # response to the client.
    # You can do accounting or modifying the final object here.

/lib/systemd/system/varnish.service file

Description=Varnish HTTP accelerator
Documentation=https://www.varnish-cache.org/docs/4.1/ man:varnishd

ExecStart=/usr/sbin/varnishd -j unix,user=vcache -F -a :80 -T localhost:6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m


/etc/default/varnish file

# Configuration file for varnish
# /etc/init.d/varnish expects the variables $DAEMON_OPTS, $NFILES and $MEMLOCK
# to be set from this shell script fragment.
# Note: If systemd is installed, this file is obsolete and ignored.  Please see
# /usr/share/doc/varnish/examples/varnish.systemd-drop-in.conf

# Should we start varnishd at boot?  Set to "no" to disable.

# Maximum number of open files (for ulimit -n)

# Maximum locked memory size (for ulimit -l)
# Used for locking the shared memory log in memory.  If you increase log size,
# you need to increase this number as well

# Default varnish instance name is the local nodename.  Can be overridden with
# the -n switch, to have more instances on a single server.
# You may need to uncomment this variable for alternatives 1 and 3 below.
# INSTANCE=$(uname -n)

# This file contains 4 alternatives, please use only one.

## Alternative 1, Minimal configuration, no VCL
# Listen on port 6081, administration on localhost:6082, and forward to
# content server on localhost:8080.  Use a 1GB fixed-size cache file.
# This example uses the INSTANCE variable above, which you need to uncomment.
# DAEMON_OPTS="-a :6081 \
#              -T localhost:6082 \
#        -b localhost:8080 \
#        -u varnish -g varnish \
#            -S /etc/varnish/secret \
#        -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,1G"

## Alternative 2, Configuration with VCL
# Listen on port 6081, administration on localhost:6082, and forward to
# one content server selected by the vcl file, based on the request.
DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s malloc,256m"

## Alternative 3, Advanced configuration
# This example uses the INSTANCE variable above, which you need to uncomment.
# See varnishd(1) for more information.
# # Main configuration file. You probably want to change it :)
# VARNISH_VCL_CONF=/etc/varnish/default.vcl
# # Default address and port to bind to
# # Blank address means all IPv4 and IPv6 interfaces, otherwise specify
# # a host name, an IPv4 dotted quad, or an IPv6 address in brackets.
# # Telnet admin interface listen address and port
# # Cache file location
# VARNISH_STORAGE_FILE=/var/lib/varnish/$INSTANCE/varnish_storage.bin
# # Cache file size: in bytes, optionally using k / M / G / T suffix,
# # or in percentage of available disk space using the % suffix.
# # File containing administration secret
# VARNISH_SECRET_FILE=/etc/varnish/secret
# # Backend storage specification
# # Default TTL used when the backend does not specify one
# # DAEMON_OPTS is used by the init script.  If you add or remove options, make
# # sure you update this section, too.
#              -f ${VARNISH_VCL_CONF} \
#              -t ${VARNISH_TTL} \
#          -S ${VARNISH_SECRET_FILE} \
#              -s ${VARNISH_STORAGE}"

## Alternative 4, Do It Yourself

If there is any other files I need to supply I'd be more than happy to do so because I've been stuck on this error for about 2 hours now with no luck searching anywhere

  • 1
    Did you clear your browser cache? 301 redirects can be cached forever. You'll need to clear your browser cache after every attempt to fix the problem. – Michael Hampton Oct 18 '18 at 0:47
  • @MichaelHampton yeah cleared the cache, opened in incognito the lot still no luck :/ – Stephen Oct 18 '18 at 0:53

Your varnish config is sending all requests to an nginx server that is configured to issue a redirect for every request, and then pointing all your HTTPS requests to that varnish server. Unsurprisingly, that is resulting in every request being redirected.

| improve this answer | |
  • But cause my website is running SSL I thought I had to send all request to nginx and then reverse proxy to Varnish? Have I set this up wrong then? – Stephen Oct 18 '18 at 7:46
  • 1
    @Coderste You have correctly terminated TLS with nginx, passed the request to varnish on port 80 (which is a bad idea for unrelated reasons), and passed it back to nginx on port 8080. But then that nginx server block does nothing but send a 301 redirect back to the same URL. It should instead be serving content. – Michael Hampton Oct 18 '18 at 12:27
  • @MichaelHampton ah okay got it! Also why is passing the request to varnish on port 80 a bad idea? Could yo elaborate? – Stephen Oct 18 '18 at 12:33
  • 1
    @Coderste You should have nothing on port 80 but a redirect to https. nginx can handle that by itself. In fact, the server block you had on port 8080 would be perfect for that exactly as it was written, with the port changed to 80. Varnish should be on some random high port, and not exposed to the world. – Michael Hampton Oct 18 '18 at 12:35
  • 1
    @Coderste There are many outdated and just plain wrong tutorials out there. Of course, you should also be aware that nginx can do its own caching and you might not even need varnish at all. :) – Michael Hampton Oct 18 '18 at 12:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.