Skip to content

Instantly share code, notes, and snippets.

@EClaesson
Created July 2, 2026 15:05
Show Gist options
  • Select an option

  • Save EClaesson/82c786f94fbae657f0a4b2777bca128c to your computer and use it in GitHub Desktop.

Select an option

Save EClaesson/82c786f94fbae657f0a4b2777bca128c to your computer and use it in GitHub Desktop.
Gluetun VPN tunnel reconnection
#!/usr/bin/env bash
set -u
# EXEC_CONTAINER must share gluetun's netns (Network=container:gluetun) AND have curl.
# The gluetun image itself has no curl (only wget without PUT support), which is why a sidecar is used for the API calls.
EXEC_CONTAINER="my-container"
GLUETUN_CONTAINER="gluetun"
GLUETUN_CONTROL_API_BASEURL="http://127.0.0.1:8000"
MAX_CONN_WAIT_SEC=180
echo "Stopping tunnel..."
podman exec "$EXEC_CONTAINER" curl -s -X PUT -d '{"status":"stopped"}' "$GLUETUN_CONTROL_API_BASEURL"/v1/vpn/status > /dev/null
until podman exec "$EXEC_CONTAINER" curl -s "$GLUETUN_CONTROL_API_BASEURL"/v1/vpn/status | grep -q stopped; do sleep 1; done
echo "Starting tunnel..."
podman exec "$EXEC_CONTAINER" curl -s -X PUT -d '{"status":"running"}' "$GLUETUN_CONTROL_API_BASEURL"/v1/vpn/status > /dev/null
until podman exec "$EXEC_CONTAINER" curl -s "$GLUETUN_CONTROL_API_BASEURL"/v1/vpn/status | grep -q running; do sleep 1; done
echo "Waiting for connectivity..."
deadline=$((SECONDS + MAX_CONN_WAIT_SEC)); ip=""
until ip=$(podman exec "$GLUETUN_CONTAINER" wget -qO- "https://api.ipify.org?format=json" 2> /dev/null | jq -r ".ip // empty"); [ -n "$ip" ]; do
if (( SECONDS > deadline )); then
echo "Deadline exceeded"
exit 1
fi
sleep 1
done
elapsed=$((SECONDS - (deadline - MAX_CONN_WAIT_SEC)))
echo "Got connectivity after $elapsed seconds"
echo "New exit IP: $ip"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment