nginx if host true with location and root - nginx

I use docker with nginx and this is my app config file:
server {
listen 80;
server_name app.me.site;
return 308 https://$host$uri;
location .well-known {
root /var/www/.well-known;
try_files /$uri /$uri/ /index.html;
}
# other configs
}
The path is /var/www/app.
I also created /var/www/.well-known for Let's Encrypt and it is accessible but it's only accessible for https.
I need to have an if cluse: if URL is app.me.site/.well-known, do not use https.
I tried to reach this but did not find any clue.

Your config is not workable because the return directive is executed at the NGX_HTTP_SERVER_REWRITE_PHASE while proper location selection will be done later at the NGX_HTTP_FIND_CONFIG_PHASE (request processing phases are described in the development guide). To fix it you should move that return directive to the location block (I also suggest to use the $request_uri variable instead the normalized $uri one):
location / {
# everything not started with the '/.well-known/' prefix will be processed here
return 308 https://$host$request_uri;
}
location /.well-known/ {
# do not append '/.well-known' suffix here!
# (see the difference between 'root' and 'alias' directives)
root /var/www;
try_files $uri =404;
}

Related

Multiple Reverse Proxy and Hosting NginX [duplicate]

I am trying to implement something like that in the nginx conf:
subdomain
sub.domain.com -> Serve html
sub.domain.com/api -> proxy to port 3001
sub.domain.com/viewer -> serve another html
subdomain2
sub2.domain.com -> proxy to port 3000
The only route that doesn't work is the viewer, I get the html from the "location /". All other configurations work well.
I tried to move the viewer to the bottom then to the top and to the middle no matter what it doesn't work.
I use CentOS7. This is the configurations currently in the server:
events {
}
http {
server {
listen 80;
listen [::]:80;
server_name www.sub.domain.com subdomain.com;
location /viewer {
root /opt/viewer/;
try_files $uri /index.html;
index index.html;
}
location / {
root /opt/client-bo/;
try_files $uri /index.html;
index index.html;
}
location /api {
proxy_pass "http://localhost:3001";
}
}
server {
listen 80;
server_name www.sub2.domain.com sub2.domain.com;
listen [::]:80;
location / {
proxy_pass "http://localhost:3000";
}
}
}
Thanks!
If your viewer app located in the /opt/viewer directory and you want it to be available under the /viewer URI prefix, you should use root /opt; for the location /viewer { ... }. Check the difference between root and alias directives.
Next, the very last argument of the try_files directive is treated as the new URI to re-evaluate, so you /index.html being treated as the new URI going to be served with the location / { ... }. You should change that directive to
try_files $uri /viewer/index.html;

NGINX - Why I am getting a 403 Forbidden for root location?

I developed a project with the following structure:
api.my-domain.com: An Restfull API built in Symfony 5.
app.my-domain.com: An Angular App.
www.my-domain.com: A simple but beautiful HTML/CSS/JS landing page.
This structure is served using NGINX on a Ubuntu server. The config files for the api and app sites are working fine. Nothing to do there.
For the landing one I have some custom requirements:
I need to redirect to the app site the request containing "login" or "pm-".
I need to support a multi-language site, so:
When someone access www.my-domain.com/**es**, the server should show index_es.html
When someone access www.my-domain.com/**en**, the server should show index_en.html
When someone access www.my-domain.com/**ca**, the server should show index_ca.html
When someone access www.my-domain.com, the server should return index_es.html; but it should also let access the other static files on the server (images, fonts, styles...) in order to get the landings working.
This requirements are already meet using the following NGINX site config site:
server {
server_name www.my-domain.com my-domain.com;
root /var/www/my-project/;
location = /es {
try_files /index_es.html /index.html;
}
location = /en {
try_files /index_en.html /index.html;
}
location = /ca {
try_files /index_ca.html /index.html;
}
location = / {
try_files /index_es.html /index.html;
}
location ~ ^/(login|pm-) {
return 301 $scheme://app.my-project.com$request_uri;
}
location / {
try_files $uri $uri/ /index_es.html;
}
error_log /var/log/nginx/my-project-error.log;
access_log /var/log/nginx/my-project-access.log;
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/my-project.com-0001/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/my-project.com-0001/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.my-project.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = my-project.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name www.my-project.com my-project.com;
listen 80;
return 404; # managed by Certbot
}
The thing is, on my first attempt to got it working, I didn't put the following piece of code:
location = / {
try_files /index_es.html /index.html;
}
Because I thought that it was enough specifying this:
location / {
try_files $uri $uri/ /index_es.html;
}
But when tried to access the www.my-domain.com I got a 403 Forbidden page from NGINX. So, the questions are:
Why I currently need to put the location = / piece of code in order to get it working?
How can I optimize the configuration in order to remove the location = / piece of code?
Thank you in advance.
Your configuration would be much cleaner if you resorted to simple rewrites directly within the server context:
server {
server_name www.my-domain.com my-domain.com;
root /var/www/my-project/;
rewrite ^/(es|en|ca)$ /index_$1.html;
location = / {
index index_es.html;
}
# ...
}
For a static website, I would recommend to completely eliminate try_files.
It makes sense only for dynamic websites, and may be evil.
Why I currently need to put the location = / piece of code in order to get it working?
Because in your posted configuration, if you remove it, then for URI /, NGINX will select location / { block, which will attempt (due to $uri/) files defined as index, which default to index.html. So it will try to check if it exists, succeed with it, and use it for serving the request.
Once you define location = /, NGINX will use that for serving, because exact matching type (=) always has priority in NGINX, over other location types.
How can I optimize the configuration in order to remove the location = / piece of code?
You don't really need to remove location = / (see adjusted config above). If anything, the exact matching type is preferable, as it will result in the fastest matching. (unless you can deal with things by removing file existence checks, see below).
Someone may argue whether:
location = /es {
try_files /index_es.html /index.html;
}
location = /en {
try_files /index_en.html /index.html;
}
location = /ca {
try_files /index_ca.html /index.html;
}
... would be faster than the rewrite suggested. It wouldn't be fast, due to try_files which makes things slower. Why, is because try_files first check a file for existence, and then makes a decision on whether to move on to the next file, or serving.
Whereas, the rewrite is doing unconditional decision on which file to use for serving. (of course, unless you have other directives affecting it).
You can also attempt to optimize even further by not using index and using rewrite for the homepage. (mind that index also bears performance penalty of file existence check, same to try_files).
Thus:
server {
server_name www.my-domain.com my-domain.com;
root /var/www/my-project/;
rewrite ^/(es|en|ca)$ /index_$1.html;
rewrite ^/$ /index_es.html;
# ...
}

Sub subdomain overridden by subdomain in NGINX

I have a server with Nginx.
I would like to set up two sites:
backend.mysite.com
staging.backend.mysite.com
Here is my server blocks config:
www.backend.mysite.com:
server {
listen 80;
server_name backend.mysite.com www.backend.mysite.com;
location / {
proxy_pass http://127.0.0.1:8800/;
}
}
server {
listen 8800;
server_name my.ip.address;
root /projects/backend/production/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
www.staging.backend.mysite.com:
server {
listen 80;
server_name staging.backend.mysite.com www.staging.backend.mysite.com;
location / {
proxy_pass http://127.0.0.1:8900/;
}
}
server {
listen 8900;
server_name my.ip.address;
root /projects/backend/staging/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
My problem is that backend.mysite.com is overriding staging.backend.mysite.com. How can I say to Nginx to never override if there is a sub subdomain on my adress?
UPDATE:
I've tried to add another domain (my_other_site.com) in my second config to check if it works:
server {
listen 80;
server_name my_other_site.com www.my_other_site.com staging.backend.mysite.com www.staging.backend.mysite.com;
location / {
proxy_pass http://127.0.0.1:8900/;
}
}
server {
listen 8900;
server_name my.ip.address;
root /projects/backend/staging/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
When I visit my_other_site.com it works well. The second site is reached as expected.
my_other_site.com, www.my_other_site.com, staging.backend.mysite.com and www.staging.backend.mysite.com have the same DNS A configuration, they are pointing on the same IP.
UPDATE 2:
When I disable www.backend.mysite.com server block, it works. The site staging.backend.mysite.com is working as expected. That mean that indeed the first block overrides the second one.
How can I tell the first server block to not take in account staging.backend.mysite.com? Is there a way to exclude a specific domain name?
Try to give for included config files same names as domain names, e.g.:
aa.domain.com --> aa.domain.com.nginx.conf
bb.domain.com --> bb.domain.com.nginx.conf
so nginx will include and catch in natural alphabetic order
I was running into the same experience, but eventually when I ran sudo nginx -T, it spat out:
nginx: [emerg] could not build server_names_hash, you should increase server_names_hash_bucket_size: 32
nginx: configuration file /etc/nginx/nginx.conf test failed
So, I edited nginx.conf and uncommented the relevant line:
# ...
server_names_hash_bucket_size: 64;
# ...
I picked 64 because that was what was in the file, commented out. Then I restarted and everything worked.
Then I cleared the cache in my browser.

How to serve relative source urls outside root from NGINX

This seems very basic, but I am not able to solve this.
I want NGINX to serve source urls outside the current root, basically starting with ../
This is my directory
common
root (NGINX root)
->index.html (NGINX default index)
common (another common folder)
I want to be able to serve
src="../common/whatever" /*outer common folder*/
src="./common" /*inner common folder; Cannot change unfortunately*/
As you can see, simple location /common will not work.
This is my current NGINX conf,
server
{
listen 83 default_server;
listen [::]:83 default_server ipv6only=on;
root C:/www/root;
index index.html index.htm;
#This does not work for inner /common folder
location /common {
root C:/www;
try_files $uri /index.html;
}
location / {
try_files $uri /index.html;
}
}
Maybe you can do the reverse:
root/
common/*
site/
site/common/*
and do something like
location /common {
try_files site/$uri $uri ...;
}
etc... which gives you $root/site/common/FILE, $root/common/FILE....

Configure nginx with multiple locations with different root folders on subdomain

I'm looking to serve the root url of a subdomain and directory of a subdomain to two different folders on my server. Here is the simple set-up that I have and is not working...
server {
index index.html index.htm;
server_name test.example.com;
location / {
root /web/test.example.com/www;
}
location /static {
root /web/test.example.com/static;
}
}
In this example going to test.example.com/ would bring the index file in /web/test.example.com/www
and going to test.example.com/static would bring the index file in /web/test.example.com/static
You need to use the alias directive for location /static:
server {
index index.html;
server_name test.example.com;
root /web/test.example.com/www;
location /static/ {
alias /web/test.example.com/static/;
}
}
The nginx wiki explains the difference between root and alias better than I can:
Note that it may look similar to the root directive at first sight, but the document root doesn't change, just the file system path used for the request. The location part of the request is dropped in the request Nginx issues.
Note that root and alias handle trailing slashes differently.
The Location directive system is
Like you want to forward all request which start /static and your data present in /var/www/static
So a simple method is separated last folder from full path , that means
Full path : /var/www/static
Last Path : /static and First path : /var/www
location <lastPath> {
root <FirstPath>;
}
So lets see what you did mistake and what is your solutions
Your Mistake :
location /static {
root /web/test.example.com/static;
}
Your Solutions :
location /static {
root /web/test.example.com;
}
server {
index index.html index.htm;
server_name test.example.com;
location / {
root /web/test.example.com/www;
}
location /static {
root /web/test.example.com;
}
}
https://nginx.org/en/docs/http/ngx_http_core_module.html#root
A little more elaborate example.
Setup: You have a website at example.com and you have a web app at example.com/webapp
...
server {
listen 443 ssl;
server_name example.com;
root /usr/share/nginx/html/website_dir;
index index.html index.htm;
try_files $uri $uri/ /index.html;
location /webapp/ {
alias /usr/share/nginx/html/webapp_dir/;
index index.html index.htm;
try_files $uri $uri/ /webapp/index.html;
}
}
...
I've named webapp_dir and website_dir on purpose. If you have matching names and folders you can use the root directive.
This setup works and is tested with Docker.
NB!!! Be careful with the slashes. Put them exactly as in the example.
If you use this, I will suggest you set up this command too.
location /static/ {
proxy_set_header Host $host/static; // if you change the directory and the browser can't find your path
alias /web/test.example.com/static/;
}
If you want to check two different directories for the same URI use this config:
server {
...
root /var/www/my-site/public/;
...
index index.php index.html index.htm;
...
location / {
root /var/www/old-site/dist/;
try_files $uri $uri/ /index.php$is_args$args;
}
...
}
If Nginx couldn't find file in /var/www/old-site/dist/ directory, then it will try file in /var/www/my-site/public/ directory, but as we said to Nginx to try files with $uri $uri/ /index.php$is_args$args patterns, so Nginx will try /index.php$is_args$args in /var/www/my-site/public/ directory. not $uri
If you want to complete your fallthrough, then replace /index.php$is_args$args with /fallthrough$uri and then add the location /fallthrough { ... } with the alias key to your target directory.
https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#root-inside-location-block

Resources