NVIDIA / NVIDIA/OpenShell

feat: minimize gateway Docker image to reduce attack surface and pull size

Open
#1,009 2 comments 0 reactions 1 assignee View on GitHub

@drew is already working on this.

Since Apr 29, 2026.

state:stale
Dominant language
Rust
Stars
8.7k
Forks
1.3k
Avg merge
2d 11h
Merged PRs (30d)
253

Description

Problem Statement

The gateway runtime image is based on nvcr.io/nvidia/base/ubuntu:noble-20251013, a full Ubuntu userspace. While the multi-stage build already avoids shipping build tools, the final image still carries unnecessary OS packages, shells, and utilities that increase:

  1. Attack surface — a compromised container has access to package managers, shells, and system utilities that aid lateral movement.
  2. Image size — larger images slow cold-start pulls, especially in air-gapped or bandwidth-constrained environments.
  3. CVE noise — distro packages accumulate vulnerabilities unrelated to the gateway binary, increasing scanner findings and maintenance burden.
Proposed Design
1. Switch base image to distroless

Replace nvcr.io/nvidia/base/ubuntu:noble with gcr.io/distroless/cc-debian13:nonroot.

This image includes glibc and libgcc — sufficient for the dynamically-linked Rust binary (built with x86_64-unknown-linux-gnu / aarch64-unknown-linux-gnu targets) — but ships no shell, no package manager, and no unnecessary utilities. It is ~20 MB compressed vs ~80 MB for the Ubuntu base.

A follow-up issue can evaluate switching to static-debian13 with a musl-linked binary for an even smaller footprint (~2 MB base), but that requires target/toolchain changes and broader testing.

2. Remove unnecessary migrations COPY

The current Dockerfile copies crates/openshell-server/migrations/ into the final image. This is unnecessary — migrations are embedded into the binary at compile time via sqlx::migrate!("./migrations/sqlite") and sqlx::migrate!("./migrations/postgres") proc macros. Removing this COPY eliminates dead weight from the image.

3. Minimal final stage
FROM gcr.io/distroless/cc-debian13:nonroot AS gateway
COPY --from=gateway-binary /build/out/openshell-gateway /usr/local/bin/
ENTRYPOINT ["openshell-gateway"]
CMD ["--port", "8080"]

Optionally the openshell user (UID 1000) can be preserved.

CA certs are included in the distroless base. No other runtime files are needed.

Alternatives Considered
  • distroless/static-debian13 — smallest possible (~2 MB) but requires switching to x86_64-unknown-linux-musl and verifying all crate dependencies work under musl. Better as a follow-up.
  • Alpine-based image — smaller than Ubuntu but still ships a shell, package manager, and introduces musl quirks (DNS resolver, stack size defaults).
  • Keep Ubuntu, remove packages — fragile (apt remove can break dep chains), doesn't eliminate shell or package manager, still large.
  • Chainguard cgr.dev/chainguard/cc-dynamic — signed and SBOM-attached but adds an external registry dependency.
Agent Investigation

Current state of deploy/docker/Dockerfile.images gateway stage:

  • Multi-stage build already separates builder from runtime.
  • Final stage: FROM nvcr.io/nvidia/base/ubuntu:noble-20251013 AS gateway
  • Installs ca-certificates and upgrades gpgv at runtime.
  • Copies binary + migrations (migrations COPY is unnecessary — embedded via sqlx::migrate!()).
  • Runs as openshell user (UID 1000).
  • Debug symbols already stripped (strip = true in [profile.release]).
  • Binary is dynamically linked against glibc (*-unknown-linux-gnu targets in cross-build.sh).

Estimated compressed image size: current ~100+ MB → ~30-40 MB with cc-debian13 + removing dead COPY.

Checklist
  • I've reviewed existing issues and the architecture docs
  • This is a design proposal, not a "please build this" request

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.