Hosting Flask Apps on Nginx

mbaoma

Mbaoma

Posted on May 1, 2021

Hosting Flask Apps on Nginx

Hi there, in this article, we would be looking at how to host a Flask app on Nginx (a webserver) on an Ubuntu Virtual Machine.

A webserver is a computer that has web server software installed (Apache, Nginx, Microsoft IIS) and serves resources, which could be webpages or multimedia files, over the web, to fulfill client's requests over the internet.

Nginx is a webserver that can be used as reverse proxy, load balancer, mail proxy and HTTP Cache. It is widely used due to it's ability to scale websites better.

The first thing, we do is to provision an Ubuntu Virtual Machine (I use Microsoft Azure) and then login to it via SSH.

To follow along with this article, you are expected to have a flask application already built and in a git repository. If you don't, you could use this

We then run the following command to update our repositories:

sudo apt update
Enter fullscreen mode Exit fullscreen mode

Dependig on the version of your Ubuntu VM, you might want to upgrade your Python version.
After this, we continue with the steps below:

  • Step 1: We clone our app's GitHub repository into our VM:
sudo apt update
git clone <repo-url>
Enter fullscreen mode Exit fullscreen mode
  • Step 2: We change our directory's name to app
ls
mv <repo-name>/ app
Enter fullscreen mode Exit fullscreen mode

(The ls command is to list all the files and directories in our current work environment)

  • Step 3: We cd into our directory, create a virtual environment and activate it
sudo apt-get install python3-venv
python3 -m venv <virtual-environment-name>
source <virtual-environment-name>/bin/activate
Enter fullscreen mode Exit fullscreen mode
  • Step 4: We install the requirements in our requirements.txt file
    pip3 install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

run

pip3 list

to see a list of all installed dependencies

If uWSGI does not install, run the following;

sudo apt-get install build-essential python3-dev
pip3 install uwsgi
Enter fullscreen mode Exit fullscreen mode

So far, so good!

  • Step 5: Now, we check if our app runs on uwsgi, but first we have to set our Uncomplicated Fire Wall (ufw) to allow both incoming and outgoing connections on port 9090, the port we would be making use of.
sudo ufw enable
sudo ufw allow 9090
Enter fullscreen mode Exit fullscreen mode

Expected result:

image

Running

sudo ufw status

shows us the current state of our firewall; whether it is active or not and the ports our firewall gives us access to.

  • Step 6: run the following
uwsgi dev.ini
Enter fullscreen mode Exit fullscreen mode
  • You might see the following in the output: image

run this,

sudo apt-get install libpcre3 libpcre3-dev
pip3 install uwsgi -I --no-cache-dir
Enter fullscreen mode Exit fullscreen mode

then re-run the command

uwsgi dev.ini
Enter fullscreen mode Exit fullscreen mode

In your browser visit

<vmipaddress>:9090/
Enter fullscreen mode Exit fullscreen mode

We expect to see our Flask app displayed via this port.

  • Step 7: we delete the firewall rule and deactivate our virtual environment
sudo ufw delete allow 9090
deactivate
Enter fullscreen mode Exit fullscreen mode
  • Step 8: install nginx
sudo apt install Nginx
Enter fullscreen mode Exit fullscreen mode

Now, we check the apps recognized by ufw and instruct it to allow for connection to Nginx:

sudo ufw app list
sudo ufw allow 'Nginx HTTP'
Enter fullscreen mode Exit fullscreen mode

To confirm if Nginx was properly installed, we type our VM's IP address in our browser.

Expected result:
image

Omoshiroi...

  • Step 9: we create systemd unit file to reboot the server running our app
sudo nano /etc/systemd/system/<custom-name-of-service-app>.service
Enter fullscreen mode Exit fullscreen mode

Example:

sudo nano /etc/systemd/system/app.service
Enter fullscreen mode Exit fullscreen mode

And type in the following contents in our file:

[Unit]
Description=A simple Flask uWSGI application
After=network.target

[Service]
User=<yourusername>
Group=www-data
WorkingDirectory=/home/<yourusername>/app
Environment="PATH=/home/<yourusername>/app/venv/bin"
ExecStart=/home/<yourusername>/app/venv/bin/uwsgi --ini <name-of-app-ini file>

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode
  • Step 10: we enable the service file we just created
sudo systemctl start <name-of-app>
sudo systemctl enable app <name-of-app>
Enter fullscreen mode Exit fullscreen mode

Expected output:
image

To check if the file is running, type:

sudo systemctl status app
Enter fullscreen mode Exit fullscreen mode

Also if a mistake is made in our service file and we correct it, we have to reload the daemon and restart systemctl

image

  • Step 11: we configure nginx by creating a config file
sudo nano /etc/nginx/sites-available/<name-of-file>
Enter fullscreen mode Exit fullscreen mode

And type in the following contents:

server {
    listen 80;
    server_name <your_ip_address> <your_domain_name>;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/<username>/app/app.sock;
    }
}
Enter fullscreen mode Exit fullscreen mode

*To check if there are any errors in our nginx configuration file, we run

sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

image

  • Step 12: we link our config file to sites-enabled directory (Nginx server blocks configuration files are stored in /etc/nginx/sites-available directory, which are enabled through symbolic links to the /etc/nginx/sites-enabled/ directory):
sudo ln -s /<path-to-config-file>/<config-file-name> /etc/nginx/sites-enabled
Enter fullscreen mode Exit fullscreen mode

Example:

sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/
Enter fullscreen mode Exit fullscreen mode

Running a syntax check at this point, comes in handy

  • Step 13: we restart nginx for our changes to take effect
sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

In our browser, we type in our VM's IP address without adding a port becase in our nginx config file, we have defined a port for nginx to listen on

tada!!
image
IP address

image
Azure custom domain name

Feel free to share your IP address with friends to check out your app

Thank you for your time!!!

Find below the GitHub repo for this task:
Github repo

Feel free to connect with me via Linkedin

Gokigen'yō

💖 💪 🙅 🚩
mbaoma
Mbaoma

Posted on May 1, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related