diff --git a/.env.example b/.env.example index 5ca052422d..8426e3a23e 100644 --- a/.env.example +++ b/.env.example @@ -5,6 +5,12 @@ OLLAMA_BASE_URL='http://localhost:11434' OPENAI_API_BASE_URL='' OPENAI_API_KEY='' +# With WEBSOCKET_MANAGER=redis, room channels require PUBLISH, SUBSCRIBE and +# PSUBSCRIBE permissions plus channel ACLs &socketio and &socketio#*. +# Set false for shared-channel delivery. This must match on every instance; +# changing it requires a full fleet restart, not a rolling restart. +# WEBSOCKET_REDIS_ROOM_CHANNELS=true + # AUTOMATIC1111_BASE_URL="http://localhost:7860" # For production, you should only need one host as diff --git a/backend/open_webui/socket/redis_room_channels.py b/backend/open_webui/socket/redis_room_channels.py index 715ccc1ea9..f5959624a6 100644 --- a/backend/open_webui/socket/redis_room_channels.py +++ b/backend/open_webui/socket/redis_room_channels.py @@ -2,6 +2,7 @@ import asyncio +from redis.exceptions import NoPermissionError from socketio import AsyncRedisManager @@ -38,6 +39,13 @@ class AsyncRedisRoomChannelManager(AsyncRedisManager): self._redis_connect() return await self.redis.publish(channel, self.json.dumps(data)) except error as exc: + if isinstance(exc, NoPermissionError): + self._get_logger().error( + 'Redis denied publishing: %s. Check PUBLISH permission and channel ACLs ' + '(&%s and &%s#*). To disable room channels, set ' + 'WEBSOCKET_REDIS_ROOM_CHANNELS=False on every instance and fully restart the fleet.', + exc, self.channel, self.channel, + ) if retries_left > 0: self._get_logger().error('Cannot publish to redis... retrying', extra={'redis_exception': str(exc)}) self.connected = False @@ -61,6 +69,13 @@ class AsyncRedisRoomChannelManager(AsyncRedisManager): async for message in self.pubsub.listen(): yield message except error as exc: + if isinstance(exc, NoPermissionError): + self._get_logger().error( + 'Redis denied subscribing: %s. Check SUBSCRIBE/PSUBSCRIBE permissions and channel ACLs ' + '(&%s and &%s#*). To disable room channels, set ' + 'WEBSOCKET_REDIS_ROOM_CHANNELS=False on every instance and fully restart the fleet.', + exc, self.channel, self.channel, + ) self._get_logger().error( f'Cannot receive from redis... retrying in {retry_sleep} secs', extra={'redis_exception': str(exc)},