resolved bug with email input
* added UID and GID environment variables * updated docs
This commit is contained in:
parent
a2ce89caa2
commit
3bd0027a3e
10 changed files with 86 additions and 61 deletions
10
.dockerignore
Normal file
10
.dockerignore
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
.git
|
||||||
|
.github
|
||||||
|
certs
|
||||||
|
|
||||||
|
.dockerignore
|
||||||
|
.gitignore
|
||||||
|
Dockerfile
|
||||||
|
letsencrypt.env
|
||||||
|
LICENSE
|
||||||
|
README.md
|
0
.github/workflows/docker-build.yml
vendored
Executable file → Normal file
0
.github/workflows/docker-build.yml
vendored
Executable file → Normal file
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
certs
|
||||||
|
|
||||||
|
letsencrypt.env
|
4
Dockerfile
Executable file → Normal file
4
Dockerfile
Executable file → Normal file
|
@ -2,17 +2,15 @@
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
||||||
# Maintainer information
|
# Maintainer information
|
||||||
ARG VCS_REF
|
|
||||||
LABEL maintainer="Maksim Stojkovic <https://github.com/maksimstojkovic>" \
|
LABEL maintainer="Maksim Stojkovic <https://github.com/maksimstojkovic>" \
|
||||||
org.label-schema.vcs-ref=$VCS_REF \
|
|
||||||
org.label-schema.vcs-url="https://github.com/maksimstojkovic/docker-letsencrypt"
|
org.label-schema.vcs-url="https://github.com/maksimstojkovic/docker-letsencrypt"
|
||||||
|
|
||||||
# Install tools required
|
# Install tools required
|
||||||
RUN apk --no-cache add certbot curl
|
RUN apk --no-cache add certbot curl
|
||||||
|
|
||||||
# Copy scripts
|
# Copy scripts
|
||||||
COPY ./scripts /scripts
|
|
||||||
WORKDIR /scripts
|
WORKDIR /scripts
|
||||||
|
COPY ./scripts /scripts
|
||||||
RUN chmod -R +x /scripts
|
RUN chmod -R +x /scripts
|
||||||
|
|
||||||
# Image starting command
|
# Image starting command
|
||||||
|
|
0
LICENSE
Executable file → Normal file
0
LICENSE
Executable file → Normal file
16
README.md
Executable file → Normal file
16
README.md
Executable file → Normal file
|
@ -8,18 +8,20 @@
|
||||||
|
|
||||||
Automatically generates Let's Encrypt certificates using a lightweight Docker container without requiring any ports to be exposed for DNS challenges.
|
Automatically generates Let's Encrypt certificates using a lightweight Docker container without requiring any ports to be exposed for DNS challenges.
|
||||||
|
|
||||||
## Variables
|
## Environment Variables
|
||||||
|
|
||||||
* `DUCKDNS_TOKEN`: Duck DNS account token (obtained from [Duck DNS](https://www.duckdns.org))
|
* `DUCKDNS_TOKEN`: Duck DNS account token (obtained from [Duck DNS](https://www.duckdns.org)) (*required*)
|
||||||
* `DUCKDNS_DOMAIN`: Full Duck DNS domain (e.g. `test.duckdns.org`)
|
* `DUCKDNS_DOMAIN`: Full Duck DNS domain (e.g. `test.duckdns.org`) (*required*)
|
||||||
* `LETSENCRYPT_EMAIL`: Email used for certificate renewal notifications (optional)
|
* `LETSENCRYPT_EMAIL`: Email used for certificate renewal notifications (optional)
|
||||||
* `LETSENCRYPT_WILDCARD`: `true` or `false`, indicating whether the SSL certificate should be for subdomains *only* of `DUCKDNS_DOMAIN` (i.e. `*.test.duckdns.org`), or for the main domain *only* (i.e. `test.duckdns.org`) (default: `false`)
|
* `LETSENCRYPT_WILDCARD`: `true` or `false`, indicating whether the SSL certificate should be for subdomains *only* of `DUCKDNS_DOMAIN` (i.e. `*.test.duckdns.org`), or for the main domain *only* (i.e. `test.duckdns.org`) (optional, default: `false`)
|
||||||
* `TESTING`: `true` or `false`, indicating whether a staging SSL certificate should be generated or not (default: `false`)
|
* `TESTING`: `true` or `false`, indicating whether a staging SSL certificate should be generated or not (optional, default: `false`)
|
||||||
|
* `UID`: User ID to apply to Let's Encrypt files generated (optional, recommended, default: `0` - root)
|
||||||
|
* `GID`: Group ID to apply to Let's Encrypt files generated (optional, recommended, default: `0` - root)
|
||||||
|
|
||||||
**Note:** The format of `DUCKDNS_DOMAIN` should be the same regardless of the value of `LETSENCRYPT_WILDCARD`.
|
**Note:** The format of `DUCKDNS_DOMAIN` should be the same regardless of the value of `LETSENCRYPT_WILDCARD`.
|
||||||
|
|
||||||
## Volumes
|
## Volumes
|
||||||
|
|
||||||
* `<certs>:/etc/letsencrypt`: A named or hosted volume which allows SSL certificates to persist and be accessed by other containers
|
* `<certs>:/etc/letsencrypt`: A named or host volume which allows SSL certificates to persist and be accessed by other containers
|
||||||
|
|
||||||
**Note:** If a hosted volume is used, the volume should be mounted in an unused directory in another container to prevent access conflicts.
|
**Note:** To use the `<certs>` host volume in another container, mount it as read-only for those containers. The `<certs>` host volume should be read-write enabled for the Letsencrypt container.
|
||||||
|
|
0
scripts/auth.sh
Executable file → Normal file
0
scripts/auth.sh
Executable file → Normal file
|
@ -1,37 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ -z "$LETSENCRYPT_EMAIL" ]; then
|
|
||||||
export EMAIL_PARAM="--register-unsafely-without-email"
|
|
||||||
else
|
|
||||||
export EMAIL_PARAM="-m ${LETSENCRYPT_EMAIL} --no-eff-email"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -z "$TESTING" ]; then
|
|
||||||
echo NOTICE: Generating staging certificate
|
|
||||||
export TEST_PARAM="--staging"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Initial check for certificates
|
|
||||||
certbot certonly --manual --preferred-challenges dns --manual-auth-hook \
|
|
||||||
/scripts/auth.sh --manual-cleanup-hook /scripts/cleanup.sh \
|
|
||||||
"${EMAIL_PARAM}" -d "${LETSENCRYPT_DOMAIN}" \
|
|
||||||
--agree-tos --manual-public-ip-logging-ok --keep ${TEST_PARAM}
|
|
||||||
|
|
||||||
# Basic check for successful certificate generation
|
|
||||||
if [ ! -d "/etc/letsencrypt/live/${LETSENCRYPT_DOMAIN}" ] || \
|
|
||||||
[ ! -f "/etc/letsencrypt/live/${LETSENCRYPT_DOMAIN}/fullchain.pem" ] || \
|
|
||||||
[ ! -f "/etc/letsencrypt/live/${LETSENCRYPT_DOMAIN}/privkey.pem" ]; then
|
|
||||||
echo ERROR: Failed to create SSL certificates
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if certificates require renewal twice a day
|
|
||||||
while :; do
|
|
||||||
# Wait for a random period within the next 12 hours
|
|
||||||
LETSENCRYPT_DELAY=$(shuf -i 1-720 -n 1)
|
|
||||||
echo Sleeping for $(($LETSENCRYPT_DELAY / 60)) hour\(s\) and $(($LETSENCRYPT_DELAY % 60)) minute\(s\)
|
|
||||||
sleep $((${LETSENCRYPT_DELAY} * 60))
|
|
||||||
|
|
||||||
echo Attempting SSL certificate renewal
|
|
||||||
certbot --manual-public-ip-logging-ok renew
|
|
||||||
done
|
|
0
scripts/cleanup.sh
Executable file → Normal file
0
scripts/cleanup.sh
Executable file → Normal file
77
scripts/start.sh
Executable file → Normal file
77
scripts/start.sh
Executable file → Normal file
|
@ -2,35 +2,84 @@
|
||||||
|
|
||||||
# Check variables DUCKDNS_TOKEN, DUCKDNS_DOMAIN
|
# Check variables DUCKDNS_TOKEN, DUCKDNS_DOMAIN
|
||||||
if [ -z "$DUCKDNS_TOKEN" ]; then
|
if [ -z "$DUCKDNS_TOKEN" ]; then
|
||||||
echo ERROR: Variable DUCKDNS_TOKEN is unset
|
echo "ERROR: Variable DUCKDNS_TOKEN is unset"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$DUCKDNS_DOMAIN" ]; then
|
if [ -z "$DUCKDNS_DOMAIN" ]; then
|
||||||
echo ERROR: Variable DUCKDNS_DOMAIN is unset
|
echo "ERROR: Variable DUCKDNS_DOMAIN is unset"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Print email notice if applicable
|
# Print email notice if applicable
|
||||||
if [ -z "$LETSENCRYPT_EMAIL" ]; then
|
if [ -z "$LETSENCRYPT_EMAIL" ]; then
|
||||||
echo NOTICE: You will not receive SSL certificate expiration notices
|
echo "INFO: You will not receive SSL certificate expiration notices"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Set certificate url based on LETSENCRYPT_WILDCARD value
|
# Set certificate url based on LETSENCRYPT_WILDCARD value
|
||||||
if [ "$LETSENCRYPT_WILDCARD" = "true" ]; then
|
if [ "$LETSENCRYPT_WILDCARD" = "true" ]; then
|
||||||
echo NOTICE: A wildcard SSL certificate will be created
|
echo "INFO: A wildcard SSL certificate will be created"
|
||||||
export LETSENCRYPT_DOMAIN=*.${DUCKDNS_DOMAIN}
|
LETSENCRYPT_DOMAIN=*.$DUCKDNS_DOMAIN
|
||||||
export WILDCARD_STR="true"
|
|
||||||
else
|
else
|
||||||
export LETSENCRYPT_DOMAIN=${DUCKDNS_DOMAIN}
|
LETSENCRYPT_DOMAIN=$DUCKDNS_DOMAIN
|
||||||
export WILDCARD_STR="false"
|
LETSENCRYPT_WILDCARD="false"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set user and group ID's for files
|
||||||
|
if [ -z "$UID" ]; then
|
||||||
|
echo "INFO: No UID specified, using root UID of 0"
|
||||||
|
UID=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$GID" ]; then
|
||||||
|
echo "INFO: No GID specified, using root GID of 0"
|
||||||
|
GID=0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Print variables
|
# Print variables
|
||||||
echo DUCKDNS_TOKEN: $DUCKDNS_TOKEN
|
echo "DUCKDNS_TOKEN: $DUCKDNS_TOKEN"
|
||||||
echo DUCKDNS_DOMAIN: $DUCKDNS_DOMAIN
|
echo "DUCKDNS_DOMAIN: $DUCKDNS_DOMAIN"
|
||||||
echo LETSENCRYPT_EMAIL: $LETSENCRYPT_EMAIL
|
echo "LETSENCRYPT_EMAIL: $LETSENCRYPT_EMAIL"
|
||||||
echo LETSENCRYPT_WILDCARD: $WILDCARD_STR \(Input: \"${LETSENCRYPT_WILDCARD}\"\)
|
echo "LETSENCRYPT_WILDCARD: $LETSENCRYPT_WILDCARD"
|
||||||
|
echo "TESTING: $TESTING"
|
||||||
|
echo "UID: $UID"
|
||||||
|
echo "GID: $GID"
|
||||||
|
|
||||||
# Start automatic ssl certificate generation
|
if [ -z "$LETSENCRYPT_EMAIL" ]; then
|
||||||
/bin/sh /scripts/cert.sh
|
EMAIL_PARAM="--register-unsafely-without-email"
|
||||||
|
else
|
||||||
|
EMAIL_PARAM="-m $LETSENCRYPT_EMAIL --no-eff-email"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$TESTING" = "true" ]; then
|
||||||
|
echo "INFO: Generating staging certificate"
|
||||||
|
TEST_PARAM="--staging"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create certificates
|
||||||
|
certbot certonly --manual --preferred-challenges dns --manual-auth-hook \
|
||||||
|
/scripts/auth.sh --manual-cleanup-hook /scripts/cleanup.sh \
|
||||||
|
$EMAIL_PARAM -d "$LETSENCRYPT_DOMAIN" \
|
||||||
|
--agree-tos --manual-public-ip-logging-ok --keep $TEST_PARAM
|
||||||
|
|
||||||
|
chown -R $UID:$GID /etc/letsencrypt
|
||||||
|
|
||||||
|
# Check for successful certificate generation
|
||||||
|
if [ ! -d "/etc/letsencrypt/live/${DUCKDNS_DOMAIN}" ] || \
|
||||||
|
[ ! -f "/etc/letsencrypt/live/${DUCKDNS_DOMAIN}/fullchain.pem" ] || \
|
||||||
|
[ ! -f "/etc/letsencrypt/live/${DUCKDNS_DOMAIN}/privkey.pem" ]; then
|
||||||
|
echo "ERROR: Failed to create SSL certificates"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if certificates require renewal twice a day
|
||||||
|
while :; do
|
||||||
|
# Wait for a random period within the next 12 hours
|
||||||
|
LETSENCRYPT_DELAY=$(shuf -i 1-720 -n 1)
|
||||||
|
echo "Sleeping for $(($LETSENCRYPT_DELAY / 60)) hour(s) and $(($LETSENCRYPT_DELAY % 60)) minute(s)"
|
||||||
|
sleep $((${LETSENCRYPT_DELAY} * 60)) # Convert to seconds
|
||||||
|
|
||||||
|
echo "INFO: Attempting SSL certificate renewal"
|
||||||
|
certbot --manual-public-ip-logging-ok renew
|
||||||
|
chown -R $UID:$GID /etc/letsencrypt
|
||||||
|
done
|
||||||
|
|
Loading…
Reference in a new issue