Community container (release candidate)

The container packages the Community server, dashboard, CLI/MCP assets, Maestro 2.6.1, Java, Android platform tools and scrcpy. Community runs one active device per installation. This guide does not change Pro licensing.

The initial target is Linux amd64 with USB-connected Android phones. Docker Desktop can validate startup but is not a substitute for Linux USB testing. Images are not yet published; build locally from this checkout. Hardware acceptance and final attribution review remain release conditions.

Prepare the host

Use Docker Engine with the Compose plugin. Set up a host group named deviceyard-usb and a udev rule granting it read/write access to the specific Android devices you intend to use. For example, adapt the vendor and product IDs below from lsusb; do not grant access to unrelated USB devices:

SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTR{idVendor}=="<vendor-id>", ATTR{idProduct}=="<product-id>", MODE="0660", GROUP="deviceyard-usb"

Install the rule under /etc/udev/rules.d/, reload the rules, and reconnect the intended idle phone. Enable USB debugging and accept its authorization prompt. Obtain the group's numeric GID with getent group deviceyard-usb and set DEVICEYARD_USB_GID to that GID. The runtime user has UID/GID 1000; the additional USB group grants access without privileged mode. Rootless Docker and user-namespace remapping need additional permission mapping and are not part of this initial supported configuration.

The container owns its ADB daemon. Stop conflicting host ADB use only after coordinating with other users of the device. It listens inside the container on 127.0.0.1:5037; never publish that port. Both CLI operations and scrcpy use this same daemon.

Supply configuration

Create a private env file outside the checkout, readable only by its owner (mode 0600). Supply the variables below with your own values:

  • DEVICE_ID: the Android serial, used for initial device registration.
  • TOKENS_JSON: {} for no initial organization-token seeding.
  • ADMIN_USERNAME, ADMIN_EMAIL, ADMIN_PASSWORD: initial administrator.
  • SESSION_SECRET: at least 32 characters, generated securely.
  • TOKEN_ENCRYPTION_KEY: exactly 64 hexadecimal characters, generated securely.

See operating for additional settings. Generate credentials with your password manager or secret manager. Keep the encryption key stable across upgrades and back it up securely with the data. Do not paste resolved Compose configuration or docker inspect environment output into tickets.

Set DEVICEYARD_ENV_FILE to the absolute path of that file. Compose fixes the application data path to /data, HOME to /home/deviceyard, and the internal HTTP port to 8080 so they match its volumes and port mapping.

docker compose -f ci/container/compose.yaml config --quiet
docker compose -f ci/container/compose.yaml up --build -d
docker compose -f ci/container/compose.yaml exec deviceyard adb devices

Open http://127.0.0.1:8080 and select the active device in the dashboard. DEVICEYARD_HTTP_PORT changes the loopback host port. Put an HTTPS reverse proxy in front for remote access; the Compose default does not expose HTTP to the LAN. The image health check verifies HTTP availability, not whether a phone is connected. Unauthorized/offline phones appear through the normal device status behavior.

Persistence and upgrades

Compose creates separate data and adb-identity named volumes. A new named volume inherits the image directory's ownership. Existing volumes must be writable by UID 1000; the entrypoint does not recursively chown operator data. The data volume holds SQLite and job artifacts; the ADB volume holds device authorization keys. Treat both as private. Do not use down --volumes for an upgrade: that deletes persistent state.

Drain running work, stop the service, and back up both volumes plus the private runtime configuration before upgrading. Use a consistent stopped database backup. Recreate the container with a tested image, retaining the same Compose project name and volumes. For rollback, retain the prior image and compatible backup; do not assume an older binary supports a newer database schema.

Once published, DEVICEYARD_IMAGE will accept an approved version or digest from ghcr.io/nmehlei/deviceyard; use up --no-build for a prebuilt image. Until then, the default local image name is intentional. Use only one runner container per data volume. Container builds do not alter the existing systemd farm deployment or updater.

Validation and notices

docker build --platform linux/amd64 -f ci/container/Dockerfile -t deviceyard-community:test .
node ci/container/smoke.cjs deviceyard-community:test

The smoke harness creates and removes its own containers and volumes; it never attaches USB devices. It checks tools, non-root execution, Community identity, persistent login and ADB identity, graceful stop, and sanitized configuration failures. Real-device acceptance additionally requires APK installation, a Maestro flow, screenshot/control and unplug/replug on Linux.

Runtime notice locations and exact OS package versions are recorded under /opt/deviceyard/notices. Test APKs and development dependencies are excluded from the runtime image. See publication audit for remaining source and redistribution checks.

View this page on GitHub ↗ · nmehlei/DeviceYard