
A systemd service may be marked as enabled as vendor preset, and this breaks the check we used to check if it was active. Here's what you get in an Ubuntu 20.04 installation: ❯ sudo systemctl status ModemManager ● ModemManager.service - Modem Manager Loaded: loaded (/lib/systemd/system/ModemManager.service; disabled; vendor preset: enabled) Active: inactive (dead) ❯ systemctl list-unit-files ModemManager.service UNIT FILE STATE VENDOR PRESET ModemManager.service disabled enabled 1 unit files listed While the list-unit-files can be filtered using `--state=enabled`, we can just rely on `systemctl is-enabled` instead.
262 lines
8.2 KiB
Bash
262 lines
8.2 KiB
Bash
#!/usr/bin/env bash
|
|
set -e
|
|
|
|
declare -a MISSING_PACKAGES
|
|
|
|
function info { echo -e "\e[32m[info] $*\e[39m"; }
|
|
function warn { echo -e "\e[33m[warn] $*\e[39m"; }
|
|
function error { echo -e "\e[31m[error] $*\e[39m"; exit 1; }
|
|
|
|
warn ""
|
|
warn "If you want more control over your own system, run"
|
|
warn "Home Assistant as a VM or run Home Assistant Core"
|
|
warn "via a Docker container."
|
|
warn ""
|
|
warn "If you want to abort, hit ctrl+c within 10 seconds..."
|
|
warn ""
|
|
|
|
sleep 10
|
|
|
|
ARCH=$(uname -m)
|
|
|
|
IP_ADDRESS=$(hostname -I | awk '{ print $1 }')
|
|
|
|
BINARY_DOCKER=/usr/bin/docker
|
|
|
|
DOCKER_REPO=homeassistant
|
|
|
|
SERVICE_DOCKER="docker.service"
|
|
SERVICE_NM="NetworkManager.service"
|
|
|
|
FILE_DOCKER_CONF="/etc/docker/daemon.json"
|
|
FILE_INTERFACES="/etc/network/interfaces"
|
|
FILE_NM_CONF="/etc/NetworkManager/NetworkManager.conf"
|
|
FILE_NM_CONNECTION="/etc/NetworkManager/system-connections/default"
|
|
|
|
URL_RAW_BASE="https://raw.githubusercontent.com/home-assistant/supervised-installer/master/files"
|
|
URL_VERSION="https://version.home-assistant.io/stable.json"
|
|
URL_BIN_APPARMOR="${URL_RAW_BASE}/hassio-apparmor"
|
|
URL_BIN_HASSIO="${URL_RAW_BASE}/hassio-supervisor"
|
|
URL_DOCKER_DAEMON="${URL_RAW_BASE}/docker_daemon.json"
|
|
URL_HA="${URL_RAW_BASE}/ha"
|
|
URL_INTERFACES="${URL_RAW_BASE}/interfaces"
|
|
URL_NM_CONF="${URL_RAW_BASE}/NetworkManager.conf"
|
|
URL_NM_CONNECTION="${URL_RAW_BASE}/system-connection-default"
|
|
URL_SERVICE_APPARMOR="${URL_RAW_BASE}/hassio-apparmor.service"
|
|
URL_SERVICE_HASSIO="${URL_RAW_BASE}/hassio-supervisor.service"
|
|
URL_APPARMOR_PROFILE="https://version.home-assistant.io/apparmor.txt"
|
|
|
|
# Check env
|
|
command -v systemctl > /dev/null 2>&1 || MISSING_PACKAGES+=("systemd")
|
|
command -v nmcli > /dev/null 2>&1 || MISSING_PACKAGES+=("network-manager")
|
|
command -v apparmor_parser > /dev/null 2>&1 || MISSING_PACKAGES+=("apparmor")
|
|
command -v docker > /dev/null 2>&1 || MISSING_PACKAGES+=("docker")
|
|
command -v jq > /dev/null 2>&1 || MISSING_PACKAGES+=("jq")
|
|
command -v curl > /dev/null 2>&1 || MISSING_PACKAGES+=("curl")
|
|
command -v dbus-daemon > /dev/null 2>&1 || MISSING_PACKAGES+=("dbus")
|
|
|
|
|
|
if [ ! -z "${MISSING_PACKAGES}" ]; then
|
|
warn "The following is missing on the host and needs "
|
|
warn "to be installed and configured before running this script again"
|
|
error "missing: ${MISSING_PACKAGES[@]}"
|
|
fi
|
|
|
|
# Check if Modem Manager is enabled
|
|
if systemctl is-enabled ModemManager.service &> /dev/null; then
|
|
warn "ModemManager service is enabled. This might cause issue when using serial devices."
|
|
fi
|
|
|
|
# Detect wrong docker logger config
|
|
if [ ! -f "$FILE_DOCKER_CONF" ]; then
|
|
# Write default configuration
|
|
info "Creating default docker daemon configuration $FILE_DOCKER_CONF"
|
|
curl -sL ${URL_DOCKER_DAEMON} > "${FILE_DOCKER_CONF}"
|
|
|
|
# Restart Docker service
|
|
info "Restarting docker service"
|
|
systemctl restart "$SERVICE_DOCKER"
|
|
else
|
|
STORAGE_DRIVER=$(docker info -f "{{json .}}" | jq -r -e .Driver)
|
|
LOGGING_DRIVER=$(docker info -f "{{json .}}" | jq -r -e .LoggingDriver)
|
|
if [[ "$STORAGE_DRIVER" != "overlay2" ]]; then
|
|
warn "Docker is using $STORAGE_DRIVER and not 'overlay2' as the storage driver, this is not supported."
|
|
fi
|
|
if [[ "$LOGGING_DRIVER" != "journald" ]]; then
|
|
warn "Docker is using $LOGGING_DRIVER and not 'journald' as the logging driver, this is not supported."
|
|
fi
|
|
fi
|
|
|
|
# Check dmesg access
|
|
if [[ "$(sysctl --values kernel.dmesg_restrict)" != "0" ]]; then
|
|
info "Fix kernel dmesg restriction"
|
|
echo 0 > /proc/sys/kernel/dmesg_restrict
|
|
echo "kernel.dmesg_restrict=0" >> /etc/sysctl.conf
|
|
fi
|
|
|
|
# Create config for NetworkManager
|
|
info "Creating NetworkManager configuration"
|
|
curl -sL "${URL_NM_CONF}" > "${FILE_NM_CONF}"
|
|
if [ ! -f "$FILE_NM_CONNECTION" ]; then
|
|
curl -sL "${URL_NM_CONNECTION}" > "${FILE_NM_CONNECTION}"
|
|
fi
|
|
|
|
warn "Changes are needed to the /etc/network/interfaces file"
|
|
info "If you have modified the network on the host manualy, those can now be overwritten"
|
|
info "If you do not overwrite this now you need to manually adjust it later"
|
|
info "Do you want to proceed with overwriting the /etc/network/interfaces file? [N/y] "
|
|
read answer < /dev/tty
|
|
|
|
if [[ "$answer" =~ "y" ]] || [[ "$answer" =~ "Y" ]]; then
|
|
info "Replacing /etc/network/interfaces"
|
|
curl -sL "${URL_INTERFACES}" > "${FILE_INTERFACES}";
|
|
fi
|
|
|
|
info "Restarting NetworkManager"
|
|
systemctl restart "${SERVICE_NM}"
|
|
|
|
# Parse command line parameters
|
|
while [[ $# -gt 0 ]]; do
|
|
arg="$1"
|
|
|
|
case $arg in
|
|
-m|--machine)
|
|
MACHINE=$2
|
|
shift
|
|
;;
|
|
-d|--data-share)
|
|
DATA_SHARE=$2
|
|
shift
|
|
;;
|
|
-p|--prefix)
|
|
PREFIX=$2
|
|
shift
|
|
;;
|
|
-s|--sysconfdir)
|
|
SYSCONFDIR=$2
|
|
shift
|
|
;;
|
|
*)
|
|
error "Unrecognized option $1"
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
PREFIX=${PREFIX:-/usr}
|
|
SYSCONFDIR=${SYSCONFDIR:-/etc}
|
|
DATA_SHARE=${DATA_SHARE:-$PREFIX/share/hassio}
|
|
CONFIG=$SYSCONFDIR/hassio.json
|
|
|
|
# Generate hardware options
|
|
case $ARCH in
|
|
"i386" | "i686")
|
|
MACHINE=${MACHINE:=qemux86}
|
|
HASSIO_DOCKER="$DOCKER_REPO/i386-hassio-supervisor"
|
|
;;
|
|
"x86_64")
|
|
MACHINE=${MACHINE:=qemux86-64}
|
|
HASSIO_DOCKER="$DOCKER_REPO/amd64-hassio-supervisor"
|
|
;;
|
|
"arm" |"armv6l")
|
|
if [ -z $MACHINE ]; then
|
|
error "Please set machine for $ARCH"
|
|
fi
|
|
HASSIO_DOCKER="$DOCKER_REPO/armhf-hassio-supervisor"
|
|
;;
|
|
"armv7l")
|
|
if [ -z $MACHINE ]; then
|
|
error "Please set machine for $ARCH"
|
|
fi
|
|
HASSIO_DOCKER="$DOCKER_REPO/armv7-hassio-supervisor"
|
|
;;
|
|
"aarch64")
|
|
if [ -z $MACHINE ]; then
|
|
error "Please set machine for $ARCH"
|
|
fi
|
|
HASSIO_DOCKER="$DOCKER_REPO/aarch64-hassio-supervisor"
|
|
;;
|
|
*)
|
|
error "$ARCH unknown!"
|
|
;;
|
|
esac
|
|
|
|
if [[ ! "${MACHINE}" =~ ^(intel-nuc|odroid-c2|odroid-n2|odroid-xu|qemuarm|qemuarm-64|qemux86|qemux86-64|raspberrypi|raspberrypi2|raspberrypi3|raspberrypi4|raspberrypi3-64|raspberrypi4-64|tinker)$ ]]; then
|
|
error "Unknown machine type ${MACHINE}!"
|
|
fi
|
|
|
|
### Main
|
|
|
|
# Init folders
|
|
if [ ! -d "$DATA_SHARE" ]; then
|
|
mkdir -p "$DATA_SHARE"
|
|
fi
|
|
|
|
# Read infos from web
|
|
HASSIO_VERSION=$(curl -s $URL_VERSION | jq -e -r '.supervisor')
|
|
|
|
##
|
|
# Write configuration
|
|
cat > "$CONFIG" <<- EOF
|
|
{
|
|
"supervisor": "${HASSIO_DOCKER}",
|
|
"machine": "${MACHINE}",
|
|
"data": "${DATA_SHARE}"
|
|
}
|
|
EOF
|
|
|
|
##
|
|
# Pull supervisor image
|
|
info "Install supervisor Docker container"
|
|
docker pull "$HASSIO_DOCKER:$HASSIO_VERSION" > /dev/null
|
|
docker tag "$HASSIO_DOCKER:$HASSIO_VERSION" "$HASSIO_DOCKER:latest" > /dev/null
|
|
|
|
##
|
|
# Install Hass.io Supervisor
|
|
info "Install supervisor startup scripts"
|
|
curl -sL ${URL_BIN_HASSIO} > "${PREFIX}/sbin/hassio-supervisor"
|
|
curl -sL ${URL_SERVICE_HASSIO} > "${SYSCONFDIR}/systemd/system/hassio-supervisor.service"
|
|
|
|
sed -i "s,%%HASSIO_CONFIG%%,${CONFIG},g" "${PREFIX}"/sbin/hassio-supervisor
|
|
sed -i -e "s,%%BINARY_DOCKER%%,${BINARY_DOCKER},g" \
|
|
-e "s,%%SERVICE_DOCKER%%,${SERVICE_DOCKER},g" \
|
|
-e "s,%%BINARY_HASSIO%%,${PREFIX}/sbin/hassio-supervisor,g" \
|
|
"${SYSCONFDIR}/systemd/system/hassio-supervisor.service"
|
|
|
|
chmod a+x "${PREFIX}/sbin/hassio-supervisor"
|
|
systemctl enable hassio-supervisor.service > /dev/null 2>&1;
|
|
|
|
#
|
|
# Install Hass.io AppArmor
|
|
info "Install AppArmor scripts"
|
|
mkdir -p "${DATA_SHARE}/apparmor"
|
|
curl -sL ${URL_BIN_APPARMOR} > "${PREFIX}/sbin/hassio-apparmor"
|
|
curl -sL ${URL_SERVICE_APPARMOR} > "${SYSCONFDIR}/systemd/system/hassio-apparmor.service"
|
|
curl -sL ${URL_APPARMOR_PROFILE} > "${DATA_SHARE}/apparmor/hassio-supervisor"
|
|
|
|
sed -i "s,%%HASSIO_CONFIG%%,${CONFIG},g" "${PREFIX}/sbin/hassio-apparmor"
|
|
sed -i -e "s,%%SERVICE_DOCKER%%,${SERVICE_DOCKER},g" \
|
|
-e "s,%%HASSIO_APPARMOR_BINARY%%,${PREFIX}/sbin/hassio-apparmor,g" \
|
|
"${SYSCONFDIR}/systemd/system/hassio-apparmor.service"
|
|
|
|
chmod a+x "${PREFIX}/sbin/hassio-apparmor"
|
|
systemctl enable hassio-apparmor.service > /dev/null 2>&1;
|
|
systemctl start hassio-apparmor.service
|
|
|
|
|
|
##
|
|
# Init system
|
|
info "Start Home Assistant Supervised"
|
|
systemctl start hassio-supervisor.service
|
|
|
|
##
|
|
# Setup CLI
|
|
info "Installing the 'ha' cli"
|
|
curl -sL ${URL_HA} > "${PREFIX}/bin/ha"
|
|
chmod a+x "${PREFIX}/bin/ha"
|
|
|
|
info
|
|
info "Home Assistant supervised is now installed"
|
|
info "First setup will take some time, when it's ready you can reach it here:"
|
|
info "http://${IP_ADDRESS}:8123"
|
|
info
|