'Websockets request fails with nginx-proxy for docker with ssl

I'm using nginx-proxy as a reverse proxy for my containers in a web server. I have a Laravel backend application with a Vue frontend and they communicate via Websockets using Laravel Websockets.

The communication works fine locally between the backend and frontend containers via HTTP but I'm having trouble using it in a web server via HTTPS.

I use acme-companion to generate and renew Let's encrypt certificates. The /etc/nginx/conf.d/default.conf file is edited following these instructions from Laravel Websockets for usage with nginx reverse proxy.

In the front end, I'm calling the WebSocket server wss://api.domain.com. As I understand, this would reach my location @ws and be proxied to the api container (copied the IP from the upstream) in port 6001 which is were my WebSocket server listens to. The problem is that no request are reaching the WebSocket server. I reloaded Nginx config after editing with nginx -s reload

Can someone help me? I can't seem to understand what I'm doing wrong or how to debug this properly as /var/log/nginx/access.log and /var/log/nginx/error.log inside the nginx-proxy container are empty. Thank you.

docker-compose.yml

version: '2'

services:

  nginx-proxy:
    container_name: nginx-proxy
    image: jwilder/nginx-proxy
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "/etc/nginx/vhost.d"
      - "/usr/share/nginx/html"
      - "/var/run/docker.sock:/tmp/docker.sock:ro"
      - "/etc/nginx/certs"

  letsencrypt-nginx-proxy-companion:
    container_name: letsencrypt-nginx-proxy-companion
    image: jrcs/letsencrypt-nginx-proxy-companion
    restart: always
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    volumes_from:
      - "nginx-proxy"

  api:
    container_name: api
    image: guizo/docker-laravel:php8.0-apache-postgres
    ports:
        - 6001:6001
    working_dir: /var/www/html
    volumes:
      - ./api:/var/www/html
    volumes_from:
      - "nginx-proxy"
    environment:
      VIRTUAL_HOST: api.domain.com
      LETSENCRYPT_HOST: api.domain.com

  app:
    container_name: app
    image: guizo/docker-nginx
    working_dir: /usr/share/nginx/html
    volumes:
      - ./app/dist:/usr/share/nginx/html
    environment:
      VIRTUAL_HOST: app.domain.com
      LETSENCRYPT_HOST: app.domain.com

/etc/nginx/conf.d/default.conf

map $http_upgrade $type {
  default "web";
  websocket "ws";
}
# api.domain.com
upstream api.domain.com-upstream {
    ## Can be connected with "dev_default" network
    # api
    server 172.18.0.4:80;
    # Fallback entry
    server 127.0.0.1 down;
}
server {
    server_name api.domain.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 api.domain.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/api.domain.com.crt;
    ssl_certificate_key /etc/nginx/certs/api.domain.com.key;
    ssl_dhparam /etc/nginx/certs/api.domain.com.dhparam.pem;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/nginx/certs/api.domain.com.chain.pem;
    add_header Strict-Transport-Security "max-age=31536000" always;
    include /etc/nginx/vhost.d/default;
    location / {
        try_files /nonexistent @$type;
    }
    location @web {
        proxy_pass http://api.domain.com-upstream;
    }
    location @ws  {
        proxy_pass             http://172.18.0.4:6001;
        proxy_set_header Host  $host;
        proxy_read_timeout     60;
        proxy_connect_timeout  60;
        proxy_redirect         off;

        # Allow the use of websockets
        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;
    }
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source