Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 84 additions & 9 deletions docs/about/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ Install OpenShell with a single command:
curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | sh
```

The script detects your operating system and installs the OpenShell CLI and gateway with your native package manager. It then starts the local gateway server so you can begin creating sandboxes.
The script detects your operating system and installs the OpenShell CLI and
gateway. On Linux, the Snap path is preferred when `snapd` is available;
otherwise the script uses the native DEB or RPM package. The gateway then
starts automatically so you can begin creating sandboxes.

You can also download release artifacts directly from the [OpenShell GitHub Releases](https://github.com/NVIDIA/OpenShell/releases) page.

Expand Down Expand Up @@ -51,6 +54,12 @@ brew services restart openshell

## Linux

On distributions that ship with `snapd`, the install script uses the Snap path
described below, unless one of the following is true:
- a native (non-snap) Docker package is present (the `openshell` snap requires the `docker` snap, for now)
- `snapd` is not present
- `OPENSHELL_INSTALL_METHOD` is set in the environment to some value other than `snap` (e.g. `OPENSHELL_INSTALL_METHOD=deb`)

On Fedora and RHEL, the install script uses RPM packages. The RPM installs the `openshell` CLI, the `openshell-gateway` daemon, and a systemd user service.

On Debian and Ubuntu, the install script uses a Debian package. The Debian package installs the `openshell` CLI, the `openshell-gateway` daemon, VM sandbox support, and a systemd user service.
Expand All @@ -77,7 +86,12 @@ sudo loginctl enable-linger $USER

## Snap

Install the OpenShell snap from the Snap Store:
On Linux distributions that ship with `snapd`, the install script installs
OpenShell from the Snap Store. The OpenShell snap bundles the CLI, the terminal
UI, and a managed gateway daemon. `snapd` handles upgrades and rollback; the
gateway runs as a system service inside the snap.

You can also install the snap directly:

```shell
sudo snap install openshell
Expand All @@ -94,19 +108,29 @@ typically `~/snap/openshell/common`. Gateway registrations live under
`$SNAP_USER_COMMON/.config/openshell/gateways/` instead of
`~/.config/openshell/gateways/`.

The OpenShell snap requires the Docker snap, which you can install with:

```shell
sudo snap install docker
```

### Snap store installs

When installing from the Snap Store, snapd automatically connects the `home`,
`network`, `network-bind`, and `ssh-keys` plugs. The `docker` plug still
requires manual connection:
When installing from the Snap Store, snapd automatically connects the `docker`,
`home`, `log-observe`, `network`, `network-bind`, and `system-observe plugs.
The remaining plug — `ssh-keys` — still requires manual connection:

```shell
sudo snap connect openshell:docker docker:docker-daemon
sudo snap connect openshell:ssh-keys
```

The snap declares `default-provider: docker` on the Docker plug so snapd will
offer to install the Docker snap, but the connection itself must be made
manually.
The `docker` interface is used to connect the `openshell` snap's `docker` plug
to the `docker` snap's `docker-daemon` slot; the `openshell` snap does not yet
work with a host-installed Docker Engine. The installer runs this and the other
interface connections for you after installing the `openshell` snap; run them
by hand if you install the snap manually. The installer is best-effort: if a
connect fails (for example because the `docker` snap is not yet running), the
snap still installs and the installer prints a warning.

### Locally built snap packages

Expand All @@ -128,6 +152,26 @@ to read logs and inspect system processes. The `docker` plug requires the
`docker:docker-daemon` slot from the Docker snap and does not work with
system-installed Docker.

### Verify the gateway

The snap-managed gateway service is `openshell.gateway`. Inspect it with:

```shell
snap services openshell
snap logs -n 100 openshell.gateway
```

Register the gateway with the CLI:

```shell
openshell gateway add http://127.0.0.1:17670 --local --name openshell
openshell status
```

The gateway listens on `http://127.0.0.1:17670` and stores its state under
`/var/snap/openshell/common/`. Override gateway settings by creating
`/var/snap/openshell/common/gateway.toml`.

