Ubuntu for a Mac Developer

I've been a Linux enthusiast as far back as 2003, starting out with an early Fedora build, then Debian, then on to Ubuntu's Warty Warthog release to free me from Windows XP and to learn about the technology that powered the internet that I love so much. I ended up absolutely loving it, and dove into things like kernel compiling and Xorg configuration with great joy. The level of customization was incredible, and I was able to experiment with different workflows and desktop environments to find the one that fit me best.

It certainly wasn't without peril, and the amount of times I had to reconfigure the graphical system after a minor package update just to regain access to my desktop definitely became frustrating over time. (This is no longer such a big issue in modern times, thankfully.) When I started pursuing contract development work in 2008, I decided that I needed to get a Mac to gain experience with its unfamiliar environment and be ready to use it with teams that were Mac-only. I found a system that I didn't have to think about customizing, and despite some craziness with early package managers like Fink and MacPorts I was able to set up a very effective development environment.

For the next 11 years, Mac was my primary environment because I wanted to focus on other things. I became a full-time developer, joined a web consultancy, transitioned from back-end to front-end, and tried (and failed) to launch my own consultancy. After all that, I'm finally in a place where I'm ready to take control of my tools again and fully customize everything to be exactly the way I want it.

The Year of the Linux Desktop

Nearly every year, at least one tech news outlet declares that "20XX is the year of the Linux desktop!" The reality is that Linux may never see mass appeal, so the year of the Linux desktop may never be coming. (That is, unless Microsoft decides to "embrace & extend" open source and switch to a proprietary Microsoft Linux because of all their headaches keeping Windows 10 stable. 🤣)  That's okay, though. I'm interested more in its appeal for a specific (yet growing) niche of the population - developers.

Customization aside, using Linux for your primary development machine can have a variety of benefits. You're much closer to your production environment than in the BSD-derived Mac environment. Installing the same packages with the same package manager that you use in your remote systems can help you gain a much greater understanding of how they are configured and run once you deploy them. Config issues and version incompatibilities can be identified along the way during development, can be addressed right away without having to deploy code to a remote server.

Actively supporting Linux development for your team also lowers a barrier of entry for new talent. There are many who can't afford or refuse to pay the premium prices of Apple, or don't like the tightly held proprietary nature of it. This doesn't diminish their ability to code or meet engineering deadlines, however. It can be very beneficial to spend some time supporting alternate development environments so that you can be open to the best candidates for the job, rather than limiting your pool to those who are familiar with OS X.

A Paradigm Shift

If you are familiar with OS X, however, Linux can be a big shift. Suddenly, there's no Command button and the Windows/Super key doesn't act the same way at all. Half of your favorite development tools only run on Mac so you need to go looking for alternatives. Trusted tools like a Magic Trackpad act odd or don't work at all. Mac users do indeed think differently than PC users, but after some searching and customization I was able to find an effective compromise.

The following notes will introduce you to a few of the tweaks that helped me become comfortable and productive on an Ubuntu 19.04/19.10 system after spending 11 years developing software on a Mac.

The Keyboard

In OS X, the key combos <Command>c and <Command>v are used for copy & paste. This leads to thumb-based muscle memory rather than pinkie-based memory. Your thumb is typically stronger and can be employed more confidently than your pinkie, so I find I'm much faster with the Mac paradigm.

To resolve this in Ubuntu, I use some custom keyboard tweaks. These should work in Ubuntu 18.04 and beyond, but they may be successful in earlier versions as well.

First, I define an xkb symbol option at /usr/share/X11/xkb/symbols/altdev, using the altwin file in the same directory as inspiration:

// Alt is Ctrl, Win is Meta, Ctrl is Super, R-Ctrl is Meta
partial modifier_keys  
xkb_symbols "win_keys" {  
    key <LALT> { [ Control_L, Control_L ] };
    key <LWIN> { [ Alt_L, Meta_L ] };  
    key <LCTL> { type[Group1] = "ONE_LEVEL",
                 symbols[Group1] = [ Super_L ] };
    key <RALT> { [ Control_R, Control_R ] };
    key <RCTL> { [ Alt_R, Meta_R ] };
};

// Super is Ctrl, Ctrl is Super
partial modifier_keys  
xkb_symbols "mac_keys" {    
    key <LWIN> { [ Control_L, Control_L ] };
    key <RWIN> { [ Control_R, Control_R ] };
    key <LCTL> { type[Group1] = "ONE_LEVEL",
                 symbols[Group1] = [ Super_L ] };
    modifier_map Control { <LWIN>, <RWIN> };
};

