Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libfetchers/registry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/libmain/shared.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down
6 changes: 3 additions & 3 deletions src/libstore-test-support/https-store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
10 changes: 5 additions & 5 deletions src/libstore/builtins/fetchurl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -73,7 +73,7 @@ static void builtinFetchurl(const BuiltinBuilderContext & ctx)
/* Try the hashed mirrors first. */
auto dof = std::get_if<DerivationOutput::CAFixed>(&out->raw);
if (dof && dof->ca.method.getFileIngestionMethod() == FileIngestionMethod::Flat)
for (auto hashedMirror : settings.hashedMirrors.get())
for (auto hashedMirror : ctx.hashedMirrors)
try {
if (!hasSuffix(hashedMirror, "/"))
hashedMirror += '/';
Expand Down
25 changes: 21 additions & 4 deletions src/libstore/filetransfer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
70 changes: 35 additions & 35 deletions src/libstore/globals.cc
Original file line number Diff line number Diff line change
@@ -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>
Expand Down Expand Up @@ -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)))
Expand All @@ -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) {
Expand Down Expand Up @@ -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());
}
Expand All @@ -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());
Expand Down Expand Up @@ -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(
Expand Down
1 change: 1 addition & 0 deletions src/libstore/include/nix/store/builtins.hh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct BuiltinBuilderContext
std::map<std::string, Path> outputs;
std::string netrcData;
std::string caFileData;
Strings hashedMirrors;
Path tmpDirInSandbox;

#if NIX_WITH_AWS_AUTH
Expand Down
65 changes: 65 additions & 0 deletions src/libstore/include/nix/store/filetransfer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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{
Expand Down Expand Up @@ -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;
Expand Down
Loading
Loading