Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
NcStatusCheck — Monitoring centralisé pour instances Nextcloud multiples | Kitploit
Outils/GitLabGitLab/jp.louvel/ncstatuscheck
Analyse des VulnérabilitésAudit de ConfigurationSécurité Cloud
GitLabjp.louvel/ncstatuscheck

NcStatusCheck

Monitoring centralisé pour instances Nextcloud multiples

Voir le dépôt
21il y a 17 joursPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

NcStatusCheck

Surveillance centralisée pour plusieurs instances Nextcloud

NcStatusCheck est un outil de surveillance qui vous permet de suivre l'état de santé de plusieurs serveurs Nextcloud depuis une interface web unique. Il analyse les versions de Nextcloud et de PHP et fournit des recommandations de mise à jour.

NcStatusCheck Interface NcStatusCheck Interface - 2

🎯 Fonctionnalités

Surveillance

  • Surveillance automatisée de plusieurs instances Nextcloud
  • Trois modes de collecte de données par serveur : Basic (version NC uniquement), Extended (données complètes via l'API serverinfo) et Push (données envoyées par l'instance distante)
  • Analyse des versions de Nextcloud et PHP
  • Détection du serveur web (nginx, Apache) et protocoles HTTP
  • Suivi up/down (mini uptime) : accessibilité actuelle + dernier changement d'état, affiché sous forme de badge rouge « hors ligne » uniquement lorsque le serveur est down. Un journal de transition limité alimente également un pourcentage de disponibilité sur 30 jours et une liste des incidents récents sur la page de détail
  • Alerte d'expiration du certificat SSL : lue à partir de la sonde HTTPS existante (pas de requête supplémentaire), badge lorsque le certificat expire bientôt (< 15d / < 7d)
  • Audit des applications installées : croise occ app:list avec l'App Store Nextcloud pour signaler les applications à vérifier — bloquant (bloquant la mise à jour, incompatible, applications de test en production) plus signaux informatifs de maturité/turbulence (récemment publié, pré-1.0, version alpha/bêta/rc, rafale de versions, version fraîchement publiée)
  • Blocs de surveillance à l'échelle de la flotte : un bloc « Applications à surveiller » (📦) et un bloc jumeau « Conteneurs à surveiller » (🐳) agrègent chaque application/Docker image signalée sur toutes les instances en une seule entrée, avec des filtres de type par groupe et une popup listant les instances impactées et leurs versions
  • Alertes proactives (webhook et/ou email) : se déclenche lors d'un changement d'état up/down confirmé (hors ligne, maintenance, rétabli) afin d'être notifié sans avoir le tableau de bord ouvert — Slack / Mattermost / Google Chat / Discord / JSON brut (ALERT_WEBHOOK_URL), et/ou un email récapitulatif par lot (ALERT_EMAIL_TO) envoyé par soumission SMTP directe à votre serveur de messagerie (PHPMailer intégré ; bascule vers le MTA local si aucun relais SMTP n'est configuré). Couvre également les signaux lents (ALERT_CHECKS) : expiration du certificat SSL (par paliers), version Nextcloud vulnérable/dépréciée, sonde Push obsolète, rapport d'audit critique, application bloquante — une alerte par nouvelle condition, pas de spam de rappel
  • Délai de grâce pour les mises à jour : une instance n'est marquée comme obsolète que quelques jours après la sortie d'un correctif (nc_update_grace_days), pour éviter de courir après une version buggée du jour
  • Colonne de santé selon le principe « silence = tout va bien » : n'affiche les badges (⚠️ avertissements, 📦 applications, 🔄 Docker, 🔒 SSL, 🔴 hors ligne, 🚧 maintenance) que lorsqu'il y a quelque chose à signaler
  • Système de cache pour les données serveur et les versions officielles

Page de détail

  • Vue complète de la configuration de chaque serveur Nextcloud (PHP, OPcache, Redis, base de données…) pour les serveurs Extended/Push
  • Page de détail basique pour les serveurs sans sonde : affiche la version, le serveur web, le protocole HTTP et un indice de mise à niveau
  • Pourcentage de disponibilité sur 30 jours et liste des incidents récents (début, fin, durée, raison), calculés à partir du journal de transition up/down limité — étiquette honnête « mesuré sur N jours » tant que le journal est plus jeune que la fenêtre
  • Règles d'avertissement de configuration avec indicateurs ⚠️, chacun pouvant être accusé réception (raison + expiration facultative)
  • Section de rapport d'audit serveur lorsque l'instance pousse son rapport mensuel nc-audit.sh
  • Accessible en cliquant sur le nom d'un serveur ou sur un indicateur de santé

Interface

  • Tableau de bord centralisé avec aperçu de l'état (les cartes de résumé n'affichent les compteurs hors ligne / certificat expirant / applications à vérifier que lorsqu'ils sont non nuls)
  • Filtres avancés par état Nextcloud, état PHP, état global, image Docker en cours d'exécution et recherche textuelle
  • Versions officielles récupérées automatiquement depuis les sources Nextcloud
  • Calendrier des versions avec les dates des versions à venir
  • Interface FR / EN / DE (sélecteur de langue dans le coin supérieur droit)

