Installing Ubuntu’s snap on Fedora Silverblue

Nelson Aloysio
2 min readMay 3, 2022
Figure: Fedora Silverblue and Canonical’s Snapcraft logos.

Silverblue is an immutable distro, which mounts most of the system’s files as read-only and tracks their changes over time using OSTree — kind of like “git for the OS” — enhancing security and repeatability (great for development!).

As Ubuntu’s snap requires access to the root file system in order to create a symlink in /snap to /var/lib/snapd/snap, successfully installing it requires a few extra steps. Besides, $HOME directory in Silverblue defaults to the more traditional path /var/home/$USER, and since snap expects it to be on its modern location /home/$USER, this must be worked around as well.

Thanks to systemd, though, this is all really easy to achieve. As Silverblue discards top-level changes on host’s restart, let’s first create a new service to make directory folders and replace symlinks in the root file system on boot:

# /etc/systemd/system/mkdir-rootfs@.service
[Unit]
Description=Enable mount points in / for OSTree
DefaultDependencies=no
[Service]
Type=oneshot
ExecStartPre=chattr -i /
ExecStart=/bin/sh -c "[ -L '%f' ] && rm '%f'; mkdir -p '%f'"
ExecStopPost=chattr +i /

Next, we’ll create two additional services. The first will bind mount /snap, in order to work around issue rpm-ostree#337 (thanks, paolope & BreiteSeite!):

# /etc/systemd/system/snap.mount
[Unit]
After=mkdir-rootfs@snap.service
Wants=mkdir-rootfs@snap.service
Before=snapd.socket
[Mount]
What=/var/lib/snapd/snap
Where=/snap
Options=bind
Type=none
[Install]
WantedBy=snapd.socket

Update: Some snaps may require that you instead enable a systemd service to create a symbolic link in /snap (thank you, Laércio de Sousa!):

# /etc/systemd/system/snap-symlink.service
[Unit]
Description=Creates /snap symlink for OSTree
DefaultDependencies=no
[Service]
Type=oneshot
ExecStartPre=chattr -i /
ExecStart=/usr/bin/ln -sf /var/lib/snapd/snap /
ExecStartPost=chattr +i /
[Install]
WantedBy=snapd.socket

We’d already be able to run snaps now, but only as root (e.g. with sudo), which isn’t ideal. To allow snaps to be run by any user, let’s create another service that will bind mount /home, to work around issue snappy#1620771:

# /etc/systemd/system/home.mount
[Unit]
After=mkdir-rootfs@home.service
Wants=mkdir-rootfs@home.service
Before=snapd.socket
[Mount]
What=/var/home
Where=/home
Options=bind
Type=none
[Install]
WantedBy=snapd.socket

Note: as Fedora uses SELinux instead of AppArmor by default, all snap applications run unconfined in the system (that is, in “classic” mode) — which is why this workaround isn’t as feasible to solve the $HOME issue. As far as I know, Ubuntu is the only distro which supports snap confinement.

Lastly, we’ll need to edit our host’s /etc/passwd file in order to update our $HOME directory from /var/home to /home, so snapd will use the new path:

sudo cp /etc/passwd /etc/passwd.bak &&
sudo sed -i 's:/var/home:/home:' /etc/passwd

We may now enable and execute our newly created systemd services:

sudo systemctl daemon-reload &&
for service in home.mount snap.mount snap-symlink.service; do
sudo systemctl enable --now "$service"
done

And that’s it! Snap may now be layered on top of Silverblue with rpm-ostree install snapd or simply re-login if it was already layered before. 🎉

--

--