This tool is composed of two shell scripts used as a wrapper around Go-Acme's Lego and an automatic
certificate updater. You can easily configure where and how your LE certificates are pushed, easing the administration
of your HTTPS services.
Both scripts are configured either using command-line flags (call <script.sh> --help
to have more information), or an
environment file (.env
) which has an example located at .env.example
.
The renew_certs.sh
shell script is the wrapper around Lego and will take care of creating or renewing your HTTPS
certificates and then performing copy actions (using cp or scp for example) to where your certificates are needed.
This script supports working on multiple domains at once and will use the domain name as a selector to know where
to send the certificates.
To configure this script's behavior you will use the services.cfg
file and perform the action of your choice to copy
the generated files.
This script is intended to be used along with a cron entry to ensure that all certificates are renewed within their
90-days validity period.
Here is an example of a working services.cfg
:
# Available variables:
## $CERT_PATH: path to domain certificate
## $PRIV_KEY_PATH: path to domain private key
## $ISSUER_PATH: path to issuer certificate
## $CERT_DIR_PATH: path to all data generated for this domain
## $CURRENT_DIR: directory where the script is located
#
# Example
mydomain.xyz,scp,-i $CURRENT_DIR/ssh_identity/id_ed25519 $CERT_PATH $PRIV_KEY_PATH [email protected]:/opt/cert_manager/new_certificates
another.io,scp,-i $CURRENT_DIR/ssh_identity/id_ed25519 $CERT_PATH $PRIV_KEY_PATH [email protected]:/opt/cert_manager/new_certificates
The install_certificates.sh
shell script is used to install and restart services that need the updated certificate file
sent by the renew_certs.sh
script. The script will use the file actions.cfg
and pre-made "actions" located in the available-actions
directory.
Actions are a way for you to tell the installation script what you want it to do. It comes in two flavors: pre-made actions, essentially a small script that performs multiple tasks, and core actions, which are basic one-task functions.
They are available in the available-actions
directory, such as nginx.sh
, and are used for well-known services to
avoid you the hassle of doing it by yourself. To use them you first have to enable the selected one by creating a symlink from
the available-actions
directory to the enabled-actions
one. Then you have to reference the action in the actions.cfg
file -with the assorted arguments required if applicable.
Here is an example of what it would look like in said file:
# Actions are below this line
update_nginx
pct_push,114,${CERT_FILE},/tmp${CERT_FILE}
pct_exec,114,ls -lah /root
Here is a non-exhaustive list of existing pre-made actions:
- nginx.sh: used to update certificates for NginX,
- pct_exec.sh: used to execute commands for Proxmox containers,
- pct_push.sh: used to push files to Proxmox containers,
- traefik.sh: used to update certificates for Traefik,
- cleanup.sh: called after all other actions, used to remove the certificates once they are successfully installed everywhere else.
Core actions are single-task actions performing a basic task like copying a file, changing the permissions of a file
or executing a shell action. They are useful if your setup does not match the one expected by a pre-made action or if
there is no pre-made action available for your specific need. They are also the functions called by pre-made actions.
If you want to see a list of what you can call, just take a look at the functions in common.sh
.
Here is a non-exhaustive list of these actions and what they do:
- quiet_print: prints a message if
-q
flag is NOT specified, - verbose_print: prints a message if
-v
flag IS specified, - assert_defined: asserts a variable is not empty,
- assert_executable: asserts a file name is an executable file,
- copy_files: copies a file to a specific destination,
- do_chown: performs a chown on a file,
- do_chmod: performs a chmod on a file.
To use a core action you only have to reference it in actions.cfg
, no need to enable anything in enabled-actions
.
The file actions.cfg
is used to execute a series of actions to update all services. You have access to
several pre-made actions, but you can also create your own. Either create your own shell script in actions-available
and
then enable it, or use available core actions to create your own scenario. You have access to several variables:
- DRY_RUN (0 or 1): set to 1 if no actions should be performed,
- EMAIL_CONTACT (string): used by Let's Encrypt,
- NO_OUTPUT (0 or 1): set to 1 if no output is expected,
- VERBOSE (0 or 1): set to 1 if extra information should be printed,
- ENV_FILE (string): path to the loaded
.env
file, - CERT_FILE (string): full path to the certificate file,
- KEY_FILE (string): full path to the key file,
- DEST_CERT_FILENAME (string): filename of the cert file,
- DEST_KEY_FILENAME (string): filename of the key file.
Additionally, all variables exported in your .env
file will be available.
The expected setup is one server used to query Let's Encrypt using the DNS challenge (only this challenge is supported) and several "clients" to which the generated certificates will be pushed. In order to use scp, a dedicated account is created on every client machine with an SSH authorization mechanism based on an identity key. A root account could be used as well but offers less security, so sudo will have to be installed too. Currently, all actions have a sudoers configuration example. Finally, a cron should be installed on the generating machine to be run every few weeks to renew certificates automatically, and another cron should be installed on client machines to check if new certificates are available for installation.
Requirements:
- Lego,
- bash 4+,
- git,
Optional, but recommended:
- sudo, if the machine generating the certificates needs an update too, and the root account is not used.
To install this project on your machine that will query Let's Encrypt you just have to clone this repository.
- bash 4+,
- git
Optional, but recommended:
- sudo, if the root account is not used.
To install this project on your clients you just have to clone the repository. It is advised to use a dedicated user for this process with a sudoers file correctly configured to allow said account to perform the certificates' installation steps.
Copy the file .env.example
to .env
and modify it according to your needs.
The only required variables are the DNS challenge type (see lego dnshelp
), and
an API KEY whose name depends on the DNS challenge.
Copy the file services.example.cfg
to services.cfg
and modify it so that the generated certificate files will be
automatically copied to the servers needing them.
Copy the file .env.example
to .env
and modify it according to your needs.
The only required variable in this file is USE_SUDO=1 if you use sudo.
Clone this repository on each server needing the certificates and copy actions.example.cfg
to actions.cfg
.
Modify actions.cfg
to perform all the steps required to update your services with the newly retrieved certificates.
You will have to enable each actions you use in your actions.cfg
with:
ln /path/to/available-actions/action.sh /path/to/enabled-actions`
WARNING: Renewing an SSL certificate IS NOT THE SAME as using the command action
renew
. If this script handles a domain it has never handled before, you MUST use therun
action.
If it's the first time you ask for a certificate for your domain WITH THIS SCRIPT, you can use:
./renew_certs.sh run <your_domain> [ <another_domain> ... ]
If your .lego directory is already populated:
./renew_certs.sh renew <your_domain> [ <another_domain> ... ]
If you want to create a wildcard certificate, this script uses the V2 Let's Encrypt server, so you can do it this way:
## will be equivalent to asking certificates for domain.com AND \*.domain.com
./renew_certs.sh run \*.domain.com
Once the generator script has finished, the certificates can be found in the .lego
directory.
The script also works as a hook that is executed every time a certificate is generated.
Take a look at services.example.cfg
, copy it to services.cfg
, modify it as needed, and the actions will be
executed on run
/renew
actions.
Suppose the new certificates are located in a directory called "new_certificates".
If only one domain is handled, you can simply do:
# directory "new_certificates" contains new certificates to install.
./install_certificates.sh ./new_certificates
If you handle multiple domains, you can use a discriminator:
./install_certificates.sh -s your_domain.com ./new_certificates
If you want to set up a cron task to automatically check for new certificates and install them you can use the --cron-mode
which does not raise errors if no certificates is found.
This mode is particularly useful, as its name suggests, when used in a cron task, to avoid triggering errors.
Here's an example of a cron task using said mode:
# m h dom mon dow command
0 5,17 * * * /opt/cert_manager/legorenewer/install_certificates.sh --cron-mode /opt/cert_manager/new_certificates/ >> /var/log/cert_renewer.log 2>&1