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:

can you help on how to run rasa with nginx in local, same situation , multiple bots hide the port number and all

hello @saurabh-m523 i have the same problem could you please help me solve this ? i am using docker-compose installation i have wo separate folder for each bot and two docker instance. both of them need to be accessible via https but i dont know how to make the configuration’s file

This is how I made it. I have multiple Rasa bots running in Ubuntu 18.04 cloud server. I use docker-compose to run them. For chatbot frontend I use Botfront webchat. Chatbot webpage is running in Apache2 webserver. And finally I have Nginx configured as HTTPS Reverse proxy. So it hides all port numbers and subdomains and also enables that behind it you can use HTTP. So here are my configuration files, hope they help
in this location

paulii@vetbot7:/etc/nginx/sites-available$
I have Nginx configuration file

server {


   server_name testibot1.omnia.fi;
   index index.php index.html index.htm index.nginx-debian.html;
   root /var/www/public_html/testibot1;

   location / {

   proxy_pass http://testibot1.omnia.fi:444;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $remote_addr;
   proxy_set_header Host $host;

   }

   location /socket.io/ {
   proxy_pass http://testibot1.omnia.fi:5006/socket.io/;
   proxy_http_version 1.1;
   proxy_set_header Upgrade $http_upgrade;
   proxy_set_header Connection 'upgrade';
   proxy_set_header Host $host;
   proxy_cache_bypass $http_upgrade;
   }

   access_log      /var/log/nginx/testibot1.fi_access.log;
   error_log       /var/log/nginx/testibot1.fi_error.log;


   listen 443 ssl; # managed by Certbot
   ssl_certificate /etc/letsencrypt/live/testibot1.omnia.fi/fullchain.pem; # managed by Certbot
   ssl_certificate_key /etc/letsencrypt/live/testibot1.omnia.fi/privkey.pem; # managed by Certbot
   include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
   ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}


server {


   server_name testibotti2.omnia.fi;
   index index.php index.html index.htm index.nginx-debian.html;
   root /var/www/public_html/testibotti2;

   location / {

   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $remote_addr;
   proxy_set_header Host $host;
   proxy_pass http://testibotti2.omnia.fi:444;
   }


   location /socket.io/ {
   proxy_pass http://testibotti2.omnia.fi:5007/socket.io/;
   proxy_http_version 1.1;
   proxy_set_header Upgrade $http_upgrade;
   proxy_set_header Connection 'upgrade';
   proxy_set_header Host $host;
   proxy_cache_bypass $http_upgrade;
   }


   access_log      /var/log/nginx/testibotti2.fi_access.log;
   error_log       /var/log/nginx/testibotti2.fi_error.log;


   listen 443 ssl; # managed by Certbot
   ssl_certificate /etc/letsencrypt/live/testibot1.omnia.fi/fullchain.pem; # managed by Certbot
   ssl_certificate_key /etc/letsencrypt/live/testibot1.omnia.fi/privkey.pem; # managed by Certbot
   include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
   ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
    if ($host = testibot1.omnia.fi) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


   listen 80;

   server_name testibot1.omnia.fi;
    return 404; # managed by Certbot


}

server {
    if ($host = testibotti2.omnia.fi) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


   listen 80;

   server_name testibotti2.omnia.fi;
   return 404; # managed by Certbot


}
 

and then my index file
in this location

paulii@vetbot7:/var/www/public_html/testibot1$

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <script src="https://cdn.jsdelivr.net/npm/rasa-webchat@0.11.12/lib/index.min.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
Testisaitti 1
<div id="webchat"></div>
<script>
  WebChat.default.init({
    showFullScreenButton: true,
    selector: "#webchat",
    initPayload: "/tervetuloa",
    customData: {"language": "fi"}, // arbitrary custom data. Stay minimal as this will be added to the socket
    //socketUrl: "http://testibot1.omnia.fi:5006",
    socketUrl: "https://testibot1.omnia.fi",
    socketPath: "/socket.io/",
    embedded: false,
    title: "AsPa botti",
    subtitle: "Testibotti 1",
    inputTextFieldHint: "Vastaa kysymyksiin",
    profileAvatar:"robot_icon.png",
    params: {"storage": "session"} // can be set to "local"  or "session". details in storage section.
  })
</script>

</body>
</html>

1 Like

hello @InnoOmnia thanks for your reply and sorry for the late reply so you generated two certificates with certbot ? how did you manage the ssl on differents ports ?

When use Certbot to create certificates it asks for what domain addresses you want to create certificates. Then Certbot add automatically all config files etc.

This is the key to use different ports

  location /socket.io/ {
   proxy_pass http://testibot1.omnia.fi:5006/socket.io/;
   proxy_http_version 1.1;
   proxy_set_header Upgrade $http_upgrade;
   proxy_set_header Connection 'upgrade';
   proxy_set_header Host $host;
   proxy_cache_bypass $http_upgrade;
   }
   location /socket.io/ {
   proxy_pass http://testibotti2.omnia.fi:5007/socket.io/;
   proxy_http_version 1.1;
   proxy_set_header Upgrade $http_upgrade;
   proxy_set_header Connection 'upgrade';
   proxy_set_header Host $host;
   proxy_cache_bypass $http_upgrade;
1 Like

oh great ! really and what about your docker-compose ?

your last post is for what file ? normally you have to modify something into the nginx folder if am not wrong

Here is docker-compose

paulii@vetbot7:~/uudet_botit$ cat docker-compose.yml
version: '3.0'
services:
  testibotti1:
    image: rasa/rasa:2.2.0-full
    restart: always
    ports:
      - 5006:5005
    volumes:
      - /home/paulii/uudet_botit/testibot1/:/app
    command:
     - run
     - -m
     - models
     - --enable-api
     - --cors
     - "*"
     - --debug

  testibotti2:
    image: rasa/rasa:2.2.0-full
    restart: always
    ports:
      - 5007:5005
    volumes:
      - /home/paulii/uudet_botit/testibot2/:/app
    command:
     - run
     - -m
     - models
     - --enable-api
     - --cors
     - "*"
     - --debug

Anything else I can help?

1 Like