Nginx - get subdomain as variable - nginx

I have a couple of subdomains with the same behavior (based on subdomain name) and I am trying to find the best solution with less overhead for the nginx server.
On that domain there are also default www and non-www domains, also a wildcard (those "couple of" subdomains should not match the wildcard).
So far I've found 3 possible solutions:
define each subdomain in separate server block, and hardcode the subdomain
server {
server_name one.domain;
# config with "one"
}
server {
server_name two.domain;
# same config with "two"
}
... three, four etc.
this should be ok, but it's not DRY (don't repeat yourself)
also it's long and looks ugly
catch server_name in a regexp
server {
server_name ~^(?<subdomain>one|two|three|...)\.domain\.com$;
# config with $subdomain
}
config is cleaner, but there is a regexp overhead, also may interact with the wildcard virtual host, I'm not sure which will take precedence
static hostname plus map
server {
server_name one.domain two.domain three.domain ....;
# config with $subdomain, where $subdomain is a map based on $server_name, extracting all characters before .
}
this should be the best approach, vhost selection is based on string compare (no regexp), but I still have regexp usage in that "map"
The question is: can the third solution be improved ?
As in extracting part of a string (i.e. $subdomain from $server_name) without using a regexp ?
All subdomains are on the same level, and all end in .domain

Related

Why does example.com behave exactly as .example.com?

I don't know why server_name example.com matches also subdomains (at least when there's not a rule for those), if there's an specific syntax for doing so:
Nginx documentation states that you can define server_name in the following ways:
Sets names of a virtual server, for example:
server_name example.com;
Server names can include an asterisk (“*”) replacing the first or last
part of a name:
server_name *.example.com;
Such names are called wildcard names.
The first two of the names mentioned above can be combined in one:
server_name .example.com;
But I tested this, and example.com behaves just as .example.com is expected, matching also all the subdomains.
This is not a problem as I can override the subdomains by setting a server for *.example.com but it seems very odd to me that if the syntax of .example.com exists with the intention to match both other two, it should mean that the other two don't match to eachother...
Why is this?
If your subdomains don't match any rule, they will be called back to the rule tagged as default_server, which, by default, is the first one on the file. In this case, the example.com rule.
This is the answer to the right question:
https://stackoverflow.com/a/64742545/8719655

Nginx uri rewriting per domain

I have few domains pointing to the same server, for example:
server_name www.domain1.dev www.domain2.dev www.domain3.dev
Most of the configurations are the same, and they are pointing at the same php file, but i have a different assets folder for each domain:
/www.domain1.dev/assets/
/www.domain2.dev/assets/
/www.domain3.dev/assets/
that's why i want to rewrite requests like http://www.domain1.dev/assets/* into http://www.domain1.dev/www.domain1.dev/assets/*
Was trying to play with location - return, but didn't find how to get current domain name.
The currently requested domain name can be in $host or $http_host. See this document for the differences.
For example:
location ^~ /assets {
root /path/to/root/$host;
}
Or:
location ^~ /assets {
return 301 /$host$request_uri;
}
An alternative approach would be to separate your domain names into separate server blocks and use an include statement to pull in the common content.

NGINX multiple server_name, but have robots.txt file for each server_name?

I have to create a server_name as a listener for origin pulls by my CDN.
The CDN wants to pull from origin.mydomain.com
I already have 100s of lines of code under www.mydomain.com that showcases all the rewrites, rules and such, and I need to use all this code again.
My easy solution would be to have
server_name www.mydomain.com origin.mydomain.com
To easily have NGINX listen for the requests to the "origin" subdomain.
My fear is that google discovers the subdomain and starts crawling it. I'd like to block google from the "origin" subdomain somehow. Since declaring multiple server_name, I am not sure I can just place robots.txt file somewhere, since using same root folder as live site.
Is there an easy way to do this?
All feedback appreciated.
Cheers
Ryan
Use two server blocks and use the include directive to pull in the common code. For example:
server {
server_name www.mydomain.com;
include /path/to/common/config;
location = /robots.txt {
root /path/to/friendly/dir;
}
}
server {
server_name origin.mydomain.com;
include /path/to/common/config;
location = /robots.txt {
root /path/to/unfriendly/dir;
}
}
So you have two robot.txt files in different directories - or use rewrite ... last to map the URI to different local files.

how to run two sites from single ip using relative paths with out domain name in nginx

hi I was wondering if we could run two sites with same ip
eg: using an ip directly without any domain name like accessing 192.168.4.250 should give me access to a site "site1" and using a relative path like 192.168.4.250/example to give acess to "site 2"
There's no reason why not, you would just end up in the 'default' server for that ip address. The two "sites" would need to live within the same 'server' (though you could use includes or send to another local port of you want to have independent configurations):
server {
listen 192.168.4.250;
server_name _;
location /example {
root /site_2;
# OR
# proxy_pass http://localhost:SOMEPORT2
}
location / {
root /site_1;
# OR
# proxy_pass http://localhost:SOMEPORT;
}
}

Nginx Reverse Proxy non listening domain catch all

Using nginx as a reverse proxy I have noted that if a site is pointed at the server but does not actually exist you get served with an existing site on the server rather than a domain cannot be found message or similar.
ie say your config block is listening for portal.test.org the user points there cname to the nginx system but with the domain header of smartportal.test.org
or say the they point a site like portal.test2.org
Could someone direct me on the following
a. How nginx decides which site to return when it does not exist as a virtual host
b. How to catch any domain that are not specified and return a default page that tells users this domain does not exist on this host
Hope someone can help I have tried googling but I think sometimes its knowing the correct terms.
Many thanks
you should use default_server parameter of listen directive and server_name directive.
your questions
How nginx decides which site to return when it does not exist as a virtual host
listen [default_server]
If the directive has the default_server parameter, then the enclosing
server {...} block will be the default server for the address:port
pair. This is useful for name-based virtual hosting where you wish to
specify the default server block for hostnames that do not match any
server_name directives. If there are no directives with the
default_server parameter, then the default server will be the first
server block in which the address:port pair appears.
server_name
This directive performs two actions:
Compares the Host header of the incoming HTTP request against the
server { ... } blocks in the Nginx configuration files and selects the
first one that matches. This is how virtual servers are defined.
Server names are processed in the following order:
1.- full, static names
2.- names with a wildcard at the start of the name — *.example.com
3.- names with a wildcard at the end of the name — www.example.*
4.- names with regular expressions
If there is no match, a server { ... } block in
the configuration file will be used based on the following order:
1.- the
server block with a matching listen directive marked as
[default|default_server]
2.- the first server block with a matching listen
directive (or implicit listen 80;)
How to catch any domain that are not specified and return a default page that tells users this domain does not exist on this host
server {
listen 1.2.3.4:80 default_server;
server_name _ "";
location / {
alias /var/www/html/domain-does-not-exists.html;
}
}
server {
listen 1.2.3.4:80 ;
server_name portal.test.org;
location / {
... your site ...
}
}

Resources