Installing Django2 on Centos7 with Nginx, Gunicorn and Postgres

 



Requirements


Command:
sudo yum install epel-release sudo yum install python-pip python-devel postgresql-server postgresql-devel postgresql-contrib gcc nginx wget git python36 sudo postgresql-setup initdb

This installs the extra packages for linux repo on centos that allows downloads of the other requirements. Then it installs the python tools we will be needing to setup a virtual env for our project along with postgres and nginx. Finally the last command initializes the Postgres db.



Setup Postgres 1


Command:
sudo systemctl start postgresql
sudo systemctl enable postgresql


This start and enables the start of the postgres database on restart.



Setup Postgres 2


Command:
sudo vi /var/lib/pgsql/data/pg_hba.conf

Edit the postgres connector file with the following info



/var/lib/pgsql/data/pg_hba.conf



                    #Skip this and copy below
# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
#host    all             all             127.0.0.1/32            ident
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
#host    all             all             ::1/128                 ident
host    all             all             ::1/128                 md5
                


Enable Postgres After the Changes


Command:

sudo systemctl restart postgresql
sudo systemctl enable postgresql


Start postgres and enable on reboot



Create Postgres Database


Command:
sudo su - postgres psql



Test the databae


Command:
exit psql -U djangodatabaseuser -h localhost -d yourdatabasename

Exit the postgres user and then use postgres to attempt to connect to the database



Get python 3.6 with


Command:
yum -y install python36
wget https://bootstrap.pypa.io/get-pip.py
sudo python3.6 get-pip.py
sudo python3.6 -m pip install virtualenv


This installed python36. I will do a guide for higher versions of python in a future blog. Back to the commands, they install python3 which is needed for django2, get pip for python 3 then installs pip then install virtualenv for our pip which we will need for building our django virtual environment in the future.



Create user for Django Project


Command:
sudo adduser djangoprojectuser

I run each Django project with a custom user for that project for security reasons.



Create Django Env Dir


Command:
sudo mkdir /home/djangoprojectuser/projectname-env sudo chown -R djangoprojectuser:djangoprojectuser /home/djangoprojectuser/projectname-env sudo cd /home/djangoprojectuser/ python3.6 -m virtualenv projectname-env sudo chown -R djangoprojectuser:djangoprojectuser /home/djangoprojectuser/projectname-env

I put this in the django project user's home dir but you can put it wherever you like.



Activate Virtual Env for Project


Command:
source yourproject-env/bin/activate

This activates the python3.6 virtual env for your project



Install Django into the Virtual Env


Command:
pip install django gunicorn psycopg2 or pip install -r requirements.txt

The top is the base you need to get django going. If you have a dev project which you probably do you can freeze the virtual env using pip freeze -l > requirements.txt and send it to the directory you want to install it from.



New Project. Skip if gitting in project


Command:
cd ..
python djangoadmin startproject projectname


This takes you back to home directory for the djangoprojectuser and then creates a project folder named whatever you put in projectname. You can then start building your app or editing your setting.py file



Install Project with Git


Command:
yum install git
git clone https://respository
cd project name
python makemigrations
python migrate
python manage.py makesuperuser
python manage.py runserver


These commands add the git folder from git. You will or should change the settings file or have it using env variables. You will want to add the djangodbuser and make sure it is setup with the postgres connector the way we are setitngs this up and I would change the secret key. You are then having python build the changes and migrate the changes to the database. Then creating an admin user and testing the dev server to make sure the project starts up correctly and is not throwing any errors.



Test Gunicorn


Command:
gunicorn --bind 0.0.0.0:8000 bottomofbarrel.wsgi:application

Make sure you are in the project dir. Then issue this command to make sure gunicorn is going to work. At this point you should be able to go your project by the http://yourip:8000. If that works you are ready to startup your service.



Deavtivate virtualenv


Command:
deactivate

This takes you out of your virtual enviroment