Administration

  • Interface d'administration pour configurer les règles de version
  • Tableau récapitulatif des modes de sonde en haut : explique les trois méthodes de collecte (Basic, Extended, Push) en un coup d'œil
  • Gestion des serveurs via l'interface web avec mise en page en cartes : deux zones de sonde distinctes (serverinfo / push), jetons masqués avec révélation, suppression en ligne
  • Bouton « Configurer les sondes » par serveur pour basculer les zones de jetons, état sauvegardé dans localStorage
  • Recherche de serveur en temps réel avec correspondance insensible aux accents
  • Générateur de script Push : génère un script cron bash prêt à l'emploi (chmod 700) pour l'instance Nextcloud distante, mis à jour automatiquement en fonction des options
  • Bouton « Déclencher Push » sur le tableau de bord : envoie une requête push à tous les serveurs push configurés (visible uniquement lorsqu'au moins un serveur push existe, temps de recharge de 5 minutes)
  • Configuration flexible des seuils de sécurité par branche Nextcloud

🏗️ Architecture```

ncstatuscheck/ ├── Frontend │ ├── index.php # Main entry point │ ├── template.html # HTML template (dashboard) │ ├── admin.html # Administration interface │ ├── detail.php # Server detail page │ ├── audit.php # Server-audit script distribution page (nc-audit.sh) │ ├── troubleshooting.php # Probe troubleshooting guide │ ├── app.js / admin.js / detail.js / audit.js / troubleshooting.js │ └── style*.css # One stylesheet per page family ├── APIs (HTTP) │ ├── api.php # Main monitoring API │ ├── detail-api.php # Detail page API (serverinfo + warnings + acks + availability) │ ├── push-api.php # Push reception + trigger + audit-report reception │ ├── ack-api.php # Warning acknowledge / unmute │ ├── admin-api.php # Version configuration routing │ ├── servers-admin-api.php # Server list management │ ├── nextcloud-versions-api.php # Official version scraping │ ├── nextcloud-apps-api.php # App store catalog (slim cache) for the apps audit │ ├── php-versions-api.php # PHP branch support data │ └── apps-warnings-api.php # Manual app warnings (known-bug list) CRUD ├── Shared modules (lib/) │ ├── auth.php # Auth + CSRF + URL redaction (defense in depth) │ ├── csrf-client.js # Auto-inject X-CSRF-Token in fetch() │ ├── nextcloud-client.php # Centralized HTTP client → remote Nextclouds │ ├── servers-store.php # Single source of truth for servers.json │ ├── uptime-state.php # Up/down state machine + transition journal + availability │ ├── alerts.php # Proactive alert dispatch: webhook + email digest │ ├── alerts-checks.php # Slow-signal alerts (SSL/version/push/audit/apps) + dedup state │ ├── smtp-mailer.php # SMTP transport adapter over vendored PHPMailer │ ├── phpmailer/ # Vendored PHPMailer (3 files + LICENSE, pinned in VERSION) │ ├── apps-warnings-manager.php # Manual app warnings storage │ ├── ui-common.js # NcUI: notify / confirm / prompt + shared app-audit messages │ ├── url-guard.php # Anti-SSRF (loopback, RFC1918, link-local…) │ ├── json-cache.php # Locked JSON read/write helpers │ └── version-config-manager.php # Version rules CRUD ├── Business logic │ ├── version-rules.php # NC / PHP status analysis engine │ ├── warnings-rules.php # Configuration warning engine │ ├── apps-rules.php # Installed-apps audit engine (store catalog cross-check) │ ├── cron-update.php # Full collection script, CLI only (twice a day) │ └── cron-ping.php # Lightweight up/down probe, CLI only (every 5 min) ├── Tools (never web-served — blocked by nginx/.htaccess) │ ├── tools/nc-audit.sh # Standalone server audit script (root, read-only) │ └── tools/ncstatuscheck-push-core.sh # Generic Push probe core (fleet-shared) ├── Tests │ └── tests/run.php # Plain-PHP test suite (no framework): php tests/run.php ├── Configuration │ ├── config.php # Central configuration (git-ignored) │ └── servers.json # Server list with tokens (git-ignored) └── Cache ├── servers_data.json # All server data ├── serverinfo_.json # Raw per-server cache (Extended) ├── push_.json # Last push payload per server ├── ack_.json # Acknowledged warnings per server ├── audit_.json # Last nc-audit.sh report per server ├── version-config.json # Version configuration ├── uptime_state.json # Up/down state per server (mini uptime) ├── uptime_history.json # Bounded up/down transition journal (availability % + incidents) ├── alerts_state.json # "Already alerted" memory of the check alerts ├── nextcloud_versions.json # Official NC versions ├── nextcloud_apps.json # App store slim catalog (apps audit) ├── apps-warnings.json # Manual app warnings (admin-curated) ├── .csrf_secret # CSRF HMAC secret (binary, 0600) └── *.log # Activity logs

deploy/ansible/ # Fleet deployment of the Push core (Ansible / scp) deploy/docker/ # Container packaging of the monitor itself

root@kitploit:~
## 🔌 Modes de collecte

Les modes ne sont pas mutuellement exclusifs — un serveur peut être en mode Étendu et Push simultanément.

| Mode | Badge | Source | Données collectées |
|------|-------|--------|----------------|
| **Basique** | *(aucun)* | `/status.php` + en-têtes HTTP | Version Nextcloud (PHP/serveur web si exposé) |
| **Étendu** | `⚡ Étendu` (violet → orange en cas d'erreur/données obsolètes) | `/ocs/v2.php/apps/serverinfo/api/v1/info` avec `NC-Token` | Version NC, PHP, serveur web, OPcache, Redis, DB, utilisateurs actifs… |
| **Push** | `📡 Push` (bleu → orange en cas d'erreur/données obsolètes) | POST vers `push-api.php` | Données poussées par l'instance NC distante via le script cron |

Le **jeton NC serverinfo** est disponible dans **Paramètres Nextcloud → Administration → Système**.

Le **jeton Push** est généré depuis l'interface d'administration ; l'administrateur fournit un script cron bash prêt à l'emploi (`chmod 700`) à déployer sur l'instance surveillée.

Les données du mode Étendu sont fournies par l'application [nextcloud/serverinfo](https://github.com/nextcloud/serverinfo), qui doit être installée et activée sur l'instance surveillée.

**Comportement de secours** : si l'API Étendue est inaccessible (erreur de connexion, jeton invalide, application non installée), NcStatusCheck revient automatiquement à `/status.php` pour récupérer au moins la version Nextcloud.

**Seuil d'obsolescence Push** : un serveur Push est considéré obsolète si aucune donnée n'a été reçue dans `auto_push_interval + 30 minutes`. L'intervalle Push par défaut est de 12 heures.

### Colonnes du tableau de bord

Le tableau de bord principal affiche 5 colonnes : **Serveur** | **Version NC** | **PHP** | **Sondes** | **Santé**

La colonne **Sondes** affiche les modes de collecte actifs pour chaque serveur :
- Badge `⚡ Étendu` (violet, devient orange en cas d'erreur de connexion ou de données obsolètes)
- Badge `📡 Push` (bleu, devient orange lorsque aucune donnée n'est reçue dans le délai)
- Les deux badges peuvent apparaître simultanément si les deux modes sont actifs
- Pas de badge = mode Basique uniquement

### Colonne Santé

La colonne Santé n'affiche quelque chose que lorsqu'il y a quelque chose à traiter :

| Indicateur | Badge | Signification |
|-----------|-------|---------|
| Hors ligne | `🔴 Hors ligne` | Instance inaccessible (sonde HTTP a échoué), avec « hors ligne depuis X » |
| Avertissements actifs | `⚠️ N` | N problèmes de configuration |
| Audit des applications | `📦 N` | N applications installées à examiner (bloquant mise à jour/incompatible) |
| Expiration SSL | `🔒 N j` | Certificat expire bientôt — orange `< 15 j`, rouge `< 7 j` ou expiré |
| Mises à jour Docker | `🔄 M` | M mises à jour de conteneurs disponibles |
| Tout OK | *(vide)* | Rien à signaler |
| Aucune donnée | `?` | Mode Basique sans données Push |

#### État haut/bas et expiration SSL

NcStatusCheck conserve un état haut/bas **minimal** par serveur (état actuel + date de dernier changement uniquement — pas de séries temporelles, pas de page d'historique). « Haut » signifie que la sonde HTTPS sortante a atteint l'instance ; un badge rouge **Hors ligne** n'apparaît que lorsque c'est bas. Lors de cette même sonde HTTPS, **l'expiration du certificat SSL** est lue gratuitement (`CURLOPT_CERTINFO`) et signalée lorsqu'elle approche. Les deux sont visibles en détail sur la page de détail. *Remarque : ces contrôles sortants ne s'appliquent pas aux instances Push uniquement que le moniteur ne contacte jamais.*

#### Audit des applications (`📦`)

Lorsqu'un serveur Push signale ses applications installées (`occ app:list`, script push v3+), NcStatusCheck les recoupe avec le catalogue de l'app store Nextcloud et signale les applications dignes d'examen. **Signalement uniquement** — l'outil ne désactive jamais rien ; il remonte des candidates (il ne peut pas savoir si une application est réellement utilisée). Seuls des signaux **factuels et binaires** sont utilisés. Le badge `📦 N` compte les constats bloquants (pas de version compatible pour la version NC actuelle, pas de version pour NC N+1 → bloque la mise à niveau, ou une application de test/développement laissée activée en production). Les constats informatifs (application obsolète sur l'instance, abandonnée en amont, incompatible PHP) sont affichés uniquement sur la page de détail. Les constats peuvent être masqués via le même mécanisme d'accusé de réception que les avertissements.

### Format `servers.json````json
[
  {"url": "https://cloud.example.com"},
  {"url": "https://cloud2.example.com", "serverinfo_token": "abc123def456"},
  {"url": "https://cloud3.example.com", "serverinfo_token": "...", "push_token": "xyz789"}
]

🚀 Installation

Prérequis

  • PHP 8.1+ avec les extensions cURL et JSON — c'est le plancher syntaxique contre lequel les tests CI sont exécutés, et non une recommandation de déploiement : 8.1 et 8.2 sont déjà dépassées leur date de fin de support de sécurité, utilisez une version actuellement prise en charge (8.3+ au moment de la rédaction) pour tout ce qui est exposé sur Internet
  • Serveur web nginx ou Apache avec HTTPS
  • Accès réseau aux serveurs Nextcloud à surveiller

Configuration du serveur web (nginx)```nginx

server { server_name monitoring.your-domain.com; root /var/www/ncstatuscheck; index index.php;

root@kitploit:~
# HTTP Basic Authentication
auth_basic "Monitoring Access";
auth_basic_user_file /etc/nginx/.htpasswd;

# Protect sensitive files/dirs (tests/run.php has no CLI-only guard — it must
# never be reachable over HTTP; same blocklist as deploy/docker/nginx.conf)
location ~ ^/(cache/|\.git|deploy/|tools/|tests/) {
    deny all;
    return 404;
}

# .txt covers servers.txt (legacy server list — real monitored URLs)
location ~* \.(log|json|txt)$ {
    deny all;
    return 404;
}

# Security headers for static HTML pages (admin.html, template.html).
# PHP pages (index.php, detail.php) send the same headers themselves
# via send_security_headers() in lib/auth.php.
location ~* \.html$ {
    add_header X-Content-Type-Options nosniff always;
    add_header X-Frame-Options DENY always;
    add_header Referrer-Policy no-referrer always;
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'" always;
    try_files $uri =404;
}

# Standard PHP configuration (adjust the socket to your PHP version —
# use a security-supported one: 8.2 has been EOL since December 2025)
location ~ \.php$ {
    fastcgi_pass unix:/run/php/php8.4-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

location / {
    try_files $uri $uri/ =404;
}

}

root@kitploit:~
> **Apache** : le dépôt comprend des fichiers `.htaccess` reflétant les règles de `deny` ci-dessus (root : bloque `*.log`/`*.json`/`*.txt` et `.git` ; `cache/`, `tools/`, `deploy/`, `tests/` : `Require all denied`). Ils ne fonctionnent que si le vhost définit `AllowOverride FileInfo AuthConfig` (ou `All`) — la valeur par défaut de Debian pour `/var/www` est `AllowOverride None`, auquel cas il faut répliquer les règles directement dans le vhost. L'authentification HTTP Basic doit de toute façon être configurée dans le vhost.

### Déploiement

1. **Cloner le dépôt**```bash
git clone https://gitlab.com/jp.louvel/ncstatuscheck.git
cd ncstatuscheck
  1. Configuration Créez votre fichier de configuration à partir du modèle :```bash cp config-example.php config.php
root@kitploit:~
Modifiez `config.php` et ajustez les chemins et l'URL à votre environnement :```php
define('MONITOR_PATH', '/var/www/ncstatuscheck');
define('MONITOR_URL', 'https://monitoring.your-domain.com'); // your public URL
define('CACHE_DIR', MONITOR_PATH . '/cache');
  1. Ajouter des serveurs

Les serveurs sont gérés directement depuis l'interface d'administration (bouton ⚙️ Admin). Vous pouvez également créer servers.json manuellement :```json [ {"url": "https://cloud.example.com"}, {"url": "https://nextcloud.mycompany.org", "serverinfo_token": "your_token_here"} ]

root@kitploit:~
> **Migration depuis `servers.txt`** : si un fichier `servers.txt` existe, il est automatiquement converti en `servers.json` lors du premier accès. Vous pouvez ensuite supprimer `servers.txt`.

4. **Définir les permissions**

nginx/PHP-FPM s'exécutent sous leur propre utilisateur (`www-data` sur Debian/Ubuntu, `nginx`/`apache` sur la famille RHEL — ajustez ci-dessous) — si vous avez cloné en tant que votre propre utilisateur de connexion, cet utilisateur ne sera presque certainement pas `www-data` ou dans son groupe, donc `chmod` seul laisse le serveur web **sans aucun accès**, même pas en lecture (chaque requête 403/404) :```bash
chown -R www-data:www-data /var/www/ncstatuscheck   # adjust the user:group to your distro

chmod 750 /var/www/ncstatuscheck
chmod 750 cache img

chmod 640 *.php *.html *.js *.css *.md
chmod 600 config.php servers.json servers.txt   # secrets / serverinfo & push tokens
chmod 660 cache/*.json cache/*.log

Si servers.json n'existe pas encore (vous laissez l'interface d'administration le créer plutôt que de suivre l'étape manuelle ci-dessus), la commande chmod 600 ci-dessus n'a simplement rien sur quoi agir — ce n'est pas grave : ServersStore::save() exécute elle-même un chmod vers 0600 à chaque écriture, donc un fichier servers.json (re)créé via l'interface d'administration ne reste jamais lisible par le groupe/monde avec des jetons serverinfo/push à l'intérieur.

  1. Authentification HTTP```bash htpasswd -c /etc/nginx/.htpasswd admin
root@kitploit:~
6. **Tâches planifiées (optionnelles)**

Deux crons complémentaires — installez les deux **dans le même appel `crontab -`** :
`crontab -` installe une toute nouvelle crontab depuis l'entrée standard, il n'ajoute pas, donc
l'exécuter deux fois (une fois par ligne) ne laisse que le *deuxième* job — le premier
disparaît silencieusement, sans erreur. Cela préserve également tout ce qui se trouve déjà dans votre
crontab (en redirigeant d'abord `crontab -l`) au lieu de l'effacer :```bash
(crontab -l 2>/dev/null; cat <<'EOF'
# Full collection (NC/PHP versions, serverinfo, app-store catalog) — twice a day
0 6,18 * * * cd /var/www/ncstatuscheck && php cron-update.php
# Lightweight reachability probe (status.php only -> up/down state) — every 5 min
*/5 * * * * cd /var/www/ncstatuscheck && php cron-ping.php
EOF
) | crontab -

