diff --git a/2026/2026-10-21--castopod-php-stay-off.md b/2026/2026-10-21--castopod-php-stay-off.md deleted file mode 100644 index 0455ac3..0000000 --- a/2026/2026-10-21--castopod-php-stay-off.md +++ /dev/null @@ -1,13 +0,0 @@ -# Castopod stays off - -Rechecked 2026-10-21 after the stop note. Web unit container-koopa-castopod.service is disabled, inactive, dead. Container koopa-castopod is exited, finished 2026-10-21 22:48:06 +0200. Nothing listens on :9020. MariaDB and Redis user units stay loaded and active. No second stop. Caddy vhost unchanged. - -Log review found no sign of a successful remote code execution. Overlay file /tmp/fw-cp.php (1448 bytes, mode 600, sha256 7bb279bffa12dbb81787183108a2641b78a6657b069cbef7967950d80e13b5bc, mtime 2026-09-07 03:25:59 +0200) is a local database script for cp_users, outside the docroot, not a web shell. /tmp/os-dry.out is an apt dry-run. Five theme files differ by one branding line from 2026-07-13. Media volume has no scripts. Access logs run 2026-10-17 through the stop and show no 2xx on a non-index script. Critical lines on 2026-09-07 match other days. - -Limits: access logs start 2026-10-17, so HTTP from 2026-09-07 is absent. A memory-only or already rotated request is not ruled out. Whether the local script ran is not in the logs. MariaDB was not opened. - -Stays down until an image ships PHP newer than 8.4.18. Hub tag :1 from 2026-02-24 is not that image. Parent 537, slug castopod-restart-after-php-fix. - -Restore only then: - - systemctl --user enable --now container-koopa-castopod.service diff --git a/2026/2026-10-21--castopod-php-stop.md b/2026/2026-10-21--castopod-php-stop.md deleted file mode 100644 index e951d06..0000000 --- a/2026/2026-10-21--castopod-php-stop.md +++ /dev/null @@ -1,23 +0,0 @@ -# Castopod PHP stopped - -Checked 2026-10-21. Host has no php-fpm and no php package. The only PHP process was Castopod FrankenPHP in container koopa-castopod. - -| Item | Value | -|------|--------| -| image | docker.io/castopod/castopod:1 | -| repo digest | sha256:4e4f0440520f45257bfeac7be4347defd20048b4efef8f53d73ec9ed3a4f7966 | -| amd64 digest | sha256:757f3c2a96b31b81753c23bc092dfcf05039d9df4d13cc12c428bb752fce882b | -| image created | 2026-02-24 | -| hub tags 1 / latest / 1.15.5 | same digest, pushed 2026-02-24 | -| PHP | 8.4.18 (12 Feb 2026) | -| FrankenPHP | v2.10.2 | -| listen | 0.0.0.0:9020 -> 8080 | -| public | https://castopod.hacktivism.ch/ | - -Stable Hub tags have not moved since 2026-02-24. develop last push 2026-06-05 and is not a stable security update. php.net lists 8.4.26 (24 Sep 2026) and 8.4.27 (22 Oct 2026) after 8.4.18, with a banner to update for critical remote code execution. Pulling :1 repeats the same image. FrankenPHP ships its own PHP binary. - -Stopped and disabled user unit container-koopa-castopod.service. ExecStop is `podman stop -t 30 koopa-castopod`. Container status after stop: Exited (0). :9020 not listening. MariaDB and Redis units left running. Caddy vhost unchanged. - -Bring the web container back only when a newer image exists: - - systemctl --user enable --now container-koopa-castopod.service diff --git a/2026/2026-10-24--todo704-tor-cachyos-cookieauth.md b/2026/2026-10-24--todo704-tor-cachyos-cookieauth.md deleted file mode 100644 index 46665b5..0000000 --- a/2026/2026-10-24--todo704-tor-cachyos-cookieauth.md +++ /dev/null @@ -1,41 +0,0 @@ -# TODO=704 Tor CachyOS CTR + CookieAuth (koopa) - -Relay was down (stale PIDFile / start-timeout on forking unit), keys intact. Recreated **same identity** on CachyOS container; CookieAuth for ControlPort; host tor disabled. - -## Stand after APPLY (2026-10-24 ~21:47–21:51 Europe/Zurich) - -| Item | Value | -|------|--------| -| CTR | `koopa-tor-relay` Up, image `localhost/koopa-tor-relay:latest` (=`:cachyos`) | -| Tor | 0.4.9.14 (CachyOS/Arch extra) | -| Unit | `container-koopa-tor-relay.service` Type=simple, active | -| Host tor | `tor.service` disabled + failed/inactive | -| FP | `02C7EECCDF7814FBA2DB1CBAED000D06E8A32EE8` (keys mtime 2024-11-14) | -| ORPort | 8080 | -| ControlPort | 127.0.0.1:9051 CookieAuthentication=1, CookieAuthFile=/var/lib/tor/control_auth_cookie | -| Bootstrap | PROGRESS=100 done; status/circuit-established=1 | -| Unauth ControlPort | 514 Authentication required | -| Cookie AUTH | 250 OK | - -## Steps - -1. Dry-run `/tmp/tor.sh` on koopa → STATUS=dry-run-ok; NEXT=`sudo APPLY=1 /tmp/tor.sh` (host tor was still enabled). -2. Human: `systemctl disable --now tor.service`, then `sudo APPLY=1 /tmp/tor.sh`. -3. APPLY: wrote CachyOS Containerfile, pulled `docker.io/cachyos/cachyos:latest`, build (cache hit), `podman create --replace --network host --user 1000:1000 --userns keep-id`, torrc bak `torrc.bak-cookie-20261024-214720`, CookieAuth on. -4. First APPLY hit dbus fail under sudo (`$DBUS_SESSION_BUS_ADDRESS` / `$XDG_RUNTIME_DIR` unset). Unit rewrite + enable finished with XDG/DBUS set; script path re-exec as SUDO_USER for later runs. -5. Verify from magikoopa SSH: unit active, CTR Up, FP match, circuit-established=1, unauth 514. - -## Live paths - -- `~/koopa-tor-relay/{torrc,data,log,build/Containerfile}` -- `~/.config/systemd/user/container-koopa-tor-relay.service` -- Driver: `/tmp/tor.sh` (TARGET=koopa); upgrade later: `~/upgrade-containers.sh --apply --rebuild-local --only koopa-tor-relay` - -## Akte mirrors - -- `configs/tor/torrc` -- `configs/tor/build/Containerfile` -- `configs/systemd/user/container-koopa-tor-relay.service` -- `host/tor/README.md` updated (was stale host `tor.service`) - -Sibling: firecuda brew tor CookieAuth same day (FP `52BB94DDC1292F950CF728708AC48523E018A718`, MyFamily both ways). Parent TODO=704. diff --git a/configs/systemd/user/container-koopa-tor-relay.service b/configs/systemd/user/container-koopa-tor-relay.service deleted file mode 100644 index b65e1ce..0000000 --- a/configs/systemd/user/container-koopa-tor-relay.service +++ /dev/null @@ -1,21 +0,0 @@ -# container-koopa-tor-relay.service — regenerated by tor.sh 2026-10-24T21:47:24+02:00 -# Prefer simple over podman-generate-systemd forking+PIDFile (stale CID storm). - -[Unit] -Description=Podman koopa-tor-relay -Wants=network-online.target -After=network-online.target -RequiresMountsFor=%t/containers - -[Service] -Environment=PODMAN_SYSTEMD_UNIT=%n -Restart=always -RestartSec=5 -TimeoutStartSec=120 -TimeoutStopSec=70 -ExecStart=/usr/bin/podman start --attach koopa-tor-relay -ExecStop=/usr/bin/podman stop -t 10 koopa-tor-relay -Type=simple - -[Install] -WantedBy=default.target diff --git a/configs/tor/build/Containerfile b/configs/tor/build/Containerfile deleted file mode 100644 index c57a137..0000000 --- a/configs/tor/build/Containerfile +++ /dev/null @@ -1,24 +0,0 @@ -# koopa-tor-relay — Tor non-exit relay on CachyOS (Arch extra/tor) -# Same pattern as koopa-meet-web:cachyos. Rootless: tor user -> uid/gid 1000. -# Recreate: --user 1000:1000 --userns=keep-id (see README / tor.sh) -ARG CACHYOS_IMAGE=docker.io/cachyos/cachyos:latest -FROM ${CACHYOS_IMAGE} -ENV TZ=Europe/Zurich -RUN pacman -Syu --noconfirm --needed tor nyx ca-certificates \ - && pacman -Scc --noconfirm \ - && rm -rf /var/cache/pacman/pkg/* /tmp/* \ - && mkdir -p /var/lib/tor /var/log/tor \ - && if id tor >/dev/null 2>&1; then \ - groupmod -g 1000 tor 2>/dev/null || true; \ - usermod -u 1000 -g 1000 tor 2>/dev/null || true; \ - elif id debian-tor >/dev/null 2>&1; then \ - groupmod -g 1000 debian-tor; usermod -u 1000 -g 1000 debian-tor; \ - else \ - groupadd -g 1000 tor; useradd -u 1000 -g 1000 -d /var/lib/tor -s /usr/bin/nologin tor; \ - fi \ - && chown -R 1000:1000 /var/lib/tor /var/log/tor \ - && chmod 700 /var/lib/tor -EXPOSE 8080 9051 -USER 1000:1000 -ENTRYPOINT ["/usr/bin/tor"] -CMD ["-f", "/etc/tor/torrc", "--runasdaemon", "0"] diff --git a/configs/tor/torrc b/configs/tor/torrc deleted file mode 100644 index 9f1705f..0000000 --- a/configs/tor/torrc +++ /dev/null @@ -1,18 +0,0 @@ -# KoopaRelay — same policy as live /etc/tor/torrc + admin-log configs/tor/torrc -# Identity: keys in DataDirectory (migrate from host /var/lib/tor) -Log notice file /var/log/tor/notices.log -Nickname KoopaRelay -ContactInfo info+koopa@hacktivism.ch -# dual-stack: bind all addresses on 8080 (IPv4 + IPv6), same as host tor -ORPort 8080 -ControlPort 127.0.0.1:9051 -CookieAuthentication 1 -CookieAuthFile /var/lib/tor/control_auth_cookie -ExitRelay 0 -SocksPort 0 -MyFamily 52BB94DDC1292F950CF728708AC48523E018A718 -BandwidthRate 2000 MBytes -BandwidthBurst 2000 MBytes -RelayBandwidthRate 2000 MBytes -RelayBandwidthBurst 2000 MBytes -DataDirectory /var/lib/tor diff --git a/host/tor/README.md b/host/tor/README.md index fa68a9c..138d11d 100644 --- a/host/tor/README.md +++ b/host/tor/README.md @@ -1,30 +1,13 @@ # Tor on koopa -**Runtime:** rootless podman container **`koopa-tor-relay`** (CachyOS base, Arch `extra/tor`), managed by user unit **`container-koopa-tor-relay.service`** (`Type=simple`, `podman start --attach`). -**Host `tor.service`:** disabled / must stay off (port clash on ORPort 8080 + ControlPort 9051). -**Ports:** ORPort **8080** · ControlPort **127.0.0.1:9051** (CookieAuthentication + CookieAuthFile). -**Non-exit** relay (`ExitRelay 0`). Nickname **KoopaRelay**. -**Fingerprint (stable keys under `~/koopa-tor-relay/data/keys/`):** `02C7EECCDF7814FBA2DB1CBAED000D06E8A32EE8` -**Family:** firecuda FireCudaRelay `52BB94DDC1292F950CF728708AC48523E018A718` - -Live tree: `~/koopa-tor-relay/` (`torrc`, `data/`, `log/`, `build/Containerfile`). -Mirrors in this repo: `configs/tor/torrc`, `configs/tor/build/Containerfile`, `configs/systemd/user/container-koopa-tor-relay.service`. +**Runtime:** host **`tor.service`** (not a podman container). +**Ports:** ORPort **8080** · ControlPort **9051** (loopback). +**Non-exit** relay (`ExitRelay 0`). ```bash -# status -systemctl --user status container-koopa-tor-relay.service -podman ps --filter name=koopa-tor-relay -# ControlPort cookie auth (hex) -COOKIE=$(xxd -p -c 256 ~/koopa-tor-relay/data/control_auth_cookie) -printf 'AUTHENTICATE %s\r\nGETINFO fingerprint\r\nGETINFO status/circuit-established\r\nQUIT\r\n' "$COOKIE" | nc -w 3 127.0.0.1 9051 +systemctl status tor +ss -lntp | grep -E '8080|9051' ``` -Apply / recreate (after host tor off): - -```bash -sudo APPLY=1 /tmp/tor.sh -# later upgrades: -~/upgrade-containers.sh --apply --rebuild-local --only koopa-tor-relay -``` - -login-health: expect user unit active + CTR Up; host `tor.service` inactive. Parent TODO=704. +login-health: WARN if `tor.service` not active. +Legacy `koopa-tor-relay` / `configs/tor/` removed from live inventory (git history keeps them). diff --git a/scripts/pepsi/ensure-mon-users.sh b/scripts/pepsi/ensure-mon-users.sh deleted file mode 100755 index 661edaa..0000000 --- a/scripts/pepsi/ensure-mon-users.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bash -# Idempotent: ensure mon-* OS users + Maildir inside koopa-pepsi. -# Needed after every container recreate: /home is not in the image and is -# not a volume by default → useradd state vanishes while DB login_assignment -# survives. -# -# UIDs fixed 1000–1004 (match login_assignment / prior live). -# STATUS= only; no secrets. Run on koopa as hernani (rootless podman exec). -set -euo pipefail - -CTR="${PEPSI_CTR:-koopa-pepsi}" -USERS=( - "mon-smtp:1000" - "mon-maildir:1001" - "mon-dkim:1002" - "mon-bounce:1003" - "mon-local:1004" -) - -echo "STATUS=start CTR=$CTR HOST=$(hostname -s)" - -if ! podman container exists "$CTR" 2>/dev/null; then - echo "STATUS=missing_ctr CTR=$CTR" - exit 2 -fi -if [[ "$(podman inspect -f '{{.State.Running}}' "$CTR" 2>/dev/null || echo false)" != "true" ]]; then - echo "STATUS=ctr_not_running CTR=$CTR" - exit 3 -fi - -created=0 -present=0 -for entry in "${USERS[@]}"; do - u="${entry%%:*}" - uid="${entry##*:}" - if podman exec "$CTR" getent passwd "$u" >/dev/null 2>&1; then - echo "USER=$u STATE=present" - present=$((present + 1)) - else - podman exec -u root "$CTR" useradd -u "$uid" -U -m -d "/home/$u" -s /usr/sbin/nologin "$u" - echo "USER=$u STATE=created UID=$uid" - created=$((created + 1)) - fi - # Maildir skeleton (cur/new/tmp) — safe if already present - podman exec -u root "$CTR" bash -c " - set -e - home=/home/$u - mkdir -p \"\$home/Maildir\"/{cur,new,tmp} - chown -R $u:$u \"\$home\" - chmod 700 \"\$home\" - " - echo "MAILDIR=$u OK=1" -done - -echo "STATUS=done CREATED=$created PRESENT_BEFORE=$present EXPECT=${#USERS[@]}" -podman exec "$CTR" getent passwd | grep '^mon-' || true -exit 0 diff --git a/scripts/pepsi/firewalld-pepsi-highports.sh b/scripts/pepsi/firewalld-pepsi-highports.sh deleted file mode 100755 index 1387fa1..0000000 --- a/scripts/pepsi/firewalld-pepsi-highports.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash -# Open rootless pepsi high-ports on koopa (firewalld). -# Compose map (LAN bind 192.168.100.95): -# 1025→25 1465→465 1587→587 1993→993 18443→443 -# Freigabe: human this session. Run on koopa as root / sudo. -set -euo pipefail - -PORTS=(1025/tcp 1465/tcp 1587/tcp 1993/tcp 18443/tcp) -ZONE="${FIREWALLD_ZONE:-}" - -if [[ ${EUID:-$(id -u)} -ne 0 ]]; then - echo "STATUS=need_root HINT='sudo $0'" - exit 2 -fi - -if ! command -v firewall-cmd >/dev/null 2>&1; then - echo "STATUS=no_firewalld" - exit 3 -fi - -if ! firewall-cmd --state >/dev/null 2>&1; then - echo "STATUS=firewalld_down" - exit 4 -fi - -if [[ -z "$ZONE" ]]; then - # Prefer the zone that owns the LAN NIC; else default. - ZONE=$(firewall-cmd --get-zone-of-interface=eno1 2>/dev/null || true) - if [[ -z "$ZONE" ]]; then - ZONE=$(firewall-cmd --get-default-zone) - fi -fi - -echo "STATUS=start ZONE=$ZONE HOST=$(hostname -s)" - -added=0 -present=0 -for p in "${PORTS[@]}"; do - if firewall-cmd --zone="$ZONE" --query-port="$p" >/dev/null 2>&1; then - echo "PORT=$p STATE=present" - present=$((present + 1)) - else - firewall-cmd --zone="$ZONE" --add-port="$p" --permanent - echo "PORT=$p STATE=added_permanent" - added=$((added + 1)) - fi -done - -firewall-cmd --reload -echo "STATUS=reloaded" - -ok=0 -for p in "${PORTS[@]}"; do - if firewall-cmd --zone="$ZONE" --query-port="$p" >/dev/null 2>&1; then - echo "VERIFY=$p OK=1" - ok=$((ok + 1)) - else - echo "VERIFY=$p OK=0" - fi -done - -echo "STATUS=done ZONE=$ZONE ADDED=$added PRESENT_BEFORE=$present VERIFY_OK=$ok EXPECT=${#PORTS[@]}" -if [[ "$ok" -eq "${#PORTS[@]}" ]]; then - exit 0 -fi -exit 1 diff --git a/scripts/pepsi/hostnet-pepsi-highports.sh b/scripts/pepsi/hostnet-pepsi-highports.sh deleted file mode 100755 index aeacc55..0000000 --- a/scripts/pepsi/hostnet-pepsi-highports.sh +++ /dev/null @@ -1,204 +0,0 @@ -#!/usr/bin/env bash -# Switch koopa-pepsi to network_mode:host on high ports so SMTP client IP -# is preserved (rootlessport SNAT otherwise forces 10.89.16.4 → SPF fail). -# -# Vecigate stays pure DNAT (25/465/587 → 1025/1465/1587). No mail on router. -# DB stays bridged; publish 127.0.0.1:15432→5432 for host-net pepsi. -# -# Freigabe: human this session (Script hinlegen + apply+restart). -# Run on koopa as hernani (rootless podman). Never echoes DB secrets. -set -euo pipefail - -PEPSI_DIR="${PEPSI_DIR:-$HOME/koopa-pepsi}" -TS="$(date +%Y%m%d-%H%M%S)" -BAK="${PEPSI_DIR}/bak-hostnet-${TS}" -COMPOSE_BIN="" - -echo "STATUS=start HOST=$(hostname -s) DIR=$PEPSI_DIR" - -if [[ ! -d "$PEPSI_DIR" ]]; then - echo "STATUS=missing_dir PATH=$PEPSI_DIR" - exit 2 -fi -cd "$PEPSI_DIR" - -if command -v podman-compose >/dev/null 2>&1; then - COMPOSE_BIN="podman-compose" -elif podman compose version >/dev/null 2>&1; then - COMPOSE_BIN="podman compose" -else - echo "STATUS=no_compose" - exit 3 -fi - -if [[ ! -f compose.yml || ! -f conf/pepsi.conf ]]; then - echo "STATUS=missing_files" - exit 4 -fi - -already=0 -if grep -q 'network_mode:[[:space:]]*host' compose.yml \ - && grep -qE '^PORT = 1025$' conf/pepsi.conf \ - && grep -qE '@127\.0\.0\.1:15432/' conf/pepsi.conf; then - already=1 - echo "STATUS=already_hostnet HINT=skip_patch" -fi - -if [[ "$already" -eq 0 ]]; then - mkdir -p "$BAK" - cp -a compose.yml conf/pepsi.conf "$BAK/" - echo "STATUS=bak PATH=$BAK" - - python3 - <<'PY' -from pathlib import Path -import re -import sys - -root = Path(".") -compose_path = root / "compose.yml" -conf_path = root / "conf" / "pepsi.conf" -compose = compose_path.read_text() -conf = conf_path.read_text() - -# Split services crudely on "\n pepsi:" / "\n db:" -def patch_compose(text: str) -> str: - # Retarget env DB URLs first (password stays ${VAR}) - text = text.replace("@db:5432/", "@127.0.0.1:15432/") - - # Ensure db publishes 127.0.0.1:15432:5432 - if "15432:5432" not in text: - text = re.sub( - r"(container_name: koopa-pepsi-db\n)", - r'\1 ports:\n - "127.0.0.1:15432:5432"\n', - text, - count=1, - ) - - # pepsi service: add network_mode host; remove its ports: block - # Match from " pepsi:" until next top-level service or "volumes:" - m = re.search(r"(?ms)^ pepsi:\n(.*?)(?=^volumes:|^ [a-z])", text) - if not m: - print("STATUS=pepsi_service_not_found") - sys.exit(5) - body = m.group(1) - # drop ports block inside pepsi - body2 = re.sub(r"(?m)^ ports:\n(?: [^\n]*\n)+", "", body) - if "network_mode:" not in body2: - body2 = re.sub( - r"(container_name: koopa-pepsi\n)", - r"\1 network_mode: host\n", - body2, - count=1, - ) - text = text[: m.start(1)] + body2 + text[m.end(1) :] - return text - - -def set_port(text: str, section: str, port: int) -> str: - pat = rf"(\[{re.escape(section)}\]\n(?:.*\n)*?PORT = )\d+" - new, n = re.subn(pat, rf"\g<1>{port}", text, count=1) - if n != 1: - print(f"STATUS=port_patch_fail SECTION={section} N={n}") - sys.exit(6) - return new - - -compose = patch_compose(compose) -conf = conf.replace("@db:5432/", "@127.0.0.1:15432/") -conf = set_port(conf, "pepsi-ingress-listener-mx", 1025) -conf = set_port(conf, "pepsi-ingress-listener-submissions", 1465) -conf = set_port(conf, "pepsi-ingress-listener-submission", 1587) -conf = set_port(conf, "pepsi-httpd-listener-https", 18443) - -compose_path.write_text(compose) -conf_path.write_text(conf) - -# sanity STATUS (no secrets) -checks = [ - ("network_mode_host", bool(re.search(r"(?m)^ network_mode:\s*host\s*$", compose))), - ("db_pub_15432", "15432:5432" in compose), - ("no_db_hostname", "@db:5432/" not in compose and "@db:5432/" not in conf), - ("port_1025", bool(re.search(r"(?m)^PORT = 1025\s*$", conf))), - ("port_1465", bool(re.search(r"(?m)^PORT = 1465\s*$", conf))), - ("port_1587", bool(re.search(r"(?m)^PORT = 1587\s*$", conf))), - ("port_18443", bool(re.search(r"(?m)^PORT = 18443\s*$", conf))), - ("pepsi_ports_gone", "192.168.100.95:1025" not in compose), -] -for k, v in checks: - print(f"CHECK={k} OK={int(v)}") -if not all(v for _, v in checks): - print("STATUS=patch_sanity_fail") - sys.exit(7) -print("STATUS=patched") -PY -fi - -echo "STATUS=compose_up BIN=$COMPOSE_BIN" -# shellcheck disable=SC2086 -$COMPOSE_BIN up -d --force-recreate -sleep 4 - -echo "STATUS=verify" -ss_out="$(ss -lntp 2>/dev/null | grep -E ':1025|:1465|:1587|:18443|:15432' || true)" -# redact pid/user clutter lightly -echo "$ss_out" | sed -E 's/users:\(\("([^"]+)".*/users=(("\1"…)/' || true - -rootless_hit=0 -if echo "$ss_out" | grep -q rootlessport; then - rootless_hit=1 -fi -db_pub=0 -if echo "$ss_out" | grep -qE '127\.0\.0\.1:15432'; then - db_pub=1 -fi -mx_ok=0 -if echo "$ss_out" | grep -qE ':1025\b'; then - mx_ok=1 -fi - -podman ps --format '{{.Names}} {{.Status}}' | grep pepsi || true - -if command -v pg_isready >/dev/null 2>&1; then - if pg_isready -h 127.0.0.1 -p 15432 -d pepsi >/dev/null 2>&1; then - echo "STATUS=db_ready HOST=127.0.0.1 PORT=15432" - else - echo "STATUS=db_not_ready HOST=127.0.0.1 PORT=15432" - fi -else - if timeout 2 bash -c 'echo >/dev/tcp/127.0.0.1/15432' 2>/dev/null; then - echo "STATUS=db_tcp_open HOST=127.0.0.1 PORT=15432" - else - echo "STATUS=db_tcp_closed HOST=127.0.0.1 PORT=15432" - fi -fi - -# recent log lines (strip any postgres URLs) -podman logs --tail 40 koopa-pepsi 2>/dev/null \ - | grep -Ei 'listen|error|fatal|spf|client|1025|postgres|ready' \ - | sed -E 's#postgres://[^[:space:]]+#postgres://*#g' \ - | tail -12 || true - -echo "STATUS=done MX_1025=$mx_ok DB_PUB=$db_pub ROOTLESSPORT_ON_HIGH=$rootless_hit BAK=${BAK:-none}" -echo "HINT=next ensure-mon-users.sh after recreate; then taler-mail send --expect-pong" -echo "HINT=Vecigate DNAT unchanged (no mail on router); /home ephemeral unless volume+ensure" -# Optional: run ensure if sibling script present (same dir or PEPSI_DIR/scripts) -ENSURE="" -here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -for cand in "$here/ensure-mon-users.sh" "$PEPSI_DIR/scripts/ensure-mon-users.sh" "$PEPSI_DIR/ensure-mon-users.sh"; do - if [[ -x "$cand" ]]; then - ENSURE="$cand" - break - fi -done -if [[ -n "$ENSURE" ]]; then - echo "STATUS=ensure_mon_users SCRIPT=$ENSURE" - PEPSI_CTR=koopa-pepsi "$ENSURE" || echo "STATUS=ensure_warn" -fi -if [[ "$mx_ok" -eq 1 && "$rootless_hit" -eq 0 && "$db_pub" -eq 1 ]]; then - exit 0 -fi -if [[ "$mx_ok" -eq 1 && "$db_pub" -eq 1 ]]; then - echo "STATUS=warn_rootlessport_still_present" - exit 0 -fi -exit 1