8

I have a server file like this

server {
listen 80;
server_name subdomain.example.com;

return 301 https://$server_name$request_uri;

location /.well-known/acme-challenge {
        root /var/www/letsencrypt;
    }
}

Now when I try sudo letsencrypt renew. It throws up and error saying can't find .well-known/acme-challenge. But as soon as I commented the return 301 line restarted the server and It worked.

Now I want to retest it putting the location first and not commenting the return 301 statement but it says certificate not due for renewal.So the question is does order in which the file is read, does it matter? and it won't automatically renew because of this reason for me, those who do renewal how do you handle this situation?

Saras Arya
  • 213
  • 1
  • 4
  • 11

3 Answers3

9

In this case, it isn't so much the ordering (a good explanation of how location and regex is evaluated can be found here: https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms).

For things like location blocks, the short version is best match wins, rather than the first match.

In your case, however, order counts because you use return. Per https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return:

Stops processing and returns the specified code to a client. The non-standard code 444 closes a connection without sending a response header.

The key here is that a return immediately stops processing/evaluation, so what is happening is that nginx isn't looking at anything below return.

So you just need to move that return clause below your location block.

As for testing, I would try adding --test-cert to your commandline (see https://certbot.eff.org/docs/using.html#certbot-command-line-options).

That should avoid the 'problem' you are having when trying to use their production server, which reports you have a valid cert and do not need a new one right now.

iwaseatenbyagrue
  • 3,588
  • 12
  • 22
2

You should include your return directive in a location block, then the normal location block matching rules are used:

server {
    listen 80;
    server_name subdomain.example.com;

    location / {
        return 301 https://$server_name$request_uri;
    }

    location /.well-known/acme-challenge {
        root /var/www/letsencrypt;
    }
}
Tero Kilkanen
  • 34,499
  • 3
  • 38
  • 58
  • This did not work for me Tero. Do you think all location blocks are processed in a given server, before a decision is made to execute one or is it like the first one that fulfills? – Saras Arya Mar 07 '17 at 07:33
  • A quote from http://nginx.org/en/docs/http/ngx_http_core_module.html#location : `To find location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, the location with the longest matching prefix is selected and remembered.` After that, regular expressions are checked and then if no match is found, then the longest match is used. So, if your configuration contains matching regular expressions, they will override this. This behavior can be changed by using `location ^~ /.well-known/acme-challenge`. – Tero Kilkanen Mar 07 '17 at 11:10
0

answering for the idea of line orders in nginx config files

Yes, it does and totally depends on different directives specified within the different context supported by Nginx. In layman's term, nginx keeps a stack of things to do and applies certain algorithms respectively with best match in mind.

Nginx uses selection algorithm to make decisions in the server context; primarily based on two directives viz. listen and server_name.

Multiple location contexts can be defined, each location is used to handle a certain type of client request, and each location is selected by virtue of matching the location definition against the client request through a selection algorithm.

The upstream context uses round-robin by default to determine which specific server to hand the request to.