Part 2: Securing Sensitive Info, Pushing Migrations, Installing Gunicorn and NGINX
Here we are going to make the Raspberry able to serve the application accessible as a normal web server would.
Remove sensitive info from the project:
pip3 install python-decouple
pip3 install dj-database-url
Add a file to store the info which will not appear in the commit (.env added to .gitignore):
nano .env
Add:
SECRET_KEY=the_secret_key_in_settings.py
DEBUG=True
ALLOWED_HOSTS=127.0.0.1 ## Enter here the ip address of your web server or it domain name or leave a * to allow any ip in a non production local server) ##
DATABASE_URL=postgres://name_of_db_user:the_password@host_name:port_number/name_of_db
Here the port number is where PostgreSQL was installed, by default: 5432.
Make changes to settings.py:
from decouple import config, Csv
import dj_database_urlSECRET_KEY = config(‘SECRET_KEY’)
DEBUG = config(‘DEBUG’, default=False, cast=bool)
ALLOWED_HOSTS = config(‘ALLOWED_HOSTS’, cast=Csv())
DATABASES = {
‘default’: dj_database_url.config(
default=config(‘DATABASE_URL’)
)
}
And add the following for static files:
STATIC_URL = ‘/static/’
STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), ‘staticfiles’)STATICFILES_DIRS = [
os.path.join(BASE_DIR, ‘static’),
]
Migrate the database:
python3 manage.py migrate
Collect static files:
python3 manage.py collectstatic
staticfiles folder will be created in the project’s parent folder for NGINX to serve the files (css, js,…)
Create a super user for the Django app:
python3 manage.py createsuperuser
Configure Gunicorn
Create a file gunicorn_start in the project root directory:
#!/bin/bash
NAME=”name_of_db”
DIR=/home/name_of_system_user/django_project/name_of_project
USER=name_of_system_user
GROUP=name_of_system_user
WORKERS=3
BIND=unix:/home/name_of_system_user/django_project/run/gunicorn.sock
DJANGO_SETTINGS_MODULE=name_of_project.settings
DJANGO_WSGI_MODULE=name_of_project.wsgi
LOG_LEVEL=errorcd $DIR
source ../venv/bin/activateexport DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DIR:$PYTHONPATHexec ../venv/bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
— name $NAME \
— workers $WORKERS \
— user=$USER \
— group=$GROUP \
— bind=$BIND \
— log-level=$LOG_LEVEL \
— log-file=-
Make file as executer:
chmod u+x gunicorn_start
Make folders for socket and logs:
mkdir run logs
Make an empty log file inside /home/name_of_system_user/django_project/logs:
touch logs/gunicorn.log
Create a configuration file in Supervisor:
sudo nano /etc/supervisor/conf.d/name_of_system_user.conf
[program:name_of_system_user]
command=/home/name_of_system_user/django_project/gunicorn_start
user=name_of_system_user
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/home/name_of_system_user/django_project/logs/gunicorn.log
Make Supervisor read the config file and update:
sudo supervisorctl reread
sudo supervisorctl update
Check Supervisor configuration:
sudo supervisorctl status name_of_system_user
In order to restart the Django server after changes were made type:
sudo supervisorctl restart name_of_system_user
Configure NGINX:
Write a file name_of_project to /etc/nginx/site-available:
upstream app_server {
server unix:/home/name_of_system_user/django_project/run/gunicorn.sock fail_timeout=0;
}server {
listen 80;
server_name website_address_OR_ip_address; # here can also be the IP address of the serverkeepalive_timeout 5;
client_max_body_size 4G;access_log /home/name_of_system_user/django_project/logs/nginx-access.log;
error_log /home/name_of_system_user/django_project/logs/nginx-error.log;location /static/ {
alias /home/name_of_system_user/staticfiles/;
}# checks for static file, if not found proxy to app
location / {
try_files $uri @proxy_to_app;
}location @proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
}
If Django there is need to get the web server accessible on a local network and the .env config file for Django’s settings:
Add the following to allow Django to look for the header first and then generate the URL:
USE_X_FORWARDED_HOST : True
And in the NGINX configuration file change the location @proxy_to_app to this:
location @proxy_to_app {
proxy_set_header Host $host;
proxy_set_header X-Url-Scheme $scheme;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_pass http://app_server;
}
Create a symbolic link (a shortcut) between sites-available and sites-enabled:
sudo ln -s /etc/nginx/sites-available/name_of_project /etc/nginx/sites-enabled/name_of_project
Remove NGINX default config file:
sudo rm /etc/nginx/sites-enabled/default
sudo service nginx restart
Add new model to models.py then run to migrate the database:
python3 manage.py makemigrations
python3 manage.py migrate