release 1.5.0: Mattermost monitoring (mattermost.taler.net)

This commit is contained in:
Hernâni Marques 2026-07-18 22:55:32 +02:00
parent 4f092b90cc
commit 9a6929ae92
No known key found for this signature in database
GPG key ID: CB5738652768F7E9
12 changed files with 219 additions and 9 deletions

View file

@ -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`

View file

@ -1 +1 @@
1.4.1
1.5.0

View file

@ -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/<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
```

113
check_mattermost.sh Executable file
View file

@ -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 '<!doctype html|<html'; then
ok "landing" "$BASE/ → HTTP $code HTML"
else
fail "landing" "$BASE/ → HTTP $code (want 200 HTML Mattermost SPA)"
fi
# --- Official Mattermost health API ---
set_group api
code=$(mm_get "$BASE/api/v4/system/ping" "$tmp/ping.json")
if [ "$code" != "200" ]; then
fail "system/ping" "$BASE/api/v4/system/ping → HTTP $code (want 200 JSON)"
else
# Ping returns JSON object (fields vary by MM version)
if python3 - "$tmp/ping.json" <<'PY' 2>/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 '<!doctype html|<html'; then
ok "login" "$BASE/login → HTTP $code HTML"
else
fail "login" "$BASE/login → HTTP $code (want 200 HTML)"
fi
# --- TLS certificate expiry (openssl s_client if available) ---
set_group tls
if command -v openssl >/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

View file

@ -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) |

View file

@ -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"
}

View file

@ -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" "$@"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 domains 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