1

I haven't really wrapped my head around how to create (working) certificates using certbot for nginx.

My sites-enables now look like this:

First, a block for the www domain with SSL. All the SSL stuff is created by certbot.

server {
root …
index … 
server_name www.doman.com
listen 443 ssl;
ssl_certificate …
ssl_certificate_key …
include …
ssl_dhparam … 
}

After this, a redirect from port 80 to port 443 for both www and non-www. The first part – the if statement – is created by certbot and not me.

server {
if ($host = www.example.com {
    return 301 https://$host$request_uri;
    }

listen *:80;
server_name domain.com www.example.com;
return 301 https://www.example.com$request_uri;

}

And finally, a block for 443 without www. I want this to redirect to www.

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

This plays out well for the domain with www. However, without www, I get "this site cannot be reached". Even when I try it with http and and not https.

Where am I fucking this up? My guess is that the third block, that used 443 for non-www, needs SSL certificates as well. But I use certbots automatic creation, and it doesn't add any.

3

I don't allow certbot to create my web server configurations. I frankly don't trust it to get it right, since it's already doing some not very efficient practices.

So I get certs with certbot certonly --webroot -w /var/www -d hostname -d hostname ...

And my nginx configuration looks like this (for one example domain):

server {
    server_name www.yes-www.org yes-www.org;

    access_log off;

    include includes/listen-80;
    include includes/cloudflare;
    include includes/letsencrypt;

    location / {
        return 301 https://$host$request_uri;
    }
}

For port 80 I'm just serving both hostnames and redirecting to https and www unconditionally.

server {
    server_name yes-www.org;

    access_log off;

    ssl_certificate /etc/letsencrypt/live/www.yes-www.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.yes-www.org/privkey.pem;

    include includes/listen-443;
    include includes/cloudflare;
    include includes/ssl;
    include includes/hsts;
    include includes/letsencrypt;

    location / {
        return 301 https://www.yes-www.org$request_uri;
    }
}

For port 443 non-www I'm just redirecting to www unconditionally.

server {
    server_name www.yes-www.org;

    root /srv/www/yes-www.org;

    access_log /var/log/nginx/yes-www.org-access.log nginx;
    access_log /var/log/nginx/cache.log cache;
    error_log /var/log/nginx/yes-www.org-error.log;

    ssl_certificate /etc/letsencrypt/live/www.yes-www.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.yes-www.org/privkey.pem;

    include includes/listen-443;
    include includes/cloudflare;
    include includes/letsencrypt;
    include includes/ssl;
    include includes/hsts;
    include includes/favicon;
    include includes/wordpress;
    include includes/php;
    include /srv/www/yes-www.org/nginx.conf;

    location ~ /\.(ht|git) {
        deny all;
    }
}

And finally here I'm serving a web site.

Note that the contents of /etc/nginx/includes/letsencrypt are:

location /.well-known/acme-challenge/ {
    root /var/www;
    try_files $uri =404;
}

Which makes certbot certonly as above work.

  • +1 for the shared webroot for every /.well-known/acme-challenge/. If I had only thought of that before, I would have saved a lot of configuration lines and time (using certonly, but configured every vhost separately). This is simply elegant and easy to maintain. – Esa Jokinen May 16 at 4:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.