diff --git a/docker-compose.yml b/docker-compose.yml index 1adfef0..cf150b1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,7 +32,6 @@ services: - 30304:30304/udp - 9005:9005/udp - 127.0.0.1:8003:8003 - - 80:80 #Let's Encrypt - 8000:8000/tcp #WSS - 127.0.0.1:8645:8645 logging: @@ -60,6 +59,7 @@ services: command: - /opt/run_node.sh depends_on: + - certbot - postgres # TODO: Commented until ready @@ -74,6 +74,21 @@ services: # depends_on: # - nwaku + certbot: + image: certbot/certbot + restart: on-failure + ports: + - 80:80 # Let's Encrypt + environment: + DOMAIN: ${DOMAIN} + volumes: + - ./run_certbot.sh:/opt/run_certbot.sh:Z + - ${CERTS_DIR:-./certs}:/etc/letsencrypt/:Z + - ./certbot-challenges:/var/www/certbot + entrypoint: sh + command: + - /opt/run_certbot.sh + prometheus: image: docker.io/prom/prometheus:latest volumes: diff --git a/run_certbot.sh b/run_certbot.sh new file mode 100644 index 0000000..99aa973 --- /dev/null +++ b/run_certbot.sh @@ -0,0 +1,60 @@ +#!/bin/sh +set -e + +if [ -z "$DOMAIN" ]; then + echo "DOMAIN not set, skipping certbot" + exit 0 +fi + +# ------------------------------- +# Configuration +# ------------------------------- +EMAIL="${EMAIL:-admin@${DOMAIN}}" # Certbot email +WEBROOT="${WEBROOT:-/var/www/certbot}" # Path served by HTTP for ACME +SLEEP_INTERVAL="${SLEEP_INTERVAL:-12h}" # Renewal check interval + +# Ensure webroot directory exists +mkdir -p "${WEBROOT}/.well-known/acme-challenge" + +# Path to cert folder +LETSENCRYPT_PATH="/etc/letsencrypt/live/${DOMAIN}" + +# ------------------------------- +# Initial certificate issuance +# ------------------------------- +if [ ! -d "${LETSENCRYPT_PATH}" ]; then + echo "[INFO] No certificate found for ${DOMAIN}, issuing a new one..." + + # Install certbot if needed (Alpine example) + if ! command -v certbot >/dev/null 2>&1; then + echo "[INFO] Installing certbot..." + apk add --no-cache certbot + fi + + certbot certonly\ + --non-interactive\ + --agree-tos\ + --no-eff-email\ + --no-redirect\ + --email admin@${DOMAIN}\ + -d ${DOMAIN}\ + --standalone + + echo "[INFO] Certificate issued successfully." +else + echo "[INFO] Certificate already exists for ${DOMAIN}." +fi + +# ------------------------------- +# Renewal loop +# ------------------------------- +echo "[INFO] Starting renewal loop every ${SLEEP_INTERVAL}..." +while true; do + echo "[INFO] Checking certificate renewal..." + certbot renew --standalone --quiet + # certbot renew --standalone ## Use this line instead to debug the output + echo "[INFO] Renewal check complete. Sleeping..." + sleep "${SLEEP_INTERVAL}" +done + + diff --git a/run_node.sh b/run_node.sh index be8f164..145cdb2 100755 --- a/run_node.sh +++ b/run_node.sh @@ -54,35 +54,40 @@ if [ -z "${DOMAIN}" ]; then fi if [ -n "${DOMAIN}" ]; then + ## A domain has been either set or inferred. Let's try to use it for websocket secure support. - LETSENCRYPT_PATH=/etc/letsencrypt/live/${DOMAIN} + apk add --no-cache openssl - if ! [ -d "${LETSENCRYPT_PATH}" ]; then - apk add --no-cache certbot + LETSENCRYPT_PATH="/etc/letsencrypt/live/${DOMAIN}" + CERT="${LETSENCRYPT_PATH}/fullchain.pem" + KEY="${LETSENCRYPT_PATH}/privkey.pem" - certbot certonly\ - --non-interactive\ - --agree-tos\ - --no-eff-email\ - --no-redirect\ - --email admin@${DOMAIN}\ - -d ${DOMAIN}\ - --standalone - fi + echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] Waiting for a valid TLS certificate for ${DOMAIN}..." - if ! [ -e "${LETSENCRYPT_PATH}/privkey.pem" ]; then - echo "The certificate does not exist. Proceeding without supporting websocket" - else - WS_SUPPORT="--websocket-support=true" - WSS_SUPPORT="--websocket-secure-support=true" - WSS_KEY="--websocket-secure-key-path=${LETSENCRYPT_PATH}/privkey.pem" - WSS_CERT="--websocket-secure-cert-path=${LETSENCRYPT_PATH}/fullchain.pem" - DNS4_DOMAIN="--dns4-domain-name=${DOMAIN}" + while true; do + if [ ! -f "${CERT}" ] || [ ! -f "${KEY}" ]; then + echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] Certificate files not found yet. Waiting..." + elif ! openssl x509 -checkend 0 -noout -in "${CERT}" >/dev/null 2>&1; then + echo "$(date '+%Y-%m-%d %H:%M:%S') [WARN] Certificate exists but is expired. Waiting for renewal..." + echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] If that takes more than 15 minutes, please remove --quiet attr in run_certbot.sh so that you can see the reason why renewal is not working." + else + echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] Valid TLS certificate detected." + break + fi - DNS_WSS_CMD="${WS_SUPPORT} ${WSS_SUPPORT} ${WSS_CERT} ${WSS_KEY} ${DNS4_DOMAIN}" - fi + sleep 60 + done + + WS_SUPPORT="--websocket-support=true" + WSS_SUPPORT="--websocket-secure-support=true" + WSS_KEY="--websocket-secure-key-path=${KEY}" + WSS_CERT="--websocket-secure-cert-path=${CERT}" + DNS4_DOMAIN="--dns4-domain-name=${DOMAIN}" + + DNS_WSS_CMD="${WS_SUPPORT} ${WSS_SUPPORT} ${WSS_CERT} ${WSS_KEY} ${DNS4_DOMAIN}" fi + if [ -n "${NODEKEY}" ]; then NODEKEY=--nodekey=${NODEKEY} fi