Skip to content

Commit a8cedbe

Browse files
committed
fix(docker): generate gateway JWT keys in compose quickstart
Fixes #2891 Signed-off-by: Eric Curtin <eric.curtin@docker.com>
1 parent 9cb72ba commit a8cedbe

3 files changed

Lines changed: 36 additions & 23 deletions

File tree

‎deploy/docker/docker-compose.yml‎

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#
1010
# Quick start:
1111
#
12-
# 1. Start the gateway:
12+
# 1. Start the gateway (init first generates JWT keys in /var/lib/openshell/tls):
1313
# docker compose up -d
1414
#
1515
# 2. Register the gateway with the CLI (one-time):
@@ -49,19 +49,16 @@
4949
# bind-mount source when sandbox containers are created. Named volumes
5050
# cannot be used here because Docker resolves bind-mount sources against the
5151
# host filesystem, not the container filesystem.
52-
#
53-
# Linux note:
54-
# host.docker.internal and host.openshell.internal are not automatically
55-
# added on Linux Docker. Add the following under the gateway service:
56-
# extra_hosts:
57-
# - "host.docker.internal:host-gateway"
58-
# - "host.openshell.internal:host-gateway"
5952

6053
services:
6154
gateway:
62-
image: ghcr.io/nvidia/openshell/gateway:${IMAGE_TAG:-latest}
55+
image: &gateway-image ghcr.io/nvidia/openshell/gateway:${IMAGE_TAG:-latest}
6356
restart: unless-stopped
6457

58+
depends_on:
59+
init:
60+
condition: service_completed_successfully
61+
6562
# Clear the default CMD so gateway.toml owns all settings (see note above).
6663
command: []
6764

@@ -96,7 +93,8 @@ services:
9693
# (e.g. /var/lib/openshell/gateway): the path must match exactly on
9794
# both the host and inside the container, and a single gateway per host
9895
# is the expected topology.
99-
- type: bind
96+
- &openshell-data
97+
type: bind
10098
source: /var/lib/openshell
10199
target: /var/lib/openshell
102100
bind:
@@ -126,3 +124,14 @@ services:
126124
# bind-mounted directory so its path is resolvable by the host Docker daemon.
127125
XDG_DATA_HOME: /var/lib/openshell
128126
HOME: /var/lib/openshell
127+
128+
# One-shot: generates the sandbox JWT keys (kept if present).
129+
init:
130+
image: *gateway-image
131+
user: "0"
132+
restart: "no"
133+
command: ["generate-certs", "--output-dir", "/var/lib/openshell/tls"]
134+
environment:
135+
HOME: /var/lib/openshell
136+
volumes:
137+
- *openshell-data

‎deploy/docker/gateway.toml‎

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@
1414
# clearing the CMD first.
1515
#
1616
# grpc_endpoint note:
17-
# host.docker.internal is automatically resolvable from containers on
18-
# Docker Desktop (Windows / macOS). On Linux, add extra_hosts to the
19-
# gateway service:
20-
# extra_hosts:
21-
# - "host.docker.internal:host-gateway"
22-
# - "host.openshell.internal:host-gateway"
17+
# Omitted on purpose. The supervisor uses host networking and reaches the
18+
# published port at http://127.0.0.1:8080 (keep OPENSHELL_PORT at 8080).
2319

2420
[openshell]
2521
version = 2
@@ -33,6 +29,18 @@ log_level = "info"
3329
compute_driver = "docker"
3430
disable_tls = true
3531

32+
# No TLS and loopback only: user calls are unauthenticated.
33+
# Supervisors still authenticate with the JWT keys below.
34+
[openshell.gateway.auth]
35+
allow_unauthenticated_users = true
36+
37+
# Written by the compose init service.
38+
[openshell.gateway.gateway_jwt]
39+
signing_key_path = "/var/lib/openshell/tls/jwt/signing.pem"
40+
public_key_path = "/var/lib/openshell/tls/jwt/public.pem"
41+
kid_path = "/var/lib/openshell/tls/jwt/kid"
42+
gateway_id = "openshell-docker"
43+
3644
[openshell.drivers.docker]
3745
# Default image pulled for `openshell sandbox create` without --from.
3846
default_image = "nvcr.io/nvidia/base/ubuntu:24.04"
@@ -44,12 +52,6 @@ supervisor_image = "ghcr.io/nvidia/openshell/supervisor:latest"
4452
image_pull_policy = "if_not_present"
4553
# Value assigned to the openshell.sandbox_namespace label on sandbox containers.
4654
sandbox_label = "openshell"
47-
# Address sandbox containers use to call back to the gateway.
48-
# The Docker driver replaces the host with host.openshell.internal and the
49-
# port with the gateway's own bind port (8080). Only the scheme survives.
50-
# The gateway must be published on port 8080 on the Docker host so that
51-
# host.openshell.internal:8080 resolves to the gateway container.
52-
grpc_endpoint = "http://host.openshell.internal:8080"
5355
# Explicit supervisor-compatible Docker default. Set RuntimeDefault or
5456
# Localhost/<profile> only when the daemon host has AppArmor available.
5557
app_armor_profile = "Unconfined"

‎docs/how-it-works/gateways/container-deployment.mdx‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ the repository contains a production-ready Compose setup with full inline docume
156156

157157
| File | Purpose |
158158
|---|---|
159-
| `docker-compose.yml` | Gateway service, volumes, and environment variables |
159+
| `docker-compose.yml` | Gateway and init services, volumes, and environment variables |
160160
| `gateway.toml` | TOML configuration mounted into the container |
161161

162162
Clone or copy those files, then start the gateway:
@@ -165,6 +165,8 @@ Clone or copy those files, then start the gateway:
165165
docker compose -f deploy/docker/docker-compose.yml up -d
166166
```
167167

168+
The `init` service runs first and writes the sandbox JWT signing keys to `/var/lib/openshell/tls` on the host. The Docker driver requires them, and existing keys are kept. Do not commit them. This setup disables TLS and user authentication and publishes the port on loopback only.
169+
168170
Register the gateway with the CLI. If registering from the same machine:
169171

170172
```shell

0 commit comments

Comments
 (0)