FAQ

Page Discussion Edit History

HttpUwsgiModuleMultipleDynamicApplications

There is a way to have a single uWSGI instance to provide backend for multiple hosts and/or applications per host:

upstream uwsgi_host {
    server 127.0.0.1:1088;
}
 
include uwsgi_params;
uwsgi_param SCRIPT_NAME   $app;        
uwsgi_param UWSGI_MODULE   $app;
uwsgi_param UWSGI_CALLABLE   "${app}_handler";
uwsgi_param UWSGI_PYHOME   $document_root;
uwsgi_param UWSGI_CHDIR   $document_root;
uwsgi_modifier1   30;   #properly sets PATH_INFO variable
 
server {
    server_name   foo;
    root   /var/www/foo;
 
    location /app1/ {
        set   $app   app1;
        uwsgi_pass   127.0.0.1:1088;
    }
 
    location /app2/ {
        set   $app   app2;
        uwsgi_pass   127.0.0.1:1088;
    }
}
 
server {
    server_name   bar;
    root   /var/www/bar;
 
    location /app1/ {
        set   $app   app1;
        uwsgi_pass   uwsgi_host;
    }
 
    location /app3/ {
        set   $app   app3;
        uwsgi_pass   uwsgi_host;
    }
}

The key aspect of this setup is providing 2 uwsgi protocol parameters: SCRIPT_NAME and SERVER_NAME. While later is handled automatically, since it is mapped in stock /etc/nginx/uwsgi_params file, SCRIPT_NAME variable needs to be passed to backend explicitly because uWSGI roster of vhost applications is keyed on "host|script" and having same host and same script name (which will be blank unless defined) would yield same application handling all requests, whichever was first initialized. Please note the UWSGI_MODULE and UWSGI_CALLABLE variables, first one provides module which is used as entry point of the WSGI application (found by providing UWSGI_PYHOME, which adds parameter to the Python path) and the second variable states the name of class to be instanced.

Minimal set of params of uWSGI in this case would be:

uwsgi -s 127.0.0.1:1088 -M --vhost

And Python modules -

app1.py

def app1_handler(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return b'app1'

app2.py

def app2_handler(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return b'app2'

app3.py

def app3_handler(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return b'app3'

In this setup uWSGI will have two distinct app1 instances (one for host foo based on /var/www/foo/app1.py and one for host bar - /var/www/bar/app1.py), one app2 for foo (/var/www/foo/app2.py) and app3 for bar (/var/www/bar/app3.py).