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
9 changes: 6 additions & 3 deletions architecture/gateway.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,12 @@ created. Both deployment paths use it:

On Kubernetes, the Helm chart runs the command via a pre-install/pre-upgrade
hook Job using the gateway image itself -- no separate cert-generation image,
no extra mirror burden in air-gapped environments. On the RPM gateway, the
same command runs from the systemd unit's `ExecStartPre` to bootstrap PKI
into the user's state directory on first start.
no extra mirror burden in air-gapped environments. On package-managed local
gateways, the same command runs from the systemd unit's `ExecStartPre` to
bootstrap PKI into the configured local TLS directory on first start. The
Linux package unit defaults that directory to `~/.local/state/openshell/tls`
through `OPENSHELL_LOCAL_TLS_DIR` so certificate generation and runtime
auto-detection use the same path across systemd versions.

Both modes share the same idempotency contract: all targets present -> skip;
partial state -> fail with a recovery hint; nothing present -> generate and
Expand Down
4 changes: 3 additions & 1 deletion crates/openshell-sandbox/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ use std::os::unix::io::RawFd;
use std::path::PathBuf;
use std::process::Stdio;
use tokio::process::{Child, Command};
use tracing::{debug, warn};
use tracing::debug;
#[cfg(target_os = "linux")]
use tracing::warn;

fn inject_provider_env(cmd: &mut Command, provider_env: &HashMap<String, String>) {
for (key, value) in provider_env {
Expand Down
3 changes: 2 additions & 1 deletion deploy/deb/openshell-gateway.service
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ After=default.target
[Service]
Type=simple
StateDirectory=openshell/gateway
Environment=OPENSHELL_LOCAL_TLS_DIR=%h/.local/state/openshell/tls
EnvironmentFile=-%E/openshell/gateway.env
ExecStartPre=/usr/bin/openshell-gateway generate-certs --output-dir %S/openshell/tls --server-san host.openshell.internal
ExecStartPre=/usr/bin/openshell-gateway generate-certs --output-dir ${OPENSHELL_LOCAL_TLS_DIR} --server-san host.openshell.internal
ExecStart=/usr/bin/openshell-gateway
Restart=on-failure
RestartSec=5s
Expand Down
6 changes: 5 additions & 1 deletion deploy/man/openshell-gateway.8.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@ View logs:
The unit runs **openshell-gateway generate-certs** as an **ExecStartPre**
step on first start. This generates a self-signed PKI bundle for mTLS
and sandbox JWT signing material, adding missing JWT files to older
TLS-only installs when needed.
TLS-only installs when needed. The packaged unit sets
**OPENSHELL_LOCAL_TLS_DIR** to *~/.local/state/openshell/tls* and uses that
same value for certificate generation and gateway startup. Override
**OPENSHELL_LOCAL_TLS_DIR** in *~/.config/openshell/gateway.env* only if you
need a custom bundle location.

The gateway then starts from built-in defaults and reads
*~/.config/openshell/gateway.toml* when that file exists.
Expand Down
5 changes: 4 additions & 1 deletion deploy/rpm/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ client certificate for all API connections and listens on
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):
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 |
|------|---------|----------|
Expand Down
6 changes: 4 additions & 2 deletions openshell.spec
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,10 @@ Type=exec
ExecStartPre=/bin/sh -c 'test -f %%E/openshell/gateway.toml || install -Dm644 /usr/share/openshell-gateway/gateway.toml.default %%E/openshell/gateway.toml'

# Auto-generate PKI on first start if not present.
# %%S expands to $XDG_STATE_HOME (~/.local/state) in user units.
ExecStartPre=/usr/bin/openshell-gateway generate-certs --output-dir %%S/openshell/tls --server-san host.openshell.internal
# The default local TLS dir uses %%h because %%S resolves differently across
# systemd user-manager versions. gateway.env may override this path.
Environment=OPENSHELL_LOCAL_TLS_DIR=%%h/.local/state/openshell/tls
ExecStartPre=/usr/bin/openshell-gateway generate-certs --output-dir ${OPENSHELL_LOCAL_TLS_DIR} --server-san host.openshell.internal

# gateway.env is honored for backward compatibility with pre-1415 installs.
# New installs use runtime defaults; create gateway.toml to override.
Expand Down
14 changes: 12 additions & 2 deletions python/openshell/release_formula_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,13 @@ def test_rpm_spec_uses_gateway_defaults_without_config_helper() -> None:

assert "init-gateway-config.sh" not in spec
assert "init-pki.sh" not in spec
assert "openshell-gateway generate-certs --output-dir %%S/openshell/tls" in spec
assert "Environment=OPENSHELL_LOCAL_TLS_DIR=%%h/.local/state/openshell/tls" in spec
assert (
"openshell-gateway generate-certs --output-dir ${OPENSHELL_LOCAL_TLS_DIR}"
in spec
)
assert "EnvironmentFile=-%%E/openshell/gateway.env" in spec
assert "%%S/openshell/tls" not in spec
assert "Environment=OPENSHELL_DRIVERS" not in spec
assert "Environment=OPENSHELL_BIND_ADDRESS" not in spec
assert "Environment=OPENSHELL_PODMAN_TLS_CA" not in spec
Expand All @@ -136,7 +141,12 @@ def test_deb_user_service_uses_gateway_defaults_without_config_helper() -> None:
)

assert "EnvironmentFile=-%E/openshell/gateway.env" in unit
assert "openshell-gateway generate-certs --output-dir %S/openshell/tls" in unit
assert "Environment=OPENSHELL_LOCAL_TLS_DIR=%h/.local/state/openshell/tls" in unit
assert (
"openshell-gateway generate-certs --output-dir ${OPENSHELL_LOCAL_TLS_DIR}"
in unit
)
assert "%S/openshell/tls" not in unit
assert "init-gateway-config.sh" not in unit
assert "ExecStart=/usr/bin/openshell-gateway" in unit
assert "--config" not in unit
Expand Down
50 changes: 50 additions & 0 deletions tasks/scripts/test-packaging-assets.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"

assert_contains() {
local file=$1
local expected=$2

if ! grep -Fq "$expected" "$file"; then
echo "FAIL: ${file} is missing expected text:" >&2
echo " ${expected}" >&2
exit 1
fi
}

assert_not_contains() {
local file=$1
local unexpected=$2

if grep -Fq "$unexpected" "$file"; then
echo "FAIL: ${file} contains stale text:" >&2
echo " ${unexpected}" >&2
exit 1
fi
}

service="${ROOT}/deploy/deb/openshell-gateway.service"
spec="${ROOT}/openshell.spec"

assert_contains \
"$service" \
'Environment=OPENSHELL_LOCAL_TLS_DIR=%h/.local/state/openshell/tls'
assert_contains \
"$service" \
'ExecStartPre=/usr/bin/openshell-gateway generate-certs --output-dir ${OPENSHELL_LOCAL_TLS_DIR} --server-san host.openshell.internal'
assert_not_contains "$service" '%S/openshell/tls'

assert_contains \
"$spec" \
'Environment=OPENSHELL_LOCAL_TLS_DIR=%%h/.local/state/openshell/tls'
assert_contains \
"$spec" \
'ExecStartPre=/usr/bin/openshell-gateway generate-certs --output-dir ${OPENSHELL_LOCAL_TLS_DIR} --server-san host.openshell.internal'
assert_not_contains "$spec" '%%S/openshell/tls'

echo "packaging asset tests passed"
7 changes: 6 additions & 1 deletion tasks/test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@

[test]
description = "Run all tests (Rust + Python)"
depends = ["test:rust", "test:python", "test:install-sh"]
depends = ["test:rust", "test:python", "test:install-sh", "test:packaging-assets"]

["test:install-sh"]
description = "Run focused install.sh shell tests"
run = "tasks/scripts/test-install-sh.sh"
hide = true

["test:packaging-assets"]
description = "Run static packaging asset tests"
run = "tasks/scripts/test-packaging-assets.sh"
hide = true

[e2e]
description = "Run all end-to-end tests (Rust + Python)"
depends = ["e2e:rust", "e2e:python"]
Expand Down
Loading