python-nginx-flask-uwsgi

Last updated on June 13th, 2022 at 02:28 pm

We are going to configure Nginx to forward request to uWSGI and serve Python applications running on Flask

In this post we will discuss in detail on how to configure uWSGi with nginx to run Python application (in flask) in Linux(Ubuntu/Redhat). You can follow the same steps for configuring Linux instances launched in AWS EC2 or any other Cloud Provider or on a regular server. I am running these example below from a Ubuntu server . Steps should be similar for RedHat or any other Linux Flavors since we are not really installing any specific package but just doing some configuration changes.

  1. Configure and deploy flask application
  2. Enable Nginx to connect to uwsgi
  3. Add uWSGI service in systemd
  4. Troubleshooting uWSGI errors
  5. Live Example

Once the above steps are completed you should be able to run your own python application behind nginx. Now lets get started

If you have not yet installed uwsgi in ubuntu please follow this tutorial (How to Install uWSGI and Flask in Ubuntu) and then come back,

Configure and deploy flask application

Make a directory named myapp (I created this under /dude/myapp directory) and create a configuration file named myapplication.ini (Just for a change we are following a working backwards strategy here)

Content of myapplication.ini file is given below

[uwsgi]
module = wsgi:app
http-socket=127.0.0.1:3232
chmod-socket = 660
vacuum = true
buffer-size=32768
master = true
processes = 10
logto = /var/log/nginx/%n.log
die-on-term = true

As you can see the module directive is calling wsgi:app

vacuum=true, try to remove all of the generated file/sockets
processes = 10, spawn 10 number of workers/processes
die-on-term = true, exit instead of brutal reload on SIGTERM
logto = /var/log/nginx/%n.log, %n is the name of the .ini file ie: myapplication

Next step is to create the end point named wsgi.py.

from myproject import app

if __name__ == '__main__':
   app.run()

You might be wondering what this myproject is, here you go you need to create that file too which contains all the details of how your application is configured, content of myproject.py file will look like the one below.

from flask import Flask
app = Flask(__name__)
@app.route("/myapp/get")
def hello():
    return "<h1 style='color:blue'>Hello There!, This is a flask application running behind nginx</h1>"
@app.route("/myapp/look")
def check():
    return "<h1 style='color:green'>I am in Look!, This is a flask application running behind nginx</h1>"
if __name__ == "__main__":
    app.run(host='0.0.0.0')

Adding new route and all other website related scripts can be including in this file (myproject.py)

Now lets do a manual testing and see whether this configuration works before doing a big change of updating nginx configuration file.

Run the command below to spawn 10 process along with a master as per our ini file

root@greenhouse-server:/dude/myapp# uwsgi --ini myapplication.ini &
[1] 390083
root@greenhouse-server:/dude/myapp# ps -ef|grep 390083
root      390083  389711  3 21:25 pts/0    00:00:00 uwsgi --ini myapplication.ini
root      390085  390083  0 21:25 pts/0    00:00:00 uwsgi --ini myapplication.ini
root      390086  390083  0 21:25 pts/0    00:00:00 uwsgi --ini myapplication.ini
root      390087  390083  0 21:25 pts/0    00:00:00 uwsgi --ini myapplication.ini
root      390088  390083  0 21:25 pts/0    00:00:00 uwsgi --ini myapplication.ini
root      390089  390083  0 21:25 pts/0    00:00:00 uwsgi --ini myapplication.ini
root      390090  390083  0 21:25 pts/0    00:00:00 uwsgi --ini myapplication.ini
root      390091  390083  0 21:25 pts/0    00:00:00 uwsgi --ini myapplication.ini
root      390092  390083  0 21:25 pts/0    00:00:00 uwsgi --ini myapplication.ini
root      390093  390083  0 21:25 pts/0    00:00:00 uwsgi --ini myapplication.ini
root      390094  390083  0 21:25 pts/0    00:00:00 uwsgi --ini myapplication.ini

We can see that it is now up and running . Let’s test the URL it by hitting directly on the uWSGI instance URI and bravo it works!!

root@greenhouse-server:/dude/myapp# curl -I localhost:3232/myapp/get
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 40

Enable nginx to connect to uWSGI

uwsgi(All lowercase) is a protocol. uWSGI is configured along with WebServers like Apache / nginx for serving Python applications.

Take a backup of your nginx configuration file that has the server 80 or 443 block, then add this within the block. Example given below is for port 80 server block

server 80 {
..
....
...

#Python Apps
location /myapp {
               include uwsgi_params;
proxy_pass http://127.0.0.1:3232;
index  index.html index.htm;
        }
}

We are enabling NGINX to forward request to http://127.0.0.1 port 3232 in which our application is listening whenever user hits <YOURWEBSITE>/myapp

Now that we have our server running successfully, next step is to configure uWSGI as a service that way we we can manage it easily via systemctl commands.

Add uWSGI service in systemd

Go To /etc/systemd/system and create a unit file called uwsgiapp.service. Add the content as shown below and save it. Make sure you modify the value with the location of your application/ .ini file in WorkingDirectory directive accordingly

root@greenhouse-server:/etc/systemd/system# cat uwsgiapp.service
[Unit]
Description=uWSGI Application
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/dude/myapp/
ExecStart=uwsgi --ini myapplication.ini
[Install]
WantedBy=multi-user.target

Enable the unit file, uWSGI service gets added to system reboots / stop-start

#systemctl enable uwsgiapp
Created symlink /etc/systemd/system/multi-user.target.wants/uwsgiapp.service → /etc/systemd/system/uwsgiapp.service.
#

Troubleshooting uWSGI errors

If you get permission denied while starting the uWSGI service

Jan 31 21:54:21 greenhouse-server systemd[1]: uwsgiapp.service: Failed with result 'exit-code'.
Jan 31 21:54:21 greenhouse-server uwsgi[390393]: [uWSGI] getting INI configuration from myapplication.ini
Jan 31 21:54:21 greenhouse-server uwsgi[390393]: open("/var/log/nginx/myapplication.log"): Permission denied [core/>

Make sure the username in which uWSGI application is running has the right permission to write to folder /var/log/ningx or file in this case myapplication.log is owned by user www-data.

Live Example

Demo

Demo 2

Leave a Reply

Your email address will not be published. Required fields are marked *