Zum Inhalt

Neuen Host aufsetzen

Ungeprüft

Diese Anleitung ist noch nicht durchgespielt worden; Befehle, Bezeichnungen und erwartete Ausgaben können abweichen. Was noch zu prüfen ist, steht in todo/doku.md.

Ziel

Eine neue VM ist so eingerichtet, dass du darauf mit cue cmd apply Container ausrollen kannst, wie auf werner und containerhost.

Voraussetzungen

In den Befehlen steht <host> für den kurzen Namen des neuen Hosts, etwa werner, und <fqdn> für seinen vollen Namen, etwa werner.garage-lab.de. Ein Host im Rechenzentrum bekommt einen Namen unter garage-lab.de, ein Host im Maschinendorf einen unter garage-lab.net.

Schritte

1. VM anlegen

Leg die VM in der Web-Oberfläche der Plattform an:

  • Betriebssystem: Rocky Linux in der Version, die auf werner läuft
  • Anmeldung als root mit deinem öffentlichen SSH-Schlüssel (~/.ssh/garagelab.pub), nicht mit Passwort

Bei Netcup stellst du zusätzlich die Firewall vor der VM so ein, dass sie nur die Ports 80 und 443 und den Port für WireGuard durchlässt, wie bei werner.

Notiere die IP-Adressen der VM. Erwartet: ssh root@<ip-adresse> hostname meldet sich ohne Passwort an und gibt einen Namen aus.

2. Namen im DNS eintragen

Für einen Host unter garage-lab.de: Trag in desec/desec_garage_lab_de.cue die Adressen unter ipam: ein und dazu einen A- und einen AAAA-Eintrag mit subname: "<host>", wie bei werner. Roll die Zone im Ordner desec/ aus wie in Änderung ausrollen, mit cue cmd plan und cue cmd apply.

Für einen Host unter garage-lab.net kommt kein Eintrag nach deSEC; den Namen löst der DNS-Server auf dem Gateway auf, der nicht im Repo steht. Bitte in Signal jemanden mit Zugang zum Gateway, den Namen dort einzutragen.

Bash
dig +short <fqdn>

Erwartet: die IPv4-Adresse der VM. Für Namen unter garage-lab.net geht das nur aus dem Netz vor Ort.

3. SSH-Zugang für alle Admins einrichten

Ergänze in deiner ~/.ssh/config den neuen Namen in der Zeile Host, die du in Arbeitsrechner einrichten, Schritt 8 angelegt hast, etwa Host werner.garage-lab.de vm-containerhost.garage-lab.net <fqdn>.

Übernimm dann die Schlüssel aller Admins von werner:

Bash
ssh werner.garage-lab.de cat /root/.ssh/authorized_keys | ssh <fqdn> 'cat >> /root/.ssh/authorized_keys'
ssh <fqdn> cat /root/.ssh/authorized_keys

Achte auf die zwei >>, damit dein Schlüssel aus Schritt 1 erhalten bleibt. Erwartet: alle Schlüssel von werner, dazu deiner; doppelt stehende Zeilen schaden nicht.

4. Zeitzone und Pakete einrichten

Bash
1
2
3
4
5
6
7
ssh <fqdn>
timedatectl set-timezone UTC
dnf -y install epel-release
crb enable
dnf -y copr enable rhcontainerbot/podman-next
dnf -y install bind-utils net-tools wireguard-tools httpd-tools bash-completion nano git podman dnf-automatic htop btop jq nfs-utils
podman --version

Erwartet: jeder dnf-Befehl endet mit Complete!, und podman --version zeigt mindestens Version 6, die syslet voraussetzt. Die übrigen Befehle in diesem Schritt und in Schritt 5 bis 7 laufen auf dem neuen Host; mit exit kommst du zurück auf deinen Rechner.

5. syslet installieren

Installiere syslet nach Installation in der syslet-Doku, für x86_64.

Bash
syslet --version

Erwartet: syslet mit Versionsnummer.

6. Dateien aus rootfs/ kopieren

Nur, wenn es für den Host einen Ordner rootfs/<host>/ gibt. Auf deinem Rechner, im Repo-Ordner:

Bash
COPYFILE_DISABLE=1 tar -C rootfs/<host> -cf - . | ssh <fqdn> tar -C / --no-same-owner --no-overwrite-dir -xf -
(cd rootfs/<host> && find . -type f | cut -c2-) | ssh <fqdn> xargs restorecon -v

Das Kopieren legt jede Datei unter demselben Pfad auf dem Host ab, wie sie unter rootfs/<host>/ liegt; der zweite Befehl gibt ihnen das passende SELinux-Label. Erwartet: keine Ausgabe vom Kopieren; restorecon nennt die Dateien, deren Label es korrigiert hat, oder gibt nichts aus.

