DuckDNS: Also generate a certificate with Let's Encrypt (0 config) (#181)

* Initial Let's Encrypt + DuckDNS

* Remove letsencrypt_duckdns

* Add cert generation with lets encrypt to DuckDNS

* Add that you have to accept terms

* Update Dockerfile

* Delete dehydrated.sh

* Update Dockerfile

* Update config.json

* Update run.sh

* Update hooks.sh

* Update run.sh

* Update hooks.sh

* Update run.sh

* Update config.json

* Update hooks.sh

* Update Dockerfile

* Update run.sh

* fix renew timer

* Update run.sh

* fix logic
This commit is contained in:
Paulus Schoutsen
2017-09-26 08:02:03 -07:00
committed by Pascal Vizeli
parent 620cb248e4
commit 54b8289e08
4 changed files with 93 additions and 6 deletions

View File

@@ -5,10 +5,12 @@ FROM $BUILD_FROM
ENV LANG C.UTF-8
# Setup base
RUN apk add --no-cache jq curl
RUN apk add --no-cache jq curl libressl \
&& curl -s -o /usr/bin/dehydrated https://raw.githubusercontent.com/lukas2511/dehydrated/v0.4.0/dehydrated \
&& chmod a+x /usr/bin/dehydrated
# Copy data
COPY run.sh /
RUN chmod a+x /run.sh
COPY *.sh /
RUN chmod a+x /*.sh
CMD [ "/run.sh" ]

View File

@@ -1,17 +1,28 @@
{
"name": "Duck DNS",
"version": "0.6",
"version": "1.0",
"slug": "duckdns",
"description": "Free Dynamic DNS (DynDNS or DDNS) service",
"url": "https://home-assistant.io/addons/duckdns/",
"startup": "services",
"boot": "auto",
"map": ["ssl:rw"],
"options": {
"lets_encrypt": {
"accept_terms": false,
"certfile": "fullchain.pem",
"keyfile": "privkey.pem"
},
"token": null,
"domains": [null],
"seconds": 300
},
"schema": {
"lets_encrypt": {
"accept_terms": "bool",
"certfile": "str",
"keyfile": "str"
},
"token": "str",
"domains": ["str"],
"seconds": "int"

32
duckdns/hooks.sh Normal file
View File

@@ -0,0 +1,32 @@
#!/bin/bash
set -e
CONFIG_PATH=/data/options.json
DOMAINS=$(jq --raw-output '.domains | join(",")' $CONFIG_PATH)
TOKEN=$(jq --raw-output '.token' $CONFIG_PATH)
CERTFILE=$(jq --raw-output '.lets_encrypt.certfile' $CONFIG_PATH)
KEYFILE=$(jq --raw-output '.lets_encrypt.keyfile' $CONFIG_PATH)
case "$1" in
"deploy_challenge")
curl -s "https://www.duckdns.org/update?domains=$DOMAINS&token=$TOKEN&txt=$4"
;;
"clean_challenge")
curl -s "https://www.duckdns.org/update?domains=$DOMAINS&token=$TOKEN&txt=removed&clear=true"
;;
"deploy_cert")
cp -f "$5" "/ssl/$CERTFILE"
cp -f "$3" "/ssl/$KEYFILE"
;;
"unchanged_cert")
;;
"startup_hook")
;;
"exit_hook")
;;
*)
echo Unknown hook "${1}"
exit 0
;;
esac

View File

@@ -1,15 +1,57 @@
#!/bin/bash
set -e
CERT_DIR=/data/letsencrypt
WORK_DIR=/data/workdir
CONFIG_PATH=/data/options.json
# Let's encrypt
LE_TERMS=$(jq --raw-output '.lets_encrypt.accept_terms' $CONFIG_PATH)
LE_DOMAINS=$(jq --raw-output '.domains[]' $CONFIG_PATH)
LE_UPDATE="0"
# DuckDNS
TOKEN=$(jq --raw-output '.token' $CONFIG_PATH)
DOMAINS=$(jq --raw-output '.domains | join(",")' $CONFIG_PATH)
WAIT_TIME=$(jq --raw-output '.seconds' $CONFIG_PATH)
# Function that performe a renew
function le_renew() {
local domain_args=()
# Prepare domain for Let's Encrypt
for domain in $LE_DOMAINS; do
domain_args+=("--domain" "$domain")
done
dehydrated --cron --hook ./hooks.sh --challenge dns-01 "${domain_args[@]}" --out "$CERT_DIR" --config "$WORK_DIR/config" || true
LE_UPDATE="$(date +%s)"
}
# Register/generate certificate if terms accepted
if [ "$LE_TERMS" == "true" ]; then
# Init folder structs
mkdir -p "$CERT_DIR"
mkdir -p "$WORK_DIR"
# Generate new certs
if [ ! -d "$CERT_DIR/live" ]; then
# Create empty dehydrated config file so that this dir will be used for storage
touch "$WORK_DIR/config"
dehydrated --register --accept-terms --config "$WORK_DIR/config"
fi
fi
# Run duckdns
while true; do
ANSWER="$(curl -sk "https://www.duckdns.org/update?domains=$DOMAINS&token=$TOKEN&ip=&verbose=true")" || true
echo "$(date): $ANSWER"
answer="$(curl -sk "https://www.duckdns.org/update?domains=$DOMAINS&token=$TOKEN&ip=&verbose=true")" || true
echo "$(date): $answer"
now="$(date +%s)"
if [ "$LE_TERMS" == "true" ] && [ $((now - LE_UPDATE)) -ge 43200 ]; then
le_renew
fi
sleep "$WAIT_TIME"
done