|
| 1 | +# Building a snap package |
| 2 | + |
| 3 | +OpenShell snap packages are defined by the root `snapcraft.yaml` and built with |
| 4 | +Snapcraft from source. |
| 5 | + |
| 6 | +The helper task under `tasks/` still stages the same payload from pre-built |
| 7 | +binaries when you want to inspect the snap root or produce local artifacts. |
| 8 | + |
| 9 | +## Prerequisites |
| 10 | + |
| 11 | +- Linux on `amd64` or `arm64` |
| 12 | +- `snap` from `snapd` |
| 13 | +- `snapcraft` |
| 14 | +- Docker from the Docker snap (`sudo snap install docker`) |
| 15 | + |
| 16 | +## Build with Snapcraft |
| 17 | + |
| 18 | +Build the snap from source with the root manifest: |
| 19 | + |
| 20 | +```shell |
| 21 | +snapcraft pack |
| 22 | +``` |
| 23 | + |
| 24 | +The manifest builds the Rust binaries inside Snapcraft, installs the CLI, |
| 25 | +gateway, and sandbox supervisor into the snap, and keeps the same runtime |
| 26 | +environment as the current deployment logic. |
| 27 | + |
| 28 | +## Staged helper flow |
| 29 | + |
| 30 | +The helper task under `tasks/` still stages the same payload from pre-built |
| 31 | +binaries when you want to inspect the snap root or produce local artifacts. |
| 32 | + |
| 33 | +For that flow, install `mise` and build: |
| 34 | + |
| 35 | +- `openshell` |
| 36 | +- `openshell-gateway` |
| 37 | +- `openshell-sandbox` |
| 38 | + |
| 39 | +## Build helper binaries |
| 40 | + |
| 41 | +Build the release binaries used by the staged helper flow: |
| 42 | + |
| 43 | +```shell |
| 44 | +mise run build:rust:snap |
| 45 | +``` |
| 46 | + |
| 47 | +This convenience target builds the CLI with `bundled-z3`, the gateway, and |
| 48 | +`openshell-sandbox` for the Docker driver to bind-mount into sandbox containers. |
| 49 | + |
| 50 | +## Pack the snap |
| 51 | + |
| 52 | +Run the packaging hook through mise: |
| 53 | + |
| 54 | +```shell |
| 55 | +VERSION="$(uv run python tasks/scripts/release.py get-version --snap)" |
| 56 | + |
| 57 | +OPENSHELL_CLI_BINARY="$PWD/target/release/openshell" \ |
| 58 | +OPENSHELL_GATEWAY_BINARY="$PWD/target/release/openshell-gateway" \ |
| 59 | +OPENSHELL_DOCKER_SUPERVISOR_BINARY="$PWD/target/release/openshell-sandbox" \ |
| 60 | +OPENSHELL_SNAP_VERSION="$VERSION" \ |
| 61 | +OPENSHELL_OUTPUT_DIR=artifacts \ |
| 62 | + mise run package:snap |
| 63 | +``` |
| 64 | + |
| 65 | +The artifact is written to `artifacts/openshell_${VERSION}_${ARCH}.snap`. The |
| 66 | +packaging hook fails before `snap pack` if `openshell-sandbox` is missing or not |
| 67 | +executable. |
| 68 | + |
| 69 | +## Stage without packing |
| 70 | + |
| 71 | +To inspect the snap root without running `snap pack`: |
| 72 | + |
| 73 | +```shell |
| 74 | +VERSION="$(uv run python tasks/scripts/release.py get-version --snap)" |
| 75 | + |
| 76 | +OPENSHELL_CLI_BINARY="$PWD/target/release/openshell" \ |
| 77 | +OPENSHELL_GATEWAY_BINARY="$PWD/target/release/openshell-gateway" \ |
| 78 | +OPENSHELL_DOCKER_SUPERVISOR_BINARY="$PWD/target/release/openshell-sandbox" \ |
| 79 | +OPENSHELL_SNAP_VERSION="$VERSION" \ |
| 80 | + mise run package:snap:stage |
| 81 | +``` |
| 82 | + |
| 83 | +The staged root is written to `artifacts/snap-root`. |
| 84 | + |
| 85 | +## Commands in the snap |
| 86 | + |
| 87 | +The snap exposes the CLI: |
| 88 | + |
| 89 | +- `openshell` |
| 90 | + |
| 91 | +It also defines a system service running the gateway with the Docker driver. |
| 92 | + |
| 93 | +- `openshell.gateway` |
| 94 | + |
| 95 | +The gateway service uses `refresh-mode: endure` so snap refreshes do not restart |
| 96 | +it while sandboxes are active. Restart the service manually when you are ready |
| 97 | +to move the gateway to the refreshed snap revision. |
| 98 | + |
| 99 | +`openshell-sandbox` is staged next to `openshell-gateway` as the Docker |
| 100 | +supervisor binary. The gateway app passes it to the in-process Docker driver |
| 101 | +through `OPENSHELL_DOCKER_SUPERVISOR_BIN=$SNAP/bin/openshell-sandbox`. The |
| 102 | +service stores its gateway database under `$SNAP_COMMON`. |
| 103 | + |
| 104 | +## Interfaces |
| 105 | + |
| 106 | +The `openshell` CLI app plugs: |
| 107 | + |
| 108 | +- `home` |
| 109 | +- `network` |
| 110 | +- `ssh-keys` |
| 111 | +- `system-observe` |
| 112 | + |
| 113 | +The `openshell.gateway` service plugs: |
| 114 | + |
| 115 | +- `docker` |
| 116 | +- `log-observe` |
| 117 | +- `network` |
| 118 | +- `network-bind` |
| 119 | +- `ssh-keys` |
| 120 | +- `system-observe` |
| 121 | + |
| 122 | +## Start a Docker gateway from the snap |
| 123 | + |
| 124 | +The snapped gateway talks to Docker through the Docker snap's |
| 125 | +`docker:docker-daemon` slot. The snap declares `default-provider: docker` on |
| 126 | +its Docker plug so snapd can install the Docker snap when OpenShell is |
| 127 | +installed. Connect the interface before using the Docker driver: |
| 128 | + |
| 129 | +```shell |
| 130 | +sudo snap connect openshell:docker docker:docker-daemon |
| 131 | +sudo snap connect openshell:log-observe |
| 132 | +sudo snap connect openshell:system-observe |
| 133 | +sudo snap connect openshell:ssh-keys |
| 134 | +``` |
| 135 | + |
| 136 | +The gateway uses Docker's default Unix socket location. The Docker snap exposes |
| 137 | +that socket through the connected `docker` interface, so no `DOCKER_HOST` |
| 138 | +override is required. The OpenShell snap still requires the Docker snap because |
| 139 | +it relies on the `docker:docker-daemon` slot; it does not work with Docker |
| 140 | +installed from a Debian package or Docker's upstream packages. |
| 141 | + |
| 142 | +The service runs the gateway with the Docker driver enabled: |
| 143 | + |
| 144 | +```shell |
| 145 | +openshell.gateway \ |
| 146 | + --drivers docker \ |
| 147 | + --disable-tls \ |
| 148 | + --port 17670 \ |
| 149 | + --db-url "sqlite:$SNAP_COMMON/gateway.db?mode=rwc" \ |
| 150 | + --docker-supervisor-bin "$SNAP/bin/openshell-sandbox" \ |
| 151 | + --docker-network-name openshell-snap \ |
| 152 | + --sandbox-namespace docker-snap \ |
| 153 | + --sandbox-image ghcr.io/nvidia/openshell-community/sandboxes/base:latest \ |
| 154 | + --sandbox-image-pull-policy IfNotPresent \ |
| 155 | + --grpc-endpoint http://host.openshell.internal:17670 |
| 156 | +``` |
| 157 | + |
| 158 | +This stores the gateway SQLite database at |
| 159 | +`/var/snap/openshell/common/gateway.db`. |
| 160 | + |
| 161 | +## Connect with the OpenShell CLI |
| 162 | + |
| 163 | +Register the snap-run gateway as a local plaintext gateway: |
| 164 | + |
| 165 | +```shell |
| 166 | +openshell gateway add http://127.0.0.1:17670 --local --name snap-docker |
| 167 | +openshell gateway select snap-docker |
| 168 | +openshell status |
| 169 | +``` |
| 170 | +
|
| 171 | +Then use normal sandbox commands: |
| 172 | +
|
| 173 | +```shell |
| 174 | +openshell sandbox create --name demo |
| 175 | +openshell sandbox connect demo |
| 176 | +``` |
| 177 | +
|
| 178 | +To avoid changing the default gateway, pass the gateway name per command: |
| 179 | +
|
| 180 | +```shell |
| 181 | +openshell --gateway snap-docker status |
| 182 | +openshell --gateway snap-docker sandbox create --name demo |
| 183 | +``` |
0 commit comments