The difference between the two options here depends on whether I'm using a Mac-based keyboard (like their wireless device) or PC-based keys. The layout is slightly different, but I have adjustments either way. With these tweaks:

  • Alt, which is positioned in the same place as Command on PC keyboards, is remapped to Control. This allows for the quick thumb-based muscle memory for copying and pasting to be preserved.
  • Super (or Win) becomes Alt (or Meta), as on a Mac keyboard.
  • Control becomes Super, providing for easy use of Gnome shortcuts and other things using the pinkie finger.

Next, I add it to the xkb rules database at /usr/share/X11/xkb/rules/evdev under ! option = symbols:

  altdev:win_keys = +altdev(win_keys)
  altdev:mac_keys = +altdev(mac_keys)

Make it available by editing /usr/share/X11/xkb/rules/evdev.lst (I typically search for "altwin" and place these lines underneath):

  altdev:win_keys     Windows Keyboard
  altdev:mac_keys     Mac Keyboard

Then, I edit /usr/share/X11/xkb/rules/evdev.xml to make them available via the Gnome Tweak Tool under Keyboard & Mouse ➡ Additional Layout Options:

    <group allowMultipleSelection="false">
      <configItem>
        <name>altdev</name>
        <description>Developer customizations</description>
      </configItem>
      <option>
        <configItem>
          <name>altdev:win_keys</name>
          <description>Windows Keyboard</description>
        </configItem>
      </option>
      <option>
        <configItem>
          <name>altdev:mac_keys</name>
          <description>Mac Keyboard</description>
        </configItem>
      </option>
    </group>

Now, for these changes to take effect and the new options to show up in the Tweak tool for you to enable, you need to log out and back in.

Magic Trackpads

The Magic Trackpad support on Ubuntu is slightly off, requiring much more pressure to register input than it should. To correct this, create the file /etc/libinput/local-overrides.quirks:

[Touchpad touch override]
MatchUdevType=touchpad
MatchName=*Magic Trackpad 2
AttrPressureRange=2:0

The Terminal

The core of any developer's system is the terminal. No matter what operating system I use today, the terminal is one of the first things I take time to customize so that it feels just right. With Ubuntu, the built-in gnome-terminal is the primary offering, though tilix is gaining quite a bit of popularity for its tiling features.

As mentioned earlier, in OS X popular terminals use <Command>c and <Command>v for copy & paste as is standard across the desktop environment. This allows them to easily differentiate between <Command>c for copying and <Control>c for sending the break command to the terminal. On a PC, there is no such differentiation. PC's use <Control>c and <Control>v for copy & paste, directly conflicting with control characters for the terminal. With the keyboard layout changes above, I can get back to Mac-style terminal interactions easily by making these changes to my gnome-terminal shortcuts:

With this configuration, any conflicting control sequence (like <Control>c) is automatically remapped to add the Shift button (like <Shift><Control>c).

One final note - to bring back the useful open command from the Mac CLI:

sudo ln -s /usr/bin/xdg-open /usr/bin/open

The Shell

I'm an avid zsh user, and I love the antigen plugin system for it. If you're curious about my dotfiles like zshrc and zshenv, check out my repo here.  Installing them both on Ubuntu led to an odd problem, however. The contents of antigen.sh are mostly empty. 😕 Here's how I install both to work around the issue:

sudo apt install curl zsh zsh-antigen
sudo curl -o /usr/share/zsh-antigen/antigen.zsh -sL git.io/antigen

To enable it, run chsh -s /usr/bin/zsh and then log out and back in. If you have trouble, try a full restart.

Service Discovery

Apple's Bonjour discovery is very convenient in the Mac world so access other computers on your network with the .local hostname suffix. To get the same experience on Ubuntu, install these packages:

sudo apt-get install avahi-daemon avahi-discover avahi-utils libnss-mdns mdns-scan

Firefox Touch Scrolling

If you have a fun convertible laptop like my Dell XPS 2-in-1, you might want to enable proper touch input in Firefox. Edit /etc/environment, and add the following variable:

MOZ_USE_XINPUT2=1

After a restart, your swipes should register nicely in Firefox!

To Linux, and beyond!

Hopefully these tips help you become just as comfortable in Linux and Gnome as I have! I'm really enjoying my return to Ubuntu as I migrate from Apple, and I'm really excited to see how the niche continues to develop over time. Whether the year of the Linux desktop ever arrives or not, I think I'm here to stay.