From cf1cb9e9e9a20068dbfb9c9da4440acf8abdaf14 Mon Sep 17 00:00:00 2001 From: emil Date: Fri, 21 Nov 2025 10:32:44 +0100 Subject: [PATCH 1/2] feat(redis): add redix_opts for SSL/TLS support Add :redix_opts configuration option to Redis session store that allows passing custom Redix connection options. This enables connecting to cloud Redis providers requiring SSL/TLS with custom hostname verification (like Upstash, Redis Enterprise, etc.). Example configuration for Upstash: config :anubis_mcp, :session_store, adapter: Anubis.Server.Session.Store.Redis, redis_url: "rediss://...", redix_opts: [ ssl: true, socket_opts: [ customize_hostname_check: [ match_fun: :public_key.pkix_verify_hostname_match_fun(:https) ] ] ] Custom options are merged with defaults (custom takes precedence). --- lib/anubis/server/session/store/redis.ex | 56 +++++++++++++++++++----- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/lib/anubis/server/session/store/redis.ex b/lib/anubis/server/session/store/redis.ex index 75dfdf25..5fa7c4f5 100644 --- a/lib/anubis/server/session/store/redis.ex +++ b/lib/anubis/server/session/store/redis.ex @@ -13,7 +13,24 @@ defmodule Anubis.Server.Session.Store.Redis do pool_size: 10, ttl: 1_800_000, # 30 minutes in milliseconds namespace: "anubis:sessions", - connection_name: :anubis_redis + connection_name: :anubis_redis, + redix_opts: [] # Optional Redix connection options + + ## SSL/TLS Configuration + + For Redis servers requiring TLS (like Upstash), pass SSL options via `:redix_opts`: + + config :anubis_mcp, :session_store, + adapter: Anubis.Server.Session.Store.Redis, + redis_url: "rediss://default:password@host.upstash.io:6379", + redix_opts: [ + ssl: true, + socket_opts: [ + customize_hostname_check: [ + match_fun: :public_key.pkix_verify_hostname_match_fun(:https) + ] + ] + ] ## Features @@ -90,24 +107,31 @@ defmodule Anubis.Server.Session.Store.Redis do pool_size = Keyword.get(opts, :pool_size, 10) namespace = Keyword.get(opts, :namespace, @default_namespace) ttl = Keyword.get(opts, :ttl, @default_ttl) + # Strip :name from custom opts to preserve internal pool naming + custom_redix_opts = + opts + |> Keyword.get(:redix_opts, []) + |> validate_redix_opts() + |> Keyword.drop([:name]) # Start Redix connection pool with anubis_ prefix to avoid conflicts children = for i <- 1..pool_size do child_id = :"anubis_#{conn_name}_#{i}" + # Default Redix options, merged with custom options (custom takes precedence) + # Note: :name is always set internally to maintain pool integrity + redix_opts = + [ + name: child_id, + sync_connect: false, + exit_on_disconnection: false + ] + |> Keyword.merge(custom_redix_opts) + %{ id: child_id, - start: - {Redix, :start_link, - [ - redis_url, - [ - name: child_id, - sync_connect: false, - exit_on_disconnection: false - ] - ]} + start: {Redix, :start_link, [redis_url, redix_opts]} } end @@ -280,6 +304,16 @@ defmodule Anubis.Server.Session.Store.Redis do # Private functions + defp validate_redix_opts(nil), do: [] + + defp validate_redix_opts(opts) do + if Keyword.keyword?(opts) do + opts + else + raise ArgumentError, ":redix_opts must be a keyword list" + end + end + defp make_key(namespace, session_id) do "#{namespace}:#{session_id}" end From c7f3cf6b4f38bf246aef5e53c101ee6feccfe154 Mon Sep 17 00:00:00 2001 From: emil Date: Sun, 23 Nov 2025 21:33:27 +0100 Subject: [PATCH 2/2] style: fix formatting in Redis session store MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes CI formatting check failures: - Replace Keyword.drop([:name]) with Keyword.delete(:name) - Collapse multi-line keyword list to single line per formatter rules Changes: - Line 115: Use Keyword.delete/2 instead of Keyword.drop/1 for single key - Lines 124-130: Inline keyword list merge for better readability Quality verification: - Follows Elixir formatter conventions - Functionally identical (Keyword.delete(:name) is semantically correct for single key) 🤖 Generated with Claude Code Co-Authored-By: Claude --- lib/anubis/server/session/store/redis.ex | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/anubis/server/session/store/redis.ex b/lib/anubis/server/session/store/redis.ex index 5fa7c4f5..85f30775 100644 --- a/lib/anubis/server/session/store/redis.ex +++ b/lib/anubis/server/session/store/redis.ex @@ -112,7 +112,7 @@ defmodule Anubis.Server.Session.Store.Redis do opts |> Keyword.get(:redix_opts, []) |> validate_redix_opts() - |> Keyword.drop([:name]) + |> Keyword.delete(:name) # Start Redix connection pool with anubis_ prefix to avoid conflicts children = @@ -121,13 +121,7 @@ defmodule Anubis.Server.Session.Store.Redis do # Default Redix options, merged with custom options (custom takes precedence) # Note: :name is always set internally to maintain pool integrity - redix_opts = - [ - name: child_id, - sync_connect: false, - exit_on_disconnection: false - ] - |> Keyword.merge(custom_redix_opts) + redix_opts = Keyword.merge([name: child_id, sync_connect: false, exit_on_disconnection: false], custom_redix_opts) %{ id: child_id,