diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..a55f4b9 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +.git +.venv +.pytest_cache +.ruff_cache +*.egg-info +__pycache__ +tests/ +.coverage +*.db diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8cb86ee --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM python:3.12-slim + +RUN apt-get update \ + && apt-get install -y --no-install-recommends libdbus-1-3 \ + && rm -rf /var/lib/apt/lists/* + +COPY . /app +RUN pip install --no-cache-dir /app \ + && chmod +x /app/entrypoint.sh + +RUN useradd -u 1000 -m tado +USER tado + +VOLUME /data +EXPOSE 4407 + +ENTRYPOINT ["/app/entrypoint.sh"] diff --git a/INSTALLATION.md b/INSTALLATION.md index d058163..4b1bd90 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -59,6 +59,58 @@ pip install . pip install git+https://github.com/ampscm/TadoLocal.git ``` +### Method 4: Container (Docker/Podman) + +Run TadoLocal in a container — no Python install required. Works on any platform +with Docker or Podman, including NAS devices and Raspberry Pi (ARM). + +#### Build + +```bash +# From the project directory +docker build -t tado-local . + +# Or with Podman +podman build -t tado-local . +``` + +#### First-time pairing + +The bridge PIN is only needed for the initial pairing. The pairing database is +persisted in the `/data` volume so it survives container restarts. + +```bash +docker run -d --name tado-local \ + -p 4407:4407 \ + -v tado-data:/data \ + -e TADO_BRIDGE_IP=192.168.1.100 \ + -e TADO_BRIDGE_PIN=123-45-678 \ + tado-local +``` + +#### Subsequent runs + +Once paired, `TADO_BRIDGE_PIN` can be omitted: + +```bash +docker run -d --name tado-local \ + -p 4407:4407 \ + -v tado-data:/data \ + -e TADO_BRIDGE_IP=192.168.1.100 \ + tado-local +``` + +#### Environment variables + +| Variable | Required | Description | +|---|---|---| +| `TADO_BRIDGE_IP` | Yes (first run) | IP address of your Tado bridge | +| `TADO_BRIDGE_PIN` | First pairing only | HomeKit PIN printed on the bridge | +| `TADO_PORT` | No (default `4407`) | Port the API listens on inside the container | + +> **Tip:** Replace `docker` with `podman` in all commands above if using Podman. +> The image is multi-arch and works on both AMD64 and ARM64. + ## Usage After installation, you can run the proxy in multiple ways: @@ -132,7 +184,6 @@ pip uninstall tado-local **Future Work**: 📋 - Comprehensive test suite -- Add Docker support - Publish to PyPI - CI/CD pipeline diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..9b87674 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,37 @@ +#!/bin/sh +set -e + +STATE_DB="/data/tado-local.db" + +if [ -z "$TADO_BRIDGE_IP" ] && [ ! -f "$STATE_DB" ]; then + echo "No TADO_BRIDGE_IP set and no existing pairing DB found at $STATE_DB." + echo "Set TADO_BRIDGE_IP (and TADO_BRIDGE_PIN for first pairing) then restart." + echo "Sleeping to keep container alive for debugging..." + exec sleep infinity +fi + +ARGS="--state $STATE_DB --port ${TADO_PORT:-4407}" + +if [ -n "$TADO_BRIDGE_IP" ]; then + ARGS="$ARGS --bridge-ip $TADO_BRIDGE_IP" +fi + +if [ -n "$TADO_BRIDGE_PIN" ]; then + ARGS="$ARGS --pin $TADO_BRIDGE_PIN" +fi + +# Forward-compatible: PR #40 accessory support (comma-separated IPs and PINs) +if [ -n "$TADO_ACCESSORY_IP" ]; then + IFS=',' + set -- $TADO_ACCESSORY_IP + idx=0 + for ip in "$@"; do + pin=$(echo "$TADO_ACCESSORY_PIN" | cut -d',' -f$((idx + 1))) + ARGS="$ARGS --accessory-ip $ip" + [ -n "$pin" ] && ARGS="$ARGS --accessory-pin $pin" + idx=$((idx + 1)) + done + unset IFS +fi + +exec tado-local $ARGS