Долгосрочное хранение логов Home Assistant (на всякий случай)

Сегодня Home Assistant не пожелал мне доброго утра как обычно. Оказалось, в половине четвертого утра аддон APC UPS Daemon без объявления войны отправил серверу команду выключения. Это удалось выяснить из логов виртуальной машины, на которой запущен сервер HA. Верю, что у аддона были веские причины для принятия такого решения, несмотря на то, что все электронные часы в доме утром показывали точное время, а значит электричество не отключалось. Чтобы распутать эту детективную историю, мне не хватило всего ничего - логов аддона APC UPS Daemon. К сожалению, Home Assistant (бывший Hass.io) устроен так, что при перезапуске сервера все контейнеры (включая аддоны) создаются заново, а значит все логи контейнеров также начинают писаться с чистого листа.

Попробуем это исправить, чтобы в следующий раз, влипнув в подобную ситуацию, иметь на руках детальную хронологию развития событий. Для этого воспользуемся готовым решением, которое запускается одной командой. Это Docker контейнер, написанный одним из ведущих широко известного в узких кругах технологического подкаста Радио-Т. Контейнер делает ровно одну вещь и делает её хорошо: собирает логи всех остальных контейнеров в указанную папку, что нам, собственно, и нужно. Теперь, даже если сервер внезапно будет выключен или перезагружен, запись логов просто продолжится с того места, где прервалась жизнь контейнера.

Приступим. Я покажу несколько вариантов создания контейнера:

  • с помощью готового файла docker-compose
  • запуском команды docker run из командной строки
  • созданием контейнера из аддона Portainer (для тех, кто устанавливал Home Assistant из готового образа без доступа к полноценной командной строке)

Репозиторий проекта находится здесь. Вдумчивые пацаны с параноидальным подходом к безопасности без моих подсказок сделают себе клон репозитория и внимательно изучат исходники, после чего соберут свой собственный образ с пасьянсом и поэтессами. Мы же сфокусируемся на простом варианте использования готового образа, доступного в Docker Hub. Для развёртывания такого контейнера достаточно одной единственной команды docker run.

Создание контейнера через docker-compose

Для запуска с помощью docker-compose достаточно скопировать себе файл docker-compose.yaml, в котором закомментировать строчку “build .” поставив перед ней символ #. Если оставить эту строку, docker-compose будет пытаться построить образ локально и станет ругаться на отсутствующие файлы репозитория. Запускаем контейнер командой docker-compose up -d и видим, как в папке logs (рядом с docker-compose.yaml) один за другим создаются логи контейнеров.

Создание контейнера из командной строки хоста

Тем, кто не пользуется docker-compose, можно не заморачиваться с его установкой, а создать контейнер прямо из командной строки вашей операционной системы. Параметр TZ (таймзона) нужен для учёта вашего часового пояса в логах. Найти нужную вам можно с помощью поискового запроса timezone list.

docker run -d --name=logger -e TZ=Europe/Moscow --restart unless-stopped -v $(pwd)/logs:/srv/logs -v /var/run/docker.sock:/var/run/docker.sock umputun/docker-logger /srv/docker-logger --files --exclude=logger

Логи будут складываться в папку logs в текущей директории (откуда была запущена команда docker run).

Создание контейнера с помощью аддона Portainer (для тех, у кого нет доступа к командной строке)

Первым делому нам надо установить аддон Portainer из репозитория Community Addons Home Assistant. Данный аддон доступен сразу после установки Home Assistant (в разделе Supervisor->Add-on Store):

Этот аддон даст нам возможность запускать любой Docker контейнер, какой мы захотим. В настройках аддона нужно отключить тумблер Protection Mode (Home Assistant начнёт истошно вопить о нарушении безопасности, что, в общем-то правда, но безграничные права - это обязательное условие для запуска аддона Portainer).

Открываем интерфейс аддона командой OPEN WEB UI и пробуем создать нужный нам контейнер.

Для этого в левом меню выбираем пункт Containers, затем Add Container. В появившемся диалоге в поле Name вводим logger, в поле Image - umputun/docker-logger:latest

В поле Command вводим /srv/docker-logger --files --exclude=logger

Переходим на закладку Volumes и подключаем два тома:

1) container: /srv/logs host: /mnt/data/supervisor/homeassistant/logs

2) container: /var/run/docker.sock host: /var/run/docker.sock

Для обоих указать тип Bind/Writable. Возможно, доступ к файлу docker.sock можно ограничить только чтением, я не проверял.

⚠️Внимание: путь /mnt/data/supervisor/homeassistant/logs будет работать только если Home Assistant (бывший Hass.io) установлен в виде готового образа операционной системы, в которой по умолчанию запрещён доступ к командной строке хоста. Если Home Assistant (бывший Hass.io) установлен поверх существующей операционной системы или Home Assistant Core установлен в свой собственный Docker контейнер, путь к папке с конфигурацией Home Assistant будет другим.

На закладке Env присваиваем переменной окружения TZ стандартное название нашей таймзоны. Это нужно для того, чтобы время в сохраняемых логах отображалось с учётом нашего часового пояса. Найти название нужной таймзоны можно с помощью поискового запроса timezone list.

На закладке Restart Policy выбираем правило Unless stopped. Оно определяет при каких условиях Docker будет пытаться автоматически перезапустить контейнер после того, как что-то пошло не так.

После ввода всех данных нажимаем Deploy the container и дожидаемся зелёного свистка сообщения Container successfully created. Открываем папку logs и радуемся появляющимся там логам всех Docker контейнеров из нашей системы.

Мы рассмотрели только часть возможностей контейнера docker-logger. В разделе Customization перечислены настройки, управляющие правилами ротации логов (ограничения максимального объёма файлов и их количества), перенаправлением вывода логов на удалённый syslog сервер и др.

Теперь даже если какой-то отбившийся от рук аддон решит перезагрузить или выключить Home Assistant, у нас есть все шансы вычислить злоумышленника по горячим следам в логах.