Gordon Zimm 75de1540b1 Seed legt keine Anleitung mehr auf der VM ab
Der late-command, der /root/ERSTINBETRIEBNAHME.txt erzeugte, ist entfernt
(11 statt 12 late-commands). Auf der VM wird nichts gelesen, und eine
mitgelieferte Anleitung altert dort: ab dem zweiten Kunden stehen auf den
Maschinen verschiedene Staende, die niemand nachzieht.

Die Handgriffe stehen jetzt im Runbook des internen Repositorys
(espo-fleet-ops/docs/runbooks/erstinbetriebnahme-kunden-vm.md); der Seed
nennt es in einer Kommentarzeile, autoinstall/README.md verweist darauf.

Dabei mitgezogen: Abschnitt "Ablageort" nannte noch die Zwischenkopie
gordon.zimm/ubuntu-autoinstall (O-26 ist seit 23.09.2026 entschieden),
und drei Links zeigten auf docs/, das es in diesem Repo nicht gibt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-25 09:48:00 +02:00

123 lines
6.8 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#cloud-config
# Autoinstall-Seed für die EspoCRM-Kunden-VM (Ubuntu Server 24.04 LTS auf Hyper-V).
# Stand 2026-09-22, abgeleitet aus gitea gordon.zimm/ubuntu-autoinstall (Commit 0cd9fc6).
# Auf einer Test-VM am 22.09.2026 vollständig durchgelaufen (Ubuntu 24.04.5, Hyper-V, 127-GiB-Platte).
#
# Grundsätze:
# * Der Seed wird per NoCloud über HTTP geladen und kann sich nicht authentisieren
# -> er enthält KEIN Geheimnis: kein benutzbares Passwort, kein RMM-Token.
# * Die ISO richtet nur das Minimum ein. Docker, Härtung, Logrotation, Firewall, Hostname und
# Instanz kommen reproduzierbar über RMM-Tasks ("alles Weitere erfolgt über ConnectWise RMM").
# * Der Seed legt keine Anleitung auf der VM ab. Die Handgriffe nach dem ersten Start stehen im
# Runbook espo-fleet-ops/docs/runbooks/erstinbetriebnahme-kunden-vm.md.
autoinstall:
version: 1
source:
id: ubuntu-server
updates: all
locale: de_DE.UTF-8
keyboard:
layout: de
timezone: Europe/Berlin
# Schnittstellennamen nicht festnageln: Hyper-V meldet je nach Kernel eth0 oder enp*.
network:
version: 2
ethernets:
primary:
match:
name: "e*"
dhcp4: true
dhcp6: false
identity:
realname: administrator
username: administrator
hostname: unkonfiguriert # ESPO-01 setzt ihn auf espo-<kuerzel> aus %companyuniqueid%
# Hash eines einmalig erzeugten 48-Zeichen-Zufallspassworts; der Klartext wurde nirgends abgelegt.
# Das Konto ist damit faktisch gesperrt, bis die late-commands je VM ein Initialpasswort setzen.
password: '$6$KDLfMzLPV6wWtwA4$9VnUET9kFWUVp07z2hkN9Kv9.WjgdIPGLmm7zb4Te47Ms7lyrw/9Ewpqf759xVfXcOfAkWJSFrxUClfeyxeuI0'
ssh:
install-server: true
allow-pw: true
authorized-keys: []
packages:
- linux-cloud-tools-virtual # hv_kvp_daemon, hv_vss_daemon, hv_fcopy_daemon
- curl # Voraussetzung des RMM-Agenten (libcurl4 kommt mit)
- bzip2 # der .run-Installer entpackt sich damit
# kein linux-azure: der Azure-Kernel ist für Azure gebaut. Soll er trotzdem bleiben,
# gehört linux-cloud-tools-azure dazu, sonst fehlen die Hyper-V-Integrationsdienste.
# Explizite Aufteilung: klein für das Betriebssystem, groß für die Nutzdaten.
# `layout: {name: lvm, sizing-policy: scaled}` wäre kürzer, gibt aber rund die Hälfte der Platte an "/" –
# auf einer reinen Docker-VM ist das an der falschen Stelle.
storage:
config:
- {type: disk, id: disk0, ptable: gpt, match: {size: largest}, wipe: superblock-recursive, preserve: false, grub_device: false}
- {type: partition, id: part-esp, device: disk0, size: 1G, flag: boot, grub_device: true, preserve: false}
- {type: format, id: fmt-esp, volume: part-esp, fstype: fat32, preserve: false}
- {type: mount, id: mnt-esp, device: fmt-esp, path: /boot/efi}
- {type: partition, id: part-boot, device: disk0, size: 2G, preserve: false}
- {type: format, id: fmt-boot, volume: part-boot, fstype: ext4, preserve: false}
- {type: mount, id: mnt-boot, device: fmt-boot, path: /boot}
- {type: partition, id: part-pv, device: disk0, size: -1, flag: lvm, preserve: false}
- {type: lvm_volgroup, id: vg0, name: ubuntu-vg, devices: [part-pv], preserve: false}
# Betriebssystem, RMM-Agent, Logs – 20 GiB sind reichlich (Bedarf real 8–12 GiB)
- {type: lvm_partition, id: lv-root, name: root-lv, volgroup: vg0, size: 20G, preserve: false}
- {type: format, id: fmt-root, volume: lv-root, fstype: ext4, preserve: false}
- {type: mount, id: mnt-root, device: fmt-root, path: /}
# `path: none` für Swap ist am 22.09.2026 auf einer Test-VM bestätigt worden.
- {type: lvm_partition, id: lv-swap, name: swap-lv, volgroup: vg0, size: 4G, preserve: false}
- {type: format, id: fmt-swap, volume: lv-swap, fstype: swap, preserve: false}
- {type: mount, id: mnt-swap, device: fmt-swap, path: none}
# Images, Container, Container-Logs – reproduzierbar, wird nicht gesichert
- {type: lvm_partition, id: lv-docker, name: docker-lv, volgroup: vg0, size: 20G, preserve: false}
- {type: format, id: fmt-docker, volume: lv-docker, fstype: ext4, preserve: false}
- {type: mount, id: mnt-docker, device: fmt-docker, path: /var/lib/docker}
# /srv (Nutzdaten) wird in late-commands anteilig angelegt, damit der Seed für jede Plattengröße passt.
late-commands:
# 1. /srv bekommt den gesamten Rest bis auf 10 GiB. Die bleiben als Platz für einen LVM-Snapshot
# vor einem Update frei: Ein Snapshot hält nur die während seiner Lebensdauer geänderten Blöcke,
# dafür sind 10 GiB reichlich. Eine grössere Reserve lohnt nicht – die VHDX ist dynamisch und
# jederzeit erweiterbar. Das lvreduce läuft vor dem mkfs und ist deshalb risikolos.
# Beispiel 128-GiB-Platte: / 20, swap 4, docker 20, /srv ~71, frei 10 GiB.
- lvcreate -y -l 100%FREE -n srv-lv ubuntu-vg
- lvreduce -y -L -10G /dev/ubuntu-vg/srv-lv
- mkfs.ext4 -q -L srv /dev/ubuntu-vg/srv-lv
- mkdir -p /target/srv
# Eintrag über UUID, wie curtin es für die übrigen Dateisysteme tut.
- >-
SRVUUID=$(blkid -s UUID -o value /dev/ubuntu-vg/srv-lv);
printf 'UUID=%s /srv ext4 defaults 0 2\n' "$SRVUUID" >> /target/etc/fstab
# 2. Je VM zufälliges Initialpasswort, am Konsolen-Login sichtbar, Wechsel beim ersten Anmelden erzwungen.
- >-
PW=$(tr -dc 'A-Za-z0-9' </dev/urandom | head -c 20);
echo "administrator:$PW" | curtin in-target -- chpasswd;
curtin in-target -- chage -d 0 administrator;
printf '\n Initialpasswort administrator: %s\n (beim ersten Anmelden ändern, danach diese Zeile aus /etc/issue entfernen)\n' "$PW" >> /target/etc/issue
# 3. Hyper-V-Integrationsdienste (Zeit/IP-Meldung, Dateisystem-Quiesce für Veeam).
# Normalerweise startet udev sie selbst; enable schadet nicht und darf fehlschlagen.
- curtin in-target -- systemctl enable hv-kvp-daemon.service hv-vss-daemon.service || true
# 4. Zum Schluss alles auf den neuesten Stand bringen. `updates: all` deckt den Stand zu Beginn der
# Installation ab; dieser Durchgang holt, was währenddessen dazugekommen ist, und räumt auf.
# NEEDRESTART_SUSPEND verhindert Dienst-Neustarts im chroot.
- curtin in-target -- sh -c 'DEBIAN_FRONTEND=noninteractive NEEDRESTART_SUSPEND=1 apt-get update'
- curtin in-target -- sh -c 'DEBIAN_FRONTEND=noninteractive NEEDRESTART_SUSPEND=1 apt-get -y -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef full-upgrade'
- curtin in-target -- sh -c 'DEBIAN_FRONTEND=noninteractive apt-get -y autoremove --purge'
- curtin in-target -- sh -c 'apt-get clean'
shutdown: poweroff