Flask application deployment with nginx and uwsgi

Please follow link before go further. Hello application in Flask with virtual env

Prequisite

  • uwsgi
  • nginx

Install uwsgi

pip3 install uwsgi

Install Nginx (Web Server)

sudo apt get install nginx

# check nginx is running or not
sudo systemctl status nginx.service

# output should be
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2019-07-20 12:18:28 IST; 4 days ago
  Process: 1642 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
  Process: 1392 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
 Main PID: 1645 (nginx)
   CGroup: /system.slice/nginx.service
           ├─1645 nginx: master process /usr/sbin/nginx -g daemon on; master_process on
           ├─1646 nginx: worker process                           
           ├─1647 nginx: worker process                           
           ├─1648 nginx: worker process                           
           └─1649 nginx: worker process                           

Jul 20 12:18:20 think systemd[1]: Starting A high performance web server and a reverse proxy server...
Jul 20 12:18:28 think systemd[1]: Started A high performance web server and a reverse proxy server.

Configure uWSGI

In the root directory of project, similar to that we created in previous post. Create a file wsgi.py

from app import app as application

if __name__ == "__main__":
    application.run()

Save file and test your wsgi file. with following command on terminal.

uwsgi --socket 0.0.0.0:8000 --protocol=http -w wsgi

And visit http://127.0.0.1:8000/. and you will see the application running in browser. So we have achieved our first step. Means our uwsgi working fine.

Create .ini configuration file

In the same project root directory, create a .ini file for uwsgi configuration. For example myproject.ini

[uwsgi]

module = wsgi

master = true
processes = 5

socket = myproject.sock
wsgi-file =/path/sample_application/wsgi.py

chmod-socket = 660
vaccum = true

die-on-term = true

If you want to create tcp connection then you below config file.

[uwsgi]

module = wsgi

master = true
processes = 5

for = 9902 9901 9900;
socket = :%(_)
wsgi-file =/path/sample_application/wsgi.py

chmod-socket = 660
vaccum = true

die-on-term = true

Save file and test ini file, run command in terminal.

uwsgi --ini myproject.ini
# or
uwsgi --ini project/path/myproject.ini

Change the project directory ownership to www-data

# so that nginx can read and write directory
sudo chown -R  {user}:wwwdata myproject

Create a uWSGI startup file

So that we can start/stop flask application service, as we do for other system services.

create a systemctl startup file at location /etc/systemd/system. For example /etc/systemd/system/myproject.service

[Unit]

Description="uWsgi server instance for myproject"
After=network.target

[Service]
User={you-user}
Group=www-data
WorkingDirectory=/home/{you-user}/path/myproject/
Environment="PATH=/home/{you-user}/virtualenvs/myproject/bin"
ExecStart=/home/{you-user}/virtualenvs/myproject/bin/uwsgi --ini /home/{you-user}/path/myproject/myproject.ini

[Install]
WantedBy=multi-user.target

Start myproject service and check status

sudo systemctl start myproject.service

# Check the status
sudo systemctl status myproject.service

# You should be able to see the socket with file with project directory. for example myproject.sock

# Enable it on startup
sudo systemctl enable myproject.service

Configure Nginx

Create a file /etc/nginx/sites-enabled/my_app

server {
    listen 80;
    server_name 127.0.0.1 localhost;

    location / {
        include uwsgi_params;
        uwsgi_pass 
        unix:/home/{your-user}/path/myproject/myproject.sock;
    }
}

For tcp connection

server {
    listen 80;
    server_name 127.0.0.1 localhost;

   location / {
        try_files $uri @application;
   }

    location @application {
        include uwsgi_params;
        uwsgi_pass 127.0.0.1:9902;
    }
}

Test your Nginx configuration and restart Nginx.

nginx -t -c /etc/nginx/nginx.conf
# output should be
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

/etc/init.d/nginx restart

That’s it. Open your localhost in browser and you will see application running with nginx and uwsgi.

Centos Settings

Check http open ports

semanage port -l | grep http_port_t
#output
http_port_t  tcp      8001, 80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t  tcp      5988

As you can see from the output above with SELinux in enforcing mode http is only allowed to bind to the listed ports. The solution is to add the ports you want to bind on to the list

semanage port -a -t http_port_t  -p tcp 8002

will add port 8002 to the list.

Note: for centos you might need to run this below command.

 setsebool -P httpd_can_network_connect 1
Flask application deployment with nginx and uwsgi
Show Buttons
Hide Buttons