release 1.6.0: mail monitoring (firefly + pixel/TSA)
This commit is contained in:
parent
9a6929ae92
commit
8d6aabaab6
12 changed files with 415 additions and 8 deletions
|
|
@ -10,6 +10,7 @@ Checks for **GNU Taler** stacks (bank, exchange, merchant; optional surface inve
|
||||||
|
|
||||||
Outside-only example: `./taler-monitoring.sh -d demo.taler.net urls`
|
Outside-only example: `./taler-monitoring.sh -d demo.taler.net urls`
|
||||||
Mattermost chat: `./taler-monitoring.sh mattermost` (default `https://mattermost.taler.net`)
|
Mattermost chat: `./taler-monitoring.sh mattermost` (default `https://mattermost.taler.net`)
|
||||||
|
Mail (firefly/pixel): `./taler-monitoring.sh mail`
|
||||||
Full local GOA example: `./taler-monitoring.sh -d hacktivism.ch urls inside versions`
|
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`
|
Repo: https://git.hacktivism.ch/hernani/taler-monitoring · tree: `~/src/taler-monitoring`
|
||||||
|
|
|
||||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
1.5.0
|
1.6.0
|
||||||
11
VERSIONS.md
11
VERSIONS.md
|
|
@ -13,11 +13,12 @@ Tags and `VERSION` use **MAJOR.FEATURE.FIX** (three components):
|
||||||
| **FEATURE** | New capabilities (phases, HTML features, i18n packs, …) |
|
| **FEATURE** | New capabilities (phases, HTML features, i18n packs, …) |
|
||||||
| **FIX** | Bugfixes and docs that do not add a feature |
|
| **FIX** | Bugfixes and docs that do not add a feature |
|
||||||
|
|
||||||
Git tags: `vMAJOR.FEATURE.FIX` (e.g. `v1.5.0`). File `VERSION` omits the `v` prefix.
|
Git tags: `vMAJOR.FEATURE.FIX` (e.g. `v1.6.0`). File `VERSION` omits the `v` prefix.
|
||||||
|
|
||||||
| Tag | Date (UTC) | Notes |
|
| Tag | Date (UTC) | Notes |
|
||||||
|-----|------------|--------|
|
|-----|------------|--------|
|
||||||
| **v1.6.0** | *planned* | **L10n** packs for user-facing strings that need localization: **fr-CH** (FrancPaysan) and **de-CH** (hacktivism / Taler CH German). |
|
| **v1.7.0** | *planned* | **L10n** packs for user-facing strings that need localization: **fr-CH** (FrancPaysan) and **de-CH** (hacktivism / Taler CH German). |
|
||||||
|
| **v1.6.0** | 2026-07-18 | **Mail monitoring:** phase `mail` (`check_mail.sh` + `mail-catalog.conf`) for **firefly** (taler.net, gnunet.org) and **pixel**/TSA (taler-systems.com, mail.anastasis.lu); MX/SMTP/IMAP/SPF/DMARC; host-agent `/taler-monitoring-mail*`. |
|
||||||
| **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.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.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.4** | 2026-07-18 | Summary i18n, monpages code-21, aptdeploy rsync path. |
|
||||||
|
|
@ -33,7 +34,7 @@ Older short tags (`v1`, `v1.0`, `v1.1`, `v1.2`, `v1.3`) are obsolete; use the th
|
||||||
|
|
||||||
## Sticky bar version (v1.3.0+)
|
## Sticky bar version (v1.3.0+)
|
||||||
|
|
||||||
Generated HTML shows the installed release tag (e.g. `v1.5.0`) next to the host line.
|
Generated HTML shows the installed release tag (e.g. `v1.6.0`) next to the host line.
|
||||||
Clicking opens the tag page on Forgejo:
|
Clicking opens the tag page on Forgejo:
|
||||||
|
|
||||||
`https://git.hacktivism.ch/hernani/taler-monitoring/src/tag/<tag>`
|
`https://git.hacktivism.ch/hernani/taler-monitoring/src/tag/<tag>`
|
||||||
|
|
@ -65,11 +66,11 @@ sudo ~/koopa-caddy/apply-monitoring-live.sh
|
||||||
| Env | `TALER_MON_LANG=en` or `fr` |
|
| Env | `TALER_MON_LANG=en` or `fr` |
|
||||||
| Auto | `*lefrancpaysan*` → fr, else en |
|
| Auto | `*lefrancpaysan*` → fr, else en |
|
||||||
|
|
||||||
Full locale packs (fr-CH / de-CH) are scheduled for **v1.6.0**.
|
Full locale packs (fr-CH / de-CH) are scheduled for **v1.7.0**.
|
||||||
|
|
||||||
## Pin a release
|
## Pin a release
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://git.hacktivism.ch/hernani/taler-monitoring.git ~/src/taler-monitoring
|
git clone https://git.hacktivism.ch/hernani/taler-monitoring.git ~/src/taler-monitoring
|
||||||
cd ~/src/taler-monitoring && git checkout v1.5.0
|
cd ~/src/taler-monitoring && git checkout v1.6.0
|
||||||
```
|
```
|
||||||
|
|
|
||||||
291
check_mail.sh
Executable file
291
check_mail.sh
Executable file
|
|
@ -0,0 +1,291 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# check_mail.sh — outside-in mail (MX / SMTP / IMAP / SPF / DMARC)
|
||||||
|
#
|
||||||
|
# Catalog: mail-catalog.conf (MAIL_CATALOG=… to override)
|
||||||
|
# Covers firefly (taler.net, gnunet.org) and pixel (taler-systems.com, …).
|
||||||
|
#
|
||||||
|
# Outside-only. Phase: mail
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
ROOT=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
# shellcheck source=lib.sh
|
||||||
|
source "$ROOT/lib.sh"
|
||||||
|
|
||||||
|
set_area mail
|
||||||
|
section "mail · MX / SMTP / IMAP / SPF / DMARC (outside-in)"
|
||||||
|
|
||||||
|
CATALOG="${MAIL_CATALOG:-$ROOT/mail-catalog.conf}"
|
||||||
|
PORT_TIMEOUT="${MAIL_PORT_TIMEOUT:-4}"
|
||||||
|
SMTP_TIMEOUT="${MAIL_SMTP_TIMEOUT:-10}"
|
||||||
|
|
||||||
|
if [ ! -f "$CATALOG" ]; then
|
||||||
|
fail "catalog" "missing $CATALOG"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# dig or host fallback
|
||||||
|
dns_mx() {
|
||||||
|
local d="$1"
|
||||||
|
if command -v dig >/dev/null 2>&1; then
|
||||||
|
dig +short +time=3 +tries=2 MX "$d" 2>/dev/null | awk '{print tolower($2)}' | sed 's/\.$//'
|
||||||
|
else
|
||||||
|
host -t MX "$d" 2>/dev/null | awk -F'in mail is |has address ' '/mail is/{print tolower($NF)}' | sed 's/\.$//'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_a() {
|
||||||
|
local h="$1"
|
||||||
|
if command -v dig >/dev/null 2>&1; then
|
||||||
|
dig +short +time=3 +tries=2 A "$h" 2>/dev/null | grep -E '^[0-9.]+$' || true
|
||||||
|
dig +short +time=3 +tries=2 AAAA "$h" 2>/dev/null | grep -E ':' || true
|
||||||
|
else
|
||||||
|
getent ahosts "$h" 2>/dev/null | awk '{print $1}' | sort -u
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_txt() {
|
||||||
|
local name="$1"
|
||||||
|
if command -v dig >/dev/null 2>&1; then
|
||||||
|
dig +short +time=3 +tries=2 TXT "$name" 2>/dev/null | tr -d '"'
|
||||||
|
else
|
||||||
|
host -t TXT "$name" 2>/dev/null | sed 's/.*"\(.*\)"/\1/'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
tcp_open() {
|
||||||
|
local h="$1" p="$2"
|
||||||
|
if command -v timeout >/dev/null 2>&1; then
|
||||||
|
timeout "$PORT_TIMEOUT" bash -c "echo >/dev/tcp/${h}/${p}" 2>/dev/null
|
||||||
|
else
|
||||||
|
bash -c "echo >/dev/tcp/${h}/${p}" 2>/dev/null
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# SMTP: read banner first, then EHLO (avoids "protocol synchronization")
|
||||||
|
smtp_probe() {
|
||||||
|
local host="$1" port="$2"
|
||||||
|
MAIL_HOST="$host" MAIL_PORT="$port" MAIL_TO="${SMTP_TIMEOUT}" python3 - <<'PY' 2>/dev/null
|
||||||
|
import os, socket, sys
|
||||||
|
host = os.environ["MAIL_HOST"]
|
||||||
|
port = int(os.environ["MAIL_PORT"])
|
||||||
|
to = float(os.environ.get("MAIL_TO", "10"))
|
||||||
|
try:
|
||||||
|
s = socket.create_connection((host, port), to)
|
||||||
|
s.settimeout(to)
|
||||||
|
banner = s.recv(1024).decode("utf-8", "replace").strip().split("\n")[0]
|
||||||
|
if not banner.startswith("220"):
|
||||||
|
print(f"bad_banner={banner[:80]}")
|
||||||
|
sys.exit(1)
|
||||||
|
s.sendall(b"EHLO taler-monitoring.invalid\r\n")
|
||||||
|
data = b""
|
||||||
|
while True:
|
||||||
|
chunk = s.recv(4096)
|
||||||
|
if not chunk:
|
||||||
|
break
|
||||||
|
data += chunk
|
||||||
|
if b"\n" in chunk and (data.endswith(b"\r\n") or len(data) > 8000):
|
||||||
|
# multi-line 250-… ends with 250 space
|
||||||
|
lines = data.decode("utf-8", "replace").splitlines()
|
||||||
|
if any(l.startswith("250 ") for l in lines):
|
||||||
|
break
|
||||||
|
if any(l.startswith("5") for l in lines[:3]):
|
||||||
|
break
|
||||||
|
text = data.decode("utf-8", "replace")
|
||||||
|
s.sendall(b"QUIT\r\n")
|
||||||
|
try:
|
||||||
|
s.recv(256)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
s.close()
|
||||||
|
starttls = "starttls" if "STARTTLS" in text.upper() else "no_starttls"
|
||||||
|
print(f"banner={banner[:60]} · {starttls}")
|
||||||
|
sys.exit(0)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"err={e}")
|
||||||
|
sys.exit(1)
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
# IMAP unencrypted greeting on 143, or just TCP on 993 (TLS)
|
||||||
|
imap_probe() {
|
||||||
|
local host="$1" port="$2"
|
||||||
|
if [ "$port" = "993" ] || [ "$port" = "995" ]; then
|
||||||
|
if tcp_open "$host" "$port"; then
|
||||||
|
echo "tcp_open tls_port=$port"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
MAIL_HOST="$host" MAIL_PORT="$port" MAIL_TO="${SMTP_TIMEOUT}" python3 - <<'PY' 2>/dev/null
|
||||||
|
import os, socket, sys
|
||||||
|
host = os.environ["MAIL_HOST"]
|
||||||
|
port = int(os.environ["MAIL_PORT"])
|
||||||
|
to = float(os.environ.get("MAIL_TO", "10"))
|
||||||
|
try:
|
||||||
|
s = socket.create_connection((host, port), to)
|
||||||
|
s.settimeout(to)
|
||||||
|
banner = s.recv(1024).decode("utf-8", "replace").strip().split("\n")[0]
|
||||||
|
s.sendall(b"a001 LOGOUT\r\n")
|
||||||
|
try:
|
||||||
|
s.recv(256)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
s.close()
|
||||||
|
if banner.upper().startswith("* OK") or "IMAP" in banner.upper():
|
||||||
|
print(f"banner={banner[:70]}")
|
||||||
|
sys.exit(0)
|
||||||
|
print(f"unexpected={banner[:70]}")
|
||||||
|
sys.exit(1)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"err={e}")
|
||||||
|
sys.exit(1)
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
info "catalog" "$CATALOG"
|
||||||
|
|
||||||
|
# Track probed hosts to avoid duplicate SMTP checks
|
||||||
|
declare -A HOST_DONE=()
|
||||||
|
|
||||||
|
while IFS= read -r line || [ -n "$line" ]; do
|
||||||
|
line=${line%%#*}
|
||||||
|
line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||||
|
[ -z "$line" ] && continue
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
set -- $line
|
||||||
|
domain=$1
|
||||||
|
expect_mx=${2:-}
|
||||||
|
mail_hosts=${3:-}
|
||||||
|
smtp_ports=${4:-25,465,587}
|
||||||
|
imap_ports=${5:-143,993}
|
||||||
|
label=${6:-$domain}
|
||||||
|
|
||||||
|
set_group "$label"
|
||||||
|
info "domain" "$domain · expected_mx=$expect_mx · hosts=$mail_hosts"
|
||||||
|
|
||||||
|
# --- MX ---
|
||||||
|
mapfile -t mx_hosts < <(dns_mx "$domain" | sed '/^$/d')
|
||||||
|
if [ "${#mx_hosts[@]}" -eq 0 ]; then
|
||||||
|
fail "mx" "$domain has no MX records"
|
||||||
|
else
|
||||||
|
ok "mx" "$domain MX → ${mx_hosts[*]}"
|
||||||
|
# expected MX match (suffix / exact)
|
||||||
|
if [ -n "$expect_mx" ]; then
|
||||||
|
matched=0
|
||||||
|
IFS=',' read -ra want_list <<<"$expect_mx"
|
||||||
|
for w in "${want_list[@]}"; do
|
||||||
|
w=$(echo "$w" | tr '[:upper:]' '[:lower:]' | sed 's/\.$//')
|
||||||
|
for m in "${mx_hosts[@]}"; do
|
||||||
|
m=$(echo "$m" | tr '[:upper:]' '[:lower:]')
|
||||||
|
case "$m" in
|
||||||
|
"$w"|"$w".*|*."$w") matched=1; break ;;
|
||||||
|
esac
|
||||||
|
[ "$m" = "$w" ] && matched=1
|
||||||
|
done
|
||||||
|
[ "$matched" = "1" ] && break
|
||||||
|
done
|
||||||
|
if [ "$matched" = "1" ]; then
|
||||||
|
ok "mx expected" "$domain MX matches catalog ($expect_mx)"
|
||||||
|
else
|
||||||
|
fail "mx expected" "$domain MX ${mx_hosts[*]} · want one of: $expect_mx"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- SPF / DMARC ---
|
||||||
|
spf=$(dns_txt "$domain" | tr '\n' ' ')
|
||||||
|
if echo "$spf" | grep -qi 'v=spf1'; then
|
||||||
|
ok "spf" "$domain has SPF"
|
||||||
|
else
|
||||||
|
warn "spf" "$domain no SPF TXT (v=spf1)"
|
||||||
|
fi
|
||||||
|
dmarc=$(dns_txt "_dmarc.$domain" | tr '\n' ' ')
|
||||||
|
if echo "$dmarc" | grep -qi 'v=dmarc1'; then
|
||||||
|
ok "dmarc" "$domain has DMARC"
|
||||||
|
else
|
||||||
|
warn "dmarc" "$domain no DMARC at _dmarc.$domain"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- mail hosts: DNS + ports + banners ---
|
||||||
|
IFS=',' read -ra hosts <<<"$mail_hosts"
|
||||||
|
for h in "${hosts[@]}"; do
|
||||||
|
h=$(echo "$h" | tr '[:upper:]' '[:lower:]' | sed 's/\.$//;s/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||||
|
[ -z "$h" ] && continue
|
||||||
|
|
||||||
|
addrs=$(dns_a "$h" | tr '\n' ' ')
|
||||||
|
if [ -z "${addrs// }" ]; then
|
||||||
|
fail "dns" "$h does not resolve (A/AAAA)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
ok "dns" "$h → $addrs"
|
||||||
|
|
||||||
|
# skip full protocol re-probe if already done
|
||||||
|
if [ "${HOST_DONE[$h]:-}" = "1" ]; then
|
||||||
|
info "host" "$h already probed this run"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
HOST_DONE[$h]=1
|
||||||
|
|
||||||
|
IFS=',' read -ra sports <<<"$smtp_ports"
|
||||||
|
for p in "${sports[@]}"; do
|
||||||
|
p=${p// /}
|
||||||
|
[ -z "$p" ] && continue
|
||||||
|
if ! tcp_open "$h" "$p"; then
|
||||||
|
# 587 optional on pixel
|
||||||
|
case "$p" in
|
||||||
|
587) warn "smtp port" "$h:$p closed/filtered (submission)" ;;
|
||||||
|
*) fail "smtp port" "$h:$p closed/filtered" ;;
|
||||||
|
esac
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
case "$p" in
|
||||||
|
465)
|
||||||
|
ok "smtp port" "$h:$p open (SMTPS)"
|
||||||
|
;;
|
||||||
|
25|587)
|
||||||
|
if detail=$(smtp_probe "$h" "$p"); then
|
||||||
|
ok "smtp" "$h:$p $detail"
|
||||||
|
else
|
||||||
|
# port open but banner failed — still ERROR for 25
|
||||||
|
if [ "$p" = "25" ]; then
|
||||||
|
fail "smtp" "$h:$p open but SMTP handshake failed · $detail"
|
||||||
|
else
|
||||||
|
warn "smtp" "$h:$p open but handshake failed · $detail"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ok "smtp port" "$h:$p open"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
IFS=',' read -ra iports <<<"$imap_ports"
|
||||||
|
for p in "${iports[@]}"; do
|
||||||
|
p=${p// /}
|
||||||
|
[ -z "$p" ] && continue
|
||||||
|
if ! tcp_open "$h" "$p"; then
|
||||||
|
fail "imap port" "$h:$p closed/filtered"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
case "$p" in
|
||||||
|
993|995)
|
||||||
|
ok "imap port" "$h:$p open (TLS)"
|
||||||
|
;;
|
||||||
|
143|110)
|
||||||
|
if detail=$(imap_probe "$h" "$p"); then
|
||||||
|
ok "imap" "$h:$p $detail"
|
||||||
|
else
|
||||||
|
warn "imap" "$h:$p open but greeting failed · $detail"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ok "imap port" "$h:$p open"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
done
|
||||||
|
done <"$CATALOG"
|
||||||
|
|
||||||
|
info "hint" "firefly = taler.net/gnunet.org MX; pixel = taler-systems.com (mail.anastasis.lu / mail.taler-systems.com)"
|
||||||
|
exit 0
|
||||||
|
|
@ -127,6 +127,8 @@ Units:
|
||||||
| `taler-monitoring-surface.service` | → `/taler-monitoring-surface*` (taler only) |
|
| `taler-monitoring-surface.service` | → `/taler-monitoring-surface*` (taler only) |
|
||||||
| `taler-monitoring-mattermost.timer` | every **1h** |
|
| `taler-monitoring-mattermost.timer` | every **1h** |
|
||||||
| `taler-monitoring-mattermost.service` | → `/taler-monitoring-mattermost*` (mattermost.taler.net) |
|
| `taler-monitoring-mattermost.service` | → `/taler-monitoring-mattermost*` (mattermost.taler.net) |
|
||||||
|
| `taler-monitoring-mail.timer` | every **4h** |
|
||||||
|
| `taler-monitoring-mail.service` | → `/taler-monitoring-mail*` (firefly + pixel MX/SMTP/IMAP) |
|
||||||
| `taler-monitoring-aptdeploy.timer` | every **4h** |
|
| `taler-monitoring-aptdeploy.timer` | every **4h** |
|
||||||
| `taler-monitoring-aptdeploy.service` | → `/taler-monitoring-aptdeploy*` (taler only) |
|
| `taler-monitoring-aptdeploy.service` | → `/taler-monitoring-aptdeploy*` (taler only) |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,8 @@ install_local() {
|
||||||
install -m 644 "$ROOT/taler-monitoring-aptdeploy.timer" "$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.service" "$home_unit/"
|
||||||
install -m 644 "$ROOT/taler-monitoring-mattermost.timer" "$home_unit/"
|
install -m 644 "$ROOT/taler-monitoring-mattermost.timer" "$home_unit/"
|
||||||
|
install -m 644 "$ROOT/taler-monitoring-mail.service" "$home_unit/"
|
||||||
|
install -m 644 "$ROOT/taler-monitoring-mail.timer" "$home_unit/"
|
||||||
|
|
||||||
systemctl --user daemon-reload
|
systemctl --user daemon-reload
|
||||||
systemctl --user enable --now taler-monitoring-hacktivism.path
|
systemctl --user enable --now taler-monitoring-hacktivism.path
|
||||||
|
|
@ -71,12 +73,14 @@ install_local() {
|
||||||
systemctl --user enable --now taler-monitoring-surface.timer
|
systemctl --user enable --now taler-monitoring-surface.timer
|
||||||
systemctl --user enable --now taler-monitoring-aptdeploy.timer
|
systemctl --user enable --now taler-monitoring-aptdeploy.timer
|
||||||
systemctl --user enable --now taler-monitoring-mattermost.timer
|
systemctl --user enable --now taler-monitoring-mattermost.timer
|
||||||
|
systemctl --user enable --now taler-monitoring-mail.timer
|
||||||
# initial stamp so path exists
|
# initial stamp so path exists
|
||||||
"$ROOT/touch-software-stamp.sh"
|
"$ROOT/touch-software-stamp.sh"
|
||||||
systemctl --user start taler-monitoring-hacktivism.service || true
|
systemctl --user start taler-monitoring-hacktivism.service || true
|
||||||
systemctl --user start taler-monitoring-surface.service || true
|
systemctl --user start taler-monitoring-surface.service || true
|
||||||
systemctl --user start taler-monitoring-aptdeploy.service || true
|
systemctl --user start taler-monitoring-aptdeploy.service || true
|
||||||
systemctl --user start taler-monitoring-mattermost.service || true
|
systemctl --user start taler-monitoring-mattermost.service || true
|
||||||
|
systemctl --user start taler-monitoring-mail.service || true
|
||||||
|
|
||||||
echo "--- status ---"
|
echo "--- status ---"
|
||||||
systemctl --user status taler-monitoring-hacktivism.path --no-pager -l | head -15
|
systemctl --user status taler-monitoring-hacktivism.path --no-pager -l | head -15
|
||||||
|
|
@ -84,13 +88,15 @@ install_local() {
|
||||||
systemctl --user status taler-monitoring-surface.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-aptdeploy.timer --no-pager -l | head -12
|
||||||
systemctl --user status taler-monitoring-mattermost.timer --no-pager -l | head -12
|
systemctl --user status taler-monitoring-mattermost.timer --no-pager -l | head -12
|
||||||
|
systemctl --user status taler-monitoring-mail.timer --no-pager -l | head -12
|
||||||
systemctl --user list-timers --all | grep taler-monitoring || true
|
systemctl --user list-timers --all | grep taler-monitoring || true
|
||||||
echo "OK host-agent (hacktivism 4h + surface 1h + aptdeploy 4h + mattermost 1h)"
|
echo "OK host-agent (hacktivism 4h + surface 1h + aptdeploy 4h + mattermost 1h + mail 4h)"
|
||||||
echo "suite: $mon"
|
echo "suite: $mon"
|
||||||
echo "manual: systemctl --user start taler-monitoring-hacktivism.service"
|
echo "manual: systemctl --user start taler-monitoring-hacktivism.service"
|
||||||
echo "manual surface: systemctl --user start taler-monitoring-surface.service"
|
echo "manual surface: systemctl --user start taler-monitoring-surface.service"
|
||||||
echo "manual aptdeploy: systemctl --user start taler-monitoring-aptdeploy.service"
|
echo "manual aptdeploy: systemctl --user start taler-monitoring-aptdeploy.service"
|
||||||
echo "manual mattermost: systemctl --user start taler-monitoring-mattermost.service"
|
echo "manual mattermost: systemctl --user start taler-monitoring-mattermost.service"
|
||||||
|
echo "manual mail: systemctl --user start taler-monitoring-mail.service"
|
||||||
echo "after upgrades: $ROOT/touch-software-stamp.sh"
|
echo "after upgrades: $ROOT/touch-software-stamp.sh"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
32
host-agent/run-mail-monitoring.sh
Executable file
32
host-agent/run-mail-monitoring.sh
Executable file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# run-mail-monitoring.sh — mail MX/SMTP/IMAP (firefly + pixel, …) → public HTML
|
||||||
|
# Public only on taler.hacktivism.ch:
|
||||||
|
# https://taler.hacktivism.ch/taler-monitoring-mail/
|
||||||
|
# https://taler.hacktivism.ch/taler-monitoring-mail_err/
|
||||||
|
#
|
||||||
|
set -uo pipefail
|
||||||
|
AGENT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
|
||||||
|
export AGENT_LABEL="${AGENT_LABEL:-mail-host-agent}"
|
||||||
|
export STATE_NAME="${STATE_NAME:-taler-mail-monitoring}"
|
||||||
|
export TALER_DOMAIN="${TALER_DOMAIN:-hacktivism.ch}"
|
||||||
|
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:-600}"
|
||||||
|
export PHASES="${PHASES:-mail 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-mail"
|
||||||
|
export HTML_ERR_DIR="taler-monitoring-mail_err"
|
||||||
|
export HTML_URL_OK="/taler-monitoring-mail/"
|
||||||
|
export HTML_URL_ERR="/taler-monitoring-mail_err/"
|
||||||
|
export PAGE_LABEL="taler-monitoring-mail"
|
||||||
|
|
||||||
|
export APT_DEPLOY_ENSURE=0
|
||||||
|
|
||||||
|
exec bash "$AGENT_DIR/run-host-report.sh" "$@"
|
||||||
18
host-agent/taler-monitoring-mail.service
Normal file
18
host-agent/taler-monitoring-mail.service
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Taler monitoring mail (firefly/pixel MX SMTP IMAP)
|
||||||
|
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=600
|
||||||
|
WorkingDirectory=%h/src/taler-monitoring
|
||||||
|
ExecStart=%h/src/taler-monitoring/host-agent/run-mail-monitoring.sh
|
||||||
|
Nice=10
|
||||||
|
TimeoutStartSec=20min
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
14
host-agent/taler-monitoring-mail.timer
Normal file
14
host-agent/taler-monitoring-mail.timer
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Periodic taler-monitoring mail (MX/SMTP/IMAP)
|
||||||
|
Documentation=file:%h/src/taler-monitoring/host-agent/README.md
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnBootSec=30min
|
||||||
|
OnUnitActiveSec=4h
|
||||||
|
AccuracySec=5min
|
||||||
|
Persistent=true
|
||||||
|
RandomizedDelaySec=10min
|
||||||
|
Unit=taler-monitoring-mail.service
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
22
mail-catalog.conf
Normal file
22
mail-catalog.conf
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
# mail-catalog.conf — domains and mail hosts for phase `mail`
|
||||||
|
#
|
||||||
|
# Format (whitespace-separated; # comments):
|
||||||
|
# domain expected_mx (comma) mail_hosts (comma) smtp_ports imap_ports label
|
||||||
|
#
|
||||||
|
# - expected_mx: MX exchange hostnames that should appear (any match = OK if multiple)
|
||||||
|
# - mail_hosts: servers to probe for SMTP/IMAP (A/AAAA + ports + optional banner)
|
||||||
|
# - ports: comma-separated; empty = skip that protocol family
|
||||||
|
#
|
||||||
|
# Override path: MAIL_CATALOG=/path/to/file
|
||||||
|
#
|
||||||
|
# GNU Taler / GNUnet mail (firefly) + TSA (pixel / mail.anastasis.lu)
|
||||||
|
|
||||||
|
# --- firefly (primary for taler.net + gnunet.org) ---
|
||||||
|
taler.net firefly.gnunet.org firefly.gnunet.org 25,465,587 143,993 taler-net
|
||||||
|
gnunet.org firefly.gnunet.org firefly.gnunet.org 25,465,587 143,993 gnunet
|
||||||
|
|
||||||
|
# --- taler-systems.com / pixel (MX mail.anastasis.lu → pixel) ---
|
||||||
|
taler-systems.com mail.anastasis.lu,pixel.taler-systems.com pixel.taler-systems.com,mail.taler-systems.com,mail.anastasis.lu 25,465 143,993 tsa-pixel
|
||||||
|
|
||||||
|
# Optional related (same pixel path; keep expected MX loose)
|
||||||
|
# anastasis.lu mail.anastasis.lu mail.anastasis.lu,pixel.taler-systems.com 25,465 143,993 anastasis
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
# /taler-monitoring-surface* → taler.hacktivism.ch only
|
# /taler-monitoring-surface* → taler.hacktivism.ch only
|
||||||
# /taler-monitoring-aptdeploy* → taler.hacktivism.ch only
|
# /taler-monitoring-aptdeploy* → taler.hacktivism.ch only
|
||||||
# /taler-monitoring-mattermost* → taler.hacktivism.ch only
|
# /taler-monitoring-mattermost* → taler.hacktivism.ch only
|
||||||
|
# /taler-monitoring-mail* → taler.hacktivism.ch only
|
||||||
|
|
||||||
# --- only inside taler.hacktivism.ch { ... } ---
|
# --- only inside taler.hacktivism.ch { ... } ---
|
||||||
handle /taler-monitoring-surface_err {
|
handle /taler-monitoring-surface_err {
|
||||||
|
|
@ -56,6 +57,21 @@
|
||||||
file_server
|
file_server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handle /taler-monitoring-mail_err {
|
||||||
|
redir /taler-monitoring-mail_err/ 302
|
||||||
|
}
|
||||||
|
handle /taler-monitoring-mail_err/ {
|
||||||
|
root * /var/www/monitoring-sites/taler.hacktivism.ch/taler-monitoring-mail_err
|
||||||
|
file_server
|
||||||
|
}
|
||||||
|
handle /taler-monitoring-mail {
|
||||||
|
redir /taler-monitoring-mail/ 302
|
||||||
|
}
|
||||||
|
handle /taler-monitoring-mail/ {
|
||||||
|
root * /var/www/monitoring-sites/taler.hacktivism.ch/taler-monitoring-mail
|
||||||
|
file_server
|
||||||
|
}
|
||||||
|
|
||||||
# --- bank + exchange + taler (each site block) ---
|
# --- bank + exchange + taler (each site block) ---
|
||||||
handle /monitoring_err {
|
handle /monitoring_err {
|
||||||
redir /monitoring_err/ 302
|
redir /monitoring_err/ 302
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ Phases:
|
||||||
ecosystem hosts (taler.net, gnunet.org, taler-systems.com, mattermost, …)
|
ecosystem hosts (taler.net, gnunet.org, taler-systems.com, mattermost, …)
|
||||||
or -d DOMAIN → that domain’s surface; port/protocol/TLS/CVE (OSV)
|
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)
|
mattermost Mattermost chat health (default mattermost.taler.net; SPA + /api/v4/system/ping)
|
||||||
|
mail MX/SMTP/IMAP for Taler mail (firefly, pixel/TSA, catalogued domains)
|
||||||
monpages public monitoring HTML via FQDN (HTTP 200 + suite page, not code 21)
|
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+
|
uses MON_HOSTS + HTML_URL_OK (same as host-agent); v1.3.1+
|
||||||
all urls + inside + versions + sanity + e2e (SSH phases only on koopa)
|
all urls + inside + versions + sanity + e2e (SSH phases only on koopa)
|
||||||
|
|
@ -113,6 +114,7 @@ Remote surface / ecosystem (explicit only — never default):
|
||||||
./taler-monitoring.sh -d hacktivism.ch surface
|
./taler-monitoring.sh -d hacktivism.ch surface
|
||||||
./taler-monitoring.sh -d lefrancpaysan.ch surface
|
./taler-monitoring.sh -d lefrancpaysan.ch surface
|
||||||
./taler-monitoring.sh mattermost # mattermost.taler.net chat health
|
./taler-monitoring.sh mattermost # mattermost.taler.net chat health
|
||||||
|
./taler-monitoring.sh mail # firefly + pixel MX/SMTP/IMAP
|
||||||
|
|
||||||
SPA pin after selfbuild:
|
SPA pin after selfbuild:
|
||||||
EXPECT_WEBUI_VERSION=1.6.11 EXPECT_WEBUI_OVERLAY=selfbuild-v1.6.11 \\
|
EXPECT_WEBUI_VERSION=1.6.11 EXPECT_WEBUI_OVERLAY=selfbuild-v1.6.11 \\
|
||||||
|
|
@ -181,7 +183,7 @@ while [ $# -gt 0 ]; do
|
||||||
CURRENCY_OVERRIDE="$2"; shift 2
|
CURRENCY_OVERRIDE="$2"; shift 2
|
||||||
;;
|
;;
|
||||||
--no-probe) NO_PROBE=1; shift ;;
|
--no-probe) NO_PROBE=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 ;;
|
urls|inside|versions|sanity|server|e2e|ladder|goa-ladder|auth401|aptdeploy|apt-deploy|apt_src|surface|ecosystem|mattermost|mail|monpages|pages|all|full) PHASES+=("$1"); shift ;;
|
||||||
*)
|
*)
|
||||||
# bare domain shorthand: ./taler-monitoring.sh taler.net
|
# bare domain shorthand: ./taler-monitoring.sh taler.net
|
||||||
if [[ "$1" == *.* && "$1" != *://* && "$1" != -* ]]; then
|
if [[ "$1" == *.* && "$1" != *://* && "$1" != -* ]]; then
|
||||||
|
|
@ -347,6 +349,7 @@ if [ "${PROGRESS_TOTAL:-0}" = "0" ] || [ -z "${PROGRESS_TOTAL:-}" ]; then
|
||||||
surface|ecosystem) _pt=$((_pt + 80)) ;;
|
surface|ecosystem) _pt=$((_pt + 80)) ;;
|
||||||
monpages|pages) _pt=$((_pt + 30)) ;;
|
monpages|pages) _pt=$((_pt + 30)) ;;
|
||||||
mattermost) _pt=$((_pt + 25)) ;;
|
mattermost) _pt=$((_pt + 25)) ;;
|
||||||
|
mail) _pt=$((_pt + 40)) ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
set_progress_total "$_pt"
|
set_progress_total "$_pt"
|
||||||
|
|
@ -465,6 +468,7 @@ for p in "${PHASES[@]}"; do
|
||||||
aptdeploy|apt-deploy|apt_src) run_phase aptdeploy "$ROOT/check_apt_deploy.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 ;;
|
surface|ecosystem) run_phase surface "$ROOT/check_surface.sh" || ec=1 ;;
|
||||||
mattermost) run_phase mattermost "$ROOT/check_mattermost.sh" || ec=1 ;;
|
mattermost) run_phase mattermost "$ROOT/check_mattermost.sh" || ec=1 ;;
|
||||||
|
mail) run_phase mail "$ROOT/check_mail.sh" || ec=1 ;;
|
||||||
monpages|pages) run_phase monpages "$ROOT/check_monitoring_pages.sh" || ec=1 ;;
|
monpages|pages) run_phase monpages "$ROOT/check_monitoring_pages.sh" || ec=1 ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue