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
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>
Step 2: We change our directory's name to
app
ls mv <repo-name>/ app
(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
Step 4: We install the requirements in our
requirements.txt
filepip3 install -r requirements.txt
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
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
Expected result:
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
- You might see the following in the output:
run this,
sudo apt-get install libpcre3 libpcre3-dev
pip3 install uwsgi -I --no-cache-dir
then re-run the command
uwsgi dev.ini
In your browser visit
<vmipaddress>:9090/
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
Step 8: install nginx
sudo apt install Nginx
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'
To confirm if Nginx was properly installed, we type our VM's IP address in our browser.
Expected result:
Omoshiroi...
- Step 9: we create systemd unit file to reboot the server running our app
Example:sudo nano /etc/systemd/system/<custom-name-of-service-app>.service
And type in the following contents in our file:sudo nano /etc/systemd/system/app.service
[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
- Step 10: we enable the service file we just created
sudo systemctl start <name-of-app> sudo systemctl enable app <name-of-app>
Expected output:
To check if the file is running, type:
sudo systemctl status app
Also if a mistake is made in our service file and we correct it, we have to reload the daemon and restart systemctl
Step 11: we configure nginx by creating a config file
sudo nano /etc/nginx/sites-available/<name-of-file>
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; } }
To check if there are any errors in our nginx configuration file, we run sudo nginx -t
- 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):
Example:sudo ln -s /<path-to-config-file>/<config-file-name> /etc/nginx/sites-enabled
sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/
Running a syntax check at this point, comes in handy
- Step 13: we restart nginx for our changes to take effect
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 onsudo systemctl restart nginx
tada!! IP address
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ō