Skip to content

Instantly share code, notes, and snippets.

@5290charlie
Forked from obolton/elb-nodejs-ws.md
Created April 14, 2017 23:53
Show Gist options
  • Save 5290charlie/0915c47c6009146b73aa6d83e5d6621a to your computer and use it in GitHub Desktop.
Save 5290charlie/0915c47c6009146b73aa6d83e5d6621a to your computer and use it in GitHub Desktop.
Configuring an AWS Elastic Load Balancer for a Node.js application using WebSockets on EC2

AWS ELB with Node.js and WebSockets

This assumes that:

  • You are using Nginx.
  • You want to accept incoming connections on port 80.
  • Your Node.js app is listening on port 3000.
  • You want to be able to connect to your Node.js instance directly as well as via the load balancer.

####1. Create load balancer

Create a load balancer in the relevant AWS region with these settings:

  • Load Balancer Protocol: TCP
  • Load Balancer Port: 80
  • Instance Protocol: TCP
  • Instance Port: 8080

For HTTPS/WSS support, add a listener with these settings:

  • Load Balancer Protocol: SSL
  • Load Balancer Port: 443
  • Instance Protocol: TCP
  • Instance Port: 8080

####2. Enable Proxy Protocol support

If the Node.js app needs to be able to see the client's real IP address for incoming WebSocket connections, you need to enable Proxy Protocol support on the load balancer. Without doing this all requests will appear to come from the load balancer.

Pour yourself a strong drink then follow the instructions here:

http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/enable-proxy-protocol.html

####2. Configure Nginx

Configure Nginx to get the client's IP address from the load balancer using Proxy Protocol. The requests from the load balancer need to be sent to a different port from ordinary connections, so that Nginx can intercept and remove the Proxy Protocol headers.

Your Nginx config should look similar to this:

# The Node.js application
upstream node_upstream {
  server localhost:3000 fail_timeout=10;
}

# Accept connections directly from clients
server {
  listen 80;
  charset utf-8;
  location / {
      proxy_pass http://node_upstream;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      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;
  }
}

# Accept connections via the load balancer
server {
  listen 8080 proxy_protocol;
  set_real_ip_from 10.0.0.0/8;
  real_ip_header proxy_protocol;
  charset utf-8;
  location / {
      proxy_pass http://node_upstream;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      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;
  }
}

####3. Create EC2 security groups

  • Assign a new security group to the load balancer which accepts incoming connections on port 80 (and 443 if you need SSL).
  • Create a security group for the EC2 instance hosting the Node.js app that:
    1. Accepts incoming connections on port 80 from all addresses.
    2. Accepts incoming connections on port 8080 only from the load balancer security group.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment