Skip to content

Add offline installation support for air-gapped devices - #537

Draft
brandonhs wants to merge 1 commit into
mainfrom
claude/quirky-einstein-w2hqy9
Draft

brandonhs wants to merge 1 commit into
mainfrom
claude/quirky-einstein-w2hqy9

Conversation

@brandonhs

Copy link
Copy Markdown
Member

Summary

Adds comprehensive offline installation and update support for DWE OS on devices without internet access. This enables deploying to air-gapped environments by building a self-contained bundle on a machine with internet, then transferring it to the target device via SSH or physical media.

The implementation includes:

  • package-offline.sh: Builds a bundle containing the release tarball, all Python wheels for the target architecture/Python version, a ttyd binary, and optional .deb packages
  • deploy-offline.sh: Orchestrates the full workflow—probes the device, builds a matching bundle, copies it over SSH, and runs the installer
  • Enhanced install-local.sh: Supports offline mode with wheelhouse and pre-built binary inputs
  • Enhanced install_requirements.sh: Handles offline system package installation and pre-built ttyd binaries
  • Enhanced create_venv.sh: Supports installing from a local wheelhouse instead of PyPI
  • Documentation: New docs/offline-update.md with detailed usage examples

Key features:

  • Automatic device probing (architecture, Python version, glibc) to ensure bundle compatibility
  • Wheel resolution with fallback to building portable wheels from source when needed
  • Support for multiple manylinux versions and platform tags
  • Validation that bundle matches device before installation
  • Virtual environment reuse across updates (only changed packages reinstalled)
  • Optional system package (.deb) bundling for environments with missing dependencies
  • Comprehensive error handling and user-friendly messaging

Fixes #[offline-install]

Type of change

  • Bug fix
  • Feature / Refactor
  • Breaking change
  • Misc.

Quick Checklist

  • I have reviewed my own code.
  • I have tested these changes locally.
  • I have tested these changes on the following platforms (optional):
    • SVC
    • microSVC (optional)
    • SVC Pro

https://claude.ai/code/session_014D18VpvYkhtJJHD47Z9viP

Devices in the field cannot reach GitHub, PyPI or a Debian mirror, but
every path through the installer assumed they could: install.sh
downloaded a release, install_requirements.sh ran apt and pulled ttyd
from GitHub, and create_venv.sh ran pip against PyPI. install-local.sh
started from a local tarball but still needed the network for the last
two, and deleted the whole install directory (venv included) on every
run, so an update could never be done without internet.

Move that requirement onto the machine doing the updating.

package-offline.sh builds a bundle on a machine that has internet: the
release tarball, every Python wheel resolved for the device's
architecture, Python version and glibc, a matching ttyd binary, and the
installer itself. pip can only cross-select wheels, so a dependency that
ships none is built here and kept only if it came out architecture
independent; anything else stops the build rather than shipping a wheel
for the wrong machine. PyEventEmitter is the current case.

deploy-offline.sh drives the whole thing over SSH: probe the device,
build a bundle for it, copy it across, install. The device makes no
outbound connection.

On the device, install-offline.sh checks the bundle against what it is
actually running before touching anything, since mismatched wheels
install cleanly and then fail at import time. install_requirements.sh
gains --offline (skip apt, take ttyd from the bundle, warn about system
packages it cannot install) and an optional --debs directory for the
rare case where a system package really has to change. create_venv.sh
gains --wheelhouse, installing with --no-index --upgrade so dependency
changes still ship with an update, pip included.

The virtual environment now survives an update instead of being rebuilt
from scratch, which is what makes an offline update practical: a repeat
run takes about a second. --recreate-venv forces the old behavior.

Along the way: install.sh and the offline path now share one installer,
releases carry install-local.sh and a VERSION file, install-local.sh
unpacks to a temporary directory rather than the caller's working
directory, the service is stopped before files are swapped under it
rather than after, and the final message reports the version actually
installed instead of an unset variable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014D18VpvYkhtJJHD47Z9viP
@brandonhs

Copy link
Copy Markdown
Member Author

Slop PR, dont judge me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants