Linux Bridges: Two Things Wearing One Name

The common analogy that a Linux bridge is "like a virtual switch" never quite holds up, and it turns out there's a concrete reason why. When you create a bridge on Linux—say, docker0 for Docker—you actually get two distinct objects:

  1. A bridge in the switching sense: it has no IP address and forwards packets blindly, just like a physical switch.
  2. A network interface with the same name as the bridge, which does have an IP address and can serve as a gateway for containers or VMs attached to it.

Switches don't have IP addresses, so the conflation of these two things is exactly what makes the analogy confusing. The interface part can even be deleted if you want just the pure bridging behavior. The two-in-one nature of brctl and related tools explains a lot of the apparent weirdness.

Fast Ubuntu Boots in Firecracker

Ubuntu Firecracker VMs were taking 2–3 minutes to boot, hanging on the systemd step "Load/Save Random Seed," which relates to kernel entropy. Several common fixes failed:

  • Adding random.trust_cpu=on to kernel boot arguments
  • Setting SYSTEMD_RANDOM_SEED_CREDIT=true or force in systemd-random-seed.service
  • Installing and enabling haveged or rng-tools
  • Disabling systemd-random-seed outright (which should have worked, but didn't in practice)

The solution that finally worked was lowering the timeout in the systemd-random-seed service file to 2 seconds. After that, VMs come up in about 5 seconds. There may be legitimate reasons to keep entropy generation running—for example, so sshd can generate session keys securely—but for now the trade-off is acceptable.

A Go Manager for Firecracker VMs

Instead of spinning up VMs via the DigitalOcean API, the goal was a small Go server that manages Firecracker VMs directly, borrowing heavily from the firectl command-line tool. The resulting code is messier than production-ready, but it works.

Starting a VM is now done with:

echo '{
    "root_image_path":  "/images/ubuntu.ext4",
    "kernel_path":    "/images/vmlinux"
}' | http post http://localhost:8080/create

Stopping it is just as simple:

echo '{"id": "DE52E8A0-C624-18CB-F948-0B50C77C8F4A"}'  | http post localhost:8080/delete

The manager is functional but still needs polish. Notable gaps include:

  • Integrating the Firecracker jailer for stronger security, as firectl does
  • Sending VM serial output somewhere other than stdout
  • Possibly converting to a REST-style interface where a DELETE request stops a VM

The immediate win is that VMs now boot in seconds rather than minutes, and managing them programmatically is no longer tied to a cloud provider's API.