Safepal Documentation

Introduction

Safepal is an app that helps report GBV related cases. Provide users with educational content and access to CSOs

Tools

  1. Django
  2. Django Rest Framework
  3. Python3
  4. Wagtail
  5. Swagger
  6. Firebase
  7. Redis
  8. Celery
  9. Supervisord
  10. Nginx
  11. FFmpeg

Server Deployment

Setup EC2 instance

  1. Log into the Safepal AWS account
  2. Go to Services > compute > EC2.
  3. Click on Launch Instance.
  4. Select Ubuntu Server 18.04 TLS(or higher)
  5. Click Review and Launch > Launch .
  6. Use existing pair(please check the documentation folder for the pem file sellio_aws_instance.pem
  7. Finally Click on Launch Instances.

SSH into the Server, Install dependencies & setup postgreSql

  1. cd Desktop/
  2. sudo chmod 400 sellio_aws_instance.pem
  3. ssh -i sellio_aws_instance.pem ubuntu@public_ip_address
  4. sudo apt-get update && apt-get upgrade -y
  5. sudo apt-get install postgresql postgresql-contrib nginx git
  6. sudo apt-get install python3-venv
  7. sudo apt-get -y install nginx
  8. sudo apt-get -y install supervisor
  9. sudo apt install redis-server
  10. sudo apt install python3-pip
  11. sudo add-apt-repository ppa:jonathonf/ffmpeg-4
  12. sudo apt-get update
  13. sudo apt-get install ffmpeg
  14. source venv/bin/activate(or install without env)
  15. git clone https://github.com/UNFPAInnovation/SafepalDjangoBackend.git
  16. pip install -r requirements.txt

Note

All servers in the Safepal Project use the sellio_aws_instance.pem.

Warning

Activate allowed hosts in /home/ubuntu/SafepalDjangoBackend/SafepalDjangoBackend/settings.py ALLOWED_HOSTS = [‘*’] Requests may not work if not activated or add the actual IP address of the server

Enable supervisor

sudo systemctl enable supervisor
sudo systemctl start supervisor

Configure Postgres

su - postgres OR sudo -u postgres psql
createuser safepaluser
createdb safepaldb --owner safepaluser
psql -c "ALTER USER safepaluser WITH PASSWORD '123'"
exit

Change password

su - postgres
\password
exit

Configure The Application User

adduser safepal
gpasswd -a safepal sudo
su - safepal

Configure python environment

Clone the project and install requirements

python3 -m venv .
source bin/activate
git clone https://github.com/UNFPAInnovation/SafepalDjangoBackend.git
pip install -r requirements.txt

Add the database configs

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'dbname',
        'USER': 'username',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '',
    }
}

Run migrations

python manage.py migrate
python manage.py collectstatic

Test if the server is running by running

python manage.py runserver 0.0.0.0:8000

Configure gunicorn

Add these to bin/activate file. Do this for production and test

export DEBUG=False
export SECRET_KEY=''
export DB_NAME=''
export DB_USER=''
export DB_PASSWORD=''
export DB_HOST=''

Note

Check the Safepal drive for the test and production credentials. Contact the Outbox developers for details. codephillip@gmail.com - 0756878460

Configure gunicorn

Install gunicorn

pip install gunicorn

Add the code vim home/safepal/bin/gunicorn_start

#!/bin/bash

NAME="safepaltest"
DIR=/home/safepal/SafepalDjangoBackend
USER=safepal
GROUP=safepal
WORKERS=3
BIND=unix:/home/safepal/run/gunicorn.sock
DJANGO_SETTINGS_MODULE=SafepalDjangoBackend.settings
DJANGO_WSGI_MODULE=SafepalDjangoBackend.wsgi
LOG_LEVEL=error

cd $DIR
source ../bin/activate

export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DIR:$PYTHONPATH

exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $WORKERS \
  --user=$USER \
  --group=$GROUP \
  --bind=$BIND \
  --log-level=$LOG_LEVEL \
  --log-file=-

