How I Bluefin: Using the ultimate developer Linux

Chicken

Background

I like to develop on the same platform I use for deployment. Most of the time that is Linux. But while my Mac and Windows using coworkers were busy shipping, I often ended up with a workstation loaded with unofficial PPA's that broke every few months and developer tooling that's miles behind macOS.

November 2022

When my buddy Jorge Castro reached out to show me a demo of his Fedora Silverblue concept "Universal Blue" I was skeptical.

Fedora has nothing for me, why would I want to learn how to administer an RPM based system when I have all this time invested in Debian derivatives??

Through patience and persistence Jorge showed me that I was looking at it the wrong way. The whole point of Universal Blue and the Bluefin derivative is that the burden of administration almost disappears. Don't get me wrong, it's still Linux, but it's not the Linux you've used elsewhere. Let's explore the differences:

OSTree Based

Effortless rollbacks.

~ instead of /

$HOME and /etc are writable. Users are forced encouraged to install applications using tools that don't write to the root filesystem.

Alternative Development Tools

Rather than polluting the host with installed libraries and development tools, Bluefin encourages the use of Flatpak, Homebrew, Distrobox, Podman, Docker, Nix, and LXD/Incus.

If I can't install any software, how do I get anything done as a developer? Bluefin encourages you to think of ~ as /. In other words, install apps and tools locally, not globally. Instead interfacing with system libraries and the OS, I move development to run out of my home directory.

For long-term tools that I'll need frequently there's Homebrew. This is where I install ripgrep or neovim or any other system tools I use frequently.

Some of my software development happens in DevContainers powered by Docker. No need to install programming languages and runtimes on the host, they're all specified in the devcontainer configuration and don't pollute the host.

For more complex projects I have Incus to create development containers. I have a folder with a dozen little bash scripts that build base containers of Debian and Ubuntu with Docker and either Homebrew (linux version) or Nix pre-installed. When I start a new project I just run a script that prompts me to choose Debian or Ubuntu, Nix or Homebrew, and less than 10 seconds later I have a container bridged to my LAN that I can connect to locally or from any other system on my network.

Graphical applications are best installed with Flatpak. Bluefin comes with a number of useful flatpak applications already installed and the first run installer gives you the option to install dozens more from Discord to OBS Studio.

The end result: things I install don't break my operating system.

So how can we make the local linux dev story look what Kelsey describes? Linux desktops don't give you what Kelsey wants out of the box ... this is why I work on bluefin-dx, to make this happen. Here's the tools we've selected:

Homebrew

Every Mac developer knows about Homebrew, but a surprisingly low number of Linux developers know that Homebrew is available on Linux as well. All the basic shell tools (ripgrep, starship, etc) I use are installed with Homebrew. In fact I whipped up a lightly opinionated configuration you can install yourself. It's based on the same configurations and tooling that Fleek provides, but without the Nix requirement.

Install with just brew from the terminal. Configure your shell with just brew-shell.

Docker

Bluefin ships with Podman by default, but Bluefin DX adds the option to enable Docker. Podman is awesome, but there are just too many times where the minor incompatibilities and differences are a deal-breaker.

Install with just docker from the terminal.

Incus

Incus - the recent fork of LXD - is my favorite containerization technology. I have a folder with a dozen or so bash scripts that create a base Incus image in both Debian and Ubuntu flavors, then extend each with Nix and Homebrew versions. The scripts add some simple base configurations, like adding my SSH keys to the images, too. I run the script weekly to create fresh base images for new projects. I end up with something like this:

> incus image list -c "ld"
+-------------+-------------+
|    ALIAS    | DESCRIPTION |
+-------------+-------------+
| debian_base | Debian base |
+-------------+-------------+
| debian_brew | Debian brew |
+-------------+-------------+
| debian_nix  | Debian nix  |
+-------------+-------------+
| ubuntu_base | Ubuntu base |
+-------------+-------------+
| ubuntu_brew | Ubuntu brew |
+-------------+-------------+
| ubuntu_nix  | Ubuntu nix  |
+-------------+-------------+

I also have Incus configured to use a host network bridge, so new containers get IP addresses on my LAN. To start a new instance for a project it's just a single command in the terminal:

incus launch -p default -p base ubuntu_brew myapp

Update

I generalized this into a tool called Blincus, so it is even easier now.

This launches the Ubuntu + Homebrew image and gives it the hostname myapp. In less than 5 seconds, the container is started and has an IP address on my network. I can connect locally with incus exec or remotely with ssh ubuntu@myapp. It's a beautiful thing!

Kubernetes

We ship both kubectl and kind on Bluefin DX so you can spin up a cluster in the blink of an eye. Because everyone needs a cluster at some point.

How do you Bluefin?

What is missing here? Your input, your experience, your use-cases. Ping me or let me know in the comments what you use for your dev laptop, we're always looking for new ideas and insights. Bluefin and Bluefin DX are a work in progress. For now, enjoy a linux desktop that still won't get you all the way there, but now that we know what we're building it won't take long, especially with your help.

Project Bluefin

Project Bluefin