Die vier gepinnten Versionen existieren im Docker-Repo fuer noble (geprueft gegen den Packages-Index), die Ursache liegt also woanders. Statt zu raten gibt das Skript jetzt im Fehlerfall die Simulation von apt (mit der konkreten unerfuellten Abhaengigkeit), die verfuegbaren Versionen inklusive iptables und nftables, die bereits installierten Docker-Pakete und haengende Installationen aus. Ausserdem -q statt -qq, damit apt ueberhaupt etwas sagt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
110 lines
5.1 KiB
Bash
Executable File
110 lines
5.1 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
|
|
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. Paketquelle von Docker einrichten (Schluessel und deb822-Quelle), falls noch nicht vorhanden.
|
|
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"; 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"; exit 1; }
|
|
|
|
# 2. Genau diese Versionen installieren und auf Hold setzen, damit nichts unbemerkt nachzieht.
|
|
# Scheitert die Installation, sagt das Skript woran - eine blosse Fehlermeldung hilft niemandem weiter.
|
|
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"
|
|
if ! DEBIAN_FRONTEND=noninteractive apt-get install -y -q $PAKETE; then
|
|
echo "--- Diagnose: was apt dazu sagt"
|
|
DEBIAN_FRONTEND=noninteractive apt-get -s install $PAKETE 2>&1 | tail -n 30
|
|
echo "--- Diagnose: was verfuegbar ist"
|
|
apt-cache policy docker-ce containerd.io docker-compose-plugin docker-buildx-plugin iptables nftables
|
|
echo "--- Diagnose: was schon installiert ist"
|
|
dpkg -l | grep -Ei 'docker|containerd|runc' || echo "keine Docker-Pakete installiert"
|
|
echo "--- Diagnose: haengende Installationen"
|
|
dpkg -l | awk '$1 !~ /^ii/ && NR > 5 {print}' || true
|
|
echo "FEHLER: Installation"
|
|
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
|
|
|
|
# 3. 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
|
|
systemctl enable --now docker >/dev/null 2>&1
|
|
systemctl restart docker || { echo "FEHLER: docker startet nicht"; exit 1; }
|
|
|
|
# 4. 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.
|
|
command -v iptables >/dev/null || { echo "FEHLER: iptables fehlt"; 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; }
|
|
|
|
# 5. 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
|