Change permission of gunicorn_start

chmod u+x bin/gunicorn_start

Make directory run

mkdir /home/safepal/run

Folder structure

_images/structure.png

Configure redis server

Edit redis settings

sudo vim /etc/redis/redis.conf

Allow systemd to run redis in a daemon

supervised systemd
6380

Restart redis

sudo systemctl restart redis.service

Configure supervisor

Create config files and log files

mkdir logs
touch logs/gunicorn-error.log
vim /etc/supervisor/conf.d/safepal-program.conf

Add service to run gunicorn and reddis

[program:safepal-program]
command=/home/safepal/bin/gunicorn_start
user=safepal
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/home/safepal/logs/gunicorn-error.log

[program:safepal-celery]
command=/home/safepal/bin/celery worker -A SafepalDjangoBackend --loglevel=INFO
directory=/home/safepal/SafepalDjangoBackend
user=safepal
numprocs=1
stdout_logfile=/home/safepal/logs/celery.log
stderr_logfile=/home/safepal/logs/celery.log
autostart=true
autorestart=true
startsecs=10

; Need to wait for currently executing tasks to finish at shutdown.
; Increase this if you have very long running tasks.
stopwaitsecs = 600

stopasgroup=true

; Set Celery priority higher than default (999)
; so, if redis is supervised, it will start first.
priority=1000
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl restart safepal-program
sudo supervisorctl restart safepal-celery
if this error is thrown. supervisor: couldn't exec /home/ubuntu/bin/gunicorn_start: EACCES
RUN: chmod +x gunicorn_start

Add static files and collect static

Add these lines to the /home/ubuntu/SafepalDjangoBackend/SafepalDjangoBackend/settings.py

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')

Then collect static files

source venv/bin/activate
(venv)$ python manage.py collectstatic

Explanation: This allows the static files like css and images to get rendered in django admin dashboard and swagger

Configure Nginx to Proxy Pass to Gunicorn

Create file named safepal-program sudo vim /etc/nginx/sites-available/safepal-program

Insert the following commands

upstream app_server {
    server unix:/home/safepal/run/gunicorn.sock fail_timeout=0;
}

server {
    listen 80;

    # add here the ip address of your server
    # or a domain pointing to that ip (like example.com or www.example.com)
    server_name x.x.x.x;

    keepalive_timeout 5;
    client_max_body_size 4G;

    access_log /home/safepal/logs/nginx-access.log;
    error_log /home/safepal/logs/nginx-error.log;

    location /static/ {
        alias /home/safepal/SafepalDjangoBackend/SafepalDjangoBackend/static/;
    }

    # checks for static file, if not found proxy to app
    location / {
        try_files $uri @proxy_to_app;
    }

    location /content {
        alias /mnt/content; # change the media url incase ints not in mnt
        access_log off;
    }

    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;
    }
}

Enable the file by linking it to the sites-enabled directory

sudo ln -s /etc/nginx/sites-available/safepal-program /etc/nginx/sites-enabled
sudo service nginx restart

Add SSL certificate

The command handles renewal of the domain as well

sudo add-apt-repository ppa:certbot/certbot
sudo apt  install certbot
sudo apt-get install python-certbot-nginx
sudo apt-get install software-properties-common
sudo certbot --nginx -d webdashboard.safepal.co

Activate storage drive(optional)

Incase you have a separate storage drive for your content, add the location in the settings.py. Then activate the drive

su - root
sudo mkfs -t ext4 /dev/sdb
sudo mount /dev/sdb1 /mnt
sudo chmod -R -v 777 /mnt/

Update of code and server

ssh ubuntu@IPADDRESS
su - safepal (then enter password)
source bin/activate
cd SafepalDjangoBackend
git add .
git stash save
git pull origin master
python manage.py collectstatic
python manage.py migrate
sudo supervisorctl restart safepal-program

OR run the script deploy.sh

cd SafepalDjangoBackend
../deploy.sh