diff --git a/Dockerfile b/Dockerfile index 1c8621a..63c9e5d 100755 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,11 @@ ENV VAR_PREFIX=/var/run \ CACHE_PREFIX=/var/cache \ CONF_PREFIX=/etc/nginx \ CERTS_PREFIX=/etc/pki/tls \ - NGINX_DOCROOT=/usr/share/nginx/html + NGINX_DOCROOT=/usr/share/nginx/html \ + GEOIP_PREFIX=/usr/share/geoip + +# Set working directory to NGINX_DOCROOT +WORKDIR ${NGINX_DOCROOT} # Create www-data user and group RUN if ! getent group www-data >/dev/null; then \ @@ -170,7 +174,7 @@ ENV CONFIG="\ --with-http_v3_module \ --add-module=/tmp/ngx_cache_purge-${NGX_CACHE_PURGE_VERSION} \ --add-module=/tmp/ngx_http_redis-${NGX_REDIS_VERSION} \ - --add-module=/tmp/ngx_http_geoip2_module \ + --add-dynamic-module=/tmp/ngx_http_geoip2_module \ --add-module=/tmp/redis2-nginx-module-${NGX_REDIS2_VERSION} \ --add-module=/tmp/srcache-nginx-module-${NGX_SRCACHE_VERSION} \ --add-module=/tmp/echo-nginx-module \ @@ -195,6 +199,9 @@ RUN cd /usr/src/nginx-$NGINX_VERSION \ RUN mkdir -p ${CERTS_PREFIX} \ && openssl dhparam -out ${CERTS_PREFIX}/dhparam.pem.default 4096 +# Create GeoIP directory +RUN mkdir -p ${GEOIP_PREFIX} + # Cleanup RUN apk del .build-deps \ && rm -rf /tmp/* \ @@ -215,7 +222,8 @@ ENV VAR_PREFIX=/var/run \ CACHE_PREFIX=/var/cache \ CONF_PREFIX=/etc/nginx \ CERTS_PREFIX=/etc/pki/tls \ - NGINX_DOCROOT=/usr/share/nginx/html + NGINX_DOCROOT=/usr/share/nginx/html \ + GEOIP_PREFIX=/usr/share/geoip # Create www-data user RUN if ! getent group www-data >/dev/null; then \ @@ -249,6 +257,7 @@ COPY --from=builder /usr/lib/nginx /usr/lib/nginx COPY --from=builder /usr/share/nginx /usr/share/nginx COPY --from=builder /etc/nginx /etc/nginx COPY --from=builder ${CERTS_PREFIX} ${CERTS_PREFIX} +COPY --from=builder ${GEOIP_PREFIX} ${GEOIP_PREFIX} # Create necessary directories and symlinks RUN mkdir -p ${LOG_PREFIX} \ @@ -265,8 +274,12 @@ COPY conf/ /conf COPY error/ ${NGINX_DOCROOT}/error COPY docker-entrypoint.sh /docker-entrypoint.sh +# Copy GeoIP databases +COPY geoip/*.mmdb ${GEOIP_PREFIX}/ + # Set permissions -RUN chmod +x /docker-entrypoint.sh +RUN chmod +x /docker-entrypoint.sh \ + && chown -R www-data:www-data ${GEOIP_PREFIX} # Set stop signal STOPSIGNAL SIGQUIT diff --git a/README.md b/README.md index dc7366f..e3a0da9 100755 --- a/README.md +++ b/README.md @@ -34,23 +34,14 @@ The first step is to build or pull the image: ### Build ```docker -docker build --build-arg "NGINX_VERSION=1.15.5" -t openbridge/nginx . +docker build --build-arg "NGINX_VERSION=1.27.4" -t openbridge/nginx . ``` -Replace `NGINX_VERSION=1.17.0` with your preferred version. You can also simply `pull` the images. See below. +Replace `NGINX_VERSION=1.27.4` with your preferred version. You can also simply `pull` the images. See below. ### Pull ```docker docker pull openbridge/nginx:latest ``` -You can also use a different version of NGINX simply by pulling a build with the NGINX version you want. For example; -```docker -docker pull openbridge/nginx:latest -docker pull openbridge/nginx:1.15.4 -docker pull openbridge/nginx:1.15.3 -``` -To see the available versions vist https://hub.docker.com/r/openbridge/nginx/tags/ - - ## Running Via Docker compose @@ -491,53 +482,6 @@ This allows you to connect to `https://localhost/testing/test_info.php` to verif Noe: Using PHP assumes you have configured a PHP backend to test anything PHP related -# Monitoring -Services in the container are monitored via Monit. One thing to note is that if Monit detects a problem with Nginx it will issue a `STOP` command. This will shutdown your container because the image uses `CMD ["nginx", "-g", "daemon off;"]`. If you are using `--restart unless-stopped` in your docker run command the server will automatically restart. - -Here is an example monitoring config: -```nginx -check process nginx with pidfile "/var/run/nginx.pid" - if not exist for 5 cycles then restart - start program = "/usr/bin/env bash -c '/usr/sbin/nginx -g daemon off'" with timeout 60 seconds - stop program = "/usr/bin/env bash -c '/usr/sbin/nginx -s stop'" - every 3 cycles - if cpu > 80% for 10 cycles then exec "/usr/bin/env bash -c '/usr/sbin/nginx -s stop'" - -check program wwwdata-permissions with path /usr/bin/env bash -c "check_wwwdata permission" - every 3 cycles - if status != 0 then exec "/usr/bin/env bash -c 'find {{NGINX_DOCROOT}} -type d -exec chmod 755 {} \; && find {{NGINX_DOCROOT}} -type f -exec chmod 644 {} \;'" - -check directory cache-permissions with path {{CACHE_PREFIX}} - every 3 cycles - if failed permission 755 then exec "/usr/bin/env bash -c 'find {{CACHE_PREFIX}} -type d -exec chmod 755 {} \;'" - -check directory cache-owner with path {{CACHE_PREFIX}} - every 3 cycles - if failed uid www-data then exec "/usr/bin/env bash -c 'find {{CACHE_PREFIX}} -type d -exec chown www-data:www-data {} \; && find {{CACHE_PREFIX}} -type f -exec chown www-data:www-data {} \;'" - -check file letsencrypt_certificate with path /etc/letsencrypt/live/{{NGINX_SERVER_NAME}}/fullchain.pem - if changed checksum then exec "/usr/bin/env bash -c '/usr/sbin/nginx -s reload'" - -check host {{NGINX_SERVER_NAME}} with address {{NGINX_SERVER_NAME}} - if failed host {{NGINX_SERVER_NAME}} port 80 protocol http - and request "/health-check" - with timeout 25 seconds - for 3 times within 4 cycles - then exec "/usr/bin/env bash -c '/usr/sbin/nginx -s reload'" - if failed host {{NGINX_SERVER_NAME}} port 443 protocol https - request "/health-check" - status = 200 - content = "healthy" - with timeout 25 seconds - for 3 times within 4 cycles - then exec "/usr/bin/env bash -c '/usr/sbin/nginx -s reload'" - if failed port 8080 for 3 cycles then exec "/usr/bin/env bash -c '/usr/sbin/nginx -s stop'" - -check program cache-size with path /usr/bin/env bash -c "check_folder {{CACHE_PREFIX}} 500" - every 20 cycles - if status != 0 then exec "/usr/bin/env bash -c 'rm -Rf /var/cache/*'" -``` - The `check_folder`, `check_host` and `check_wwwdata` scripts provide additional health check utility of make sure that permissions, cache size and host respond correctly. For example, `check_host` will validate that SPA rendering service is properly serving the expected content. This can help detect if there are issues where certain user-agents that can not render SPA are being served the incorrect content. This can wreak havoc with your SEO if a pre-render service is not working as expected. Best to catch it as early as possible so you can mitigate any issues. # Content Delivery Network If you want to activate CDN for assets like images, you can set your location to redirect those requests to your CDN: diff --git a/conf/php/nginx/conf.d/brotli.conf b/conf/php/nginx/conf.d/brotli.conf index 41f4e61..a3f1775 100644 --- a/conf/php/nginx/conf.d/brotli.conf +++ b/conf/php/nginx/conf.d/brotli.conf @@ -5,7 +5,8 @@ brotli_static on; # Compression settings brotli_comp_level 5; # Compression level (1-11, higher values provide better compression at the cost of CPU usage) brotli_min_length 256; # Only compress responses larger than 256 bytes -brotli_buffers 8 8k; # Number and size of buffers used for compression +brotli_buffers 16 8k; # Increased number of buffers for better handling of concurrent requests +brotli_window 512k; # Explicitly set window size (default is 512k) # Specify MIME types for Brotli compression, grouped by category @@ -42,10 +43,15 @@ brotli_types # Text types text/cache-manifest + text/calendar text/css + text/html + text/javascript + text/markdown text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component - text/x-cross-domain-policy; + text/x-cross-domain-policy + text/xml; diff --git a/conf/php/nginx/conf.d/geo.conf b/conf/php/nginx/conf.d/geo.conf new file mode 100644 index 0000000..a2c7f3f --- /dev/null +++ b/conf/php/nginx/conf.d/geo.conf @@ -0,0 +1,24 @@ +# GeoIP2 database settings for HTTP context +geoip2 /usr/share/geoip/GeoLite2-Country.mmdb { + auto_reload 5m; + $geoip2_metadata_country_build metadata build_epoch; + $geoip2_data_country_code default=- country iso_code; + $geoip2_data_country_name default=- country names en; +} + +geoip2 /usr/share/geoip/GeoLite2-City.mmdb { + auto_reload 5m; + $geoip2_metadata_city_build metadata build_epoch; + $geoip2_data_city_name default=- city names en; + $geoip2_data_region_name default=- subdivisions 0 names en; + $geoip2_data_region_code default=- subdivisions 0 iso_code; + $geoip2_data_postal_code default=- postal code; + $geoip2_data_latitude default=- location latitude; + $geoip2_data_longitude default=- location longitude; +} + +geoip2 /usr/share/geoip/GeoLite2-ASN.mmdb { + auto_reload 5m; + $geoip2_data_asn default=- autonomous_system_number; + $geoip2_data_asn_org default=- autonomous_system_organization; +} \ No newline at end of file diff --git a/conf/php/nginx/conf.d/gzip.conf b/conf/php/nginx/conf.d/gzip.conf index ecd05fb..e1faf7c 100644 --- a/conf/php/nginx/conf.d/gzip.conf +++ b/conf/php/nginx/conf.d/gzip.conf @@ -2,9 +2,9 @@ gzip on; # Compression settings -gzip_comp_level 7; # Compression level (1-9); 7 is a good balance of speed and compression +gzip_comp_level 6; # Slightly reduced from 7 for better CPU balance gzip_min_length 256; # Only compress responses larger than 256 bytes -gzip_buffers 8 4k; # Number and size of buffers for compression +gzip_buffers 16 8k; # Increased buffer size for better performance gzip_http_version 1.1; # Only compress responses for HTTP/1.1 and above # Specify MIME types for gzip compression, grouped by category @@ -20,9 +20,11 @@ gzip_types application/rss+xml application/vnd.ms-fontobject application/wasm + application/x-javascript application/x-web-app-manifest+json application/xhtml+xml application/xml + application/octet-stream # Font types (include these if your fonts are not already compressed) font/eot @@ -36,11 +38,13 @@ gzip_types image/bmp image/svg+xml image/webp + image/x-icon # Text types text/cache-manifest text/calendar text/css + text/html # Added critical text/html MIME type text/javascript text/markdown text/plain @@ -54,4 +58,5 @@ gzip_types # Additional gzip settings gzip_vary on; # Enable Vary header for proxies and clients gzip_proxied any; # Enable compression for all proxied requests -gzip_disable "MSIE [1-6]\.(?!.*SV1)"; # Disable gzip for old versions of Internet Explorer +gzip_static on; # Serve pre-compressed .gz files if available +gzip_disable "MSIE [1-6]\.(?!.*SV1)"; # Disable gzip for old versions of Internet Explorer \ No newline at end of file diff --git a/conf/php/nginx/conf.d/secure.conf b/conf/php/nginx/conf.d/secure.conf index 3c5fb3a..f9106a9 100644 --- a/conf/php/nginx/conf.d/secure.conf +++ b/conf/php/nginx/conf.d/secure.conf @@ -21,75 +21,82 @@ location ^~ /.well-known/acme-challenge/ { allow all; } -############################################## -# WordPress Specific Allowances -############################################## - -# WordPress REST API - must be defined early to ensure valid API calls are handled correctly -location /wp-json/ { - try_files $uri $uri/ /index.php$is_args$args; -} - -# Allow wp-includes assets (CSS, JS, images, etc.) -location ~* ^/wp-includes/.*\.(js|css|png|jpg|jpeg|gif|ico)$ { - allow all; -} - -############################################## -# Blocking Sensitive Files & Directories -############################################## - -# Block sensitive WordPress configuration files -location ~* ^/(wp-config\.php|wp-config-sample\.php)$ { - return 403; -} - -# Block sensitive system files -location ~* ^/(boot\.ini|etc/passwd|self/environ)$ { - return 403; -} -# Block hidden files and repository directories -# Exclude /wp-admin and /wp-json to avoid blocking legitimate admin/API requests -location ~* ^/(\..*|Entries.*|Repository|Root|Tag|Template|wp-content/uploads/nginx-helper/)$ { - if ($request_uri !~* ^/(wp-admin|wp-json)) { +# # # WordPress Admin Area Access Control +location ~ ^/wp-admin($|/) { + # Check if the user is allowed based on geo location + if ($wp_admin_allowed = 0) { return 403; } -} - -# Block PHP execution in uploads and similar directories -location ~* ^/(wp-content/uploads|wp-content/uploads/sucuri|wp-content/updraft)/.*\.php$ { - return 403; -} -############################################## -# Blocking Malicious Patterns -############################################## + # Regular WordPress handling + try_files $uri $uri/ /index.php$is_args$args; -# Block potentially malicious patterns (e.g. eval(), phpinfo, etc.) -# Exempt /wp-json requests to ensure valid REST API calls aren’t blocked -location ~* (&pws=0|_vti_|\(null\)|(eval\\(|self/environ|mobiquo|phpinfo|shell\.php|sqlpatch|webshell\.php)) { - if ($request_uri !~* ^/wp-json/) { - return 403; + # PHP processing + location ~ \.php$ { + fastcgi_pass php-fpm; + include /etc/nginx/fastcgi.d/fastcgi.conf; } } -# Block SQL injection attempts -# Exempt /wp-json requests so legitimate API calls aren’t affected -location ~* (drop[^-]|insert|md5|select|union|=%27|/'/?) { - if ($request_uri !~* ^/wp-json/) { +# # Also protect wp-login.php +location = /wp-login.php { + # Check if the user is allowed based on geo location + if ($wp_admin_allowed = 0) { return 403; } -} - -############################################## -# Blocking Dangerous File Extensions -############################################## -# Block access to files with dangerous extensions -# Exclude /wp-admin and /wp-json to avoid interfering with valid backend/API functionality -location ~* \.(bak|conf|dist|fla|in[ci]|log|psd|sh|sql|sw[op]|engine|inc|info|install|make|module|profile|test|po|.*sql|tpl\.php|php_|pl|cgi|py|lua|asp|jsp)$ { - if ($request_uri !~* ^/(wp-admin|wp-json)) { - return 403; - } + # PHP processing + fastcgi_pass php-fpm; + include /etc/nginx/fastcgi.d/fastcgi.conf; +} + +location = /geoip-test { + add_header Content-Type text/plain; + return 200 "Remote Address: $remote_addr\n +IP Detection:\n +- X-Forwarded-For: $http_x_forwarded_for\n +- X-Real-IP: $http_x_real_ip\n +\n +GeoIP Information:\n +- Country Code: $geoip2_data_country_code\n +- Country Name: $geoip2_data_country_name\n +- City Name: $geoip2_data_city_name\n +- Region Name: $geoip2_data_region_name\n +- Region Code: $geoip2_data_region_code\n +- Postal Code: $geoip2_data_postal_code\n +- Latitude: $geoip2_data_latitude\n +- Longitude: $geoip2_data_longitude\n +- ASN: $geoip2_data_asn\n +- ASN Org: $geoip2_data_asn_org\n +\n +GeoIP Database Info:\n +- Country DB Build Epoch: $geoip2_metadata_country_build\n +- City DB Build Epoch: $geoip2_metadata_city_build\n"; } + +# Also add a JSON version for programmatic testing +location = /geoip-test.json { + add_header Content-Type application/json; + return 200 '{ + "remote_addr": "$remote_addr", + "x_forwarded_for": "$http_x_forwarded_for", + "x_real_ip": "$http_x_real_ip", + "geoip2": { + "country_code": "$geoip2_data_country_code", + "country_name": "$geoip2_data_country_name", + "city_name": "$geoip2_data_city_name", + "region_name": "$geoip2_data_region_name", + "region_code": "$geoip2_data_region_code", + "postal_code": "$geoip2_data_postal_code", + "latitude": "$geoip2_data_latitude", + "longitude": "$geoip2_data_longitude", + "asn": "$geoip2_data_asn", + "asn_org": "$geoip2_data_asn_org" + }, + "database_info": { + "country_build": "$geoip2_metadata_country_build", + "city_build": "$geoip2_metadata_city_build" + } + }'; +} \ No newline at end of file diff --git a/conf/php/nginx/conf.d/ssl.conf b/conf/php/nginx/conf.d/ssl.conf index 4021f3d..e267144 100644 --- a/conf/php/nginx/conf.d/ssl.conf +++ b/conf/php/nginx/conf.d/ssl.conf @@ -12,11 +12,8 @@ ssl_trusted_certificate /etc/letsencrypt/live/{{NGINX_SERVER_NAME}}/chain.pem; ssl_protocols TLSv1.2 TLSv1.3; # Specify strong ciphers; the order is important for prioritizing secure algorithms -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:\ -ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:\ -ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; +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'; + ssl_prefer_server_ciphers on; # Use modern elliptic curves for ECDH key exchange @@ -29,6 +26,18 @@ ssl_session_cache shared:SSL:50m; ssl_session_timeout 30m; ssl_session_tickets off; +############################################## +# HTTP/3 Specific Settings +############################################## +# These settings help optimize TLS for HTTP/3 +ssl_early_data on; # Enable 0-RTT for faster reconnections +quic_retry on; # Enable QUIC retry packets for DoS prevention +quic_gso on; # Enable Generic Segmentation Offload if available +ssl_reject_handshake off; # Allow HTTP/3 connection attempts even if SNI doesn't match + +# Set specific QUIC settings for transport parameters +http3_stream_buffer_size 2048; + ############################################## # Diffie-Hellman Parameters ############################################## diff --git a/conf/php/nginx/conf.d/zstd.conf b/conf/php/nginx/conf.d/zstd.conf new file mode 100644 index 0000000..743ceaa --- /dev/null +++ b/conf/php/nginx/conf.d/zstd.conf @@ -0,0 +1,57 @@ +# Enable ZSTD compression +zstd on; +zstd_static on; # Serve pre-compressed .zst files if available + +# Compression settings +zstd_comp_level 5; # Compression level (1-22, higher values provide better compression at the cost of CPU usage) +zstd_min_length 256; # Only compress responses larger than 256 bytes +zstd_buffers 16 8k; # Number and size of buffers used for compression + +# Specify MIME types for ZSTD compression, grouped by category +zstd_types + # Application types + application/atom+xml + application/javascript + application/json + application/ld+json + application/manifest+json + application/rss+xml + application/vnd.geo+json + application/vnd.ms-fontobject + application/x-font-ttf + application/x-javascript + application/x-web-app-manifest+json + application/xhtml+xml + application/xml + application/wasm + application/octet-stream + + # Font types + font/eot + font/opentype + font/otf + font/ttf + font/woff + font/woff2 + + # Image types + image/avif + image/bmp + image/svg+xml + image/webp + image/x-icon + + # Text types + text/cache-manifest + text/calendar + text/css + text/html + text/javascript + text/markdown + text/plain + text/vcard + text/vnd.rim.location.xloc + text/vtt + text/x-component + text/x-cross-domain-policy + text/xml; \ No newline at end of file diff --git a/conf/php/nginx/fastcgi.d/fastcgi.conf b/conf/php/nginx/fastcgi.d/fastcgi.conf index a3a1698..24bce59 100644 --- a/conf/php/nginx/fastcgi.d/fastcgi.conf +++ b/conf/php/nginx/fastcgi.d/fastcgi.conf @@ -75,3 +75,22 @@ fastcgi_param SERVER_NAME $server_name; # (Required if PHP was built with --enable-force-cgi-redirect) fastcgi_param REDIRECT_STATUS 200; fastcgi_param HTTP_AUTHORIZATION $http_authorization; + + +# Country information +fastcgi_param GEOIP2_DATA_COUNTRY_CODE $geoip2_data_country_code; +fastcgi_param GEOIP2_DATA_COUNTRY_NAME $geoip2_data_country_name; +fastcgi_param GEOIP2_METADATA_COUNTRY_BUILD $geoip2_metadata_country_build; + +# City information +fastcgi_param GEOIP2_DATA_CITY_NAME $geoip2_data_city_name; +fastcgi_param GEOIP2_DATA_REGION_NAME $geoip2_data_region_name; +fastcgi_param GEOIP2_DATA_REGION_CODE $geoip2_data_region_code; +fastcgi_param GEOIP2_DATA_POSTAL_CODE $geoip2_data_postal_code; +fastcgi_param GEOIP2_DATA_LATITUDE $geoip2_data_latitude; +fastcgi_param GEOIP2_DATA_LONGITUDE $geoip2_data_longitude; +fastcgi_param GEOIP2_METADATA_CITY_BUILD $geoip2_metadata_city_build; + +# ASN information +fastcgi_param GEOIP2_DATA_ASN $geoip2_data_asn; +fastcgi_param GEOIP2_DATA_ASN_ORG $geoip2_data_asn_org; \ No newline at end of file diff --git a/conf/php/nginx/header.d/httpd.conf b/conf/php/nginx/header.d/httpd.conf index 024d685..9dade62 100644 --- a/conf/php/nginx/header.d/httpd.conf +++ b/conf/php/nginx/header.d/httpd.conf @@ -6,6 +6,7 @@ add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; # Note: This header is deprecated in some modern browsers. add_header X-UA-Compatible "IE=Edge" always; # Only needed for legacy IE support +add_header Content-Security-Policy "object-src 'none'; base-uri 'self'; upgrade-insecure-requests;" always; ############################################## # Custom & Caching Headers @@ -17,6 +18,6 @@ add_header X-Robots-Tag "$noindex" always; # Additional Security Headers ############################################## add_header Referrer-Policy "strict-origin-when-cross-origin" always; -add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; +add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()" always; add_header Cross-Origin-Opener-Policy "same-origin" always; add_header Cross-Origin-Resource-Policy "same-origin" always; diff --git a/conf/php/nginx/header.d/proxy.conf b/conf/php/nginx/header.d/proxy.conf index 7db1427..2dcc37e 100644 --- a/conf/php/nginx/header.d/proxy.conf +++ b/conf/php/nginx/header.d/proxy.conf @@ -2,8 +2,8 @@ # Standard Proxy Headers ############################################## 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-Real-IP $http_x_forwarded_for; +proxy_set_header X-Forwarded-For $http_x_forwarded_for; proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port; proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl; diff --git a/conf/php/nginx/map.d/geo/access.map b/conf/php/nginx/map.d/geo/access.map new file mode 100644 index 0000000..1e2c00c --- /dev/null +++ b/conf/php/nginx/map.d/geo/access.map @@ -0,0 +1,38 @@ +# First, ensure GeoIP2 variables are defined +# Add this to the http context of your nginx.conf or in conf.d/geoip2.conf + +# Check if the GeoIP2 region is either MA or NY +map $geoip2_data_region_code $region_ok { + default 0; + "MA" 1; + "NY" 1; +} + +# Check if the GeoIP2 country is US +map $geoip2_data_country_code $country_ok { + default 0; + "US" 1; +} + +# Combine the geo checks: allowed only if both pass ("11") +map "$region_ok$country_ok" $geo_allowed { + default 0; + "11" 1; +} + +# Add this before your final map for $wp_admin_allowed +map $remote_addr $ip_whitelist { + default 0; + 127.0.0.1 1; # Local access + 192.168.0.0/16 1; # Your office IP + 173.48.114.33 1; # Your office IP + # Add more IPs as needed +} + +# Final decision: allow access if the client is from an allowed IP or passes geo checks +map "$ip_whitelist$geo_allowed" $wp_admin_allowed { + default 0; + "10" 1; # Allowed by IP whitelist (first digit is 1) + "01" 1; # Allowed by geo (second digit is 1) + "11" 1; # Allowed by both +} \ No newline at end of file diff --git a/conf/php/nginx/nginx.conf b/conf/php/nginx/nginx.conf index c3c672b..4b98cbc 100755 --- a/conf/php/nginx/nginx.conf +++ b/conf/php/nginx/nginx.conf @@ -5,6 +5,9 @@ timer_resolution 100ms; pcre_jit on; thread_pool default threads=32 max_queue=65536; +load_module "/usr/lib/nginx/modules/ngx_http_geoip2_module.so"; +load_module "/usr/lib/nginx/modules/ngx_stream_geoip2_module.so"; + events { worker_connections 65535; multi_accept on; @@ -18,6 +21,20 @@ http { charset UTF-8; etag on; + # Replace with your Docker network CIDR if needed + set_real_ip_from 172.0.0.0/8; + set_real_ip_from 192.168.0.0/16; + set_real_ip_from 10.0.0.0/8; + set_real_ip_from 127.0.0.1; + set_real_ip_from ::1; + + # Define which header to use for real IP (choose one) + real_ip_header X-Forwarded-For; + # real_ip_header X-Real-IP; + + # Process the last IP in X-Forwarded-For as the client IP + real_ip_recursive off; + # File transfer and connection tuning sendfile on; # Enable sendfile for performance sendfile_max_chunk 512k; @@ -83,10 +100,16 @@ http { '"upstream_status": "$upstream_status", ' '"upstream_response_time": "$upstream_response_time", ' '"upstream_response_length": "$upstream_response_length", ' - '"upstream_cache_status": "$upstream_cache_status" } }'; + '"upstream_cache_status": "$upstream_cache_status", ' + '"geoip2_country_code": "$geoip2_data_country_code", ' + '"geoip2_country_name": "$geoip2_data_country_name", ' + '"geoip2_city_name": "$geoip2_data_city_name", ' + '"geoip2_region_name": "$geoip2_data_region_name", ' + '"geoip2_latitude": "$geoip2_data_latitude", ' + '"geoip2_longitude": "$geoip2_data_longitude" } }'; access_log {{LOG_PREFIX}}/access.log main_ext; - error_log {{LOG_PREFIX}}/access.log debug; # Use a higher level (e.g. warn) in production + error_log {{LOG_PREFIX}}/access.log warn; # Use a higher level (e.g. warn) in production # DNS Resolver Settings resolver 1.1.1.1 8.8.8.8 8.8.4.4 valid=300s; @@ -120,6 +143,7 @@ http { proxy_cache_key $scheme$request_method$host$request_uri$is_args$args; # Global Purge Control + include /etc/nginx/conf.d/geo.conf; geo $purge_allowed { include /etc/nginx/geo.d/purge.conf; } # Global Expiration Settings and Index Files @@ -129,10 +153,15 @@ http { # Include global modules for compression and security include /etc/nginx/conf.d/brotli.conf; include /etc/nginx/conf.d/gzip.conf; + include /etc/nginx/conf.d/zstd.conf; include /etc/nginx/conf.d/proxy.conf; include /etc/nginx/conf.d/botblocker-nginx-settings.conf; include /etc/nginx/conf.d/globalblacklist.conf; + include /etc/nginx/map.d/geo/access.map; # Include available sites (vhosts) include /etc/nginx/sites-available/*; + + + } diff --git a/conf/php/nginx/sites-available/default.vhost b/conf/php/nginx/sites-available/default.vhost index e41c1fb..7d8bab0 100644 --- a/conf/php/nginx/sites-available/default.vhost +++ b/conf/php/nginx/sites-available/default.vhost @@ -17,7 +17,13 @@ server { server_name {{NGINX_SERVER_NAME}} www.{{NGINX_SERVER_NAME}} *.{{NGINX_SERVER_NAME}}; listen *:443 default_server ssl; listen [::]:443 default_server ssl reuseport; + listen *:443 quic; + listen [::]:443 quic reuseport; http2 on; + http3 on; + + # Add HTTP/3 advertisement + add_header Alt-Svc 'h3=":443"; ma=86400'; # Domain-specific document root root {{NGINX_DOCROOT}}; @@ -46,6 +52,9 @@ server { # Include CDN settings (if used only by this site) include /etc/nginx/conf.d/cdn.conf; + # Include SEO configuration + include /etc/nginx/conf.d/seo.conf; + # Main Location Block - Proxy all Requests to the Upstream 'proxy' location / { proxy_pass http://proxy/; @@ -75,4 +84,4 @@ server { include /etc/nginx/conf.d/location.conf; include /etc/nginx/redis.d/location.conf; -} +} \ No newline at end of file diff --git a/geoip/GeoIP.dat b/geoip/GeoIP.dat deleted file mode 100644 index be8b031..0000000 Binary files a/geoip/GeoIP.dat and /dev/null differ diff --git a/geoip/GeoIP.dat.gz b/geoip/GeoIP.dat.gz deleted file mode 100644 index aa47eeb..0000000 Binary files a/geoip/GeoIP.dat.gz and /dev/null differ diff --git a/geoip/GeoLite2-ASN.mmdb b/geoip/GeoLite2-ASN.mmdb new file mode 100644 index 0000000..620fd8f Binary files /dev/null and b/geoip/GeoLite2-ASN.mmdb differ diff --git a/geoip/GeoLite2-City.mmdb b/geoip/GeoLite2-City.mmdb new file mode 100644 index 0000000..9c8beb7 Binary files /dev/null and b/geoip/GeoLite2-City.mmdb differ diff --git a/geoip/GeoLite2-Country.mmdb b/geoip/GeoLite2-Country.mmdb new file mode 100644 index 0000000..1212f58 Binary files /dev/null and b/geoip/GeoLite2-Country.mmdb differ diff --git a/geoip/GeoLiteCity.dat b/geoip/GeoLiteCity.dat deleted file mode 100644 index 1adb8c3..0000000 Binary files a/geoip/GeoLiteCity.dat and /dev/null differ diff --git a/geoip/GeoLiteCity.dat.gz b/geoip/GeoLiteCity.dat.gz deleted file mode 100644 index 2487499..0000000 Binary files a/geoip/GeoLiteCity.dat.gz and /dev/null differ