nginx setup WordPress multiple domains and subdomains - wordpress

Anyone can point me please, in setting up nginx correctly.
I have 3 domains and 1 subdomain, and I have problem with only one domain.
All domains have main server block the same
domain1.com
server {
# Server host
server_name domain1.com *.domain1.com; # Other domains are set to 1.com, 2.com ...
# Server ports
listen 80;
listen [::]:80 ipv6only=on;
listen 443 ssl http2;
listen [::]:443 ipv6only=on ssl http2;
Now funny thing is this:
$ curl -I http://www.domain2.com,
HTTP/1.1 200 OK
Link: <http://www.domain3.com/>; rel=shortlink
$ curl -I https://domain2.com
HTTP/1.1 302 Found
Location: https://www.domain1.com
So non-www https redirects to domain1.com, and www http displays domain3.com.
I have tried to add:
server {
listen 80;
listen [::]:80;
server_name www.domain2.com, domain2.com;
return 301 https://www.domain2.com$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name domain2.com;
return 301 https://www.domain2.com$request_uri;
}
But this doesn't helps.
I see that probably some settings are redundant but not sure why is this not working.
What I want to achieve is:
domain2.com, www.domain2.com > https://www.domain2.com
I also have a subdomain here, but that one is working well: dev.domain2.com

I think it could have to do with you separating the server names by a comma instead of just a space. Try removing the comma in this line and see if you have any luck?
server_name www.domain2.com, domain2.com;

Related

Configuring Nginx - routing traffic from HTTP to HTTPS and BAD REQUEST error (local host, no domain)

I'm trying to configure my Nginx in a way so that all HTTP requests are redirected to HTTPS. This is a testing environment and I don't have the domain, hence, I'm not sure whether the redirect can function properly. The host part is simply 127.0.0.1. This is the current configuration:
server {
listen 80;
listen [::]:80;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name _;
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
...
I also tried:
removing server_name _;
putting the return 301 in a location block;
adding further ssl settings, such as ssl_session_timeout, ssl_protocols, ssl_prefer_server_ciphers.
ssl on has been removed.
The syntax has been tested, nginx reloaded, the ports have been tested with nmap (both 80 and 443 are open).
When I curl -k (since the certificate is self-signed) 127.0.0.1 I get this message:
301 Moved Permanently
nginx/1.14.0 (Ubuntu)
When I curl -k 127.0.0.1:443 I get this message:
400 The plain HTTP request was sent to HTTPS port 400 Bad Request The
plain HTTP request was sent to HTTPS port nginx/1.14.0 (Ubuntu)
Could someone help me to understand what am I doing wrong? I'd be happy to provide more information. Thank you so much!!
So here is an nginx config that is working for me.
upstream app {
server app:8080;
}
server {
listen 80;
listen [::]:80;
server_name webprojects-dev.co.uk;
return 301 https://webprojects-dev.co.uk$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 http2;
server_name webprojects-dev.co.uk;
include /etc/nginx/common.conf;
include /etc/nginx/ssl.conf;
location / {
proxy_pass http://app;
include /etc/nginx/common_location.conf;
}
}
In this instance nginx is running in a stack of docker containers networked with docker compose but that shouldnt have any bearing on how it works.
The upstream is the app container (and port) for a reverse proxy.
The first server block is forwarding on requests to https. As you can see the main difference between mine and yours is the server_name is the domain name and is also included in the return 301 statement.
The second server block is for https. Again server_name is a domain but other than that the only other difference I can see is I don't have ssl on the line listen [::]:443.
Disclaimer: Not an expert on nginx. I just hacked away till I had a reverse proxy config that works for me and now I just copy and paste it for everything.

Nginx redirects subdomain foo to www.foo to www.www.foo etc

I just changed my config from a regular to a wildcard certificate. Now my nginx is misbehaving.
# redirect http to https
server {
listen 80 default_server;
listen [::]:80 default_server;
return 301 https://$host$request_uri;
}
# redirect naked to www
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
include ssl.conf;
return 301 https://www.$host$request_uri;
}
# serve subdomain www
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.com;
include ssl.conf;
# ...
}
# serve subdomain mmm
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name mmm.example.com;
include ssl.conf;
# ...
}
# ...etc.
The above works, but fails for non-existent subdomains (instead of returning 404). So if I try notexist.example.com it will redirect me to www.notexist.example.com and give me a certificate warning. If I click ok, it will redirect to www.www.notexist.example.com, and then www.www.www.notexist.example.com, etc.
What am I doing wrong?
Since you want to catch all non-existent subdomains you need an extra server block at the end, marked as default - like listen 443 ssl default_server; The server_name for this block does not matter - as long as it does not match any of the other server blocks (so you can simply use server_name _;)
Any domain that is not already handled by another server block will be handled by the default one - you can either redirect to your canonical domain or just return 404.

Nginx - Generic redirect all www to non-www

