Files
logos-messaging-module/flake.nix
osmaczko d169885318 flake: cap the delivery node's log level at build time
liblogosdelivery logs its own peer discovery, subscription upkeep and mesh heartbeats at INFO and DEBUG, several lines a second, so an embedding host's console is dominated by traffic it never asked for. The `logLevel` a caller passes to createNode cannot turn them off: chronicles resolves each statement's level at compile time unless the library is built with `chronicles_runtime_filtering`, which it is not, so the level the node stores at startup has nothing reading it.

Override the library's compile-time ceiling to WARN, the level that drops the traffic in question while keeping anything that reports a problem. Restoring the node's diagnostics means lowering it here and building the library from source, since the binary cache carries only the value committed here.
2026-07-21 18:04:59 +02:00

117 lines
5.5 KiB
Nix

{
description = "Logos Delivery Module";
# Pull pre-built artifacts (liblogosdelivery, librln, …) from the self-hosted
# Logos Attic cache. Read-only and public; see infra-ci#263.
nixConfig = {
extra-substituters = [ "https://cache.nix.logos.co/public" ];
extra-trusted-public-keys = [ "public:Z1wyVBEx8PHbXujYB52Mysv9Rd8rWIhyQ3bQyef9yy4=" ];
};
inputs = {
logos-module-builder.url = "github:logos-co/logos-module-builder";
nix-bundle-lgx.url = "github:logos-co/nix-bundle-lgx";
logos-delivery.url = "git+https://github.com/logos-messaging/logos-delivery?submodules=1";
};
outputs = inputs@{ logos-module-builder, ... }:
let
# The node's own logger drowns an embedding host: peer discovery,
# subscription upkeep and mesh heartbeats all log at INFO or DEBUG,
# several lines a second, whatever `logLevel` the caller passes to
# createNode. That key cannot silence them, because chronicles resolves
# each statement's level at compile time unless the library is built with
# `chronicles_runtime_filtering`, which it is not, leaving nothing to read
# the level the node stores at startup. Cap it at build time instead.
# Lowering this restores the node's diagnostics and costs a source build
# of the library, which the binary cache has only for this value.
quietedDelivery.packages = builtins.mapAttrs
(_system: systemPackages: {
liblogosdelivery = systemPackages.liblogosdelivery.override {
chroniclesLogLevel = "WARN";
};
})
inputs.logos-delivery.packages;
in
logos-module-builder.lib.mkLogosModule {
src = ./.;
configFile = ./metadata.json;
flakeInputs = inputs;
externalLibInputs = {
logosdelivery = {
input = quietedDelivery;
packages.default = "liblogosdelivery";
};
# Bundle librln.dylib alongside liblogosdelivery.dylib so the transitive
# dep resolves at runtime (and during logos-cpp-generator dlopen).
# Sourced from logos-delivery (not zerokit directly) so we bundle the
# exact, cargoHash-corrected librln that liblogosdelivery links — zerokit
# v2.0.2's own rln package has a stale committed cargoHash.
rln = {
input = inputs.logos-delivery;
packages.default = "rln";
};
};
tests = {
dir = ./tests;
mockCLibs = [ "logosdelivery" ];
# liblogosdelivery.dylib has a Cargo-baked absolute path to librln.dylib.
# Rewrite it to @rpath/librln.dylib so the dynamic linker can find it via
# the lib/ RPATH set on the integration test binary.
# TODO: remove once logos-module-builder mkLogosModuleTests.nix handles
# transitive dylib dependency rewriting in its preConfigure (similar to
# the postInstall rewrite done for the main module build).
preConfigure = ''
if [ -f lib/liblogosdelivery.dylib ]; then
OLD_RLN=$(otool -L lib/liblogosdelivery.dylib | awk '/librln/{print $1}')
if [ -n "$OLD_RLN" ]; then
install_name_tool -change "$OLD_RLN" "@rpath/librln.dylib" lib/liblogosdelivery.dylib
fi
fi
'';
};
# Bundle runtime libraries alongside the plugin.
postInstall = ''
# liblogosdelivery.dylib has a sandbox-baked absolute path for librln.dylib
# (Cargo bakes the build-time path as the install name). Rewrite it to
# @rpath/librln.dylib so the dynamic linker finds it via @loader_path.
if [ -f "$out/lib/liblogosdelivery.dylib" ]; then
OLD_RLN=$(otool -L "$out/lib/liblogosdelivery.dylib" | awk '/librln/{print $1}')
if [ -n "$OLD_RLN" ]; then
echo "Fixing librln rpath in liblogosdelivery.dylib: $OLD_RLN -> @rpath/librln.dylib"
install_name_tool -change "$OLD_RLN" "@rpath/librln.dylib" \
"$out/lib/liblogosdelivery.dylib"
fi
# Add @loader_path/. as an rpath so that Nim's runtime dlopen("libpq.dylib")
# finds the bundled libpq in the same directory as liblogosdelivery.dylib.
if ! otool -l "$out/lib/liblogosdelivery.dylib" | awk '
$1 == "cmd" && $2 == "LC_RPATH" { in_rpath = 1; next }
in_rpath && $1 == "path" { print $2; in_rpath = 0 }
' | grep -Fxq "@loader_path/."; then
install_name_tool -add_rpath "@loader_path/." \
"$out/lib/liblogosdelivery.dylib"
fi
fi
# Use pkg-config to locate the exact libpq from the build environment
LIBPQ_LIBDIR=$(pkg-config --variable=libdir libpq 2>/dev/null || true)
if [ -n "$LIBPQ_LIBDIR" ] && [ -d "$LIBPQ_LIBDIR" ]; then
for f in "$LIBPQ_LIBDIR"/libpq.*; do
[ -f "$f" ] && cp -L "$f" $out/lib/ 2>/dev/null || true
done
fi
# libpq is loaded at runtime via dlopen/dlsym (not a linked dependency),
# so install_name_tool has no effect on macOS — otool -L won't show libpq.
# On Linux, dlopen with a bare name searches the calling library's DT_RUNPATH,
# so setting $ORIGIN makes libpq.so discoverable from the same directory.
if [ -f "$out/lib/liblogosdelivery.so" ]; then
echo "Fixing rpath in liblogosdelivery.so: adding \$ORIGIN for dlopen libpq resolution"
chmod u+w "$out/lib/liblogosdelivery.so"
patchelf --set-rpath '$ORIGIN' "$out/lib/liblogosdelivery.so"
fi
'';
};
}