Skip to content
Open
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
15 changes: 15 additions & 0 deletions images/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## How to test kernel-images changes locally with docker

- Make relevant changes to kernel-images example adding a new endpoint at `kernel-images/server/cmd/api/api/computer.go`, example I added `SetCursor()` endpoint.
- Run openApi to generate the boilerplate for the new endpoints with make oapi-generate
- Check changes at `kernel-images/server/lib/oapi/oapi.go`
- `cd kernel-images/images/chromium-headful`
- Build and run the docker image with `./build-docker.sh && ENABLE_WEBRTC=true ./run-docker.sh`
- Open http://localhost:8080/ in your browser
- Now new endpoint should be available for tests example curl command:
```sh
curl -X POST localhost:444/computer/cursor \
-H "Content-Type: application/json" \
-d '{"hidden": true}'
```

190 changes: 131 additions & 59 deletions images/chromium-headful/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,75 +1,166 @@
FROM docker.io/golang:1.25.0 AS server-builder
WORKDIR /workspace/server

ARG TARGETOS
# Allow cross-compilation when building with BuildKit platforms
ARG TARGETARCH
ARG TARGETOS
ARG CACHEIDPREFIX=${TARGETOS:-linux}-${TARGETARCH:-amd64}-golang1250
ENV CGO_ENABLED=0

COPY server/go.mod ./
COPY server/go.sum ./
RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
RUN --mount=type=cache,target=/root/.cache/go-build,id=$CACHEIDPREFIX-go-build \
--mount=type=cache,target=/go/pkg/mod,id=$CACHEIDPREFIX-go-pkg-mod \
go mod download

COPY server/ .

# Build kernel-images API
RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
RUN --mount=type=cache,target=/root/.cache/go-build,id=$CACHEIDPREFIX-go-build \
--mount=type=cache,target=/go/pkg/mod,id=$CACHEIDPREFIX-go-pkg-mod \
GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-amd64} \
go build -ldflags="-s -w" -o /out/kernel-images-api ./cmd/api

# Build chromium launcher
RUN GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-amd64} \
RUN --mount=type=cache,target=/root/.cache/go-build,id=$CACHEIDPREFIX-go-build \
--mount=type=cache,target=/go/pkg/mod,id=$CACHEIDPREFIX-go-pkg-mod \
GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-amd64} \
go build -ldflags="-s -w" -o /out/chromium-launcher ./cmd/chromium-launcher

# webrtc client
FROM node:22-bullseye-slim AS client
WORKDIR /src

# Allow cross-compilation when building with BuildKit platforms
ARG TARGETARCH
ARG TARGETOS
ARG CACHEIDPREFIX=${TARGETOS:-linux}-${TARGETARCH:-amd64}-node22bullseye

COPY images/chromium-headful/client/package*.json ./
RUN --mount=type=cache,target=/root/.npm npm install
RUN --mount=type=cache,target=/root/.npm,id=$CACHEIDPREFIX-npm npm install
COPY images/chromium-headful/client/ .
RUN --mount=type=cache,target=/root/.npm npm run build
RUN --mount=type=cache,target=/root/.npm,id=$CACHEIDPREFIX-npm npm run build

# xorg dependencies
FROM docker.io/ubuntu:22.04 AS xorg-deps
WORKDIR /xorg

# Allow cross-compilation when building with BuildKit platforms
ARG TARGETARCH
ARG TARGETOS
ARG CACHEIDPREFIX=${TARGETOS:-linux}-${TARGETARCH:-amd64}-ubuntu2204

