Je viens de faire l’acquisition d’un NVME pour mon laptop, je garde cependant mon SSHD de 500Go afin d’y mettre mes données. Plutôt que de faire une copie de mon SSHD vers mon NVME, je me dis que refaire une installation complète pourrait être sympa.
Ce que je veux
Puisque j’ai un laptop que je bouge partout, il faut qu’il soit crypté …. (non je déconne, on dit chiffré, je voulais en faire râler certains ^^), c’est indispensable. J’ai 2 disques, le disque nvme de 250Go sera donc le disque système, et le deuxième de 500Go, sera le disque des partitions home.
Mon laptop est multi-utilisateurs, et je veux absolument que les homes de mes utilisateurs soient chiffrés indépendamment, donc exit crypttab, à la place j’utiliserai pam_mount.
Ensuite je voudrais utiliser btrfs pour entre autre son système de sous-volumes et de snapshots, le but étant de faire un snapshots à chaque modification systèmes.
Pour le reste, ça restera du basique, un environnement MATE, quelques logiciels, quelques tweaks, et ce sera bien.
Pour l’OS, j’ai choisi Wind…. Archlinux, pourquoi ? PARCE QUE !!!!!!
Pourquoi ArchLinux ???
J’ai commencé à utiliser ArchLinux en 2011, et depuis je n’arrive pas à changer de distribution, de temps en temps je me dis que je vais tester autres choses, mais au bout de quelques semaines, je reviens toujours sous Arch (et/ou dérivés).
J’aime Arch pour plusieurs raisons, déjà c’est du Rolling Release, donc toujours à jour, ensuite y’a un nombre de paquets impressionnants dans les repos, ce qui comble 90% de mes besoins (j’ai jamais atteint ça avec les autres distributions), et en plus il y a AUR qui me permets d’atteindre les 99,99%. Pacman, l’outil de gestion des paquets, est très performant, et très rapide, personnellement j’utilise yay, qui permets en plus de gérer les paquets AUR.
De plus ArchLinux à pour moi une petite histoire, c’est avec lui que j’ai mis les mains dedans (même si j’étais linuxiens depuis un moment), mais j’ai appris énormément, et pour moi, Archlinux est le meilleur compromis d’apprentissage entre des distributions dites “simples” (Ubuntu, Fedora, Debian, Mint etc …), et des sources-based comme Gentoo voir un LFS (y’a pas mieux pour l’apprentissage), y’a beaucoup d’action manuelle, mais cela reste accessible.
Installation de base
Préparation du media
Je pars du principe que vous savez récupérer une ISO et booter dessus, pour les plus faignants d’entre vous, vous pouvez la télécharger ici
Avant de commencer, il faut changer la disposition du clavier avec loadkeys (Attention clavier en qwerty de base) :
$ loadkeys fr-pc # donc on tape loqdkeys fr)pc
Puis si comme moi, vous utilisez un laptop, il faudra le connecter au wifi :
$ iwctl
[iwd]# device list
NetworkConfigurationEnabled: disabled
StateDirectory: /var/lib/iwd
Version: 1.28
[iwd]# device list
Devices *
--------------------------------------------------------------------------------
Name Address Powered Adapter Mode
--------------------------------------------------------------------------------
wlan0 XX:XX:XX:XX:XX:XX on phy0 station
[iwd]# station wlan0 scan
[iwd]# station wlan0 get-networks
Available networks *
--------------------------------------------------------------------------------
Network name Security Signal
--------------------------------------------------------------------------------
> myhome_5GHz psk ****
myhome psk ****
[iwd]# station wlan0 connect myhome_5GHz
Type the network passphrase for myhome_5GHz psk.
Passphrase: **************************************
[iwd]# quit
Normalement vous êtes désormais connecté au réseau, pour vérifier, vous pouvez faire un :
$ ip a show dev wlan0
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether XX:XX:XX:XX:XX:XX brd ff:ff:ff:ff:ff:ff
inet 192.168.1.26/24 metric 600 brd 192.168.1.255 scope global dynamic wlan0
valid_lft 86050sec preferred_lft 86050sec
inet6 2a01:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX/64 scope global temporary dynamic
valid_lft 86368sec preferred_lft 568sec
inet6 2a01:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 86368sec preferred_lft 568sec
inet6 fe80::XXXX:XXXX:XXXX:XXXX/64 scope link
valid_lft forever preferred_lft forever
Personnellement, je vais me connecter sur mon laptop en ssh, pour pouvoir copier des commandes plus rapidement, pour ceci il suffit d’ajouter un mot de passe à root :
$ passwd
New password:
Retype new password:
passwd: password updated successfully
et via l’ip local récupéré plus haut, vous pouvez y accéder.
Partitionnement du disque
Comme dis tout à l’heure, je vais chiffrer mon installation, et utiliser btrfs, mais il faut tout de même une partition /boot.
Personnellement, je ne chiffre pas le /boot, pour une raison simple, je n’ai jamais réussi à changer la disposition du clavier à ce stade, donc compliqué pour mon mot de passe. De plus, mon risque de corruption de mon /boot est plutôt faible, puisque c’est mon PC perso, et à part moi, personnes chez moi et dans mes connaissances ne pourraient le faire.
Etrangement, mon NVME est simplement détecté en SSD standard, je l’ai testé sur mon Desktop, et il est pourtant reconnu en NVME. Cela ne bloque en aucun cas la procédure.
Pour le disque system :
$ parted /dev/sdb
(parted) mklabel gpt
(parted) mkpart "EFI system partition" fat32 0% 500MiB
(parted) set 1 esp on
(parted) mkpart "system" btrfs 500MiB 100%
(parted) quit
Pour le home, je vais devoir utiliser lvm, car btrfs ne supporte pas le chiffrement d’un sous-volumes :
$ parted /dev/sda
(parted) mkpart "home" btrfs 0% 100%
(parted) quit
$ pvcreate /dev/sda1
Physical volume "/dev/sda1" successfully created.
$ vgcreate vghome /dev/sda1
Volume group "vghome" successfully created
Pour le moment je ne crée pas de volume logique, nous verrons plus tard pour les homes des utilisateurs.
Chiffrement via luks
On commence par chiffrer le disque système :
$ cryptsetup luksFormat /dev/sdb2
WARNING!
========
This will overwrite data on /dev/sdb2 irrevocably.
Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/sdb2:
Verify passphrase:
cryptsetup luksFormat /dev/sdb2 19.12s user 0.36s system 84% cpu 23.158 total
Pour le moment j’ai mis une passphrase générique, d’environ 30 caractères, qui servira de passphrase de secours. Ensuite chaque passphrase de chaques utilisateurs sera également ajouté à ce volume, nous y reviendrons.
Puis on ouvre le conteneur system chiffré :
$ cryptsetup luksOpen /dev/sdb2 crypt-system
Enter passphrase for /dev/sdb2:
On peut donc les voir dans /dev/mapper
:
$ ls /dev/mapper
control crypt-system
Formatage des partitions
Nous partitions /dev/sdb1 en fat32, et le reste en btrfs évidemment
$ mkfs.fat -F32 /dev/sdb1
mkfs.fat 4.2 (2021-01-31)
$ mkfs.btrfs /dev/mapper/crypt-system
btrfs-progs v5.18.1
See http://btrfs.wiki.kernel.org for more information.
NOTE: several default settings have changed in version 5.15, please make sure
this does not affect your deployments:
- DUP for metadata (-m dup)
- enabled no-holes (-O no-holes)
- enabled free-space-tree (-R free-space-tree)
Label: (null)
UUID: 57c59ad7-848b-41a9-a79c-de2269f01cb5
Node size: 16384
Sector size: 4096
Filesystem size: 223.07GiB
Block group profiles:
Data: single 8.00MiB
Metadata: DUP 1.00GiB
System: DUP 8.00MiB
SSD detected: yes
Zoned device: no
Incompat features: extref, skinny-metadata, no-holes
Runtime features: free-space-tree
Checksum: crc32c
Number of devices: 1
Devices:
ID SIZE PATH
1 223.07GiB /dev/mapper/crypt-system
Création des sous-volumes btrfs
Pour ceci, nous allons déjà monter nos partitions :
$ mount /dev/mapper/crypt-system /mnt
Puis nous créons différents sous-volumes, sur le system nous aurons :
- @ pour le /
- @root pour le /root
- @log pour le /var/log
- @opt pour le /opt
- @tmp pour le /tmp (à voir si j’utilise un tmpfs)
- @snapshots pour les /.snapshots
Pourquoi utiliser des sous-volumes ?
Ce n’est pas une obligation, mais personnellement, je vais ajouter un hook à pacman, pour qu’à chaque installations ou mise à jours, il génère un snapshots de@
, mais je ne veux pas faire de snapshots des logs, des temporaires, du /root ou même du /opt, mais seulement de tout le reste.
Donc pour créer les sous-volumes, nous utiliserons btrfs subvolume create <PATH>
:
$ btrfs subvolume create /mnt/@
Create subvolume '/mnt/@'
$ btrfs subvolume create /mnt/@root
Create subvolume '/mnt/@root'
$ btrfs subvolume create /mnt/@log
Create subvolume '/mnt/@log'
$ btrfs subvolume create /mnt/@opt
Create subvolume '/mnt/@opt'
$ btrfs subvolume create /mnt/@tmp
Create subvolume '/mnt/@tmp'
$ btrfs subvolume create /mnt/@snapshots
Create subvolume '/mnt/@snapshots'
Puis nous pouvons démonter notre /mnt :
$ umount -R /mnt
Pour le home, on partira sur un sous-volumes LVM par utilisateurs, mais nous verrons ceci plus tard.
Montage des partitions
Pour pouvoir installer nos paquets, nous devons monter les partitions, nous procédons comme ceci :
$ mount -o subvol=@,defaults,noatime,nodiratime,ssd,compress=zstd /dev/mapper/crypt-system /mnt
$ mkdir -p /mnt/{var/log,boot,root,.snapshots,tmp,opt}
$ mount -o subvol=@root,defaults,noatime,nodiratime,ssd,compress=zstd /dev/mapper/crypt-system /mnt/root
$ mount -o subvol=@log,defaults,noatime,nodiratime,ssd,compress=zstd /dev/mapper/crypt-system /mnt/var/log
$ mount -o subvol=@opt,defaults,noatime,nodiratime,ssd,compress=zstd /dev/mapper/crypt-system /mnt/opt
$ mount -o subvol=@tmp,defaults,noatime,nodiratime,ssd,compress=zstd /dev/mapper/crypt-system /mnt/tmp
$ mount -o subvol=@snapshots,defaults,noatime,nodiratime,ssd,compress=zstd /dev/mapper/crypt-system /mnt/.snapshots
$ mount /dev/sdb1 /mnt/boot
Installation de Archlinux
Installation minimal
Avant d’installer la base, nous allons choisir les meilleurs mirroir pour nous, perso j’utilise reflector pour ceci :
$ reflector --country France --latest 10 --sort rate --save /etc/pacman.d/mirrorlist
Maintenant nous pouvons installer les paquets :
$ pacstrap /mnt \
base \
linux-zen \
linux-firmware \
vim \
net-tools \
wireless_tools \
btrfs-progs \
lvm2 \
wget \
curl \
zsh \
sudo \
iwd \
dhclient \
intel-ucode # ou amd-ucode si processeur amd
J’aime bien le kernel Zen, qui offre de bonne performance, et moins de mise à jour que celui de base.
Puis nous générons le fstab :
$ genfstab -U -p /mnt >> /mnt/etc/fstab
$ cat /mnt/etc/fstab
# Static information about the filesystems.
# See fstab(5) for details.
# <file system> <dir> <type> <options> <dump> <pass>
# /dev/mapper/crypt-system
UUID=50117f74-7c40-43ef-918b-c14d59c47450 / btrfs rw,noatime,nodiratime,compress=zstd:3,ssd,space_cache=v2,subvolid=256,subvol=/@ 0 0
# /dev/mapper/crypt-system
UUID=50117f74-7c40-43ef-918b-c14d59c47450 /root btrfs rw,noatime,nodiratime,compress=zstd:3,ssd,space_cache=v2,subvolid=257,subvol=/@root 0 0
# /dev/mapper/crypt-system
UUID=50117f74-7c40-43ef-918b-c14d59c47450 /var/log btrfs rw,noatime,nodiratime,compress=zstd:3,ssd,space_cache=v2,subvolid=258,subvol=/@log 0 0
# /dev/mapper/crypt-system
UUID=50117f74-7c40-43ef-918b-c14d59c47450 /opt btrfs rw,noatime,nodiratime,compress=zstd:3,ssd,space_cache=v2,subvolid=259,subvol=/@opt 0 0
# /dev/mapper/crypt-system
UUID=50117f74-7c40-43ef-918b-c14d59c47450 /tmp btrfs rw,noatime,nodiratime,compress=zstd:3,ssd,space_cache=v2,subvolid=260,subvol=/@tmp 0 0
# /dev/mapper/crypt-system
UUID=50117f74-7c40-43ef-918b-c14d59c47450 /.snapshots btrfs rw,noatime,nodiratime,compress=zstd:3,ssd,space_cache=v2,subvolid=261,subvol=/@snapshots 0 0
Configuration de base
Pour configurer notre système, nous allons chrooter, c’est à dire, changer le répertoire / de notre système, mais avant, je vais copier le mirrorlist :
$ cp /etc/pacman.d/mirrorlist /mnt/etc/pacman.d/mirrorlist
$ arch-chroot /mnt
[root@archiso /]#
Nous allons modifier quelques fichiers :
$ echo "KEYMAP=fr" > /etc/vconsole.conf
$ echo -e "en_US.UTF-8 UTF-8\nfr_FR.UTF-8 UTF-8" > /etc/locale.gen
$ locale-gen
$ echo "LANG=fr_FR.UTF-8" >> /etc/locale.conf
$ echo "laptop" > /etc/hostname
Configuration du initramfs
Il faudra modifier la variable HOOKS dans le /etc/mkinitcpio.conf
:
HOOKS=(base systemd autodetect modconf keyboard sd-vconsole block sd-encrypt btrfs filesystems fsck)
puis on génére l’image d’init :
$ mkinitcpio -p linux-zen
Installation du chargeur de démarrage
Puisque nous sommes sur arch, avec systemd donc, autant utiliser systemd-boot qui est déjà installé :
$ bootctl --esp-path=/boot install
Created "/boot/EFI".
Created "/boot/EFI/systemd".
Created "/boot/EFI/BOOT".
Created "/boot/loader".
Created "/boot/loader/entries".
Created "/boot/EFI/Linux".
Copied "/usr/lib/systemd/boot/efi/systemd-bootx64.efi" to "/boot/EFI/systemd/systemd-bootx64.efi".
Copied "/usr/lib/systemd/boot/efi/systemd-bootx64.efi" to "/boot/EFI/BOOT/BOOTX64.EFI".
Random seed file /boot/loader/random-seed successfully written (32 bytes).
Not booted with EFI, skipping EFI variable setup.
Not booted with EFI, skipping EFI variable setup.
Récupérez l’UUID de votre partition :
$ blkid | grep sdb2
/dev/sdb2: UUID="50117f74-7c40-43ef-918b-c14d59c47450" TYPE="crypto_LUKS" PARTLABEL="crypt-system" PARTUUID="40178r52-5g10-75gf-541g-c45d75g45785"
On crée un fichier /boot/loader/entries/arch.conf :
title Arch Linux
linux /vmlinuz-linux-zen
initrd /intel-ucode.img # ou /amd-ucode.img
initrd /initramfs-linux-zen.img
options rd.luks.uuid=50117f74-7c40-43ef-918b-c14d59c47450 root=/dev/mapper/luks-50117f74-7c40-43ef-918b-c14d59c47450 rootflags=subvol=@ rd.luks.options=discard quiet nowatchdog splash rw
Nous pouvons également ajouter une entrée pour le fallback (/boot/loader/entries/arch-fallback.conf) :
title Arch Linux
linux /vmlinuz-linux-zen-fallback
initrd /intel-ucode.img # ou /amd-ucode.img
initrd /initramfs-linux-zen-fallback.img
options rd.luks.uuid=50117f74-7c40-43ef-918b-c14d59c47450 root=/dev/mapper/luks-50117f74-7c40-43ef-918b-c14d59c47450 rootflags=subvol=@ rd.luks.options=discard quiet nowatchdog splash rw
ainsi que /boot/loader/loader.conf :
default arch.conf
editor no
timeout 4
console-mode max
Redémarrage
Voici le moment de vérité, il faut maintenant rebooter la machine, mais avant ceci, nous allons créer un mdp root :
[root@archiso /]$ passwd
New password:
Retype new password:
passwd: password updated successfully
[root@archiso /]$ exit
$ umount -R /mnt
$ reboot
Normalement, au boot il est censé vous demander de rentrer le mot de passe de votre disque dur.
Puis vous accédez à l’authentification.
Si vous êtes en wifi, il vous faudra vous reconnecter
$ systemctl start iwd
$ iwctl station wlan0 connect myhome_5GHz
$ dhclient wlan0
Gestion des utilisateurs
Comme vous l’avez remarqué, je n’ai pas créé d’utilisateur pour le moment, mais simplement un VG pour y mettre mes homes.
Beaucoup aurait créer une seul partition home, chiffré avec une clé, et monté via crypttab, cependant, dans le cadre d’un PC multi-utilisateur, je préfère créer une partition par utilisateurs, et de chiffrer celle-ci indépendamment avec un mot de passe unique, afin que l’utilisateur X, n’est pas accès au fichier de l’utilisateur Y et vice-versa.
pam_mount
Pour ceci nous utiliserons pam_mount, qu’il faut donc installer :
$ pacman -S pam_mount
Puis il faut modifier le fichier /etc/pam.d/system-login
:
auth required pam_shells.so
auth requisite pam_nologin.so
auth optional pam_mount.so
auth include system-auth
account required pam_access.so
account required pam_nologin.so
account include system-auth
password optional pam_mount.so
password include system-auth
session optional pam_loginuid.so
session optional pam_keyinit.so force revoke
session [success=1 default=ignore] pam_succeed_if.so service = systemd-user quiet
session optional pam_mount.so
session include system-auth
session optional pam_motd.so motd=/etc/motd
session optional pam_mail.so dir=/var/spool/mail standard quiet
-session optional pam_systemd.so
session required pam_env.so user_readenv=1
Création de l’utilisateur xataz
Création du volume de l’utilisateur
Pour ça c’est plutôt simple :
$ lvcreate -L200G -n xataz vghome
Logical volume "xataz" created.
Chiffrement du volume
On réutilise cryptsetup pour chiffrer notre volume, en utilisant le mot de passe que nous voudrons pour cet utilisateur :
$ cryptsetup luksFormat /dev/mapper/vghome-xataz
ATTENTION !
===========
Cette action écrasera définitivement les données sur /dev/mapper/vghome-xataz.
Êtes-vous sûr ? (Typez « yes » en majuscules) : YES
Saisissez la phrase secrète pour /dev/mapper/vghome-xataz :
Vérifiez la phrase secrète :
Puis nous déverrouillons notre conteneur chiffré :
$ cryptsetup luksOpen /dev/mapper/vghome-xataz xataz
Saisissez la phrase secrète pour /dev/mapper/vghome-xataz :
$
Formatage et montage du volume
On formate en btrfs donc :
$ mkfs.btrfs /dev/mapper/xataz
btrfs-progs v5.18.1
See http://btrfs.wiki.kernel.org for more information.
NOTE: several default settings have changed in version 5.15, please make sure
this does not affect your deployments:
- DUP for metadata (-m dup)
- enabled no-holes (-O no-holes)
- enabled free-space-tree (-R free-space-tree)
Label: (null)
UUID: 40b7a970-333f-44ce-ad82-d2f9e6156bab
Node size: 16384
Sector size: 4096
Filesystem size: 199.98GiB
Block group profiles:
Data: single 8.00MiB
Metadata: DUP 1.00GiB
System: DUP 8.00MiB
SSD detected: no
Zoned device: no
Incompat features: extref, skinny-metadata, no-holes
Runtime features: free-space-tree
Checksum: crc32c
Number of devices: 1
Devices:
ID SIZE PATH
1 199.98GiB /dev/mapper/xataz
et on monte
$ mkdir /home/xataz
$ mount /dev/mapper/xataz /home/xataz
J’ai pour habitude de toujours créer 2 sous-volumes, un pour la racine et l’autre pour les snapshots :
$ btrfs subvolume create /home/xataz/@
Create subvolume '/home/xataz/@'
$ btrfs subvolume create /home/xataz/@snapshots
Create subvolume '/home/xataz/@snapshots'
Création de l’utilisateur
$ useradd --no-create-home --home-dir /home/xataz/ --shell /bin/zsh xataz
$ chown -R xataz: /home/xataz
$ passwd xataz
Nouveau mot de passe :
Retapez le nouveau mot de passe :
passwd: password updated successfully
Ajout du mdp de l’utilisateur dans le volume chiffré system
Afin que mon utilisateur n’ai pas à connaitre le mot de passe super-admin de fou du volume system, j’ajoutes son mot de passe à celui-ci :
$ cryptsetup luksAddKey /dev/sdb2
Entrez une phrase secrète existante :
Entrez une nouvelle phrase secrète pour l'emplacement de clé :
Vérifiez la phrase secrète :
Configuration du pam_mount.conf.xml
Il ne nous reste plus qu’à créer la configuration pour pam_mount, afin de monter la partition home, seulement lors de la connexion.
Pour cela, nous allons modifier le fichier /etc/security/pam_mount.conf.xml :
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE pam_mount SYSTEM "pam_mount.conf.xml.dtd">
<pam_mount>
<debug enable="0" />
<mntoptions allow="nosuid,nodev,loop,encryption,fsck,nonempty,allow_root,allow_other" />
<mntoptions require="nosuid,nodev" />
<logout wait="0" hup="no" term="no" kill="no" />
<mkmountpoint enable="1" remove="true" />
<volume user="xataz" fstype="crypt" path="/dev/vghome/xataz" mountpoint="~" options="subvol=@,allow_discard,fstype=btrfs,compress=zstd" />
<volume user="xataz" path="/dev/disk/by-uuid/54cd455hdf-d613-47fd-b1fc-2f24daf12dbe" mountpoint="~/.snapshots" options="subvol=@snapshots,allow_discard,fstype=btrfs,compress=zstd" />
</pam_mount>
Par contre nous avons un soucis lors de la déconnexion, les répertoires home ne se démontent pas.
Je n’ai trouvé aucune solution satisfaisante, certains utilisent une crontrab par exemple qui check toutes les minutes la présence ou non d’un processus utilisateur, je trouvais cela pas très propre.
En regardant les logs, j’ai vu qu’a la déconnexion, le service user@.service était appelé, j’ai donc décidé de créer un service systemd pour ceci, qui s’exécutera lors de la dernière session fermé, pour ceci il suffit :
Création du script /usr/lib/systemd/systemd-user-crypthome-dir :
#!/bin/bash
user=$(id -nu $2)
if [ "$1" == "stop" ]; then
luksMapper=$(mount | grep -w $user | awk '{print $1}')
umount -R /home/$user
cryptsetup luksClose $luksMapper
fi
Puis on le rends exécutable avec chmod +x /usr/lib/systemd/systemd-user-crypthome-dir
Ensuite nous créons un service, via le fichier /usr/lib/systemd/system/systemd-user-crypthome-dir@.service :
[Unit]
Description=Umount encrypted home dir
After=systemd-user-sessions.service dbus.service
StopWhenUnneeded=yes
IgnoreOnIsolate=yes
[Service]
ExecStart=/usr/lib/systemd/systemd-user-crypthome-dir start %i
ExecStop=/usr/lib/systemd/systemd-user-crypthome-dir stop %i
Type=oneshot
RemainAfterExit=yes
Slice=user-%i.slice
Il faut forcément un ExecStart, il ne fera rien ici, mais ce n’est pas grave.
Et ensuite, il faut ajouter ce service en Require dans /usr/lib/systemd/system/user@.service :
[...]
Requires=user-runtime-dir@%i.service systemd-user-crypthome-dir@%i.service
[...]
En fait avec systemd-login, le service user@.service est exécuté, et sera réexécuté lors de la fermeture de la dernière session, ce qui aura pour but de démonter votre home.
Création d’un script pour simplifier ceci
Maintenant que nous l’avons fait à la main, c’est toujours mieux de simplifier, je vous donne donc mon script fait rapidement pour l’occasion :
#!/bin/bash
## Config ##
VG=vghome
TYPEFS=btrfs
DEFAULT_SIZE=100G
DEFAULT_SHELL=/bin/zsh
############
echo -e "Username: \c"
read USERNAME
echo -e "Password: \c"
read -s PASSWORD
echo -e "\nRetype Password: \c"
read -s RETYPEPASSWORD
echo -e "\nSize home: (default: $DEFAULT_SIZE) \c"
read SIZE
echo -e "Shell: (default: $DEFAULT_SHELL) \c"
read SHELL
if [ "$PASSWORD" != "$RETYPEPASSWORD" ]; then
echo "Password doesn't match"
exit 1
fi
tmpfile=$(mktemp)
echo -n "$PASSWORD" > $tmpfile
if [ "$SIZE" == "" ]; then SIZE=$DEFAULT_SIZE; fi
if [ "$SHELL" == "" ]; then SHELL=$DEFAULT_SHELL; fi
echo "Create partition"
lvcreate -L $SIZE -n $USERNAME $VG
echo "Encrypt partition"
cat $tmpfile | cryptsetup luksFormat /dev/mapper/vghome-$USERNAME
echo "Open partition"
cat $tmpfile | cryptsetup luksOpen /dev/mapper/vghome-$USERNAME $USERNAME
echo "Format partition"
mkfs.$TYPEFS /dev/mapper/$USERNAME
echo "Mount partition"
mkdir -p /home/$USERNAME/.snapshots
mount /dev/mapper/$USERNAME /home/$USERNAME
UUID=$(blkid | grep "/dev/mapper/$USERNAME" | awk '{print $2}' | cut -d'"' -f2)
echo "Create subvolume"
btrfs subvolume create /home/$USERNAME/@
btrfs subvolume create /home/$USERNAME/@snapshots
echo "Create user"
useradd --no-create-home --home-dir /home/$USERNAME/ --shell $SHELL $USERNAME
echo -e "$PASSWORD\n$PASSWORD" | passwd $USERNAME
chown -R $USERNAME: /home/$USERNAME
echo "Add password on system partition"
cryptsetup luksAddKey /dev/sdb2 $tmpfile
echo "Configuration du pam_mount"
sed -i "s#</pam_mount># <volume user=\"$USERNAME\" fstype=\"crypt\" path=\"/dev/vghome/$USERNAME\" mountpoint=\"~\" options=\"subvol=@,allow_discard,fstype=btrfs,compress=zstd\" />\n</pam_mount>#" /etc/security/pam_mount.conf.xml
sed -i "s#</pam_mount># <volume user=\"$USERNAME\" path=\"/dev/disk/by-uuid/$UUID\" mountpoint=\"~/.snapshots\" options=\"subvol=@snapshots,allow_discard,fstype=btrfs,compress=zstd\" />\n</pam_mount>#" /etc/security/pam_mount.conf.xml
echo "Cleanup"
umount /home/$USERNAME
cryptsetup luksClose /dev/mapper/$USERNAME
unset $PASSWORD
unset $RETYPEPASSWORD
unset $USERNAME
unset $SIZE
unset $SHELL
rm -rf $tmpfile
C’est loin d’être parfait, mais ça fonctionne, y’a surement de l’optimisation à faire, et ajouter une option pour supprimer l’utilisateur, mais aussi le modifier.
Et quand on l’exécute :
$ create_user
Username: copine
Password:
Retype Password:
Size home (default: 100G):
Shell (default: /bin/zsh):
Create partition
WARNING: crypto_LUKS signature detected on /dev/vghome/copine at offset 0. Wipe it? [y/n]: y
Wiping crypto_LUKS signature on /dev/vghome/copine.
WARNING: crypto_LUKS signature detected on /dev/vghome/copine at offset 16384. Wipe it? [y/n]: y
Wiping crypto_LUKS signature on /dev/vghome/copine.
Logical volume "copine" created.
Encrypt partition
Open partition
Format partition
btrfs-progs v5.18.1
See http://btrfs.wiki.kernel.org for more information.
NOTE: several default settings have changed in version 5.15, please make sure
this does not affect your deployments:
- DUP for metadata (-m dup)
- enabled no-holes (-O no-holes)
- enabled free-space-tree (-R free-space-tree)
Label: (null)
UUID: 2c5107c8-8aea-49ba-b507-8cec54183fc6
Node size: 16384
Sector size: 4096
Filesystem size: 99.98GiB
Block group profiles:
Data: single 8.00MiB
Metadata: DUP 1.00GiB
System: DUP 8.00MiB
SSD detected: no
Zoned device: no
Incompat features: extref, skinny-metadata, no-holes
Runtime features: free-space-tree
Checksum: crc32c
Number of devices: 1
Devices:
ID SIZE PATH
1 99.98GiB /dev/mapper/copine
Mount partition
Create snapshots subvolume
Create subvolume '/home/copine/@snapshots'
Create user
Nouveau mot de passe : Retapez le nouveau mot de passe : passwd: password updated successfully
Add password on system partition
Entrez une phrase secrète existante :
Configuration du pam_mount
Cleanup
Et voilà, mon nouvel utilisateur est correctement créer, avec sa partition, chiffré par son mot de passe unique que je ne connais pas, de plus, elle peux aussi déchiffrer le disque système avec son mot de passe à elle.
Tweak de Archlinux
Snapshots automatique
Archlinux étant une distribution en rolling Release, et même si les régressions sont devenu très rare, je pense qu’il est indispensable de faire un snapshots avant chaque modification de paquets (Installation, Mise à jour ou même suppression). Pour ceci, nous avons les Hooks pacman.
Un hook est une action qui sera exécutée avant ou après la modification de paquet.
Les snapshots avec btrfs
Pour faire un snapshots avec btrfs, c’est plutôt simple :
$ btrfs subvolume snapshot / /.snapshot/testsnapshot
Create a snapshot of '/' in '/.snapshots/testsnapshot'
Cependant il est facile de créer et supprimer des snapshots, mais les restaurer et faire des rollbacks, c’est beaucoup plus compliqué. Le but ici n’est pas d’expliquer toute les possibilité de btrfs, ceci fera surement l’objet d’un futur article.
Création du hook
Pour ceci, il faut créer le fichier /etc/pacman.d/hooks/snapshots.hook
:
[Trigger]
Operation = Install
Operation = Upgrade
Operation = Remove
Type = Package
Target = *
[Action]
Depends = coreutils
When = PreTransaction
Exec = /usr/local/bin/btrfs-snapshots
Donc là en gros, avant toute transaction (When = PreTransaction
), et pour les installations, mises à jour et Suppression de paquet, il faut exécuter /usr/local/bin/btrfs-snapshots.
Et voici le script (très simple) de la génération de snapshots /usr/local/bin/btrfs-snapshots
:
#!/bin/bash
DATE=$(date +%Y%m%d%H%M%S)
echo "Snapshot /"
btrfs subvolume snapshot / /.snapshots/auto-snapshot-$DATE
Là par exemple, ça tombe bien, j’avais des mises à jour à faire, donc je le lance :
$ pacman -Syu
pacman -Syu
:: Synchronisation des bases de données de paquets…
core 158,3 KiB 464 KiB/s 00:00 [#####################################################################################################] 100% extra 1827,3 KiB 20,7 MiB/s 00:00 [#####################################################################################################] 100% community 6,8 MiB 28,7 MiB/s 00:00 [#####################################################################################################] 100%:: Début de la mise à jour complète du système…
résolution des dépendances…
recherche des conflits entre paquets…
Paquets (11) binutils-2.39-3 btrfs-progs-5.19-1 ca-certificates-mozilla-3.82-1 gcc-libs-12.2.0-1 glibc-2.36-3 gnutls-3.7.7-3 ldns-1.8.3-1 linux-zen-5.19.3.zen1-1 tzdata-2022c-1 vim-9.0.0236-1 vim-runtime-9.0.0236-1
Taille totale du téléchargement : 249,94 MiB
Taille totale installée : 460,41 MiB
Taille de mise à jour nette : -0,09 MiB
:: Procéder à l’installation ? [O/n]
[...]
:: Exécution des crochets (« hooks ») de pré-transaction…
(1/2) Removing linux initcpios...
(2/2) snapshots.hook
Snapshot /
Create a snapshot of '/' in '/.snapshots/auto-snapshot-20220823125324'
:: Traitement des changements du paquet…
( 1/11) mise à jour de tzdata [#####################################################################################################] 100%
[...]
:: Exécution des crochets (« hooks ») de post-transaction…
(1/7) Reloading system manager configuration...
(2/7) Creating temporary files...
(3/7) Reloading device manager configuration...
(4/7) Arming ConditionNeedsUpdate...
(5/7) Rebuilding certificate stores...
(6/7) Updating module dependencies...
(7/7) Updating linux initcpios...
[...]
et comme on peux le voir, j’ai bien un snapshot :
$ btrfs subvolume list -s /
ID 274 gen 396 cgen 396 top level 261 otime 2022-08-23 12:53:25 path @snapshots/auto-snapshot-20220823125324
Purge des snapshots
Il peux être sympa de purger un peu les snapshots, j’ai également un petit script pour ceci :
NB_REMEMBER_SNAPSHOTS=5
NB_SNAPSHOTS=$(btrfs subvol list -s / | wc -l)
if [ $NB_REMEMBER_SNAPSHOTS -lt $NB_SNAPSHOTS ]; then
NB_DELETE_SNAPSHOTS=$(($NB_SNAPSHOTS-$NB_REMEMBER_SNAPSHOTS))
for i in $(btrfs subvol list -s / | head -$NB_DELETE_SNAPSHOTS | awk '{print $14}' | sed 's#@#/.#'); do btrfs subvol delete $i; done
fi
Là il garde seulement les 5 derniers snapshots.
Nous pouvons ajouter ce script au script de snapshots.
Génération du menu systemd-boot
Alors là c’est un peu plus compliqué, perso, je suis un bourrin, je vous code :
rm -rf /boot/loader/entries/snapshots*
LIST_SNAPSHOTS=$(ls /.snapshots)
for snapshot in $LIST_SNAPSHOTS; do
date=$(echo $snapshot | cut -d"-" -f3)
sed -e "s#^title.*#title Arch Linux Snapshot ($date)#" \
-e "s#rootflags=subvol=@#rootflags=subvol=@snapshots/$snapshot#" \
/boot/loader/entries/arch.conf > /boot/loader/entries/${snapshot}.conf
done
Nous pouvons également l’ajouter ce script au script de snapshots.
/usr/local/bin/btrfs-snapshots complet
Une fois complet, mon script de snapshots ressemble à ceci :
#!/bin/bash
### CONFIG ###
NB_REMEMBER_SNAPSHOTS=5
##############
DATE=$(date +%Y%m%d%H%M%S)
echo "Snapshot /"
btrfs subvolume snapshot / /.snapshots/auto-snapshot-$DATE
echo "Remove old snapshots"
NB_SNAPSHOTS=$(btrfs subvol list -s / | wc -l)
if [ $NB_REMEMBER_SNAPSHOTS -lt $NB_SNAPSHOTS ]; then
NB_DELETE_SNAPSHOTS=$(($NB_SNAPSHOTS-$NB_REMEMBER_SNAPSHOTS))
for i in $(btrfs subvol list -s / | head -$NB_DELETE_SNAPSHOTS | awk '{print $14}' | sed 's#@#/.#'); do btrfs subvol delete $i; done
fi
echo "Generate systemd-boot menu"
rm -rf /boot/loader/entries/snapshots*
LIST_SNAPSHOTS=$(ls /.snapshots)
for snapshot in $LIST_SNAPSHOTS; do
date=$(echo $snapshot | cut -d"-" -f3)
sed -e "s#^title.*#title Arch Linux Snapshot ($date)#" \
-e "s#rootflags=subvol=@#rootflags=subvol=@snapshots/$snapshot#" \
/boot/loader/entries/arch.conf > /boot/loader/entries/${snapshot}.conf
done
Backup du noyau
Le problème, c’est que ma partition /boot est séparée, donc les kernels ne sont pas inclus dans le snapshot. Il est important aussi de sauvegarder ceci, donc nous pouvons également le faire via les hooks :
Création du hook
On crée donc le hook /etc/pacman.d/hooks/linux-zen.hook
:
[Trigger]
Operation = Install
Operation = Upgrade
Operation = Remove
Type = Package
Target = linux-zen
[Action]
When = PreTransaction
Exec = /usr/local/bin/backup-linux-zen
la petite particularité, c’est le Target = linux-zen, qui veut dire en gros que ce hook ne sera exécuté que si c’est le package linux-zen qui est modifié.
Création du script
On crée également le script /usr/local/bin/backup-linux-zen
:
#!/bin/bash
cp -f /boot/vmlinuz-linux-zen{,.old}
cp -f /boot/initramfs-linux-zen.img{,.old}
cp -f /boot/initramfs-linux-zen-fallback.img{,.old}
Puis on le rend exécutable :
$ chmod +x /usr/local/bin/backup-linux-zen
Création de l’entrée systemd-boot
Pour ceci c’est plutôt simple, nous allons créer le fichier /boot/loader/entries/archold.conf :
title Arch Linux OLD kernel
linux /vmlinuz-linux-zen.old
initrd /intel-ucode.img.old
initrd /initramfs-linux-zen.img.old
options rd.luks.uuid=b432b224-c656-4ba8-9010-3475da5aafbc root=UUID="57c59ad7-848b-41a9-a79c-de2269f01cb5" rootflags=subvol=@ rd.luks.options=discard quiet nowatchdog splash rw
Et voilà, désormais notre kernel sera sauvegardé s’il y a une modification de celui-ci, bon là je ne garde que la dernière version, mais pour moi c’est suffisant.
Installation de MATE
Cette partie n’aura rien de particulier, car c’est du basique pour ceux ayant déjà installé une Archlinux
Installation des paquets
On installe quelques paquets, alors que certains installent d’abord xorg, puis mate, et pour finir par lightdm (ou autre), moi je préfère installer tout en une seule fois.
$ pacman -S xorg xorg-server mate mate-extra lightdm lightdm-gtk-greeter networkmanager network-manager-applet xdg-user-dirs
[...]
pour configurer le bon clavier sur x11 :
$ localectl set-x11-keymap fr
On configure network-manager pour utiliser iwd en créant le fichier /etc/NetworkManager/conf.d/wifi_backend.conf
:
[device]
wifi.backend=iwd
puis on lance lightdm :
$ systemctl enable iwd
$ systemctl enable NetworkManager
$ systemctl enable lightdm
$ reboot
Installation des logiciels
Premier logiciel à installer, c’est yay, mais non disponible sur les repos, mais sur AUR, assez marrant, yay permets l’installation depuis AUR, mais est sur AUR aussi.
Pour l’installer, nous aurons besoin de base-devel et git :
$ pacman -S git base-devel
On télécharge le repo git (a faire avec un utilisateur non root):
$ git clone https://aur.archlinux.org/yay.git
$ cd yay
$ makepkg -si
il va également falloir activer les repos multilib, pour installer des logiciels comme Steam ou lutris, pour ceci on modifie le fichier /etc/pacman.conf :
[multilib]
Include = /etc/pacman.d/mirrorlist
et c’est good, maintenant plus qu’à installer mes logiciels, je vous mets la commande en vrac, elle n’est pas forcément complète :
$ yay -Syu firefox firefox-i18n-fr brave-bin mpv libreoffice-fresh libreoffice-fresh-fr \
ulauncher youtube-dl \
bitwarden bitwarden-cli \
terminator code postman-bin neovim rustup python-pip pgadmin4 \
teams discord element-desktop \
steam steam-native-runtime lutris vulkan-intel lib32-vulkan-intel \
qemu-full virt-manager virt-viewer dnsmasq vde2 bridge-utils openbsd-netcat ebtables libguestfs snapd \
vagrant podman terraform minio-client scaleway-cli aws-cli azure-cli-bin ansible kubectl helm kubectx \
rclone restic \
pipewire-jack \
mpv inskape gimp darktable spotify playerctl
Conclusion
Et voilà, mon archlinux est installé, et configuré, il reste un peu de personnalisation (thème gtk, pack d’icone etc …), mais globalement, c’est totalement fonctionnel et il ne me manque pas grand chose.
J’espère être sortie des sentiers battus de chacun, avec une installation un peu spécifique.