diff --git a/lix/libstore/globals.cc b/lix/libstore/globals.cc index f78a4409c..a5da2b728 100644 --- a/lix/libstore/globals.cc +++ b/lix/libstore/globals.cc @@ -50,7 +50,6 @@ namespace nix { appropriately. (This wouldn't work on the socket itself since it must be deleted and recreated on startup.) */ #define DEFAULT_SOCKET_DIR "/daemon-socket" -#define LEGACY_SOCKET "/socket" Settings settings; @@ -68,14 +67,14 @@ Settings::Settings() , nixManDir(canonPath(NIX_MAN_DIR)) { if (auto socketDirFromEnv = getEnvNonEmpty("LIX_DAEMON_SOCKET_DIR")) { - nixDaemonSockets_ = {{canonPath(*socketDirFromEnv + LEGACY_SOCKET)}}; + nixDaemonSockets_ = {{canonPath(*socketDirFromEnv + LEGACY_SOCKET_COMBINED)}}; } else if (auto socketPathFromEnv = getEnvNonEmpty("NIX_DAEMON_SOCKET_PATH")) { nixDaemonSockets_ = {{canonPath(*socketPathFromEnv)}}; } else { auto baseDir = nixStateDir + DEFAULT_SOCKET_DIR; // this should always match the list of sockets created by daemonLoop and the socket units nixDaemonSockets_ = { - {canonPath(baseDir + LEGACY_SOCKET)}, + {canonPath(baseDir + LEGACY_SOCKET_COMBINED)}, }; } diff --git a/lix/libstore/uds-remote-store.cc b/lix/libstore/uds-remote-store.cc index 0e4d69e6a..fb76b0fae 100644 --- a/lix/libstore/uds-remote-store.cc +++ b/lix/libstore/uds-remote-store.cc @@ -51,7 +51,9 @@ UDSRemoteStore::UDSRemoteStore( std::string UDSRemoteStore::getUri() { if (path) { - return std::string("unix://") + *path; + return fmt( + "unix://%s%s", *path, config().protocol.overridden ? fmt("?protocol=%s", config().protocol) : "" + ); } else { return "daemon"; } @@ -84,7 +86,17 @@ ref UDSRemoteStore::openConnection() std::list candidates; if (path) { - candidates.emplace_back(*path); + if (config().protocol == "any") { + candidates.emplace_back(*path + LEGACY_SOCKET_COMBINED); + } else { + for (const auto & proto : tokenizeString>(config().protocol.get(), " ,")) { + if (proto == "legacy-combined") { + candidates.emplace_back(*path); + } else { + throw Error("can't connect to %s with unknown daemon protocol %s", *path, proto); + } + } + } } else { candidates = settings.nixDaemonSockets() | std::views::transform([](auto & socket) { return socket.path; }) diff --git a/lix/libstore/uds-remote-store.hh b/lix/libstore/uds-remote-store.hh index a6cb74710..dc3bfb612 100644 --- a/lix/libstore/uds-remote-store.hh +++ b/lix/libstore/uds-remote-store.hh @@ -8,6 +8,8 @@ namespace nix { +constexpr inline std::string_view LEGACY_SOCKET_COMBINED = "/socket"; + struct UDSRemoteStoreConfig : virtual LocalFSStoreConfig, virtual RemoteStoreConfig { UDSRemoteStoreConfig(const Params & params) @@ -17,6 +19,24 @@ struct UDSRemoteStoreConfig : virtual LocalFSStoreConfig, virtual RemoteStoreCon { } + const Setting protocol{ + this, + "legacy-combined", + "protocol", + R"( + Space-or-comma-separated list of protocols to try to connect to, in preference order. + Currently supported: + - `legacy-combined` (default): legacy wire protocol using a single combined socket. + The provided path will be used *unmodified* to locate the combined daemon socket. + + Also supports the special value `any` to try *all* known protocols using the provided + path as the *base* directory for sockets. Unlike `legacy-combined` this will append a + `/socket` to the given path when trying to connect with the legacy-combined protocol. + + Ignored unless a path is also present. + )" + }; + const std::string name() override { return "Local Daemon Store"; } std::string doc() override; diff --git a/lix/libstore/uds-remote-store.md b/lix/libstore/uds-remote-store.md index 8df0bd6ff..eddb51555 100644 --- a/lix/libstore/uds-remote-store.md +++ b/lix/libstore/uds-remote-store.md @@ -4,6 +4,6 @@ R"( This store type accesses a Nix store by talking to a Nix daemon listening on the Unix domain socket *path*. The store pseudo-URL -`daemon` is equivalent to `unix:///nix/var/nix/daemon-socket/socket`. +`daemon` is equivalent to `unix:///nix/var/nix/daemon-socket?protocol=any`. )"