sharenet/registry/nginx.conf
continuist f607d93d21
Some checks are pending
CI/CD Pipeline (Fully Isolated DinD) / Run Tests (DinD) (push) Waiting to run
CI/CD Pipeline (Fully Isolated DinD) / Build and Push Docker Images (DinD) (push) Blocked by required conditions
CI/CD Pipeline (Fully Isolated DinD) / Deploy to Production (push) Blocked by required conditions
Changes to podman config for running outside home folder
2025-08-23 23:07:29 -04:00

220 lines
7.2 KiB
Nginx Configuration File

# Docker Registry v2 Nginx Configuration with Enhanced Security
# Port 443: Unauthenticated pulls (GET requests only)
# Port 4443: Authenticated operations (login, logout, push, delete, etc.)
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
# Rate limiting with different zones for different operations
limit_req_zone $binary_remote_addr zone=registry:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=push:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=2r/s;
# Connection limiting
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
# Upstream Docker Registry
upstream registry {
server localhost:5000;
keepalive 32;
# Health check
keepalive_requests 100;
keepalive_timeout 60s;
}
# HTTP server for unauthenticated pulls on port 443
server {
listen 443 ssl http2;
server_name _;
# Connection limits
limit_conn conn_limit_per_ip 10;
# SSL Configuration - TLS 1.2/1.3 only with modern ciphers
ssl_certificate /etc/registry/certs/registry.crt;
ssl_certificate_key /etc/registry/certs/private/registry.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
# Security headers with HSTS
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'none'; frame-ancestors 'none';" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
# Client max body size for large image uploads
client_max_body_size 2G;
client_body_timeout 60s;
client_header_timeout 60s;
# Rate limiting for read operations
limit_req zone=registry burst=20 nodelay;
# Block all write operations explicitly
if ($request_method !~ ^(GET|HEAD)$) {
return 405 "Method Not Allowed";
}
# Block suspicious user agents
if ($http_user_agent ~* (bot|crawler|spider|scraper)) {
return 403 "Forbidden";
}
# Allow all GET requests to v2 API (Docker Registry itself will handle security)
location /v2/ {
proxy_pass http://registry;
proxy_set_header Host $http_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 $scheme;
proxy_read_timeout 900;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_buffering off;
proxy_request_buffering off;
# Additional security headers for registry
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
}
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
# Block access to hidden files
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Block access to sensitive files
location ~* \.(htaccess|htpasswd|ini|log|sh|sql|conf)$ {
deny all;
access_log off;
log_not_found off;
}
location / {
return 404;
}
access_log /var/log/nginx/registry_access.log;
error_log /var/log/nginx/registry_error.log;
}
# HTTPS server for authenticated operations on port 4443
server {
listen 4443 ssl http2;
server_name _;
# Connection limits
limit_conn conn_limit_per_ip 5;
# SSL Configuration - TLS 1.2/1.3 only with modern ciphers
ssl_certificate /etc/registry/certs/registry.crt;
ssl_certificate_key /etc/registry/certs/private/registry.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
# Security headers with HSTS
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'none'; frame-ancestors 'none';" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
# Client max body size for large image uploads
client_max_body_size 2G;
client_body_timeout 60s;
client_header_timeout 60s;
# Rate limiting for write operations
limit_req zone=push burst=10 nodelay;
# Rate limiting for login attempts
location ~ ^/v2/.*/blobs/uploads/ {
limit_req zone=login burst=3 nodelay;
auth_basic "Docker Registry v2";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://registry;
proxy_set_header Host $http_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 $scheme;
proxy_read_timeout 900;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_buffering off;
proxy_request_buffering off;
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
}
# Basic authentication for write operations
location ~ ^/v2/.*$ {
# Require auth for all v2 API operations
auth_basic "Docker Registry v2";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://registry;
proxy_set_header Host $http_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 $scheme;
proxy_read_timeout 900;
proxy_connect_timeout 60;
proxy_send_timeout 60;
proxy_buffering off;
proxy_request_buffering off;
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
}
# Block access to hidden files
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Block access to sensitive files
location ~* \.(htaccess|htpasswd|ini|log|sh|sql|conf)$ {
deny all;
access_log off;
log_not_found off;
}
location / {
return 404;
}
access_log /var/log/nginx/registry_auth_access.log;
error_log /var/log/nginx/registry_auth_error.log;
}
}