chore: initialise la structure du projet SentinelMesh

- Workspace Cargo avec backend, agent-scan-network, agent-metric
- Skeleton Rust pour les trois crates (Axum, Tokio, SQLx)
- Documentation : README, FEATURES, ROADMAP, ARCHITECTURE, API, INSTALL
- Exemples de widgets Glance (custom-api)
- Script d'installation agents (squelette Phase 5)
- Docker Compose + Dockerfile backend
- .gitignore et CLAUDE.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-19 05:59:12 +02:00
parent 452fded27f
commit 7cf56f24ef
22 changed files with 671 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
/target/
**/*.rs.bk
Cargo.lock
.env
*.sqlite
*.sqlite-journal
+112
View File
@@ -0,0 +1,112 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Langue de travail
Toutes les discussions, commentaires dans le code, messages de commit et réponses de Claude doivent être **en français uniquement**.
## Project Overview
SentinelMesh is a modular homelab infrastructure monitoring platform (currently in Phase 1 — architecture/bootstrap). It is composed of:
- **backend/** — Central Rust API server (Axum + Tokio + SQLite + OpenAPI)
- **agents/agent-scan-network/** — Rust daemon: network discovery (ICMP, ARP, MAC, services)
- **agents/agent-metric/** — Rust daemon: system metrics collection (CPU/RAM/HDD/GPU/DMI)
- **widgets/widget-network-scan/** — Glance-compatible widget: discovered devices
- **widgets/widget-agent-metrics/** — Glance-compatible widget: system metrics
- **install/** — Automated agent install/update scripts (curl | bash, systemd)
## Architecture Rules
- **Strict separation**: agents collect → backend centralizes → widgets display. Widgets never talk to agents directly.
- **API-first**: every piece of data must be reachable via `/api/v1/`. No data without an endpoint.
- **Agents are standalone**: they expose their own local JSON API and push to the backend, independent of Glance.
- **Glance widgets use `custom-api` type** (or `extension`). Never modify the Glance codebase — it lives in `repo_glance/glance/` as a read-only reference.
- Development order is fixed: backend → agent-scan-network → widget-network-scan → agent-metric → widget-agent-metrics → install system.
## Glance Reference
The Glance dashboard source is cloned locally at `repo_glance/glance/` — consult it for widget conventions, API formats, and template patterns. Never modify it. Glance widget types to use: `custom-api` (preferred), `extension` (WIP, needs separate HTTP server), `iframe` (for full interactive apps).
Example Glance widget config targets:
```yaml
- type: custom-api
title: SentinelMesh Network
cache: 30s
url: http://sentinelmesh/api/v1/widgets/network
- type: custom-api
title: SentinelMesh Metrics
cache: 1s
url: http://sentinelmesh/api/v1/widgets/metrics
```
## Technology Stack
| Layer | Technologies |
|-------|-------------|
| Backend | Rust, Axum, Tokio, Serde JSON, SQLx, SQLite (→ PostgreSQL later) |
| Agents | Rust, Tokio, systemd, JSON, plugin/module architecture |
| Widgets | HTML/JS (minimal vanilla), Glance `custom-api` format |
| API | REST JSON `/api/v1/`, OpenAPI/Swagger mandatory, WebSocket/SSE planned |
| Icons | Heroicons or selfh.st/icons — stored locally, no remote loading |
| Deployment | Docker Compose (MVP), multi-arch: amd64, arm64, Raspberry Pi |
## Build & Dev Commands
Once code exists, standard commands will be:
```bash
# Backend
rtk cargo build # Build
rtk cargo check # Fast type check
rtk cargo clippy # Lint
rtk cargo test # Run all tests
rtk cargo test <test_name> # Run single test
rtk cargo test -- --nocapture # Tests with stdout
# Agents (same pattern, from agent directory)
rtk cargo build --release # Release binary for deployment
```
Always use `rtk` prefix for all shell commands to reduce token consumption.
## Gitea Remote
Project is hosted at: `https://git.maison43gil.com/gilles/SentinelMesh`
User: `gilles` — credentials are in local environment, not in code.
## API Design Principles
- Versioned: all endpoints under `/api/v1/`
- Strict JSON, no optional formats
- OpenAPI spec must be maintained alongside code
- Key endpoints: `/api/v1/agents`, `/api/v1/metrics`, `/api/v1/network`, `/api/v1/events`, `/api/v1/hardware`, `/api/v1/processes`, `/api/v1/install`, `/api/v1/update`
## Agent Architecture
Agents must:
- Self-register with the backend on startup
- Expose a local JSON API
- Support future publish targets: MQTT, WebSocket, Prometheus, InfluxDB, Home Assistant, Grafana, Node-RED
- Be installable via: `curl -fsSL https://gitea.../install.sh | bash --server <url> --port <n> --token <t> --agent-type <type>`
- Run as systemd services
### Metric collection frequencies (agent-metric)
- **1s**: CPU, RAM, GPU, network throughput
- **30min**: HDD usage, SMART, disk temps
- **Boot + 2×/day**: hostname, DMI, CPU model, RAM, GPU info, network interfaces, BIOS, OS version
- **Instant events**: boot, shutdown, sleep, wake, network state change
## Storage
MVP: SQLite via SQLx. Schema must anticipate future migration to PostgreSQL and timeseries DB (InfluxDB). Plan for retention, compression, and aggregation from the start.
## Security Requirements (MVP)
Token-based auth for all API calls, rate limiting, input validation, audit logs. TLS and agent validation planned for later phases.
## Documentation to Maintain
`README.md`, `INSTALL.md`, `API.md`, `ROADMAP.md`, `ARCHITECTURE.md`, `CONTRIBUTING.md`, `CHANGELOG.md`
+15
View File
@@ -0,0 +1,15 @@
[workspace]
resolver = "2"
members = [
"backend",
"agents/agent-scan-network",
"agents/agent-metric",
]
[workspace.dependencies]
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
anyhow = "1"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+65
View File
@@ -0,0 +1,65 @@
# Fonctionnalités SentinelMesh
## Backend central
- [ ] API REST versionnée `/api/v1/`
- [ ] Documentation OpenAPI/Swagger
- [ ] Auto-découverte et enregistrement des agents
- [ ] Stockage SQLite (→ PostgreSQL futur)
- [ ] Auth par token
- [ ] Rate limiting
- [ ] Support futur WebSocket/SSE
## Agent — Découverte réseau (`agent-scan-network`)
- [ ] Scan ICMP (ping sweep)
- [ ] Découverte ARP
- [ ] Détection MAC + OUI (constructeur)
- [ ] Résolution DNS locale
- [ ] Détection services : HTTP, HTTPS, SSH, SMB, NFS, MQTT, Docker, Proxmox, Home Assistant
- [ ] Scan de ports
- [ ] API JSON locale
- [ ] Export vers le backend
- [ ] Mode daemon + systemd
- [ ] Export futur MQTT
## Agent — Métriques système (`agent-metric`)
- [ ] CPU, RAM, GPU, réseau (1s)
- [ ] HDD usage, SMART, températures (30min)
- [ ] DMI, hardware, BIOS, interfaces réseau (boot + 2×/jour)
- [ ] Événements : boot, shutdown, veille, reprise, changement réseau
- [ ] Architecture plugin/modulaire
- [ ] Support futur : Docker, Proxmox, NVIDIA/AMD GPU, Kubernetes
## Widget — Réseau (`widget-network-scan`)
- [ ] Tuile par équipement : nom, IP, type, icône, état, ping, services
- [ ] Popup détaillé : MAC, ports, constructeur, historique, liens rapides
- [ ] Groupement automatique
- [ ] Filtres et tri
- [ ] Favoris
- [ ] Personnalisation par tuile
## Widget — Métriques (`widget-agent-metrics`)
- [ ] Tuile par machine : CPU, RAM, HDD, GPU, température, état
- [ ] Popup : hardware complet, processus top 5, SMART, réseau, liens rapides
- [ ] Historique futur
## Installateur
- [ ] Script `curl | bash` avec paramètres `--server`, `--port`, `--token`, `--agent-type`
- [ ] Création service systemd automatique
- [ ] Enregistrement backend automatique
- [ ] Gestion des mises à jour
- [ ] Multi-architecture : amd64, arm64, Raspberry Pi
## Extensions futures
- [ ] MQTT
- [ ] Prometheus
- [ ] InfluxDB
- [ ] Home Assistant
- [ ] Grafana / Node-RED
- [ ] Multi-dashboard
+49
View File
@@ -0,0 +1,49 @@
# SentinelMesh
Plateforme modulaire de supervision d'infrastructure orientée homelab et self-hosting.
## Composants
| Composant | Description |
|-----------|-------------|
| `backend/` | API centrale Rust (Axum + Tokio + SQLite) |
| `agents/agent-scan-network/` | Daemon Rust de découverte réseau |
| `agents/agent-metric/` | Daemon Rust de collecte de métriques système |
| `widgets/widget-network-scan/` | Widget Glance — équipements réseau |
| `widgets/widget-agent-metrics/` | Widget Glance — métriques système |
| `install/` | Scripts d'installation et de mise à jour |
## Démarrage rapide
```bash
# Lancer le backend (développement)
cd backend && cargo run
# Lancer un agent
cd agents/agent-scan-network && cargo run
# Stack complète
docker compose up -d
```
## Intégration Glance
```yaml
- type: custom-api
title: SentinelMesh — Réseau
cache: 30s
url: http://sentinelmesh:8080/api/v1/widgets/network
- type: custom-api
title: SentinelMesh — Métriques
cache: 1s
url: http://sentinelmesh:8080/api/v1/widgets/metrics
```
## Documentation
- [Architecture](docs/ARCHITECTURE.md)
- [API](docs/API.md)
- [Installation](docs/INSTALL.md)
- [Roadmap](ROADMAP.md)
- [Fonctionnalités](FEATURES.md)
+51
View File
@@ -0,0 +1,51 @@
# Roadmap SentinelMesh
## Phase 1 — Architecture & Backend (en cours)
- [x] Structure du dépôt
- [ ] Workspace Cargo
- [ ] Backend Axum skeleton
- [ ] Base SQLite + migrations
- [ ] Endpoints API v1 de base
- [ ] Documentation OpenAPI
## Phase 2 — Découverte réseau
- [ ] `agent-scan-network` MVP : ICMP, ARP, MAC, OUI, DNS
- [ ] Détection services (HTTP, SSH, SMB…)
- [ ] API JSON locale de l'agent
- [ ] Push vers le backend
- [ ] `widget-network-scan` Glance (tuile + popup)
## Phase 3 — Métriques système
- [ ] `agent-metric` : CPU/RAM/réseau (1s)
- [ ] `agent-metric` : HDD/SMART (30min)
- [ ] `agent-metric` : DMI/hardware (boot)
- [ ] Événements système
- [ ] `widget-agent-metrics` Glance
## Phase 4 — UX & Personnalisation
- [ ] Popups détaillés widgets
- [ ] Filtres, tri, favoris
- [ ] Icônes locales (Heroicons / selfh.st)
- [ ] Personnalisation par équipement
## Phase 5 — Déploiement & Distribution
- [ ] Script d'installation agents
- [ ] Gestion des mises à jour
- [ ] Docker Compose production
- [ ] Build multi-arch (amd64, arm64, Raspberry Pi)
- [ ] CI/CD Gitea
## Phase 6 — Extensions
- [ ] MQTT
- [ ] WebSocket / SSE
- [ ] Historique + agrégation + retention
- [ ] Prometheus / InfluxDB
- [ ] Home Assistant / Grafana
- [ ] Support multi-dashboard
- [ ] PostgreSQL
+13
View File
@@ -0,0 +1,13 @@
[package]
name = "agent-metric"
version = "0.1.0"
edition = "2021"
[dependencies]
tokio = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
anyhow = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
axum = "0.8"
+18
View File
@@ -0,0 +1,18 @@
use tracing::info;
use tracing_subscriber::EnvFilter;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.init();
info!("agent-metric démarré");
// TODO Phase 3 : collecte CPU/RAM/GPU/réseau (1s)
// TODO Phase 3 : collecte HDD/SMART/températures (30min)
// TODO Phase 3 : collecte DMI/hardware/BIOS (boot)
// TODO Phase 3 : événements système
Ok(())
}
+13
View File
@@ -0,0 +1,13 @@
[package]
name = "agent-scan-network"
version = "0.1.0"
edition = "2021"
[dependencies]
tokio = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
anyhow = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
axum = "0.8"
+16
View File
@@ -0,0 +1,16 @@
use tracing::info;
use tracing_subscriber::EnvFilter;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.init();
info!("agent-scan-network démarré");
// TODO Phase 2 : scan ICMP, ARP, MAC/OUI, DNS, détection services
// TODO Phase 2 : API JSON locale + push backend
Ok(())
}
+17
View File
@@ -0,0 +1,17 @@
[package]
name = "sentinelmesh-backend"
version = "0.1.0"
edition = "2021"
[dependencies]
axum = "0.8"
tokio = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
anyhow = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio", "macros", "migrate"] }
tower-http = { version = "0.6", features = ["cors", "trace"] }
utoipa = { version = "4", features = ["axum_extras"] }
utoipa-swagger-ui = { version = "7", features = ["axum"] }
+13
View File
@@ -0,0 +1,13 @@
FROM rust:1.82-alpine AS builder
RUN apk add --no-cache musl-dev
WORKDIR /app
COPY Cargo.toml Cargo.lock* ./
COPY src ./src
RUN cargo build --release
FROM alpine:3.21
RUN apk add --no-cache ca-certificates
WORKDIR /app
COPY --from=builder /app/target/release/sentinelmesh-backend .
EXPOSE 8080
CMD ["./sentinelmesh-backend"]
+24
View File
@@ -0,0 +1,24 @@
use axum::{routing::get, Router};
use tracing::info;
use tracing_subscriber::EnvFilter;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.init();
let app = Router::new().route("/api/v1/health", get(health));
let addr = "0.0.0.0:8080";
info!("SentinelMesh backend démarré sur {addr}");
let listener = tokio::net::TcpListener::bind(addr).await?;
axum::serve(listener, app).await?;
Ok(())
}
async fn health() -> &'static str {
"ok"
}
+14
View File
@@ -0,0 +1,14 @@
services:
backend:
build: ./backend
ports:
- "8080:8080"
volumes:
- sentinelmesh-data:/data
environment:
DATABASE_URL: sqlite:///data/sentinelmesh.sqlite
RUST_LOG: info
restart: unless-stopped
volumes:
sentinelmesh-data:
+62
View File
@@ -0,0 +1,62 @@
# API SentinelMesh
Base URL : `http://<host>:8080/api/v1/`
Toutes les réponses sont en JSON. Auth par token Bearer (header `Authorization: Bearer <token>`).
## Endpoints
### Santé
| Méthode | Endpoint | Description |
|---------|------------------|--------------------|
| GET | `/api/v1/health` | État du backend |
### Agents
| Méthode | Endpoint | Description |
|---------|-----------------------|--------------------------------|
| GET | `/api/v1/agents` | Liste des agents enregistrés |
| POST | `/api/v1/agents` | Enregistrement d'un agent |
| GET | `/api/v1/agents/{id}` | Détail d'un agent |
### Réseau
| Méthode | Endpoint | Description |
|---------|-----------------------|------------------------------------|
| GET | `/api/v1/network` | Équipements découverts |
| POST | `/api/v1/network` | Push scan depuis agent |
| GET | `/api/v1/network/{ip}`| Détail d'un équipement |
### Métriques
| Méthode | Endpoint | Description |
|---------|-----------------------|------------------------------------|
| GET | `/api/v1/metrics` | Métriques de tous les agents |
| POST | `/api/v1/metrics` | Push métriques depuis agent |
| GET | `/api/v1/metrics/{id}`| Métriques d'un agent |
### Widgets (consommés par Glance)
| Méthode | Endpoint | Cache Glance |
|---------|-------------------------------|--------------|
| GET | `/api/v1/widgets/network` | 30s |
| GET | `/api/v1/widgets/metrics` | 1s |
### Événements
| Méthode | Endpoint | Description |
|---------|-----------------------|--------------------------|
| GET | `/api/v1/events` | Journal des événements |
| POST | `/api/v1/events` | Push événement |
### Installation / Mise à jour
| Méthode | Endpoint | Description |
|---------|-----------------------|--------------------------------|
| GET | `/api/v1/install` | Commande d'installation |
| GET | `/api/v1/update` | Commande de mise à jour |
## Documentation interactive
Swagger UI disponible sur : `http://<host>:8080/swagger-ui/`
+41
View File
@@ -0,0 +1,41 @@
# Architecture SentinelMesh
## Vue d'ensemble
```
┌─────────────────────────────────────────────────────────┐
│ Dashboards (Glance…) │
│ widget-network-scan widget-agent-metrics │
└──────────────────────┬──────────────────────────────────┘
│ /api/v1/widgets/*
┌──────────────────────▼──────────────────────────────────┐
│ Backend central (Rust/Axum) │
│ /api/v1/agents /api/v1/metrics /api/v1/network │
│ SQLite (→ PostgreSQL futur) │
└────────────┬────────────────────────┬───────────────────┘
│ push JSON │ push JSON
┌────────────▼────────┐ ┌──────────▼────────────────────┐
│ agent-scan-network │ │ agent-metric │
│ ICMP/ARP/MAC/DNS │ │ CPU/RAM/HDD/GPU/DMI/Events │
│ Détection services │ │ Multi-fréquence │
│ API JSON locale │ │ API JSON locale │
└─────────────────────┘ └───────────────────────────────┘
```
## Principes
- **Séparation stricte** : collecte → centralisation → affichage. Jamais de lien direct widget ↔ agent.
- **API-first** : toute donnée accessible via `/api/v1/`.
- **Agents autonomes** : fonctionnent sans le dashboard, exposent leur propre API locale.
- **Faiblement couplé** : les widgets sont remplaçables par n'importe quel dashboard.
## Flux de données
1. Les agents scannent / collectent en local.
2. Ils poussent les données vers le backend via HTTP JSON.
3. Le backend stocke, agrège et expose via `/api/v1/`.
4. Glance interroge les endpoints widgets (`/api/v1/widgets/*`) à la fréquence de cache configurée.
## Extensions futures
Les agents pourront publier directement vers : MQTT, Prometheus, InfluxDB, Home Assistant, Grafana, Node-RED.
+59
View File
@@ -0,0 +1,59 @@
# Installation SentinelMesh
## Prérequis
- Docker + Docker Compose (recommandé)
- ou Rust >= 1.82 pour une compilation locale
## Docker Compose (recommandé)
```bash
git clone https://git.maison43gil.com/gilles/SentinelMesh.git
cd SentinelMesh
docker compose up -d
```
Le backend est accessible sur `http://localhost:8080`.
## Compilation locale
```bash
# Backend
cd backend && cargo build --release
# Agent découverte réseau
cd agents/agent-scan-network && cargo build --release
# Agent métriques
cd agents/agent-metric && cargo build --release
```
## Installation des agents (Phase 5)
```bash
curl -fsSL http://<backend>/install.sh | bash \
--server http://<backend> \
--token <token> \
--agent-type scan-network
curl -fsSL http://<backend>/install.sh | bash \
--server http://<backend> \
--token <token> \
--agent-type metric
```
## Intégration Glance
Ajouter dans `glance.yml` :
```yaml
- type: custom-api
title: SentinelMesh — Réseau
cache: 30s
url: http://<backend>:8080/api/v1/widgets/network
- type: custom-api
title: SentinelMesh — Métriques
cache: 1s
url: http://<backend>:8080/api/v1/widgets/metrics
```
+15
View File
@@ -0,0 +1,15 @@
# Exemple de widget Glance — Métriques système SentinelMesh
# À intégrer dans votre glance.yml
- type: custom-api
title: Métriques systèmes
cache: 1s
url: http://sentinelmesh:8080/api/v1/widgets/metrics
template: |
{{ range .agents }}
<div class="widget-type-sentinelmesh-metrics">
<h3>{{ .hostname }}</h3>
<div>CPU: {{ .cpu_percent }}%</div>
<div>RAM: {{ .ram_percent }}%</div>
<div>Temp: {{ .temperature_c }}°C</div>
</div>
{{ end }}
+19
View File
@@ -0,0 +1,19 @@
# Exemple de widget Glance — Découverte réseau SentinelMesh
# À intégrer dans votre glance.yml
- type: custom-api
title: Réseau local
cache: 30s
url: http://sentinelmesh:8080/api/v1/widgets/network
template: |
{{ range .sections }}
<div class="widget-type-sentinelmesh-network">
<h3>{{ .name }} — {{ .cidr }}</h3>
{{ range .items }}
<div class="device {{ .state }}">
<span class="hostname">{{ .hostname }}</span>
<span class="ip">{{ .ip }}</span>
<span class="state">{{ .state }}</span>
</div>
{{ end }}
</div>
{{ end }}
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
# Script d'installation des agents SentinelMesh
set -euo pipefail
SERVER=""
PORT="8080"
TOKEN=""
AGENT_TYPE=""
HOSTNAME_OVERRIDE=""
usage() {
echo "Usage: $0 --server <url> --token <token> --agent-type <scan-network|metric> [--port <port>] [--hostname <name>]"
exit 1
}
while [[ $# -gt 0 ]]; do
case "$1" in
--server) SERVER="$2"; shift 2 ;;
--port) PORT="$2"; shift 2 ;;
--token) TOKEN="$2"; shift 2 ;;
--agent-type) AGENT_TYPE="$2"; shift 2 ;;
--hostname) HOSTNAME_OVERRIDE="$2"; shift 2 ;;
*) usage ;;
esac
done
[[ -z "$SERVER" || -z "$TOKEN" || -z "$AGENT_TYPE" ]] && usage
# TODO Phase 5 : téléchargement binaire, création config, enregistrement backend, service systemd
echo "Installation agent-${AGENT_TYPE}${SERVER}:${PORT} (non implémenté — Phase 5)"
+9
View File
@@ -0,0 +1,9 @@
# widget-agent-metrics
Widget Glance affichant les métriques système remontées par les agents.
**Source de données** : `agent-metric` via le backend (`/api/v1/widgets/metrics`)
**Développement** : Phase 4
Voir [exemples/glance-metrics.yaml](../../examples/glance-metrics.yaml) pour la configuration Glance.
+9
View File
@@ -0,0 +1,9 @@
# widget-network-scan
Widget Glance affichant les équipements découverts sur le réseau local.
**Source de données** : `agent-scan-network` via le backend (`/api/v1/widgets/network`)
**Développement** : Phase 2
Voir [exemples/glance-network.yaml](../../examples/glance-network.yaml) pour la configuration Glance.