Running 2 Gunicorn Apps and Nginx with Supervisord
<p>This problem has admittedly stumped me for months. I've just procrastinated fixing other bugs and putting this aside until now where it HAS to be fixed --</p>

<p>I am trying to run 2 separate gunicorn apps and start nginx within the same supervisord.conf file. When I start supervisor, I am able to successfully run the handlecalls app but when I go to the website that commentbox is responsible for loading, I get an internal service error (500).</p>

<p>When I run the handlecalls and commentbox apps separately with the commands following the command field, the apps run fine. Why is the commentbox program giving me a 500 error when I try to run both with supervisord?</p>

<h1>my supervisord script:</h1>

<pre><code>[program:nginx]
directory = /var/www/vmail
command = service nginx start -g "daemon off;"
autostart = True

[program:commentbox]
directory = /var/www/vmail
command = gunicorn app:app -bind 0.0.0.0:8000
autostart = True

[program:handlecalls]
directory = /var/www/vmail
command = gunicorn handle_calls:app --bind 0.0.0.0:8000
autostart = True

[supervisord]
directory = /var/www/vmail
logfile = /var/www/vmail/supervisorerrs.log
loglevel = trace
</code></pre>

<p>This has nothing to do with supervisord. Supervisord is just a way for you to start/stop/restart your server. This has more to do with your server's configuration.</p>

<p>The basic: To serve two gunicorn apps with nginx, you have to run them on two different ports, then config nginx to proxy_pass the request to their respective ports. The reson is: once a process is running on a port, that port cannot be used by another process.</p>

<p>So change the configuration in your supervisord script to:</p>

<pre><code>[program:commentbox]
directory = /var/www/vmail
command = gunicorn app:app -bind 0.0.0.0:8000
autostart = True

[program:handlecalls]
directory = /var/www/vmail
command = gunicorn handle_calls:app --bind 0.0.0.0:8001
autostart = True
</code></pre>

<p>Then in your nginx server's configuration for <code>handlecalls</code></p>

<pre><code>proxy_pass 127.0.0.1:8081
</code></pre>

<p><strong>Update: Here is the basics of deploying a web application</strong></p>

<ol>
<li>As mentioned above, one port can only be listened by a process.</li>
<li>You can use nginx as a http server, listening to port <code>80</code> (or <code>443</code> for https), then passing the request to other applications listening to other ports (for example, <code>commentbox</code> on port <code>8000</code> and handlecalls on port <code>8001</code>)</li>
<li><p>You can add rules to nginx as how to serve your application by adding certain server configuration files in <code>/etc/nginx/sites-available/</code> (by default. It is different in some cases). The rules should specify a way for nginx to know which application it should send the request to, for example:</p>

<ul>
<li>To reuse the same http port (<code>80</code>), each application should be assigned to a different domain. i.e: <code>commentbox.yourdomain.com</code> for <code>commentbox</code> and <code>handlecalls.yourdomain.com</code> for <code>handlecalls</code></li>
<li>A way to serve two different apps on the same domain, is for them to serve on different ports. For example: <code>yourdomain.com</code> would serve <code>commentbox</code> and <code>yourdomain.com:8080</code> would serve <code>handlecalls</code></li>
<li>A way to serve two different apps on the same domain and the same ports, is for them to serve on two different endpoints. For example <code>yourdomain.com/commentbox</code> would serve <code>commentbox</code> and <code>yourdomain.com/handlecalls</code> would serve <code>handlecalls</code></li>
</ul></li>
<li><p>After adding configuration files to <code>/etc/nginx/sites-available/</code>, you must symlink those files to <code>/etc/nginx/sites-enabled/</code>, well, to tell nginx that you want to enable them. You can add the files directly to <code>/etc/nginx/sites-enabled/</code>, but I don't recommend it, since it doesn't give you a convenient way to enable/disable your application.</p></li>
</ol>

<p><strong>Update: Here is how to config nginx to serve gunicorn applications using two different subdomains:</strong></p>

<ol>
<li>Add two subdomains <code>commentbox.yourdomain.com</code> and <code>handlecalls.yourdomain.com</code>, and point them both to your server's IP.</li>
<li><p>Create a a configuration file for <code>commentbox</code> at <code>/etc/nginx/sites-available/commentbox</code> with the following content (edit as fit):</p>

<pre><code>server {
    listen 80; 

    server_name           commentbox.yourdomain.com;

    root                  /path/to/your/application/static/folder;    
    location / {
        try_files         $uri @app;
    }

    location @app {
        proxy_set_header   Host $http_host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_redirect     off;
        proxy_pass         http://127.0.0.1:8000;
    }
}
</code></pre></li>
<li><p>Create a configuration file for <code>handlecalls</code> at <code>/etc/nginx/sites-available/handlecalls</code> with the following content (edit as fit):</p>

<pre><code>server {
    listen 80; 

    server_name           handlecalls.yourdomain.com;

    root                  /path/to/your/application/static/folder;    
    location / {
        try_files         $uri @app;
    }

    location @app {
        proxy_set_header   Host $http_host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_redirect     off;
        proxy_pass         http://127.0.0.1:8001;
    }
}
</code></pre></li>
<li><p>Create symlinks to enable those servers:</p>

<pre><code>sudo ln -s /etc/nginx/sites-available/commentbox /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/handlecalls /etc/nginx/sites-enabled/
</code></pre></li>
<li><p>Restart nginx to take effect</p>

<pre><code>sudo service nginx restart
</code></pre></li>
</ol>

python nginx gunicorn supervisord supervisor