Files
gree-controller/docs/LXC.md
T
2026-08-23 22:31:30 +02:00

5.6 KiB

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:

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:

/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:

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/<UTC timestamp>/,
  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:

sudo ./scripts/update.sh --skip-tests

Service helper

./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:

systemctl status gree-controller
journalctl -u gree-controller -f

Configuration

Edit:

/etc/gree-controller.env

and restart:

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:

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:

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:

systemctl restart gree-controller
journalctl -u gree-controller -n 100 --no-pager

During discovery the log should contain a line similar to:

Starting GREE discovery target=10.87.65.127:7000 local=10.87.65.27:<ephemeral> 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.

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:

getifaddrs failed
Address family not supported by protocol (os error 97)

update the systemd unit or add AF_NETLINK to RestrictAddressFamilies, then run:

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.