Step 1 - Installing the Components from the Ubuntu Repositories

Install required package in given below

[email protected]:~# sudo apt update

#These will include python3-pip along with a few more packages and development tools necessary for a robust programming environment

[email protected]:~# sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools

Step 2 - Creating  Python Virtual Environment

#installing the pythin3-venv package will install the venv module

[email protected]:~# sudo apt install python3-venv

#make a parent directory for our Flask project

[email protected]:~# mkdir ~/example
[email protected]:~# cd ~/example/
[email protected]:~/example#

#Create virtual environment to store your Flask project’s Python requirements

[email protected]:~/example# python3 -m venv exampleenv

It will install a local copy of Python and pip into the directory. Called exampleenv with in your project directory..

Before installing applications you must activate the virtual environment Use this command for activation.

[email protected]:~/example# source exampleenv/bin/activate
(exampleenv) [email protected]:~/example#

prompt will change to indicate then you are in virtual environment it will look like this

(exampleenv) [email protected]:~/example#

Step 3 — Setting Up  Flask Application

you are in your virtual environment, you can install Flask and Gunicorn and get started on designing your application in here.

install wheel with the local instance of pip to ensure that our packages

(exampleenv) [email protected]:~/example# pip install wheel

Install Flask and Gunicorn

(exampleenv) [email protected]:~/example# pip install gunicorn flask

Creating a Sample App

Now you can create simple application. Flask is a microframework. It does not include many of the tools  that more full-featured frameworks might

Now create our Flask app in a single file called

(exampleenv) [email protected]:~/example# nano ~/example/

from flask import Flask

app = Flask(__name__)


def hello():

    return "<h1 style='color:blue'>Hello There!</h1>"

if __name__ == "__main__":'')

The above configuration save and exit

You are followed the initial server setup guide, you should have a UFW firewall enabled. To test the application  you need to allow access to port 5000 in ufw

(exampleenv) [email protected]:~/example# sudo ufw allow 5000

Now Test your application now :

(exampleenv) [email protected]:~/example# python

* Serving Flask app "example" (lazy loading)

* Environment: production

WARNING: This is a development server. Do not use it in a production deployment.

Use a production WSGI server instead.

* Debug mode: off

* Running on (Press CTRL+C to quit)

http://your_server_ip:5000 - Visit your ip address followed by :5000 Port number  

Should see something like this

CTRL-C in your terminal window to stop the Flask development server

Creating the WSGI Entry Point

create a file that will serve as the entry point in our Application.This will tell our Gunicorn server how to interact with the application

Create file inside of Project Directory

(exampleenv) [email protected]:~/example# nano ~/example/

from example import app

if __name__ == "__main__":

Save and close the above file. (from example import app) example is our flask Application Name.

Step 4 - Configuring Gunicorn

Our Application is now written with an entry point established. Now we can configuring Gunicorn. Before moving we check our Gunicorn can serve the application correctly or not.

simply passing it the name of our entry point. In our case wsgi:app

(exampleenv) [email protected]:~/example# gunicorn --bind wsgi:app

See Output like this :

[2021-03-01 09:24:49 +0100] [27840] [INFO] Starting gunicorn 20.0.4

[2021-03-01 09:24:49 +0100] [27840] [INFO] Listening at: (27840)

[2021-03-01 09:24:49 +0100] [27840] [INFO] Using worker: sync

[2021-03-01 09:24:49 +0100] [27843] [INFO] Booting worker with pid: 27843

Now visit your Server ip address with :5000

Eg : http://your_server_ip:5000 in our case our server ip address is

You can see the Application output

We are confirmed that it’s functioning properly . CTRL + C To terminate the Terminal Window.

Deactivate our Virtual Environment Using Following Command :

(exampleenv) [email protected]:~/example# deactivate

Python command will use the System’s Python  environment again

create the systemd service unit file.automatically start Gunicorn and serve the Flask application whenever the server boots. Create .service files with the /etc/systemd/system  Directory.

start with the [Unit] section. used to specify metadata and dependencies.put a description of our service.init system to only start this after the networking target has been reached

[email protected]:/etc/systemd/system# cat example.service


Description=Gunicorn instance example

####open up the [Service] section####

it will specify the user and group that we want the process to run under. give group ownership to the www-data group so that Nginx can communicate easily with the Gunicorn processes.replace the username here with your username. PATH environment variable so that the init system knows that the executables for the process are located within our virtual environment

→ Start 3 worker processes

→ Create and bind Unix Socket File.

→ example.sock within our project directory or /home Directory.. We’ll set an umask value of 007 so that the socket file is created giving access to the owner and group.while restricting other access

→ Specify the WSGI entry point file name   - (wsgi:app)  






ExecStart=/root/example/exampleenv/bin/gunicorn --workers 3 --bind unix:/tmp/example.sock -m 007 wsgi:app

####[Install] section####

→ This will tell systemd  link this service to if we enable it to start at boot.


