pump.io is selfish. It's intended to run on a standard web port, but it doesn't want to share that port with other services. This poses a problem to people who, like me, want to host their own pump.io server, but don't want to dedicate an entire host to it. So let's proxy it.
Disclaimer
The pump.io documentation advises against running pump.io behind a proxy, as doing so may cause the service to perform at a degraded level. The method presented seems to work okay for me, but your mileage may vary.
Also, keep in mind that if you already run a pump.io server, changing your server port may (will) break your existing OAuth relationships.
Why proxy?
If you're not already running services on standard web ports on your host, and you don't plan to do so in the future, then you don't need to worry about setting up a proxy in front of pump.io. Just follow the documentation to run pump.io directly on port 80 or 443. I strongly recommend running on port 443 with SSL enabled. I like Namecheap for cheap SSL certificates and StartSSL for free SSL certificates. Neither of these would be a good choice for an e-commerce site, but they're not bad for basic personal sites.
If you are already running services on standard web ports, then you won't be able to run pump.io on those ports. This is a common issue for web-facing software, and there are generally a couple of common solutions to this issue. One common solution is to configure a webserver to route certain incoming requests on a standard web port to an application handler via FastCGI or similar protocol. This cannot (currently?) be done with pump.io
Another common method of running web-facing services on a machine that already runs webservers is to proxy certain incoming requests on standard web ports to a service running on a separate port. This can currently be done with pump.io ... sort of. The pump.io documentation suggests that proxying pump.io behind a web server is going to make WebSockets "work less well." My webserver of choice, lighttpd, doesn't even have support for WebSockets. Other webservers such as nginx may support proxying WebSockets; in fact, there are articles describing how to configure pump.io behing nginx, such as this one. But this article describes a different solution: running pump.io and a separate webserver behind HAProxy.
The Case for HAProxy
HAProxy is a high-availability load balancer and proxy for TCP and HTTP connections. In a common scenario, a high-traffic site would run HAProxy on a web-facing machine and distribute the traffic to a number of separate hosts. That's all overkill for our application. But HAProxy also provides TCP and HTTP proxying which makes it an ideal WebSockets proxy.
Architecture
The proxy configuration makes use of HAProxy, lighttpd, and pump.io. A separate, dedicated subdomain (pump2.thisshitistemp.com) is created to access the pump.io service.
HAProxy sits in front of everything. Incoming requests on port 80 and 443 are received by HAProxy and routed to the appropriate destination based on simple configuration directives.
Within HAProxy, HTTP connections on port 80 are forwarded directly to lighttpd. However, since port 80 is not in use by HAProxy, lighttpd is modified to listen for HTTP requests on port 8080. Similarly, lighttpd is modified to listen for HTTPS requests on port 8443. But connections received by HAProxy on port 443 aren't immediately forwarded to lighttpd. First, HAProxy reads the destination hostname from the Server Name Indication (SNI). If the destination matches the pump.io subdomain, then HAProxy forwards that request directly to the pump.io service running on port 31337. Otherwise, the request is forwarded to lighttpd on port 8443.
+-----------+ all HTTP +------------+
----> :80 | --------- | ------------------> :8080 | |
| | | |
| HAProxy | | lighttpd |
| | other HTTPS | |
----> :443 | ---SNI--- | ------------------> :8443 | |
+-----------+ +------------+
|
| +------------+
| | |
| | |
| | pump.io |
| pump2.thisshitistemp.com | |
+-------------------------> :31337 | |
+------------+
Host Configuration
pump.io
Here are the relevant bits of the pump.io config file.
pump.io.json:
{
"hostname": "pump2.thisshitistemp.com",
"address": "127.0.0.1",
"port": 31337,
"urlPort": 443,
"noweb": false,
"site": "pump2.thisshitistemp.com",
}
HAProxy
And here is the HAProxy config file.
global
log 127.0.0.1 local2
chroot /usr/share/haproxy
pidfile /run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
defaults
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
frontend http-in *:80
mode http
default_backend servers
frontend https-in *:443
mode tcp
option tcplog
option socket-stats
option ssl-hello-chk
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
use_backend pumpio-ssl if { req_ssl_sni -i pump2.thisshitistemp.com }
default_backend servers-ssl
backend servers
mode http
option httpclose
option forwardfor
cookie JSESSIONID prefix
server server1 127.0.0.1:8000 cookie A check
backend servers-ssl
server server-ssl1 127.0.0.1:8001 check
backend pumpio-ssl
use-server pump if { req_ssl_sni -i pump2.thisshitistemp.com }
server pump 127.0.0.1:31337 weight 0