Der erste Lauf auf der Pilotkunden-VM endete Failed, sichtbar war nur needrestarts Abschlussmeldung aus dem apt-Lauf - also die Stelle, an der die Pakete fertig installiert waren. Zwischen apt-mark hold und docker --version gibt das Skript nichts aus; aus dem Protokoll liess sich deshalb nicht lesen, wo der Lauf stehen geblieben ist. Zwei Aenderungen: Die lange Ausgabe des apt-Laufs wird aufgefangen und nur im Fehlerfall gezeigt (letzte 30 Zeilen) - sie verdraengt sonst den Bericht am Ende, dasselbe Problem wie der Pull-Fortschritt bei ESPO-03. Und die stumme Strecke bekommt vier knappe Standmeldungen, sodass die letzte Zeile der Ausgabe immer verraet, wie weit der Lauf gekommen ist. Ausserdem tragen jetzt alle Abbrueche des Hauptskripts die Zeile ESPO02_ERGEBNIS: FEHLER - der Script Monitor sucht danach. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
122 lines
6.0 KiB
Bash
Executable File
122 lines
6.0 KiB
Bash
Executable File
#!/bin/bash
|
|
# ESPO-02-Docker - installiert Docker in gepinnter Version, setzt die Daemon-Grundlagen und
|
|
# beschraenkt den Zugang zu veroeffentlichten Container-Ports auf das eigene Subnetz.
|
|
# Laeuft als root ueber einen RMM-Task, idempotent.
|
|
# Ob der Lauf erlaubt ist, entscheidet der Task selbst per If/Then auf espo_zustand.
|
|
set -u
|
|
|
|
# Standzeile: zeigt im Protokoll, welche Fassung tatsaechlich gelaufen ist.
|
|
echo "ESPO-02-Docker, Skriptstand 2026-09-25"
|
|
FEHLER=0
|
|
|
|
# Gepinnte Staende - hier wird der Flottenstand gesetzt, nicht auf der VM entschieden.
|
|
DOCKER_VERSION="5:29.8.1-1~ubuntu.24.04~noble"
|
|
CONTAINERD_VERSION="2.3.5-1~ubuntu.24.04~noble"
|
|
COMPOSE_VERSION="5.5.1-1~ubuntu.24.04~noble"
|
|
BUILDX_VERSION="0.37.1-1~ubuntu.24.04~noble"
|
|
|
|
# 1. Konkurrierende Pakete entfernen. Die offizielle Doku verlangt das ausdruecklich, bevor
|
|
# installiert wird: containerd.io buendelt containerd und runc und steht mit beiden in Conflicts.
|
|
ALTPAKETE="$(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc 2>/dev/null | awk '$2 != "deinstall" {print $1}')"
|
|
if [ -n "$ALTPAKETE" ]; then
|
|
echo "Konkurrierende Pakete gefunden: $ALTPAKETE"
|
|
DEBIAN_FRONTEND=noninteractive apt-get remove -y -q $ALTPAKETE || { echo "FEHLER: konkurrierende Pakete nicht entfernbar"; echo "ESPO02_ERGEBNIS: FEHLER"; exit 1; }
|
|
else
|
|
echo "Konkurrierende Pakete: keine installiert"
|
|
fi
|
|
|
|
# 2. Paketquelle von Docker einrichten (Schluessel und deb822-Quelle), falls noch nicht vorhanden.
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y -q ca-certificates curl >/dev/null
|
|
install -m 0755 -d /etc/apt/keyrings
|
|
if [ ! -s /etc/apt/keyrings/docker.asc ]; then
|
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc || { echo "FEHLER: Schluessel nicht ladbar"; echo "ESPO02_ERGEBNIS: FEHLER"; exit 1; }
|
|
chmod a+r /etc/apt/keyrings/docker.asc
|
|
fi
|
|
cat > /etc/apt/sources.list.d/docker.sources <<CONF
|
|
Types: deb
|
|
URIs: https://download.docker.com/linux/ubuntu
|
|
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
|
|
Components: stable
|
|
Architectures: $(dpkg --print-architecture)
|
|
Signed-By: /etc/apt/keyrings/docker.asc
|
|
CONF
|
|
apt-get update -qq || { echo "FEHLER: apt-get update"; echo "ESPO02_ERGEBNIS: FEHLER"; exit 1; }
|
|
|
|
# 3. Genau diese Versionen installieren und auf Hold setzen, damit nichts unbemerkt nachzieht.
|
|
PAKETE="docker-ce=$DOCKER_VERSION docker-ce-cli=$DOCKER_VERSION containerd.io=$CONTAINERD_VERSION"
|
|
PAKETE="$PAKETE docker-compose-plugin=$COMPOSE_VERSION docker-buildx-plugin=$BUILDX_VERSION"
|
|
# Die Ausgabe wird aufgefangen und nur im Fehlerfall gezeigt: Sie ist lang und verdraengt sonst
|
|
# den Bericht am Ende aus dem Ausfuehrungsprotokoll (dasselbe Problem wie der Pull bei ESPO-03).
|
|
if APT_AUSGABE="$(DEBIAN_FRONTEND=noninteractive apt-get install -y -q $PAKETE 2>&1)"; then
|
|
echo "Pakete installiert: docker-ce $DOCKER_VERSION, containerd.io $CONTAINERD_VERSION, compose, buildx"
|
|
else
|
|
echo "FEHLER: Installation"; echo "$APT_AUSGABE" | tail -30; echo "ESPO02_ERGEBNIS: FEHLER"; exit 1
|
|
fi
|
|
apt-mark hold docker-ce docker-ce-cli containerd.io docker-compose-plugin docker-buildx-plugin >/dev/null
|
|
echo "Versionen auf hold gesetzt"
|
|
|
|
# 4. Daemon-Grundlagen: Logrotation, weil der Standardtreiber nicht rotiert.
|
|
# Keine abweichende Bindeadresse: die Ports muessen fuer den Reverse Proxy erreichbar sein,
|
|
# die Beschraenkung uebernimmt Schritt 4.
|
|
install -d -m 0755 /etc/docker
|
|
cat > /etc/docker/daemon.json <<'CONF'
|
|
{
|
|
"log-driver": "local",
|
|
"log-opts": { "max-size": "20m", "max-file": "5" },
|
|
"live-restore": true
|
|
}
|
|
CONF
|
|
echo "daemon.json geschrieben, Docker-Dienst wird gestartet"
|
|
systemctl enable --now docker >/dev/null 2>&1
|
|
systemctl restart docker || { echo "FEHLER: docker startet nicht"; echo "ESPO02_ERGEBNIS: FEHLER"; exit 1; }
|
|
echo "Docker-Dienst laeuft"
|
|
|
|
# 5. Firewall: Docker setzt seine Weiterleitungsregeln vor die INPUT-Kette und umgeht damit ufw.
|
|
# DOCKER-USER ist die dafuer vorgesehene Stelle. Das Subnetz ermittelt die VM selbst,
|
|
# es ist also kein kundenspezifischer Wert noetig.
|
|
echo "Firewallregeln werden eingerichtet"
|
|
command -v iptables >/dev/null || { echo "FEHLER: iptables fehlt"; echo "ESPO02_ERGEBNIS: FEHLER"; exit 1; }
|
|
cat > /usr/local/sbin/espo-docker-firewall <<'CONF'
|
|
#!/bin/bash
|
|
# Laesst an veroeffentlichte Container-Ports nur das eigene Subnetz heran, verwirft den Rest.
|
|
set -u
|
|
IFACE="$(ip -4 route show default | awk '{print $5; exit}')"
|
|
SUBNETZ="$(ip -4 route show dev "$IFACE" proto kernel scope link | awk '{print $1; exit}')"
|
|
[ -n "$IFACE" ] && [ -n "$SUBNETZ" ] || { echo "FEHLER: Schnittstelle oder Subnetz nicht ermittelbar"; exit 1; }
|
|
iptables -F DOCKER-USER
|
|
iptables -A DOCKER-USER -i "$IFACE" -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN
|
|
iptables -A DOCKER-USER -i "$IFACE" -s "$SUBNETZ" -j RETURN
|
|
iptables -A DOCKER-USER -i "$IFACE" -j DROP
|
|
iptables -A DOCKER-USER -j RETURN
|
|
echo "DOCKER-USER: nur $SUBNETZ ueber $IFACE"
|
|
CONF
|
|
chmod 0755 /usr/local/sbin/espo-docker-firewall
|
|
cat > /etc/systemd/system/espo-docker-firewall.service <<'CONF'
|
|
[Unit]
|
|
Description=Zugang zu veroeffentlichten Docker-Ports auf das eigene Subnetz beschraenken
|
|
After=docker.service
|
|
Requires=docker.service
|
|
PartOf=docker.service
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
RemainAfterExit=yes
|
|
ExecStart=/usr/local/sbin/espo-docker-firewall
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
CONF
|
|
systemctl daemon-reload
|
|
systemctl enable espo-docker-firewall.service >/dev/null 2>&1
|
|
systemctl restart espo-docker-firewall.service || { echo "FEHLER: Firewallregeln nicht gesetzt"; FEHLER=1; }
|
|
|
|
# 6. Ergebnis zeigen und pruefen.
|
|
docker --version
|
|
docker compose version
|
|
docker info --format 'Logtreiber: {{.LoggingDriver}} Live-Restore: {{.LiveRestoreEnabled}}'
|
|
iptables -S DOCKER-USER
|
|
[ "$(docker info --format '{{.LoggingDriver}}')" = "local" ] || { echo "FEHLER: Logtreiber nicht gesetzt"; FEHLER=1; }
|
|
iptables -S DOCKER-USER | grep -q -- '-j DROP' || { echo "FEHLER: DOCKER-USER ohne DROP-Regel"; FEHLER=1; }
|
|
|
|
if [ "$FEHLER" -eq 0 ]; then echo "ESPO02_ERGEBNIS: OK"; exit 0; else echo "ESPO02_ERGEBNIS: FEHLER"; exit 1; fi
|