Learn How To Serve Flask application With Gunicorn Nginx And SSL On Ubuntu In This Simple Guide

Serve Flask application with Gunicorn Nginx and SSL on ubuntu
Content

Introduction

Once you had deployed your Flask server on an EC2 instance and it ran successfully, you might be got excited and share the hosted IP with your friends to experience the application you have developed. But wait! Do you feel there is something missing? A URL such as “https://tezeract.ai/”? And your friends should get your personal & secure URL rather than hosted IP? If you said YES on these questions, it means you’re on the right place to get your answers.

If you think that linking your application with secure URL is the only thing you will learn in this article, so you’re wrong as it contains more than you expected because serving your flask application with Gunicorn, Nginx and in the end connect it with SSL will improve the Reliability, Performance, and Security of your Applications. So, lets get started.

Prerequisites

The prerequisites for the deployment of your AI Server on EC2 instance are: 

  1. Active AWS Credentials (Root or AMI user with access) 
  2. Login details of your EC2 instance (.pem file or credentials)
  3. Working and deployed Python Server on EC2 (contains atleast one API). 
  4. A cup of Coffee!

If you haven’t build your Flask server or haven’t deploy your Flask-python server on your EC2 instance yet, please visit these articles according to your requirements, respectively:

Getting Started with Gunicorn

Gunicorn, sometimes called as ‘Green Unicorn’ is a Python HTTP server for WSGI applications. The Gunicorn server is easy to use, uses few server resources, and works well with many different web frameworks. It is also fairly quick. 

Gunicorn runs multiple processes, to allow running any Python application concurrently. It offers the ideal balance of performance, adaptability, and configuration simplicity. 

Further Reading

Getting Started with Nginx

Nginx is a free and open-source software that works as a webserver, mainly used for improving the performance, relaibility and security of your applications. 

There are many features of Nginx which we used on the daily basis, but the most common ones are reverse proxy, load balancing, HTTP cache and mail proxy.

Further Reading

Serve your Application

As our Python servers are not optimal and safe for deployment purposes, and when you run the server with python, it usually says that don’t use this for deployment, that’s why we will be using gunicorn to handle and manage the Python server and nginx to proxy the request to port 8000 (where gunicorn runs) from port 80.

From anypart of globe, whenever request came from client side, Nginx server will proxy it and pass it to gunicorn to handle, gunciron will use Flask server to process according to configurations and send the response back to Nginx server which Nginx server will display to client.

Lets check if our python server is running and take actions to configure guicorn.

Run the below command to check if python server is running, by default it runs on port 5000 (or will run on port which you defined in your run.py file)

sudo lsof -i -P -n | grep LISTEN

As you see in the above screenshot, all the ports which are in running state got displayed and our python server is not actively running. In case, if it was running you might need to run this command to stop your server first. 

Command to stop the specific port: sudo fuser -k 5000/tcp (where 5000 is the port in which your app is running)

Configuring Gunicorn to Flask Server

Now, lets configure gunciron to use your flask server. There would be only 2 steps for the configuration.

  1. Install Gunciorn
  2. Run the command

To install gunciron run the below command, make sure to active your virtual environment first:

pip install gunicorn

Once gunicorn is installed, change the directory where your run.py file exists and run the following command:

gunicorn --bind 0.0.0.0:8000 run:app --daemon 

In the above command, I have used two arguments in gunciron command:

  1. bind: It will bind the port to your server specifically running on your mention host and port. 
  2. daemon: When you log out off the server the gunicorn process exits, to make sure it stays running for Nginx you will need to run it on the back process even if you stop the terminal, and that’s where the daemon argument plays its role.

For a more advanced configuration for gunicorn try the below command:

gunicorn --worker-class gevent --bind 0.0.0.0:8000 run:app --timeout 2400 --workers=2 --threads=2 --daemon

To get a better understanding of the arguments, kindly visit the official documentation link regarding the gunicorn configurations.

Further Reading

Now, when you listen to the ports, you can see your flask application is successfully able to run with gunicorn on port 8000.

Configure Nginx as a web server

For using Nginx as a webserver, we will need to install the required dependencies, which can be done by typing the following commands:

