# The IP address (typically localhost) and port that the NetBox WSGI process should listen on
bind = '127.0.0.1:8001'

# Number of gunicorn workers to spawn. This should typically be 2n+1, where
# n is the number of CPU cores present.
workers = 5

# Number of threads per worker process
threads = 3

# Timeout (in seconds) for a request to complete
timeout = 120

# The maximum number of requests a worker can handle before being respawned
max_requests = 5000
max_requests_jitter = 500

contrib/gunicorn.py
# The IP address (typically localhost) and port that the NetBox WSGI process should listen on
bind = '127.0.0.1:8001'

# Number of gunicorn workers to spawn. This should typically be 2n+1, where
# n is the number of CPU cores present.
workers = 5

# Number of threads per worker process
threads = 3

# Timeout (in seconds) for a request to complete
timeout = 120

# The maximum number of requests a worker can handle before being respawned
max_requests = 5000
max_requests_jitter = 500

# Uncomment this line to accept HTTP headers containing underscores, e.g. for remote
# authentication support. See https://docs.gunicorn.org/en/stable/settings.html#header-map
# header-map = 'dangerous'

contrib/gunicorn.py
diff --git a/contrib/gunicorn.py b/contrib/gunicorn.py
index 89d6943b494..4b2b7c6b053 100644
--- a/contrib/gunicorn.py
+++ b/contrib/gunicorn.py
@@ -14,3 +14,7 @@
 # The maximum number of requests a worker can handle before being respawned
 max_requests = 5000
 max_requests_jitter = 500
+
+# Uncomment this line to accept HTTP headers containing underscores, e.g. for remote
+# authentication support. See https://docs.gunicorn.org/en/stable/settings.html#header-map
+# header-map = 'dangerous'
diff --git a/docs/administration/authentication/overview.md b/docs/administration/authentication/overview.md
index f81a50c0b88..0c8858b2ff5 100644
--- a/docs/administration/authentication/overview.md
+++ b/docs/administration/authentication/overview.md
@@ -26,7 +26,10 @@ REMOTE_AUTH_BACKEND = 'netbox.authentication.RemoteUserBackend'
 
 Another option for remote authentication in NetBox is to enable HTTP header-based user assignment. The front end HTTP server (e.g. nginx or Apache) performs client authentication as a process external to NetBox, and passes information about the authenticated user via HTTP headers. By default, the user is assigned via the `REMOTE_USER` header, but this can be customized via the `REMOTE_AUTH_HEADER` configuration parameter.
 
-Optionally, user profile information can be supplied by `REMOTE_USER_FIRST_NAME`, `REMOTE_USER_LAST_NAME` and `REMOTE_USER_EMAIL` headers. These are saved to the users profile during the authentication process. These headers can be customized like the `REMOTE_USER` header.
+Optionally, user profile information can be supplied by `REMOTE_USER_FIRST_NAME`, `REMOTE_USER_LAST_NAME` and `REMOTE_USER_EMAIL` headers. These are saved to the user's profile during the authentication process. These headers can be customized like the `REMOTE_USER` header.
+
+!!! warning Verify Header Compatibility
+    Some WSGI servers may drop headers which contain unsupported characters. For instance, gunicorn v22.0 and later silently drops HTTP headers containing underscores. This behavior can be disabled by changing gunicorn's [`header_map`](https://docs.gunicorn.org/en/stable/settings.html#header-map) setting to `dangerous`.
 
 ### Single Sign-On (SSO)
 
diff --git a/docs/configuration/remote-authentication.md b/docs/configuration/remote-authentication.md
index e7fe56a095e..5f28d987f0a 100644
--- a/docs/configuration/remote-authentication.md
+++ b/docs/configuration/remote-authentication.md
@@ -85,6 +85,9 @@ Default: `'HTTP_REMOTE_USER'`
 
 When remote user authentication is in use, this is the name of the HTTP header which informs NetBox of the currently authenticated user. For example, to use the request header `X-Remote-User` it needs to be set to `HTTP_X_REMOTE_USER`. (Requires `REMOTE_AUTH_ENABLED`.)
 
+!!! warning Verify Header Compatibility
+    Some WSGI servers may drop headers which contain unsupported characters. For instance, gunicorn v22.0 and later silently drops HTTP headers containing underscores. This behavior can be disabled by changing gunicorn's [`header_map`](https://docs.gunicorn.org/en/stable/settings.html#header-map) setting to `dangerous`.
+
 ---
 
 ## REMOTE_AUTH_USER_EMAIL

OpenIDC SSO through apache stopped working after update to 3.7.6
### Deployment Type

Self-hosted

### NetBox Version

v3.7.6

### Python Version

3.9

### Steps to Reproduce

This is a longstanding NetBox instance. It runs under gunicorn, proxied through apache which is configured to use mod_auth_openid for authentication. 

NetBox's configuration includes:
REMOTE_AUTH_ENABLED = True
REMOTE_AUTH_BACKEND = 'netbox.authentication.RemoteUserBackend'
REMOTE_AUTH_HEADER = 'HTTP_OIDC_CLAIM_PREFERRED_USERNAME'
REMOTE_AUTH_AUTO_CREATE_USER = True

This was working fine until the update to 3.7.6 following our usual procedure:

Pull and checkout v3.7.6.

Run upgrade.sh

Restart NetBox gunicorn service, netbox-rq and apache

Since the upgrade, NetBox has presented a login box instead of logging in as the REMOTE_AUTH_HEADER user. Using tcpdump, I can see the "OIDC_CLAIM_preferred_username" header is being sent to gunicorn. Other instances using the same OpenIDC configuration are working.


### Expected Behavior

REMOTE_AUTH login using OpenIDC credentials.

### Observed Behavior

The web frontend prompts for username and password.
