Setting up Django and your web server with uWSGI and nginx

Date posted: 05-oct-2018

 

In this article, we will see how to setup a Django web application on Ubuntu 16.04 server. We’ll use UWSGIservice to deploy our webapp along with Nginx.

Requirements:-

Python 3.6

Django 2.0.7

Nginx 1.10.3

Ubuntu 16.04

Install Python basic packages

sudo apt-get install python3-dev  python3-pip 

sudo apt-get install python3-setuptools

sudo apt-get install python3-kivy

Install Virutal Environment

pip3 install virtualenv virtualenvwrapper

Install Django

pip3 install django

Install UWSGI

sudo pip install uwsgi

Now we need to create the vassals folder, which is the folder where our .ini files (called vassals) will reside upon. Inside vassals we will have two other folders: available and enabled. The first will contain all the (.ini) configuration files. While the second (enabled) will contain a symlink to the files at available

cd /etc/

sudo mkdir uwsgi

cd uwsgi

sudo mkdir vassals

cd vassals

sudo mkdir enabled

sudo mkdir available

Now we need to create an emperor.ini file, which will contain the path for the other vassals at enabled:

sudo nano /etc/uwsgi/vassals/emperor.ini

Add this lines to the file:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
[uwsgi]
emperor = /etc/uwsgi/vassals/enabled
[uwsgi] emperor = /etc/uwsgi/vassals/enabled
[uwsgi]

emperor = /etc/uwsgi/vassals/enabled

Now, it’s time to deamonize uwsgi. In order to do it, create a usgi.service file at /etc/systemd/system/:

sudo vi /etc/systemd/system/uwsgi.service

Now, paste the following content into it:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
[Unit]
Description=uWSGI Emperor
After=syslog.target
[Service]
ExecStart=/usr/local/bin/uwsgi --ini /etc/uwsgi/vassals/emperor.ini
# Requires systemd version 211 or newer
RuntimeDirectory=uwsgi
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all
[Install]
WantedBy=multi-user.target
[Unit] Description=uWSGI Emperor After=syslog.target [Service] ExecStart=/usr/local/bin/uwsgi --ini /etc/uwsgi/vassals/emperor.ini # Requires systemd version 211 or newer RuntimeDirectory=uwsgi Restart=always KillSignal=SIGQUIT Type=notify StandardError=syslog NotifyAccess=all [Install] WantedBy=multi-user.target
[Unit]
Description=uWSGI Emperor
After=syslog.target

[Service]
ExecStart=/usr/local/bin/uwsgi --ini /etc/uwsgi/vassals/emperor.ini
# Requires systemd version 211 or newer
RuntimeDirectory=uwsgi
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all

[Install]
WantedBy=multi-user.target

To start the service

sudo systemctl start uwsgi

To check service status

systemctl status uwsgi

Lets enable the service. So that it starts at boot

sudo systemctl enable uwsgi

To stop the service

sudo systemctl stop uwsgi

Lets configure our django project to run with uwsgi.

Lets create a file /etc/uwsgi/vassals/available/kb_web.ini

vi /etc/uwsgi/vassals/available/web_app.ini

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# webapp_uwsgi.ini file
[uwsgi]
# Django-related settings
# the base directory (full path)
chdir = /var/www/webapp
# Django's wsgi file
module = webapp.wsgi
enable-threads = true
# process-related settings
# master
master = true
# maximum number of worker processes
processes = 10
listen = 100
# the socket (use the full path to be safe
socket = /var/www/webapp/webapp/web_app.sock
# ... with appropriate permissions - may be needed
chmod-socket = 666
# clear environment on exit
vacuum = true
max-requests = 1000
#limit-as = 128
daemonize = /var/log/uwsgi-emperor.log
# webapp_uwsgi.ini file [uwsgi] # Django-related settings # the base directory (full path) chdir = /var/www/webapp # Django's wsgi file module = webapp.wsgi enable-threads = true # process-related settings # master master = true # maximum number of worker processes processes = 10 listen = 100 # the socket (use the full path to be safe socket = /var/www/webapp/webapp/web_app.sock # ... with appropriate permissions - may be needed chmod-socket = 666 # clear environment on exit vacuum = true max-requests = 1000 #limit-as = 128 daemonize = /var/log/uwsgi-emperor.log
# webapp_uwsgi.ini file
[uwsgi]

# Django-related settings
# the base directory (full path)
chdir           = /var/www/webapp
# Django's wsgi file
module          = webapp.wsgi
enable-threads = true

# process-related settings
# master
master          = true
# maximum number of worker processes
processes       = 10
listen  = 100
# the socket (use the full path to be safe
socket          = /var/www/webapp/webapp/web_app.sock
# ... with appropriate permissions - may be needed
chmod-socket    = 666
# clear environment on exit
vacuum          = true
max-requests = 1000
#limit-as = 128
daemonize =  /var/log/uwsgi-emperor.log

Lets create a symlink to enabled folder

ln -s /etc/uwsgi/vassals/available/kb_web.ini /etc/uwsgi/vassals/enabled/

Please make sure you’ve uploaded your project folder under /var/www

ls -l /var/www/webapp

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
drwxr-xr-x 3 www-data www-data 4096 Sep 14 05:41 bin
drwxr-xr-x 6 root root 4096 Oct 4 13:46 webapp
-rwxr-xr-x 1 root root 538 Aug 10 02:14 manage.py
-rw-r--r-- 1 root root 275 Aug 10 02:14 requirements
drwxr-xr-x 3 www-data www-data 4096 Sep 14 05:41 bin drwxr-xr-x 6 root root 4096 Oct 4 13:46 webapp -rwxr-xr-x 1 root root 538 Aug 10 02:14 manage.py -rw-r--r-- 1 root root 275 Aug 10 02:14 requirements
drwxr-xr-x 3 www-data www-data 4096 Sep 14 05:41 bin
drwxr-xr-x 6 root     root     4096 Oct  4 13:46 webapp
-rwxr-xr-x 1 root     root      538 Aug 10 02:14 manage.py
-rw-r--r-- 1 root     root      275 Aug 10 02:14 requirements

Lets manually verify the application by running this command

python3 manage.py runserver 0.0.0.0:8000

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# python3 manage.py runserver 0.0.0.0:8000
Performing system checks...
System check identified no issues (0 silenced).
October 05, 2018 - 12:17:12
Django version 2.0.7, using settings 'kb1988.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
# python3 manage.py runserver 0.0.0.0:8000 Performing system checks... System check identified no issues (0 silenced). October 05, 2018 - 12:17:12 Django version 2.0.7, using settings 'kb1988.settings' Starting development server at http://0.0.0.0:8000/ Quit the server with CONTROL-C.
# python3 manage.py runserver 0.0.0.0:8000
Performing system checks...

System check identified no issues (0 silenced).
October 05, 2018 - 12:17:12
Django version 2.0.7, using settings 'kb1988.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.

It looks fine and no python module errors.

Configure nginx domain

Lets configure nginx virtual host

vi /etc/nginx/sites-available/webapp.com

Enter the below contents. You can adjust the folder path as per your needs.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
upstream web_app {
server unix:///var/www/webapp/webapp/kb_web.sock; # for a file socket
}
server {
# the port your site will be served on
listen 80;
# the domain name it will serve for
server_name pheonixsolutions.com
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste
location /media {
alias /var/www/webapp/webapp/media; # your Django project's media files - amend as required
}
location /static {
alias /var/www/webapp/webapp/static;
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass web_app;
include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
}
}
upstream web_app { server unix:///var/www/webapp/webapp/kb_web.sock; # for a file socket } server { # the port your site will be served on listen 80; # the domain name it will serve for server_name pheonixsolutions.com charset utf-8; # max upload size client_max_body_size 75M; # adjust to taste location /media { alias /var/www/webapp/webapp/media; # your Django project's media files - amend as required } location /static { alias /var/www/webapp/webapp/static; } # Finally, send all non-media requests to the Django server. location / { uwsgi_pass web_app; include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed } }
upstream web_app {
     server unix:///var/www/webapp/webapp/kb_web.sock; # for a file socket
}
server {
    # the port your site will be served on
    listen      80;
    # the domain name it will serve for
    server_name pheonixsolutions.com
    charset     utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste
    location /media  {
        alias /var/www/webapp/webapp/media;  # your Django project's media files - amend as required
    }

    location /static {
        alias /var/www/webapp/webapp/static;
    }

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  web_app;
        include     /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
    }
}

Verify nginx syntax test

nginx -t

Reload nginx service

/etc/init.d/nginx reload

Restart UWSGI

service restart uwsgi 

Your domain should work at http://pheonixsolutions.com

Added tips:-

To create superuser admin

virtualenv command , which will give platform to run source/bin/activate.

source /var/www/webapp/bin/activate

python3 manage.py createsuperuser --username=devops --

email=devops@pheonixsolutions.com
Enter password: ********

To collect static files from all the apps in one place

python3 manage.py collectstatic

If you run into errors, You should mention STATIC_ROOT path in your settings.py file. And then run above command again.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
STATIC_ROOT = '/var/www/webapp/webapp/static/'
STATIC_ROOT = '/var/www/webapp/webapp/static/'
STATIC_ROOT = '/var/www/webapp/webapp/static/'

 

Steps to eradicate Django migration errors-“core_module issue” :

In python you need to do migrate the changes on prod while its running. If we didn’t complete the migration properly.

 

This kind of error will make us more disappointing at a last stage of migration. we will see errors like shown below.

 

This image has an empty alt attribute; its file name is Screen-Shot-2019-03-29-at-1.23.41-PM-1-1024x343.png

As the error stats that this is an issue with core module. We believe that the code migration didn’t applied completely.

To resolve that we need to run below commands:-

python3.6 manage.py makemigrations core
python3.6 manage.py migrate core

Now login to your django admin panel and check. The errors should be gone.

That’s it. We’re done with the setup!

Leave a Reply