diff --git a/includes/cache.conf b/includes/cache.conf deleted file mode 100644 index 037854a5e3..0000000000 --- a/includes/cache.conf +++ /dev/null @@ -1,92 +0,0 @@ -# web app -location / { - add_header Cache-Control "no-store, no-cache, public, must-revalidate, proxy-revalidate, max-age=0"; - add_header Pragma "no-cache"; - etag off; - if_modified_since off; - expires -1; - ## Security - ## Always HTTPS - add_header Strict-Transport-Security "max-age=31449600; includeSubDomains" always; # 1 year - ## Don't open in Iframe - add_header X-Frame-Options "DENY" always; - ## No content type autodiscovery - add_header X-Content-Type-Options "nosniff" always; - ## Don't disclose full url when navigating to links - add_header Referrer-Policy "strict-origin" always; - ## New Header for features - ## https://www.w3.org/TR/permissions-policy-1/ - add_header Permissions-Policy "microphone=(); geolocation=(self); camera=()" always; - ## CSP - ## TODO: WHEN GOING PROD CHANGE TO Content-Security-Policy - add_header Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline' fonts.googleapis.com *.fontawesome.com; font-src fonts.gstatic.com *.fontawesome.com; script-src 'self'; script-src-elem 'self'; base-uri 'self'; img-src https://* 'self' data:; trusted-types angular; require-trusted-types-for 'script'" always; -} - -location ~* \.(?:css|js)$ { - add_header Cache-Control "public, max-age=2628000"; # 1 month - ## Security - ## Always HTTPS - add_header Strict-Transport-Security "max-age=31449600; includeSubDomains" always; # 1 year - ## Don't open in Iframe - add_header X-Frame-Options "DENY" always; - ## No content type autodiscovery - add_header X-Content-Type-Options "nosniff" always; - ## Don't disclose full url when navigating to links - add_header Referrer-Policy "strict-origin" always; - ## New Header for features - ## https://www.w3.org/TR/permissions-policy-1/ - add_header Permissions-Policy "microphone=(); geolocation=(self); camera=()" always; - ## CSP - ## TODO: WHEN GOING PROD CHANGE TO Content-Security-Policy - add_header Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline' fonts.googleapis.com; font-src fonts.gstatic.com; script-src 'self'; script-src-elem 'self'; base-uri 'self'; img-src https://* 'self' data:; trusted-types angular; require-trusted-types-for 'script'" always; -} - -# TODO: Should we cache JSON files in assets? -location ~* \.(?:jpg|jpeg|gif|png|ico|xml|webp|json)$ { - add_header Cache-Control "public, max-age=86400"; # 1 day - ## Security - ## Always HTTPS - add_header Strict-Transport-Security "max-age=31449600; includeSubDomains" always; # 1 year - ## Don't open in Iframe - add_header X-Frame-Options "DENY" always; - ## No content type autodiscovery - add_header X-Content-Type-Options "nosniff" always; - ## Don't disclose full url when navigating to links - add_header Referrer-Policy "strict-origin" always; - ## New Header for features - ## https://www.w3.org/TR/permissions-policy-1/ - add_header Permissions-Policy "microphone=(); geolocation=(self); camera=()" always; - ## CSP - ## TODO: WHEN GOING PROD CHANGE TO Content-Security-Policy - add_header Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline' fonts.googleapis.com; font-src fonts.gstatic.com; script-src 'self'; script-src-elem 'self'; base-uri 'self'; img-src https://* 'self' data:; trusted-types angular; require-trusted-types-for 'script'" always; -} - -location ~* \.(?:eot|woff|woff2|ttf|svg|otf) { - add_header Cache-Control "public, max-age=2628000"; # 1 month - - # TODO: Allow CORS requests for fonts? - add_header Access-Control-Allow-Origin *; - - types {font/opentype otf;} - types {application/vnd.ms-fontobject eot;} - types {font/truetype ttf;} - types {application/font-woff woff;} - types {font/x-woff woff2;} - types {image/svg+xml svg svgz;} - - ## Security - ## Always HTTPS - add_header Strict-Transport-Security "max-age=31449600; includeSubDomains" always; # 1 year - ## Don't open in Iframe - add_header X-Frame-Options "DENY" always; - ## No content type autodiscovery - add_header X-Content-Type-Options "nosniff" always; - ## Don't disclose full url when navigating to links - add_header Referrer-Policy "strict-origin" always; - ## New Header for features - ## https://www.w3.org/TR/permissions-policy-1/ - add_header Permissions-Policy "microphone=(); geolocation=(self); camera=()" always; - ## CSP - ## TODO: WHEN GOING PROD CHANGE TO Content-Security-Policy - add_header Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline' fonts.googleapis.com; font-src fonts.gstatic.com; script-src 'self'; script-src-elem 'self'; base-uri 'self'; img-src https://* 'self' data:; trusted-types angular; require-trusted-types-for 'script'" always; -} \ No newline at end of file diff --git a/includes/security.conf b/includes/security.conf new file mode 100644 index 0000000000..45729f2e8d --- /dev/null +++ b/includes/security.conf @@ -0,0 +1,15 @@ +## Security +## Always HTTPS +add_header Strict-Transport-Security "max-age=31449600; includeSubDomains" always; # 1 year +## Don't open in Iframe +add_header X-Frame-Options "DENY" always; +## No content type autodiscovery +add_header X-Content-Type-Options "nosniff" always; +## Don't disclose full url when navigating to links +add_header Referrer-Policy "strict-origin" always; +## New Header for features +## https://www.w3.org/TR/permissions-policy-1/ +add_header Permissions-Policy "microphone=(); geolocation=(self); camera=()" always; +## CSP +## TODO: WHEN GOING PROD CHANGE TO Content-Security-Policy +add_header Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline' fonts.googleapis.com *.fontawesome.com; font-src fonts.gstatic.com *.fontawesome.com; script-src 'self'; script-src-elem 'self'; base-uri 'self'; img-src https://* 'self' data:; trusted-types angular; require-trusted-types-for 'script'" always; \ No newline at end of file diff --git a/nginx.conf b/nginx.conf index 8f745be7e0..73e890812e 100644 --- a/nginx.conf +++ b/nginx.conf @@ -77,26 +77,32 @@ http { # Directory where static files are located root {{ env "APP_ROOT" }}/dist/out-of-school; - location / { - # If HTTP request is made, redirect to HTTPS requests - set $updated_host $host; - if ($http_x_forwarded_host != "") { - set $updated_host $http_x_forwarded_host; - } + # If HTTP request is made, redirect to HTTPS requests + set $updated_host $host; + if ($http_x_forwarded_host != "") { + set $updated_host $http_x_forwarded_host; + } - if ($http_x_forwarded_proto != "https") { - return 301 https://$updated_host$request_uri; - } + if ($http_x_forwarded_proto != "https") { + return 301 https://$updated_host$request_uri; + } + + location / { # Send the content at / in response to *any* requested endpoint if (!-e $request_filename) { rewrite ^(.*)$ / break; } - # Specify files sent to client if specific file not requested (e.g. # GET www.example.com/). NGINX sends first existing file in the list. - index index.html index.htm Default.htm; + index index.html; + + add_header Cache-Control "no-store, no-cache, public, must-revalidate, proxy-revalidate, max-age=0"; + add_header Pragma "no-cache"; + etag off; + if_modified_since off; + expires -1; - include {{ env "APP_ROOT" }}/includes/*.conf; + include {{ env "APP_ROOT" }}/includes/security.conf; } # (Security) Don't serve dotfiles, except .well-known/, which is needed by @@ -105,5 +111,43 @@ http { deny all; return 404; } + + location ~* \.(?:json)$ { + add_header Cache-Control "no-store, no-cache, public, must-revalidate, proxy-revalidate, max-age=0"; + add_header Pragma "no-cache"; + etag off; + if_modified_since off; + expires -1; + + include {{ env "APP_ROOT" }}/includes/security.conf; + } + + location ~* \.(?:css|js)$ { + add_header Cache-Control "public, max-age=2628000"; # 1 month + + include {{ env "APP_ROOT" }}/includes/security.conf; + } + + location ~* \.(?:jpg|jpeg|gif|png|ico|xml|webp|svg)$ { + add_header Cache-Control "public, max-age=86400"; # 1 day + + include {{ env "APP_ROOT" }}/includes/security.conf; + } + + location ~* \.(?:eot|woff|woff2|ttf|otf) { + add_header Cache-Control "public, max-age=2628000"; # 1 month + + # TODO: Allow CORS requests for fonts? + add_header Access-Control-Allow-Origin *; + + types {font/opentype otf;} + types {application/vnd.ms-fontobject eot;} + types {font/truetype ttf;} + types {application/font-woff woff;} + types {font/x-woff woff2;} + types {image/svg+xml svg svgz;} + + include {{ env "APP_ROOT" }}/includes/security.conf; + } } } \ No newline at end of file