DEV Community

loading...

Deploying a Django Application Using Apache2

Nina Hwang
πŸ‘©πŸ»β€πŸ’» ν™©μ±„μ˜ 🐣 Junior Backend Developer
・Updated on ・4 min read

After you finish creating your django application, you may want to deploy it so that it can be used. There are several ways to do it. In this post, I will show you how to deploy django applicaion using Apache2.

I will use:

  • Django
  • Anaconda3
  • AWS EC2
  • Ubuntu 18.04
  • Apache2
  • Let's Encrypt

Before I begin, I created a very simple django application. Currently it is running on localhost, port 8000.
Alt Text
Create requirements.txt

$ pip freeze > requirements.txt
Enter fullscreen mode Exit fullscreen mode

1. EC2 Setup

Install Anaconda3

To create a virtual environment, let's install anaconda3 first.

$ sudo apt-get update && sudo apt-get upgrade

$ sudo apt-get install curl

$ curl -O https://repo.anaconda.com/archive/Anaconda3-2020.02-Linux-x86_64.sh
Enter fullscreen mode Exit fullscreen mode

(you can find other versions here)

$ bash Anaconda3-2020.02-Linux-x86_64.sh
Enter fullscreen mode Exit fullscreen mode

If this command

$ conda env list
Enter fullscreen mode Exit fullscreen mode

returns an error, run this command.

$ export PATH=(path to anaconda3 directory)/anaconda3/bin:$PATH
$ source ~/.bashrc
Enter fullscreen mode Exit fullscreen mode

Then create a virtual environment.

$ conda create -n (any name you want) python=(python version)
Enter fullscreen mode Exit fullscreen mode

Setting Up a Django Devolopment Environment

After activating the virtual environment you created, install django. Then transfer your local django files into the EC2 instance. You can use git or FTP.

$ pip install -r /path/to/requirements.txt
Enter fullscreen mode Exit fullscreen mode

Run this command so that all packages you need are installed.
Alt Text
Now the application is running on EC2 public ip.

2. Application Deployment

Install Apache2

$ sudo apt-get install apache2
Enter fullscreen mode Exit fullscreen mode

Once apache2 is installed, this page is shown when you try to connect to your EC2 instance on HTTP port.
Alt Text

Connecting Domain Name to Your Application

To set up domain name on apache server, edit apache.conf file. It is located in /etc/apache2.

$ sudo vim apache2.conf
Enter fullscreen mode Exit fullscreen mode

Add these lines.

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so


<VirtualHost *:80>
    ServerAdmin (your contact address)
    ServerName (your domain)

    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / http://localhost:8000/
    ProxyPassReverse / http://localhost:8000/

    <Directory (path to your django root - where wsgi.py is)>
        <Files wsgi.py>
            Require all granted
        </Files>
    </Directory>
</VirtualHost>
Enter fullscreen mode Exit fullscreen mode

Virtual hosts can be name-based by using ServerName. An http server generally uses port 80 and '*:80' means any IP address on port 80. When someone access to your server with web browser using the domain you wrote as ServerName, apache2 server will redirect to localhost:8000

Start your server with this command.

$ sudo systemctl restart apache2
Enter fullscreen mode Exit fullscreen mode

If the command returns an error, check the error message by running

$ sudo systemctl status apache2
Enter fullscreen mode Exit fullscreen mode

Or, you can check out the error log in /var/log/apache2/error.log

If there's no 'modules' directory inside of /etc/apache2, it is located in /usr/lib/apache2. Find the directory and copy it into /etc/apache2.

$ sudo cp -r /usr/lib/apache2/modules /etc/apache2/modules
Enter fullscreen mode Exit fullscreen mode

If all errors were fixed, restart the server.

Alt Text

SSL Setup

Now the deployment is done but you see that 'Not Secure' warning in the address bar? That means there is a lack of security for the connection, because I am using HTTP protocol instead of HTTPS. HTTPS provides encryption and authentication, therefore it is more secure than HTTP.

Apache2 Setup

Let's Encrypt offers free SSL certificates. Certbot is for automatically using Let's Encrypt certificates to enable HTTPS.

$ sudo snap install --classic certbot
$ sudo certbot --apache
Enter fullscreen mode Exit fullscreen mode

If you can find pem files in /etc/letsencrypt/live/(your domain), you are good to go.
Now edit your apache2.conf file again.
Add these lines in <VirtualHost> to redirect HTTP to HTTPS.

<VirtualHost *:80>
...
        RewriteEngine On
        RewriteCond %{SERVER_NAME} =(your domain)
        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
...
</VirtualHost>
Enter fullscreen mode Exit fullscreen mode

Once you installed Let's Encrypt, you can find apache2-le-ssl.conf file in /etc/apache2. Edit this file.

<IfModule mod_ssl.c>
<VirtualHost *:443>
        ServerAdmin (your contact address)
        ServerName (your domain)
        ProxyRequests Off
        ProxyPreserveHost On
        SSLProxyEngine on
        SSLProxyVerify none
        SSLProxyCheckPeerCN off
        SSLProxyCheckPeerName off
        SSLProxyCheckPeerExpire off
        ProxyPass / https://localhost:8001/
        ProxyPassReverse / https://localhost:8001/

        <Directory (path to your django root - where wsgi.py is)>
                <Files wsgi.py>
                        Require all granted
                </Files>
        </Directory>


SSLCertificateFile /etc/letsencrypt/live/(your domain)/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/(your domain)/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
Enter fullscreen mode Exit fullscreen mode

Django Setup

Since runserver only works for HTTP, install django-sslserver

$ pip install django-sslserver
Enter fullscreen mode Exit fullscreen mode

Edit settings.py

# settings.py
INSTALLED_APPS = [
    ...
    'sslserver',
    ...
]

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_PRELOAD = True
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
Enter fullscreen mode Exit fullscreen mode

Then, run this command.

$ python manage.py runsslserver 0:8001
Enter fullscreen mode Exit fullscreen mode

If you want to run server using gunicorn, run this.

$ nohup gunicorn --certfile=/home/ubuntu/anaconda3/envs/(your conda virtual environment name)/lib/python3.9/site-packages/sslserver/certs/development.crt --keyfile=/home/ubuntu/anaconda3/envs/(your conda virtual environment name)/lib/python3.9/site-packages/sslserver/certs/development.key --bind 0.0.0.0:8001 (your django project name).wsgi &
Enter fullscreen mode Exit fullscreen mode

Alt Text
See that lock? Your site is now encrypted.

Discussion (0)