From bd5272ebac77418acdb1074c36ee1ccebb791847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hern=C3=A2ni=20Marques?= Date: Thu, 16 Jul 2026 19:14:12 +0200 Subject: [PATCH] Automate Taler merchant and bank app start after container boot. Containers only run sleep infinity; host ensure-taler-apps plus user systemd units start postgres, httpd, libeufin, and auto-confirm. --- .../order.conf | 4 + .../apps.conf | 3 + .../apps.conf | 4 + configs/systemd/user/taler-bank-apps.service | 14 ++ .../systemd/user/taler-merchant-apps.service | 15 ++ scripts/taler-shared/ensure-taler-apps.sh | 163 ++++++++++++++++++ .../taler-shared/install-ensure-taler-apps.sh | 43 +++++ 7 files changed, 246 insertions(+) create mode 100644 configs/systemd/user/container-koopa-paivana.service.d/order.conf create mode 100644 configs/systemd/user/container-taler-hacktivism-bank.service.d/apps.conf create mode 100644 configs/systemd/user/container-taler-hacktivism.service.d/apps.conf create mode 100644 configs/systemd/user/taler-bank-apps.service create mode 100644 configs/systemd/user/taler-merchant-apps.service create mode 100644 scripts/taler-shared/ensure-taler-apps.sh create mode 100644 scripts/taler-shared/install-ensure-taler-apps.sh diff --git a/configs/systemd/user/container-koopa-paivana.service.d/order.conf b/configs/systemd/user/container-koopa-paivana.service.d/order.conf new file mode 100644 index 0000000..c0678cc --- /dev/null +++ b/configs/systemd/user/container-koopa-paivana.service.d/order.conf @@ -0,0 +1,4 @@ +[Unit] +# Paivana needs merchant private API — start after merchant apps, not only container shell +After=taler-merchant-apps.service container-taler-hacktivism.service +Wants=taler-merchant-apps.service diff --git a/configs/systemd/user/container-taler-hacktivism-bank.service.d/apps.conf b/configs/systemd/user/container-taler-hacktivism-bank.service.d/apps.conf new file mode 100644 index 0000000..5bcc386 --- /dev/null +++ b/configs/systemd/user/container-taler-hacktivism-bank.service.d/apps.conf @@ -0,0 +1,3 @@ +[Unit] +Wants=taler-bank-apps.service +Before=taler-bank-apps.service diff --git a/configs/systemd/user/container-taler-hacktivism.service.d/apps.conf b/configs/systemd/user/container-taler-hacktivism.service.d/apps.conf new file mode 100644 index 0000000..e831845 --- /dev/null +++ b/configs/systemd/user/container-taler-hacktivism.service.d/apps.conf @@ -0,0 +1,4 @@ +[Unit] +# Pull in in-container app start after the empty sleep infinity shell is up +Wants=taler-merchant-apps.service +Before=taler-merchant-apps.service diff --git a/configs/systemd/user/taler-bank-apps.service b/configs/systemd/user/taler-bank-apps.service new file mode 100644 index 0000000..7eb3ef2 --- /dev/null +++ b/configs/systemd/user/taler-bank-apps.service @@ -0,0 +1,14 @@ +[Unit] +Description=Start Taler bank apps inside taler-hacktivism-bank +Documentation=file:%h/src/koopa/koopa-admin-log/scripts/taler-shared/ensure-taler-apps.sh +After=network-online.target container-taler-hacktivism-bank.service +Wants=network-online.target container-taler-hacktivism-bank.service + +[Service] +Type=oneshot +RemainAfterExit=yes +TimeoutStartSec=300 +ExecStart=%h/.local/bin/ensure-taler-apps.sh bank + +[Install] +WantedBy=default.target diff --git a/configs/systemd/user/taler-merchant-apps.service b/configs/systemd/user/taler-merchant-apps.service new file mode 100644 index 0000000..22deacd --- /dev/null +++ b/configs/systemd/user/taler-merchant-apps.service @@ -0,0 +1,15 @@ +[Unit] +Description=Start Taler merchant apps inside taler-hacktivism +Documentation=file:%h/src/koopa/koopa-admin-log/scripts/taler-shared/ensure-taler-apps.sh +After=network-online.target container-taler-hacktivism.service +Wants=network-online.target container-taler-hacktivism.service + +[Service] +Type=oneshot +RemainAfterExit=yes +# Merchant start_base + helpers can take a while after cold boot +TimeoutStartSec=300 +ExecStart=%h/.local/bin/ensure-taler-apps.sh merchant + +[Install] +WantedBy=default.target diff --git a/scripts/taler-shared/ensure-taler-apps.sh b/scripts/taler-shared/ensure-taler-apps.sh new file mode 100644 index 0000000..ed59020 --- /dev/null +++ b/scripts/taler-shared/ensure-taler-apps.sh @@ -0,0 +1,163 @@ +#!/usr/bin/env bash +# Host (hernani@koopa): start Taler *apps inside* merchant/bank containers. +# +# Containers use CMD sleep infinity — podman start alone is not enough. +# Called by user systemd units after container-taler-*.service. +# +# Usage: +# ensure-taler-apps.sh # merchant + bank + helpers +# ensure-taler-apps.sh merchant +# ensure-taler-apps.sh bank +# ensure-taler-apps.sh status +set -euo pipefail + +MER_CTR="${MER_CTR:-taler-hacktivism}" +BANK_CTR="${BANK_CTR:-taler-hacktivism-bank}" +AUTO_LOOP_SECS="${AUTO_CONFIRM_LOOP_SECS:-2}" +WAIT_SECS="${WAIT_SECS:-90}" + +log() { printf '%s %s\n' "$(date -Iseconds)" "$*"; } + +# Oneshot container-*.service stays "active" after podman stop — always start here. +ensure_container() { + local name="$1" + if podman inspect -f '{{.State.Running}}' "$name" 2>/dev/null | grep -qx true; then + return 0 + fi + log "container $name: not running — podman start" + podman start "$name" >/dev/null +} + +wait_running() { + local name="$1" i + ensure_container "$name" + for i in $(seq 1 "$WAIT_SECS"); do + if podman inspect -f '{{.State.Running}}' "$name" 2>/dev/null | grep -qx true; then + return 0 + fi + sleep 1 + done + log "ERROR: container $name not running after ${WAIT_SECS}s" + return 1 +} + +ctr_has_proc() { + local ctr="$1" pattern="$2" + podman exec "$ctr" bash -lc "ps -eo args= | grep -F -- '$pattern' | grep -v grep" >/dev/null 2>&1 +} + +ensure_merchant() { + wait_running "$MER_CTR" + if ctr_has_proc "$MER_CTR" 'taler-merchant-httpd'; then + log "merchant: httpd already up" + return 0 + fi + log "merchant: start base (postgres/nginx)…" + podman exec -u root "$MER_CTR" \ + /root/start_base_services_for_taler.sh --no-shell + log "merchant: start_merchant.sh…" + podman exec -u root "$MER_CTR" \ + runuser -u taler-merchant-httpd -- /usr/local/bin/start_merchant.sh + log "merchant: done" +} + +ensure_bank() { + wait_running "$BANK_CTR" + if ! ctr_has_proc "$BANK_CTR" 'libeufin-bank'; then + log "bank: start base + libeufin-bank…" + podman exec -u root "$BANK_CTR" \ + /root/start_base_services_for_taler_bank.sh --no-shell --start-bank + else + log "bank: libeufin-bank already up" + fi + + # Landing nginx on :9013 (separate from bank API :9012) + if ! podman exec "$BANK_CTR" bash -lc "ss -tln 2>/dev/null | grep -q ':9013 '" 2>/dev/null; then + log "bank: start landing nginx :9013…" + podman exec -u root "$BANK_CTR" bash -lc ' + if [ -x /etc/init.d/nginx ]; then /etc/init.d/nginx start || true + else nginx || true + fi + ' + else + log "bank: nginx :9013 already listening" + fi + + ensure_bank_helpers + log "bank: done" +} + +# Single auto-confirm loop + demo-withdraw API (idempotent) +ensure_bank_helpers() { + local n + # Collapse duplicate loops (common after manual restarts) + n=$(podman exec "$BANK_CTR" bash -lc \ + "ps -eo pid=,args= | awk '/auto-confirm-withdrawals\\.sh --loop/ {print \$1}'" 2>/dev/null || true) + set -- $n + if [ "$#" -gt 1 ]; then + log "bank: stop $(($# - 1)) extra auto-confirm pid(s)…" + shift # keep first + for pid in "$@"; do + podman exec -u root "$BANK_CTR" kill "$pid" 2>/dev/null || true + done + sleep 0.3 + fi + if [ "$#" -eq 0 ]; then + log "bank: start auto-confirm --loop ${AUTO_LOOP_SECS}…" + podman exec -u root -d "$BANK_CTR" \ + /usr/local/bin/auto-confirm-withdrawals.sh --loop "$AUTO_LOOP_SECS" \ + || log "WARN: auto-confirm start failed (script missing?)" + else + log "bank: auto-confirm already running" + fi + + if podman exec "$BANK_CTR" test -f /usr/local/bin/demo-withdraw-api.py 2>/dev/null; then + if ! ctr_has_proc "$BANK_CTR" 'demo-withdraw-api.py'; then + log "bank: start demo-withdraw-api…" + podman exec -u root -d "$BANK_CTR" \ + python3 /usr/local/bin/demo-withdraw-api.py \ + || log "WARN: demo-withdraw-api start failed" + else + log "bank: demo-withdraw-api already running" + fi + fi +} + +status() { + echo "=== containers ===" + podman ps -a --filter name='taler-hacktivism' --format '{{.Names}} {{.Status}}' + echo "=== merchant procs (sample) ===" + podman exec "$MER_CTR" bash -lc "ps -eo args= | grep -E 'taler-merchant-httpd|postgres -D|nginx: master' | grep -v grep || true" 2>/dev/null || echo "(container down)" + echo "=== bank procs (sample) ===" + podman exec "$BANK_CTR" bash -lc "ps -eo args= | grep -E 'libeufin-bank|auto-confirm|demo-withdraw|nginx: master' | grep -v grep || true" 2>/dev/null || echo "(container down)" + echo "=== public ===" + for u in \ + https://taler.hacktivism.ch/config \ + https://taler.hacktivism.ch/intro/ \ + https://bank.hacktivism.ch/config \ + https://bank.hacktivism.ch/intro/ + do + code=$(curl -sk -o /dev/null -w '%{http_code}' --connect-timeout 4 --max-redirs 0 "$u" || echo err) + printf ' %s %s\n' "$code" "$u" + done +} + +cmd="${1:-all}" +case "$cmd" in + all|"") + ensure_merchant + ensure_bank + ;; + merchant) ensure_merchant ;; + bank) ensure_bank ;; + helpers) ensure_bank_helpers ;; + status) status ;; + -h|--help) + sed -n '2,16p' "$0" + exit 0 + ;; + *) + echo "unknown: $cmd (all|merchant|bank|helpers|status)" >&2 + exit 2 + ;; +esac diff --git a/scripts/taler-shared/install-ensure-taler-apps.sh b/scripts/taler-shared/install-ensure-taler-apps.sh new file mode 100644 index 0000000..60f2367 --- /dev/null +++ b/scripts/taler-shared/install-ensure-taler-apps.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# Install ensure-taler-apps + user systemd units on this host (hernani@koopa). +# Run from admin-log checkout or with ADMIN_LOG set. +set -euo pipefail + +ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +ADMIN_LOG="${ADMIN_LOG:-$ROOT}" +UNIT_SRC="$ADMIN_LOG/configs/systemd/user" +BIN_DST="${HOME}/.local/bin" +UNIT_DST="${HOME}/.config/systemd/user" + +mkdir -p "$BIN_DST" "$UNIT_DST" + +install -m 0755 "$ADMIN_LOG/scripts/taler-shared/ensure-taler-apps.sh" \ + "$BIN_DST/ensure-taler-apps.sh" + +install -m 0644 "$UNIT_SRC/taler-merchant-apps.service" "$UNIT_DST/" +install -m 0644 "$UNIT_SRC/taler-bank-apps.service" "$UNIT_DST/" + +mkdir -p \ + "$UNIT_DST/container-taler-hacktivism.service.d" \ + "$UNIT_DST/container-taler-hacktivism-bank.service.d" \ + "$UNIT_DST/container-koopa-paivana.service.d" + +install -m 0644 "$UNIT_SRC/container-taler-hacktivism.service.d/apps.conf" \ + "$UNIT_DST/container-taler-hacktivism.service.d/apps.conf" +install -m 0644 "$UNIT_SRC/container-taler-hacktivism-bank.service.d/apps.conf" \ + "$UNIT_DST/container-taler-hacktivism-bank.service.d/apps.conf" +install -m 0644 "$UNIT_SRC/container-koopa-paivana.service.d/order.conf" \ + "$UNIT_DST/container-koopa-paivana.service.d/order.conf" + +systemctl --user daemon-reload +systemctl --user enable taler-merchant-apps.service taler-bank-apps.service + +echo "Installed:" +echo " $BIN_DST/ensure-taler-apps.sh" +echo " $UNIT_DST/taler-{merchant,bank}-apps.service (enabled)" +echo " drop-ins: container-taler-hacktivism{,-bank}.service.d/apps.conf" +echo " drop-in: container-koopa-paivana.service.d/order.conf" +echo +echo "Start now (if containers already up):" +echo " systemctl --user start taler-merchant-apps.service taler-bank-apps.service" +echo " $BIN_DST/ensure-taler-apps.sh status"