Migration HAOS vers Home Assistant Docker

J’ai débuté sur Home Assistant OS (HAOS) puis j’ai migré vers la solution Home Assistant Docker pour pouvoir exploiter la pleine puissance de mon raspberry Pi 5.
Ayant atteint un niveau de complétude satisfaisant, je souhaite partager avec vous le fruit de mon travail. L’objectif n’est pas de débattre sur ce qui est bien ou pas bien, seulement de regrouper en un seul endroit une solution compléte.

Pour installer Home Assistant disons qu’il y a 3 types d’installation :

  1. Home Assistant vers HAOS
    Home Assistant installé via son propre système d’exploitation
    Avantage : Solution all-inclusive, facile a déployer, compléte, ergonomique, bref du bon boulot de la part de Nabu Casa.
    Inconvénient : Le système est un peu fermé et on ne peut pas faire plusieurs choses en meme temps avec son Raspberry comme l’utiliser en tant qu’ordinateur de bureau.

  2. Home Assistant version HAOS installé sur machine virtuelle
    Une machine virtuelle type Proxmox permet de faire croire à HAOS et tout seul.
    [Article] Installer Home Assistant OS avec Proxmox (VM)
    Avantage : On profite de toute la puissance de HAOS tout en pouvant faire autre chose de son Raspberry en même temps comme un ordinateur de bureau.
    Inconvénient : Je ne sais pas, je l’ai pas fait :stuck_out_tongue:

  3. Home Assistant version Docker
    Home Assistant core tourne dans un conteneur type docker (un peu comme fait HAOS) sauf qu’on garde la main sur le système d’exploitation.
    Avantage : On fait faire a peu prés tout se que l’on veut avec son Raspberry
    Inconvénient : Rien n’est intégré, il faut tout gérer soit même. Pour ceux qui veulent découvrir linux c’est un bon exercice ^^

Donc vous l’aurez compris, je m’interesse à la migraration de 1 vers 3 en conservant l’intégralité de mes automatisations et fonctionnalités initiales mais je ne vais pas forcément faire la publicité pour ce choix.

Situation de départ :
Raspberry Pi 5 avec Dongle Zigbee Sononf 3.0+ et carte SSD.
Installation de Home Assistant OS (aujourd’hui 2025.12.3) avec les add-ons suivants :
MQTT Mosquitto, Zigbee2MQTT, Let’sEncrypt, DuckDNS, FileEditor et Backup to Google Drive

Situation d’arrivée :
Raspberry Pi 5 avec Carte d’extension bottom M2 Seeed Studio + Disque NVMe + ventilateur Ice Tower cooler+ et dongle Zigbee Sononf 3.0+
Systeme d’exploitation : Debian bookworm 12.12 + docker (1.52)
Logiciels : Portainer, DuckDns, LetEncrypt, Mosquitto MQTT, Zigbee2MQTT, Watchtower, MQTT Explorer (falcutatif)
Avec pas mal de sueur, patience et huile de coude, on arrive a obtenir un environnement équivalent (sauf qu’on ne peut pas rebooter le raspberry depuis Home Assistant ^^)

J’ai découpé mon tuto en différents sujets:

Etape 1 : Réaliser ses backup sous Home Asisstant

Je vous recommande vivement d’installer l’add-on Backup Google Drive pour enregistrer votre backup sur le cloud, surtout si votre HAOS tourne sur SSD. Les cartes SSD ne sont pas réputées pour leur fiabilité.
Suivez ce tuto très bien fait :

Lancer un Full Backup en incluant les adds-ons puis garder sur le cloud dans un endroit precis cette sauvegarde + Télécharger le kit de secours!
NB: Si vous utilisez Zigbee2Mqtt, les identifiants des appareils linkés seront enregistrés dans le Full Backup.

Etape 2: Configurer sa box Router

Commencez par configurer votre box/router pour ouvrir les ports et rediriger les requêtes vers le raspberry.
Commencons pas fixer l’adresse IP du Raspberry sur le réseau local.


Connectez vous sur votre box locale
Généralement il faut se connecter sur l’adresse http://192.168.1.1 depuis un navigateur.
En cas de doute, vous pouvez vérifier l’adresse gateway avec cette commande dans un terminal (ou regarder les propriétés du réseau sur le desktop):

nmcli -p device show

Nb: Sur Free, tout se passe sur le site internet Free de votre espace client.

Pour moi, j’ai le Raspberry en ETHernet sur l’IP 192.168.1.73 (et aussi en Wifi sur l’IP192.168.1.74 mais c’est redondant). Donc ajoutez le en statique. Menu IPV4/DHCP

Ensuite la redirection des ports : Menu IPV4/NAT


Il faut ouvrir :

  • 80 pour les réquetes HTTP (et la création des certificats TLS)
  • 443 pour les réquetes HTTPS
  • 22 pour les connections SSH (terminal à distance)
  • 8123 pour se connecter à Home Assistant
  • 9443 pour se connecter à Portainer
  • 3218 si vous souhaitez utiliser FileEditor hors du réseau local (attention comporte qq risques, voir FileEditor)
  • 8080 pour accéder au Frontend Zigbee2MQTT depuis l’extérieur
  • 1883 si vous avez des périphériques MQTT dans votre maison de campagne ^^
  • 5572 pour accéder au Frontend de Rclone (up to you)

Nb: Moi j’ai qq redirections supplémentaires pour accéder aux fonctions importantes via Wifi lorsque mon cable Ethernet est débranché, mais à priori vous en aurez pas l’utilité.

Etape 3 : Installation de Duckdns

Allez sur le site https://www.duckdns.org/

Se creer un compte.
Creer un domain puis enregistrer son adresse IP.

