NGINX - Renewal and rewrites

Sorry if the question has already been asked and I didn’t found the answer here (then please just point me to it):

I am using Let’s Encrypt Plesk extension and all works fine, also the renewal as long as I don’t force a https rewrite.
As soon as I implement a rewrite rule like

if ($scheme = http) { return 301 https://$server_name$request_uri; }
and issue a renewal, I receive the error, that the certificate could not be renewed because of problem to access .well-known directory (anonymised):

Domain: domain.tld Type: unauthorized Detail: Invalid response from http://domain.tld/.well-known /acme-challenge/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx []: 404

Problem is, that the update mechanism looks at http but I redirect everything to https.

So far, I din’t found any way to rewrite all to https except the .well-known directory.

I use a workaround now to only rewrite the root directory, but this is not optimal:

if ($request_uri = /) { set $test A; } if ($scheme = 'http') { set $test "${test}B"; } if ($test = AB) { rewrite ^/(.*)$ https://domain.tld/$1 permanent; }

Anyone has a good idea, how to tweak this to work? Didn’t found a golden rewrite rule which works for me.

Thanks for any useful reply!

Cheers Peter

Hello @heckpet,

You should avoid so many ifs and rewrites, to accomplish your task, process request to /.well-known/acme-challenge/ uri using http and the rest of uris processed by https you could use two location directives:

server {
    listen       80;
    server_name  yourdomain.tld;
    location ^~ /.well-known/acme-challenge/ {
        default_type "text/plain";
        root /path/to/your/root/dir;
    location / {
        return 301 https://$server_name$request_uri;

Anyway, letsencrypt boulder follows redirects so you should not have this issue at all. Are you sure that your letsencrypt client is writing the challenge in the dir that should be accesed using https://yourdomain.tld/.well-known/acme-challenge/random_challenge_created_by_letsencrypt_client ?.


Hello sahsanu,

thanks - but here the problem is with PLESK:

If I define this in the Plesk Panel (I have a form field, where I can add additional NGINX statements), it doesn’t work as I can’t define a new location for "/"
If I do so in the config file, Plesk will overwrite it at next update.

When I use

if ($scheme = http) { return 301 https://$server_name$request_uri; }

instead, it fails.

Ciao Peter

I had the exact same problem with one of my subdomains. When I’ve checked its config, I’ve realized unlike all the others, this one doesn’t have the redirect from HTTP to HTTPS. That I’m solving with following configuration.

server {
  listen 80;
  return 301$request_uri;

server {
  // all settings like root, location, ssl...

The first is there to simply listen for anything on HTTP and redirect it to HTTPS. I find it slightly more sexy than having conditions around in config file.

1 Like

This code works:

if ($scheme != https) {
return 301 https://domain.tld$request_uri;