Preparar para publicar en Read the Docs

Signed-off-by: Edgar Alvarado Taleno <edgar.alvaradotaleno@ucr.ac.cr>
This commit is contained in:
Edgar Alvarado Taleno 2025-04-10 15:52:02 -06:00
parent b78b5a210b
commit 77f3f78332
190 changed files with 48425 additions and 102 deletions

View file

@ -0,0 +1,158 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Apache httpd &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Using async and await" href="../async-await.html" />
<link rel="prev" title="nginx" href="nginx.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="../async-await.html" title="Using async and await"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="nginx.html" title="nginx"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Apache httpd</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="apache-httpd">
<h1>Apache httpd<a class="headerlink" href="#apache-httpd" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://httpd.apache.org/">Apache httpd</a> is a fast, production level HTTP server. When serving
your application with one of the WSGI servers listed in <a class="reference internal" href="index.html"><span class="doc">Deploying to Production</span></a>, it
is often good or necessary to put a dedicated HTTP server in front of
it. This “reverse proxy” can handle incoming requests, TLS, and other
security and performance concerns better than the WSGI server.</p>
<p>httpd can be installed using your system package manager, or a pre-built
executable for Windows. Installing and running httpd itself is outside
the scope of this doc. This page outlines the basics of configuring
httpd to proxy your application. Be sure to read its documentation to
understand what features are available.</p>
<section id="domain-name">
<h2>Domain Name<a class="headerlink" href="#domain-name" title="Link to this heading"></a></h2>
<p>Acquiring and configuring a domain name is outside the scope of this
doc. In general, you will buy a domain name from a registrar, pay for
server space with a hosting provider, and then point your registrar
at the hosting providers name servers.</p>
<p>To simulate this, you can also edit your <code class="docutils literal notranslate"><span class="pre">hosts</span></code> file, located at
<code class="docutils literal notranslate"><span class="pre">/etc/hosts</span></code> on Linux. Add a line that associates a name with the
local IP.</p>
<p>Modern Linux systems may be configured to treat any domain name that
ends with <code class="docutils literal notranslate"><span class="pre">.localhost</span></code> like this without adding it to the <code class="docutils literal notranslate"><span class="pre">hosts</span></code>
file.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">/etc/hosts</span></code></span><a class="headerlink" href="#id2" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="mf">127.0.0.1</span> <span class="n">hello</span><span class="o">.</span><span class="n">localhost</span>
</pre></div>
</div>
</div>
</section>
<section id="configuration">
<h2>Configuration<a class="headerlink" href="#configuration" title="Link to this heading"></a></h2>
<p>The httpd configuration is located at <code class="docutils literal notranslate"><span class="pre">/etc/httpd/conf/httpd.conf</span></code> on
Linux. It may be different depending on your operating system. Check the
docs and look for <code class="docutils literal notranslate"><span class="pre">httpd.conf</span></code>.</p>
<p>Remove or comment out any existing <code class="docutils literal notranslate"><span class="pre">DocumentRoot</span></code> directive. Add the
config lines below. Well assume the WSGI server is listening locally at
<code class="docutils literal notranslate"><span class="pre">http://127.0.0.1:8000</span></code>.</p>
<div class="literal-block-wrapper docutils container" id="id3">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">/etc/httpd/conf/httpd.conf</span></code></span><a class="headerlink" href="#id3" title="Link to this code"></a></div>
<div class="highlight-apache notranslate"><div class="highlight"><pre><span></span><span class="nb">LoadModule</span><span class="w"> </span>proxy_module<span class="w"> </span>modules/mod_proxy.so
<span class="nb">LoadModule</span><span class="w"> </span>proxy_http_module<span class="w"> </span>modules/mod_proxy_http.so
<span class="nb">ProxyPass</span><span class="w"> </span>/<span class="w"> </span>http://127.0.0.1:8000/
<span class="nb">RequestHeader</span><span class="w"> </span>set<span class="w"> </span>X-Forwarded-Proto<span class="w"> </span>http
<span class="nb">RequestHeader</span><span class="w"> </span>set<span class="w"> </span>X-Forwarded-Prefix<span class="w"> </span>/
</pre></div>
</div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">LoadModule</span></code> lines might already exist. If so, make sure they are
uncommented instead of adding them manually.</p>
<p>Then <a class="reference internal" href="proxy_fix.html"><span class="doc">Tell Flask it is Behind a Proxy</span></a> so that your application uses the <code class="docutils literal notranslate"><span class="pre">X-Forwarded</span></code>
headers. <code class="docutils literal notranslate"><span class="pre">X-Forwarded-For</span></code> and <code class="docutils literal notranslate"><span class="pre">X-Forwarded-Host</span></code> are automatically
set by <code class="docutils literal notranslate"><span class="pre">ProxyPass</span></code>.</p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Apache httpd</a><ul>
<li><a class="reference internal" href="#domain-name">Domain Name</a></li>
<li><a class="reference internal" href="#configuration">Configuration</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="nginx.html" title="previous chapter">nginx</a>
<li>Next: <a href="../async-await.html" title="next chapter">Using <code class="docutils literal notranslate"><span class="pre">async</span></code> and <code class="docutils literal notranslate"><span class="pre">await</span></code></a></ul>
</li>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><div id="ethical-ad-placement"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2010 Pallets.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>

View file

@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ASGI &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Tell Flask it is Behind a Proxy" href="proxy_fix.html" />
<link rel="prev" title="eventlet" href="eventlet.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="proxy_fix.html" title="Tell Flask it is Behind a Proxy"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="eventlet.html" title="eventlet"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">ASGI</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="asgi">
<h1>ASGI<a class="headerlink" href="#asgi" title="Link to this heading"></a></h1>
<p>If youd like to use an ASGI server you will need to utilise WSGI to
ASGI middleware. The asgiref
<a class="reference external" href="https://github.com/django/asgiref#wsgi-to-asgi-adapter">WsgiToAsgi</a>
adapter is recommended as it integrates with the event loop used for
Flasks <a class="reference internal" href="../async-await.html#async-await"><span class="std std-ref">Using async and await</span></a> support. You can use the adapter by
wrapping the Flask app,</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">asgiref.wsgi</span><span class="w"> </span><span class="kn">import</span> <span class="n">WsgiToAsgi</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">Flask</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
<span class="o">...</span>
<span class="n">asgi_app</span> <span class="o">=</span> <span class="n">WsgiToAsgi</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
</pre></div>
</div>
<p>and then serving the <code class="docutils literal notranslate"><span class="pre">asgi_app</span></code> with the ASGI server, e.g. using
<a class="reference external" href="https://github.com/pgjones/hypercorn">Hypercorn</a>,</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ hypercorn module:asgi_app
</pre></div>
</div>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="eventlet.html" title="previous chapter">eventlet</a>
<li>Next: <a href="proxy_fix.html" title="next chapter">Tell Flask it is Behind a Proxy</a></ul>
</li>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><div id="ethical-ad-placement"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2010 Pallets.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>

View file

