Files
homelab-design/decisions/0020-internal-registry-for-cicd.md
Billy D. 3a46a98be3
All checks were successful
Update README with ADR Index / update-readme (push) Successful in 6s
docs: add ADR index workflow, standardize all ADR formats
- Add Gitea Action to auto-update README badges and ADR table on push
- Standardize 8 ADRs from heading-style to inline metadata format
- Add shields.io badges for ADR counts (total/accepted/proposed)
- Replace static directory listing with linked ADR table in README
- Accept ADR-0030 (MFA/YubiKey strategy)
2026-02-09 17:25:27 -05:00

131 lines
4.8 KiB
Markdown

# 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/