Skip to content

Commit 97c517d

Browse files
committed
Record builder host name in build provenance
1 parent cd0c020 commit 97c517d

File tree

9 files changed

+55
-8
lines changed

9 files changed

+55
-8
lines changed

src/libstore/globals.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include <curl/curl.h>
1616
#include <nlohmann/json.hpp>
1717

18+
#include <limits.h>
19+
1820
#ifndef _WIN32
1921
# include <sys/utsname.h>
2022
#endif
@@ -267,6 +269,20 @@ const ExternalBuilder * Settings::findExternalDerivationBuilderIfSupported(const
267269
return nullptr;
268270
}
269271

272+
std::optional<std::string> Settings::getHostName()
273+
{
274+
if (hostName != "")
275+
return hostName;
276+
277+
#ifndef _WIN32
278+
char hostname[_POSIX_HOST_NAME_MAX + 1];
279+
if (gethostname(hostname, sizeof(hostname)) == 0)
280+
return std::string(hostname);
281+
#endif
282+
283+
return std::nullopt;
284+
}
285+
270286
std::string nixVersion = PACKAGE_VERSION;
271287

272288
const std::string determinateNixVersion = DETERMINATE_NIX_VERSION;

src/libstore/include/nix/store/globals.hh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,6 +1441,16 @@ public:
14411441
* derivation, or else returns a null pointer.
14421442
*/
14431443
const ExternalBuilder * findExternalDerivationBuilderIfSupported(const Derivation & drv);
1444+
1445+
Setting<std::string> hostName{
1446+
this,
1447+
"",
1448+
"host-name",
1449+
R"(
1450+
The name of this host for recording build provenance. If unset, the Unix host name is used.
1451+
)"};
1452+
1453+
std::optional<std::string> getHostName();
14441454
};
14451455

14461456
// FIXME: don't use a global variable.

src/libstore/include/nix/store/provenance.hh

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,26 @@ struct BuildProvenance : Provenance
1818
*/
1919
OutputName output;
2020

21+
/**
22+
* The hostname of the machine on which the derivation was built, if known.
23+
*/
24+
std::optional<std::string> buildHost;
25+
2126
/**
2227
* The provenance of the derivation, if known.
2328
*/
2429
std::shared_ptr<const Provenance> next;
2530

2631
// FIXME: do we need anything extra for CA derivations?
2732

28-
BuildProvenance(const StorePath & drvPath, const OutputName & output, std::shared_ptr<const Provenance> next)
33+
BuildProvenance(
34+
const StorePath & drvPath,
35+
const OutputName & output,
36+
std::optional<std::string> buildHost,
37+
std::shared_ptr<const Provenance> next)
2938
: drvPath(drvPath)
3039
, output(output)
40+
, buildHost(std::move(buildHost))
3141
, next(std::move(next))
3242
{
3343
}

src/libstore/provenance.cc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ nlohmann::json BuildProvenance::to_json() const
99
{"type", "build"},
1010
{"drv", drvPath.to_string()},
1111
{"output", output},
12+
{"buildHost", buildHost},
1213
{"next", next ? next->to_json() : nlohmann::json(nullptr)},
1314
};
1415
}
@@ -18,8 +19,12 @@ Provenance::Register registerBuildProvenance("build", [](nlohmann::json json) {
1819
std::shared_ptr<const Provenance> next;
1920
if (auto p = optionalValueAt(obj, "next"); p && !p->is_null())
2021
next = Provenance::from_json(*p);
21-
return make_ref<BuildProvenance>(
22-
StorePath(getString(valueAt(obj, "drv"))), getString(valueAt(obj, "output")), next);
22+
std::optional<std::string> buildHost;
23+
if (auto p = optionalValueAt(obj, "buildHost"))
24+
buildHost = p->get<std::optional<std::string>>();
25+
auto buildProv = make_ref<BuildProvenance>(
26+
StorePath(getString(valueAt(obj, "drv"))), getString(valueAt(obj, "output")), buildHost, next);
27+
return buildProv;
2328
});
2429

2530
nlohmann::json CopiedProvenance::to_json() const

src/libstore/unix/build/derivation-builder.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1868,7 +1868,8 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
18681868
newInfo.deriver = drvPath;
18691869
newInfo.ultimate = true;
18701870
if (drvProvenance)
1871-
newInfo.provenance = std::make_shared<const BuildProvenance>(drvPath, outputName, drvProvenance);
1871+
newInfo.provenance =
1872+
std::make_shared<const BuildProvenance>(drvPath, outputName, settings.getHostName(), drvProvenance);
18721873
store.signPathInfo(newInfo);
18731874

18741875
finish(newInfo.path);

src/nix/provenance-show.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ R""(
88
# nix provenance show /run/current-system
99
/nix/store/k145bdxhdb89i4fkvgdisdz1yh2wiymm-nixos-system-machine-25.05.20251210.d2b1213
1010
← copied from cache.flakehub.com
11-
← built from derivation /nix/store/w3p3xkminq61hs00kihd34w1dglpj5s9-nixos-system-machine-25.05.20251210.d2b1213.drv (output out)
11+
← built from derivation /nix/store/w3p3xkminq61hs00kihd34w1dglpj5s9-nixos-system-machine-25.05.20251210.d2b1213.drv (output out) on build-machine
1212
← instantiated from flake output github:my-org/my-repo/6b03eb949597fe96d536e956a2c14da9901dbd21?dir=machine#nixosConfigurations.machine.config.system.build.toplevel
1313
```
1414

src/nix/provenance.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@ struct CmdProvenanceShow : StorePathsCommand
5757
provenance = copied->next;
5858
} else if (auto build = std::dynamic_pointer_cast<const BuildProvenance>(provenance)) {
5959
logger->cout(
60-
"← built from derivation " ANSI_BOLD "%s" ANSI_NORMAL " (output " ANSI_BOLD "%s" ANSI_NORMAL ")",
60+
"← built from derivation " ANSI_BOLD "%s" ANSI_NORMAL " (output " ANSI_BOLD "%s" ANSI_NORMAL
61+
") on " ANSI_BOLD "%s" ANSI_NORMAL,
6162
store.printStorePath(build->drvPath),
62-
build->output);
63+
build->output,
64+
build->buildHost.value_or("unknown host").c_str());
6365
provenance = build->next;
6466
} else if (auto flake = std::dynamic_pointer_cast<const FlakeProvenance>(provenance)) {
6567
// Collapse subpath/tree provenance into the flake provenance for legibility.

tests/functional/common/init.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ gc-reserved-space = 0
5252
substituters =
5353
flake-registry = $TEST_ROOT/registry.json
5454
show-trace = true
55+
host-name = test-host
5556
include nix.conf.extra
5657
trusted-users = $(whoami)
5758
${_NIX_TEST_EXTRA_CONFIG:-}

tests/functional/flakes/provenance.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ builder=$(nix eval --raw "$flake1Dir#packages.$system.default._builder")
1818
# Building a derivation should have tree+subpath+flake+build provenance.
1919
[[ $(nix path-info --json --json-format 1 "$outPath" | jq ".\"$outPath\".provenance") = $(cat <<EOF
2020
{
21+
"buildHost": "test-host",
2122
"drv": "$(basename "$drvPath")",
2223
"next": {
2324
"flakeOutput": "packages.$system.default",
@@ -92,6 +93,7 @@ nix copy --from "file://$binaryCache" "$outPath" --no-check-sigs
9293
{
9394
"from": "file://$binaryCache",
9495
"next": {
96+
"buildHost": "test-host",
9597
"drv": "$(basename "$drvPath")",
9698
"next": {
9799
"flakeOutput": "packages.$system.default",
@@ -124,7 +126,7 @@ EOF
124126
[[ $(nix provenance show "$outPath") = $(cat <<EOF
125127
$outPath
126128
← copied from file://$binaryCache
127-
← built from derivation [1m$drvPath[0m (output [1mout[0m)
129+
← built from derivation [1m$drvPath[0m (output [1mout[0m) on [1mtest-host[0m
128130
← instantiated from flake output git+file://$flake1Dir?ref=refs/heads/master&rev=$rev#packages.$system.default
129131
EOF
130132
) ]]

0 commit comments

Comments
 (0)