XMonad - NetworkManager menu using xmobar and Tkinter (xnm)

I recently moved to using XMonad semi-fulltime, which is working out nicely most of the time. However the one sticking point is that when I try to work somewhere other than my flat or my office I had to drop to the command line and use nmcli to connect to wifi or to enable my builtin 4G modem.

This is less than ideal, there doesn't appear to by any simple NetworkManager popup/interface I could integrate easily with my xmobar setup - I wanted to have a little icon launch a UI that allowed me to the wifi network to connect to or switch on my 4G modem.

To address this I put together a little python app using Tkinter which updates network connectivity settings through NetworkManager's D-Bus API. The app is launched by clicking an area on Xmobar containing the dynnetwork widget beside a neat little old-school TTY icon:

Clicking this area will raise a menu like the below - listing WiFi and Modem interfaces

Above you can see that /dev/cdc-wdm0 is connected to my "Vodafone CZ" connection - there's a little chain icon beside it. Clicking on this connection would disconnect. Selecting one of the WiFi networks would have either connected automatically (if it was Open) or raised a popup asking for a password (if it was password-protected).

To achieve this you need to do a couple of simple things. Firstly ensure that the necessary dependencies are installed, and checkout the code

    $ sudo apt-get install python-tk python-networkmanager
    $ git clone https://github.com/smcl/xnm

Then ensure your xmobar template has the following line, which will display the dynnetwork info beside a TTY (assuming Font Awesome is installed as Additional Font #1 in xmobar):

<action=`/home/sean/.xmonad/xnm.py`>%dynnetwork% <fn=1></fn></action>

And that's it!

Linux - networking without a UI using nmcli

The XMonad setup I described in this blog post should be functional and extendable enough to get started. However there is one glaring omission - no easy way to configure any wifi or 3G/4G networks you want to connect to. So it's useful to know a little about nmcli, the command-line interface to NetworkManager. This can also be useful if you're futzing around with a linux box remotely.

Fire up an xterm and run the following to check out which network interfaces you have available, and what state they are in:

    $ nmcli dev status
    DEVICE             TYPE      STATE            CONNECTION  
    cdc-wdm0           gsm       disconnected     -- 
    wlan0              wifi      disconnected     --
    F4:31:C3:30:E3:6F  bt        disconnected     --          
    eth0               ethernet  unavailable      --          
    lo                 loopback  unmanaged        --          

So we've five interfaces, none of which are connected to anything. I'll focus on the extremely common use-cases - connecting to open and secured wifi networks using the "wlan0" device, as well as connecting to 3G/4G networks using the "cdc/wdm0" device.

WiFi

To view available networks near you:

    $ nmcli dev wifi list
    *  SSID       MODE   CHAN  RATE       SIGNAL  BARS  SECURITY         
       Rotor bar  Infra  8     54 Mbit/s  72      ▂▄▆_                   
       ahnet      Infra  11    54 Mbit/s  42      ▂▄__  WEP              
       eduroam    Infra  1     54 Mbit/s  15      ▂___  WPA1 WPA2 802.1X 
       vakan      Infra  13    54 Mbit/s  12      ▂___  WEP              
       JAMU       Infra  1     54 Mbit/s  10      ▂___                   

If we want to connect to "Rotor bar" - an open, unsecured network, we can do the following

    $ nmcli device wifi connect "Rotor bar"
    Device 'wlan0' successfully activated with 'ccb0a5a1-ef8d-4fea-966f-7999f2611345'.

If this network was instead secured with the password "123456789" we would instead have used:

    $ nmcli dev wifi con "Rotor bar" password "123456789"

And when we want to disconnect from the WiFi, we can run:

    $ nmcli dev disconnect iface wlan0

And if we wanted to reconnect to this network:

    $ nmcli con up id "Rotor bar"

Mobile Broadband

We can check if you have already set up a Mobile Broadband (3G, LTE, etc seem to be appear as type "gsm") connection :
    $ nmcli connection show | grep gsm
    Vodafone CZ             2756323d-e364-49dc-9d86-92b8c2a44d15  gsm              --     

In my case I'd previously setup "Vodafone CZ" using the NetworkManager applet in XFCE, however if we want to do this in the CLI all we need to do is make sure a config file is present in the /etc/NetworkManager/system-connections folder which has the right setup

    $ sudo cat /etc/NetworkManager/system-connections/Vodafone\ CZ
    [connection]
    id=Vodafone CZ
    uuid=2756323d-e364-49dc-9d86-92b8c2a44d15
    type=gsm
    autoconnect=false
    permissions=
    secondaries=

    [gsm]
    apn=internet
    number=*99***1#
    password-flags=1
    pin=1234

    [serial]
    baud=115200

    [ipv4]
    dns=8.8.8.8;
    dns-search=
    method=auto
 
    [ipv6]
    addr-gen-mode=stable-privacy
    dns-search=
    ip6-privacy=0
    method=auto

So, assuming you're using Vodafone in the Czech Republic you can use this config, tweak the PIN as necessary (it's the SIM PIN, btw) rerun nmcli connection show to check NetworkManager knows about it, and then run the following to bring it up:

    $ nmcli connection up id "Vodafone CZ"
    Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/27)
And to disconnect
    $ nmcli connection down id "Vodafone CZ"
    Connection 'Vodafone CZ' successfully deactivated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/27)

So there we have it - it's possible there's a strange configuration that you need, so you may have to dig into the nmcli man pages - but as long as you have some sort of internet connection I found the followingpages useful: