diff --git a/README.md b/README.md index 1b09a57..cf64d52 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,15 @@ lookups, fail2ban's jail count and the custom `findtime` hardening, all 7 public vhosts by expected HTTP status code (plus a genuine Gitea API check, not just a static-page response), and all 6 Docker containers. +Also prints a **Versions** block (added 2026-07-26, informational only — +doesn't affect the PASS/WARN/FAIL count) listing what's actually running +for every service above plus each Docker container's image tag and, where +the image tag alone doesn't say much (`:latest`/`:apache`/`:lts`/`:alpine`), +the real version queried from inside the running container itself +(Portainer's own `/api/status`, Nextcloud's `occ status`, the actual +`nginx`/`mariadb`/`redis-server` binaries, Gitea's API) — a quick reference +after any upgrade without having to SSH in and check each service by hand. + Runs automatically once per boot via `sanity-check.service` (a oneshot unit, `systemctl enable`d, `After=` all the relevant services plus a 10s settle delay before running) — covers OS upgrades, kernel updates, and diff --git a/scripts/alpha/sanity-check.sh b/scripts/alpha/sanity-check.sh index f367306..d2b2c99 100644 --- a/scripts/alpha/sanity-check.sh +++ b/scripts/alpha/sanity-check.sh @@ -24,6 +24,33 @@ echo "alpha.jayfield.org sanity check - $(date -Is)" . /etc/os-release echo "OS: $PRETTY_NAME, kernel $(uname -r), uptime $(uptime -p)" +# ---------- Versions ---------- +# Informational only, not pass/fail - a quick reference for what's +# actually running without having to SSH in and check each service +# individually after an upgrade. +section "Versions" +echo "apache2: $(apache2 -v 2>/dev/null | head -1)" +echo "bind9: $(named -v 2>/dev/null | cut -d' ' -f1-2)" +echo "postfix: $(postconf mail_version 2>/dev/null)" +echo "dovecot: $(dovecot --version 2>/dev/null)" +echo "rspamd: $(rspamd --version 2>/dev/null | head -1)" +echo "redis-server: $(redis-server --version 2>/dev/null)" +echo "mariadb: $(mysql --version 2>/dev/null)" +echo "fail2ban: $(fail2ban-client --version 2>/dev/null)" +echo "docker: $(docker --version 2>/dev/null)" +echo "docker compose: $(docker compose version 2>/dev/null | head -1)" +echo "certbot: $(certbot --version 2>/dev/null)" +echo "php7.4: $(php7.4 -v 2>/dev/null | head -1)" +echo "php8.0: $(php8.0 -v 2>/dev/null | head -1)" +echo +echo "Docker containers:" +echo " portainer: $(sudo docker inspect portainer -f '{{.Config.Image}}' 2>/dev/null), app $(curl -sk --max-time 3 https://127.0.0.1:9443/api/status 2>/dev/null | python3 -c 'import json,sys; print(json.load(sys.stdin).get("Version","?"))' 2>/dev/null || echo unknown)" +echo " web (nginx): $(sudo docker exec web nginx -v 2>&1)" +echo " nextcloud: $(sudo docker inspect nextcloud -f '{{.Config.Image}}' 2>/dev/null), app $(sudo docker exec -u www-data nextcloud php occ status 2>/dev/null | grep versionstring | awk '{print $3}')" +echo " nextcloud-db: $(sudo docker exec nextcloud-db mariadb --version 2>/dev/null)" +echo " nextcloud-redis: $(sudo docker exec nextcloud-redis redis-server --version 2>/dev/null)" +echo " gitea: $(sudo docker inspect gitea -f '{{.Config.Image}}' 2>/dev/null), API reports $(curl -s --max-time 3 https://git.jayfield.org/api/v1/version 2>/dev/null | python3 -c 'import json,sys; print(json.load(sys.stdin).get("version","?"))' 2>/dev/null || echo unknown)" + # ---------- System package consistency ---------- section "System package consistency" if [ -z "$(sudo dpkg --audit 2>&1)" ]; then