About
Linux
Enable Booting from Snapshots in Linux Mint with BTRFS
One of the most powerful features of BTRFS is the ability to boot directly from snapshots, providing an excellent disaster recovery solution. After setting up BTRFS with proper subvolume structure, here’s how to enable snapshot booting in Linux Mint.
Installing grub-btrfs
The grub-btrfs utility automatically detects BTRFS snapshots and adds them to your GRUB menu:
git clone https://github.com/Antynea/grub-btrfs.git
cd grub-btrfs/
sudo make install
Configuring the Service
Configure the grub-btrfs daemon to work with Timeshift snapshots:
sudo systemctl edit --full grub-btrfsd
Modify the ExecStart line to:
ExecStart=/usr/bin/grub-btrfsd --syslog --timeshift-auto
This configuration automatically detects Timeshift snapshots without needing to specify a custom path.
Enabling the Service
Start and enable the service:
sudo systemctl restart grub-btrfsd
sudo systemctl enable grub-btrfsd
Updating GRUB Configuration
Finally, update your GRUB configuration to include the snapshots:
sudo grub-mkconfig -o /boot/grub/grub.cfg
How It Works
- The
grub-btrfsdservice runs in the background, monitoring for new snapshots - Each time a snapshot is created (manually or via Timeshift schedules), it’s automatically added to the GRUB menu
- On reboot, you’ll see additional boot entries for each available snapshot
- Booting from a snapshot provides a perfect recovery option if system updates or changes cause issues
Important Notes
- Ensure your BTRFS structure follows the recommended layout with separate subvolumes
- Timeshift snapshots should be stored in the
@snapshotssubvolume at the BTRFS filesystem root - Regular GRUB updates are required to include newly created snapshots in the boot menu
This setup transforms your Linux Mint installation into a resilient system where any problematic change can be instantly reverted by simply rebooting into a previous snapshot.
Automating Snapshots with timeshift-autosnap-apt
To enhance my BTRFS snapshot strategy, I’ve implemented timeshift-autosnap-apt which automatically creates snapshots before APT operations.
Installation Process
Installed it from source because it’s not official, I did an enhancement request on the mint repo.
git clone https://github.com/wmutschl/timeshift-autosnap-apt.git /home/$USER/Applications/timeshift-autosnap-apt
cd /home/$USER/Applications/timeshift-autosnap-apt
sudo make install
How It Works
- Automatically creates Timeshift snapshots before any APT operation (install, upgrade, remove)
- Integrates seamlessly with existing APT commands - no changes to your workflow needed
- Works in conjunction with your existing grub-btrfs setup for bootable snapshots
Benefits
- Exactly when it’s most important, a snapshot is made
- Automatic recovery points without manual intervention
- Perfect complement to scheduled Timeshift snapshots
- If an update breaks something, simply reboot into the pre-update snapshot
This tool combined with your existing BTRFS and grub-btrfs setup creates a robust, self-healing system similar to the one implemented in OpenSUSE Tumbleweed, made with zypper and snapper.
btrfs on Debian
Debian is awesome, nontheless some adjustments are needed. I restored my system to integrate btrfs and automatic snapshot. Just remember some pitfalls:
- Automatic partitioning is going to use ext4, so work with gparted to prepare in advance all the partitions.
@and@homesubvolumes are generated automatically, then at first boot you’ll need to manually create at least a subvolume for/var/logand one for snapshots. If using Timeshift, then snapshots will go in/timeshift-btrfsmandatory. Beware to not create subvolumes inside the @ subvolume. To create them at top level, first mount @ on /mntwithsudo mount -t btrfs -o subvolid=5 /dev/sda3 /mntthensudo btrfs subvolume create /mnt/@snapshots. Modify/etc/fstabaccordinglyUUID=xxx-yyy-zzz /timeshift-btrfs btrfs defaults,subvol=@snapshots 0 0. Do the same with@log.- Eventually other subvolume could be mounted for other well known directories, like
/tmpor/opt. - Set Timeshift and use a backup utility for
/homefolder. Mint has one preinstalled.
keep the system running
Desktop distributions will likely sleep after 15 minutes on the login screen. A modern alternative approach for disabling suspend and hibernation is to create /etc/systemd/sleep.conf.d/sleep.conf as
[Sleep]
AllowSuspend=no
AllowHibernation=no
AllowSuspendThenHibernate=no
AllowHybridSleep=no
Virtualization
Podman
Podman has been my choice, not only because it’s safer than docker but it’s also very powerful. Daemonless, integrates very well with systemd with quadlets, rootless if needed, and plays well in pods or kubes.
keep containers running
Containers will run until the owner is logged in. To let them run after the ssh session, lingering must be enabled for the user with loginctl enable-linger.
SElinux directory labels
Tip
Read a log of what went wrong with your quadlet:
/usr/lib/systemd/system-generators/podman-system-generator --user --dryrun
Tip
Containers log example:
journalctl --user -xeu caddy.service
Warning
In rootless mode, always use
systemctl --user <command>to enable new containers
Apache
Start an Apache container for fast development
podman run --rm \
-v "$PWD":/usr/local/apache2/htdocs/ \
httpd:latest
Caddy
A fair Caddy quadlets set:
#caddy.network
[Network]
NetworkName=caddy.network
#caddy_config.volume
[Volume]
VolumeName=caddy_config
#caddy_data.volume
[Volume]
VolumeName=caddy_data
#caddy.container
[Unit]
Description=Caddy OVH
[Container]
ContainerName=caddy
Image=localhost/caddy-ovh:2
Volume=%h/.config/containers/storage/caddy/conf:/etc/caddy
Volume=%h/.config/containers/storage/caddy/sites:/srv
Volume=%h/.config/containers/storage/caddy/logs:/var/log/caddy
Volume=caddy_data:/data
Volume=caddy_config:/config
PublishPort=80:80
PublishPort=443:443
Network=caddy.network
Environment=EMAIL=info@epicjourney.dev
Environment=LOG_FILE=/data/access.log
[Service]
Restart=always
[Install]
WantedBy=default.target
generate directories
mkdir -p ~/.config/containers/storage/caddy/{conf,sites,logs}
Containerfile
This quadlet relies on a Caddy instance builded with the ovh dns plugin.
#Containerfile
FROM docker.io/caddy:2-builder AS builder
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
xcaddy build \
--with github.com/caddy-dns/ovh
FROM docker.io/caddy:2
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
Caddyfile
A working OVH configuration plus some trivial websites and reverse proxies. This file runs this website.
{
email info@epicjourney.dev
dns ovh {
endpoint ovh-eu
application_key secret
application_secret secret
consumer_key secret
}
}
www.epicjourney.dev {
redir https://epicjourney.dev{uri} permanent
}
epicjourney.dev {
root * /srv/epicjourney.dev
file_server
encode gzip zstd
}
git.epicjourney.dev {
reverse_proxy forgejo:3000
}
bind privileged ports with rootless containers
I choose this solution
echo "net.ipv4.ip_unprivileged_port_start=80" | sudo tee /etc/sysctl.d/99-unprivileged-ports.conf
sudo sysctl -p /etc/sysctl.d/99-unprivileged-ports.conf
Here is a good explanation with other options
Forgejo
A good quadlet to run Forgejo:
# forgejo.container
[Unit]
Description=Forgejo Rootless Service
[Container]
ContainerName=forgejo
UserNS=keep-id:uid=1000,gid=1000
Environment=USER_UID=1000
Environment=USER_GID=1000
Image=codeberg.org/forgejo/forgejo:14-rootless
Network=caddy.network
PublishPort=2222:2222
Volume=%h/.config/containers/storage/forgejo/conf:/etc/gitea
Volume=%h/.config/containers/storage/forgejo:/var/lib/gitea
Volume=/etc/localtime:/etc/localtime:ro
[Service]
Restart=always
[Install]
WantedBy=default.target
copy this in
.config/containers/systemd/forgejo.container
some considerations
This is to run a rootless container. UserNS is there so that the user inside the container will have the same number as the user outside, or else the volume shall be set owned by user 100999.
Forgejo is served by a reverse proxy, Caddy in this case, so it stays in the proxy’s network.
The conf:/etc/gitea volume is kept empty, but it’s required in the documentation.
create directories
mkdir -p .config/containers/storage/forgejo/conf
MacBook Air 2011
wireless driver
My MacBook Air Mid 2011 has a Broadcom BCM4322 chip, supported by broadcom-wl driver. This driver isn’t mantained anymore, so remember to manually download and install it by some mantained repo. Just search for bcm4322 tumbleweed next time you wipe your system.
coreboot
coreboot with internal flashing
HTML
HTML5 boilerplate
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>HTML5 Blank Template</title>
<meta name="description" content="Basic HTML boilerplate" />
<link href="styles.css" rel="stylesheet" />
</head>
<script src="scripts.js"></script>
<body>
</body>
</html>