Setup Nginx And uWSGI For Flask (Python Apps) On Ubuntu 16.04
December 7, 2017Install Python
Install Python 2.x and pip
.
sudo apt-get install python-dev python-pip
sudo -H pip install --upgrade pip
For Python 3.x. For pip command, use pip3 install [PACKAGE]
.
sudo apt-get install python3-pip python3-dev
Install Flask libraries
Create a directory for flask app.
mkdir /code
cd /code
mkdir myapp
cd myapp
Create requirements.txt
with the following content.
# Latest version: https://pypi.python.org/pypi/Flask
Flask==0.12.2
Install virtualenv
, create a virtualenv named env
and activate it.
sudo -H pip install virtualenv
virtualenv env
source env/bin/activate
Install flask
and dependencies into lib
directory.
pip install -t lib -r requirements.txt
Deactivate env
.
deactivate
Create flask app
Make a directory to create flask application within myapp
directory.
mkdir app
cd app
Create python file app.py
within myapp
directory.
import os
import sys
# import libraries in lib directory
base_path = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(base_path, 'lib'))
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return 'Hello'
Create python file run.py
.
from app import app
if __name__ == '__main__':
app.run()
Install uwsgi
Install Python 2.x and uwsgi.
sudo -H pip install uwsgi
Check if uwsgi
is available.
uwsgi --version
Test using uwsgi
to serve the flask app. Make sure the execute this within myapp
directory.
uwsgi --socket 0.0.0.0:8080 --protocol=http -w run:app
Launch another ssh to test if the flask app is accessible.
curl http://localhost:8080
You can configure uwsgi
service to run as service/daemon using Upstart or Systemd.
Running uWSGI via Upstart (Ubuntu 14.04)
Run in uwsgi in Emperor mode to support multiple apps.
Create /etc/init/uwsgi.conf
.
cd /etc/init
sudo nano uwsgi.conf
We shall run uwsgi
using nginx/www-data credential.
# Emperor uWSGI script
description "uWSGI Emperor"
start on runlevel [2345]
stop on runlevel [06]
respawn
exec uwsgi --master --die-on-term --emperor /etc/uwsgi/vassals --uid www-data --gid www-data --daemonize /var/log/uwsgi/emperor.log
Running uWSGI via Systemd (Ubuntu 16.04)
sudo nano /etc/systemd/system/emperor.uwsgi.service
We apply Group=www-data
+ RuntimeDirectory=uwsgi
+ RuntimeDirectoryMode=0775
to enable uWGI access to /var/run/uwsgi/
to write socket file.
[Unit]
Description=uWSGI Emperor
After=network.target
[Service]
Group=www-data
ExecStart=/usr/local/bin/uwsgi --ini /etc/uwsgi/emperor.ini
# Requires systemd version 211 or newer
RuntimeDirectory=uwsgi
RuntimeDirectoryMode=0775
Restart=always
KillSignal=SIGQUIT
Type=notify
# dont log to syslog, follow logto
# StandardError=syslog
NotifyAccess=all
[Install]
WantedBy=multi-user.target
Create /etc/uwsgi/emperor.ini
as uwsgi
configuration file.
cd etc
sudo mkdir uwsgi
cd uwsgi
sudo nano emperor.ini
[uwsgi]
emperor = /etc/uwsgi/vassals
uid = www-data
gid = www-data
logto = /var/log/uwsgi/emperor.log
logfile-chown = www-data:www-data
Create uWSGI app configuration file
Create /etc/uwsgi/vassals/myapp.ini
as uwsgi
app configuration file.
mkdir vassals
cd vassals
sudo nano myapp.ini
[uwsgi]
chdir = /code/myapp
module = run:app
# python env
home = /code/myapp/env
# touch this file to reload the app
touch-reload = /code/myapp/run.py
# logto = /var/log/uwsgi/myapp.log
req-logger = file:/var/log/uwsgi/myapp-request.log
logger = file:/var/log/uwsgi/myapp.log
# master with 2 worker process (based on CPU number)
master = true
processes = 2
# use unix socket for integration with nginx
socket = /var/run/uwsgi/myapp.sock
chmod-socket = 660
# enable socket cleanup when process stop
vacuum = true
# ensure compatibility with init system
die-on-term = true
Create /var/log/uwsgi/
.
sudo mkdir /var/log/uwsgi/
sudo chown www-data:adm /var/log/uwsgi/
sudo chmod 755 /var/log/uwsgi/
Start uwsgi.
sudo service emperor.uwsgi start
Enable the service (autostart when system boot).
sudo systemctl enable emperor.uwsgi
You can also use the following commands.
systemctl start emperor.uwsgi.service
systemctl status emperor.uwsgi.service
systemctl stop emperor.uwsgi.service
systemctl restart emperor.uwsgi.service
Note: if there are error starting uWSGI, you can check the following logs
sudo tail -f /var/log/syslog
sudo tail -f /var/log/uwsgi/emperor.log
sudo tail -f /var/log/uwsgi/myapp.log
Note: you can also configure one service per app in systemd (not using emperor mode).
Install and Setup Nginx for uWSGI
Install Nginx.
sudo apt-get install nginx
Test if Nginx is working.
curl http://localhost
Make a copy of default nginx configuration file.
cd /etc/nginx/sites-available
sudo cp default myapp
Edit the myapp
configuration file.
sudo nano myapp
Configurations which require edit are commented as // EDIT:
.
server {
...
// EDIT: remove default_server
listen 80;
listen [::]:80;
// EDIT:
server_name [DOMAIN_NAME];
// EDIT:
location / {
# try_files $uri $uri/ =404;
include uwsgi_params;
uwsgi_pass unix:/var/run/uwsgi/myapp.sock;
}
}
Enable our new site.
sudo ln -s /etc/nginx/sites-available/food /etc/nginx/sites-enabled
Check if there are any syntax error.
sudo nginx -t
Restart nginx. You can use sudo service nginx restart
as well.
sudo systemctl restart nginx
Test if ngix is serving the Flask up through uWSGI.
curl http://[DOMAIN_NAME]
Allow Nginx port for firewall
List the application configuration which ufw
understand.
sudo ufw app list
Available applications:
- Nginx Full (HTTP + HTTPS)
- Nginx HTTP
- Nginx HTTPS
- OpenSSH
You can choose HTTP or Full (if you plan to enable SSL later)
sudo ufw allow 'Nginx HTTP'
Verify if the changes is successful.
sudo ufw status
Now you can test to access your website from a external browser http://[DOMAIN_NAME]
.
References:
- https://www.digitalocean.com/community/tutorials/how-to-set-up-uwsgi-and-nginx-to-serve-python-apps-on-ubuntu-14-04
- https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-uwsgi-and-nginx-on-ubuntu-16-04
- https://www.digitalocean.com/community/tutorials/how-to-serve-django-applications-with-uwsgi-and-nginx-on-ubuntu-16-04
If you can't, do send some 💖 to @d_luaz or help to share this article.
Pixtory App (Alpha) - easily organize photos on your phone into a blog.
暖心芽 (WIP) 🌞❤️🌱 - reminder of hope, warmth, thoughts and feelings (or just quotes).
LuaPass - offline password manager
- algo-trading
- algolia
- analytics
- android
- android-ktx
- android-permission
- android-studio
- apps-script
- bash
- binance
- bootstrap
- bootstrapvue
- chartjs
- chrome
- cloud-functions
- coding-interview
- contentresolver
- coroutines
- crashlytics
- crypto
- css
- dagger2
- datastore
- datetime
- docker
- eslint
- firebase
- firebase-auth
- firebase-hosting
- firestore
- firestore-security-rules
- flask
- fontawesome
- fresco
- git
- github
- glide
- godot
- google-app-engine
- google-cloud-storage
- google-colab
- google-drive
- google-maps
- google-places
- google-play
- google-sheets
- gradle
- html
- hugo
- inkscape
- java
- java-time
- javascript
- jetpack-compose
- jetson-nano
- kotlin
- kotlin-serialization
- layout
- lets-encrypt
- lifecycle
- linux
- logging
- lubuntu
- markdown
- mate
- material-design
- matplotlib
- md5
- mongodb
- moshi
- mplfinance
- mysql
- navigation
- nginx
- nodejs
- npm
- nuxtjs
- nvm
- pandas
- payment
- pip
- pwa
- pyenv
- python
- recylerview
- regex
- room
- rxjava
- scoped-storage
- selenium
- social-media
- ssh
- ssl
- static-site-generator
- static-website-hosting
- sublime-text
- ubuntu
- unit-test
- uwsgi
- viewmodel
- viewpager2
- virtualbox
- vue-chartjs
- vue-cli
- vue-router
- vuejs
- vuelidate
- vuepress
- web-development
- web-hosting
- webpack
- windows
- workmanager
- wsl
- yarn