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 --
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).
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?
my supervisord script:
[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
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.
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.
So change the configuration in your supervisord script to:
[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
Then in your nginx server's configuration for handlecalls
proxy_pass 127.0.0.1:8081
Update: Here is the basics of deploying a web application
- As mentioned above, one port can only be listened by a process.
- You can use nginx as a http server, listening to port
80
(or 443
for https), then passing the request to other applications listening to other ports (for example, commentbox
on port 8000
and handlecalls on port 8001
)
You can add rules to nginx as how to serve your application by adding certain server configuration files in /etc/nginx/sites-available/
(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:
- To reuse the same http port (
80
), each application should be assigned to a different domain. i.e: commentbox.yourdomain.com
for commentbox
and handlecalls.yourdomain.com
for handlecalls
- A way to serve two different apps on the same domain, is for them to serve on different ports. For example:
yourdomain.com
would serve commentbox
and yourdomain.com:8080
would serve handlecalls
- 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
yourdomain.com/commentbox
would serve commentbox
and yourdomain.com/handlecalls
would serve handlecalls
After adding configuration files to /etc/nginx/sites-available/
, you must symlink those files to /etc/nginx/sites-enabled/
, well, to tell nginx that you want to enable them. You can add the files directly to /etc/nginx/sites-enabled/
, but I don't recommend it, since it doesn't give you a convenient way to enable/disable your application.
Update: Here is how to config nginx to serve gunicorn applications using two different subdomains:
- Add two subdomains
commentbox.yourdomain.com
and handlecalls.yourdomain.com
, and point them both to your server's IP.
Create a a configuration file for commentbox
at /etc/nginx/sites-available/commentbox
with the following content (edit as fit):
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;
}
}
Create a configuration file for handlecalls
at /etc/nginx/sites-available/handlecalls
with the following content (edit as fit):
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;
}
}
Create symlinks to enable those servers:
sudo ln -s /etc/nginx/sites-available/commentbox /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/handlecalls /etc/nginx/sites-enabled/
Restart nginx to take effect
sudo service nginx restart