ENV DEBIAN_FRONTEND=noninteractive
RUN --mount=type=cache,target=/var/cache/apt,sharing=private,id=ubuntu2204-aptcache \
--mount=type=cache,target=/var/lib/apt,sharing=private,id=ubuntu2204-aptlib \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-apt-cache \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=$CACHEIDPREFIX-apt-lib \
set -eux; \
rm -f /etc/apt/apt.conf.d/docker-clean; \
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache; \
set -eux; \
apt-get update; \
apt-get --no-install-recommends -y install \
git gcc pkgconf autoconf automake libtool make xorg-dev xutils-dev;
COPY images/chromium-headful/xorg-deps/ /xorg/
# build xf86-video-dummy v0.3.8 with RandR support
RUN set -eux; \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-apt-cache \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=$CACHEIDPREFIX-apt-lib \
set -eux; \
cd xf86-video-dummy/v0.3.8; \
patch -p1 < ../01_v0.3.8_xdummy-randr.patch; \
autoreconf -v --install; \
./configure; \
make -j$(nproc); \
make install;
# build custom input driver
RUN set -eux; \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-apt-cache \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=$CACHEIDPREFIX-apt-lib \
set -eux; \
cd xf86-input-neko; \
./autogen.sh --prefix=/usr; \
./configure; \
make -j$(nproc); \
make install;

FROM docker.io/ubuntu:22.04 AS ffmpeg-downloader

# Allow cross-compilation when building with BuildKit platforms
ARG TARGETARCH
ARG TARGETOS
ARG CACHEIDPREFIX=${TARGETOS:-linux}-${TARGETARCH:-amd64}-ubuntu2204

RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-apt-cache \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=$CACHEIDPREFIX-apt-lib \
set -xe; \
rm -f /etc/apt/apt.conf.d/docker-clean; \
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache; \
apt-get -yqq update; \
apt-get -yqq --no-install-recommends install ca-certificates curl xz-utils;

# Download FFmpeg (latest static build) for the recording server
RUN --mount=type=cache,target=/tmp/cache/ffmpeg,sharing=locked,id=$CACHEIDPREFIX-ffmpeg \
<<-'EOT'
set -eux
FFMPEG_CACHE_PATH="/tmp/cache/ffmpeg"
case ${TARGETARCH:-amd64} in
"amd64") FFMPEG_TARGET_ARCH="64" ;;
"arm64") FFMPEG_TARGET_ARCH="arm64" ;;
esac
FFMPEG_TARGET=linux${FFMPEG_TARGET_ARCH:?}
ARCHIVE_NAME="ffmpeg-n7.1-latest-${FFMPEG_TARGET}-gpl-7.1.tar.xz"
FFMPEG_CACHED_ARCHIVE_PATH="$FFMPEG_CACHE_PATH/$ARCHIVE_NAME"
FFMPEG_CACHED_ARCHIVE_CHECKSUM_PATH="$FFMPEG_CACHED_ARCHIVE_PATH.sha256"
URL="https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/$ARCHIVE_NAME"
TEMPORARY_SHA256_CHECKSUM_PATH=$(mktemp /tmp/tmp_sha256.XXXXXXXXXX)
CONTINUE="true"
echo "Downloading FFmpeg checksum"
if curl --connect-timeout 10 -fsSL "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/checksums.sha256" -o $TEMPORARY_SHA256_CHECKSUM_PATH; then
grep -F "$ARCHIVE_NAME" $TEMPORARY_SHA256_CHECKSUM_PATH > $FFMPEG_CACHED_ARCHIVE_CHECKSUM_PATH
else
echo "Failed to connect to ffmpeg static build provider for checksum."
echo "Checking for cached version to use."
if [ -f "$FFMPEG_CACHED_ARCHIVE_CHECKSUM_PATH" ]; then
echo "Found cached checksum."
else
echo "Unable to locate cached checksum."
CONTINUE="false"
fi
fi
rm $TEMPORARY_SHA256_CHECKSUM_PATH

if [ "$CONTINUE" = "false" ]; then
exit 1
fi

echo "Checking cache for FFmpeg archive and validating checksum"
if (cd $FFMPEG_CACHE_PATH && sha256sum --check $FFMPEG_CACHED_ARCHIVE_CHECKSUM_PATH); then
echo "Checksum validated, using cached FFmpeg archive"
else
echo "Downloading FFmpeg static build from $URL"
curl -fsSL "$URL" -o $FFMPEG_CACHED_ARCHIVE_PATH
echo "Validating checksum of FFmpeg static build download"
(cd $FFMPEG_CACHE_PATH && sha256sum --check $FFMPEG_CACHED_ARCHIVE_CHECKSUM_PATH)
fi

