Install Python
Install Python 2.x and pip.
sudo apt-get install python-dev python-pipsudo -H pip install --upgrade pipFor Python 3.x. For pip command, use pip3 install [PACKAGE].
sudo apt-get install python3-pip python3-devInstall Flask libraries
Create a directory for flask app.
mkdir /codecd /codemkdir myappcd myappCreate requirements.txt with the following content.
# Latest version: https://pypi.python.org/pypi/Flask
Flask==0.12.2Install virtualenv, create a virtualenv named env and activate it.
sudo -H pip install virtualenvvirtualenv envsource env/bin/activateInstall flask and dependencies into lib directory.
pip install -t lib -r requirements.txtDeactivate env.
deactivateCreate flask app
Make a directory to create flask application within myapp directory.
mkdir appcd appCreate 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 uwsgiCheck if uwsgi is available.
uwsgi --versionTest 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:appLaunch another ssh to test if the flask app is accessible.
curl http://localhost:8080You 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.confWe 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.logRunning uWSGI via Systemd (Ubuntu 16.04)
sudo nano /etc/systemd/system/emperor.uwsgi.serviceWe 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.targetCreate /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-dataCreate 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 = trueCreate /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 startEnable the service (autostart when system boot).
sudo systemctl enable emperor.uwsgiYou can also use the following commands.
systemctl start emperor.uwsgi.servicesystemctl status emperor.uwsgi.servicesystemctl stop emperor.uwsgi.servicesystemctl restart emperor.uwsgi.serviceNote: if there are error starting uWSGI, you can check the following logs
sudo tail -f /var/log/syslogsudo tail -f /var/log/uwsgi/emperor.logsudo 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 nginxTest if Nginx is working.
curl http://localhostMake a copy of default nginx configuration file.
cd /etc/nginx/sites-availablesudo cp default myappEdit the myapp configuration file.
sudo nano myappConfigurations 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-enabledCheck if there are any syntax error.
sudo nginx -tRestart nginx. You can use sudo service nginx restart as well.
sudo systemctl restart nginxTest 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 listAvailable 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 statusNow 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