initial commit
This commit is contained in:
commit
e903be8aed
4
README.md
Normal file
4
README.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# letsencrypt-tools
|
||||||
|
|
||||||
|
etc/letsencrypt/cli.ini
|
||||||
|
email = hostmaster@example.com
|
90
bin/letsencrypt-certonly.sh
Normal file
90
bin/letsencrypt-certonly.sh
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# must be root
|
||||||
|
if [ "$USER" != "root" ]; then
|
||||||
|
exec sudo $0
|
||||||
|
fi
|
||||||
|
|
||||||
|
help()
|
||||||
|
{
|
||||||
|
thisfilename=$(basename -- "$0")
|
||||||
|
echo "$thisfilename"
|
||||||
|
echo "Create a Let's Encrypt certificate."
|
||||||
|
echo ""
|
||||||
|
echo "Usage: $thisfilename domain [OPTIONS]"
|
||||||
|
echo ""
|
||||||
|
echo " -h Print this help."
|
||||||
|
echo " -n Dry Run - don't create cert, just echo command to run."
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
# check for and set domain
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
if [ $1 == "-h" ]; then
|
||||||
|
help
|
||||||
|
else
|
||||||
|
domain=$1
|
||||||
|
shift
|
||||||
|
# basic but good enough domain name regex validation
|
||||||
|
if [[ ! $domain =~ ^(([a-zA-Z](-?[a-zA-Z0-9])*)\.)+[a-zA-Z]{2,}$ ]] ; then
|
||||||
|
echo "ERROR: Invalid domain name: $1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
help
|
||||||
|
fi
|
||||||
|
|
||||||
|
# set any options that were passed
|
||||||
|
while getopts "hn" opt; do
|
||||||
|
case "${opt}" in
|
||||||
|
h )
|
||||||
|
help
|
||||||
|
exit;;
|
||||||
|
n )
|
||||||
|
dryrun=true
|
||||||
|
;;
|
||||||
|
\? )
|
||||||
|
echo "Invalid option: $OPTARG" 1>&2
|
||||||
|
exit;;
|
||||||
|
: )
|
||||||
|
echo "Invalid option: $OPTARG requires an argument" 1>&2
|
||||||
|
exit;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# set vars
|
||||||
|
command="certbot certonly --cert-name $domain"
|
||||||
|
dnscheck=false
|
||||||
|
ips=(`ip -4 -o addr show | awk '{ print $4 }' | cut -d / -f 1`)
|
||||||
|
|
||||||
|
# check dns for domain
|
||||||
|
dns=`host -t A $domain|grep 'has address'|awk '{ print $4 }'`
|
||||||
|
if [[ " ${ips[@]} " =~ " ${dns} " ]]; then
|
||||||
|
command="$command -d $domain"
|
||||||
|
dnscheck=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check dns for www subdomain
|
||||||
|
dns=`host -t A www.$domain|grep 'has address'|awk '{ print $4 }'`
|
||||||
|
if [[ " ${ips[@]} " =~ " ${dns} " ]]; then
|
||||||
|
command="$command -d www.$domain"
|
||||||
|
dnscheck=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# copy above www subdomain section and modify as desired to
|
||||||
|
# automatically check for and add additional subdomains to cert
|
||||||
|
|
||||||
|
# check if any of the dns lookups passed
|
||||||
|
if [[ "$dnscheck" = "false" ]]; then
|
||||||
|
echo "All dns checks failed, can't create cert."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# run (or display) command
|
||||||
|
if [[ "$dryrun" = "true" ]]; then
|
||||||
|
echo "Run this command to create cert:"
|
||||||
|
echo "$command"
|
||||||
|
else
|
||||||
|
$command
|
||||||
|
fi
|
80
bin/letsencrypt-del.sh
Normal file
80
bin/letsencrypt-del.sh
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
help()
|
||||||
|
{
|
||||||
|
thisfilename=$(basename -- "$0")
|
||||||
|
echo "Delete an existing Let's Encrypt certificate."
|
||||||
|
echo ""
|
||||||
|
echo "Usage: $thisfilename cert-name(domain) [OPTIONS]"
|
||||||
|
echo ""
|
||||||
|
echo " -h Print this help."
|
||||||
|
echo " -r Revoke cert from Let's Encrypt before deleting files."
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
# check for and set domain
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
if [ $1 == "-h" ]; then
|
||||||
|
help
|
||||||
|
else
|
||||||
|
domain=$1
|
||||||
|
shift
|
||||||
|
# basic but good enough domain name regex validation
|
||||||
|
if [[ ! $domain =~ ^(([a-zA-Z](-?[a-zA-Z0-9])*)\.)+[a-zA-Z]{2,}$ ]] ; then
|
||||||
|
echo "ERROR: Invalid domain name: $1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
help
|
||||||
|
fi
|
||||||
|
|
||||||
|
# set any options that were passed
|
||||||
|
while getopts "hr" opt; do
|
||||||
|
case "${opt}" in
|
||||||
|
h )
|
||||||
|
help
|
||||||
|
exit;;
|
||||||
|
r )
|
||||||
|
revoke=true
|
||||||
|
;;
|
||||||
|
\? )
|
||||||
|
echo "Invalid option: $OPTARG" 1>&2
|
||||||
|
exit;;
|
||||||
|
: )
|
||||||
|
echo "Invalid option: $OPTARG requires an argument" 1>&2
|
||||||
|
exit;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
# start by checking if the renewal config exits
|
||||||
|
if test -f "/etc/letsencrypt/renewal/$domain.conf"; then
|
||||||
|
|
||||||
|
if [[ "$revoke" = "true" ]]; then
|
||||||
|
certbot revoke --cert-path /etc/letsencrypt/live/$domain/fullchain.pem
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -f "/etc/letsencrypt/renewal/$domain.conf"; then
|
||||||
|
rm "/etc/letsencrypt/renewal/$domain.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -d "/etc/letsencrypt/live/$domain"; then
|
||||||
|
rm -r "/etc/letsencrypt/live/$domain"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -d "/etc/letsencrypt/archive/$domain"; then
|
||||||
|
rm -r "/etc/letsencrypt/archive/$domain"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -f "/etc/ssl/letsencrypt/$domain.pem"; then
|
||||||
|
rm "/etc/ssl/letsencrypt/$domain.pem";
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -h "/etc/ssl/letsencrypt/mail.$domain.pem"; then
|
||||||
|
rm "/etc/ssl/letsencrypt/mail.$domain.pem";
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "Did not find cert for $domain."
|
||||||
|
fi
|
4
etc/apache2/conf-available/certbot.conf
Normal file
4
etc/apache2/conf-available/certbot.conf
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# ACME (Automatic Certificate Management Environment)
|
||||||
|
<Location "/.well-known/acme-challenge/">
|
||||||
|
ProxyPass "http://127.0.0.1:18080/.well-known/acme-challenge/"
|
||||||
|
</Location>
|
11
etc/letsencrypt/cli.ini
Normal file
11
etc/letsencrypt/cli.ini
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# Because we are using logrotate for greater flexibility, disable the
|
||||||
|
# internal certbot logrotation.
|
||||||
|
max-log-backups = 0
|
||||||
|
email = hostmaster@example.com
|
||||||
|
agree-tos = True
|
||||||
|
allow-subset-of-names = True
|
||||||
|
expand = True
|
||||||
|
keep-until-expiring = True
|
||||||
|
non-interactive = True
|
||||||
|
standalone = True
|
||||||
|
http-01-port=18080
|
33
etc/letsencrypt/renewal-hooks/deploy/cp-to-etc-ssl.sh
Normal file
33
etc/letsencrypt/renewal-hooks/deploy/cp-to-etc-ssl.sh
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# script is run once per domain after successful renewal with these vars available:
|
||||||
|
# $RENEWED_LINEAGE=/etc/letsencrypt/live/example.com
|
||||||
|
# $RENEWED_DOMAINS="example.com www.example.com"
|
||||||
|
|
||||||
|
# makes sure vars were passed and LE cert exits
|
||||||
|
if [ ! -n "$RENEWED_LINEAGE" ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$RENEWED_LINEAGE/fullchain.pem" ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "/etc/ssl/letsencrypt" ]; then
|
||||||
|
install --owner=root --group=ssl-cert --mode=750 --directory /etc/ssl/letsencrypt
|
||||||
|
fi
|
||||||
|
|
||||||
|
DOMAIN=`basename $RENEWED_LINEAGE`
|
||||||
|
PEM="/etc/ssl/letsencrypt/$DOMAIN.pem"
|
||||||
|
|
||||||
|
# If the file doesn't already exist first create empty file with correct ownership and
|
||||||
|
# permissions. Thus the copied cert is *never* world readable, not even for an instant.
|
||||||
|
if [ ! -f "$PEM" ]; then
|
||||||
|
install --owner=root --group=ssl-cert --mode=640 /dev/null $PEM
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat $RENEWED_LINEAGE/fullchain.pem > $PEM
|
||||||
|
cat $RENEWED_LINEAGE/privkey.pem >> $PEM
|
||||||
|
# set perms & ownership again just for good measure, should be redundant
|
||||||
|
chmod 640 $PEM
|
||||||
|
chown root:ssl-cert $PEM
|
75
etc/letsencrypt/renewal-hooks/post/sync-certs-to-etc-ssl.sh
Normal file
75
etc/letsencrypt/renewal-hooks/post/sync-certs-to-etc-ssl.sh
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# sync-certs-to-etc-ssl.sh
|
||||||
|
#
|
||||||
|
# Takes all Let's Encrypt certs & keys and concats them in
|
||||||
|
# to pem files for use by apache, dovecot, exim, haproxy, etc.
|
||||||
|
#
|
||||||
|
# Install this script in to /etc/letsencrypt/renewal-hooks/post/
|
||||||
|
# to have it run automatically after attempting to obtain/renew certificates.
|
||||||
|
#
|
||||||
|
# Alternatively you can put the script in a different location and then
|
||||||
|
# run sync-certs-to-etc-ssl.sh manually after creating or renewing certs,
|
||||||
|
# or specificy the path to the script with the --post-hook cerbot command option
|
||||||
|
# to have it automatically run when attempting to obtain/renew certificates.
|
||||||
|
|
||||||
|
# make dir if it doesn't already exist
|
||||||
|
if [[ ! -e /etc/ssl/letsencrypt/ ]]; then
|
||||||
|
install --owner=root --group=ssl-cert --mode=750 --directory /etc/ssl/letsencrypt
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check that Let's Encrpyt archive dir exists before proceeding
|
||||||
|
if [ ! -d "/etc/letsencrypt/archive" ]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get list of Let's Encrpyt certs
|
||||||
|
# Check the "archive" dir instead of "live" as "live"
|
||||||
|
# has a README file that we don't want in our array.
|
||||||
|
cd /etc/letsencrypt/archive/
|
||||||
|
lecerts=(*)
|
||||||
|
# get list of certs in the SSL dir
|
||||||
|
cd /etc/ssl/letsencrypt/
|
||||||
|
sslcerts=(*)
|
||||||
|
|
||||||
|
# First cycle thru /etc/ssl/letsencrypt/ and remove any pem
|
||||||
|
# files that don't have a cert in /etc/ssl/letsencrypt/
|
||||||
|
# (removes certs that have been deleted from letsencrypt).
|
||||||
|
for sslcert in "${!sslcerts[@]}"
|
||||||
|
do
|
||||||
|
# set cert variable
|
||||||
|
cert=${sslcerts[$sslcert]}
|
||||||
|
# remove .pem from end of $cert
|
||||||
|
cert=$(basename $cert .pem)
|
||||||
|
if [[ ! " ${lecerts[@]} " =~ " $cert " ]]; then
|
||||||
|
rm /etc/ssl/letsencrypt/${sslcerts[$sslcert]}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# add / update pem files in /etc/ssl/letsencrypt/
|
||||||
|
for lecert in "${!lecerts[@]}"
|
||||||
|
do
|
||||||
|
# set cert variable
|
||||||
|
cert=${lecerts[$lecert]}
|
||||||
|
if [ -f "/etc/ssl/letsencrypt/$cert.pem" ]; then
|
||||||
|
# /etc/ssl/letsencrypt/ pem file already exists
|
||||||
|
# get modified times and only upate if newer
|
||||||
|
LECERTTIME=`date +%s -r /etc/letsencrypt/live/$cert/fullchain.pem`
|
||||||
|
SSLCERTTIME=`date +%s -r /etc/ssl/letsencrypt/$cert.pem`
|
||||||
|
if [[ $LECERTTIME -gt $SSLCERTTIME ]]; then
|
||||||
|
# make sure perms are correct, should be redundant
|
||||||
|
chmod 640 /etc/ssl/letsencrypt/$cert.pem
|
||||||
|
chown root:ssl-cert /etc/ssl/letsencrypt/$cert.pem
|
||||||
|
# replace existing cert with new data
|
||||||
|
cat /etc/letsencrypt/live/$cert/fullchain.pem > /etc/ssl/letsencrypt/$cert.pem
|
||||||
|
cat /etc/letsencrypt/live/$cert/privkey.pem >> /etc/ssl/letsencrypt/$cert.pem
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# /etc/ssl/letsencrypt/ pem file does not exists. First create
|
||||||
|
# empty file with correct ownership and permissions. Thus the
|
||||||
|
# copied cert is *never* world readable, not even for an instant.
|
||||||
|
install --owner=root --group=ssl-cert --mode=640 /dev/null /etc/ssl/letsencrypt/$cert.pem
|
||||||
|
cat /etc/letsencrypt/live/$cert/fullchain.pem > /etc/ssl/letsencrypt/$cert.pem
|
||||||
|
cat /etc/letsencrypt/live/$cert/privkey.pem >> /etc/ssl/letsencrypt/$cert.pem
|
||||||
|
fi
|
||||||
|
done
|
Loading…
Reference in New Issue
Block a user