Re-running this appends duplicates if these lines are already present — check with crontab -l first if unsure.

cron-ping.php est volontairement minimal : il ne fait que vérifier le status.php de chaque instance et mettre à jour l'état up/down (cache/uptime_state.json), afin de pouvoir s'exécuter fréquemment sans charge. Une instance n'est marquée down qu'après UPTIME_FAIL_THRESHOLD sondes consécutives échouées (par défaut 2 → ~10 min avec une cadence de 5 min) ; le retour à up est immédiat. Le cron-update.php complet reste inchangé pour tout le reste.

Docker (alternative au bare-metal)

Au lieu des étapes 1 à 6 ci-dessus, NcStatusCheck peut également fonctionner comme une petite stack docker compose (PHP-FPM + nginx + un conteneur cron) — le dépôt est monté en bind tel quel, sans étape de build ni Composer, donc il reflète exactement l'agencement bare-metal, simplement conteneurisé. Sert uniquement du HTTP simple (port 8080 par défaut) — placez votre propre proxy inverse de terminaison TLS devant.

L'installation complète — configuration, les pièges de permissions (uid 82, pré-création de servers.json), l'authentification HTTP Basic, cron, les mises à jour et les sauvegardes — se trouve entièrement dans deploy/docker/README.md. Commencez par là ; cette section est intentionnellement juste un pointeur, pour éviter de maintenir deux copies des mêmes étapes en synchronisation.

