# LXC installation and update This document describes the supported Debian/Ubuntu systemd deployment used for LXC testing. ## First installation Unpack the source archive inside the container and run: ```bash cd gree-controller chmod +x scripts/*.sh sudo ./scripts/install.sh ``` The installer: 1. installs required build packages when missing, 2. installs stable Rust with rustup when Cargo is unavailable, 3. runs `cargo test --all-targets`, 4. builds `target/release/gree-controller`, 5. creates the `gree-controller` system user/group, 6. creates `/var/lib/gree-controller`, `/opt/gree-controller` and `/var/backups/gree-controller`, 7. installs the systemd unit, 8. creates `/etc/gree-controller.env` only when it does not already exist, 9. enables/restarts the service, 10. verifies `GET /api/health`. Installed state is intentionally outside the extracted source directory: ```text /opt/gree-controller/gree-controller installed binary /etc/gree-controller.env persistent configuration/secrets /var/lib/gree-controller/gree-controller.db persistent SQLite database /var/backups/gree-controller/ update backups /etc/systemd/system/gree-controller.service systemd service ``` The default installation starts in simulator mode. Change `GREE_CONTROLLER_SIMULATE=false` and `GREE_CONTROLLER_AUTO_SEED=false` in `/etc/gree-controller.env` when moving to physical units, then restart the service. ## Update Unpack a newer source archive and run from that new directory: ```bash sudo ./scripts/update.sh ``` The update workflow is designed to minimize downtime and preserve the database: 1. build dependencies/Rust are checked, 2. tests run while the currently installed controller stays online, 3. the new release binary is built while the old service stays online, 4. the service is stopped, 5. the installed binary, service unit, environment file and SQLite database are copied to `/var/backups/gree-controller//`, 6. the new binary/unit is installed, 7. systemd starts the new version, 8. `/api/health` is checked, 9. on failure the old binary, unit and database are restored automatically. The updater does not overwrite `/etc/gree-controller.env` during a successful update. Use `--skip-tests` only for deliberate fast testing: ```bash sudo ./scripts/update.sh --skip-tests ``` ## Service helper ```bash ./scripts/service.sh status ./scripts/service.sh health ./scripts/service.sh logs sudo ./scripts/service.sh restart sudo ./scripts/service.sh stop sudo ./scripts/service.sh start ``` Equivalent native commands remain available: ```bash systemctl status gree-controller journalctl -u gree-controller -f ``` ## Configuration Edit: ```text /etc/gree-controller.env ``` and restart: ```bash sudo ./scripts/service.sh restart ``` Do not store controller or Home Assistant secrets in the source tree. ## Database and SQL layout Runtime persistence uses SQLite. All schema definitions and SQL statements in the Rust application are centralized in: ```text src/queries.rs ``` `src/db.rs` contains connection/transaction logic and maps database rows to Rust domain models, but it does not embed SQL statements. ## Two network interfaces When the LXC has a management interface and a dedicated GREE network, configure the service environment explicitly. Example for `eth1` on `10.87.65.0/25`: ```env GREE_CONTROLLER_GREE_INTERFACE=eth1 GREE_CONTROLLER_DISCOVERY_BROADCAST=auto This explicit interface configuration is recommended for predictable LXC deployments. Version 0.3.7 also automatically selects the directly connected local IPv4 address for a GREE device when the interface variable is omitted; for example, a target in `10.87.65.0/25` selects the local address on that subnet. GREE_CONTROLLER_SIMULATE=false GREE_CONTROLLER_AUTO_SEED=false ``` Restart the service after editing `/etc/gree-controller.env`: ```bash systemctl restart gree-controller journalctl -u gree-controller -n 100 --no-pager ``` During discovery the log should contain a line similar to: ```text Starting GREE discovery target=10.87.65.127:7000 local=10.87.65.27: interface=eth1 ``` Use `scripts/network-debug.sh` for routing diagnostics. ## Mixed GREE model generations Version 0.3.7 can discover both AES-ECB and AES-GCM modules. In the Web UI choose **Discover -> Auto (V1 + V2)** and use 3-5 scan passes. If a family is still missing, repeat with V1-only and V2-only to see which protocol its Wi-Fi module answers with. A single command/status timeout no longer immediately flips a device offline; offline requires three consecutive communication failures. ## Multi-NIC LXC and AF_NETLINK When `GREE_CONTROLLER_GREE_INTERFACE` is set, the controller enumerates IPv4 addresses with Linux `getifaddrs()`. On Linux this requires a Netlink socket. The systemd sandbox therefore allows `AF_NETLINK` in addition to `AF_UNIX`, `AF_INET`, and `AF_INET6`. If an older unit reports: ```text getifaddrs failed Address family not supported by protocol (os error 97) ``` update the systemd unit or add `AF_NETLINK` to `RestrictAddressFamilies`, then run: ```bash systemctl daemon-reload systemctl restart gree-controller ``` For a dedicated GREE NIC such as `eth1`, the expected startup/bind log should identify the IPv4 address of that interface instead of `0.0.0.0`. ### Legacy V1 devices discovered but not binding Version 0.3.8 sends the GREE protocol `tcid` and inner `mac` identifiers in canonical lowercase hexadecimal. If an older `502cc6...` device is discovered on UDP/7000 but stays offline after bind timeouts, update to v0.3.8 before changing routing or firewall settings. With debug logging, `Sending GREE request` should show `wire_mac=502cc6...` in lowercase. ## Home Assistant HTTPS with a self-signed certificate The optional outbound HA sensor client validates TLS certificates by default. For a trusted local endpoint such as `https://10.87.65.2` that uses a self-signed, expired or hostname-mismatched certificate, enable **Settings -> Allow invalid/self-signed HTTPS certificate** and save. The same initial setting can be supplied as `HA_ALLOW_INVALID_TLS=true`. This opt-in affects only controller -> Home Assistant sensor requests. It does not change the GREE UDP transport and it does not add HTTPS termination to the controller itself.