Initial commit

This commit is contained in:
GuiPoM
2026-06-02 19:55:35 +02:00
commit fd92876381
9 changed files with 879 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
* text=auto
nas-* text eol=lf
+127
View File
@@ -0,0 +1,127 @@
# nas-scripts
Scripts de gestion des mises à jour pour NAS sous OpenMediaVault 8.
## Installation
```bash
cp nas-update-system nas-upgrade-system nas-docker-pull nas-docker-up nas-docker-prune nas-update /usr/local/bin/
chmod +x /usr/local/bin/nas-update-system /usr/local/bin/nas-upgrade-system \
/usr/local/bin/nas-docker-pull /usr/local/bin/nas-docker-up \
/usr/local/bin/nas-docker-prune /usr/local/bin/nas-update
```
## Scripts
### `nas-update`
Script racine interactif. Orchestre toutes les étapes dans l'ordre :
1. Analyse système (apt)
2. Pull et détection des mises à jour Docker
3. Upgrade système (confirmation)
4. Upgrade Docker (tout ou conteneur par conteneur)
5. Nettoyage des images orphelines
```bash
nas-update
```
---
### `nas-update-system`
Vérifie les mises à jour système disponibles via apt. Ne modifie rien.
- Mode terminal : affichage coloré des paquets upgradables
- Mode non-interactif (HA) : output JSON
```bash
nas-update-system
```
```json
{"count":2,"reboot_required":false,"packages":[{"name":"curl","current":"7.88.0","available":"7.88.1"}]}
```
---
### `nas-upgrade-system`
Applique les mises à jour système (`apt full-upgrade`).
- Mode terminal : affiche le bilan + confirmation avant d'appliquer
- Mode non-interactif (HA) : applique directement
```bash
nas-upgrade-system
```
---
### `nas-docker-pull`
Pull toutes les images Docker des conteneurs actifs et détecte les mises à jour disponibles. **Ne recrée pas les conteneurs.**
Idempotent : tant que `nas-docker-up` n'a pas recréé les conteneurs, le check détecte toujours l'écart.
- Mode terminal : affichage coloré
- Mode non-interactif (HA) : output JSON
```bash
nas-docker-pull
```
```json
{"count":1,"containers":[{"name":"jellyfin","image":"jellyfin/jellyfin:latest","compose_dir":"/opt/stacks/jellyfin","current":"10.9.0","available":"disponible"}]}
```
---
### `nas-docker-up`
Recrée les conteneurs sur la nouvelle image via `docker compose up -d --remove-orphans`.
- Sans argument : propose la mise à jour de tous les conteneurs ayant une image plus récente
- Avec argument : cible une stack spécifique
- Mode terminal : confirmation par stack ou tout d'un coup
- Mode non-interactif (HA) : applique directement
```bash
nas-docker-up # toutes les stacks
nas-docker-up jellyfin # stack spécifique
```
---
### `nas-docker-prune`
Nettoie les images Docker orphelines (dangling). À appeler après `nas-docker-up`.
```bash
nas-docker-prune
```
---
## Intégration Home Assistant
Voir `nas-ha-config.yaml` pour la configuration complète.
```yaml
shell_command:
nas_update_system: "ssh -F /config/.ssh/config omv 'sudo nas-update-system'"
nas_upgrade_system: "ssh -F /config/.ssh/config omv 'sudo nas-upgrade-system'"
nas_docker_pull: "ssh -F /config/.ssh/config omv 'sudo nas-docker-pull'"
nas_docker_up: "ssh -F /config/.ssh/config omv 'sudo nas-docker-up'"
nas_docker_up_stack: "ssh -F /config/.ssh/config omv 'sudo nas-docker-up {{ stack }}'"
nas_docker_prune: "ssh -F /config/.ssh/config omv 'sudo nas-docker-prune'"
```
## Flux typique depuis HA
```
nas_docker_pull → détecte les mises à jour dispo (idempotent)
nas_docker_up → applique les mises à jour
nas_docker_prune → nettoie les anciennes images
```
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
# nas-docker-prune — Nettoie les images Docker orphelines (dangling)
# Usage : nas-docker-prune
# À appeler après nas-docker-up pour supprimer les anciennes images remplacées
set -euo pipefail
if [ -t 1 ]; then INTERACTIVE=true; else INTERACTIVE=false; fi
if $INTERACTIVE; then
CYAN='\033[0;36m'
GREEN='\033[0;32m'
BOLD='\033[1m'
RESET='\033[0m'
echo -e "${CYAN}🧹 Nettoyage des images orphelines...${RESET}"
fi
docker image prune -f
if $INTERACTIVE; then
echo -e "${GREEN}✅ Nettoyage terminé.${RESET}"
fi
+90
View File
@@ -0,0 +1,90 @@
#!/bin/bash
# nas-docker-pull — Pull les images Docker et détecte les mises à jour disponibles
# Usage : nas-docker-pull
# Output : JSON (mode non-interactif) ou texte coloré (mode terminal)
# Idempotent : tant que nas-docker-up n'a pas recréé les conteneurs,
# le conteneur tourne sur l'ancien image ID → l'écart est toujours détecté
set -euo pipefail
if [ -t 1 ]; then INTERACTIVE=true; else INTERACTIVE=false; fi
# Couleurs (mode terminal uniquement)
if $INTERACTIVE; then
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
RESET='\033[0m'
else
RED='' GREEN='' YELLOW='' CYAN='' BOLD='' RESET=''
fi
containers_json=""
count=0
if $INTERACTIVE; then
echo -e "${BOLD}--- Vérification des images Docker ---${RESET}"
fi
while IFS=: read -r container_id container_name; do
# Récupérer le compose_dir via le label
compose_dir=$(docker inspect --format='{{index .Config.Labels "com.docker.compose.project.working_dir"}}' "$container_id" 2>/dev/null | xargs)
# Ignorer les conteneurs hors compose
if [ -z "$compose_dir" ] || [ ! -d "$compose_dir" ]; then
continue
fi
image_name=$(docker inspect --format='{{.Config.Image}}' "$container_id")
old_image_id=$(docker inspect --format='{{.Image}}' "$container_id")
old_ver=$(docker inspect --format='{{index .Config.Labels "org.opencontainers.image.version"}}' "$container_id" 2>/dev/null || echo "")
[ -z "$old_ver" ] && old_ver="inconnue"
if $INTERACTIVE; then
echo -ne " Vérification de ${CYAN}${container_name}${RESET}... "
fi
if ! docker pull "$image_name" > /dev/null 2>&1; then
if $INTERACTIVE; then echo -e "${YELLOW}⚠ Erreur de pull (ignoré)${RESET}"; fi
continue
fi
new_image_id=$(docker inspect --format='{{.Id}}' "$image_name" 2>/dev/null)
if [ "$old_image_id" != "$new_image_id" ]; then
new_ver=$(docker inspect --format='{{index .Config.Labels "org.opencontainers.image.version"}}' "$image_name" 2>/dev/null || echo "")
[ -z "$new_ver" ] && new_ver="disponible"
if $INTERACTIVE; then
echo -e "${YELLOW}MAJ DISPONIBLE${RESET} : ${YELLOW}${old_ver}${RESET} → ${GREEN}${new_ver}${RESET}"
fi
entry="{\"name\":\"${container_name}\",\"image\":\"${image_name}\",\"compose_dir\":\"${compose_dir}\",\"current\":\"${old_ver}\",\"available\":\"${new_ver}\"}"
if [ $count -eq 0 ]; then
containers_json="${entry}"
else
containers_json="${containers_json},${entry}"
fi
count=$((count + 1))
else
if $INTERACTIVE; then echo -e "${GREEN}✅ À jour${RESET}"; fi
fi
done < <(docker ps --format "{{.ID}}:{{.Names}}")
# Toujours écrire le JSON dans /tmp pour nas-update
printf '{"count":%d,"containers":[%s]}\n' "$count" "$containers_json" > /tmp/nas-docker-pull.json
if $INTERACTIVE; then
echo ""
echo -e "${BOLD}--- Bilan ---${RESET}"
if [ $count -eq 0 ]; then
echo -e "${GREEN}✅ Tous les conteneurs sont à jour.${RESET}"
else
echo -e "${YELLOW}🐳 ${count} conteneur(s) à mettre à jour.${RESET}"
fi
else
cat /tmp/nas-docker-pull.json
fi
+224
View File
@@ -0,0 +1,224 @@
#!/bin/bash
# nas-docker-up — Applique les mises à jour Docker via docker compose up -d
# Usage : nas-docker-up [stack_name]
# Sans argument : met à jour tous les conteneurs ayant une image plus récente
# Avec argument : met à jour uniquement la stack spécifiée
# Mode HA (non-interactif) : applique directement, pas de prompt
# Mode terminal : confirmation par stack (sauf si stack spécifiée en argument)
set -euo pipefail
if [ -t 1 ]; then INTERACTIVE=true; else INTERACTIVE=false; fi
TARGET_STACK="${1:-}"
# Couleurs (mode terminal uniquement)
if $INTERACTIVE; then
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
RESET='\033[0m'
else
RED='' GREEN='' YELLOW='' CYAN='' BOLD='' RESET=''
fi
# --- Détection de l'env global OMV ---
OMV_GLOBAL_ENV=""
if [ -f "/etc/omv-compose.env" ]; then
OMV_GLOBAL_ENV="/etc/omv-compose.env"
elif [ -f "/srv/omv-compose.env" ]; then
OMV_GLOBAL_ENV="/srv/omv-compose.env"
fi
# --- Collecte des conteneurs à mettre à jour ---
containers_to_update=()
images_to_update=()
compose_dirs=()
container_ids=()
old_versions=()
new_versions=()
if $INTERACTIVE; then
echo -e "${BOLD}--- Phase 1 : Recherche des mises à jour ---${RESET}"
fi
while IFS=: read -r container_id container_name; do
# Filtrer par stack si argument fourni
if [ -n "$TARGET_STACK" ] && [ "$container_name" != "$TARGET_STACK" ]; then
stack_label=$(docker inspect --format='{{index .Config.Labels "com.docker.compose.project"}}' "$container_id" 2>/dev/null | xargs)
if [ "$stack_label" != "$TARGET_STACK" ]; then
continue
fi
fi
compose_dir=$(docker inspect --format='{{index .Config.Labels "com.docker.compose.project.working_dir"}}' "$container_id" 2>/dev/null | xargs)
if [ -z "$compose_dir" ] || [ ! -d "$compose_dir" ]; then
continue
fi
image_name=$(docker inspect --format='{{.Config.Image}}' "$container_id")
old_image_id=$(docker inspect --format='{{.Image}}' "$container_id")
old_ver=$(docker inspect --format='{{index .Config.Labels "org.opencontainers.image.version"}}' "$container_id" 2>/dev/null || echo "")
[ -z "$old_ver" ] && old_ver="inconnue"
if $INTERACTIVE; then
echo -ne " Vérification de ${CYAN}${container_name}${RESET}... "
fi
if ! docker pull "$image_name" > /dev/null 2>&1; then
if $INTERACTIVE; then echo -e "${YELLOW}⚠ Erreur de pull (ignoré)${RESET}"; fi
continue
fi
new_image_id=$(docker inspect --format='{{.Id}}' "$image_name" 2>/dev/null)
if [ "$old_image_id" != "$new_image_id" ]; then
new_ver=$(docker inspect --format='{{index .Config.Labels "org.opencontainers.image.version"}}' "$image_name" 2>/dev/null || echo "")
[ -z "$new_ver" ] && new_ver="disponible"
if $INTERACTIVE; then
echo -e "${YELLOW}MAJ DISPONIBLE${RESET} : ${YELLOW}${old_ver}${RESET} → ${GREEN}${new_ver}${RESET}"
fi
containers_to_update+=("$container_name")
images_to_update+=("$image_name")
compose_dirs+=("$compose_dir")
container_ids+=("$container_id")
old_versions+=("$old_ver")
new_versions+=("$new_ver")
else
if $INTERACTIVE; then echo -e "${GREEN}✅ À jour${RESET}"; fi
fi
done < <(docker ps --format "{{.ID}}:{{.Names}}")
if [ ${#containers_to_update[@]} -eq 0 ]; then
if $INTERACTIVE; then
echo ""
echo -e "${GREEN}✅ Aucun conteneur à mettre à jour.${RESET}"
echo -e "${CYAN}🧹 Nettoyage des images orphelines...${RESET}"
fi
docker image prune -f > /dev/null
exit 0
fi
if $INTERACTIVE; then
echo ""
echo -e "${BOLD}--- Phase 2 : Bilan des mises à jour disponibles ---${RESET}"
for i in "${!containers_to_update[@]}"; do
echo -e " • ${CYAN}${containers_to_update[$i]}${RESET} : ${YELLOW}${old_versions[$i]}${RESET} → ${GREEN}${new_versions[$i]}${RESET}"
done
echo ""
# Si stack spécifique : pas de question sur le mode, on applique directement
if [ -z "$TARGET_STACK" ]; then
UPDATE_ALL=false
while true; do
read -p "Mettre à jour TOUS ces conteneurs ? [y]es (Tout) / [n]o (Choisir par conteneur) : " global_choice
case "$global_choice" in
[yY]*) UPDATE_ALL=true; break ;;
[nN]*) UPDATE_ALL=false; break ;;
*) echo "Veuillez répondre par y ou n." ;;
esac
done
else
UPDATE_ALL=true
fi
fi
# --- Phase 3 : Application ---
if $INTERACTIVE; then
echo ""
echo -e "${BOLD}--- Phase 3 : Application des mises à jour ---${RESET}"
fi
START_DIR=$(pwd)
upgraded=0
failed=0
for i in "${!containers_to_update[@]}"; do
c_name="${containers_to_update[$i]}"
c_dir="${compose_dirs[$i]}"
c_old_ver="${old_versions[$i]}"
c_new_ver="${new_versions[$i]}"
DO_UPDATE=false
if ! $INTERACTIVE; then
# Mode HA : toujours appliquer
DO_UPDATE=true
elif [ "$UPDATE_ALL" = true ]; then
DO_UPDATE=true
else
while true; do
read -p "Mettre à jour '${c_name}' (${c_old_ver} → ${c_new_ver}) ? [y/n] : " choice
case "$choice" in
[yY]*) DO_UPDATE=true; break ;;
[nN]*) DO_UPDATE=false; break ;;
*) echo "Veuillez répondre par y ou n." ;;
esac
done
fi
if [ "$DO_UPDATE" = true ]; then
if $INTERACTIVE; then
echo -e " 🚀 Mise à jour de ${CYAN}${c_name}${RESET} dans ${c_dir}..."
fi
if cd "$c_dir" 2>/dev/null; then
ENV_ARGS=""
# Env global OMV
if [ -n "$OMV_GLOBAL_ENV" ] && [ -f "$OMV_GLOBAL_ENV" ]; then
ENV_ARGS="--env-file $OMV_GLOBAL_ENV"
else
# Fallback : chercher global.env ou .env dans le dossier parent
PARENT_DIR=$(dirname "$c_dir")
if [ -f "$PARENT_DIR/global.env" ]; then
ENV_ARGS="--env-file $PARENT_DIR/global.env"
elif [ -f "$PARENT_DIR/.env" ]; then
ENV_ARGS="--env-file $PARENT_DIR/.env"
fi
fi
# .env local (toujours ajouté s'il existe)
if [ -f ".env" ]; then
ENV_ARGS="$ENV_ARGS --env-file .env"
fi
if docker compose $ENV_ARGS up -d --remove-orphans 2>&1; then
if $INTERACTIVE; then
echo -e " ${GREEN}✅ ${c_name} mis à jour avec succès.${RESET}"
fi
upgraded=$((upgraded + 1))
else
if $INTERACTIVE; then
echo -e " ${RED}❌ Échec de la mise à jour pour ${c_name}.${RESET}"
fi
failed=$((failed + 1))
fi
else
if $INTERACTIVE; then
echo -e " ${RED}❌ Impossible d'accéder à ${c_dir}.${RESET}"
fi
failed=$((failed + 1))
fi
else
if $INTERACTIVE; then
echo -e " ⏭ Mise à jour ignorée pour ${c_name}."
fi
fi
cd "$START_DIR"
done
if $INTERACTIVE; then
echo ""
echo -e "${BOLD}--- Terminé ---${RESET}"
echo -e " ${GREEN}✅ ${upgraded} mis à jour${RESET} ${RED}❌ ${failed} en échec${RESET}"
else
printf '{"upgraded":%d,"failed":%d}\n' "$upgraded" "$failed"
fi
+51
View File
@@ -0,0 +1,51 @@
# configuration.yaml — Home Assistant shell_command pour le NAS
#
# Ajouter dans configuration.yaml :
#
# shell_command:
# nas_update_system: "ssh -F /config/.ssh/config omv 'sudo nas-update-system'"
# nas_upgrade_system: "ssh -F /config/.ssh/config omv 'sudo nas-upgrade-system'"
# nas_docker_pull: "ssh -F /config/.ssh/config omv 'sudo nas-docker-pull'"
# nas_docker_up: "ssh -F /config/.ssh/config omv 'sudo nas-docker-up'"
# nas_docker_up_stack: "ssh -F /config/.ssh/config omv 'sudo nas-docker-up {{ stack }}'"
#
# Exemples d'utilisation depuis un script HA ou une automation :
#
# service: shell_command.nas_update_system
# service: shell_command.nas_upgrade_system
# service: shell_command.nas_docker_pull
# service: shell_command.nas_docker_up
# service: shell_command.nas_docker_up_stack
# data:
# stack: jellyfin
#
# ─────────────────────────────────────────────────────────────────────────────
# Sensor command_line pour exposer le résultat du check système dans HA
# ─────────────────────────────────────────────────────────────────────────────
#
# command_line:
# - sensor:
# name: NAS System Updates
# unique_id: nas_system_updates
# command: "ssh -F /config/.ssh/config omv 'sudo nas-update-system'"
# scan_interval: 3600
# value_template: "{{ value_json.count }}"
# json_attributes:
# - packages
# - reboot_required
#
# - sensor:
# name: NAS Docker Updates
# unique_id: nas_docker_updates
# command: "ssh -F /config/.ssh/config omv 'sudo nas-docker-pull'"
# scan_interval: 3600
# value_template: "{{ value_json.count }}"
# json_attributes:
# - containers
#
# Ces sensors exposent :
# - sensor.nas_system_updates → nombre de paquets apt upgradables
# - sensor.nas_docker_updates → nombre de conteneurs Docker à mettre à jour
# - sensor.nas_system_updates.reboot_required → true/false
# - sensor.nas_system_updates.packages → liste des paquets
# - sensor.nas_docker_updates.containers → liste des conteneurs
+202
View File
@@ -0,0 +1,202 @@
#!/bin/bash
# nas-update — Script racine de gestion des mises à jour NAS
# Orchestre nas-update-system, nas-upgrade-system, nas-docker-pull, nas-docker-up, nas-docker-prune
# Usage : nas-update
set -euo pipefail
# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
RESET='\033[0m'
echo -e "${BOLD}=====================================================${RESET}"
echo -e "${BOLD} NAS — Gestionnaire de mises à jour ${RESET}"
echo -e "${BOLD}=====================================================${RESET}"
echo ""
# ─────────────────────────────────────────────────────
# Phase 1 : Analyse système
# ─────────────────────────────────────────────────────
echo -e "${BOLD}--- Phase 1 : Analyse système (apt) ---${RESET}"
nas-update-system
echo ""
# ─────────────────────────────────────────────────────
# Phase 2 : Analyse Docker (pull + détection diffs)
# ─────────────────────────────────────────────────────
echo -e "${BOLD}--- Phase 2 : Analyse Docker ---${RESET}"
nas-docker-pull
# Lire le JSON écrit par nas-docker-pull
docker_json=$(cat /tmp/nas-docker-pull.json 2>/dev/null || echo '{"count":0,"containers":[]}')
containers_to_update=()
compose_dirs=()
old_versions=()
new_versions=()
while IFS= read -r line; do
name=$(echo "$line" | grep -o '"name":"[^"]*"' | cut -d'"' -f4)
compose_dir=$(echo "$line" | grep -o '"compose_dir":"[^"]*"' | cut -d'"' -f4)
current=$(echo "$line" | grep -o '"current":"[^"]*"' | cut -d'"' -f4)
available=$(echo "$line" | grep -o '"available":"[^"]*"' | cut -d'"' -f4)
[ -z "$name" ] && continue
containers_to_update+=("$name")
compose_dirs+=("$compose_dir")
old_versions+=("$current")
new_versions+=("$available")
done < <(echo "$docker_json" | grep -o '{[^}]*}')
echo ""
# ─────────────────────────────────────────────────────
# Phase 3 : Upgrade système
# ─────────────────────────────────────────────────────
echo -e "${BOLD}--- Phase 3 : Mise à jour système ---${RESET}"
while true; do
read -p "Appliquer apt full-upgrade ? [y/n] : " sys_choice
case "$sys_choice" in
[yY]*)
nas-upgrade-system
break
;;
[nN]*)
echo -e "${YELLOW}⏭ Mise à jour système ignorée.${RESET}"
break
;;
*) echo "Veuillez répondre par y ou n." ;;
esac
done
echo ""
# ─────────────────────────────────────────────────────
# Phase 4 : Upgrade Docker
# ─────────────────────────────────────────────────────
echo -e "${BOLD}--- Phase 4 : Mise à jour Docker ---${RESET}"
if [ ${#containers_to_update[@]} -eq 0 ]; then
echo -e "${GREEN}✅ Aucun conteneur à mettre à jour.${RESET}"
echo ""
echo -e "${BOLD}=====================================================${RESET}"
echo -e "${GREEN} Terminé ! ${RESET}"
echo -e "${BOLD}=====================================================${RESET}"
exit 0
fi
echo ""
echo -e "${BOLD}Bilan des conteneurs à mettre à jour :${RESET}"
for i in "${!containers_to_update[@]}"; do
echo -e " • ${CYAN}${containers_to_update[$i]}${RESET} : ${YELLOW}${old_versions[$i]}${RESET} → ${GREEN}${new_versions[$i]}${RESET}"
done
echo ""
UPDATE_ALL=false
while true; do
read -p "Mettre à jour TOUS ces conteneurs ? [y]es (Tout) / [n]o (Choisir par conteneur) / [s]kip (Ignorer tout) : " docker_choice
case "$docker_choice" in
[yY]*) UPDATE_ALL=true; break ;;
[nN]*) UPDATE_ALL=false; break ;;
[sS]*) echo -e "${YELLOW}⏭ Mise à jour Docker ignorée.${RESET}"; break ;;
*) echo "Veuillez répondre par y, n ou s." ;;
esac
done
if [[ "$docker_choice" =~ ^[sS] ]]; then
echo ""
echo -e "${BOLD}=====================================================${RESET}"
echo -e "${GREEN} Terminé ! ${RESET}"
echo -e "${BOLD}=====================================================${RESET}"
exit 0
fi
# Détection de l'env global OMV
OMV_GLOBAL_ENV=""
if [ -f "/etc/omv-compose.env" ]; then
OMV_GLOBAL_ENV="/etc/omv-compose.env"
elif [ -f "/srv/omv-compose.env" ]; then
OMV_GLOBAL_ENV="/srv/omv-compose.env"
fi
START_DIR=$(pwd)
upgraded=0
failed=0
for i in "${!containers_to_update[@]}"; do
c_name="${containers_to_update[$i]}"
c_dir="${compose_dirs[$i]}"
c_old_ver="${old_versions[$i]}"
c_new_ver="${new_versions[$i]}"
DO_UPDATE=false
if [ "$UPDATE_ALL" = true ]; then
DO_UPDATE=true
else
while true; do
read -p " Mettre à jour '${c_name}' (${c_old_ver} → ${c_new_ver}) ? [y/n] : " choice
case "$choice" in
[yY]*) DO_UPDATE=true; break ;;
[nN]*) DO_UPDATE=false; break ;;
*) echo "Veuillez répondre par y ou n." ;;
esac
done
fi
if [ "$DO_UPDATE" = true ]; then
echo -e " 🚀 Mise à jour de ${CYAN}${c_name}${RESET}..."
if cd "$c_dir" 2>/dev/null; then
ENV_ARGS=""
if [ -n "$OMV_GLOBAL_ENV" ] && [ -f "$OMV_GLOBAL_ENV" ]; then
ENV_ARGS="--env-file $OMV_GLOBAL_ENV"
else
PARENT_DIR=$(dirname "$c_dir")
if [ -f "$PARENT_DIR/global.env" ]; then
ENV_ARGS="--env-file $PARENT_DIR/global.env"
elif [ -f "$PARENT_DIR/.env" ]; then
ENV_ARGS="--env-file $PARENT_DIR/.env"
fi
fi
if [ -f ".env" ]; then
ENV_ARGS="$ENV_ARGS --env-file .env"
fi
if docker compose $ENV_ARGS up -d --remove-orphans 2>&1; then
echo -e " ${GREEN}✅ ${c_name} mis à jour avec succès.${RESET}"
upgraded=$((upgraded + 1))
else
echo -e " ${RED}❌ Échec pour ${c_name}.${RESET}"
failed=$((failed + 1))
fi
else
echo -e " ${RED}❌ Impossible d'accéder à ${c_dir}.${RESET}"
failed=$((failed + 1))
fi
else
echo -e " ⏭ Ignoré : ${c_name}"
fi
cd "$START_DIR"
done
# ─────────────────────────────────────────────────────
# Phase 5 : Nettoyage des images orphelines
# ─────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}--- Phase 5 : Nettoyage ---${RESET}"
nas-docker-prune
echo ""
echo -e "${BOLD}=====================================================${RESET}"
echo -e "${BOLD} Terminé ! ${RESET}"
echo -e " Docker : ${GREEN}✅ ${upgraded} mis à jour${RESET} ${RED}❌ ${failed} en échec${RESET}"
echo -e "${BOLD}=====================================================${RESET}"
+80
View File
@@ -0,0 +1,80 @@
#!/bin/bash
# nas-update-system — Vérifie les mises à jour système disponibles (apt)
# Usage : nas-update-system
# Output : JSON (mode non-interactif) ou texte coloré (mode terminal)
set -euo pipefail
if [ -t 1 ]; then INTERACTIVE=true; else INTERACTIVE=false; fi
# Couleurs (mode terminal uniquement)
if $INTERACTIVE; then
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
RESET='\033[0m'
else
RED='' GREEN='' YELLOW='' CYAN='' BOLD='' RESET=''
fi
if $INTERACTIVE; then
echo -e "${BOLD}--- Mise à jour de la liste des paquets ---${RESET}"
fi
apt-get update -qq 2>/dev/null
# Parser apt list --upgradable
# Format : nom/suite version arch [upgradable from: ancienne_version]
packages_json=""
count=0
while IFS= read -r line; do
# Ignorer la ligne d'avertissement "Listing..."
[[ "$line" =~ ^Listing ]] && continue
[[ -z "$line" ]] && continue
# Extraire le nom (avant le /)
name=$(echo "$line" | cut -d'/' -f1)
# Extraire la version disponible (2ème champ)
available=$(echo "$line" | awk '{print $2}')
# Extraire la version actuelle (après "upgradable from:")
current=$(echo "$line" | grep -oP 'upgradable from: \K[^\]]+' || echo "inconnue")
if $INTERACTIVE; then
echo -e " ${CYAN}${name}${RESET} : ${YELLOW}${current}${RESET} → ${GREEN}${available}${RESET}"
fi
# Construire JSON
entry="{\"name\":\"${name}\",\"current\":\"${current}\",\"available\":\"${available}\"}"
if [ $count -eq 0 ]; then
packages_json="${entry}"
else
packages_json="${packages_json},${entry}"
fi
count=$((count + 1))
done < <(apt list --upgradable 2>/dev/null)
# Vérifier si reboot requis
reboot_required=false
if [ -f /var/run/reboot-required ]; then
reboot_required=true
fi
if $INTERACTIVE; then
echo ""
echo -e "${BOLD}--- Bilan ---${RESET}"
if [ $count -eq 0 ]; then
echo -e "${GREEN}✅ Système à jour.${RESET}"
else
echo -e "${YELLOW}📦 ${count} paquet(s) à mettre à jour.${RESET}"
fi
if $reboot_required; then
echo -e "${RED}⚠️ Redémarrage requis.${RESET}"
fi
else
printf '{"count":%d,"reboot_required":%s,"packages":[%s]}\n' \
"$count" "$reboot_required" "$packages_json"
fi
+81
View File
@@ -0,0 +1,81 @@
#!/bin/bash
# nas-upgrade-system — Applique les mises à jour système (apt full-upgrade)
# Usage : nas-upgrade-system
# Mode HA (non-interactif) : applique directement, output JSON
# Mode terminal : affiche le bilan + confirmation avant d'appliquer
set -euo pipefail
if [ -t 1 ]; then INTERACTIVE=true; else INTERACTIVE=false; fi
# Couleurs (mode terminal uniquement)
if $INTERACTIVE; then
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
RESET='\033[0m'
else
RED='' GREEN='' YELLOW='' CYAN='' BOLD='' RESET=''
fi
# S'assurer que la liste est à jour
if $INTERACTIVE; then
echo -e "${BOLD}--- Mise à jour de la liste des paquets ---${RESET}"
fi
apt-get update -qq 2>/dev/null
# Récupérer les paquets upgradables
upgradable=$(apt list --upgradable 2>/dev/null | grep -v '^Listing' | grep -v '^$')
count=$(echo "$upgradable" | grep -c . || true)
if [ "$count" -eq 0 ]; then
if $INTERACTIVE; then
echo -e "${GREEN}✅ Système déjà à jour, rien à faire.${RESET}"
else
printf '{"status":"already_up_to_date","upgraded":0,"reboot_required":false}\n'
fi
exit 0
fi
if $INTERACTIVE; then
echo ""
echo -e "${BOLD}--- Paquets à mettre à jour (${count}) ---${RESET}"
while IFS= read -r line; do
[[ -z "$line" ]] && continue
name=$(echo "$line" | cut -d'/' -f1)
available=$(echo "$line" | awk '{print $2}')
current=$(echo "$line" | grep -oP 'upgradable from: \K[^\]]+' || echo "inconnue")
echo -e " ${CYAN}${name}${RESET} : ${YELLOW}${current}${RESET} → ${GREEN}${available}${RESET}"
done <<< "$upgradable"
echo ""
read -p "Appliquer la mise à jour de ces ${count} paquet(s) ? [y/n] : " confirm
case "$confirm" in
[yY]*) ;;
*) echo -e "${YELLOW}Annulé.${RESET}"; exit 0 ;;
esac
echo ""
echo -e "${BOLD}--- Application de apt full-upgrade ---${RESET}"
fi
# Appliquer
DEBIAN_FRONTEND=noninteractive apt-get full-upgrade -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" 2>&1
# Vérifier reboot requis
reboot_required=false
if [ -f /var/run/reboot-required ]; then
reboot_required=true
fi
if $INTERACTIVE; then
echo ""
echo -e "${GREEN}✅ Mise à jour terminée.${RESET}"
if $reboot_required; then
echo -e "${RED}⚠️ Redémarrage requis.${RESET}"
fi
else
printf '{"status":"upgraded","upgraded":%d,"reboot_required":%s}\n' \
"$count" "$reboot_required"
fi