Custom Kaniko image (from Google’s debug variant) for Forgejo Actions: build & push container images in CI/CD by just setting env vars—no Docker daemon needed.
https://git.van-hemmen.com/actions/kaniko
- Shell 70.7%
- Dockerfile 29.3%
|
All checks were successful
/ docker-tag (push) Successful in 19s
## What
Adds a **`REGISTRY_INSECURE`** setting to `build.sh` (default `false`). When set to `true`, the wrapper passes Kaniko's `--insecure-registry=${REGISTRY_HOST}`, so a pipeline can push to Forgejo's in-cluster Service over plain HTTP instead of through the public ingress.
## Why
See #7. The runners and Forgejo run on the same node, but pushes to `git.van-hemmen.com` go out through Traefik and back. Traefik's ~60 s per-request timeout cuts large layer uploads, and `actions/sindri`'s `coder-xfce-vnc` builds fail at the push with `PATCH …/blobs/uploads/…: 502 Bad Gateway`. Forgejo logs `unexpected EOF` on uploads lasting 60.0–60.7 s.
## Changes
- **`build.sh`**
- New `REGISTRY_INSECURE` setting: `true`/`TRUE`/`True`/`1`/`yes` enables it; `false`/`0`/`no`/empty leaves it off. It's checked right after the defaults are set, so an invalid value stops the job before any build work.
- When enabled, `--insecure-registry=${REGISTRY_HOST}` is added to the Kaniko call. That flag covers only the named registry, so pulls from Docker Hub and other registries keep using TLS.
- `REGISTRY_INSECURE` is shown in the settings summary printed before the build.
- With the setting unset or `false`, the Kaniko command is byte-for-byte the same as today.
- **`README.md`**: new row in the settings table, plus a "Pushing to an in-cluster registry" section with example settings. It notes that `REGISTRY_HOST` must match the destination host (port included), that pulls stay `git.van-hemmen.com/…`, and that Forgejo's login request still goes to its public URL.
## Verification
- The Kaniko executor inside `actions/kaniko:26.7.0` supports `--insecure-registry` ("Insecure registry using plain HTTP to push and pull"), checked with `/kaniko/executor --help` in a pod.
- I ran the modified `build.sh` in that image's `/busybox/sh`, with the `exec /kaniko/executor` line replaced by `echo`:
| Case | Result |
|---|---|
| Unset | `… --dockerfile=./Dockerfile --no-push` (unchanged) |
| `REGISTRY_INSECURE=false` | unchanged |
| `true` + `REGISTRY_HOST=app-http-service.forgejo.svc.cluster.local:3000` + destination | `… --target=ci --insecure-registry=app-http-service.forgejo.svc.cluster.local:3000 --destination=app-http-service.forgejo.svc.cluster.local:3000/actions/sindri:ci-abc`; `config.json` keyed on that host:port |
| `REGISTRY_INSECURE=ture` | `Error: REGISTRY_INSECURE must be true or false (got 'ture').`, exit 1 |
- `sh -n` passes. `shellcheck -s sh` reports nothing new: a warning on the existing `eval` on line 10, and SC2086 infos on the intentionally unquoted `$…_FLAG` arguments, which follow the existing `$TARGET_FLAG`/`$DEST_FLAGS` pattern.
**Not yet verified:** an actual push through the internal Service. Pushing this branch makes `docker-dev` publish `git.van-hemmen.com/actions/kaniko:<sha>`. A companion `actions/sindri` branch uses that image with `REGISTRY_INSECURE=true` as the end-to-end test, and I'll report the result on this PR.
## After merge
Tag a release so `actions/sindri`'s workflows can pin the new version.
Closes #7
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01XPajGyTH2js52mY5WSJoNA
Reviewed-on: #8
Reviewed-by: Guillaume "B.B." Van Hemmen <guillaumehemmen@noreply.git.van-hemmen.com>
|
||
|---|---|---|
| .forgejo/workflows | ||
| build.sh | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTING.md | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
kaniko (action)
Custom Kaniko image (forked from Google’s
gcr.io/kaniko-project/executor:debug) for Forgejo Actions.
Build & push OCI-compatible container images in your pipelines without a
Docker daemon. Just set a few environment variables.
Highlights
| Feature | Benefit |
|---|---|
| Daemon-less builds | Works in completely rootless, container-only environments |
| Debug base | Includes /shell & common tools for troubleshooting |
| Registry-agnostic | Push to Docker Hub, GHCR, Harbor, Quay, Google Artifact Registry, etc. |
| Small wrapper script | Autodetects credentials and common env-var combos |
Image tags
| Tag | Base | Intended use |
|---|---|---|
latest |
Google debug executor |
General CI pipelines |
Quick start
# .forgejo/workflows/build.yaml
name: Build & push image
on:
push:
branches: [ main ]
jobs:
build:
runs-on: docker
container:
image: git.van-hemmen.com/actions/kaniko:latest
steps:
- name: Build & push with Kaniko
run: /bin/build.sh
env:
# --- mandatory --------------------------------------------------------
KANIKO_CONTEXT: git://git.van-hemmen.com/actions/kaniko.git
GIT_REF_NAME: ${{ github.ref_name }}
GIT_USERNAME: ${{ secrets.docker_username }}
GIT_PASSWORD: ${{ secrets.access_token }}
# --- optional (only needed when you plan to push) ---------------------
REGISTRY_HOST: ghcr.io
REGISTRY_USER: ${{ secrets.docker_username }}
REGISTRY_PASS: ${{ secrets.access_token }}
KANIKO_DESTINATION: git.van-hemmen.com/myorg/myapp:${GITHUB_SHA}
# --- fine-tuning ------------------------------------------------------
KANIKO_DOCKERFILE: ./Dockerfile
KANIKO_VERBOSITY: info
KANIKO_TARGET: production
Environment variables
| Variable | Required | Purpose | Example value |
|---|---|---|---|
KANIKO_CONTEXT |
Yes | Build context (git://). |
git://git.van-hemmen.com/actions/kaniko.git |
GIT_REF_NAME |
Yes | Branch or tag that is being built. | ${{ github.ref_name }} |
GIT_USERNAME |
Yes | Username with access to KANIKO_CONTEXT when it is private. |
${{ secrets.GIT_USERNAME }} |
GIT_PASSWORD |
Yes | Token/password paired with GIT_USERNAME. |
${{ secrets.GIT_PASSWORD }} |
REGISTRY_HOST |
No (default git.van-hemmen.com) |
Target registry hostname. | ghcr.io |
REGISTRY_USER |
No* | Registry username. Enables push only if both REGISTRY_USER and REGISTRY_PASS are set. |
${{ secrets.REGISTRY_USER }} |
REGISTRY_PASS |
No* | Registry password/token. | ${{ secrets.REGISTRY_PASS }} |
REGISTRY_INSECURE |
No (default false) |
true uses plain HTTP for REGISTRY_HOST only (Kaniko --insecure-registry). See below. |
true |
KANIKO_DESTINATION |
No | Comma-separated list of image references to push (variables like ${{ github.sha }} are expanded). |
ghcr.io/myorg/app:${{ github.sha }},ghcr.io/myorg/app:latest |
KANIKO_DOCKERFILE |
No (default ./Dockerfile) |
Path to the Dockerfile relative to the context. | ./docker/Dockerfile.alpine |
KANIKO_VERBOSITY |
No (default info) |
Log level (trace, debug, info, warn, error, fatal, panic). |
debug |
KANIKO_TARGET |
No | Target build stage for multi-stage Dockerfiles. If not set, all stages are built. | production |
* REGISTRY_USER / REGISTRY_PASS are only needed when the registry requires
authentication.
Pushing to an in-cluster registry
When the runner and Forgejo run in the same Kubernetes cluster, pushing to the public hostname sends every layer out through the ingress and back in. That is slower, and the ingress's request timeout can cut large layer uploads. Push to Forgejo's Service over plain HTTP instead:
env:
REGISTRY_HOST: app-http-service.forgejo.svc.cluster.local:3000
REGISTRY_INSECURE: 'true'
REGISTRY_USER: ${{ secrets.docker_username }}
REGISTRY_PASS: ${{ secrets.access_token }}
KANIKO_DESTINATION: app-http-service.forgejo.svc.cluster.local:3000/myorg/myapp:${GITHUB_SHA}
REGISTRY_HOSTmust match the host inKANIKO_DESTINATIONexactly, port included. Credentials are stored under that key, and only that host switches to HTTP; base-image pulls from other registries keep using TLS.- Forgejo stores images by owner and name, not by hostname, so the image is still
pulled as
git.van-hemmen.com/myorg/myapp:<tag>. - Forgejo's token endpoint stays on its public
ROOT_URL(https://git.van-hemmen.com/v2/token). That is one small HTTPS request per push; the layer data goes to the Service. - Only use this where the path to the Service is already private. On this cluster the Service is internal, and node-to-node traffic goes through WireGuard.