From c262715eb4613d27773005e21345c1d696628f2c Mon Sep 17 00:00:00 2001 From: Chl Date: Thu, 21 Sep 2023 02:17:33 +0200 Subject: [PATCH] Ajout template LXC Debian 12 Bookworm --- Home.md | 3 +- creation-template-lxc-debian-12-bookworm.md | 291 ++++++++++++++++++++ 2 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 creation-template-lxc-debian-12-bookworm.md diff --git a/Home.md b/Home.md index 22d6e1d..5d5e6d6 100644 --- a/Home.md +++ b/Home.md @@ -1,3 +1,4 @@ Bienvenue sur le Wiki. -* [Création d'un template LXC unprivileged de Debian 10 Buster](creation-template-lxc-debian-buster) \ No newline at end of file +* [Création d'un template LXC unprivileged de Debian 10 Buster](creation-template-lxc-debian-buster) +* [Hyperviseur LXC et template unprivileged de Debian 12 Bookworm](creation-template-lxc-debian-12-bookworm) diff --git a/creation-template-lxc-debian-12-bookworm.md b/creation-template-lxc-debian-12-bookworm.md new file mode 100644 index 0000000..61f3f9c --- /dev/null +++ b/creation-template-lxc-debian-12-bookworm.md @@ -0,0 +1,291 @@ +# Hyperviseur pour développeur avec template LXC unprivileged Debian 12 _Bookworm_ + +Ce document retrace la configuration d'une Debian 12 Bookworm afin d'en faire +un "hyperviseur de développeur", c'est à dire un peu comme Docker, faire tourner +des conteneurs en partageant certains sous-répertoires avec l'hôte. + +On retracera aussi la création d'un template de conteneur unprivileged d'une Debian 12. + +Quelques points annexes : +- l'utilisation courante doit pouvoir se faire avec des droits simples (non-root et non-sudoer), +- dans ce document, ledit utilisateur a comme uid 1000. À adapter au besoin. +- /home sera une partition Btrfs + +Avertissements liminaires : +- `lxc-create -t debian` dit explicitement ne pas gérer les conteneurs non-privilégiés, cependant je n'ai trouvé aucune contre-indication à créer le template privilégié et faire un _uidshift_ maison. C'est la piste détaillée ici. +- une autre piste consiste à partir d'un `debootstrap` et faire le travail manuellement. Il faut cependant penser à initialiser pas mal de petites choses comme pour openvz (locales, fuseau horaire, `/etc/machine-id`, etc.) +- ce tuto est en bêta : caveat emptor. + + +## Configuration de l'hôte + +Installation du paquet `lxc` et activation (optionnelle) des quotas sur la partition Btrfs : +``` +# en root +apt install lxc +btrfs quota enable /home +``` + +Configuration de la partition Btrfs (ajout de `user_subvol_rm_allowed` dans `/etc/fstab` pour pouvoir supprimer des conteneurs) : +``` +/dev/mapper/blablavg-home /home btrfs user_subvol_rm_allowed 0 0 +``` + +Configuration des accès non-privilégiés (réseau + uidmap) : +``` +# /etc/lxc/lxc-usernet +ltorvalds veth br0 10 +``` + +``` +# /etc/subuid +ltorvalds:100000:65536 +``` + +``` +# /etc/subgid +ltorvalds:100000:65536 +``` + +Ensuite, on reconfigure l'interface réseau en tant que bridge : + +* normalement, le paquet `bridge-utils` a été installé en dépendance de `lxc` mais par prudence, vérifier qu'il est bien là : `dpkg -l bridge-utils` +* on en profite pour ajouter quelques interfaces virtuelles _tap_ qui peuvent servir lors de besoins précis (tunnels, VM Qemu) +* TODO: si l'interface physique est une carte wifi, c'est plus compliqué. À mettre ici à l'occasion. + +``` +# /etc/network/interfaces + +# The loopback network interface +auto lo +iface lo inet loopback + +# The primary network interface +auto br0 +iface br0 inet static + pre-up ip tuntap add dev tap0 mode tap user ltorvalds + pre-up ip link set tap0 up + pre-up ip tuntap add dev tap1 mode tap user ltorvalds + pre-up ip link set tap1 up + pre-up ip tuntap add dev tap2 mode tap user ltorvalds + pre-up ip link set tap2 up + bridge_ports enp0s25 tap0 tap1 tap2 + bridge_stp off + bridge_maxwait 5 + bridge_fd 0 + address 192.168.0.5/24 + gateway 192.168.0.1 + post-down ip link set tap0 down + post-down ip tuntap del dev tap0 mode tap + post-down ip link set tap1 down + post-down ip tuntap del dev tap1 mode tap + post-down ip link set tap2 down + post-down ip tuntap del dev tap2 mode tap + +iface br0 inet6 static + address 2a01:abcd:ef::5/112 + gateway 2a01:abcd:ef::1 +``` + +Enfin, on prépare la configuration de l'utilisateur +``` +# en utilisateur lambda +mkdir /home/ltorvalds/lxc +mkdir -p /home/ltorvalds/.config/lxc +echo "lxc.lxcpath = /home/ltorvalds/lxc" >> /home/ltorvalds/.config/lxc/lxc.conf +``` + + +## Création du template + +On commence par créer un répertoire de cache dans le même volume Btrfs, puis on lance la commande de création : +``` +# en root (sudo -i) + +cd /home/ltorvalds/lxc +mkdir cache +LXC_CACHE_PATH=/home/ltorvalds/lxc/cache MIRROR=http://apt-proxy.example.net:3142/debian SECURITY_MIRROR=http://apt-proxy.example.net:3142/debian lxc-create -n debian-12-bookworm-systemd-lxccreate -P /home/ltorvalds/lxc -t debian -B btrfs -- -r bookworm +``` + +On complète notre magnifique template ainsi : +``` +# en root (sudo -i) + +# nettoyage +btrfs subvol delete cache/debian/rootfs-bullseye-amd64 +rm -rvf cache/ + +# droits +chown 100000:ltorvalds debian-12-bookworm-systemd-lxccreate +chown ltorvalds:ltorvalds debian-12-bookworm-systemd-lxccreate/config +# Repris de https://unix.stackexchange.com/questions/127554/building-unprivileged-userns-lxc-container-from-scratch-by-migrating-a-privil/420317#420317 +export SUBUID=100000 +export SUBGID=100000 +#find debian-buster-lxccreate/rootfs | while read i; do CURRENT_UID=$(stat --format=%u $i); CURRENT_GID=$(stat --format=%g $i); NEW_SUBUID=$((CURRENT_UID+SUBUID)); NEW_SUBGID=$((CURRENT_GID+SUBGID)); echo "chown -h $NEW_SUBUID.$NEW_SUBGID $i"; done +# Version "noms-de-fichiers-bizarres". Attention bashism sur 'read -d'. +find debian-12-bookworm-systemd-lxccreate/rootfs -print0 | while IFS= read -r -d '' i; do CURRENT_UID=$(stat --format=%u "$i"); CURRENT_GID=$(stat --format=%g "$i"); NEW_SUBUID=$((CURRENT_UID+SUBUID)); NEW_SUBGID=$((CURRENT_GID+SUBGID)); [ $CURRENT_UID -lt $SUBUID ] && [ $CURRENT_GID -lt $SUBGID ] && chown -h $NEW_SUBUID:$NEW_SUBGID "$i" || echo "uid or gid already changed for $i ?"; done +``` + + +### Adaptation de la configuration + +On remplace la config par : +``` +# For additional config options, please look at lxc.container.conf(5) +# Distribution configuration +#lxc.include = /usr/share/lxc/config/debian.common.conf +#lxc.include = /usr/share/lxc/config/debian.userns.conf +lxc.include = /usr/share/lxc/config/common.conf +lxc.tty.dir = +lxc.arch = linux64 +# Container specific configuration +lxc.tty.max = 4 +lxc.arch = amd64 +lxc.pty.max = 1024 +# À 1000, on arrête la traduction des UID et on reprend ensuite +# pour avoir une correspondance sur les montages partagés. +#lxc.idmap = u 0 100000 65536 +#lxc.idmap = g 0 100000 65536 +lxc.idmap = u 0 100000 1000 +lxc.idmap = g 0 100000 1000 +lxc.idmap = u 1000 1000 1 +lxc.idmap = g 1000 1000 1 +lxc.idmap = u 1001 101001 64534 +lxc.idmap = g 1001 101001 64534 +lxc.mount.auto = proc:mixed sys:ro cgroup:mixed +# FS configuration +lxc.rootfs.path = btrfs:/home/ltorvalds/lxc/debian-12-bookworm-systemd-lxccreate/rootfs + +# Point de montage à partager avec l'hôte +#lxc.mount.entry = /home/ltorvalds/dev/project-ro home/ltorvalds/dev/project-ro none bind,create=dir,ro 0 0 +#lxc.mount.entry = /home/ltorvalds/dev/project-rw home/ltorvalds/dev/project-rw none bind,create=dir 0 0 + +# Network configuration +lxc.uts.name = debian-12-bookworm-systemd-lxccreate +#lxc.net.0.type = empty +lxc.net.0.type = veth +lxc.net.0.link = br0 +lxc.net.0.flags = up +lxc.net.0.hwaddr = 00:16:3e:83:ab:cd +lxc.net.0.ipv4.address = 192.168.0.199/24 +lxc.net.0.ipv4.gateway = 192.168.0.139 +lxc.net.0.ipv6.address = 2a01:ab:cd:ef::abcd:ff/112 +lxc.net.0.ipv6.gateway = 2a01:ab:cd:ef::abcd:1 + +# Profil Apparmor +# Pour Debian Buster, on est souvent obligés de passer en unconfined +# ou par exemple de reconfigurer l'unit systemd d'Apache pour qu'il n'ait +# pas de privatetmp & similaires. +# /etc/systemd/system/apache2.service.d/override.conf +# [Service] +# PrivateTmp=false +lxc.apparmor.profile = lxc-container-default-cgns +#lxc.apparmor.profile = lxc-container-default-with-nesting +#lxc.apparmor.profile = unconfined +#lxc.apparmor.profile = generated +#lxc.apparmor.allow_nesting = 1 +# Uncomment the following line to support nesting containers: +#lxc.include = /usr/share/lxc/config/nesting.conf +# (Be aware this has security implications) + +lxc.cgroup2.memory.high = 1900M +lxc.cgroup2.memory.max = 2G +``` + + +### Adaptation à l'intérieur du conteneur + +On lance le conteneur et on s'y projette : +``` +lxc-unpriv-start -n debian-bullseye-lxccreate +lxc-unpriv-attach -n debian-bullseye-lxccreate + +su - + +cd /etc + +# Préférence personnelle sur la verbosité de debconf +dpkg-reconfigure debconf + +# Versionnage de /etc (etckeeper est plus lourd mais très bien aussi) +apt install git --no-install-recommends +cat <.gitignore +/ld.so.cache +/adjtime +/nologin +/.pwd.lock +*- +*~ +*.old +*-old +EOF + +git init +chmod 0700 .git +git add . +git commit -a -m "commit initial" + +# Mon éditeur et mon paginateur favoris +apt install vim less +update-alternatives --config editor + +dpkg-reconfigure tzdata +apt install nullmailer # "" / mail.example.net / postmaster@example.net +rm mailname && ln -s hostname mailname # pas très orthodoxe :-/ + +apt install nftables netcat-openbsd + +cd /usr/local/share +git clone https://code.bugness.org/chl/scripts-admin-quickndirty-public.git +cd /etc +cat </etc/apt/apt.conf.d/44proxy +Acquire::http::Proxy-Auto-Detect "/usr/local/share/scripts-admin/apt-conf-proxy.sh"; +EOF +# Vérifier que /etc/apt/sources.list soit a peu près ok : +# deb http://ftp.fr.debian.org/debian bookworm main +# deb http://ftp.fr.debian.org/debian bookworm-updates main +# deb http://security.debian.org bookworm/updates main + +# Pour regagner un peu d'espace disque +apt clean + +# Pour accélérer le boot, commenter l'entrée 'eth0 dhcp...' dans /etc/network/interfaces +# L'interface virtuelle est créée et gérée par LXC de toute façon. +``` + +### Reconfiguration automatique + + +``` +cat </etc/systemd/system/reset-ssh-server-keys.service +[Unit] +Description=Regenerate OpenSSH server keys +#ConditionPathExists=!/etc/ssh/ssh_host_rsa_key +# If we do it before network.target or ssh.service, the restart of openssh initiated by dpkg-reconfigure hangs and makes us timeout. +After=network.target + +[Service] +Type=oneshot +ExecStart=/bin/bash -c "(/bin/date; echo $(( $RANDOM * $RANDOM * $RANDOM * $RANDOM )) )| /usr/bin/md5sum | /usr/bin/cut -f 1 -d ' ' >/etc/machine-id" +ExecStart=/bin/sh -c "/bin/rm -vf /etc/ssh/ssh_host_*" +ExecStart=/usr/sbin/dpkg-reconfigure openssh-server +ExecStartPost=-/bin/bash -c "/bin/systemctl disable reset-ssh-server-keys" +ExecStartPost=/bin/rm -f /etc/systemd/system/reset-ssh-server-keys.service +TimeoutSec=120 +RemainAfterExit=no + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable reset-ssh-server-keys +``` + +## Utilisation courante +On peut ensuite profiter du template en tant qu'utilisateur simple via : +``` +lxc-copy -n debian-12-bookworm-systemd-lxccreate -N project1234-dev +# The MAC address will be changed by LXC but remember to affect a new IP +# and possibly new subuid (but that topic will be for another day). +# +# Also, the journalctl seems empty on first boot. Because of the changed hostname ? +```