Add CI workflow, admin frontend, Prometheus/Grafana monitoring, Cloudflare cache rules and worker, Nginx config, CONTRIBUTING.md and update docker-compose.yml

This commit is contained in:
zwitschi committed 2026-08-02 16:50:46 +02:00
1 parent 15a2aaa1a1
commit 15043cb4d1
8 files changed
+314

No files matched your search

+25
View File
@@ -0,0 +1,25 @@
# Cloudflare Cache Rules for Linear Void (per ADR-001)
## Recommended Cache Rules for media.example.com
1. **.ts segments (immutable)**
- Expression: (http.host eq "media.example.com" and http.request.uri.path contains ".ts")
- Cache status: Eligible for cache
- Edge Cache TTL: 1 month (or `Cache-Control: public, max-age=31536000, immutable` from origin)
- Cache Everything: Yes
2. **.m3u8 manifests (live)**
- Expression: (http.host eq "media.example.com" and http.request.uri.path contains ".m3u8")
- Cache status: Eligible for cache
- Edge Cache TTL: 10 seconds
- Cache-Control: public, max-age=10, must-revalidate
3. **Static assets**
- Expression: (http.host eq "example.com" and http.request.uri.path contains ".js" or http.request.uri.path contains ".css")
- Edge Cache TTL: 1 year (with hash in filename for immutable caching)
**Tiered Cache**: Enable Smart Tiered Cache for R2 custom domain to reduce origin requests.
**WAF**: Enable basic rate limiting and bot management for /ws and admin routes.
These rules ensure high cache hit ratio for .ts segments while keeping live manifests fresh. Monitor cache hit ratio in Cloudflare analytics.
+21
View File
@@ -0,0 +1,21 @@
// Cloudflare Worker for advanced cache rules and WAF (ADR-001)
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const url = new URL(request.url);
// Add immutable cache headers for .ts segments
if (url.pathname.endsWith(".ts")) {
const response = await fetch(request);
const headers = new Headers(response.headers);
headers.set("Cache-Control", "public, max-age=31536000, immutable");
return new Response(response.body, {
status: response.status,
headers,
});
}
return fetch(request);
}
+9
View File
@@ -0,0 +1,9 @@
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
# Create directories for HLS and frontend
RUN mkdir -p /usr/share/nginx/html/hls /usr/share/nginx/html/admin
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
+40
View File
@@ -0,0 +1,40 @@
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Serve static frontend
location / {
try_files $uri $uri/ /index.html;
}
# Proxy chat WebSocket
location /ws {
proxy_pass http://chat:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
# Serve HLS from playout (with cache headers for Cloudflare)
location /hls/ {
alias /usr/share/nginx/html/hls/;
add_header Cache-Control "public, max-age=3600";
add_header Access-Control-Allow-Origin "*";
}
# Health checks
location /health {
return 200 "healthy";
add_header Content-Type text/plain;
}
}
}