Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ revision
*.html
ci/cache
ci/packages
contrib/nix/flake.lock
78 changes: 78 additions & 0 deletions contrib/nix/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@

# Building CFEngine with nix

## Common workflow

You add a change in one of your repo. This workflow assumes you commit your changes first — `nix flake update` needs a stable commit to pin to (an uncommitted/dirty tree is handled differently; see the note at the end).


```
victor-moene@victomoe:~/northern.tech/cfengine/core (cfengine-flake)$ touch a
victor-moene@victomoe:~/northern.tech/cfengine/core (cfengine-flake)$ git add a
victor-moene@victomoe:~/northern.tech/cfengine/core (cfengine-flake)$ git commit -m "a"
[cfengine-flake 150282eb4] a
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 a
victor-moene@victomoe:~/northern.tech/cfengine/core (cfengine-flake)$ git status
On branch cfengine-flake
Your branch is ahead of 'origin/cfengine-flake' by 1 commit.
(use "git push" to publish your local commits)

nothing to commit, working tree clean
```

Then you update buildscripts' flake.lock

```
victor-moene@victomoe:~/northern.tech/cfengine/buildscripts/contrib/nix (cfengine-buildscripts-flake)$ nix flake update
warning: Git tree '/home/victor-moene/northern.tech/cfengine/buildscripts' is dirty
warning: updating lock file "/home/victor-moene/northern.tech/cfengine/buildscripts/contrib/nix/flake.lock":
• Updated input 'core':
'git+file:///home/victor-moene/northern.tech/cfengine/core?dir=contrib/nix&ref=refs/heads/cfengine-flake&rev=87d67cce8b4367d21139282256d23f7f407aca49&submodules=1' (2026-09-07)
→ 'git+file:///home/victor-moene/northern.tech/cfengine/core?dir=contrib/nix&ref=refs/heads/cfengine-flake&rev=150282eb48c808a745abcdfee69cc0d409313a14&submodules=1' (2026-09-07)
• Updated input 'enterprise/core':
'git+file:///home/victor-moene/northern.tech/cfengine/core?dir=contrib/nix&ref=refs/heads/cfengine-flake&rev=87d67cce8b4367d21139282256d23f7f407aca49&submodules=1' (2026-09-07)
→ 'git+file:///home/victor-moene/northern.tech/cfengine/core?dir=contrib/nix&ref=refs/heads/cfengine-flake&rev=150282eb48c808a745abcdfee69cc0d409313a14&submodules=1' (2026-09-07)
• Updated input 'mission-portal/nova/core':
'git+file:///home/victor-moene/northern.tech/cfengine/core?dir=contrib/nix&ref=refs/heads/cfengine-flake&rev=87d67cce8b4367d21139282256d23f7f407aca49&submodules=1' (2026-09-07)
→ 'git+file:///home/victor-moene/northern.tech/cfengine/core?dir=contrib/nix&ref=refs/heads/cfengine-flake&rev=150282eb48c808a745abcdfee69cc0d409313a14&submodules=1' (2026-09-07)
• Updated input 'mission-portal/nova/enterprise/core':
'git+file:///home/victor-moene/northern.tech/cfengine/core?dir=contrib/nix&ref=refs/heads/cfengine-flake&rev=87d67cce8b4367d21139282256d23f7f407aca49&submodules=1' (2026-09-07)
→ 'git+file:///home/victor-moene/northern.tech/cfengine/core?dir=contrib/nix&ref=refs/heads/cfengine-flake&rev=150282eb48c808a745abcdfee69cc0d409313a14&submodules=1' (2026-09-07)
• Updated input 'nova/core':
'git+file:///home/victor-moene/northern.tech/cfengine/core?dir=contrib/nix&ref=refs/heads/cfengine-flake&rev=87d67cce8b4367d21139282256d23f7f407aca49&submodules=1' (2026-09-07)
→ 'git+file:///home/victor-moene/northern.tech/cfengine/core?dir=contrib/nix&ref=refs/heads/cfengine-flake&rev=150282eb48c808a745abcdfee69cc0d409313a14&submodules=1' (2026-09-07)
• Updated input 'nova/enterprise/core':
'git+file:///home/victor-moene/northern.tech/cfengine/core?dir=contrib/nix&ref=refs/heads/cfengine-flake&rev=87d67cce8b4367d21139282256d23f7f407aca49&submodules=1' (2026-09-07)
→ 'git+file:///home/victor-moene/northern.tech/cfengine/core?dir=contrib/nix&ref=refs/heads/cfengine-flake&rev=150282eb48c808a745abcdfee69cc0d409313a14&submodules=1' (2026-09-07)
```

