I'm running nginx on two ports, one for HTTPS and the other for HTTP, but identical in all other ways (i.e. location directives, etc.). I'd like to avoid writing the same rules twice.
Is there a way in nginx config files to write my rules in some sort of block and then include them inside my server directives?
yes, you can include extra files into you configuration, see the docs and example below here:
server {
listen 80;
include location_directives.conf
}
server {
ssl on;
listen 443 default spdy ssl;
include location_directives.conf
}
P.S. By the way, it's prefer to use return 301 to redirect from http to https instead of define the rules for both servers blocks
server {
listen 80;
return 301 https://$host$request_uri;
}
Related
I want to redirect all domain from www to non-www using Nginx config file nginx.conf.
I have tried using the below configuration but it only work for URL start with HTTP but does not work for HTTPS
I have added below server block
server {
server_name "~^(?!www\.).*" ;
return 301 $scheme://$1$request_uri ;
}
Since you didn't specify listening port in the server block you've shown in your question, it will listen on a plain HTTP TCP port 80 by default. You need to specify
listen 443 ssl;
to listen on an HTTPS TCP port 443. However to make the server block workable via the HTTPS protocol, you'd need to specify an SSL certificate/key (at least), and to made a user browser following a redirect returned by nginx, that certificate should be a valid one, issued for the domain name you want to be redirected, or the browser will complain about invalid certificate and won't follow the redirect location.
So if you want to use some kind of universal server block for redirecting every HTTPS request from www to non-www domain, it will be impossible unless you have a certificate that include every domain name you want do redirect (which seems to be impossible to have for a custom non-predefined list of domain names).
Update
Although this isn't a thing I'd do for myself in a production environment, actually there is a way to achieve workable solution using the lua-resty-auto-ssl (see the documentation examples), OpenResty/lua-nginx-module and the following sever block (remember that server names specified by domain prefix have the lowest priority comparing to exact matched server names, e.g. www.example.com, or server names specified by domain suffix, e.g. *.example.com):
init_by_lua_block {
auto_ssl = (require "resty.auto-ssl").new()
auto_ssl:set("allow_domain", function(domain)
return true
end)
auto_ssl:init()
}
map $host $basename {
~^www\.(.+) $1;
default $host;
}
server {
listen 443 ssl;
server_name www.*;
ssl_certificate_by_lua_block {
auto_ssl:ssl_certificate()
}
ssl_certificate /path/to/dummy.crt;
ssl_certificate_key /path/to/dummy.key;
return 301 https://$basename$request_uri;
}
In order for this to work you'd also need the corresponding plain HTTP block to allow ACME challenge(s) to be successfully completed:
server {
listen 80;
server_name www.*;
location / {
return 301 https://$basename$request_uri;
}
location /.well-known/acme-challenge/ {
content_by_lua_block {
auto_ssl:challenge_server()
}
}
}
I configured nginx (and dnsmasq) to listen to example.test and *.example.test wildcard subdomain. Everything seems to work fine. Here is nginx.conf:
server {
listen 80;
server_name ~(\.)?example\.test$;
...
}
Now I want to respond to all other *.test domains from their own directory on disk. I just don't know how to make it happen, following config doesn't work (just disables above configuration):
server {
listen 80;
server_name \.test;
...
}
Even following configuration has same effect:
server {
listen 80;
server_name ~(?!(\.)?example)\.test;
...
}
Both these configs work, but disables *.example.test and example.test configuration and responds to them just as other *.test domains.
Here is my question:
How can I configure nginx to respond to *.test but respond to example.test and *.example.test in a different way?
After a wasting a whole day, I finally managed to fix the issue.
For those who may find themselves in such a confusing situation, here is the solution:
# First server block for default configuration:
server {
listen 80;
server_name ~^[a-zA-Z0-9\-_]+\.test$; # matches domain names (e.g. anything.test)
...
}
server {
listen 80;
server_name ~(\.)?example\.test$ example.test; # matches all subdomains (e.g. subdomain.example.test and sub.subdomain.example.test) as well as example.test
...
}
I looked around to see NGINX configuration for ALL domains and sub-domain but I can only find configurations that are specified.
This is what I want to achieve
server {
listen 80;
server_name all;
return 301 https://www.test.com$request_uri;
}
but then I don't want www.test.com forwarded, only anything else that doesn't match it, even if it is like x.test.com it should be forward too
how I can do it?
You need to provide a separate server block for the domain you don't want to redirect. For example:
server {
listen 80;
server_name www.test.com;
# rest of configuration
}
server {
listen 80 default_server;
return 301 https://www.test.com$request_uri;
}
BTW, you are redirecting to https. Then you need to listen not only 80, but 443 as well. I hope you have it working and left out for the question's simplicity. Otherwise, the documentation is here.
We have an application where we use subdomains for each of our customer's installations. so we have customer1.ourapp.com, customer2.ourapp.com, customer3.ourapp.com and so on.
Because of security we want to redirect all http to https, since we have a wildcard SSL certificate.
Also, some customers are not that tech savvy and add www to their domain name, so then you get things like: http://www.customer1.ourapp.com or https://www.customer1.ourapp.com. In those cases the SSL certificate isn't valid because of the subsubdomain.
I'm trying to write the vhost config for nginx to make the correct redirect in these two cases. I got the http to https redirect to work with:
server {
listen 80;
server_name *.ourapp.com;
#Rewrite all nonssl requests to ssl.
return 301 https://$host$request_uri$is_args$args;
}
correct url's use:
server {
listen 443;
server_name *.ourapp.com;
#Rest of config
}
Made an attempt for the subsub domains, but it's not matching:
server {
server_name "~^(.*)\.(.*)\.ourapp\.com$";
return 301 https://$2.ourapp.com$request_uri;
}
Any idea how to get this working?
Wildcarded server takes precedence over regexp'ed one and matches 'www...' too.
You can use one definition for both cases:
server_name ~ ^(?:.*\.)?(.*)\.ourapp\.com$;
return 301 https://$1.ourapp.com$request_uri;
We have secure and non-secure domains for our website e.g. secure.xyz.com and xyz.com
I used following link to make single server handle both port 80 and 443 traffic.
http://nginx.org/en/docs/http/configuring_https_servers.html#single_http_https_server
server {
listen 80;
listen 443 ssl;
server_name secure.xyz.com xyz.com;
....
ssl_certificate secure.xyz.com.crt;
ssl_certificate_key secure.xyz.com.key;
...
}
Every thing works fine except that $_SERVER's variable 'SERVER_NAME' is set to 'secure.xyz.com'. So that this hostname appears on non-secure page with 'http', e.g., 'http://secure.xyz.com'.
My queries are:
Does Nginx always pick the first server from the config ... irrespective of what client has requested? (and passes to proxy (php-fpm)?).
We have a lot of rules, so if we create two separate server (as per following), do I need to copy the rules in both places? Is there any maintainable way, like 'include /common_rules.conf'? I tried using 'location' rules (only) in the file, also I tried using 'server' encapsulating location rules however it does not work.
server {
listen 443;
server_name secure.xyz.com;
ssl on;
ssl_certificate secure.xyz.com.crt;
...
include common_rules.conf; ===>???
}
server {
listen 80;
server_name xyz.com;
...
include common_rules.conf; ===>???
}
Any help is highly appreciated.