hack.chat icon indicating copy to clipboard operation
hack.chat copied to clipboard

HTTPS guide?

Open dennisjanssen opened this issue 8 years ago • 19 comments
trafficstars

I wanted to try and host one of those on a Raspberry Pi. I got everything to work as intended, but now I'm pretty clueless how to make it work over SSL. Has anyone managed to get this to work with Let's Encrypt? And if so... Any clues on how to do it?

I've read bits about hosting the static files on Apache of nginx, but I have no idea how to even get started on that. Any help would be appreciated!

dennisjanssen avatar Aug 01 '17 08:08 dennisjanssen

It's really easy and there are plenty of articles on it online: https://www.exratione.com/2013/06/websockets-over-ssl-with-nodejs-and-nginx/

raf924 avatar Aug 01 '17 08:08 raf924

Well, yes, I found a few like those... But then how do I change that to incorporate the port 6060 server, do I move the static files to /var/www or do I change the path, ... It's mostly how to configure the nginx together with Hack.Chat I'm struggling with I guess. But thanks for your help already!

dennisjanssen avatar Aug 01 '17 09:08 dennisjanssen

how to configure the nginx together with Hack.Chat

look at "how to proxy websockets using nginx" that will give you a client <--encrypted--> nginx <--local-->hack.chat connection. E.G this article looks good: https://www.nginx.com/blog/websocket-nginx/ (you can skip the npm and javascript part as you use hack.chat for that.

something like this should work (you probably want to add ssl directives though)

http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }

    upstream websocket {
        server 127.0.0.1:6060;
    }

    server {
        listen 6061;
        location / {
            proxy_pass http://websocket;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    }
}

then you need to change these lines: https://github.com/AndrewBelt/hack.chat/blob/master/client/client.js#L61-L68 to something like

ws = new WebSocket('wss://' + document.domain + ':6061')

M4GNV5 avatar Aug 01 '17 11:08 M4GNV5

this is what I have for a hc fork

server {                                                                                                                                     
    listen 80;                                                                                                                               
    server_name not.yourbusin.ess;                                                                                                      
    rewrite ^ https://$http_host$request_uri? permanent;                                                                                     
}                                                                                                                                            
                                                                                                                                             
server{                                                                                                                                      
  listen 443;                                                                                                                                
  ssl on;                                                                                                                                    
  server_name not.yourbusin.ess;                                                                                                        
  fastcgi_param   HTTPS               on;                                                                                                    
  fastcgi_param   HTTP_SCHEME         https;                                                                                                 
  ssl_certificate /etc/letsencrypt/live/not.yourbusin.ess/fullchain.pem;                                                                
  ssl_certificate_key /etc/letsencrypt/live/not.yourbusin.ess/privkey.pem;                                                              
  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_pass http://127.0.0.1:8080/;                                                                                                       
  }                                                                                                                                          
  location /chatws {                                                                                                                         
    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_pass http://127.0.0.1:6060/;                                                                                                       
    proxy_http_version 1.1;                                                                                                                  
    proxy_set_header Upgrade websocket;                                                                                                      
    proxy_set_header Connection upgrade;                                                                                                     
  }                                                                                                                                          
}              

raf924 avatar Aug 01 '17 12:08 raf924

Okay, this helped! I've managed to generate Let's Encrypt keys, edited your example file, etc. I ran into a snag where another app was using the 8080 port, but fixed that already. But now I'm afraid I'm stuck again, getting the error 502 Bad Gateway from nginx. Also, this might be relevant, HC is still working on port 80 and not redirecting me to HTTPS. Any ideas where to start looking?

dennisjanssen avatar Aug 01 '17 19:08 dennisjanssen

did you copy over this part

server {                                                                                                                                     
    listen 80;                                                                                                                               
    server_name not.yourbusin.ess;                                                                                                      
    rewrite ^ https://$http_host$request_uri? permanent;                                                                                     
}    

that's the part that makes the redirect also the content of my location / is not relevant to you because hc deliver static files while the fork I'm using uses a webserver.

raf924 avatar Aug 01 '17 19:08 raf924

Found it, I was starting HC on port 80 and obviously nginx on port 80, so letting HC start on port 8080 fixed that error.

I think I'm at my final issue. Everything works now, except that my console throws an error that he either can't reach URL:6060 (which I guess makes sense, since nginx is rerouting /chat-ws there) or that URL/chat-ws throws a 404. By now, I guessed I should edit this line: https://github.com/AndrewBelt/hack.chat/blob/master/client/client.js#L67 to

ws = new WebSocket('wss://' + document.domain + '/chat-ws')

But neither option is really working out. I'm going to guess I'm all good after that, so many thanks for your help already!


EDIT: Ugh, nevermind, noticed now your file says chatws instead of the chat-ws HC used. Dumb on my part. Thanks for helping me out on this!

dennisjanssen avatar Aug 01 '17 19:08 dennisjanssen

well on HC it's /chat-ws but on my nginx file it's /chatws that may be why you're struggling

raf924 avatar Aug 01 '17 19:08 raf924

Hi everyone, I've configured NGINX as a reverse proxy doing SSL termination. But I'm not sure if I should terminate it and pass along the request as plain http to the web socket or pass along the TLS to wss? If so then wouldn't wss also need to be configured with the path to the crt? Where / how should I make those changes?

Thanks!

nginx.conf:

server {
    listen 80;
    server_name site.chat www.site.chat;

    # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    return 301 https://$host$request_uri?;
}

server {
    listen 443 ssl;
    ssl on;   
    server_name site.chat www.site.chat;

    ssl_certificate /path/to/ssl_certificate.pem;
    ssl_certificate_key /path/to/ssl_private_key.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;

    ## verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /path/to/ssl_trust_chain.pem;

    resolver 74.82.42.42;

  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_pass http://127.0.0.1:8080/;
  }
  location /chat-ws {
    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_pass http://127.0.0.1:6060/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade websocket; 
    proxy_set_header Connection upgrade;
  }  

}

I receive this error:

root@www:/var/www/site.chat/hack.chat# npm start                                                                                                                                                                    

> [email protected] start /var/www/site.chat/hack.chat
> node server.js

Loaded config 'config.json'
Started server on 127.0.0.1:6060
/var/www/site.chat/hack.chat/server.js:64
                        socket._receiver.flush();
                                         ^

TypeError: socket._receiver.flush is not a function
    at WebSocket.<anonymous> (/var/www/site.chat/hack.chat/server.js:64:21)
    at emitOne (events.js:115:13)
    at WebSocket.emit (events.js:210:7)
    at Receiver._receiver.onmessage (/var/www/site.chat/hack.chat/node_modules/ws/lib/WebSocket.js:146:47)
    at Receiver.dataMessage (/var/www/site.chat/hack.chat/node_modules/ws/lib/Receiver.js:389:14)
    at Receiver.getData (/var/www/site.chat/hack.chat/node_modules/ws/lib/Receiver.js:330:12)
    at Receiver.startLoop (/var/www/site.chat/hack.chat/node_modules/ws/lib/Receiver.js:165:16)
    at Receiver.add (/var/www/site.chat/hack.chat/node_modules/ws/lib/Receiver.js:139:10)
    at Socket._ultron.on (/var/www/site.chat/hack.chat/node_modules/ws/lib/WebSocket.js:142:22)
    at emitOne (events.js:115:13)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: `node server.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     `/root/.npm/_logs/2017-09-30T10_13_58_468Z-debug.log

with this client.js line change: ws = new WebSocket('wss://' + document.domain + '/chat-ws')`

if I make client.js read: ws = new WebSocket('ws://' + document.domain + '/chat-ws')`

Then the page just sits there and fails.

Not sure how to proceed?

newdayhost avatar Sep 30 '17 10:09 newdayhost

@newdayhost See this for the error https://github.com/AndrewBelt/hack.chat/issues/136

raf924 avatar Sep 30 '17 13:09 raf924

I was able to get it to work by setting:

"homepage": "https://github.com/AndrewBelt/hack.chat",
"dependencies": {
  "ws": "=1.1.1"
},

in package.json and re-running npm install

Thanks @raf924 !

newdayhost avatar Oct 01 '17 01:10 newdayhost

@raf924 if i use you config i get error 400 on wss....

phonicmouse avatar Nov 21 '17 21:11 phonicmouse

Because the path is different on my config. It should be /chat-ws

raf924 avatar Nov 22 '17 12:11 raf924

@raf924 i changed that and checked everything double, i've also tried to change ws dependency from 3.0.0 to 1.1.1 and nothing change

phonicmouse avatar Nov 22 '17 13:11 phonicmouse

when you downgrade a dependency, you should remove its folder from node_modules or delete the whole node_modules folder and start npm install again

raf924 avatar Nov 22 '17 13:11 raf924

i know, i've done everything i know, but it still have problems.....

phonicmouse avatar Nov 22 '17 14:11 phonicmouse

you didn't modify the code?

raf924 avatar Nov 22 '17 14:11 raf924

dont know how, but using upstream with nginx reverse proxy it worked, thanks for support ;)

upstream websocket {
        server 127.0.0.1:6060;
}

phonicmouse avatar Nov 22 '17 14:11 phonicmouse

Weird you shouldn't have had to do that but great.

raf924 avatar Nov 22 '17 14:11 raf924