🐳 Harden Nginx security headers

Signed-off-by: Francis Santiago <francis.santiago@kaleidos.net>
This commit is contained in:
Francis Santiago 2026-05-06 20:06:35 +02:00
parent e07ad9cb53
commit 50df7cb5c4
3 changed files with 43 additions and 0 deletions

View File

@ -10,6 +10,8 @@
### :bug: Bugs fixed
- Harden Nginx responses with standard security headers and hide upstream `X-Powered-By` headers
## 2.16.0 (Unreleased)
### :boom: Breaking changes & Deprecations

View File

@ -74,6 +74,11 @@ http {
resolver 127.0.0.11 ipv6=off;
etag off;
proxy_hide_header X-Powered-By;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-Frame-Options SAMEORIGIN always;
root /home/penpot/penpot/frontend/resources/public;
@ -211,6 +216,10 @@ http {
proxy_set_header User-Agent "curl/8.5.0";
proxy_set_header Host "raw.githubusercontent.com";
proxy_set_header Accept "*/*";
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-Frame-Options SAMEORIGIN always;
add_header Access-Control-Allow-Origin $http_origin;
proxy_buffering off;
}
@ -235,6 +244,10 @@ http {
proxy_cache penpot;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-Frame-Options SAMEORIGIN always;
add_header Access-Control-Allow-Origin $http_origin;
add_header Cache-Control max-age=86400;
add_header X-Cache-Status $upstream_cache_status;
@ -257,16 +270,28 @@ http {
proxy_cache penpot;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-Frame-Options SAMEORIGIN always;
add_header Access-Control-Allow-Origin $http_origin;
add_header Cache-Control max-age=86400;
add_header X-Cache-Status $upstream_cache_status;
}
location ~* \.(jpg|png|svg|ttf|woff|woff2|gif)$ {
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-Frame-Options SAMEORIGIN always;
add_header Cache-Control "public, max-age=604800" always; # 7 days
}
location ~* \.(js|css|wasm)$ {
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-Frame-Options SAMEORIGIN always;
add_header Cache-Control "no-store" always;
}
@ -274,6 +299,10 @@ http {
return 301 " /404";
}
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-Frame-Options SAMEORIGIN always;
add_header Cache-Control "no-store" always;
try_files $uri /index.html$is_args$args /index.html =404;
}

View File

@ -80,6 +80,11 @@ http {
charset utf-8;
etag off;
proxy_hide_header X-Powered-By;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-Frame-Options SAMEORIGIN always;
root /var/www/app/;
@ -177,6 +182,10 @@ http {
include /etc/nginx/overrides/location.d/*.conf;
location ~* \.(js|css|jpg|png|svg|gif|ttf|woff|woff2|wasm|map)$ {
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-Frame-Options SAMEORIGIN always;
add_header Cache-Control "public, max-age=604800" always; # 7 days
}
@ -184,6 +193,9 @@ http {
return 301 " /404";
}
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-Frame-Options SAMEORIGIN always;
add_header Cache-Control "no-store, no-cache, max-age=0" always;
try_files $uri /index.html$is_args$args /index.html =404;