Pour la suite mon domain sera toto.duckdns.org à remplacer par votre nom de domain.

Notez qq part le n° de token généré.


Etape 4 : Installer Let’s Encrypt

On démarre dans le dur, pour moi c’est l’étape la plus compliquée.

Lets Encrypt permet d’obtenir des certificats SSL/TLS afin d’utiliser Home Assistant en https.

A savoir: si Home Assistant est configuré en Https, toutes les integrations dans l’interface graphique via des Iframes doivent être en https également.

Lets Encrypt s’installe a travers Certbot

Mais avant cela, il faut installer un petit serveur web : NGinx
Tuto très facile à suivre :

Dans une console taper les instructions suivantes :

sudo apt update -y
sudo apt install nginx -y
sudo systemctl enable nginx


Ensuite, pour installer Certbot, je propose de suivre les instructions pour Nginx et Linux PIP.
Sources :

Installer python :

sudo apt install python3 python3-dev python3-venv libaugeas-dev gcc

Creer un environnement python

sudo python3 -m venv /opt/certbot/
sudo /opt/certbot/bin/pip install --upgrade pip

Installer Certbot

sudo /opt/certbot/bin/pip install certbot certbot-nginx

Creer un lien symbolique pour garantir que Certbot sera accessible partout

sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot

Laisser Certbot configurer NGinx pour activer le https:

sudo certbot --nginx

Suivez ce petit guide pour la configuration de Certbot:

Il va demander qq info dont le nom du domain créé précédement avec Duckdns.


Ajouter une plannification de tache pour vérifier les certificats (tous le 1er du mois à minuit):

echo "0 0 1 * * root /opt/certbot/bin/python -c 'import random; import time; time.sleep(random.random() * 3600)' && sudo certbot renew -q" | sudo tee -a /etc/crontab > /dev/null

Commande à lancer tous les mois pour verifier que certbot est à jour (ou ajouter une ligne dans votre crontab comme au dessus : sudo nano /etc/crontab) :

sudo /opt/certbot/bin/python3 -m pip install --upgrade pip

Etape 5 : Installation de Docker

Source:

ou


Prérequis (mise à jour et qq fonctions indispensables):
cd /
apt update && apt upgrade
apt install curl gpg

Récupérez la clée GPG officielle pour garantir la provenance de l'appli:
mkdir -m 0755 -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg

Ajouter Docker aux sources-list du gestionnaire de packet APT
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null

