-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add renewal support (major code organization refactoring)
- Loading branch information
Showing
9 changed files
with
224 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
CERTBOT_EMAIL=${CERTBOT_EMAIL-hostmaster@example.com} | ||
|
||
LE_DIR="/etc/letsencrypt" | ||
WEBROOT="/tmp/webroot" | ||
ACME_PATH=".well-known/acme-challenge" | ||
LOCK_FILE="/tmp/certbot.lck" | ||
|
||
mkdir -p "$WEBROOT/$ACME_PATH" "$LE_DIR/failed" | ||
echo "ok" > "$WEBROOT/$ACME_PATH/test.txt" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,113 +1,27 @@ | ||
#!/usr/bin/env bash | ||
|
||
LOOP_SLEEP=${LOOP_SLEEP-60s} | ||
CERTBOT_EMAIL=${CERTBOT_EMAIL-hostmaster@example.com} | ||
|
||
LE_DIR=/etc/letsencrypt | ||
TRAEFIK_EXPORT=${LE_DIR}/traefik.yml | ||
WEBROOT=/tmp/webroot | ||
source ./config.sh | ||
source ./logger.sh | ||
|
||
mkdir -p $WEBROOT/.well-known/acme-challenge $LE_DIR/failed | ||
log_info "Using email: $CERTBOT_EMAIL" | ||
log_info "Initial list of domains from certbot.domain labels ..." | ||
./domains.sh | ||
|
||
function get_domains() { | ||
local sock=/var/run/docker.sock | ||
local url=http://v1.45/services | ||
LAST_DATE=x$(date +"%Y-%m-%d") | ||
|
||
curl -s --unix-socket $sock $url \ | ||
| jq -r '.[] | select(.Spec.Labels["com.docker.stack.namespace"] != null) | .Spec.Name' \ | ||
| xargs -I {} sh -c "curl -s --unix-socket $sock $url/{} | jq -r '.Spec.Labels[\"certbot.domain\"] | select(.)'" \ | ||
| grep \. | sed 's/,/\n/g' | ||
} | ||
|
||
function export_certificates() { | ||
FILE=$TRAEFIK_EXPORT | ||
( | ||
printf "tls:\n options:\n default:\n minVersion: VersionTLS12\n certificates:\n" | ||
while read DOMAIN; do | ||
printf " # CERT FILE $DOMAIN\n" | ||
printf " - certFile: |-\n" | ||
sed -e 's/^/ /' $DOMAIN/fullchain.pem | ||
printf " keyFile: |-\n" | ||
sed -e 's/^/ /' $DOMAIN/privkey.pem | ||
done < <(find $LE_DIR/live/ -maxdepth 1 -mindepth 1 -type d -print) | ||
) > ${FILE}.new | ||
mv ${FILE}.new $FILE | ||
} | ||
|
||
function run_certbot() { | ||
SERVER_PID="" | ||
EXPORT=0 | ||
while read DOMAIN; do | ||
if [ -d $LE_DIR/live/$DOMAIN ]; then | ||
continue | ||
fi | ||
if [ -f $LE_DIR/failed/$DOMAIN ]; then | ||
echo "-W|$DOMAIN|Skipping domain marked as failed ..." >&2 | ||
continue | ||
fi | ||
|
||
if [ -z "$SERVER_PID" ]; then | ||
echo "-I|Starting http server ..." >&2 | ||
python -m http.server 80 --directory $WEBROOT & | ||
SERVER_PID=$! | ||
sleep 5 | ||
echo "-I|Done." >&2 | ||
fi | ||
|
||
FILE=.well-known/acme-challenge/check-${DOMAIN}-$(date +%s) | ||
TEST_URL="http://$DOMAIN/$FILE" | ||
echo "-I|$DOMAIN|Test challenge accessibility $TEST_URL ..." >&2 | ||
log_info "Entering loop with $LOOP_SLEEP sleep ..." | ||
while true; do | ||
sleep $LOOP_SLEEP | ||
|
||
echo "certbot" > $WEBROOT/$FILE | ||
curl --silent -v --max-time 5 $TEST_URL > /tmp/result | ||
ERR=$? | ||
rm -f $WEBROOT/$FILE | ||
if [ $ERR -ne 0 -o "$(cat /tmp/result)" != "certbot" ]; then | ||
echo "-E|$DOMAIN|Domain challenge failed $TEST_URL" >&2 | ||
continue | ||
fi | ||
NEW_DATE=$(date +"%Y-%m-%d") | ||
|
||
echo "-I|$DOMAIN|Domain challenge ok, run certbot ..." | ||
certbot certonly \ | ||
--webroot -w $WEBROOT \ | ||
--non-interactive \ | ||
--agree-tos \ | ||
--no-eff-email \ | ||
--keep-until-expiring \ | ||
-m $CERTBOT_EMAIL \ | ||
--cert-name $DOMAIN \ | ||
-d $DOMAIN > $LE_DIR/failed/$DOMAIN | ||
if [ $? -eq 0 ]; then | ||
echo "-I|$DOMAIN|Cerbot ok" >&2 | ||
rm -f $LE_DIR/failed/$DOMAIN | ||
EXPORT=1 | ||
if [[ $LAST_DATE != $NEW_DATE ]]; then | ||
LAST_DATE=$NEW_DATE | ||
log_info "New date detected renewing ..." | ||
./renew.sh | ||
else | ||
echo "-I|$DOMAIN|Cerbot failed." >&2 | ||
./issue.sh | ||
fi | ||
|
||
done < <(get_domains) | ||
|
||
if [ -n "$SERVER_PID" ]; then | ||
echo "-I|Killing http server ..." >&2 | ||
kill $SERVER_PID | ||
sleep 5 | ||
echo "-I|Done." >&2 | ||
fi | ||
|
||
if [ $EXPORT = 1 ]; then | ||
echo "-I|Exporting certificates for traefik ..." >&2 | ||
export_certificates | ||
echo "-I|Done." >&2 | ||
fi | ||
} | ||
|
||
|
||
echo "-I|Using email: $CERTBOT_EMAIL" | ||
echo "-I|Initial list of domains from certbot.domain labels ..." | ||
get_domains | ||
|
||
echo "-I|Entering loop with $LOOP_SLEEP sleep ..." | ||
while true; do | ||
run_certbot | ||
sleep $LOOP_SLEEP | ||
done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#!/usr/bin/env bash | ||
|
||
SOCK=/var/run/docker.sock | ||
URL=http://v1.45/services | ||
|
||
curl -s --unix-socket $SOCK $URL \ | ||
| jq -r '.[] | select(.Spec.Labels["com.docker.stack.namespace"] != null) | .Spec.Name' \ | ||
| xargs -I {} sh -c "curl -s --unix-socket $SOCK $URL/{} | jq -r '.Spec.Labels[\"certbot.domain\"] | select(.)'" \ | ||
| grep \. | sed 's/,/\n/g' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#!/usr/bin/env bash | ||
|
||
source ./config.sh | ||
source ./logger.sh | ||
|
||
TRAEFIK_EXPORT=${LE_DIR}/traefik.yml | ||
|
||
log_info "Exporting certificates for traefik ..." | ||
|
||
FILE=$TRAEFIK_EXPORT | ||
( | ||
printf "tls:\n options:\n default:\n minVersion: VersionTLS12\n certificates:\n" | ||
while read DOMAIN; do | ||
printf " # CERT FILE $DOMAIN\n" | ||
printf " - certFile: |-\n" | ||
sed -e 's/^/ /' $DOMAIN/fullchain.pem | ||
printf " keyFile: |-\n" | ||
sed -e 's/^/ /' $DOMAIN/privkey.pem | ||
done < <(find $LE_DIR/live/ -maxdepth 1 -mindepth 1 -type d -print) | ||
) > ${FILE}.new | ||
mv ${FILE}.new $FILE | ||
|
||
log_info "Export done." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#!/usr/bin/env bash | ||
|
||
source ./config.sh | ||
source ./logger.sh | ||
|
||
SERVER_PID="" | ||
EXPORT=0 | ||
while read DOMAIN; do | ||
if [ -d $LE_DIR/live/$DOMAIN ]; then | ||
continue | ||
fi | ||
if [ -f $LE_DIR/failed/$DOMAIN ]; then | ||
log_warn "$DOMAIN|Skipping domain marked as failed ..." | ||
continue | ||
fi | ||
|
||
if [ -z "$SERVER_PID" ]; then | ||
log_info "Starting http server ..." | ||
python -m http.server 80 --directory $WEBROOT & | ||
SERVER_PID=$! | ||
trap "kill $SERVER_PID" EXIT | ||
sleep 5 | ||
fi | ||
|
||
FILE="$ACME_PATH/check-${DOMAIN}-$(date +%s)" | ||
TEST_URL="http://$DOMAIN/$FILE" | ||
log_info "$DOMAIN|Test challenge accessibility $TEST_URL ..." | ||
|
||
echo "certbot" > $WEBROOT/$FILE | ||
curl --silent -v --max-time 5 $TEST_URL > /tmp/result | ||
ERR=$? | ||
rm -f $WEBROOT/$FILE | ||
if [ $ERR -ne 0 -o "$(cat /tmp/result)" != "certbot" ]; then | ||
log_error"$DOMAIN|Domain challenge failed $TEST_URL" | ||
continue | ||
fi | ||
|
||
log_info "$DOMAIN|Domain challenge ok, run certbot ..." | ||
|
||
{ | ||
flock 200 | ||
certbot certonly \ | ||
--webroot -w $WEBROOT \ | ||
--non-interactive \ | ||
--agree-tos \ | ||
--no-eff-email \ | ||
--keep-until-expiring \ | ||
-m $CERTBOT_EMAIL \ | ||
--cert-name $DOMAIN \ | ||
-d $DOMAIN > $LE_DIR/failed/$DOMAIN | ||
|
||
CERTBOT_RESULT=$? | ||
|
||
} 200>$LOCK_FILE | ||
|
||
if (( $CERTBOT_RESULT == 0 )); then | ||
log_info "$DOMAIN|Cerbot ok" | ||
rm -f $LE_DIR/failed/$DOMAIN | ||
EXPORT=1 | ||
else | ||
log_error"$DOMAIN|Cerbot failed read log $LE_DIR/failed/$DOMAIN ." | ||
fi | ||
|
||
done < <(./domains.sh) | ||
|
||
if [ $EXPORT = 1 ]; then | ||
./export.sh | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
log() { | ||
local level color message | ||
level=$1 | ||
message=$2 | ||
|
||
case "$level" in | ||
INFO) | ||
color=$'\e[36m' | ||
;; | ||
WARNING) | ||
color=$'\e[35m' | ||
;; | ||
ERROR) | ||
color=$'\e[31m' | ||
;; | ||
*) | ||
color=$'\e[39m' | ||
;; | ||
esac | ||
|
||
reset=$'\e[39m' | ||
timestamp=$(date +"%Y-%m-%d %H:%M:%S") | ||
|
||
if [[ -t 1 || -n $CONTENT_TYPE ]]; then | ||
echo -e "${color}-${level:0:1}|${timestamp}|${message}${reset}" | ||
else | ||
echo "-${level:0:1}|${timestamp}|${message}" | ||
fi | ||
|
||
logger -t SCRIPT_NAME -p user.${level,,} "${timestamp} - ${level} - ${message}" | ||
} | ||
|
||
log_info() { | ||
log "INFO" "$1" | ||
} | ||
|
||
log_warn() { | ||
log "WARNING" "$1" | ||
} | ||
|
||
log_error() { | ||
log "ERROR" "$1" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#!/usr/bin/env bash | ||
|
||
source ./config.sh | ||
source ./logger.sh | ||
|
||
DOMAIN=$(ls /etc/letsencrypt/live/*/cert.pem -1tr | awk -F/ 'NR==1{print $5}') | ||
if [[ -z $DOMAIN ]]; then | ||
log_warn "No live domain found, terminating." | ||
exit | ||
fi | ||
log_info "Will use $DOMAIN to test challenge accessibility." | ||
|
||
log_info "Starting http server ..." | ||
python -m http.server 80 --directory $WEBROOT & | ||
trap "kill $!" exit | ||
sleep 5 | ||
log_info "Started." | ||
|
||
FILE="$ACME_PATH/check-renew-$(date +%s)" | ||
TEST_URL="http://$DOMAIN/$FILE" | ||
log_info "Test challenge accessibility $TEST_URL ..." | ||
|
||
echo "certbot" > $WEBROOT/$FILE | ||
curl --silent -v --max-time 5 $TEST_URL > /tmp/result | ||
ERR=$? | ||
rm -f $WEBROOT/$FILE | ||
if [ $ERR -ne 0 -o "$(cat /tmp/result)" != "certbot" ]; then | ||
log_error "Test challenge failed $TEST_URL" | ||
exit 1 | ||
fi | ||
|
||
log_info "Calling certbot renew ..." | ||
{ | ||
flock 200 | ||
certbot renew --webroot -w $WEBROOT --non-interactive | ||
|
||
CERTBOT_RESULT=$? | ||
|
||
} 200>$LOCK_FILE | ||
|
||
if (( $CERTBOT_RESULT == 0 )); then | ||
log_info "Cerbot ok" | ||
./export.sh | ||
else | ||
log_error"Cerbot failed." | ||
fi |