Grimoire-
Command
.es

GNU+Linux command memo

OS Debian : from old disk to new disk

1. version en

A few days ago I bought an SSD drive to upgrade a slow machine from its mechanical spinning plates drive.

It was a simple plan :

  • get the old drive out ;

  • plug the two drives to another machine [1] ;

  • move the system from the old disk to the new SSD, partition by partition…

If both drives had the exact same size, a simple dd would have been enough, but let’s assume that the new drive is slightly smaller than the old one…

gparted managed to move the /boot and /boot/efi partitions, located at the beginning of the drive (running a Debian Stretch), but the tool don’t know yet how to work with LUKS encrypted partitions.

So I created a Linux partition, and followed up about the LUKS steps myself :

# cryptsetup luksFormat /dev/sdc3 (1)
WARNING!
========
This will overwrite data on /dev/sdc3 irrevocably.
Are you sure? (Type uppercase yes):  YES
Enter LUKS passphrase:
Verify passphrase:
Command successful.
# cryptsetup luksOpen /dev/sdc3 sdc3_crypt (2)
Enter passphrase for /dev/sdc3:
# pvcreate /dev/mapper/sdc3_crypt (3)
# vgcreate <machine>-vg /dev/mapper_sdc3_crypt (3)
# lvcreate -L 4114612224b -n swap_1 <machine>-vg (4)
# dd if=/dev/<old>-vg/swap_1 of=/dev/<machine>-vg/swap_1 bs=1024K conv=noerror,sync status=progress
# lvcreate -L 495192113152b -n root <machine>-vg
# mkfs.ext4 /dev/mapper/<machine>-vg/root (5)
# mkdir /mnt/new
# mount /dev/mapper/<machine>--vg-root /mnt/new (6)
# rsync -a --stats --progress /mnt/old/ /mnt/new (7)
(8)
1 First, format the partition to make it a LUKS container.
2 Then open the container, which becomes accessible via a regular device file located in /dev/mapper/<nom>.
3 Create there an LVM physical volume, and a volume group.
4 Add LVM logical volumes for the root and swap in this physical volume. To find the size of the partitions I used : lvdisplay /dev/<old>-vg/swap_1 --units b
5 Format the logical volumes as Ext4.
6 Mount them.
7 Copy files via rsync this time, to avoid copying the major empty part of the partition, as dd would have done, and also because the new SSD drive is slightly smaller than the old HDD drive. I’m told that a cp -a would have been faster.
8 Here I omitted the command to mount the old drive in /mnt/old, it’s now an exercise for the reader.

Then, we still have to unmount things :

# umount /mnt/new
# cryptsetup luksClose sdc3_crypt

At this stage, we still miss a grub on the new drive, as it was not contained in the partitions we copied. It’s possible de copy a grub as well via dd on the right sector of the beginning of the drive : dd if=/dev/sdb bs=512 count=1 of=/dev/sdc ; but here I also renamed the LVM physical volume, so anyway I need to recreated an initramfs.

So let’s to go chroot. The usefull commands for this were already described here, and the allow to change the root of a running GNU+Linux system. This will allow us to recreate an initramfs and to launch a grub-install command on the new drive, while it’s still impossible to boot on it yet.

# mkdir /media/disk
# mount /dev/mapper/<machine>--vg-root /media/disk (1)
# mount /dev/sda2 /media/disk/boot (2)
# mount /dev/sda1 /media/disk/boot/efi (2)
# mount -o bind /dev /media/disk/dev
# mount -o bind /sys /media/disk/sys
# mount -o bind /proc /media/disk/proc
# chroot /media/disk
# ls /media (3)
# grub-install /dev/sda && update-grub (4)
1 Here it’s for an encrypted Debian (Jessie, Stretch)
2 Mount non-encrypted boot (and efi) partition if any
3 There is no disk folder anymore, you got in !
4 Optional : to re-install GRUB once chrooted for instance

So for the grub it’s done, now we might have to update partition identifiers in the /etc/fstab (on Ubuntu for instance, using blkid to discover new UUIDs), and then let’s update the initramfs:

