Deploying react and django with nginx and guincorn

Deploying react and django with nginx and guincorn

react djang.png Deploying react and django with nginx and guincorn Deploying react with django isn't straight forward but I am here to assist you with that. We will be going through how to deploy both react and django as the main and subdomain using the same server/ubuntu instance. What this means is you will deploy your frontend and backend separately on two different subdomains such as the frontend will be accessed via example.com while the django backend api will be accessed via api.example.com

Prerequisite knowledge

  • Experience with ubuntu
  • Experience with GitHub
  • Linux based system with ubuntu 16 and above

Tools

  • GitHub
  • AWS/DigitalOcean/Cloudcone i.e a cloud provider
  • Domain

First login to your server using putty and your root access Use terminal and run:

apt update && apt upgrade -y

Set hostname for server. I used test-server. You can use whatever you want.

hostnamectl set-hostname test-server

Create a limited user and give sudo privileges

run

adduser USERNAME .

Enter password and skip through the rest of the questions. then run

adduser USERNAME sudo

logout as root by typing exit and log in with your username: ssh username@IP Pull both frontend and backend code from github using

git clone

Installing some important packages

sudo apt-get install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx

Set Up Nginx Server Blocks Creating the First Server Block File For React Frontend Install NodeJS and npm Use Current Release

sudo apt-get install curl
curl -sL https://deb.nodesource.com/setup_13.x | sudo -E bash -
sudo apt-get install nodejs

As mentioned above, we will create our first server block config file by copying over the default file:

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example.com

Now, open the new file you created in your text editor with sudo privileges:

sudo nano /etc/nginx/sites-available/example.com

Ignore the commented lines, and look at the code similar to this:

server {
        listen 80 ;
        listen [::]:80;

       root /home/username/react-frontend/build;
       index index.html index.htm;

       server_name your_IP domain.com www.domain.com;

        location / {
                try_files $uri /index.html =404;
        }
}

Then Enable the file by linking to the sites-enabled dir

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled

Test NGINX config

sudo nginx -t

Restart Nginx Server

sudo systemctl restart nginx

Create the Second Server Block File which will be for django First Install some dependencies

run sudo apt install virtualenv ufw

Change to your virtualenv run

virtualenv venv -p python3

run

source venv/bin/activate

Back out to the directory that has manage.py Run

python manage.py collectstatic

Install Gunicorn run

pip install gunicorn

Check to see if gunicorn can host your django project. Change DjangoProject to whatever your project is called run

gunicorn --bind 0.0.0.0:8000 DjangoProject.wsgi

Create gunicorn systemd file run

sudo nano /etc/systemd/system/gunicorn.service

Paste the following and be sure to update your project name, path and username accordingly:

[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=username
Group=www-data
WorkingDirectory=/home/username/DjangoProject
ExecStart=/home/username/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/username/DjangoProject/DjangoProject.sock DjangoProject.wsgi:application
[Install]
WantedBy=multi-user.target

Step : Run the following commands to enable gunicorn:

sudo systemctl start gunicorn
sudo systemctl enable gunicorn
sudo systemctl status gunicorn
sudo systemctl daemon-reload
sudo systemctl restart gunicorn

Now that we have our initial server block configuration, we can use that as a basis for our second file. Copy it over to create a new file:

sudo cp /etc/nginx/sites-available/example.com /etc/nginx/sites-available/test.com

Open the new file with sudo privileges in your editor:

sudo nano /etc/nginx/sites-available/test.com

Paste the following and be sure update your own IP, username, path and project name This covers http, https will be covered below

server {
        listen 80;
        server_name IP;
        location = /favicon.ico { access_log off; log_not_found off; }
        location /static/ {
            root /home/username/DjangoProject;
        }
        location / {
            include proxy_params;
            proxy_pass http://unix:/home/username/DjangoProject/DjangoProject.sock;
        }
    }

Link and test nginx config Link:

sudo ln -s /etc/nginx/sites-available/django-project/etc/nginx/sites-enabled

Test:

sudo nginx -t

Reload Nginx and Gunicorn

sudo systemctl restart gunicorn
sudo systemctl restart nginx

In order to avoid a possible hash bucket memory problem that can arise from adding additional server names, we will also adjust a single value within our /etc/nginx/nginx.conf file. Open the file now:

sudo nano /etc/nginx/nginx.conf

Within the file, find the server_names_hash_bucket_size directive. Remove the # symbol to uncomment the line: /etc/nginx/nginx.conf

http {
    . . .
    server_names_hash_bucket_size 64;
    . . .
}

Now, let's activate SSL and bind the domains to their respective proxies Install Certbot and it's Nginx plugin with apt:

sudo apt install certbot python3-certbot-nginx

Certbot is now ready to use, but in order for it to automatically configure SSL for Nginx, we need to verify some of Nginx's configuration. Obtain an SSL Certificate First we obtain SSL certificate for the react url

sudo certbot - nginx -d example.com -d www.example.com

This runs certbot with the --nginx plugin, using -d to specify the domain names we'd like the certificate to be valid for. If that's successful, certbot will ask how you'd like to configure your HTTPS settings. Output Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

Select your choice then hit ENTER. The configuration will be updated, and Nginx will reload to pick up the new settings. certbot will wrap up with a message telling you the process was successful and where your certificates are stored: Let's finish by testing the renewal process.

Verify Certbot Auto-Renewal

You can query the status of the timer with systemctl:

sudo systemctl status certbot.timer

To test the renewal process, you can do a dry run with certbot:

sudo certbot renew - dry-run

If you see no errors, you're all set. When necessary, Certbot will renew your certificates and reload Nginx to pick up the changes. If the automated renewal process ever fails, Let's Encrypt will send a message to the email you specified, warning you when your certificate is about to expire. Now, repeat the same SSL process for the django domain

Credits:

Credits to

  1. Ousseynou Diop for the react deployment guide
  2. Satssehgalfor the django deployment guide
  3. Digitaloceanfor all their articles