Skip to content

v1.1.2

Choose a tag to compare

@troke12 troke12 released this 22 Feb 05:29
· 11 commits to master since this release

Release notes – v1.1.2

Frontend

Docker pull copy per tag

  • On the repository page (tag list), each tag row shows the full docker pull <registry>/<group>/<repo>:<tag> command with a Copy button.
  • Registry URL is taken from VITE_REGISTRY_URL when set; otherwise the current host in production or localhost:5000 in development.
  • Optional env: see .env.example for VITE_REGISTRY_URL.

Nginx template: registry proxy

  • /v2 location proxies to the backend with:
    • proxy_request_buffering off – streams large PATCH bodies (layer uploads) instead of buffering, reducing server-to-server push retries.
    • client_max_body_size 0 – no upload size limit.
    • Long timeouts (900s) for connect, send, and read.
  • Use this when exposing the registry via the frontend (e.g. NPM → refity-frontend → backend).

Backend

Docker push from same host (connection reuse)

  • Fix: When the Docker daemon and Refity registry run on the same host, docker push could retry on the first layer; the POST (initiate blob
    upload) succeeded but the following PATCH (upload blob) did not reach the handler.
  • Cause: Docker reuses the same TCP connection for POST then PATCH. The handler did not read the POST body, which can break connection reuse
    for the next request.
  • Change: The initiate-blob-upload handler now drains the request body (io.Copy(io.Discard, r.Body) and r.Body.Close()) before handling,
    so the connection is ready for the PATCH.
  • No API or config change; upgrade and redeploy to benefit.

Docker push behind reverse proxy ("short copy" fix)

  • Fix: docker push through a reverse proxy (e.g. Cloudflare → Nginx Proxy Manager → Refity) failed with short copy: wrote 1 of 2294 while
    pushing via direct IP worked fine.
  • Cause: Three issues combined:
    1. Absolute Location URLs – Upload handlers returned Location: https://host/v2/... with scheme and host. If the proxy didn't set
      X-Forwarded-Proto correctly or the scheme mismatched, the Docker client followed the Location to the wrong endpoint and the connection was reset
      after 1 byte.
    2. Monolithic uploads ignored in async mode – Docker sends small blobs (config, ~2 KB) via POST /v2/.../uploads/?digest=sha256:...
      (monolithic). The handler only accepted this when SFTP_SYNC_UPLOAD=true; in the default async mode it discarded the body and returned 202,
      forcing an unnecessary PATCH round-trip that could fail through proxies.
    3. Manual 100-Continue – The PATCH handler called w.WriteHeader(100) manually, which interfered with Nginx's own Expect: 100-continue
      handling and could produce duplicate or garbled interim responses.
  • Changes:
    • All Location headers now use relative paths (/v2/...) instead of absolute URLs — matches the official Docker Distribution (registry)
      behavior and works behind any proxy without configuration.
    • Monolithic blob uploads (POST with ?digest=) now work in both sync and async modes. In async mode the blob is written to local staging
      first, then uploaded to SFTP in the background.
    • Removed manual w.WriteHeader(http.StatusContinue) — Go's net/http sends 100 Continue automatically when r.Body is read.
  • No API or config change; upgrade and redeploy to benefit.

Summary

Area Change
Frontend Per-tag docker pull copy on repository page
Frontend Nginx /v2 proxy: stream body, long timeouts
Backend Drain POST body in initiateBlobUpload for same-host push
Backend Relative Location URLs, monolithic async uploads, remove manual 100-Continue for reverse proxy compatibility
Config Optional VITE_REGISTRY_URL in .env.example