Nginx-Certbot-Debians 2. Setbacks

Robert Crowther Apr 2022
Last Modified: May 2023

PrevNext

This setup can go wrong…

I ran Certbot too early!

On an empty config file? No worries. For installation, you can run it again and again,

sudo certbot --nginx

When challenged, say to Certbot you will reuse the original certificates.

Certbot install likes working Port 80 server blocks

Certbot likes to work with an existing, running, server. On Port 80, as HTTP. The Vertbot instructions for every system start like this,

To use Certbot, you’ll need…

The reason Certbot likes this is because it can then scan the file, identify server configuration, then inject something useful. If there is no configuration, Certbot install does nothing.

How do I add a subdomain?

Everyone asks this. Certbot is guessy. It wants to supplement existing certificates. So asks you about that, even if you type something else in. It has an ‘–expand’ command, that guesses. I’m not keen on that command. I prefer facts. I follow an idea from a post listed in the references. List your existing certificates,

sudo certbot certificates

All certificates have a name. Get the name, then target certificates. Add all domains to this command, because Certbot will erase current contents,

sudo certbot certonly --cert-name zerohour.com -d zerohour.com,www.zerohour.com

As for Certbot install, this is where it goes pickle‐shaped. See, Certbot will handle installing into an existing block, say you want to add ‘www.zerohour.com’ to ‘zerohour.com’.

But let’s say you want some other functionality, so want a separate block for your ‘smokingwreakage.zerohour.com’ domain name. Certbot will be confused. Won’t do anything bad, but will refuse to write. This is where people end with multiple certificates for the same domain, or blocks that won’t authenticate. Maybe you’d be best abandoning the Certbot installer and handwriting the block. You should have the certificate list on the original route, so copy and paste over, then can write in the redirect,

# New block for new subdomain
server {
    listen       443 ssl;
    listen       [::]:443 ssl;

    server_name smokingwreakage.zerohour.co.uk;
    root    /usr/share/nginx/wreakagezerohour;
    access_log   /var/log/nginx/wreakagezerohour/access.log;
    error_log    /var/log/nginx/wreakagezerohourerror.log;

    location / {
        limit_except GET { deny all; }
    }

    #########################
    # Certbot certificates
    #########################
    ssl_certificate /etc/letsencrypt/live/zerohour.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/zerohour.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
    # Add new subdomain here
    if ($host = smokingwreakage.zerohour.com) {
        return 301 https://$host$request_uri;
    }

    if ($host = zerohour.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen       80 ;
    listen       [::]:80 ;

    # Add new subdomain here
    server_name zerohour.com smokingwreakage.zerohour.com;
    return 404; # managed by Certbot
}

Check also the post in References.

How do I add a new domain?

You need a working server block. It needs to be symlimked into ‘sites‐enabled,

sudo ln -s /etc/nginx/sites-available/com.hourone.conf /etc/nginx/sites-enabled/

And needs to be passed by,

nginx -t

Otherwise Certbot will fail.

If you’ve run a Certbot install on a non‐working config—easy to do—despite dire warnings and abrupt behaviour, Certbot will make the certificate. You can get in a big tangle with this, generating multiple certificates. You can get out by listing the certificates, tidy up surplus files, then run this as install instead,

certbot install --cert-name hourone.com

Which only runs the install routine.

An /etc/nginx/nginx.conf

As of 2022,

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
        # multi_accept on;
}

http {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;

        # server_tokens off;

        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Gzip Settings
        ##

        gzip on;

        # gzip_vary on;
        # gzip_proxied any;
        # gzip_comp_level 6;
        # gzip_buffers 16 8k;
        # gzip_http_version 1.1;
        # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;


        ##
        # Virtual Host Configs
        ##

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}


#mail {
#       # See sample authentication script at:

#       # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
#       # auth_http localhost/auth.php;
#       # pop3_capabilities "TOP" "USER";
#       # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
#       server {
#               listen     localhost:110;
#               protocol   pop3;
#               proxy      on;
#       }
#
#       server {
#               listen     localhost:143;
#               protocol   imap;
#               proxy      on;
#       }
#}

Debianess

Debian packaging is rigourous. If code can’t be placed in as Debain approves, and fit with Debian ethos, it will be hacked intil it does. But there are reasons for the packaging decisions in Debian.

This is about two directories in ‘/etc/nginx/’, ‘sites‐available’, and ‘sites‐enabled’,

├── sites-enabled
│   └── default
└── sites-available
    └── default

Which is a Debian reconfiguration, and true for, as well as Nginx, Debian packaging of Apache. First, you are supposed to write one config file per route/server. On a remote terminal editor, this makes life easier. Second, it means you can drop or raise a server segment by pulling the configuration in and out of the directory—which is neat.

But that is not enough. First, if you’re writing or moving files, it means the whole server is down while you do that. Second, if something goes wrong in the editing, it can cause temp files to appear—‐if those temp files can be interpreted as configuration by the server, you are in trouble. So Debian provide the second directory, ‘sites‐enabled’. What you do is, when you have finished the configuration, or want to enable/diable a site, you make a symlink into ‘sites enabled’. That is a very fast thing to do. If the config works, it is near‐seamless. With bo danger of leaving junk about. For Apache, Debian provide a script for this action called ‘a2ensite’. No script for Nginx. But the intent is the same.

Should I use the Debian structure?

There’s downsides. Unless you’ve found this information somewhere, you’ll never know about it. And the structure is an over‐abstraction for a small server. Will you remember all this in one year’s time? However, I give you one reason why you should, even if Debian are near forcing you into this. Let’s say you ignore them, then write config straight into ‘/etc/nginx/nginx.conf’. You will, if you spot them, get code riddled with errors,

nginx: [warn] conflicting server name "zerohour.com" on 0.0.0.0:443, ignored

The Nginx test command,

nginx -t

returns,

...
conflicting server name "zerohour.com" on 0.0.0.0:80, ignored

If you go online, you’ll find other coders have run into this problem.

Here is the problem… these lines in ‘nginx.conf,

        ##
        # Virtual Host Configs
        ##

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;

They are importing live configuration from other files. Thus, there are many declarations of the same server in different blocks—thus the conflicts. If you want your hacky stab at one‐file configuration to work, you need to comment those two out.

All good? See Part Three Maintaining Certbot to check this will stay running.

Refs

Nano shortcuts, always useful here,

https://www.nano-editor.org/dist/latest/cheatsheet.html

Certbot, my site is running on… instructions,

https://certbot.eff.org/instructions

Debian on some aspects on their packaging,

https://wiki.debian.org/Nginx/DirectoryStructure

The How Do I Add A Subdomain To Certbot question,

https://unix.stackexchange.com/questions/301266/certbot-add-www-domain-to-existing-domain-certificate