#!/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 </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