flake.nix
Rama main · réplica de lectura del repositorio original.
{
description = "tummycrypt/tcfs - FOSS self-hosted odrive replacement";
# Public Attic read endpoint used by local dev and CI.
# CI/release workflows push with `attic login` separately.
nixConfig = {
extra-substituters = [
"https://nix-cache.tinyland.dev/main"
];
extra-trusted-public-keys = [
"main:eaUydxuDu7xBoy5cCo3MdknYAkVyTIASQ7DGuwxa+XA="
];
};
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
crane.url = "github:ipetkov/crane";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, rust-overlay, crane, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs { inherit system overlays; };
rustVersion = "1.93.0";
rustTargets = [
"x86_64-unknown-linux-gnu"
"aarch64-unknown-linux-gnu"
"x86_64-apple-darwin"
"aarch64-apple-darwin"
"aarch64-apple-ios"
"aarch64-apple-ios-sim"
];
rustToolchain = pkgs.rust-bin.stable.${rustVersion}.default.override {
extensions = [ "rust-src" "rust-analyzer" "clippy" "rustfmt" ];
targets = rustTargets;
};
craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain;
# Common build inputs for all crates
commonBuildInputs = with pkgs; [
protobuf
pkg-config
openssl
] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [
fuse3
rocksdb
] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [
apple-sdk
];
# Source filter: include .proto files alongside standard Cargo sources
src = let
protoFilter = path: _type: builtins.match ".*\\.proto$" path != null;
filter = path: type:
(protoFilter path type) || (craneLib.filterCargoSources path type);
in pkgs.lib.cleanSourceWith {
src = craneLib.path ./.;
inherit filter;
};
# Common args shared by all crate builds
commonArgs = {
inherit src;
buildInputs = commonBuildInputs;
nativeBuildInputs = with pkgs; [ pkg-config protobuf perl ];
} // pkgs.lib.optionalAttrs pkgs.stdenv.isLinux {
ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include";
ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib";
};
# Pre-build workspace deps (shared across all crate builds for caching)
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
# The Linux Nix build sandbox cannot faithfully run tests that
# exercise tcfs's fail-closed trusted-path/ACL validators, for two
# environment reasons verified at syscall level (TIN-2853):
# 1. Nix's sandbox seccomp filter fails the entire xattr syscall
# family with ENOTSUP (upstream linux-derivation-builder.cc:
# "Prevent builders from using EAs or ACLs"), so the POSIX ACL
# probe in tcfs-sync's path_acl can never reach the filesystem
# and correctly fails closed.
# 2. The sandbox user namespace maps a single uid, so every
# ancestor above /build (/, /nix/store, /tmp) appears as
# overflowuid 65534 and is rejected by the euid-or-root
# ancestor-ownership validator.
# Rather than disabling whole checkPhases, skip exactly the affected
# tests; the checked-in lists under nix/checks/ document each one.
# Darwin runs the full suites (empty flags).
linuxSandboxSkipFlags = skipFile:
pkgs.lib.optionalString pkgs.stdenv.isLinux (
let
names = builtins.filter
(line: line != "" && !pkgs.lib.hasPrefix "#" line)
(pkgs.lib.splitString "\n" (builtins.readFile skipFile));
in
"-- " + pkgs.lib.concatMapStringsSep " " (name: "--skip ${name}") names
);
# Build individual crates as separate derivations
tcfsd = craneLib.buildPackage (commonArgs // {
inherit cargoArtifacts;
pname = "tcfsd";
# Registered-root safety tests create real fixture repositories.
# gitMinimal (not pkgs.git) keeps the docbook/full-git doc chain out
# of the check closure, matching tcfs-cli below.
nativeCheckInputs = [ pkgs.gitMinimal ];
# Skip only the trusted-path/ACL validator tests that the Linux
# sandbox cannot faithfully run (see linuxSandboxSkipFlags above and
# the list's header for the full analysis, TIN-2853).
cargoTestExtraArgs = linuxSandboxSkipFlags ./nix/checks/linux-sandbox-skip-tcfsd.txt;
# Vendor OpenSSL on macOS to avoid dyld Team ID mismatch
# when launchd loads the binary (Nix store openssl has different
# code signature than the daemon binary).
cargoExtraArgs = "-p tcfsd"
+ pkgs.lib.optionalString pkgs.stdenv.isDarwin " --features openssl-vendored";
meta.mainProgram = "tcfsd";
});
tcfs-cli = craneLib.buildPackage (commonArgs // {
inherit cargoArtifacts;
pname = "tcfs-cli";
cargoExtraArgs = "-p tcfs-cli";
# keep-both CLI tests (TIN-2658) run real `git` repos in checkPhase;
# the build sandbox has no ambient git.
nativeBuildInputs = commonArgs.nativeBuildInputs ++ [ pkgs.gitMinimal ];
# Skip only the trusted-path/ACL validator tests that the Linux
# sandbox cannot faithfully run (see linuxSandboxSkipFlags above and
# the list's header for the full analysis, TIN-2853).
cargoTestExtraArgs = linuxSandboxSkipFlags ./nix/checks/linux-sandbox-skip-tcfs-cli.txt;
meta.mainProgram = "tcfs";
});
tcfs-tui = craneLib.buildPackage (commonArgs // {
inherit cargoArtifacts;
pname = "tcfs-tui";
cargoExtraArgs = "-p tcfs-tui";
meta.mainProgram = "tcfs-tui";
});
tcfs-mcp = craneLib.buildPackage (commonArgs // {
inherit cargoArtifacts;
pname = "tcfs-mcp";
cargoExtraArgs = "-p tcfs-mcp";
meta.mainProgram = "tcfs-mcp";
});
# FileProvider FFI static library (pure Rust build).
# Header: $out/include/tcfs_file_provider.h
# Library: $out/lib/libtcfs_file_provider.a
# Used by: swift/fileprovider/build.sh (impure, needs system swiftc)
tcfs-file-provider-staticlib = craneLib.buildPackage (commonArgs // {
inherit cargoArtifacts;
pname = "tcfs-file-provider-staticlib";
cargoExtraArgs = "-p tcfs-file-provider --no-default-features --features grpc";
postInstall = ''
mkdir -p $out/lib $out/include
find target -name "libtcfs_file_provider.a" -exec cp {} $out/lib/ \;
find target -name "tcfs_file_provider.h" -exec cp {} $out/include/ \;
'';
});
# macOS .app bundle for TCC persistence.
# TCC grants (Full Disk Access, etc.) are tied to bundle ID + CDHash.
# Bare binaries in /nix/store/ lose grants on every rebuild.
# This bundle provides a stable identity (io.tinyland.tcfsd).
tcfsd-app = pkgs.lib.optionalAttrs pkgs.stdenv.isDarwin (
pkgs.stdenv.mkDerivation {
pname = "tcfsd-app";
version = tcfsd.version or "0.12.6";
dontUnpack = true;
buildInputs = [ pkgs.darwin.sigtool ];
installPhase = ''
mkdir -p $out/Applications/TCFSDaemon.app/Contents/MacOS
cp ${tcfsd}/bin/tcfsd $out/Applications/TCFSDaemon.app/Contents/MacOS/tcfsd
cp ${./swift/daemon/resources/Info.plist} $out/Applications/TCFSDaemon.app/Contents/Info.plist
# Ad-hoc sign for local use; Developer ID signing done out-of-band
codesign -f -s - --options runtime $out/Applications/TCFSDaemon.app || true
'';
}
);
in {
packages = {
default = tcfsd;
inherit tcfsd tcfs-cli tcfs-tui tcfs-mcp tcfs-file-provider-staticlib;
} // pkgs.lib.optionalAttrs pkgs.stdenv.isDarwin {
inherit tcfsd-app;
};
# Eval-only regression check for the programs.tcfs config renderer
# (natsTokenFile must not drop syncRoot; OI-1003-Q177).
checks.tcfs-user-config-render =
assert import ./nix/tests/tcfs-user-config-render.nix { inherit (pkgs) lib; };
pkgs.runCommand "tcfs-user-config-render" { } "touch $out";
devShells.default = pkgs.mkShell {
buildInputs = commonBuildInputs ++ (with pkgs; [
rustToolchain
# Proto codegen
protobuf
# Security tooling
age
sops
# Infrastructure
opentofu
kubectl
kubernetes-helm
kustomize
# Build tooling
go-task
cargo-watch
cargo-deny
cargo-audit
shellcheck
jq
# NATS
natscli
# Lazy hydration demo helpers
awscli2
s5cmd
minio-client
openssh
# Docs tooling
lychee
pandoc
tectonic
mermaid-cli
# Dev tools
git
just
yq-go
]);
TCFS_RUST_TOOLCHAIN = rustVersion;
shellHook = ''
# Home Manager user profiles may carry an older rustc/cargo ahead
# of Nix's shell paths. Keep the project-pinned toolchain first.
export PATH="$PWD/target/debug:$PWD/target/release:${pkgs.lib.makeBinPath [ rustToolchain pkgs.go-task pkgs.just pkgs.shellcheck pkgs.jq.bin pkgs.awscli2 pkgs.s5cmd pkgs.minio-client ]}:$PATH"
echo "tcfs devShell (tummycrypt monorepo)"
echo " rustc --version # pinned toolchain should report ${rustVersion}"
echo " just --list # show available recipes"
echo " task --list # show go-task tasks"
echo " cargo build # build workspace"
echo " task dev # start local stack + watch"
'';
} // pkgs.lib.optionalAttrs pkgs.stdenv.isLinux {
ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include";
ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib";
};
}
) // {
# NixOS modules (system-level)
nixosModules.tcfsd = import ./nix/modules/tcfs-daemon.nix;
# Home Manager modules (user-level)
homeManagerModules.tcfs = import ./nix/modules/tcfs-user.nix;
};
}