Reverse Proxy Headers

When running Bugsink behind a reverse proxy, you need to configure the reverse proxy to forward requests to Bugsink. This guide will help you configure the right headers and settings for your reverse proxy; it does not cover the more general setup of a reverse proxy.

Our recommended reverse proxy is Nginx; if you want something that JustWorks™, that might be the best choice. However, if you’re using a different reverse proxy, you can still use this guide to configure it correctly.

We further assume that if you’re using a reverse proxy, you’re also using HTTPS. Because you should be using HTTPS, and if you’re going to the trouble of setting up a reverse proxy, you might as well use HTTPS.

The Headers

  • Host: set this header to the original host. (In Nginx, you can use $host.) Bugsink uses the Host header to determine the domain of the request. If you don’t set this header, Bugsink will complain that some other host (typically localhost, or the IP address of the server) is not in ALLOWED_HOSTS.

  • X-Forwarded-Proto: set this header to the original scheme. (In Nginx, you can use $scheme.) If you’re only serving HTTPS, you can also simply set this header to the string https. This directive corresponds to the setting "SECURE_PROXY_SSL_HEADER" in your bugsink_conf.py file. If you don’t set this header, Bugsink will not be able to determine whether the current request is secure or not. This can lead to problems with the CSRF protection, i.e. the message "(wrong scheme); fix your proxy's X-Forwarded-Proto".

  • X-Real-IP: set this header to the client’s IP address. (In Nginx, you can use $remote_addr) This allows Bugsink to know the IP address of the client. Set USE_X_REAL_IP to True in your bugsink_conf.py file to let Bugsink know where to find the client’s IP address.

Alternative: X-Forwarded-For Header

The X-Forwarded-For header is an alternative to the X-Real-IP header. This is not recommended, but it is supported.

The header should contain a list of IP addresses, with the client’s IP address being the first one. If you’re using multiple proxies, each proxy should append its IP address to the list. (In Nginx, you can use proxy_add_x_forwarded_for.)

In Bugsink, set USE_X_FORWARDED_FOR to True and X_FORWARDED_FOR_PROXY_COUNT to the number of proxies that are in front of Bugsink.

Setting the count explicitly is necessary because the X-Forwarded-For header is a list of IP addresses, and proxies typically simply add to this list rather than override the value. As such, any spoofed values will be present in this list. If the number of proxies is known, Bugsink can detect this.

The fact that two settings are required (and that these must be set correctly) is why we recommend using the X-Real-IP. However, X-Forwarded-For is supported for those who need it.

Nginx Configuration

Here is a partial Nginx configuration file that sets the required headers and settings:

# Set the Host header to the original host. Note: we don't
# use X-Forwarded-Host here, so there is no need to set
# USE_X_FORWARDED_HOST to True in the configuration file.
proxy_set_header Host $host;

# Because the server is behind a proxy, it needs to know
# the original IP address of the client. The below directive
# passes this info in the X-Real-IP header. This is picked up by
# Bugsink when USE_X_REAL_IP is set to True in the configuration
# file.
proxy_set_header X-Real-IP $remote_addr;

# Alternative, more brittle way to do the same (see docs):
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# Set the X-Forwarded-Proto header to the original scheme;
# because Django/Bugsink is behind a proxy, it needs to
# know the original scheme to know whether the current
# request is secure or not. This directive corresponds to
# the setting "SECURE_PROXY_SSL_HEADER" in your bugsink_conf.py
# file.
proxy_set_header X-Forwarded-Proto $scheme;

# Set up HSTS with a long max-age (1 year) and the
# "preload" directive, which tells browsers to include
# your site in their HSTS preload list. This means that
# browsers will only connect to your site over HTTPS, even
# if the user types in the URL without the "https://"
# prefix.
add_header Strict-Transport-Security "max-age=31536000; preload" always;

A full Nginx configuration file can be found in our single-server production installation guide.