1Standalone WSGI Containers 2========================== 3 4There are popular servers written in Python that contain WSGI applications and 5serve HTTP. These servers stand alone when they run; you can proxy to them 6from your web server. Note the section on :ref:`deploying-proxy-setups` if you 7run into issues. 8 9Gunicorn 10-------- 11 12`Gunicorn`_ 'Green Unicorn' is a WSGI HTTP Server for UNIX. It's a pre-fork 13worker model ported from Ruby's Unicorn project. It supports both `eventlet`_ 14and `greenlet`_. Running a Flask application on this server is quite simple:: 15 16 $ gunicorn myproject:app 17 18`Gunicorn`_ provides many command-line options -- see ``gunicorn -h``. 19For example, to run a Flask application with 4 worker processes (``-w 204``) binding to localhost port 4000 (``-b 127.0.0.1:4000``):: 21 22 $ gunicorn -w 4 -b 127.0.0.1:4000 myproject:app 23 24The ``gunicorn`` command expects the names of your application module or 25package and the application instance within the module. If you use the 26application factory pattern, you can pass a call to that:: 27 28 $ gunicorn "myproject:create_app()" 29 30.. _Gunicorn: https://gunicorn.org/ 31.. _eventlet: https://eventlet.net/ 32 33 34uWSGI 35-------- 36 37`uWSGI`_ is a fast application server written in C. It is very configurable 38which makes it more complicated to setup than gunicorn. 39 40Running `uWSGI HTTP Router`_:: 41 42 $ uwsgi --http 127.0.0.1:5000 --module myproject:app 43 44For a more optimized setup, see :doc:`configuring uWSGI and NGINX <uwsgi>`. 45 46.. _uWSGI: https://uwsgi-docs.readthedocs.io/en/latest/ 47.. _uWSGI HTTP Router: https://uwsgi-docs.readthedocs.io/en/latest/HTTP.html#the-uwsgi-http-https-router 48 49Gevent 50------- 51 52`Gevent`_ is a coroutine-based Python networking library that uses 53`greenlet`_ to provide a high-level synchronous API on top of `libev`_ 54event loop:: 55 56 from gevent.pywsgi import WSGIServer 57 from yourapplication import app 58 59 http_server = WSGIServer(('', 5000), app) 60 http_server.serve_forever() 61 62.. _Gevent: http://www.gevent.org/ 63.. _greenlet: https://greenlet.readthedocs.io/en/latest/ 64.. _libev: http://software.schmorp.de/pkg/libev.html 65 66Twisted Web 67----------- 68 69`Twisted Web`_ is the web server shipped with `Twisted`_, a mature, 70non-blocking event-driven networking library. Twisted Web comes with a 71standard WSGI container which can be controlled from the command line using 72the ``twistd`` utility:: 73 74 $ twistd web --wsgi myproject.app 75 76This example will run a Flask application called ``app`` from a module named 77``myproject``. 78 79Twisted Web supports many flags and options, and the ``twistd`` utility does 80as well; see ``twistd -h`` and ``twistd web -h`` for more information. For 81example, to run a Twisted Web server in the foreground, on port 8080, with an 82application from ``myproject``:: 83 84 $ twistd -n web --port tcp:8080 --wsgi myproject.app 85 86.. _Twisted: https://twistedmatrix.com/trac/ 87.. _Twisted Web: https://twistedmatrix.com/trac/wiki/TwistedWeb 88 89.. _deploying-proxy-setups: 90 91Proxy Setups 92------------ 93 94If you deploy your application using one of these servers behind an HTTP proxy 95you will need to rewrite a few headers in order for the application to work. 96The two problematic values in the WSGI environment usually are ``REMOTE_ADDR`` 97and ``HTTP_HOST``. You can configure your httpd to pass these headers, or you 98can fix them in middleware. Werkzeug ships a fixer that will solve some common 99setups, but you might want to write your own WSGI middleware for specific 100setups. 101 102Here's a simple nginx configuration which proxies to an application served on 103localhost at port 8000, setting appropriate headers: 104 105.. sourcecode:: nginx 106 107 server { 108 listen 80; 109 110 server_name _; 111 112 access_log /var/log/nginx/access.log; 113 error_log /var/log/nginx/error.log; 114 115 location / { 116 proxy_pass http://127.0.0.1:8000/; 117 proxy_redirect off; 118 119 proxy_set_header Host $host; 120 proxy_set_header X-Real-IP $remote_addr; 121 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 122 proxy_set_header X-Forwarded-Proto $scheme; 123 } 124 } 125 126If your httpd is not providing these headers, the most common setup invokes the 127host being set from ``X-Forwarded-Host`` and the remote address from 128``X-Forwarded-For``:: 129 130 from werkzeug.middleware.proxy_fix import ProxyFix 131 app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1) 132 133.. admonition:: Trusting Headers 134 135 Please keep in mind that it is a security issue to use such a middleware in 136 a non-proxy setup because it will blindly trust the incoming headers which 137 might be forged by malicious clients. 138 139If you want to rewrite the headers from another header, you might want to 140use a fixer like this:: 141 142 class CustomProxyFix(object): 143 144 def __init__(self, app): 145 self.app = app 146 147 def __call__(self, environ, start_response): 148 host = environ.get('HTTP_X_FHOST', '') 149 if host: 150 environ['HTTP_HOST'] = host 151 return self.app(environ, start_response) 152 153 app.wsgi_app = CustomProxyFix(app.wsgi_app) 154