#!/usr/bin/env sh set -u cd "$(dirname "$0")" get_env() { key="$1" awk -F= -v k="$key" '$1==k {sub(/^[^=]*=/, ""); print; exit}' .env 2>/dev/null || true } set_env() { key="$1"; value="$2"; tmp=".env.tmp.$$" awk -v k="$key" -v v="$value" ' BEGIN {done=0} index($0,k"=")==1 {print k"="v; done=1; next} {print} END {if(!done) print k"="v} ' .env > "$tmp" && mv "$tmp" .env } bool_true() { case "${1:-}" in 1|true|TRUE|yes|YES|on|ON) return 0 ;; *) return 1 ;; esac } port_owner() { port="$1" docker ps --format '{{.Names}} {{.Ports}}' 2>/dev/null | awk -v p=":${port}->" 'index($0,p){print $1; exit}' } port_free() { [ -z "$(port_owner "$1")" ] } choose_free_port() { start="$1" p="$start" n=0 while [ "$n" -lt 100 ]; do if port_free "$p"; then printf '%s' "$p"; return 0; fi p=$((p+1)); n=$((n+1)) done return 1 } ensure_port() { key="$1"; fallback="$2" val="$(get_env "$key")" [ -n "$val" ] || return 0 owner="$(port_owner "$val")" [ -z "$owner" ] && return 0 case "$owner" in greenfield-siem-*) return 0 ;; esac if bool_true "$(get_env AUTO_PORTS)"; then new="$(choose_free_port "$fallback")" || { echo "FEHLER: Kein freier Ersatzport für $key gefunden." >&2 exit 1 } echo "Portkonflikt: $key=$val wird bereits von '$owner' benutzt -> verwende $new." set_env "$key" "$new" else echo "FEHLER: $key=$val ist bereits durch '$owner' belegt. AUTO_PORTS=true aktivieren oder .env anpassen." >&2 exit 1 fi } probe_clickhouse() { image="$1" echo "Prüfe ClickHouse-Binary '$image' auf dieser CPU ..." docker pull "$image" >/dev/null 2>&1 || return 125 set +e docker run --rm --entrypoint clickhouse "$image" local --query 'SELECT 1' >/tmp/siem-clickhouse-probe.out 2>/tmp/siem-clickhouse-probe.err rc=$? set -e return "$rc" } [ -f .env ] || { echo "FEHLER: .env fehlt." >&2; exit 1; } ARCH="$(uname -m 2>/dev/null || echo unknown)" echo "Host-Architektur: $ARCH" if command -v lscpu >/dev/null 2>&1; then lscpu | awk -F: '/Architecture|Model name|Vendor ID|CPU op-mode/{gsub(/^[ \t]+/,"",$2); print $1 ": " $2}' || true fi # Resolve host-port collisions before Compose creates containers. ensure_port UI_PORT 18080 ensure_port INGRESS_PORT 18090 ensure_port CLICKHOUSE_HTTP_PORT 18123 ensure_port CLICKHOUSE_NATIVE_PORT 19000 ensure_port POSTGRES_PORT 15432 ensure_port REDPANDA_KAFKA_PORT 29092 ensure_port REDPANDA_ADMIN_PORT 29644 ensure_port REDPANDA_CONSOLE_PORT 18081 ensure_port GARAGE_S3_PORT 13900 ensure_port GARAGE_ADMIN_PORT 13903 ensure_port PROMETHEUS_PORT 19090 ensure_port GRAFANA_PORT 13000 if bool_true "$(get_env CLICKHOUSE_CPU_PROBE)"; then image="$(get_env CLICKHOUSE_IMAGE)" [ -n "$image" ] || image='clickhouse/clickhouse-server:26.3.17.56' if probe_clickhouse "$image"; then echo "ClickHouse CPU-Probe: OK ($image)" else rc=$? echo "ClickHouse CPU-Probe fehlgeschlagen (Exit $rc)." >&2 cat /tmp/siem-clickhouse-probe.err >&2 2>/dev/null || true fallback="$(get_env CLICKHOUSE_FALLBACK_IMAGE)" if [ -n "$fallback" ] && [ "$fallback" != "$image" ]; then echo "Teste LTS-Fallback: $fallback" if probe_clickhouse "$fallback"; then echo "LTS-Fallback läuft auf dieser CPU. CLICKHOUSE_IMAGE wird auf $fallback gesetzt." set_env CLICKHOUSE_IMAGE "$fallback" exit 0 else frc=$? echo "Auch LTS-Fallback fehlgeschlagen (Exit $frc)." >&2 cat /tmp/siem-clickhouse-probe.err >&2 2>/dev/null || true fi fi echo >&2 echo "ClickHouse kann auf dieser CPU/VM mit den offiziellen Images nicht ausgeführt werden." >&2 case "$ARCH" in x86_64|amd64) echo "Das offizielle amd64-Image benötigt mindestens SSE3. Prüfe: grep -m1 '^flags' /proc/cpuinfo" >&2 echo "Bei einer VM: CPU-Modell auf 'host' / CPU-Passthrough stellen, sofern die physische CPU SSE3 unterstützt." >&2 ;; aarch64|arm64) echo "Das offizielle arm64-Image benötigt ARMv8.2-A plus RCpc-Unterstützung." >&2 echo "Bei einer VM: CPU-Passthrough aktivieren. Auf älterer ARMv8.0/8.1-Hardware ist ein offizielles aktuelles Image nicht kompatibel." >&2 ;; esac echo "Diagnose: ./host-info.sh" >&2 exit 42 fi fi