### Gateway service

The gateway runs as a snap daemon with `refresh-mode: endure`, meaning snapd
Expand All @@ -139,6 +183,37 @@ a snap refresh when you need the updated binary:
sudo systemctl restart snap.openshell.gateway
```

### When to choose Snap

Use the `openshell` snap when `snapd` is available and no native Docker Engine
is installed, and you want atomic upgrades and rollback, a single self-contained
and sandboxed install, or a desktop launcher that surfaces the OpenShell
terminal UI in the application menu.

Use the `openshell` `.deb` or `.rpm` file when `snapd` is unavailable or when
you already run Docker from a non-snap source. The installer falls back to
these methods on hosts with native Docker.

### Force an install method

Set `OPENSHELL_INSTALL_METHOD` to force a specific install method instead of
relying on auto-detection. Supported values:

| Value | Install path |
|---|---|
| `deb` | Debian package via `apt`/`dpkg` |
| `rpm` | RPM package via `dnf`/`yum`/`zypper`/`rpm` |
| `snap` | Snap package via `snapd` |
| `homebrew` | Homebrew formula via `brew` (macOS only; not yet supported on Linux) |

When the variable is unset, the script auto-detects the host package manager
as described above. If the requested method's package manager is not
installed, the installer aborts with an error.

```shell
curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | OPENSHELL_INSTALL_METHOD=deb sh
```

## Kubernetes

Kubernetes deployments use the OpenShell Helm chart. For step-by-step installation, refer to [Kubernetes Setup](/kubernetes/setup). For chart values and packaging details, refer to the [Helm chart README](https://github.com/NVIDIA/OpenShell/blob/main/deploy/helm/openshell/README.md).
Expand Down
140 changes: 135 additions & 5 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ OPTIONS:
ENVIRONMENT VARIABLES:
OPENSHELL_VERSION Release tag to install (default: latest tagged release).
Set OPENSHELL_VERSION=dev to install the rolling dev build.
OPENSHELL_INSTALL_METHOD
Force a specific install method. Supported values:
deb, rpm, snap, homebrew. When unset, the script
auto-detects the host package manager.
OPENSHELL_ACK_BREAKING_UPGRADE
Set to 1 only after backing up and cleaning up a
pre-v0.0.37 installation.
Expand All @@ -60,9 +64,10 @@ NOTES:
from ${GITHUB_URL}/releases/latest.

Linux installs the Debian package on amd64/arm64 or the RPM packages on
x86_64/aarch64, depending on the host package manager.
macOS installs the release Homebrew formula on Apple Silicon and starts a
brew services-backed local gateway.
x86_64/aarch64, depending on the host package manager. When snapd is
available and no native Docker Engine is installed, the installer prefers
the Snap path. macOS installs the release Homebrew formula on Apple Silicon
and starts a brew services-backed local gateway.
EOF
}

Expand All @@ -76,6 +81,14 @@ require_cmd() {
fi
}

has_snapd() {
has_cmd snap && systemctl is-active --quiet snapd.socket 2>/dev/null
}

has_native_docker() {
has_cmd docker && ! snap list docker >/dev/null 2>&1
}

download() {
_url="$1"
_output="$2"
Expand Down Expand Up @@ -468,7 +481,33 @@ detect_platform() {
}

linux_package_method() {
if has_cmd dpkg; then
case "${OPENSHELL_INSTALL_METHOD:-}" in
"")
;;
snap)
echo "snap"
return 0
;;
deb|apt)
echo "deb"
return 0
;;
rpm|dnf|yum|zypper)
echo "rpm"
return 0
;;
homebrew|brew)
echo "homebrew"
return 0
;;
*)
error "OPENSHELL_INSTALL_METHOD='${OPENSHELL_INSTALL_METHOD}' is not supported; use one of: deb, rpm, snap, homebrew"
;;
esac

if has_snapd && ! has_native_docker; then
echo "snap"
elif has_cmd dpkg; then
echo "deb"
elif has_cmd rpm; then
echo "rpm"
Expand Down Expand Up @@ -953,6 +992,81 @@ install_linux_rpm() {
start_user_gateway
}

install_linux_snap() {
require_cmd snap
set_linux_target_runtime_dir

# Docker snap must be installed before openshell so that the
# openshell:docker -> docker:docker-daemon interface connection
# can succeed. The docker-daemon slot doesn't exist until the
# Docker snap itself is present.
if ! snap list docker >/dev/null 2>&1; then
info "docker snap not found, installing..."
as_root snap install docker
else
info "docker snap already present"
fi

info "installing openshell snap..."
as_root snap install openshell

# Connect required interfaces. Docker, home, log-observe, network,
# network-bind, and system-observe auto-connect on install; the remaining
# plug (ssh-keys) needs explicit connection. snap connect is idempotent — it
# succeeds whether the connection was just made or already existed.
as_root snap connect openshell:ssh-keys

info "installed openshell snap from Snap Store"
info "registering local gateway as ${TARGET_USER}..."
register_local_gateway_snap
wait_for_local_gateway_listener_snap
wait_for_local_gateway_status
}

register_local_gateway_snap() {
_register_bin="${OPENSHELL_REGISTER_BIN:-openshell}"

if _add_output="$($_register_bin gateway add "http://127.0.0.1:${LOCAL_GATEWAY_PORT}" --local --name openshell 2>&1)"; then
[ -z "$_add_output" ] || print_gateway_add_output "$_add_output"
return 0
fi

_add_status=$?

case "$_add_output" in
*"already exists"*)
info "local gateway already exists; removing and re-adding it..."
remove_local_gateway_registration
"$_register_bin" gateway add "http://127.0.0.1:${LOCAL_GATEWAY_PORT}" --local --name openshell
;;
*)
printf '%s\n' "$_add_output" >&2
return "$_add_status"
;;
esac
}

wait_for_local_gateway_listener_snap() {
_timeout="${OPENSHELL_INSTALL_GATEWAY_TIMEOUT_SNAP:-90}"
_elapsed=0
_last_output=""
_probe_url="http://127.0.0.1:${LOCAL_GATEWAY_PORT}/"

info "waiting for local gateway listener to become reachable..."
while [ "$_elapsed" -lt "$_timeout" ]; do
if _last_output="$(curl -sS --max-time 2 "$_probe_url" 2>&1)"; then
info "local gateway listener is reachable"
return 0
fi
sleep 1
_elapsed=$((_elapsed + 1))
done

[ -z "$_last_output" ] || printf '%s
' "$_last_output" >&2
error "local gateway listener did not become reachable at ${_probe_url} within ${_timeout}s"
}

install_macos_homebrew() {
check_macos_platform

Expand Down Expand Up @@ -1033,20 +1147,36 @@ main() {

case "$PLATFORM" in
linux)
require_linux_package_glibc
case "$(linux_package_method)" in
snap)
install_linux_snap
;;
deb)
require_linux_package_glibc
install_linux_deb
;;
rpm)
require_linux_package_glibc
install_linux_rpm
;;
homebrew)
# TODO: implement install_linux_homebrew for Linuxbrew hosts
# (e.g. Universal Blue/Bazzite). Homebrew is accepted as a method
# value but not yet wired to an installer on Linux.
error "the 'homebrew' install method is not yet supported on Linux"
;;
*)
error "unsupported Linux package method"
;;
esac
;;
darwin)
case "${OPENSHELL_INSTALL_METHOD:-}" in
""|homebrew|brew) ;;
*)
error "only the 'homebrew' install method is supported on macOS"
;;
esac
install_macos_homebrew
;;
*)
Expand Down
Loading
Loading