Install the Packages from the Ubuntu Repositories first. If you are using Django with Python 3, type:
sudo apt-get update
sudo apt-get install python3-pip python3-dev libpq-dev nginx
Postgresql installation
sudo apt-get update
sudo apt-get install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx
MySQL installation
sudo apt-get update
sudo apt-get install mysql-server
mysql_secure_installation
Database creation
CREATE DATABASE myproject;
- Postgres
CREATE USER myprojectuser WITH PASSWORD 'password';
GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
- MySQL
CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON * . * TO 'newuser'@'localhost';
Python VirtualEnv Creation
sudo -H pip3 install --upgrade pip
sudo -H pip3 install virtualenv
cd ~/myproject
virtualenv myprojectenv
source myprojectenv/bin/activate
pip install django gunicorn psycopg2 (For Postgres)
Changes in setting.py
ALLOWED_HOSTS = [ ‘*’ ]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'myproject',
'USER': 'myprojectuser',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '',
}
}
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'myproject',
'USER': 'myprojectuser',
'PASSWORD': 'password',
}
}
Migrations
Now, we can migrate the initial database schema to our database using the management script:
python manage.py makemigrations
python manage.py migrate
Create an administrative user for the project by typing:
python manage.py createsuperuser
You will have to select a username, provide an email address, and choose and confirm a password. We can collect all of the static content into the directory location we configured by typing:
python manage.py collectstatic
Create a Gunicorn systemd Service File
Now, we are going to implement a more robust way of starting and stopping the application server with Gunicorn. To accomplish this, we’ll make a systemd service file.
Create and open a systemd service file for Gunicorn with sudo privileges in your text editor:
sudo nano /etc/systemd/system/gunicorn.service
gunicorn.service file
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
Type=notify
# the specific user that our service will run as
User=root
Group=root
# another option for an even more restricted service is
# DynamicUser=yes
# see http://0pointer.net/blog/dynamic-users-with-systemd.html
RuntimeDirectory=gunicorn
WorkingDirectory=/var/www/html/[ProjectName]
ExecStart=/var/www/html/[ProjectName]/project_venv/bin/gunicorn config.wsgi
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Check for the Gunicorn Socket File
Check the status of the process to find out whether it was able to start:
sudo systemctl status gunicorn
Create gunicorn.socket
sudo nano /etc/systemd/system/gunicorn.socket
gunicorn.socket File
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
# Our service won't need permissions for the socket, since it
# inherits the file descriptor by socket activation
# only the nginx daemon will need access to the socket
User=www-data
# Optionally restrict the socket permissions even more.
# Mode=600
[Install]
WantedBy=sockets.target
Run gunicorn service
sudo systemctl start gunicorn
sudo systemctl enable gunicorn
sudo systemctl status gunicorn
sudo systemctl daemon-reload
sudo systemctl restart gunicorn
Configure Nginx to Proxy Pass to Gunicorn
sudo nano /etc/nginx/sites-available/[ProjectName]
Then, type
upstream app_server {
server unix:/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
listen [::]:80;
server_name 128.199.221.253; # here can also be the IP address of the server
keepalive_timeout 5;
client_max_body_size 4G;
access_log /var/www/html/[ProjectName]/logs/nginx-access.log;
error_log /var/www/html/[ProjectName]/logs/nginx-error.log;
location /static/ {
autoindex on;
alias /var/www/html/[ProjectName]/static/;
}
# 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;
}
}
Adding SSL Certificate
upstream app_server {
server unix:/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
listen [::]:80;
server_name 128.199.79.246; # here can also be the IP address of the server
return 301 https://[DomainName]$request_uri;
}
server{
# SSL configuration
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name [DomainName];
ssl on;
ssl_certificate /etc/ssl/certs/cert.pem;
ssl_certificate_key /etc/ssl/private/key.pem;
ssl_client_certificate /etc/ssl/certs/cloudflare.crt;
ssl_verify_client on;
keepalive_timeout 5;
client_max_body_size 4G;
access_log /home/[UserName]/logs/nginx-access.log;
error_log /home/[UserName]/logs/nginx-error.log;
location /static/ {
autoindex on;
alias /home/[UserName]/[ProjectName]/[DjangoAppName]/static/;
}
# 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;
}
}
Restart all the service
sudo systemctl daemon-reload
sudo systemctl restart gunicorn
sudo nginx -t && sudo systemctl restart nginx