Create Gunicorn service


Command:
sudo vi /etc/systemd/system/projectname.service
Then click i to go into insert mode


This starts to configure the systemd service. Paste the below into it.



/etc/systemd/system/gunicorn.service



                    [Unit]
Description=Projectname daemon
After=network.target

[Service]
User=djangoprojectuser
Group=nginx
WorkingDirectory=/home/djangoprojectuser/project/
ExecStart=/home/djangoprojectuser/djangoproject-env/bin/gunicorn --workers 3 --bind unix:/home/djangoprojectuser/djangoproject/bottomofthebarrel.sock bottomofbarrel.wsgi:application

[Install]
WantedBy=multi-user.target
                


Save the serice


Command:
click esc
type :wq!


This exits insert mode and saves the file



Enable the Django Service


Command:
sudo systemctl start projectname
sudo systemctl enable projectname


Start the service that you just created. Whatever you can name the service whatever you want but I find it easiest to name it based on the project.



Nginx Config


Command:
sudo vi /etc/nginx/nginx.conf

This takes you to default nginx config. There will be another blog on how to do seperate site configs. Find the server block and make the changes below



Nginx Server Block



                    ###Match the server block with something similar to below###
server {
    access_log /var/log/nginx/projectname-access.log;
    error_log /var/log/nginx/projectname-error.log;
    server_name yourdomain.com;
    gzip on;
    gzip_proxied any;
    gzip_buffers 16 8k;
    gzip_types    text/plain application/javascript application/x-javascript text/javascript text/xml text/css;
    gzip_vary on;

    location = /favicon.ico { access_log off; log_not_found off; }  
    location /static/ {
    autoindex on;
    alias /home/djangprojectuser/project/static/;
}
    location /media/ {
    autoindex on;
    alias  /home/djangprojectuser/project//media/;
}

   location / {
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_pass http://unix /home/djangprojectuser/project/gallowaylabs.sock;
  }
                


Nginx config explained


Command:
Esc
:wq!


The top command saves the config. In the actual name, put your domain name or ip for server, it is going to listen on 80 if you do not change this. Point the static and media to where you have saved them in your file, I keep them in the main project folder. fianlly you want to make sure the proxy_pass is pointing to where you had the .sock file go in the service. This is the unix socket that is created by gunicorn that nginx is using for requests. Not that in your settings file you will need add allowed host name to whatever you nginx server is listening for.



Nginx permissions for Project


Command:
sudo usermod -a -G djangoprojectuser nginx
chmod -r 710 /home/djangoprojectuser


The first command puts you into the nginx group so nginx can access your folders. The second sets permissions on the project folder and env.



Testing nginx


Command:
sudo nginx -t

Test the nginx config. You will find errors in /var/log/nginx/error.log by default. A common error you will find with little details is SE Linux enabled on centos. You can disable if you want to get it running fast. Otherwise set to permissive and write custom rules for your Django app.



Enable Nginx


Command:
sudo systemctl start nginx
sudo systemctl enable nginx


Start nginx which should work fine if the tests have passed. Then the second command enables nginx on restart.



Firewall rules


Command:
yum install firewalld
sudo firewall-cmd --zone=public --add-port=443/tcp --permanent
sudo firewall-cmd --zone=public --add-port=80/tcp --permanent


This makes sure firewalld is installed. The second command per mentally opens 443 and the next command does the same for 80.



SSL Cert


Command:
sudo yum install certbot-nginx
certbot --nginx


These commands should find your domain from nginx and then you can click option 2 for a permanent redirect from 80 to 443. Note that if you do not have public dns that is the same as the certbot this part will fail but you will still be able to access your site in clear text from http. I would not log into the admin portal if you are doing this as it will be in clear text with no encryption.



Conclusion


Command:
You should be up and running

At this point as long as you have dns records or are accessing through ip, you should have a fully functioning django website. Do some testing and make sure you set DEBUG=false in the settings file.