Configurando GRUB: /boot y Btrfs, snapshots.
Actualización: para restaurar el sistema en Arch ya no utilizo snapper rollback, sino este otro script. Para crear snapshots sí que utilizo snapper normal.
He estado instalando Arch con root formateado en Btrfs, incluído /boot. Anteriormente había probado Fedora junto con ese sistema de ficheros, pero el instalador exigía separar /boot en otra partición o volumen con ext4.
Hice un snapshot mediante snapper
. Más tarde quise modificar /etc/grub.d/40_custom
para añadir un nuevo menuentry a GRUB, para un segundo disco duro. Sin embargo, no surtía ningún efecto después de aplicar los cambios tras el habitual grub-mkconfig -o /boot/grub/grub.cfg
y posterior reinicio.
Encontré este hilo en el que un usuario se plantea cómo grub encuentra el fichero grub.cfg
entre varios snapshots/subvolúmenes BTRFS (esto ha cambiado actualmente, como veremos más abajo). Se responde a sí mismo:
I think I’ve figured out what is going on.
Grub will look for grub.cfg in the subvolume that you chrooted to and executed grub-install. So to get grub to read the correct grub.cfg in the correct subvolume:
# mount the BTRFS root subvol
$ mount /dev/sdXY mnt -o subvol=/
# set the default mounting subvol
$ btrfs sub set NNN mnt
# remount the BTRFS partition, it will mount the subvolume set in previous step
$ umount mnt && mount /dev/sdaXY mnt
# chroot into the subvolume
$ arch-chroot mnt /bin/bash
#inside chroot run grub-install
$ grub-install --target=i386-pc /dev/sdX
# Edit grub and remove the rootflags from the linux entry
# Reboot
At this point grub will read grub.cfg from the /.snapshots/ACTIVE/boot/grub/grub.cfg then since there is no rootflags set, it will mount the default subvolume. This allows you to rollback changes with some subvolume renaming and ‘btrfs subvolume set-default’. Also the vmlinuz-linux and initrd will always be the correct versions between kernel updates.
Last edited by zyisrad (2016-03-26 20:50:41)
NOTA: En btrfs sub set NNN <punto_de_montaje>
, set
es una abreviatura set-default
.
En la wiki también se menciona esta reinstalación de grub, haciendo referencia al mismo hilo:
Note: After changing the default subvolume on a system with GRUB, you should run
grub-install
again to notify the bootloader of the changes. See this forum thread.
Como decía antes, este comportaniento ha cambiado en grub 2.02. Ahora, grub buscará grub.cfg en el subvolumen root (id=5), independientemente de que al hacer grub-install nuestro volumen por defecto fuese otro:
This is an attempt to document adding the functionality to Fedora’s GRUB to respect the default subvolume that is set on a btrfs FS when looking for grub.cfg and grub modules. The use case I am interested in for this is to have a single filesystem (the root filesystem
/
) that includes/boot/
and can be snapshotted. If/boot
is included in the snapshot then it is guaranteed to have the right information at the time the snapshot was created. If grub’s core.img respects default subvolumes then all you need to do to rollback to a previous snapshot is to set the default subvolume to that snapshot and reboot. No other work required.NOTE:: This functionailty used to the default in grub but was removed in:
82591fa – Make / in btrfs refer to real root, not the default volume.
https://github.com/dustymabe/fedora-grub-boot-btrfs-default-subvolume/tree/master/fedora24
Sabiendo esto, modifico el grub.cfg del subvolumne raíz. Es decir, hacemos snapper rollback, montamos:
sudo mount /dev/sda1 /mnt/arroba/ -o subvol=/@
NOTA: en mi instalación actual el volumen root es /
, no /@
… y editamos a saco /mnt/arroba/boot/grub/grub.cfg para cambiar el snapshot al que se apunta:
linux /@/.snapshots/X/snapshot/boot/vmlinuz-linux root=[...]
initrd /@/.snapshots/X/snapshot/boot/initramfs-linux.img
…donde X es el snapshot nuevo que snapper ha creado después del rollback:
[j@furin ~]$ sudo btrfs subvolume get-default /
ID 342 gen 47635 top level 265 path @/.snapshots/39/snapshot
Si no aplicamos estos cambios en grub, todo seguirá funcionando bien mientras no actualicemos el kernel (vmlinuz-linux) o initramfs:
EDIT2: Turns out that GRUB (at least the version with F32) does not play nice with snapper after all. The problem is that GRUB uses the kernel and initrd paths relative to the btrfs toplevel (id=5), meaning that if you make a rollback with snapper, the kernel and initrd are loaded from the original subvolume created on installation. Other than that everything works, but if after the rollback there’s a kernel update, nothing will work.
https://www.reddit.com/r/Fedora/comments/hxh3um/btrfs_snapper_users/
También aquí se menciona este peligro:
core.img is only going to point to one /boot, which may not be the /boot snapshot needed for the kernel and initrd. This will be really confusing for mortal users. They’d be unlikely to figure it out and understand it, without documentation.
Una aclaración final: una cosa es el subvolumen donde grub busca el fichero grub.cfg (root, id=5), y otra dónde arranca el SO después, que viene especificado en rootflags=subvol=${rootsubvol}
, dentro de grub.cfg. Puede omitirse y entonces cargará el subvolumen por defecto.
Detalles Arch
Aparte de esto, un par de detalles sobre BTRFS en Arch:
Añadir el subvolumen @/.snapshots
en fstab, montado en /.snaphots
. De lo contrario, perderemos el acceso a /.snapshots
tras hacer snapper rollback, puesto que @/.snapshots
es un subvolumen de @
(ver aquí)
UUID=<UUID> /.snapshots btrfs subvol=@/.snapshots 0 0
En el primer rollback he necesitado poner la opción --ambit classic
. De lo contrario me saltaba este error:
"Cannot detect ambit since default subvolume is unknown"
Ver también este enlace. En rollbacks posteriores no ha sido necesario.
Docker
Docker va creando subvolúmenes en /var/lib/docker/btrfs. Es conveniente crear un volumen para esa ruta y montarlo explícitamente, al igual que hemos hecho para .snapshots. De lo contrario, al hacer rollback nos desaparecerán los contenedores, puesto que los snapshots no incluyen subvolúmenes, y un subvolumen sólo se montará automáticamente cuando estemos en el volumen bajo el que se creó originalmente. Ver más detalles aquí
# /etc/fstab
UUID=<UUID> /var/lib/docker/btrfs btrfs subvol=@docker 0 0