25 Commits

Author SHA1 Message Date
53935f50a1 Merge pull request '1.0.0' (#4) from develop into master
Some checks failed
continuous-integration/drone/tag Build is failing
Reviewed-on: #4
2023-06-21 18:20:15 +00:00
a079be7a7c make CLOUDFLARE_TOKEN override instead of append 2023-06-21 17:48:29 +00:00
daf09c2688 add CLOUDFLARE_TOKEN to env vars 2023-06-21 17:32:17 +00:00
12c5cc0b26 add build dependencies for arm 2023-06-20 22:14:44 +00:00
afe5564d3e update readme 2023-06-20 21:27:42 +00:00
e8746b41f8 update build logic 2023-06-20 21:27:36 +00:00
e98549ced0 add goreleaser 2023-06-20 21:27:27 +00:00
df6719d802 change to s6 2023-06-20 21:27:01 +00:00
da97eed84e change to alpine 2023-06-20 21:26:11 +00:00
bc046870b5 Update 'README.md' 2023-01-02 16:40:31 +00:00
51fb94b5d7 Update '.drone.yml' 2022-12-25 20:38:20 +00:00
e6afb009ea Update '.drone.yml' 2022-12-25 19:18:06 +00:00
6d4ca72071 Update 'README.md' 2022-12-25 19:09:13 +00:00
8b57c507cf Update 'README.md' 2022-12-25 19:07:54 +00:00
f4f8bfb64b Add '.drone.yml' 2022-12-25 18:50:54 +00:00
c8daded5b0 Update 'README.md' 2022-12-25 18:48:33 +00:00
6056a0bcd7 Update 'README.md' 2022-06-21 16:56:35 +00:00
d2999b8307 Prevented dhparams regenerating if they already exist 2022-06-21 11:58:46 +00:00
5a24a284d0 Formatting 2022-06-20 22:42:29 +00:00
c25786a930 Add GENERATE_DHPARAM 2022-06-20 22:41:27 +00:00
09bdaf819c Added PROPOGATION_TIME variable 2022-06-20 22:08:30 +00:00
1773f9d3ee Update 'README.md' 2022-06-19 17:11:20 +00:00
47d5a4aaaf Fix typo 2022-06-18 23:12:11 +00:00
85ec77a260 Formatting fix 2022-06-18 23:10:07 +00:00
afd88220aa first commit 2022-06-18 23:08:39 +00:00
5 changed files with 86 additions and 253 deletions

View File

@ -11,30 +11,17 @@ FROM base-${TARGETARCH}${TARGETVARIANT}
ARG S6_OVERLAY_VERSION=3.1.5.0 ARG S6_OVERLAY_VERSION=3.1.5.0
# Core variables
ENV PUID=1000
ENV PGID=1000
ENV TZ=UTC
ENV GENERATE_DHPARAM=true
ENV INTERVAL="0 */6 * * *"
# Single domain
ENV DOMAINS= ENV DOMAINS=
ENV EMAIL= ENV EMAIL=
ENV INTERVAL="0 */6 * * *"
ENV STAGING=false ENV STAGING=false
# Custom CA support
ENV CUSTOM_CA=
ENV CUSTOM_CA_SERVER=
# Different plugin support (to support Cloudflare but also normal mode)
ENV PLUGIN=standalone
ENV PROPOGATION_TIME=10 ENV PROPOGATION_TIME=10
ENV GENERATE_DHPARAM=true
ENV TZ=UTC
ENV PUID=1000
ENV PGID=1000
ENV CLOUDFLARE_TOKEN= ENV CLOUDFLARE_TOKEN=
## Multi-cert support
ENV CERT_COUNT=1
#Get required packages #Get required packages
RUN apk update && apk add curl bash python3 py3-virtualenv procps tzdata nano shadow xz busybox-suid openssl RUN apk update && apk add curl bash python3 py3-virtualenv procps tzdata nano shadow xz busybox-suid openssl

View File

@ -2,7 +2,7 @@
![Drone (self-hosted) with branch](https://img.shields.io/drone/build/MrMeeb/certbot-cron-docker/master?label=latest&server=https%3A%2F%2Fdrone.mrmeeb.stream&style=for-the-badge) ![Drone (self-hosted) with branch](https://img.shields.io/drone/build/MrMeeb/certbot-cron-docker/develop?label=develop&server=https%3A%2F%2Fdrone.mrmeeb.stream&style=for-the-badge) ![Drone (self-hosted) with branch](https://img.shields.io/drone/build/MrMeeb/certbot-cron-docker/master?label=latest&server=https%3A%2F%2Fdrone.mrmeeb.stream&style=for-the-badge) ![Drone (self-hosted) with branch](https://img.shields.io/drone/build/MrMeeb/certbot-cron-docker/develop?label=develop&server=https%3A%2F%2Fdrone.mrmeeb.stream&style=for-the-badge)
Dockerised Certbot that utilises cron to schedule creating and renewing SSL certificates. Supports standalone, webroot or Cloudflare methods. Automatic renewal attempt happens every 6 hours by default. Dockerised Certbot that utilises cron to schedule creating and renewing SSL certificates. Uses Cloudflare for DNS-01 verification. Automatic renewal attempt happens every 6 hours by default.
## Tags ## Tags
@ -18,9 +18,8 @@ Dockerised Certbot that utilises cron to schedule creating and renewing SSL cert
docker run -d --name certbot \ docker run -d --name certbot \
-e EMAIL=admin@domain.com \ -e EMAIL=admin@domain.com \
-e DOMAINS=domain.com \ -e DOMAINS=domain.com \
-e PLUGIN=cloudflare \
-e CLOUDFLARE_TOKEN=123abc -e CLOUDFLARE_TOKEN=123abc
-v ./certbot-cron:/config \ -v /docker/certbot-cron:/config \
git.mrmeeb.stream/mrmeeb/certbot-cron:latest git.mrmeeb.stream/mrmeeb/certbot-cron:latest
``` ```
@ -37,78 +36,30 @@ services:
environment: environment:
- EMAIL=admin@domain.com - EMAIL=admin@domain.com
- DOMAINS=domain.com,*.domain.com - DOMAINS=domain.com,*.domain.com
- PLUGIN=cloudflare
- CLOUDFLARE_TOKEN=123abc - CLOUDFLARE_TOKEN=123abc
``` ```
## Environment Variables: ## Environment Variables:
### Core Options: | Variable | Default Value | Description |
Core options to the container
| Variable | Default | Description |
| --- | --- | --- | | --- | --- | --- |
|PUID |int |1000 |Sets the UID of the user certbot runs under | |PUID |int |1000 |Sets the UID of the user certbot runs under |
|PGID |int |1000 |Sets the GID of the user certbot runs under | |PGID |int |1000 |Sets the GID of the user certbot runs under |
|TZ |[List of valid TZs](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List) |UTC |Sets the timezone of the container | |TZ |[List of valid TZs](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List) |UTC |Sets the timezone of the container |
| GENERATE_DHPARAM | true (case-sensitive) | Generate Diffie-Hellman keys in /config/letsencrypt/keys |
| INTERVAL | 0 */6 * * * | How often certbot attempts to renew the certificate. Cron syntax |
| CERT_COUNT | 1 | How many certificates certbot will try to issue (more than 1 not yet implemented) |
### Certificate Options
These options apply when `CERT_COUNT` is `1`
| Variable | Default | Description |
| --- | --- | --- |
| EMAIL | None | Email address for renewal information & other communications | | EMAIL | None | Email address for renewal information & other communications |
| DOMAINS | None | Domains to be included in the certificate. Comma separated list, no spaces. Wildcards supported | | DOMAINS | None | Domains to be included in the certificate. Comma separated list, no spaces. Wildcards supported |
| STAGING | false (case-sensitive) | Uses the LetsEncrypt staging endpoint for testing - avoids the aggressive rate-limiting of the production endpoint. **Not supported when using a custom Certificate Authority.** | | INTERVAL | 0 */6 * * * | How often certbot attempts to renew the certificate. Cron syntax |
| STAGING | false (case-sensitive) | Uses the LetsEncrypt staging endpoint for testing - avoids the aggressive rate-limiting of the production endpoint |
### Plugins
Plugins that can used for issuing a certificate
| Variable | Default | Description |
| --- | --- | --- |
| PLUGIN | standalone | Options are `webroot`, `standalone`, or `cloudflare` |
- `webroot` - relies on a webserver running on the FQDN for which you're trying to issue a certificate to serve validation files
- Requires the webserver's root directory to be mounted to the container as `/config/webroot`
- `standalone` - certbot spawns a webserver on port 80 for validation
- Requires this container to be bound to port 80 on the host
- `cloudflare` - Creates a TXT record with Cloudflare pointing to the domain you're requesting a certificate for
- Requires the domain you're requesting a certificate for to be entered in Cloudflare
#### Cloudflare Plugin
Options that affect the behaviour of certbot running with the Cloudflare plugin
| Variable | Default | Description |
| --- | --- | --- |
| PROPOGATION_TIME | 10 | The amount of time (seconds) that certbot waits for the TXT records to propogate to Cloudflare before verifying - the more domains in the certificate, the longer you might need | | PROPOGATION_TIME | 10 | The amount of time (seconds) that certbot waits for the TXT records to propogate to Cloudflare before verifying - the more domains in the certificate, the longer you might need |
| CLOUDFLARE_TOKEN | null | Cloudflare token for verification | | GENERATE_DHPARAM | true (case-sensitive) | Generate Diffie-Hellman keys in /config/letsencrypt/keys |
| CLOUDFLARE_TOKEN | N/A | Cloudflare token for verification |
### Custom Certificate Authority
Options to use a custom Certificate Authority, for example when issuing internal certificates
| Variable | Default | Description |
| --- | --- | --- |
| CUSTOM_CA | null | Name of the root certificate Certbot/ACME will trust requesting the certificate, e.g `root.pem`. **Must be placed in `/config/custom_ca`** |
| CUSTOM_CA_SERVER | null | Custom server URL used by Certbot/ACME when requesting a certificate, e.g `https://ca.internal/acme/acme/directory` |
## Volumes ## Volumes
| Docker path | Purpose | | Docker path | Purpose |
| --- | --- | | --- | --- |
| /config | Stores configs and LetsEncrypt output for mounting in other containers | /config | Stores configs and LetsEncrypt output for mounting in other containers
| /config/custom_ca | Mountpoint for a custom Certificate Authority root certificate. **Required if `CUSTOM_CA` is set**
| /config/webroot | Mountpoint for the webroot of a separate webserver. **Required if `PLUGIN=webroot` is set**
## Ports ## Other
| Port | Purpose | Thanks to [this guy](https://stackoverflow.com/questions/63447441/docker-stop-for-crond-times-out) for explaining how to make cron actually shutdown when stopping the container.
| --- | --- |
| 80 | Used by ACME to verify domain ownership. **Required if `PLUGIN=standalone` is set**

View File

@ -32,177 +32,54 @@ then
touch /config/.crontab.txt touch /config/.crontab.txt
fi fi
#Cleanup renew list and create it fresh, ready for commands to be run and added if [ ! -f /config/.secrets/cloudflare.ini ]
echo "#!/command/with-contenv bash" > /config/renew-list.sh then
echo "" >> /config/.renew-list.sh
function single_domain {
if [ ! -z $CUSTOM_CA ]
then
echo "Using a custom CA for issuing certificates"
if [ ! -d /config/custom_ca ]
then
mkdir /config/custom_ca
echo "Please place your custom CA file into /config/custom_ca and restart the container"
exit 1
fi
if [ -z "$(ls -A /config/custom_ca)" ]
then
echo "The CUSTOM_CA option is populated, but the /config/custom_ca dir is empty. Please place your root certificate in this directory and restart the container"
exit 1
fi
if [ -z $CUSTOM_CA_SERVER ]
then
echo "CUSTOM_CA_SERVER has not been defined. It is required for using a custom CA to issue a certificate"
exit 1
fi
#REQUESTS_CA_BUNDLE=/config/custom_ca/$CUSTOM_CA
CUSTOM_CA_PATH=/config/custom_ca/$CUSTOM_CA
CUSTOM_CA_SERVER_OPT="--server $CUSTOM_CA_SERVER"
if [ $STAGING ]
then
echo "Staging is not supported when using a custom CA, so overriding. To remove this alert, set staging to false."
STAGING=false
fi
fi
BASE_COMMAND=(certbot certonly --non-interactive --config-dir /config/letsencrypt --work-dir /config/.tmp --logs-dir /config/logs --key-path /config/letsencrypt/keys --expand --agree-tos $CUSTOM_CA_SERVER_OPT --email $EMAIL -d $DOMAINS)
## Run with Cloudflare plugin
if [ $PLUGIN == "cloudflare" ]
then
echo "Using Cloudflare plugin"
if [ ! -f /config/.secrets/cloudflare.ini ]
then
touch /config/.secrets/cloudflare.ini touch /config/.secrets/cloudflare.ini
fi fi
if [ -n "$CLOUDFLARE_TOKEN" ] if [ -n "$CLOUDFLARE_TOKEN" ]
then then
echo "Cloudflare token is present" echo "Cloudflare token is present"
echo "dns_cloudflare_api_token = $CLOUDFLARE_TOKEN" > /config/.secrets/cloudflare.ini echo "dns_cloudflare_api_token = $CLOUDFLARE_TOKEN" > /config/.secrets/cloudflare.ini
fi fi
if [ ! -s /config/.secrets/cloudflare.ini ] if [ ! -s /config/.secrets/cloudflare.ini ]
then then
echo "cloudflare.ini is empty - please add your Cloudflare credentials or API key before continuing. This can be done as an ENV var, or by editing the file directly" echo "cloudflare.ini is empty - please add your Cloudflare credentials or API key before continuing. This can be done as an ENV var, or by editing the file directly"
exit 1 exit 22
fi fi
#Securing cloudflare.ini to supress warnings #Securing cloudflare.ini to supress warnings
chmod 600 /config/.secrets/cloudflare.ini chmod 600 /config/.secrets/cloudflare.ini
echo "Creating certificates, or attempting to renew if they already exist" echo "Creating certificates, or attempting to renew if they already exist"
if [ $STAGING = true ] if [[ $STAGING = true ]]
then then
echo "Using staging endpoint - THIS SHOULD BE USED FOR TESTING ONLY" echo "Using staging endpoint - THIS SHOULD BE USED FOR TESTING ONLY"
${BASE_COMMAND[@]} --dns-cloudflare --dns-cloudflare-propagation-seconds $PROPOGATION_TIME --dns-cloudflare-credentials /config/.secrets/cloudflare.ini --staging certbot certonly --staging --non-interactive --config-dir /config/letsencrypt --work-dir /config/.tmp --logs-dir /config/logs --key-path /config/letsencrypt/keys --expand --agree-tos --dns-cloudflare --dns-cloudflare-propagation-seconds $PROPOGATION_TIME --dns-cloudflare-credentials /config/.secrets/cloudflare.ini --email $EMAIL -d $DOMAINS
# Add to renewal list
echo "REQUESTS_CA_BUNDLE=$CUSTOM_CA_PATH ${BASE_COMMAND[@]} --dns-cloudflare --dns-cloudflare-propagation-seconds $PROPOGATION_TIME --dns-cloudflare-credentials /config/.secrets/cloudflare.ini --staging" >> /config/renew-list.sh
echo "Creation/renewal attempt complete" echo "Creation/renewal attempt complete"
elif [ $STAGING = false ] elif [[ $STAGING = false ]]
then then
echo "Using production endpoint" echo "Using production endpoint"
${BASE_COMMAND[@]} --dns-cloudflare --dns-cloudflare-propagation-seconds $PROPOGATION_TIME --dns-cloudflare-credentials /config/.secrets/cloudflare.ini certbot certonly --non-interactive --config-dir /config/letsencrypt --work-dir /config/.tmp --logs-dir /config/logs --key-path /config/letsencrypt/keys --expand --agree-tos --dns-cloudflare --dns-cloudflare-propagation-seconds $PROPOGATION_TIME --dns-cloudflare-credentials /config/.secrets/cloudflare.ini --email $EMAIL -d $DOMAINS
# Add to renewal list
echo "REQUESTS_CA_BUNDLE=$CUSTOM_CA_PATH ${BASE_COMMAND[@]} --dns-cloudflare --dns-cloudflare-propagation-seconds $PROPOGATION_TIME --dns-cloudflare-credentials /config/.secrets/cloudflare.ini" >> /config/renew-list.sh
echo "Creation/renewal attempt complete" echo "Creation/renewal attempt complete"
else else
echo "Unrecognised option for STAGING variable - check your configuration" echo "Unrecognised option for STAGING variable - check your configuration"
exit 1 exit 22
fi fi
## Run with Standalone plugin if [[ $GENERATE_DHPARAM = true ]] && [[ ! -s /config/letsencrypt/keys/ssl-dhparams.pem ]]
elif [ $PLUGIN == "standalone" ] then
then
echo "Using HTTP verification via built-in web-server - please ensure port 80 is exposed."
if [ $STAGING = true ]
then
echo "Using staging endpoint - THIS SHOULD BE USED FOR TESTING ONLY"
REQUESTS_CA_BUNDLE=$CUSTOM_CA_PATH ${BASE_COMMAND[@]} --standalone --staging
# Add to renewal list
echo "REQUESTS_CA_BUNDLE=$CUSTOM_CA_PATH ${BASE_COMMAND[@]} --standalone --staging" >> /config/renew-list.sh
echo "Creation/renewal attempt complete"
elif [ $STAGING = false ]
then
echo "Using production endpoint"
REQUESTS_CA_BUNDLE=$CUSTOM_CA_PATH ${BASE_COMMAND[@]} --standalone
# Add to renewal list
echo "REQUESTS_CA_BUNDLE=$CUSTOM_CA_PATH ${BASE_COMMAND[@]} --standalone" >> /config/renew-list.sh
echo "Creation/renewal attempt complete"
else
echo "Unrecognised option for STAGING variable - check your configuration"
exit 1
fi
## Run with webroot plugin
elif [ $PLUGIN == "webroot" ]
then
echo "Using HTTP verification via webroot - please ensure you have mounted a webroot at /config/webroot from a web-server reachable via the domain you are issuing a certificate for."
if [ $STAGING = true ]
then
echo "Using staging endpoint - THIS SHOULD BE USED FOR TESTING ONLY"
REQUESTS_CA_BUNDLE=$CUSTOM_CA_PATH ${BASE_COMMAND[@]} --webroot --webroot-path /config/webroot --staging
# Add to renewal list
echo "REQUESTS_CA_BUNDLE=$CUSTOM_CA_PATH ${BASE_COMMAND[@]} --webroot --webroot-path /config/webroot --staging" >> /config/renew-list.sh
echo "Creation/renewal attempt complete"
elif [ $STAGING = false ]
then
echo "Using production endpoint"
REQUESTS_CA_BUNDLE=$CUSTOM_CA_PATH ${BASE_COMMAND[@]} --webroot --webroot-path /config/webroot
# Add to renewal list
echo "REQUESTS_CA_BUNDLE=$CUSTOM_CA_PATH ${BASE_COMMAND[@]} --webroot --webroot-path /config/webroot" >> /config/renew-list.sh
echo "Creation/renewal attempt complete"
else
echo "Unrecognised option for STAGING variable - check your configuration"
exit 1
fi
else
echo "Unrecognised option for PLUGIN variable - check your configuration"
fi
if [ $GENERATE_DHPARAM = true ] && [ ! -s /config/letsencrypt/keys/ssl-dhparams.pem ]
then
echo "Generating Diffie-Hellman keys, saved to /config/letsencrypt/keys" echo "Generating Diffie-Hellman keys, saved to /config/letsencrypt/keys"
openssl dhparam -out /config/letsencrypt/keys/ssl-dhparams.pem 4096 openssl dhparam -out /config/letsencrypt/keys/ssl-dhparams.pem 4096
fi
echo "$INTERVAL /certbot-renew.sh >> /config/logs/renew.log" > /config/.crontab.txt
echo "Starting automatic renewal job. Schedule is $INTERVAL"
crontab /config/.crontab.txt
}
if [ $CERT_COUNT == 1 ]
then
single_domain
fi fi
echo "$INTERVAL /certbot-renew.sh >> /config/logs/renew.log" > /config/.crontab.txt
echo "Starting automatic renewal job. Schedule is $INTERVAL"
crontab /config/.crontab.txt

View File

@ -3,4 +3,18 @@
echo '' echo ''
date date
echo "Attempting to renew certificates" echo "Attempting to renew certificates"
bash /config/.renew-list.sh if [[ $STAGING = true ]]
then
echo "Using staging endpoint - THIS SHOULD BE USED FOR TESTING ONLY"
certbot certonly --staging --non-interactive --config-dir /config/letsencrypt --work-dir /config/.tmp --logs-dir /config/logs --key-path /config/letsencrypt/keys --expand --agree-tos --dns-cloudflare --dns-cloudflare-propagation-seconds $PROPOGATION_TIME --dns-cloudflare-credentials /config/.secrets/cloudflare.ini --email $EMAIL -d $DOMAINS
echo "Renewal attempt complete"
elif [[ $STAGING = false ]]
then
echo "Using production endpoint"
certbot certonly --non-interactive --config-dir /config/letsencrypt --work-dir /config/.tmp --logs-dir /config/logs --key-path /config/letsencrypt/keys --expand --agree-tos --dns-cloudflare --dns-cloudflare-propagation-seconds $PROPOGATION_TIME --dns-cloudflare-credentials /config/.secrets/cloudflare.ini --email $EMAIL -d $DOMAINS
echo "Renewal attempt complete"
else
echo "Unrecognised option for STAGING variable - check your configuration"
exit 8
fi

View File

@ -15,14 +15,18 @@ echo ""
echo "Initialising container" echo "Initialising container"
echo " echo "
---------------------------------------------------------------------- ----------------------------------------------------------------------
ENVIRONMENT (only core variables shown) ENVIRONMENT
---------------------------------------------------------------------- ----------------------------------------------------------------------
PUID=${PUID} PUID=${PUID}
PGID=${PGID} PGID=${PGID}
TZ=${TZ} TZ=${TZ}
DOMAINS=${DOMAINS}
EMAIL=${EMAIL}
INTERVAL=${INTERVAL} INTERVAL=${INTERVAL}
STAGING=${STAGING}
PROPOGATION_TIME=${PROPOGATION_TIME}
GENERATE_DHPARAM=${GENERATE_DHPARAM} GENERATE_DHPARAM=${GENERATE_DHPARAM}
CERT_COUNT=${CERT_COUNT} CLOUDFLARE_TOKEN=${CLOUDFLARE_TOKEN}
---------------------------------------------------------------------- ----------------------------------------------------------------------
" "
@ -37,7 +41,7 @@ if [[ ! "${PUID}" -eq 0 ]] && [[ ! "${PGID}" -eq 0 ]]; then
groupmod -o -g "${PGID}" mrmeeb groupmod -o -g "${PGID}" mrmeeb
else else
echo "Running as root is not supported, please fix your PUID and PGID!" echo "Running as root is not supported, please fix your PUID and PGID!"
sleep infinity exit 1
fi fi
echo "Checking permissions in /config and /app." echo "Checking permissions in /config and /app."