Skip to content
Merged
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
2 changes: 1 addition & 1 deletion INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ A protocol-specific `400` or `404` can still prove connectivity. `Connection ref

## Chromium Sandbox

Hatch keeps Chromium's sandbox enabled when the container runtime allows it. If the container is started with `--security-opt no-new-privileges:true`, Chromium cannot use its setuid sandbox, so Hatch automatically adds `--no-sandbox` for that session.
If the container is started with `--security-opt no-new-privileges:true`, Chromium cannot use its setuid sandbox, so Hatch automatically adds `--no-sandbox` for that session. Hatch also adds Chromium's `--test-type` flag in that mode to suppress Chromium's unsupported command-line flag warning.

If an unusually restrictive host still prevents Chromium from starting, diagnose the host first. As a last resort, set:

Expand Down
2 changes: 2 additions & 0 deletions PRD.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Hatch must provide browser-based desktop access through HTTPS from the container
### Acceptance Criteria

- The default container listens on HTTPS port `443`.
- Plain HTTP requests sent to the published HTTPS port redirect to the equivalent `https://` URL.
- The HTTPS server proxies `/guacamole/` to Guacamole on `127.0.0.1:8080`.
- Guacamole connects through `guacd` on `127.0.0.1:4822`.
- `guacd` connects to xrdp on `127.0.0.1:3389`.
Expand All @@ -17,5 +18,6 @@ Hatch must provide browser-based desktop access through HTTPS from the container
- The generated Guacamole credentials are printed to container logs and usable when the container is started detached.
- Docker users can map any host port to container port `443`, for example `-p 8443:443`.
- Host-network OAuth callback mode remains documented for cases where Chromium must reach a callback listener on host loopback.
- Default Docker and Docker Compose starts do not show Chromium's unsupported `--no-sandbox` warning.
- The README presents the HTTPS Guacamole flow as the primary quickstart and keeps Docker Compose as a lower-priority option.
- An E2E smoke test validates the HTTPS Guacamole login path and confirms the browser desktop starts.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ Do not publish direct RDP access. Hatch exposes HTTPS for browser access, and xr

The default certificate is self-signed. Use a reverse proxy, load balancer, or mounted certificate files if you need a publicly trusted certificate. Certbot HTTP-01 validation requires public port 80, while DNS-01 can issue certificates without opening port 80.

When the container is started with `--security-opt no-new-privileges:true`, Hatch automatically adds Chromium's `--no-sandbox` flag because the setuid sandbox cannot run under that kernel setting.
When the container is started with `--security-opt no-new-privileges:true`, Hatch automatically adds Chromium's `--no-sandbox` compatibility flag because the setuid sandbox cannot run under that kernel setting. Hatch also adds Chromium's `--test-type` flag in that mode to suppress Chromium's unsupported command-line flag warning.

Browser persistence is off by default. If persistent browser sessions are required, mount `/home/oauth/.config/chromium` as a Docker volume and protect it as sensitive authentication material.

Expand Down
2 changes: 1 addition & 1 deletion config/chromium-launch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -eu
FLAGS="--disable-dev-shm-usage --no-first-run --no-default-browser-check --disable-session-crashed-bubble"
if grep -q '^NoNewPrivs:[[:space:]]*1$' /proc/self/status 2>/dev/null; then
FLAGS="$FLAGS --no-sandbox"
FLAGS="$FLAGS --no-sandbox --test-type"
fi
if [ "$#" -eq 0 ]; then set -- about:blank; fi
# shellcheck disable=SC2086
Expand Down
15 changes: 14 additions & 1 deletion scripts/e2e-guacamole.sh
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ if ! curl -kfsS "https://127.0.0.1:${HTTPS_PORT}/guacamole/" >/dev/null; then
exit 1
fi

HTTP_REDIRECT_LOCATION="$(curl -sSI "http://127.0.0.1:${HTTPS_PORT}/" 2>/dev/null | sed -n 's/^[Ll]ocation: //p' | tr -d '\r' | tail -n 1 || true)"
if [ "$HTTP_REDIRECT_LOCATION" != "https://127.0.0.1:${HTTPS_PORT}/" ]; then
docker logs "${PREFIX}-hatch" >&2 || true
echo "ERROR: HTTP on the HTTPS port did not redirect to https://127.0.0.1:${HTTPS_PORT}/." >&2
echo "Observed Location: ${HTTP_REDIRECT_LOCATION:-<none>}" >&2
exit 1
fi

GUAC_USER="$(docker logs "${PREFIX}-hatch" 2>&1 | sed -n 's/^Guacamole user: //p' | tail -n 1)"
GUAC_PASSWORD="$(docker logs "${PREFIX}-hatch" 2>&1 | sed -n 's/^Guacamole password: //p' | tail -n 1)"
if [ -z "$GUAC_USER" ] || [ -z "$GUAC_PASSWORD" ]; then
Expand Down Expand Up @@ -121,7 +129,12 @@ GUAC_PASSWORD="$GUAC_PASSWORD" \
}

for _ in $(seq 1 45); do
if docker exec "${PREFIX}-hatch" sh -lc "pgrep -af 'chromium.*${URL}' >/dev/null"; then
if docker exec -e EXPECTED_URL="$URL" "${PREFIX}-hatch" sh -lc "pgrep -af '[c]hromium' | grep -F -- \"\$EXPECTED_URL\" >/dev/null"; then
if ! docker exec -e EXPECTED_URL="$URL" "${PREFIX}-hatch" sh -lc "pgrep -af '[c]hromium' | grep -F -- \"\$EXPECTED_URL\" | grep -F -- '--test-type' >/dev/null"; then
echo "ERROR: Chromium did not start with --test-type to suppress unsupported flag warnings." >&2
docker exec -e EXPECTED_URL="$URL" "${PREFIX}-hatch" sh -lc "pgrep -af '[c]hromium' | grep -F -- \"\$EXPECTED_URL\" || true" >&2 || true
exit 1
fi
echo "Guacamole E2E succeeded: HTTPS login reached Hatch RDP and Chromium opened $URL"
exit 0
fi
Expand Down
1 change: 1 addition & 0 deletions scripts/guacamole-config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ server {
ssl_certificate_key $TLS_KEY;
ssl_protocols TLSv1.2 TLSv1.3;
absolute_redirect off;
error_page 497 =301 https://\$http_host\$request_uri;

access_log /dev/stdout;
error_log /dev/stderr warn;
Expand Down
Loading