Skip to content

Instantly share code, notes, and snippets.

@ckandoth
Last active August 10, 2019 22:27
Show Gist options
  • Save ckandoth/2281dab10324a7316fcf to your computer and use it in GitHub Desktop.
Save ckandoth/2281dab10324a7316fcf to your computer and use it in GitHub Desktop.
Set up nginx and uwsgi emperor on a CentOS 6.7 box
# GOAL: On a CentOS 6.7 minimal install, set up nginx as a reverse proxy to uWSGI Emperor with python 2.7.11 as a plugin to run Flask apps
# ::NOTE:: All instructions below are run as a sudoer, not as root. Talk to your sysadmins if you're not a sudoer.
# Install bare essentials:
sudo yum install -y epel-release
sudo yum groupinstall 'Development Tools'
sudo yum install -y vim openssl unzip nginx openssl-devel zlib-devel sqlite-devel bzip2-devel libffi-devel lapack-devel blas-devel libpng-devel freetype-devel
# Set SELINUX=disabled in the file below, and reboot, or this tutorial will get unnecessarily complicated:
sudo vim /etc/sysconfig/selinux
#############
### Nginx ###
#############
# Create an nginx virtual host that redirects everything to uWSGI:
# ::NOTE:: Let nginx handle static/media files; it's more efficient at those than uWSGI
sudo vim /etc/nginx/conf.d/uwsgi.conf
## -------------- Contents for /etc/nginx/conf.d/uwsgi.conf -------------- ##
server {
listen 80;
server_name haystack-dev.mskcc.org; # Replace with your IP or FQDN
location / {
include uwsgi_params;
uwsgi_pass unix:/var/tmp/uwsgi.sock;
}
}
## -------------------------------------------------------------------------- ##
# Start the nginx service, and make sure it restarts on reboot:
sudo service nginx start
sudo chkconfig nginx on
################
## Python 2.7 ##
################
# Move to a folder where we can download and build various source code:
cd /opt/common/CentOS_6-dev/python/src
# Point to the folder where we want to install python 2.7:
export PYTHON_PREFIX=/opt/common/CentOS_6-dev/python/python-2.7.11
# Download Python source, configure, make, and install to folder above:
curl -LO https://www.python.org/ftp/python/2.7.11/Python-2.7.11.tgz
tar -zxf Python-2.7.11.tgz
cd Python-2.7.11
./configure --prefix=$PYTHON_PREFIX --enable-shared --enable-unicode=ucs4 LDFLAGS="-Wl,-rpath=$PYTHON_PREFIX/lib"
make
make install
cd ../
# Make sure the latest setuptools and pip are installed:
$PYTHON_PREFIX/bin/python -m ensurepip
$PYTHON_PREFIX/bin/pip install --upgrade setuptools pip
# Install all the various packages we use here at MSKCC:
$PYTHON_PREFIX/bin/pip install --upgrade alabaster ansi argparse azure babel biopython drmaa filemagic fireworks fusepy ipython lockfile markerlib nose powerline-status pygments pyvcf sh snowballstemmer sphinx virtualenv wheel
$PYTHON_PREFIX/bin/pip install --upgrade pysam matplotlib pandas cython scipy
#####################
### uWSGI Emperor ###
#####################
# Move to a folder where we can download and build various source code:
cd /opt/common/CentOS_6-dev/python/src
# Download uWSGI source, build it, an http plugin, and a plugin for our python 2.7 install above:
curl -LO https://github.com/unbit/uwsgi/archive/2.0.12.tar.gz
tar -zxf 2.0.12.tar.gz
cd uwsgi-2.0.12
$PYTHON_PREFIX/bin/python uwsgiconfig.py --build core
$PYTHON_PREFIX/bin/python uwsgiconfig.py --plugin plugins/http core
$PYTHON_PREFIX/bin/python uwsgiconfig.py --plugin plugins/python core python27
# Install uWSGI, and store the plugins where uWSGI will be configured to find it:
sudo cp uwsgi /usr/local/bin/
sudo mkdir -p /usr/local/lib/uwsgi
sudo cp *_plugin.so /usr/local/lib/uwsgi/
cd ../
# Create a unix user+group named uwsgi, which will run the Emperor:
sudo adduser uwsgi
# Create a uWSGI init.d file to start/stop/restart the Emperor as a daemonized service:
sudo vim /etc/init.d/uwsgi
## --------------------- Contents for /etc/init.d/uwsgi --------------------- ##
#!/bin/sh
#
# uwsgi - This script starts and stops the uWSGI emperor
#
# chkconfig: - 85 15
# description: Fast, self-healing, application container server
# processname: uwsgi
# Source function library.
. /etc/rc.d/init.d/functions
PATH=/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
PROG=/usr/local/bin/uwsgi
OWNER=uwsgi
NAME=uwsgi
DAEMON_OPTS="--ini /usr/local/etc/uwsgi.ini --daemonize /var/log/uwsgi.log"
[ -f /etc/sysconfig/uwsgi ] && . /etc/sysconfig/uwsgi
lockfile=/var/lock/subsys/uwsgi
start () {
echo -n "Starting $NAME: "
daemon $PROG $DAEMON_OPTS
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop () {
echo -n "Stopping $NAME: "
killproc $PROG -INT
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
restart () {
stop
start
}
rh_status () {
status $PROG
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart)
$1
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
restart
;;
*)
echo "Usage: $0 {start|stop|restart|condrestart|try-restart|status}" >&2
exit 2
;;
esac
exit 0
## -------------------------------------------------------------------------- ##
# Make it an executable script:
sudo chmod 755 /etc/init.d/uwsgi
# Edit the uWSGI core config file, to customize Emperor defaults:
sudo vim /usr/local/etc/uwsgi.ini
## ---------------------- Contents for /usr/local/etc/uwsgi.ini ----------------------- ##
[uwsgi]
binary-path = /usr/local/bin/uwsgi
uid = uwsgi
gid = uwsgi
plugins-dir = /usr/local/lib/uwsgi
emperor = /srv/www/vassals/*/*.ini
cap = setgid,setuid
## -------------------------------------------------------------------------- ##
# ::NOTE:: Change "/srv/www/vassals" above to where Emperor can glob for subfolders
# with .ini files for each app that it needs to monitor for edits, and load.
# Start uWSGI Emperor, and make sure it restarts on reboot:
sudo service uwsgi start
sudo chkconfig uwsgi on
#########################
### Test 2 Flask Apps ###
#########################
# Create 2 minimalist flask apps, and 1 .ini file for Emperor to find.
## --------------- Contents for /srv/www/vassals/app1/app1.py --------------- ##
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return "<span style='color:red'>Hello World! I am App 1...</span>"
## -------------------------------------------------------------------------- ##
## --------------- Contents for /srv/www/vassals/app2/app2.py --------------- ##
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return "<span style='color:blue'>Hello World! I am App 2...</span>"
## -------------------------------------------------------------------------- ##
## -------------- Contents for /srv/www/vassals/uwsgi/uwsgi.ini --------------- ##
[uwsgi]
socket = /var/tmp/uwsgi.sock
chmod-socket = 666
plugin = /usr/local/lib/uwsgi/python27
mount = /app1=/srv/www/vassals/app1/app1.py
mount = /app2=/srv/www/vassals/app2/app2.py
callable = app
manage-script-name = true
processes = 4
master = true
vacuum = true
## -------------------------------------------------------------------------- ##
# After creating the files above, check Emperor's log file:
sudo tail -n40 /var/log/uwsgi.log
# If it says something like the following, then Emperor loaded it correctly:
# [emperor] vassal /srv/www/vassals/uwsgi/uwsgi.ini is ready to accept requests
# Visit http://haystack-dev.mskcc.org/app1 and http://haystack-dev.mskcc.org/app2 which should
# correctly show their respective Hello World messages.
# If you see a "502 Bad Gateway" message, then the bug is at nginx. See this file for errors:
sudo tail -n40 /var/log/nginx/error.log
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment