New services, cleanup, readme

This commit is contained in:
Thomas Lovén 2021-09-03 10:52:44 +02:00
parent 05c8d61e0a
commit a0e3ff6375
5 changed files with 225 additions and 13 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
**/*
!.gitignore
!docker-compose.yml
!README.md
!hass
!hass/*

76
README.md Normal file
View File

@ -0,0 +1,76 @@
# Home Assistant docker compose
This compose sets up Home Assistant and services used by it
## hass
Home assistant container.
The image is specially built with the following features
- Home Assistant doesn't run as root
- /config is a volume
- /home/hass/.local/lib is a volume to make pip cache persistent between rebuilds
- Port 8123 is exposed by default
- Added a healthcheck
- If the env variable WAITDB_HOST is set Home Assistant doesn't start until the mysql database at that host with username WAITDB_USER and password WAITDB_PASS is available.
Available on all networks.
Make sure to select all network adapters as active under Configuration->General->Network so `discovery` works.
To update:
```bash
> docker-compose build --pull hass
> docker-compose down hass
> docker-compose up -d hass
```
## db
Mariadb for Home Assistant use.
## dbadmin
PHPMyAdmin container for tweaking the database if necessary.
Start when needed.
## mqtt
Mosquitto server.
Exposed to IOT network (which is also accessible from LAN thanks to its netmask).
## influx
Storage for Home Assistant sensor data
## grafana
For pretty plotting of data from `influx`
## deconz
Deconz container
`/dev/conbee` is created on the host by a udev rule in `/etc/udev/rules.d/10-conbee-local.rules`:
```
ACTION="add", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6015", SYMLINK+="conbee"
```
VNC is activated with password `secret`. This is not exposed outside of the docker internal network, though (can be connected to with e.g. a guacamole container).
A simple healthcheck is added for stability.
## plejd
plejd2mqtt container
https://github.com/thomasloven/plejd2mqtt - a standalone version of a Home Assistant add-on which connects plejd via bluetooth to MQTT.
Access to the bluetooth bus is required through `/var/run/dbus`.
## Mobile
pajikos/sms-gammu-gateway exposes GSM modem functionality via REST.
`/dev/gsmmodem` is created on the host by a udev rule in `/etc/udev/rules.d/999-gsm-modem.rules`:
```
ACTION=="add", ATTRS{idVendor}=="2001", ATTRS{idProduct}=="ac01", RUN+="/usr/sbin/usb_modeswitch -K -v 2001 -p ac01 -V 2001 -P 7e3d"
SUBSYSTEM=="tty", ACTION=="add", ENV{ID_VENDOR_ID}=="2001", ENV{ID_MODEL_ID}=="7e3d", ENV{ID_USB_INTERFACE_NUM}=="01", SYMLINK+="gsmmodem"
```
This requires [usb-modeswitch](https://packages.debian.org/bullseye/usb-modeswitch) to be installed on the host, and the exact commands vary greatly from device to device. The above works for my D-Link DWM222, but may or may not work with your D-Link DWM222.
Health check added for stability

View File

@ -8,10 +8,31 @@ networks:
lan:
external: true
volumes:
hass:
driver: local
driver_opts:
o: bind
type: none
device: /data/files/hass
video:
driver: local
driver_opts:
o: bind
type: none
device: /data/video
music:
driver: local
driver_opts:
o: bind
type: none
device: /data/music
services:
hass:
container_name: hass
image: homeassistant/home-assistant
build: ./hass
image: thomasloven/home-assistant
restart: always
networks:
default:
@ -19,20 +40,24 @@ services:
iot:
lan:
volumes:
- /data/files/hass:/config
- hass:/config
- video:/media/video
- music:/media/music
- /etc/localtime:/etc/localtime:ro
environment:
WAITDB_HOST: db
WAITDB_USER: hass
WAITDB_PASS: hass
depends_on:
- db
working_dir: /config
labels:
traefik.enable: true
traefik.docker.network: web
traefik.http.services.hass.loadbalancer.server.port: 8123
traefik.http.routers.hass.rule: HOST(`${HASS_ROOT}`)
traefik.http.routers.hass.tls.certResolver: le
environment:
TZ: Europe/Stockholm
db:
image: mariadb
image: mariadb:10.4.12
restart: always
volumes:
- ./db:/var/lib/mysql
@ -44,9 +69,22 @@ services:
MYSQL_PASSWORD: hass
MYSQL_ROOT_PASSWORD: hass
dbadmin:
image: phpmyadmin
networks:
default:
web:
environment:
PMA_ARBITRARY: 1
labels:
traefik.enable: true
traefik.docker.network: web
traefik.http.routers.dbadmin.rule: HOST(`db.${HASS_ROOT}`)
traefik.http.routers.dbadmin.middlewares: auth@file
traefik.http.routers.dbadmin.tls.certResolver: le
mqtt:
image: eclipse-mosquitto:latest
image: eclipse-mosquitto:1.6
restart: always
networks:
default:
@ -55,6 +93,7 @@ services:
volumes:
- ./mqtt/data:/mosquitto/data
- ./mqtt/log:/mosquitto/log
#- ./mqtt/config:/mosquitto/config
grafana:
image: grafana/grafana
@ -70,10 +109,11 @@ services:
traefik.enable: true
traefik.docker.network: web
traefik.http.routers.grafana.rule: HOST(`grafana.${HASS_ROOT}`)
traefik.http.routers.grafana.middlewares: auth@file
traefik.http.routers.grafana.tls.certResolver: le
influx:
image: influxdb
image: influxdb:1.8
restart: always
volumes:
- ./influx:/var/lib/influxdb
@ -87,26 +127,52 @@ services:
# Devices
deconz:
image: marthoc/deconz:amd64
image: marthoc/deconz:amd64-2.05.77
restart: always
devices:
- /dev/conbee:/dev/ttyUSB0
volumes:
- ./deconz:/root/.local/share/dresden-elektronik/deCONZ
- ./deconz-otau:/root/otau
- /etc/timezone:/etc/timezone
networks:
web:
default:
# vnc:
environment:
DECONZ_VNC_MODE: 1
DECONZ_VNC_PASSWORD: secret
DEBUG_OTAU: 1
DECONZ_WEB_PORT: 8081
ports:
- 8081:8081
labels:
traefik.enable: true
traefik.docker.network: web
traefik.http.services.deconz.loadbalancer.server.port: 80
traefik.http.routers.deconz.rule: HOST(`deconz.avagen.${PRIVATE_DOMAIN}`)
traefik.http.services.deconz.loadbalancer.server.port: 8081
traefik.http.routers.deconz.rule: HOST(`deconz.${HASS_ROOT}`)
traefik.http.routers.deconz.middlewares: auth@file
traefik.http.routers.deconz.tls.certResolver: le
healthcheck:
test: curl http://localhost:5900 || exit 1
# mysensors:
# rflink:
plejd:
image: thomasloven/plejd2mqtt
restart: always
environment:
PLEJD_SITE:
PLEJD_USERNAME:
PLEJD_PASSWORD:
MQTT_BROKER: mqtt://mqtt
volumes:
- /var/run/dbus:/var/run/dbus
mobile:
image: pajikos/sms-gammu-gateway
restart: always
devices:
- /dev/gsmmodem:/dev/mobile
healthcheck:
test: ["CMD", "wget", "-O", "-", "localhost:5000/signal"]

41
hass/Dockerfile Normal file
View File

@ -0,0 +1,41 @@
ARG HASS_VERSION=latest
FROM homeassistant/home-assistant:$HASS_VERSION
RUN apk add --update-cache zbar mysql-client \
&& rm -rf /var/cache/apk/*
# Check if root
# If running as root, remove setuid and setgid flags of everything
# Then add a hass user and make that the owner of /config
# Finally, make pip install to user folders
RUN python3 -c 'import os; assert os.geteuid() == 0, "Already non-root! Skip changing user"' \
&& find / -xdev -type f -perm /u+s -exec chmod -c u-s {} \; \
&& find / -xdev -type f -perm /g+s -exec chmod -c g-s {} \; \
&& adduser -D hass \
&& addgroup hass dialout \
&& chown hass /config \
&& mkdir -p ~hass/.config/pip \
&& chown hass ~hass/.config \
&& chown hass ~hass/.config/pip \
&& echo -e '[install]\nuser = yes' > ~hass/.config/pip/pip.conf \
&& mkdir -p ~hass/.local/lib \
&& chown hass ~hass/.local \
&& chown hass ~hass/.local/lib
COPY wait-for-db.sh /home/hass/wait-for-db.sh
RUN chmod +x /home/hass/wait-for-db.sh
USER hass
# Make /config persistent even if not mounted
VOLUME /config
# Make pip cache persistent
VOLUME /home/hass/.local/lib
WORKDIR /config
# Export default port for use with routers like traefik
EXPOSE 8123/tcp
CMD ["/home/hass/wait-for-db.sh", "python3", "-m", "homeassistant", "-v", "--config", "/config"]
HEALTHCHECK CMD curl http://localhost:8123/ || exit 1

21
hass/wait-for-db.sh Normal file
View File

@ -0,0 +1,21 @@
#!/bin/bash
# wait-for-db.sh
set -e
host=${WAITDB_HOST}
user=${WAITDB_USER}
pass=${WAITDB_PASS}
echo "$host $user $pass"
if [[ -v host ]]; then
until mysql --host="$host" --user="$user" --password="$pass" -e '\q'; do
>&2 echo "Database unavailable - sleeping"
sleep 1
done
>&2 echo "Database available!"
fi
>&2 echo "Executing command"
exec "$@"