Let's Encrypt

From Indie IT Wiki

Introduction

Lets Encrypt is a free, automated, and open certificate authority brought to you by the non-profit Internet Security Research Group (ISRG).

LetsEncrypt have grown to be the third largest Certificate Authority in the world. They currently have 1.93 million unexpired certificates in the wild, making them one of the largest Certificate Authorities in the world.

https://letsencrypt.org

https://letsencrypt.org/getting-started/

Status of Operation

Status Page

Debug

Diagnostic tool and website to help figure out why you can't issue a certificate for Let's Encrypt.

https://github.com/letsdebug/letsdebug

https://letsdebug.net/

Chain of Trust

Certificates

ISRG Root X1 cert in PEM format

Installation of Certbot

Ubuntu 20.04

Standalone

certbot certonly --webroot -w /var/www/www.domain.com/html/ -d www.domain.com -d domain.com --agree-tos --email me@domain.com --no-eff-email 

Using NginX

sudo apt-get -y install snapd
sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --version
sudo certbot --nginx

One liner...

sudo certbot --nginx -d www.domain.com -d domain.com --agree-tos --email me@domain.com --no-eff-email

Ubuntu 16.04+

https://certbot.eff.org/lets-encrypt/ubuntubionic-other

sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt update
sudo apt install certbot

Ubuntu 14.04

sudo -i
apt-get install git
mkdir misc
cd misc/
git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt/
./letsencrypt-auto certonly --standalone --email me@mydomain.co.uk -d mail.mydomain.co.uk
./certbot-auto certificates

Generate Certificate - DOCKER

sudo -i
mkdir -p /root/docker/certbot/{certs,logs}
docker pull certbot/certbot
docker run --rm -it -v "/root/docker/certbot/certs/:/etc/letsencrypt/" -v "/root/docker/certbot/logs/:/var/log/letsencrypt/" -p 80:80 certbot/certbot certonly --dry-run --standalone -d mail.domain.me.uk -d www.domain.me.uk -d domain.me.uk --agree-tos --email info@domain.me.uk --no-eff-email
docker run --rm -it -v "/root/docker/certbot/certs/:/etc/letsencrypt/" -v "/root/docker/certbot/logs/:/var/log/letsencrypt/" -p 80:80 certbot/certbot certonly --standalone -d mail.domain.me.uk -d www.domain.me.uk -d domain.me.uk --agree-tos --email info@domain.me.uk --no-eff-email
docker run --rm -it -v "/root/docker/certbot/certs/:/etc/letsencrypt/" -v "/root/docker/certbot/logs/:/var/log/letsencrypt/" -p 80:80 certbot/certbot certificates

Generate Certificate - ACME Script

Install ...

curl https://get.acme.sh | sh -s email=me@example.com

Get certificate ...

acme.sh --set-default-ca --server letsencrypt --issue -d example.com

https://github.com/acmesh-official/acme.sh

https://github.com/acmesh-official/acme.sh/wiki

Generate Certificate - Manual

service lighttpd stop
certbot certonly --standalone --email me@example.com --agree-tos -d www.example.com --pre-hook "service lighttpd stop" --post-hook "service lighttpd start"
cd /etc/letsencrypt/live/www.example.com/
cat privkey.pem cert.pem > ssl.pem
service lighttpd start

Check Certificate

certbot certificates

Renew Certificates

Adding A Domain To An Existing Certificate

This will add 'domain.com' to an existing certificate for just 'www.domain.com'.

Get your certificate name...

certbot certificates

Expand and add the extra domain to that certificate...

certbot --nginx --expand --cert-name www.domain.com -d www.domain.com,domain.com

FORCE Renew Certificates

certbot renew --force-renew

Using Hooks

If you want to run a series of commands ONLY upon a successful renewal and deployment, then use the --deploy-hook option...

certbot renew -n --cert-name example.com --deploy-hook /path/to/script/justforexamplecom.sh

...which, for example will run a script to create a pfx certificate file and restart an Emby server :-)

NGINX

certbot renew --pre-hook "service nginx stop" --post-hook "service nginx start"

LIGHTTPD

certbot renew --pre-hook "service lighttpd stop" --post-hook "service lighttpd start"

https://certbot.eff.org/docs/using.html?highlight=hooks#renewing-certificates

Unbound Vulnerability Checker

https://checkhost.unboundtest.com/

unknown: remote error: tls: alert(112)

Lighttpd

NEW

You can use the pre-hook and post-hook options to renew a certificate...

/etc/letsencrypt/renewal-hooks/
|-- deploy
|-- post
|   `-- www.domain.org.uk-post.sh
`-- pre
    `-- www.domain.org.uk-pre.sh

# www.domain.org.uk-pre.sh
service lighttpd stop && 
exit;

#!/bin/bash
# www.domain.org.uk-post.sh
cd /etc/letsencrypt/live/www.domain.org.uk/ && 
cat privkey.pem cert.pem >ssl.pem && 
service lighttpd restart && 
exit;

certbot renew --cert-name www.domain.org.uk --pre-hook /etc/letsencrypt/renewal-hooks/pre/www.domain.org.uk-pre.sh --post-hook /etc/letsencrypt/renewal-hooks/post/www.domain.org.uk-post.sh

OLD

/etc/letsencrypt/renewal-hooks/
|-- deploy
|-- post
|   `-- post.sh
`-- pre
    `-- pre.sh

#!/bin/bash
# pre.sh
service lighttpd stop && 
exit;

#!/bin/bash
# post.sh
cd /etc/letsencrypt/live/www.domain.co.uk/ && 
cat privkey.pem cert.pem >ssl.pem && 
service lighttpd restart && 
exit;

certbot renew

Revoke and Delete Certificates

You must first revoke and then delete a certificate, which helps Certbot servers.

certbot revoke --cert-name example.com

The above command will ask you if you want to delete the certificate as well, but if you forget or make a mistake then you can run the command separately...

certbot delete --cert-name example.com

https://certbot.eff.org/docs/using.html?highlight=hooks#revoking-certificates

Change Registered Email Address

certbot register --email user@example.com --update-registration

TLS Renew NEW Method

certbot renew --preferred-challenges tls-alpn-01

LetsEncrypt with Bitnami AWS Lightsail

https://docs.bitnami.com/aws/how-to/generate-install-lets-encrypt-ssl/

Script

/opt/bitnami/letsencrypt/scripts/renew-certificate.sh

sudo /opt/bitnami/ctlscript.sh stop apache
sudo /opt/bitnami/letsencrypt/lego --tls --email="info@domain.co.uk" --domains="domain.co.uk" --domains="www.domain.co.uk" --path="/opt/bitnami/letsencrypt" renew --days 90 --preferred-chain="ISRG Root X1"
sudo /opt/bitnami/ctlscript.sh start apache
sudo service postfix restart
sudo service dovecot restart

Preferred Chain

For Letsencrypt.org Production server, there are 2 chains provided:

Name              Default
DST Root CA X3    Yes
ISRG Root X1      No

To use the option --preferred-chain="ISRG Root X1" ...

/opt/bitnami/letsencrypt/lego --tls --email="info@domain.co.uk" --domains="domain.co.uk" --domains="www.domain.co.uk" --path="/opt/bitnami/letsencrypt" renew --days 90 --preferred-chain="ISRG Root X1"
Certificate chain
0 s:CN = domain.co.uk
  i:C = US, O = Let's Encrypt, CN = R3
1 s:C = US, O = Let's Encrypt, CN = R3
  i:C = US, O = Internet Security Research Group, CN = ISRG Root X1

Let's Encrypt with AWS Route 53 DNS

Automated

You'll need the Certbot plugin for AWS Route 53 and the pip version of certbot.

Install and check all is working...

sudo -i
apt-get remove certbot
pip3 install --upgrade pip
pip3 install certbot certbot-dns-route53
ln -s /usr/local/bin/certbot /usr/bin/certbot
ldconfig
which certbot
certbot certificates

Create a new AWS User 'certbot' with this policy attached...

{
    "Version": "2012-10-17",
    "Id": "certbot-dns-route53 sample policy",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "route53:ListHostedZones",
                "route53:GetChange"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "route53:ChangeResourceRecordSets"
            ],
            "Resource": [
                "arn:aws:route53:::hostedzone/YOUR_ZONE_ID"
            ]
        }
    ]
}

Edit the AWS Credentials file with the new profile...

nano ~/.aws/credentials

[certbot]
aws_access_key_id = YOUR_ID
aws_secret_access_key = YOUR_KEY

Run the renew command with the profile environment variable on each of your domains and subdomains...

AWS_PROFILE=certbot certbot certonly --dns-route53 -d www.mydomain.com -d mydomain.com

...there will be a 30 second delay while certbot waits for the DNS Zone to update then removes the TXT records, so don't panic if it seems to have stalled :-)

Restart your web server and check the web site's padlock!

Also...

https://nandovieira.com/using-lets-encrypt-in-development-with-nginx-and-aws-route53

Manually

You can perform a manual verification - with the 'manual' plugin...

certbot -d sub.domain.com --manual --preferred-challenges dns certonly

Certbot will then provide you an instructions to manually update a TXT record for the domain in order to proceed with the validation.

Please deploy a DNS TXT record under the name
_acme-challenge.sub.domain.com with the following value:

667drNmQL3vX6bu8XXXXXX0wKNBlCny8yrjF1lSaUndc

Once this is deployed,
Press ENTER to continue
Once you have updated DNS record, press Enter, certbot will continue and if LetsEncrypt CA verifies the challenge, certificate is issued as normally.

You may also use a command with more options to minimize interactivity and answering certbot questions. Note that manual plugin does not yet support non-interactive mode.

NOTE: The renewal does not work with the manual plugin as it runs in non-interactive mode. More info at official Certbot documentation.

https://serverfault.com/questions/750902/how-to-use-lets-encrypt-dns-challenge-validation

https://certbot.eff.org/docs/using.html#dns-plugins

Documentation

https://certbot-dns-route53.readthedocs.io/en/stable/

https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html#best-practices-for-configuring-credentials

https://jloh.co/posts/certbot-route53-dns-validation/

LetsEncrypt with NGiNX

NEW

sudo -i
snap install core
snap refresh core
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot
certbot --nginx --email me@domain.co.uk --agree-tos --no-eff-email -d www.domain.co.uk -d domain.co.uk
cat /etc/nginx/sites-enabled/www.domain.co.uk
systemctl reload nginx

OLD

sudo -i
apt-get install python-certbot-nginx
certbot --nginx --email me@domain.co.uk --agree-tos --no-eff-email -d www.domain.co.uk -d domain.co.uk
cat /etc/nginx/sites-enabled/www.domain.co.uk
systemctl reload nginx

LetsEncrypt with IIS

sudo -i
openssl pkcs12 -export -out /tmp/certificate.pfx -inkey /etc/letsencrypt/live/domain.uk.com/privkey.pem -in /etc/letsencrypt/live/domain.uk.com/cert.pem -certfile /etc/letsencrypt/live/domain.uk.com/chain.pem

LetsEncrypt with Dovecot

http://wiki.indie-it.com/wiki/Dovecot#Let.27s_Encrypt_SSL_Certificate_and_Dovecot

LetsEncrypt with Postfix

smtpd_tls_cert_file = /etc/letsencrypt/live/mail.domain.co.uk/cert.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.domain.co.uk/privkey.pem
smtpd_tls_CAfile = /etc/letsencrypt/live/mail.domain.co.uk/chain.pem

LetsEncrypt with Webmin

sudo -i
cd /etc/letsencrypt/live/www.domain.uk.com
cat privkey.pem cert.pem > ssl.pem
nano /etc/webmin/miniserv.conf
certfile=/etc/letsencrypt/live/www.domain.uk.com/cert.pem
keyfile=/etc/letsencrypt/live/www.domain.uk.com/privkey.pem
extracas=/etc/letsencrypt/live/www.domain.uk.com/fullchain.pem
service webmin restart

LetsEncrypt with Lighttpd

NEW Method

The cert file names can now go on 3 separate lines (which are the 3 files from LE), so you don't need to create a cat file for 'ssl.pem' ...

$SERVER["socket"] == ":443" {
  ssl.engine = "enable"
  ssl.pemfile = "/etc/letsencrypt/live/www.domain.com/cert.pem"
  ssl.privkey = "/etc/letsencrypt/live/www.domain.com/privkey.pem"
  ssl.ca-file = "/etc/letsencrypt/live/www.domain.com/fullchain.pem"
  ssl.cipher-list = "ECDHE-RSA-AES256-SHA384:AES256-SHA256:HIGH:!MD5:!aNULL:!EDH:!AESGCM"
  ssl.honor-cipher-order = "enable"
  ssl.use-sslv2 = "disable"
  ssl.use-sslv3 = "disable"
  ssl.ec-curve = "secp384r1"
}

https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_SSL

Fix Error: Invalid response from

Let's Encrypt needs to be able to write and read from the directory .well-known/acme-challenge so make sure you create this directory on your web server root, change the permissions and edit the config file to ignore that folder for WordPress permalinks with PHP...

sudo -i
cd /var/www/domain.com/html/
mkdir -p .well-known/acme-challenge
chown -R www-data:www-data .well-known/
chmod -R 0775 .well-known/
nano /etc/lighttpd/domain.com.conf

...
url.rewrite-final = (
# Exclude directories
"^/(wp-admin|wp-includes|wp-content|gallery2|.well-known)/(.*)" => "$0",
# Exclude root php files
"^/(.*.php)" => "$0",
# Handle permalinks and feeds
"^/(.*)$" => "/index.php/$1"
)
...

service lighttpd restart
certbot renew

Initial Setup

sudo -i
git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt
cd /opt/letsencrypt
./letsencrypt-auto certonly --webroot -w /var/www/domain.uk.com/html/ -d domain.uk.com -d www.domain.uk.com
cd /etc/letsencrypt/live/www.domain.uk.com
cat privkey.pem cert.pem > ssl.pem
nano /etc/lighttpd/domain.uk.com.conf
$HTTP["host"] =~ "www\.domain\.uk\.com$" {
  $SERVER["socket"] == ":443" {
    ssl.engine = "enable"
    ssl.pemfile = "/etc/letsencrypt/live/domain.uk.com/ssl.pem"
    ssl.ca-file = "/etc/letsencrypt/live/domain.uk.com/fullchain.pem"
    ssl.cipher-list = "ECDHE-RSA-AES256-SHA384:AES256-SHA256:HIGH:!MD5:!aNULL:!EDH:!AESGCM"
    ssl.honor-cipher-order = "enable"
    ssl.use-compression = "disable"
    ssl.use-sslv2 = "disable"
    ssl.use-sslv3 = "disable"
    ssl.ec-curve = "secp384r1"
  }
server.document-root = "/var/www/domain.uk.com/html"
server.errorlog = "/var/www/domain.uk.com/logs/error.log"
accesslog.filename = "/var/www/domain.uk.com/logs/access.log"
}
service lighttpd reload

Automated Renewal

sudo -i
git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt
touch /etc/cron.weekly/letsencrypt
chmod +x /etc/cron.weekly/letsencrypt
nano /etc/cron.weekly/letsencrypt

# Automatically Renew Letsencrypt Certs
/opt/letsencrypt/letsencrypt-auto renew --webroot --webroot-path /var/www/domain.uk.com/html/
# Rebuild the cert
cd /etc/letsencrypt/live/domain.uk.com/
cat privkey.pem cert.pem > ssl.pem
# Reload lighttpd
/etc/init.d/lighttpd reload

Complete Example of Cron Weekly

/opt/letsencrypt/letsencrypt-auto renew --pre-hook "service apache2 stop" --post-hook "service apache2 start"

root@server1.domain.co.uk ~ $ (screen) /etc/cron.weekly/letsencrypt
Upgrading certbot-auto 0.15.0 to 0.16.0...
Replacing certbot-auto...
Creating virtual environment...
Installing Python packages...
Installation succeeded.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
-------------------------------------------------------------------------------
Processing /etc/letsencrypt/renewal/webmail.domain.co.uk.conf
-------------------------------------------------------------------------------
Cert is due for renewal, auto-renewing...
Running pre-hook command: service apache2 stop
Output from service:
 * Stopping web server apache2
Renewing an existing certificate
Performing the following challenges:
tls-sni-01 challenge for webmail.domain.co.uk
tls-sni-01 challenge for server1.domain.co.uk
Waiting for verification...
Cleaning up challenges
-------------------------------------------------------------------------------
new certificate deployed without reload, fullchain is
/etc/letsencrypt/live/webmail.domain.co.uk/fullchain.pem
-------------------------------------------------------------------------------
Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/webmail.domain.co.uk/fullchain.pem (success)
Running post-hook command: service apache2 start
Output from service:
 * Starting web server apache2

Thanks - https://freek.ws/2017/03/19/setting-up-lets-encrypt-with-lighttpd-and-automatic-certificate-renewal/

Thanks - https://nwgat.ninja/setting-up-letsencrypt-with-lighttpd/

Test Certificates

Root and Intermediate Certificates as TXT

Let's Encrypt Root Certificates

SMTP / TLS

openssl s_client -CAfile /etc/letsencrypt/live/mail.example.co.uk/fullchain.pem -connect localhost:25 -starttls smtp

IMAPS

openssl s_client -CAfile /etc/letsencrypt/live/mail.example.co.uk/fullchain.pem -connect localhost:993 -quiet

POPS

openssl s_client -CAfile /etc/letsencrypt/live/mail.example.co.uk/fullchain.pem -connect localhost:995 -quiet

CHECK EXPIRY DATE

echo | openssl s_client -servername www.shellhacks.com -connect www.shellhacks.com:443 2>/dev/null | openssl x509 -noout -dates