From 9a6929ae924729656ef64eef40c84da14433f187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hern=C3=A2ni=20Marques?= Date: Sat, 18 Jul 2026 22:55:32 +0200 Subject: [PATCH] release 1.5.0: Mattermost monitoring (mattermost.taler.net) --- README.md | 1 + VERSION | 2 +- VERSIONS.md | 11 +- check_mattermost.sh | 113 ++++++++++++++++++ host-agent/README.md | 2 + host-agent/install-host-agent.sh | 8 +- host-agent/run-mattermost-monitoring.sh | 35 ++++++ .../taler-monitoring-mattermost.service | 18 +++ host-agent/taler-monitoring-mattermost.timer | 14 +++ site-gen/caddy-monitoring-handles.snippet | 16 +++ surface-catalog.conf | 2 +- taler-monitoring.sh | 6 +- 12 files changed, 219 insertions(+), 9 deletions(-) create mode 100755 check_mattermost.sh create mode 100755 host-agent/run-mattermost-monitoring.sh create mode 100644 host-agent/taler-monitoring-mattermost.service create mode 100644 host-agent/taler-monitoring-mattermost.timer diff --git a/README.md b/README.md index 71dfb9e..414b9d8 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Checks for **GNU Taler** stacks (bank, exchange, merchant; optional surface inve | **Host-agent + HTML** | Optional: timers run the suite and publish sticky-bar HTML under `…/monitoring/` (and surface/aptdeploy paths) | Outside-only example: `./taler-monitoring.sh -d demo.taler.net urls` +Mattermost chat: `./taler-monitoring.sh mattermost` (default `https://mattermost.taler.net`) Full local GOA example: `./taler-monitoring.sh -d hacktivism.ch urls inside versions` Repo: https://git.hacktivism.ch/hernani/taler-monitoring · tree: `~/src/taler-monitoring` diff --git a/VERSION b/VERSION index 13175fd..3e1ad72 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.4.1 \ No newline at end of file +1.5.0 \ No newline at end of file diff --git a/VERSIONS.md b/VERSIONS.md index 66ee14f..5e2f8b2 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -13,11 +13,12 @@ Tags and `VERSION` use **MAJOR.FEATURE.FIX** (three components): | **FEATURE** | New capabilities (phases, HTML features, i18n packs, …) | | **FIX** | Bugfixes and docs that do not add a feature | -Git tags: `vMAJOR.FEATURE.FIX` (e.g. `v1.4.1`). File `VERSION` omits the `v` prefix. +Git tags: `vMAJOR.FEATURE.FIX` (e.g. `v1.5.0`). File `VERSION` omits the `v` prefix. | Tag | Date (UTC) | Notes | |-----|------------|--------| -| **v1.5.0** | *planned* | **L10n** packs for user-facing strings that need localization: **fr-CH** (FrancPaysan) and **de-CH** (hacktivism / Taler CH German). | +| **v1.6.0** | *planned* | **L10n** packs for user-facing strings that need localization: **fr-CH** (FrancPaysan) and **de-CH** (hacktivism / Taler CH German). | +| **v1.5.0** | 2026-07-18 | **Mattermost monitoring:** phase `mattermost` (`check_mattermost.sh`) for `mattermost.taler.net` (SPA + `/api/v4/system/ping` + TLS); host-agent HTML `/taler-monitoring-mattermost*`; hourly timer. | | **v1.4.1** | 2026-07-18 | **Docs/versioning:** canonical tree `~/src/taler-monitoring`; docs use generic ops/outside-runner wording (no client hostnames); tags always **MAJOR.FEATURE.FIX**. | | **v1.3.4** | 2026-07-18 | Summary i18n, monpages code-21, aptdeploy rsync path. | | **v1.3.3** | 2026-07-18 | GIT notes vs GUI notes; monpages in TESTS. | @@ -32,7 +33,7 @@ Older short tags (`v1`, `v1.0`, `v1.1`, `v1.2`, `v1.3`) are obsolete; use the th ## Sticky bar version (v1.3.0+) -Generated HTML shows the installed release tag (e.g. `v1.4.1`) next to the host line. +Generated HTML shows the installed release tag (e.g. `v1.5.0`) next to the host line. Clicking opens the tag page on Forgejo: `https://git.hacktivism.ch/hernani/taler-monitoring/src/tag/` @@ -64,11 +65,11 @@ sudo ~/koopa-caddy/apply-monitoring-live.sh | Env | `TALER_MON_LANG=en` or `fr` | | Auto | `*lefrancpaysan*` → fr, else en | -Full locale packs (fr-CH / de-CH) are scheduled for **v1.5.0**. +Full locale packs (fr-CH / de-CH) are scheduled for **v1.6.0**. ## Pin a release ```bash git clone https://git.hacktivism.ch/hernani/taler-monitoring.git ~/src/taler-monitoring -cd ~/src/taler-monitoring && git checkout v1.4.1 +cd ~/src/taler-monitoring && git checkout v1.5.0 ``` diff --git a/check_mattermost.sh b/check_mattermost.sh new file mode 100755 index 0000000..650e3b1 --- /dev/null +++ b/check_mattermost.sh @@ -0,0 +1,113 @@ +#!/usr/bin/env bash +# check_mattermost.sh — outside-in checks for Taler Mattermost (chat) +# +# Default host: mattermost.taler.net +# Override: MATTERMOST_PUBLIC=https://mattermost.example.org +# MATTERMOST_HOST=mattermost.example.org +# +# Outside-only (no SSH). Phase name: mattermost +# +set -euo pipefail +ROOT=$(cd "$(dirname "$0")" && pwd) +# shellcheck source=lib.sh +source "$ROOT/lib.sh" + +set_area mattermost +section "mattermost · public chat (outside-in)" + +if [ -n "${MATTERMOST_PUBLIC:-}" ]; then + BASE="${MATTERMOST_PUBLIC%/}" +elif [ -n "${MATTERMOST_HOST:-}" ]; then + BASE="https://${MATTERMOST_HOST}" +else + BASE="https://mattermost.taler.net" +fi +HOST=${BASE#https://} +HOST=${HOST#http://} +HOST=${HOST%%/*} + +info "target" "$BASE" + +tmp=$(mktemp -d) +trap 'rm -rf "$tmp"' EXIT + +# GET with follow redirects (Mattermost SPA often 302 → /) +mm_get() { + local url="$1" out="$2" + curl -skS -L --max-redirs 5 -m "${TIMEOUT:-12}" -o "$out" -w '%{http_code}' "$url" 2>/dev/null || echo 000 +} + +# --- DNS / HTTPS landing --- +set_group landing +code=$(mm_get "$BASE/" "$tmp/root.html") +if [ "$code" = "200" ] && head -c 512 "$tmp/root.html" | grep -qiE '/dev/null +import json, sys +p = sys.argv[1] +with open(p) as f: + d = json.load(f) +if not isinstance(d, dict): + sys.exit(2) +# older builds may include status; newer still return object with backends +sys.exit(0) +PY + then + ok "system/ping" "$BASE/api/v4/system/ping → HTTP 200 JSON" + else + fail "system/ping" "$BASE/api/v4/system/ping → HTTP 200 but not valid JSON object" + fi +fi + +# --- Login SPA (must be served for users) --- +set_group login +code=$(mm_get "$BASE/login" "$tmp/login.html") +if [ "$code" = "200" ] && head -c 512 "$tmp/login.html" | grep -qiE '/dev/null 2>&1; then + end=$(echo | openssl s_client -servername "$HOST" -connect "${HOST}:443" 2>/dev/null \ + | openssl x509 -noout -enddate 2>/dev/null | sed 's/notAfter=//') + if [ -n "$end" ]; then + # days remaining + end_epoch=$(date -d "$end" +%s 2>/dev/null || date -j -f "%b %d %T %Y %Z" "$end" +%s 2>/dev/null || echo 0) + now_epoch=$(date +%s) + if [ "$end_epoch" -gt 0 ]; then + days=$(( (end_epoch - now_epoch) / 86400 )) + if [ "$days" -lt 0 ]; then + fail "tls cert" "$HOST cert expired ($end)" + elif [ "$days" -lt 14 ]; then + warn "tls cert" "$HOST expires in ${days}d ($end)" + elif [ "$days" -lt 30 ]; then + warn "tls cert" "$HOST expires in ${days}d ($end)" + else + ok "tls cert" "$HOST valid · ${days}d left · $end" + fi + else + info "tls cert" "$HOST notAfter=$end" + fi + else + warn "tls cert" "$HOST could not read certificate" + fi +else + info "tls cert" "openssl not available — skip expiry check" +fi + +info "hint" "surface catalog also lists $HOST; this phase is Mattermost-specific (SPA + /api/v4/system/ping)" +exit 0 diff --git a/host-agent/README.md b/host-agent/README.md index 6419f65..7390860 100644 --- a/host-agent/README.md +++ b/host-agent/README.md @@ -125,6 +125,8 @@ Units: | `taler-monitoring-hacktivism.service` | oneshot → `/monitoring*` (urls inside versions) | | `taler-monitoring-surface.timer` | every **1h** | | `taler-monitoring-surface.service` | → `/taler-monitoring-surface*` (taler only) | +| `taler-monitoring-mattermost.timer` | every **1h** | +| `taler-monitoring-mattermost.service` | → `/taler-monitoring-mattermost*` (mattermost.taler.net) | | `taler-monitoring-aptdeploy.timer` | every **4h** | | `taler-monitoring-aptdeploy.service` | → `/taler-monitoring-aptdeploy*` (taler only) | diff --git a/host-agent/install-host-agent.sh b/host-agent/install-host-agent.sh index 5fe9e21..f28c21f 100755 --- a/host-agent/install-host-agent.sh +++ b/host-agent/install-host-agent.sh @@ -62,29 +62,35 @@ install_local() { install -m 644 "$ROOT/taler-monitoring-surface.timer" "$home_unit/" install -m 644 "$ROOT/taler-monitoring-aptdeploy.service" "$home_unit/" install -m 644 "$ROOT/taler-monitoring-aptdeploy.timer" "$home_unit/" + install -m 644 "$ROOT/taler-monitoring-mattermost.service" "$home_unit/" + install -m 644 "$ROOT/taler-monitoring-mattermost.timer" "$home_unit/" systemctl --user daemon-reload systemctl --user enable --now taler-monitoring-hacktivism.path systemctl --user enable --now taler-monitoring-hacktivism.timer systemctl --user enable --now taler-monitoring-surface.timer systemctl --user enable --now taler-monitoring-aptdeploy.timer + systemctl --user enable --now taler-monitoring-mattermost.timer # initial stamp so path exists "$ROOT/touch-software-stamp.sh" systemctl --user start taler-monitoring-hacktivism.service || true systemctl --user start taler-monitoring-surface.service || true systemctl --user start taler-monitoring-aptdeploy.service || true + systemctl --user start taler-monitoring-mattermost.service || true echo "--- status ---" systemctl --user status taler-monitoring-hacktivism.path --no-pager -l | head -15 systemctl --user status taler-monitoring-hacktivism.timer --no-pager -l | head -12 systemctl --user status taler-monitoring-surface.timer --no-pager -l | head -12 systemctl --user status taler-monitoring-aptdeploy.timer --no-pager -l | head -12 + systemctl --user status taler-monitoring-mattermost.timer --no-pager -l | head -12 systemctl --user list-timers --all | grep taler-monitoring || true - echo "OK host-agent (hacktivism 4h + surface 1h + aptdeploy 4h)" + echo "OK host-agent (hacktivism 4h + surface 1h + aptdeploy 4h + mattermost 1h)" echo "suite: $mon" echo "manual: systemctl --user start taler-monitoring-hacktivism.service" echo "manual surface: systemctl --user start taler-monitoring-surface.service" echo "manual aptdeploy: systemctl --user start taler-monitoring-aptdeploy.service" + echo "manual mattermost: systemctl --user start taler-monitoring-mattermost.service" echo "after upgrades: $ROOT/touch-software-stamp.sh" } diff --git a/host-agent/run-mattermost-monitoring.sh b/host-agent/run-mattermost-monitoring.sh new file mode 100755 index 0000000..4986c3c --- /dev/null +++ b/host-agent/run-mattermost-monitoring.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# run-mattermost-monitoring.sh — Mattermost (mattermost.taler.net) → public HTML +# Public only on taler.hacktivism.ch: +# https://taler.hacktivism.ch/taler-monitoring-mattermost/ +# https://taler.hacktivism.ch/taler-monitoring-mattermost_err/ +# +set -uo pipefail +AGENT_DIR=$(cd "$(dirname "$0")" && pwd) + +export AGENT_LABEL="${AGENT_LABEL:-mattermost-host-agent}" +export STATE_NAME="${STATE_NAME:-taler-mattermost-monitoring}" +export TALER_DOMAIN="${TALER_DOMAIN:-hacktivism.ch}" +# remote public service — no SSH / podman +export INSIDE_PODMAN=0 +export LOCAL_STACK=0 +export SKIP_SSH=1 +export INSIDE_MODE="${INSIDE_MODE:-none}" +export CONTINUE_ON_ERROR="${CONTINUE_ON_ERROR:-1}" +export RUN_TIMEOUT="${RUN_TIMEOUT:-300}" +# dedicated job: mattermost + public page check +export PHASES="${PHASES:-mattermost monpages}" +export MON_HOSTS="${MON_HOSTS:-taler.hacktivism.ch}" +export HTML_OUT="${HTML_OUT:-$HOME/monitoring-sites-staging}" +export DEPLOY_WWW_ROOT="${DEPLOY_WWW_ROOT:-/var/www/monitoring-sites}" + +export HTML_OK_DIR="taler-monitoring-mattermost" +export HTML_ERR_DIR="taler-monitoring-mattermost_err" +export HTML_URL_OK="/taler-monitoring-mattermost/" +export HTML_URL_ERR="/taler-monitoring-mattermost_err/" +export PAGE_LABEL="taler-monitoring-mattermost" + +export MATTERMOST_PUBLIC="${MATTERMOST_PUBLIC:-https://mattermost.taler.net}" +export APT_DEPLOY_ENSURE=0 + +exec bash "$AGENT_DIR/run-host-report.sh" "$@" diff --git a/host-agent/taler-monitoring-mattermost.service b/host-agent/taler-monitoring-mattermost.service new file mode 100644 index 0000000..002aa60 --- /dev/null +++ b/host-agent/taler-monitoring-mattermost.service @@ -0,0 +1,18 @@ +[Unit] +Description=Taler monitoring Mattermost (mattermost.taler.net outside-in) +Documentation=file:%h/src/taler-monitoring/host-agent/README.md +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +Environment=PATH=%h/.local/bin:/usr/local/bin:/usr/bin:/bin +Environment=CONTINUE_ON_ERROR=1 +Environment=RUN_TIMEOUT=300 +WorkingDirectory=%h/src/taler-monitoring +ExecStart=%h/src/taler-monitoring/host-agent/run-mattermost-monitoring.sh +Nice=10 +TimeoutStartSec=15min + +[Install] +WantedBy=default.target diff --git a/host-agent/taler-monitoring-mattermost.timer b/host-agent/taler-monitoring-mattermost.timer new file mode 100644 index 0000000..3b077b0 --- /dev/null +++ b/host-agent/taler-monitoring-mattermost.timer @@ -0,0 +1,14 @@ +[Unit] +Description=Periodic taler-monitoring Mattermost (chat health) +Documentation=file:%h/src/taler-monitoring/host-agent/README.md + +[Timer] +OnBootSec=25min +OnUnitActiveSec=1h +AccuracySec=2min +Persistent=true +RandomizedDelaySec=5min +Unit=taler-monitoring-mattermost.service + +[Install] +WantedBy=timers.target diff --git a/site-gen/caddy-monitoring-handles.snippet b/site-gen/caddy-monitoring-handles.snippet index 1c09531..54cca0c 100644 --- a/site-gen/caddy-monitoring-handles.snippet +++ b/site-gen/caddy-monitoring-handles.snippet @@ -9,6 +9,7 @@ # /monitoring* → bank + exchange + taler.hacktivism.ch # /taler-monitoring-surface* → taler.hacktivism.ch only # /taler-monitoring-aptdeploy* → taler.hacktivism.ch only +# /taler-monitoring-mattermost* → taler.hacktivism.ch only # --- only inside taler.hacktivism.ch { ... } --- handle /taler-monitoring-surface_err { @@ -40,6 +41,21 @@ file_server } + handle /taler-monitoring-mattermost_err { + redir /taler-monitoring-mattermost_err/ 302 + } + handle /taler-monitoring-mattermost_err/ { + root * /var/www/monitoring-sites/taler.hacktivism.ch/taler-monitoring-mattermost_err + file_server + } + handle /taler-monitoring-mattermost { + redir /taler-monitoring-mattermost/ 302 + } + handle /taler-monitoring-mattermost/ { + root * /var/www/monitoring-sites/taler.hacktivism.ch/taler-monitoring-mattermost + file_server + } + # --- bank + exchange + taler (each site block) --- handle /monitoring_err { redir /monitoring_err/ 302 diff --git a/surface-catalog.conf b/surface-catalog.conf index 16d5755..ad1bdc3 100644 --- a/surface-catalog.conf +++ b/surface-catalog.conf @@ -16,6 +16,7 @@ git.taler.net 443,22 https taler-git bugs.taler.net 443 https taler-bugs lists.taler.net 443 https taler-lists tutorials.taler.net 443 https taler-tutorials +mattermost.taler.net 443 https mattermost bank.demo.taler.net 443 https demo-bank exchange.demo.taler.net 443 https demo-exchange backend.demo.taler.net 443 https demo-merchant @@ -35,7 +36,6 @@ stage.my.taler-ops.ch 443 https tops-stage-merchant exchange.stage.taler-ops.ch 443 https tops-stage-exchange nexus.stage.taler-ops.ch 443 https tops-stage-nexus shops.taler-ops.ch 443 https tops-shops -mattermost.taler.net 443 https mattermost # --- gnunet.org --- www.gnunet.org 443,80 https gnunet-www diff --git a/taler-monitoring.sh b/taler-monitoring.sh index 3c6e39b..13d03b5 100755 --- a/taler-monitoring.sh +++ b/taler-monitoring.sh @@ -40,6 +40,7 @@ Phases: surface REMOTE-ONLY public inventory (NOT in default/all/full): ecosystem hosts (taler.net, gnunet.org, taler-systems.com, mattermost, …) or -d DOMAIN → that domain’s surface; port/protocol/TLS/CVE (OSV) + mattermost Mattermost chat health (default mattermost.taler.net; SPA + /api/v4/system/ping) monpages public monitoring HTML via FQDN (HTTP 200 + suite page, not code 21) uses MON_HOSTS + HTML_URL_OK (same as host-agent); v1.3.1+ all urls + inside + versions + sanity + e2e (SSH phases only on koopa) @@ -111,6 +112,7 @@ Remote surface / ecosystem (explicit only — never default): ./taler-monitoring.sh surface ./taler-monitoring.sh -d hacktivism.ch surface ./taler-monitoring.sh -d lefrancpaysan.ch surface + ./taler-monitoring.sh mattermost # mattermost.taler.net chat health SPA pin after selfbuild: EXPECT_WEBUI_VERSION=1.6.11 EXPECT_WEBUI_OVERLAY=selfbuild-v1.6.11 \\ @@ -179,7 +181,7 @@ while [ $# -gt 0 ]; do CURRENCY_OVERRIDE="$2"; shift 2 ;; --no-probe) NO_PROBE=1; shift ;; - urls|inside|versions|sanity|server|e2e|ladder|goa-ladder|auth401|aptdeploy|apt-deploy|apt_src|surface|ecosystem|monpages|pages|all|full) PHASES+=("$1"); shift ;; + urls|inside|versions|sanity|server|e2e|ladder|goa-ladder|auth401|aptdeploy|apt-deploy|apt_src|surface|ecosystem|mattermost|monpages|pages|all|full) PHASES+=("$1"); shift ;; *) # bare domain shorthand: ./taler-monitoring.sh taler.net if [[ "$1" == *.* && "$1" != *://* && "$1" != -* ]]; then @@ -344,6 +346,7 @@ if [ "${PROGRESS_TOTAL:-0}" = "0" ] || [ -z "${PROGRESS_TOTAL:-}" ]; then aptdeploy) _pt=$((_pt + 20)) ;; surface|ecosystem) _pt=$((_pt + 80)) ;; monpages|pages) _pt=$((_pt + 30)) ;; + mattermost) _pt=$((_pt + 25)) ;; esac done set_progress_total "$_pt" @@ -461,6 +464,7 @@ for p in "${PHASES[@]}"; do auth401) run_phase auth401 "$ROOT/check_auth401.sh" || ec=1 ;; aptdeploy|apt-deploy|apt_src) run_phase aptdeploy "$ROOT/check_apt_deploy.sh" || ec=1 ;; surface|ecosystem) run_phase surface "$ROOT/check_surface.sh" || ec=1 ;; + mattermost) run_phase mattermost "$ROOT/check_mattermost.sh" || ec=1 ;; monpages|pages) run_phase monpages "$ROOT/check_monitoring_pages.sh" || ec=1 ;; esac done