a615b7ebfd
Closes leeworks-agents/api-company#5 (docs-site Astro scaffold) Closes leeworks-agents/api-company#9 (metrics instrumentation standard) Closes leeworks-agents/api-company#10 (Gitea Actions openapi aggregation pipeline) Closes leeworks-agents/api-company#11 (docs-site Flux HelmRelease) Closes leeworks-agents/api-company#12 (SEO blog posts x3) Closes leeworks-agents/api-company#13 (legal docs ToS/Privacy/AUP) Closes leeworks-agents/api-company#14 (DNS documentation) ## Changes ### docs/legal/ - terms-of-service.md — API usage, liability, account termination, governing law - privacy-policy.md — request log retention (90d), no PII sold, data sharing - acceptable-use-policy.md — rate limit abuse, scraping prohibition, resale ban ### docs/metrics-standard.md - Defines api_requests_total, api_response_duration_seconds, api_data_freshness_seconds - Fastify (TypeScript) and FastAPI (Python) reference middleware implementations - Prometheus scrape config and Grafana dashboard guidance ### docs/registry.md - Decision: use Gitea built-in container registry (no new infra) - Image naming convention, auth, Kubernetes imagePullSecrets, ingress config ### docs/dns.md - Required A records for all 6 subdomains - cert-manager ClusterIssuer and Ingress TLS examples - Verification commands and human-operator action items ### docs-site/ - Astro 4 + MDX + sitemap scaffold - Base layout with nav linking all APIs, blog, RapidAPI, status - Landing page with API cards - Per-API Redoc viewer pages (zip-enrichment, holidays, air-quality) - Blog index + 3 SEO blog posts (~1000 words each with JSON-LD) - Dockerfile (multi-stage: node build + nginx serve) - nginx.conf with gzip, caching, health endpoint ### flux/ - gitea-runner/: gitea-act-runner HelmRelease (org-scope, dind) - monitoring/: kube-prometheus-stack + Gatus HelmReleases - Prometheus with pod annotation scraping - Grafana at grafana.leeworks.dev with persistence - Gatus status page at status.leeworks.dev, 90-day retention - docs-site/: Deployment + Service + Ingress via raw chart - api-company-source/: GitRepository + Kustomization reference manifests - kustomization.yaml: root kustomize entry point (build validated) ### .gitea/workflows/build-docs.yaml - Aggregates openapi.yaml from zip-enrichment, holidays, air-quality repos - Builds Astro docs-site - Pushes image to registry.leeworks.dev/leeworks-agents/docs-site - Triggered on push to main, schedule daily 02:00 UTC, workflow_dispatch
164 lines
4.8 KiB
Markdown
164 lines
4.8 KiB
Markdown
# Container Registry: registry.leeworks.dev
|
|
|
|
**Decision Date:** 2026-05-24
|
|
**Status:** Planned (Phase 0 prerequisite)
|
|
|
|
---
|
|
|
|
## Decision: Use Gitea's Built-in Container Registry
|
|
|
|
We will use **Gitea's built-in container registry** (OCI-compatible, enabled via `GITEA_CONTAINER_REGISTRY`) rather than deploying a separate `distribution/distribution` instance.
|
|
|
|
### Rationale
|
|
|
|
1. **No new infra** — Gitea is already deployed; enabling the container registry is a config flag, not a new deployment.
|
|
2. **Integrated auth** — API keys, org-scoped tokens, and CI secrets work natively with the Gitea registry.
|
|
3. **Simpler CI** — Gitea Actions workflows can use `${{ secrets.GITEA_TOKEN }}` to push to `gitea.leeworks.dev/leeworks-agents/<image>`.
|
|
4. **OCI compliance** — Gitea's container registry is OCI v1 compliant, compatible with Docker, Podman, and Kubernetes image pulls.
|
|
|
|
---
|
|
|
|
## Registry Hostname
|
|
|
|
```
|
|
registry.leeworks.dev
|
|
```
|
|
|
|
This will be a reverse proxy/ingress alias for `gitea.leeworks.dev` (Gitea's container registry endpoint).
|
|
|
|
Alternatively, Docker clients can use the Gitea hostname directly:
|
|
```
|
|
gitea.leeworks.dev/leeworks-agents/<image>:<tag>
|
|
```
|
|
|
|
If a separate hostname is preferred by the operator, configure an Nginx ingress to proxy `registry.leeworks.dev` → Gitea's container registry port.
|
|
|
|
---
|
|
|
|
## Image Naming Convention
|
|
|
|
```
|
|
registry.leeworks.dev/leeworks-agents/<repo-name>:<tag>
|
|
```
|
|
|
|
| API | Image |
|
|
|-----|-------|
|
|
| ZIP Enrichment | `registry.leeworks.dev/leeworks-agents/zip-enrichment:latest` |
|
|
| Holidays | `registry.leeworks.dev/leeworks-agents/holidays:latest` |
|
|
| Air Quality | `registry.leeworks.dev/leeworks-agents/air-quality:latest` |
|
|
| Docs Site | `registry.leeworks.dev/leeworks-agents/docs-site:latest` |
|
|
|
|
Tags should also include the git SHA for traceability: `:<sha>` in addition to `:latest`.
|
|
|
|
---
|
|
|
|
## Authentication
|
|
|
|
### Pushing from CI (Gitea Actions)
|
|
|
|
```yaml
|
|
- name: Log in to registry
|
|
run: |
|
|
echo "${{ secrets.GITEA_TOKEN }}" | docker login registry.leeworks.dev \
|
|
-u ${{ gitea.actor }} --password-stdin
|
|
|
|
- name: Build and push
|
|
run: |
|
|
docker build -t registry.leeworks.dev/leeworks-agents/${{ gitea.repository_name }}:${{ gitea.sha }} .
|
|
docker push registry.leeworks.dev/leeworks-agents/${{ gitea.repository_name }}:${{ gitea.sha }}
|
|
docker tag registry.leeworks.dev/leeworks-agents/${{ gitea.repository_name }}:${{ gitea.sha }} \
|
|
registry.leeworks.dev/leeworks-agents/${{ gitea.repository_name }}:latest
|
|
docker push registry.leeworks.dev/leeworks-agents/${{ gitea.repository_name }}:latest
|
|
```
|
|
|
|
### Pulling from Kubernetes
|
|
|
|
Create an image pull secret in each namespace:
|
|
|
|
```bash
|
|
kubectl create secret docker-registry gitea-registry \
|
|
--docker-server=registry.leeworks.dev \
|
|
--docker-username=<gitea-user> \
|
|
--docker-password=<gitea-token> \
|
|
--docker-email=ci@leeworks.dev \
|
|
-n <namespace>
|
|
```
|
|
|
|
Reference in pod spec:
|
|
```yaml
|
|
spec:
|
|
imagePullSecrets:
|
|
- name: gitea-registry
|
|
```
|
|
|
|
---
|
|
|
|
## Enabling Gitea Container Registry
|
|
|
|
If not already enabled, the Gitea administrator needs to ensure:
|
|
|
|
1. In `app.ini` (or Helm values), container registry is enabled:
|
|
```ini
|
|
[packages]
|
|
ENABLED = true
|
|
```
|
|
2. The Gitea service is accessible on port 443 at `gitea.leeworks.dev`.
|
|
3. If using `registry.leeworks.dev` as an alias, configure an Nginx Ingress:
|
|
```yaml
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: registry-ingress
|
|
namespace: gitea
|
|
annotations:
|
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
nginx.ingress.kubernetes.io/proxy-body-size: "0"
|
|
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
|
|
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
|
|
spec:
|
|
ingressClassName: nginx
|
|
tls:
|
|
- hosts:
|
|
- registry.leeworks.dev
|
|
secretName: registry-tls
|
|
rules:
|
|
- host: registry.leeworks.dev
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: gitea-http
|
|
port:
|
|
number: 3000
|
|
```
|
|
|
|
---
|
|
|
|
## Verification
|
|
|
|
```bash
|
|
# Test login
|
|
docker login registry.leeworks.dev -u <user> -p <token>
|
|
|
|
# Test push
|
|
docker pull alpine:latest
|
|
docker tag alpine:latest registry.leeworks.dev/leeworks-agents/test:latest
|
|
docker push registry.leeworks.dev/leeworks-agents/test:latest
|
|
|
|
# Test pull from cluster
|
|
kubectl run test-pull --image=registry.leeworks.dev/leeworks-agents/test:latest \
|
|
--image-pull-policy=Always --rm -it --restart=Never -- echo "Registry works"
|
|
```
|
|
|
|
---
|
|
|
|
## Phase 4 Reference
|
|
|
|
All API repos should update their `ROADMAP.md §Phase 4` to reference:
|
|
```
|
|
registry.leeworks.dev/leeworks-agents/<repo>:<tag>
|
|
```
|
|
as the image target for CI pushes and Flux HelmRelease image references.
|