feat: built-in CDN asset delivery platform #561

Closed
opened 2026-06-07 15:24:58 +00:00 by jmiller · 1 comment
Owner

Summary

Add a built-in CDN/asset delivery platform to MokoGitea that serves repository content, release artifacts, and static sites through cacheable HTTP endpoints with proper headers, access control, and analytics. All UI lives within existing MokoGitea repo/org settings and tabs.

Motivation

CDN is a natural extension of a git hosting platform and one of the easiest infrastructure features to meter for commercial licensing (bandwidth, storage, custom domains). Self-hosted alternatives (GitHub Pages, GitLab Pages/Package Registry) charge premium tier pricing for equivalent features.

Feature Scope

Core: CDN Endpoints

  • Raw file serving - /:owner/:repo/cdn/:ref/*filepath serves repo files with proper Cache-Control, ETag, and Content-Type headers
  • Release artifact delivery - versioned binary downloads with resume support and download counters
  • Static site hosting - serve a branch/tag as a static site (index.html routing, SPA fallback option)
  • Downstream CDN-friendly (Cloudflare, nginx, etc. can edge-cache via standard HTTP caching)

Repo-Level UI (new "CDN" tab or sub-tab under Settings)

  • Enable/disable CDN per repo
  • Branch/tag selector - choose which ref to serve as the CDN origin
  • Root directory - serve from repo root, /docs, /public, /dist, etc.
  • Custom domain mapping - bind a custom domain (e.g., cdn.acme.com) to a repo's CDN endpoint
  • Auto-TLS via ACME/Let's Encrypt for custom domains
  • Access control - public, org-members-only, or token-authenticated
  • Cache invalidation - manual purge button + auto-purge on push to served branch

Org-Level UI (under org settings)

  • CDN overview dashboard - bandwidth usage, top repos, request counts
  • Domain management - all custom domains across the org in one place
  • Default CDN policy - org-wide defaults for cache TTL, access control, allowed file types
  • Usage limits/quotas - set per-repo or per-org bandwidth and storage caps

Analytics (visible in repo CDN tab)

  • Download/request counts per file and per release asset
  • Bandwidth consumed (daily/weekly/monthly)
  • Geographic distribution (from request headers, best-effort)
  • Top referrers

API for CI/CD

  • Push artifacts from pipelines to CDN-served paths
  • Cache invalidation endpoint (POST /:owner/:repo/cdn/purge)
  • Usage/analytics query endpoint

Architecture Notes

  • Piggybacks on existing MokoGitea router and auth middleware
  • Repo content served directly from git objects (no duplication to disk)
  • In-memory LRU cache for hot files, respects git object hashes for invalidation
  • Custom domain routing via SNI + host header matching
  • Download counters stored in existing DB (new table cdn_analytics)
  • Release asset serving reuses existing release attachment storage

Commercial Licensing Angle

  • Free tier: CDN endpoints enabled, no custom domains, basic analytics
  • Paid tier: custom domains, auto-TLS, advanced analytics, higher bandwidth quotas
  • Metered: bandwidth overages, storage beyond quota
## Summary Add a built-in CDN/asset delivery platform to MokoGitea that serves repository content, release artifacts, and static sites through cacheable HTTP endpoints with proper headers, access control, and analytics. All UI lives within existing MokoGitea repo/org settings and tabs. ## Motivation CDN is a natural extension of a git hosting platform and one of the easiest infrastructure features to meter for commercial licensing (bandwidth, storage, custom domains). Self-hosted alternatives (GitHub Pages, GitLab Pages/Package Registry) charge premium tier pricing for equivalent features. ## Feature Scope ### Core: CDN Endpoints - **Raw file serving** - `/:owner/:repo/cdn/:ref/*filepath` serves repo files with proper `Cache-Control`, `ETag`, and `Content-Type` headers - **Release artifact delivery** - versioned binary downloads with resume support and download counters - **Static site hosting** - serve a branch/tag as a static site (index.html routing, SPA fallback option) - Downstream CDN-friendly (Cloudflare, nginx, etc. can edge-cache via standard HTTP caching) ### Repo-Level UI (new "CDN" tab or sub-tab under Settings) - **Enable/disable CDN** per repo - **Branch/tag selector** - choose which ref to serve as the CDN origin - **Root directory** - serve from repo root, `/docs`, `/public`, `/dist`, etc. - **Custom domain mapping** - bind a custom domain (e.g., `cdn.acme.com`) to a repo's CDN endpoint - **Auto-TLS** via ACME/Let's Encrypt for custom domains - **Access control** - public, org-members-only, or token-authenticated - **Cache invalidation** - manual purge button + auto-purge on push to served branch ### Org-Level UI (under org settings) - **CDN overview dashboard** - bandwidth usage, top repos, request counts - **Domain management** - all custom domains across the org in one place - **Default CDN policy** - org-wide defaults for cache TTL, access control, allowed file types - **Usage limits/quotas** - set per-repo or per-org bandwidth and storage caps ### Analytics (visible in repo CDN tab) - Download/request counts per file and per release asset - Bandwidth consumed (daily/weekly/monthly) - Geographic distribution (from request headers, best-effort) - Top referrers ### API for CI/CD - Push artifacts from pipelines to CDN-served paths - Cache invalidation endpoint (`POST /:owner/:repo/cdn/purge`) - Usage/analytics query endpoint ## Architecture Notes - Piggybacks on existing MokoGitea router and auth middleware - Repo content served directly from git objects (no duplication to disk) - In-memory LRU cache for hot files, respects git object hashes for invalidation - Custom domain routing via SNI + host header matching - Download counters stored in existing DB (new table `cdn_analytics`) - Release asset serving reuses existing release attachment storage ## Commercial Licensing Angle - Free tier: CDN endpoints enabled, no custom domains, basic analytics - Paid tier: custom domains, auto-TLS, advanced analytics, higher bandwidth quotas - Metered: bandwidth overages, storage beyond quota
Author
Owner

Update Stream Integration

The CDN system should integrate with the existing update stream infrastructure so repos act as distribution origins, not just code repositories.

Flow

  1. User adds/updates a file in their repo (e.g., dist/app.js, release binaries, static assets)
  2. manifest.xml defines which files/directories are CDN-published via a new <cdn> block (served paths, cache TTL, access level)
  3. On push to the served branch, the update stream picks up the change and notifies downstream subscribers
  4. CDN endpoint serves the file with proper caching headers; subscribers can pull the new version automatically

manifest.xml CDN block (example)

<cdn enabled="true">
  <serve path="dist/" />
  <serve path="assets/" />
  <cache-ttl>3600</cache-ttl>
  <access>public</access>
</cdn>

Why this matters

  • The update stream already handles version tracking, subscriber notifications, and metadata sync across repos
  • Adding CDN awareness means repos become first-class asset distribution points - a file committed to a repo is instantly available via CDN URL and downstream consumers are notified of the update
  • This is the differentiator vs. GitHub Pages / GitLab Pages - those are static site hosts, this is a version-aware asset distribution system with subscriber notifications built in

CDN Settings Page - Remote Address Allowlist

Add a CDN settings page (repo-level and org-level) with an allowed remote addresses configuration to prevent CDN overusage and abuse:

Repo Settings > CDN > Access Control

  • IP/CIDR allowlist - only serve CDN content to requests from specified IP ranges (e.g., 10.0.0.0/8, 203.0.113.0/24)
  • Domain/referrer allowlist - restrict which referring domains can embed or link to CDN assets (prevents hotlinking)
  • Rate limiting - per-IP request rate limits (e.g., 100 req/min) with configurable burst
  • Geographic restrictions - optional country-level allow/deny based on request origin

Org Settings > CDN > Defaults

  • Org-wide default allowlist that applies to all repos unless overridden
  • Global rate limit and bandwidth cap across all repos in the org
  • Alert thresholds - notify admins when usage exceeds configured limits
## Update Stream Integration The CDN system should integrate with the existing update stream infrastructure so repos act as **distribution origins**, not just code repositories. ### Flow 1. User adds/updates a file in their repo (e.g., `dist/app.js`, release binaries, static assets) 2. `manifest.xml` defines which files/directories are CDN-published via a new `<cdn>` block (served paths, cache TTL, access level) 3. On push to the served branch, the update stream picks up the change and notifies downstream subscribers 4. CDN endpoint serves the file with proper caching headers; subscribers can pull the new version automatically ### manifest.xml CDN block (example) ```xml <cdn enabled="true"> <serve path="dist/" /> <serve path="assets/" /> <cache-ttl>3600</cache-ttl> <access>public</access> </cdn> ``` ### Why this matters - The update stream already handles version tracking, subscriber notifications, and metadata sync across repos - Adding CDN awareness means repos become first-class asset distribution points - a file committed to a repo is instantly available via CDN URL and downstream consumers are notified of the update - This is the differentiator vs. GitHub Pages / GitLab Pages - those are static site hosts, this is a **version-aware asset distribution system** with subscriber notifications built in --- ## CDN Settings Page - Remote Address Allowlist Add a CDN settings page (repo-level and org-level) with an **allowed remote addresses** configuration to prevent CDN overusage and abuse: ### Repo Settings > CDN > Access Control - **IP/CIDR allowlist** - only serve CDN content to requests from specified IP ranges (e.g., `10.0.0.0/8`, `203.0.113.0/24`) - **Domain/referrer allowlist** - restrict which referring domains can embed or link to CDN assets (prevents hotlinking) - **Rate limiting** - per-IP request rate limits (e.g., 100 req/min) with configurable burst - **Geographic restrictions** - optional country-level allow/deny based on request origin ### Org Settings > CDN > Defaults - Org-wide default allowlist that applies to all repos unless overridden - Global rate limit and bandwidth cap across all repos in the org - Alert thresholds - notify admins when usage exceeds configured limits
Sign in to join this conversation.