sudo apt-get updatesudo apt-get install python3-pip python3-dev nginx

You can verify that if Nginx has been successfully been setup by typing your instance Public IP v4 on the browser, it should look like the below-attached image.

If you’re seeing this ‘Welcome to Nginx’ screen on your browser, congrats! You’re very close to achieving the final target. Let’s move ahead and remove the default nginx files by the following commands:

sudo rm /etc/nginx/sites-enabled/default
sudo rm /etc/nginx/sites-available/default

To proxy our traffic to port 8000, we will be going to configure Nginx. For that, create a config file inside the sites-available folder, I named it ‘myapp.com’ & then add a symlink to sites-enabled in Nginx.

From the first command, the config file would be made, and the second one would help to make the file editable more easily. 

sudo touch /etc/nginx/sites-available/myapp.com
sudo chown -R $USER:$USER /etc/nginx/sites-available/myapp.com

Change the directory to sites-available, if you’re already not there, open the config file (myapp.com).

cd /etc/nginx/sites-available/

Paste the below content in your config file.

server{listen 80;
location / {proxy_pass http://127.0.0.1:8000/;}}

Your terminal screen should be like below and you can press ctrl+X to exit & save.

You might be curious about what we have done in the config file, let me explain this. ‘listen 80;’ tells Nginx to listen to all incoming requests on port 80, and ‘proxy_pass http://127.0.0.1:8000/;’ tells Nginx to act as a proxy and serve all those requests to port 8000, where our gunicorn is setup & running.

As discussed above, we have to add a symlink to the sites-enabled directory, so let’s do that with the help of the following command:

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

Now, restart the Nginx server by:

sudo service nginx restart

You know what we have done? We have successfully set up and configured the Nginx and gunicorn to server our flask server. Hurryyy!!! Take a sip of coffee and open your browser with your Public IP to see that magic, Yes! Your app is now on AWS, successfully running with Nginx and Gunicorn.

Installing SSL

Now, we’re on the final stage to achieve our target, where we will set up and install SSL to secure our connections. To get a free domain you can visit freenom.com

You can log in to your freenom account and check if your desired domain is available by pressing the Check Availability button available on the site as below:

Hope you get your required domain, and once you click the ‘Get it now’ button, you will be redirected to the screen similar to below-attached image, where you can select Period as ‘12 Months’ for getting your domain free for over a period of one year!

Once you press the button ‘Continue’, you will be redirected to the page where you can manage your DNS for your domain. This is the very important part, where you need to add a record of Type A, put your EC2 machine public IP v4 in the Target column, and press the button ‘Save Changes’. 

You can now review and checkout by pressing the ‘Complete Order’ button.

Wow! You now have your domain. Let’s connect it with your application.

It’s very easy to install the SSL certificate on Ubuntu using letscrypt. Open your config file and type the server name below listen to the command in the file.

server_name domain.com;

Your config file should look like this:

Save it and restart Nginx server! You’re almost there.

sudo service nginx restart

Now, run the following commands:

sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python3-certbot-nginx
sudo certbot --nginx 

Once the commands run successfully, follow the prompts and enter the details which are required.

Put your email here, and press Enter:

Leave the input blank, and press Enter:

Write 2 (recommended), and then press Enter:

Congratulations!!!

Wait for a while and put your domain on the browser, where you will see your flask app running successfully on your domain, server by Gunicorn, and Nginx webserver.

Conclusion

Today, you have learned about how you can Serve Flask application with Gunicorn Nginx and SSL on Ubuntu EC2 instance. You have configured gunicorn to use your flask server and also created an Nginx server that proxies web client requests to the application server. Apart from that, you secured traffic to your server with Let’s Encrypt. You have gained an understanding of the flow of the client requests and how it serves in production. 

From now on, you can easily build and deploy your AI-functional applications, so Kudos to you!

I hope you get this article fruitful and feel worth it to give it a read. In the next article, I will try to use a process manager named ‘Supervisor’ to improve and manage gunicorn.

To get further inside on how to make your servers more secure that are being deployed on AWS give a read to this article “How To Make Your AWS EC2 Machine Secure

Abdul Hannan

Abdul Hannan

Co-Founder & CEO

Share

Suggested Articles