# update-initramfs -u
The grub-install command is not too tightly dependent on the running kernel version, but the update-initramfs is. So when using it in a chroot environment one must be careful that the running kernel is compatible with the one of system that will use the generated initramfs.

If everything went well, no error messages where output. Now the simplest way to get out of the chroot is to reboot the host machine (it spares the umount work).

Then, the new drive have to be put back in the machine, and, a disappointment can still show up… as the EFI BIOSes need to find a particular *.efi file on the drive to boot from, to accept to let the execution flow to load from it (with the awaited grub bootloader). That was the reason of this previous note. And to do so, BIOSes need a FAT32 partition on the drive (in /boot/efi for Debian) because the BIOS can’t read anything else than FAT32. Then, the BIOS is not always fitted with an interface to add the *.efi paths to the boot list. So one may :

  • seek this file from a BIOS file explorer at boot time ;

  • run again a # grub-install once Debian loaded, for grub-install to write the missing information directly in the BIOS.

So this is it. The first idea was simple : change the main storage device of a machine ; but it took me farther than expected. It’s still feasible though, and I hope this guide could help you doing it.

2. version fr

Il y a peu, j’ai acheté un SSD pour remplacer le disque dur mécanique, à plateaux tournant, d’un ordinateur portable jugé lent.

Le plan de départ était simple :

  • sortir l’ancien disque de la machine,

  • brancher l’ancien et le nouveau support de stockage sur une machine [2],

  • déplacer le système, du vieux disque au nouveau SSD, partition par partition…

Si les deux disques avaient été exactement de la même taille, un simple dd aurait suffit, mais ici le nouveau disque SSD est légèrement plus petit que le vieux HDD…

gparted a effectivement pu me déplacer la partition /boot et la partition /boot/efi toutes deux situées au début du disque (installé en Debian Stretch) mais l’outil ne sait pas (encore) manipuler des volumes chiffrés LUKS.

Du coup, il faut créer une partition type Linux, et enchainer avec LUKS à la main :

# cryptsetup luksFormat /dev/sdc3 (1)
WARNING!
========
This will overwrite data on /dev/sdc3 irrevocably.
Are you sure? (Type uppercase yes):  YES
Enter LUKS passphrase:
Verify passphrase:
Command successful.
# cryptsetup luksOpen /dev/sdc3 sdc3_crypt (2)
Enter passphrase for /dev/sdc3:
# pvcreate /dev/mapper/sdc3_crypt (3)
# vgcreate <machine>-vg /dev/mapper_sdc3_crypt (3)
# lvcreate -L 4114612224b -n swap_1 <machine>-vg (4)
# dd if=/dev/<old>-vg/swap_1 of=/dev/<machine>-vg/swap_1 bs=1024K conv=noerror,sync status=progress
# lvcreate -L 495192113152b -n root <machine>-vg
# mkfs.ext4 /dev/mapper/<machine>-vg/root (5)
# mkdir /mnt/new
# mount /dev/mapper/<machine>--vg-root /mnt/new (6)
# rsync -a --stats --progress /mnt/old/ /mnt/new (7)
(8)
1 Tout d’abord, formater la partition pour en faire un conteneur LUKS
2 Puis ouvrir ce conteneur, qui devient accessible via le périphérique /dev/mapper/<nom>
3 Créer là un volume physique LVM, ainsi qu’un groupe de volumes.
4 Ajouter les volumes logiques des partitions racine et d’échange dans ce volume physique LVM. Pour trouver la taille des partitions en question, j’ai utilisé : lvdisplay /dev/<old>-vg/swap_1 --units b
5 Formatage du volume logique en EXT4
6 Montage
7 Copie des fichiers utiles via rsync cette fois, pour éviter d’avoir à faire un dd sur l’ensemble du disque qui est principalement vide, et aussi parce que le disque de destination est légèrement plus petit que le disque d’origine. On me rapporte qu’un cp -a aurait été plus rapide.
8 Enfin, j’ai omis les commandes utiles au montage du disque d’origine dans /mnt/old je les laisse en exercice au lecteur.

Ensuite il faut encore tout démonter :

