Files
OpenShell/deploy/rpm/CONFIGURATION.md
Jesse JaggarsandDrew Newberry 02b664bb0d refactor(config): normalize and enforce gateway schema v2 (#2814)
* refactor(config): normalize compute driver field names

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* refactor(config): introduce canonical gateway fields

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* refactor(config): enforce gateway schema version 2

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(config): preserve compute driver runtime guarantees

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(config): address schema v2 review regressions

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(config): complete schema v2 migration safeguards

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(config): expand schema v2 regression coverage

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(config): add schema v2 parity manifest

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(config): correct parity manifest inventory

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* docs(config): record schema v2 intentional changes

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* docs(config): disposition schema v2 parity gaps

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): add dual schema parity harness

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): establish compute lifecycle parity baseline

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(config): preserve gateway option compatibility

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): record gateway option parity

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* docs(config): close gateway-wide parity gaps

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(podman): apply configured pids limit

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): validate Podman option parity

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): add Kubernetes option parity harness

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): record Kubernetes option parity

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): disposition VM parity lanes

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): add external driver parity lane

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(e2e): preserve external driver pull policy

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): attest parity artifacts and launches

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): require clean parity build sources

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): bind parity runtime artifacts

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(e2e): use isolated supervisor tags

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(e2e): qualify parity image tags

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(e2e): serve parity supervisor locally

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): isolate parity podman services

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): harden parity evidence provenance

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): pin parity sandbox artifacts

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): attest parity runtime inputs

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): bind parity runtime evidence

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): record compute boundary parity

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(e2e): disposition cross-cutting parity lanes

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(packaging): preflight gateway config upgrades

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(config): preserve rebase integration guarantees

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(ci): isolate temporary git signing config

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(config): update remaining schema v2 consumers

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(ci): provide e2fs tools to VM tests

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(config): align preflight with gateway startup

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(vm): preserve rootfs tar configuration

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* chore(config): adopt duration unit constructors

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(packaging): preflight RPM gateway config

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(config): address driver review findings

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(e2e): require fresh semantic parity evidence

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* fix(docker): update tests for renamed sandbox label

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>

* test(gateway): preserve selective driver coverage after rebase

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

---------

Signed-off-by: Jesse Jaggars <jjaggars@redhat.com>
Signed-off-by: Drew Newberry <anewberry@nvidia.com>
Co-authored-by: Drew Newberry <anewberry@nvidia.com>
2026-09-11 05:00:24 +00:00

11 KiB

OpenShell Gateway Configuration (RPM)

Configuration reference for the OpenShell gateway when installed via the RPM package on Fedora and RHEL systems.

For first-time setup, see QUICKSTART.md. For troubleshooting, see TROUBLESHOOTING.md.

Default configuration

The RPM ships a default TOML configuration template at /usr/share/openshell-gateway/gateway.toml.default. On first start of openshell-gateway.service, the systemd unit copies this template to ~/.config/openshell/gateway.toml if no config file exists there yet.

The defaults are tuned for rootless Podman use:

[openshell]
version = 2

[openshell.gateway]
compute_driver = "podman"

The RPM does not override bind_address. The primary listener uses the built-in 127.0.0.1:17670 default. The Podman driver reports the callback interface it needs, and the gateway adds a separate listener scoped to that interface. This keeps the general API off unrelated host interfaces.

compute_driver = "podman" pins the compute driver to Podman. Without this, the gateway auto-detects in order: Kubernetes, Podman, Docker. Pinning prevents unexpected driver selection if Docker is also installed on the host.

Customizing the configuration

Edit ~/.config/openshell/gateway.toml directly. The package-owned template at /usr/share/openshell-gateway/gateway.toml.default is not read at runtime and may change during an RPM upgrade. The active user copy is preserved. During a schema-v2 upgrade, the service replaces only the recognized package-generated v1 copy; it never rewrites an edited configuration. Before generating certificates or starting the gateway, the service runs openshell-gateway config preflight against the effective configuration and stops if validation fails.

To apply environment variable overrides that persist across upgrades without editing the TOML file, add them to ~/.config/openshell/gateway.env:

# Example: explicitly expose the primary listener on one host interface
OPENSHELL_BIND_ADDRESS=192.168.1.10

