In this short tutorial, I will demonstrate how to deploy a Django project on Heroku while serving static files from your own domain.
- python (https://www.python.org/downloads/)
- Django (https://docs.djangoproject.com/en/3.2/topics/install/)
- virtualenv (https://virtualenv.pypa.io/en/latest/installation.html)
- pip (https://pip.pypa.io/en/stable/installation/)
- heroku-cli (https://devcenter.heroku.com/articles/heroku-cli)
You do not need to use virtualenv, but it is highly recommended to use an isolated environment for different projects. Another option to virtualenv, for deploying to Heroku, is pipenv.
sudo apt install python3 sudo apt install python3-django sudo apt install python3-virtualenv sudo apt install python3-pip sudo snap install --classic heroku
We can now create our Django project named myproject
django-admin startproject myproject
You now want to go to the root of your project and set up your virtual environment.
Navigate to your project
Make a virtual environment
Activate your virtual environment
Install Django in your virtual environment
pip install django
We now want to create a new Heroku project.
This will create a domain at https://example.herokuapp.com so select the project name to be the domain you want your project to be hosted at. (You can later add a custom domain).
First, we want to change the
SECRET_KEY to an environment variable, because we want to have a unique
SECRET_KEY in production that we don't push to version control.
SECRET_KEY = os.getenv('SECRET_KEY', 'change-in-production')
Now we can set our production environment variable with
heroku config:set SECRET_KEY=very-long-secret-key
We now need to set up static files and turn off DEBUG mode in production.
We are going to use whitenoise to serve static files. First, we need to install it
pip install whitenoise
Next, we add the whitenoise middleware to the top of the middleware section
MIDDLEWARE = [ 'whitenoise.middleware.WhiteNoiseMiddleware', # First in list ... ]
Next, we set up the path of our static files
STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static')
We then install django_heroku to configure default values.
pip install django_heroku
We enable the django_heroku settings, but set staticfiles and allowed_hosts to False, because we want to specify our own static file options and change allowed_hosts from the django_heroku default value ['*'] to prevent Host Header attacks.
django_heroku.settings(locals(), staticfiles=False, allowed_hosts=False)
At the bottom of the settings.py file, we will now add settings specific to Heroku.
if "DYNO" in os.environ: STATIC_ROOT = 'static'
We will now add git to our project.
heroku git:remote -a example
We now want to disable DEBUG in production and add our domain to our allowed hosts. We add these options in the if
"DYNO" in os.environ block because we only want these settings to be in effect in production.
if "DYNO" in os.environ: STATIC_ROOT = 'static' ALLOWED_HOSTS = ['example.herokuapp.com'] DEBUG = False
First, we will add the Procfile. To do this just add a file called Procfile (without any extension) to the root of your project. On ubuntu and mac simply write
We then install gunicorn which is the HTTP server we use in production on Heroku.
pip install gunicorn
while in the terminal while in the root directory. Next, add the following to the file
web: gunicorn myproject.wsgi --log-file -
Our last step is to create the requirements.txt file, which will specify all the packages that we have used. Since we used a virtual environment, this step is very easy. All we have to do is type
pip freeze > requirements.txt
in the terminal while being in our projects root directory. This will add all our packages installed through pip to the requirements.txt file automatically.
If you weren't using a virtual environment, you can also manually create a requirements.txt file in the root directory and manually add all the requirements. If you did everything correctly your requirements.txt file should look like
asgiref==3.4.1 dj-database-url==0.5.0 Django==3.2.7 django-heroku==0.3.1 gunicorn==20.1.0 psycopg2==2.9.1 pytz==2021.1 sqlparse==0.4.2 whitenoise==5.3.0
We are now ready to deploy our project.
git add . git commit -m "My first project is ready to be deplayed" git push heroku main
And we are done! Your project is now deployed to Heroku.
If you want to make sure your project only works over https you want to add the following options to your production settings.
if "DYNO" in os.environ: STATIC_ROOT = 'static' ALLOWED_HOSTS = ['example.herokuapp.com'] DEBUG = False SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') SECURE_SSL_REDIRECT = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SECURE- Ensures your CSRF cookies will be served over https.
SESSION_COOKIE_SECURE- Ensures your session cookies will be served over https.
SECURE_SSL_REDIRECT- Will redirect all HTTP traffic to https