libstore: migrate caFile, netrcFile, and downloadSpeed to FileTransferSettings

The `caFile`, `netrcFile`, and `downloadSpeed` settings are only used by
the file transfer subsystem but lived in the global `Settings` class.
This moves them to `FileTransferSettings` where they belong.

Co-authored-by: Amaan Qureshi <git@amaanq.com>
This commit is contained in:
eveeifyeve
2026-02-11 12:28:49 -05:00
committed by Amaan Qureshi
parent 46eabe34c2
commit 04d13a96e3
10 changed files with 162 additions and 124 deletions

View File

@@ -92,7 +92,7 @@ void Registry::remove(const Input & input)
static std::filesystem::path getSystemRegistryPath()
{
return settings.nixConfDir / "registry.json";
return nixConfDir() / "registry.json";
}
static std::shared_ptr<Registry> getSystemRegistry(const Settings & settings)

View File

@@ -305,9 +305,9 @@ void printVersion(const std::string & programName)
std::cout << "System type: " << settings.thisSystem << "\n";
std::cout << "Additional system types: " << concatStringsSep(", ", settings.extraPlatforms.get()) << "\n";
std::cout << "Features: " << concatStringsSep(", ", cfg) << "\n";
std::cout << "System configuration file: " << (settings.nixConfDir / "nix.conf").string() << "\n";
std::cout << "System configuration file: " << nixConfFile() << "\n";
std::cout << "User configuration files: "
<< os_string_to_string(ExecutablePath{.directories = settings.nixUserConfFiles}.render()) << "\n";
<< os_string_to_string(ExecutablePath{.directories = nixUserConfFiles()}.render()) << "\n";
std::cout << "Store directory: " << settings.nixStore << "\n";
std::cout << "State directory: " << settings.nixStateDir << "\n";
}

View File

@@ -80,13 +80,13 @@ void HttpsBinaryCacheStoreTest::SetUp()
std::this_thread::sleep_for(std::chrono::milliseconds(50));
/* FIXME: Don't use global settings. Tests are not run concurrently, so this is fine for now. */
oldCaCert = settings.caFile;
settings.caFile = caCert.string();
oldCaCert = fileTransferSettings.caFile;
fileTransferSettings.caFile = caCert.string();
}
void HttpsBinaryCacheStoreTest::TearDown()
{
settings.caFile = oldCaCert;
fileTransferSettings.caFile = oldCaCert;
serverPid.kill();
delTmpDir.reset();
}

View File

@@ -14,12 +14,12 @@ static void builtinFetchurl(const BuiltinBuilderContext & ctx)
this to be stored in a file. It would be nice if we could just
pass a pointer to the data. */
if (ctx.netrcData != "") {
settings.netrcFile = "netrc";
writeFile(settings.netrcFile, ctx.netrcData, 0600);
fileTransferSettings.netrcFile = "netrc";
writeFile(fileTransferSettings.netrcFile, ctx.netrcData, 0600);
}
settings.caFile = "ca-certificates.crt";
writeFile(*settings.caFile.get(), ctx.caFileData, 0600);
fileTransferSettings.caFile = "ca-certificates.crt";
writeFile(*fileTransferSettings.caFile.get(), ctx.caFileData, 0600);
auto out = get(ctx.drv.outputs, "out");
if (!out)

View File