Is it possible to make a generic HTTP -> HTTPS and WWW -> non-WWW redirect in Nginx which impact all domains. Or do I need to set it up for every single domain?
I've made the HTTP->HTTPS as follows:
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
You should use two server blocks for this:
server { # redirect http/https www.example.com to https://example.com
listen 80;
listen 443 ssl;
server_name www.example.com;
ssl_certificate <path_to_ssl_cert_for_domain_www.example.com>;
ssl_certificate_key <path_to_key_for_ssl_cert_above>;
# other ssl parameters here if needed
return 301 https://example.com$request_uri;
}
server { # redirect http://example.com to https://example.com
listen 80;
server_name example.com;
return 301 https://example.com$request_uri;
}
server { # main site config
listen 443 ssl;
server_name example.com;
# rest of your configuration here
...
}
Usually paid SSL certificates already includes both domain name with www prefix and without it. If you're using Lets Encrypt service, you can generate certificate for both example.com and www.example.com by yourself.

Nginx redirecting to the wrong site; poorly formed server_name directive

The Problem
When you type example.com into the address bar of a browser WITHOUT entering the scheme, i.e. http:// or https://, Nginx redirects the user to https://api.example.com instead of https://example.com as intended. I'm pretty sure there's something wrong with my Nginx config, but I'm not sure what.
Details
I'm hosting two websites on the same server, with the same IP. The relevant bits from the DNS zone file looks something like (domain and IP anonymized here):
example.com. 1800 IN A xxx.xxx.xxx.xxx
www.example.com. 1800 IN CNAME example.com.
api.example.com. 1800 IN CNAME example.com.
I have two SSL certs installed (provided by letsencrypt), one for each site, and both sites are configured to redirect to HTTPS. I have two vhost config files, one for each site, as follows:
/etc/nginx/sites-available/api
/etc/nginx/sites-available/default
Both are symlinked into /etc/nginx/sites-enabled/. The relevant bits from the two config files are as follows:
# /etc/nginx/sites-available/api
server {
listen 80;
listen [::]:80 ipv6only=on;
server_name api.example.com;
return 301 https://api.example.com$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
include snippets/api-ssl-params.conf; # ssl config info
server_name api.example.com;
# ... the rest of the site config ...
}
and:
# /etc/nginx/sites-available/default
server {
listen 80;
listen [::]:80;
server_name www.example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 default_server ipv6only=on;
include snippets/ssl-params.conf; # ssl config info
server_name example.com;
# ... the rest of the site config ...
}
I don't understand why just entering example.com into the address bar would redirect to https://api.example.com because:
just plain example.com doesn't appear in the api config file anywhere
example.com shouldn't match the server_name directive api.example.com
the server blocks in default are marked as default_server so shouldn't that take precedence when an ambiguous domain name was typed in?
Thanks!!!
Duh. Figured it out in the process of writing the question. The problem is that just plain example.com doesn't appear in the server_name directive for either of the sites listening on port 80. Since that causes ambiguity, nginx picks the first site in alphabetic order.
I updated the config file for the default site as follows:
# /etc/nginx/sites-available/default
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com; # <-- CHANGED THIS LINE
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 default_server ipv6only=on;
include snippets/ssl-params.conf; # ssl config info
server_name example.com;
# ... the rest of the site config ...
}
And all was right with the universe.

Nginx server_name & listen matches specified patterns

In this example the domain has been replaced with domain.com
Our main issue:
When i type https://domain.com i don't get redirected to https://www.domain.com, we currently don't have a rule for this what would be the best way to solve this?
According to our nginx configuration we have not specified 443 for https://domain.com but still its accessible, why is that?
We have valid ssl certificates for both domain.com and www.domain.com.
We do not have a wildcard certificate *.domain.com.
Our Configuration:
#All non-matching patterns
server
{
listen 80;
#enabling this will cause things to break.
#2015/12/18 09:21:54 [error] 32165#0: *1661 no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking, client: *censored*, server: 0.0.0.0:443
#listen 443 ssl;
#Horrible looking match all pattern.
server_name _ "" domain.com *.domain.com;
return 301 https://www.domain.com$request_uri;
}
#Main site ssl enforced
server
{
listen 443 ssl;
server_name www.domain.com ios.domain.com android.domain.com;
...
}
#Staging / Test site
server
{
listen 443 ssl;
listen 80;
server_name stage.domain.com;
...
}
#Rental cars site ssl enforced
server
{
listen 443 ssl;
server_name hyrbil.domain.com;
...
}
#ios redirect to enforce https
server
{
listen 80;
server_name ios.domain.com;
return 301 https://ios.domain.com$request_uri;
}
#android redirect to enforce https
server
{
listen 80;
server_name android.domain.com;
return 301 https://android.domain.com$request_uri;
}
Bonus question:
Is it possible to match all ssl traffic and do a redirect unless it matches a specific domain, for example make https://xxx.domain.com pass a 301 to https://www.domain.com even tho i don't have a certificate for xxx.domain.com without showing "This page is unsecure, are you sure that you want to proceeed"?
If you have one virtualhost listening on 443, all traffic reaches your IP address will be served by that virtualhost.
Create an SSL virtualhost for domain.com and put a simple redirect in it.
Or create a "catch all/default" SSL virtualhost, and check the HOST header and redirect regarding that, like:
if ($host !~* ^www\.doman\.com$) {
rewrite ^(.*)$ http://www.domain.com$1 permanent;
}
But it will show SSL certificate error on all FQDNs not included in your certificate!

Resources