Zu Urzeiten, als es weder Xen noch KVM gab, hab ich, nach einem kurzen Intermezzo zu Linux-VServer, User Mode Linux genutzt, um virtuelle Server zu betreiben.
Hierbei wird der Kernel als normaler (Userspace-)Prozess gestartet.
Ich habe mir die Frage gestellt, ob ich eine VM mithilfe von User Mode Linux auf Uberspace betreiben kann.
Die Kernelkonfigurationsdatei (.config) habe ich aus dem debian-Paket (config.amd64) genommen.
Der Versuch den Kernel auf meinem Uberspace zu kompilieren ist aufgrund der Betagtheit des CentOS mit irgendwelchen obskuren Fehlern abgebrochen - nach der dritten Datei, die ich manuell angepasst habe, hatte ich keine Lust mehr und habe geschaut, wie ich den Kernel auf meinem Rechner als statisches Programm kompilieren kann.
Nur CONFIG_STATIC_LINK=y zu setzen, hat bei mir nicht geklappt - ich musste in der arch/um/Kconfig zwei Zeilen unter config STATIC_LINK noch eine Zeile auskommentieren:
# depends on CC_CAN_LINK_STATIC_NO_RUNTIME_DEPS || !MAY_HAVE_RUNTIME_DEPS
Danach ein beherztes make ARCH=um und nach einiger Zeit hatte ich ein statisches linux-Binary.
Das Dateisystem des User Mode Linux ist ein Imagedatei und da ich bei Uberspace kein root habe, musste ich das Image auf meinem Rechner vorbereiten:
dd if=/dev/zero of=debian.img bs=1M count=$((1024*5))
mkfs.ext4 debian.img
mount -o loop debian.img /mnt
debootstrap trixie /mnt
Die erste Zeile erstellt eine Imagedatei, die 5 GB groß ist, die zweite erstellt ein ext4-System darin, die dritte mountet dieses nach /mnt und die letzte Zeile
installiert ein Debian trixie.
Danach bin ich per chroot /mnt /bin/bash in das neue System gewechselt.
Es müssen alle Standard-Terminals deaktiviert (und maskiert) werden und stattdessen eins auf tty0 gestartet werden:
rm /etc/systemd/system/getty.target.wants/getty@*
for i in $(seq 2 6); do ln -sf /dev/null /etc/systemd/system/getty@tty$i.service; done
ln -sf /dev/null /etc/systemd/system/getty-static.service
ln -s /usr/lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty0.service
Außerdem habe ich per passwd ein root-Passwort gesetzt.
Auch die Netzwerkkonfiguration kann man schon gut vorbereiten:
cat >> /etc/network/interfaces <<EOF
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 10.0.2.15/24
post-up ip route add default dev \$IFACE
EOF
Abschließend die Chroot-Umgebung per exit verlassen und die Imagedatei mit umount /mnt unmounten.
Das Image habe ich danach einfach per SCP auf meinen Uberspace kopiert.
Soweit so gut. Als ich User Mode Linux früher als Virtualisierungslösung benutzt habe, habe ich die Netzwerkanbindung mit TAP-Devices realisiert, was jedoch root erfordert, was ich, wie oben erwähnt, bei Uberspace nicht habe.
In der Netzwerkdokumentation vom User Mode Linux bin ich jedoch über den Satz “slirp - if you don’t have root access on the host to setup networking, or if you don’t want to allocate an IP to your UML” gestolpert. Das klang genau nach dem was ich brauchte.
Also flugs die Quellen runtergeladen (vom Debian-Mirror, weil zum kompilieren sowieso die Patches aus dem Debian-Paket notwendig sind):
mkdir ~/slirp
cd ~/slirp
wget http://deb.debian.org/debian/pool/main/s/slirp/slirp_1.0.17.orig.tar.gz
wget http://deb.debian.org/debian/pool/main/s/slirp/slirp_1.0.17-11.debian.tar.xz
tar xf slirp_1.0.17.orig.tar.gz
tar xf slirp_1.0.17-11.debian.tar.xz
cd slirp-1.0.17/
for i in ../debian/patches/*.patch; do patch -p1 -i "$i"; done
cd src/
./configure
make CFLAGS="-I. -DUSE_PPP -DUSE_MS_DNS -fno-strict-aliasing -Wno-unused -std=gnu89 -DFULL_BOLT"
Da ich das User Mode Linux hinterher per SSH erreichen wollte, musste ich einen Port in der Uberspace Firewall öffnen:
uberspace port add
Damit das Portforwarding für SSH funktioniert, brauchte es zum Starten von Slirp ein Wrapperscript:
#! /usr/bin/env bash
exec /home/USERNAME/slirp/slirp-1.0.17/src/slirp "redir PORT 22" "host address 10.0.2.2"
USERNAME ist hierbei durch den eigenen Uberspace Benutzernamen und PORT durch den eben geöffneten Port ersetzt werden.
Jetzt konnte ich das erste mal das UML starten:
/home/USERNAME/linux ubd0=/home/USERNAME/debian.img root=/dev/ubda rw mem=256M eth0=slirp,,/home/USERNAME/slirp.sh reboot=force
Das mem=256M sagt hierbei, dass das User Mode Linux maximal 256MB RAM nutzen darf, was okay sein sollte, da auf https://manual.uberspace.de/basics-resources/#ram
steht, dass ein Asteroid maximal 1.5 GB nutzen darf.
Nachdem das User Mode Linux gestartet war, konnte ich mich einloggen (mit root und dem Passwort von oben) und per apt-get --no-install-recommends install openssh-server
einen SSH-Server installieren. Danach habe ich noch meinen SSH Public Key nach /root/.ssh/authorized_keys gelegt und konnte mich per SSH einloggen:
ssh -pPORT USERSPACE-HOST
Fazit: Man kann das machen, es ist aber nicht besonders schnell. Ich sehe das ganze nur als PoC und werde das nicht produktiv betreiben.