Example configurations
This is a list of tips and tricks aimed at showing you how versatile uWSGI is.
Do not use them as copy&paste source, try to understand and adapt them to your setup !!!
Django on Apache
Put a file (named django_wsgi.py) in your project directory:
import os #substitute mysite with the name of your project !!! os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler()
Run the uWSGI server on a TCP socket
uwsgi --socket 127.0.0.1:3031 --chdir <path to your project directory> --pp .. -w django_wsgi
(adding .. to the pythonpath is needed to allows project.app imports styles in your application's files)
or use the xml configuration:
<uwsgi> <socket>127.0.0.1:3031</socket> <chdir>path to your django project directory</chdir> <pythonpath>..</pythonpath> <module>django_wsgi</module> </uwsgi>
uwsgi -x django.xml
Finally, add <Location> directive to apache configuration
<Location /> SetHandler uwsgi-handler uWSGISocket 127.0.0.1:3031 </Location>
Do not forget to load the uwsgi apache2 module in your apache configuration (normally it will be installed in /usr/lib/apache2)
Django again but with fun
Run without configuration files or wsgi module (beware of pythonpath, djtest in this test must be importable):
./uwsgi -s 127.0.0.1:3031 -M -p 4 --env DJANGO_SETTINGS_MODULE=djtest.settings -w "django.core.handlers.wsgi:WSGIHandler()"
Run with only xml
<uwsgi> <socket>127.0.0.1:3031</socket> <master/> <processes>4</processes> <env>DJANGO_SETTINGS_MODULE=djtest.settings</env> <module>django.core.handlers.wsgi:WSGIHandler()</module> </uwsgi>
./uwsgi -x mydjango.xml
...or with a .ini file
[uwsgi] socket = 127.0.0.1:3031 master = true processes = 4 env = DJANGO_SETTINGS_MODULE=djtest.settings module = django.core.handlers.wsgi:WSGIHandler()
./uwsgi --ini mydjango.ini
Pylons and nginx the happy way
add uWSGI configuration directly in your development.ini/production.ini or whatever config file you are using for Pylons
[uwsgi] socket = /tmp/i_am_a_unix_socket.sock master = true processes = 1
./uwsgi --ini-paste <path_to_your_pylons-configuration_file>
finally add a location to nginx.conf
location / {
include uwsgi_params;
uwsgi_pass unix:///tmp/i_am_a_unix_socket.sock;
}
Pyramid and nginx
The same as Pylons and nginx
Trac on apache in a sub-uri
Put this wsgi script (call it mytrac.py) in a dir in the pythonpath (or add the dir with the <pythonpath> directive)
import os import trac.web.main os.environ['TRAC_ENV'] = '<absolute_path_to_trac_project>' applications = {'/trac':trac.web.main.dispatch_request}
Run the server
uwsgi -s /tmp/uwsgi.sock -C -w mytrac
Modify apache
<Location /trac> SetHandler uwsgi-handler uWSGISocket /tmp/uwsgi.sock </Location>
Better trac (on /)
uwsgi -s /tmp/uwsgi.sock -C -w trac.web.main:dispatch_request --env TRAC_ENV=<absolute_path_to_trac_project>
Django and Mercurial just married
import uwsgi from mercurial import demandimport; demandimport.enable() from mercurial.hgweb.hgwebdir_mod import hgwebdir hgapp = hgwebdir('hgweb.config') import os os.environ['DJANGO_SETTINGS_MODULE'] = 'app.settings' import django.core.handlers.wsgi djangoapp = django.core.handlers.wsgi.WSGIHandler() uwsgi.applications = {'':djangoapp, '/hg':hgapp}
Web2Py (2uWSGI)
This is the "one-man-band" of all python frameworks.
Unzip it in your directory of choice and...
./uwsgi --pythonpath <path_to_your_web2py_dir> --module wsgihandler -s /tmp/we2py.sock
or
<uwsgi> <pythonpath>path_to_your_web2py_dir</pythonpath> <module>wsgihandler</module> <socket>/tmp/web2py.sock</socket> <master/> <processes>8</processes> <memory-report/> </uwsgi>
./uwsgi -x myweb2py.xml
Web2Py behind Mongrel2
Some environ vars were not set or set incorrectly in older versions of uWSGI.
Add the following to gluon/main.py in the wsgibase function, directly below the comment block ( # handle fcgi ....), at the top of the triple nested try statement (align with the comment and other code there!):
uwsgi = environ.get('uwsgi.version')
if uwsgi:
uwsgi_version = []
for x in uwsgi.split('.'):
for y in x.split('-'):
if y == 'dev':
y = -1
uwsgi_version.append(int(y))
if uwsgi and uwsgi_version < [1, 1, -1, 1996]:
# handles uWSGI broken path_info AND missing QUERY_STRING
environ['PATH_INFO'] = ''
if uwsgi and not environ.get('REMOTE_ADDR'):
# REMOTE_ADDR is used for logging, which silently fails
environ['REMOTE_ADDR'] = environ.get('HTTP_X_FORWARDED_FOR',
'address.unknown')
3 Web2Py instances, one XML configuration
(please do not get too excited about the next lines)
<foo> <uwsgi id="app1"> <pythonpath>app1/web2py</pythonpath> <module>wsgihandler</module> <master/> <processes>4</processes> <socket>/tmp/web2py_app1.sock</socket> </uwsgi> <uwsgi id="app2"> <pythonpath>app2/web2py</pythonpath> <module>wsgihandler</module> <master/> <processes>4</processes> <socket>/tmp/web2py_app2.sock</socket> </uwsgi> <uwsgi id="app3"> <pythonpath>app3/web2py</pythonpath> <module>wsgihandler</module> <master/> <processes>4</processes> <socket>/tmp/web2py_app3.sock</socket> </uwsgi> </foo>
Now run 3 instances of uwsgi
./uwsgi -x megaconf.xml:app1 ./uwsgi -x megaconf.xml:app2 ./uwsgi -x megaconf.xml:app3
Ok, i have heard you... "Why the fu*k i cannot use 3 different xml files ?"
You can, but then you cannot do this magic:
<uwsgi> <pythonpath id="app1">app1/web2py</pythonpath> <pythonpath id="app2">app2/web2py</pythonpath> <pythonpath id="app3">app3/web2py</pythonpath> <module>wsgihandler</module> <master/> <processes>4</processes> <socket id="app1">/tmp/web2py_app1.sock</socket> <socket id="app2">/tmp/web2py_app2.sock</socket> <socket id="app3">/tmp/web2py_app3.sock</socket> </uwsgi>
A little note:
We have used the <foo> root tag for multiple <uwsgi> blocks. This can be every name you want. This will allows you to put <uwsgi> configurations on other xml files.
Flask deploy
Flask is an amazing microframework. Deploying it on uWSGI is super-fast/super-easy
(call it myapp.py)
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return "Hello World!" if __name__ == '__main__': app.run()
./uwsgi -s /tmp/mysock.sock --module myapp --callable app
or
./uwsgi -s /tmp/mysock.sock -w myapp:app
UNIX gurus, please sit down
No description, only code for real men
#!/bin/sh export UWSGI_SOCKET=/tmp/uwsgi.sock export UWSGI_MODULE=trac.web.main export UWSGI_CALLABLE=dispatch_request export UWSGI_MASTER=1 export UWSGI_PROCESSES=8 export UWSGI_MEMORY_REPORT=1 export UWSGI_HARAKIRI=30 export TRAC_ENV=/tmp/mytrac exec /usr/bin/uwsgi
The shebang mess
On systems like FreeBSD or OSX you can do funny things like this:
#!/usr/bin/uwsgi --socket :3031 --callable app from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return "Hello World!" if __name__ == '__main__': app.run()
but on (for example) Linux systems you will get:
uwsgi: unrecognized option '--socket :3031 --callable app'
sadly there is no easy fix :(
Use the embedded HTTP server/router
Oh yes, you do not need to have a real webserver:
./uwsgi --http 127.0.0.1:8080 --module myapp --callable app
this will run myapp:app on http port 8080
Force uWSGI to natively speaks HTTP (or fastcgi)
listen on http port 8090
./uwsgi --socket :8090 --protocol=http --module myapp --callable app
listen on fastcgi port 5000
./uwsgi --socket :5000 --protocol=fastcgi --module myapp --callable app
MoinMoin online now
Untar the moinmoin tarball and simply run uWSGI from moin-x.xx directory:
/usr/bin/uwsgi -s /tmp/moin.sock --wsgi-file wiki/server/moin.wsgi -M -p 4
you can mount it on a subdir (example: /wiki) with:
/usr/bin/uwsgi -s /tmp/moin.sock --mount /wiki=wiki/server/moin.wsgi -M -p 4
then change your apache config
<Location /wiki> SetHandler uwsgi-handler uWSGISocket /tmp/moin.sock </Location>
or nginx
location /wiki {
include uwsgi_params;
uwsgi_param SCRIPT_NAME /wiki;
uwsgi_modifier1 30;
uwsgi_pass unix:/tmp/uwsgi.sock;
}
Bazaar smart server in virtualenv with <eval> config
virtualenv mybzr ./mybzr/bin/easy_install bzr
Now create an xml configuration file with embedded wsgi module
<uwsgi> <processes>4</processes> <master/> <home>bzu</home> <socket>:8001</socket> <memory-report/> <eval> from bzrlib.transport.http import wsgi application = wsgi.make_app("/Users/serena/bzr", "/", readonly=False) </eval> </uwsgi>
Yes, it is fun but what if my python code contains (xml)invalid symbols (like <,>,&) ?
use the xml CDATA feature:
<uwsgi> <processes>4</processes> <master/> <home>bzu</home> <socket>:8001</socket> <memory-report/> <![CDATA[ from bzrlib.transport.http import wsgi application = wsgi.make_app("/Users/serena/bzr", "/", readonly=False) ]]> </uwsgi>
...and run
./uwsgi -x bazaar.xml
(Django + PEP-370 + shell scripting) unleashed
(only for python >= 2.6)
install Django in a user directory (with pip):
export PYTHONUSERBASE=/home/damjan/django-app/env pip install --user Django
create a shell script in your Django project directory (/home/damjan/django-app/django370.sh):
#!/bin/sh DIRNAME=`dirname $0` cd $DIRNAME export PYTHONUSERBASE=$DIRNAME/env export UWSGI_MODULE="django.core.handlers.wsgi" export UWSGI_CALLABLE="WSGIHandler()" export DJANGO_SETTINGS_MODULE="myapp.settings" exec /usr/local/bin/uwsgi "$@"
chmod +x it
run it !!!:
/home/damjan/django-app/django370.sh -M -p 4 --socket 127.0.0.1:1717
Werkzeug test_app with embedded http server port 9090
./uwsgi -w werkzeug.testapp:test_app --http :9090
Two Pinax site in two virtualenv in two virtualhost with only one uWSGI instance
We have two virtualenv, DJANGOVENVS/pinax1 and DJANGOVENVS/pinax2.
Each virtualenv contains a pinax site in the directory 'pinaxsite' and a script (called pinax.py) in every pinaxsite/deploy directory (that is a copy of deploy/pinax.wsgi)
Now configure nginx
server {
listen 8080;
server_name sirius.local;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:3031;
uwsgi_param UWSGI_PYHOME /Users/roberto/DJANGOVENVS/pinax1;
uwsgi_param UWSGI_SCRIPT deploy.pinax;
uwsgi_param UWSGI_CHDIR /Users/roberto/DJANGOVENVS/pinax1/pinaxsite;
}
}
server {
listen 8080;
server_name localhost;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:3031;
uwsgi_param UWSGI_PYHOME /Users/roberto/DJANGOVENVS/pinax2;
uwsgi_param UWSGI_SCRIPT deploy.pinax;
uwsgi_param UWSGI_CHDIR /Users/roberto/DJANGOVENVS/pinax2/pinaxsite;
}
}
and run uWSGI in VirtualHosting mode
./uwsgi -s :3031 -M -p 10 --vhost --no-site
web.py the raw way
Add a WSGI callable to your app:
application = app.wsgifunc()
example: (call it testapp.py)
import web urls = ( '/(.*)', 'hello' ) app = web.application(urls, globals()) class hello: def GET(self, name): if not name: name = 'World' return 'Hello, ' + name + '!' application = app.wsgifunc()
run it:
./uwsgi -s /tmp/web.py.socket -w testapp
Step by step guide for repoze.plone
Oh yes, you can run Plone with uWSGI...
You need python2 .4
wget http://www.python.org/ftp/python/2.4.6/Python-2.4.6.tar.bz2 tar jxvf Python-2.4.6.tar.bz2 cd Python-2.4.6 ./configure --prefix=/opt/uPlone make make install wget http://peak.telecommunity.com/dist/ez_setup.py /opt/uPlone/bin/python ez_setup.py /opt/uPlone/bin/easy_install -i http://dist.repoze.org/plone/latest/simple repoze.plone wget http://projects.unbit.it/downloads/uwsgi-latest.tar.gz tar zxvf uwsgi-latest.tar.gz cd uwsgi-X.X.X /opt/uPlone/bin/python uwsgiconfig.py --build cp uwsgi /opt/uPlone/bin cd /opt/uPlone ./bin/mkzope2instance . ./bin/addzope2user admin admin ./bin/uwsgi --http :9090 -M --memory-report -T --ini-paste etc/zope2.ini
Beware of cd uwsgi-X.X.X line, it must be substituted with the right uwsgi source directory
Remember that Zope startup can be slow, so wait until all the workers are spawned before connecting
Some Zope module use threads, so remeber to add -T
ZODB does not coop well with multiprocess environments so starts only 1 worker, or use ZEO and spawn all the workers you want.
If you are using a version >= 0.9.7 you can start more threads per worker using the --threads <n> option. Single-worker+threads works flawlessly with zope/plone
./bin/uwsgi --socket /tmp/uwsgi.sock --chmod -M --memory-report --ini-paste etc/zope2.ini --threads 10
Save your resources when your apps are idle
Use the --idle flag
uwsgi --master --idle 30 --processes 4 --socket /tmp/uwsgi.sock --wsgi-file myapp.wsgi
After 30 seconds of inactivity the workers will be taken off. At the first request they will be respawned.
Massive Django hosting with automagic config and lower resource impact (nginx+Emperor+fastrouter+subscriptions+idle, requires uWSGI 0.9.8.1)
There are various options to host massive applications, this example will show one that require pratically no work to add new apps after the initial setup.
First, configure nginx
location / {
include uwsgi_params;
# force the fastrouter to use the Host header as key for domain:app mappings
uwsgi_param UWSGI_FASTROUTER_KEY $host;
uwsgi_pass /tmp/fastrouter.socket
}
On every request, nginx will contact the FastRouter asking for a specific hostname.
Now we will create a magic config template for a Django app (supposing all of the projects are in /var/apps and will run as django uid/gid).
Each project wil be available at <projectname>.example.com and all of the domains (one-per-line) specified in the file domains.txt in each project dir.
[uwsgi] djangoproject = /var/apps/%n/ env = DJANGO_SETTINGS_MODULE=%n.settings pymodule-alias = %n=%(djangoproject) chdir = %(djangoproject) module = django.core.handlers.wsgi:WSGIHandler() socket = 127.0.0.1:0 master = true processes = 4 idle = 3600 uid = django gid = django subscribe-to = 127.0.0.1:3032:%n.example.com subscribe-to = 127.0.0.1:3032:@%(djangoproject)/domains.txt
the first directive create a config placeholder (the absolute path of the project dir) that will be used in the rest of the config file
the socket option use '0' as the port number. This will bind to a random port. This is not a problem as the Subscription subsystem will communicate it to the fastrouter.
With idle we inform the master of the instance to shut down worker inactive for more than 1 hour.
The last subscribe-to directive use the @ to inform the master to take the key from a file
Move this file in /etc/djangoapps (this is the directory that will be scanned by the emperor for new django apps) and call it 'django_base' (or something similar without extension, so the emperor will not consider it as a valid config file)
Now let's spawn the emperor and the fastrouter
uwsgi --master --emperor /etc/djangoapps --fastrouter /tmp/fastrouter.socket --fastrouter-subscription-server 127.0.0.1:3032
We are ready, copy your project to /var/apps and spawn it simply symlinking /etc/djangoapps/django_base to /etc/djangoapps/<projectname>.ini
Example (for a project in /var/apps/pinax000)
ln -s /etc/djangoapps/django_base /etc/djangoapps/pinax000.ini
When you want to remove the app simply remove the symlink (or touch it for a reload)
... and massive RubyOnRails hosting with aggressive memory control and zerg mode
This is the same setup of the previous example but using yaml files (directly linked in rails root of each app) and a second template used for ZergMode.
WARNING in this example we use the libyaml-based parser (selected at uWSGI compile time if available). If you are using the embedded one (simpler, dumber but more tolerant) simply remove the ticks surrounding the strings in the config files
We suppose a Rails3 style application (refinerycms is a good candidate) with config.ru file.
Let's define our base template (we will put it in /etc/uwsgi/rails_base_template)
uwsgi: plugins: rack master: 1 processes: 4 memory-report: 1 railsroot: "/var/railsapps/%c" chdir: "%(railsroot)" rack: "%(railsroot)/config.ru" idle: 300 ruby-gc-freq: 10 subscribe-to: "127.0.0.1:3032:%c.example.com,7" subscribe-to: 127.0.0.1:3032:@domains.txt socket: 127.0.0.1:0 show-config: 1 post-buffering: 4096 zerg-server: "/var/run/zergs/%n.sock" reload-on-rss: 256
Instead of %n, this time we will use %c. It resolve to the name of the dir containing the config file. In this way we can put a uwsgi_base.yml in each rails root and add various links to zerg instances in the same directory.
the subscription system is the same. The only difference is on specifying the modifier (Rack uses the 7) with an additional (comma separated) section.
post-buffering is required for rack apps
ruby-gc-freq will set after how many requests the ruby GC must be called.
idle mode is set to 5 minutes (do not be afraid of slow-rails-startup as copy-on-write is used all over the place)
show-config is used to print a ini style image of the current configuration. This is a good form of first-aid debugging.
reload-on-rss will reload workers using more that 256 megs of physical memory.
then we define a template for zergs (we will put it in /etc/uwsgi/rails_zerg_template):
uwsgi: plugins: rack master: 1 processes: 2 memory-report: 1 railsroot: "/var/railsapps/%c" chdir: "%(railsroot)" rack: "%(railsroot)/config.ru" idle: 300 ruby-gc-freq: 10 post-buffering: 4096 zerg: "/var/run/zergs/%c.sock" reload-on-rss: 256
we set only 2 process for each zerg instance. There is no need for subscription as the original instance will continue to send data to the fastrouter.
If you want your zergs to be able to survive on main instance death, add subscriptions even in the zerg template
Now run the emperor with glob style search path
uwsgi --master --emperor /var/railsapps/*/uwsgi_*.yml --fastrouter /tmp/fastrouter.socket --fastrouter-subscription-server 127.0.0.1:3032
To add a rails instance make a link from base template to uwsgi.yml in your rails root
ln -s /etc/uwsgi/rails_base_template /var/railsapps/app000/uwsgi_base.yml ln -s /etc/uwsgi/rails_base_template /var/railsapps/a_second_app/uwsgi_base.yml ln -s /etc/uwsgi/rails_base_template /var/railsapps/a_third_app/uwsgi_base.yml ... and so on ...
Then app000 start being slashdotted and we need to add power to it
(remember to check if you have enough resources to add more workers)
ln -s /etc/uwsgi/rails_zerg_template /var/railsapps/app000/uwsgi_zerg1.yml
hmm not enough power, let's add another zerg
ln -s /etc/uwsgi/rails_zerg_template /var/railsapps/app000/uwsgi_zerg2.yml
When local resources are finished you will need to add another server.
Simply follow the same setup but without enabling fastrouter and without running nginx.
The second server will subscribe to the fastrouter on the first one (remember to bind the subscription server to a routable address) and load balancing will happen automagically.
Example on node1:
uwsgi --master --emperor /var/railsapps/*/uwsgi_*.yml --fastrouter /tmp/fastrouter.socket --fastrouter-subscription-server 192.168.0.1:3032
On node2 simply:
uwsgi --master --emperor /var/railsapps/*/uwsgi_*.yml
And change subscriptions to point to address 192.168.0.1:3032
uwsgi: plugins: rack master: 1 processes: 4 memory-report: 1 railsroot: "/var/railsapps/%c" chdir: "%(railsroot)" rack: "%(railsroot)/config.ru" idle: 300 ruby-gc-freq: 10 subscribe-to: "192.168.0.1:3032:%c.example.com,7" subscribe-to: 192.168.0.1:3032:@domains.txt socket: 127.0.0.1:0 show-config: 1 post-buffering: 4096 zerg-server: "/var/run/zergs/%n.sock" reload-on-rss: 256
You can add all of the nodes you want and subscribe them to the main.
Using python Queue module for implementing async management of long running task
Remember to add --enable-threads and --master
import Queue from threading import Thread import uwsgi CONSUMERS = 4 def consumer(q): while True: item = q.get() print(item) #... DO A HEAVY TASK HERE ... q.task_done() def spawn_consumers(): global q q = Queue.Queue() for i in range(CONSUMERS): t = Thread(target=consumer,args=(q,)) t.daemon = True t.start() print("consumer %d on worker %d started" % (i, uwsgi.worker_id())) # set the function to call after each fork() uwsgi.post_fork_hook = spawn_consumers def application(env, start_response): global q # we pass a copy of the env dictionary as it gets cleared after yield/return q.put(env.copy()) start_response('200 OK', [('Content-Type', 'text/html')]) #end the request yield "Task enqueued"
Execute a function every 30 seconds in the spooler
Abuse uWSGI Decorators, they kick ass !!!
from uwsgidecorators import * @timer(30, target='spooler') def hello_world(signum): print("30 seconds elapsed")
The interesting part is the target attribute. It points to the process (the spooler in this case) that has to execute the handler
Config via pipe
print """ [uwsgi] socket = :3031 module = welcome """
python generate.py | uwsgi --ini -
A bottle app+uWSGI embedded in the same binary
uWSGI 0.9.8.2 (many thanks to Cal Leeming of Simplicity Media Ltd for the idea) has the possibility to embed binary files (config files included) in its executable.
To add files simply list them in your build profile:
[uwsgi] inherit = default embed_files = uwsgidecorators.py,bottle.py,foobar.jpg embed_config = myapp.ini
running
python uwsgiconfig.py --build <buildprofile>
will create a uWSGI binary with 3 files and 1 configuration linked in
You can now reference those files with sym://symbol
where symbol is the name of the embedded files with . and / substituted with _ (bottle.py will be bottle_py and so on)
uwsgi --pymodule-alias bottle=sym://bottle_py
will map the bottle module to the file embedded as bottle_py
Let's see a full example
- step 1, the WSGI bottle app (myapp.py)
from bottle import route, run, default_app @route('/:name') def index(name='World'): return '<b>Hello %s!</b>' % name application = default_app()
- step 2, the uWSGI config file (myapp.ini)
[uwsgi] pymodule-alias = bottle=sym://bottle_py file = sym://myapp_py socket = :3031
- step 3, the build profile (buildconf/allinone.ini)
[uwsgi] inherit = default embed_files = bottle.py,myapp.py embed_config = myapp.ini
- step 4, build them all
python uwsgiconfig --build allinone
- step 5, simply run uwsgi ;)
./uwsgi
Varnish and nginx, the best way (0.9.8.4)
Starting from 0.9.8.4 the http parser of uWSGI has been extremely improved. Normally you would put nginx+uwsgi behind varnish. This is a completely WASTE OF RESOURCES.
If you have written your app to map static assets to an external domain, you can simply put uWSGI directly behind varnish and leave nginx alone to serve static files.
To start uWSGI in high-performance http mode (beware, this is completely different from the --http option given by the http plugin)
uwsgi --http-socket 127.0.0.1:3031 --master --processes 4 --module myapp
(as you can see it is a normal uwsgi startup command line, with the addition of --http-socket instead of --socket)
Now point your varnish to the uwsgi http socket
backend uwsgi { .host = "127.0.0.1"; .port = "3031"; } sub vcl_recv { set req.backend = uwsgi; }
pretty boring...
What about load balancing between multiple uwsgi instances ?
backend uwsgi0 { .host = "127.0.0.1"; .port = "3031"; } backend uwsgi1 { .host = "192.168.0.17"; .port = "3031"; } director uwsgi round-robin { { .backend = uwsgi0; } { .backend = uwsgi1; } } sub vcl_recv { set req.backend = uwsgi; }
obviously you can add probe objects if you want to have a more reliable healthcheck system.
What about putting nginx behind varnish ?
Pretty easy, simply add nginx as a new backend and route specific requests to it:
backend uwsgi { .host = "127.0.0.1"; .port = "8080"; } backend nginx { .host = "127.0.0.1"; .port = "80"; } sub vcl_recv { if (req.url ~ "^/images") { set req.backend = nginx; } else { set req.backend = uwsgi; } }
Cheroke wizard for single-process 2 + flask+trac
Recent Cherokee uWSGI wizard can load all of the uWSGI config files.
The following config file (.ini format) will load 2 flask apps and a trac one in the same process. Use it as the default handler for your site/virtualhost
[uwsgi] ; this will search for app callable (as normally used by flask apps) callable = app ; the first flask app mounted under /app1 mount = /app1:/home/spock/apps/myapp1.py ; the second one mount = /app2:/home/spock/apps/myapp2.py ; the third one (trac) env = TRAC_ENV=path_to_trac_project mount = /trac=trac.web.main:dispatch_request ; this will instruct uWSGI to automatically rebuild requests without the help of cherokee manage-script-name = true
Binding the http router on privileged (80) ports
Binding on port 80 requires root privileges. Obviously it is bad to run the uWSGI stack as root, you will always want to drop its privileges.
Use shared sockets:
./uwsgi --shared-socket :80 --http =0 --uid 1000 --gid 1000
That means: create a socket on port 80 that can be used by various components. The "http" component will use it thanks to the '=n' form (n is the number of socket to use)
