Source-owned Forgejo Actions job image
  • Python 92%
  • Shell 4.5%
  • Dockerfile 3.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-13 14:22:48 +00:00
.dockerignore Add Dockerfile with Node.js and Docker CLI for Gitea Actions 2025-12-12 15:11:06 +01:00
Dockerfile fix: preserve sealed scanner transitions 2026-08-30 14:43:35 +02:00
Dockerfile.system-hz-hermetic fix: preserve sealed scanner transitions 2026-08-30 14:43:35 +02:00
Dockerfile.system-hz-r2-provider ci: preload locked Cloudflare provider in runner image 2026-09-10 14:46:22 +02:00
Dockerfile.system-hz-rust-osv ci: seal Rust advisory snapshot for workstation helper 2026-09-18 04:23:02 +02:00
Dockerfile.system-hz-rust193 ci: add sealed Rust 1.93 runner leaf source 2026-10-01 20:25:25 +02:00
Dockerfile.system-hz-rust199 ci: keep Rust 1.93 beside 1.99 behind a sealed toolchain selector 2026-10-12 15:15:55 +02:00
LICENSE Add Dockerfile with Node.js and Docker CLI for Gitea Actions 2025-12-12 15:11:06 +01:00
osv-rust-snapshot.json ci: seal Rust advisory snapshot for workstation helper 2026-09-18 04:23:02 +02:00
README.md test(runner): verify installed Rust and retained offline consumers 2026-10-04 00:36:32 +02:00
README.system-hz-rust199.md docs: state the measured size of the two-toolchain image 2026-10-12 15:24:58 +02:00
rust193-inputs.json ci: add sealed Rust 1.93 runner leaf source 2026-10-01 20:25:25 +02:00
rust199-inputs.json ci: add sealed Rust 1.99 runner leaf 2026-10-12 13:49:58 +02:00
supplychain-hermetic fix: preserve sealed scanner transitions 2026-08-30 14:43:35 +02:00
system-hz-rust-select.sh ci: keep Rust 1.93 beside 1.99 behind a sealed toolchain selector 2026-10-12 15:15:55 +02:00
test-installed-system-hz-rust193-host.py test(runner): deliver accepted installed-image host controller 2026-10-06 00:06:00 +02:00
test-installed-system-hz-rust193.py test(runner): verify installed Rust and retained offline consumers 2026-10-04 00:36:32 +02:00
test-installed-system-hz-rust199.py ci: keep Rust 1.93 beside 1.99 behind a sealed toolchain selector 2026-10-12 15:15:55 +02:00
test-rust-osv-offline.py ci: seal Rust advisory snapshot for workstation helper 2026-09-18 04:23:02 +02:00
test-system-hz-hermetic.sh fix: preserve sealed scanner transitions 2026-08-30 14:43:35 +02:00
test-system-hz-r2-provider.sh ci: preload locked Cloudflare provider in runner image 2026-09-10 14:46:22 +02:00
test-system-hz-rust-osv.py ci: seal Rust advisory snapshot for workstation helper 2026-09-18 04:23:02 +02:00
test-system-hz-rust193.py ci: add sealed Rust 1.93 runner leaf source 2026-10-01 20:25:25 +02:00
test-system-hz-rust199.py ci: keep Rust 1.93 beside 1.99 behind a sealed toolchain selector 2026-10-12 15:15:55 +02:00
verify-installed-system-hz-rust193-host.py test(runner): deliver accepted installed-image host controller 2026-10-06 00:06:00 +02:00
verify-installed-system-hz-rust193.py test(runner): verify installed Rust and retained offline consumers 2026-10-04 00:36:32 +02:00
verify-installed-system-hz-rust199.py ci: keep Rust 1.93 beside 1.99 behind a sealed toolchain selector 2026-10-12 15:15:55 +02:00

act-node-docker

Forgejo Actions compatible runner image with Node.js, Docker CLI, Kubernetes tools, and infrastructure CLIs for use with Forgejo Actions (act-runner).

The canonical source is https://git.noel.sh/noel/act-node-docker.

Features

  • Based on catthehacker/ubuntu:act-latest (GitHub Actions compatible)
  • Node.js pre-installed (for GitHub Actions that require it)
  • Docker CLI with Buildx and Compose plugins
  • Kubernetes tooling with kubectl and kustomize
  • Infrastructure tooling with atmos, tofu, infisical, jq, and ripgrep
  • Hermetic source security tooling with supplychain, OSV Scanner, Gitleaks, zizmor, and a digest-pinned PyPI vulnerability snapshot
  • Codewire CI native tooling with Protocol Buffers compiler and well-known type headers, PostgreSQL client, pkg-config, GTK 3, WebKitGTK 4.1, and XKB X11 development metadata
  • A system-cluster hermetic derivative with checksum-pinned Helm and ShellCheck
  • Checksum-pinned Kind for disposable exact-image integration gates
  • Checksum-pinned sccache for host Rust compilation against disposable local or explicitly configured remote cache backends
  • The checksum-pinned Cilium 1.19.5 chart for networkless bootstrap rendering
  • Checksum-pinned PyYAML for offline manifest contract validation
  • Checksum-pinned Ubuntu runtime packages required by pinned Chromium browser verification, installed during the networkless build phase
  • A sealed-input build contract: an external tokenless fetch phase verifies the exact SHA-256 inputs, then BuildKit mounts them read-only and runs every Dockerfile step with networking disabled
  • Compatible with act-runner's Docker-in-Docker setup

