{"id":16891091,"url":"https://github.com/michyweb/nginx-security-conf","last_synced_at":"2025-03-20T08:19:05.572Z","repository":{"id":199348028,"uuid":"85690506","full_name":"michyweb/nginx-security-conf","owner":"michyweb","description":"Secure Configuration for Nginx","archived":false,"fork":false,"pushed_at":"2022-06-03T11:42:27.000Z","size":18,"stargazers_count":65,"open_issues_count":0,"forks_count":22,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-01-25T09:23:43.855Z","etag":null,"topics":["nginx-configuration","protection","secure-headers","security","security-hardening","ssl"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/michyweb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-03-21T10:49:17.000Z","updated_at":"2025-01-21T15:02:38.000Z","dependencies_parsed_at":null,"dependency_job_id":"2c925b7c-cdb4-49b5-9c12-7a96d78d1ab3","html_url":"https://github.com/michyweb/nginx-security-conf","commit_stats":null,"previous_names":["michyweb/nginx-security-conf"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michyweb%2Fnginx-security-conf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michyweb%2Fnginx-security-conf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michyweb%2Fnginx-security-conf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michyweb%2Fnginx-security-conf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/michyweb","download_url":"https://codeload.github.com/michyweb/nginx-security-conf/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244574845,"owners_count":20474823,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nginx-configuration","protection","secure-headers","security","security-hardening","ssl"],"created_at":"2024-10-13T17:05:35.972Z","updated_at":"2025-03-20T08:19:05.545Z","avatar_url":"https://github.com/michyweb.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# nginx-security-conf\nthe best security conf for nginx\n\n```bash\n# @author: @M1ChyB\t\n# works in nginx/1.13.4 - OpenSSL 1.0.1t \n\t\n# don't send the nginx version number in error pages and Server header\nserver_tokens off;\n\t\n\nserver {\n\tlisten 80;\n\tlisten [::]:80;\n\tserver_name example.com;\n\treturn 301 https://$server_name$request_uri;\n}\n\n\nserver {\n\t# Avoid HTTP/2 downgrading. Instead, use HTTP/2 end to end. https://portswigger.net/research/http2\n\tlisten [::]:443 ssl http2 ipv6only=on default_server;\n    \tlisten 443 ssl http2 default_server;\n\t\n\taccess_log /path/to/site/dir/logs/access.log;\n\terror_log /path/to/site/dir/logs/error.log;\n\t\n\troot /path/to/site/dir/webroot;\n\t# index index.php index.html;\n\tserver_name example.com\n\t\n\t# Directive describes the zone, in which the session states are stored i.e. store in slimits.\n\t# 1m can handle 32000 sessions with 32 bytes/session, set to 5m x 32000 session\n\tlimit_zone slimits $binary_remote_addr 5m;\n\n\t# Control maximum number of simultaneous connections for one session i.e. \n\t# restricts the amount of connections from a single ip address \n\tlimit_conn slimits 5;\n\n\t# buffer policy\n\tclient_body_buffer_size 1K;\n\tclient_header_buffer_size 1k;\n\tclient_max_body_size 1k;\n\tlarge_client_header_buffers 2 1k;\n\n\tssl_certificate /etc/nginx/ssl/star_forgott_com.crt;\n\tssl_certificate_key /etc/nginx/ssl/star_forgott_com.key;\n\t\n\t# enable session resumption to improve https performance\n\t# http://vincent.bernat.im/en/blog/2011-ssl-session-reuse-rfc5077.html\n\tssl_session_timeout 1d;\n\tssl_session_cache shared:SSL:50m;\n\tssl_session_tickets off;\n\t\n\t# to generate your dhparam.pem file, run in the terminal\n\t# openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048\n\t# ssl_dhparam /etc/nginx/ssl/dhparam.pem;\n\t# We don't use DHE with the current cipher suites. \n\t\n\tssl_protocols TLSv1.2 TLSv1.3;\n\tssl_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\";\n\tssl_prefer_server_ciphers on;\n\tssl_ecdh_curve secp384r1;\n\t\n\tresolver 8.8.8.8;\n\t\n\t# OCSP Stapling ---\n\t# fetch OCSP records from URL in ssl_certificate and cache them\n\tssl_stapling on;\n\tssl_stapling_verify on;\n\t## verify chain of trust of OCSP response using Root CA and Intermediate certs\n\tssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;\n\t\n\t# SECURITY HEADERS #\n\t\n\t# HSTS\n\t# Recommended: If the site owner would like their domain to be included in the HSTS preload list https://hstspreload.org/ maintained by Chrome (and used by Firefox and Safari), then use the header below. \n\t# Sending the preload directive from your site can have PERMANENT CONSEQUENCES and prevent users from accessing your site and any of its subdomains if you find you need to switch \n\t# back to HTTP. Please read the details at hstspreload.appspot.com/#removal before sending the header with \"preload\".\n\t# Strict-Transport-Security: max-age=31536000; includeSubDomains; preload\n\t# The `preload` flag indicates the site owner's consent to have their domain preloaded. The site owner still needs to then go and submit the domain to the list.\n\tadd_header Strict-Transport-Security \"max-age=31536000; includeSubdomains; preload\";\n\t\n\t# Httpoxy vulnerability\n\tproxy_set_header Proxy \"\";\n\n\t# Request headers for overwriting\n\tproxy_set_header X-Original-URL \"\";\n\tproxy_set_header X-Rewrite-URL \"\";\n\tproxy_set_header X-Rewrite-URL \"\";\n\tproxy_set_header X-Host \"\";\n\tproxy_set_header X-Forwarded-Server \"\";\n\tproxy_set_header X-HTTP-Host-Override \"\";\n\tproxy_set_header Forwarded \"\";\n\t\n\t# Prevent Information leaks\n\tproxy_hide_header X-Powered-By;\n\tproxy_hide_header Server;\n\tproxy_hide_header X-AspNetMvc-Version;\n\tproxy_hide_header X-AspNet-Version;\n\t\n\t# http://blog.portswigger.net/2017/07/cracking-lens-targeting-https-hidden.html\n\tproxy_set_header clientIPAddress \"\";\n\tproxy_set_header x-forwarded-for \"\";\n\tproxy_set_header client-ip \"\";\n\tproxy_set_header forwarded \"\";\n\tproxy_set_header from  \"\";\n\tproxy_set_header referer \"\";\n\tproxy_set_header x-client-ip \"\";\n\tproxy_set_header x-originating-ip \"\";\n\tproxy_set_header x-wap-profile \"\";\n\t\n\t# http security headers\n\tadd_header X-Content-Type-Options nosniff;\n\tadd_header X-Frame-Options DENY;\n\tadd_header Pragma no-cache;\n\tadd_header Cache-Control no-store;\n\tadd_header X-XSS-Protection \"1; mode=block\";\n\tadd_header Referrer-Policy origin-when-cross-origin;\n\tadd_header X-Permitted-Cross-Domain-Policies none;\n\t\n\t# Add Security cookie flags \n\tproxy_cookie_path ~(.*) \"$1; SameSite=strict; secure; httponly\";\n\t\n\t# nonce!!, upgrade-insecure-requests!!\n\tadd_header Content-Security-Policy \"upgrade-insecure-requests; default-src 'self'; base-uri 'self'; require-sri-for script; script-src 'self' 'unsafe-inline' 'unsafe-eval' 'strict-dynamic' 'nonce-JjECqn6A' http: https:; object-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https: http:; media-src 'none'; frame-src 'self'; font-src 'self'; connect-src 'self' wss:; report-uri https://yourdomain.report-uri.com/r/d/csp/enforce;\"\n\t\n\t# Deprecated\n\t# add_header Public-Key-Pins 'pin-sha256=\"XXXXXXXXXXXXXX\"; pin-sha256=\"YYYYYYYYYYYYYYYYYY\";'; max-age=10000; includeSubDomains;\n\t\n\t\n\tlocation / {\n\t\ttry_files $uri $uri/ /index.php;\n\t}\n\n\tlocation ~ \\.php$ {\n\t\tproxy_set_header X-Real-IP  $remote_addr;\n\t\tproxy_set_header X-Forwarded-For $remote_addr;\n\t\tproxy_set_header Host $host;\n\t\tproxy_pass http://127.0.0.1:8080;\n\t}\n\t\n\t\n\t# MANAGE ERRORS AND AVOID SERVE CERTAIN FILES # \n\t\n\tadd_header Allow \"GET, POST, HEAD\";\n\t## Only allow these request methods ##\n\t## Do not accept DELETE, SEARCH and other methods ##\n\tif ($request_method !~ ^(GET|HEAD|POST)$ ) {\n\t\treturn 444;\n\t}\n\t\n\t# Allow access to the ACME Challenge for Let's Encrypt \u003c- \u003c3\n\tlocation ~ /\\.well-known\\/acme-challenge {\n\t\tallow all;\n\t}\n\t\n\t# Deny all attempts to access hidden files\n\t# such as .htaccess, .htpasswd, .DS_Store (Mac), .git, .etc...\n\tlocation ~ /\\. {\n\t\tdeny all;\n\t}\n\t\n\terror_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 420 422 423 424 426 428 429 431 444 449 450 451 500 501 502 503 504 505 506 507 508 509 510 511 /error.html;\n\tlocation  /error.html {\n\t\tinternal;\n\t}\n\t\n}\n\n```\n\nThanks to:\n\n1. https://mozilla.github.io/server-side-tls/ssl-config-generator/\n2. https://scotthelme.co.uk/\n3. https://report-uri.io/home/tools\n4. https://securityheaders.io/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichyweb%2Fnginx-security-conf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmichyweb%2Fnginx-security-conf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichyweb%2Fnginx-security-conf/lists"}