# umount /mnt/new
# cryptsetup luksClose sdc3_crypt

Puis, il manque un grub sur le nouveau disque, vu qu’il n’est pas contenu dans les partitions déplacées ou recopiées. Il est possible de recopier le grub aussi, à coup de dd du bon secteur en début de disque : dd if=/dev/sdb bs=512 count=1 of=/dev/sdc ; mais j’ai aussi renommé mon volume physique dans l’histoire, et avais donc de toutes façons besoin de recréer mon initramfs.

Direction le chroot donc. Cette suite de commandes déjà présentée ici permet de changer la racine de son système GNU+Linux en cours de fonctionnement. Cela va ici permettre de recréer un initramfs pour le nouveau système et d’utiliser la commande grub-install sur le nouveau disque, alors qu’il n’est pour l’instant pas encore possible de démarrer ce nouveau disque.

# mkdir /media/disk
# mount /dev/mapper/<machine>--vg-root /media/disk (1)
# mount /dev/sda2 /media/disk/boot (2)
# mount /dev/sda1 /media/disk/boot/efi (2)
# mount -o bind /dev /media/disk/dev
# mount -o bind /sys /media/disk/sys
# mount -o bind /proc /media/disk/proc
# chroot /media/disk
# ls /media (3)
# grub-install /dev/sda && update-grub (4)
1 Here it’s for an encrypted Debian (Jessie, Stretch)
2 Mount non-encrypted boot (and efi) partition if any
3 There is no disk folder anymore, you got in !
4 Optional : to re-install GRUB once chrooted for instance

Maintenant il faut peut être encore mettre à jour les identifiants de partition dans le fichier /etc/fstab (comme c’est le cas pour Ubuntu qui utilise des UUIDs, qu’on peut découvrir via la commande blkid), et tant qu’on y est, recréons donc l'initramfs :

# update-initramfs -u
Autant le mise à jour du grub est peu dépendante de la version du noyau en cours de fonctionnement (lors d’un chroot), autant la mise à jour de l'initramfs présentée ici nécessite que le système accomplissant la mise à jour tourne sur un noyau compatible avec celui du système qui devra démarrer avec tout seul ensuite.

Si tout se passe sans messages d’erreur, le plus simple (pour s’éviter de démonter tout le chroot), c’est encore de redémarrer : reboot.

Ensuite on place le disque dans la nouvelle machine, et une grosse déception peut encore nous attendre ! En effet, les BIOS EFI ont besoin de savoir trouver un fichier précis sur le disque dur cible, pour accepter de passer la main à un gestionnaire de d’amorçage. D’où ce précédent billet, et le besoin d’une partition /boot/efi formatée en FAT32 (car le BIOS ne sait pas lire autre chose). Ensuite le BIOS ne propose pas forcément une interface permettant de créer une entrée de démarrage depuis ses menus, ce qui oblige à :

  • cherche le fichier *.efi qui va bien à la main depuis les menus du BIOS ;

  • relancer un # grub-install une fois le système démarré pour que ce programme aille écrire l’information utile aux directement dans le BIOS.

Voilà, l’idée de départ était simple : changer le disque dur d’une machine ; mais ça m’aura emmené plus loin que prévu. Ça reste toutefois raisonnablement possible, et j’espère que ce guide vous y aidera.

PS : Voici un article très détaillé sur le sujet, de Lionel Draghi sur LinuxFR.org, qui explore LVM en profondeur ainsi que d’autres options de configuration permettant d’améliorer la durée de vie d’un SSD. LVM permet de réaliser un déménagement de système d’exploitation sans avoir à rebooter la machine (même si en pratique pour un ordinateur portable, il faudra bien physiquement échanger les disques).


1. In practice, if you just want to copy data from one drive to another, you might prefer to plug a backup drive to the machine where the source drive is and get significantly faster transfer rates
2. En pratique, si vous voulez juste copier des données d’un disque à l’autre, vous préfèrerez sûrement brancher un disque de sauvegarde sur la machine contenant le disque source, afin d’obtenir de meilleurs vitesses de transfert.