In der Informatik-Infrastruktur haben wir eine Docker-basierte Umgebung, die Ihr vom ersten Semester an benutzt, um dort in einer isolierten Umgebung Web-Anwendungen zu entwickeln (docker).
Im dritten Semester untersuchen wir in dem Modul Vernetzte Systeme mit welchen Techniken und Werkzeugen skalierbare, redundante und separierte Systeme aufgebaut werden. Das wird üblicherweise in virtuellen Maschinen und Containern auf Servern in Rechenzentren - in der Cloud - durchgeführt.
Hier wollen wir Euch zeigen, wie Ihr auf Eurem Laptop eine kleine Umgebung mit docker aufbauen könnt, die derjenigen in der Infrastruktur ähnelt und mit der Ihr Vernetzung und Verteilung üben könnt und die Ihr mit in Euer Berufsleben nehmen könnt.
Dazu müsst Ihr die Umgebung so aufbauen, wie es unter setup.html, wezterm.html und hopper.html beschrieben ist.
Zudem muss nun unter Windows noch die WSL2 mit Ubuntu installiert sein und unter MacOS/ARM utm und darin Ubuntu/Server installiert sein.
Alternativ für MacOS und Linux probieren wir gerade lima (Linux Machine) aus (siehe unten).
Sorgt in jedem Fall dafür, dass Ihr eine aktuelle Ubuntu (ab 24.04) oder Debian-Distribution laufen habt und dass Ihr dort mit ssh hineinkommt.
Folgt der Anleitung unter Microsoft/wsl/install. Sorgt zuvor dafür, dass Eure Windows-Version auf dem aktuellen Stand ist.
Nach der Installation solltet Ihr noch dafür sorgen, dass Ihr schnell mit ssh ubuntu innerhalb des Terminals in Eure Ubuntu-Installation kommt. Startet dazu die wsl aus der Powershell oder git-bash heraus, installiert erst einmal die minimale Software (openssh-server, vim, curl) und sorgt dafür, dass der ssh-Server automatisch gestartet wird.
Nach dem update legt den Port des ssh-Servers innerhalb der WSL auf 2222 und startet mit systemctl den ssh-Server neu, damit die Änderung wirksam wird.
Seit einiger Zeit übernimmt offensichtlich systemd diesen Teil und wir müssen in /etc/systemd/system/sockets.target.wants/ssh.socket auch noch den ListenStream von 22 auf 2222 setzen.
Wenn Ihr Probleme habt - z.B. systemctl meldet, dass systemd nicht der Prozess 1 sei, dann könnte es sein, dass Eure WSL selbst nicht aktuell ist.
Bringt sie dann mit wsl --update auf den aktuellen Stand. Weitere hilfreiche Kommandos für die wsl gibt es unter basic-commands
wsl
sudo apt update
sudo apt install -y openssh-server vim curl
sudo vim /etc/ssh/sshd_config
# passe dort den Eintrag an:
Port 2222
# und verlasse den vim ...
sudo vim /etc/systemd/system/sockets.target.wants/ssh.socket
# passe dort den Eintrag an
ListenStream=2222
# und verlasse den vim
sudo systemctl daemon-reload
sudo systemctl enable ssh
sudo systemctl restart ssh
Da wir nicht nur mal eben in die Linux-Umgebung hineinwollen, sondern sie eine ständig verfügbare Arbeitsumgebung sein soll, müssen wir noch dafür sorgen, dass sie sich nicht wieder abschaltet, wenn wir mal nicht im Terminal drin sind. Innerhalb der WSL gebt dafür an:
dbus-launch true
Und wenn sie automatisch beim Windowsstart mit hochgefahren werden soll, legt eine Datei runwsl.bat im Autostart-Ordner unter Windows an mit dem Inhalt:
wsl --exec dbus-launch true
Die Konfiguration für das passwortlose Einloggen in die VM mit ssh ubuntu löst Ihr analog zu der Installation aus dem ersten Semester.
Hier die Kurzfassung:
Editiert die Datei ~/.ssh/config in der git-bash - also unter Windows - so, dass dort der Alias ubuntu auf die wsl zeigt.
host ubuntu
hostname localhost
port 2222
user EUER-LINUX-USER
Auch hier könnt Ihr mit der richtigen Kombination aus ssh-keygen und ssh-keyscan das erstmalige Nachfragen beim Fingerprint verhindern.
ssh-keygen -R [localhost]:2222; ssh-keyscan -p 2222 -4 localhost >> .ssh/known_hosts
Unter MacOS empfehlen wir im Moment lima statt utm. Die Installation ist einfacher und ähnelt derjenigen unter Linux. Siehe Abschnitt Lima Linux Machine
Für Mac-Systeme installiert utm als Virtualisieungssoftware wie unter https://mac.getutm.app/ beschrieben.
Nach der Installation von utm solltet Ihr darin Ubuntu 24.04 installieren (guides/ubuntu). Ich empfehle die Server-Variante. Achtet darauf, genügend Speicher zur Verfügung zu stellen (wenn möglich 32GB).
Unter Linux könnt Ihr docker direkt installieren. Unter Windows und MacOS muss docker in einer Linux-VM installiert sein. Ihr könnt natürlich, wenn Ihr Euch herausfordern wollt, auch unter Linux eine Linux-VM mit kvm installieren und dort dann docker installieren.
Für den Moment empfehle ich hier ebenfalls lima.
lima wirkt ausgesprochen leichtgewichtig und ist schnell mal eben installiert. Zudem gibt es lima für Linux und MacOS.
Sowohl unter MacOS als auch unter Linux (debian/ubuntu) ging es bei mir nach der Anleitung unter https://lima-vm.io/docs/installation/ unter dem Abschnitt Binary.
Für MacOS mit brew installiert es so wie es da steht.
Für Linux statt brew install jq dann einfach sudo apt install jq (was vermutlich schon passiert ist). Die beiden anderen Zeilen mit curl funktionieren dann auch. Lediglich vor dem tar muss ebenfalls sudo stehen. Danach dann limactl start und dann lima und man ist drin. Selbst ssh ist dann vorbereit (der Port wird ausgegeben (60022) und es müssten dann nur noch Einträge in der .ssh/config nachgezogen werden).
Notfalls lässt sich mit
limactl shell default bash -c 'cat >>~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub
der Public-Key nachträglich injizieren und Ihr könnt Euch einloggen.
ssh -p 60022 localhost
Falls angemerkt wird, dass noch ein Paket fehlt, ist es vermutlich qemu
sudo apt install qemu-system qemu-utils
Etwas ungewöhnlich ist, dass man mit dem Kommando lima in dem Verzeichnis auch innerhalb der VM ist, in dem das Kommando aufgerufen wurde. Mit cd kommt man dann wie gewöhnlich in das VM-spezifische Homeverzeichnis. Wenn Ihr hingegen mit ssh in die VM geht, ist das aktuelle Verzeichnis direkt das VM-Homeverzeichnis.
Bei meinem Lenovo X260 Notebook mit debian musste ich noch dafür sorgen, dass die Virtualisierung insgesamt aktiviert wird. Das stellt man im BIOS ein (bei mir: F1 beim Booten drücken und dann in den Menüs Virtualisierung suchen und aktivieren).
Mit:
grep --color vmx /proc/cpuinfo # intel
grep --color svm /proc/cpuinfo # amd
seht Ihr dann, ob Hardware-Virtualisierung aktiviert ist.
(Quelle: cyberciti.biz)
Auf einem meiner Systeme (debian) musste ich mich noch zur Gruppe kvm hinzufügen (sudo usermod -aG kvm ...) und beim Start die Konfiguration so anpassen, dass unter firmware der Parameter legacyBIOS auf true steht (kvm-permission-denied).
Bei lima werden beim Starten (also auch beim automatischen Starten nach dem Booten des Laptops) die Host-Keys normalerweise neu erzeugt. Beim erstmaligen Verbinden über ssh wird geprüft, ob der Host - bzw. dessen Key in der .ssh/known_hosts bekannt ist. Falls nicht, wird der fingerprint angezeigt und wir sollen sie prüfen und gegebenenfalls mit yes bestätigen.
Inhaltlich ist das eher ein Thema für die Security-Veranstaltungen - also: was kann eigentlich passieren, wenn man all zu blindlings jeweils mit yes bestätigt? Auf jeden Fall ein sehr spannendes Thema und wer Lust und Interesse hat, kann sich damit gerne beschäftigen - z.B. mit Understanding SSH Host Keys .
Aus einem Host-Key, der sich mit ssh-keyscan erfragen lässt, wird mit ssh-keygen der Fingerprint berechnen:
ssh-keyscan -p 60022 localhost | ssh-keygen -lf -
Für hopper gelten folgende Fingerprints:
ssh-keyscan -p 8080 hopper.hs-bremerhaven.de | ssh-keygen -lf -
# hopper.hs-bremerhaven.de:8080 SSH-2.0-OpenSSH_9.7p1 Debian-4
# hopper.hs-bremerhaven.de:8080 SSH-2.0-OpenSSH_9.7p1 Debian-4
# hopper.hs-bremerhaven.de:8080 SSH-2.0-OpenSSH_9.7p1 Debian-4
# hopper.hs-bremerhaven.de:8080 SSH-2.0-OpenSSH_9.7p1 Debian-4
# hopper.hs-bremerhaven.de:8080 SSH-2.0-OpenSSH_9.7p1 Debian-4
2048 SHA256:hfbmouXTPHIVX/ar4i7QlDrMkX+ygPeCTPWMjPcVwwc [hopper.hs-bremerhaven.de]:8080 (RSA)
256 SHA256:tqmc7laeYMeRFZwgIFheEBPPr3dCpqAfvBI9/tx6O+M [hopper.hs-bremerhaven.de]:8080 (ECDSA)
256 SHA256:uSmqfeC1Eij31faRWjOgI2GtGblQxjhYFvYlMHO7XrU [hopper.hs-bremerhaven.de]:8080 (ED25519)
Jedenfalls wird bei lima cloud-init genutzt. Das ist ein mittlerweile ausgesprochen weit verbreitetes Verfahren um bei Cloud-Providern wie Hetzer oder Amazon virtuelle Maschinen bei der Initialisierung konfigurieren zu lassen.
Hier nur so viel: Bei cloud-init wird mit einer Text-Datei (im yaml-Format) beschrieben, wie die zu erzeugende VM aussehen soll (welche Software nachinstalliert werden soll, welche User angelegt werden sollen, etc).
Wir müssen nun bei der Initialisierung der lima-default-VM dafür sorgen, dass an einer bestimmten Stelle explizit angegeben wird, dass wir beim Starten die Host-Keys nicht neu erzeugen. Ich habe für lima (MacOS und Linux) eine kleine Konfigurationsdatei vorbereitet, die Ihr statt der Default-Konfiguration von lima nutzen solltet.
Wie bei mir üblich, holt Ihr sie Euch mit curl aus meinem Web-Verzeichnis:curl -O https://informatik.hs-bremerhaven.de/oradfelder/lima.yaml
Danach könnt Ihr sie nutzen, um eine VM zu erzeugen und dann zu starten:
cat lima.yaml | limactl create --name=default -
limactl start
Ab dann solltet Ihr die VM stoppen und starten können, ohne dass Ihr den Key neu bestätigen müsst. Beim erstmaligen ssh -p 60022 localhost müsst Ihr das natürlich trotzdem bestätigen - es ist ja jetzt eine neue VM und damit hat sie auch neue Host-Keys ...) Nach dem Stoppen und Starten jedoch werdet Ihr nicht mehr gefragt...
Schaut ruhig in die yaml-Datei hinein - das ist die Default-Config von lima, bei der ich lediglich zwei Dinge angepasst habe:
Umkonfigurieren der cloud-init Struktur
provision:
- mode: system
script: |
#!/bin/sh
mkdir -p /etc/cloud/cloud.cfg.d
echo "ssh_deletekeys: false" > /etc/cloud/cloud.cfg.d/lima-local.cfg
Den Port localhost:8000 in die VM als Port 80 forwarden (auf Port 80 lauscht später der apache2-Webserver)
portForwards:
- guestPort: 80
hostPort: 8000 # overrides the default value 80
Für die Automatisierung des Erzeugens von lokalen VMs ist es hilfreich, die bisherigen Keys mit ssh-keygen -R zu entfernen und die neuen mit ssh-keyscan anzuhängen:
ssh-keygen -R [localhost]:60022 # entferne die Keys aus .ssh/known_hosts
ssh-keyscan -p 60022 localhost >> .ssh/known_hosts # scannen und anfügen
Sobald Ihr mit ssh in Eure Linux-Umgebung kommt, sorgt zunächst dafür, dass sie auf dem aktuellen Stand ist:
sudo apt update && sudo apt -y upgrade
Dann solltet Ihr dringend mit:
sudo update-alternatives --set editor /usr/bin/vim.basic
dafür sorgen, dass Ihr nicht im falschen Moment im nano landet und dann
vielleicht nicht wisst, wie Ihr dort wieder herauskommt ...
Ich tendiere dazu, unter allen Systemen als Standard en_US.UTF-8 einzutragen, da ansonsten einige Programme (date, bc, ...) sich aufgrund der Lokalisierung anders verhalten.
sudo sed -i "s/^# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/g" /etc/locale.gen && \
sudo locale-gen en_US.UTF-8 && \
sudo update-locale LANG=en_US.UTF-8
Wenn Ihr genug Platz habt in der VM solltet Ihr Euch auch dort wieder unser Standard-Setup installieren - bzw. eine Variante ohne die grafischen Anwendungen - wir wollen ja im Server arbeiten. Dieses Mal nur als Liste für eine hopper-ähnliche Umgebung - jeweils einzeln oder alle zusammen könnt Ihr die Software mit sudo apt -y install selbständig hinzufügen:
a2ps apache2 apache2-utils bash-builtins bash-completion
bat bc bsdmainutils build-essential coreutils csvkit curl direnv dos2unix
ed emacs-nox ffmpeg fonts-liberation git gnuplot-nox
gpg graphviz html2text imagemagick inkscape
inotify-tools iperf3 iproute2 iputils-ping
jq jid libxml2-utils maven moreutils mutt ncat
net-tools nftables nmap openjdk-17-jdk openjdk-17-doc openjdk-17-source openssh-server
pdf2svg pdftk plantuml poppler-utils procps pv pwgen python-is-python3 python3-pygments python3-venv
qrencode redis-server restic shellcheck
shfmt socat sqlite3 sshfs tcpdump
tidy tree unzip valgrind vim w3m wrk websocketd
wget wrk xml2 xmlstarlet xxd xsltproc
zbar-tools
Solch eine Sammlung von Paketen lässt sich gut in eine Textdatei kopieren und dann in einer Schleife installieren. Allerdings wird man gegebenenfalls nach jedem installierten Paket gefragt, welche Dienste neu zu starten sind. Das lässt sich durch entsprechende Umgebungsvariablen verhindern:
while read -r line; do sudo bash -c "export DEBIAN_FRONTEND=noninteractive;export NEEDRESTART_MODE=a; apt install -y $line"; done < packs.txt
Insgesamt ist dann mit den noch zu installierenden docker
und nodejs in der VM etwa 10 GB für das System verbraucht.
Wenn es bei Euch eng ist, sprecht mit uns, was Ihr weglassen könnt.
Denkt unter Ubuntu und Debian daran, dass Ihr auch hier einen Softlink für bat setzt:
sudo ln -s /usr/bin/batcat /usr/local/bin/bat
Nur im dritten Semester, wenn wir mit Docker arbeiten: Da wir in den docker-Containern auch einen Webserver auf Port 80 installieren, solltet Ihr baldmöglich den installierten apache2 deaktivieren.
sudo systemctl stop apache2
sudo systemctl disable apache2
Für diejenigen, die Linux direkt installiert haben (und nicht in einer VM): Ihr braucht nicht per ssh auf Euren Rechner zu kommen und solltet das auch vorerst abschalten:
sudo systemctl stop ssh
sudo systemctl disable ssh
Zudem ist vermutlich nftables bei Euch als Firewall eingerichtet. Die solltet Ihr auch gleich so einrichten, dass erst einmal Euer Rechner nach außen hin abgesichert ist. Prüft zuerst, ob nftables installiert und aktiviert ist:
sudo systemctl status nftables
Falls dort inactive angzeigt wird, sollte es mit
sudo systemctl enable nftables
sudo systemctl start nftables
aktiviert und gestartet werden. Gegebenenfalls muss dann auch der docker-Daemon einmal mit
sudo systemctl restart docker
neu gestartet werden, damit er seine Regeln dort wieder hineinschreiben kann. Nach dem
nächsten Systemstart ist das nicht mehr notwendig.
Die unterschiedlichen Distributionen benutzen nun unterschiedliche Frontends für nftables oder gar andere Firewall-Systeme wie ufw. Mein Vorschlag wäre, direkt auf nftables zu setzen.
Bisweilen ist es notwendig, die lokale Zeitzone einzustellen:
sudo timedatectl set-timezone "Europe/Berlin"
Danach installiert docker nach der Anleitung auf Install Docker Engine on Debian bzw. Install Docker Engine on Ubuntu jeweils unter dem Abschnitt Install using the apt repository.
Sorgt dann dafür, dass Euer Standarduser, mit dem Ihr in die WSL oder VM kommt, Mitglied der Gruppe docker ist, damit Ihr nicht jedesmal sudo vor die docker-Befehle schreiben müsst.
sudo usermod -aG docker $USER
Damit Ihr dann für die aktuelle Sitzung auch in der Gruppe seid:
newgrp docker
Nach dem nächsten Einloggen seid Ihr dann automatisch in der Gruppe.
Auf keinen Fall installiert Euch irgendeine docker for ...-Variante.
Es mag einfacher erscheinen, mit dem grafischen Werkzeug zu arbeiten, bei dem die konkrete Arbeit wegabstrahiert wird. Hier geht es aber nur zum Teil um docker als solches, sondern vornehmlich um docker als Werkzeug, um auf Euren Notebooks eine Netzwerkumgebung einzurichten, wie sie dann in realen Umgebungen aus vernetzten Rechnern besteht.
Und natürlich könnt Ihr, wenn erst einmal VM und docker soweit eingerichtet sind, auch alle 'klassischen' docker-Dinge tun.
Sowohl unter Windows/WSL2 als auch in UTM/lima/Ubuntu wird zunächst die derzeitige LTS (Long Term Support) Version 24.04 installiert. Falls Ihr noch aus dem vorigen Semester 22.04 oder eine Zwischenversion habt, lässt sie sich in einem Schritt upgraden:
sudo apt update
sudo apt upgrade -y
sudo apt dist-upgrade -y
sudo apt install update-manager-core -y
sudo sed -i 's/normal/lts/g' /etc/update-manager/release-upgrades
sudo sed -E -i -'s/jammy|lunar|kinetic|mantic/noble/g' /etc/apt/sources.list
sudo apt update
sudo apt upgrade -y
sudo apt dist-upgrade -y
sudo reboot
# bzw. unter Windows in der git-bash:
# wsl shutdown
# wsl bash -i -c "nohup sleep 3600 &>/tmp/sleep.log &"
Dementsprechend kann nun auch das jdk-17 deinstalliert und jdk-21 installiert werden, falls das noch nicht der Fall ist.
sudo apt purge openjdk-17-jdk openjdk-17-doc openjdk-17-source
sudo apt install -y openjdk-21-jdk openjdk-21-doc openjdk-21-source
sudo apt autoremove -y
Erst im nächsten Schritt lässt sich dann auf 23.10 upgraden, was sicher auch getan werden sollte, da im Januar 2024 die Version 23.04 ihr End of Life erfuhr:
sudo do-release-upgrade
Es gibt sehr unterschiedliche Arbeitsweisen mit docker und je nachdem, wie es praktiziert wird und in welcher Entwicklungswelt wir unterwegs sind, wird auch unterschiedliches in der VM selbst benötigt. Wir machen unterwegs einen kleinen Ausflug in die typische Entwicklung mit Javascript/Node und dort ist es üblich, dass eine aktuelle node-Umgebung zum Arbeiten in der VM bzw. dem umgebenden Linux installiert ist und dort entwickelt wird. Daher ist es wichtig, hier eine passende node-Version zu installieren. Macht das bitte unbedingt nach dem aktuell empfohlen Verfahren, wie es im unten stehenden Link beschrieben ist, und folgt nicht irgendwelchen veralteten Webseiten!
Auf der Seite https://github.com/nodesource/distributions findet Ihr den Weg - ähnlich wie bei docker - ein externes Repository in die eigene Paketverwaltung mit aufzunehmen. Das sind immer die drei Schritte:
Ihr werdet recht oft aufgefordert werden, mit dem Paketmanager irgendetwas global zu installieren und benötigt dann dafür sudo-Rechte. Das ist aber nicht immer vernünftig. Auch wenn es keine perfekte Lösung ist, scheint das Umbiegen des globalen Installationsverzeichnisses auf ein HOME-lokales der bessere Weg zu sein.
mkdir "${HOME}/.npm-packages"
npm config set prefix "${HOME}/.npm-packages"
Dann sollte die .bashrc mit den folgenden Zeilen ergänzt werden:
NPM_PACKAGES="${HOME}/.npm-packages"
export PATH="$PATH:$NPM_PACKAGES/bin"
export MANPATH="${MANPATH-$(manpath)}:$NPM_PACKAGES/share/man"
Damit wird dafür gesorgt, dass dann auch vermeintlich global installierte Pakete im Pfad gefunden werden und Binaries ebenfalls. Mit npm config list kann dann ab dem nächsten Einloggen auf die aktuelle Konfiguration zugegriffen werden und mit npm list -g die installierten globalen Pakete aufgelistet werden. Dependency-Management in der Javascript-Welt ist nicht so richtig rund gelöst. Zu npm kommen noch npx, nvm und yarn und manches andere dazu.