osousa / livematrix

Livechat integration for your website, using matrix.
GNU General Public License v3.0
66 stars 5 forks source link

HTTPS Wont work. #3

Open GmodCentral opened 1 year ago

GmodCentral commented 1 year ago

All websites are required to have HTTPS now, when trying to open a chat on a site with this embedded into it via https, it fails and cant connect. If I disable https, it works fine.

osousa commented 1 year ago

Hello there,

It indeed works over TLS, i am using secure websockets (WSS) as well. You can check my personal website osousa.me

If you wish, i can provide you with my nginx configuration.

orangestreet commented 10 months ago

Hi I have the same issue can you please share your nginx config

osousa commented 10 months ago

Hi I have the same issue can you please share your nginx config

Hi there,

here you have a working example that is configured to use one website (website.com), together with the livematrix binary (lm.website.com):

# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
proxy_set_header X-Original-URI $request_uri;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
server {
    server_name _; # This is just an invalid value which will never trigger on a real hostname.
    server_tokens off;
    listen 80;
    access_log /var/log/nginx/access.log vhost;
    return 503;
}
server {
    server_name _; # This is just an invalid value which will never trigger on a real hostname.
    server_tokens off;
    listen 443 ssl http2;
    access_log /var/log/nginx/access.log vhost;
    return 503;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;
    ssl_certificate /etc/nginx/certs/default.crt;
    ssl_certificate_key /etc/nginx/certs/default.key;
}

# lm.website.com
upstream lm.website.com {
        ## Can be connected with "mego" network
        # livematrix
        server 172.21.0.6:8000;
}
server {
    server_name lm.website.com;
    listen 80 ;
    access_log /var/log/nginx/access.log vhost;
    # Do not HTTPS redirect Let'sEncrypt ACME challenge
    location ^~ /.well-known/acme-challenge/ {
        auth_basic off;
        auth_request off;
        allow all;
        root /usr/share/nginx/html;
        try_files $uri =404;
        break;
    }
    location / {
        return 301 https://$host$request_uri;
    }
}
server {
    server_name lm.website.com;
    listen 443 ssl http2 ;
    access_log /var/log/nginx/access.log vhost;
    ssl_session_timeout 5m;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;
    ssl_certificate /etc/nginx/certs/lm.website.com.crt;
    ssl_certificate_key /etc/nginx/certs/lm.website.com.key;
    ssl_dhparam /etc/nginx/certs/lm.website.com.dhparam.pem;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/nginx/certs/lm.website.com.chain.pem;
    add_header Strict-Transport-Security "max-age=31536000" always;
    include /etc/nginx/vhost.d/default;
    location / {
        proxy_pass http://lm.website.com;
}
}

# website.com
upstream website.com {
        ## Can be connected with "mego" network
        # me
        server 172.21.0.5:8080;
}
server {
    server_name website.com;
    listen 80 ;
    access_log /var/log/nginx/access.log vhost;
    # Do not HTTPS redirect Let'sEncrypt ACME challenge
    location ^~ /.well-known/acme-challenge/ {
        auth_basic off;
        auth_request off;
        allow all;
        root /usr/share/nginx/html;
        try_files $uri =404;
        break;
    }
    location / {
        return 301 https://$host$request_uri;
    }
}
server {
    server_name website.com;
    listen 443 ssl http2 ;
    access_log /var/log/nginx/access.log vhost;
    ssl_session_timeout 5m;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;
    ssl_certificate /etc/nginx/certs/website.com.crt;
    ssl_certificate_key /etc/nginx/certs/website.com.key;
    ssl_dhparam /etc/nginx/certs/website.com.dhparam.pem;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/nginx/certs/website.com.chain.pem;
    add_header Strict-Transport-Security "max-age=31536000" always;
    include /etc/nginx/vhost.d/default;
    location / {
        proxy_pass http://website.com;
}
}

# www.website.com
upstream www.website.com {
        ## Can be connected with "mego" network
        # me
        server 172.21.0.5:8080;
}
server {
    server_name www.website.com;
    listen 80 ;
    access_log /var/log/nginx/access.log vhost;
    # Do not HTTPS redirect Let'sEncrypt ACME challenge
    location ^~ /.well-known/acme-challenge/ {
        auth_basic off;
        auth_request off;
        allow all;
        root /usr/share/nginx/html;
        try_files $uri =404;
        break;
    }
    location / {
        return 301 https://$host$request_uri;
    }
}
server {
    server_name www.website.com;
    listen 443 ssl http2 ;
    access_log /var/log/nginx/access.log vhost;
    ssl_session_timeout 5m;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;
    ssl_certificate /etc/nginx/certs/www.website.com.crt;
    ssl_certificate_key /etc/nginx/certs/www.website.com.key;
    ssl_dhparam /etc/nginx/certs/www.website.com.dhparam.pem;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/nginx/certs/www.website.com.chain.pem;
    add_header Strict-Transport-Security "max-age=31536000" always;
    include /etc/nginx/vhost.d/default;
    location / {
        proxy_pass http://www.website.com;
}
}

This is my docker-compose.yml for my nginx-proxy that deals with routing traffic for the website and livematrix:

version: '2'

services:
  nginx-proxy:
    image: nginxproxy/nginx-proxy
    container_name: nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ~/.local/nginx-proxy/conf:/etc/nginx/conf.d
      - ~/.local/nginx-proxy/vhost:/etc/nginx/vhost.d
      - ~/.local/nginx-proxy/html:/usr/share/nginx/html
      - ~/.local/nginx-proxy/certs:/etc/nginx/certs:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro

  acme-companion:
    image: nginxproxy/acme-companion
    container_name: nginx-proxy-acme
    environment:
      - DEFAULT_EMAIL=osousa@pm.me
    volumes_from:
      - nginx-proxy
    volumes:
      - ~/.local/nginx-proxy/certs:/etc/nginx/certs:rw
      - ~/.local/nginx-proxy/acme:/etc/acme.sh
      - /var/run/docker.sock:/var/run/docker.sock:ro

volumes:
  conf: 
  vhost: 
  html: 
  certs: 
  acme: 

networks:
  default:
    name: mego
    external: true

Notice that i am sharing the network from docker.

This is my docker-compose.yml i use to deploy both the website and the livematrix:

version: '3.9'

services:
  me: 
    tty: true
    image: alpine:latest
    container_name: me
    restart: always
    volumes: 
      - ./misc/:/home/
    environment:
      - VIRTUAL_PORT=8080
      - VIRTUAL_HOST=website.com,www.website.com
      - LETSENCRYPT_HOST=website.com,www.website.com
      - LETSENCRYPT_EMAIL=username@website.com
      - ME_IPADDR=mdb
      - ME_PORT=3306
    expose:
      - "8080"
    entrypoint: 
      - "/home/entrypoint_me.sh"
    depends_on:
      - mdb

  livematrix: 
    tty: true
    image: debian:11-slim
    container_name: livematrix
    restart: always
    volumes: 
      - ./misc/:/home/
    environment:
      - VIRTUAL_PORT=8000
      - VIRTUAL_HOST=lm.website.com
      - LETSENCRYPT_HOST=lm.website.com 
      - LETSENCRYPT_EMAIL=username@website.com
    expose:
      - "8000"
    entrypoint: 
      - "/home/entrypoint_livematrix.sh"
    depends_on:
      - mdb
  mdb: 
    tty: true
    image: mariadb:latest
    container_name: mdb
    volumes:
      - ~/.local/mariadb:/var/lib/mysql
    environment:
      - MYSQL_USER="username"
      - MYSQL_HOST="mdb"
      - MYSQL_ROOT_PASSWORD="password"
      - MYSQL_PASSWORD="password"
      - MYSQL_DATABASE="username"
    restart: always

networks:
  default:
    name: mego
    external: true

Notice also that "me" container is my website, and "livematrix" container is for live matrix to run. Now take notice of the nginx-proxy and you'll understand how things are wired.

I have automation scripts to deal with letsencrypt cert deployments, containers and nginx-proxy configs but you can configure the nginx-proxy manually after deploying your website and livematrix containers. Of course you can avoid using docker at all, and do it all on your host, just use the nginx-proxy config i gave you and change the values manually. It will be easier this way. You can do letsencrypt manually as well, just make sure you point the nginx-proxy paths to your letsencrypt generated ones.

orangestreet commented 10 months ago

Thanks for this but there are a couple of variables defined that I do not have the values for:

proxy_set_header Connection $proxy_connection; proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl; proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;

I am not sure if they are in your include: include /etc/nginx/vhost.d/default;

I just cannot seem to connect to the web socket the initial https redirect works as it should.

orangestreet commented 10 months ago

server {

    root /usr/share/nginx/somefolder;
    index index.html index.htm index.nginx-debian.html;

    server_name whatever.domain.com;
    location / {
       proxy_pass http://<ip>:<port>;
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "Upgrade";
       proxy_set_header Host $host;
    }

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

} server { if ($host = whatever.domain.com) { return 301 https://$host$request_uri; } # managed by Certbot

    listen 80;

    server_name whatever.domain.com;
return 404; # managed by Certbot

}

orangestreet commented 10 months ago

This is my working nginx config after some trial and error..... thx for the pointers.