################################################################################ # Ultra Image Server # A production grade image processing server setup powered by imgproxy and nginx # # Author: Mai Nhut Tan # Copyright: 2021-2024 SHIN Company https://code.shin.company/ # URL: https://shinsenter.github.io/docker-imgproxy/ ################################################################################ # Generated by nginxconfig.io # https://www.digitalocean.com/community/tools/nginx#?domains.0.server.documentRoot=%2Fhome&domains.0.server.wwwSubdomain=true&domains.0.https.forceHttps=false&domains.0.https.hstsPreload=true&domains.0.https.certType=custom&domains.0.https.sslCertificate=%2Fetc%2Fnginx%2Fcerts%2Fserver.crt&domains.0.https.sslCertificateKey=%2Fetc%2Fnginx%2Fcerts%2Fserver.key&domains.0.php.php=false&domains.0.reverseProxy.reverseProxy=true&domains.0.routing.index=index.html&domains.0.routing.fallbackHtml=true&domains.0.logging.accessLog=true&domains.0.logging.errorLog=true&domains.0.restrict.getMethod=true&domains.0.restrict.headMethod=true&global.https.portReuse=true&global.https.ocspCloudflareType=both&global.https.ocspGoogleType=both&global.https.ocspOpenDns=false&global.https.ocspOpenDnsType=both&global.https.ocspQuad9Type=both&global.https.ocspVerisignType=both&global.https.letsEncryptCertRoot=%2Fetc%2Fnginx%2Fcerts%2Fletsencrypt%2Flive%2F&global.security.limitReq=true&global.reverseProxy.proxyConnectTimeout=10&global.reverseProxy.proxySendTimeout=30&global.reverseProxy.proxyReadTimeout=30&global.performance.assetsExpiration=max&global.performance.mediaExpiration=30d&global.performance.svgExpiration=max&global.performance.fontsExpiration=max&global.logging.logNotFound=true&global.logging.cloudflare=true&global.logging.trueClientIp=true&global.logging.cfIpCountry=true&global.logging.cdnLoop=true&global.nginx.user=nginx&global.nginx.pid=%2Fvar%2Frun%2Fnginx.pid&global.nginx.clientMaxBodySize=1&global.nginx.typesHashMaxSize=4096&global.nginx.typesHashBucketSize=1024&global.docker.dockerfile=true&global.docker.dockerCompose=true&global.tools.modularizedStructure=false&global.tools.symlinkVhost=false user nginx; pid /var/run/nginx.pid; worker_processes auto; worker_rlimit_nofile 65535; # Load modules include /etc/nginx/modules-enabled/*.conf; events { multi_accept on; worker_connections 65535; } http { charset utf-8; sendfile on; tcp_nopush on; tcp_nodelay on; server_tokens off; types_hash_max_size 4096; types_hash_bucket_size 1024; client_max_body_size 1M; recursive_error_pages on; # MIME include mime.types; default_type application/octet-stream; # Log Format log_format cloudflare '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" "$http_user_agent" ' '"$upstream_cache_status" "$imgproxy_rewrite" ' '$http_cf_ray $http_cf_connecting_ip $http_true_client_ip ' '$http_cf_ipcountry $http_cdn_loop'; # Logging access_log /var/log/nginx/access.log cloudflare; error_log /var/log/nginx/error.log error; # Limits limit_req_log_level warn; limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m; # SSL Session ssl_session_timeout 1d; ssl_session_cache shared:SSL:32m; ssl_session_tickets off; # Diffie-Hellman parameter for DHE ciphersuites ssl_dhparam /etc/nginx/dhparam.pem; # Mozilla Intermediate configuration 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; # OCSP Stapling ssl_stapling off; ssl_stapling_verify off; resolver_timeout 10s; resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] 8.8.8.8 8.8.4.4 [2001:4860:4860::8888] [2001:4860:4860::8844] valid=60s; ## Get file URI from non-normalized $request_uri map $request_uri $file_uri { default '$request_uri'; ~^(?.*)\?.*$ '$parsed_path'; } # Connection header for WebSocket reverse proxy map $http_upgrade $connection_upgrade { default upgrade; "" close; } map $remote_addr $proxy_forwarded_elem { # IPv4 addresses can be sent as-is ~^[0-9.]+$ "for=$remote_addr"; # IPv6 addresses need to be bracketed and quoted ~^[0-9A-Fa-f:.]+$ "for=\"[$remote_addr]\""; # Unix domain socket names cannot be represented in RFC 7239 syntax default "for=unknown"; } map $http_forwarded $proxy_add_forwarded { # If the incoming Forwarded header is syntactically valid, append to it "~^(,[ \\t]*)*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*([ \\t]*,([ \\t]*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*)?)*$" "$http_forwarded, $proxy_forwarded_elem"; # Otherwise, replace it default "$proxy_forwarded_elem"; } # includes other config files, including imgproxy.conf include /etc/nginx/nginx.d/*.conf; # main server server { set $html_root /home; server_name _; root $html_root; index index.html; # HTTP listen 80 reuseport default_server; listen [::]:80 reuseport default_server; # SSL # listen 443 ssl http2 reuseport; # listen [::]:443 ssl http2 reuseport; # ssl_certificate /etc/nginx/certs/server.crt; # ssl_certificate_key /etc/nginx/certs/server.key; # Proxy options proxy_http_version 1.1; proxy_intercept_errors on; proxy_no_cache $arg_nocache; proxy_ssl_verify off; proxy_cache_background_update off; proxy_cache_bypass $http_upgrade $arg_bypass $arg_debug $arg_nocache; proxy_cache_lock on; proxy_cache_lock_age 5s; proxy_cache_lock_timeout 5s; proxy_cache_methods GET HEAD; proxy_cache_min_uses 1; proxy_cache_revalidate on; proxy_cache_valid 200 206 6h; proxy_cache_valid any 1m; proxy_cache_use_stale error timeout invalid_header updating http_429 http_500 http_502 http_503 http_504; # Proxy headers proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Forwarded $proxy_add_forwarded; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; # Proxy timeouts proxy_connect_timeout 10s; proxy_send_timeout 30s; proxy_read_timeout 30s; # security headers add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'; frame-ancestors 'self';" always; add_header Permissions-Policy "interest-cohort=()" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; # gzip gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml; # . files location ~ /\.(?!well-known) { deny all; } # restrict methods if ($request_method !~ ^(GET|HEAD)$) { return '405'; } # favicon.ico location = /favicon.ico { log_not_found off; access_log off; } # robots.txt location = /robots.txt { log_not_found off; access_log off; } # proxy handlers error_page 418 = @imgproxy; error_page 421 = @remote; if ($imgproxy_rewrite) { return 418; } if ($origin_server ~ ^https?://) { return 421; } # error pages error_page 401 403 404 405 422 429 500 501 502 503 504 =404 @fallback; # for imgproxy server location @imgproxy { # fallback to error image and error HTTP status error_page 401 403 404 405 422 429 =404 @fallback; error_page 500 501 502 503 504 =503 @fallback; add_header X-Cache $upstream_cache_status; add_header X-Debug $debug_imgproxy_rewrite always; proxy_cache $imgproxy_cache; proxy_cache_key $imgproxy_rewrite; proxy_pass http://upstream_imgproxy${imgproxy_rewrite}; } # for remote servers location @remote { # fallback to error image and error HTTP status error_page 401 403 404 405 422 429 =404 @fallback; error_page 500 501 502 503 504 =503 @fallback; add_header X-Origin ${origin_server}${origin_uri} always; add_header X-Debug $debug_imgproxy_rewrite always; etag off; proxy_pass ${origin_server}${origin_uri}; } # for fallback location @fallback { internal; etag off; add_header X-Fallback $fallback_uri always; add_header X-Debug $debug_imgproxy_rewrite always; try_files $fallback_uri $fallback_uri/; } # for localhost location / { try_files $origin_uri $uri $uri/ =404; } } }