From 9dc4e504a290f2ee1aa0fe19a78f4f9b9a1f4743 Mon Sep 17 00:00:00 2001 From: Paulo Date: Wed, 23 Sep 2026 00:27:47 +0200 Subject: [PATCH] Boot the browser image with the drukbox base entrypoint --- .github/actions/dgoss/action.yml | 28 ++++++++++++++++++++ .github/workflows/on-pull-request-images.yml | 25 +++++++---------- deploy/browser/Dockerfile | 7 ++--- deploy/browser/entrypoint | 22 +++------------ deploy/browser/goss.yaml | 26 ++++++++++++++++++ 5 files changed, 72 insertions(+), 36 deletions(-) create mode 100644 .github/actions/dgoss/action.yml create mode 100644 deploy/browser/goss.yaml diff --git a/.github/actions/dgoss/action.yml b/.github/actions/dgoss/action.yml new file mode 100644 index 00000000..ef22a0dc --- /dev/null +++ b/.github/actions/dgoss/action.yml @@ -0,0 +1,28 @@ +name: Validate an image with goss +description: >- + Boots a loaded image the way the drukbox docker provider boots a druks box + and checks the goss.yaml beside its Dockerfile inside it. +inputs: + image: + description: The loaded image to boot. + required: true + files-path: + description: The directory that holds goss.yaml. + required: true +runs: + using: composite + steps: + - shell: bash + env: + GOSS_VERSION: 0.4.10 + GOSS_FILES_PATH: ${{ inputs.files-path }} + GOSS_OPTS: -r 30s -s 1s --format documentation + IMAGE: ${{ inputs.image }} + run: | + curl -fsSL "https://github.com/goss-org/goss/releases/download/v$GOSS_VERSION/goss_${GOSS_VERSION}_linux_x86_64.tar.gz" \ + | tar -xz -C "$RUNNER_TEMP" goss + curl -fsSL -o "$RUNNER_TEMP/dgoss" "https://github.com/goss-org/goss/releases/download/v$GOSS_VERSION/dgoss" + chmod +x "$RUNNER_TEMP/dgoss" + GOSS_PATH="$RUNNER_TEMP/goss" "$RUNNER_TEMP/dgoss" run \ + -e DRUKBOX_SSH_USER=druks -e 'DRUKBOX_AUTHORIZED_KEY=ssh-ed25519 AAAA goss' \ + "$IMAGE" diff --git a/.github/workflows/on-pull-request-images.yml b/.github/workflows/on-pull-request-images.yml index 0a657eab..1db8d939 100644 --- a/.github/workflows/on-pull-request-images.yml +++ b/.github/workflows/on-pull-request-images.yml @@ -36,21 +36,10 @@ jobs: load: true tags: druks-sandbox:pr cache-from: type=gha,scope=sandbox - # dgoss boots the image the way the drukbox docker provider does and - # checks deploy/sandbox/goss.yaml inside it. - - name: Validate the sandbox image - env: - GOSS_VERSION: 0.4.10 - GOSS_FILES_PATH: deploy/sandbox - GOSS_OPTS: -r 30s -s 1s --format documentation - run: | - curl -fsSL "https://github.com/goss-org/goss/releases/download/v$GOSS_VERSION/goss_${GOSS_VERSION}_linux_x86_64.tar.gz" \ - | tar -xz -C "$RUNNER_TEMP" goss - curl -fsSL -o "$RUNNER_TEMP/dgoss" "https://github.com/goss-org/goss/releases/download/v$GOSS_VERSION/dgoss" - chmod +x "$RUNNER_TEMP/dgoss" - GOSS_PATH="$RUNNER_TEMP/goss" "$RUNNER_TEMP/dgoss" run \ - -e DRUKBOX_SSH_USER=druks -e 'DRUKBOX_AUTHORIZED_KEY=ssh-ed25519 AAAA goss' \ - druks-sandbox:pr + - uses: ./.github/actions/dgoss + with: + image: druks-sandbox:pr + files-path: deploy/sandbox # The Docker Sandboxes template must keep its base's boot contract after # the toolchain layers: `sbx create` sends no environment variables, drukbox @@ -108,4 +97,10 @@ jobs: context: deploy/browser platforms: linux/amd64 push: false + load: true + tags: druks-browser:pr cache-from: type=gha,scope=browser + - uses: ./.github/actions/dgoss + with: + image: druks-browser:pr + files-path: deploy/browser diff --git a/deploy/browser/Dockerfile b/deploy/browser/Dockerfile index 759f0b8e..d297b9ba 100644 --- a/deploy/browser/Dockerfile +++ b/deploy/browser/Dockerfile @@ -3,12 +3,13 @@ # vault session and drive it — over CDP or pinchtab, both loopback-only, # reached through SSH like every sandbox. No harness ever runs here. # -# Built from the drukbox sandbox base (Ubuntu + sshd); the entrypoint -# seeds a non-root user and starts the display stack. +# Built from the drukbox sandbox base (Ubuntu + sshd). The image adds a +# non-root user; its entrypoint starts the display stack, then the base +# entrypoint seeds that user's key and runs sshd. # # Published by .github/workflows/publish-sandbox-image.yml as # ghcr.io/czpython/druks/browser. -FROM ghcr.io/czpython/drukbox/sandbox:latest@sha256:72c6ab246c53481051d8d4ec9ed34e9aff47f539f989f625cf20ba82e9b3f311 +FROM ghcr.io/czpython/drukbox/sandbox:latest@sha256:cccf324cada9c1b0df409858dac8188e0ed2591ed88ee3d5fb59db9055a75244 SHELL ["/bin/bash", "-o", "pipefail", "-c"] diff --git a/deploy/browser/entrypoint b/deploy/browser/entrypoint index 64621e6c..e7f9da6f 100644 --- a/deploy/browser/entrypoint +++ b/deploy/browser/entrypoint @@ -1,21 +1,9 @@ #!/usr/bin/env bash -# First-boot entrypoint. Seeds the non-root ``druks`` user like the sandbox -# entrypoint, then the display stack: Xvfb for the browser to render into, -# loopback-only VNC for the login window's bridge. SSH stays the only ingress. +# The display stack, then the drukbox base entrypoint boots the box: Xvfb for +# the browser to render into, loopback-only VNC for the login window's bridge. +# SSH stays the only ingress. set -euo pipefail -: "${DRUKBOX_AUTHORIZED_KEY:?DRUKBOX_AUTHORIZED_KEY is required}" - -install -d -m 700 -o druks -g druks /home/druks/.ssh -printf '%s\n' "$DRUKBOX_AUTHORIZED_KEY" > /home/druks/.ssh/authorized_keys -chmod 600 /home/druks/.ssh/authorized_keys -chown druks:druks /home/druks/.ssh/authorized_keys - -# Persist caller-supplied env for SSH sessions: pam_env reads /etc/environment. -for name in ${DRUKBOX_ENV_KEYS:-}; do - printf '%s=%s\n' "$name" "${!name-}" >> /etc/environment -done - Xvfb :99 -screen 0 1920x1080x24 -nolisten tcp -ac & # The VNC port binds loopback only and is reached solely over the authenticated # SSH channel, so SSH is the gate and x11vnc runs without its own password. @@ -24,6 +12,4 @@ Xvfb :99 -screen 0 1920x1080x24 -nolisten tcp -ac & x11vnc -display :99 -loop -forever -listen 127.0.0.1 -rfbport 5900 \ -nopw -noxdamage -shared & -ssh-keygen -A - -exec /usr/sbin/sshd -D -e +exec /usr/local/bin/drukbox-entrypoint diff --git a/deploy/browser/goss.yaml b/deploy/browser/goss.yaml new file mode 100644 index 00000000..bf0933ea --- /dev/null +++ b/deploy/browser/goss.yaml @@ -0,0 +1,26 @@ +# The boot contract of the browser image: the drukbox base entrypoint seeds +# the ``druks`` user this image adds, and the display stack is up on loopback. +# dgoss checks it in CI with DRUKBOX_SSH_USER=druks and +# DRUKBOX_AUTHORIZED_KEY="ssh-ed25519 AAAA goss". +file: + /home/druks/.ssh/authorized_keys: + exists: true + mode: "0600" + owner: druks + group: druks + contents: + - ssh-ed25519 AAAA goss +process: + sshd: + running: true + Xvfb: + running: true + x11vnc: + running: true +port: + tcp:22: + listening: true + tcp:5900: + listening: true + ip: + - 127.0.0.1