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:

XMonad - quickstart and intro

XMonad is a minimalist Window Manager written in Haskell. There are plenty of pretty screenshots of various xmonad setups on the net, but as a newbie it's not clear how to use them or how to get started. Say you find yourself in the  XMonad/Config archive page and find a pretty looking screenshot like NNoel's (below):

You install XMonad, update your .xinitrc, restart X and this is what you actually see:

It's a little intimidating to be confronted with this, and it's really tough to know how to go from "I have a blank screen" to "check out my shiny desktop". There's no easy way to get to a Settings/Configuration menu to customise things, and clicking around achieves very little indeed. Even firing up a web browser to google for some guides isn't very obvious. 

I recently went through this whole process, and managed to piece together a nice simple xmonad config. This is a guide to how to go from blank screen to a setup like the below:

We've got a status bar which shows handy things like workspaces, info about any active network interfaces, the usual cpu/memory usage shenanigans, volume (from a slightly hacky script, more on that later) date and the weather where I am. Also the little Tux emoji in the corner is clickable - by default it saves a screenshot of the whole screen, but you can customise it pretty easily since it's just executing a command in the shell.

To get this sort of setup we first need to make sure a couple of fonts are installed - Source Code Pro and Font Awesome. You could just run the commands below, but if you want could find the latest release of Source Code Pro on this page in case there's any updates:

    $ curl -LO https://github.com/adobe-fonts/source-code-pro/archive/2.010R-ro/1.030R-it.tar.gz
    $ tar -xzf 1.030R-it.tar.gz
    $ git clone https://github.com/FortAwesome/Font-Awesome
    $ sudo cp source-code-pro-2.010R-ro-1.030R-it/TTF/*.ttf Font-Awesome/fonts/*.ttf /usr/share/fonts
    $ fc-cache -f -v

Now we can install the necessary packages that we need:

    $ sudo apt-get install xmonad xmonad-contrib xmobar dmenu cabal-install
    $ cabal install xmonad-extras

Finally we can pull down my xmonad config from github

    $ cd && git clone http://github.com/smcl/xmonad .xmonad

Now all the packages are installed, and the Xmonad config is all setup we can restart X and should see something like this

Still a blank screen, but now we have a little status bar. To start with we can bring up an xterm by hitting Windows-Shift-Return:

Obviously from xterm we can launch whatever app we want from here, like firefox:

We can close windows using either some app-specific functionality (Ctrl-Q in firefox, or typing "exit" in xterm), but you can also close the current selected window from XMonad by holding down Windows-Shift-C.

Launching your apps from an xterm could be a little inconvenient, and the terminal itself could fill up with diagnostic messages unless you remember to redirect stderr to /Dev/null each time. 're squeezed side-by-side it's not ideal, plus your xterm will fill up with all sorts of fun diagnostic messages. A better way to work is to launch them using dmenu - a program we installed earlier that let's us launch applications from within monad easily. To bring up dmenu hit Windows-P, if you start typing it'll attempt to autocomplete programs from your PATH:

I tend to use workspaces to organise my windows - so I'll have firefox running on its own in one, then a couple of xterms in another, emacs on its own somewhere else etc. To create a new workspace and switch to it press Windows-1, Windows-2 ... Windows-9. If you're in, say, workspace 1 and you want to move the current window to workspace 2 you can his Windows-Shift-2.

The location used for the weather status is hardcoded in ~/.xmobar/xmobarrc. It's decided by the first arg to "Run Weather" - in my case I've used LKTB, which is the ICAO code for Brno airport. Find your nearest airport's ICAO code using this page and find/replace both instances of LKTB (there should be two) in the file.

Now that the irritating part of XMonad is out of the way, you can see what else you can do by checking out the XMonad tour or take a look at the cheat-sheet below and experimenting. 

I'd also recommend fiddling around with ~/.xmonad/xmobarrc (documentation is here) adding new items to the status bar. Particularly the "Run Com ..." which let's you run arbitrary commands and will display whatever the output was . The reason it might look a little odd is that it's written in Haskell, so you might want to spent a little time with the excellent Learn You A Haskell to get familiar - but honestly you could get pretty far just copy-pasting existing lines and tinkering with them.