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>
123 lines
6.8 KiB
Plaintext
123 lines
6.8 KiB
Plaintext
#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
|