@ -0,0 +1,167 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>eventlet &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="ASGI" href="asgi.html" />
<link rel="prev" title="gevent" href="gevent.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="asgi.html" title="ASGI"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="gevent.html" title="gevent"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">eventlet</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="eventlet">
<h1>eventlet<a class="headerlink" href="#eventlet" title="Link to this heading"></a></h1>
<p>Prefer using <a class="reference internal" href="gunicorn.html"><span class="doc">Gunicorn</span></a> with eventlet workers rather than using
<a class="reference external" href="https://eventlet.net/">eventlet</a> directly. Gunicorn provides a much more configurable and
production-tested server.</p>
<p><a class="reference external" href="https://eventlet.net/">eventlet</a> allows writing asynchronous, coroutine-based code that looks
like standard synchronous Python. It uses <a class="reference external" href="https://greenlet.readthedocs.io/en/latest/">greenlet</a> to enable task
switching without writing <code class="docutils literal notranslate"><span class="pre">async/await</span></code> or using <code class="docutils literal notranslate"><span class="pre">asyncio</span></code>.</p>
<p><a class="reference internal" href="gevent.html"><span class="doc">gevent</span></a> is another library that does the same thing. Certain
dependencies you have, or other considerations, may affect which of the
two you choose to use.</p>
<p>eventlet provides a WSGI server that can handle many connections at once
instead of one per worker process. You must actually use eventlet in
your own code to see any benefit to using the server.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>When using eventlet, greenlet&gt;=1.0 is required, otherwise context locals
such as <code class="docutils literal notranslate"><span class="pre">request</span></code> will not work as expected. When using PyPy,
PyPy&gt;=7.3.7 is required.</p>
<p>Create a virtualenv, install your application, then install
<code class="docutils literal notranslate"><span class="pre">eventlet</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install eventlet
</pre></div>
</div>
</section>
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>To use eventlet to serve your application, write a script that imports
its <code class="docutils literal notranslate"><span class="pre">wsgi.server</span></code>, as well as your app or app factory.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">wsgi.py</span></code></span><a class="headerlink" href="#id2" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">eventlet</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">eventlet</span><span class="w"> </span><span class="kn">import</span> <span class="n">wsgi</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">hello</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">create_app</span><span class="p">()</span>
<span class="n">wsgi</span><span class="o">.</span><span class="n">server</span><span class="p">(</span><span class="n">eventlet</span><span class="o">.</span><span class="n">listen</span><span class="p">((</span><span class="s2">&quot;127.0.0.1&quot;</span><span class="p">,</span> <span class="mi">8000</span><span class="p">)),</span> <span class="n">app</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ python wsgi.py
(x) wsgi starting up on http://127.0.0.1:8000
</pre></div>
</div>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>eventlet should not be run as root because it would cause your
application code to run as root, which is not secure. However, this
means it will not be possible to bind to port 80 or 443. Instead, a
reverse proxy such as <a class="reference internal" href="nginx.html"><span class="doc">nginx</span></a> or <a class="reference internal" href="apache-httpd.html"><span class="doc">Apache httpd</span></a> should be used
in front of eventlet.</p>
<p>You can bind to all external IPs on a non-privileged port by using
<code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> in the server arguments shown in the previous section.
Dont do this when using a reverse proxy setup, otherwise it will be
possible to bypass the proxy.</p>
<p><code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> is not a valid address to navigate to, youd use a specific
IP address in your browser.</p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">eventlet</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="gevent.html" title="previous chapter">gevent</a>
<li>Next: <a href="asgi.html" title="next chapter">ASGI</a></ul>
</li>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><div id="ethical-ad-placement"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2010 Pallets.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>

View file

@ -0,0 +1,166 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>gevent &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="eventlet" href="eventlet.html" />
<link rel="prev" title="uWSGI" href="uwsgi.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="eventlet.html" title="eventlet"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="uwsgi.html" title="uWSGI"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">gevent</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="gevent">
<h1>gevent<a class="headerlink" href="#gevent" title="Link to this heading"></a></h1>
<p>Prefer using <a class="reference internal" href="gunicorn.html"><span class="doc">Gunicorn</span></a> or <a class="reference internal" href="uwsgi.html"><span class="doc">uWSGI</span></a> with gevent workers rather
than using <a class="reference external" href="https://www.gevent.org/">gevent</a> directly. Gunicorn and uWSGI provide much more
configurable and production-tested servers.</p>
<p><a class="reference external" href="https://www.gevent.org/">gevent</a> allows writing asynchronous, coroutine-based code that looks
like standard synchronous Python. It uses <a class="reference external" href="https://greenlet.readthedocs.io/en/latest/">greenlet</a> to enable task
switching without writing <code class="docutils literal notranslate"><span class="pre">async/await</span></code> or using <code class="docutils literal notranslate"><span class="pre">asyncio</span></code>.</p>
<p><a class="reference internal" href="eventlet.html"><span class="doc">eventlet</span></a> is another library that does the same thing. Certain
dependencies you have, or other considerations, may affect which of the
two you choose to use.</p>
<p>gevent provides a WSGI server that can handle many connections at once
instead of one per worker process. You must actually use gevent in your
own code to see any benefit to using the server.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>When using gevent, greenlet&gt;=1.0 is required, otherwise context locals
such as <code class="docutils literal notranslate"><span class="pre">request</span></code> will not work as expected. When using PyPy,
PyPy&gt;=7.3.7 is required.</p>
<p>Create a virtualenv, install your application, then install <code class="docutils literal notranslate"><span class="pre">gevent</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install gevent
</pre></div>
</div>
</section>
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>To use gevent to serve your application, write a script that imports its
<code class="docutils literal notranslate"><span class="pre">WSGIServer</span></code>, as well as your app or app factory.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">wsgi.py</span></code></span><a class="headerlink" href="#id2" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">gevent.pywsgi</span><span class="w"> </span><span class="kn">import</span> <span class="n">WSGIServer</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">hello</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">create_app</span><span class="p">()</span>
<span class="n">http_server</span> <span class="o">=</span> <span class="n">WSGIServer</span><span class="p">((</span><span class="s2">&quot;127.0.0.1&quot;</span><span class="p">,</span> <span class="mi">8000</span><span class="p">),</span> <span class="n">app</span><span class="p">)</span>
<span class="n">http_server</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
</pre></div>
</div>
</div>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ python wsgi.py
</pre></div>
</div>
<p>No output is shown when the server starts.</p>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>gevent should not be run as root because it would cause your
application code to run as root, which is not secure. However, this
means it will not be possible to bind to port 80 or 443. Instead, a
reverse proxy such as <a class="reference internal" href="nginx.html"><span class="doc">nginx</span></a> or <a class="reference internal" href="apache-httpd.html"><span class="doc">Apache httpd</span></a> should be used
in front of gevent.</p>
<p>You can bind to all external IPs on a non-privileged port by using
<code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> in the server arguments shown in the previous section. Dont
do this when using a reverse proxy setup, otherwise it will be possible
to bypass the proxy.</p>
<p><code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> is not a valid address to navigate to, youd use a specific
IP address in your browser.</p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">gevent</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="uwsgi.html" title="previous chapter">uWSGI</a>
<li>Next: <a href="eventlet.html" title="next chapter">eventlet</a></ul>
</li>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><div id="ethical-ad-placement"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2010 Pallets.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>

View file

@ -0,0 +1,207 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Gunicorn &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Waitress" href="waitress.html" />
<link rel="prev" title="Deploying to Production" href="index.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="waitress.html" title="Waitress"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="index.html" title="Deploying to Production"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Gunicorn</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="gunicorn">
<h1>Gunicorn<a class="headerlink" href="#gunicorn" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://gunicorn.org/">Gunicorn</a> is a pure Python WSGI server with simple configuration and
multiple worker implementations for performance tuning.</p>
<ul class="simple">
<li><p>It tends to integrate easily with hosting platforms.</p></li>
<li><p>It does not support Windows (but does run on WSL).</p></li>
<li><p>It is easy to install as it does not require additional dependencies
or compilation.</p></li>
<li><p>It has built-in async worker support using gevent or eventlet.</p></li>
</ul>
<p>This page outlines the basics of running Gunicorn. Be sure to read its
<a class="reference external" href="https://docs.gunicorn.org/">documentation</a> and use <code class="docutils literal notranslate"><span class="pre">gunicorn</span> <span class="pre">--help</span></code> to understand what features
are available.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>Gunicorn is easy to install, as it does not require external
dependencies or compilation. It runs on Windows only under WSL.</p>
<p>Create a virtualenv, install your application, then install
<code class="docutils literal notranslate"><span class="pre">gunicorn</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install gunicorn
</pre></div>
</div>
</section>
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>The only required argument to Gunicorn tells it how to load your Flask
application. The syntax is <code class="docutils literal notranslate"><span class="pre">{module_import}:{app_variable}</span></code>.
<code class="docutils literal notranslate"><span class="pre">module_import</span></code> is the dotted import name to the module with your
application. <code class="docutils literal notranslate"><span class="pre">app_variable</span></code> is the variable with the application. It
can also be a function call (with any arguments) if youre using the
app factory pattern.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span># equivalent to &#39;from hello import app&#39;
$ gunicorn -w 4 &#39;hello:app&#39;
# equivalent to &#39;from hello import create_app; create_app()&#39;
$ gunicorn -w 4 &#39;hello:create_app()&#39;
Starting gunicorn 20.1.0
Listening at: http://127.0.0.1:8000 (x)
Using worker: sync
Booting worker with pid: x
Booting worker with pid: x
Booting worker with pid: x
Booting worker with pid: x
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">-w</span></code> option specifies the number of processes to run; a starting
value could be <code class="docutils literal notranslate"><span class="pre">CPU</span> <span class="pre">*</span> <span class="pre">2</span></code>. The default is only 1 worker, which is
probably not what you want for the default worker type.</p>
<p>Logs for each request arent shown by default, only worker info and
errors are shown. To show access logs on stdout, use the
<code class="docutils literal notranslate"><span class="pre">--access-logfile=-</span></code> option.</p>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>Gunicorn should not be run as root because it would cause your
application code to run as root, which is not secure. However, this
means it will not be possible to bind to port 80 or 443. Instead, a
reverse proxy such as <a class="reference internal" href="nginx.html"><span class="doc">nginx</span></a> or <a class="reference internal" href="apache-httpd.html"><span class="doc">Apache httpd</span></a> should be used
in front of Gunicorn.</p>
<p>You can bind to all external IPs on a non-privileged port using the
<code class="docutils literal notranslate"><span class="pre">-b</span> <span class="pre">0.0.0.0</span></code> option. Dont do this when using a reverse proxy setup,
otherwise it will be possible to bypass the proxy.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ gunicorn -w 4 -b 0.0.0.0 &#39;hello:create_app()&#39;
Listening at: http://0.0.0.0:8000 (x)
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> is not a valid address to navigate to, youd use a specific
IP address in your browser.</p>
</section>
<section id="async-with-gevent-or-eventlet">
<h2>Async with gevent or eventlet<a class="headerlink" href="#async-with-gevent-or-eventlet" title="Link to this heading"></a></h2>
<p>The default sync worker is appropriate for many use cases. If you need
asynchronous support, Gunicorn provides workers using either <a class="reference external" href="https://www.gevent.org/">gevent</a>
or <a class="reference external" href="https://eventlet.net/">eventlet</a>. This is not the same as Pythons <code class="docutils literal notranslate"><span class="pre">async/await</span></code>, or the
ASGI server spec. You must actually use gevent/eventlet in your own code
to see any benefit to using the workers.</p>
<p>When using either gevent or eventlet, greenlet&gt;=1.0 is required,
otherwise context locals such as <code class="docutils literal notranslate"><span class="pre">request</span></code> will not work as expected.
When using PyPy, PyPy&gt;=7.3.7 is required.</p>
<p>To use gevent:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ gunicorn -k gevent &#39;hello:create_app()&#39;
Starting gunicorn 20.1.0
Listening at: http://127.0.0.1:8000 (x)
Using worker: gevent
Booting worker with pid: x
</pre></div>
</div>
<p>To use eventlet:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ gunicorn -k eventlet &#39;hello:create_app()&#39;
Starting gunicorn 20.1.0
Listening at: http://127.0.0.1:8000 (x)
Using worker: eventlet
Booting worker with pid: x
</pre></div>
</div>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Gunicorn</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
<li><a class="reference internal" href="#async-with-gevent-or-eventlet">Async with gevent or eventlet</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="index.html" title="previous chapter">Deploying to Production</a>
<li>Next: <a href="waitress.html" title="next chapter">Waitress</a></ul>
</li>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><div id="ethical-ad-placement"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2010 Pallets.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>

View file

@ -0,0 +1,171 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Deploying to Production &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Gunicorn" href="gunicorn.html" />
<link rel="prev" title="Security Considerations" href="../web-security.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="gunicorn.html" title="Gunicorn"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="../web-security.html" title="Security Considerations"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Deploying to Production</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="deploying-to-production">
<h1>Deploying to Production<a class="headerlink" href="#deploying-to-production" title="Link to this heading"></a></h1>
<p>After developing your application, youll want to make it available
publicly to other users. When youre developing locally, youre probably
using the built-in development server, debugger, and reloader. These
should not be used in production. Instead, you should use a dedicated
WSGI server or hosting platform, some of which will be described here.</p>
<p>“Production” means “not development”, which applies whether youre
serving your application publicly to millions of users or privately /
locally to a single user. <strong>Do not use the development server when
deploying to production. It is intended for use only during local
development. It is not designed to be particularly secure, stable, or
efficient.</strong></p>
<section id="self-hosted-options">
<h2>Self-Hosted Options<a class="headerlink" href="#self-hosted-options" title="Link to this heading"></a></h2>
<p>Flask is a WSGI <em>application</em>. A WSGI <em>server</em> is used to run the
application, converting incoming HTTP requests to the standard WSGI
environ, and converting outgoing WSGI responses to HTTP responses.</p>
<p>The primary goal of these docs is to familiarize you with the concepts
involved in running a WSGI application using a production WSGI server
and HTTP server. There are many WSGI servers and HTTP servers, with many
configuration possibilities. The pages below discuss the most common
servers, and show the basics of running each one. The next section
discusses platforms that can manage this for you.</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="gunicorn.html">Gunicorn</a></li>
<li class="toctree-l1"><a class="reference internal" href="waitress.html">Waitress</a></li>
<li class="toctree-l1"><a class="reference internal" href="mod_wsgi.html">mod_wsgi</a></li>
<li class="toctree-l1"><a class="reference internal" href="uwsgi.html">uWSGI</a></li>
<li class="toctree-l1"><a class="reference internal" href="gevent.html">gevent</a></li>
<li class="toctree-l1"><a class="reference internal" href="eventlet.html">eventlet</a></li>
<li class="toctree-l1"><a class="reference internal" href="asgi.html">ASGI</a></li>
</ul>
</div>
<p>WSGI servers have HTTP servers built-in. However, a dedicated HTTP
server may be safer, more efficient, or more capable. Putting an HTTP
server in front of the WSGI server is called a “reverse proxy.”</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="proxy_fix.html">Tell Flask it is Behind a Proxy</a></li>
<li class="toctree-l1"><a class="reference internal" href="nginx.html">nginx</a></li>
<li class="toctree-l1"><a class="reference internal" href="apache-httpd.html">Apache httpd</a></li>
</ul>
</div>
<p>This list is not exhaustive, and you should evaluate these and other
servers based on your applications needs. Different servers will have
different capabilities, configuration, and support.</p>
</section>
<section id="hosting-platforms">
<h2>Hosting Platforms<a class="headerlink" href="#hosting-platforms" title="Link to this heading"></a></h2>
<p>There are many services available for hosting web applications without
needing to maintain your own server, networking, domain, etc. Some
services may have a free tier up to a certain time or bandwidth. Many of
these services use one of the WSGI servers described above, or a similar
interface. The links below are for some of the most common platforms,
which have instructions for Flask, WSGI, or Python.</p>
<ul class="simple">
<li><p><a class="reference external" href="https://help.pythonanywhere.com/pages/Flask/">PythonAnywhere</a></p></li>
<li><p><a class="reference external" href="https://cloud.google.com/appengine/docs/standard/python3/building-app">Google App Engine</a></p></li>
<li><p><a class="reference external" href="https://cloud.google.com/run/docs/quickstarts/build-and-deploy/deploy-python-service">Google Cloud Run</a></p></li>
<li><p><a class="reference external" href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-flask.html">AWS Elastic Beanstalk</a></p></li>
<li><p><a class="reference external" href="https://docs.microsoft.com/en-us/azure/app-service/quickstart-python">Microsoft Azure</a></p></li>
</ul>
<p>This list is not exhaustive, and you should evaluate these and other
services based on your applications needs. Different services will have
different capabilities, configuration, pricing, and support.</p>
<p>Youll probably need to <a class="reference internal" href="proxy_fix.html"><span class="doc">Tell Flask it is Behind a Proxy</span></a> when using most hosting
platforms.</p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Deploying to Production</a><ul>
<li><a class="reference internal" href="#self-hosted-options">Self-Hosted Options</a><ul>
</ul>
</li>
<li><a class="reference internal" href="#hosting-platforms">Hosting Platforms</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li>Previous: <a href="../web-security.html" title="previous chapter">Security Considerations</a>
<li>Next: <a href="gunicorn.html" title="next chapter">Gunicorn</a>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><div id="ethical-ad-placement"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2010 Pallets.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>

View file

@ -0,0 +1,181 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>mod_wsgi &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="uWSGI" href="uwsgi.html" />
<link rel="prev" title="Waitress" href="waitress.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="uwsgi.html" title="uWSGI"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="waitress.html" title="Waitress"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">mod_wsgi</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="mod-wsgi">
<h1>mod_wsgi<a class="headerlink" href="#mod-wsgi" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://modwsgi.readthedocs.io/">mod_wsgi</a> is a WSGI server integrated with the <a class="reference external" href="https://httpd.apache.org/">Apache httpd</a> server.
The modern <a class="reference external" href="https://pypi.org/project/mod-wsgi/">mod_wsgi-express</a> command makes it easy to configure and
start the server without needing to write Apache httpd configuration.</p>
<ul class="simple">
<li><p>Tightly integrated with Apache httpd.</p></li>
<li><p>Supports Windows directly.</p></li>
<li><p>Requires a compiler and the Apache development headers to install.</p></li>
<li><p>Does not require a reverse proxy setup.</p></li>
</ul>
<p>This page outlines the basics of running mod_wsgi-express, not the more
complex installation and configuration with httpd. Be sure to read the
<a class="reference external" href="https://pypi.org/project/mod-wsgi/">mod_wsgi-express</a>, <a class="reference external" href="https://modwsgi.readthedocs.io/">mod_wsgi</a>, and <a class="reference external" href="https://httpd.apache.org/">Apache httpd</a> documentation to
understand what features are available.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>Installing mod_wsgi requires a compiler and the Apache server and
development headers installed. You will get an error if they are not.
How to install them depends on the OS and package manager that you use.</p>
<p>Create a virtualenv, install your application, then install
<code class="docutils literal notranslate"><span class="pre">mod_wsgi</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install mod_wsgi
</pre></div>
</div>
</section>
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>The only argument to <code class="docutils literal notranslate"><span class="pre">mod_wsgi-express</span></code> specifies a script containing
your Flask application, which must be called <code class="docutils literal notranslate"><span class="pre">application</span></code>. You can
write a small script to import your app with this name, or to create it
if using the app factory pattern.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">wsgi.py</span></code></span><a class="headerlink" href="#id2" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">hello</span><span class="w"> </span><span class="kn">import</span> <span class="n">app</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">app</span>
</pre></div>
</div>
</div>
<div class="literal-block-wrapper docutils container" id="id3">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">wsgi.py</span></code></span><a class="headerlink" href="#id3" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">hello</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">create_app</span><span class="p">()</span>
</pre></div>
</div>
</div>
<p>Now run the <code class="docutils literal notranslate"><span class="pre">mod_wsgi-express</span> <span class="pre">start-server</span></code> command.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ mod_wsgi-express start-server wsgi.py --processes 4
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">--processes</span></code> option specifies the number of worker processes to
run; a starting value could be <code class="docutils literal notranslate"><span class="pre">CPU</span> <span class="pre">*</span> <span class="pre">2</span></code>.</p>
<p>Logs for each request arent show in the terminal. If an error occurs,
its information is written to the error log file shown when starting the
server.</p>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>Unlike the other WSGI servers in these docs, mod_wsgi can be run as
root to bind to privileged ports like 80 and 443. However, it must be
configured to drop permissions to a different user and group for the
worker processes.</p>
<p>For example, if you created a <code class="docutils literal notranslate"><span class="pre">hello</span></code> user and group, you should
install your virtualenv and application as that user, then tell
mod_wsgi to drop to that user after starting.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ sudo /home/hello/.venv/bin/mod_wsgi-express start-server \
/home/hello/wsgi.py \
--user hello --group hello --port 80 --processes 4
</pre></div>
</div>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">mod_wsgi</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="waitress.html" title="previous chapter">Waitress</a>
<li>Next: <a href="uwsgi.html" title="next chapter">uWSGI</a></ul>
</li>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><div id="ethical-ad-placement"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2010 Pallets.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>

View file

@ -0,0 +1,162 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>nginx &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Apache httpd" href="apache-httpd.html" />
<link rel="prev" title="Tell Flask it is Behind a Proxy" href="proxy_fix.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="apache-httpd.html" title="Apache httpd"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="proxy_fix.html" title="Tell Flask it is Behind a Proxy"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">nginx</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="nginx">
<h1>nginx<a class="headerlink" href="#nginx" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://nginx.org/">nginx</a> is a fast, production level HTTP server. When serving your
application with one of the WSGI servers listed in <a class="reference internal" href="index.html"><span class="doc">Deploying to Production</span></a>, it is
often good or necessary to put a dedicated HTTP server in front of it.
This “reverse proxy” can handle incoming requests, TLS, and other
security and performance concerns better than the WSGI server.</p>
<p>Nginx can be installed using your system package manager, or a pre-built
executable for Windows. Installing and running Nginx itself is outside
the scope of this doc. This page outlines the basics of configuring
Nginx to proxy your application. Be sure to read its documentation to
understand what features are available.</p>
<section id="domain-name">
<h2>Domain Name<a class="headerlink" href="#domain-name" title="Link to this heading"></a></h2>
<p>Acquiring and configuring a domain name is outside the scope of this
doc. In general, you will buy a domain name from a registrar, pay for
server space with a hosting provider, and then point your registrar
at the hosting providers name servers.</p>
<p>To simulate this, you can also edit your <code class="docutils literal notranslate"><span class="pre">hosts</span></code> file, located at
<code class="docutils literal notranslate"><span class="pre">/etc/hosts</span></code> on Linux. Add a line that associates a name with the
local IP.</p>
<p>Modern Linux systems may be configured to treat any domain name that
ends with <code class="docutils literal notranslate"><span class="pre">.localhost</span></code> like this without adding it to the <code class="docutils literal notranslate"><span class="pre">hosts</span></code>
file.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">/etc/hosts</span></code></span><a class="headerlink" href="#id2" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="mf">127.0.0.1</span> <span class="n">hello</span><span class="o">.</span><span class="n">localhost</span>
</pre></div>
</div>
</div>
</section>
<section id="configuration">
<h2>Configuration<a class="headerlink" href="#configuration" title="Link to this heading"></a></h2>
<p>The nginx configuration is located at <code class="docutils literal notranslate"><span class="pre">/etc/nginx/nginx.conf</span></code> on
Linux. It may be different depending on your operating system. Check the
docs and look for <code class="docutils literal notranslate"><span class="pre">nginx.conf</span></code>.</p>
<p>Remove or comment out any existing <code class="docutils literal notranslate"><span class="pre">server</span></code> section. Add a <code class="docutils literal notranslate"><span class="pre">server</span></code>
section and use the <code class="docutils literal notranslate"><span class="pre">proxy_pass</span></code> directive to point to the address the
WSGI server is listening on. Well assume the WSGI server is listening
locally at <code class="docutils literal notranslate"><span class="pre">http://127.0.0.1:8000</span></code>.</p>
<div class="literal-block-wrapper docutils container" id="id3">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">/etc/nginx.conf</span></code></span><a class="headerlink" href="#id3" title="Link to this code"></a></div>
<div class="highlight-nginx notranslate"><div class="highlight"><pre><span></span><span class="k">server</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kn">listen</span><span class="w"> </span><span class="mi">80</span><span class="p">;</span>
<span class="w"> </span><span class="kn">server_name</span><span class="w"> </span><span class="s">_</span><span class="p">;</span>
<span class="w"> </span><span class="kn">location</span><span class="w"> </span><span class="s">/</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kn">proxy_pass</span><span class="w"> </span><span class="s">http://127.0.0.1:8000/</span><span class="p">;</span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-For</span><span class="w"> </span><span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Proto</span><span class="w"> </span><span class="nv">$scheme</span><span class="p">;</span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Host</span><span class="w"> </span><span class="nv">$host</span><span class="p">;</span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Prefix</span><span class="w"> </span><span class="s">/</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<p>Then <a class="reference internal" href="proxy_fix.html"><span class="doc">Tell Flask it is Behind a Proxy</span></a> so that your application uses these headers.</p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">nginx</a><ul>
<li><a class="reference internal" href="#domain-name">Domain Name</a></li>
<li><a class="reference internal" href="#configuration">Configuration</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="proxy_fix.html" title="previous chapter">Tell Flask it is Behind a Proxy</a>
<li>Next: <a href="apache-httpd.html" title="next chapter">Apache httpd</a></ul>
</li>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><div id="ethical-ad-placement"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2010 Pallets.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>

View file

@ -0,0 +1,121 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tell Flask it is Behind a Proxy &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="nginx" href="nginx.html" />
<link rel="prev" title="ASGI" href="asgi.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="nginx.html" title="nginx"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="asgi.html" title="ASGI"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Tell Flask it is Behind a Proxy</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="tell-flask-it-is-behind-a-proxy">
<h1>Tell Flask it is Behind a Proxy<a class="headerlink" href="#tell-flask-it-is-behind-a-proxy" title="Link to this heading"></a></h1>
<p>When using a reverse proxy, or many Python hosting platforms, the proxy
will intercept and forward all external requests to the local WSGI
server.</p>
<p>From the WSGI server and Flask applications perspectives, requests are
now coming from the HTTP server to the local address, rather than from
the remote address to the external server address.</p>
<p>HTTP servers should set <code class="docutils literal notranslate"><span class="pre">X-Forwarded-</span></code> headers to pass on the real
values to the application. The application can then be told to trust and
use those values by wrapping it with the
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/middleware/proxy_fix/" title="(in Werkzeug v3.1.x)"><span>X-Forwarded-For Proxy Fix</span></a> middleware provided by Werkzeug.</p>
<p>This middleware should only be used if the application is actually
behind a proxy, and should be configured with the number of proxies that
are chained in front of it. Not all proxies set all the headers. Since
incoming headers can be faked, you must set how many proxies are setting
each header so the middleware knows what to trust.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">werkzeug.middleware.proxy_fix</span><span class="w"> </span><span class="kn">import</span> <span class="n">ProxyFix</span>
<span class="n">app</span><span class="o">.</span><span class="n">wsgi_app</span> <span class="o">=</span> <span class="n">ProxyFix</span><span class="p">(</span>
<span class="n">app</span><span class="o">.</span><span class="n">wsgi_app</span><span class="p">,</span> <span class="n">x_for</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">x_proto</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">x_host</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">x_prefix</span><span class="o">=</span><span class="mi">1</span>
<span class="p">)</span>
</pre></div>
</div>
<p>Remember, only apply this middleware if you are behind a proxy, and set
the correct number of proxies that set each header. It can be a security
issue if you get this configuration wrong.</p>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="asgi.html" title="previous chapter">ASGI</a>
<li>Next: <a href="nginx.html" title="next chapter">nginx</a></ul>
</li>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><div id="ethical-ad-placement"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2010 Pallets.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>

View file

@ -0,0 +1,220 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>uWSGI &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="gevent" href="gevent.html" />
<link rel="prev" title="mod_wsgi" href="mod_wsgi.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="gevent.html" title="gevent"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="mod_wsgi.html" title="mod_wsgi"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">uWSGI</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="uwsgi">
<h1>uWSGI<a class="headerlink" href="#uwsgi" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://uwsgi-docs.readthedocs.io/en/latest/">uWSGI</a> is a fast, compiled server suite with extensive configuration
and capabilities beyond a basic server.</p>
<ul class="simple">
<li><p>It can be very performant due to being a compiled program.</p></li>
<li><p>It is complex to configure beyond the basic application, and has so
many options that it can be difficult for beginners to understand.</p></li>
<li><p>It does not support Windows (but does run on WSL).</p></li>
<li><p>It requires a compiler to install in some cases.</p></li>
</ul>
<p>This page outlines the basics of running uWSGI. Be sure to read its
documentation to understand what features are available.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>uWSGI has multiple ways to install it. The most straightforward is to
install the <code class="docutils literal notranslate"><span class="pre">pyuwsgi</span></code> package, which provides precompiled wheels for
common platforms. However, it does not provide SSL support, which can be
provided with a reverse proxy instead.</p>
<p>Create a virtualenv, install your application, then install <code class="docutils literal notranslate"><span class="pre">pyuwsgi</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install pyuwsgi
</pre></div>
</div>
<p>If you have a compiler available, you can install the <code class="docutils literal notranslate"><span class="pre">uwsgi</span></code> package
instead. Or install the <code class="docutils literal notranslate"><span class="pre">pyuwsgi</span></code> package from sdist instead of wheel.
Either method will include SSL support.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ pip install uwsgi
# or
$ pip install --no-binary pyuwsgi pyuwsgi
</pre></div>
</div>
</section>
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>The most basic way to run uWSGI is to tell it to start an HTTP server
and import your application.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ uwsgi --http 127.0.0.1:8000 --master -p 4 -w hello:app
*** Starting uWSGI 2.0.20 (64bit) on [x] ***
*** Operational MODE: preforking ***
mounting hello:app on /
spawned uWSGI master process (pid: x)
spawned uWSGI worker 1 (pid: x, cores: 1)
spawned uWSGI worker 2 (pid: x, cores: 1)
spawned uWSGI worker 3 (pid: x, cores: 1)
spawned uWSGI worker 4 (pid: x, cores: 1)
spawned uWSGI http 1 (pid: x)
</pre></div>
</div>
<p>If youre using the app factory pattern, youll need to create a small
Python file to create the app, then point uWSGI at that.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">wsgi.py</span></code></span><a class="headerlink" href="#id2" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">hello</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">create_app</span><span class="p">()</span>
</pre></div>
</div>
</div>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ uwsgi --http 127.0.0.1:8000 --master -p 4 -w wsgi:app
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">--http</span></code> option starts an HTTP server at 127.0.0.1 port 8000. The
<code class="docutils literal notranslate"><span class="pre">--master</span></code> option specifies the standard worker manager. The <code class="docutils literal notranslate"><span class="pre">-p</span></code>
option starts 4 worker processes; a starting value could be <code class="docutils literal notranslate"><span class="pre">CPU</span> <span class="pre">*</span> <span class="pre">2</span></code>.
The <code class="docutils literal notranslate"><span class="pre">-w</span></code> option tells uWSGI how to import your application</p>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>uWSGI should not be run as root with the configuration shown in this doc
because it would cause your application code to run as root, which is
not secure. However, this means it will not be possible to bind to port
80 or 443. Instead, a reverse proxy such as <a class="reference internal" href="nginx.html"><span class="doc">nginx</span></a> or
<a class="reference internal" href="apache-httpd.html"><span class="doc">Apache httpd</span></a> should be used in front of uWSGI. It is possible to
run uWSGI as root securely, but that is beyond the scope of this doc.</p>
<p>uWSGI has optimized integration with <a class="reference external" href="https://uwsgi-docs.readthedocs.io/en/latest/Nginx.html">Nginx uWSGI</a> and
<a class="reference external" href="https://uwsgi-docs.readthedocs.io/en/latest/Apache.html#mod-proxy-uwsgi">Apache mod_proxy_uwsgi</a>, and possibly other servers, instead of using
a standard HTTP proxy. That configuration is beyond the scope of this
doc, see the links for more information.</p>
<p>You can bind to all external IPs on a non-privileged port using the
<code class="docutils literal notranslate"><span class="pre">--http</span> <span class="pre">0.0.0.0:8000</span></code> option. Dont do this when using a reverse proxy
setup, otherwise it will be possible to bypass the proxy.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ uwsgi --http 0.0.0.0:8000 --master -p 4 -w wsgi:app
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> is not a valid address to navigate to, youd use a specific
IP address in your browser.</p>
</section>
<section id="async-with-gevent">
<h2>Async with gevent<a class="headerlink" href="#async-with-gevent" title="Link to this heading"></a></h2>
<p>The default sync worker is appropriate for many use cases. If you need
asynchronous support, uWSGI provides a <a class="reference external" href="https://www.gevent.org/">gevent</a> worker. This is not the
same as Pythons <code class="docutils literal notranslate"><span class="pre">async/await</span></code>, or the ASGI server spec. You must
actually use gevent in your own code to see any benefit to using the
worker.</p>
<p>When using gevent, greenlet&gt;=1.0 is required, otherwise context locals
such as <code class="docutils literal notranslate"><span class="pre">request</span></code> will not work as expected. When using PyPy,
PyPy&gt;=7.3.7 is required.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ uwsgi --http 127.0.0.1:8000 --master --gevent 100 -w wsgi:app
*** Starting uWSGI 2.0.20 (64bit) on [x] ***
*** Operational MODE: async ***
mounting hello:app on /
spawned uWSGI master process (pid: x)
spawned uWSGI worker 1 (pid: x, cores: 100)
spawned uWSGI http 1 (pid: x)
*** running gevent loop engine [addr:x] ***
</pre></div>
</div>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">uWSGI</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
<li><a class="reference internal" href="#async-with-gevent">Async with gevent</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="mod_wsgi.html" title="previous chapter">mod_wsgi</a>
<li>Next: <a href="gevent.html" title="next chapter">gevent</a></ul>
</li>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><div id="ethical-ad-placement"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2010 Pallets.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>

View file

@ -0,0 +1,164 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Waitress &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="mod_wsgi" href="mod_wsgi.html" />
<link rel="prev" title="Gunicorn" href="gunicorn.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="mod_wsgi.html" title="mod_wsgi"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="gunicorn.html" title="Gunicorn"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Waitress</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="waitress">
<h1>Waitress<a class="headerlink" href="#waitress" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://docs.pylonsproject.org/projects/waitress/">Waitress</a> is a pure Python WSGI server.</p>
<ul class="simple">
<li><p>It is easy to configure.</p></li>
<li><p>It supports Windows directly.</p></li>
<li><p>It is easy to install as it does not require additional dependencies
or compilation.</p></li>
<li><p>It does not support streaming requests, full request data is always
buffered.</p></li>
<li><p>It uses a single process with multiple thread workers.</p></li>
</ul>
<p>This page outlines the basics of running Waitress. Be sure to read its
documentation and <code class="docutils literal notranslate"><span class="pre">waitress-serve</span> <span class="pre">--help</span></code> to understand what features
are available.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>Create a virtualenv, install your application, then install
<code class="docutils literal notranslate"><span class="pre">waitress</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install waitress
</pre></div>
</div>
</section>
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>The only required argument to <code class="docutils literal notranslate"><span class="pre">waitress-serve</span></code> tells it how to load
your Flask application. The syntax is <code class="docutils literal notranslate"><span class="pre">{module}:{app}</span></code>. <code class="docutils literal notranslate"><span class="pre">module</span></code> is
the dotted import name to the module with your application. <code class="docutils literal notranslate"><span class="pre">app</span></code> is
the variable with the application. If youre using the app factory
pattern, use <code class="docutils literal notranslate"><span class="pre">--call</span> <span class="pre">{module}:{factory}</span></code> instead.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span># equivalent to &#39;from hello import app&#39;
$ waitress-serve --host 127.0.0.1 hello:app
# equivalent to &#39;from hello import create_app; create_app()&#39;
$ waitress-serve --host 127.0.0.1 --call hello:create_app
Serving on http://127.0.0.1:8080
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">--host</span></code> option binds the server to local <code class="docutils literal notranslate"><span class="pre">127.0.0.1</span></code> only.</p>
<p>Logs for each request arent shown, only errors are shown. Logging can
be configured through the Python interface instead of the command line.</p>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>Waitress should not be run as root because it would cause your
application code to run as root, which is not secure. However, this
means it will not be possible to bind to port 80 or 443. Instead, a
reverse proxy such as <a class="reference internal" href="nginx.html"><span class="doc">nginx</span></a> or <a class="reference internal" href="apache-httpd.html"><span class="doc">Apache httpd</span></a> should be used
in front of Waitress.</p>
<p>You can bind to all external IPs on a non-privileged port by not
specifying the <code class="docutils literal notranslate"><span class="pre">--host</span></code> option. Dont do this when using a reverse
proxy setup, otherwise it will be possible to bypass the proxy.</p>
<p><code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> is not a valid address to navigate to, youd use a specific
IP address in your browser.</p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Waitress</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="gunicorn.html" title="previous chapter">Gunicorn</a>
<li>Next: <a href="mod_wsgi.html" title="next chapter">mod_wsgi</a></ul>
</li>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><div id="ethical-ad-placement"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2010 Pallets.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>