Force_ssl fails to upgrade websocket, but manual Plug.SSL plug works fine

I have a server that runs behind a Traefik (managed by Dokploy) reverse proxy which is behind Cloudflare CDN.

If I have this config for prod:

config :core, CoreWeb.Endpoint,
  force_ssl: [
    rewrite_on: [:x_forwarded_host, :x_forwarded_port, :x_forwarded_proto]
  ]

I will see warnings like this:

Plug.SSL is redirecting GET /live/websocket to https://hexhound.dev with status 301

From what I can see, the websocket tries to connect but the request will reach the phoenix backend with scheme :http instead of :https because (AFAIK) of Traefik.

If I comment the config and instead add this plug manually to my endpoint right after use Phoenix.Endpoint, otp_app: :core directly mimicking the exact opts the force_ssl flag will generate for Plug.SSL:

plug Plug.SSL,
  rewrite_on: [:x_forwarded_host, :x_forwarded_port, :x_forwarded_proto],
  host: {CoreWeb.Endpoint, :host, []}

Then, I will not see these websocket requests at all in the backend and the websocket will connect successfully.

I looked in Phoenix.Endpoint code, and AFAICT, both options should be equivalent. But they can’t be as the first one fails and the second one works fine.

Any idea what is happening here?

Looking more into this, seems like the difference between them is that with force_ssl the plug will be added before the websocket “validation”, while in my case it is before, meaning that a websocket connection never reaches my plug if I set it manually, while via force_ssl they do.

In that case, is it fine to just disable force_ssl altogether? Should I keep my manual plug call in Endpoint in this case or can I also get rid of it because in the end of the day all traffic is behind Traefik anyway?