Read-only mirror — the public repositories of the Forgejo instance, refreshed every 10 minutes. The live instance (fg.dieschoenewolke.de) is reachable only over the VPN; clone here with https://git.dieschoenewolke.de/git/<owner>/<repo>.git.
summaryrefslogtreecommitdiff
path: root/deploy/nginx-edge-img.conf
diff options
context:
space:
mode:
Diffstat (limited to 'deploy/nginx-edge-img.conf')
-rw-r--r--deploy/nginx-edge-img.conf68
1 files changed, 68 insertions, 0 deletions
diff --git a/deploy/nginx-edge-img.conf b/deploy/nginx-edge-img.conf
new file mode 100644
index 0000000..3d6ac16
--- /dev/null
+++ b/deploy/nginx-edge-img.conf
@@ -0,0 +1,68 @@
+# --- img.dieschoenewolke.de: public read-only OCI mirror ---------------------
+# Merge this block into /root/Compose/Webserver/NginxEdge/nginx/default.conf
+# (write in place: `cat new > default.conf`) and force-recreate edge-nginx.
+#
+# docker/containerd/skopeo/crane all speak plain GET+HEAD with a Go or Docker
+# user agent. CRS treats those as scanners, so AppSec is off for this host - the
+# CrowdSec IP bouncer still applies and the registry itself is read-only.
+# `limit_except GET` is the second lock: even if zot were reconfigured, the edge
+# refuses every write verb.
+#
+# A path-based /v2/ on git.dieschoenewolke.de is NOT an option: OCI clients
+# build the repository name from <host>/<path>, so a shared host would force
+# names like git.dieschoenewolke.de/distroless/static and the /v2/ base path
+# would have to be stripped by the edge. docker's ping is
+# GET /v2/ (not /git/v2/), so the mirror gets its own name. The wildcard
+# *.dieschoenewolke.de certificate already covers it - no cert change.
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ listen 443 quic;
+ listen [::]:443 quic;
+ http2 on;
+ server_name img.dieschoenewolke.de;
+ access_log /dev/stdout edge;
+
+ set $crowdsec_disable_appsec 1;
+
+ add_header Alt-Svc 'h3=":443"; ma=86400' always;
+
+ ssl_certificate /certs/edge.crt;
+ ssl_certificate_key /certs/edge.key;
+ ssl_protocols TLSv1.2 TLSv1.3;
+ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
+ ssl_prefer_server_ciphers off;
+ ssl_ecdh_curve X25519:prime256v1:secp384r1;
+ ssl_session_cache shared:SSL:10m;
+ ssl_session_timeout 1d;
+ ssl_session_tickets off;
+
+ more_set_headers
+ "Strict-Transport-Security: max-age=31536000; includeSubDomains"
+ "X-Content-Type-Options: nosniff"
+ "Referrer-Policy: strict-origin-when-cross-origin";
+
+ # a manifest/index is a few hundred KB; layers are streamed, never buffered
+ client_max_body_size 4m;
+
+ location / {
+ limit_except GET {
+ deny all;
+ }
+
+ proxy_pass http://127.0.0.1:5000;
+ proxy_http_version 1.1;
+ proxy_set_header Connection "";
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto https;
+ # stream blobs instead of spooling them to the edge disk (28 GB root)
+ proxy_buffering off;
+ proxy_max_temp_file_size 0;
+ proxy_request_buffering off;
+ proxy_read_timeout 900s;
+ proxy_send_timeout 900s;
+ proxy_cache off;
+ }
+}