Last active
January 5, 2026 14:18
-
-
Save aont/a1a83daffe219b0ad6e5d854cd6d2d5a to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| [Unit] | |
| Description=cert & deploy | |
| After=multi-user.target | |
| [Service] | |
| Type=simple | |
| ExecStart=/usr/libexec/acmebot/cert-deploy.sh | |
| EnvironmentFile=/etc/acmebot/env | |
| PrivateTmp=true | |
| [Install] | |
| WantedBy=multi-user.target |
This file contains hidden or 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
| #!/bin/bash | |
| # Must run as root | |
| if (( EUID != 0 )); then | |
| echo "This script must be run as root. Exiting." | |
| exit 1 | |
| fi | |
| set -xe | |
| set -o pipefail | |
| CERTPATH="${ACME_HOME}/${MAIN_DOMAIN}" | |
| local_ip="" | |
| cleanup() { | |
| # Always close port even on failure | |
| echo "[info] upnp port close" 1>&2 | |
| sudo -u"$EXECUTE_USER" -H upnpc -d 80 tcp || true | |
| } | |
| trap cleanup EXIT | |
| # jq is required for this block | |
| echo "[info] getting local address (ip -j route get + jq)" 1>&2 | |
| if ! command -v jq >/dev/null 2>&1; then | |
| echo "[error] jq is not installed. Exiting." 1>&2 | |
| exit 1 | |
| fi | |
| local_ip="$(ip -j route get 1.1.1.1 | jq -r '.[0].prefsrc // empty')" | |
| if [ -z "$local_ip" ] || [ "$local_ip" = "null" ]; then | |
| echo "[error] failed to detect local_ip via ip -j route get" 1>&2 | |
| exit 1 | |
| fi | |
| echo "[info] local_ip=${local_ip}" 1>&2 | |
| # NOTE: This opens WAN:80 -> LAN:80. | |
| echo "[info] upnp port open (WAN 80 -> LAN 80)" 1>&2 | |
| sudo -u"$EXECUTE_USER" -H upnpc -a "${local_ip}" 80 80 tcp 600 | |
| echo "[info] acme.sh (webroot)" 1>&2 | |
| # Check for the existence of acme.sh | |
| if [ ! -x "$ACME_SH" ]; then | |
| echo "[error] acme.sh not found: $ACME_SH" 1>&2 | |
| echo "[hint] install: curl https://get.acme.sh | sh -s email=$EMAIL" 1>&2 | |
| exit 1 | |
| fi | |
| # Expand domain arguments into -d ... | |
| # Normalize DOMAINLIST so that it works whether it is "a,b,c" or "a b c" | |
| DOMAIN_ARGS=() | |
| while read -r d; do | |
| [ -n "$d" ] && DOMAIN_ARGS+=("-d" "$d") | |
| done < <(echo "$DOMAINLIST" | tr ', ' '\n' | sed '/^$/d') | |
| # Issue (or renew): | |
| # --webroot for validation | |
| # --home to fix the acme.sh home under LEPATH | |
| # --accountemail for the account email | |
| # --keylength for RSA 4096 | |
| # | |
| # Important: | |
| # If certificates already exist, they will only be renewed when necessary | |
| # (this is acme.sh behavior) | |
| set +e | |
| sudo -u"$EXECUTE_USER" -H "$ACME_SH" \ | |
| --home "$ACME_HOME" \ | |
| --accountemail "$EMAIL" \ | |
| --issue --webroot "$WEBROOT" \ | |
| --keylength 4096 \ | |
| "${DOMAIN_ARGS[@]}" | |
| ACME_STATUS=$? | |
| set -e | |
| if [ $ACME_STATUS -eq 2 ]; then | |
| echo "[info] acme.sh exited with code $ACME_STATUS (renew not necessary)" 1>&2 | |
| exit | |
| fi | |
| if [ $ACME_STATUS -ne 0 ]; then | |
| echo "[warn] acme.sh exited with code $ACME_STATUS" 1>&2 | |
| exit $ACME_STATUS | |
| fi | |
| # Deployment destinations (aligned with the original script paths) | |
| NGINX_CERT_DIR="/etc/nginx/pki/certs" | |
| IPSEC_PRIV="/etc/ipsec.d/private/privkey.pem" | |
| IPSEC_CACERT="/etc/ipsec.d/cacerts/chain.pem" | |
| IPSEC_CERT="/etc/ipsec.d/certs/fullchain.pem" | |
| echo "[info] install certs (acme.sh --install-cert)" 1>&2 | |
| RELOAD_FLAG="/tmp/.reload-flag-$(date "+%Y%m%d%H%M%S%N")" | |
| # acme.sh install is normally executed only when a renewal occurs | |
| # (intended to be called after --issue) | |
| # Bundle restarts/tests into --reloadcmd so that failures cause acme.sh to fail | |
| "$ACME_SH" \ | |
| --home "$ACME_HOME" \ | |
| --install-cert -d "$MAIN_DOMAIN" \ | |
| --fullchain-file "${NGINX_CERT_DIR}/fullchain.pem" \ | |
| --key-file "${NGINX_CERT_DIR}/privkey.pem" \ | |
| --ca-file "${IPSEC_CACERT}" \ | |
| --reloadcmd "touch '${RELOAD_FLAG}'" | |
| if [[ -f "${RELOAD_FLAG}" ]]; then | |
| nginx -t | |
| systemctl restart nginx | |
| systemctl restart strongswan-starter | |
| rm "${RELOAD_FLAG}" | |
| fi | |
| echo "[info] done" 1>&2 |
This file contains hidden or 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
| [Unit] | |
| Description=Run certbot_update_cert periodically | |
| [Timer] | |
| OnCalendar=*-*-* 00:00:00 | |
| OnCalendar=*-*-* 12:00:00 | |
| RandomizedDelaySec=1h | |
| Persistent=true | |
| [Install] | |
| WantedBy=timers.target |
This file contains hidden or 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
| EXECUTE_USER=acmebot | |
| DOMAINLIST=hoge.ddns.net | |
| MAIN_DOMAIN=hoge.ddns.net | |
| EMAIL=hoge@mail.com | |
| ACME_HOME=/var/lib/acmebot/acme.sh | |
| ACME_SH=/usr/libexec/acmebot/acme.sh | |
| WEBROOT=/var/lib/acmebot/webroot |
This file contains hidden or 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
| #!/bin/bash | |
| # Must run as root | |
| if (( EUID != 0 )); then | |
| echo "This script must be run as root. Exiting." | |
| exit 1 | |
| fi | |
| set -xe | |
| . ./env | |
| mkdir -p --mode=0755 "${WEBROOT}" | |
| mkdir -p --mode=0755 /etc/acmebot | |
| install --mode=0400 ./env /etc/acmebot/ | |
| mkdir -p --mode=0755 /usr/libexec/acmebot/ | |
| install --mode=0555 ./cert-deploy.sh /usr/libexec/acmebot/ | |
| if [[ ! -f "${ACME_SH}" ]]; then | |
| curl -o "${ACME_SH}" https://get.acme.sh | |
| chmod 0755 "${ACME_SH}" | |
| fi | |
| install --mode=0644 cert-deploy.service /etc/systemd/system/ | |
| install --mode=0644 cert-deploy.timer /etc/systemd/system/ | |
| systemctl daemon-reload | |
| systemctl enable cert-deploy.timer | |
| systemctl start cert-deploy.timer |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment