Skip to content

Instantly share code, notes, and snippets.

@benley
Forked from mrcjkb/NOTES.md
Last active October 31, 2025 18:34
Show Gist options
  • Save benley/b597fa79225b9516b0ccd6012aabece2 to your computer and use it in GitHub Desktop.
Save benley/b597fa79225b9516b0ccd6012aabece2 to your computer and use it in GitHub Desktop.
crowdstrike falcon-sensor on nixos
{
stdenv,
lib,
dpkg,
autoPatchelfHook,
zlib,
openssl,
libnl,
...
}:
let
# Run a command and capture its output as a string (by writing output to the nix store and reading it back)
runCommandString = command:
let
outputDerivation = stdenv.mkDerivation {
name = "run-command-string";
buildCommand = ''
{ ${command} } > "$out"
'';
};
in
builtins.readFile outputDerivation;
in
stdenv.mkDerivation rec {
pname = "falcon-sensor-unwrapped";
version = runCommandString ''
${dpkg}/bin/dpkg-deb -f ${src} version | tr -d "\n"
'';
arch = "x86_64-linux";
src = ./falcon-sensor_7.30.0-18306_amd64.deb;
nativeBuildInputs = [
autoPatchelfHook
dpkg
zlib
];
propagatedBuildInputs = [
openssl
libnl
];
sourceRoot = ".";
unpackCmd =
/*
bash
*/
''
dpkg-deb -x "$src" .
'';
installPhase = ''
cp -r ./ $out/
'';
meta = with lib; {
mainProgram = "falconctl";
description = "Crowdstrike Falcon Sensor";
homepage = "https://www.crowdstrike.com/";
license = licenses.unfree;
platforms = platforms.linux;
};
}
{
falcon-sensor-unwrapped,
buildFHSEnv,
symlinkJoin,
...
}: let
falconFHSWrapper = mainProgram: buildFHSEnv {
name = mainProgram;
targetPkgs = pkgs: with pkgs; [libnl openssl];
runScript = "${falcon-sensor-unwrapped}/opt/CrowdStrike/${mainProgram}";
};
falconctl = falconFHSWrapper "falconctl";
falcond = falconFHSWrapper "falcond";
falcon-kernel-check = falconFHSWrapper "falcon-kernel-check";
in
symlinkJoin {
pname = "falcon-sensor";
version = falcon-sensor-unwrapped.version;
paths = [
falconctl
falcond
falcon-kernel-check
];
}
{
description = "Crowdstrike Falcon Sensor for NixOS";
outputs = {
self,
nixpkgs,
...
}: let
system = "x86_64-linux";
pkgs = import nixpkgs {
inherit system;
overlays = [
self.overlays.default
];
};
module-test = pkgs.callPackage (import ./module-test.nix self.nixosModules.default) {};
kernel-check = pkgs.callPackage ./kernel-check.nix {};
in {
packages.${system} = rec {
default = falcon-sensor;
inherit
(pkgs)
falcon-sensor
falcon-sensor-unwrapped
;
inherit
module-test
kernel-check
;
};
devShells.${system}.default = pkgs.mkShell {
name = "crowdstrike-devShell";
buildInputs = with pkgs; [
git-lfs
];
};
checks.${system}.default = module-test;
overlays.default = import ./overlay.nix;
nixosModules.default = import ./nixos-module.nix {falcon-sensor-overlay = self.overlays.default;};
};
}
# A simple test to quickly check kernel compatibility
{testers}:
testers.nixosTest {
name = "falcon-sensor-kernel-check";
nodes.machine = {pkgs, ...}: {
environment.systemPackages = [
pkgs.falcon-sensor
];
boot.kernelPackages = pkgs.linuxKernel.packages.linux_6_8;
};
testScript =
/*
python
*/
''
machine.start()
machine.wait_for_unit("multi-user.target")
machine.succeed("falcon-kernel-check")
'';
}
falcon-sensor-module: {
testers
}:
testers.nixosTest {
name = "falcon-sensor-module-nixosTest";
nodes.machine = {pkgs, ...}: {
imports = [falcon-sensor-module];
services.falcon-sensor.enable = true;
services.gnome.gnome-keyring.enable = true;
# For driverInteractive
programs.neovim = {
enable = true;
defaultEditor = true;
};
};
testScript =
/*
python
*/
''
import time
machine.start()
machine.wait_for_unit("multi-user.target")
machine.succeed("falcon-kernel-check")
machine.wait_for_unit("falcon-sensor.service")
assert "active (running)" in machine.succeed("systemctl status falcon-sensor.service")
# Assert that it's not in reduced-functionality mode
timeout = time.time() + 60 # 1 minute from now
while "rfm-state=false" not in machine.succeed("falconctl -g --rfm-state"):
assert time.time() < timeout, "falcon-sensor remained in rfm-state."
time.sleep(1)
'';
}
{falcon-sensor-overlay}: {
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.services.falcon-sensor;
in {
options = {
services.falcon-sensor = {
enable = mkEnableOption (mdDoc "Crowdstrike Falcon Sensor");
kernelPackages = mkOption {
default = pkgs.linuxKernel.packages.linux_6_8;
defaultText = literalExpression "pkgs.linuxKernel.packages.linux_6_8";
type = types.nullOr types.raw;
description = "falcon-sensor has a whitelist of supported kernels. This option sets the linux kernel.";
};
cid = mkOption {
type = types.str;
description = "Customer ID (CID) for your Crowdstrike Falcon Sensor.";
};
};
};
config =
mkIf cfg.enable
(mkMerge [
{
nixpkgs.overlays = [
falcon-sensor-overlay
];
environment.systemPackages = [
pkgs.falcon-sensor
];
systemd = {
tmpfiles.settings = {
"10-falcon-sensor" = {
"/opt/CrowdStrike" = {
d = {
group = "root";
user = "root";
mode = "0770";
};
};
};
};
services.falcon-sensor = {
enable = true;
description = "Crowdstrike Falcon Sensor";
unitConfig.DefaultDependencies = false;
after = ["local-fs.target" "systemd-tmpfiles-setup.service"];
conflicts = ["shutdown.target"];
before = ["sysinit.target" "shutdown.target"];
serviceConfig = {
StandardOutput = "journal";
ExecStartPre = [
(pkgs.writeScript "falcon-init"
/*
bash
*/
''
#!${pkgs.bash}/bin/bash
set -euo
ln -sf ${pkgs.falcon-sensor-unwrapped}/opt/CrowdStrike/* /opt/CrowdStrike/
/run/current-system/sw/bin/falconctl -s --trace=debug
# Replace <cid> with your CID
/run/current-system/sw/bin/falconctl -s --cid="${cfg.cid}" -f
/run/current-system/sw/bin/falconctl -g --cid
'')
];
ExecStart = "/run/current-system/sw/bin/falcond";
User = "root";
Type = "forking";
PIDFile = "/var/run/falcond.pid";
Restart = "on-failure";
TimeoutStopSec = "60s";
KillMode = "control-group";
KillSignal = "SIGTERM";
};
wantedBy = ["multi-user.target"];
};
};
}
(mkIf (cfg.kernelPackages != null) {
boot.kernelPackages = mkForce cfg.kernelPackages;
})
]);
}

Notice

(from @mrcjkb)

I am sharing this for educational purposes only.

I DO NOT recommend using crowdstrike falcon-sensor. It is proprietary garbage that has caused overheating issues on two of my NixOS machines. Please do not ask me to help you troubleshoot this or add this to your nixos system.

final: prev: {
falcon-sensor-unwrapped = final.callPackage ./falcon-sensor-unwrapped.nix {};
falcon-sensor = final.callPackage ./falcon-sensor.nix {};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment