Linux Server setup

Store TLS certificates

Until now, our domain and subdomain can only be accessed via the unencrypted HTTP protocol. This is not up-to-date at all and certainly not secure. Search engines, for example, are extremely reluctant to suggest pages that do not offer a secure TLS connection.

TLS stands for Transport Layer Security and is the successor to SSL (Secure Sockets Layer). Although SSL is considered an outdated security protocol, the name persists. So when SSL is advertised, the new standard TLS is actually meant.

TLS certificates can be self-signed or purchased free of charge:

  • OpenSSL, free software (free of charge)
  • Let's Encrypt, free certification authority (free of charge)
  • commercial certification bodies (fee required)

A certification authority (CA) is subject to strict audits, in which security concepts and technical infrastructure are checked in particular. Despite all this, it is a free decision of the software manufacturer to recognize a certification authority as trustworthy or not.

Self-signed certificates are generally considered untrustworthy, as their authenticity is not confirmed by an independent organization. However, there are also free certification authorities, such as Let's Encrypt, which issue certificates free of charge.

Certificate authorities issue SSL certificates only for domains, not for IP addresses.

In order to obtain certificates from free certification authorities, there are requirements that we fulfill with our cloud server and domain:

  • root access on the server
  • a qualified domain name that can be queried via DNS
  • a website that is already online and accessible via port 80

In this chapter, we will obtain trusted certificates for our domain and subdomain from Let's Encrypt. We will also create a self-signed certificate for our server IP. The validity period of certificates is limited in time, so an automatism is needed that renews the certificates early before they expire. We had already discussed the topic of cronjobs at logrotate.

Check SSL and TLS

In the meantime, we let the online service SSL Labs check our configuration and the status of the encryption. Currently, no certificate is stored, so the result for our domain is correspondingly negative:

SSL Labs
SSL Labs: Assessment failed

We will repeat this test later and hopefully we will get an "A", maybe even an "A+" rating.

Next steps:


Install Certbot

Certbot is a free ACME client software (Automatic Certificate Management Environment) that helps us retrieve and renew Let's Encrypt certificates. The software can do more, but that is the main purpose for us.

Install Certbot:


__$ sudo apt install -y certbot
 

Let's Encrypt certificate for the domain

Before we really get started, I would like to open a spoiler: Certbot can be given some level of control over Nginx or Apache. From experience, this is a convenient solution until the components are out of sync with each other. Maybe when Certbot needs to be updated, but the servers have to wait to update because of ongoing web projects. I try to avoid such dependencies, which usually means that there is extra work in the implementation. I use Certbot to request certificates and renew them automatically. That's all I want it to do. I want to control the configuration of the server services myself.

Basically, the domain or subdomain must be publicly accessible via port 80 for the certificate request. What we have already prepared in the last chapter under server block for a domain.

With the following command we apply for a certificate with Certbot at Let's Encrypt. It should be valid for the domain and the "subdomain" www:


__$ sudo certbot certonly -d linuxserversetup.com -d www.linuxserversetup.com --rsa-key-size 4096
 

There is a more compact command, where the webroot method and directory are also specified: sudo certbot certonly --webroot -w /var/www/com.linuxserversetup -d linuxserversetup.com -d www.linuxserversetup.com --rsa-key-size 4096

Of course, we have to prove the ownership of the domain. We do this with the "webroot" method. We have already created the webroot for the domain: /var/www/com.linuxserversetup. My input to the above command is:

  • Place files in webroot directory (webroot): 2
  • Enter email address: Confirmations, bug reports and announcements from Let's Encrypt go to this address.
  • Please read the Terms of Service: a
  • Newsletter: n
  • Input the webroot for linuxserversetup.com: /var/www/com.linuxserversetup
  • Select the webroot for www.linuxserversetup.com: 2

Saving debug log to /var/log/letsencrypt/letsencrypt.log

How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Spin up a temporary webserver (standalone)
2: Place files in webroot directory (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Plugins selected: Authenticator webroot, Installer None
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): tom@linuxservrsetup.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: a

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: n

Obtaining a new certificate
Performing the following challenges:
http-01 challenge for linuxserversetup.com
http-01 challenge for www.linuxserversetup.com
Input the webroot for linuxserversetup.com: (Enter 'c' to cancel): /var/www/com.linuxserversetup

Select the webroot for www.linuxserversetup.com:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Enter a new webroot
2: /var/www/com.linuxserversetup
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/linuxserversetup.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/linuxserversetup.com/privkey.pem
   Your cert will expire on 2022-02-23. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

The answer contains the location where the certificates were stored. More precisely, there are links to the actual files:


__$ sudo ls -la /etc/letsencrypt/live/linuxserversetup.com/
	

Output:


drwxr-xr-x 2 root root 4096 Jan  4 12:02 .
drwx------ 3 root root 4096 Jan  4 12:02 ..
lrwxrwxrwx 1 root root   44 Jan  4 12:02 cert.pem -> ../../archive/linuxserversetup.com/cert1.pem
lrwxrwxrwx 1 root root   45 Jan  4 12:02 chain.pem -> ../../archive/linuxserversetup.com/chain1.pem
lrwxrwxrwx 1 root root   49 Jan  4 12:02 fullchain.pem -> ../../archive/linuxserversetup.com/fullchain1.pem
lrwxrwxrwx 1 root root   47 Jan  4 12:02 privkey.pem -> ../../archive/linuxserversetup.com/privkey1.pem
-rw-r--r-- 1 root root  692 Jan  4 12:02 README

The certificates are valid for three months and are automatically renewed within the last month. The cronjob for this was created here:


__$ sudo nano /etc/cron.d/certbot
 

Output:

/etc/cron.d/certbot


# /etc/cron.d/certbot: crontab entries for the certbot package
#
# Upstream recommends attempting renewal twice a day
#
# Eventually, this will be an opportunity to validate certificates
# haven't been revoked, etc.  Renewal will only occur if expiration
# is within 30 days.
#
# Important Note!  This cronjob will NOT be executed if you are
# running systemd as your init system.  If you are running systemd,
# the cronjob.timer function takes precedence over this cronjob.  For
# more details, see the systemd.timer manpage, or use systemctl show
# certbot.timer.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew

On our Ubuntu Linux it is rather unlikely that this crontab is taken into account, since here usually an systemd timer controls the timers and crons. Therefore Certbot has created an /lib/systemd/system/certbot.timer that triggers the execution of /lib/systemd/system/certbot.service every 12 hours.

Now, to find out if systemd has control on the system, it is enough to check the existence of /run/system/system/:


__$ ls /run/systemd/system/
	

About the output by systemctl list-timers, the Certbot timer should be listed:


__$ systemctl list-timers
	

Output:


NEXT                        LEFT          LAST                        PASSED       UNIT                         ACTIVATES
...
Wed 2022-01-05 16:40:04 UTC 29min left    Wed 2022-01-05 02:55:54 UTC 13h ago      certbot.timer                certbot.service
...

Let's also look into the certbot.timer file:


__$ cat /lib/systemd/system/certbot.timer
 

Output:

/lib/systemd/system/certbot.timer


[Unit]
Description=Run certbot twice daily

[Timer]
OnCalendar=*-*-* 00,12:00:00
RandomizedDelaySec=43200
Persistent=true

[Install]
WantedBy=timers.target

And the associated service certbot.service:


__$ cat /lib/systemd/system/certbot.service
 

Output:

/lib/systemd/system/certbot.service


[Unit]
Description=Certbot
Documentation=file:///usr/share/doc/python-certbot-doc/html/index.html
Documentation=https://letsencrypt.readthedocs.io/en/latest/
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot -q renew
PrivateTmp=true

There we see that the command /usr/bin/certbot -q renew renews the certificates.

After a certificate is renewed, Nginx must be reloaded. The Certbot parameter --deploy-hook is suitable for this task. A bad solution would be to use this over the certbot.service. The complete file with the changed ExecStart line would then look like this:

/lib/systemd/system/certbot.service


[Unit]
Description=Certbot
Documentation=file:///usr/share/doc/python-certbot-doc/html/index.html
Documentation=https://letsencrypt.readthedocs.io/en/latest/
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot -q renew --deploy-hook "service nginx reload"
PrivateTmp=true

With the next update this change is gone again

A better place is the generated file /etc/letsencrypt/renewal/linuxserversetup.com.conf in the [renewalparams] section.


__$ cat /etc/letsencrypt/renewal/linuxserversetup.com.conf
 

Output:


# renew_before_expiry = 30 days
version = 0.40.0
archive_dir = /etc/letsencrypt/archive/linuxserversetup.com
cert = /etc/letsencrypt/live/linuxserversetup.com/cert.pem
privkey = /etc/letsencrypt/live/linuxserversetup.com/privkey.pem
chain = /etc/letsencrypt/live/linuxserversetup.com/chain.pem
fullchain = /etc/letsencrypt/live/linuxserversetup.com/fullchain.pem

# Options used in the renewal process
[renewalparams]
account = adg4c513fhe12318sfvb76fd387
rsa_key_size = 4096
authenticator = webroot
server = https://acme-v02.api.letsencrypt.org/directory
[[webroot_map]]
linuxserversetup.com = /var/www/com.linuxserversetup
www.linuxserversetup.com = /var/www/com.linuxserversetup

Here we add renew_hook = service nginx reload. We can edit the file as usual with the editor nano or with this one-liner. With sed we search the line [renewalparams] and add the renew_hook part below it:


__$ sudo sed -i '/\[renewalparams]/arenew_hook = service nginx reload' /etc/letsencrypt/renewal/linuxserversetup.com.conf
	

The complete file will look like this:

/etc/letsencrypt/renewal/linuxserversetup.com.conf


__$ cat /etc/letsencrypt/renewal/linuxserversetup.com.conf
	

/etc/letsencrypt/renewal/linuxserversetup.com.conf


# renew_before_expiry = 30 days
version = 0.40.0
archive_dir = /etc/letsencrypt/archive/linuxserversetup.com
cert = /etc/letsencrypt/live/linuxserversetup.com/cert.pem
privkey = /etc/letsencrypt/live/linuxserversetup.com/privkey.pem
chain = /etc/letsencrypt/live/linuxserversetup.com/chain.pem
fullchain = /etc/letsencrypt/live/linuxserversetup.com/fullchain.pem

# Options used in the renewal process
[renewalparams]
account = adg4c513fhe12318sfvb76fd387
rsa_key_size = 4096
authenticator = webroot
server = https://acme-v02.api.letsencrypt.org/directory
renew_hook = service nginx reload
[[webroot_map]]
linuxserversetup.com = /var/www/com.linuxserversetup
www.linuxserversetup.com = /var/www/com.linuxserversetup

The .well-known access

For authorization by Let's Encrypt, access to a specific address (http://www.linuxserversetup.com/.well-known/acme-challenge/) must be given. On the server side, the webroot directory, which was previously specified during the application, is used by the letsencrypt service to create a temporary file under /var/www/com.linuxserversetup.com/.well-known/acme-challenge. After the certificate is renewed, this file is also removed. We have to create the .well-known/acme-challenge path ourselves, which we will get to in a moment. A note at this point: the .well-known folder is notorious for hackers placing their malware there after a successful break-in. It is well hidden there and can be accessed from the Internet through the aforementioned share. So it doesn't hurt to look in there from time to time or to create an automatism that empties these folders in certain time intervals.

Apply certificates in the NGINX configuration

We have to change the responsible configuration file (/etc/nginx/sites-available/com.linuxserversetup.conf) for HTTPS accordingly:


__$ sudo nano /etc/nginx/sites-available/com.linuxserversetup.conf
 

The file should have the following content:

/etc/nginx/sites-available/com.linuxserversetup.conf


