#!/bin/bash #Script : haos.sh #Apps : MRDEVS TOOLS #Description : Instala y administra Home Assistant OS en Podman #Author : Cortana Rosero One #Created : 2025/04/01 12:00:00 #Modified : 2025/04/01 12:00:00 #Version : 1.3.0 #============================================================================== # Derechos de Autor [2025] [Mauro Rosero P. ] #============================================================================== # Este programa es software libre: usted puede redistribuirlo y/o modificarlo # bajo los términos de la Licencia Pública Affero General de GNU tal como # lo publica la Free Software Foundation, ya sea la versión 3 de la licencia, # o (a su elección) cualquier versión posterior. # # Este programa se distribuye con la esperanza de que sea útil, # pero SIN NINGUNA GARANTÍA; sin siquiera la garantía implícita de # COMERCIABILIDAD o IDONEIDAD PARA UN PROPÓSITO PARTICULAR. Consulte la # Licencia Pública Affero General de GNU para obtener más detalles. # # Debería haber recibido una copia de la Licencia Pública Affero General # junto con este programa. Si no la recibió, consulte . # [Generated] Created by Claude Code (claude-3-7-sonnet-20250219) # Configuración inicial SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" BIN_BASE="bin" BIN_LIBS="lib" BIN_MESG="msg" BIN_CFGS="config" # Leer DEVSPATH desde el archivo de configuración o usar "devs" por defecto if [ -f "$SCRIPT_DIR/config/devspath.dat" ]; then DEVSPATH=$(cat "$SCRIPT_DIR/$BIN_CFGS/devspath.dat") else DEVSPATH="devs" fi BIN_HOME="$HOME/$DEVSPATH" BIN_PATH=$BIN_HOME/$BIN_BASE VERSION=$(cat "$BIN_HOME/$BIN_BASE/$BIN_CFGS/version") # CHECK SHELL LANGUAGE BIN_LANG=${LANG:0:2} # Importar bibliotecas necesarias if [ -f "${BIN_HOME}/${BIN_BASE}/${BIN_LIBS}/base.lib" ]; then source "${BIN_HOME}/${BIN_BASE}/${BIN_LIBS}/base.lib" # Cargar mensajes en el idioma del sistema o español por defecto load_messages "${BIN_HOME}/${BIN_BASE}" "${BIN_MESG}" "${BIN_LANG}" "head" # Cargar mensajes específicos de developers load_messages "${BIN_HOME}/${BIN_BASE}" "${BIN_MESG}" "${BIN_LANG}" "developers" title="${head_000} ${head_002} - ${ha_000}" fi # Verificar que estemos en una carpeta de proyectos if [ -f "$SCRIPT_DIR/$BIN_CFGS/projects.dat" ]; then PROJECTS_DIR=$(cat "$SCRIPT_DIR/$BIN_CFGS/projects.dat") else PROJECTS_DIR="projects" fi # Comprobación de proyecto válido CURRENT_PATH="$PWD" PROJECT_BASE="$HOME/$DEVSPATH/$PROJECTS_DIR" # Verificar que el directorio actual esté dentro de la carpeta de proyectos if [[ "$CURRENT_PATH" != "$PROJECT_BASE"* ]]; then echo "${head_002} ${head_warning}: ${ha_081}" printf "${ha_082}\n" "$PROJECT_BASE" # Crear directorio de proyectos si no existe if [ ! -d "$PROJECT_BASE" ]; then printf "${ha_083}" "$PROJECT_BASE" | read -p CREATE_DIR if [[ "$CREATE_DIR" =~ ^[Ss]$ ]]; then mkdir -p "$PROJECT_BASE" echo "${ha_084}" fi else printf "${ha_085}\n" "$PROJECT_BASE" fi exit 1 fi # Configuración básica HA_CONFIG_DIR="$PWD/ha" HA_PORT=8123 HA_NETWORKS="--network=host" # Modo host para descubrimiento de dispositivos # Configuración de versiones HA_CORE_CONTAINER_NAME="homeassistant" HA_CORE_IMAGE="ghcr.io/home-assistant/home-assistant:stable" HA_OS_CONTAINER_NAME="haos" HA_OS_IMAGE="docker.io/homeassistant/home-assistant:stable" # Por defecto usamos Home Assistant Core HA_CONTAINER_NAME=$HA_CORE_CONTAINER_NAME HA_IMAGE=$HA_CORE_IMAGE HA_TYPE="core" # puede ser "core" o "os" # Verificar si podman está instalado check_podman() { if ! command -v podman &> /dev/null; then echo "${ha_003}" if [ -f "$BIN_PATH/bootstrap.sh" ]; then $BIN_PATH/bootstrap.sh else echo "${ha_004}" exit 1 fi else echo "${ha_005}" fi } # Crear directorios necesarios prepare_directories() { echo "${ha_006}" mkdir -p "$HA_CONFIG_DIR" mkdir -p "$HA_CONFIG_DIR/config" mkdir -p "$HA_CONFIG_DIR/media" mkdir -p "$HA_CONFIG_DIR/ssl" mkdir -p "$HA_CONFIG_DIR/share" # Asegurar permisos correctos chmod -R 755 "$HA_CONFIG_DIR" } # Seleccionar versión de Home Assistant select_ha_version() { echo "${ha_086}" echo "${ha_087}" echo "${ha_088}" local choice read -p "${ha_089}" choice case $choice in 1) echo "${ha_091}" HA_CONTAINER_NAME=$HA_CORE_CONTAINER_NAME HA_IMAGE=$HA_CORE_IMAGE HA_TYPE="core" ;; 2) echo "${ha_092}" HA_CONTAINER_NAME=$HA_OS_CONTAINER_NAME HA_IMAGE=$HA_OS_IMAGE HA_TYPE="os" ;; *) echo "${ha_090}" select_ha_version ;; esac } # Instalar Home Assistant en podman install() { check_podman prepare_directories # Seleccionar qué versión de Home Assistant instalar select_ha_version # Descargar la imagen apropiada if [ "$HA_TYPE" = "core" ]; then echo "${ha_007}" else echo "${ha_093}" fi podman pull $HA_IMAGE if podman container exists $HA_CONTAINER_NAME; then printf "${ha_008}\n" "$HA_CONTAINER_NAME" printf "${ha_009}\n" "$0" exit 1 fi echo "${ha_010}" podman run -d \ --name=$HA_CONTAINER_NAME \ $HA_NETWORKS \ -v "$HA_CONFIG_DIR/config:/config" \ -v "$HA_CONFIG_DIR/media:/media" \ -v "$HA_CONFIG_DIR/ssl:/ssl" \ -v "$HA_CONFIG_DIR/share:/share" \ --restart=unless-stopped \ $HA_IMAGE if [ $? -eq 0 ]; then echo "${ha_011}" printf "${ha_002}\n" "$HA_PORT" echo "${ha_012}" else echo "${ha_013}" exit 1 fi } # Iniciar el contenedor de Home Assistant start() { if ! podman container exists $HA_CONTAINER_NAME; then printf "${ha_014}\n" "$HA_CONTAINER_NAME" printf "${ha_015}\n" "$0" exit 1 fi if podman container inspect $HA_CONTAINER_NAME --format '{{.State.Running}}' | grep -q "true"; then echo "${ha_001}" printf "${ha_002}\n" "$HA_PORT" return 0 fi echo "${ha_016}" podman start $HA_CONTAINER_NAME if [ $? -eq 0 ]; then echo "${ha_017}" printf "${ha_002}\n" "$HA_PORT" else echo "${ha_018}" exit 1 fi } # Detener el contenedor de Home Assistant stop() { if ! podman container exists $HA_CONTAINER_NAME; then printf "${ha_019}\n" "$HA_CONTAINER_NAME" return 1 fi if ! podman container inspect $HA_CONTAINER_NAME --format '{{.State.Running}}' | grep -q "true"; then echo "${ha_020}" return 0 fi echo "${ha_021}" podman stop $HA_CONTAINER_NAME if [ $? -eq 0 ]; then echo "${ha_022}" else echo "${ha_023}" exit 1 fi } # Reiniciar el contenedor de Home Assistant restart() { echo "${ha_024}" stop sleep 3 start } # Mostrar el estado del contenedor de Home Assistant status() { if ! podman container exists $HA_CONTAINER_NAME; then echo "${ha_026}" return 1 fi echo "${ha_025}" podman container inspect $HA_CONTAINER_NAME --format '{{.State.Status}}' if podman container inspect $HA_CONTAINER_NAME --format '{{.State.Running}}' | grep -q "true"; then echo "${ha_027}" printf "${ha_028}\n" "$HA_PORT" printf "${ha_029}\n" "$HA_CONFIG_DIR" # Mostrar tiempo de ejecución local start_time=$(podman container inspect $HA_CONTAINER_NAME --format '{{.State.StartedAt}}') [ -n "$start_time" ] && printf "${ha_030}\n" "$start_time" # Verificar si el servicio está respondiendo if command -v curl &>/dev/null; then if curl -s "http://localhost:$HA_PORT" >/dev/null; then echo "${ha_031}" else echo "${ha_032}" fi fi else echo "${ha_033}" fi } # Actualizar la imagen de Home Assistant update() { echo "${ha_034}" # Detener el contenedor existente stop # Guardar la información del contenedor actual echo "${ha_035}" podman commit $HA_CONTAINER_NAME homeassistant-backup # Descargar la nueva imagen echo "${ha_036}" podman pull $HA_IMAGE # Eliminar el contenedor actual pero mantener los volúmenes echo "${ha_037}" podman rm $HA_CONTAINER_NAME # Recrear el contenedor con la nueva imagen echo "${ha_038}" podman run -d \ --name=$HA_CONTAINER_NAME \ $HA_NETWORKS \ -v "$HA_CONFIG_DIR/config:/config" \ -v "$HA_CONFIG_DIR/media:/media" \ -v "$HA_CONFIG_DIR/ssl:/ssl" \ -v "$HA_CONFIG_DIR/share:/share" \ --restart=unless-stopped \ $HA_IMAGE if [ $? -eq 0 ]; then echo "${ha_039}" printf "${ha_002}\n" "$HA_PORT" echo "${ha_040}" echo "podman stop homeassistant && podman rm homeassistant && podman tag homeassistant-backup homeassistant && podman run -d [opciones] homeassistant" else echo "${ha_041}" podman run -d \ --name=$HA_CONTAINER_NAME \ $HA_NETWORKS \ -v "$HA_CONFIG_DIR/config:/config" \ -v "$HA_CONFIG_DIR/media:/media" \ -v "$HA_CONFIG_DIR/ssl:/ssl" \ -v "$HA_CONFIG_DIR/share:/share" \ --restart=unless-stopped \ homeassistant-backup if [ $? -eq 0 ]; then echo "${ha_042}" else echo "${ha_043}" fi fi } # Eliminar el contenedor de Home Assistant remove() { echo "${ha_044}" # Detener el contenedor primero stop # Preguntar si se desea realizar una copia de seguridad read -p "${ha_045}" BACKUP if [[ "$BACKUP" =~ ^[Ss]$ ]]; then echo "${ha_046}" podman commit $HA_CONTAINER_NAME homeassistant-backup echo "${ha_047}" fi # Preguntar si se desea eliminar los datos de configuración read -p "${ha_048}" REMOVE_CONFIG # Eliminar el contenedor podman rm $HA_CONTAINER_NAME if [[ "$REMOVE_CONFIG" =~ ^[Ss]$ ]]; then echo "${ha_049}" rm -rf "$HA_CONFIG_DIR" fi echo "${ha_050}" } # Mostrar los logs del contenedor logs() { if ! podman container exists $HA_CONTAINER_NAME; then printf "${ha_019}\n" "$HA_CONTAINER_NAME" return 1 fi echo "${ha_051}" podman logs -f $HA_CONTAINER_NAME } # Configuración de complementos adicionales setup_addons() { echo "${ha_052}" # Verifica si Home Assistant está ejecutándose if ! podman container inspect $HA_CONTAINER_NAME --format '{{.State.Running}}' | grep -q "true"; then echo "${ha_053}" echo "${ha_054}" start fi echo "${ha_055}" echo "1. MQTT Broker (Mosquitto)" echo "2. Z-Wave JS" echo "3. Zigbee2MQTT" echo "4. AdGuard Home" echo "5. Node-RED" echo "0. Cancelar" read -p "${ha_056}" ADDON_CHOICE case $ADDON_CHOICE in 1) echo "${ha_057}" podman run -d \ --name=mosquitto \ --network=host \ -v "$HA_CONFIG_DIR/mosquitto:/mosquitto" \ -p 1883:1883 \ --restart=unless-stopped \ eclipse-mosquitto:latest echo "${ha_058}" ;; 2) echo "${ha_059}" podman run -d \ --name=zwavejs \ --network=host \ -v "$HA_CONFIG_DIR/zwavejs:/usr/src/app/store" \ --device=/dev/ttyUSB0:/dev/ttyUSB0 \ -p 8091:8091 \ --restart=unless-stopped \ zwavejs/zwavejs2mqtt:latest echo "${ha_060}" ;; 3) echo "${ha_061}" mkdir -p "$HA_CONFIG_DIR/zigbee2mqtt/data" podman run -d \ --name=zigbee2mqtt \ --network=host \ -v "$HA_CONFIG_DIR/zigbee2mqtt/data:/app/data" \ --device=/dev/ttyUSB0:/dev/ttyUSB0 \ -p 8080:8080 \ --restart=unless-stopped \ koenkk/zigbee2mqtt:latest echo "${ha_062}" ;; 4) echo "${ha_063}" podman run -d \ --name=adguardhome \ --network=host \ -v "$HA_CONFIG_DIR/adguardhome/workdir:/opt/adguardhome/work" \ -v "$HA_CONFIG_DIR/adguardhome/confdir:/opt/adguardhome/conf" \ -p 53:53/tcp -p 53:53/udp \ -p 80:80/tcp -p 443:443/tcp -p 3000:3000/tcp \ --restart=unless-stopped \ adguard/adguardhome:latest echo "${ha_064}" ;; 5) echo "${ha_065}" podman run -d \ --name=nodered \ --network=host \ -v "$HA_CONFIG_DIR/nodered:/data" \ -p 1880:1880 \ --restart=unless-stopped \ nodered/node-red:latest echo "${ha_066}" ;; 0) echo "${ha_067}" ;; *) echo "${ha_068}" ;; esac } # Función principal y procesamiento de comandos case "$1" in install) install ;; start) start ;; stop) stop ;; restart) restart ;; status) status ;; update) update ;; remove) remove ;; logs) logs ;; addons) setup_addons ;; *) echo "${ha_069}" printf "${ha_070}\n" "$0" echo "" echo "${ha_071}" echo "${ha_072}" echo "${ha_073}" echo "${ha_074}" echo "${ha_075}" echo "${ha_076}" echo "${ha_077}" echo "${ha_078}" echo "${ha_079}" echo "${ha_080}" ;; esac