Configuring a Workshop Image
Orchestra runs each workshop session behind two authentication layers, so the application inside the pod must start unauthenticated. You don’t need to build a custom image for this — point a template at a stock upstream image and configure it with the template’s App Port, Environment variables, and Container args fields.
The no-auth contract
Section titled “The no-auth contract”Every session is fronted by oauth2-proxy (at the ingress, establishes who the user is) and the per-pod Orchestra sidecar (enforces session ownership). By the time a request reaches your app, it’s already authenticated. If the app also requires a login, participants get a confusing second prompt — and in the proxied setup they often can’t satisfy it (e.g. a JupyterLab token they never see). So the app must:
- start with its own auth disabled, and
- listen on a single HTTP port, set as the template’s App Port (the sidecar
proxies to
http://localhost:<port>).
The fields
Section titled “The fields”- App Port — the port the app listens on. RStudio:
8787. JupyterLab:8888. - Environment variables — one
KEY=valueper line. Merged on top of the operator’s defaults (DISABLE_AUTH,ROOT), with your values winning. - Container args — one argument per line. Replaces the image’s default command (CMD) while keeping its entrypoint.
Recipes
Section titled “Recipes”Stock rocker/rstudio and bioconductor/bioconductor_docker images work with
no env or args — the operator already injects DISABLE_AUTH=true and
ROOT=true, which rocker honors to skip the login.
- App Port:
8787 - Environment variables: (empty)
- Container args: (empty)
To re-enable the RStudio login for some reason, override the default:
DISABLE_AUTH=falseStock docker-stacks images (quay.io/jupyter/base-notebook, minimal-notebook,
scipy-notebook, …) need args to disable the token and accept proxied requests.
- App Port:
8888 - Container args:
start-notebook.py--IdentityProvider.token=--ServerApp.token=--ServerApp.password=--ServerApp.allow_origin=*--ServerApp.trust_xheaders=True--ServerApp.disable_check_xsrf=True--ServerApp.ip=0.0.0.0Why each line:
start-notebook.py— the image’s launcher; must be first (args replace CMD).--IdentityProvider.token=/--ServerApp.token=/--ServerApp.password=— empty values disable the login.--ServerApp.allow_origin=*,--trust_xheaders=True,--disable_check_xsrf=True— let proxied XHR/WebSocket requests through; token-disable alone isn’t enough behind a reverse proxy.--ServerApp.ip=0.0.0.0— bind all interfaces so the sidecar can reach it.
Verifying
Section titled “Verifying”-
Save the template, then launch a session from it.
-
Confirm the spec carries your values:
Terminal window kubectl get workshop <name> -o jsonpath='{.spec.port} {.spec.env} {.spec.args}{"\n"}' -
Confirm the app container got them, and the sidecar targets the right port:
Terminal window kubectl get pod <pod> -o jsonpath='{range .spec.containers[*]}{.name}: env={.env[*].name} args={.args}{"\n"}{end}' -
Open the session URL — you should land directly in RStudio/JupyterLab with no in-app login prompt (oauth2-proxy still guards the front door).
Anything else
Section titled “Anything else”The contract is image-agnostic. Any image works as long as it can start without authentication and listen on one HTTP port — set that port as App Port, and use env/args to turn off whatever login it ships with.