In short, the flake.lock is a file pinning all the inputs of the final derivation.

Now you can build with the newest commit:

```
victor-moene@victomoe:~/northern.tech/cfengine/buildscripts/contrib/nix (cfengine-buildscripts-flake)$ nix build .#community-client -o myoutput
```

You can choose to build `community-client`, `enterprise-client` or `enterprise-hub`. These are listed in `buildscripts/contrib/nix/flake.nix`

Where myoutput is a symlink with the compiled binaries. For exemple, from a previous build, I got:

```
victor-moene@victomoe:~/northern.tech/cfengine/buildscripts/contrib/nix (cfengine-buildscripts-flake)$ ls myoutput
bin cgi-bin conf error etc htdocs icons lib logs masterfiles master_software_updates modules php sbin share var
```

CFEngine expects some level of permissions on its source files, so you might have to copy the output somewhere else.

## Sharing builds

To share fully reproducible builds, simply share the `flake.lock` file, and run nix build. This assumes you have the same commits in the repos.

## Garbage collection

Nix stores every derivation as a unique package in the Nix store, so disk usage can grow quickly. Run `nix-collect-garbage` (or `nix-collect-garbage -d` to also remove old generations) from time to time to reclaim space.

Note: any `-o` result symlink (e.g. `myoutput`) acts as a garbage-collection root — as long as it exists, Nix won't clean up the store paths it points to. Remove old output symlinks you no longer need before running garbage collection, or point `-o` at `/tmp` so they get cleaned up automatically.

6 changes: 6 additions & 0 deletions contrib/nix/community-client.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{ symlinkJoin, core, masterfiles }:

symlinkJoin {
name = "cfengine-community-client";
paths = [ core masterfiles ];
}
9 changes: 9 additions & 0 deletions contrib/nix/enterprise-client.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{ symlinkJoin, core, enterprise }:

# Deliberately no masterfiles here: an enterprise agent gets its policy
# from the hub it's bootstrapped to, unlike the standalone community
# agent, which ships default policy to bootstrap itself.
symlinkJoin {
name = "cfengine-enterprise-client";
paths = [ core enterprise ];
}
10 changes: 10 additions & 0 deletions contrib/nix/enterprise-hub.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{ symlinkJoin, core, enterprise, nova, masterfiles, missionPortal, apacheHttpd, php }:

# apacheHttpd/php are included so they're on PATH/in the closure for
# whoever deploys this (a NixOS module, a container, ...) to actually run
# the hub's web UI against -- this derivation doesn't configure or start
# Apache itself, same as it doesn't start cf-serverd/cf-hub.
symlinkJoin {
name = "cfengine-enterprise-hub";
paths = [ core enterprise nova masterfiles missionPortal apacheHttpd php ];
}
48 changes: 48 additions & 0 deletions contrib/nix/flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
description = "CFEngine meta-flake: community-client, enterprise-client, enterprise-hub";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
# Absolute paths required -- see the comment in
# enterprise/contrib/nix/flake.nix for why relative "../.." doesn't
# work here.
core.url = "git+file:///home/victor-moene/northern.tech/cfengine/core?dir=contrib/nix";
enterprise.url = "git+file:///home/victor-moene/northern.tech/cfengine/enterprise?dir=contrib/nix";
nova.url = "git+file:///home/victor-moene/northern.tech/cfengine/nova?dir=contrib/nix";
masterfiles.url = "git+file:///home/victor-moene/northern.tech/cfengine/masterfiles?dir=contrib/nix";
mission-portal.url = "git+file:///home/victor-moene/northern.tech/cfengine/mission-portal?dir=contrib/nix";
};

outputs = { self, nixpkgs, flake-utils, core, enterprise, nova, masterfiles, mission-portal }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};

coreOut = core.packages.${system}.default;
enterpriseOut = enterprise.packages.${system}.default;
novaOut = nova.packages.${system}.default;
masterfilesOut = masterfiles.packages.${system}.default;
missionPortalOut = mission-portal.packages.${system}.default;
in
{
packages = {
community-client = pkgs.callPackage ./community-client.nix {
core = coreOut;
masterfiles = masterfilesOut;
};
enterprise-client = pkgs.callPackage ./enterprise-client.nix {
core = coreOut;
enterprise = enterpriseOut;
};
enterprise-hub = pkgs.callPackage ./enterprise-hub.nix {
core = coreOut;
enterprise = enterpriseOut;
nova = novaOut;
masterfiles = masterfilesOut;
missionPortal = missionPortalOut;
};
};
}
);
}
Loading