# force https
server {
  listen      80;
  server_name www.linuxserversetup.com linuxserversetup.com;

  location ~ /.well-known/acme-challenge/ {
    default_type "text/plain";
    root /var/www/com.linuxserversetup/;
    try_files $uri =404;
    break;
  }

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

# main block
server {
  listen      443 ssl http2 default_server;
  listen      [::]:443 ssl http2;
  server_name www.linuxserversetup.com;

  root        /var/www/com.linuxserversetup/;
  index       index.htm;

  location / {
    try_files $uri $uri/ /index.htm;
  }

  location = /favicon.ico { access_log off; log_not_found off; }

  ssl_certificate /etc/letsencrypt/live/linuxserversetup.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/linuxserversetup.com/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/linuxserversetup.com/chain.pem;
}

Create folder path for automatic renewal of Let's Encrypt certificates:


__$ mkdir -p /var/www/com.linuxserversetup/.well-known/acme-challenge
 

After saving we check the new configuration and restart NGINX:


__$ sudo nginx -t
__$ sudo systemctl reload nginx
 

Check Certbot's automatic renewal

Before going any further, we can check if Certbot is able to renew certificates at all. For this purpose there is the parameter --dry-run. This simulates the process and creates a report afterwards.


__$ sudo certbot renew --dry-run
 

Check with SSL Labs

If we now repeat the test with SSL Labs, our configuration should be rated "A":

SSL Labs: A-Rating

The rating can be further improved by adding a Diffie-Hellman key. We create one using OpenSSL, the location should be /etc/ssl/certs/:


__$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
 

Attention spoilers: The calculation will take at least 10 minutes on our CPX11:


Generating DH parameters, 4096 bit long safe prime, generator 2
This is going to take a long time
...............................................+..................................
..................................................................................
...................................................................+..............
..................................................................................
..................................................................................
 

By enabling HSTS, even an "A+" rating is possible. By HSTS the HTTP header Strict-Transport-Security is transmitted, which tells the browser that this address should only be called via HTTPS. The supplied value, is the period in seconds for which the browser should remember this. Usually one year (31536000 seconds).

We enter the path to the PEM certificate and the HSTS header into the NGINX site configuration as before:


__$ sudo nano /etc/nginx/sites-available/com.linuxserversetup.conf
 

The final file will look like this:

/etc/nginx/sites-available/com.linuxserversetup.conf


# force https
server {
  listen      80;
  server_name www.linuxserversetup.com linuxserversetup.com;

  location ~ /.well-known/acme-challenge/ {
    default_type "text/plain";
    root /var/www/com.linuxserversetup/;
    try_files $uri =404;
    break;
  }

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

# redirect to www
server {
  listen      443;
  server_name linuxserversetup.com;
  return      301 $scheme://www.$server_name$request_uri;
}

# main block
server {
  listen      443 ssl http2 default_server;
  listen      [::]:443 ssl http2;
  server_name www.linuxserversetup.com;

  root        /var/www/com.linuxserversetup/;
  index       index.htm;

  location / {
    try_files $uri $uri/ /index.htm;
  }

  location = /favicon.ico { access_log off; log_not_found off; }

  ssl_certificate /etc/letsencrypt/live/linuxserversetup.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/linuxserversetup.com/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/linuxserversetup.com/chain.pem;

  # dhparam
  ssl_dhparam /etc/ssl/certs/dhparam.pem;

  # HSTS
  add_header Strict-Transport-Security "max-age=31536000";
}

Finally, we also specify the allowed encryption methods (ciphers) for a connection with ssl_ciphers, which a browser must support. Here we have to find a good balance between security and sufficient browser compatibility:


ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
 

We can write this default in global settings of NGINX:


__$ sudo nano /etc/nginx/nginx.conf
 

The complete file will look like this:

/etc/nginx/nginx.conf


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;
  types_hash_max_size 2048;
  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;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

  ##
  # 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;
  #  }
  #}

And as usual: Check NGINX and restart:


__$ sudo nginx -t
__$ sudo systemctl reload nginx
 

The rating of SSL Labs should now be "A+":

SSL Labs: A+ Rating

The page ssl-config.mozilla.org can help to make further settings. However, it should be noted that there should still be some backward compatibility. Because a too strict TLS configuration will exclude older devices.


Self-signed TLS certificate for the default server block

Let's Encrypt issues TLS certificates only for qualified domain names. Therefore, we have to provide a self-signed certificate for our IP. Usually it is not desired that someone retrieves the server IP directly in the browser. But since it is possible, this exchange should also be encrypted. At this point it is not important whether the certificate is trustworthy. It does what it is supposed to do, namely encrypt. And if that is too insecure, you should not visit the IP.

Using the following OpenSSL command, we create a certificate and key using the RSA encryption method. The complexity should be 2048 bits with a validity period of 365 days:


__$ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt
 

During the procedure I confirm Country Name with EN and Common Name with the server IP 116.203.69.89. For the rest you can specify or simply by boarding.


gned.key -out /etc/ssl/certs/nginx-selfsigned.crt
Generating a RSA private key
.................................................+++++
......+++++
writing new private key to '/etc/ssl/private/nginx-selfsigned.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:116.203.68.89
Email Address []:

The generated files are:

  • /etc/ssl/private/nginx-selfsigned.key
  • /etc/ssl/certs/nginx-selfsigned.crt

__$ sudo ls -la /etc/ssl/private/
__$ sudo ls -la /etc/ssl/certs/
	

Now we just have to store them in the default configuration above.

Let's open the file for editing:


__$ sudo nano /etc/nginx/sites-available/default
 

We will add another server block at the beginning of the file. This redirects from HTTP to HTTPS, enforcing an encrypted transfer. The second original block will be supplemented with the two paths leading to the self-signed key (ssl_certificate) and the certificate (ssl_certificate_key).

While we're at it, we can also include the Diffie-Hellman key generated above.

The complete file should have the following content:

/etc/nginx/sites-available/default


# force https
server {
  listen 80;
  server_name _;
  return 301 https://116.203.68.89;
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  server_name _;

  root /var/www/default;
  index index.htm;

  location / {
    try_files $uri $uri/ /index.htm;
  }

  location = /favicon.ico { access_log off; log_not_found off; }

  ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
  ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
  ssl_dhparam /etc/ssl/certs/dhparam.pem;
}
 

Let's check the new configuration and restart NGINX:


__$ sudo nginx -t
__$ sudo systemctl reload nginx
 

Let's Encrypt certificate for the subdomain

Basically, the first section repeats where we set up a certificate for the domain. Therefore, the steps now for the domain in fast forward.

The subdomain must be reachable via port 80, which we already prepared in the last chapter under server block for a subdomain.

Apply for a certificate from Let's Encrypt:


__$ sudo certbot certonly -d dev.linuxserversetup.com --rsa-key-size 4096
	
  • Place files in webroot directory (webroot): 2
  • Enter email address
  • Please read the Terms of Service: a
  • Newsletter: n
  • Input the webroot for dev.linuxserversetup.com: /var/www/com.linuxserversetup.dev

Change the configuration file for HTTPS:


__$ sudo nano /etc/nginx/sites-available/com.linuxserversetup.dev.conf
	

The file should have the following content:

/etc/nginx/sites-available/com.linuxserversetup.dev.conf


# force https
server {
  listen      80;
  server_name dev.linuxserversetup.com;

  location ~ /.well-known/acme-challenge/ {
    default_type "text/plain";
    root /var/www/com.linuxserversetup.dev/;
    try_files $uri =404;
    break;
  }

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

# main block
server {
  listen      443 ssl http2;
  listen      [::]:443 ssl http2;
  server_name dev.linuxserversetup.com;

  root        /var/www/com.linuxserversetup.dev/;
  index       index.htm;

  location / {
    try_files $uri $uri/ /index.htm;
  }

  location = /favicon.ico { access_log off; log_not_found off; }

  ssl_certificate /etc/letsencrypt/live/dev.linuxserversetup.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/dev.linuxserversetup.com/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/dev.linuxserversetup.com/chain.pem;

  # dhparam
  ssl_dhparam /etc/ssl/certs/dhparam.pem;

  # HSTS
  add_header Strict-Transport-Security "max-age=31536000";
}

Create the path /var/www/com.linuxserversetup.dev/.well-known/acme-challenge for Let's Encrypt:


__$ mkdir -p /var/www/com.linuxserversetup.dev/.well-known/acme-challenge
	

Restart NGINX:


__$ sudo systemctl reload nginx
 

Delete domain from Certbot

For the sake of completeness, here are instructions on how to exclude a domain from the Certbot process and remove the corresponding Certbot files.

Execute the command certbot delete and select the domain to be deleted:


__$ sudo certbot delete
	

Certbot displays a numbered list and expects you to enter a number:


Saving debug log to /var/log/letsencrypt/letsencrypt.log

Which certificate(s) would you like to delete?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: linuxserversetup.com
2: dev.linuxserversetup.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 

After entering a number, a message is displayed that the domain has been deleted by Certbot:


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Deleted all files relating to certificate dev.linuxserversetup.com.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -