Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
eef8a1a
chore: bump version
lovesegfault Feb 13, 2026
6e88d0c
upload-release: disable containerd image store to preserve gzip layer…
amaanq Feb 16, 2026
b42319a
Merge pull request #15259 from obsidiansystems/backport-15252-to-2.33…
xokdvium Feb 16, 2026
e2af953
libutil/logging: Generalize writeToStderr into writeFullLogging
dramforever Feb 25, 2026
e258c32
libutil/logging: Use writeFullLogging in JSONLogger::write
dramforever Feb 25, 2026
a35595c
Merge pull request #15338 from NixOS/backport-15335-to-2.33-maintenance
internal-nix-ci[bot] Feb 25, 2026
296b8d7
Fix the nix-community/patsh/0.2.1 flake regression test (again)
edolstra Apr 25, 2025
0769726
Merge pull request #15343 from NixOS/backport-15341-to-2.33-maintenance
internal-nix-ci[bot] Feb 26, 2026
f543870
libstore: handle root path in RemoteFSAccessor::maybeLstat
LunNova Mar 8, 2026
1bd5fc5
Fix compatibility with lowdown 3
lisanna-dettwyler Mar 14, 2026
dbc3aa4
Merge pull request #15479 from NixOS/backport-15417-to-2.33-maintenance
internal-nix-ci[bot] Mar 15, 2026
db62d8d
Merge pull request #15483 from NixOS/backport-15475-to-2.33-maintenance
internal-nix-ci[bot] Mar 15, 2026
fa15a4c
fix(libstore/aws-creds): add STS WebIdentity provider to credential c…
lovesegfault Mar 17, 2026
ddae831
fix(libstore/aws-creds): add ECS container provider to credential chain
lovesegfault Mar 17, 2026
cb0e7fc
docs(rl-next): note restored S3 WebIdentity and ECS credential providers
lovesegfault Mar 17, 2026
de0b4c0
Merge pull request #15514 from NixOS/backport-15507-to-2.33-maintenance
internal-nix-ci[bot] Mar 18, 2026
d94e72a
Don't destroy windowSize mutex
edolstra Mar 25, 2026
7879276
Merge pull request #15561 from NixOS/backport-15551-to-2.33-maintenance
internal-nix-ci[bot] Mar 25, 2026
c4917ee
packaging: Make binaryTarball more reproducible
xokdvium Mar 26, 2026
28f2ce9
Merge pull request #15570 from NixOS/backport-15565-to-2.33-maintenance
internal-nix-ci[bot] Mar 26, 2026
ab2c750
tests/functional/stale-file-handle: Skip if the error doesn't happen
dramforever Mar 26, 2026
85d69b8
Merge pull request #15582 from NixOS/backport-15572-to-2.33-maintenance
internal-nix-ci[bot] Mar 27, 2026
2c5ce4c
libstore: Make temporary in-store directory not world-readable
xokdvium Apr 2, 2026
e7bf1cd
derivation-builder: Don't use copyFile for FOD output copying, put th…
xokdvium Apr 2, 2026
e4491cf
libstore: Use landlock with LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET for n…
xokdvium Apr 5, 2026
6a4351a
Merge tag '2.33.4' into sync-2.33.4
edolstra Apr 23, 2026
7d8efbc
sentry-native: Enable separate debug info
edolstra Apr 23, 2026
dd0920f
upload-debug-info-to-sentry.py: Upload .so files without separate deb…
edolstra Apr 23, 2026
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 .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.33.3
2.33.4
26 changes: 26 additions & 0 deletions doc/manual/rl-next/s3-credential-chain-web-identity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
synopsis: "S3: restore STS WebIdentity and ECS container credential providers"
prs: [15507]
---

Nix 2.33 replaced the S3 backend's `aws-sdk-cpp` credential chain with a
custom chain built on `aws-c-auth`. That chain omitted two providers,
breaking S3 binary cache access in container workloads:

- **STS WebIdentity** (`AWS_WEB_IDENTITY_TOKEN_FILE`, `AWS_ROLE_ARN`,
`AWS_ROLE_SESSION_NAME`) — used by EKS IRSA, GitHub Actions OIDC, and
any `sts:AssumeRoleWithWebIdentity` federation.
- **ECS container metadata** (`AWS_CONTAINER_CREDENTIALS_RELATIVE_URI`,
`AWS_CONTAINER_CREDENTIALS_FULL_URI`) — used by ECS tasks and EKS Pod
Identity.

The typical symptom was a misleading IMDS error
(`Valid credentials could not be sourced by the IMDS provider`), because
IMDS is the last provider tried after the correct one was skipped.

Both providers are now part of the chain, ordered to match the
pre-2.33 `DefaultAWSCredentialsProviderChain`:
`Environment → SSO → Profile → STS WebIdentity → (ECS | IMDS)`.
As in both the old and new AWS SDK default chains, ECS and IMDS are
mutually exclusive: when container credential environment variables are
set, IMDS is skipped.
6 changes: 4 additions & 2 deletions maintainers/upload-debug-info-to-sentry.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ def main():
for lib in libs:
build_id = get_build_id(lib)
if build_id is None:
print(f" {lib} (no build ID)", file=sys.stderr)
print(f" {lib} (no build ID, uploading binary)", file=sys.stderr)
debug_files.append(lib)
continue

local = find_debug_file_in_dirs(build_id, args.debug_dir)
Expand All @@ -141,7 +142,8 @@ def main():

debuginfo = fetch_debuginfo(build_id)
if debuginfo is None:
print(f" {lib} ({build_id}, no debug info in cache)", file=sys.stderr)
print(f" {lib} ({build_id}): no separate debug info, uploading binary", file=sys.stderr)
debug_files.append(lib)
continue
print(f" {lib} ({build_id}): member={debuginfo['member']}", file=sys.stderr)
nar_path = download_nar(build_id, debuginfo["archive"])
Expand Down
5 changes: 3 additions & 2 deletions packaging/binary-tarball.nix
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ runCommand "nix-binary-tarball-${version}" env ''
fn=$out/$dir.tar.xz
mkdir -p $out/nix-support
echo "file binary-dist $fn" >> $out/nix-support/hydra-build-products
tar cfJ $fn \
tar cf - \
--sort=name \
--owner=0 --group=0 --mode=u+rw,uga+r \
--mtime='1970-01-01' \
--absolute-names \
Expand All @@ -90,5 +91,5 @@ runCommand "nix-binary-tarball-${version}" env ''
$TMPDIR/install-freebsd-multi-user.sh \
$TMPDIR/install-multi-user \
$TMPDIR/reginfo \
$(cat ${installerClosureInfo}/store-paths)
$(cat ${installerClosureInfo}/store-paths) | xz --threads=1 > $fn
''
2 changes: 2 additions & 0 deletions packaging/sentry-native.nix
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,6 @@ stdenv.mkDerivation rec {
"out"
"dev"
];

separateDebugInfo = true;
}
4 changes: 3 additions & 1 deletion src/libcmd/markdown.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ static std::string doRenderMarkdownToTerminal(std::string_view markdown)
# endif
.feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES,
.oflags =
# if HAVE_LOWDOWN_1_4
# if HAVE_LOWDOWN_3
LOWDOWN_NORELLINK
# elif HAVE_LOWDOWN_1_4
LOWDOWN_TERM_NORELLINK // To render full links while skipping relative ones
# else
LOWDOWN_TERM_NOLINK
Expand Down
4 changes: 4 additions & 0 deletions src/libcmd/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ configdata.set(
'HAVE_LOWDOWN_1_4',
lowdown.version().version_compare('>= 1.4.0').to_int(),
)
configdata.set(
'HAVE_LOWDOWN_3',
lowdown.version().version_compare('>= 3.0.0').to_int(),
)

readline_flavor = get_option('readline-flavor')
if readline_flavor == 'editline'
Expand Down
100 changes: 87 additions & 13 deletions src/libstore/aws-creds.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# include <aws/crt/auth/Credentials.h>
# include <aws/crt/io/Bootstrap.h>

// C library headers for SSO provider support
// C library headers for SSO, STS WebIdentity, and ECS credential providers
# include <aws/auth/credentials.h>

// C library headers for custom logging
Expand Down Expand Up @@ -170,6 +170,53 @@ static std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider> createSSOProvider(
return createWrappedProvider(aws_credentials_provider_new_sso(allocator, &options), allocator);
}

/**
* Create an STS WebIdentity credentials provider using the C library directly.
* This reads AWS_WEB_IDENTITY_TOKEN_FILE, AWS_ROLE_ARN, AWS_ROLE_SESSION_NAME,
* and AWS_REGION from the environment (falling back to the profile config).
* Used by EKS IRSA, GitHub Actions OIDC, and other sts:AssumeRoleWithWebIdentity flows.
* Returns nullptr if the required parameters can't be resolved.
*/
static std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider> createSTSWebIdentityProvider(
const std::string & profileName,
Aws::Crt::Io::ClientBootstrap * bootstrap,
Aws::Crt::Io::TlsContext * tlsContext,
Aws::Crt::Allocator * allocator = Aws::Crt::ApiAllocator())
{
aws_credentials_provider_sts_web_identity_options options;
AWS_ZERO_STRUCT(options);

options.bootstrap = bootstrap->GetUnderlyingHandle();
options.tls_ctx = tlsContext ? tlsContext->GetUnderlyingHandle() : nullptr;
if (!profileName.empty()) {
options.profile_name_override = aws_byte_cursor_from_c_str(profileName.c_str());
}

return createWrappedProvider(aws_credentials_provider_new_sts_web_identity(allocator, &options), allocator);
}

/**
* Create an ECS container credentials provider using the C library directly.
* This reads AWS_CONTAINER_CREDENTIALS_RELATIVE_URI or
* AWS_CONTAINER_CREDENTIALS_FULL_URI (plus the optional
* AWS_CONTAINER_AUTHORIZATION_TOKEN / _TOKEN_FILE) from the environment.
* Used by ECS tasks and EKS Pod Identity.
* Returns nullptr if neither URI env var is set.
*/
static std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider> createECSProvider(
Aws::Crt::Io::ClientBootstrap * bootstrap,
Aws::Crt::Io::TlsContext * tlsContext,
Aws::Crt::Allocator * allocator = Aws::Crt::ApiAllocator())
{
aws_credentials_provider_ecs_environment_options options;
AWS_ZERO_STRUCT(options);

options.bootstrap = bootstrap->GetUnderlyingHandle();
options.tls_ctx = tlsContext ? tlsContext->GetUnderlyingHandle() : nullptr;

return createWrappedProvider(aws_credentials_provider_new_ecs_from_environment(allocator, &options), allocator);
}

static AwsCredentials getCredentialsFromProvider(std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider> provider)
{
if (!provider || !provider->IsValid()) {
Expand Down Expand Up @@ -223,13 +270,14 @@ class AwsCredentialProviderImpl : public AwsCredentialProvider
// This ensures AWS logs respect Nix's verbosity settings and are formatted consistently.
initialiseAwsLogger();

// Create a shared TLS context for SSO (required for HTTPS connections)
// Create a shared TLS context for SSO, STS WebIdentity, and ECS providers (required for HTTPS)
auto allocator = Aws::Crt::ApiAllocator();
auto tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitDefaultClient(allocator);
tlsContext =
std::make_shared<Aws::Crt::Io::TlsContext>(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT, allocator);
if (!tlsContext || !*tlsContext) {
warn("failed to create TLS context for AWS SSO; SSO authentication will be unavailable");
warn(
"failed to create TLS context for AWS credential providers; SSO, STS WebIdentity, and ECS container authentication will be unavailable");
tlsContext = nullptr;
}

Expand Down Expand Up @@ -273,19 +321,20 @@ AwsCredentialProviderImpl::createProviderForProfile(const std::string & profile)

debug("[pid=%d] creating new AWS credential provider for profile '%s'", getpid(), profileDisplayName);

// Build a custom credential chain: Environment → SSO → Profile → IMDS
// Build a custom credential chain: Environment → SSO → Profile → STS WebIdentity → ECS → IMDS
// This works for both default and named profiles, ensuring consistent behavior
// including SSO support and proper TLS context for STS-based role assumption.
Aws::Crt::Auth::CredentialsProviderChainConfig chainConfig;
auto allocator = Aws::Crt::ApiAllocator();

auto addProviderToChain = [&](std::string_view name, auto createProvider) {
auto addProviderToChain = [&](std::string_view name, auto createProvider) -> bool {
if (auto provider = createProvider()) {
chainConfig.Providers.push_back(provider);
debug("Added AWS %s Credential Provider to chain for profile '%s'", name, profileDisplayName);
} else {
debug("Skipped AWS %s Credential Provider for profile '%s'", name, profileDisplayName);
return true;
}
debug("Skipped AWS %s Credential Provider for profile '%s'", name, profileDisplayName);
return false;
};

// 1. Environment variables (highest priority)
Expand All @@ -311,12 +360,37 @@ AwsCredentialProviderImpl::createProviderForProfile(const std::string & profile)
return Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderProfile(profileConfig, allocator);
});

// 4. IMDS provider (for EC2 instances, lowest priority)
addProviderToChain("IMDS", [&]() {
Aws::Crt::Auth::CredentialsProviderImdsConfig imdsConfig;
imdsConfig.Bootstrap = bootstrap;
return Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderImds(imdsConfig, allocator);
});
// 4. STS WebIdentity (AWS_WEB_IDENTITY_TOKEN_FILE + AWS_ROLE_ARN — EKS IRSA, GitHub Actions OIDC)
// 5. ECS container metadata (AWS_CONTAINER_CREDENTIALS_RELATIVE_URI — ECS tasks, EKS Pod Identity)
// ECS and IMDS are mutually exclusive per both the aws-c-auth default chain and the
// pre-2.33 aws-sdk-cpp DefaultAWSCredentialsProviderChain: when container credential
// env vars are set, IMDS is skipped so a transient ECS endpoint failure can't silently
// fall through to the (typically broader) EC2 instance profile.
bool ecsAdded = false;
if (tlsContext) {
addProviderToChain("STS WebIdentity", [&]() {
return createSTSWebIdentityProvider(profile, bootstrap, tlsContext.get(), allocator);
});
ecsAdded =
addProviderToChain("ECS", [&]() { return createECSProvider(bootstrap, tlsContext.get(), allocator); });
} else {
debug(
"Skipped AWS STS WebIdentity and ECS Credential Providers for profile '%s': TLS context unavailable",
profileDisplayName);
}

// 6. IMDS provider (for EC2 instances, lowest priority) — only if ECS didn't claim the slot
if (!ecsAdded) {
addProviderToChain("IMDS", [&]() {
Aws::Crt::Auth::CredentialsProviderImdsConfig imdsConfig;
imdsConfig.Bootstrap = bootstrap;
return Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderImds(imdsConfig, allocator);
});
} else {
debug(
"Skipped AWS IMDS Credential Provider for profile '%s': ECS provider is active (mutually exclusive)",
profileDisplayName);
}

return Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderChain(chainConfig, allocator);
}
Expand Down
2 changes: 2 additions & 0 deletions src/libstore/remote-fs-accessor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ std::shared_ptr<SourceAccessor> RemoteFSAccessor::accessObject(const StorePath &

std::optional<SourceAccessor::Stat> RemoteFSAccessor::maybeLstat(const CanonPath & path)
{
if (path.isRoot())
return Stat{.type = tDirectory};
auto res = fetch(path);
return res.first->maybeLstat(res.second);
}
Expand Down
23 changes: 14 additions & 9 deletions src/libutil/logging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,18 +150,23 @@ class SimpleLogger : public Logger

Verbosity verbosity = lvlInfo;

void writeToStderr(std::string_view s)
static void writeFullLogging(Descriptor fd, std::string_view s)
{
try {
writeFull(getStandardError(), s, false);
writeFull(fd, s, false);
} catch (SystemError & e) {
/* Ignore failing writes to stderr. We need to ignore write
errors to ensure that cleanup code that logs to stderr runs
to completion if the other side of stderr has been closed
unexpectedly. */
/* Ignore failing logging writes. We need to ignore write
errors to ensure that cleanup code that writes logs runs
to completion if the other side of the logging fd has
been closed unexpectedly. */
}
}

void writeToStderr(std::string_view s)
{
writeFullLogging(getStandardError(), s);
}

std::unique_ptr<Logger> makeSimpleLogger(bool printBuildLogs)
{
return std::make_unique<SimpleLogger>(printBuildLogs);
Expand Down Expand Up @@ -245,15 +250,15 @@ struct JSONLogger : Logger

void write(const nlohmann::json & json)
{
auto line =
(includeNixPrefix ? "@nix " : "") + json.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
auto line = (includeNixPrefix ? "@nix " : "")
+ json.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace) + "\n";

/* Acquire a lock to prevent log messages from clobbering each
other. */
try {
auto state(_state.lock());
if (state->enabled)
writeLine(fd, line);
writeFullLogging(fd, line);
} catch (...) {
bool enabled = false;
std::swap(_state.lock()->enabled, enabled);
Expand Down
2 changes: 1 addition & 1 deletion src/libutil/terminal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int w

// Note: this object intentionally leaks to avoid a destructor ordering issue (specifically, ~ProgressBar() calling
// getWindowSize() after windowSize has been destroyed).
static auto * const windowSize = new Sync<std::pair<unsigned short, unsigned short>>({0, 0});
static auto * const windowSize = new Sync<std::pair<unsigned short, unsigned short>>{{0, 0}};

void updateWindowSize()
{
Expand Down
Loading