User Group Growth and COVID-19

I’m a lifelong learner and Linux user. I enjoy teaching as a way to learn things myself; this often leads me to volunteer positions with multiple local tech clubs. Most recently, I’ve become a director at the local UNIX user’s group.

MUUG provides Manitobans with a nearby open-source software mirror. Our $20/year membership fee helps offset the associated costs. The repo mirror and our monthly newsletter are both excellent services – but the main thing that members engage with is the community element of the in-person monthly meeting.

People come from every corner of the city, and from out of town – even from bordering North Dakota and Minnesota – to watch our presentations, eat some snacks, and network with fellow enthusiasts. We are a reasonably active club with some very bright and talented members – if you need to hash out a UNIX or Linux problem in or near Winnipeg, this is the place to come.

Due to COVID-19, we are unable to run our in-person meetups, and members were no longer getting the same value they once were. Membership renewals were starting to suffer; and without membership renewals, we can’t keep our repository servers running (not forever, anyway) – so how do we keep our members engaged in the middle of a global pandemic?

Our first step was to get a virtual meeting platform up and running. To that end, we installed our own Jitsi server with a gracious hosting donation from MERLIN; in fact, the first online presentation we offered was how to install your own Jitsi server. While I won’t say it’s been a perfect experience for every member, it has overall worked very well. We have seen record attendance numbers, as it is now easier to attend the meeting (after all, we do cater to people who like to hack on computers in their basements.)

The modern MUUG presentation, ca. 2021

This approach has been successful at engaging our existing members – but how do we attract new growth to offset members we have already lost? Historically, we have relied on word-of-mouth, people putting up posters in their workspace,, and a basic social media presence. As one of the millennials on the board, it was my sworn duty to suggest we try our hand at social media advertising.

The first step – which social networks do UNIX and Linux nerds like to use most? …we have no idea. While we agreed Twitter may be the platform with the most enthusiasts, the Twitter users among us admitted to hardly ever engaging with ads on the platform. We reasoned that Facebook is as good a platform as any to start with, as we already use it to list our events.

With board buy-in and fertile advertising ground – what are we going to advertise, exactly? We could promote our website in general – but I think most UNIX nerds in Manitoba have already seen that. To deliver the most engagement with prospective members, we elected to advertise our next monthly meeting. We usually have a presentation component as well – so we brainstormed a topical learning event that people care about: “Open source solutions for remote work”. Very apropos for 2021. I provided presentations on Jitsi and wireguard VPN, while my co-director Alberto provided a presentation on Nextcloud and Collabora.

The board settled on a $100 budget, and we opted to run the ad for 2 weeks prior to the meeting. We were able to target multiple relevant demographics, all within the geography of our choice:

  • Interests: System administrator, DevOps, Computer engineering, Network administrator, Mac OS or Linux,
  • Behaviours: Small business owners
  • Employers: Computer science
  • Job title: Unix Systems Administrator 
  • Industry: IT and Technical Services

What were the results?

  • Our ad reached just over 4000 individuals
  • 42 people replied as “going” or “interested”
  • In the period of the ad running and the event itself, we received 5 new membership applications

I don’t recall a better-attended meeting. We had over 35 people in attendance – that’s big for us! We had many newcomers from smaller cities, and we had some excellent discussions during our opening roundtable. People were enjoying themselves. That’s a success in itself.

Do 5 new members sound like a lot? It’s not a huge amount, but it covers our ad expense in the first year alone. Many members stay on for at least 2 years – so I’d call that a great first attempt! We are choosing to wait a few months before running new ad campaigns so that we can judge their efficacy in relative isolation. This helps us cut costs, and ideally, we can figure out which platform gets us the most engagement.

Thank you to Alberto, Brad, and the rest of the MUUG board and membership for working together to keep our humble club a lively one.

Building a Magic Mirror; Nifty Opto-Isolator Tricks

After seeing a critical mass of Magic Mirror builds online, I caved and built one as a Christmas gift for my girlfriend – I made a few innovations on top of the other builds I’ve seen, so I’ve documented them here.  I drew much of the inspiration from Dylan Pierce in particular, so be sure to check out his build log as well!  Here’s the finished product, before wall-mounting:



Build Process:

As I did not have the patience to spec out my own LCD panel, I decided to purchase a used victim TV, and worked from there.  The first step was to pop the bezel off and take a few measurements:




With measurements of the LCD panel itself, I was able to mount the LCD panel in a basic 2×4 frame:


The LCD Panel did not have any usable mounting holes that could mate with the 2×4, so I held it in place with some small angle brackets.

After installing the brackets, I realized the single-screw mounting hole would be prone to rotation – some flank screws made for a quick fix.  Also pictured: speed holes


I eventually added small metal mending plates to sandwich the LCD bezel in the frame (not pictured)

The TV I had cannibalised did not support HDMI/CEC control via the raspi, so I patched in to the power button with an opto-isolator (Sharp PC817).  By using an opto-isolator, the raspi only “sees” an LED as the load, allowing for safe coupling between the raspi and the TV circuitry.  The pin spacing on the PC817 was conducive to patching in directly to the tactile switches.  I also replaced the TV’s “off” LED with an opto-isolator connected in the opposite direction – this lets the raspi know if the TV is on or not.  This is important, because the power button is of the on/off toggle type; the raspi wouldn’t be able to know if it was turning it “on” or “off” otherwise, it would only know that it is changing the state.




