NGINX Templates and Let'sEncrypt Challenge

I’m having a problem which I do not know how to solve it. I’ve created a custom NGINX Template, because I want special mappings for my web app.

I have and app running in port 8181 and I want to link it to myapp.com. I have a special need regarding some host names. I would like that home.myapp.com take me to the /home endpoint if it has no endpoint selected (root), but also take me to the selected endpoint if set, for example home.myapp.com/any-other-endpoint should take me to /any-other-endpoint

So this is the relevant part of the nginx template:

server {
    listen      %ip%:%proxy_ssl_port% ssl http2;
    server_name myapp.com www.myapp.com;
    ssl_certificate      %ssl_pem%;
    ssl_certificate_key  %ssl_key%;
    ssl_stapling on;
    ssl_stapling_verify on;
    error_log  /var/log/%web_system%/domains/%domain%.error.log error;

    include %home%/%user%/conf/web/%domain%/nginx.hsts.conf*;

    location / {
        proxy_pass      https://%ip%:8181;
        location ~* ^.+\.(%proxy_extensions%)$ {
            root           %sdocroot%;
            access_log     /var/log/%web_system%/domains/%domain%.log combined;
            access_log     /var/log/%web_system%/domains/%domain%.bytes bytes;
            expires        max;
            try_files      $uri @fallback;
        }
    }

    location /error/ {
        alias   %home%/%user%/web/%domain%/document_errors/;
    }

    location @fallback {
        proxy_pass      https://%ip%:8181;
    }

    location ~ /\.ht    {return 404;}
    location ~ /\.svn/  {return 404;}
    location ~ /\.git/  {return 404;}
    location ~ /\.hg/   {return 404;}
    location ~ /\.bzr/  {return 404;}

    proxy_hide_header Upgrade;

    include %home%/%user%/conf/web/%domain%/nginx.ssl.conf_*;
}


server {
    listen      %ip%:%proxy_ssl_port% ssl http2;
    server_name home.myapp.com;
    ssl_certificate      %ssl_pem%;
    ssl_certificate_key  %ssl_key%;
    ssl_stapling on;
    ssl_stapling_verify on;
    error_log  /var/log/%web_system%/domains/%domain%.error.log error;

    include %home%/%user%/conf/web/%domain%/nginx.hsts.conf*;

    location ~* ^/(.*)$ {
        proxy_pass      https://%ip%:8181;
        location ~* ^.+\.(%proxy_extensions%)$ {
            root           %sdocroot%;
            access_log     /var/log/%web_system%/domains/%domain%.log combined;
            access_log     /var/log/%web_system%/domains/%domain%.bytes bytes;
            expires        max;
            try_files      $uri @fallback;
        }
    }

    location = / {
        proxy_pass      https://%ip%:8181/home;
    }


    location /error/ {
        alias   %home%/%user%/web/%domain%/document_errors/;
    }

    location @fallback {
        proxy_pass      https://%ip%:8181;
    }

    location ~ /\.ht    {return 404;}
    location ~ /\.svn/  {return 404;}
    location ~ /\.git/  {return 404;}
    location ~ /\.hg/   {return 404;}
    location ~ /\.bzr/  {return 404;}

    proxy_hide_header Upgrade;

    include %home%/%user%/conf/web/%domain%/nginx.ssl.conf_*;
}

When using it, it works perfectly fine… The problem is with the Let’s Encrypt challenges.

For example, this challenge (editted the final part) works perfectly fine:

https://myapp.com/.well-known/acme-challenge/nakldnu3904ui23nasjd0ajd-ada

But this does not:

https://home.myapp.com/.well-known/acme-challenge/nakldnu3904ui23nasjd0ajd-ada

They should both work in the same way, as per my initial requests, but as they don’t I think maybe my configuration is wrong…

Another thing I don’t understand is that in my app, any unrecognized endpoint should take the user to /login. So for example, myapp.com/unkonwn redirects me to myapp.com/login… This is what happens with the not working challenge, it takes me to /login… in a way, that’s is correct… but so, why does the other challenge work? It’s the same app…

One thing I guess is that the non-working challenge URL is taking me to /home/.well-known/acme-challenge/nakldnu3904ui23nasjd0ajd-ada

I hope you can help me clarify this! Thanks in advance!

In the DNS you need to have a distinct IP for home.myapp.com as well as www.home.myapp.com to make that challenge work. This is - most likely - not the case.

Thanks for your reply!

I do not understand what you mean… In the web configuration of Hestia, home.myapp.com and www.myapp.com are alias. of the myapp.com domain

If you want to have home.myapp.com to be an alias of myapp.com, then you need to remove the confusion of Nginx here:

**Server1:**
server {
    listen      %ip%:%proxy_ssl_port% ssl http2;
    server_name myapp.com www.myapp.com;
}

**Server2:**
server {
    listen      %ip%:%proxy_ssl_port% ssl http2;
    server_name home.myapp.com;
}

Is there any reason why you want to confuse Nginx by having two servers with Server1 and Server2? It appears that you are confused. And your confusion confused me.

Combine both the servers into one and have an alias of home.myapp.com WITHIN THE SERVER1 for myapp.com!

Currently, if there is a call for home.myapp.com, then it will not serve as an alias of myapp.com for Server 1, because Nginx will see that there is no alias or server name in Sever2.

Thanks again Deepak! I start dealing (and learning) nginx (also hestia templates) only two months ago and maybe I’m not using it as I should.

The reason why I have two blocks is because I want different location handling (I don’t know if that term is correct), notice the location blocks:

## ROOT
server {
    listen      %ip%:%proxy_ssl_port% ssl http2;
    server_name myapp.com www.myapp.com;

    location / {
        proxy_pass      https://%ip%:8181;
    }
}

# HOME
server {
    listen      %ip%:%proxy_ssl_port% ssl http2;
    server_name home.myapp.com;

    location ~* ^/(.*)$ {
        proxy_pass      https://%ip%:8181;
    }

    location = / {
        proxy_pass      https://%ip%:8181/home;
    }
}

Here are the redirections I would like to achieve (I will put a bullet-number at the beginning of each row so I can reference it later):

1- myapp.com -------------------> https://%ip%:8181
2- myapp.com/any-endpoint ------> https://%ip%:8181/any-endpoint
3- home.myapp.com --------------> https://%ip%:8181/home
4- home.myapp.com/any-endpoint -> https://%ip%:8181/any-endpoint

The (1) and (2) should be handled with first server block and (3) and (4) by the second block. The reasons that push me to have two blocks are (1) and (3) I don’t know how to distinguish them if they are in the same block. The second block says that if the locations is EXACTLY / then go to the /home endpoint.

From the second server block, location ~* ^/(.*)$ { should handle ANY ENDPOINT except root and location = / { should handle only the root endpoint.

If I manually test this configuration according to the redirections above, it works perfectly fine. The problem ONLY arise with the challenge from Let’sEncrypt. Maybe the challenge URL and the regex in the location block is the problem. Could it be because the challenge endpoint starts with a DOT.

Is there a way I can test (or see logs) on how nginx is resolving the “redirection” according to the input URL?

The challenge endpoint starting with a DOT has nothing to do with your probem. Nginx logs are under the /var/log directory. If you did not configure it yet, you can use extra commands to produce a flavour in there.

Nginx will match request URL like this:

1-https://%ip%:8181 -------------------> myapp.com
2-https://%ip%:8181/any-endpoint  ------> myapp.com/any-endpoint
3-https://%ip%:8181/home --------------> home.myapp.com

Following request from Lets Encrypt may be giving you a problem (I do not know):

4-https://%ip%:8181/any-endpoint -> home.myapp.com/any-endpoint

Because Nginx should process match request URL from Lets Encrypt as below:

1-https://%ip%:8181/any-endpoint ---> 2-myapp.com/any-endpoint

You can use other methods to differentiate serving of files from different directories based on different URL detection.

You can use .htaccess with rewrite to map an incoming URL request to a different URL or a different directory.

Another method is to use the Module ngx_http_rewrite_module.

Info on creating NGINX Rewrite Rules is here:
Nginx rewrite Module
How to create Nginx rewrite rules

Try it out with one server block. I do not know how redirect will work in your environment.