Duplication of various settings between Nginx and django

Hello,

I know this is a noob question but I cannot find guidance. I created a blog as a learning exercise for
django and python. It is live deployed now using the (seemingly classic!) Nginx, Gunicorn and Django stack. My question is around various security settings which seemingly can be made either at both Nginx level or django level. Because of this, the response header is showing duplicates with mismatches where they do not align.

Whilst it does not appear as an issue in itself( website responds and renders all fine ), I was wondering what is best practice/the norm? Is there a hierarchy of priority e.g. make the setting in Nginx if you can otherwise apply it in django? Or is it normal to make the same settings in all layers where it is available?

Example live response header below - note the doubling up of referrer-policy and a couple of others:


content-encoding: gzip
content-security-policy: default-src 'self' http: https: data: blob: 'unsafe-inline'; frame-ancestors 'self';
content-type: text/html; charset=utf-8
cross-origin-opener-policy: same-origin
date: Mon, 11 Apr 2022 12:08:04 GMT
permissions-policy: interest-cohort=()
referrer-policy: same-origin
referrer-policy: same-origin
server: nginx
strict-transport-security: max-age=3600
strict-transport-security: max-age=31536000; includeSubDomains
vary: Accept-Encoding
x-content-type-options: nosniff
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 1; mode=block

I’m ignoring Gunicorn for time being even though some of the same setting are available there as as well.

I’m not aware of any truly “global” best practices defined in this area, but I can tell you what we do.
We use a stack consisting of haproxy, nginx, uwsgi, and Django. We handle custom headers on a case-by-case basis depending upon where they need to be set, using the basic principle of applying headers as late as possible. That means that if an entire haproxy host should have a certain header applied, it’s applied in haproxy, if a site needs a header, we configure it in nginx, and similarly down through uwsgi and Django. (We only have a small handful of headers that we need to do this with. For example, haproxy serves as our ssl endpoint. Everything done behind it is done through http, not https. So haproxy is responsible for any headers associated with ssl.)