feat(tops): Taler Operations design previews (ng1–ng3)

Static previews on ports 9090–9092: DD 90 branding (Montserrat,
#0042B3, logo), FINMA sticky, no taler-ops-www build. ng1 landing,
ng2 step/amount sliders + tabs, ng3 classic mirror. Podman nginx,
bin/up.sh, Caddy snippet, /CHANGES notes for current site only.
This commit is contained in:
Hernâni Marques 2026-07-10 17:36:51 +02:00
parent 497bc1243d
commit f821dc0eb4
No known key found for this signature in database
16 changed files with 1593 additions and 0 deletions

190
configs/taler-ops-ng/bin/up.sh Executable file
View file

@ -0,0 +1,190 @@
#!/usr/bin/env bash
# Install / refresh Taler Operations design previews on koopa.
# Ports: 9090 (ng1), 9091 (ng2), 9092 (ng3 classic).
#
# Run ON koopa as hernani (rootless podman):
# ~/koopa-tops/bin/up.sh
# ~/koopa-tops/bin/up.sh --refresh-classic # re-mirror taler-ops.ch into ng3
# ~/koopa-tops/bin/up.sh --down
#
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"
COMPOSE=(podman compose -f deploy/compose.yml)
# older podman-compose fallback
if ! podman compose version >/dev/null 2>&1; then
if command -v podman-compose >/dev/null 2>&1; then
COMPOSE=(podman-compose -f deploy/compose.yml)
fi
fi
log() { printf '[tops] %s\n' "$*"; }
ensure_dirs() {
mkdir -p ng1 ng2 ng3
if [ ! -f ng1/index.html ]; then
log "ERROR: ng1/index.html missing — copy configs/taler-ops-ng from koopa-admin-log first"
exit 1
fi
if [ ! -f ng2/index.html ]; then
log "ERROR: ng2/index.html missing"
exit 1
fi
# nginx container user must read bind mounts
chmod -R a+rX ng1 ng2 ng3 2>/dev/null || true
}
# Classic / stable-era site: HTTP mirror of production only.
# Do NOT build taler-ops-www (Jinja/Parcel) — if upstream is old/broken, we skip builds.
# Branch note: git.taler.net/taler-ops-www **stable** = stable website source; master = dev.
mirror_classic() {
log "mirroring classic site → ng3/ (from https://taler-ops.ch/) — no source build"
log "taler-ops-www: branch 'stable' = stable site; we never run make/parcel here"
local tmp
tmp=$(mktemp -d)
# shellcheck disable=SC2064
trap "rm -rf '$tmp'" RETURN
if command -v wget >/dev/null 2>&1; then
wget -q -r -np -nH --cut-dirs=0 -E -p -k \
--directory-prefix="$tmp" \
--domains=taler-ops.ch \
--timeout=20 --tries=2 \
https://taler-ops.ch/en/index.html \
https://taler-ops.ch/de/index.html \
https://taler-ops.ch/fr/index.html \
2>/dev/null || true
# flatten: prefer mirrored en as index if present
if [ -d "$tmp" ]; then
rm -rf ng3/*
# wget often creates host dir
if [ -d "$tmp/taler-ops.ch" ]; then
cp -a "$tmp/taler-ops.ch/." ng3/ 2>/dev/null || true
else
cp -a "$tmp/." ng3/ 2>/dev/null || true
fi
fi
fi
# Fallback / ensure something serves if mirror thin
if [ ! -f ng3/index.html ] && [ ! -f ng3/en/index.html ]; then
log "mirror incomplete — writing ng3 fallback index (points at live + FINMA text)"
cat >ng3/index.html <<'HTML'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Taler Operations · classic (ng3)</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 40rem; margin: 2rem auto; padding: 0 1rem; line-height: 1.5; }
.finma { position: sticky; top: 0; background: #1a0508; color: #ffe8ec; border-bottom: 3px solid #ff4d6a;
padding: 0.6rem 0.75rem; font-size: 0.85rem; font-weight: 600; margin: -2rem -1rem 1.5rem; }
a { color: #04c; }
</style>
</head>
<body>
<aside class="finma" role="note">
<strong>FINMA legal notice:</strong>
Taler Operations AG operates the Taler payment system in Switzerland.
Taler Operations is <strong>not supervised by FINMA</strong>.
Escrowed customer assets are not subject to deposit insurance but held in a segregated bank account.
</aside>
<h1>Classic site (ng3)</h1>
<p>
This preview is meant to serve the <strong>stable / classic</strong> Taler Operations website.
Source: <code>taler-ops-www</code> branch <code>stable</code>; production:
<a href="https://taler-ops.ch/">https://taler-ops.ch/</a>
</p>
<p>Mirror failed on this host — open production for the full classic UI, or re-run
<code>./bin/up.sh --refresh-classic</code> with network + wget.</p>
<p><a href="https://taler-ops.ch/en/">→ Open live classic EN</a></p>
</body>
</html>
HTML
elif [ -f ng3/en/index.html ] && [ ! -f ng3/index.html ]; then
# convenience root redirect
cat >ng3/index.html <<'HTML'
<!DOCTYPE html>
<html lang="en"><head>
<meta charset="utf-8" /><meta http-equiv="refresh" content="0;url=en/index.html" />
<title>Redirect</title></head>
<body><p><a href="en/index.html">English</a></p></body></html>
HTML
fi
# keep /CHANGES even after mirror wipe
if [ -f deploy/CHANGES-ng3.html ]; then
mkdir -p ng3/CHANGES
cp -f deploy/CHANGES-ng3.html ng3/CHANGES/index.html
elif [ -f ng3/CHANGES/index.html ]; then
:
else
mkdir -p ng3/CHANGES
# minimal fallback if repo copy missing
printf '%s\n' '<!DOCTYPE html><html lang="de"><head><meta charset="utf-8"/><title>CHANGES ng3</title></head><body><h1>CHANGES ng3</h1><p>Classic mirror. FINMA disclaimer on main site. Branch stable = stable website. Port 9092.</p><p><a href="/">Home</a></p></body></html>' >ng3/CHANGES/index.html
fi
chmod -R a+rX ng3 2>/dev/null || true
log "ng3 ready ($(du -sh ng3 | awk '{print $1}'))"
}
cmd_up() {
ensure_dirs
if [ ! -f ng3/index.html ] && [ ! -f ng3/en/index.html ]; then
mirror_classic
fi
log "pulling nginx image…"
podman pull docker.io/library/nginx:1.27-alpine
log "starting containers on :9090 :9091 :9092 …"
"${COMPOSE[@]}" up -d --force-recreate
sleep 1
cmd_status
cat <<'EOF'
=== Caddy (on host) ===
Add vhosts from deploy/Caddyfile.snippet then:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy # or however you reload
DNS: tops.ng1/ng2/ng3.hacktivism.ch → this host
Local smoke (no Caddy):
curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:9090/
curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:9091/
curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:9092/
EOF
}
cmd_down() {
log "stopping…"
"${COMPOSE[@]}" down || true
}
cmd_status() {
podman ps --filter name=koopa-tops --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' || true
for p in 9090 9091 9092; do
code=$(curl -sS -m 3 -o /dev/null -w '%{http_code}' "http://127.0.0.1:${p}/" 2>/dev/null || echo fail)
log "port $p → HTTP $code"
done
}
cmd_refresh_classic() {
mirror_classic
"${COMPOSE[@]}" up -d --force-recreate tops-ng3
cmd_status
}
case "${1:-up}" in
up|start) cmd_up ;;
down|stop) cmd_down ;;
status|ps) cmd_status ;;
--refresh-classic|refresh-classic) cmd_refresh_classic ;;
-h|--help)
sed -n '2,12p' "$0" | sed 's/^# \?//'
;;
*)
log "unknown arg: $1 (try up|down|status|--refresh-classic)"
exit 2
;;
esac