A menu script for Docker media containers, with a VPN routing check
If you run a group of media containers (the *arr apps, download clients, flaresolverr and so on), a small menu script saves typing for the common jobs. The most useful part is a check that download clients really leave through the VPN.
Pick the "media" group by name
media_containers() {
docker ps --format '{{.Names}}' |
grep -E 'sonarr|radarr|lidarr|prowlarr|bazarr|sabnzbd|qbittorrent|deluge|transmission|flaresolverr' | sort
}
A simple menu
PS3="Choose: "
select opt in "List containers" "Restart media group" "Check VPN routing" "Quit"; do
case $REPLY in
1) docker ps --format 'table {{.Names}}\t{{.Status}}' ;;
2) read -rp "Restart $(media_containers | wc -l) containers? (y/N) " a
[[ $a == [yY] ]] && media_containers | xargs -r docker restart ;;
3) vpn_check ;;
4) break ;;
esac
done
Ask for confirmation before bulk actions. A "restart all" that also starts stopped containers will bring back anything you stopped on purpose.
Check that download clients use the VPN
Compare the public IP seen from inside each client with the host's own public IP. They should be different.
vpn_check() {
local host_ip c ip
host_ip=$(curl -fsS https://ifconfig.me)
for c in qbittorrent deluge transmission sabnzbd; do
docker inspect "$c" >/dev/null 2>&1 || continue
ip=$(docker exec "$c" curl -fsS --max-time 10 https://ifconfig.me 2>/dev/null) || ip="(no answer)"
if [[ $ip == "$host_ip" ]]; then echo "LEAK $c: $ip (same as host)"
else echo "OK $c: $ip"; fi
done
}
- Many images don't include
curl. Usewget -qO-, or run the check from the VPN container (gluetun) that the clients share. - Inside
[[ ... ]], put spaces before]]. Writing"$ip"]is a syntax error that only shows up when that branch runs.
Small bash pitfalls in scripts like this
- Send status messages to stderr (
>&2) in functions whose stdout you capture with$(...). - Counters set inside
cmd | while ...are lost, because the loop runs in a subshell. Usewhile ...; done < <(cmd)instead. -
local x=$(cmd); echo $?always reports 0. Declare the variable first:local x; x=$(cmd).