Reputation: 1125
I'm trying to make my django app work behind SSL, using nginx, gunicorn; all installed in a server that can be accessed in intranet but not from outside. These are my settings.
settings.py:
...
SECURITY_MIDDLEWARE = ('django.middleware.security.SecurityMiddleware',)
MIDDLEWARE_CLASSES = SECURITY_MIDDLEWARE + MIDDLEWARE_CLASSES
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
X_FRAME_OPTIONS = 'SAMEORIGIN'
SECURE_HSTS_SECONDS = 60
SECURE_BROWSER_XSS_FILTER = True
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
nginx.conf:
server {
listen 80;
server_name HOSTNAME;
location / {
proxy_set_header Host $host;
proxy_pass http://unix:/tmp/HOSTNAME.socket;
proxy_set_header X-Forwarded-Protocol $scheme;
rewrite ^ https://$host/$request_uri permanent;
}
}
Wondering if someone can point me to the correct solution.
Upvotes: 2
Views: 2111
Reputation: 1125
disclaimer: I'm new to web development. I'm also the author of the question.
edit: In /var/log/nginx/HOSTNAME_error.log I was getting the following error:
no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking
Based on Steve's answer, this question (see comment for link), and this blog, I finally made my app to work behind SSL.
I created an SSL certificate and key using the following command (unexperienced users like me shall note that these certificates are self-signed, therefore browsers classify the connection as insecure. However transactions are correctly encrypted. For more information on the command see the blog):
dzdo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
Changed my nginx.conf to (since I'm using DjangoWhiteNoise, my nginx conf doesn't handle static neither media files):
server {
listen 80;
server_name HOSTNAME;
rewrite ^/(.*) https://HOST/$1 permanent;
}
server {
listen 443 ssl;
server_name HOSTNAME;
access_log /var/log/nginx/HOSTNAME_access.log combined;
error_log /var/log/nginx/HOSTNAME_error.log error;
# To create an SSL certificate:
# dzdo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
location / {
proxy_pass http://unix:/tmp/HOST.socket;
proxy_redirect off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Finally, I set my Django security settings to:
...
SECURITY_MIDDLEWARE = ('django.middleware.security.SecurityMiddleware',)
MIDDLEWARE_CLASSES = SECURITY_MIDDLEWARE + MIDDLEWARE_CLASSES
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
X_FRAME_OPTIONS = 'SAMEORIGIN'
SECURE_HSTS_SECONDS = 60
SECURE_BROWSER_XSS_FILTER = True
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
Hope this can help folks like me.
Upvotes: 2
Reputation: 12195
Just in case, have you tried setting ALLOWED_HOSTS
, too?
Also, reading this from the docs:
If turning this to True causes infinite redirects, it probably means your site is running behind a proxy and can’t tell which requests are secure and which are not. Your proxy likely sets a header to indicate secure requests; you can correct the problem by finding out what that header is and configuring the SECURE_PROXY_SSL_HEADER setting accordingly.
then looking at what you have there in your nginx conf:
listen 80
...
proxy_set_header X-Forwarded-Protocol $scheme;
Are you sure that $scheme
is https
and not http
? You're listening on port 80, not port 443 and your SECURE_PROXY_SSL_HEADER
setting looks like it's expecting https
when it may be getting a unsecured http request forwarded.
Just a guess, looking at the configs.
Upvotes: 1