I'm transitioning from Apache to Nginx and I'm trying to figure out how to get my subdomain rewrite rules to work.
Apache
The Apache configuration I have basically moves all traffic to HTTPS and changes .net and .org domains to the main .com domain. Some of our users still think that every URL should start with "www" so the setup removes it if there is also another subdomain. URLs without any subdomain are redirected to https://www.example.com which isn't necessarily mandatory for the site to work.
# HTTP
<VirtualHost *:80>
RewriteEngine on
# Redirect http://example.tld -> https://www.example.com
RewriteCond %{SERVER_PORT} !^443$
RewriteCond %{HTTP_HOST} ^example\.(com|net|org)
RewriteRule ^(.*)$ https://www.example.com$1
# Redirect http://www.subdomain.example.tld -> https://subdomain.example.com
RewriteCond %{SERVER_PORT} !^443$
RewriteCond %{HTTP_HOST} ^www.([^\.]+)\.example\.(com|net|org)
RewriteRule ^(.*)$ https://%1.example.com$1
# Redirect http://subdomain.example.tld -> https://subdomain.example.com
RewriteCond %{SERVER_PORT} !^443$
RewriteCond %{HTTP_HOST} ^([^\.]+)\.example\.(com|net|org)
RewriteRule ^(.*)$ https://%1.example.com$1 [NC,R,L]
# ...
</VirtualHost>
# HTTPS
<VirtualHost *:443>
RewriteEngine on
# Redirect https://example.tld -> https://www.example.com
RewriteCond %{HTTP_HOST} ^example\.(com|net|org)
RewriteRule ^(.*)$ https://www.example.com$1
# Redirect https://www.subdomain.example.tld -> https://subdomain.example.com
RewriteCond %{HTTP_HOST} ^www.([^\.]+)\.example\.(com|net|org)
RewriteRule ^(.*)$ https://%1.example.com$1
# Redirect https://subdomain.example.(net|org) -> https://subdomain.example.com
RewriteCond %{HTTP_HOST} ^([^\.]+)\.example\.(net|org)
RewriteRule ^(.*)$ https://%1.example.com$1 [NC,R,L]
# Otherwise serve https://subdomain.example.com
# ...
</VirtualHost>
Nginx
The Nginx configuration I have so far works in most cases but I don't know how to remove "www" when the URL is in the form http(s)://www.subdomain.example.tld. According to https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#server-name-if "if is evil" so I tried to keep them out of the most common use cases.
# Redirect http://subdomain.example.com -> https://subdomain.example.com
# Redirect http://example.com -> https://example.com
server {
listen 80;
server_name .example.com;
return 301 https://$host$request_uri;
}
# Redirect https://subdomain.example.(net|org) -> https://subdomain.example.com
server {
listen 80;
server_name .example.net .example.org;
if ($host ~* "^([^.]+(\.[^.]+)*)\.example\.(net|org)$") {
set $subdomain $1;
rewrite ^(.*)$ https://$subdomain.example.com$1 permanent;
break;
}
return 301 https://www.example.com;
}
# Otherwise serve https://subdomain.example.com
server {
listen 443 ssl;
server_name .example.com;
# ...
}
So my question is how do I remove the "www" part when there is another subdomain already present the right Nginx way? In an optimal case the Nginx configuration should work the same way my old Apache config did. There are many questions and answers which cover simple cases where subdomains can be listed by hand in the configuration file. This is not an option for me.