initial import for Open Source 🎉

This commit is contained in:
Jimmy Zelinskie 2019-11-12 11:09:47 -05:00
parent 1898c361f3
commit 9c0dd3b722
2048 changed files with 218743 additions and 0 deletions

8
conf/nginx/dhparams.pem Normal file
View file

@ -0,0 +1,8 @@
-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEAk7fEh4MFr446aU61ZGxCl8VHvcJhDGcdd+3zaNxdWF7Wvr5QE8zX
QswoM5K2szlK7klcJOXer2IToHHQQn00nuWO3m6quZGV6EPbRmRKfRGa8pzSwH+R
Ph0OUpEQPh7zvegeVwEbrblD7i53ookbHlYGtxsPb28Y06OP5/xpks9C815Zy4gy
tx2yHi4FkFo52yErBF9jD/glsZYVHCo42LFrVGa5/7V0g++fG8yXCrBnqmz2d8FF
uU6/KJcmDCUn1m3mDfcf5HgeXSIsukW/XMZ3l9w1fdluJRwdEE9W2ePgqMiG3eC0
2T1sPfXCdXPQ7/5Gzf1eMtRZ/McipxVbgwIBAg==
-----END DH PARAMETERS-----

View file

@ -0,0 +1,7 @@
# vim: ft=nginx
server {
listen 8080 default_server;
server_name _;
rewrite ^ https://$host$request_uri? permanent;
}

73
conf/nginx/http-base.conf Normal file
View file

@ -0,0 +1,73 @@
# vim: ft=nginx
set_real_ip_from 0.0.0.0/0;
real_ip_recursive on;
log_format lb_logs '$remote_addr ($proxy_protocol_addr) '
'- $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'($request_time $request_length $upstream_response_time)';
types_hash_max_size 2048;
include /etc/opt/rh/rh-nginx112/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
client_body_temp_path /tmp/nginx 1 2;
proxy_temp_path /tmp/nginx-proxy;
fastcgi_temp_path /tmp/nginx-fastcgi;
uwsgi_temp_path /tmp/nginx-uwsgi;
scgi_temp_path /tmp/nginx-scgi;
sendfile on;
gzip on;
gzip_http_version 1.0;
gzip_proxied any;
gzip_min_length 500;
gzip_disable "MSIE [1-6]\.";
gzip_types text/plain text/xml text/css
text/javascript application/x-javascript
application/javascript image/svg+xml
application/octet-stream;
map $proxy_protocol_addr $proper_forwarded_for {
"" $proxy_add_x_forwarded_for;
default $proxy_protocol_addr;
}
map $http_x_forwarded_proto $proper_scheme {
default $scheme;
https https;
}
upstream web_app_server {
server unix:/tmp/gunicorn_web.sock fail_timeout=0;
}
upstream jwtproxy_secscan {
server unix:/tmp/jwtproxy_secscan.sock fail_timeout=0;
}
upstream verbs_app_server {
server unix:/tmp/gunicorn_verbs.sock fail_timeout=0;
}
upstream registry_app_server {
server unix:/tmp/gunicorn_registry.sock fail_timeout=0;
}
# NOTE: Exposed for the _internal_ping *only*. All other secscan routes *MUST* go through
# the jwtproxy.
upstream secscan_app_server {
server unix:/tmp/gunicorn_secscan.sock fail_timeout=0;
}
upstream build_manager_controller_server {
server localhost:8686;
}
upstream build_manager_websocket_server {
server localhost:8787;
}

129
conf/nginx/nginx.conf.jnj Normal file
View file

@ -0,0 +1,129 @@
# vim: ft=nginx
include root-base.conf;
{% if use_https %}
http {
include http-base.conf;
include hosted-http-base.conf;
include rate-limiting.conf;
server_names_hash_bucket_size 64;
resolver 127.0.0.1:8053 valid=10s;
ssl_ciphers '{{ ssl_ciphers }}';
ssl_protocols {% for ssl_protocol in ssl_protocols %}{{ ssl_protocol }} {% endfor %};
ssl_session_cache shared:SSL:60m;
ssl_session_timeout 2h;
ssl_session_tickets on;
ssl_prefer_server_ciphers on;
ssl_dhparam dhparams.pem;
server {
server_name _;
ssl_certificate ../stack/ssl.cert;
ssl_certificate_key ../stack/ssl.key;
include server-base.conf;
listen 8443 ssl http2 default;
ssl on;
# This header must be set only for HTTPS
add_header Strict-Transport-Security "max-age=63072000; preload";
access_log /var/log/nginx/access.log lb_logs;
}
server {
server_name _;
ssl_certificate ../stack/ssl.cert;
ssl_certificate_key ../stack/ssl.key;
include server-base.conf;
listen 7443 ssl http2 default proxy_protocol;
ssl on;
# This header must be set only for HTTPS
add_header Strict-Transport-Security "max-age=63072000; preload";
real_ip_header proxy_protocol;
access_log /var/log/nginx/access.log lb_logs;
}
{% if v1_only_domain %}
server {
include server-base.conf;
server_name {{ v1_only_domain }};
{% if use_old_certs %}
ssl_certificate ../stack/ssl.old.cert;
ssl_certificate_key ../stack/ssl.old.key;
{% else %}
ssl_certificate ../stack/ssl.cert;
ssl_certificate_key ../stack/ssl.key;
{% endif %}
listen 8443 ssl;
ssl on;
# This header must be set only for HTTPS
add_header Strict-Transport-Security "max-age=63072000; preload";
access_log /var/log/nginx/access.log lb_logs;
}
server {
server_name {{ v1_only_domain }};
{% if use_old_certs %}
ssl_certificate ../stack/ssl.old.cert;
ssl_certificate_key ../stack/ssl.old.key;
{% else %}
ssl_certificate ../stack/ssl.cert;
ssl_certificate_key ../stack/ssl.key;
{% endif %}
include server-base.conf;
listen 7443 ssl proxy_protocol;
ssl on;
# This header must be set only for HTTPS
add_header Strict-Transport-Security "max-age=63072000; preload";
real_ip_header proxy_protocol;
access_log /var/log/nginx/access.log lb_logs;
}
{% endif %}
}
{% else %}
http {
include http-base.conf;
include rate-limiting.conf;
resolver 127.0.0.1:8053 valid=10s;
server {
include server-base.conf;
listen 8080 default;
access_log /var/log/nginx/access.log lb_logs;
}
}
{% endif %}

View file

