nginx > varnish > hhvm

This can happen when you've configured WordPress to redirect all insecure traffic to a secure URL (e.g. through .htaccess). What happens is that the first request arrives, gets stripped of SSL headers, and hits WordPress, which notices the connection isn't secure, and consequently sends a redirect upstream to the client.

If you don't think WordPress is doing this, try it with some flat PHP (something really straightforward like <?php phpinfo(); ?>). If it does it with the flat PHP, the best way to debug this tends to be to either sniff traffic between Point A and Point B (to see where the disconnect between expected traffic and reality is appearing), or to go directly to the interesting ports (e.g. via the http://host:port/ URI syntax, by modifying your "hosts" file, and/or using port forwarding) and go up the stack one service at a time until you get data inconsistent with what you'd expect.


Turns out I needed to add:

fastcgi_param HTTPS on;

in the location block passing to php and everything is now working as intended.