While Django is great for quickly developing a website with Python, there are a few settings that you must configure before considering your server ready for production.
In this tutorial, you’ll learn some of these critical production settings for Django that you should implement before going live with your website.
Before you start:
- In this tutorial, the Django project is named microdomains and the app is named udoms. Please change these values accordingly.
- Check out my tutorial on setting up Django with uWSGI on Nginx to understand the server stack that I’m working with.
1. Hide the Secret Key
Although the secret key is hardcoded in the settings.py
file when you use django-admin
to start a Django project, this must be removed before going to production for security reasons.
Instead of hardcoding the SECRET_KEY
:
... # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '2oo2r0y7nafm3cy&6nz=rf=7j@(_szusbj4ktdjgn_zfq1x948' ...
read it from a file like this:
... # SECURITY WARNING: keep the secret key used in production secret! with open(os.path.join(BASE_DIR, 'secret_key.txt')) as f: SECRET_KEY = f.read().strip() ...
Of course, you must also create the file called secret_key.txt
in the root of your project or somewhere else on your server.
2oo2r0y7nafm3cy&6nz=rf=7j@(_szusbj4ktdjgn_zfq1x948
2. Install an SSL Certificate for HTTPS
It is critical nowadays that your website has an SSL certificate, even if it doesn’t touch any sensitive data. An SSL certificate allows your Django website’s traffic to be encrypted and sent over HTTPS.
You can install an SSL certificate for Django websites running on an Apache or Nginx server. Check out this video tutorial for how to get a free SSL certificate from Let’s Encrypt with Certbot.
If you are running Django on OpenLiteSpeed, check out this video for how to install an SSL certificate.
3. Django HTTPS Settings
With an SSL certificate installed on your web server, you’ll want to configure a few Django settings for security.
Add the following lines to your settings.py
file:
# HTTPS settings SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True SECURE_SSL_REDIRECT = True
- SESSION_COOKIE_SECURE: ensures a secure session cookie is used
- CSRF_COOKIE_SECURE: ensures a secure CSRF cookie is used
- SECURE_SSL_REDIRECT: all non-HTTP requests are redirect to HTTPS
These settings allow Django to take advantage of the HTTPS protocol.
4. Django HSTS Settings
Similar to above, you’ll also want to configure a few HTTP Strict Transport Security (HSTS) settings for Django. HSTS essentially instructs browsers to refuse to connect to your domain with an insecure connection.
Add the following lines to your settings.py
file:
# HSTS settings SECURE_HSTS_SECONDS = 31536000 # 1 year SECURE_HSTS_PRELOAD = True SECURE_HSTS_INCLUDE_SUBDOMAINS = True
- SECURE_HSTS_SECONDS: prevents browsers from connecting to your website with an insecure connection for the specified duration in seconds
- SECURE_HSTS_PRELOAD: the preload directive is added to the HSTS header
- SECURE_HSTS_INCLUDE_SUBDOMAINS: the includeSubDomains directive is added to the HSTS header
Even if you don’t have a subdomain, it’s a good idea to include all of these HSTS settings.
5. Only Serve Your Domain Name
In order to prevent HTTP host header attacks, you should explicitly specify which domain names that Django can serve.
Set the ALLOWED_HOSTS
variable in your settings.py
file to your domain name:
... ALLOWED_HOSTS = ['micro.domains', 'www.micro.domains'] ...
As you can see, ALLOWED_HOSTS
accepts a list of domain name where you can specify the www and non-www version of your website.
6. Turn Off Debug Mode
Debug mode in Django is super useful for development purposes; however, it has no place being turned on in a production server.
Set the DEBUG
variable in your settings.py
file to False:
# SECURITY WARNING: don't run with debug turned on in production! DEBUG = False
7. Copy Static Files
When using runserver
during development, Django will serve static files (images, CSS, JS) for you. This is inefficient and your web server is better at it.
In production, all of your static files must exist in a directory i.e. STATIC_ROOT and your web server should serve them to the public i.e. STATIC_URL.
Set these values in your settings.py
file:
# Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.1/howto/static-files/ STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, "static/")
Django has a management command that will copy all of your static files into your STATIC_ROOT.
python manage.py collectstatic
Just make sure your web server is configured to serve these files. If you are using Nginx, your conf file (probably in /etc/nginx/sites-available/
) will look something like this:
... location /static { alias /home/udoms/microdomains/static; #Django project's static files } ...
If you need more help with this, see my tutorial on how to set up Django on Nginx.
Automated Django Deployment Check
You can verify that your Django website is ready for production:
python manage.py check --deploy
While this check is not comprehensive, if you see the following output, you are “ready for production”:
System check identified no issues (0 silenced).
Please let me know if you have any questions about configuring your Django server for production and website for public release.
2 Responses
I followed through your How to Deploy Django on Nginx with uWSGI (full tutorial) and got communications working with HTTP. However when I use https and apply the https settings in this document I don’t get anything back from my curl command which is now using https. Do you have any pointers? The allowed hosts has the domain name and https://domain name.
Hi Tony, An excellent tutorial. Thank you for for taking the time to put this up. Very helpful.