Table of Contents

,

Deploying Django website

On remote server; make user and add to superuser group

adduser django_maja
aadduser django_maja sudo

Insert public key and disable password authentication

mkdir -m 700 .ssh
vi .ssh/authorized_keys
  
sudo vi /etc/ssh/sshd_config
systemctl restart sshd.service

Configure firewall

sudo apt install ufw
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable
sudo apt install python3-pip python3-venv apache2 libapache2-mod-wsgi-py3

Deploy Django

On local machine get required python packages and transfer files to server

source venv/bin/activate
pip freeze > requirements.txt
scp -r yourproject django_maja@example.org:~/

On remote server

python3 -m venv yourproject/venv
source yourproject/venv/bin/activate
pip install --upgrade pip
pip install -r yourproject/requirements.txt

Add domain in allowed hosts

vi yourproject/settings.py

...
ALLOWED_HOSTS = ['example.org','www.example.org']
...
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
...

Collect static files

python manage.py collectstatic

Test site

sudo ufw allow 8080
cd /etc/apache2/sites-available/
sudo cp 000-default.conf example.org.conf
<VirtualHost *:80>
 
    ServerName example.org
    ServerAlias example.org
 
    ServerAdmin webmaster@localhost
 
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
 
  RewriteEngine on
  RewriteCond %{SERVER_NAME} =(www\.)?example.org [OR]
  RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
sudo a2ensite example.org.conf && sudo a2dissite 000-default.conf
sudo chown :www-data yourproject/db.sqlite3 && sudo chown :www-data yourproject/ && sudo chmod 664 yourproject/db.sqlite3
sudo chown -R :www-data yourproject/media/ && sudo chmod -R 775 yourproject/media

Move sensitive information

Get SECRET_KEY from yourproject/yourproject/settings.py

sudo mkdir /etc/my_django_config
sudo vi /etc/my_django_config/yourproject.json
vi yourproject/yourproject/settings.py
...
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""

import os
import json

with open('/etc/my_django_config/yourproject.json') as f:
    config = json.load(f)
...
SECRET_KEY = config['SECRET_KEY']
...
sudo ufw delete allow 8080
sudo systemctl restart apache2

Enable ssl with letsencrypt

Download cerbot

Enable apache mods

sudo a2enmod ssl rewrite

Run certbot

sudo certbot

Create letsencrypt config file

sudo vi /etc/apache2/sites-available/example.org-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
        ServerName example.org
        ServerAlias www.example.org
 
        ServerAdmin webmaster@localhost
 
        ErrorLog ${APACHE_LOG_DIR}/error-example.log
        CustomLog ${APACHE_LOG_DIR}/access-example.log combined
 
        Include /etc/letsencrypt/options-ssl-apache.conf
        SSLCertificateFile /etc/letsencrypt/live/example.org/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/example.org/privkey.pem
 
        Alias /static /home/django_maja/example/static
        <Directory /home/django_maja/example/static>
        Require all granted
        </Directory>
 
        Alias /media /home/django_maja/example/media
        <Directory /home/django_maja/example/media>
        Require all granted
        </Directory>
 
        <Directory /home/django_maja/example/example/>
        <Files wsgi.py>
          Require all granted
        </Files>
        </Directory>
 
        WSGIScriptAlias / /home/django_maja/example/example/wsgi.py
        WSGIDaemonProcess example_django python-path=/home/django_maja/example python-home=/home/django_maja/example/venv
        WSGIProcessGroup example_django
 
</VirtualHost>
</IfModule>

Enable site and restart apache

sudo a2ensite example.org-ssl.conf
sudo systemctl restart apache2

Troubleshooting

RequiredDependencyException: jpeg

Error:

...
Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-install-tbcs638c/pillow_8a743b86be7a43dabab5b1bfbde4a377/setup.py", line 804, in <module>
        raise RequiredDependencyException(msg)
    __main__.RequiredDependencyException:
    
    The headers or library files could not be found for jpeg,
    a required dependency when compiling Pillow from source.

...

Install:

apt-get install libjpeg-dev zlib1g-dev

Tested on

See also

References