This crate deploys an OSCAR exposed service that provides a browser-based terminal powered by ghostty-web. The terminal runs inside the service container and includes oscar-cli, tmux, and a standard Bash shell.
The service is intended to be deployed per user. By default, the launcher reads the OSCAR service access token from the mounted service FDL and reuses it as the terminal access token, so the browser login token matches the service token managed by OSCAR.
The container can also preconfigure oscar-cli against the in-cluster OSCAR API by injecting an OIDC refresh token as a secret.
ghostty-webfrontend with a PTY-backed WebSocket sessionoscar-clipreinstalled in the container imagetmuxfor optional session management inside the terminal- Persistent workspace backed by a mounted MinIO bucket
The example fdl.yml mounts the bucket path /ghostty-web from minio.default into /mnt/ghostty-web inside the container. The launcher script uses WORKSPACE_DIR directly as the working directory and also stores shell history plus oscar-cli user config there.
Keep mount.path and WORKSPACE_DIR aligned if you want to bind a different bucket or prefix for each user.
Run the build from the crate root so the Dockerfile can copy script.sh and the files under docker/:
docker build -f docker/Dockerfile -t ghcr.io/grycap/ghostty-web:0.1.0 .Push the resulting image to the registry you plan to use and update fdl.yml if needed.
Base deployment:
oscar-cli apply fdl.ymlBefore deploying, replace the placeholder secrets in fdl.yml:
OSCAR_OIDC_REFRESH_TOKEN: OIDC refresh token used byoscar-cli
Persistent workspace:
- Edit
fdl.yml - Set
mount.pathto the bucket or prefix you want to expose in/mnt - Apply the file again
After deployment, access the service through:
https://<OSCAR-ENDPOINT>/system/services/<service-name>/exposed/?token=<service-token>
On first access, the server validates the token, issues an HttpOnly session cookie, and redirects the browser to the same URL without the token query parameter. The WebSocket terminal then reuses that cookie.
When OSCAR_OIDC_REFRESH_TOKEN is set, the startup script generates ~/.oscar-cli/config.yaml with a default cluster that points to the in-cluster OSCAR service endpoint:
oscar:
local-cluster:
endpoint: http://oscar.oscar.svc.cluster.local:8080
oidc_refresh_token: <refresh-token>
ssl_verify: false
default: local-cluster- This crate assumes one deployed instance per user.
- The service is stateful from the user's point of view if a bucket is mounted, even though the exposed service itself runs as a single pod.
- If your OSCAR cluster expects
portinstead ofapi_portin theexposeblock, replace that key accordingly. - The launcher reads the token from
/oscar/config/function_config.yamlby default. You can override that path withOSCAR_SERVICE_FDL_PATH. - If the launcher cannot read a token from the OSCAR FDL, it falls back to
TERMINAL_TOKENif that environment variable is already present. - If neither the OSCAR service token nor
TERMINAL_TOKENis available, the application-side authentication is disabled and the terminal becomes publicly accessible. - The generated
oscar-cliconfig is written to~/.config/oscar/config.yamlinside the container and uses mode0600. - If you mount
/mnt, the workspace can persist independently from the in-container credentials. Review whether you want the generated CLI config to persist together with that workspace.