tar -xJf $FFMPEG_CACHED_ARCHIVE_PATH -C /tmp
install -m755 /tmp/ffmpeg-*/bin/ffmpeg /usr/local/bin/ffmpeg
install -m755 /tmp/ffmpeg-*/bin/ffprobe /usr/local/bin/ffprobe
rm -rf /tmp/ffmpeg*
EOT

FROM ghcr.io/onkernel/neko/base:3.0.8-v1.3.0 AS neko
# ^--- now has event.SYSTEM_PONG with legacy support to keepalive
FROM node:22-bullseye-slim AS node-22
FROM docker.io/ubuntu:22.04

# Allow cross-compilation when building with BuildKit platforms
ARG TARGETARCH
ARG TARGETOS
ARG CACHEIDPREFIX=${TARGETOS:-linux}-${TARGETARCH:-amd64}-ubuntu2204

ENV DEBIAN_FRONTEND=noninteractive
ENV DEBIAN_PRIORITY=high

RUN --mount=type=cache,target=/var/cache/apt,sharing=private,id=ubuntu2204-aptcache \
--mount=type=cache,target=/var/lib/apt,sharing=private,id=ubuntu2204-aptlib \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-apt-cache \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=$CACHEIDPREFIX-apt-lib \
rm -f /etc/apt/apt.conf.d/docker-clean; \
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache; \
apt-get update && \
Expand Down Expand Up @@ -119,50 +210,21 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=private,id=ubuntu2204-aptca
fonts-nanum \
fontconfig \
unzip && \
apt-get clean && fc-cache -f
fc-cache -f

# install ffmpeg manually since the version available in apt is from the 4.x branch due to #drama.
# as of writing these static builds will be the latest 7.0.x release.
RUN --mount=type=cache,target=/tmp/cache/ffmpeg,id=ffmpeg \
<<-'EOT'
set -eux
URL="https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz"
echo "Downloading FFmpeg MD5 checksum"
if ! curl --connect-timeout 10 -fsSL "${URL}.md5" -o /tmp/cache/ffmpeg/ffmpeg.tar.xz.md5; then
echo "Failed to connect to ffmpeg static build provider for MD5 checksum."
echo "Checking for cached version to use."
if [ ! -f /tmp/cache/ffmpeg/ffmpeg.tar.xz.md5 ]; then
echo "Unable to locate cached MD5 checksum. Exiting."
exit 1
else
echo "Found cached MD5 checksum."
fi
fi
sed -i -e 's/ .*$/ \/tmp\/cache\/ffmpeg\/ffmpeg.tar.xz/' /tmp/cache/ffmpeg/ffmpeg.tar.xz.md5
echo "Checking cache for FFmpeg archive and validating MD5 checksum"
if md5sum --check /tmp/cache/ffmpeg/ffmpeg.tar.xz.md5; then
echo "Checksum validated, using cached FFmpeg archive"
else
echo "Downloading FFmpeg static build from $URL"
curl -fsSL "$URL" -o /tmp/cache/ffmpeg/ffmpeg.tar.xz
echo "Validating MD5 checksum of FFmpeg static build download"
md5sum --check /tmp/cache/ffmpeg/ffmpeg.tar.xz.md5
fi
tar -xJf /tmp/cache/ffmpeg/ffmpeg.tar.xz -C /tmp
install -m755 /tmp/ffmpeg-*/ffmpeg /usr/local/bin/ffmpeg
install -m755 /tmp/ffmpeg-*/ffprobe /usr/local/bin/ffprobe
rm -rf /tmp/ffmpeg*
EOT
COPY --from=ffmpeg-downloader /usr/local/bin/ffmpeg /usr/local/bin/ffmpeg
COPY --from=ffmpeg-downloader /usr/local/bin/ffprobe /usr/local/bin/ffprobe

# runtime
ENV USERNAME=root
RUN --mount=type=cache,target=/var/cache/apt,sharing=private,id=ubuntu2204-aptcache \
--mount=type=cache,target=/var/lib/apt,sharing=private,id=ubuntu2204-aptlib \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-apt-cache \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=$CACHEIDPREFIX-apt-lib \
set -eux; \
apt-get update; \
apt-get --no-install-recommends -y install \
wget ca-certificates python2 supervisor xclip xdotool \
pulseaudio dbus-x11 xserver-xorg-video-dummy \
wget ca-certificates python2 supervisor xclip xdotool unclutter \
pulseaudio dbus-x11 xserver-xorg-video-dummy rtkit upower \
libcairo2 libxcb1 libxrandr2 libxv1 libopus0 libvpx7 \
x11-xserver-utils \
gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
Expand All @@ -187,14 +249,15 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=private,id=ubuntu2204-aptca
/home/$USERNAME/.local/share/xorg; \
chmod 1777 /var/log/neko; \
chown $USERNAME /var/log/neko/ /tmp/runtime-$USERNAME; \
chown -R $USERNAME:$USERNAME /home/$USERNAME;
chown -R $USERNAME:$USERNAME /home/$USERNAME; \
chmod 777 /etc/pulse;

# install chromium and sqlite3 for debugging the cookies file
RUN --mount=type=cache,target=/var/cache/apt,sharing=private,id=ubuntu2204-aptcache \
--mount=type=cache,target=/var/lib/apt,sharing=private,id=ubuntu2204-aptlib \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-apt-cache \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=$CACHEIDPREFIX-apt-lib \
add-apt-repository -y ppa:xtradeb/apps;
RUN --mount=type=cache,target=/var/cache/apt,sharing=private,id=ubuntu2204-aptcache \
--mount=type=cache,target=/var/lib/apt,sharing=private,id=ubuntu2204-aptlib \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-apt-cache \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=$CACHEIDPREFIX-apt-lib \
apt update -y && \
apt -y install chromium && \
apt --no-install-recommends -y install sqlite3;
Expand All @@ -214,8 +277,8 @@ RUN set -eux; \
ln -sf /usr/local/lib/node_modules/corepack/dist/corepack.js /usr/local/bin/corepack; \
fi

# Install TypeScript and Playwright globally
RUN --mount=type=cache,target=/root/.npm npm install -g typescript playwright-core tsx
# Install TypeScript, Playwright, Patchright globally
RUN --mount=type=cache,target=/root/.npm,id=$CACHEIDPREFIX-npm npm install -g typescript playwright-core patchright tsx

# setup desktop env & app
ENV DISPLAY_NUM=1
Expand All @@ -225,6 +288,10 @@ ENV WITHDOCKER=true

COPY images/chromium-headful/xorg.conf /etc/neko/xorg.conf
COPY images/chromium-headful/neko.yaml /etc/neko/neko.yaml
COPY images/chromium-headful/default.pa /etc/pulse/default.pa
COPY images/chromium-headful/daemon.conf /etc/pulse/daemon.conf
COPY images/chromium-headful/dbus-pulseaudio.conf /etc/dbus-1/system.d/pulseaudio.conf
COPY images/chromium-headful/dbus-mpris.conf /etc/dbus-1/system.d/mpris.conf
COPY --from=neko /usr/bin/neko /usr/bin/neko
COPY --from=client /src/dist/ /var/www
COPY --from=xorg-deps /usr/local/lib/xorg/modules/drivers/dummy_drv.so /usr/lib/xorg/modules/drivers/dummy_drv.so
Expand All @@ -244,6 +311,11 @@ COPY --from=server-builder /out/chromium-launcher /usr/local/bin/chromium-launch
# Copy the Playwright executor runtime
COPY server/runtime/playwright-executor.ts /usr/local/lib/playwright-executor.ts

RUN useradd -m -s /bin/bash kernel
RUN useradd -m -s /bin/bash kernel && \
usermod -aG audio,video,pulse,pulse-access kernel

# Environment variables for audio
ENV XDG_RUNTIME_DIR=/tmp/runtime-kernel
ENV PULSE_SERVER=unix:/tmp/runtime-kernel/pulse/native

ENTRYPOINT [ "/wrapper.sh" ]
4 changes: 3 additions & 1 deletion images/chromium-headful/build-unikernel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Move to the script's directory so relative paths work regardless of the caller CWD
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
cd "$SCRIPT_DIR"
source "$SCRIPT_DIR/../../shared/ensure-common-build-run-vars.sh" chromium-headful
source "$SCRIPT_DIR/../../shared/ensure-common-build-run-vars.sh" chromium-headful require-ukc-vars
source "$SCRIPT_DIR/../../shared/erofs-utils.sh"

# Ensure the mkfs.erofs tool is available
Expand All @@ -25,6 +25,8 @@ docker cp cnt-"$app_name":/ ./.rootfs
rm -f initrd || true
sudo mkfs.erofs --all-root -d2 -E noinline_data -b 4096 initrd ./.rootfs

echo "Image index/name: $UKC_INDEX/$IMAGE"

# Package the unikernel (and the new initrd) to KraftCloud
kraft pkg \
--name $UKC_INDEX/$IMAGE \
Expand Down
9 changes: 7 additions & 2 deletions images/chromium-headful/client/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,20 @@ FROM $BASE_IMAGE AS client

WORKDIR /src

# Allow cross-compilation when building with BuildKit platforms
ARG TARGETARCH
ARG TARGETOS
ARG CACHEIDPREFIX=${TARGETOS:-linux}-${TARGETARCH:-amd64}-node18bullseye

#
# install dependencies
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm npm install
RUN --mount=type=cache,target=/root/.npm,id=$CACHEIDPREFIX-npm npm install

#
# build client
COPY . .
RUN --mount=type=cache,target=/root/.npm npm run build
RUN --mount=type=cache,target=/root/.npm,id=$CACHEIDPREFIX-npm npm run build

#
# artifacts from this stage
Expand Down
2 changes: 1 addition & 1 deletion images/chromium-headful/client/public/browserconfig.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#19bd9c</TileColor>
<TileColor>#7B42F6</TileColor>
</tile>
</msapplication>
</browserconfig>
6 changes: 3 additions & 3 deletions images/chromium-headful/client/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png">
<link rel="manifest" href="site.webmanifest">
<link rel="mask-icon" href="safari-pinned-tab.svg" color="#19bd9c">
<meta name="msapplication-TileColor" content="#19bd9c">
<meta name="theme-color" content="#19bd9c">
<link rel="mask-icon" href="safari-pinned-tab.svg" color="#7B42F6">
<meta name="msapplication-TileColor" content="#7B42F6">
<meta name="theme-color" content="#7B42F6">
<style> /* weird iOS bug, if this is not set right here, video just does not start */ .video-container { width: 100%; height: 100%; } </style>
</head>
<body>
Expand Down
4 changes: 4 additions & 0 deletions images/chromium-headful/client/public/kernel.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions images/chromium-headful/client/public/site.webmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"type": "image/png"
}
],
"theme_color": "#19bd9c",
"background_color": "#19bd9c",
"theme_color": "#7B42F6",
"background_color": "#7B42F6",
"display": "standalone"
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ $background-modifier-accent: hsla(0, 0%, 100%, 0.06);
$elevation-low: 0 1px 0 rgba(4, 4, 5, 0.2), 0 1.5px 0 rgba(6, 6, 7, 0.05), 0 2px 0 rgba(4, 4, 5, 0.05);
$elevation-high: 0 8px 16px rgba(0, 0, 0, 0.24);

$style-primary: #19bd9c;
$style-primary: #7B42F6;
$style-error: #d32f2f;

$menu-height: 40px;
Expand Down
Loading