3

I've a server running Ubuntu 18.04 and Nginx and have a fully functioning instance of Jitsi Meet hosted on it. On the other hand I have 2 other sites (one a react front end and the other a backend) and i need them to have ssl certificates since we are using Jitsi Meet api from the front end and chrome is not letting us give permissions on the mic and camera because the front end is not secure.

So I tried installing certbot and getting a Let's Encrypt certificate but when i get it and try to restart nginx, it fails.

I think it has something to do with Jitsi using the port 443 or something but I really can't tell...

This is the nginx conf for jitsi domain:

server_names_hash_bucket_size 64;

server {
    listen 80;
    listen [::]:80;
    server_name video.<base-domain>;

    location ^~ /.well-known/acme-challenge/ {
       default_type "text/plain";
       root         <path-to-jitsi>;
    }
    location = /.well-known/acme-challenge/ {
       return 404;
    }
    location / {
       return 301 https://$host$request_uri;
    }
}
server {
    listen 4444 ssl http2;
    listen [::]:4444 ssl http2;
    server_name video.<base-domain>;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:E$

    add_header Strict-Transport-Security "max-age=31536000";

    ssl_certificate /etc/letsencrypt/live/video.<base-domain>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/video.<base-domain>/privkey.pem;

    root <path-to-jitsi>;

    # ssi on with javascript for multidomain variables in config.js
    ssi on;
    ssi_types application/x-javascript application/javascript;

    index index.html index.htm;
    error_page 404 /static/404.html;

    gzip on;
    gzip_types text/plain text/css application/javascript application/json;
    gzip_vary on;

    location = /config.js {
        alias /etc/jitsi/meet/video.<base-domain>-config.js;
    }
 #ensure all static content can always be found first
    location ~ ^/(libs|css|static|images|fonts|lang|sounds|connection_optimization|.well-known)/(.*)$
    {
        add_header 'Access-Control-Allow-Origin' '*';
        alias <path-to-jitsi>/$1/$2;
    }

    # BOSH
    location = /http-bind {
        proxy_pass      http://localhost:5280/http-bind;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $http_host;
    }

    # xmpp websockets
    location = /xmpp-websocket {
        proxy_pass http://127.0.0.1:5280/xmpp-websocket?prefix=$prefix&$args;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
        tcp_nodelay on;
    }
 location ~ ^/([^/?&:'"]+)$ {
        try_files $uri @root_path;
    }

    location @root_path {
        rewrite ^/(.*)$ / break;
    }

    location ~ ^/([^/?&:'"]+)/config.js$
    {
       set $subdomain "$1.";
       set $subdir "$1/";

       alias /etc/jitsi/meet/video.<base-domain>-config.js;
    }

    #Anything that didn't match above, and isn't a real file, assume it's a room name and redirect to /
    location ~ ^/([^/?&:'"]+)/(.*)$ {
        set $subdomain "$1.";
        set $subdir "$1/";
        rewrite ^/([^/?&:'"]+)/(.*)$ /$2;
    }
 # BOSH for subdomains
    location ~ ^/([^/?&:'"]+)/http-bind {
        set $subdomain "$1.";
        set $subdir "$1/";
        set $prefix "$1";

        rewrite ^/(.*)$ /http-bind;
    }

    # websockets for subdomains
    location ~ ^/([^/?&:'"]+)/xmpp-websocket {
        set $subdomain "$1.";
        set $subdir "$1/";
        set $prefix "$1";

        rewrite ^/(.*)$ /xmpp-websocket;
    }
}

this is the nginx conf for the front end domain:

server{
    server_name app.<base-domain> www.app.<base-domain>;
    root <path-to-front>;
        index index.html index.htm;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    charset utf-8;

    location / {
       try_files $uri /index.html;
    }


    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    error_log  /var/log/nginx/default-error.log error;

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }



   listen 443 ssl; # managed by Certbot
   ssl_certificate /etc/letsencrypt/live/app.<base-domain>/fullchain.pem; # managed by Certbot
   ssl_certificate_key /etc/letsencrypt/live/app.<base-domain>/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 = app.<base-domain>) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    server_name app.<base-domain> www.app.<base-domain>;
    listen 80;
    return 404; # managed by Certbot
}

this is the nginx error.log:

2020/05/15 12:21:58 [emerg] 20330#20330: bind() to 0.0.0.0:443 failed (98: Address already in use)
2020/05/15 12:21:58 [emerg] 20330#20330: bind() to 0.0.0.0:443 failed (98: Address already in use)
2020/05/15 12:21:58 [emerg] 20330#20330: bind() to 0.0.0.0:443 failed (98: Address already in use)
2020/05/15 12:21:58 [emerg] 20330#20330: bind() to 0.0.0.0:443 failed (98: Address already in use)
2020/05/15 12:21:58 [emerg] 20330#20330: bind() to 0.0.0.0:443 failed (98: Address already in use)
2020/05/15 12:21:58 [emerg] 20330#20330: still could not bind()

I was hoping someone can tell how I should configure this in order to have both jitsi and the front end secure.

I also will add that both domains are actually subdomains... meaning jitsi domain is video..com and front is app..com

the real config has base-domain and paths correctly specified... If I remove all ssl config from the front end nginx configuration, everything work again.

hunvee3
  • 47
  • 6
  • I think I'm having the same problem. To clarify: can you see if another process has the `443` port bound for itself? We can't see it being bound by anything, can you? And can you see the port being open in your firewall? If you can't see who has bound it, and the port is open in the FW, then I'm pretty sure we're experiencing the exact same issue. – felix91gr May 30 '20 at 05:47
  • Hi, i forgot to reply this. Apparently the problem was the turnserver. I uninstalled it and it worked. I followed one of the comments in this thread https://community.jitsi.org/t/bind-to-0-0-0-0-443-failed/28615/2 – hunvee3 Jun 08 '20 at 23:20
  • I see. We solved it by basically uninstalling all that was jitsi-exclusive and doing a custom install so that it could not take a hold of the port 443. It was pretty hard (jitsi seems like it really wants to exist by itself in the server), but it worked :3 – felix91gr Jun 10 '20 at 00:20

1 Answers1

0

if you need customized nginx file, here it is. But you should work on for security concerns.

** For standalone(without Docker) remove "resolver 127.0.0.1 valid=5s ipv6=off;" then change rest of 127.0.0.1 to localhost

Docker-jitsi-meet Custom Nginx Configuration

server {
      resolver 127.0.0.1 valid=5s ipv6=off;
      listen 80;
      listen [::]:80;
       server_name jitsiConf.domain.com; # managed by Certbot
       location /.well-known/acme-challenge {
            root /var/www/letsencrypt;
            default_type "text/plain";
            try_files $uri =404;
          }
       location / {
            return 301 https://$host$request_uri;
          }
      #rewrite ^ https://$http_host$request_uri? permanent; # force redirect http to https

  }
server {
    resolver 127.0.0.1 valid=5s ipv6=off;
    listen 443 ssl;
    listen   [::]:443 ssl;
    server_name jitsiConf.domain.com; # managed by Certbot

    ssl on;
    ssl_certificate /etc/letsencrypt/live/jitsiConf.domain.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/jitsiConf.domain.com/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

    ssl_protocols TLSv1.2 TLSv1.3;

    ssl_session_cache shared:SSL:50m;

    proxy_cookie_path / "/; HTTPOnly; Secure";
  add_header Expect-CT "enforce, max-age=21600";
  add_header Feature-Policy "payment none";

  keepalive_timeout    70;
  sendfile             on;
  client_max_body_size 0;

  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;


    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";

    # this tells the browser that jitsi can't be embedded in a Frame
    add_header X-Frame-Options "DENY";

    # List of Browser-Features which are allowed / denied for this Site
    add_header Feature-Policy "geolocation 'none'; camera 'self'; microphone 'self'; speaker 'self'; autoplay 'none'; battery 'none'; accelerometer 'none'; autoplay 'none'; payment 'none';";


    ssi on;
    ssi_types application/x-javascript application/javascript;



    # ensure all static content can always be found first
    #location ~ ^/(libs|css|static|images|fonts|lang|sounds|connection_optimization|.well-known)/(.*)$
    #{
    #    add_header 'Access-Control-Allow-Origin' '*';
    #}

    #location ~ ^/(?!(http-bind|external_api\.|xmpp-websocket))([a-zA-Z0-9=_äÄöÖüÜß\?\-]+)$ {
     #  rewrite ^/(.*)$ / break;
    #}

    location / {
         expires max;
        log_not_found off;
        proxy_cache_valid 200 120m;
            ssi on;
            set $upstream_endpoint http://127.0.0.1:8100;
            proxy_pass $upstream_endpoint;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header Host $host;
    }
    # BOSH
    location /http-bind {
        set $upstream_endpoint http://127.0.0.1:5280;
        proxy_pass      $upstream_endpoint/http-bind;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;
    }
    # xmpp websockets
    location /xmpp-websocket {
        set $upstream_endpoint http://127.0.0.1:5280;
        proxy_pass $upstream_endpoint;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        tcp_nodelay on;
    }
}

Also this configuration will be stuck on CSP error. Just for test developments this code will allow all CSP risks. you can add under the

ssl_session_cache shared:SSL:50m;

set $CSP_image  "img-src      'self' 'unsafe-inline' 'unsafe-eval' data: *.printfriendly.com *.w.org *.gravatar.com *.vimeocdn.com; ";
set $CSP_script "script-src   'self' 'unsafe-inline' 'unsafe-eval' *.w.org *.gravatar.com *.googleapis.com *.jsdelivr.net *.printfriendly.com *.kxcdn.com *.vimeocdn.com *.hs-analytics.net *.securitymetrics.com *.google-analytics.com; ";
set $CSP_style  "style-src    'self' 'unsafe-inline' *.googleapis.com *.bootstrapcdn.com *.gstatic.com *.vimeocdn.com; ";
set $CSP_font   "font-src     'self' data: *.googleapis.com *.bootstrapcdn.com *.gstatic.com *.googleapis.com; ";
set $CSP_frame  "frame-src    'self' *.vimeocdn.com *.vimeo.com; ";
set $CSP_object "object-src   'self' ; ";
set $CSP        "default-src  'self' ; ${CSP_image} ${CSP_script} ${CSP_style} ${CSP_font} ${CSP_frame} ${CSP_object}";

add_header Content-Security-Policy $CSP;

CSPallow **sorry i couldn't find original post*

HOO
  • 11
  • 3