# Internal Registry URLs for CI/CD * Status: accepted * Date: 2026-02-02 * Deciders: Billy * Technical Story: Bypass Cloudflare 100MB limit by using internal registry endpoints for CI pushes ## Context | Factor | Details | |--------|---------| | Problem | Cloudflare proxying limits uploads to 100MB per request | | Impact | Docker images (20GB+) and large packages fail to push | | Current Setup | Gitea at `git.daviestechlabs.io` behind Cloudflare | | Internal Access | `registry.lab.daviestechlabs.io` bypasses Cloudflare | Our Gitea instance is accessible via two URLs: - **External**: `git.daviestechlabs.io` - proxied through Cloudflare (DDoS protection, caching) - **Internal**: `registry.lab.daviestechlabs.io` - direct access from cluster network Cloudflare's free tier enforces a 100MB upload limit per request. This blocks: - Docker image pushes (multi-GB layers) - Large Python package uploads - Any artifact exceeding 100MB ## Decision **Use internal registry URLs for all CI/CD artifact uploads.** CI/CD workflows running on Gitea Actions runners (which are inside the cluster) should use `registry.lab.daviestechlabs.io` for: - Docker image pushes - PyPI package uploads - Any large artifact uploads External URLs remain for: - Git operations (clone, push, pull) - Package downloads (pip install, docker pull) - Human access via browser ## Architecture ``` ┌─────────────────────────────────────────────────────────────────┐ │ INTERNET │ └─────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────┐ │ Cloudflare │ │ (100MB limit) │ └────────┬────────┘ │ ▼ ┌──────────────────────────────┐ │ git.daviestechlabs.io │ │ (external access) │ └──────────────────────────────┘ │ │ same Gitea instance │ ┌──────────────────────────────┐ │ registry.lab.daviestechlabs │ │ (internal, no limits) │ └──────────────────────────────┘ ▲ │ direct upload │ ┌──────────────────────────────┐ │ Gitea Actions Runner │ │ (in-cluster) │ └──────────────────────────────┘ ``` ## Consequences ### Positive - **No upload size limits** for CI/CD artifacts - **Faster uploads** (no Cloudflare proxy overhead) - **Lower latency** for in-cluster operations - **Cost savings** (reduced Cloudflare bandwidth) ### Negative - **Two URLs to maintain** in workflow configurations - **Runners must be in-cluster** (cannot use external runners for uploads) - **DNS split-horizon** required if accessing from outside ### Neutral - External users can still pull packages/images via Cloudflare URL - Git operations continue through external URL (small payloads) ## Implementation ### Docker Registry Login ```yaml - name: Login to Internal Registry uses: docker/login-action@v3 with: registry: registry.lab.daviestechlabs.io username: ${{ secrets.REGISTRY_USER }} password: ${{ secrets.REGISTRY_TOKEN }} ``` ### PyPI Upload ```yaml - name: Publish to Gitea PyPI run: | twine upload \ --repository-url https://registry.lab.daviestechlabs.io/api/packages/daviestechlabs/pypi \ dist/* ``` ### Environment Variable Pattern For consistency across workflows: ```yaml env: REGISTRY_EXTERNAL: git.daviestechlabs.io REGISTRY_INTERNAL: registry.lab.daviestechlabs.io ``` ## Related - [ADR-0019: Handler Deployment Strategy](ADR-0019-handler-deployment-strategy.md) - Uses PyPI publishing - Cloudflare upload limits: https://developers.cloudflare.com/workers/platform/limits/