Jellyfin in docker with nginx reverse proxy not working

Okay, so I have jellyfin running in a container. On the docker host running the container, I have set up an nginx reverse proxy with a certificate signed by internal CA.

I can access it when I’m on the same subnet, 10.0.1.0/24. I’ve added 10.0.2.0/24 as LAN networks, and in the remote ip address filter. All good so far. Problem comes when I try to login from the 10.0.2.0/24 subnet; “Connection failure”…

Any tips? The log says the web socket isn’t handled properly it seems;

System.Net.WebSockets.WebSocketException (22230344): The remote party closed the WebSocket connection without completing the close handshake. ---> System.Net.WebSockets.WebSocketException (22230344): The remote party closed the WebSocket connection without completing the close handshake.
   at System.Net.WebSockets.ManagedWebSocket.ThrowIfEOFUnexpected(Boolean throwOnPrematureClosure)
   at System.Net.WebSockets.ManagedWebSocket.EnsureBufferContainsAsync(Int32 minimumRequiredBytes, CancellationToken cancellationToken, Boolean throwOnPrematureClosure)
   at System.Net.WebSockets.ManagedWebSocket.ReceiveAsyncPrivate[TWebSocketReceiveResultGetter,TWebSocketReceiveResult](Memory`1 payloadBuffer, CancellationToken cancellationToken, TWebSocketReceiveResultGetter resultGetter)
   at System.Net.WebSockets.ManagedWebSocket.ReceiveAsyncPrivate[TWebSocketReceiveResultGetter,TWebSocketReceiveResult](Memory`1 payloadBuffer, CancellationToken cancellationToken, TWebSocketReceiveResultGetter resultGetter)
   at Emby.Server.Implementations.SocketSharp.WebSocketSharpListener.ProcessWebSocketRequest(HttpContext ctx)

Edit: reading more in the logs I realize that the above message might be a follow-up error from this;

[2019-10-24 22:47:28.209 +02:00] [ERR] Failed to Connect or Bind to server
System.AggregateException: One or more errors occurred. (No such device or address) ---> System.Net.Internals.SocketExceptionFactory+ExtendedSocketException: No such device or address
   at System.Net.Dns.InternalGetHostByName(String hostName)
   at System.Net.Dns.ResolveCallback(Object context)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Dns.HostResolutionEndHelper(IAsyncResult asyncResult)
   at System.Net.Dns.EndGetHostAddresses(IAsyncResult asyncResult)
   at System.Net.Dns.<>c.<GetHostAddressesAsync>b__25_1(IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at Novell.Directory.Ldap.Connection.connect(String host, Int32 port, Int32 semaphoreId)
   at Novell.Directory.Ldap.LdapConnection.Connect(String host, Int32 port)
   at Jellyfin.Plugin.LDAP_Auth.LdapAuthenticationProviderPlugin.Authenticate(String username, String password)
---> (Inner Exception #0) System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (00000005, 6): No such device or address
   at System.Net.Dns.InternalGetHostByName(String hostName)
   at System.Net.Dns.ResolveCallback(Object context)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Dns.HostResolutionEndHelper(IAsyncResult asyncResult)
   at System.Net.Dns.EndGetHostAddresses(IAsyncResult asyncResult)
   at System.Net.Dns.<>c.<GetHostAddressesAsync>b__25_1(IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)<---

I’m not sure the websocket error would stop you from logging in. Can you ping the jellyfin server from the device which is failing to log in?

Also is that error in an app? Have you tried using a browser to see if that works?

I can ping it, yes. I can even open the login page and type in my username and password.

Did you follow the reverse proxy guide in the docs? http://jellyfin.org/docs/general/administration/reverse-proxy.html#nginx

It includes a section about websockets

If you look in the console of your browser when you load the page and try logging in does it give you any error messages?

Console says

Error opening web socket: Error: Cannot open web socket without access token.
Disabling default event handling
returning instance from getOrAddApiClient
Requesting url without automatic networking: https://jellyfin.my.internal.domain.com/Users/authenticatebyname

The authenticatebyname request fails with response code 400, which seems to be linked to the error message in the log;

System.Net.WebSockets.WebSocketException (1919243877): The remote party closed the WebSocket connection without completing the close handshake. ---> System.Net.WebSockets.WebSocketException (1919243877): The remote party closed the WebSocket connection without completing the close handshake.
   at System.Net.WebSockets.ManagedWebSocket.ThrowIfEOFUnexpected(Boolean throwOnPrematureClosure)
   at System.Net.WebSockets.ManagedWebSocket.EnsureBufferContainsAsync(Int32 minimumRequiredBytes, CancellationToken cancellationToken, Boolean throwOnPrematureClosure)
   at System.Net.WebSockets.ManagedWebSocket.ReceiveAsyncPrivate[TWebSocketReceiveResultGetter,TWebSocketReceiveResult](Memory`1 payloadBuffer, CancellationToken cancellationToken, TWebSocketReceiveResultGetter resultGetter)
   at System.Net.WebSockets.ManagedWebSocket.ReceiveAsyncPrivate[TWebSocketReceiveResultGetter,TWebSocketReceiveResult](Memory`1 payloadBuffer, CancellationToken cancellationToken, TWebSocketReceiveResultGetter resultGetter)
   at Emby.Server.Implementations.SocketSharp.WebSocketSharpListener.ProcessWebSocketRequest(HttpContext ctx)

This is my current nginx configuration, only thing not in here is the SSL stapling;

server {
	listen 80;
	server_name jellyfin.my.internal.domain.com;
	return 301 https://$host$request_uri;
}

server {
	listen 443 ssl http2;
	server_name jellyfin.my.internal.domain.com;
	ssl_certificate         /etc/nginx/ssl/jellyfin.crt;
	ssl_certificate_key     /etc/nginx/ssl/jellyfin.key;
	ssl_protocols           TLSv1 TLSv1.1 TLSv1.2;
	ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
	ssl_trusted_certificate /etc/nginx/ssl/rootCA.crt;
	
	location / {
		proxy_http_version 1.1;
		proxy_pass http://localhost:8096;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
		proxy_set_header Host $host;
		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 $scheme;
		proxy_set_header X-Forwarded-Protocol $scheme;
		proxy_set_header X-Forwarded-Host $http_host;
		proxy_redirect off;
		proxy_buffering off;
	}
	
	location /socket {
		proxy_pass http://localhost:8096;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
		proxy_set_header Host $host;
		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 $scheme;
		proxy_set_header X-Forwarded-Protocol $scheme;
		proxy_set_header X-Forwarded-Host $http_host;
	}
} 

… Re-created user and got it working.