Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e41f909
api changes for file i/o
rgarcia Aug 3, 2025
a9062e4
implementation
rgarcia Aug 3, 2025
33de44e
file directory ops
rgarcia Aug 3, 2025
3e191ac
Fix fs watch goroutine leaks and improve error handling
cursoragent Aug 3, 2025
8c3bed1
Improve fs watch goroutine lifecycle and resource management
cursoragent Aug 3, 2025
0953976
Support custom file permissions when writing files via API
cursoragent Aug 3, 2025
e895649
Fix file listing to handle stat errors and correctly set file metadata
cursoragent Aug 3, 2025
f7313f6
Fix race condition and prevent blocking in filesystem watch events
cursoragent Aug 3, 2025
f02ae76
vet
rgarcia Aug 4, 2025
5550c86
fix sse
rgarcia Aug 5, 2025
808f925
Fix user and group lookup error handling in SetFilePermissions
cursoragent Aug 5, 2025
5821cdd
Merge branch 'main' into raf/kernel-19-support-file-io
rgarcia Aug 5, 2025
70ad2e8
Merge branch 'main' into raf/kernel-19-support-file-io
rgarcia Aug 6, 2025
53b054a
add server to headless image (so we have file i/o there too)
rgarcia Aug 6, 2025
494147f
test script
rgarcia Aug 6, 2025
549e537
post -> put
rgarcia Aug 6, 2025
cd08bba
Improve file permission handling with direct UID/GID and fallback lookup
cursoragent Aug 6, 2025
63ccaa3
Handle write errors in SSE event streaming to prevent potential hanging
cursoragent Aug 6, 2025
59e236d
Improve file system watcher with safe close and recursive monitoring
cursoragent Aug 6, 2025
e6af0d9
good bot
rgarcia Aug 6, 2025
9da2bb1
pr comments
rgarcia Aug 6, 2025
bc28626
more 400s -> 500s
rgarcia Aug 6, 2025
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
3 changes: 1 addition & 2 deletions images/chromium-headful/build-docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ set -e -o pipefail
# Move to the script's directory so relative paths work regardless of the caller CWD
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
cd "$SCRIPT_DIR"

IMAGE="${IMAGE:-onkernel/kernel-cu-test:latest}"
source ../../shared/ensure-common-build-run-vars.sh chromium-headful

source ../../shared/start-buildkit.sh

Expand Down
7 changes: 5 additions & 2 deletions images/chromium-headful/build-unikernel.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#!/usr/bin/env bash

source common.sh
source ../../shared/erofs-utils.sh
# 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/erofs-utils.sh"

# Ensure the mkfs.erofs tool is available
if ! check_mkfs_erofs; then
Expand Down
17 changes: 0 additions & 17 deletions images/chromium-headful/common.sh

This file was deleted.

6 changes: 2 additions & 4 deletions images/chromium-headful/run-docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ set -ex -o pipefail
# Move to the script's directory so relative paths work regardless of the caller CWD
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
cd "$SCRIPT_DIR"

IMAGE="${IMAGE:-onkernel/kernel-cu-test:latest}"
NAME="${NAME:-kernel-cu-test}"
source ../../shared/ensure-common-build-run-vars.sh chromium-headful

# Directory on host where recordings will be saved
HOST_RECORDINGS_DIR="$SCRIPT_DIR/recordings"
Expand Down Expand Up @@ -45,7 +43,7 @@ RUN_ARGS=(
)

if [[ "${WITH_KERNEL_IMAGES_API:-}" == "true" ]]; then
RUN_ARGS+=( -p 10001:10001 )
RUN_ARGS+=( -p 444:10001 )
RUN_ARGS+=( -e WITH_KERNEL_IMAGES_API=true )
fi

Expand Down
14 changes: 9 additions & 5 deletions images/chromium-headful/run-unikernel.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
#!/usr/bin/env bash
set -euo pipefail

source common.sh
name=chromium-headful-test
kraft cloud inst rm $name || true
# 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 ../../shared/ensure-common-build-run-vars.sh chromium-headful

kraft cloud inst rm $NAME || true

# Name for the Kraft Cloud volume that will carry Chromium flags
volume_name="${name}-flags"
volume_name="${NAME}-flags"

# ------------------------------------------------------------------------------
# Prepare Kraft Cloud volume containing Chromium flags
Expand Down Expand Up @@ -45,7 +49,7 @@ deploy_args=(
-e HOME=/
-e RUN_AS_ROOT="$RUN_AS_ROOT" \
-v "$volume_name":/chromium
-n "$name"
-n "$NAME"
)

if [[ "${WITH_KERNEL_IMAGES_API:-}" == "true" ]]; then
Expand Down
1 change: 1 addition & 0 deletions images/chromium-headless/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
image/.rootfs
image/bin
2 changes: 0 additions & 2 deletions images/chromium-headless/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
1. Build and run the image, tagging it with a name you'd like to use:

```bash
export IMAGE=onkernel/chromium-headless
./build-docker.sh
./run-docker.sh
```
Expand All @@ -25,7 +24,6 @@ uv run python main.py http://localhost:9222
1. Build and run the image, tagging it with a name you'd like to use:

```bash
export IMAGE=onkernel/chromium-headless
export UKC_TOKEN=
export UKC_METRO=
# latest UKC also allows pushing to metro-specific indexes
Expand Down
15 changes: 13 additions & 2 deletions images/chromium-headless/build-docker.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
#!/usr/bin/env bash
set -e -o pipefail

source common.sh
(cd image && docker build -t $IMAGE .)
# 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 ../../shared/ensure-common-build-run-vars.sh chromium-headless

source ../../shared/start-buildkit.sh

# Build the kernel-images API binary and place it into the Docker build context
source ../../shared/build-server.sh "$SCRIPT_DIR/image/bin"

# Build (and optionally push) the Docker image
(cd image && docker build -t "$IMAGE" .)
9 changes: 7 additions & 2 deletions images/chromium-headless/build-unikernel.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/usr/bin/env bash

source common.sh
# 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 ../../shared/ensure-common-build-run-vars.sh chromium-headless
source ../../shared/erofs-utils.sh

# Ensure the mkfs.erofs tool is present
Expand All @@ -14,8 +17,10 @@ set -euo pipefail
cd image/

# Build the root file system
source ../../shared/start-buildkit.sh
source ../../../shared/start-buildkit.sh
rm -rf ./.rootfs || true
# Build the API binary
source ../../../shared/build-server.sh "$(pwd)/bin"
app_name=chromium-headless-build
docker build --platform linux/amd64 -t "$IMAGE" .
docker rm cnt-"$app_name" || true
Expand Down
14 changes: 0 additions & 14 deletions images/chromium-headless/common.sh

This file was deleted.

14 changes: 14 additions & 0 deletions images/chromium-headless/image/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ RUN set -xe; \
RUN add-apt-repository -y ppa:xtradeb/apps
RUN apt update -y && apt install -y chromium ncat

# Install FFmpeg (latest static build) for the recording server
RUN set -eux; \
URL="https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz"; \
echo "Downloading FFmpeg static build from $URL"; \
curl -fsSL "$URL" -o /tmp/ffmpeg.tar.xz; \
tar -xJf /tmp/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*

# Remove upower to prevent spurious D-Bus activations and logs
RUN apt-get -yqq purge upower || true && rm -rf /var/lib/apt/lists/*

Expand All @@ -44,3 +54,7 @@ COPY ./xvfb_startup.sh /usr/bin/xvfb_startup.sh

# Wrapper script set environment
COPY ./wrapper.sh /usr/bin/wrapper.sh

# Copy the kernel-images API binary built during the build process
COPY bin/kernel-images-api /usr/local/bin/kernel-images-api
ENV WITH_KERNEL_IMAGES_API=false
27 changes: 27 additions & 0 deletions images/chromium-headless/image/wrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,17 @@ cleanup () {
echo "Cleaning up..."
kill -TERM $pid 2>/dev/null || true
kill -TERM $pid2 2>/dev/null || true
if [[ -n "${pid3:-}" ]]; then
kill -TERM $pid3 2>/dev/null || true
fi
if [ -n "${dbus_pid:-}" ]; then
kill -TERM $dbus_pid 2>/dev/null || true
fi
}
trap cleanup TERM INT
pid=
pid2=
pid3=
INTERNAL_PORT=9223
CHROME_PORT=9222 # External port mapped to host
echo "Starting Chromium on internal port $INTERNAL_PORT"
Expand All @@ -138,11 +142,34 @@ ncat \
-l "$CHROME_PORT" \
--keep-open & pid2=$!

# Optionally start the kernel-images API server file i/o
if [[ "${WITH_KERNEL_IMAGES_API:-}" == "true" ]]; then
echo "✨ Starting kernel-images API."
API_PORT="${KERNEL_IMAGES_API_PORT:-10001}"
API_FRAME_RATE="${KERNEL_IMAGES_API_FRAME_RATE:-10}"
API_DISPLAY_NUM="${KERNEL_IMAGES_API_DISPLAY_NUM:-${DISPLAY_NUM:-1}}"
API_MAX_SIZE_MB="${KERNEL_IMAGES_API_MAX_SIZE_MB:-500}"
API_OUTPUT_DIR="${KERNEL_IMAGES_API_OUTPUT_DIR:-/recordings}"

mkdir -p "$API_OUTPUT_DIR"

PORT="$API_PORT" \
FRAME_RATE="$API_FRAME_RATE" \
DISPLAY_NUM="$API_DISPLAY_NUM" \
MAX_SIZE_MB="$API_MAX_SIZE_MB" \
OUTPUT_DIR="$API_OUTPUT_DIR" \
/usr/local/bin/kernel-images-api & pid3=$!
fi

# Wait for Chromium to exit; propagate its exit code
wait "$pid"
exit_code=$?
echo "Chromium exited with code $exit_code"
# Ensure ncat proxy is terminated
kill -TERM "$pid2" 2>/dev/null || true
# Ensure kernel-images API server is terminated
if [[ -n "${pid3:-}" ]]; then
kill -TERM "$pid3" 2>/dev/null || true
fi

exit "$exit_code"
30 changes: 25 additions & 5 deletions images/chromium-headless/run-docker.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
#!/usr/bin/env bash
set -ex -o pipefail

source common.sh
# 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 ../../shared/ensure-common-build-run-vars.sh chromium-headless

docker run -it --rm \
-p 9222:9222 \
-e WITH_DOCKER=true \
$IMAGE /usr/bin/wrapper.sh
# Directory on host where recordings will be saved when the API is enabled
HOST_RECORDINGS_DIR="$SCRIPT_DIR/recordings"
mkdir -p "$HOST_RECORDINGS_DIR"

RUN_ARGS=(
--name "$NAME"
--privileged
--tmpfs /dev/shm:size=2g
-p 9222:9222
-e WITH_DOCKER=true
)

if [[ "${WITH_KERNEL_IMAGES_API:-}" == "true" ]]; then
RUN_ARGS+=( -p 444:10001 )
RUN_ARGS+=( -e WITH_KERNEL_IMAGES_API=true )
RUN_ARGS+=( -v "$HOST_RECORDINGS_DIR:/recordings" )
fi

docker rm -f "$NAME" 2>/dev/null || true
docker run -it --rm "${RUN_ARGS[@]}" "$IMAGE" /usr/bin/wrapper.sh
30 changes: 20 additions & 10 deletions images/chromium-headless/run-unikernel.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail

source common.sh
name="chromium-headless-test"
# 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 ../../shared/ensure-common-build-run-vars.sh chromium-headless

kraft cloud inst rm "$name" || true
kraft cloud inst rm "$NAME" || true

kraft cloud inst create \
--start \
-M 1G \
-p 9222:9222/tls \
--vcpus 1 \
-n "$name" \
$IMAGE
deploy_args=(
--start
-M 1G
-p 9222:9222/tls
--vcpus 1
-n "$NAME"
)

if [[ "${WITH_KERNEL_IMAGES_API:-}" == "true" ]]; then
deploy_args+=( -p 444:10001/tls )
deploy_args+=( -e WITH_KERNEL_IMAGES_API=true )
fi

kraft cloud inst create "${deploy_args[@]}" "$IMAGE"
3 changes: 3 additions & 0 deletions server/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ oapi-generate: $(OAPI_CODEGEN)
pnpm i -g @apiture/openapi-down-convert
openapi-down-convert --input openapi.yaml --output openapi-3.0.yaml
$(OAPI_CODEGEN) -config ./oapi-codegen.yaml ./openapi-3.0.yaml
@echo "Fixing oapi-codegen issue https://github.com/oapi-codegen/oapi-codegen/issues/1764..."
go run ./scripts/oapi/patch_sse_methods.go -file ./lib/oapi/oapi.go -expected-replacements 1
go fmt ./lib/oapi/oapi.go
go mod tidy

build: | $(BIN_DIR)
Expand Down
5 changes: 5 additions & 0 deletions server/cmd/api/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"os"
"sync"
"time"

"github.com/onkernel/kernel-images/server/lib/logger"
Expand All @@ -18,6 +19,9 @@ type ApiService struct {

recordManager recorder.RecordManager
factory recorder.FFmpegRecorderFactory
// Filesystem watch management
watchMu sync.RWMutex
watches map[string]*fsWatch
}

var _ oapi.StrictServerInterface = (*ApiService)(nil)
Expand All @@ -34,6 +38,7 @@ func New(recordManager recorder.RecordManager, factory recorder.FFmpegRecorderFa
recordManager: recordManager,
factory: factory,
defaultRecorderID: "default",
watches: make(map[string]*fsWatch),
}, nil
}

Expand Down
Loading
Loading