To override the path to the TOML config file entirely:

# In ~/.config/openshell/gateway.env
OPENSHELL_GATEWAY_CONFIG=/path/to/custom/gateway.toml

For one-off service overrides that persist across package upgrades:

systemctl --user edit openshell-gateway

TLS (mTLS)

The RPM enables mutual TLS by default. The gateway requires a valid client certificate for all API connections. Its primary listener uses 127.0.0.1:17670; Podman callback traffic uses the additional listener described in "Default configuration" above.

Auto-generated certificates

On first start, the systemd user service runs openshell-gateway generate-certs --output-dir ~/.local/state/openshell/tls --server-san host.openshell.internal to generate certificates with rcgen (the same routine the CLI uses for local mTLS bundles). The unit sets OPENSHELL_LOCAL_TLS_DIR to that path and uses the same value for certificate generation and gateway startup. To use a custom bundle location, set OPENSHELL_LOCAL_TLS_DIR in ~/.config/openshell/gateway.env before starting the service.

File Purpose Location
CA certificate Root of trust ~/.local/state/openshell/tls/ca.crt
CA private key Signs server and client certs ~/.local/state/openshell/tls/ca.key
Server certificate Gateway TLS identity ~/.local/state/openshell/tls/server/tls.crt
Server private key Gateway TLS key ~/.local/state/openshell/tls/server/tls.key
Client certificate CLI and sandbox identity ~/.local/state/openshell/tls/client/tls.crt
Client private key CLI and sandbox key ~/.local/state/openshell/tls/client/tls.key

Client certificates are also copied to the CLI auto-discovery directory:

~/.config/openshell/gateways/openshell/mtls/
  ca.crt
  tls.crt
  tls.key

The CLI automatically discovers these certificates when connecting to a gateway on localhost or 127.0.0.1.

Server certificate SANs

The auto-generated server certificate includes these Subject Alternative Names:

  • localhost
  • openshell
  • openshell.openshell.svc
  • openshell.openshell.svc.cluster.local
  • host.containers.internal
  • host.docker.internal
  • host.openshell.internal
  • 127.0.0.1

To connect from a remote machine, you need externally-managed certificates with additional SANs. See "Remote CLI access" in TROUBLESHOOTING.md.

Using externally-managed certificates

To use certificates from an external CA or cert-manager:

  1. Place the server cert, key, and CA cert on the filesystem.

  2. Edit ~/.config/openshell/gateway.toml:

    [openshell.gateway.tls]
    cert_path = "/path/to/server/tls.crt"
    key_path = "/path/to/server/tls.key"
    client_ca_path = "/path/to/ca.crt"
    
  3. Place the client cert where the CLI expects it:

    ~/.config/openshell/gateways/openshell/mtls/
      ca.crt
      tls.crt
      tls.key
    

Rotating certificates

Delete the TLS state directory and restart the gateway:

rm -rf ~/.local/state/openshell/tls
systemctl --user restart openshell-gateway

The gateway regenerates the PKI on next start.

Disabling TLS

WARNING: With TLS disabled, the gateway API has no authentication. Keep the bind address on 127.0.0.1, or place the gateway behind a TLS-terminating reverse proxy that enforces its own authentication.

To disable TLS (not recommended for production):

  1. Edit ~/.config/openshell/gateway.toml:

    [openshell.gateway]
    disable_tls = true
    
  2. Remove or comment out the guest_tls_* entries in ~/.config/openshell/gateway.toml if they are set.

  3. Restart the gateway.

Sandbox TLS

When mTLS is enabled, the Podman driver bind-mounts the client certificates into each sandbox container so the supervisor process can establish an mTLS connection back to the gateway.

The following TOML fields control the host-side paths of the client certificates that are mounted into sandbox containers:

[openshell.gateway]
guest_tls_ca = "/home/user/.local/state/openshell/tls/ca.crt"
guest_tls_cert = "/home/user/.local/state/openshell/tls/client/tls.crt"
guest_tls_key = "/home/user/.local/state/openshell/tls/client/tls.key"

Inside the container, the supervisor reads them from:

  • /etc/openshell/tls/client/ca.crt
  • /etc/openshell/tls/client/tls.crt
  • /etc/openshell/tls/client/tls.key