Ca revient à écrire deb [arch=arm64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable dans le fichier /etc/apt/sources.list.d/docker.list


Mise à jour de APT et installation:
apt update
apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

QQ manip pour assurer que Docker soit lancé et activer le redémarrage automatique de Docker à l’allumage

sudo systemctl start docker
sudo systemctl enable docker

Vérifiez que Docker fonctionne :
docker run hello-world

message déplacé plus haut

Etape 6: Installation de Portainer

Source :


Je vous propose de créer un répertoire scripts dans votre Home puis un répertoire portainer dans celui ci. Donc avec un terminal ou sous le Desktop :

cd ~/
mkdir scripts
cd scripts/
mkdir portainer
cd portainer/

Puis dans ~/scripts/portainer créer un fichier portainer-compose.yaml

nano portainer-compose.yaml

Et coller cette description :

services:
  portainer:
    container_name: portainer
    image: portainer/portainer-ce:lts
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
      - /etc/localtime:/etc/localtime:ro # pour synchroniser l'heure avec l'hôte
      - /etc/letsencrypt:/etc/letsencrypt:ro
    ports:
      - 9443:9443
      #- 8000:8000  # Remove if you do not intend to use Edge Agents
    environment:
      - CSP=false #pour autoriser l'affichage dans un iframe dans HA
    command:
       --tlscert /etc/letsencrypt/live/toto.duckdns.org/fullchain.pem
       --tlskey /etc/letsencrypt/live/toto.duckdns.org/privkey.pem

volumes:
  portainer_data:
    name: portainer_data
    external: true

networks:
  default:
    name: portainer_network

Maintenant nous allons faire un petit script pour installer (ou mettre à jour) Portainer.
Le script s’appelera install_portainer.sh

touch install_portainer.sh       # cree le fichier
chmod +x install_portainer.sh    # le rend executable
nano install_portainer.sh        # ouvre l'editeur

et coller ce petit script :

#!/bin/bash
echo "Mon installateur portainer"
docker pull portainer/portainer-ce:lts

docker stop portainer
docker rm portainer
docker compose -f portainer-compose.yaml up -d
sleep 2s
docker logs portainer
echo "Portainer mis a jour!"

Plus qu’à l’executer :

./install_portainer.sh

Si les certificats sont OK, Portainer écoutera l’adresse en HTTPS, sinon il sera acessbile en HTTP.


Connectez vous avec un navigateur à Portainer en allant sur https://172.18.0.2:9443 pour un acces local ou https://toto.duckdns.org:9443 pour un acces depuis Internet.

Il faut se créer un compte (login+mdp) et créer un nouvel environnement local.
Pour la suite on va ajouter des stacks qui vont permettre de créer des conteners

Etape 7: Installation de Mosquitto MQTT

Source:


Dans Portainer, créer un nouveau stack, donner lui le nom de mqtt par exemple et dans l’éditeur coller ce compose.yaml :

services:
  mosquitto:
    image: eclipse-mosquitto
    container_name: mqtt
    restart: always
    volumes:
      - config:/mosquitto/config
      - data:/mosquitto/data
      - log:/mosquitto/log
    ports:
      - 1883:1883 # adresse pour les requetes MQTT
      - 9001:9001 # adresse pour les requêtes socket
    networks:
      mon_reseau:
        ipv4_address: 172.20.0.10
      
volumes:
  config:
  data:
  log:

networks:
  mon_reseau:
    name: reseau_mqtt
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.20.0.0/24
          gateway: 172.20.0.254

Finir par l’action deployer


Passons à la configuration.

Rentrer en mode SSH dans le container pour creer un compte toto/mdp

docker exec -it mqtt sh


Puis creer le compte :

mosquitto_passwd -c mosquitto/config/mqtt_passwd TOTO

exit #pour sortir une fois le compte cree

Ensuite editez le fichier mosquitto.conf dans le répertoire mqtt_config, pour connaitre le chemin exacte tapez (vous pouvez aussi passer par FileEditor, voir plus bas) :

docker volume inspect mqtt_config
sudo ls /var/lib/docker/volumes/mqtt_config/_data -lh
sudo nano /var/lib/docker/volumes/mqtt_config/_data/mosquitto.conf 


et ajouter les lignes suivantes au fichier :

listener 1883
listener 9001
protocol websockets
persistence true
persistence_location /mosquitto/data
allow_anonymous false
password_file mosquitto/config/mqtt_passwd

Relancer le container

docker restart mqtt

Et voila, votre Broker MQTT est normalement opérationnel. Vous pouvez le tester avec MQTT Explorer, voir ci dessous.

Etape 8: Installation de Zigbee2MQTT

Source:

Pour utilisation avec un Dongle Zigbee sur port USB :

sudo ls -l /dev/serial/by-id

20251220_13h10m04s_grim

Il faut recopier la partie usb-Itead…-if00-port0 dans la pile ci-dessous.

Creer un nouveau stack zigbee2mqtt ainsi :

services:
  zigbee2mqtt:
    container_name: zigbee2mqtt
    image: ghcr.io/koenkk/zigbee2mqtt
    restart: always
    volumes:
      - /opt/docker/zigbee2mqtt:/app/data
      - /run/udev:/run/udev:ro         # donne accès en lecture au gestionnaire de périphériques
      - /etc/letsencrypt:/etc/letsencrypt:ro
    ports:
      - 8080:8080   # Port pour le frontend
    environment:
      - TZ=Europe/Paris
    devices:
      - /dev/serial/by-id/usb-Itead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_V2_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx-if00-port0:/dev/ttyUSB0
    networks:
      reseau_mqtt:
        ipv4_address: 172.20.0.2

networks:
  reseau_mqtt:
    external: true

Maintenant cliquer sur « Deploy the stack » pour installer Zigbee2mqtt sur docker.

A ce stade il faut arreter le conteneur Zigbee2MQTT et passer à l’installation de Home Assistant (étape 10) avant de poursuivre.

Une fois HomeAssistant installé, reprenons la configuration de Zigbee2MQTT.


Configuration de Zigbee2mqtt sur docker :

Connectez vous à nouveau en SSH sur votre serveur puis aller dans votre dossier Zigbee2mqtt /opt/docker/zigbee2mqtt et éditer le fichier configuration.yaml
Si vous avez configurer FileEditor (étape 9), ça peut être fait depuis ce dernier.

cd /opt/docker/zigbee2mqtt
sudo nano configuration.yaml

et recopier ces lignes au debut du fichier :

homeassistant:
  enabled: true
mqtt:
  base_topic: zigbee2mqtt
  server: mqtt://172.20.0.10:1883
  user: login_de_MQTT
  password: mdp_de_MQTT
serial:
  port: /dev/ttyUSB0
  adapter: ember
frontend:
  enabled: true
  package: zigbee2mqtt-frontend
  port: 8080
  host: 172.20.0.2
  auth_token: '!secret.yaml auth_token'
  url: 'https://toto.duckdns.org:8080'
  ssl_cert: /etc/letsencrypt/live/toto.duckdns.org/fullchain.pem
  ssl_key: /etc/letsencrypt/live/toto.duckdns.org/privkey.pem
  base_url: /
  notification_filter:
    - 'z2m: Failed to ping.*'
  disable_ui_serving: false

Pensez à corriger avec vos identififants du broker Mosquitto MQTT et mettre votre nom de DNS.

La ligne auth_token: '!secret.yaml auth_token' fait référence à un mot de passe enregistré dans un fichier secret.yaml dans le meme répertoire que configuration.yaml.
Dans ce fichier, il y a une ligne par paramètre secret. Dans le mien j’ai mis simplement :

auth_token: mot_de_passe_admin_de_Zigbee

Ce mot de passe est demandé à l’ouverture du frontend de Zigbee2MQTT.


C'est terminé pour Zigbee2MQTT. Si le conteneur était arrété, pensez à le relancer. Vous pouvez vous connecter au Frontend à cette adresse : `https://172.20.0.2:8080`

Bonus
Personnelement j’ai un bug sur mon dongle: quand je le touche, il se déconnecte et arrête Zigbee2Mqtt avec le message exit code 2 et Docker ne le relance pas malgrès la politique restart: always
Mon contournement : créer un script qui vérifie toute les minutes si Zigbee2Mqtt est toujours actif, sinon le rédemarre.
Pour cela je créé un script relunch_zigbee.sh dans mon répertoire scripts

touch relunch_zigbee.sh       # cree le fichier
chmod +x relunch_zigbee.sh    # le rend executable
nano relunch_zigbee.sh        # ouvre l'editeur

Voici le script :

#!/bin/bash

MY_DOCK=zigbee2mqtt

if [ $(docker ps 2>&1 | grep -c "${MY_DOCK}") -eq 1 ]
then 
	echo "Docker ${MY_DOCK} is running"
	exit 0
fi

echo "Docker ${MY_DOCK} is stopped..."

#relance le docker
docker start ${MY_DOCK}
#docker logs ${MY_DOCK} --follow --tail 5

#envoi une notification par email
docker run --rm nickfedor/shoutrrr:latest send --message "Docker ${MY_DOCK} has been relunched!"  --url "smtp://login:mdp@smtp.free.fr:587/?fromaddress=email@free.fr&toaddresses=email@gmail.com&encryption=ExplicitTLS&usestarttls=yes&timeout=30s"

exit 0

Penser à remplacer login/mdp et email pour vos identifiants free par exemple.

Pour que ce script soit executé toutes les minutes, il faut l’ajouter au planificateur de tache cron:

crontab -e

et ajouter cette ligne au cron :

* * * * * /home/user/scripts/relunch_zigbee.sh >/dev/null

user à remplacer par votre nom d’utilisateur sur le raspberry.

Etape 9: Installation de File Editor aussi appelé HAAS configurator

FileEditor est un éditeur de text/script particuliere agréable a utiliser pour Home Assistant.
On peut ajouter des montages sous Docker pour accéder à la majorité de notre fichier de configuration.

Créer un nouveau stack fileeditor ainsi:

services:
  fileeditor:
    container_name: file_editor
    image: "causticlab/hass-configurator-docker:latest"
    restart: unless-stopped
    ports:
      - "3218:3218/tcp"
    volumes:
      - /opt/docker/hass-configurator/config:/config  # fichier de configuration de FileEdit
      - /opt/docker/ha/config:/hass-config  # pour accéder à HA
      - /opt/docker/zigbee2mqtt:/hass-config/zigbee2mqtt # pour acceder à Zigbee2MQTT
      - /home/USER/scripts:/hass-config/scripts # pour acceder aux scripts dans Home
      - /var/lib/docker/volumes/mqtt_config/_data:/hass-config/mqtt # pour acceder à MQTT
      - /etc/letsencrypt:/etc/letsencrypt:ro
    environment:
      - HC_BASEPATH=/hass-config
      - HC_ENFORCE_BASEPATH=true
      - HC_DIRSFIRST=true
      - HC_SSL_CERTIFICATE=/etc/letsencrypt/live/toto.duckdns.org/fullchain.pem
      - HC_SSL_KEY=/etc/letsencrypt/live/toto.duckdns.org/privkey.pem
      - HC_HASS_API=https://172.20.0.1:8123/api/
      - HC_HASS_API_PASSWORD=token_from_HA
      - HC_USERNAME=Login_de_file_editor
      - HC_PASSWORD=Un_mot_de_passe
    networks:
      reseau_mqtt:
        ipv4_address: 172.20.0.12

networks:
  reseau_mqtt:
    external: true

Alors il faut remplacer USER par votre nom d’utilisateur sur Raspberry, remplacer toto par votre DNS et choisir un couple login/mdp pour l’auhentification HTTP.

Attention à bien mettre un nom d’utilisateur/mot de passe suffisament fort, surtout si vous ouvrez le port 3218 de votre router car toute votre configuration HomeAssistant sera accessible depuis Internet!


Le HASS_API_PASSWORD s’obtient dans HomeAssistant en créant un token dans son profil/sécurité :

Etape 10: Installation de HomeAssistant

Enfin, on arrive au moment tant attendu.
Voici le stack tant attendu :slight_smile: donc nouveau stack homeassistant :

services:
  homeassistant:
    image: homeassistant/home-assistant:stable
    container_name: homeassistant
    restart: always
    environment:
      - TZ=Europe/Paris
    ports:
      - 8123:8123
    volumes:
      - /opt/docker/ha/config:/config
      - /etc/localtime:/etc/localtime:ro
      - /opt/docker/zigbee2mqtt:/config/zigbee2mqtt # pour ajouter Zigbee2mqtt aux backup
      - /etc/letsencrypt:/etc/letsencrypt:ro
      - /etc/letsencrypt/live/toto.duckdns.org/:/ssl:ro # pas sur de l'utilite...
    labels:
      com.centurylinklabs.watchtower.lifecycle.pre-update: sh /config/generate_backup.sh >>/config/watchtower.log
      com.centurylinklabs.watchtower.lifecycle.pre-update-timeout: 100
    networks:
      reseau_mqtt:
        ipv4_address: 172.20.0.1

networks:
  reseau_mqtt:
    external: true

La partie labels est liée à Watchtower pour les mises à jour automatiques. Voir plus loin.
Remplacer toto par votre DNS comme d’hab.


Configuration de HomeAssistant
Ouvrir le fichier /opt/docker/ha/config/configuration.yaml
Soit avec FileEditor, soit dans un terminal :

cd /opt/docker/ha/config
sudo nano configuration.yaml

et renseigner le fichier ansi :

# Loads default set of integrations. Do not remove.
default_config:

http:
  server_port: 8123
  ssl_certificate: /etc/letsencrypt/live/toto.duckdns.org/fullchain.pem
  ssl_key: /etc/letsencrypt/live/toto.duckdns.org/privkey.pem
  use_x_forwarded_for: true
  trusted_proxies:
    - 192.168.1.1
  ip_ban_enabled: True
  login_attempts_threshold: 10

# Load frontend themes from the themes folder
frontend:
  themes: !include_dir_merge_named themes

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

Remplacer toto par votre DNS.


Restauration de votre sauvegarde Home Assistant.
Si vous avez déjà installé Zigbee2MQTT, pensez à l’arréter avant de restaurer la sauvegarde car il va écraser votre base de donnée pour rétablir les link déjà créé.

Allez dans Home Assistant à l’adresse https://172.20.0.1:8123 (ou depuis Internet https://toto.duckdns.org:8123)
Puis dans HomeAssistant/Paramètre/Système/Sauvegarde restaurez la sauvegarde que vous avez mis au chaud sur votre Cloud tout au début du tuto.
Lien vers un pas à pas : Guide de restauration à partir d'une sauvegarde dans Home Assistant - Domotique Technoseb27


Attention, la restauration de la sauvegarde va également ré-écrire le fichier configuration.yaml avec des réglagles non adapté… Il faut donc recommencer l’étape Configuration de HomeAssistant.
Une fois fait, relancer le conteneur Home Assistant.


Configuration de MQTT
Il faut corriger l’adresse de l’intégration MQTT pour qu’il pointe bien vers notre broker sous Docker.
Allez dans HomeAssistant/Paramètres/Appareils et services/MQTT
Sélectionner les 3 points verticaux puis Reconfigurer



Entrer l’adresse IP locale du serveur 172.20.0.10 + identifiant/mdp de Mosquitto MQTT :


Ajouter des Intégration dans l’interface de Home Assistant
Pour ajouter des raccourcis depuis Home Assistant vers vos différentes intégrations Docker (Portainer, Zigbee2MQTT, FileEditor, etc) il faut aller dans HomeAssistant/Paramètre/Tableaux de bord => Ajouter un tableau de bord (icon en bas à droite) >> Page Web


Entrez les URL Internet de vos intégrations.
Par exmple : https://toto.duckdns.org:8080 pour Zigbee2MQTT

Etape 11: Installation de MQTT Explorer [falcutatif]

Source:

Mon stack :

services:
 mqtt-explorer:
    container_name: mqtt-explorer
    image: smeagolworms4/mqtt-explorer
    hostname: mqtt-explorer
    ports:
        - 9002:9002
    environment:
        - HTTP_PORT=9002
        - CONFIG_PATH=/mqtt-explorer/config
        - TZ=Europe/Paris
        #- SSL_KEY_PATH=/etc/letsencrypt/live/TOTO.duckdns.org/privkey.pem  
        #- SSL_CERT_PATH=/etc/letsencrypt/live/TOTO.duckdns.org/fullchain.pem 
    volumes:
        - config:/mqtt-explorer/config
        - /etc/timezone:/etc/timezone:ro
        - /etc/letsencrypt:/etc/letsencrypt:ro

    networks:
      reseau_mqtt:
        ipv4_address: 172.20.0.11
volumes:
  config:
networks:
  reseau_mqtt:
    external: true

Nb: Si j’active la connection en TLS à MQTT-Explorer, il n’arrive pas à se connecter au broker MQTT…

Allez à l’adresse http://172.20.0.11:9002
Puis connectez vous avec vos identifiants MQTT (étape 7)

Etape 12: Installation du conteneur DuckDNS
Le conteneur DuckDNS sert à maintenir à jour votre nom de domain pour qu’il pointe vers la bonne adresse IP. Etant donné que votre adresse IP peut changer selon le bon vouloir de votre opérateur, il faut le checker régulièrement.

Nouveau stack duckdns :

services:
  duckdns:
    image: lscr.io/linuxserver/duckdns
    container_name: duckdns
    environment:
      - TZ=Europe/Paris
      - SUBDOMAINS=toto
      - TOKEN=token #insérez votre token
      - LOG_FILE=false #optional
    volumes:
      - /opt/docker/duckdns/config:/config #optional
    restart: unless-stopped

SUBDOMAINS= : Si votre domain est toto.duckdns.org, rentrer just toto
TOKEN= : Numéro de token généré sur le site Duckdns.


Une fois déployé, regardez les *logs* pour vérifier qu'il est bien configuré.

Etape 13: Installation de Watchtower

Source:

Watchtower sert à mettre à jour automatiquement les images de Docker dés qu’il trouve une nouvelle version disponible.

Créer un nouveau stack watchtower

services:
  watchtower:
    container_name: watchtower
    image: nickfedor/watchtower
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock # acces à Docker
      - /etc/timezone:/etc/timezone:ro
    environment:
      TZ: Europe/Paris
      WATCHTOWER_CLEANUP: true  #supprime automatiquement les vieilles images
      WATCHTOWER_SCHEDULE: "0 0 4 * * *"  # check tous les jours à 4h du mat
      WATCHTOWER_LIFECYCLE_HOOKS: true
      WATCHTOWER_UPDATE_ON_START: true
      WATCHTOWER_NOTIFICATIONS: email
      WATCHTOWER_NOTIFICATION_EMAIL_FROM: toto@free.fr
      WATCHTOWER_NOTIFICATION_EMAIL_TO: toto@gmail.com
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER: smtp.free.fr
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT: 587
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER: toto
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD: xxxx
      WATCHTOWER_NOTIFICATION_EMAIL_DELAY: 10

Etape 14: Installation de Rclone

Source:

RClone est un utilitaire pour copier/synchroniser des répertoires avec des disques Cloud.
On va utiliser la version serveur RC pour être accessible via commandes HTTP/API

Créez ce stack Rclone :

services:
  rclone:
    image: rclone/rclone:latest
    container_name: rclone
    volumes:
      - /opt/docker/rclone:/config/rclone
      - /opt/docker/rclone/logs:/logs
      - /opt/docker/rclone/cache:/root/.cache/rclone # This is for the WebUI, not VFS
      - /home/user:/hostfs:rshared
      - /var/cache/rclone:/vfsCache
      - /etc/passwd:/etc/passwd:ro
      - /etc/group:/etc/group:ro
      - /etc/fuse.conf:/etc/fuse.conf:ro
      - /etc/letsencrypt:/etc/letsencrypt:ro
      - /opt/docker/ha/config:/opt/docker/ha/config # rend nos répertoire HA accessibles depuis Rclone RC
    devices:
      - /dev/fuse:/dev/fuse:rwm
    cap_add:
      - SYS_ADMIN
    security_opt:
      - apparmor:unconfined
    command:
      - rcd
      - --rc-web-gui
      - --rc-web-gui-no-open-browser
      - --rc-addr=:5572
      - --rc-user=rclone_user
      - --rc-pass=rclone_pw
      - --rc-cert=/etc/letsencrypt/live/toto.duckdns.org/fullchain.pem
      - --rc-key=/etc/letsencrypt/live/toto.duckdns.org/privkey.pem
      - --log-level=NOTICE
      - --cache-dir=/vfsCache
    network_mode: host
#    networks:
#      reseau_mqtt:
#        ipv4_address: 172.20.0.4
    ports:
      - 5572:5572
    environment:
      - TZ=Europe/Paris
    restart: unless-stopped
  rclone_initializer:
    #image: ghcr.io/coanghel/rclone-docker-automount/rclone-init:latest
    image: ghcr.io/Gandalf77bo/rclone-docker-automount/rclone-init:latest
    container_name: rclone_initializer
    environment:
      - RCLONE_USERNAME=rclone_user
      - RCLONE_PASSWORD=rclone_pw
      - RCLONE_PORT=5572
      - RCLONE_CERT=/etc/letsencrypt/live/toto.duckdns.org/fullchain.pem
      - RCLONE_KEY=/etc/letsencrypt/live/toto.duckdns.org/privkey.pem
    volumes:
      - /opt/docker/rclone/initializer:/app/
      - /etc/letsencrypt:/etc/letsencrypt:ro
    restart: unless-stopped
    depends_on:
      - rclone
    networks:
      reseau_mqtt:
        ipv4_address: 172.20.0.14

networks:
  reseau_mqtt:
    external: true

Ce stack va déployer Rclone ainsi qu’un script qui permet de monter automatiquement le répertoire distant au démarrage.
Je du faire un branch du projet GitHub Coanghel afin d’ajouter le support du HTTPS.
Choisissez un couple identifiant /mdp pour Rclone qu’il faut renseigner à la fois à Rclone et au script.
Corriger également l’endroit de montage du répertoire Gdrive : /home/user:/hostfs:rshared, moi je le monte dans mon home.

On va lancer Rclone en 2 fois. 1er fois pour configurer les access puis une 2nd fois avec les réglages normaux.


Création des identifiants Google pour utilisation de Gdrive avec Rclone

Allez dans https://console.cloud.google.com
Allez dans API et Services et activer Google Drive API


Puis dans Identifiants faire Créer des identifiants Oauth :

Type d’application : Application de Bureau
Nom: Rclone ou autre
Normalement vos codes s’affichent. Conservez les précieusement! Vous pouvez les téléchager au format JSON depuis l’écran Oauth/Client pendant qq mois seulement.

Edit:
L’ajout de son compte comme utilisateur de test permet de tester l’API pendant pour pouvoir semaine, apres quoi le token est à regénérer. Ce n’est pas pérenne donc je déconseil cette méthode.
l’utiliser. Pour cela, allez dans Audience et ajoutez votre adresse email tout en bas :

Méthode pérenne :

Dans Acces aux Données faites Ajouter ou Supprimer des niveaux d'accés et cochez ces 3 services :

Puis dans Audience faites Publier l'application
Etant donné que l’on a pas renseigner tout les champs pour publier l’application, elle va rester indéfiniement au status de Vérification.

Fermez l’onglet.
Voila, normalement vos identifiants Google Auth sont OK.


Installation et configuration de Rclone :
Donc pour configurer Rclone, il faut le lancer une 1ere fois avec dans le stack le network_mode: host. Désactiver les 3 autres lignes networks.
Lancer le déploiement pout ouvrir un terminal et taper :

docker exec -it rclone rclone config

Cela va créer un fichier de configuration /opt/docker/rclone/rclone.conf
Taper n pour créer un nouveau remote et donnez lui un petit nom.
Storage: pour moi Gdrive = 22
Client_id: l’identifiant Oauth généré par google du style 1820098191102-135xxxx.apps.googleusercontent.com
Client_secret: le mot de passa associé genre GOCSPX-rxxxxxdpPM
Scope: 1
Service_account_file: rien
Edit Advance conf: n
Use Web browser: y


Faites un copier/coller du lien afficher dans une fenetre de votre navigateur.
Cela va ouvrir une fenetre de sélection de compte Google. Autorisez l’accés.
Si votre compte Google Auth est à l’état publier/vérification, dans la fenetre d’autorisation des accés il faut forcer la main en cliquant en bas l’option "Go to Rclone (unsafe)"

Si tout se passe bien, le terminal affichera « toker captured » ou qq chose comme ça.
Si qq tourne mal, faite Ctrl+c pour arreter et recommencez.


Lancement de Rclone en mode normal
Modifier le stack pour ajouter un # devant la ligne network_mode: host
et enlever les commentaire devant

    networks:
      reseau_mqtt:
        ipv4_address: 172.20.0.4

Re-déployer le stack.


Utiliser rclone-docker-automount
Source:

Pour l’utiliser il faut créer le répertoire ou le point de montage doit se faire.
Ici ce sera /home/user/Gdrive/mount
Puis créer un répertoire initializer dans Rclone.

cd /opt/docker/rclone
sudo mkdir initializer
cd initializer
sudo wget https://raw.githubusercontent.com/gandalf77bo/rclone-docker-automount/master/mounts.json # pour telecharger le fichier mounts.json
sudo wget https://raw.githubusercontent.com/gandalf77bo/rclone-docker-automount/master/rclone_initializer.py # pour télécharger le script qui pour une raison inconnue ne se télécharge pas tout seul!

Editez le fichier mounts.json pour peaufiner les réglages (sudo nano mounts.json)
Le mien est ainsi :

[
 {
    "fs": "Gdrive:",
    "mountPoint": "/hostfs/Gdrive/mount",
    "mountOpt": {
	"AllowOther": true,
	"AllowNonEmpty": true
    },
    "vfsOpt": {
	"CacheMode": "full",
	"GID": 1000,
	"UID": 1000
    }
  }
]

nb: /hostfs est un volume docker defini dans le stack. Pour moi il pointe vers /home/user. Donc le point de montage final est /home/user/Gdrive/mount

J’ai déjà rencontré l’erreur failed to mount FUSE fs: fusermount: exit status 1
Sur Internet ils recommandent de vérifier si fude3 est bien installé : sudo apt install fuse3
Dans mon cas, le répertoire mount était verrouillé mais sans lien vers Gdrive, j’ai du le supprimer en faisant : sudo umount /home/user/Gdrive/mount

Je partage ici qq scripts sympas :slight_smile:

Dans mon répertoire /home/USER/scripts/

Envoi d’email avec Curl
Fichier email.sh

#!/bin/bash

if [[ ($# == 0) || ($# -gt 2)]]; then
	echo 'Syntaxe: email.sh [titre] contenu'
	exit 1
fi
if [[ $# == 1 ]]; then
	sub="Notification"
	body="$1"
fi
if [[ $# == 2 ]]; then
	sub="$1"
	body="$2"
fi

declare -A email;
email['user']="xxx@free.fr"
email['pass']="xxxxxxx"
email['smtp']="smtp.free.fr"
email['port']='587'
email['rcpt']='xxx@gmail.com' # adresse destinataire

email_content='From: Raspberry <'"${email['user']}"'>
To: "Gmail" <'"${email['rcpt']}"'>
Subject: '"$sub"'
Date: '"$(date)"'

'"$body"'
';

echo "$email_content" | curl -s \
    --url "smtp://${email['smtp']}:${email['port']}" \
    --user "${email['user']}:${email['pass']}" \
    --mail-from "${email['user']}" \
    --mail-rcpt "${email['rcpt']}" \
    --upload-file - # email_content


if [[ $? == 0 ]]; then
    echo "Email sent to ${email['rcpt']}!"
else
    echo "curl error code $?"
    man curl | grep "^ \+$? \+"
fi

exit 0

Synchronisation de fichier avec mon Gdrive tous les jours à 5h avec Rclone
Fichier sync_gdrive_rc.sh

#!/bin/bash

DOMAIN=mondomain.duckdns.org
RCLONE_USER=G
RCLONE_MDP=xxxxx
FOLDER=/opt/docker/ha/config/backups
REMOTE_FOLDER="Gdrive:/Home_Assistant/backups"
JSON='{
"srcFs":"'"${FOLDER}"'",
"dstFs":"'"${REMOTE_FOLDER}"'"
}'

#doc : https://git.frostfs.info/KurlesHS/rclone/src/branch/graceful-cancel/docs/content/rc.md
curl -vvv \
        --cert "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" \
        --key "/etc/letsencrypt/live/${DOMAIN}/privkey.pem" \
        --insecure \
	-H "Content-Type: application/json" \
	-d "${JSON}" \
        "https://${RCLONE_USER}:${RCLONE_MDP}@127.0.0.1:5572/sync/sync"
$RETOUR=$?

if [[ $RETOUR == 0 ]]; then
    echo 'Rclone RC sync okay!';
else
    echo "curl error code $RETOUR";
    man curl | grep "^ \+$RETOUR \+"
fi

echo "$(date) Rclone sync ${FOLDER} to ${BACKUP_FOLDER}!" | tee sync_gdrive.log
exit 0

et on ajoute une planification journaliere avec crontab -e

0 5 * * * /home/USER/scripts/sync_gdrive_rc.sh >/home/USER/scripts/sync_gdrive_rc.cron.log

Scripts pour déclencher un backup de HomeAssistant avant une mise à jour via Watchtower

Tout d’abord dans le stack de Home assistant, vous aurez besoin des lignes suivantes pour déclencher le script avant la mise à jour par WatchTower

    labels:
      - com.centurylinklabs.watchtower.lifecycle.pre-update="/config/generate_backup.sh"
      - com.centurylinklabs.watchtower.lifecycle.pre-update-timeout=180

Le script en question /config/generate_backup.sh doit être dans /opt/docker/ha/config/generate_backup.sh

#!/bin/bash

#source : nck974 @ https://community.home-assistant.io/t/what-backup-strategy-when-running-home-assistant-in-docker/262539/27

##########
# CONFIG

# This has to be configured in an automation
HA_WEBHOOK=https://127.0.0.1:8123/api/webhook/backup-create-backup-123

# Configure the backups folder inside your config
LOCAL_PATH=/config # dans le référentiel du conteneur HA
HA_BACKUP_FOLDER=$LOCAL_PATH/backups
if [ ! -d $HA_BACKUP_FOLDER ]
then
	LOCAL_PATH=/opt/docker/ha/config
	HA_BACKUP_FOLDER="$LOCAL_PATH/backups"
fi

# Configuration of rclone
# rclone path where the backups will be sent
BACKUP_FOLDER=/opt/docker/ha/config/backups 
REMOTE_BACKUP_FOLDER="Gdrive:/Home_Assistant/backups"
# RClone Auth id
RCLONE_USER=G
RCLONE_PW=xxxxxxxx

# Configure the maximum time the script waits for the backup to complete
WAITING_TIME=20

# my log file
LOGFILE=$LOCAL_PATH/generate_backup.log

touch $LOGFILE
echo "${DATE_STRING} Demarrage du script" >$LOGFILE
echo "LOCAL_PATH=${LOCAL_PATH}" >>$LOGFILE
echo "HA_BACKUP_FOLDER=${HA_BACKUP_FOLDER}" >>$LOGFILE

##########
# START HA BACKUP
#DATE_STRING=$(date +%Y-%m-%d)
DATE_STRING=$(date +"%F_%T")

//echo "$(date) Script generate_back.sh Starting."
echo "Verification du repertoire Backup..." >>$LOGFILE
if [ ! -d ${HA_BACKUP_FOLDER} ]; then echo "HA_BACKUP_FOLDER is not set" >>$LOGFILE && exit 75; fi


echo "Sending generate backup to backup hook..." >>$LOGFILE
curl -v \
	--cert /etc/letsencrypt/live/rosine33.duckdns.org/fullchain.pem \
	--key /etc/letsencrypt/live/rosine33.duckdns.org/privkey.pem \
	--insecure \
	-d '{"data":"'${DATE_STRING}'"}' \
	-H "Content-Type: application/json" \
	${HA_WEBHOOK} \
	>> $LOGFILE

echo "Waiting for the backup to be generated... for ${DATE_STRING}" >>$LOGFILE
attempt=1
until cat "${LOCAL_PATH}/home-assistant.log" | tail -n 10 | grep -q "Backup created for date: ${DATE_STRING}"; do
    if [ "$attempt" -ge "$WAITING_TIME" ]; then
        echo "Timeout reached after $WAITING_TIME attempts. Abort!" >>$LOGFILE
	echo "Contenu de ${LOCAL_PATH}/home-assistant.log" >>$LOGFILE
	cat "${LOCAL_PATH}/home-assistant.log" >>$LOGFILE
        exit 75
    fi
    let attempt++
    sleep 1
done


echo "Nettoyage des vieux Custom Backup..." >>$LOGFILE
declare -a LIST_FILES
LIST_FILES=(`ls -t1 ${HA_BACKUP_FOLDER}/Custom_backup_*.tar`) #creer un tableau
rm -f ${LIST_FILES[@]:3} &>>$LOGFILE


echo "Config backup done for ${DATE_STRING}" >$HA_BACKUP_FOLDER/backup.log

echo "Sending backup to backup server with Rclone RC..." >>$LOGFILE
JSON='{
"srcFs":"'"${BACKUP_FOLDER}"'",
"dstFs":"'"${REMOTE_BACKUP_FOLDER}"'"
}'

curl -v \
        --cert /etc/letsencrypt/live/rosine33.duckdns.org/fullchain.pem \
        --key /etc/letsencrypt/live/rosine33.duckdns.org/privkey.pem \
        --insecure \
        -H "Content-Type: application/json" \
        -d "${JSON}" \
	--user "${RCLONE_USER}:${RCLONE_PW}" \
        'https://rclone:5572/sync/sync' \
        >> $LOGFILE 2>&1
RETOUR=$?

if [ $RETOUR != 0 ]
then
	echo "curl error code '$RETOUR'" >>$LOGFILE
	man curl | grep "^ \+$RETOUR \+" >>$LOGFILE
	exit 75
fi


echo "Config backup done for ${DATE_STRING}" >>$LOGFILE
/home/Gilles/scripts/email.sh 'Generate_backup.sh' 'Success!' >>$LOGFILE

echo "$(date) Script generate_back.sh successfully executed."
exit 0

Ce script fait appel a mon script email.sh dans mon répertoire home. Pensez à corriger le chemin :slight_smile:
Pensez a faire sudo chmod +x generate_backup.sh pour le rendre executable.
Pour tester le script dans les condition de Watchtower il faut rentrer dans la conteneur HomeAsistant ainsi :

docker exec -it homeassistant sh
./generate_backup.sh
exit # pour sortir du conteneur

Tous les log sont stockés dans /opt/docker/ha/config/generate_backup.log

Ce script envoit une demande à HomeAssistant via la plateforme webhook. Il faut donc créer le script correspondant dans HomeAssisant :

alias: "Backup: Create backup hook"
description: ""
triggers:
  - allowed_methods:
      - POST
    local_only: true
    webhook_id: backup-create-backup-123
    trigger: webhook
conditions: []
actions:
  - action: system_log.write
    metadata: {}
    data:
      level: warning
      message: "Creating backup... "
  - action: backup.create
    data: {}
  - action: system_log.write
    metadata: {}
    data:
      level: warning
      message: |
        Backup created for date: {{ trigger.json.data }}
mode: single

Mettre un reverse Proxy ??

A voir dans le futur :^^

Bonjour
sans minimiser ton travail et merci pour le partage, Home Assistant sous docker intégrant nativement les sauvegardes locales ou/et vers un NAS ou/et Google Drive, c’est beaucoup de surcouches qui peuvent être source de problèmes, J’ai fait récemment une migration HAOS vers docker et un retour vers HAOS il y a mois, ça se passe bien avec le système de sauvegarde native

Gérer les sauvegardes ainsi que pour HA, il y a peu d’intérêts effectivement, par contre en considérant qu’il y a d’autres données à sauvegarder concernant d’autres containers, cela permet d’avoir un seul et unique système de backup.

Par contre toute la difficulté est de sauvegarder proprement tout cela (portainer par exemple qui lock sa base de données durant son exécution).