Usage

System CI

docker pull nexus-system-hz-eu-1.tail.noel.sh/oci-approved/act-node-docker@sha256:c9f5387dc5b0ec128af3b16002ebd30d1323bc51bc511404c4c8b22a6288952c

The former Docker Hub image is retained only as the immutable bootstrap base recorded in infrastructure provenance. New system CI artifacts are published to Nexus and consumed by digest through oci-approved.

Forgejo Runner Configuration

Configure your act-runner labels to use this image:

runner_labels:
  - "ubuntu-latest:docker://nexus-system-hz-eu-1.tail.noel.sh/oci-approved/act-node-docker@sha256:c9f5387dc5b0ec128af3b16002ebd30d1323bc51bc511404c4c8b22a6288952c"
  - "ubuntu-22.04:docker://nexus-system-hz-eu-1.tail.noel.sh/oci-approved/act-node-docker@sha256:c9f5387dc5b0ec128af3b16002ebd30d1323bc51bc511404c4c8b22a6288952c"
  - "ubuntu-24.04:docker://nexus-system-hz-eu-1.tail.noel.sh/oci-approved/act-node-docker@sha256:c9f5387dc5b0ec128af3b16002ebd30d1323bc51bc511404c4c8b22a6288952c"

Docker Socket Access

For jobs that need to build Docker images, mount the Docker socket from the DinD sidecar. In your act-runner Helm values:

container:
  options: "-v /var/run/docker.sock:/var/run/docker.sock"

Building Locally

docker build -t act-node-docker:latest .

Offline Cloudflare provider layer

Dockerfile.system-hz-r2-provider adds the Cloudflare 5.24.0 Linux amd64 provider archive to the existing system CI image sha256:2cbc40c091b1e5e3b48214e208d9fdff30a4f0afda5e661b5c6cde977b7f3bca. The parent uses the publisher's oci-promoted/act-node-docker reference; consumers retain their separate oci-approved pull path. The derivative inherits that image's toolchain and keeps the existing 16-input Dockerfile.system-hz-hermetic recipe unchanged.

The sealed _build_inputs directory contains this single public input:

Archive SHA-256
terraform-provider-cloudflare_5.24.0_linux_amd64.zip 2390fc5df95addfd47d3f638964a1f9f6192a8c84ad3b1eab554ef88e0ac4091

The archive comes from the upstream Cloudflare release. Its checksum matches the Codewire R2 lifecycle component's lockfile. The networkless build checks the input and installed bytes, requires a full lowercase source commit through SOURCE_REVISION, and installs the archive with root ownership and mode 0444 at:

/opt/infra-artifacts/tofu-providers/registry.opentofu.org/cloudflare/cloudflare/terraform-provider-cloudflare_5.24.0_linux_amd64.zip

The consumer selects this packed filesystem mirror through a private OpenTofu CLI configuration and uses its readonly dependency lockfile. It does not need provider credentials for mocked plan tests. A filesystem mirror and TF_PLUGIN_CACHE_DIR must be separate directories.

Run ./test-system-hz-r2-provider.sh for source-boundary checks and synthetic installation tests. These do not build an image or execute a provider. The existing separated prefetch/publisher Flux transaction documented in infra's docs/runbooks/nexus-oci-bootstrap.md owns publication. It seals the reviewed source and archive before the credential-bearing networkless build. Published image acceptance must execute the real offline mocked plans and existing toolchain checks before infra adopts its digest. The source, revision and approved parent are recorded in OCI labels.

Offline Rust advisory database layer

Dockerfile.system-hz-rust-osv adds only the crates.io OSV snapshot described in osv-rust-snapshot.json to the accepted R2-provider image sha256:36ed662b60eac8f9ee826a88288ec88feb3cd07d4a057352ffcac77a25a38ce0. The existing binaries, Cloudflare provider and PyPI snapshot are inherited unchanged. This supplies offline Rust dependency coverage; it is not a scanner-policy exception or a claim that the inherited PyPI snapshot was refreshed.