@ -0,0 +1,66 @@
# vim: ft=nginx
# Define two buckets: Once for http1 connections (which we force to shard across our fleet) and
# one for http2 connections (which will all hit the same node).
map $http2 $http1_bucket {
"" $proxy_protocol_addr; # HTTP1 case: use the IP address, since shared across nodes.
default $request_id; # HTTP2 case: use request ID to "disable" check.
}
map $http2 $http2_bucket {
"" $request_id; # HTTP1 case: use the request ID to "disable" check.
default $connection; # HTTP2 case: use the connection serial number to limit.
}
# Define two additional buckets that fall to $request_id (thus no effective rate limiting) if
# a specific set of namespaces is matched. This allows us to turn off rate limiting selectively
# for special internal namespaces.
map $namespace $namespaced_http1_bucket {
{% for namespace in non_rate_limited_namespaces %}
"{{ namespace }}" $request_id;
{% endfor %}
{% if enable_rate_limits %}
default $http1_bucket;
{% else %}
default $request_id;
{% endif %}
}
map $namespace $namespaced_http2_bucket {
{% for namespace in non_rate_limited_namespaces %}
"{{ namespace }}" $request_id;
{% endfor %}
{% if enable_rate_limits %}
default $http2_bucket;
{% else %}
default $request_id;
{% endif %}
}
{% if enable_rate_limits %}
limit_req_zone $http_authorization zone=staticauth:10m rate=30r/s;
{% else %}
limit_req_zone $request_id zone=staticauth:10m rate=300r/s;
{% endif %}
limit_req_zone $http1_bucket zone=dynamicauth_very_light_http1:10m rate=30r/s;
limit_req_zone $http2_bucket zone=dynamicauth_very_light_http2:10m rate=600r/s;
limit_req_zone $namespaced_http1_bucket zone=namespaced_dynamicauth_very_light_http1:10m rate=30r/s;
limit_req_zone $namespaced_http2_bucket zone=namespaced_dynamicauth_very_light_http2:10m rate=600r/s;
limit_req_zone $http1_bucket zone=dynamicauth_light_http1:10m rate=20r/s;
limit_req_zone $http2_bucket zone=dynamicauth_light_http2:10m rate=400r/s;
limit_req_zone $namespaced_http1_bucket zone=namespaced_dynamicauth_light_http1:10m rate=20r/s;
limit_req_zone $namespaced_http2_bucket zone=namespaced_dynamicauth_light_http2:10m rate=400r/s;
# This zone should always be used with burst=<number> (nodelay|delay) as the
# limit is very low on purpose but should allow for the burst of traffic
# required for a registry operation. The burst number should also vary per
# endpoint.
limit_req_zone $http1_bucket zone=dynamicauth_heavy_http1:10m rate=1r/s;
limit_req_zone $http2_bucket zone=dynamicauth_heavy_http2:10m rate=20r/s;
limit_req_zone $namespaced_http1_bucket zone=namespaced_dynamicauth_heavy_http1:10m rate=1r/s;
limit_req_zone $namespaced_http2_bucket zone=namespaced_dynamicauth_heavy_http2:10m rate=20r/s;
limit_req_status 429;
limit_req_log_level warn;

1
conf/nginx/resolver.conf Normal file
View file

@ -0,0 +1 @@
resolver 127.0.0.1:8053 valid=10s;

15
conf/nginx/root-base.conf Normal file
View file

@ -0,0 +1,15 @@
# vim: ft=nginx
pid /tmp/nginx.pid;
error_log /var/log/nginx/error.log;
worker_processes auto;
worker_priority -10;
worker_rlimit_nofile 10240;
daemon off;
events {
worker_connections 10240;
accept_mutex off;
}

View file

