Over the past six months I’ve been deploying my Python projects using uWSGI and NGINX almost elusively. While they each have an overwhelming number configuration options available, deploying basic apps with them can be pretty painless. Here’s one simple option for setting up your LEMP stack on Ubuntu 12.04 and deploying a Flask application.

Getting started with LEMP

Before installing any new software, make sure your system is up to date. If installing MariaDB, you’ll first need to add the right repository for your release. The below example adds a repository for MariaDB 5.5 on Ubuntu 12.04.

sudo apt-get install python-software-properties
sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xcbcb082a1bb943db
sudo add-apt-repository 'deb http://ftp.osuosl.org/pub/mariadb/repo/5.5/ubuntu precise main'

Regardless of whether or not you’re installing MariaDB, update your package lists and upgrade any necessary packages.

sudo apt-get update
sudo apt-get -y upgrade

Install pip and some dependent packages.

sudo apt-get -y install build-essential debconf-utils python-dev libpcre3-dev libssl-dev python-pip

MariaDB

If the appropriate repository was added, begin MariaDB installation. During this installation you’ll be asked to set a password for the MariaDB root user.

apt-get -y install mariadb-server

Once the installation finishes, run a script and follow the prompts to secure it.

mysql_secure_installation

Nginx

The Nginx package installed by the Ubuntu repository will likely be much older than the current release. This should work just fine for your app, but you’ll miss out any new features and fixes.

sudo apt-get -y install nginx

If you want the newest version of Nginx, you can add the repository for the latest stable release.

sudo add-apt-repository ppa:nginx/stable
sudo apt-get update
sudo apt-get -y install nginx

Visit your server’s hostname or IP address in your browser. If the installation was successful you’ll see a placeholder site that can be disabled by removing its link in sites-enabled.

sudo rm /etc/nginx/sites-enabled/default

Create a new site configuration for you application. Here we’re using a Unix socket instead of TCP.

sudo nano /etc/nginx/sites-available/flaskapp
server {
    listen 80;
    server_name $hostname;

    location /static {
        alias /srv/www/flaskapp/app/static;
    }

    location / { try_files $uri @flaskapp; }
    location @flaskapp {
        include uwsgi_params;
        uwsgi_pass unix:/tmp/flaskapp.sock;
        }
    }

Create directories for your site and link the site’s configuration to sites-enabled so Nginx will use it.

sudo mkdir -p /srv/www/flaskapp/app/static
sudo mkdir -p /srv/www/flaskapp/app/templates
sudo ln -s /etc/nginx/sites-available/flaskapp /etc/nginx/sites-enabled/flaskapp

uWSGI

Install uWSGI with pip and create directories for configuration files and logs.

pip install uwsgi
mkdir /etc/uwsgi
mkdir /var/log/uwsgi

Emperor mode is great for handling apps because it will spawn, stop, and reload processes as necessary. In this deployment the Emperor is started via Upstart with very basic parameters to allow for more flexibility when configuring applications.

sudo nano /etc/init/uwsgi-emperor.conf
description "uWSGI Emperor"
start on runlevel [2345]
stop on runlevel [06]
exec uwsgi --die-on-term --emperor /etc/uwsgi --logto /var/log/uwsgi/uwsgi.log

Create a uWSGI configuration file for your application.

sudo nano /etc/uwsgi/flaskapp.ini
[uwsgi]
chdir = /srv/www/flaskapp
logto = /var/log/uwsgi/flaskapp.log
virtualenv = /srv/www/flaskapp/venv
socket = /tmp/flaskapp.sock
uid = www-data
gid = www-data
master = true
wsgi-file = wsgi.py
callable = app
vacuum = true

Create a simple application file to test the configuration.

sudo nano /srv/www/flaskapp/wsgi.py
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return "It works!"

Final steps

Configuring of the LEMP stack components is almost complete. Now you’ll install Flask within a virtualenv.

sudo pip install virtualenv
cd /srv/www/flaskapp
virtualenv venv
source venv/bin/activate
pip install flask

Change the permissions so www-data can access application files.

sudo chgrp -R www-data /srv/www/*
sudo chmod -R g+rw /srv/www/*
sudo sh -c 'find /srv/www/* -type d -print0 | sudo xargs -0 chmod g+s'

Start uWSGI and restart Nginx.

start uwsgi-emperor
service nginx restart

Visit your server’s hostname or IP in your browser once again. You should see, “It works!”

You have successfully deployed a LEMP stack!

%d bloggers like this: