{"id":907,"date":"2020-03-31T17:47:11","date_gmt":"2020-03-31T17:47:11","guid":{"rendered":"http:\/\/www.tech-g.com\/?p=907"},"modified":"2023-06-16T09:20:32","modified_gmt":"2023-06-16T09:20:32","slug":"wordpress-varnish-nginx-the-ssl-https-detection-problem","status":"publish","type":"post","link":"https:\/\/www.voodoo.business\/blog\/2020\/03\/31\/wordpress-varnish-nginx-the-ssl-https-detection-problem\/","title":{"rendered":"WordPress, Varnish, nginx: The SSL https detection problem"},"content":{"rendered":"\n<p>I have a certain setup with a Varnish5 caching reverse proxy, with nginx to terminate SSL connections.<\/p>\n\n\n\n<p>The problem with this setup is that wordpress can&#8217;t detect https, hence, it can not enforce it, nor will it link the CSS accordingly etc&#8230;, and if your blog&#8217;s address starts with https, you have a problem.<\/p>\n\n\n\n<p>there is more than one solution that i will enumerate here, I chose to force all connections to come through https (The first), but there are others, the one i will present here (Which i did not use) resolves the problem and allows wordpress to detect whether we are on a secure connection or not.<\/p>\n\n\n\n<p>And even though this post-article talks about wordpress, everything here can apply to any PHP application (Or even other applications written in different programming languages)<\/p>\n\n\n\n<p>1- Enforce https for the whole website<\/p>\n\n\n\n<p>The simplest way to solve the problem (Which i chose) is to redirect all traffic to https.<\/p>\n\n\n\n<p>in the varnish script, implement the following<\/p>\n\n\n\n<p>in the sub vcl_recv, implement the following<\/p>\n\n<pre>if (req.http.host ~ \"^(www\\.)?example\\.com$\") \n{\n\tif (req.http.host ~ \"^(?i)example.com\" || req.http.X-Forwarded-Proto !~ \"(?i)https\") {\n\t\treturn (synth(750, \"\"));\n\t}\n}\n<\/pre>\n\n\n\n<p>Now, the following section is the sub vcl_synth<\/p>\n<pre>sub vcl_synth {\n    if (resp.status == 750) {\n        set resp.status = 301;\n        set resp.http.Location = \"https:\/\/www.example.com\" + req.url;\n        return(deliver);\n    }\n}\n<\/pre>\n\n\n\n<p>Once the above is in place in the varnish script, You will need to tell wordpress that it&#8217;s all HTTPS (SSL)<\/p>\n\n\n\n<p>We do that in the config file, the only file we know that does not change when we update<\/p>\n\n\n\n<pre>define('FORCE_SSL_ADMIN', true);\n$_SERVER['HTTPS']='on';\n<\/pre>\n\n\n\n<p>Now, the above should do it if you don&#8217;t mind that your website only works in https, if you do want http to remain an option, then here is another solution<\/p>\n\n\n\n<p>Start by creating a phpinfo() page to check whether you have the $_SERVER[&#8216;<code>HTTP_X_FORWARDED_PROTO<\/code>&#8216;] variable , if you do, your work is partially done, but you need to mind too things<\/p>\n\n\n\n<p>the varnish server needs to only cache the https copy (because most browsers won&#8217;t allow mixed content these days, and if the css is linked to as http, it won&#8217;t display correctly), you can do that easily with something like the following in the <code>vcl_hash <\/code> area<\/p>\n\n\n\n<pre>\nif (req.http.X-Forwarded-Proto) {\n        hash_data(req.http.X-Forwarded-Proto);\n    }\n<\/pre>\n\n\n\n<p>And then, also in the wp-config file, add the following (probably almost anywhere)<\/p>\n\n\n\n<pre>\nif ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')\n        $_SERVER['HTTPS']='on';\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I have a certain setup with a Varnish5 caching reverse proxy, with nginx to terminate SSL connections. The problem with this setup is that wordpress can&#8217;t detect https, hence, it can not enforce it, nor will it link the CSS accordingly etc&#8230;, and if your blog&#8217;s address starts with https, you have a problem. there [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[170,171],"tags":[],"class_list":["post-907","post","type-post","status-publish","format-standard","hentry","category-nginx","category-varnish"],"_links":{"self":[{"href":"https:\/\/www.voodoo.business\/blog\/wp-json\/wp\/v2\/posts\/907","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.voodoo.business\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.voodoo.business\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.voodoo.business\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.voodoo.business\/blog\/wp-json\/wp\/v2\/comments?post=907"}],"version-history":[{"count":16,"href":"https:\/\/www.voodoo.business\/blog\/wp-json\/wp\/v2\/posts\/907\/revisions"}],"predecessor-version":[{"id":928,"href":"https:\/\/www.voodoo.business\/blog\/wp-json\/wp\/v2\/posts\/907\/revisions\/928"}],"wp:attachment":[{"href":"https:\/\/www.voodoo.business\/blog\/wp-json\/wp\/v2\/media?parent=907"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.voodoo.business\/blog\/wp-json\/wp\/v2\/categories?post=907"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.voodoo.business\/blog\/wp-json\/wp\/v2\/tags?post=907"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}