Skip to content

feat(snap): ship the VM driver in the snap and use it by default - #4627

Open
olivercalder wants to merge 5 commits into
NVIDIA:mainfrom
olivercalder:snap-ship-vm-driver
Open

olivercalder wants to merge 5 commits into
NVIDIA:mainfrom
olivercalder:snap-ship-vm-driver

Conversation

@olivercalder

Copy link
Copy Markdown
Contributor

Summary

Ship the VM driver in the OpenShell snap package. This means the snap no longer needs to depend on a Docker daemon being already present at install time. Instead, the snap should now work out of the box on its own, and users can still opt to use a different compute driver if desired.

Related Issue

Closes #4625

Changes

  • Bundles the standalone VM compute driver in the OpenShell snap.
  • Adds e2fsprogs utilities required to create and modify VM-backed ext4 disks under strict snap confinement.
  • Connects the kvm interface for both system and user gateway services.
  • Makes the bundled VM driver the snap default when no compute driver is explicitly selected through the service environment or gateway TOML.
  • Preserves explicit driver selections from OPENSHELL_COMPUTE_DRIVER, gateway configuration, and the legacy OPENSHELL_DRIVERS variable.
  • Replaces the snap installer’s Docker prerequisite and readiness checks with non-blocking kvm access checks and remediation guidance.
  • Allows gateway registration and status operations without kvm access while warning that VM sandbox creation will fail.
  • Changes the release canary from a system-Docker snap test to a VM-backed snap test on a kvm-capable runner.
  • Removes obsolete canary coverage for missing Docker and the incompatible Docker snap.

Testing

  • Checks appropriate to the affected code and behavior pass
  • Unit tests added/updated (if applicable)
  • E2E tests added/updated (if applicable)

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

@copy-pr-bot

copy-pr-bot Bot commented Oct 15, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@olivercalder

Copy link
Copy Markdown
Contributor Author

This is intended to supersede #2894

- Bundles the standalone VM compute driver in the OpenShell snap.
- Adds e2fsprogs utilities required to create and modify VM-backed ext4
  disks under strict snap confinement.
- Connects the kvm interface for both system and user gateway services.
- Makes the bundled VM driver the snap default when no compute driver is
  explicitly selected through the service environment or gateway TOML.
- Preserves explicit driver selections from OPENSHELL_COMPUTE_DRIVER,
  gateway configuration, and the legacy OPENSHELL_DRIVERS variable.
- Replaces the snap installer’s Docker prerequisite and readiness checks
  with non-blocking kvm access checks and remediation guidance.
- Allows gateway registration and status operations without kvm access
  while warning that VM sandbox creation will fail.
- Changes the release canary from a system-Docker snap test to a
  VM-backed snap test on a kvm-capable runner.
- Removes obsolete canary coverage for missing Docker and the
  incompatible Docker snap.

Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
…o-connected

The Snap Store assertion request for the `openshell` snap to
auto-connect the `kvm` (and `podman`) interfaces was granted:

https://forum.snapcraft.io/t/privileged-interface-request-for-openshell-podman-and-kvm/53663

Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
…e gateway user

Signed-off-by: Oliver Calder <oliver.calder@canonical.com>
…ferences

Signed-off-by: Oliver Calder <oliver.calder@canonical.com>

@krishicks krishicks left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Written by Claude Code, reviewed by @krishicks.

Thanks for this. Bundling the VM driver so the snap works without Docker is a big improvement, and #4812 builds on it well. I'm deliberately keeping this review to the minimum needed to merge a working first pass; everything else can be follow-up issues. There are three blocking items, two of them as inline comments:

  1. kvm isn't connected (inline on install.sh). The kvm interface doesn't connect automatically without a Snap Store grant, and nothing in the installer connects it, so Store installs probably end up with the new default unusable.

  2. Existing Docker users get switched to VM (inline on snap-gateway-wrapper.sh). After a refresh and restart, existing snap gateways move from Docker to VM, and the gateway then prunes their sandbox records.

  3. Please run the confined VM path once before merge. CI hasn't run on this PR, and the ubuntu-snap-vm canary only runs after Release Dev has published to latest/edge. Could you do one manual pass on a KVM host and post the output?

    sudo snap install ./openshell_*.snap --dangerous
    sudo snap connect openshell:kvm
    snap run --shell openshell.user-gateway -c 'mke2fs -V && debugfs -V && e2fsck -V'
    openshell sandbox create --name snap-vm-check --detach
    openshell sandbox exec --name snap-vm-check --no-tty -- true
    openshell sandbox delete snap-vm-check

    The canary only checks command -v for the e2fsprogs tools. Snapcraft doesn't set LD_LIBRARY_PATH for core24, so I want to confirm the staged libext2fs and related libraries actually load. If they don't, the gateway preflight probe would stop the gateway from starting.

