Skip to content

Instantly share code, notes, and snippets.

@bmatthewshea
Last active April 18, 2024 16:40
Show Gist options
  • Star 34 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save bmatthewshea/f6a66ddb2e52ccdbc905aed73d9ca59c to your computer and use it in GitHub Desktop.
Save bmatthewshea/f6a66ddb2e52ccdbc905aed73d9ca59c to your computer and use it in GitHub Desktop.
Debian/Ubuntu - CERTBOT without SNAP/SNAPD

CERTBOT - Install using Python PIP

Install Certbot using Python PIP (Package Installer for Python) - without using SNAP, APT or SYSTEMD. (Debian/Ubuntu)


This guide will help you install LetsEncrypt / Certbot using venv PIP under Debian/Ubuntu.

  • This guide has been tested up to Debian 12 / Bookworm.

  • You should already be somewhat familiar with LetsEncrypt, Certbot and any plugin you might need.

  • A DNS plugin (AWS Route53) is used here, but this guide is about the install method- not plugins, or validation methods.

  • This pip Python install method should also work on other Linux distributions that support python3, venv, and pip.

In my opinion, this is the best install method (as of now) as the APT version is always behind and I refuse to use SNAPD.

Brady Shea / bmatthewshea 28SEP2021
Script original location: https://gist.github.com/bmatthewshea/f6a66ddb2e52ccdbc905aed73d9ca59c

Last Updated: 24FEB2024:

  • Updated 'upgrading' to include all components involved.
  • Outline cleanup and correct URLs/anchors
  • Other general cleanup/typos/etc

Update 31DEC2023:

  • Updated to use approved/eff.org pip install instructions. (See references below)
  • These steps now use python3 -m venv instead of system/repo/apt pip.
  • Change is due to pyopenssl compatibility problems (the apt/repo version). (See comments)
  • Tested/working on Ubuntu 20, 22 and Debian 10, 11, 12.

1. Cleanup, Install Python PIP, PIP dependencies and Certbot

You should only run a single installed version of certbot.
You should not mix installation methods!
Optionally, some cleanup should be done just in case it's already installed/orphaned.
WARNING: If you have any certificates, you will need to recreate them after this!

Cleanup

Ignore any 'not found' errors:

sudo apt remove certbot* --purge # Purge any old certbots via apt.
sudo apt-add-repository --remove ppa:certbot/certbot # Remove certbot repo.
sudo snap remove certbot
sudo -H pip uninstall certbot; sudo -H pip3 uninstall certbot
pip uninstall certbot; pip3 uninstall certbot
sudo rm /usr/bin/certbot
sudo rm /usr/local/bin/certbot
rm ~/.local/usr/bin/certbot
rm ~/.local/bin/certbot
# You do not always need to delete the cert area, but it's usually best to start fresh:
sudo rm -rf /etc/letsencrypt
# Deactivate and remove any Certbot virtual Python environments you had running/setup.
# Example:
# `deactivate; sudo rm -rf /opt/certbot`
sudo apt update && sudo apt autoremove  # Re-update and remove any orphaned packages.

Install

Install Python 3 Pip under a virtual environment (we use /opt/certbot here) and upgrade it:

sudo apt update && sudo apt install python3 python3-venv libaugeas0
sudo python3 -m venv /opt/certbot/
sudo /opt/certbot/bin/pip install --upgrade pip

Install Certbot using venv Python pip to the virtual area and then symlink it to our path:

sudo /opt/certbot/bin/pip install certbot certbot
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot

Before going any further, it's a good idea to make sure it is now installed and found in path:
certbot --version
Should give something like:
certbot x.x.x
Then try:
sudo certbot certificates

  • At this point you shouldn't have any unless you chose to keep the /etc/letsencrypt area.

  • The first run of "sudo certbot certificates" should also regenerate the /etc/letsencrypt area if you wiped it.

2a. (Optional) Install needed plugins

Optional - If you use AWS-Route53 DNS you'll need this. Or, pick your own plugin (if needed):

sudo /opt/certbot/bin/pip install certbot-dns-route53

For errors such as:

ERROR: zope-component 5.0.1 has requirement zope.interface>=5.3.0a1, but you'll have zope-interface 4.7.1 which is incompatible.

Upgrade the individual python package mentioned in error:

sudo /opt/certbot/bin/pip install zope.interface --upgrade

You should see: "Successfully installed zope.interface-5.4.0" depending on name-version.
If errors were encountered during plugin installation, upgrading (or reinstalling) certbot (sudo /opt/certbot/bin/pip install --upgrade certbot) should also give 0 errors now. Re-check it is found and functions again per above (Step 1).
If so, continue on..

2b. (Optional) Create an AWS-IAM credentials file

Again, I include this here for completeness only.
This guide is really about installing certbot using pip. If you do not use Route53, skip this.

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

sudo mkdir /root/.aws && sudo chmod 700 /root/.aws
sudo touch /root/.aws/credentials && sudo chmod 600 /root/.aws/credentials
sudo nano /root/.aws/credentials # (Add your own IAM creds in this file and save.)

3. Dry Run and Execution

Always do a "dry run" first - especially on a new install:

sudo certbot certonly --dry-run --agree-tos --dns-route53 --cert-name example -d example.net -d *.example.net

You should see: "The dry run was successful.". If so, execute same line w/o dry-run:

sudo certbot certonly --agree-tos --dns-route53 --cert-name example -d example.net -d *.example.net

If command completes successfully, you now have a functioning and up-to-date certbot installed via pip.

4. (Optional, but recommended) Setup automatic renewal

-The Cronjob-

Execute this command for a renewal cronjob. Update venv python location if needed:

echo "0 0,12 * * * root /opt/certbot/bin/python -c 'import random; import time; time.sleep(random.random() * 3600)' && sudo /usr/bin/certbot renew -q" | sudo tee /etc/cron.d/certbot > /dev/null

Please note that the official guide has this command tee'ed/appended to end of /etc/crontab.
I prefer to use /etc/cron.d/certbot instead. I also recreate a new file (no tee flags as opposed to using -a append flag).

5. (Optional, but recommended) Setup renewal "hooks"

-Renewal Hooks-

"Global" hook methods (operates on all renewals regardless of certificate name, or type):

  • You can opt to add it to cli.ini
    • Example: post-hook /full/path/to/script/or/command
  • Or, directly on command line
    • Example: certbot renew --pre-hook /script/or/command --post-hook /script/or/command ...
  • Or, you can add a shell script to /etc/letsencrypt/renewal-hooks in the /post or /pre areas.

If you have many LE certificates and all of them need the same EXACT renewal parameters, you will probably want to use ONE of the "global" methods above such as the cli.ini file. You will add hook statements in same manner as the examples below, with the exception of the /renewal-hooks/ area. If you use this area, you create a shell script that stops, or restarts services (which amount to the same thing as the hook statements below).

For more granularity we are doing it a bit differently here:

We will edit the "renewal configuation" file for just one certificate.

Note: the '(certname)' is what you set for --cert-name (when you created it above):

sudo nano /etc/letsencrypt/renewal/(certname).conf
  • If you need to execute something after renewal runs, you would add a post_hook =. Once a renewal happens, you will need to reload or restart any daemons/services which depend on this renewed certificate. (Examples would be a webserver, email services, etc.)

  • If you need to execute something before renew runs, you would add a pre_hook =. An example of when this is needed is when using standalone as the Certbot verification type. You will need to stop the system webserver before the renewal. You would issue a 'stop' on the pre_hook and a 'start' on the post_hook to Apache or Nginx (etc), so they aren't blocking the web port Certbot uses for verfication.

Under "[renewalparams]" add a line similar to one of the examples.

Example #1 (DNS authentication used. We only need to restart services to pickup new certificate.):

post_hook = systemctl restart apache2

Example #2 (DNS authentication used. We only need to restart services to pickup new certificate.):

post_hook = systemctl restart nginx postfix dovecot

Example #3 (Web authentication used. Needs web port open. Stop/(RE)Start web server.):

pre_hook  = systemctl stop nginx
post_hook = systemctl restart nginx postfix

Example #4 (Uses DNS authentication. Web server stop unneeded. Email only server with multiple ssl virual domains.):

post_hook = /usr/sbin/postmap -F hash:/etc/postfix/vmail_ssl.map; systemctl restart postfix dovecot

Please note that you can also use a shell script instead of actual directive/commands.

5. Expanding (or removing) domains on the certificate

If you need to add (or delete!) domain(s) at a later date, you can use the --expand parameter to update it. Make sure you include ALL the original domains as well, or they will get removed (you will be prompted to continue before anything drastic happens).

sudo certbot certonly --expand --dns-route53 --cert-name example \
-d example.net -d *.example.net -d example.com -d *.example.com -d example.org -d *.example.org

6. Upgrading

To upgrade everything (and all dependencies), run these. You should probably do them seperately (do PIP first) and if you want to really stay up-to-date you should probably do this once a month - cronjob?:

sudo /opt/certbot/bin/pip install --upgrade pip
sudo /opt/certbot/bin/pip install --upgrade certbot
# And any plugin used:    
sudo /opt/certbot/bin/pip install --upgrade certbot-dns-route53

References

https://letsencrypt.org/docs/
https://pypi.org/project/certbot/
https://certbot.eff.org/instructions?ws=other&os=pip
https://eff-certbot.readthedocs.io/en/stable
https://eff-certbot.readthedocs.io/en/stable/packaging.html
https://eff-certbot.readthedocs.io/en/stable/using.html#renewing-certificates
https://eff-certbot.readthedocs.io/en/stable/using.html#pre-and-post-validation-hooks

Top

Copy link

ghost commented Jun 28, 2022

Works great (I'm using Debian), thanks!

@bmatthewshea
Copy link
Author

bmatthewshea commented Dec 31, 2023

Entire guide has been updated to use https://certbot.eff.org/instructions?ws=other&os=pip method.

There is a conflict with the pyopenssl package as installed by Deb/Ubuntu repo/apt. So, I am avoiding the "system python/pip" / "repo version", now.

(Certbot pip depends on cryptography and cryptography depends on pyOpenSSL.)

This problem was brought to my attention by user "tanius" at the "AskUbuntu" stack site (Thanks, Tanius):

https://askubuntu.com/questions/1278936/install-certbot-on-ubuntu-20-04/1366594?noredirect=1#comment2618268_1366594

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment