#!/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_loopback_helper() { # Optional helper (loopback helper) — loopback :19097 if podman exec "$MER_CTR" bash -lc "ss -tln 2>/dev/null | grep -q ':19097'" 2>/dev/null; then log "merchant: loopback :19097 already listening" return 0 fi if ! podman exec "$MER_CTR" test -f /usr/local/bin/ui-unlock-api.py 2>/dev/null; then log "merchant: WARN helper missing" return 0 fi log "merchant: start loopback helper :19097…" podman exec -u root -d "$MER_CTR" python3 /usr/local/bin/ui-unlock-api.py \ || log "WARN: loopback helper start failed" } ensure_merchant() { wait_running "$MER_CTR" if ctr_has_proc "$MER_CTR" 'taler-merchant-httpd'; then log "merchant: httpd already up" ensure_merchant_loopback_helper 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 ensure_merchant_loopback_helper 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