[email protected]:/etc/systemd/system#

Our Main systemd Unit file Given Below


Description=Gunicorn instance example






ExecStart=/root/example/exampleenv/bin/gunicorn --workers 3 --bind unix:/home/example.sock -m 007 wsgi:app


Save and exit

#Reload Daemon Using Following Command

[email protected]:~/example/exampleenv/bin# systemctl daemon-reload

#start example.service file Using Following Command.

[email protected]:~/example/exampleenv/bin# systemctl start example.service

[email protected]:~/example/exampleenv/bin# systemctl status example.service

● example.service - Gunicorn instance example

Loaded: loaded (/etc/systemd/system/example.service; disabled; vendor preset: enabled)

Active: active (running) since Mon 2021-03-01 09:37:53 CET; 4s ago

Main PID: 28040 (gunicorn)

Tasks: 4 (limit: 2301)

CGroup: /system.slice/example.service

├─28040 /root/example/exampleenv/bin/python3 /root/example/exampleenv/bin/gunicorn --worker

├─28042 /root/example/exampleenv/bin/python3 /root/example/exampleenv/bin/gunicorn --worker

├─28043 /root/example/exampleenv/bin/python3 /root/example/exampleenv/bin/gunicorn --worker

└─28044 /root/example/exampleenv/bin/python3 /root/example/exampleenv/bin/gunicorn --worker

Mar 01 09:37:53 systemd[1]: Started Gunicorn instance example.

Mar 01 09:37:53 gunicorn[28040]: [2021-03-01 09:37:53 +0100] [28040] [

Mar 01 09:37:53 gunicorn[28040]: [2021-03-01 09:37:53 +0100] [28040] [

Mar 01 09:37:53 gunicorn[28040]: [2021-03-01 09:37:53 +0100] [28040] [

Mar 01 09:37:53 gunicorn[28040]: [2021-03-01 09:37:53 +0100] [28042] [

Mar 01 09:37:53 gunicorn[28040]: [2021-03-01 09:37:53 +0100] [28043] [

Mar 01 09:37:53 gunicorn[28040]: [2021-03-01 09:37:53 +0100] [28044] [

[email protected]:~/example/exampleenv/bin#

Step 5 — Configuring Nginx to Proxy Requests

Gunicorn application server should now be up and running configure Nginx to pass web requests to that socket.creating a new server block configuration file in Nginx’s site-available  directory - example

#install nginx package using Following Command:

[email protected]:~# apt-get install nginx
[email protected]:~# nano /etc/nginx/site-available/example

Open Server Block file and Listening On Port 80.use this block for requests for our server’s domain name. location block that matches every request. proxy_params file that specifies some general proxying parameters. pass the requests to the socket we defined using the proxy_pass

server {
listen 80;
location / {
include proxy_params;
proxy_pass http://unix:/tmp/example.sock;

Save and close the file

enable the Nginx server block configuration.Create link to sites-enabled directory

[email protected]:~# ln -s /etc/nginx/site-available/example /etc/nginx/site-enabled

you can test for syntax errors - using Following command

[email protected]:~# nginx -t
[email protected]:/etc/nginx/sites-available# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[email protected]:/etc/nginx/sites-available#

There is no syntax Error showing.Then restart nginx process using following command

[email protected]:/etc#sudo systemctl restart nginx

We don’t need access through port 5000. Now we are removing that rule using following command

[email protected]:/etc#sudo ufw delete allow 5000
[email protected]:/etc#sudo ufw allow 'Nginx Full’

now be able to navigate to your server’s domain name in your web browser.should see your application’s output

Step 6 - Securing the Application

let’s get an SSL certificate for your domain. Secure The Application using Let’s Encrypt Certificate Using.

Install Certbot’s Nginx package using apt Package

[email protected]:/etc/nginx/sites-available# sudo apt install python3-certbot-nginx

Certbot provides a variety of ways to obtain SSL certificates through plugins. To use the plugin using following command.

Certbot with the --nginx plugin, using -d to specify the Domain name

If you run this command First Time it  will be prompted to enter an email address and agree to the terms of service. Certbot will communicate with the Let’s Encrypt server

[email protected]:~# sudo certbot --nginx -d

Saving debug log to /var/log/letsencrypt/letsencrypt.log

Plugins selected: Authenticator nginx, Installer nginx

Obtaining a new certificate

Performing the following challenges:

http-01 challenge for

Waiting for verification...

Cleaning up challenges

Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/example

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): 2

Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/example

Congratulations! You have successfully enabled

You should test your configuration at:


- Congratulations! Your certificate and chain have been saved at:


Your key file has been saved at:


Your cert will expire on 2021-05-30. To obtain a new or tweaked

version of this certificate in the future, simply run certbot again

with the "certonly" option. To non-interactively renew *all* of

your certificates, run "certbot renew"

- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt:

Donating to EFF:

verify the configuration, navigate to your domain, using https://