Originally, I was going to power the TV on and off via cron job, until a coworker suggested putting a sensor in to turn the mirror on when someone is in front of it.  I just happened to have a spare ultrasonic sensor around, so I mounted it into the frame and wired it up via GPIO pins on the rpi:


With all the electronics connected + working, I glued the fancy mirror-glass in place (Actually, it’s acrylic), and added a nice aesthetic touch with some faux-oak molding and iron-on veneer (ran out of veneer, so the bottom got the thin piece).  I measured the mirror piece to have a 0.5″ margin beyond the viewable LCD portion so that I could affix it to the LCD bezel for a tight fit.  Mirror glass was the same used by Dylan Pierce available at TAP Plastics:

The notch is in place to accommodate a power cable while wall-mounted.  Also pictured: speed holes


The ultrasonic sensors were a bit tricky; I drilled holes in the moulding and adjusted them with a dremel.  They are by no means perfect…



And here’s a view of the rear/electronics – the intention is that this will be wall-mounted, so I didn’t bother with a protective cover.  Zip ties were applied liberally.




Note: The optoisolator / ultrasonic sensor circuitry was soldered onto a piece of perfboard that mated with the RPi’s GPIO header


The base software installation uses raspbian jessie and MagicMirror², and raspbian packages python-gpiozero and wiringpi (i.e. install via sudo apt-get install _____).  All GPIO control code is below.

Note: all .sh and .py files live in /home/pi, the .service files live in /etc/systemd/system/, enable via:

  • cd /etc/systemd/system
  • sudo systemctl enable detect_person.service
  • sudo systemctl enable tv.service

This allows for control via, e.g. sudo service tv [start|stop].  The tv.service serves to turn on the tv during the boot process (as well as for general debugging), while the detect_person service performs the ongoing operation for person detection.   Note that the particulars in need to be tuned to the environment that the mirror is installed in!

I also had to play with some settings /boot/config.txt to get the right screen orientation, see the comments in that file for details.




Using web browser on one interface when multiple are available

In some cases, you need to connect to a VPN to do remote work. Typically this sets the VPN interface to be the default gateway – and so, all your web traffic/etc will route through your VPN connection. This becomes troublesome if your VPN endpoint wont route out to the web.

For example, I’m ssh-ed into some work servers right now, and need the internet to write this awesome blog post. My VPN endpoint at the office does not route any traffic to the web, by design.

To get around this, first add a static route for the subnet associated with your VPN interface

sudo route add -net netmask gw

Then, remove the default route that is trying to shove all your http traffic onto the VPN

sudo route del default

Finally, re-create your default interface to specifically route out your LAN’s gateway

sudo route add default gw

There are probably better ways to configure this – likely, there exists a way to keep the VPN interface from becoming the default gateway – but this is quick and easy 🙂

Mounting a CD from the Linux command line

This is more for my own records than anything else – this is how you mount a CD (or .iso image) from the command line:

mount -t iso9660 /dev/sr0 /mnt #mount a CD/DVD from optical drive
mount -t iso9660 /path/to/file.iso /mnt #mount an .iso file

that is all! Depending on your system, you’ll likely need to use sudo/be root.

Edit: On some distributions (Ubuntu 12.04 server for example), the cdrom device is known as /dev/cdrom instead of /dev/sr0

Rejuvinating an old laptop… with electrical tape

What do you do with a busted laptop?  Many people are quick to throw them away.  Others turn them into FreeNAS boxes, or other useful servers.  For the machine I inherited today, I decided to turn it into an all-in-one style desktop PC.  The screen still worked, it was able to boot windows – the only trouble being that it was in physically rough shape.



Basically, the screen had become detached from the rest of the machine – but all the cables were still in place for it to function.  After some light tweaking, I was able to get the screen to flip around the body of the laptop and sit flat on the reverse side:


But how to keep it in place?  Being impatient and lazy (usually a dangerous combination), I tried my lucking using an entire roll of electrical tape to keep it all together.  Because why not?

Partway through the taping

Being that this thing is going to mount against something on the reverse, I removed the keyboard as well.  So it’s not bumping its keys into stuff all the time.

As luck would have it, I had an old monitor stand kicking around – works as a nice little kickstand. Not perfectly stable, but still more solid than I was expecting:

Starting to take form…

Now all that’s left is to wipe the old Vista install and put on a fresh OS…

Tape starting to lift in the top-right corner, this was later fixed. The answer, of course, was more tape.

A few hours of tinkering, an old laptop, some electrical tape, and a fresh Xubuntu install made for a perfectly good bedroom workstation.  Not bad for one night!

Bash aliases for productivity and memorability

A very quick hack that I’ve found very useful over the years – an alias lets you rename a command, a set of commands, etc.

For example, the ALSA command-line volume control interface, alsamixer, is much more memorable as salsamixer:

alias salsamixer='alsamixer'

Just stick that in your ~/.bashrc file, run a source ~/.bashrc (or log out and back in) and you can run the command salsamixer.  Neat, no?


Another super handy one for debian/ubuntu/mint users:

alias sagi='sudo apt-get install'

Again, append that to your ~/.bashrc file.  Now, you can install software with 16 less keystrokes:

sagi python-mysqldb


Neat, hey?