@@ -35,6 +35,22 @@ namespace nix {
const unsigned int RETRY_TIME_MS_DEFAULT = 250;
const unsigned int RETRY_TIME_MS_TOO_MANY_REQUESTS = 60000;
std::filesystem::path FileTransferSettings::getDefaultSSLCertFile()
{
for (auto & fn :
{"/etc/ssl/certs/ca-certificates.crt", "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"})
if (pathAccessible(fn))
return fn;
return "";
}
FileTransferSettings::FileTransferSettings()
{
auto sslOverride = getEnv("NIX_SSL_CERT_FILE").value_or(getEnv("SSL_CERT_FILE").value_or(""));
if (sslOverride != "")
caFile = sslOverride;
}
FileTransferSettings fileTransferSettings;
static GlobalConfig::Register rFileTransferSettings(&fileTransferSettings);
@@ -482,8 +498,9 @@ struct curlFileTransfer : public FileTransfer
curl_easy_setopt(req, CURLOPT_HTTPHEADER, requestHeaders.get());
if (settings.downloadSpeed.get() > 0)
curl_easy_setopt(req, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) (settings.downloadSpeed.get() * 1024));
if (fileTransferSettings.downloadSpeed.get() > 0)
curl_easy_setopt(
req, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) (fileTransferSettings.downloadSpeed.get() * 1024));
if (request.method == HttpMethod::Head)
curl_easy_setopt(req, CURLOPT_NOBODY, 1);
@@ -512,7 +529,7 @@ struct curlFileTransfer : public FileTransfer
curl_easy_setopt(req, CURLOPT_SEEKDATA, this);
}
if (auto & caFile = settings.caFile.get())
if (auto & caFile = fileTransferSettings.caFile.get())
curl_easy_setopt(req, CURLOPT_CAINFO, caFile->c_str());
#if !defined(_WIN32)
@@ -525,7 +542,7 @@ struct curlFileTransfer : public FileTransfer
/* If no file exist in the specified path, curl continues to work
anyway as if netrc support was disabled. */
curl_easy_setopt(req, CURLOPT_NETRC_FILE, settings.netrcFile.get().c_str());
curl_easy_setopt(req, CURLOPT_NETRC_FILE, fileTransferSettings.netrcFile.get().c_str());
curl_easy_setopt(req, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
if (writtenToSink)

View File

@@ -1,12 +1,14 @@
#include "nix/store/globals.hh"
#include "nix/util/config-global.hh"
#include "nix/util/current-process.hh"
#include "nix/util/executable-path.hh"
#include "nix/util/archive.hh"
#include "nix/util/args.hh"
#include "nix/util/abstract-setting-to-json.hh"
#include "nix/util/compute-levels.hh"
#include "nix/util/executable-path.hh"
#include "nix/util/signals.hh"
#include "nix/store/filetransfer.hh"
#include <algorithm>
#include <map>
@@ -88,24 +90,6 @@ Settings::Settings()
#endif
(getEnvNonEmpty("NIX_STORE_DIR").value_or(getEnvNonEmpty("NIX_STORE").value_or(NIX_STORE_DIR))))
, nixStateDir(canonPath(getEnvNonEmpty("NIX_STATE_DIR").value_or(NIX_STATE_DIR)))
, nixConfDir(canonPath(getEnvOsNonEmpty(OS_STR("NIX_CONF_DIR"))
.transform([](auto && s) { return std::filesystem::path(s); })
.value_or(resolveNixConfDir())))
, nixUserConfFiles([] {
// Use the paths specified in NIX_USER_CONF_FILES if it has been defined
auto nixConfFiles = getEnvOs(OS_STR("NIX_USER_CONF_FILES"));
if (nixConfFiles.has_value()) {
return ExecutablePath::parse(*nixConfFiles).directories;
}
// Use the paths specified by the XDG spec
std::vector<std::filesystem::path> files;
auto dirs = getConfigDirs();
for (auto & dir : dirs) {
files.insert(files.end(), dir / "nix.conf");
}
return files;
}())
, nixDaemonSocketFile(canonPath(getEnvOsNonEmpty(OS_STR("NIX_DAEMON_SOCKET_PATH"))
.transform([](auto && s) { return std::filesystem::path(s); })
.value_or(nixStateDir / DEFAULT_SOCKET_PATH)))
@@ -115,10 +99,6 @@ Settings::Settings()
#endif
allowSymlinkedStore = getEnv("NIX_IGNORE_SYMLINK_STORE") == "1";
auto sslOverride = getEnv("NIX_SSL_CERT_FILE").value_or(getEnv("SSL_CERT_FILE").value_or(""));
if (sslOverride != "")
caFile = sslOverride;
/* Backwards compatibility. */
auto s = getEnv("NIX_REMOTE_SYSTEMS");
if (s) {
@@ -151,21 +131,21 @@ Settings::Settings()
void loadConfFile(AbstractConfig & config)
{
auto applyConfigFile = [&](const Path & path) {
auto applyConfigFile = [&](const std::filesystem::path & path) {
try {
std::string contents = readFile(path);
config.applyConfig(contents, path);
config.applyConfig(contents, path.string());
} catch (SystemError &) {
}
};
applyConfigFile((settings.nixConfDir / "nix.conf").string());
applyConfigFile(nixConfFile());
/* We only want to send overrides to the daemon, i.e. stuff from
~/.nix/nix.conf or the command line. */
config.resetOverridden();
auto files = settings.nixUserConfFiles;
auto files = nixUserConfFiles();
for (auto file = files.rbegin(); file != files.rend(); file++) {
applyConfigFile(file->string());
}
@@ -176,6 +156,35 @@ void loadConfFile(AbstractConfig & config)
}
}
const std::filesystem::path & nixConfDir()
{
static const std::filesystem::path dir =
canonPath(getEnvOsNonEmpty(OS_STR("NIX_CONF_DIR"))
.transform([](auto && s) { return std::filesystem::path(s); })
.value_or(resolveNixConfDir()));
return dir;
}
const std::vector<std::filesystem::path> & nixUserConfFiles()
{
static const std::vector<std::filesystem::path> files = [] {
// Use the paths specified in NIX_USER_CONF_FILES if it has been defined
auto nixConfFiles = getEnvOs(OS_STR("NIX_USER_CONF_FILES"));
if (nixConfFiles.has_value()) {
return ExecutablePath::parse(*nixConfFiles).directories;
}
// Use the paths specified by the XDG spec
std::vector<std::filesystem::path> files;
auto dirs = getConfigDirs();
for (auto & dir : dirs) {
files.insert(files.end(), dir / "nix.conf");
}
return files;
}();
return files;
}
unsigned int Settings::getDefaultCores()
{
const unsigned int concurrency = std::max(1U, std::thread::hardware_concurrency());
@@ -275,15 +284,6 @@ bool Settings::isWSL1()
#endif
}
std::filesystem::path Settings::getDefaultSSLCertFile()
{
for (auto & fn :
{"/etc/ssl/certs/ca-certificates.crt", "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"})
if (pathAccessible(fn))
return fn;
return "";
}
const ExternalBuilder * Settings::findExternalDerivationBuilderIfSupported(const Derivation & drv)
{
if (auto it = std::ranges::find_if(

View File

@@ -12,6 +12,7 @@
#include "nix/util/url.hh"
#include "nix/store/config.hh"
#include "nix/store/globals.hh"
#if NIX_WITH_AWS_AUTH
# include "nix/store/aws-creds.hh"
#endif
@@ -21,6 +22,12 @@ namespace nix {
struct FileTransferSettings : Config
{
private:
static std::filesystem::path getDefaultSSLCertFile();
public:
FileTransferSettings();
Setting<bool> enableHttp2{this, true, "http2", "Whether to enable HTTP/2 support."};
Setting<std::string> userAgentSuffix{
@@ -77,6 +84,64 @@ struct FileTransferSettings : Config
not processed quickly enough to exceed the size of this buffer, downloads may stall.
The default is 1048576 (1 MiB).
)"};
Setting<unsigned int> downloadSpeed{
this,
0,
"download-speed",
R"(
Specify the maximum transfer rate in kilobytes per second you want
Nix to use for downloads.
)"};
Setting<std::filesystem::path> netrcFile{
this,
nixConfDir() / "netrc",
"netrc-file",
R"(
If set to an absolute path to a `netrc` file, Nix uses the HTTP
authentication credentials in this file when trying to download from
a remote host through HTTP or HTTPS. Defaults to
`$NIX_CONF_DIR/netrc`.
The `netrc` file consists of a list of accounts in the following
format:
machine my-machine
login my-username
password my-password
For the exact syntax, see [the `curl`
documentation](https://ec.haxx.se/usingcurl-netrc.html).
> **Note**
>
> This must be an absolute path, and `~` is not resolved. For
> example, `~/.netrc` won't resolve to your home directory's
> `.netrc`.
)"};
Setting<std::optional<std::filesystem::path>> caFile{
this,
getDefaultSSLCertFile(),
"ssl-cert-file",
R"(
The path of a file containing CA certificates used to
authenticate `https://` downloads. Nix by default uses
the first of the following files that exists:
1. `/etc/ssl/certs/ca-certificates.crt`
2. `/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt`
The path can be overridden by the following environment
variables, in order of precedence:
1. `NIX_SSL_CERT_FILE`
2. `SSL_CERT_FILE`
)",
{},
// Don't document the machine-specific default value
false};
};
extern FileTransferSettings fileTransferSettings;

View File

@@ -29,6 +29,30 @@ struct MaxBuildJobsSetting : public BaseSetting<unsigned int>
unsigned int parse(const std::string & str) const override;
};
/**
* The directory where system configuration files are stored.
*
* This is needed very early during initialization, before a main
* `Settings` object can be constructed.
*/
const std::filesystem::path & nixConfDir();
/**
* The path to the system configuration file (`nix.conf`).
*/
static inline std::filesystem::path nixConfFile()
{
return nixConfDir() / "nix.conf";
}
/**
* A list of user configuration files to load.
*
* This is needed very early during initialization, before a main
* `Settings` object can be constructed.
*/
const std::vector<std::filesystem::path> & nixUserConfFiles();
struct LogFileSettings : public virtual Config
{
/**
@@ -72,8 +96,6 @@ class Settings : public virtual Config, private LocalSettings, private LogFileSe
bool isWSL1();
std::filesystem::path getDefaultSSLCertFile();
public:
Settings();
@@ -118,16 +140,6 @@ public:
*/
std::filesystem::path nixStateDir;
/**
* The directory where system configuration files are stored.
*/
std::filesystem::path nixConfDir;
/**
* A list of user configuration files to load.
*/
std::vector<std::filesystem::path> nixUserConfFiles;
/**
* File name of the socket the daemon listens to.
*/
@@ -314,7 +326,7 @@ public:
Setting<std::string> builders{
this,
"@" + nixConfDir.string() + "/machines",
"@" + (nixConfDir() / "machines").string(),
"builders",
R"(
A semicolon- or newline-separated list of build machines.
@@ -732,64 +744,6 @@ public:
/nix/store/a724znygmd1cac856j3gfsyvih3lw07j-bash-4.4-p23`.
)"};
Setting<unsigned int> downloadSpeed{
this,
0,
"download-speed",
R"(
Specify the maximum transfer rate in kilobytes per second you want
Nix to use for downloads.
)"};
Setting<std::string> netrcFile{
this,
(nixConfDir / "netrc").string(),
"netrc-file",
R"(
If set to an absolute path to a `netrc` file, Nix uses the HTTP
authentication credentials in this file when trying to download from
a remote host through HTTP or HTTPS. Defaults to
`$NIX_CONF_DIR/netrc`.
The `netrc` file consists of a list of accounts in the following
format:
machine my-machine
login my-username
password my-password
For the exact syntax, see [the `curl`
documentation](https://ec.haxx.se/usingcurl-netrc.html).
> **Note**
>
> This must be an absolute path, and `~` is not resolved. For
> example, `~/.netrc` won't resolve to your home directory's
> `.netrc`.
)"};
Setting<std::optional<std::filesystem::path>> caFile{
this,
getDefaultSSLCertFile(),
"ssl-cert-file",
R"(
The path of a file containing CA certificates used to
authenticate `https://` downloads. Nix by default uses
the first of the following files that exists:
1. `/etc/ssl/certs/ca-certificates.crt`
2. `/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt`
The path can be overridden by the following environment
variables, in order of precedence:
1. `NIX_SSL_CERT_FILE`
2. `SSL_CERT_FILE`
)",
{},
// Don't document the machine-specific default value
false};
Setting<bool> useXDGBaseDirectories{
this,
false,
@@ -843,7 +797,7 @@ public:
};
// FIXME: don't use a global variable.
extern Settings settings;
extern nix::Settings settings;
/**
* Load the configuration (from `nix.conf`, `NIX_CONFIG`, etc.) into the

View File

@@ -18,6 +18,7 @@
#include "nix/store/globals.hh"
#include "nix/store/build/derivation-env-desugar.hh"
#include "nix/util/terminal.hh"
#include "nix/store/filetransfer.hh"
#include <sys/un.h>
#include <fcntl.h>
@@ -1261,11 +1262,11 @@ void DerivationBuilderImpl::runChild(RunChildArgs args)
if (drv.isBuiltin() && drv.builder == "builtin:fetchurl") {
try {
ctx.netrcData = readFile(settings.netrcFile);
ctx.netrcData = readFile(fileTransferSettings.netrcFile);
} catch (SystemError &) {
}
if (auto & caFile = settings.caFile.get())
if (auto & caFile = fileTransferSettings.caFile.get())
try {
ctx.caFileData = readFile(*caFile);
} catch (SystemError &) {

View File

@@ -2,6 +2,7 @@
# include "nix/store/globals.hh"
# include "nix/store/personality.hh"
# include "nix/store/filetransfer.hh"
# include "nix/util/cgroup.hh"
# include "nix/util/linux-namespaces.hh"
# include "nix/util/logging.hh"
@@ -562,7 +563,7 @@ struct ChrootLinuxDerivationBuilder : ChrootDerivationBuilder, LinuxDerivationBu
if (pathExists(path))
ss.push_back(path);
if (auto & caFile = settings.caFile.get()) {
if (auto & caFile = fileTransferSettings.caFile.get()) {
if (pathExists(*caFile))
pathsInChroot.try_emplace(
"/etc/ssl/certs/ca-certificates.crt", canonPath(caFile->native(), true), true);