title: configuring flask-socketio with nginx,gunicorn and supervisor
body: <p>I am having hard time configuring flask-socketio to work with nginx,gunicorn and supervisor. Every thing works fine on local mechine i have tested all events and functions and they are working well. But I am unable to make it work on production server.
  The only thin i get in <strong>frontend.log</strong> is
  <strong>INFO|engineio.server               |server.py:150 <strong>init</strong>             ]: Server initialized for eventlet.</strong></p>
  <p>Here are my configuration.</p>
  <p>this is my <strong><code>__init__.py</code></strong></p>
  <pre><code>import os
  import logging
  import gevent
  import datetime
  import rollbar
  from flask_bootstrap import Bootstrap
  from flask_socketio import SocketIO
  from gevent.queue import Queue
  from gevent.event import AsyncResult
  import zmq.green as zmq
  
  from werkzeug.contrib.fixers import ProxyFix
  
  # Greens the postgress connector
  
  try:
      import psycogreen.gevent
  
      psycogreen.gevent.patch_psycopg()
  except ImportError:
      pass
  
  from rauth.service import OAuth2Service
  
  from flask import Flask, Request
  from flask_sqlalchemy import SQLAlchemy
  from flask_bcrypt import Bcrypt
  from flask_login import LoginManager, current_user
  from flask_assets import Environment
  from flask_uploads import UploadSet, configure_uploads, IMAGES
  
  from app.util import setup_logging
  from app.exceptions import TimeoutError, BackendError
  import app.exceptions
  
  socketio = SocketIO()
  
  flask_app = None
  
  
  # Have to use an actor pattern because we cannot allow more than one request to
  # be pending at a time.
  class Backend(gevent.Greenlet):
      def __init__(self):
          super(Backend, self).__init__()
  
          self.inbox = Queue()
          self.zmq_context = zmq.Context()
          self.zmq_socket = None
          self.init_socket()
  
      def init_socket(self):
          zmq_socket = self.zmq_socket
          if zmq_socket is not None:
              zmq_socket.close(0)
  
          zmq_socket = self.zmq_context.socket(zmq.REQ)
          zmq_socket.connect(flask_app.config[&quot;SERVER_ZMQ_URI&quot;])
          self.zmq_socket = zmq_socket
  
      def process(self, request):
          zmq_socket = self.zmq_socket
  
          poller = zmq.Poller()
          poller.register(zmq_socket, zmq.POLLIN)
  
          zmq_socket.send_json({
              &quot;command&quot;: request[&quot;command&quot;],
              &quot;arguments&quot;: request[&quot;arguments&quot;]
          })
          sockets = dict(poller.poll(10 * 1000))
  
          if zmq_socket not in sockets:
              self.init_socket()
              result = request[&quot;result&quot;]
              result.set_exception(TimeoutError(&quot;The request to the backend timed out.&quot;))
              return
  
          received = zmq_socket.recv_json()
  
          result = request[&quot;result&quot;]
          if received[&quot;success&quot;]:
              result.set(received[&quot;result&quot;])
          else:
              result.set_exception(BackendError(received[&quot;result&quot;]))
  
      def _run(self):
          while True:
              self.process(self.inbox.get())
  
      def send(self, command, **kwargs):
          result = AsyncResult()
          self.inbox.put({
              &quot;command&quot;: command,
              &quot;arguments&quot;: kwargs,
              &quot;result&quot;: result
          })
          return result.get()
  
  
  class RollbarRequest(Request):
      @property
      def rollbar_person(self):
          if current_user.is_anonymous:
              return {
                  &quot;id&quot;: 0,
                  &quot;username&quot;: &quot;anonymous&quot;
              }
          return {
              &quot;id&quot;: current_user.id,
              &quot;username&quot;: current_user.name,
              &quot;email&quot;: current_user.email_address
          }
  
  
  def create_app(*args, **kwargs):
      global flask_app
      global l
  
      app_mode = os.environ.get(&quot;APP_MODE&quot;)
  
      assert app_mode is not None, &quot;APP_MODE environment variable must be set&quot;
  
      flask_app = Flask(__name__)
      flask_app.request_class = RollbarRequest
      flask_app.config.from_object(&quot;config.mode_{}&quot;.format(app_mode))
      flask_app.config[&quot;APP_MODE&quot;] = app_mode
      setup_logging(flask_app.config[&quot;LOGGING_LEVEL&quot;])
      l = logging.getLogger(__name__)
      l.info(&quot;starting in mode {}&quot;.format(app_mode))
  
      if not flask_app.config[&quot;DEBUG&quot;]:
          rollbar.init(
              flask_app.config[&quot;ROLLBAR_API_KEY&quot;],
              app_mode,
              allow_logging_basic_config=False
          )
  
      flask_app.jinja_env.globals.update(
          current_year=lambda: datetime.datetime.now().year
      )
  
      if not flask_app.debug:
          flask_app.wsgi_app = ProxyFix(flask_app.wsgi_app)
  
      flask_app.db = SQLAlchemy(flask_app)
      flask_app.bcrypt = Bcrypt(flask_app)
      flask_app.assets = Environment(flask_app)
      Bootstrap(flask_app)
      flask_app.images = UploadSet(&quot;images&quot;, IMAGES)
      configure_uploads(flask_app, flask_app.images)
  
         
      from app import views
      from app import models
      from app import commands
  
      flask_app.backend = Backend()
      flask_app.backend.start()
  
      app.exceptions.register(flask_app)
      socketio.init_app(flask_app)
      return flask_app
  </code></pre>
  <p>This is my <strong>manage.py</strong></p>
  <pre><code>import gevent.monkey
  
  gevent.monkey.patch_all()
  
  import click
  from app import create_app, socketio
  from flask.cli import FlaskGroup
  
  
  @click.group(cls=FlaskGroup, create_app=create_app, add_default_commands=False)
  def cli():
      &quot;&quot;&quot;App management script.&quot;&quot;&quot;
      socketio.run(create_app, debug=False, log_output=True, async_mode='eventlet')
  
  
  if __name__ == &quot;__main__&quot;:
      cli()
  </code></pre>
  <p><strong>nginx configuration</strong> file inside /usr/local/nginx/conf/nginx.conf</p>
  <pre><code>user www-data;
  worker_processes auto;
  #pid /run/nginx.pid;
  
  events {
          worker_connections 1024;
          # multi_accept on;
  }
  # RTMP configuration
  rtmp {
      server {
          listen 1935; # Listen on standard RTMP port
          chunk_size 4000;
  
          application my_app_name {
              live on;
              # Turn on HLS
              hls off;
              hls_path /mnt/hls/;
              hls_fragment 3;
              hls_playlist_length 60;
              # disable consuming the stream from nginx as rtmp
              #deny play all;
              record off;
              on_publish http://127.0.0.1:5000/authenticate_user;
              on_publish_done  http://127.0.0.1:5000/end_live;
          }
      }
  }
  
  http {
                  directio 512;
          ##
          # Basic Settings
          ##
  
          sendfile on;
          tcp_nopush on;
          tcp_nodelay on;
          keepalive_timeout 65;
          types_hash_max_size 2048;
          # server_tokens off;
  
          # server_names_hash_bucket_size 64;
          # server_name_in_redirect off;
  
          include /etc/nginx/mime.types;
          default_type application/octet-stream;
  
          ##
          # SSL Settings
          ##
  
          ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
          ssl_prefer_server_ciphers on;
  
          ##
          # Logging Settings
          ##
  
          access_log /var/log/nginx/access.log;
          error_log /var/log/nginx/error.log;
  
          ##
          # Gzip Settings
          ##
  
          gzip on;
          gzip_disable &quot;msie6&quot;;
  
          # gzip_vary on;
          # gzip_proxied any;
          # gzip_comp_level 6;
          # gzip_buffers 16 8k;
          # gzip_http_version 1.1;
          # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
  
          ##
          # Virtual Host Configs
          ##
  
          include /etc/nginx/conf.d/*.conf;
          include /etc/nginx/sites-enabled/*;
          server {
                  listen 8080;
  
                  location / {
                          # Disable cache
                          add_header 'Cache-Control' 'no-cache';
  
                          # CORS setup
                          add_header 'Access-Control-Allow-Origin' '*' always;
                          add_header 'Access-Control-Expose-Headers' 'Content-Length';
  
                          # allow CORS preflight requests
                          if ($request_method = 'OPTIONS') {
                                  add_header 'Access-Control-Allow-Origin' '*';
                                  add_header 'Access-Control-Max-Age' 1728000;
                                  add_header 'Content-Type' 'text/plain charset=UTF-8';
                                  add_header 'Content-Length' 0;
                                  return 204;
                          }
                          types {
                                  application/dash+xml mpd;
                                  application/vnd.apple.mpegurl m3u8;
                                  video/mp2t ts;
                          }
                            root /mnt/;
                  }
      }
  }
  </code></pre>
  <p>this is my <strong>app configuration</strong> file inside /etc/nginx/sites-enabled/app.conf</p>
  <pre><code>server {
      listen 80 default_server;
      return 301 https://$host$request_uri;
  }
  server {
      listen 443 ssl default_server;
      server_name dev.my_app_name.com
      client_max_body_size 32M;
      keepalive_timeout 15;
      add_header Strict-Transport-Security max-age=31536000;
      ssl_certificate keys/cert.pem;
      ssl_certificate_key keys/key.pem;
      ssl_session_cache shared:SSL:10m;
      ssl_session_timeout 10m;
      ssl_password_file keys/key_phrase;
      ssl_ciphers &quot;EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS&quot;;
      ssl_prefer_server_ciphers on;
      ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
      location / {
          proxy_redirect off;
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_set_header X-Forwarded-Host $host;
          proxy_set_header X-Forwarded-Port $server_port;
          proxy_pass http://127.0.0.1:5000;
      }
  
      location /socket.io {
          proxy_pass http://127.0.0.1:5000/socket.io;
          proxy_redirect off;
          proxy_buffering off;
  
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection &quot;Upgrade&quot;;
  
      }
      location /var/ {
          internal;
          alias /home/%(username)s/var/;
      }
      location /static/ {
          location ~* \.(js|css)$ {
              expires 30d;
          }
          expires 1h;
          alias /home/%(username)s/my_app_name/app/static/;
          access_log off;
          log_not_found off;
      }
      location /robots.txt {
          expires 1h;
          root /home/%(username)s/my_app_name/app/static/html;
          access_log off;
          log_not_found off;
      }
  }
  </code></pre>
  <p>and this is my <strong>supervisor configuration</strong> for app</p>
  <pre><code>[group:app]
  programs=gunicorn, backend
  [program:gunicorn]
  command= /home/ubuntu/app-pyvenv/bin/gunicorn 'app:create_app()' -c config/gunicorn.py -p ../var/run/gunicorn.pid
  environment=APP_MODE=&quot;production&quot;
  directory=/home/ubuntu/my_app_name
  user=ubuntu
  autostart=true
  autorestart=true
  redirect_stderr=true
  stdout_logfile=/home/ubuntu/var/log/frontend.log
  
  [program:backend]
  command=/home/ubuntu/my_app_name/manage.py server execbackend -p ../var/run/backend.pid
  environment=APP_MODE=&quot;production&quot;,LC_ALL=&quot;C.UTF-8&quot;,LANG=&quot;C.UTF-8&quot;
  directory=/home/ubuntu/my_app_name
  user=ubuntu
  autostart=true
  autorestart=true
  redirect_stderr=true
  stdout_logfile=/home/ubuntu/var/log/backend.log
  </code></pre>