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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Public container images for cloud work, built multi-arch and rootless with secur

| Image | Description |
|---|---|
| `ghcr.io/cloudsnacks/actions-runner` | Rootless GitHub Actions runner for [Actions Runner Controller](https://github.com/actions/actions-runner-controller), with docker CLI and buildx |
| `ghcr.io/cloudsnacks/actions-runner` | Rootless GitHub Actions runner for [Actions Runner Controller](https://github.com/actions/actions-runner-controller), with docker CLI, buildx and a mise-managed CLI toolchain ([`mise.toml`](images/actions-runner/mise.toml)) |
| `ghcr.io/cloudsnacks/claude-code` | Headless Claude Code agent with git-repo and agent-profile bootstrap |
| `ghcr.io/cloudsnacks/dev-desktop` | Arch Linux dev workstation with Hyprland streamed over [Sunshine](https://github.com/LizardByte/Sunshine)/Moonlight, cloud tooling, and AI coding agents (`linux/amd64` only, needs `/dev/dri`) |
| `ghcr.io/cloudsnacks/infisical-mcp` | Infisical MCP server (secrets management over MCP) |
Expand Down
29 changes: 28 additions & 1 deletion images/actions-runner/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,33 @@ RUN DOCKER_ARCH="$(case "${TARGETARCH}" in amd64) echo x86_64 ;; arm64) echo aar
&& docker --version \
&& docker buildx version

# Workflow tooling that GitHub's own hosted images ship and Ubuntu does not
# usefully package — there is no gh in the archive at all, and its `yq` is the
# unrelated Python jq-wrapper with different syntax. Without them here every
# workflow that opens a PR or patches a manifest curls its own copy into
# RUNNER_TEMP, which is the per-repo drift this image exists to absorb.
#
# The list lives in mise.toml, one line per tool, so growing it costs no
# Dockerfile. Renovate's native mise manager reads that file, which is why
# those entries carry no `# renovate:` annotation. mise itself is fetched as a
# pinned release binary rather than through the unpinned mise.run installer.
# renovate: datasource=github-releases depName=jdx/mise
ARG MISE_VERSION=2026.7.17
# Data dir stays root-owned and read-only to the runner user; the cache is the
# only path mise writes to at runtime, so it points somewhere world-writable.
ENV MISE_DATA_DIR=/opt/mise \
MISE_CONFIG_DIR=/opt/mise \
MISE_CACHE_DIR=/tmp/mise-cache \
PATH=/opt/mise/shims:$PATH
COPY mise.toml /opt/mise/config.toml
RUN MISE_ARCH="$(case "${TARGETARCH}" in amd64) echo x64 ;; *) echo "${TARGETARCH}" ;; esac)" \
&& curl -fsSL -o /tmp/mise \
"https://github.com/jdx/mise/releases/download/v${MISE_VERSION}/mise-v${MISE_VERSION}-linux-${MISE_ARCH}" \
&& install -o root -g root -m 0755 /tmp/mise /usr/bin/mise \
&& rm -f /tmp/mise \
&& mise install --yes \
&& mise ls --installed

USER runner

LABEL org.opencontainers.image.description="GitHub Actions runner for Actions Runner Controller, with docker CLI and buildx"
LABEL org.opencontainers.image.description="GitHub Actions runner for Actions Runner Controller, with docker CLI, buildx and a mise-managed CLI toolchain"
9 changes: 6 additions & 3 deletions images/actions-runner/metadata.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
---
name: actions-runner
description: GitHub Actions runner for Actions Runner Controller, with docker CLI and buildx
description: GitHub Actions runner for Actions Runner Controller, with docker CLI, buildx and a mise-managed CLI toolchain
# <upstream runner version>-<revision>. Bump the revision whenever this image's
# contents change without RUNNER_VERSION moving, so scale sets pulling with the
# default IfNotPresent policy get a tag they have not already cached. Renovate
# tracks upstream on RUNNER_VERSION in the Dockerfile — deliberately not
# annotated here, since a -N suffix is a semver pre-release and would be
# "upgraded" straight back to the bare release.
version: 2.336.0-2
version: 2.336.0-3
platforms:
- linux/amd64
- linux/arm64
test: /home/runner/bin/Runner.Listener --version && tmux -V && docker --version && docker buildx version && dpkg -s libatomic1 libnss3 libgbm1 fonts-noto-color-emoji >/dev/null && test "$LANG" = C.UTF-8 && id -nG | grep -qw docker
# The mise loop is deliberately generic over mise.toml: every tool listed there
# must resolve through the shims on PATH and run as the runner user, so adding
# a tool needs no edit here.
test: /home/runner/bin/Runner.Listener --version && tmux -V && docker --version && docker buildx version && jq --version && test "$(mise ls --installed --json | jq 'keys|length')" -eq "$(yq -p toml -oy '.tools|length' /opt/mise/config.toml)" && for t in $(mise ls --installed --json | jq -r 'keys[]'); do command -v "$t" | grep -q '^/opt/mise/shims/' && "$t" --version >/dev/null || exit 1; done && dpkg -s libatomic1 libnss3 libgbm1 fonts-noto-color-emoji >/dev/null && test "$LANG" = C.UTF-8 && id -nG | grep -qw docker
12 changes: 12 additions & 0 deletions images/actions-runner/mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Long-tail CLI tooling for workflows: one line per tool. Renovate's native
# mise manager matches this filename by default, so entries here need no
# `# renovate:` annotation and no addition to the repo's custom manager.
#
# Only static, version-insensitive binaries belong here. Anything a workflow
# pins against (language runtimes, kubectl, helm) stays out and is left to the
# setup-* actions, which cache into RUNNER_TOOL_CACHE.
[tools]
gh = "2.96.0"
hadolint = "2.14.0"
shellcheck = "0.11.0"
yq = "4.53.3"