Uwsgi to run Lua or Python scripts

Introduction

Confusingly, "uwsgi" is both name of the binary application and one of the protocols it supports, while uWSGI is the name of the whole project because it started as a server supporting the WSGI protocol to run Python web applications. uwsgi also supports the FastCGI protocol, but the uwsgi protocol is faster for strings smaller than 64K.

Note that for light-load sites, uwsgi can't be used as a web server directly, with no need for a bigger front-end web server. In addition to its own binary protocol called (you guessed it) "uwsgi", uwsgi also supports FastCGI for higher loads.

If using Nginx as the front-end web server, "nging -V" will show if uwsgi was compiled in the application.

Setup

From a package

  1. apt-get update
  2. apt-cache search uwsgi
  3. apt-cache show uwsgi
  4. apt-get install nginx uwsgi

From source

As of January 2014, the source code has moved to GitHub while the documentation is at ReadTheDocs.

Compiling requires installing a C compiler and Python.

uwsgi can run Lua scripts in two different ways: Plain ol' CGI for small sites (which requires installing the Lua interpreter or LuaJit), or WSAPI for heavier sites (WSAPI is to Lua what WSGI is to Python; The Lua interpreter will be compiled into the uwsgi binary.)

This is how to compile and run uwsgi as a stand-alone HTTP server to serve static files and run Lua scripts.

CGI

  1. Install Lua or LuaJit
  2. apt-get install build-essential python python-dev
  3. make cgi

WSAPI

  1. Install Lua or LuaJit
  2. apt-get install build-essential python python-dev
  3. UWSGICONFIG_LUAPC=luajit
  4. make lua 

Using a configuration file

To avoid passing several parameters at the command prompt, use an INI file. Here's an example:

[uwsgi]
workdir = /tmp/uwsgi-2.0.3
ipaddress = 0.0.0.0
 
http = %(ipaddress):8080
stats = 127.0.0.1:9191
processes = 4
threads = 2
uid=nobody
gid=nogroup
 
static-index = index.html
static-index = index.htm
check-static = %(workdir)/www
static-skip-ext = .lua
 
http-modifier1=9 ;cgi plug-in
 
cgi = /cgi=%(workdir)/cgi
cgi-allowed-ext = .lua
cgi-helper = .lua=lua
cgi-index = index.lua
 
;for use by init script
daemonize = %(workdir)/uwsgi.log
pidfile = %(workdir)/uwsgi.pid

Launch uwsgi: ./uwsgi myapp.ini

Next

http://uwsgi-docs.readthedocs.org/en/latest/CGI.html

http://uwsgi-docs.readthedocs.org/en/latest/Lua.html

http://uwsgi-docs.readthedocs.org/en/latest/HTTP.html

http://uwsgi-docs.readthedocs.org/en/latest/StaticFiles.html

Start/stop script

 

Password-protect directory

Forbid directory listing

Securing uwsgi

Writing a CGI script

  1. print ("\nHello, World")
     
  2. Aim your browser at http://server:8000/mycgi.lua

Features needed

Issues

How to kill uwsgi with no start/stop script?

ps aux | grep uwsgi

kill -SIGINT <PID of master process>

CHECK What's the difference between http, http-socket, and socket?

What does http-modifier1 really do?

How to build apt-get package from uwsgi binary? No need: it's just a single file

How to launch uwsgi as web server, and deliver static HTML pages and run "Hello world" in Lua?

Difference between "make" and "python uwsgiconfig.py"?

How to enable default homepage (index.html)?

How to secure directory?

How to call Lua script from HTML page?

How to secure uwsgi?

How to use sockets instead of TCP?

How to relaunch if crashes?

How to remove Python interpreter and keep Lua interpreter?

How to handle 404?

How to handle form + script?

What's the difference?
python uwsgiconfig.py --plugin plugins/lua
uwsgi --build-plugin plugins/lua

http://uwsgi-docs.readthedocs.org/en/latest/StaticFiles.html

http://uwsgi-docs.readthedocs.org/en/latest/InternalRouting.html

Docs - Reading Notes

http://uwsgi-docs.readthedocs.org/en/latest/

uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191

Note:

- Bind the stats socket to a private address (unless you know what you are doing), otherwise everyone could access it!

- You may want to use “uwsgitop” (just pip install it), which is a top-like tool for monitoring instances.

If you think about writing some init.d script for spawning uWSGI, just sit (and calm) down and check if your system offers you a better (more modern) approach.

Each distribution has chosen its startup system (Upstart, SystemD, etc.) and there are tons of process managers available: Supervisor, god, Circus, etc.

uWSGI will integrate very well with all of them (we hope), but if you plan to deploy a big number of apps check the uWSGI Emperor, it is the dream of every devops.

Always avoid running your uWSGI instances as root. You can drop privileges using the uid and gid options:

To build a basic uwsgi and only include the Lua plug-in: python uwsgiconfig.py --plugin plugins/lua core

Plugins can be compiled statically into the application or as shared libraries.

Graceful reload: uwsgi --reload /tmp/project-master.pid

Stopping the server: uwsgi --stop /tmp/project-master.pid

 

/tmp/uwsgi-2.0# ./uwsgi –show-config

unable to load configuration from –show-config

 

If an HTTP request has a body (like a POST request generated by a form), you have to read (consume) it in your application. If you do not do this, the communication socket with your webserver may be clobbered. If you are lazy you can use the post-buffering option that will automatically read data for you. For Rack applications this is automatically enabled.

If you plan to use UNIX sockets (as opposed to TCP), remember they are standard filesystem objects. This means they have permissions and as such your webserver must have write access to them.

Common sense: do not run uWSGI instances as root. You can start your uWSGIs as root, but be sure to drop privileges with the uid and gid options.

Resources