diff --git a/.env.example b/.env.example index 19f1dd2..fb07bd1 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,23 @@ +# API_SECRET_KEy sert à sécuriser l'accès à l'API de votre application. API_SECRET_KEY= + +# DISCORD_BOT_TOKEN & DISCORD_CHANNEL_ID pour le bot discord DISCORD_BOT_TOKEN= DISCORD_CHANNEL_ID= + +# BACKUPS_REMOTE_HOST, BACKUPS_REMOTE_ROOT et BACKUPS_MAX_FILES pour la gestion des backups BACKUPS_REMOTE_HOST= BACKUPS_REMOTE_ROOT= BACKUPS_MAX_FILES= + +# DISK_COMMAND_REMOTE et DISK_COMMAND_LOCAL pour les commandes de vérification de l'espace disque DISK_COMMAND_REMOTE= -DISK_COMMAND_LOCAL= \ No newline at end of file +DISK_COMMAND_LOCAL= + +# BACKUP_SCRIPT_COMMAND_BACKUP_BDD_RECETTE, BACKUP_SCRIPT_COMMAND_CHECK_STATUT_RECETTE et BACKUP_SCRIPT_COMMAND_BACKUP_VAULTWARDEN pour les commandes de backup et de vérification des statuts +BACKUP_SCRIPT_COMMAND_BACKUP_BDD_RECETTE= +BACKUP_SCRIPT_COMMAND_CHECK_STATUT_RECETTE= +BACKUP_SCRIPT_COMMAND_BACKUP_VAULTWARDEN= + +# A quelle heure les backups doivent être effectués (format 24h) +BACKUPS_HOUR=19 \ No newline at end of file diff --git a/README.md b/README.md index 98e1014..ad8e5ce 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,14 @@ -# Projet Monitoring +# Supervisor + +`Supervisor` est une application Nuxt qui centralise plusieurs besoins d'exploitation dans une interface web unique : + +- suivi de l'état general d'applications distantes +- consultation de l'espace disque local et distant +- visualisation de métriques système de la machine qui execute l'application +- contrôle et téléchargement de sauvegardes via SSH +- lecture de messages Discord depuis un canal configure + +Le nom du package npm visible dans le depot est `disk-monitor`, mais l'interface et la structure du projet exposent clairement le nom `Supervisor`. ## Installation du projet @@ -15,79 +25,105 @@ https://wiki.malio.fr/bookstack/books/environnement-de-dev/chapter/linux ### Installation du projet Une fois les prérequis installés, cloner le dépôt puis installer les dépendances. +Les étapes ci-dessous sont celles qui sont réellement supportées par le depot. + +### 1. Cloner le depot + +```bash +git clone gitea@gitea.malio.fr:MALIO-DEV/Supervisor.git +cd Supervisor +``` + +### 2. Preparer le fichier d'environnement + +Le depot fournit un exemple dans `.env.example`. + +```bash +cp .env.example .env +``` + +### 3. Renseigner les variables necessaires + +#### Generation d'une valeur pour `API_SECRET_KEY` + +Le depot impose la presence d'un secret, mais ne fournit pas de commande officielle pour le générer. + +Exemple de commande compatible : + +```bash +openssl rand -hex 32 +``` +Cette commande sert simplement à produire une valeur aléatoire facile à placer dans `.env`. + +Les variables visibles dans le depot sont : + +- `API_SECRET_KEY` : secret attendu par le middleware d'authentification pour toutes les routes `/api/*` sauf `/api/ping` +- `DISCORD_BOT_TOKEN` : token du bot utilise par endpoint Discord +- `DISCORD_CHANNEL_ID` : identifiant du canal Discord a lire +- `BACKUPS_REMOTE_HOST` : hôte SSH cible pour les operations distantes +- `BACKUPS_REMOTE_ROOT` : dossier racine des sauvegardes sur l'hôte distant +- `BACKUPS_MAX_FILES` : nombre maximal de fichiers retournés par dossier de backup +- `DISK_COMMAND_REMOTE` : commande shell utilisée pour la verification disque distante +- `DISK_COMMAND_LOCAL` : commande shell utilisée pour la verification disque locale +- `BACKUP_SCRIPT_COMMAND_BACKUP_BDD_RECETTE` : commande a exécuter pour le script "Backup BDD recette" +- `BACKUP_SCRIPT_COMMAND_CHECK_STATUT_RECETTE` : commande à exécuter pour le script "Check statut recette" +- `BACKUP_SCRIPT_COMMAND_BACKUP_VAULTWARDEN` : commande à exécuter pour le script "Backup vault warden" +- `BACKUPS_HOUR` : heure attendue des sauvegardes pour le contrôle de fraicheur + +### 4. Installer les dépendances + ```bash npm install ``` -Lancer ensuite le serveur de développement. +### 5. Lancer le serveur de développement ```bash npm run dev ``` -L’application sera accessible sur : -http://localhost:3000 +Par défaut, l'application Nuxt sera accessible sûr . -Si une erreur liée à la version de Node apparaît, vérifier que Node ≥ 20 est utilisé via nvm. +## Configuration necessaire -nvm install 20 -nvm use 20 +### Authentification API -## Utilisation du projet -### Frontend +Le middleware `server/middleware/auth.ts` protege toutes les routes `/api/*`, sauf `/api/ping`. -Lancer le serveur de développement. -``` -npm run dev -``` -Compilation pour la production. -``` -npm run build -``` -Prévisualisation du build de production. -``` -npm run preview -``` +Consequence visible : + +- si `API_SECRET_KEY` est vide, les appels API sont refusés avec `401 Unauthorized` +- l'application web pose aussi un cookie HTTP-only via `server/middleware/auth-cookie.ts` pour réutiliser ce secret coté navigateur + +### SSH pour les backups + +Les fonctionnalités de backup utilisent `ssh` avec les options `BatchMode=yes` et `ConnectTimeout=5` dans `server/utils/ssh.ts`. Cela implique un accès sans saisie interactive de mot de passe. + +Elements a preparer cote SSH : + +- une cle privée disponible sur la machine qui execute `Supervisor` +- une clé ssh pour les différentes machines cibles, si necessaire pour les différents usages (backup BDD, backup Vault warden, check statut recette) + +Le depot ne fixe pas de noms de fichiers de clés SSH ni de chemin obligatoire. Les noms exacts ne sont donc pas vérifiables dans le code. ## Commandes utiles -Installation des dépendances. -``` -npm install -``` -Lancer le serveur de développement. -``` +Commandes déclarées dans `package.json` : + +```bash npm run dev -``` -Build de production. -``` npm run build -``` -Prévisualisation du build. -``` +npm run generate npm run preview +npm run lint +npm run lint:fix ``` -Supprimer les dépendances et réinstaller proprement. -``` -rm -rf node_modules package-lock.json -npm install -Déploiement -``` -Construire l’application. -``` -npm run build -``` -Les fichiers générés se trouvent dans : -.output/ -Le serveur peut ensuite être lancé avec : -``` -node .output/server/index.mjs -``` -Il est recommandé d’utiliser un reverse proxy comme Nginx en production. +Usage : -### Notes - -Les accès SSH ou les chemins système utilisés par les endpoints doivent rester côté serveur. -Ne jamais exposer de credentials dans le frontend. -Les variables sensibles doivent être stockées dans un fichier .env. \ No newline at end of file +- `npm run dev` : lance l'application en développement +- `npm run build` : construit l'application pour la production +- `npm run generate` : généré une sortie statique si ce mode est compatible avec votre usage +- `npm run preview` : prévisualisé le build Nuxt +- `npm run lint` : execute ESLint +- `npm run lint:fix` : applique les corrections ESLint automatiques : collecte périodique CPU, mémoire et réseau \ No newline at end of file diff --git a/assets/css/main.css b/assets/css/main.css index 1a04409..d7aaddf 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -34,12 +34,35 @@ min-height: 100vh; font-family: var(--font-display); background: rgb(var(--m-bg)); + background-image: + radial-gradient(circle at top left, rgb(var(--m-accent) / 0.1), transparent 24%), + radial-gradient(circle at top right, rgb(var(--m-success) / 0.08), transparent 18%); color: rgb(var(--m-text)); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; transition: background-color 0.4s ease, color 0.4s ease; } + ::selection { + background: rgb(var(--m-accent) / 0.28); + color: rgb(var(--m-text)); + } + + a, + button { + transition: + color 0.2s ease, + background-color 0.2s ease, + border-color 0.2s ease, + box-shadow 0.2s ease, + transform 0.2s ease; + } + + :focus-visible { + outline: 2px solid rgb(var(--m-accent) / 0.85); + outline-offset: 2px; + } + img { display: block; } @@ -75,6 +98,13 @@ transition: box-shadow 0.3s ease; } + .card-glow:hover { + box-shadow: + 0 0 0 1px rgb(var(--m-accent) / calc(var(--m-card-border-opacity) + 0.04)), + 0 10px 30px -10px rgba(0, 0, 0, calc(var(--m-shadow-opacity) + 0.08)), + 0 0 56px -14px rgb(var(--m-accent) / 0.1); + } + .card-glow-success { box-shadow: 0 0 0 1px rgb(var(--m-success) / 0.15), @@ -165,3 +195,14 @@ ::-webkit-scrollbar-thumb:hover { background: rgb(var(--m-muted)); } + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} diff --git a/components/BackupRun.vue b/components/BackupRun.vue index 0243eaa..639dce8 100644 --- a/components/BackupRun.vue +++ b/components/BackupRun.vue @@ -187,8 +187,7 @@ const runScript = async (key: string) => { ? error.data.statusMessage : null - message.value = statusMessage || "Erreur lors de l'opération" - message.value = error?.data?.statusMessage || "Erreur execution script" + message.value = statusMessage || "Erreur execution script" output.value = "" emit("result", { key, diff --git a/components/MessageDiscord.vue b/components/MessageDiscord.vue index 7f17a83..3767056 100644 --- a/components/MessageDiscord.vue +++ b/components/MessageDiscord.vue @@ -56,12 +56,15 @@ const { data: messages, error } = await useFetch('/api/discord/messages', { diff --git a/components/Speed-test.vue b/components/Speed-test.vue index c0243d4..0848ae4 100644 --- a/components/Speed-test.vue +++ b/components/Speed-test.vue @@ -118,10 +118,13 @@ async function runTests() { diff --git a/components/StatusBackup.vue b/components/StatusBackup.vue new file mode 100644 index 0000000..c2f9140 --- /dev/null +++ b/components/StatusBackup.vue @@ -0,0 +1,224 @@ + + + + + diff --git a/components/StatusSite.vue b/components/StatusSite.vue index 9e3b883..1616b83 100644 --- a/components/StatusSite.vue +++ b/components/StatusSite.vue @@ -1,7 +1,7 @@