@ -0,0 +1,337 @@
# vim: ft=nginx
keepalive_timeout 5;
if ($host = "www.quay.io") {
return 301 $proper_scheme://quay.io$request_uri;
}
# Disable the ability to be embedded into iframes
add_header X-Frame-Options DENY;
# Proxy Headers
proxy_set_header X-Forwarded-For $proper_forwarded_for;
proxy_set_header X-Forwarded-Proto $proper_scheme;
proxy_set_header Host $host;
proxy_redirect off;
proxy_set_header Transfer-Encoding $http_transfer_encoding;
location / {
proxy_pass http://web_app_server;
}
location /push {
proxy_pass http://web_app_server;
client_max_body_size 5M;
}
location /realtime {
proxy_pass http://web_app_server;
proxy_buffering off;
proxy_request_buffering off;
}
location ~ ^/_storage_proxy/([^/]+)/([^/]+)/([^/]+)/(.+) {
include resolver.conf;
auth_request /_storage_proxy_auth;
proxy_pass $2://$3/$4$is_args$args;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $3;
add_header Host $3;
proxy_buffering off;
proxy_request_buffering off;
proxy_read_timeout 60s;
}
location = /_storage_proxy_auth {
proxy_pass http://web_app_server;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
proxy_read_timeout 10;
}
location ~ ^/v2/_catalog(.*)$ {
proxy_pass http://registry_app_server;
proxy_read_timeout 10;
keepalive_timeout 0; # Disables HTTP 1.1 keep-alive and forces round-robin.
{% if enable_rate_limits %}
limit_req zone=dynamicauth_heavy_http1 burst=1 nodelay;
limit_req zone=dynamicauth_heavy_http2 burst=5 nodelay;
{% endif %}
}
location /secscan/ {
proxy_pass http://jwtproxy_secscan;
}
location /secscan/_internal_ping {
proxy_pass http://secscan_app_server;
}
{% if signing_enabled %}
location ~ ^/v2/(.+)/_trust/tuf/(.*)$ {
set $upstream_tuf {{ tuf_server }};
proxy_pass $upstream_tuf$uri;
proxy_set_header Host "{{ tuf_host }}";
}
{% endif %}
location /cnr {
proxy_buffering off;
proxy_request_buffering off;
proxy_pass http://registry_app_server;
proxy_read_timeout 120;
proxy_temp_path /tmp 1 2;
{% if enable_rate_limits %}
limit_req zone=staticauth burst=5 nodelay;
{% endif %}
}
location /api/ {
proxy_pass http://web_app_server;
{% if enable_rate_limits %}
limit_req zone=dynamicauth_heavy_http1 burst=25 nodelay;
limit_req zone=dynamicauth_heavy_http2 burst=100 nodelay;
{% endif %}
keepalive_timeout 0; # Disables HTTP 1.1 keep-alive and forces round-robin.
}
location /api/suconfig {
proxy_pass http://web_app_server;
# For suconfig, set our read timeout as super large for both DB migrations
# and awaiting for secrets to be updated.
proxy_read_timeout 2000;
}
# This block handles blob requests, and will receive a high volume of traffic, so we set the burst
# much higher.
location ~ /v2/([^/]+)\/[^/]+/blobs/ {
# If we're being accessed via v1.quay.io, pretend we don't support v2.
if ($host = "v1.quay.io") {
return 404;
}
# NOTE: We disable gzip for HEAD requests because Docker issues them to determine the Content
# Length of a blob. Unfortunately, nginx, seeing an empty body, overwrites the header with
# a length of 0, which breaks this functionality.
if ($request_method = HEAD) {
gzip off;
}
proxy_buffering off;
proxy_request_buffering off;
proxy_read_timeout 2000;
proxy_temp_path /tmp 1 2;
client_max_body_size {{ maximum_layer_size }};
# Setting ANY header clears all inherited proxy_set_header directives
proxy_set_header X-Forwarded-For $proper_forwarded_for;
proxy_set_header X-Forwarded-Proto $proper_scheme;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_pass http://registry_app_server;
set $namespace $1;
{% if enable_rate_limits %}
limit_req zone=namespaced_dynamicauth_light_http1 burst=50 nodelay;
limit_req zone=namespaced_dynamicauth_light_http2 burst=100 nodelay;
{% endif %}
keepalive_timeout 0; # Disables HTTP 1.1 keep-alive and forces round-robin.
}
# This block handles tags endpoint requests, for which we want to restrict traffic due to how
# heavy an operation it can be
location ~ /v2/([^/]+)\/[^/]+/tags/ {
# If we're being accessed via v1.quay.io, pretend we don't support v2.
if ($host = "v1.quay.io") {
return 404;
}
# Setting ANY header clears all inherited proxy_set_header directives
proxy_set_header X-Forwarded-For $proper_forwarded_for;
proxy_set_header X-Forwarded-Proto $proper_scheme;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_pass http://registry_app_server;
set $namespace $1;
{% if enable_rate_limits %}
limit_req zone=namespaced_dynamicauth_heavy_http1 burst=2 nodelay;
limit_req zone=namespaced_dynamicauth_heavy_http2 burst=2 nodelay;
{% endif %}
keepalive_timeout 0; # Disables HTTP 1.1 keep-alive and forces round-robin.
}
# This block handles manifests endpoint requests, for which we want to restrict traffic heavier than
# the generic V2 operations, as it handles pushes and pulls.
location ~ /v2/([^/]+)\/[^/]+/manifests/ {
# If we're being accessed via v1.quay.io, pretend we don't support v2.
if ($host = "v1.quay.io") {
return 404;
}
# Setting ANY header clears all inherited proxy_set_header directives
proxy_set_header X-Forwarded-For $proper_forwarded_for;
proxy_set_header X-Forwarded-Proto $proper_scheme;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_pass http://registry_app_server;
set $namespace $1;
{% if enable_rate_limits %}
limit_req zone=namespaced_dynamicauth_light_http1 burst=10 nodelay;
limit_req zone=namespaced_dynamicauth_light_http2 burst=50 nodelay;
{% endif %}
keepalive_timeout 0; # Disables HTTP 1.1 keep-alive and forces round-robin.
}
# This block applies to the beginning of a push or pull
location = /v2/auth {
# If we're being accessed via v1.quay.io, pretend we don't support v2.
if ($host = "v1.quay.io") {
return 404;
}
# Setting ANY header clears all inherited proxy_set_header directives
proxy_set_header X-Forwarded-For $proper_forwarded_for;
proxy_set_header X-Forwarded-Proto $proper_scheme;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_pass http://registry_app_server;
{% if enable_rate_limits %}
limit_req zone=staticauth burst=2 nodelay;
{% endif %}
keepalive_timeout 0; # Disables HTTP 1.1 keep-alive and forces round-robin.
}
# This block handles all other V2 requests, for which we can use a higher rate limit.
location ~ ^/v2 {
# If we're being accessed via v1.quay.io, pretend we don't support v2.
if ($host = "v1.quay.io") {
return 404;
}
# NOTE: We disable gzip for HEAD requests because Docker issues them to determine the Content
# Length of a blob. Unfortunately, nginx, seeing an empty body, overwrites the header with
# a length of 0, which breaks this functionality. Included here for completeness.
if ($request_method = HEAD) {
gzip off;
}
# Setting ANY header clears all inherited proxy_set_header directives
proxy_set_header X-Forwarded-For $proper_forwarded_for;
proxy_set_header X-Forwarded-Proto $proper_scheme;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_pass http://registry_app_server;
{% if enable_rate_limits %}
limit_req zone=dynamicauth_very_light_http1 burst=20 nodelay;
limit_req zone=dynamicauth_very_light_http2 burst=80 nodelay;
{% endif %}
keepalive_timeout 0; # Disables HTTP 1.1 keep-alive and forces round-robin.
}
location /v1/ {
# Setting ANY header clears all inherited proxy_set_header directives
proxy_set_header X-Forwarded-For $proper_forwarded_for;
proxy_set_header X-Forwarded-Proto $proper_scheme;
proxy_set_header Host $host;
proxy_buffering off;
proxy_request_buffering off;
proxy_http_version 1.1;
proxy_pass http://registry_app_server;
proxy_temp_path /tmp 1 2;
client_max_body_size {{ maximum_layer_size }};
{% if enable_rate_limits %}
limit_req zone=dynamicauth_heavy_http1 burst=5 nodelay;
limit_req zone=dynamicauth_heavy_http2 burst=25 nodelay;
{% endif %}
keepalive_timeout 0; # Disables HTTP 1.1 keep-alive and forces round-robin.
}
location = /v1/_ping {
add_header Content-Type text/plain;
add_header X-Docker-Registry-Version 0.6.0;
add_header X-Docker-Registry-Standalone 0;
return 200 'true';
}
location /c1/ {
proxy_buffering off;
proxy_request_buffering off;
proxy_pass http://verbs_app_server;
proxy_temp_path /tmp 1 2;
{% if enable_rate_limits %}
limit_req zone=staticauth burst=5 nodelay;
{% endif %}
}
location /static/ {
# checks for static file, if not found proxy to app
alias {{static_dir}}/;
error_page 404 /404;
}
error_page 502 {{static_dir}}/502.html;
location ~ ^/b1/controller(/?)(.*) {
proxy_pass http://build_manager_controller_server/$2;
}
location ~ ^/b1/socket(/?)(.*) {
proxy_pass http://build_manager_websocket_server/$2;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300;
}