fix(install): drop podman as hard dependency for RPM installation#2137
fix(install): drop podman as hard dependency for RPM installation#2137pimlock wants to merge 10 commits into
Conversation
Remove Podman package and service coupling, rely on existing runtime detection, and surface actionable installer startup diagnostics. Document runtime prerequisites and VM packaging across install methods. Closes #2007 Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
|
🌿 Preview your docs: https://nvidia-preview-pr-2137.docs.buildwithfern.com/openshell |
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
|
Addressed the documentation feedback in
|
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
Implemented proposal: runtime-neutral installation with gateway-owned detectionThe final implementation treats package installation and gateway health as separate outcomes while keeping optional compute runtimes outside OpenShell's ownership. Contract
Detection and guidance
Gateway startup now detects all available runtimes in Kubernetes → Podman → Docker priority order. On every automatic start it:
This gateway-level warning is necessary because the environment can change after installation. For example, adding Podman to a Docker-only host leaves the running gateway unchanged, but the next restart selects Podman unless Docker is pinned. Why this optionThe approach preserves the installation invariants: packages remain runtime-neutral, detection remains observational, user configuration remains explicit, and the gateway is never exposed beyond loopback without an operator action. The installer provides immediate discoverability, while gateway startup provides durable guidance for later environment changes. Alternatives explored
The final implementation combines the useful parts of the last two options: immediate installer guidance plus authoritative startup diagnostics, without automatic configuration changes. |
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
|
@maxamillion @drew this is now implemented as a runtime-neutral installation contract. Problem: a Docker-only RHEL host could not install OpenShell because the RPM required Podman. Implemented outcome:
The main installation invariants are: native package installation, CLI and gateway availability, a supervised user service, preserved user configuration, loopback/TLS defaults, no management of optional runtimes, explicit operator-owned driver pinning, and a clear split between package success and service health. We explored:
The selected design combines installer detection for immediate discoverability with gateway startup warnings for long-term correctness. This covers runtimes installed after OpenShell while keeping detection observational and all configuration changes explicit. |
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
|
|
||
| report_detected_compute_driver() { | ||
| _gateway_bin="${OPENSHELL_GATEWAY_BIN:-openshell-gateway}" | ||
| if ! _detected_driver="$(as_target_user "$_gateway_bin" config detect-driver)"; then |
There was a problem hiding this comment.
Not sure if exposing the detected driver just for this is worth it. Arguably it provides a slightly better UX, guiding the user, rather than requiring after-the-fact troubleshooting.
There was a problem hiding this comment.
Thinking out loud here. Instead of implementing this in a shell script, does it make sense to add something like an openshell check command? (out of scope for this PR though).
There was a problem hiding this comment.
I like this idea, this kind of diagnostics on the openshell side would make sense, maybe in the form of openshell-gateway doctor? Then that could detect the driver and run doctor on that? This way we only orchestrate the process of gathering info, but we don't need to understand specifics about the driver.
In this case the podman driver would check the config and output "you need to bind the gateway to 0.0.0.0, because you're using a rootless podman".
Stop enumerating the VM driver libexec search paths in the RPM CONFIGURATION doc; defer to the driver_dir setting and the gateway's startup error, which lists the directories it actually searched. Correct the VM README (the single detailed source) to match the four paths the gateway searches. Align the QUICKSTART detection order with the other docs (Kubernetes, then Podman, then Docker) and drop the no-op bind-address reset from the config-set example. Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
| - Do not install, remove, start, or configure optional Docker and Podman | ||
| runtimes. |
There was a problem hiding this comment.
This is unrelated to this change, but currently the Docker driver will stop all sandboxes if the gateway is restarted (as it would be under upgrade).
| On RPM-family Linux x86_64 and aarch64 systems, `install.sh` installs the | ||
| `openshell` and `openshell-gateway` RPM packages from the selected release tag. | ||
| The RPM gateway package is configured for the Podman driver. | ||
| The RPM does not include `openshell-driver-vm`. Install the matching standalone |
There was a problem hiding this comment.
Question: Is there a specific reason for this, or is it just because it's not tested?
There was a problem hiding this comment.
I checked with @drew - there is no reason for this, other than when the RPM was introduced/VM still being experimental. Drew said he will get this cleaned up (i.e. provide parity for all installation methods) with "stable" support for VM driver.
| struct SetArgs { | ||
| /// Select one compute driver, or use `auto` to remove an existing pin. | ||
| #[arg(long, value_name = "DRIVER")] | ||
| compute_driver: Option<String>, | ||
|
|
||
| /// Set the gateway listener socket address. | ||
| #[arg(long = "bind-address", value_name = "IP:PORT")] | ||
| gateway_bind_address: Option<SocketAddr>, | ||
| } |
There was a problem hiding this comment.
Do we have to explicitly add options that we want to be able to set via the CLI? Would we be able to infer them from the toml keys?
There was a problem hiding this comment.
Good question.
I wanted to keep this one simple, with an idea that later we can add an option to support any arbitrary config field. But then there would be 2 ways of setting these 2 fields. I think we could support setting arbitrary keys right away, one thing to figure out would be arrays, specifically arrays of tables and what to support there (e.g. delete ith item?)
There was a problem hiding this comment.
Is this file name aligned with the functionality. While config set does update the config, the detect driver command does not.
There was a problem hiding this comment.
Good catch.
The set was the original command and through some iterations I got to adding driver detect and didn't notice agent adding it in the same file.
| /// Gateway startup reads this file. Config subcommands update it. Gateway | ||
| /// command-line flags and `OPENSHELL_*` environment variables continue to | ||
| /// take precedence over file values at runtime. | ||
| #[arg(long, env = "OPENSHELL_GATEWAY_CONFIG", global = true)] |
There was a problem hiding this comment.
In the nvidia-ctk CLI I also implemented an nvidia-ctk config --set KEY=VALUE command. Here I had the default behaviour be that it prints the modified CONFIG (with --config specifying the path) to stdout by default and added an --in-place flag to update the specified input. Alternatively one could redirect to an arbitrary file.
| let Some(driver) = detected.first().copied() else { | ||
| return Err(Error::config( | ||
| "no compute driver configured and auto-detection found no suitable driver; \ | ||
| install and start Docker or Podman, or install the VM driver and select it \ | ||
| with `openshell-gateway config set --compute-driver vm`", | ||
| )); | ||
| }; |
There was a problem hiding this comment.
Question: Why do we call detect_drivers() here and then use .first() instead of calling detect_driver?
There was a problem hiding this comment.
Ok, I see, it's because we log the list of detected drivers later.
There was a problem hiding this comment.
Yeah, this was just for the purpose of producing log output.
I think it would be clearer to have 2 variables: selected (String) and available ([String]).
| example, pin Docker: | ||
|
|
||
| ```shell | ||
| openshell-gateway config set --compute-driver docker |
There was a problem hiding this comment.
What if this were:
| openshell-gateway config set --compute-driver docker | |
| openshell-gateway config --set openshell.gateway.drivers=docker --in-place |
There was a problem hiding this comment.
Yeah, we could go that route! Similar comment: #2137 (comment)
Would config set make more sense than config --set? What other -- would the config have? Other parts of our CLI use the subcommands to describe a behavior and flags/params to provide input (e.g. policy set, inference set).
openshell-gateway config set openshell.gateway.drivers docker
# kubectl/gh uses this
# should be easier to provide completions
# only supports single value at a time? I think being able to atomically update multiple things in one command would be good.
openshell-gateway config set openshell.gateway.drivers=docker
# allows providing multiple values at a time
openshell-gateway config set --key openshell.gateway.drivers --value docker
# unnecessary verbosity| After=podman.socket | ||
| Wants=podman.socket |
There was a problem hiding this comment.
Does this mean that on some systems the gateway may come up before Podman is ready? Will the service restart until the selected (or auto-detected) backend is ready?
There was a problem hiding this comment.
Yes, that's exactly right, the openshell-gateway will exit if the driver doesn't initialize. With Restart=on-failure serviced will try again, until it works.
The failure mode may be slightly different depending on whether docker is installed on the host.
Let's say both podman and docker are installed and gateway is configured to auto-detect. Auto-detection skips podman, because the socket is not ready yet, but docker is ready -> the gateway starts with docker.
I think this is okay, since the gateway is configured with auto-detection.
If the gateway is configured with podman as the driver, the gateway won't start until podman socket is available and responding.
Unless I'm misunderstanding something, this also seems to negate the purpose of using a package manager to begin with by sidestepping dependency management. The user installs the package which does not pull in a dependent runtime so the |
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
|
Thanks for taking a look @maxamillion. This may be something better discussed during the call, so I will keep this brief. Btw I'm not sold on this solution and I don't have much experience in this space, so any feedback or guidance is appreciated. I will start with the original problem, so we can discuss the solution in that context. The original problem: user cannot install OpenShell on their system (Rocky 8, still supported until 2029). They already have docker installed and openshell installation fails when installing podman, which they don't want to use anyways. The outcome is: cannot install openshell because of that, at least not using the official script. It's still possible to install by downloading binaries manually.
I think having the package manager is still useful - it manages the artifacts, versions, checksums, removal, etc.
Yes, this is correct, the dependent runtime is a prerequisite in this model. This is already the case with deb and homebrew installation. I'd consider things like container engine to be of an host-level infrastructure, rather than user-space, so not bringing them in as part of application's dependency does make sense, especially that openshell can work with multiple of them. This may be an argument for making the VM driver the default, since that's more self-contained (but it's also limited - it requires nested virtualization). My sense is that installing a container engine together with openshell is a bit heavyweight and should be considered carefully. If we did go that route, I'd see it as something that the user needs to explicitly agree to, e.g. through a prompt in install script (if installing interactively) or a flag, e.g. Related to your point
we could make the driver not required on the gateway startup. Any operation requiring the driver would fail, but the gateway could be up. This would add complexity to driver management, it would get registered at the first successful interaction, etc. |
Thinking about this some more, maybe relying on podman by default is a good solution (assuming docker is not installed on the system) and the user doesn't explicitly opt-out? |
Summary
Make package installation runtime-neutral so installing OpenShell does not require Podman, Docker, or another optional compute runtime. The RPM no longer depends on Podman, package-managed gateways retain automatic driver selection, and the installer reports package installation and gateway health as separate outcomes.
This version keeps runtime detection inside the gateway.
install.shuses the read-only detection CLI for immediate guidance, while every gateway start logs the selected driver, all detected alternatives, multi-runtime pinning guidance, and the rootless Podman bind command when applicable.Related Issue
Closes #2007
Installation Invariants
openshellandopenshell-gatewayartifacts in the package manager's standard executable path.Changes
podman.socketordering from the RPM spec.127.0.0.1:17670.openshell-gateway config detect-driverwith stablekubernetes,podman,docker, ornoneoutput.install.shadvisory: it never changes driver selection or listener configuration.openshell-gateway config setfor typed, validated, comment-preserving, atomic TOML updates.package installation succeededseparately fromgateway service is healthy.install.shand gateway diagnostics.Runtime Scenarios
install.shreturns nonzero with diagnostics. The service keeps retrying and can recover after a runtime is installed. Rootless Podman still requires the explicit bind change before sandboxes can call back.openshell-gateway config set --compute-driver <driver>guidance.Why This Option
This design follows the invariants above: package installation stays independent of optional runtimes, configuration remains operator-owned and visible in TOML, loopback is never widened implicitly, and runtime changes after installation remain observable. Keeping the warning in the gateway is important because an installer-only warning cannot cover Docker or Podman installed later.
Automatic selection remains the zero-configuration recovery path. Explicit
config setcommands are the stability mechanism when an operator wants a fixed driver.Alternatives Explored
install.sh. Rejected because repository setup, rootless configuration, daemon lifecycle, licensing, and enterprise policy vary across supported systems.install.sh --compute-driver/OPENSHELL_INSTALL_COMPUTE_DRIVER. Implemented during exploration, then removed because it duplicated gateway configuration policy and made installation persist a driver choice.OPENSHELL_DRIVERSin service definitions. Rejected because environment values outrank TOML and make later config edits appear ineffective.0.0.0.0when Podman is detected. Rejected because runtime probing must not silently expose the gateway on host interfaces.install.sh. Insufficient because runtimes can be installed or removed after installation.detect-driverfor immediate Podman guidance.Testing
mise run pre-commitpassesmise run testpasses (included bymise run pre-commit)mise run cipasses (mise run pre-commitis thecialias)Focused coverage:
Checklist