Non-blocking items to file as follow-ups:

  • The /dev/kvm check in the wrapper uses access(), which ignores AppArmor, so it passes even when the plug is disconnected.
  • On hosts with no KVM access and no other runtime, install.sh fails with a generic listener timeout instead of saying why.
  • The compute_driver grep in the wrapper misses dotted keys under [openshell] and inline tables. When it misses, the environment variable overrides the explicit TOML setting.

Comment thread install.sh
export OPENSHELL_GATEWAY_CONFIG="$OPENSHELL_SNAP_CONFIG_FILE"
fi

# The snap prefers the bundled VM driver when KVM is usable. Preserve an

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking. This changes the driver for existing snap installs. Before this PR, snap users had to have Docker, and almost nobody set compute_driver, so their gateways auto-detected Docker. After a refresh, the next restart sets OPENSHELL_COMPUTE_DRIVER=vm whenever /dev/kvm is readable and writable. refresh-mode: endure only delays this until the next reboot or login; install.sh restarts the gateway right away. Then the reconcile sweep (prune_missing_sandbox, crates/openshell-server/src/compute/mod.rs) deletes every sandbox record that the VM driver doesn't report, once the 5-minute grace period passes, and the Docker containers keep running unmanaged.

There's a related problem. The choice is re-evaluated on every start, and logind's /dev/kvm ACL only exists while the user has an active local session. So a lingering gateway that starts at boot picks a different driver than one restarted after login, and each change prunes the other driver's sandbox records.

Suggested minimal fix: make the decision once per state directory and remember it. Existing installs keep auto-detection; fresh installs get vm. Untested sketch:

if [ -z "${OPENSHELL_COMPUTE_DRIVER+x}" ] \
    && [ -z "${OPENSHELL_DRIVERS+x}" ]
then
    # ... existing config_file discovery unchanged ...

    if [ -n "${OPENSHELL_DB_URL:-}" ]; then
        db_file=${OPENSHELL_DB_URL#sqlite:}
        db_file=${db_file%%\?*}
        state_dir=$(dirname "$db_file")
    else
        state_dir="${XDG_STATE_HOME}/openshell/gateway"
        db_file="${state_dir}/openshell.db"
    fi
    default_file="${state_dir}/snap-default-compute-driver"

    if [ ! -f "$default_file" ]; then
        mkdir -p "$state_dir"
        if [ -e "$db_file" ]; then
            # Existing install: keep the pre-VM auto-detection behavior.
            echo auto >"$default_file"
        elif [ -r "$kvm_device" ] && [ -w "$kvm_device" ]; then
            echo vm >"$default_file"
        else
            echo auto >"$default_file"
        fi
    fi

    if <no compute_driver in config_file (existing grep)> \
        && [ "$(cat "$default_file")" = vm ]
    then
        export OPENSHELL_COMPUTE_DRIVER=vm
    fi
fi

This also means #4812's Podman support can't silently take over existing installs: auto-detection tries Podman before Docker, so an existing Docker user who also has Podman would otherwise move to Podman on the next fallback restart.

If we'd rather not carry this logic, a release note telling existing snap users to set compute_driver = "docker" in ~/snap/openshell/common/.config/openshell/gateway.toml before refreshing would also work. That depends on how many people are on latest/stable today.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion, I like the check once, write value to snap user data, then use it in the future. A release note doesn't really help because of automatic refreshes.

I think I've figured out what we really want:

  1. If the default file already exists, use whatever it says (unless there's a real TOML config value)
  2. If this is the first run after a clean install, then write vm to the default file and use it in the future
  3. If this is the first run after a refresh, write docker to the default file and use it

This would be accomplished nicely by the install/post-refresh hooks, except that those hooks run as root at the system level, and users could have different drivers and gateways. But I have an idea: We know whether a user gateway has run before based on whether it has mTLS credentials generated in the user gateway config directory. So if certs don't exist yet, we can assume it's a fresh install or at least fresh user gateway, and set vm in the defaults file. If there are already certs then we can assume it's been run before with the docker driver and write docker in the defaults file and do that.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds good to me.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've created #4844 which we may prefer rather than doing a snap-specific driver-caching mechanism here.

This branch has not been deployed

No deployments
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.

packaging(snap): ship the VM driver in the snap package

2 participants