Immutable/snapshot system?

This commit is contained in:
2026-03-05 03:50:33 -08:00
parent aaf0466521
commit 239f5e37df
9 changed files with 95 additions and 34 deletions
+7 -4
View File
@@ -1,4 +1,7 @@
proc /proc proc defaults 0 0
BOOTDEV /boot vfat defaults 0 2
EFIDEV /boot/efi vfat defaults 0 2
ROOTDEV / ext4 defaults,noatime 0 1
proc /proc proc defaults 0 0
BOOTDEV /boot vfat defaults 0 2
EFIDEV /boot/efi vfat defaults 0 2
ROOTDEV / btrfs defaults,noatime,compress=zstd,subvol=@ 0 1
ROOTDEV /home btrfs defaults,noatime,compress=zstd,subvol=@home 0 2
ROOTDEV /var btrfs defaults,noatime,compress=zstd,subvol=@var 0 2
ROOTDEV /.snapshots btrfs defaults,noatime,compress=zstd,subvol=@snapshots 0 2
+6 -3
View File
@@ -1,3 +1,6 @@
proc /proc proc defaults 0 0
BOOTDEV /boot/firmware vfat defaults 0 2
ROOTDEV / ext4 defaults,noatime 0 1
proc /proc proc defaults 0 0
BOOTDEV /boot/firmware vfat defaults 0 2
ROOTDEV / btrfs defaults,noatime,compress=zstd,subvol=@ 0 1
ROOTDEV /home btrfs defaults,noatime,compress=zstd,subvol=@home 0 2
ROOTDEV /var btrfs defaults,noatime,compress=zstd,subvol=@var 0 2
ROOTDEV /.snapshots btrfs defaults,noatime,compress=zstd,subvol=@snapshots 0 2
+31 -25
View File
@@ -1,30 +1,36 @@
#!/bin/bash
FSTAB_FILE="/etc/fstab"
set -e
if [ "$1" == "enable" ]; then
echo "Enabling read-only mode..."
SUBVOL="/"
# Modify fstab to set root filesystem as read-only
sudo sed -i 's|\(PARTUUID=[^ ]* / .* ext4 \)defaults,noatime|\1ro,noatime|' "$FSTAB_FILE"
# Remount root as read-only
sudo mount -o remount,ro /
echo "System is now read-only. Reboot for changes to persist."
elif [ "$1" == "disable" ]; then
echo "Disabling read-only mode..."
# Modify fstab to set root filesystem as writable
sudo sed -i 's|\(PARTUUID=[^ ]* / .* ext4 \)ro,noatime|\1defaults,noatime|' "$FSTAB_FILE"
# Remount root as writable
sudo mount -o remount,rw /
echo "System is now writable. Reboot for changes to persist."
else
echo "Usage: system-readonly enable|disable"
usage() {
echo "Usage: system-readonly enable|disable|status"
exit 1
fi
}
case "$1" in
enable)
echo "Enabling read-only mode..."
btrfs property set -ts "${SUBVOL}" ro true
mount -o remount,ro "${SUBVOL}"
echo "Root is read-only. Full effect on next reboot."
;;
disable)
echo "Disabling read-only mode..."
btrfs property set -ts "${SUBVOL}" ro false
mount -o remount,rw "${SUBVOL}"
echo "Root is writable."
;;
status)
RO=$(btrfs property get -ts "${SUBVOL}" ro 2>/dev/null | awk -F= '{print $2}')
if [ "${RO}" = "true" ]; then
echo "Read-only: enabled"
else
echo "Read-only: disabled"
fi
;;
*)
usage
;;
esac
+2
View File
@@ -1,6 +1,8 @@
ssh less fbset sudo psmisc strace ed ncdu
console-setup keyboard-configuration debconf-utils parted
build-essential manpages-dev bash-completion gdb pkg-config
btrfs-progs
snapper
python-is-python3
v4l-utils
avahi-daemon
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash -e
# Install snapper config for root subvolume
mkdir -p "${ROOTFS_DIR}/etc/snapper/configs"
install -m 644 files/snapper-root.conf "${ROOTFS_DIR}/etc/snapper/configs/root"
# Register root config with snapper
echo 'SNAPPER_CONFIGS="root"' > "${ROOTFS_DIR}/etc/default/snapper"
# Install apt pre/post snapshot hook
install -m 644 files/apt-snapper-hook "${ROOTFS_DIR}/etc/apt/apt.conf.d/80-snapper"
# Enable snapper timeline timer
on_chroot << EOF
systemctl enable snapper-timeline.timer
systemctl enable snapper-cleanup.timer
EOF
@@ -0,0 +1,2 @@
DPkg::Pre-Invoke { "if [ -x /usr/bin/snapper ] && snapper -c root list >/dev/null 2>&1; then snapper -c root create --type pre --cleanup-algorithm number --print-number --description 'apt'; fi"; };
DPkg::Post-Invoke { "if [ -x /usr/bin/snapper ] && snapper -c root list >/dev/null 2>&1; then snapper -c root create --type post --cleanup-algorithm number --print-number --description 'apt'; fi"; };
@@ -0,0 +1,25 @@
SUBVOLUME="/"
FSTYPE="btrfs"
# Snapshot type
ALLOW_GROUPS="wheel sudo"
SYNC_ACL="yes"
# Timeline snapshots (automatic periodic)
TIMELINE_CREATE="yes"
TIMELINE_CLEANUP="yes"
TIMELINE_MIN_AGE="1800"
TIMELINE_LIMIT_HOURLY="5"
TIMELINE_LIMIT_DAILY="7"
TIMELINE_LIMIT_WEEKLY="0"
TIMELINE_LIMIT_MONTHLY="0"
TIMELINE_LIMIT_YEARLY="0"
# Number snapshots cleanup
NUMBER_CLEANUP="yes"
NUMBER_MIN_AGE="1800"
NUMBER_LIMIT="50"
NUMBER_LIMIT_IMPORTANT="10"
# Exclude /var and /home from root snapshots (they have their own subvolumes)
BACKGROUND_COMPARISON="yes"
+1
View File
@@ -0,0 +1 @@
grub-btrfs
+4 -2
View File
@@ -14,8 +14,10 @@ sed -i 's/#WaylandEnable=false/WaylandEnable=false/' /etc/gdm3/daemon.conf
touch /var/lib/gdm/run-initial-setup
EOF
# polkit fixes
install -m 644 files/polkit-admin.conf "${ROOTFS_DIR}/etc/polkit-1/localauthority.conf.d/51-admin.conf"
# polkit fixes (seems to be rpi only thing)
if [[ "${ARCH}" == "arm64" || "${ARCH}" == "armhf" ]]; then
install -m 644 files/polkit-admin.conf "${ROOTFS_DIR}/etc/polkit-1/localauthority.conf.d/51-admin.conf"
fi
# Include custom vendor file for gnome-inital-setup
mkdir -p "${ROOTFS_DIR}/usr/share/gnome-initial-setup/"