7 Critical Django Production Server Settings to Configure Before Going Live

Django production server settings

Hey there! Some links on this page may be affiliate links which means that, if you choose to make a purchase, I may earn a small commission at no extra cost to you. I greatly appreciate your support!

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.


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.

YouTube video

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: 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_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.

YouTube video

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).

YouTube video

Please let me know if you have any questions about configuring your Django server for production and website for public release.


Meet Tony

Tony from Tony Teaches Tech headshot

With a strong software engineering background, Tony is determined to demystify the web. Discover why Tony quit his job to pursue this mission. You can join the Tony Teaches Tech community here.

One Response

  1. 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.

Leave a Reply

Your email address will not be published. Required fields are marked *