3

I want to serve an website via https://the.example.com (thus with a non-standard sub-domain), but the same website should also be entered with https://example.com and https://www.example.com (+the http counterparts).

So if you type https://www.example.com/page you should be redirected to https://the.example.com/page, and if you type http://example.com/page you should be redirected to the same page.

I made this now with nginx for http like this:

server {
    listen 80;
    server_name example.com www.example.com the.example.com;
    return 301 https://the.example.com$request_uri;
}

and this block for the non-standard https URL's:

server {
    listen 443 ssl http2;
    server_name www.example.com example.com;

    location /.well-known/ {
        allow all;
    }

    location / {
        return 301 https://the.example.com$request_uri;
    }
}

and this block for the actual (canonical) website:

server {
    listen 443 ssl http2;
    server_name the.example.com;

    location ...
}

I left out most lines for brevity. I only want one redirect, before you are on the real site.

The http-site and the canonical https-site work, but I get certificate problems with https://www.example.com and https://example.com.

I requested three certificates, like so:

certbot certonly --webroot -w "/some/root" -d www.example.com -m user@examp.e.com --agree-tos
certbot certonly --webroot -w "/some/root" -d example.com -m user@examp.e.com --agree-tos
certbot certonly --webroot -w "/some/root" -d the.example.com -m user@examp.e.com --agree-tos

How is this supposed to work? Should the sub-sites have their own webroot, or should the webroot and/or certificate be shared? I'm a bit lost here as to what is happening...

doekman
  • 257
  • 2
  • 11
  • 1
    Do you need three separate certificates? You can request all subdomains + your main domain in one using multiple `-d [domain]` switches in one certbot call and use the one multi-domain-certificate in all configs. Or use a wildcard cert, if you want and are able to. – Lenniey Dec 30 '19 at 11:41

2 Answers2

1

you need to have separate configurations for domains: www.example.com and example.com

server {
    listen 443 ssl http2;
    server_name www.example.com;
    
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;

    location /.well-known/ {
        allow all;
    }

    location / {
        return 301 https://the.example.com$request_uri;
    }
}
server {
    listen 443 ssl http2;
    server_name example.com;
    
    ssl_certificate     example.com.crt;
    ssl_certificate_key example.com.key;

    location /.well-known/ {
        allow all;
    }

    location / {
        return 301 https://the.example.com$request_uri;
    }
}

with your configuration

I requested three certificates, like so:

certbot certonly --webroot -w "/some/root" -d www.example.com -m user@examp.e.com --agree-tos

certbot certonly --webroot -w "/some/root" -d example.com -m user@examp.e.com --agree-tos

certbot certonly --webroot -w "/some/root" -d the.example.com -m user@examp.e.com --agree-tos

each domain configuration must points to its own certificate file and key

unless the certificate is wildcard *example.com

little_dog
  • 156
  • 4
  • _each domain configuration must points to its own certificate file._ That's not true, you can have multiple domains/subdomains in one certificate file. – Lenniey Dec 30 '19 at 11:44
  • yes, you are right, thats why in my answer is: `unless the certificate is wildcard *example.com` – little_dog Dec 30 '19 at 11:47
  • 1
    No, not only wildcard, but you can have multiple distinguished domains in one file. Like `example.com` and `www.example.com`, no need for a wildcard cert. – Lenniey Dec 30 '19 at 11:49
  • 1
    ok, I tried to improve my answer – little_dog Dec 30 '19 at 11:57
1

You can use the same server configuration for multiple subdomains as well as the main domain. However, you MUST have .well-known/acme-challenge on port 80 without SSL:

# The canonical site: we want this in our addressbar
server {
    listen       443 ssl http2;
    server_name  husker.example.com;  

    ssl_certificate         /etc/letsencrypt/live/husker.example.com/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/husker.example.com/privkey.pem;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}

server {
    listen       443 ssl http2;
    server_name  www.example.com  secure.example.com  example.com;

    # same certificates, different server because of redirect
    ssl_certificate         /etc/letsencrypt/live/husker.example.com/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/husker.example.com/privkey.pem;

    # This redirects everything else to the canonical address
    location / {
        return 301 https://husker.example.com$request_uri;
    }
}

server {
    listen       80;
    server_name  husker.example.com;
    server_name  www.example.com  secure.example.com  example.com;

    # Allow anyone to view the acme-challenge; certbot needs this
    location /.well-known/acme-challenge {
        allow all;
        root /var/www/certbot/;
    }

    # This redirects everything else to the canonical address
    location / {
        return 301 https://husker.example.com$request_uri;
    }
}

When you request the cert, you have to put all your domains in one line:

certbot certonly --webroot -w "/some/root" -d example.com -d www.example.com -d secure.example.com -m user@examp.e.com --agree-tos

This will create one cert, with the first domain listed as the subject, in this case example.com, and then add the rest of the domains as a SubjectAlternativeName.

doekman
  • 257
  • 2
  • 11
scuba_mike
  • 376
  • 4
  • 11
  • OK, this helps. So I only need one certificate-file, and one webroot location. I probably also want `http://www.example.com` and `http://example.com` to redirect to the `https` site, so I think I can add that. But I still have a question. How would I redirect traffic from `https://www.example.com` and `https://example.com` to `https://husker.example.com` within the same server-directive? – doekman Dec 30 '19 at 15:07
  • The way that this server directive is set up, a re-direction is not required since example.com, www.example.com, and husker.example.com are all served with the same files. So `https://www.example.com/index.html` would be the same file as `https://husker.example.com/index.html` and `https://example.com/index.html`. I've updated my answer to show you what a location declaration would look like. – scuba_mike Dec 30 '19 at 15:15
  • I'm not sure I understand the answer. I want all users to have `https://the.example.com` in their address bar, even if they typed something else. Google calls this 'canonical domain'. Serving the same files is not enough. How do you tell nginx what the canonical domain is? – doekman Dec 30 '19 at 15:21
  • Could you add a line like this? `if ($hostname != 'the.example.com') { return 301 https://the.example.com$request_uri; }` – doekman Dec 30 '19 at 15:26
  • Thanks for the clarification. That part was helpful. If you want the URL bar to say `https://the.example.com`, then you will need to do this with two server declarations. Do not use `if` as it has unintended consequences. I've created a pastebin with a configuration that should work. https://pastebin.com/Wu7SSXJr – scuba_mike Dec 30 '19 at 16:19
  • OK, I can confirm it's working now completely as I wanted.I've editted your post. As soon as it's peer reviewed, I can accept the answer, so others might benefit from it. Thanks, and also thanks to @little_dog. – doekman Dec 31 '19 at 18:09