On SELinux-enabled systems, the Podman driver automatically applies the :z relabel option to these bind mounts. No manual SELinux configuration is required.

Configuration reference

Upgrading from a previous release? See the "Migrating from gateway.env" section in TROUBLESHOOTING.md for the env-to-TOML mapping and notes on the default port, bind address, and database path changes.

Gateway and driver settings have local runtime defaults. The gateway reads ~/.config/openshell/gateway.toml when that file exists. Set OPENSHELL_GATEWAY_CONFIG in the launch environment to use a different file.

Use systemctl --user edit openshell-gateway for service environment overrides that persist across package upgrades.

Gateway settings

TOML option Default Description
bind_address 127.0.0.1:17670 (gateway default) Address for the primary gRPC/HTTP API listener.
compute_driver "podman" (RPM default) When unset, the gateway auto-detects Kubernetes, then Podman, then Docker. The RPM default pins to Podman; legacy compute_drivers lists are rejected.
[openshell.drivers.podman].default_image ghcr.io/nvidia/openshell-community/sandboxes/base:latest Default sandbox image.
[openshell.drivers.podman].supervisor_image ghcr.io/nvidia/openshell/supervisor:latest Supervisor image mounted into Podman sandboxes.
[openshell.gateway].guest_tls_ca, guest_tls_cert, guest_tls_key auto-generated paths Gateway-owned client TLS material injected into the selected local driver and mounted into sandbox containers.
[openshell.gateway.tls] paths auto-generated paths Server TLS certificate, key, and client CA.
disable_tls unset Set to true to disable TLS.

The database URL is not accepted in TOML. When OPENSHELL_DB_URL is unset, the gateway uses sqlite:$XDG_STATE_HOME/openshell/gateway/openshell.db.

Driver TOML settings

Create ~/.config/openshell/gateway.toml when you need to customize driver settings:

[openshell]
version = 2

[openshell.gateway]
compute_driver = "podman"

[openshell.drivers.podman]
default_image = "ghcr.io/nvidia/openshell-community/sandboxes/base:latest"
image_pull_policy = "if_not_present"
health_check_interval_secs = 10
network_name = "openshell"
stop_timeout_secs = 10

Image management

The gateway pulls container images automatically on first sandbox creation. The default pull policy is if_not_present, which means images are pulled once and then cached by Podman.

To update cached images:

podman pull ghcr.io/nvidia/openshell/supervisor:latest
podman pull ghcr.io/nvidia/openshell-community/sandboxes/base:latest

Or set image_pull_policy = "always" in [openshell.drivers.podman] to pull on every sandbox creation.

To pin specific image versions instead of :latest, set these values in [openshell.drivers.podman]:

supervisor_image = "ghcr.io/nvidia/openshell/supervisor:v0.0.37"
default_image = "ghcr.io/nvidia/openshell-community/sandboxes/base:v0.0.37"

For air-gapped environments:

  1. On a connected machine, pull and save the images:

    podman pull ghcr.io/nvidia/openshell/supervisor:latest
    podman pull ghcr.io/nvidia/openshell-community/sandboxes/base:latest
    podman save -o supervisor.tar ghcr.io/nvidia/openshell/supervisor:latest
    podman save -o sandbox.tar ghcr.io/nvidia/openshell-community/sandboxes/base:latest
    
  2. Transfer the tarballs to the air-gapped host and load them:

    podman load -i supervisor.tar
    podman load -i sandbox.tar
    
  3. Set pull policy to never:

    [openshell.drivers.podman]
    image_pull_policy = "never"
    

File locations

Purpose Path
Gateway binary /usr/bin/openshell-gateway
CLI binary /usr/bin/openshell
Systemd user unit /usr/lib/systemd/user/openshell-gateway.service
Default TOML config template (read-only) /usr/share/openshell-gateway/gateway.toml.default
Active gateway TOML configuration ~/.config/openshell/gateway.toml
Optional environment variable overrides ~/.config/openshell/gateway.env
TLS certificates ~/.local/state/openshell/tls/
CLI client certs ~/.config/openshell/gateways/openshell/mtls/
Gateway database ~/.local/state/openshell/gateway/openshell.db