# 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`. Use `wget -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. Use `while ...; done < <(cmd)` instead.
- `local x=$(cmd); echo $?` always reports 0. Declare the variable first: `local x; x=$(cmd)`.
