Skip to content

Instantly share code, notes, and snippets.

@BeeFox-sys
Last active December 5, 2025 05:45
Show Gist options
  • Select an option

  • Save BeeFox-sys/6c423850093d56258649aa4f4f8aeb55 to your computer and use it in GitHub Desktop.

Select an option

Save BeeFox-sys/6c423850093d56258649aa4f4f8aeb55 to your computer and use it in GitHub Desktop.
VPN Manager for systems using Mullvad and Tailscale (without the intergreation)
#!/bin/zsh
# Requires: notify-send, Mullvad, Tailscale, ZSH
# Option -n creates system notification
flag_notify=0
zparseopts -D -K -- \
n=flag_notify
status_func () {
echo -e "\033[31;90mTailscale Status:\033[0m"
tailscale status --peers=false
echo -e "\033[31;90mMullvad Status:\033[0m"
mullvad status
}
notify_func () {
if [[ $flag_notify != "0" ]]; then
notify-send -i mullvad-vpn -a "VPN Manager" "$1"
fi
echo "$1"
}
tailscale_status=$(tailscale status --peers=false)
ts_toggle=1
if [[ $tailscale_status == "Tailscale is stopped." ]]; then
ts_toggle=0
fi
#echo $ts_toggle
mullvad_status=$(mullvad status --json | jq -r .state)
mv_toggle=1
if [[ $mullvad_status == "disconnected" ]]; then
mv_toggle=0
fi
#echo $mv_toggle
connect_func () {
tailscale down
mullvad connect
notify_func 'Connected to Mullvad and Disabled Tailscale!'
}
disconnect_func () {
mullvad disconnect
tailscale up
notify_func 'Disconnected from Mullvad and Enabled Tailscale!'
}
run_func () {
if [[ $ts_toggle == 1 && $mv_toggle == 0 ]]; then
eval $1
elif [[ $ts_toggle == 0 && $mv_toggle == 1 ]]; then
eval $2
elif [[ $ts_toggle == 0 && $mv_toggle == 0 ]]; then
eval $3
else
eval $4
fi
}
case $1 in
status)
status_func
;;
up)
run_func \
connect_func \
'notify_func "Mullvad already up!"' \
'notify_func "Both Mullvad and Tailscale Disabled.
Enabling Mullvad!" && mullvad connect'\
'notify_func "Both Mullvad and Tailscale Enabled.
Disabling Tailscale!" && tailscale down'
;;
down)
run_func \
'notify_func "Mullvad already down!"' \
disconnect_func \
'notify_func "Both Mullvad and Tailscale Disabled.
Enabling Tailscale!" && tailscale up'\
'notify_func "Both Mullvad and Tailscale Enabled.
Disabling Mullvad!" && mullvad disconnect'
;;
toggle)
run_func \
connect_func \
disconnect_func \
'notify_func "Both Mullvad and Tailscale Disabled.
Enabling Tailscale!" && tailscale up'\
'notify_func "Both Mullvad and Tailscale Enabled.
Disabling Tailscale!" && tailscale down'
;;
*)
echo "Usage: $0 [-n] {up|down|toggle|status}"
exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment