Running multiple chatbots on same server and hiding ports

Hey guys, Im developing two different chatbots and I have them on a Google Platform VM. I want to know how to access to them like this:

-> https://mydomain.com/chatbot1

-> https://mydomain.com/chatbot2

Instead of having:

-> https://mydomain.com:5001

-> https://mydomain.com:5002

I want to do that so I can run multiple chatbots on the same VM and I dont expose the ports. After doing this the idea is to insert the chatbot on a 3rd user web like this:

<script>
  WebChat.default.init({
    selector: "#webchat",
    initPayload: "XXX",
    interval: 1000,
    customData: {"userId": "123"},
    socketUrl: "http://mydomain.com/chatbot1",
    socketPath: "/socket.io/",
    title: "XXX",
    subtitle: "XXX",
    inputTextFieldHint: "XXX",
    connectingText: "XXX",
    hideWhenNotConnected: true,
    fullScreenMode: false,
    showFullScreenButton: false,
    profileAvatar: "xxx.jpg",
    params: {
      images: {
        dims: {
          width: 250,
          height: 200,
        }
      },
      storage: "XXX",
    },
  })
</script>

Both need to run through HTTPS. Is this possible? Do I need Apache or something similar? If this is the case, how can I configure it?

I dont know if it is relevant but I only have access to the VM through SSH.

You can achieve this with nginx. nginx will listen for requests coming at port 443 (HTTPS) and will act as a reverse proxy to forward the requests coming at these locations to the appropriate server.

Thanks! Could you give me an example of this with the code that I put above?

I suggest you read more about nginx.

You’ll need a config file for nginx, you can use something similar to the following:

server {
	listen 443 default_server;
	server_name mydomain.com;
	ssl on;
	ssl_certificate /path/to/certificate;
	ssl_certificate_key /path/to/certificate/key;
	ssl_session_cache shared:SSL:10m;

	location /chatbot1/ {
		proxy_pass http://localhost:5001/;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;                                                      
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
	}

	location /chatbot2/ {
		proxy_pass http://localhost:5002/;
		proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
	}

}

server {
	listen 80 default_server;
	server_name mydomain.com;
	return 301 https://$host$request_uri;
}

Note: I see that you want to use the socketio channel, hence the config of nginx above has been modified to upgrade the http connections to websocket connection.

1 Like

Thank you very much!

I tried it. Now I have nginx running on my server with the code that you gave me. But when I change from this:

  socketUrl: "https://chatbot.example.com.ar:5004",

to this:

  socketUrl: "https://chatbot.example.com.ar/chatbot1",

on my webpage, it doesnt work. My whole nginx.conf file looks like this:

user ib;
worker_processes auto;
error_log  logs/error.log;
pid     logs/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
        # multi_accept on;
}

http {

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        gzip on;

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;

        server {
                listen 443 ssl default_server;
                server_name chatbot.example.com.ar;
                ssl on;

                ssl_certificate         /etc/letsencrypt/live/chatbot.example.com.ar/fullchain.pem;
                ssl_certificate_key     /etc/letsencrypt/live/chatbot.example.com.ar/privkey.pem;
                ssl_trusted_certificate /etc/letsencrypt/live/chatbot.example.com.ar/chain.pem;
                ssl_session_cache shared:SSL:10m;

                location /chatbot1/ {
                        proxy_pass http://localhost:5004/;
                        proxy_http_version 1.1;
                        proxy_set_header Upgrade $http_upgrade;
                        proxy_set_header Connection "upgrade";
                        proxy_set_header Host $host;
                }
               location /chatbot2/ {
                        proxy_pass http://localhost:5006/;
                        proxy_http_version 1.1;
                        proxy_set_header Upgrade $http_upgrade;
                        proxy_set_header Connection "upgrade";
                        proxy_set_header Host $host;
                }

        }

        server {
                listen 80;
                server_name chatbot.example.com.ar;
                return 301 https://$host$request_uri;
        }


}

I dont know if I am doing something wrong or what. Maybe I should add the map and upstream websocket as its shown here?

Please if you can help me I would be very glad :grin::grin:

Cheers,

Facu

Could you change your script to this and try again?

 <script>
      WebChat.default.init({
        selector: "#webchat",
        initPayload: "XXX",
        interval: 1000,
        customData: {"userId": "123"},
        socketUrl: "https://mydomain.com",
        socketPath: "/chatbot1/socket.io/",
        title: "XXX",
        subtitle: "XXX",
        inputTextFieldHint: "XXX",
        connectingText: "XXX",
        hideWhenNotConnected: true,
        fullScreenMode: false,
        showFullScreenButton: false,
        profileAvatar: "xxx.jpg",
        params: {
          images: {
            dims: {
              width: 250,
              height: 200,
            }
          },
          storage: "XXX",
        },
      })
    </script>
1 Like

I have just tried it but it seems that doesn’t work neither.

Just to be sure, I run this two commands:

rasa run actions

rasa run --ssl-certificate /xxx/fullchain.pem --ssl-keyfile /xxx/privkey.pem --port 5004 -vv --cors '*' --enable-api --model xxx --endpoints /xxx/endpoints.yml --credentials /xxx/credentials.yml

And doing this it works if I put this:

 socketUrl: "https://chatbot.example.com.ar:5004",

So I dont think that the problem is a port misunderstanding :thinking:

You don’t need to run rasa with ssl arguments, that’s why we are configuring nginx to use https and act as a reverse proxy to rasa server.

1 Like

Well I remember doing this sometime ago and it worked for me. I’ll check day after tomorrow and see if I’m missing anything.

1 Like

Im going to try without the ssl arguments in rasa run and I will tell you.

I really appreciate your time and answers, they are helping me a lot. Thank you very much!!

You are welcome. I see that you have declared your server in nginx.conf file. I think the correct way to do this is to create a seperate conf file inside the sites-available directory and create a symbolic link to it in the sites-enabled directory. Atleast that’s how I did it back then :thinking:

1 Like

Hi! Finally it works!! Thank you very much. This wouldn’t be possible without your help. :hugs::hugs:

I’m going to list the things I have done to sum up for future users that might have the same question:

  1. Install nginx
  2. In your /etc/nginx/sites-available/default add the code that @saurabh-m523 put above ( make sure that you have a symbolic link to this file in /etc/nginx/sites-enabled/)
  3. On your html file, you should put this:
    socketUrl: "https://mydomain.com/",
    socketPath: "/chatbot1/socket.io/",
  1. And finally, you should run rasa without ssl certification

Thank you ver much @saurabh-m523 !!!

1 Like

You are welcome! :slightly_smiling_face: