├── LICENSE ├── README.md ├── wireguard-rofi.sh └── wireguard.sh /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Kim Brose 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wireguard-rofi-waybar 2 | 3 | This project is intended as a plugin for [Waybar](https://github.com/Alexays/Waybar/) (and [rofi](https://github.com/davatorium/rofi)) users who want to manage their [WireGuard](https://www.wireguard.com/) connections with [NetworkManager](https://wiki.gnome.org/Projects/NetworkManager). 4 | 5 | It consists of 2 components: 6 | 1. `wireguard.sh` is a shell interface to get active and available wireguard connections and toggle them. 7 | 2. `wireguard-rofi.sh` is a scripted rofi custom mode (see `man 5 rofi-script`) 8 | 9 | It should be easy to adapt it for other bars than Waybar or similar as well. You can also simply use only either the indicator part in Waybar or the rofi menu. 10 | 11 | # Usage 12 | 13 | When you're connected to wireguard using NetworkManager, a segment showing the VPN's name and your IP will appear in your Waybar. You can click this segment to open a rofi menu that allows you to connect or disconnect to and from any WireGuard connection available through NetworkManager. 14 | The rofi menu is color coded by connection status (dis/connected). When toggling an action, a notification is sent to your notification daemon by `notify-send`, if you have it installed. 15 | You can also bind a hotkey to call the rofi menu without using the mouse. 16 | 17 | Follow the [installation guide](#Installation) to set this up. 18 | 19 | For information on how to use `wireguard.sh`'s script mode, take a look at its comment header. 20 | 21 | # Requirements 22 | 23 | - [bash](https://www.gnu.org/software/bash/) 24 | - [NetworkManager](https://wiki.gnome.org/Projects/NetworkManager) (specifically `nmcli`) 25 | - for the indicator: [Waybar](https://github.com/Alexays/Waybar/) 26 | - for the toggle menu: [Rofi](https://github.com/davatorium/rofi) or since you're likely using Wayland, [its fork with Wayland support](https://github.com/lbonn/rofi) 27 | - optionally, for notifications: `notify-send` ([libnotify](https://developer.gnome.org/notification-spec/)) and a notification daemon 28 | - optionally, for updating waybar instantly upon dis/connecting: a `pkill` implementation such as the [procps](https://gitlab.com/procps-ng/procps) version, which you likely already have 29 | - optionally, for the `short` format option: `sed` 30 | 31 | I'm personally using it on Arch Linux with the following packages: 32 | 33 | - core/bash 34 | - extra/networkmanager 35 | - community/waybar 36 | - aur/rofi-lbonn-wayland-git 37 | - extra/libnotify 38 | - (community/sway) 39 | - (core/procps-ng) 40 | - (core/sed) 41 | 42 | # Installation 43 | 44 | To install this, simply put wireguard.sh and wireguard-rofi.sh somewhere waybar can read them and make sure they're executable (`chmod 755` or similar). 45 | Your user account also needs access rights to NetworkManager, or `nmcli` to be precise. 46 | 47 | I use this repo as a submodule to my dotfiles at `~/.config/waybar/wireguard-rofi-waybar`. Just take care to adjust the paths appropriately in your config. 48 | 49 | ## Configure Waybar 50 | 51 | This will make a custom segment available to your Waybar. 52 | Leave the `"on-click"` line out if not using rofi. 53 | 54 | ``` 55 | "custom/wireguard": { 56 | "format": "{}", 57 | "exec": "~/.config/waybar/wireguard-rofi-waybar/wireguard.sh", 58 | "on-click": "rofi -modi 'WireGuard:~/.config/waybar/wireguard-rofi-waybar/wireguard-rofi.sh' -show WireGuard", 59 | "interval": 60, 60 | "return-type": "json" 61 | } 62 | ``` 63 | 64 | ### Optional Configuration 65 | 66 | The `pkill` command and `"signal"` are used to instantly update the display after calling the rofi menu by clicking on the Waybar segment, so modify both occurences of the value (`6`) to a signal that is still unused in your Waybar config. 67 | 68 | **Tip**: By default, both the VPN name and client IP are shown. For some smaller screens a more compact format might be desireable, which is supported by the `short` switch if you have `sed` installed. Edit your config to `"exec": "~/.config/waybar/wireguard-rofi-waybar/wireguard.sh short",` to enable it. The complete information is still available via the tooltip! 69 | 70 | **Tip**: You can add more rofi arguments to the `"on-click"` setting if desired, e.g. to set your theme. 71 | 72 | ``` 73 | "custom/wireguard": { 74 | "format": "{}", 75 | "exec": "~/.config/waybar/wireguard-rofi-waybar/wireguard.sh short", 76 | "on-click": "rofi -modi 'WireGuard:~/.config/waybar/wireguard-rofi-waybar/wireguard-rofi.sh' -show WireGuard -theme mytheme; pkill -SIGRTMIN+6 waybar", 77 | "signal": 6, 78 | "interval": 60, 79 | "return-type": "json" 80 | } 81 | ``` 82 | 83 | ## Add hotkey to sway 84 | 85 | I personally use the [sway](https://swaywm.org/) tiled window manager. 86 | You can bind a key combo by using a similar command to the `"on-click"` setting in your Waybar config. 87 | 88 | ``` 89 | # wireguard 90 | bindsym $mod+Shift+w exec "rofi -modi 'WireGuard:~/.config/waybar/wireguard-rofi-waybar/wireguard-rofi.sh' -show WireGuard; pkill -SIGRTMIN+6 waybar" 91 | ``` 92 | 93 | # Contributions 94 | 95 | ... and suggestions are welcome, just open an issue or pull request. 96 | 97 | # See also 98 | 99 | If you use systemd rather than NetworkManager, you might be interested in [wireguard-manager](https://github.com/Klafyvel/wireguard-manager). 100 | -------------------------------------------------------------------------------- /wireguard-rofi.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # WireGuard custom menu script to manage NetworkManager WireGuard connections using rofi 4 | # install to the same directory as wireguard.sh 5 | # example usage with rofi: rofi -modi 'WireGuard:~/.config/rofi/wireguard-rofi.sh' -show WireGuard 6 | 7 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 8 | 9 | if [[ $# != 0 ]] 10 | then 11 | if [[ "$@" == "quit" ]] 12 | then 13 | exit 0 14 | elif [[ "$1" != "reload" ]] 15 | then 16 | connection=$(echo $1 | cut -d: -f1) 17 | message="$($SCRIPT_DIR/wireguard.sh toggle $connection)" 18 | if command -v notify-send >/dev/null 2>&1; then 19 | notify-send "wireguard" "$message" 20 | fi 21 | exit 0 22 | fi 23 | fi 24 | 25 | active=-1 26 | urgent=-1 27 | 28 | while read -r state connection IP 29 | do 30 | if [[ "$state" == "connected:" ]] 31 | then 32 | active=$(($active+1)) 33 | elif [[ "$state" == "available:" ]] 34 | then 35 | urgent=$(($urgent+1)) 36 | fi 37 | if [[ "$IP" != "" ]] 38 | then 39 | connection="$connection [$IP]" 40 | fi 41 | echo -en "$connection\0icon\x1fwireguard\n" 42 | done < <($SCRIPT_DIR/wireguard.sh menu) 43 | 44 | if [[ $active -ge 0 ]] 45 | then 46 | echo -en "\0active\x1f0-$active\n" 47 | fi 48 | if [[ $urgent -ge 0 ]] 49 | then 50 | echo -en "\0urgent\x1f$(($active+1))-$(($active+1+$urgent))\n" 51 | fi 52 | 53 | echo "reload" 54 | echo "quit" 55 | -------------------------------------------------------------------------------- /wireguard.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # nmcli WireGuard abstraction layer for use with my waybar module and rofi custom menu script 4 | # 5 | # requires nmcli on your path 6 | # install to the same directory as wireguard-rofi.sh 7 | # 8 | # usage: ./wireguard.sh [short|menu|toggle NAME] 9 | # no argument: print current connections 10 | # short: print current connections in short format 11 | # menu: print all connections 12 | # toggle NAME: toggle connection NAME 13 | 14 | if ! command -v nmcli >/dev/null 2>&1; then 15 | echo "ERROR: 'nmcli' not found" 16 | echo "This tool is a 'nmcli' frontend, hence you should install NetworkManager before trying to use it." 17 | exit 1 18 | fi 19 | 20 | nargs=$# 21 | get="no" 22 | showmenu="no" 23 | short="no" 24 | dotoggle="no" 25 | if [[ $nargs == 0 ]] 26 | then 27 | get="yes" 28 | elif [[ $nargs == 1 ]] 29 | then 30 | if [[ $1 == "menu" ]] 31 | then 32 | showmenu="yes" 33 | elif [[ $1 == "short" ]] 34 | then 35 | if ! command -v sed >/dev/null 2>&1; then 36 | echo "ERROR: 'sed' not found" 37 | echo "Please install 'sed' to enable the 'short' option." 38 | exit 1 39 | fi 40 | get="yes" 41 | short="short" 42 | fi 43 | elif [[ $nargs == 2 ]] 44 | then 45 | if [[ $1 == "toggle" ]] 46 | then 47 | dotoggle="yes" 48 | conn="$2" 49 | fi 50 | fi 51 | 52 | nmclicmd="nmcli connection" 53 | wgconns="$nmclicmd show" 54 | wgactive="$wgconns --active" 55 | 56 | connected=() 57 | available=() 58 | 59 | function get_conns { 60 | while read -r name uuid type device 61 | do 62 | if [[ $type != "wireguard" ]] 63 | then 64 | continue 65 | fi 66 | 67 | if [[ $device != "--" ]] 68 | then 69 | while read -r key value 70 | do 71 | if [[ $key != "ipv4.addresses:" ]] 72 | then 73 | continue 74 | fi 75 | connected+=("$name: $value") 76 | done < <($wgconns $name) 77 | else 78 | available+=("$name") 79 | fi 80 | done < <($1) 81 | } 82 | 83 | function print_conns { 84 | local first="yes" 85 | local array_print="$1[@]" 86 | local array_print=("${!array_print}") 87 | local text="" 88 | local tooltip="" 89 | if [ "${#array_print[@]}" -le 0 ] 90 | then 91 | return 92 | fi 93 | if [[ "$2" == "list" ]] 94 | then 95 | for c in "${array_print[@]}" 96 | do 97 | echo "$1: $c" 98 | done 99 | else 100 | for c in "${array_print[@]}" 101 | do 102 | if [[ "$first" != "yes" ]] 103 | then 104 | text="$text | " 105 | tooltip="$tooltip\n" 106 | fi 107 | if [[ "$2" == "short" ]] 108 | then 109 | text="$text$(echo -n $c | sed -E 's/^(.+): ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]+)$/\1/')" 110 | else 111 | text="$text$c" 112 | fi 113 | tooltip="$tooltip$c" 114 | first="no" 115 | done 116 | echo "{\"text\": \"$text\", \"tooltip\": \"$tooltip\"}" 117 | fi 118 | } 119 | 120 | function array_contains { 121 | local array_has="$1[@]" 122 | local array_has=("${!array_has}") 123 | local element="$2" 124 | for e in "${array_has[@]}" 125 | do 126 | if [[ "$e" == *"$element"* ]] 127 | then 128 | echo "yes" 129 | return 130 | fi 131 | done 132 | echo "no" 133 | } 134 | 135 | if [[ $get == "yes" ]] 136 | then 137 | get_conns "$wgactive" 138 | print_conns connected "$short" 139 | 140 | elif [[ $showmenu == "yes" ]] 141 | then 142 | get_conns "$wgconns" 143 | print_conns connected "list" 144 | print_conns available "list" 145 | 146 | 147 | elif [[ $dotoggle == "yes" ]] 148 | then 149 | get_conns "$wgconns" 150 | 151 | if [[ "$(array_contains connected $conn)" == "yes" ]] 152 | then 153 | $nmclicmd down "$conn" 154 | elif [[ "$(array_contains available $conn)" == "yes" ]] 155 | then 156 | $nmclicmd up "$conn" 157 | else 158 | echo "err: connection not found" 159 | exit 1 160 | fi 161 | 162 | else 163 | echo "err: wrong args" 164 | exit 1 165 | fi 166 | --------------------------------------------------------------------------------