diff options
author | Yuqian Yang <crupest@crupest.life> | 2025-02-21 00:36:11 +0800 |
---|---|---|
committer | Yuqian Yang <crupest@crupest.life> | 2025-02-21 00:58:57 +0800 |
commit | da756422d9734d1d704e0cbcd248c17c30cd4f90 (patch) | |
tree | 7f2674c3a03e9cdd2b9624a8bc6b0479a1072f56 | |
parent | ce16f3f4f3cec88335c49ab16f636efb5d2db2d6 (diff) | |
download | crupest-da756422d9734d1d704e0cbcd248c17c30cd4f90.tar.gz crupest-da756422d9734d1d704e0cbcd248c17c30cd4f90.tar.bz2 crupest-da756422d9734d1d704e0cbcd248c17c30cd4f90.zip |
feat(nginx): move certbot to nginx.
-rw-r--r-- | docker/auto-certbot/Dockerfile | 20 | ||||
-rwxr-xr-x | docker/auto-certbot/daemon.bash | 107 | ||||
-rwxr-xr-x | docker/auto-certbot/get-cert-domains.py | 38 | ||||
-rw-r--r-- | docker/nginx/Dockerfile | 3 | ||||
-rw-r--r-- | docker/nginx/certbot.bash | 9 | ||||
-rw-r--r-- | docker/nginx/nginx-wrapper.bash | 7 | ||||
-rw-r--r-- | templates/docker-compose.yaml.template | 27 |
7 files changed, 22 insertions, 189 deletions
diff --git a/docker/auto-certbot/Dockerfile b/docker/auto-certbot/Dockerfile deleted file mode 100644 index eeb6475..0000000 --- a/docker/auto-certbot/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM certbot/certbot:latest - -ARG CRUPEST_AUTO_CERTBOT_ADDITIONAL_PACKAGES="" -RUN apk add --no-cache tini coreutils bash ${CRUPEST_AUTO_CERTBOT_ADDITIONAL_PACKAGES} && python -m pip install cryptography - - -ARG CRUPEST_DOMAIN -ARG CRUPEST_ADDITIONAL_DOMAIN_LIST="" -ARG CRUPEST_EMAIL -ARG CRUPEST_AUTO_CERTBOT_POST_HOOK="" -# install bash -ENV CRUPEST_DOMAIN=${CRUPEST_DOMAIN} -ENV CRUPEST_ADDITIONAL_DOMAIN_LIST=${CRUPEST_ADDITIONAL_DOMAIN_LIST} -ENV CRUPEST_EMAIL=${CRUPEST_EMAIL} -ENV CRUPEST_AUTO_CERTBOT_POST_HOOK=${CRUPEST_AUTO_CERTBOT_POST_HOOK} -COPY daemon.bash /daemon.bash -COPY get-cert-domains.py /get-cert-domains.py -VOLUME ["/var/www/certbot", "/etc/letsencrypt", "/var/lib/letsencrypt"] -ENTRYPOINT ["tini", "--"] -CMD [ "/daemon.bash" ] diff --git a/docker/auto-certbot/daemon.bash b/docker/auto-certbot/daemon.bash deleted file mode 100755 index d79387e..0000000 --- a/docker/auto-certbot/daemon.bash +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env bash - -set -e - -# Check I'm root. -if [[ $EUID -ne 0 ]]; then - echo "This script must be run as root" 1>&2 - exit 1 -fi - -# Check certbot version. -certbot --version - -# Check domain -if [[ -z "$CRUPEST_DOMAIN" ]]; then - echo "CRUPEST_DOMAIN can't be empty!" 1>&2 - exit 1 -fi - -# Check email -if [[ -z "$CRUPEST_EMAIL" ]]; then - echo "CRUPEST_EMAIL can't be empty!" 1>&2 - exit 2 -fi - -# Check CRUPEST_CERT_PATH, default to /etc/letsencrypt/live/$CRUPEST_DOMAIN/fullchain.pem -if [ -z "$CRUPEST_CERT_PATH" ]; then - CRUPEST_CERT_PATH="/etc/letsencrypt/live/$CRUPEST_DOMAIN/fullchain.pem" -fi - -# Check CRUPEST_CERT_PATH exists. -if [ ! -f "$CRUPEST_CERT_PATH" ]; then - echo "Cert file does not exist. You may want to generate it manually with aio script." 1>&2 - exit 3 -fi - -echo "Root domain:" "$CRUPEST_DOMAIN" -echo "Email:" "$CRUPEST_EMAIL" -echo "Cert path: ${CRUPEST_CERT_PATH}" - -# Check CRUPEST_AUTO_CERTBOT_RENEW_COMMAND is defined. -if [ -z "$CRUPEST_AUTO_CERTBOT_RENEW_COMMAND" ]; then - echo "CRUPEST_AUTO_CERTBOT_RENEW_COMMAND is not defined or empty. Will use the default one." -else - printf "CRUPEST_AUTO_CERTBOT_RENEW_COMMAND is defined as:\n%s\n" "$CRUPEST_AUTO_CERTBOT_RENEW_COMMAND" -fi - -domains_str="$(/get-cert-domains.py "${CRUPEST_CERT_PATH}")" - -printf "Domain list:\n%s\n" "$domains_str" - -mapfile -t domains <<< "$domains_str" - -for domain in "${domains[@]}"; do - domain_options=("${domain_options[@]}" -d "$domain") -done - -options=(-n --agree-tos -m "$CRUPEST_EMAIL" --webroot -w /var/www/certbot "${domain_options[@]}") -if [ -n "$CRUPEST_AUTO_CERTBOT_POST_HOOK" ]; then - printf "You have defined a post hook:\n%s\n" "$CRUPEST_AUTO_CERTBOT_POST_HOOK" - options=("${options[@]}" --post-hook "$CRUPEST_AUTO_CERTBOT_POST_HOOK") -fi - -# Use test server to test. -certbot certonly --force-renewal --test-cert --dry-run "${options[@]}" - -function check_and_renew_cert { - expire_info=$(openssl x509 -enddate -noout -in "$CRUPEST_CERT_PATH") - - # Get ssl certificate expire date. - expire_date=$(echo "$expire_info" | cut -d= -f2) - - echo "SSL certificate expire date: $expire_date" - - # Convert expire date to UNIX timestamp. - expire_timestamp="$(date -d "$expire_date" +%s)" - - # Minus expire timestamp with 30 days in UNIX timestamp. - renew_timestamp="$((expire_timestamp - 2592000))" - echo "Renew SSL certificate at: $(date -d @$renew_timestamp)" - - # Get rest time til renew. - rest_time_in_second="$((renew_timestamp - $(date +%s)))" - rest_time_in_day=$((rest_time_in_second / 86400)) - echo "Rest time til renew: $rest_time_in_second seconds, aka, about $rest_time_in_day days" - - # Do we have rest time? - if [ $rest_time_in_second -gt 0 ]; then - # Sleep 1 hour. - echo "I'm going to sleep for 1 day to check again." - sleep 1d - else - # No, renew now. - echo "Renewing now..." - - if [ -n "$CRUPEST_AUTO_CERTBOT_RENEW_COMMAND" ]; then - $CRUPEST_AUTO_CERTBOT_RENEW_COMMAND - else - certbot certonly "${options[@]}" - fi - fi -} - -# Run check_and_renew_cert in infinate loop. -while true; do - check_and_renew_cert -done diff --git a/docker/auto-certbot/get-cert-domains.py b/docker/auto-certbot/get-cert-domains.py deleted file mode 100755 index 9bd28c8..0000000 --- a/docker/auto-certbot/get-cert-domains.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import os -from os.path import * -from cryptography.x509 import * -from cryptography.x509.oid import ExtensionOID - -# Check only one argument -if len(sys.argv) != 2: - print("You should only specify one argument, aka, the path of cert.", - file=sys.stderr) - exit(1) - -cert_path = sys.argv[1] - -if not exists(cert_path): - print("Cert file does not exist.", file=sys.stderr) - exit(2) - -if not isfile(cert_path): - print("Cert path is not a file.") - exit(3) - -if not 'CRUPEST_DOMAIN' in os.environ: - print("Please set CRUPEST_DOMAIN environment variable to root domain.", file=sys.stderr) - exit(4) - -root_domain = os.environ['CRUPEST_DOMAIN'] - -with open(cert_path, 'rb') as f: - cert = load_pem_x509_certificate(f.read()) - ext = cert.extensions.get_extension_for_oid( - ExtensionOID.SUBJECT_ALTERNATIVE_NAME) - domains: list = ext.value.get_values_for_type(DNSName) - domains.remove(root_domain) - domains = [root_domain, *domains] - print('\n'.join(domains)) diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile index 86052b9..67d41d1 100644 --- a/docker/nginx/Dockerfile +++ b/docker/nginx/Dockerfile @@ -7,3 +7,6 @@ RUN pnpm install --frozen-lockfile && pnpm run build FROM nginx:mainline COPY --from=build-www /sites/www/dist /srv/www ADD sites/www/favicon.ico /srv/www/favicon.ico +RUN apt update && apt-get install -y tini certbot && rm -rf /var/lib/apt/lists/* +ADD --chmod=755 certbot.bash nginx-wrapper.bash /app/ +CMD ["/usr/bin/tini", "--", "/app/nginx-wrapper.bash"] diff --git a/docker/nginx/certbot.bash b/docker/nginx/certbot.bash new file mode 100644 index 0000000..0b8e3b7 --- /dev/null +++ b/docker/nginx/certbot.bash @@ -0,0 +1,9 @@ +#!/usr/bin/bash + +set -e + +while true; do + certbot renew --deploy-hook "nginx -s reload" + echo "Sleep one day before next certbot renew." + sleep 1d +done diff --git a/docker/nginx/nginx-wrapper.bash b/docker/nginx/nginx-wrapper.bash new file mode 100644 index 0000000..bd566aa --- /dev/null +++ b/docker/nginx/nginx-wrapper.bash @@ -0,0 +1,7 @@ +#!/usr/bin/bash + +set -e + +/app/certbot.bash & + +nginx "-g" "daemon off;" diff --git a/templates/docker-compose.yaml.template b/templates/docker-compose.yaml.template index 9005d5e..ea3e425 100644 --- a/templates/docker-compose.yaml.template +++ b/templates/docker-compose.yaml.template @@ -23,8 +23,10 @@ services: volumes: - "./generated/nginx/conf.d:/etc/nginx/conf.d:ro" - "./generated/nginx/common:/etc/nginx/common:ro" - - "./data/certbot/certs:/etc/letsencrypt:ro" + - "./data/certbot/certs:/etc/letsencrypt" - "./data/certbot/webroot:/srv/acme:ro" + - "./data/certbot/data:/var/lib/letsencrypt" + - "./data/certbot/webroot:/var/www/certbot" - "blog-public:/srv/www/blog:ro" restart: on-failure:3 @@ -42,29 +44,6 @@ services: - "./generated/v2ray-config.json:/etc/v2fly/config.json:ro" restart: on-failure:3 - auto-certbot: - pull_policy: build - depends_on: - - nginx - build: - context: ./docker/auto-certbot - dockerfile: Dockerfile - pull: true - args: - - CRUPEST_DOMAIN=@@CRUPEST_DOMAIN@@ - - CRUPEST_EMAIL=@@CRUPEST_EMAIL@@ - - CRUPEST_AUTO_CERTBOT_ADDITIONAL_PACKAGES=docker-cli - - CRUPEST_AUTO_CERTBOT_POST_HOOK=docker restart nginx - tags: - - "crupest/auto-certbot:latest" - volumes: - - "./data/certbot/certs:/etc/letsencrypt" - - "./data/certbot/data:/var/lib/letsencrypt" - - "./data/certbot/webroot:/var/www/certbot" - # map docker socket to allow auto-certbot to restart nginx - - "/var/run/docker.sock:/var/run/docker.sock" - restart: on-failure:3 - auto-backup: pull_policy: build build: |