📋 Utilisation

Interface principale

  • Allez à https://monitoring.votre-domaine.com
  • Consultez le tableau de bord avec l'état de tous vos serveurs
  • Utilisez les filtres pour affiner par statut ou rechercher
  • Vérifiez les versions officielles et le calendrier des publications

Administration

  • Ouvrez l'interface d'administration via le bouton "⚙️ Admin"
  • Un tableau récapitulatif des modes de sondage en haut de la page explique les différences entre les méthodes de collecte Basic, Extended et Push
  • Gestion des serveurs : chaque serveur est affiché sous forme de carte avec deux zones de sondage repliables :
    • Zone Serverinfo : configurer le jeton de lecture (NC → tirage NcStatusCheck)
    • Zone Push : générer un jeton push et télécharger le script cron prêt à l'emploi pour l'instance distante
  • Configuration Nextcloud : définir les versions sécurisées minimales par branche (effets de survol sur les lignes)
  • Configuration PHP : définir les statuts recommandé/prise en charge par version

Page détaillée

Accessible en cliquant sur n'importe quel nom de serveur ou son indicateur de santé.

Pour les serveurs Basic (pas de sonde Extended ou Push), une page simplifiée affiche les données disponibles (version NC, serveur web, protocole HTTP) avec un avis et une suggestion pour activer une sonde.

Pour les serveurs Extended / Push, la page détaillée complète affiche des sections séparées :

API

NcStatusCheck expose plusieurs points de terminaison REST :

API principale (api.php)

  • GET ?action=get_data — Récupérer les données (cache ou rafraîchissement)
  • POST ?action=refresh_data — Forcer la mise à jour de tous les serveurs

API Push (push-api.php)

  • POST avec en-tête push_token — Recevoir les données push d'une instance NC distante
  • POST ?action=request_push_all — Demander un push immédiat de tous les serveurs push configurés (définit un indicateur de déclenchement consommé par le script cron distant)

Le script cron généré par l'interface d'administration est divisé en deux : un noyau générique /usr/local/bin/ncstatuscheck-push.sh — identique sur chaque serveur (toute la logique) — piloté par une petite configuration par instance /etc/ncstatuscheck/<slug>.conf (SERVER_URL, SLUG, OCC_CMD, DOCKER_ENABLED, SKOPEO_ENABLED). Il est invoqué sous la forme ncstatuscheck-push.sh /etc/ncstatuscheck/<slug>.conf [--test]. Le noyau refuse de sourcer une configuration accessible en écriture par le groupe/tout le monde (anti-injection de code).

Il est multi-cible (fan-out) : les données sont collectées une fois et poussées vers chaque moniteur listé dans /etc/ncstatuscheck/targets-<slug>.conf (une ligne url|push_token[|http_user|http_pass] par moniteur). L'admin de chaque moniteur émet une commande idempotente pour s'enregistrer.

Plusieurs instances Nextcloud sur un même hôte : les chemins par instance sont suffixés par un dérivé de l'URL surveillée (ex. → ) : , , , , état . Seul le noyau est partagé, donc les instances colocalisées n'entrent jamais en collision.

API de détail (detail-api.php)

  • GET ?server=<url> — Données complètes serverinfo + avertissements calculés pour un serveur Extended/Push

API d'administration

  • admin-api.php — Configuration des versions
  • servers-admin-api.php — Gestion des serveurs (get_servers, add_server, remove_server, update_server_token, generate_push_token, remove_push_token)
  • nextcloud-versions-api.php — Versions officielles

🩺 Audit du serveur (nc-audit.sh)

Un sous-système séparé de la surveillance : un script bash autonome et en lecture seule (tools/nc-audit.sh) exécuté en tant que root sur un serveur Nextcloud pour un audit ponctuel / mensuel du réglage du web + PHP + base de données, recoupé avec la capacité physique de la machine (RAM, CPU, type de disque). Destiné à une offre de supervision gérée : le client l'installe, le moniteur ne reçoit que des rapports — aucun accès machine/réseau requis. Le script ne fait que lire la configuration (aucune modification), imprime un rapport coloré et en écrit une copie dans /tmp.

Ce qu'il vérifie : capacité du serveur (RAM/CPU/SSD-HDD, swappiness, détection de serveur partagé) · Nextcloud (versions, cron, cache, environnement Redis runtime, type de base de données, journaux) · PHP/PHP-FPM (SAPI de service réel, environnement OPcache, mémoire multi-pool) · Apache (mémoire worker sensible au MPM) · Nginx · PostgreSQL · MariaDB · hygiène de sécurité (fail2ban ou CrowdSec + bouncer + blocklist communautaire ; mises à jour en attente / redémarrage / services sur bibliothèques obsolètes) · réconciliation du budget RAM (InnoDB + FPM + Apache vs RAM réelle) · analyse approfondie avec des outils optionnels s'ils sont déjà présents (mysqltuner, pt-variable-advisor, apache2buddy, sar/iostat).```bash

Download (the page distributes it; the repo raw URL is public)

curl -fsSL https://gitlab.com/jp.louvel/ncstatuscheck/-/raw/master/tools/nc-audit.sh -o /usr/local/bin/nc-audit.sh chmod 700 /usr/local/bin/nc-audit.sh

sudo nc-audit.sh # auto-detect, dedicated server sudo nc-audit.sh /var/www/nextcloud # explicit path (or NC_PATH=…) sudo NC_RAM_BUDGET_PCT=50 nc-audit.sh # shared host: size to 50% of RAM

root@kitploit:~
**Hôtes multi-instances** (plusieurs Nextclouds + une base de données partagée). `NC_RAM_BUDGET_PCT`
est alors le budget **total** de la pile ; `NC_PHP_SHARE_PCT`% de celui-ci (par défaut 60, le reste
couvre la base de données, le serveur web et le système d'exploitation — à réduire sur les serveurs lourds en base de données) est la part PHP, répartie entre
les pools FPM par **poids** (une importance relative — pas un pourcentage, pas des Mo) pour obtenir une
cible `pm.max_children` par pool :```
target = PHP_share × (weight / Σ weights) / ~50 MB per process

La cible est un plafond que le budget permet, pas une valeur que vous devez définir (n'augmentez qu'un pool qui sature effectivement). Les poids sont votre affaire — l'outil ne les devine jamais.```bash

Weights you provide (a human judgment — the tool never guesses them):

sudo NC_RAM_BUDGET_PCT=70 NC_INSTANCES="poolA:4,poolB:2,poolC:1" nc-audit.sh

Interactive helper (terminal only): lists the pools, asks a weight for each,

prints the targets + a reusable NC_INSTANCES line:

sudo NC_RAM_BUDGET_PCT=70 nc-audit.sh --tune-fpm

