upstream krdsh_quay_web { server unix:/home/user/quay-run/gunicorn_web.sock fail_timeout=0; } upstream krdsh_quay_registry { server unix:/home/user/quay-run/gunicorn_registry.sock fail_timeout=0; } upstream krdsh_quay_secscan { server unix:/home/user/quay-run/gunicorn_secscan.sock fail_timeout=0; } proxy_cache_path /var/cache/angie/proxy/krdsh-quay keys_zone=krdsh_cache_quay:10m levels=1:2; map $http2:$http3 $krdsh_quay_http1_bucket { default $request_id; ## current instanse is not behind LB/ingress, ## so $proxy_protocol_addr is meaningless # ":" $proxy_protocol_addr; ":" $remote_addr; } map $http2 $krdsh_quay_http2_bucket { default $connection; "" $request_id; } map $http3 $krdsh_quay_http3_bucket { default $quic_connection; "" $request_id; } map $uri $krdsh_quay_namespace { default ""; ## ~*^/v2/([^/]+)(?:/[^/]+)+/blobs/ $1; ## ~*^/v2/([^/]+)/[^/]+/tags/ $1; ## ~*^/v2/([^/]+)/[^/]+/manifests/ $1; ~*^/v2/([^/]+)/.+/(?:blobs|manifests|tags)/ $1; } ## use $request_id to remove (tight) request limit map $krdsh_quay_namespace:$krdsh_remote_type $krdsh_quay_http1_ns_bucket { default $krdsh_quay_http1_bucket; ~*^(?:k2|krd): $request_id; ## remove limits for internal usage ~^[^:]+:internal$ $request_id; } map $krdsh_quay_namespace:$krdsh_remote_type $krdsh_quay_http2_ns_bucket { default $krdsh_quay_http2_bucket; ~*^(?:k2|krd): $request_id; ## remove limits for internal usage ~^[^:]+:internal$ $request_id; } map $krdsh_quay_namespace:$krdsh_remote_type $krdsh_quay_http3_ns_bucket { default $krdsh_quay_http3_bucket; ~*^(?:k2|krd): $request_id; ## remove limits for internal usage ~^[^:]+:internal$ $request_id; } map $cookie_patternfly $krdsh_quay_ui { default old; true new; } map $request_method:$uri $krdsh_quay_nocache { default 1; ## cache requests: ## - ^/api/v1/repository/.+/tag/$ ## - ^/api/v1/repository/.+/manifest/.+$ ~*^(?:GET|HEAD):/api/v1/repository/(?:krd|k2|library|docker_io|quay_io|gcr_io|ghcr_io|registry_k8s_io)/.+/(?:tag/|manifest/.+)$ ""; } limit_req_zone $http_authorization zone=krdsh_quay_staticauth:10m rate=30r/s; limit_req_zone $krdsh_quay_http1_bucket zone=krdsh_quay_http1_light:10m rate=60r/s; limit_req_zone $krdsh_quay_http2_bucket zone=krdsh_quay_http2_light:10m rate=600r/s; limit_req_zone $krdsh_quay_http3_bucket zone=krdsh_quay_http3_light:10m rate=600r/s; limit_req_zone $krdsh_quay_http1_ns_bucket zone=krdsh_quay_http1_ns_light:10m rate=60r/s; limit_req_zone $krdsh_quay_http2_ns_bucket zone=krdsh_quay_http2_ns_light:10m rate=600r/s; limit_req_zone $krdsh_quay_http3_ns_bucket zone=krdsh_quay_http3_ns_light:10m rate=600r/s; limit_req_zone $krdsh_quay_http1_bucket zone=krdsh_quay_http1_medium:10m rate=50r/s; limit_req_zone $krdsh_quay_http2_bucket zone=krdsh_quay_http2_medium:10m rate=500r/s; limit_req_zone $krdsh_quay_http3_bucket zone=krdsh_quay_http3_medium:10m rate=500r/s; limit_req_zone $krdsh_quay_http1_ns_bucket zone=krdsh_quay_http1_ns_medium:10m rate=50r/s; limit_req_zone $krdsh_quay_http2_ns_bucket zone=krdsh_quay_http2_ns_medium:10m rate=500r/s; limit_req_zone $krdsh_quay_http3_ns_bucket zone=krdsh_quay_http3_ns_medium:10m rate=500r/s; limit_req_zone $krdsh_quay_http1_bucket zone=krdsh_quay_http1_heavy:10m rate=5r/s; limit_req_zone $krdsh_quay_http2_bucket zone=krdsh_quay_http2_heavy:10m rate=50r/s; limit_req_zone $krdsh_quay_http3_bucket zone=krdsh_quay_http3_heavy:10m rate=50r/s; limit_req_zone $krdsh_quay_http1_ns_bucket zone=krdsh_quay_http1_ns_heavy:10m rate=5r/s; limit_req_zone $krdsh_quay_http2_ns_bucket zone=krdsh_quay_http2_ns_heavy:10m rate=50r/s; limit_req_zone $krdsh_quay_http3_ns_bucket zone=krdsh_quay_http3_ns_heavy:10m rate=50r/s; server { server_name quay.krd.sh; include snip.d/listen-http; access_log off; log_not_found off; root /var/www/empty; include snip.d/https-alt-svc; include snip.d/http-base-security-headers; keepalive_timeout 0; include snip.d/empty-favicon; location / { return 301 https://$host$uri$is_args$args; } } server { server_name quay.krd.sh; include snip.d/listen-https; include snip.d/ssl-krd.sh; access_log off; log_not_found off; root /var/www/empty; include snip.d/http-base-security-headers; include snip.d/proxy-common-headers; include snip.d/proxy-accept-encoding; include snip.d/proxy-connection-close; include snip.d/proxy-early-data; proxy_set_header Host $host; proxy_set_header Transfer-Encoding $http_transfer_encoding; proxy_redirect ~*^https?://$host(?:|:[0-9]+)/(.*)$ https://$host/$1; error_page 502 /home/user/quay-run-static/static/502.html; limit_req_status 429; limit_req_log_level warn; js_import njs/quay.js; location /static/ { root /home/user/quay-run-static; expires 1d; gzip_static on; brotli_static on; zstd_static on; error_page 404 /404; } location @old_ui { proxy_pass http://krdsh_quay_web; } location @new_ui { root /home/user/quay-run-static/static/patternfly; index index.html; gzip_static on; brotli_static on; zstd_static on; rewrite ^/(?:overview|organization|repository|tag) /index.html break; } location / { js_content quay.route_ui; js_var $krdsh_quay_ui_njs "$krdsh_quay_ui"; } location /angular { # Expire cookie and switch to old UI add_header Set-Cookie "patternfly=deleted; path=/; Expires=Thu, Jan 01 1970 00:00:00 UTC"; return 302 /$is_args$args; } location /react { # Set cookie and witch to new UI add_header Set-Cookie "patternfly=true; path=/; SameSite=Lax; HttpOnly;" always; return 302 /$is_args$args; } # Temporarily force signin for old and new UI to route to web app location /signin { proxy_pass http://krdsh_quay_web/; } # Capture traffic that needs to go to web_app, see /web.py location ~* ^/(?:config|csrf_token|oauth1|oauth2|webhooks|keys|.well-known|customtrigger|userfiles/) { proxy_pass http://krdsh_quay_web; } # Capture old UI paths that aren't present in new UI location ~* ^/(?:user/|search) { proxy_pass http://krdsh_quay_web; } location /push { proxy_pass http://krdsh_quay_web; client_max_body_size 5M; } location /realtime { proxy_pass http://krdsh_quay_web; proxy_buffering off; proxy_request_buffering off; } location /secscan/ { proxy_pass http://krdsh_quay_secscan; } # location ~ ^/v2/.+/_trust/tuf/ { # proxy_pass https://tuf.krd.sh$uri; # include snip.d/proxy-common-headers; # include snip.d/proxy-accept-encoding; # include snip.d/proxy-connection-close; # include snip.d/proxy-early-data; # proxy_set_header Host $host; # } location ~* ^/api/v1/repository(?:/.+/tag/|/.+/manifest/.+)$ { limit_req zone=krdsh_quay_http1_medium burst=50 nodelay; limit_req zone=krdsh_quay_http2_medium burst=100 nodelay; limit_req zone=krdsh_quay_http3_medium burst=100 nodelay; proxy_pass http://krdsh_quay_web; keepalive_timeout 0; proxy_cache krdsh_cache_quay; proxy_cache_key $uri$is_args$args; proxy_cache_bypass $http_pragma $http_authorization $krdsh_quay_nocache; proxy_no_cache $http_pragma $http_authorization $krdsh_quay_nocache; expires 30s; proxy_cache_valid 200 1m; proxy_cache_valid 10s; proxy_ignore_client_abort on; proxy_ignore_headers Cache-Control Expires Set-Cookie Vary; proxy_hide_header Cache-Control; proxy_hide_header Expires; proxy_hide_header Set-Cookie; proxy_hide_header Vary; ## quirks proxy_temp_file_write_size 4m; } location /api/ { limit_req zone=krdsh_quay_http1_heavy burst=25 nodelay; limit_req zone=krdsh_quay_http2_heavy burst=100 nodelay; limit_req zone=krdsh_quay_http3_heavy burst=100 nodelay; proxy_pass http://krdsh_quay_web; keepalive_timeout 0; } location /api/suconfig { proxy_pass http://krdsh_quay_web; proxy_read_timeout 2000; } ## Docker Registry V2 location = /v2/auth { limit_req zone=krdsh_quay_staticauth burst=10 nodelay; proxy_pass http://krdsh_quay_registry; keepalive_timeout 0; } location ~* ^/v2/_catalog { limit_req zone=krdsh_quay_http1_heavy burst=1 nodelay; limit_req zone=krdsh_quay_http2_heavy burst=5 nodelay; limit_req zone=krdsh_quay_http3_heavy burst=5 nodelay; proxy_pass http://krdsh_quay_registry; keepalive_timeout 0; proxy_read_timeout 10; } location ~* ^/v2/.+/blobs/ { limit_req zone=krdsh_quay_http1_ns_medium burst=50 nodelay; limit_req zone=krdsh_quay_http2_ns_medium burst=100 nodelay; limit_req zone=krdsh_quay_http3_ns_medium burst=100 nodelay; proxy_pass http://krdsh_quay_registry; keepalive_timeout 0; proxy_buffering off; proxy_request_buffering off; proxy_read_timeout 2000; proxy_send_timeout 2000; client_max_body_size 10G; http2_chunk_size 32k; include snip.d/disable-comp; } location ~* ^/v2/.+/tags/ { limit_req zone=krdsh_quay_http1_ns_heavy burst=2 nodelay; limit_req zone=krdsh_quay_http2_ns_heavy burst=2 nodelay; limit_req zone=krdsh_quay_http3_ns_heavy burst=2 nodelay; proxy_pass http://krdsh_quay_registry; keepalive_timeout 0; } location ~* ^/v2/.+/manifests/ { limit_req zone=krdsh_quay_http1_ns_medium burst=10 nodelay; limit_req zone=krdsh_quay_http2_ns_medium burst=50 nodelay; limit_req zone=krdsh_quay_http3_ns_medium burst=50 nodelay; proxy_pass http://krdsh_quay_registry; keepalive_timeout 0; } location /v2/ { limit_req zone=krdsh_quay_http1_light burst=20 nodelay; limit_req zone=krdsh_quay_http2_light burst=80 nodelay; limit_req zone=krdsh_quay_http3_light burst=80 nodelay; proxy_pass http://krdsh_quay_registry; keepalive_timeout 0; } ## Docker Registry V1 ## KrD: seems to be legacy location /v1/ { return 444; } # location /v1/ # { # limit_req zone=krdsh_quay_http1_heavy burst=5 nodelay; # limit_req zone=krdsh_quay_http2_heavy burst=25 nodelay; # limit_req zone=krdsh_quay_http3_heavy burst=25 nodelay; # proxy_pass http://krdsh_quay_registry; # proxy_buffering off; # proxy_request_buffering off; # client_max_body_size 10G; # keepalive_timeout 0; # } # location = /v1/_ping # { # default_type text/plain; # add_header X-Docker-Registry-Version 0.6.0; # add_header X-Docker-Registry-Standalone 0; # return 200 "true"; # } }