Prefetch the generation-bound public URL into _build_inputs under the exact manifest filename. Verify its committed checksum before sealing and again in the publisher. The networkless recipe installs root-owned, read-only database bytes at /opt/supplychain/cache/osv-scanner/crates.io/all.zip. OSV exports are mutable; the recorded generation, timestamp and digest identify one snapshot, not a perpetual latest version. An unavailable generation or checksum mismatch must fail closed and requires a reviewed new pin, never an automatic re-pin.

test-system-hz-rust-osv.py checks the source boundary and exercises installation with synthetic bytes. test-rust-osv-offline.py ARCHIVE exercises the actual scanner against the pinned public snapshot using generated vulnerable/fixed Cargo lockfiles and missing/corrupt database cases; it uses no credentials or network-capable scan flags. Neither test is proof of a published image.

Publication follows Infra's existing separated prefetch/publisher Flux transaction. Before adopting the new digest, verify its registry manifest and labels through the pull-only identity, then run the real offline scanner and still-consumed supplychain revisions as UID1000 in a deny-all-egress pod with no credential mounts. Preserve package discovery, vulnerability detection and fail-closed missing-data behavior. Then rerun the affected exact-head source approval; finding a genuine dependency advisory must remain a failure.

Sealed Rust 1.93 leaf

Dockerfile.system-hz-rust193 installs the five checksum-pinned Rust 1.93.0 inputs from rust193-inputs.json over its immutable parent. GNU, static musl, ARM GNU and both Darwin standard libraries share the sealed /opt/infra-rust/1.93.0 prefix. Its fixed rustup interface reports those targets and refuses toolchain mutation with exit 64. The inherited provider, advisory databases and tools remain part of acceptance.

test-system-hz-rust193.py checks the recipe and synthetic installation. test-installed-system-hz-rust193.py checks concrete refusals, including changed fixture identities, absent scanner discovery or mock-plan results, bounded child output and cleanup of a detached child after a deadline. Neither test qualifies an installed image.

The installed verifier runs inside an isolated Linux amd64 container:

python3 -I -B /verification/verify-installed-system-hz-rust193.py /verification/consumers

Before running it, the host must bind the exact image ID, parent layers and source labels, seal the verifier and its closed public consumer inventory, and inspect the complete container configuration. Run as UID and GID 1000 with a read-only root, no network, no credentials or sockets, and bounded resources and lifetime. The only writable mounts are owned disposable work and temporary directories; kill and reap the owned process family before cleanup. Guest checks supplement this host inspection.

Acceptance executes the retained Codewire runner assertion, genuine GNU and static musl compiler probes, fmt and Clippy, all five installed standard libraries, the fixed toolchain mutation refusal, four offline scanner cases and both retained supplychain revisions. It also executes Infra's exact public R2 lifecycle test entrypoint and requires all 11 real OpenTofu mock plans and their successful summary. The provider and advisory archive hashes are checked before and after the run. This verifier does not replace or relabel an older Kubernetes Job result.

Private registry pull access, publication and infrastructure adoption are separate actions. A passing source test or local image verification does not publish an image or change runner configuration.

What's Included

Tool Version Notes
Node.js Latest from base image For GitHub Actions
npm Latest from base image Package manager
Docker CLI Latest stable Client only, connects to external daemon
Docker Buildx Latest stable Multi-platform builds
Docker Compose Latest stable v2 plugin
kubectl 1.36.1 Kubernetes client
kustomize 5.8.1 Kubernetes manifest customization
atmos noeljackson/atmos d64609ef8 Stack and workflow orchestration with Hetzner auth support
supplychain noeljackson/supplychain ee0abebcd Strict source security gate with fail-closed OSV offline mode
OSV Scanner 2.4.0 Uses the image's digest-pinned PyPI database in hermetic workflows
Gitleaks 8.30.1 Redacted repository secret scanning
zizmor 1.25.2 Offline GitHub/Gitea workflow audit
OpenTofu 1.11.6 Terraform-compatible IaC
Infisical CLI 0.43.58 Secret injection
jq OS package JSON processing
ripgrep OS package Fast repository search
protoc and Protobuf headers OS packages Rust and Connect contract generation, including well-known types
PostgreSQL client OS package Database and integration verification
GTK/WebKitGTK/XKB development metadata OS packages Codewire GPUI/Wry Linux verification
Helm 3.16.4 Added by Dockerfile.system-hz-hermetic for offline runner validation
ShellCheck 0.11.0 Added by Dockerfile.system-hz-hermetic for offline shell validation
Kind 0.32.0 Added by Dockerfile.system-hz-hermetic for offline disposable cluster tests
sccache 0.17.0 Checksum-pinned static musl binary for host Rust compilation
Cilium chart 1.19.5 Stored at /opt/infra-artifacts/cilium-1.19.5.tgz for networkless rendering
PyYAML 6.0.2 Checksum-pinned CPython 3.12 amd64 wheel for manifest contract validation
Chromium native runtime Noble-pinned ALSA, NSPR, and NSS libraries installed from four checksum-pinned sealed .deb inputs

License

MIT