chore(ci): publish the image under ghcr.io/zoolutions - #98
Merged
Conversation
The repo moved to the zoolutions org for enterprise Actions minutes, and a workflow's GITHUB_TOKEN can only write packages in its own owner namespace - pushing to the mhenrixon user package now fails with "permission_denied: The requested installation does not exist" (which is why v1.0.0.2 never published). Point the publish workflow, the release script and the docs at ghcr.io/zoolutions/kamal-proxy. The dash gem's repository defaults move in lockstep (zoolutions/kamal#109).
mhenrixon
enabled auto-merge (squash)
August 10, 2026 09:57
mhenrixon
added a commit
to zoolutions/kamal
that referenced
this pull request
Aug 10, 2026
…0.0.3 The repos moved to the zoolutions org (enterprise Actions minutes), and a workflow's GITHUB_TOKEN can only write packages in its own owner namespace - so the proxy's publish workflow could no longer push to the mhenrixon user package, which is why the v1.0.0.2 image never appeared. The image now publishes as ghcr.io/zoolutions/kamal-proxy (zoolutions/kamal-proxy#98); this points the gem's repository defaults, docs, tests, integration harness, toolkit and the dash CLI image workflow at the new org. MINIMUM_VERSION moves to v1.0.0.3: the v1.0.0.2 tag predates the workflow fix, so its tag-triggered build pushes to the old org and can never publish - v1.0.0.3 is the same Go code cut from dash after the fix. Manifest regenerated for it (flag surface unchanged). Refs #108
4 tasks
mhenrixon
added a commit
to zoolutions/kamal
that referenced
this pull request
Aug 10, 2026
…rt transfer and per-zone DNS providers (#109) * chore(proxy): require kamal-proxy v1.0.0.2 Bump MINIMUM_VERSION to the proxy release carrying the dynamic redirect map, deny lists, cert store import/export and per-zone DNS-01 providers (kamal-proxy#86-#90), and regenerate the flag manifest from that tag's binary. The four new deploy flags the manifest gains are wired up in the commits that follow. Refs #108 * feat(proxy): redirects_source, deny lists and per-zone DNS-01 providers deploy.yml keys for three of the v1.0.0.2 proxy capabilities, so none of them needs the run.flags escape hatch: * proxy/redirects_source {source, interval}: the dynamic redirect map (--redirects-source/--redirects-interval). Edge disposition - it answers at the loadbalancer like ssl_domains and canonical_host - and composes with static redirects (map first, rules on a miss). The validator mirrors the ssl_domains source shape and refuses an interval below the proxy's own 10s minimum at config time. * proxy/deny_ips + proxy/deny_user_agents (--deny-ip/--deny-user-agent), edge beside allow_ips/rate_limit. IP entries get the allow_ips validation; UA patterns are shape-checked only (Go RE2 and Ruby Onigmo disagree at the edges - same reasoning as redirects/rewrites). The root-healthcheck-path guard, the trusted_proxies no-effect check and the cannot-identify-clients warning now count deny_ips, since deny rules key on the same client address. * proxy/run/acme/dns_provider hash form: zone=provider entries pinning each zone to the DNS host that serves it, `default` covering the rest, emitted as repeatable --acme-dns-provider flags with the bare default last. The string form keeps meaning what it always has. Refs #108 * feat(proxy): kamal proxy export_certs / import_certs CLI for the v1.0.0.2 certificate store transfer: export the estate for disaster recovery, import from a Traefik acme.json or restore an exported archive - the Traefik-migration path that must work before the first proxy boot. Both commands target the host that owns TLS: the loadbalancer host when load balancing, else the primary host. The command surface is shared by the proxy and loadbalancer builders (Commands::Proxy::CertTransfer); each supplies its own container, config volume and one-off image, so a loadbalancer sharing a proxy host transfers through the shared kamal-proxy volume. Transport picks the safe path per state: a running container exports through its RPC socket under the proxy's certificate write lock, a stopped one through a one-off offline container. Archives leave via the apps-config bind mount - the one path that is both a host and a container path - and imports stream through stdin into the one-off container, because a bind-mounted source would need host permissions the container user cannot be guaranteed to have, and the store must be written as the image's own user. Import refuses a running container (offline-only in the proxy) except for --verify, which only reads the archive; contradictory flag combinations fail before anything uploads, mirroring kamal-proxy's own flag groups. Refs #108 * chore(proxy): move the proxy image to ghcr.io/zoolutions, require v1.0.0.3 The repos moved to the zoolutions org (enterprise Actions minutes), and a workflow's GITHUB_TOKEN can only write packages in its own owner namespace - so the proxy's publish workflow could no longer push to the mhenrixon user package, which is why the v1.0.0.2 image never appeared. The image now publishes as ghcr.io/zoolutions/kamal-proxy (zoolutions/kamal-proxy#98); this points the gem's repository defaults, docs, tests, integration harness, toolkit and the dash CLI image workflow at the new org. MINIMUM_VERSION moves to v1.0.0.3: the v1.0.0.2 tag predates the workflow fix, so its tag-triggered build pushes to the old org and can never publish - v1.0.0.3 is the same Go code cut from dash after the fix. Manifest regenerated for it (flag surface unchanged). Refs #108 * fix(integration): fail setup.sh at a broken seed pull Without set -e a failed proxy-image seed (pull/tag/push into registry:4443) exits 0 - the script ends with rm -f - and the miss surfaces much later, deep inside an unrelated deploy, as "manifest unknown". Exactly the failure-at-a-distance the seeding comment warns about; now the setup step fails on the line that broke. * fix(proxy): harden cert transfer per review; finish org sweep Review findings from PR #109 (cubic): * import: an apostrophe in --resolver could end the single-quoted sh -c payload and run arbitrary commands on the target host - build the payload with Base#shell, which escapes embedded quotes. * export: take the deploy lock (a concurrent deploy could reboot the proxy mid-export and tear the offline read), and remove the archive in an ensure so a failed download does not leave private keys on the host. * import: move upload! inside the ensure's reach so a failed or partial upload cannot leave certificate material behind either. * acme: a non-string, blank or whitespace zone key would emit an --acme-dns-provider entry no zone ever matches - reject it at config time. * finish the ghcr org sweep: test/integration/main_test.rb and the testing-rules examples spell the image with regex-escaped dots, which the plain-string replace could not match. * fix(integration): surface setup.sh stderr in the harness failure message The harness's docker_compose captures stdout and discards the stderred block, so a docker daemon error in the seed (they all print to stderr) left three CI runs failing blind after "gems installed". exec 2>&1 puts everything setup.sh does onto the one stream the failure message carries.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The repo moved to the zoolutions org; a workflow's GITHUB_TOKEN can only write packages in its own owner namespace, so pushing to the
mhenrixonuser package fails withpermission_denied: The requested installation does not exist— which is why the v1.0.0.2 image never published.Points
docker-publish.yml,script/release-dashand the docs atghcr.io/zoolutions/kamal-proxy. After merging, v1.0.0.3 will be cut fromdash(same Go code as the never-published v1.0.0.2 — that tag's workflow still pushes to the old org, so it can never publish) and the dash gem's defaults move in lockstep (zoolutions/kamal#109).Note: after the first publish, make the new ghcr package public — kamal deploys and integration tests pull anonymously.
Summary by cubic
Switch Docker image publishing to
ghcr.io/zoolutions/kamal-proxyto fix CI permission errors after the org move and unblock new releases. Updates the release script and docs to match.Bug Fixes
.github/workflows/docker-publish.ymltags toghcr.io/zoolutions/kamal-proxy(latestand versioned).script/release-dashmessages to the new namespace.ghcr.io/mhenrixon/kamal-proxytoghcr.io/zoolutions/kamal-proxy.Migration
ghcr.io/zoolutions/kamal-proxyto public (anonymous pulls).v1.0.0.3fromdashand update the gem’sMINIMUM_VERSIONto that tag.Written for commit 1940868. Summary will update on new commits.