Bash
ssh <fqdn> 'systemctl daemon-reload && sysctl --system'

Erwartet: sysctl listet unter anderem die Dateien aus etc/sysctl.d/.

Schalte dann die Timer und Mounts aus rootfs/<host>/etc/systemd/system/ ein: auf werner system-backup.timer, auf containerhost mnt-backup.mount. Für mnt-backup.mount muss das NAS die Freigabe für die Adresse des Hosts erlauben; frag in Signal nach, falls das noch nicht so ist.

Bash
1
2
3
ssh werner.garage-lab.de systemctl enable --now system-backup.timer
ssh vm-containerhost.garage-lab.net systemctl enable --now mnt-backup.mount
ssh vm-containerhost.garage-lab.net ls /mnt/backup

Erwartet: Created symlink … je Unit; ls zeigt die Ordner auf dem NAS, darunter werner-garage-lab-de.

7. Automatische Updates einschalten

Die Einstellungen kommen mit etc/dnf/automatic.conf aus Schritt 6, der Zeitpunkt mit etc/systemd/system/dnf-automatic-install.timer.d/override.conf. Gibt es diese Dateien für den neuen Host noch nicht, leg sie vorher in rootfs/<host>/ an, nach dem Vorbild von werner, und wiederhol Schritt 6.

Bash
systemctl enable --now dnf-automatic-install.timer
systemctl list-timers dnf-automatic-install.timer

Erwartet: In der Spalte NEXT steht der nächste Morgen zu der Uhrzeit (UTC) aus override.conf.

8. WireGuard-Tunnel einrichten

Nur für einen Host außerhalb des Maschinendorfs, der wie werner über einen WireGuard-Tunnel mit dem Server-VLAN verbunden wird. Führe WireGuard-Tunnel einrichten aus; die Subnetze des Netzwerks caddy aus Schritt 4 dort trägst du erst nach dem ersten apply ein.

Erwartet: wg show zeigt den Peer mit einem latest handshake vor wenigen Sekunden.

9. Schlüssel des Hosts für SOPS eintragen

Auf deinem Rechner:

Bash
ssh <fqdn> cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age

Erwartet: eine Zeile, die mit age1 beginnt.

Ergänze in syslet/.sops.yaml unter keys: eine Zeile - &server_<host> age1… und unter creation_rules: eine neue Regel nach dem Muster der vorhandenen:

YAML
1
2
3
4
5
  - path_regex: <host>/.*\.enc\.yaml$
    key_groups:
      - age:
          - *admin_<name>
          - *server_<host>

Unter age: stehen alle Admins, die auch in den anderen Regeln stehen, und der neue Host. Erwartet: git diff syslet/.sops.yaml zeigt die neue Zeile unter keys: und die neue Regel.

10. Ordner für den Host anlegen

Leg syslet/<host>/host.cue an:

Text Only
1
2
3
4
5
6
7
8
9
@extern(embed)

package syslet

fqdn: "<fqdn>"

secretFiles: _ @embed(glob=creds-*.enc.yaml,type=text,allowEmptyGlob)

sysdef: {}

Ohne die Zeile secretFiles bekommt der Host keine Secrets. Container kommen später in eigenen Dateien dazu, wie in App hinzufügen.

Bash
1
2
3
cd syslet/<host>
cue fmt
cue cmd plan

Erwartet: No changes detected. All units are up to date.

11. Committen und pushen

Bash
1
2
3
4
cd ../..
git add desec syslet/.sops.yaml syslet/<host>
git commit -m "add host <host>"
git push

Erwartet: am Ende von git push eine Zeile main -> main.

Prüfen

  • cue cmd plan in syslet/<host> zeigt No changes detected. All units are up to date.
  • ssh <fqdn> systemctl --failed zeigt 0 loaded units listed.
  • Bei einem Host mit Tunnel: ssh <fqdn> ping -c 3 vm-containerhost.garage-lab.net bekommt Antworten.

Wenn etwas schiefgeht

  • cue cmd plan meldet reference "fqdn" not found: Du bist nicht im Ordner syslet/<host>.
  • cue cmd plan meldet syslet: command not found: syslet liegt auf dem Host nicht im PATH von root; prüf Schritt 5.
  • cue cmd plan meldet decryption failed für ein Secret: Die Datei ist nicht für den Host verschlüsselt; prüf die Regel aus Schritt 9 und verschlüssele die Datei mit sops updatekeys neu, wie in Neue Person freischalten, Schritt 4.
  • dnf copr enable meldet einen Fehler: Prüf, ob Schritt 4 mit crb enable und epel-release durchgelaufen ist.
  • Kein Handshake im Tunnel: WireGuard-Tunnel prüfen
  • Allgemeines: Set up SOPS in a CUE repository in der syslet-Doku und Manage several hosts