System Containers
Bluefin Server uses systemd-nspawn system containers for separate Linux
userspaces that share the host kernel. They are not virtual machines, OCI
workloads, or system extensions merged into the host's /usr.
The managed Homebrew environment and a manually added Ubuntu toolbox have separate lifecycles. Run host administration commands from a host shell with root or authorized sudo access. Being the Homebrew owner does not grant general sudo access.
Am I on the host or in a container?
Run these commands in the shell you are unsure about, including inside a tmux pane:
systemd-detect-virt --container
hostname
type -a just brew tmux omp
systemd-nspawnmeans a system container. The hostname identifies the machine:bluefin-homebrewfor the managed Homebrew environment, orubuntufor the example below.none, with a nonzero exit status, means no container was detected. This also applies when Bluefin Server itself runs in a VM;--containerexcludes VM detection.- Your username, home directory and project paths can look identical on both sides. They do not identify the execution environment.
Console and SSH logins start on the host. The Homebrew integration does not move that login shell into a container. It exposes command launchers instead:
/usr/bin/brewdispatches into the Homebrew machine; it is not native Homebrew./var/lib/bluefin-homebrew/commands/<command>also dispatches into that machine. Native host commands earlier inPATHtake priority over these launchers.- Inside the Homebrew machine, brewed programs run directly from
/home/linuxbrew/.linuxbrew.
What about just omp and tmux?
just does not guarantee host execution. If just comes from Homebrew, its
recipe runs inside the Homebrew machine, even when invoked at a host prompt.
With a native host just, individual recipe commands can still enter the guest
through their Homebrew launchers.
A Homebrew-installed tmux runs its server, pane shells and any omp launched in
those panes inside the Homebrew machine. These are not separate containers.
Inspect a custom recipe with just --show omp in the directory where you normally
run it. Bluefin Server does not ship an omp recipe.
Detaching from tmux returns to the shell that attached; exit closes a pane.
Detached sessions survive SSH disconnects, but not a Homebrew machine restart or
host reboot. To administer the host, use a separate host login or return to your
original host shell. Sudo inside a guest is not a way back to the host.
Inspect machines from the host
machinectl list
machinectl list-images
machinectl status bluefin-homebrew
list shows running machines; list-images shows stored images, including ones
that are stopped. An image version such as homebrew_<version>.raw is not the
running machine name bluefin-homebrew.
Manage the Homebrew environment
Setup
The Home Server installer profile provisions the Homebrew environment and its
nonroot owner. See the USB installer guide for installation
and private account/SSH credentials. The profile prepares the machine before
console and SSH login. Do not manually import a second machine named homebrew
for this profile.
The optional homebrew update feature supplies a version-matched machine image
and a homebrew-integration system extension containing the host bridge. Normal
OS updates select the matching immutable machine image without replacing your
installed packages.
The profile also installs tmux and neovim once in the background. Login does
not wait for those packages; a failed installation retries at the next boot.
After the first successful installation, removing a default package does not
cause it to be installed again.
Packages and shared files
Run package operations as the configured nonroot owner, without sudo:
brew list
brew install ripgrep
brew update
brew upgrade
Only the owner may run brew. Other provisioned users can execute installed
tools with a read-only prefix. Automatic Homebrew updates and install-time
cleanup are disabled; run updates and cleanup explicitly.
| Data | Location and persistence |
|---|---|
| Installed packages | Host /var/lib/bluefin-homebrew/prefix, mounted at guest /home/linuxbrew/.linuxbrew; survives machine restarts and OS updates. |
| User homes and configured project roots | Shared read-write at the same paths, with the caller's UID/GID and normal file permissions. |
Guest /var | Persistent under host /var/lib/bluefin-homebrew/guest-var. |
Guest /etc and other overlay changes | Preparation rebuilds guest /etc at host boot or when preparation is rerun, not on a machine-only restart. Other overlay changes are temporary. Edit host configuration from the host. |
Dispatch accepts a working directory in your authorized home or an explicit
PROJECT_ROOTS directory configured by an administrator in the host's root-owned
/etc/bluefin-homebrew.conf. / deliberately maps to the guest root. If a
command reports that its working directory is outside the authorized roots,
return to your home or ask the administrator to configure the project path.
Shared files and the host network make this a trusted toolbox, not a sandbox for untrusted packages. Homebrew-installed Docker/Podman clients use the selected host engine's API; their workloads do not run nested inside the Homebrew machine. See Enabling Extensions for optional host engines.
Status, logs and restarts
Run on the host:
systemctl status bluefin-homebrew.service
journalctl -b -u bluefin-homebrew-prepare.service -u bluefin-homebrew.service
sudo systemctl restart bluefin-homebrew.service
Restarting ends all guest processes, including tmux and omp. It preserves installed packages and shared files. For an intentional stop/start:
sudo systemctl stop bluefin-homebrew.service
sudo systemctl start bluefin-homebrew.service
After changing shared-root configuration, stop the machine, rerun preparation, then start it:
sudo systemctl stop bluefin-homebrew.service
sudo systemctl restart bluefin-homebrew-prepare.service
sudo systemctl start bluefin-homebrew.service
Do not use the generic system-container start/reset workflow for this managed
machine or delete its package prefix to troubleshoot it. To disable the feature,
follow extension removal.
Example: add an Ubuntu container
This creates a separate, writable Ubuntu 24.04 LTS toolbox named ubuntu on
an x86-64 Bluefin Server host. It does not change Homebrew or install Ubuntu
packages into Bluefin. On ARM64, select the arm64 archive instead.
Download and verify the rootfs
In an empty working directory, download the root tarball from the
official release directory.
Do not use the VM .img or the small LXD metadata archive. These commands need
curl, gpg and sha256sum:
base=https://cloud-images.ubuntu.com/releases/noble/release
image=ubuntu-24.04-server-cloudimg-amd64-root.tar.xz
key=D2EB44626FDDC30B513D5BB71A5D6C4C7DB87C81
curl -fLO "$base/$image" &&
curl -fLO "$base/SHA256SUMS" &&
curl -fLO "$base/SHA256SUMS.gpg" &&
curl -fL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x$key" -o ubuntu-cloud-key.asc &&
gpg --import ubuntu-cloud-key.asc &&
gpg --verify SHA256SUMS.gpg SHA256SUMS &&
sha256sum --check --ignore-missing SHA256SUMS
Continue only if the signature and archive checksum checks succeed. Check the signer fingerprint against the one above, published in Ubuntu's verification guide. An uncertified-key trust warning is expected for a newly imported key; the signature must still be good and its fingerprint must match. Verification uses your user GPG keyring; leave Bluefin's OS update trust keyring unchanged.
Import and start Ubuntu
From a host shell, in the directory containing the verified archive:
sudo importctl --class=machine import-tar ./ubuntu-24.04-server-cloudimg-amd64-root.tar.xz ubuntu
sudo install -d -m 0755 /etc/systemd/nspawn
sudo tee /etc/systemd/nspawn/ubuntu.nspawn >/dev/null <<'EOF'
[Exec]
Boot=yes
ResolvConf=replace-host
[Network]
Private=no
VirtualEthernet=no
EOF
sudo system-container start ubuntu
sudo system-container enter ubuntu
importctl imports the verified local file, not its URL, into
/var/lib/machines/ubuntu. machinectl manages the running machine; the
system-container helper wraps its start, poweroff, shell and remove commands.
Entering opens a root Ubuntu shell without needing the cloud image's locked
account password.
This example shares the host network and DNS, so guest services can occupy host ports. Host homes and projects are not shared automatically. Containers share the host kernel; installing an Ubuntu kernel does not replace Bluefin's.
Work inside Ubuntu
These commands run inside Ubuntu, not on the Bluefin host:
hostname
systemd-detect-virt --container
apt-get update
apt-get upgrade
exit
Expect hostname ubuntu and container type systemd-nspawn. After exit, you
are back in the host shell that entered Ubuntu.
Stop, start and autostart
Run on the host:
machinectl status ubuntu
sudo system-container stop ubuntu
stop requests a clean shutdown. Wait until machinectl list no longer lists
Ubuntu before starting it again:
sudo system-container start ubuntu
sudo machinectl enable ubuntu # optional: start at host boot
sudo machinectl disable ubuntu # undo autostart; does not stop it
Packages and files survive stop/start and Bluefin OS updates. Keep Ubuntu updated with apt inside it, independently of Bluefin sysupdate and Brew updates.
Back up, remove or restore Ubuntu
First disable autostart and stop the service synchronously. Then export its filesystem from the host:
sudo machinectl disable ubuntu
sudo systemctl stop [email protected]
sudo importctl export-tar ubuntu ./ubuntu-backup.tar.xz
Reset deletes the entire Ubuntu guest filesystem. Save your data and verify your backup before removing it:
sudo system-container reset ubuntu
sudo rm /etc/systemd/nspawn/ubuntu.nspawn
To restore an exported backup, import it under the same name, recreate the
ubuntu.nspawn configuration above and start it:
sudo importctl --class=machine import-tar ./ubuntu-backup.tar.xz ubuntu