From d5791a4ac528965dfd4b6078293e5d350a777598 Mon Sep 17 00:00:00 2001 From: Bram Date: Mon, 3 Aug 2026 21:31:10 +0200 Subject: [PATCH] Enhance gluetun PIA WireGuard rotator with improved rate limit handling and retry logic. Update README to document new RATE_LIMIT_WAIT_SECONDS variable for managing retries after PIA rate limits. --- .../gluetun-pia-wireguard-rotator/README.md | 1 + .../entrypoint.sh | 35 ++++++++++++++++--- .../gluetun-pia-wireguard-rotator/rotate.sh | 30 +++++++++++++--- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/Dockers/gluetun-pia-wireguard-rotator/README.md b/Dockers/gluetun-pia-wireguard-rotator/README.md index 68f3bd6..4e1c306 100644 --- a/Dockers/gluetun-pia-wireguard-rotator/README.md +++ b/Dockers/gluetun-pia-wireguard-rotator/README.md @@ -36,6 +36,7 @@ docker run --rm --entrypoint pia-wg-config bramkel/gluetun-pia-wireguard-rotator | `WG_CONFIG_PATH` | `/config/wireguard/wg0.conf` | Pad waar `wg0.conf` wordt geschreven | | `ROTATOR_STATE_PATH` | `/config/rotator-state.json` | Laatste rotatie-metadata | | `ROTATE_AT` | `03:00` | Dagelijks rotatietijdstip (`HH:MM`, in `TZ`) | +| `RATE_LIMIT_WAIT_SECONDS` | `3600` | Wachttijd bij PIA rate-limit (`429` / `too_many_attempts`) vóór retry | | `TZ` | `Europe/Brussels` | Tijdzone voor scheduling | ## Output diff --git a/Dockers/gluetun-pia-wireguard-rotator/entrypoint.sh b/Dockers/gluetun-pia-wireguard-rotator/entrypoint.sh index 0b423f5..ce9bb23 100644 --- a/Dockers/gluetun-pia-wireguard-rotator/entrypoint.sh +++ b/Dockers/gluetun-pia-wireguard-rotator/entrypoint.sh @@ -28,13 +28,40 @@ sleep_until_next_rotate() { sleep "$wait_s" } +# Matches rotate.sh EXIT_RATE_LIMITED (EX_TEMPFAIL) +readonly EXIT_RATE_LIMITED=75 + +run_rotation() { + local reason="$1" + local wait_s="${RATE_LIMIT_WAIT_SECONDS:-3600}" + local rc + + while true; do + log "$reason" + rc=0 + /usr/local/bin/rotate.sh || rc=$? + case "$rc" in + 0) + return 0 + ;; + "$EXIT_RATE_LIMITED") + log "PIA rate-limited (too many attempts); waiting ${wait_s}s before retry" + sleep "$wait_s" + reason="Retrying rotation after rate-limit wait" + ;; + *) + >&2 echo "Rotation failed with exit code $rc" + return "$rc" + ;; + esac + done +} + log "Starting gluetun PIA WireGuard rotator (TZ=${TZ:-UTC}, ROTATE_AT=${ROTATE_AT:-03:00})" -log "Running rotation on startup" -/usr/local/bin/rotate.sh +run_rotation "Running rotation on startup" while true; do sleep_until_next_rotate - log "Running scheduled daily rotation" - /usr/local/bin/rotate.sh + run_rotation "Running scheduled daily rotation" done diff --git a/Dockers/gluetun-pia-wireguard-rotator/rotate.sh b/Dockers/gluetun-pia-wireguard-rotator/rotate.sh index 9ee463c..d5d9280 100644 --- a/Dockers/gluetun-pia-wireguard-rotator/rotate.sh +++ b/Dockers/gluetun-pia-wireguard-rotator/rotate.sh @@ -130,6 +130,31 @@ write_state() { chmod 644 "$state_path" } +# EX_TEMPFAIL — entrypoint retries after RATE_LIMIT_WAIT_SECONDS +readonly EXIT_RATE_LIMITED=75 + +generate_wg_config() { + local region="$1" + local out="$2" + local output rc=0 + + # Capture stdout+stderr so we can detect PIA 429 rate limits. + output="$(pia-wg-config -v -r "$region" -o "$out" "$PIA_USER" "$PIA_PASS" 2>&1)" || rc=$? + printf '%s\n' "$output" >&2 + + if ((rc == 0)); then + return 0 + fi + + if [[ "$output" == *"too_many_attempts"* || "$output" == *"status 429"* ]]; then + >&2 echo "pia-wg-config rate-limited for region=$region" + return "$EXIT_RATE_LIMITED" + fi + + >&2 echo "pia-wg-config failed for region=$region" + return 1 +} + rotate_once() { require_env PIA_USER require_env PIA_PASS @@ -146,10 +171,7 @@ rotate_once() { local tmp_conf="${tmp_dir}/wg0.conf" log "Generating WireGuard config with pia-wg-config" - if ! pia-wg-config -v -r "$region" -o "$tmp_conf" "$PIA_USER" "$PIA_PASS"; then - >&2 echo "pia-wg-config failed for region=$region" - exit 1 - fi + generate_wg_config "$region" "$tmp_conf" if ! grep -q '^\[Interface\]' "$tmp_conf"; then >&2 echo "Generated config missing [Interface] section"