Install Python
Install Python 2.x and pip
.
sudo apt-get install python-dev python-pipsudo -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 /codecd /codemkdir myappcd 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 virtualenvvirtualenv envsource 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 appcd app
Create python file app.py
within myapp
directory.
import osimport sys# import libraries in lib directorybase_path = os.path.dirname(__file__)sys.path.insert(0, os.path.join(base_path, 'lib'))from flask import Flaskapp = Flask(__name__)@app.route('/')def home(): return 'Hello'
Create python file run.py
.
from app import appif __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/initsudo 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 etcsudo mkdir uwsgicd uwsgisudo 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 vassalscd vassalssudo 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.servicesystemctl status emperor.uwsgi.servicesystemctl stop emperor.uwsgi.servicesystemctl 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-availablesudo 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