root@kitploit:~
**Rapport push-back** (optionnel, réutilise l'infrastructure Push) : `nc-audit.sh --push
/etc/ncstatuscheck/<slug>.conf` lance l'audit et envoie le rapport (POST) au(x)
moniteur(s), qui le stockent et l'affichent sur la page détaillée du serveur
(« 🩺 Server audit »). Généralement un cron mensuel. La page web (admin, bêta) à
l'adresse `audit.php` distribue le script (téléchargement + en ligne + GitLab
one‑liner) et affiche sa version.

> **Les outils d'analyse avancée ne sont jamais installés** par le script – ils
> ne s'exécutent que s'ils sont déjà présents (pas de `curl | bash`, pas
> d'installation automatique), chacun étant limité par `timeout`.

## 🔧 Configuration avancée

### Personnalisation des règles de version

Les règles d'évaluation sont configurables via l'interface d'administration :

**Statuts Nextcloud :**
- `dev` — Version de développement
- `stable` — Version stable actuelle
- `oldstable` — Version stable précédente prise en charge
- `deprecated` — Version obsolète

**Statuts PHP :**
- `recommended` — Version recommandée
- `supported` — Version prise en charge
- `deprecated` — Version obsolète

### Variables de configuration

Modifiez `config.php` pour adapter la configuration :```php
// Environment: 'dev' or 'prod'
define('ENV', 'prod');

// Paths and URLs
define('MONITOR_PATH', '/var/www/ncstatuscheck');
define('MONITOR_URL', 'https://monitoring.your-domain.com');

// Main server cache duration
define('CACHE_MAX_AGE', 86400); // 24 hours

// Official Nextcloud versions cache duration
define('VERSIONS_CACHE_AGE', 86400);

// Consecutive failed probes before a server is marked "down" (min 1)
define('UPTIME_FAIL_THRESHOLD', 2);

// Proactive alerts — webhook on a confirmed up/down state change.
// Empty URL = disabled. Format: 'slack' (default, also Mattermost/Google Chat),
// 'discord', or 'raw' (structured JSON). The URL usually carries a secret, so it
// is never logged in full — see config-example.php for details.
define('ALERT_WEBHOOK_URL', '');
define('ALERT_WEBHOOK_FORMAT', 'slack');

// Check alerts on top of up/down (cron-update cadence, 2×/day): SSL expiry
// tiers, vulnerable (below min_secure) or deprecated Nextcloud version, stale
// Push data, critical audit report, blocking apps-audit finding. Edge-triggered with a persisted state
// (cache/alerts_state.json): one alert per NEW condition, no reminders, re-arms
// when resolved (renewed cert, fixed/acked app…). First run arms silently.
define('ALERT_CHECKS', 'ssl,version,push_stale,audit,apps'); // '' = up/down only
define('ALERT_SSL_DAYS', '30,14,7');                          // days-left tiers

// Email channel, independent of the webhook (either one arms the alerting).
// One digest mail per batch. Recommended transport: direct SMTP submission to
// your mail server (vendored PHPMailer, lib/phpmailer/ — nothing to set up on
// the host). Without ALERT_SMTP_HOST it falls back to PHP mail() (local MTA).
define('ALERT_EMAIL_TO', '');    // comma list of recipients, '' = off
define('ALERT_EMAIL_FROM', '');  // default: ncstatuscheck@<hostname>
define('ALERT_SMTP_HOST', '');   // e.g. 'mail.example.org', '' = mail() fallback
define('ALERT_SMTP_PORT', 587);
define('ALERT_SMTP_SECURITY', 'starttls'); // 'starttls' | 'tls' | 'none'
define('ALERT_SMTP_USER', '');
define('ALERT_SMTP_PASS', '');

Voir config-example.php pour la liste complète et commentée des options (y compris DEMO_MODE et PUSH_SCRIPT_VERSION).

🛡️ Sécurité

Mesures mises en œuvre

  • Authentification HTTP Basic obligatoire, doublée par une vérification d'authentification au niveau de l'application sur chaque point d'accès administrateur (défense en profondeur)
  • Protection CSRF : jeton HMAC injecté automatiquement sur chaque requête de mutation (lib/csrf-client.js + csrf_require())
  • Protection anti-SSRF sur chaque URL fournie par l'opérateur (boucle locale, RFC1918, lien-local rejetés ; redirections HTTPS uniquement ; vérification de l'adresse IP après connexion)
  • HTTPS requis avec certificats Let's Encrypt
  • Protection des fichiers de données et des journaux : règles nginx (voir ci-dessus) reflétées par les fichiers .htaccess fournis pour Apache ; servers.json avec chmod 0600 automatiquement (jetons à l'intérieur)
  • En-têtes de sécurité (CSP, X-Frame-Options, nosniff, Referrer-Policy) sur chaque page servie par PHP
  • Validation stricte des URL sur toutes les entrées
  • Scripts clients exécutés en tant que root : la configuration de l'instance est sourcée en tant que root et le fichier de cibles décide où les données collectées sont envoyées — les deux sont refusés s'ils ne sont ni non inscriptibles par le groupe/tout le monde, ni détenus par un tiers
  • : un push n'est accepté que lorsque l'URL dans le corps correspond à une entrée ET que réussit sur le jeton de entrée, de sorte qu'un serveur surveillé compromis ne peut ni lire ni écraser les données d'un autre. / se situent derrière l'authentification admin + CSRF. Vérifié de bout en bout dans un scénario de client compromis

Recommandations

  • Utiliser des mots de passe forts pour l'authentification HTTP
  • Restreindre l'accès aux adresses connues — l'onglet Filtrage IP de l'administration génère les règles pour vous (voir ci-dessous)
  • Surveiller les journaux pour détecter les tentatives d'intrusion
  • Maintenir PHP et les dépendances système à jour

Bannière d'état de config.php (administration)

config.php est dans .gitignore et édité manuellement par serveur, donc il dérive — silencieusement, puisque presque chaque constante a une valeur par défaut dans le code. Une bannière en haut de la page d'administration signale ce qui ne va pas réellement, et uniquement quand quelque chose ne va pas : un PUSH_SCRIPT_VERSION laissé par une mise à jour, aucun transport d'alerte configuré, une balise de fermeture finale émettant un octet avant tout header(), un répertoire de cache non inscriptible, des constantes absentes qui tombent silencieusement sur les valeurs par défaut.

En lecture seule par conception et sans action de sauvegarde, pour la même raison que l'onglet Notifications : config.php appartient à root et contient des secrets. Le contenu du fichier ne voyage jamais — seuls des faits à son sujet — et aucun secret n'est lu.

Filtrage IP (onglet administration)

Tout ce qui précède est au niveau de l'application : n'importe qui sur Internet peut encore atteindre le moniteur et le sonder, seul le mot de passe les arrête. L'onglet Filtrage IP génère les règles qui placent une liste d'autorisation devant l'application, de sorte que les hôtes inconnus ne peuvent pas du tout lui parler. C'est une défense en profondeur, pas un remplacement de l'authentification Basic ou des jetons de push — et cela ne produit que du texte à vérifier et coller, cela n'écrit jamais une configuration de serveur web ou de pare-feu.

Deux classes de source, délibérément inégales, de sorte qu'un serveur surveillé compromis ne puisse pas atteindre l'administration :

ClasseQuiPeut atteindre
pushinstances surveillées en mode Push uniquement/push-api.php, rien d'autre
adminbastion / VPN / adresse de bureau fixetout

Les instances interrogées en mode Basique/Étendu n'ouvrent aucune connexion entrante et n'obtiennent aucune entrée de liste d'autorisation.

Les adresses proviennent de deux sources, et la différence est importante : l'enregistrement DNS d'un domaine surveillé est son adresse d'entrée, tandis que son push part de son adresse de sortie. Lorsqu'elles diffèrent, seule la seconde fonctionne. push-api.php enregistre donc l'adresse source réelle de chaque push (source_ip dans le cache des pushes), et l'onglet l'autorise, signalant l'incohérence. Tant qu'un serveur n'a pas poussé une fois, il revient sur le DNS A+AAAA et le mentionne.

Trois sorties :

  • nginx (recommandé) — un fichier conf.d autonome (geo + map) plus une seule ligne if ($ncsc_forbidden) { return 403; } dans le vhost. Pas besoin de dupliquer le bloc fastcgi, les fichiers statiques sont également couverts (admin.html en fait partie), et /.well-known/acme-challenge/ reste ouvert pour que le renouvellement du certificat ne casse pas silencieusement.
  • Apache 2.4 — <LocationMatch> avec une anticipation négative plus un <Location> pour le point de terminaison push, de sorte que les deux sections ne puissent pas se chevaucher et que rien ne dépende de l'ordre de fusion d'Apache. Toutes les adresses d'une règle vont sur une seule ligne Require ip : plusieurs lignes dans <RequireAll> sont en ET, ce que personne ne peut satisfaire.
  • ufw — grossier par nature (un filtre de paquets voit les ports, pas les URL), il ne peut donc pas exprimer la séparation push/admin. Utilisez-le uniquement comme couche externe.

Le générateur refuse d'émettre lorsqu'aucune adresse d'administration n'est donnée, avertit lorsque l'adresse de l'opérateur lui-même n'est pas couverte, et avertit lorsque la requête est passée par un proxy (car geo et Require ip lisent le pair de transport, donc derrière un proxy, chaque client se ressemble). L'extrait ufw généré place la règle SSH en premier, maintient le port 80 ouvert pour le défi HTTP-01, et explicite le piège IPv6 : contrairement à nginx, qui refuse une adresse v6 non listée, ufw ne filtre pas le v6 du tout sauf si IPV6=yes est défini — un hôte double pile serait autrement grand ouvert sur IPv6.

Limite connue, signalée dans la page elle-même : une fois les règles appliquées, cet onglet ne découvre rien de nouveau. Un push refusé est rejeté par le serveur web avant d'atteindre PHP, donc l'adresse enregistrée reste la dernière qui est passée — et semble toujours vérifiée. Deux conséquences : ajouter un serveur Push signifie régénérer et réappliquer les règles, sinon son premier push est refusé ; et si l'adresse d'une instance change, la nouvelle n'est lisible que dans le journal d'accès du serveur web (grep 'push-api.php' access.log | grep ' 403 '). L'onglet affiche donc la date de dernière observation de chaque adresse et la signale dès qu'elle est plus ancienne qu'un cycle de push manqué complet — le même seuil que l'alerte push_stale, qui couvre le même angle mort depuis l'autre côté.

Distinguer un problème de filtrage d'un autre : un GET nu sur le point de terminaison push sépare proprement les couches, sans effet secondaire et sans jeton nécessaire — exécutez-le depuis la machine concernée, puisque ce qui est jugé est l'adresse de sortie de cette machine :```bash curl -sS -o /dev/null -w '%{http_code}\n' https://your-monitor/push-api.php

root@kitploit:~
| Réponse | Signification |
|---|---|---|
| `403` | bloqué par le filtrage IP |
| `401` | filtrage passé, Basic auth répond — le problème est ailleurs |
| `405` | la requête a atteint l'application (GET n'est pas une méthode acceptée ici) |
| rien / timeout | pas le filtrage : un filtre répond, il ne devient pas silencieux |

Relancez avec `-u user:password` pour lever un doute sur un `403` : si le code ne bouge pas, c'est bien le filtrage. Vérifié sur nginx et Apache (y compris avec `Require valid-user` activé), le filtre répond *avant* l'authentification — et un `403` provenant de l'application elle-même contient toujours du JSON dans le corps.

La logique des snippets se trouve dans `lib/hardening-rules.php`, qui est pure et couverte par `tests/run.php` : les snippets sont le produit ici, et un mauvais snippet soit bloque l'opérateur, soit laisse une brèche. Les sorties nginx et Apache ont été vérifiées comportementalement (serveurs réels, adresses sources réelles, y compris des tentatives de path-traversal depuis la classe `push`).

### Analyse automatisée (étape CI `security`)

L'analyse des dépendances (`npm/pnpm audit`, Snyk Open Source, Dependabot) est une non-opération ici : il n'y a pas de `package.json` ni de `composer.json` — rien à analyser. Le risque réside dans le code personnalisé (~15k lignes de PHP, ~6k de JS) et dans les scripts shell qui s'exécutent **en tant que root** sur les instances surveillées (`tools/*.sh`). Le pipeline est ciblé là-dessus :

| Job | Outil | Bloquant | Périmètre |
|---|---|---|---|
| `secrets_scan` | gitleaks | oui | secrets commités (arbre de travail) |
| `sast_semgrep` | semgrep (`p/php`, `p/javascript`, `p/owasp-top-ten`) | oui | SSRF, authz/CSRF manquants, XSS |
| `shellcheck` | shellcheck (`--severity=warning`) | oui | `tools/*.sh` — root sur les hôtes clients |
| `dockerfile_misconfig` | trivy misconfig | oui | `deploy/docker/` |
| `container_cve` | trivy image | non (`allow_failure`) | l'image que `deploy/docker` construit, plus `nginx:alpine` |
| `ui_tests` | node (sans dépendances) | oui | invariants d'échappement de `lib/ui-common.js` (régressions XSS passées) |
| `phpmailer_freshness` | API GitHub | non (`allow_failure`) | pin vendu vs version amont |
| `deploy_selfcheck` | nc-selfcheck.sh | oui | le jeu de règles nginx livré (règles de refus + en-têtes de sécurité) déployé dans un conteneur jetable |

Tous les jobs bloquants ont une **base de zéro constatation**, donc toute nouvelle alerte est un signal réel. Deux choix délibérés, documentés en ligne dans `.gitlab-ci.yml` :

- **`php.lang.security.injection.echoed-request` est exclue** de semgrep : elle signale chaque `echo json_encode()` comme XSS, ce que fait légitimement chaque point d'API ici (réponses JSON, pas HTML). Cela représentait 10 des 10 constatations au premier passage, toutes fausses. La conserver habituerait tout le monde à ignorer le job.
- **Les deux jobs `allow_failure` rapportent des faits amont** (une CVE dans `nginx:alpine` ou une dont le correctif n'a pas encore atteint la branche Alpine, une nouvelle version de PHPMailer) qu'une demande de fusion ne peut pas corriger. Rouge mais toléré est le signal précis — "il est temps de reconstruire / rafraîchir le vendoring" — pas une raison pour bloquer un travail non lié. `phpmailer_freshness` signale une API GitHub inaccessible ou limitée comme un *skip*, jamais comme "obsolète".
- **`container_cve` analyse l'image qu'il construit, pas le tag `FROM`.** Le Dockerfile durcit la base avec `apk --no-cache upgrade` (l'image PHP officielle est en retard sur les dépôts Alpine — elle a livré c-ares 1.34.6-r0 alors que 1.34.8-r0, corrigeant CVE-2026-33630, était déjà publiée). Analyser le tag de base rapporterait donc des CVE que l'image livrée n'a plus : un job orange permanent que personne ne lit.

Les listes blanches sont intentionnellement restreintes : `.gitleaks.toml` excuse les chaînes de substitution **littérales**, jamais des fichiers de documentation entiers (mettre `README.md` en liste blanche aveuglerait l'analyse le jour où un vrai secret y est collé) — donc un nouveau jeton d'exemple dans la documentation doit y être ajouté. `.trivyignore` contient une seule entrée, `DS-0002`, argumentée dans le fichier : le maître php-fpm doit démarrer en tant que root pour descendre ses workers à `www-data` (uid 82).

### Vérification post-déploiement (`nc-selfcheck.sh`)

La CI peut verrouiller la configuration *livrée* (le job `deploy_selfcheck` ci-dessus met le jeu de règles nginx dans un conteneur et le sonde), mais elle ne peut pas vérifier le serveur sur lequel vous avez réellement déployé — hôte différent, identifiants Basic-auth, permissions du système de fichiers. `tools/nc-selfcheck.sh` comble cette lacune. C'est un script bash autonome et en lecture seule (même modèle que `nc-audit.sh`) que vous exécutez après chaque déploiement :```bash
# Black-box, no credentials: confirms Basic auth is enforced (401) and that
# sensitive files are blocked (cache/, servers.*, .git, config.php source).
bash tools/nc-selfcheck.sh https://monitoring.example.com

# + security headers behind Basic auth:
bash tools/nc-selfcheck.sh -u user:pass https://monitoring.example.com

# + filesystem checks (run ON the host): servers.json / config.php / CSRF-secret
# permissions, and a stray closing "?>" in config.php.
bash tools/nc-selfcheck.sh --webroot /var/www/ncstatuscheck https://monitoring.example.com

Il retourne un code de sortie non nul en cas de découverte critique (fuite de source, fichier secret non verrouillé, stockage de jetons lisible par tous, authentification Basic manquante), ce qui permet de bloquer un déploiement — intégrez-le dans votre script de synchronisation/déploiement en tant qu'étape postérieure. WARN/INFO ne font jamais échouer l'exécution.

🧪 Tests et développement

Mode développement```php

// In config.php define('ENV', 'dev');

root@kitploit:~
En mode développement, des informations supplémentaires sont affichées (version PHP, serveur web).

### Test du serveur
Utilisez l'interface d'administration pour ajouter un serveur par URL. Le serveur sera interrogé lors du prochain rafraîchissement des données.

### Journaux de débogage
Consultez les fichiers journaux dans `cache/` :
- `monitor.log` — Journaux généraux de l'application
- `cron.log` — Journaux complets du script de collecte (`cron-update.php`)
- `ping.log` — Journaux légers des sondes up/down (`cron-ping.php`)
- `alerts.log` — Envoi proactif des alertes (webhook/email), ne journalise jamais les secrets webhook ni les identifiants SMTP

### Suite de tests```bash
php tests/run.php   # plain-PHP assertions, no framework — exit 0 = all green

Couvre la logique métier pure (règles version/apps, avertissements, machine d'état de disponibilité et uptime, machine d'état de déduplication/réarmement des alertes, générateurs d'emails).

🤝 Contribuer

Signaler un bug

Ouvrez un nouveau ticket avec :

  • Une description détaillée du problème
  • Étapes pour reproduire
  • Journaux d'erreurs si disponibles
  • Votre configuration d'environnement

Proposer une amélioration

  1. Ouvrez un ticket pour discuter de votre idée
  2. Forkez le projet
  3. Créez une branche pour votre fonctionnalité
  4. Implémentez avec documentation
  5. Soumettez une demande de fusion

📝 Licence

Ce projet est sous licence GNU AGPL v3.

👥 Crédits

NcStatusCheck est développé par ézéo, une coopérative numérique spécialisée dans les solutions open source.

Contributeurs

  • Équipe ézéo — Développement initial et maintenance

Besoin d'aide ? Consultez les issues ou contactez l'équipe ézéo.

Télécharger l’outil
SectionChamps
Système NextcloudVersion, mode debug, memcache local/distribué, file locking, espace disque
PHPVersion, memory_limit, upload_max_filesize, max_execution_time, FPM, OPcache
Serveur webNom + version, protocole HTTP
Base de donnéesType, version, taille
CacheRedis, taux de hit APCu
Utilisateurs actifs5 dernières min, 1 h, 24 h, 7 jours
<slug>
latest.ezeo.coop
latest_ezeo_coop
<slug>.conf
/etc/cron.d/ncstatuscheck-<slug>
targets-<slug>.conf
ncstatuscheck-push-<slug>.log
…-<slug>.<md5>.last

Nextcloud fonctionnant dans Docker (image officielle, compose, AIO) : entièrement pris en charge — le script est installé sur l'hôte (cron root + accès au démon Docker), jamais à l'intérieur du conteneur, et occ passe par docker exec : OCC_CMD=docker exec -u www-data <conteneur> php occ (conteneur AIO : nextcloud-aio-nextcloud). Le générateur de script d'administration a un type d'installation prédéfini qui préremplit cela. N'ajoutez jamais -t (pas de TTY sous cron) ; gardez -u www-data (l'image officielle refuse occ en tant que root).

Déploiement / mises à jour de flotte : comme le noyau est un seul fichier identique, mettre à jour la logique sur de nombreux serveurs = remplacer ce seul fichier (le marqueur ↑ signale les serveurs exécutant une version plus ancienne). Voir deploy/ansible/ pour un playbook prêt à l'emploi (ou une simple boucle scp). Le moniteur reste passif — il n'envoie jamais de code vers la flotte ; l'ancre de confiance est votre propre accès SSH, pas le moniteur.

Migration depuis une installation pré-v4 (script monolithique par instance) : supprimez l'ancien /usr/local/bin/ncstatuscheck-push-<slug>.sh et /etc/cron.d/ncstatuscheck-<slug> avant d'installer le noyau + la configuration (le targets-<slug>.conf est réutilisé tel quel), sinon vous ferez un double push.

Isolation entre les instances surveillées
hash_equals()
cette
request_push
request_push_all
  • Rapport de destination des pushes : chaque instance déclare vers quels moniteurs elle pousse (URL uniquement, jamais les jetons) ; la page de détail les affiche et une alerte se déclenche lorsque l'ensemble change — une ligne supplémentaire dans targets.conf copie silencieusement chaque push vers un tiers sinon
  • Assainissement des charges utiles des pushes : les ID d'application sont autorisés via une liste blanche de caractères ; les champs Docker libres (nom, image, version, statut) sont dépouillés de <>"'& à l'ingestion, en plus de l'échappement au rendu
  • Vérification SSL/TLS pour les connexions sortantes — jamais désactivée, y compris pour le transport d'alerte SMTP
  • Réponses distantes limitées (2 Mo) : un serveur surveillé contrôle entièrement ce qu'il répond et rien n'authentifie cette direction. Sans limite, un serveur qui diffuse simplement des données épuise la mémoire de PHP — une erreur fatale qu'aucun try/catch ne peut attraper, ce qui tuerait la boucle de collecte en cours et, avec elle, toutes les alertes pour l'ensemble de la flotte
  • Anonymisation en mode démo couvre plus que l'URL : les noms de conteneurs, les hôtes de registres privés dans les références d'images et le nom d'hôte cité dans les messages d'erreur cURL sont tous nettoyés, à la fois sur le tableau de bord et sur la page de détail