Fixes the registry push failure from PR #6's first real run (#16): docker/login-action against 192.168.0.3:3000 hit server gave HTTP response to HTTPS client — Docker refuses any non-localhost registry over plain HTTP by default.
Stacked on #7 (same file, unraid-template.xml, different fields — rebased on it to avoid a conflict).
What was considered and rejected (full record in docs/DECISIONS.md D17)
insecure-registries in daemon.json — the obvious fix. Rejected after reading this Unraid host's actual /etc/rc.d/rc.docker: applying it needs a full dockerd restart, and with Live Restore disabled here, that stops all ~40 other containers on the box first (Plex, Home Assistant, Vaultwarden, everything) as part of the restart sequence.
A real Let's Encrypt cert on a public bbergle.com subdomain — this host's other subdomains are Cloudflare-proxied (confirmed via dig), which would terminate TLS at Cloudflare's edge and never reach anything we control.
What was built instead
A 10-year self-signed cert for registry.bbergle.com, no real domain dependency.
An NPMplus proxy host (registry.bbergle.com → 192.168.0.3:3000 over plain HTTP internally), on NPMplus's real HTTPS port (9537 on this host — found via docker port NPMplus, not assumed to be 443, which turned out to be a different nginx process on the box).
/etc/hosts on the Unraid host mapping registry.bbergle.com → itself — the only client that ever needs to resolve this is that host's own dockerd (DooD), so this sidesteps DNS/Cloudflare/router NAT entirely.
The cert's CA dropped into /etc/docker/certs.d/registry.bbergle.com:9537/ca.crt — confirmed via Docker's own docs this is read per-connection, no daemon restart.
docker/setup-buildx-action@v3 pinned to driver: docker instead of its default docker-container driver, which runs an isolated builder that doesn't see /etc/docker/certs.d and would have silently defeated all of the above (confirmed via a docker/buildx GitHub issue before relying on it).
How this was verified
Not just built and hoped — actually exercised, and it caught a real bug:
First manual workflow_dispatch (run #18) failed with x509: certificate signed by unknown authority — the certs.d directory was missing the :9537 port suffix (created before we knew NPMplus's real port). Fixed, then confirmed with docker login directly on the host that the response changed from a TLS trust error to a proper unauthorized before re-running CI.
Second dispatch (run #19): succeeded. Confirmed via Gitea's packages API that the image actually landed, and separately pulled the manifest back through registry.bbergle.com:9537 from the Unraid host to confirm the full round trip, not just that CI reported green.
What's not done
The /etc/hosts entry and certs.d file are not persisted across a reboot — both live under /, which Unraid rebuilds from /boot on every boot, and wiring this into /boot/config/go was left as a deliberate follow-up for you to trigger when ready, given earlier caution about editing anything under /boot autonomously.
Fixes the registry push failure from PR #6's first real run (#16): `docker/login-action` against `192.168.0.3:3000` hit `server gave HTTP response to HTTPS client` — Docker refuses any non-localhost registry over plain HTTP by default.
Stacked on #7 (same file, unraid-template.xml, different fields — rebased on it to avoid a conflict).
## What was considered and rejected (full record in docs/DECISIONS.md D17)
- **`insecure-registries` in `daemon.json`** — the obvious fix. Rejected after reading this Unraid host's actual `/etc/rc.d/rc.docker`: applying it needs a full `dockerd` restart, and with `Live Restore` disabled here, that stops all ~40 other containers on the box first (Plex, Home Assistant, Vaultwarden, everything) as part of the restart sequence.
- **A real Let's Encrypt cert on a public `bbergle.com` subdomain** — this host's other subdomains are Cloudflare-proxied (confirmed via `dig`), which would terminate TLS at Cloudflare's edge and never reach anything we control.
## What was built instead
- A 10-year self-signed cert for `registry.bbergle.com`, no real domain dependency.
- An NPMplus proxy host (`registry.bbergle.com` → `192.168.0.3:3000` over plain HTTP internally), on NPMplus's real HTTPS port (`9537` on this host — found via `docker port NPMplus`, not assumed to be 443, which turned out to be a *different* nginx process on the box).
- `/etc/hosts` on the Unraid host mapping `registry.bbergle.com` → itself — the only client that ever needs to resolve this is that host's own `dockerd` (DooD), so this sidesteps DNS/Cloudflare/router NAT entirely.
- The cert's CA dropped into `/etc/docker/certs.d/registry.bbergle.com:9537/ca.crt` — confirmed via Docker's own docs this is read per-connection, no daemon restart.
- `docker/setup-buildx-action@v3` pinned to `driver: docker` instead of its default `docker-container` driver, which runs an isolated builder that doesn't see `/etc/docker/certs.d` and would have silently defeated all of the above (confirmed via a docker/buildx GitHub issue before relying on it).
## How this was verified
Not just built and hoped — actually exercised, and it caught a real bug:
- First manual `workflow_dispatch` (run #18) failed with `x509: certificate signed by unknown authority` — the `certs.d` directory was missing the `:9537` port suffix (created before we knew NPMplus's real port). Fixed, then confirmed with `docker login` directly on the host that the response changed from a TLS trust error to a proper `unauthorized` before re-running CI.
- Second dispatch (run #19): **succeeded**. Confirmed via Gitea's packages API that the image actually landed, and separately pulled the manifest back through `registry.bbergle.com:9537` from the Unraid host to confirm the full round trip, not just that CI reported green.
## What's not done
The `/etc/hosts` entry and `certs.d` file are **not** persisted across a reboot — both live under `/`, which Unraid rebuilds from `/boot` on every boot, and wiring this into `/boot/config/go` was left as a deliberate follow-up for you to trigger when ready, given earlier caution about editing anything under `/boot` autonomously.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
release.yml's first real run failed: docker/login-action against
192.168.0.3:3000 hit "server gave HTTP response to HTTPS client" — Docker
refuses any non-localhost registry over plain HTTP by default, so this was
never actually a workflow bug.
Rejected insecure-registries in daemon.json after reading this Unraid host's
own rc.docker script: applying it needs a full dockerd restart, and with
Live Restore disabled here, that stops every one of the ~40 other containers
on the box first. Also rejected a real Let's Encrypt cert on a public
bbergle.com subdomain — this host's other subdomains are Cloudflare-proxied,
which would terminate TLS at Cloudflare's edge and never reach our own cert
at all.
Chosen instead, scoped to touch nothing already working: a self-signed cert
for registry.bbergle.com behind a new NPMplus proxy host (found its real
HTTPS port, 9537, by reading `docker port NPMplus` rather than assuming 443,
which is a different nginx process on this box entirely); an /etc/hosts
entry on the Unraid host so only that host needs to resolve the name (no
DNS record, no router/NAT dependency); and its CA dropped into
/etc/docker/certs.d, which Docker's own docs confirm is read per-connection
with no daemon restart required. Also pins buildx to driver: docker instead
of setup-buildx-action's default docker-container driver, which runs an
isolated builder that doesn't see /etc/docker/certs.d and would have quietly
defeated all of the above.
Full record, including what was rejected and why, in docs/DECISIONS.md D17.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R2ZKeWkZV7ehf7fivrAkkG
Was tag-push-or-manual-dispatch only. Adds a push:main trigger so main stays
continuously deployable without needing a version tag for every change.
Also fixes a real bug this surfaced while testing the D17 registry-TLS fix:
the old tag logic unconditionally retagged :latest on every run, including
manual test dispatches off a feature branch — one such dispatch, done while
verifying the previous commit, silently overwrote :latest with a
feature-branch build. Tag resolution now only moves :latest on an actual
main push or a version tag; a manual dispatch gets its own
manual-<timestamp>-<sha> tag and leaves :latest alone.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R2ZKeWkZV7ehf7fivrAkkG
BBergle
merged commit bd74c2c7c1 into fix/deploy-unraid-template-port2026-09-21 20:59:15 -04:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Fixes the registry push failure from PR #6's first real run (#16):
docker/login-actionagainst192.168.0.3:3000hitserver gave HTTP response to HTTPS client— Docker refuses any non-localhost registry over plain HTTP by default.Stacked on #7 (same file, unraid-template.xml, different fields — rebased on it to avoid a conflict).
What was considered and rejected (full record in docs/DECISIONS.md D17)
insecure-registriesindaemon.json— the obvious fix. Rejected after reading this Unraid host's actual/etc/rc.d/rc.docker: applying it needs a fulldockerdrestart, and withLive Restoredisabled here, that stops all ~40 other containers on the box first (Plex, Home Assistant, Vaultwarden, everything) as part of the restart sequence.bbergle.comsubdomain — this host's other subdomains are Cloudflare-proxied (confirmed viadig), which would terminate TLS at Cloudflare's edge and never reach anything we control.What was built instead
registry.bbergle.com, no real domain dependency.registry.bbergle.com→192.168.0.3:3000over plain HTTP internally), on NPMplus's real HTTPS port (9537on this host — found viadocker port NPMplus, not assumed to be 443, which turned out to be a different nginx process on the box)./etc/hostson the Unraid host mappingregistry.bbergle.com→ itself — the only client that ever needs to resolve this is that host's owndockerd(DooD), so this sidesteps DNS/Cloudflare/router NAT entirely./etc/docker/certs.d/registry.bbergle.com:9537/ca.crt— confirmed via Docker's own docs this is read per-connection, no daemon restart.docker/setup-buildx-action@v3pinned todriver: dockerinstead of its defaultdocker-containerdriver, which runs an isolated builder that doesn't see/etc/docker/certs.dand would have silently defeated all of the above (confirmed via a docker/buildx GitHub issue before relying on it).How this was verified
Not just built and hoped — actually exercised, and it caught a real bug:
workflow_dispatch(run #18) failed withx509: certificate signed by unknown authority— thecerts.ddirectory was missing the:9537port suffix (created before we knew NPMplus's real port). Fixed, then confirmed withdocker logindirectly on the host that the response changed from a TLS trust error to a properunauthorizedbefore re-running CI.registry.bbergle.com:9537from the Unraid host to confirm the full round trip, not just that CI reported green.What's not done
The
/etc/hostsentry andcerts.dfile are not persisted across a reboot — both live under/, which Unraid rebuilds from/booton every boot, and wiring this into/boot/config/gowas left as a deliberate follow-up for you to trigger when ready, given earlier caution about editing anything under/bootautonomously.🤖 Generated with Claude Code