├── 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 |
--------------------------------------------------------------------------------