Initial commit

This commit is contained in:
kirbara 2025-12-01 13:23:24 +07:00
commit cfcc57a8bd
Signed by: exp
GPG key ID: D7E63AD0019E75D9
353 changed files with 18756 additions and 0 deletions

View file

@ -0,0 +1,21 @@
on:
pull_request:
push:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
flake-check:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
name: Nix flake check
runs-on: ${{matrix.os}}
steps:
- uses: wimpysworld/nothing-but-nix@main
if: matrix.os == 'ubuntu-latest'
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main
- uses: actions/checkout@v5
- run: nix flake metadata
- run: nix flake check

View file

@ -0,0 +1,17 @@
# Bug Reproduction den
Use this small template to reproduce bugs in den.
Create a **minimal** bug reproduction at [`modules/bug.nix`](modules/bug.nix)
Then run tests:
```console
nix flake check
```
Format code with:
```console
nix fmt
```

222
flake/den/templates/bogus/flake.lock generated Normal file
View file

@ -0,0 +1,222 @@
{
"nodes": {
"den": {
"locked": {
"lastModified": 1763285091,
"narHash": "sha256-F2OsALSm86dfNA2grd5MVRPpAWZf4ZuuCzpYG7H0P9g=",
"owner": "vic",
"repo": "den",
"rev": "227451c9a99fb084bc6b66878c7f6f3e75f625d2",
"type": "github"
},
"original": {
"owner": "vic",
"ref": "main",
"repo": "den",
"type": "github"
}
},
"flake-aspects": {
"locked": {
"lastModified": 1763284357,
"narHash": "sha256-mPMHkhpOIsj2lg+KIcapFd4uj2N/9mZZ6RZBo/p5O1c=",
"owner": "vic",
"repo": "flake-aspects",
"rev": "6a6d47f531ad57ac854cee689e84f2e28861ec49",
"type": "github"
},
"original": {
"owner": "vic",
"repo": "flake-aspects",
"type": "github"
}
},
"flake-file": {
"locked": {
"lastModified": 1762466468,
"narHash": "sha256-OTAbN2Vmdn6Km2AYN+G6QrCdQUtbqaJKAJATP0tGkB8=",
"owner": "vic",
"repo": "flake-file",
"rev": "6a7da81583a42ba339a06aed2d0f3ee4a164f265",
"type": "github"
},
"original": {
"owner": "vic",
"repo": "flake-file",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"nixpkgs-lib"
]
},
"locked": {
"lastModified": 1762440070,
"narHash": "sha256-xxdepIcb39UJ94+YydGP221rjnpkDZUlykKuF54PsqI=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "26d05891e14c88eb4a5d5bee659c0db5afb609d8",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1762463325,
"narHash": "sha256-33YUsWpPyeBZEWrKQ2a1gkRZ7i0XCC/2MYpU6BVeQSU=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "0562fef070a1027325dd4ea10813d64d2c967b39",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"import-tree": {
"locked": {
"lastModified": 1762327901,
"narHash": "sha256-AJ96FNj50DU0bTyIzAPkPOjCZTHqjURVjok8qoXvmqM=",
"owner": "vic",
"repo": "import-tree",
"rev": "90fa129798be99cde036b78658e89475710966a1",
"type": "github"
},
"original": {
"owner": "vic",
"repo": "import-tree",
"type": "github"
}
},
"nix-auto-follow": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1754073254,
"narHash": "sha256-CQp/v2HQ7AtGJQqFGRZLHt4MZAK3NF94I6GDaRyhbsc=",
"owner": "fzakaria",
"repo": "nix-auto-follow",
"rev": "5baa00b79d4cc46523da0b8b3532c5163d151be4",
"type": "github"
},
"original": {
"owner": "fzakaria",
"repo": "nix-auto-follow",
"type": "github"
}
},
"nix-unit": {
"inputs": {
"flake-parts": [
"flake-parts"
],
"nixpkgs": [
"nixpkgs"
],
"treefmt-nix": [
"treefmt-nix"
]
},
"locked": {
"lastModified": 1762507096,
"narHash": "sha256-dE3CbZR8KRDdb3b4fhMnpvhEl6XB+UnrLezuFekQ2ME=",
"owner": "nix-community",
"repo": "nix-unit",
"rev": "0d7230bc54783b812a5817398885aec660a93051",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-unit",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1762361079,
"narHash": "sha256-lz718rr1BDpZBYk7+G8cE6wee3PiBUpn8aomG/vLLiY=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "ffcdcf99d65c61956d882df249a9be53e5902ea5",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"den": "den",
"flake-aspects": "flake-aspects",
"flake-file": "flake-file",
"flake-parts": "flake-parts",
"home-manager": "home-manager",
"import-tree": "import-tree",
"nix-auto-follow": "nix-auto-follow",
"nix-unit": "nix-unit",
"nixpkgs": "nixpkgs",
"nixpkgs-lib": [
"nixpkgs"
],
"systems": "systems",
"treefmt-nix": "treefmt-nix"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1762410071,
"narHash": "sha256-aF5fvoZeoXNPxT0bejFUBXeUjXfHLSL7g+mjR/p5TEg=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "97a30861b13c3731a84e09405414398fbf3e109f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -0,0 +1,77 @@
# DO-NOT-EDIT. This file was auto-generated using github:vic/flake-file.
# Use `nix run .#write-flake` to regenerate it.
{
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } (inputs.import-tree ./modules);
inputs = {
den = {
url = "github:vic/den/main";
};
flake-aspects = {
url = "github:vic/flake-aspects";
};
flake-file = {
url = "github:vic/flake-file";
};
flake-parts = {
inputs = {
nixpkgs-lib = {
follows = "nixpkgs-lib";
};
};
url = "github:hercules-ci/flake-parts";
};
home-manager = {
inputs = {
nixpkgs = {
follows = "nixpkgs";
};
};
url = "github:nix-community/home-manager";
};
import-tree = {
url = "github:vic/import-tree";
};
nix-auto-follow = {
inputs = {
nixpkgs = {
follows = "nixpkgs";
};
};
url = "github:fzakaria/nix-auto-follow";
};
nix-unit = {
inputs = {
flake-parts = {
follows = "flake-parts";
};
nixpkgs = {
follows = "nixpkgs";
};
treefmt-nix = {
follows = "treefmt-nix";
};
};
url = "github:nix-community/nix-unit";
};
nixpkgs = {
url = "github:nixos/nixpkgs/nixpkgs-unstable";
};
nixpkgs-lib = {
follows = "nixpkgs";
};
systems = {
url = "github:nix-systems/default";
};
treefmt-nix = {
inputs = {
nixpkgs = {
follows = "nixpkgs";
};
};
url = "github:numtide/treefmt-nix";
};
};
}

View file

@ -0,0 +1,27 @@
{ inputs, lib, ... }:
{
den.hosts.x86_64-linux.igloo.users.tux = { };
den.hosts.aarch64-darwin.apple.users.tim = { };
# Use aspects to create a **minimal** bug reproduction
den.aspects.igloo.nixos =
{ pkgs, ... }:
{
users.users.tux.packages = [ pkgs.hello ];
};
# rename "it works", evidently it has bugs
flake.tests."test it works" =
let
tux = inputs.self.nixosConfigurations.igloo.config.users.users.tux;
expr.len = lib.length tux.packages;
expr.names = map lib.getName tux.packages;
expected.len = 1;
expected.names = [ "hello" ];
in
{
inherit expr expected;
};
}

View file

@ -0,0 +1,7 @@
{ inputs, lib, ... }:
{
flake-file.inputs.flake-file.url = lib.mkDefault "github:vic/flake-file";
imports = [
inputs.flake-file.flakeModules.dendritic
];
}

View file

@ -0,0 +1,33 @@
# DO-NOT-CHANGE. Keep your reproduction minimalistic!
#
# try not adding new inputs
# but if you have no options (pun intended)
# here's the place.
#
# IF you make any change to this file, use:
# `nix run .#write-flake`
#
# We provide nix-unit and home-manager for common
# usage.
{ inputs, ... }:
{
# change "main" with a commit where bug is present
flake-file.inputs.den.url = "github:vic/den/main";
flake-file.inputs.nix-unit = {
url = "github:nix-community/nix-unit";
inputs.nixpkgs.follows = "nixpkgs";
inputs.flake-parts.follows = "flake-parts";
inputs.treefmt-nix.follows = "treefmt-nix";
};
flake-file.inputs.home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
imports = [
inputs.nix-unit.modules.flake.default
];
}

View file

@ -0,0 +1,12 @@
{
perSystem = {
treefmt = {
projectRootFile = "flake.nix";
programs.nixfmt.enable = true;
programs.nixfmt.excludes = [ ".direnv" ];
programs.deadnix.enable = true;
programs.mdformat.enable = true;
programs.yamlfmt.enable = true;
};
};
}

View file

@ -0,0 +1,8 @@
# DO-NOT-EDIT: nix-unit configuration.
{ lib, inputs, ... }:
{
perSystem.nix-unit = {
allowNetwork = lib.mkDefault true;
inputs = lib.mkDefault inputs;
};
}

View file

@ -0,0 +1,17 @@
{ den, ... }:
{
den.default.nixos.system.stateVersion = "25.11";
den.default.homeManager.home.stateVersion = "25.11";
den.default.darwin.system.stateVersion = 6;
den.default.includes = [
den._.home-manager
den._.define-user
den.aspects.no-boot
];
den.aspects.no-boot.nixos = {
boot.loader.grub.enable = false;
fileSystems."/".device = "/dev/fake";
};
}

View file

@ -0,0 +1,27 @@
on:
pull_request:
push:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
flake-check:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
name: Nix flake check ${{matrix.os}}
runs-on: ${{matrix.os}}
steps:
- uses: wimpysworld/nothing-but-nix@main
if: matrix.os == 'ubuntu-latest'
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main
- uses: actions/checkout@v5
- run: nix flake metadata
- run: |
cat <<-EOF > modules/ci-runtime.nix
{
_module.args.CI = true;
}
EOF
- run: nix flake check

View file

@ -0,0 +1,35 @@
# Getting Started Guide
Steps you can follow after cloning this template:
- Be sure to read the [den documentation](https://vic.github.io/den)
- Update den input.
```console
nix flake update den
```
- Run checks to test everything works.
```console
nix flake check
```
- Read [modules/den.nix](modules/den.nix) where hosts and homes definitions are for this example.
- Read [modules/namespace.nix](modules/namespace.nix) where a new `eg` (an example) aspects namespace is created.
- Read [modules/aspects/igloo.nix](modules/aspects/igloo.nix) where the `igloo` host is configured.
- Read [modules/aspects/alice.nix](modules/aspects/alice.nix) where the `alice` user is configured.
- Run the VM.
```console
nix run .#vm
```
- Edit and run VM loop.
Feel free to add more aspects, organize things to your liking.

173
flake/den/templates/default/flake.lock generated Normal file
View file

@ -0,0 +1,173 @@
{
"nodes": {
"darwin": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1762627886,
"narHash": "sha256-/QLk1bzmbcqJt9sU43+y/3tHtXhAy0l8Ck0MoO2+evQ=",
"owner": "nix-darwin",
"repo": "nix-darwin",
"rev": "5125a3cd414dc98bbe2c528227aa6b62ee61f733",
"type": "github"
},
"original": {
"owner": "nix-darwin",
"repo": "nix-darwin",
"type": "github"
}
},
"den": {
"locked": {
"lastModified": 1763285091,
"narHash": "sha256-F2OsALSm86dfNA2grd5MVRPpAWZf4ZuuCzpYG7H0P9g=",
"owner": "vic",
"repo": "den",
"rev": "227451c9a99fb084bc6b66878c7f6f3e75f625d2",
"type": "github"
},
"original": {
"owner": "vic",
"repo": "den",
"type": "github"
}
},
"flake-aspects": {
"locked": {
"lastModified": 1763284357,
"narHash": "sha256-mPMHkhpOIsj2lg+KIcapFd4uj2N/9mZZ6RZBo/p5O1c=",
"owner": "vic",
"repo": "flake-aspects",
"rev": "6a6d47f531ad57ac854cee689e84f2e28861ec49",
"type": "github"
},
"original": {
"owner": "vic",
"repo": "flake-aspects",
"type": "github"
}
},
"flake-file": {
"locked": {
"lastModified": 1762732765,
"narHash": "sha256-sVxN4q4V8jhIAF44aPSMULIJMJ5eG5HtzcQgbr2UEBg=",
"owner": "vic",
"repo": "flake-file",
"rev": "7b037ae446102d3ccc5e23d3c52d5ada8e0fc4f3",
"type": "github"
},
"original": {
"owner": "vic",
"repo": "flake-file",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"nixpkgs-lib"
]
},
"locked": {
"lastModified": 1762810396,
"narHash": "sha256-dxFVgQPG+R72dkhXTtqUm7KpxElw3u6E+YlQ2WaDgt8=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "0bdadb1b265fb4143a75bd1ec7d8c915898a9923",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1762787259,
"narHash": "sha256-t2U/GLLXHa2+kJkwnFNRVc2fEJ/lUfyZXBE5iKzJdcs=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "37a3d97f2873e0f68711117c34d04b7c7ead8f4e",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"import-tree": {
"locked": {
"lastModified": 1762327901,
"narHash": "sha256-AJ96FNj50DU0bTyIzAPkPOjCZTHqjURVjok8qoXvmqM=",
"owner": "vic",
"repo": "import-tree",
"rev": "90fa129798be99cde036b78658e89475710966a1",
"type": "github"
},
"original": {
"owner": "vic",
"repo": "import-tree",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1762482733,
"narHash": "sha256-g/da4FzvckvbiZT075Sb1/YDNDr+tGQgh4N8i5ceYMg=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "e1ebeec86b771e9d387dd02d82ffdc77ac753abc",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"darwin": "darwin",
"den": "den",
"flake-aspects": "flake-aspects",
"flake-file": "flake-file",
"flake-parts": "flake-parts",
"home-manager": "home-manager",
"import-tree": "import-tree",
"nixpkgs": "nixpkgs",
"nixpkgs-lib": [
"nixpkgs"
],
"systems": "systems"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -0,0 +1,55 @@
# DO-NOT-EDIT. This file was auto-generated using github:vic/flake-file.
# Use `nix run .#write-flake` to regenerate it.
{
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } (inputs.import-tree ./modules);
inputs = {
darwin = {
inputs = {
nixpkgs = {
follows = "nixpkgs";
};
};
url = "github:nix-darwin/nix-darwin";
};
den = {
url = "github:vic/den";
};
flake-aspects = {
url = "github:vic/flake-aspects";
};
flake-file = {
url = "github:vic/flake-file";
};
flake-parts = {
inputs = {
nixpkgs-lib = {
follows = "nixpkgs-lib";
};
};
url = "github:hercules-ci/flake-parts";
};
home-manager = {
inputs = {
nixpkgs = {
follows = "nixpkgs";
};
};
url = "github:nix-community/home-manager";
};
import-tree = {
url = "github:vic/import-tree";
};
nixpkgs = {
url = "github:nixos/nixpkgs/nixpkgs-unstable";
};
nixpkgs-lib = {
follows = "nixpkgs";
};
systems = {
url = "github:nix-systems/default";
};
};
}

View file

@ -0,0 +1,70 @@
{ den, eg, ... }:
{
den.aspects.alice = {
# Alice can include other aspects.
# For small, private one-shot aspects, use let-bindings like here.
# for more complex or re-usable ones, define on their own modules,
# as part of any aspect-subtree.
includes =
let
# deadnix: skip # not required, showcasing angle-brackets syntax.
inherit (den.lib) __findFile;
customEmacs.homeManager =
{ pkgs, ... }:
{
programs.emacs.enable = true;
programs.emacs.package = pkgs.emacs30-nox;
};
in
[
# from local bindings.
customEmacs
# from the aspect tree, cooper example is defined bellow
den.aspects.cooper
den.aspects.setHost
# from the `eg` namespace.
eg.autologin
# den included batteries that provide common configs.
<den/primary-user> # alice is admin always.
(<den/user-shell> "fish") # default user shell
];
# Alice configures NixOS hosts it lives on.
nixos =
{ pkgs, ... }:
{
users.users.alice.packages = [ pkgs.vim ];
};
# Alice home-manager.
homeManager =
{ pkgs, ... }:
{
home.packages = [ pkgs.htop ];
};
# <user>.provides.<host>, via eg/routes.nix
provides.igloo =
{ host, ... }:
{
nixos.programs.nh.enable = host.name == "igloo";
};
};
# This is a context-aware aspect, that emits configurations
# **anytime** at least the `user` data is in context.
# read more at https://vic.github.io/den/context-aware.html
den.aspects.cooper =
{ user, ... }:
{
nixos.users.users.${user.userName}.description = "Alice Cooper";
};
den.aspects.setHost =
{ host, ... }:
{
networking.hostName = host.hostName;
};
}

View file

@ -0,0 +1,48 @@
{
config,
# deadnix: skip # enable <den/brackets> syntax for demo.
__findFile ? __findFile,
den,
...
}:
{
# Lets also configure some defaults using aspects.
# These are global static settings.
den.default = {
darwin.system.stateVersion = 6;
nixos.system.stateVersion = "25.05";
homeManager.home.stateVersion = "25.05";
};
# These are functions that produce configs
den.default.includes = [
# ${user}.provides.${host} and ${host}.provides.${user}
<eg/routes>
# Enable home-manager on all hosts.
<den/home-manager>
# Automatically create the user on host.
<den/define-user>
# Disable booting when running on CI on all NixOS hosts.
(if config ? _module.args.CI then <eg/ci-no-boot> else { })
# NOTE: be cautious when adding fully parametric functions to defaults.
# defaults are included on EVERY host/user/home, and IF you are not careful
# you could be duplicating config values. For example:
#
# # This will append 42 into foo option for the {host} and for EVERY {host,user}
# ({ host, ... }: { nixos.foo = [ 42 ]; }) # DO-NOT-DO-THIS.
#
# # Instead try to be explicit if a function is intended for ONLY { host }.
(den.lib.take.exactly (
# deadnix: skip
{ OS, host }:
{
nixos.networking.hostName = host.hostName;
}
))
];
}

View file

@ -0,0 +1,15 @@
{
# autologin is context-aware, parametric aspect.
# it applies only if the context has at least { user }
# meaning that has access to user data
eg.autologin =
{ user, ... }:
{
nixos =
{ config, lib, ... }:
lib.mkIf config.services.displayManager.enable {
services.displayManager.autoLogin.enable = true;
services.displayManager.autoLogin.user = user.userName;
};
};
}

View file

@ -0,0 +1,9 @@
{
eg.ci-no-boot = {
description = "Disables booting during CI";
nixos = {
boot.loader.grub.enable = false;
fileSystems."/".device = "/dev/null";
};
};
}

View file

@ -0,0 +1,37 @@
# This example implements an aspect "routing" pattern.
#
# Unlike `den.default` which is `parametric.atLeast`
# we use `parametric.fixedTo` here, which help us
# propagate an already computed context to all includes.
#
# This aspect, when installed in a `parametric.atLeast`
# will just forward the same context.
# The `mutual` helper returns an static configuration which
# is ignored by parametric aspects, thus allowing
# non-existing aspects to be just ignored.
#
# Be sure to read: https://vic.github.io/den/dependencies.html
# See usage at: defaults.nix, alice.nix, igloo.nix
#
{ den, eg, ... }:
{
# Usage: `den.default.includes [ eg.routes ]`
eg.routes =
let
inherit (den.lib) parametric;
# eg, `<user>._.<host>` and `<host>._.<user>`
mutual = from: to: den.aspects.${from.aspect}._.${to.aspect} or { };
routes =
{ host, user, ... }@ctx:
{
__functor = parametric.fixedTo ctx;
includes = [
(mutual user host)
(mutual host user)
];
};
in
routes;
}

View file

@ -0,0 +1,16 @@
let
installer = variant: {
nixos =
{ modulesPath, ... }:
{
imports = [ (modulesPath + "/installer/cd-dvd/installation-cd-${variant}.nix") ];
};
};
in
{
# make USB/VM installers.
eg.vm-bootable.provides = {
tui = installer "minimal";
gui = installer "graphical-base";
};
}

View file

@ -0,0 +1,15 @@
{ eg, ... }:
{
eg.vm.provides = {
gui.includes = [
eg.vm
eg.vm-bootable._.gui
eg.xfce-desktop
];
tui.includes = [
eg.vm
eg.vm-bootable._.tui
];
};
}

View file

@ -0,0 +1,19 @@
{
eg.xfce-desktop.nixos =
{ lib, ... }:
{
# https://gist.github.com/nat-418/1101881371c9a7b419ba5f944a7118b0
services.xserver = {
enable = true;
desktopManager = {
xterm.enable = false;
xfce.enable = true;
};
};
services.displayManager = {
defaultSession = lib.mkDefault "xfce";
enable = true;
};
};
}

View file

@ -0,0 +1,20 @@
{
den.aspects.igloo = {
# igloo host provides some home-manager defaults to its users.
homeManager.programs.direnv.enable = true;
# NixOS configuration for igloo.
nixos =
{ pkgs, ... }:
{
environment.systemPackages = [ pkgs.hello ];
};
# <host>.provides.<user>, via eg/routes.nix
provides.alice =
{ user, ... }:
{
homeManager.programs.helix.enable = user.name == "alice";
};
};
}

View file

@ -0,0 +1,5 @@
{
den.hosts.x86_64-linux.igloo.users.alice = { };
den.hosts.aarch64-darwin.apple.users.alice = { };
den.homes.x86_64-linux.alice = { };
}

View file

@ -0,0 +1,6 @@
{ inputs, ... }:
{
imports = [
inputs.flake-file.flakeModules.dendritic
];
}

View file

@ -0,0 +1,37 @@
# This repo was generated with github:vic/flake-file#dendritic template.
# Run `nix run .#write-flake` after changing any input.
#
# Inputs can be placed in any module, the best practice is to have them
# as close as possible to their actual usage.
# See: https://vic.github.io/dendrix/Dendritic.html#minimal-and-focused-flakenix
#
# For our template, we enable home-manager and nix-darwin by default, but
# you are free to remove them if not being used by you.
{ inputs, ... }:
{
flake-file.inputs = {
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
darwin = {
url = "github:nix-darwin/nix-darwin";
inputs.nixpkgs.follows = "nixpkgs";
};
## these stable inputs are for wsl
#nixpkgs-stable.url = "github:nixos/nixpkgs/release-25.05";
#home-manager-stable.url = "github:nix-community/home-manager/release-25.05";
#home-manager-stable.inputs.nixpkgs.follows = "nixpkgs-stable";
#nixos-wsl = {
# url = "github:nix-community/nixos-wsl";
# inputs.nixpkgs.follows = "nixpkgs-stable";
# inputs.flake-compat.follows = "";
#};
};
}

View file

@ -0,0 +1,14 @@
{ inputs, den, ... }:
{
# create an `eg` (example!) namespace.
imports = [ (inputs.den.namespace "eg" false) ];
# you can have more than one namespace, create yours.
# imports = [ (inputs.den.namespace "yours" true) ];
# you can also import namespaces from remote flakes.
# imports = [ (inputs.den.namespace "ours" inputs.theirs) ];
# this line enables den angle brackets syntax in modules.
_module.args.__findFile = den.lib.__findFile;
}

View file

@ -0,0 +1,34 @@
# Some CI checks to ensure this template always works.
# Feel free to adapt or remove when this repo is yours.
{ inputs, ... }:
{
perSystem =
{
pkgs,
self',
lib,
...
}:
let
checkCond = name: cond: pkgs.runCommandLocal name { } (if cond then "touch $out" else "");
apple = inputs.self.darwinConfigurations.apple.config;
igloo = inputs.self.nixosConfigurations.igloo.config;
alice-at-igloo = igloo.home-manager.users.alice;
vmBuilds = !pkgs.stdenvNoCC.isLinux || builtins.pathExists (self'.packages.vm + "/bin/vm");
iglooBuilds = !pkgs.stdenvNoCC.isLinux || builtins.pathExists (igloo.system.build.toplevel);
appleBuilds = !pkgs.stdenvNoCC.isDarwin || builtins.pathExists (apple.system.build.toplevel);
in
{
checks."igloo builds" = checkCond "igloo-builds" iglooBuilds;
checks."apple builds" = checkCond "apple-builds" appleBuilds;
checks."vm builds" = checkCond "vm-builds" vmBuilds;
checks."alice enabled igloo nh" = checkCond "alice.provides.igloo" igloo.programs.nh.enable;
checks."igloo enabled alice helix" =
checkCond "igloo.provides.alice" alice-at-igloo.programs.helix.enable;
checks."alice-custom-emacs" = checkCond "hm.programs.emacs.package" (
"emacs-nox" == lib.getName alice-at-igloo.programs.emacs.package
);
};
}

View file

@ -0,0 +1,22 @@
# enables `nix run .#vm`. it is very useful to have a VM
# you can edit your config an launch the VM to test stuff
# instead of having to reboot each time.
{ inputs, eg, ... }:
{
den.aspects.igloo.includes = [
eg.vm._.gui
# eg.vm._.tui
];
perSystem =
{ pkgs, ... }:
{
packages.vm = pkgs.writeShellApplication {
name = "vm";
text = ''
${inputs.self.nixosConfigurations.igloo.config.system.build.vm}/bin/run-igloo-vm "$@"
'';
};
};
}

276
flake/den/templates/examples/flake.lock generated Normal file
View file

@ -0,0 +1,276 @@
{
"nodes": {
"darwin": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1762039661,
"narHash": "sha256-oM5BwAGE78IBLZn+AqxwH/saqwq3e926rNq5HmOulkc=",
"owner": "nix-darwin",
"repo": "nix-darwin",
"rev": "c3c8c9f2a5ed43175ac4dc030308756620e6e4e4",
"type": "github"
},
"original": {
"owner": "nix-darwin",
"repo": "nix-darwin",
"type": "github"
}
},
"den": {
"locked": {
"lastModified": 1763285091,
"narHash": "sha256-F2OsALSm86dfNA2grd5MVRPpAWZf4ZuuCzpYG7H0P9g=",
"owner": "vic",
"repo": "den",
"rev": "227451c9a99fb084bc6b66878c7f6f3e75f625d2",
"type": "github"
},
"original": {
"owner": "vic",
"repo": "den",
"type": "github"
}
},
"flake-aspects": {
"locked": {
"lastModified": 1763284357,
"narHash": "sha256-mPMHkhpOIsj2lg+KIcapFd4uj2N/9mZZ6RZBo/p5O1c=",
"owner": "vic",
"repo": "flake-aspects",
"rev": "6a6d47f531ad57ac854cee689e84f2e28861ec49",
"type": "github"
},
"original": {
"owner": "vic",
"repo": "flake-aspects",
"type": "github"
}
},
"flake-file": {
"locked": {
"lastModified": 1761535278,
"narHash": "sha256-OPZ7XpG778i9CIJfchAwgrZGZ9z1dWJzfN18VFxCyS4=",
"owner": "vic",
"repo": "flake-file",
"rev": "57b2a65831ae49e4f9218dbba1c2dc9700f6cd68",
"type": "github"
},
"original": {
"owner": "vic",
"repo": "flake-file",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"nixpkgs-lib"
]
},
"locked": {
"lastModified": 1762040540,
"narHash": "sha256-z5PlZ47j50VNF3R+IMS9LmzI5fYRGY/Z5O5tol1c9I4=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "0010412d62a25d959151790968765a70c436598b",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1762087455,
"narHash": "sha256-hpbPma1eUKwLAmiVRoMgIHbHiIKFkcACobJLbDt6ABw=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "43e205606aeb253bfcee15fd8a4a01d8ce8384ca",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"home-manager-stable": {
"inputs": {
"nixpkgs": [
"nixpkgs-stable"
]
},
"locked": {
"lastModified": 1758463745,
"narHash": "sha256-uhzsV0Q0I9j2y/rfweWeGif5AWe0MGrgZ/3TjpDYdGA=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "3b955f5f0a942f9f60cdc9cacb7844335d0f21c3",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "release-25.05",
"repo": "home-manager",
"type": "github"
}
},
"import-tree": {
"locked": {
"lastModified": 1761120675,
"narHash": "sha256-TEbh9zISiQcU82VwVoEbmXHnSGlUxTwvjJA9g9ErSDA=",
"owner": "vic",
"repo": "import-tree",
"rev": "a037ed2a58fc0ebed9e93b9ef79b0646e648f719",
"type": "github"
},
"original": {
"owner": "vic",
"repo": "import-tree",
"type": "github"
}
},
"nix-auto-follow": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1754073254,
"narHash": "sha256-CQp/v2HQ7AtGJQqFGRZLHt4MZAK3NF94I6GDaRyhbsc=",
"owner": "fzakaria",
"repo": "nix-auto-follow",
"rev": "5baa00b79d4cc46523da0b8b3532c5163d151be4",
"type": "github"
},
"original": {
"owner": "fzakaria",
"repo": "nix-auto-follow",
"type": "github"
}
},
"nixos-wsl": {
"inputs": {
"flake-compat": [],
"nixpkgs": [
"nixpkgs-stable"
]
},
"locked": {
"lastModified": 1761969132,
"narHash": "sha256-0me4+e+1VxNuvySSw0voqMCWU/eUmTuth7f4+Q2jbUY=",
"owner": "nix-community",
"repo": "nixos-wsl",
"rev": "761582d6ab431549fe1396d2cd681e3fe9376020",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixos-wsl",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1761880412,
"narHash": "sha256-QoJjGd4NstnyOG4mm4KXF+weBzA2AH/7gn1Pmpfcb0A=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "a7fc11be66bdfb5cdde611ee5ce381c183da8386",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1762081535,
"narHash": "sha256-+j+CUiaUoa87EhnSOqG5pwXdJWahP8vo6BE0ekssdzs=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "2afc9d6e79b59ea9bcaf620d335623b0f7c2ce96",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "release-25.05",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"darwin": "darwin",
"den": "den",
"flake-aspects": "flake-aspects",
"flake-file": "flake-file",
"flake-parts": "flake-parts",
"home-manager": "home-manager",
"home-manager-stable": "home-manager-stable",
"import-tree": "import-tree",
"nix-auto-follow": "nix-auto-follow",
"nixos-wsl": "nixos-wsl",
"nixpkgs": "nixpkgs",
"nixpkgs-lib": [
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable",
"systems": "systems",
"treefmt-nix": "treefmt-nix"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1761311587,
"narHash": "sha256-Msq86cR5SjozQGCnC6H8C+0cD4rnx91BPltZ9KK613Y=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "2eddae033e4e74bf581c2d1dfa101f9033dbd2dc",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -0,0 +1,93 @@
# DO-NOT-EDIT. This file was auto-generated using github:vic/flake-file.
# Use `nix run .#write-flake` to regenerate it.
{
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } (inputs.import-tree ./modules);
inputs = {
darwin = {
inputs = {
nixpkgs = {
follows = "nixpkgs";
};
};
url = "github:nix-darwin/nix-darwin";
};
den = {
url = "github:vic/den";
};
flake-aspects = {
url = "github:vic/flake-aspects";
};
flake-file = {
url = "github:vic/flake-file";
};
flake-parts = {
inputs = {
nixpkgs-lib = {
follows = "nixpkgs-lib";
};
};
url = "github:hercules-ci/flake-parts";
};
home-manager = {
inputs = {
nixpkgs = {
follows = "nixpkgs";
};
};
url = "github:nix-community/home-manager";
};
home-manager-stable = {
inputs = {
nixpkgs = {
follows = "nixpkgs-stable";
};
};
url = "github:nix-community/home-manager/release-25.05";
};
import-tree = {
url = "github:vic/import-tree";
};
nix-auto-follow = {
inputs = {
nixpkgs = {
follows = "nixpkgs";
};
};
url = "github:fzakaria/nix-auto-follow";
};
nixos-wsl = {
inputs = {
flake-compat = {
follows = "";
};
nixpkgs = {
follows = "nixpkgs-stable";
};
};
url = "github:nix-community/nixos-wsl";
};
nixpkgs = {
url = "github:nixos/nixpkgs/nixpkgs-unstable";
};
nixpkgs-lib = {
follows = "nixpkgs";
};
nixpkgs-stable = {
url = "github:nixos/nixpkgs/release-25.05";
};
systems = {
url = "github:nix-systems/default";
};
treefmt-nix = {
inputs = {
nixpkgs = {
follows = "nixpkgs";
};
};
url = "github:numtide/treefmt-nix";
};
};
}

View file

@ -0,0 +1,5 @@
User TODO: REMOVE this directory (or disable its import from den.nix)
It is used to implement tests for all den features so we can validate at CI.
Use it as reference to see how den features are used, however, be aware that this might not be the best practices for file/aspect organization.

View file

@ -0,0 +1,6 @@
# this is a non-dendritic darwin class module file.
# automatically discovered by `den.import-tree` as enabled in auto-imports.nix
{ ... }:
{
# see nix-darwin options.
}

View file

@ -0,0 +1,14 @@
# this is a non-dendritic nix class module file.
# automatically discovered by `den.import-tree` as enabled in auto-imports.nix
#
# USER TODO: Remove this file.
# suppose this file was auto-generated by nixos-generate-config or some other hardware tooling.
{ lib, ... }:
{
# used in CI to test this file was actually imported.
options.auto-imported = lib.mkOption {
readOnly = true;
type = lib.types.bool;
default = true;
};
}

View file

@ -0,0 +1,27 @@
# Adds some checks for CI
{
perSystem =
{
pkgs,
checkFile,
rockhopper,
honeycrisp,
cam,
bob,
...
}:
let
checks.x86_64-linux = {
vm = checkFile "vm-builds" "${rockhopper.config.system.build.vm}/bin/run-rockhopper-vm";
hosts-rockhopper = checkFile "nixos-builds" rockhopper.config.system.build.toplevel;
homes-cam = checkFile "home-builds" cam.activation-script;
};
checks.aarch64-darwin = {
hosts-honeycrisp = checkFile "darwin-builds" honeycrisp.config.system.build.toplevel;
homes-bob = checkFile "darwin-home-builds" bob.activation-script;
};
in
{
checks = checks.${pkgs.system} or { };
};
}

View file

@ -0,0 +1,30 @@
{
# Including an static aspect should not cause duplicate definitions
den.aspects.alice.includes = [
{
homeManager =
{ pkgs, ... }:
{
programs.emacs.enable = true;
programs.emacs.package = pkgs.emacs30-nox;
};
}
];
perSystem =
{
checkCond,
alice-at-rockhopper,
lib,
...
}:
{
checks.alice-custom-emacs = checkCond "set uniquely via a static includes" (
let
expr = lib.getName alice-at-rockhopper.programs.emacs.package;
expected = "emacs-nox";
in
expr == expected
);
};
}

View file

@ -0,0 +1,35 @@
{ lib, ... }:
let
# A custom `nixos` class module that defines an option `names`.
# Used to test that we are not duplicating values from owned configs.
nixosNames = names: { options.${names} = lib.mkOption { type = lib.types.listOf lib.types.str; }; };
in
{
den.default.nixos.imports = [ (nixosNames "people") ];
den.default.includes = [
(
{ user, ... }:
{
nixos.people = [ user.name ];
}
)
];
den.aspects.rockhopper.includes = [
# Example: importing a third-party nixos module.
{ nixos.imports = [ (nixosNames "names") ]; }
];
den.aspects.rockhopper.nixos.names = [ "tux" ];
perSystem =
{ checkCond, rockhopper, ... }:
{
checks.rockhopper-default-people = checkCond "set from den.default for each user" (
rockhopper.config.people == [ "alice" ]
);
checks.rockhopper-names-single-entry = checkCond "custom nixos array option set once" (
rockhopper.config.names == [ "tux" ]
);
};
}

View file

@ -0,0 +1,27 @@
{ den, ... }:
{
den.default.includes = [
# Example: parametric over many contexts: { home }, { host, user }, { fromUser, toHost }
den.provides.define-user
];
perSystem =
{
checkCond,
rockhopper,
adelie,
...
}:
{
checks.alice-exists-on-rockhopper = checkCond "den.default.user.includes defines user on host" (
rockhopper.config.users.users.alice.isNormalUser
);
checks.alice-not-exists-on-adelie = checkCond "den.default.user.includes defines user on host" (
!adelie.config.users.users ? alice
);
checks.will-exists-on-adelie = checkCond "den.default.user.includes defines user on host" (
adelie.config.users.users.will.isNormalUser
);
};
}

View file

@ -0,0 +1,8 @@
{ inputs, ... }:
{
# Example: adelie host using github:nix-community/NixOS-WSL
den.aspects.adelie.nixos = {
imports = [ inputs.nixos-wsl.nixosModules.default ];
wsl.enable = true;
};
}

View file

@ -0,0 +1,37 @@
{ self, ... }:
{
perSystem =
{ pkgs, ... }:
let
checkFile =
name: file:
pkgs.runCommandLocal name { } ''
ls -la ${file} | tee $out
'';
checkCond =
name: cond:
let
code = if cond then "touch $out" else ''echo "Cond-Failed: ${name}"'';
in
pkgs.runCommandLocal name { } code;
rockhopper = self.nixosConfigurations.rockhopper;
honeycrisp = self.darwinConfigurations.honeycrisp;
adelie = self.wslConfigurations.adelie;
cam = self.homeConfigurations.cam;
bob = self.homeConfigurations.bob;
luke = self.homeConfigurations.luke;
alice-at-rockhopper = rockhopper.config.home-manager.users.alice;
alice-at-honeycrisp = honeycrisp.config.home-manager.users.alice;
in
{
_module.args = {
inherit checkCond checkFile;
inherit rockhopper honeycrisp adelie;
inherit cam bob luke;
inherit alice-at-rockhopper alice-at-honeycrisp;
};
};
}

View file

@ -0,0 +1,13 @@
{
# Example: host provides static config to all its users hm.
den.aspects.rockhopper.homeManager.programs.direnv.enable = true;
perSystem =
{ checkCond, alice-at-rockhopper, ... }:
{
checks.host-contributes-to-user = checkCond "rockhopper contributes to all its users" (
alice-at-rockhopper.programs.direnv.enable
);
};
}

View file

@ -0,0 +1,42 @@
{ lib, ... }:
let
# Example: configuration that depends on both host and user. provides only to HM.
host-to-user-conditional =
{
user,
host,
...
}:
if user.userName == "alice" && !lib.hasSuffix "darwin" host.system then
{
homeManager.programs.git.enable = true;
}
else
{ };
in
{
den.aspects.rockhopper.includes = [
# Example: host provides parametric user configuration.
host-to-user-conditional
];
perSystem =
{
checkCond,
alice-at-rockhopper,
alice-at-honeycrisp,
...
}:
{
checks.alice-hm-git-enabled-on = checkCond "home-managed git for alice at rockhopper" (
alice-at-rockhopper.programs.git.enable
);
checks.alice-hm-git-enabled-off = checkCond "home-managed git for alice at honeycrisp" (
!alice-at-honeycrisp.programs.git.enable
);
};
}

View file

@ -0,0 +1,28 @@
# configures class-automatic module auto imports for hosts/users/homes.
# See documentation at modules/aspects/provides/import-tree.nix
{
# deadnix: skip
__findFile ? __findFile,
...
}:
{
# alice imports non-dendritic <class> modules from _non_dendritic/alice/_<class>/*.nix
den.aspects.alice.includes = [ (<den/import-tree> ./_non_dendritic/alice) ];
# See the documentation at batteries/import-tree.nix
den.default.includes = [
(<den/import-tree/host> ./_non_dendritic/hosts)
(<den/import-tree/user> ./_non_dendritic/users)
(<den/import-tree/home> ./_non_dendritic/homes)
];
# tests
perSystem =
{ checkCond, rockhopper, ... }:
{
checks.import-tree = checkCond "auto-imported from rockhopper/_nixos" (
rockhopper.config.auto-imported
);
};
}

View file

@ -0,0 +1,5 @@
{ inputs, den, ... }:
{
imports = [ (inputs.den.namespace "eg" false) ];
_module.args.__findFile = den.lib.__findFile;
}

View file

@ -0,0 +1,41 @@
let
# Example: adds hello into each user. provides only to OS.
hello-package-for-user =
{
user,
host,
...
}:
{
${host.class} =
{ pkgs, ... }:
{
users.users.${user.userName}.packages = [ pkgs.hello ];
};
};
in
{
den.default.includes = [ hello-package-for-user ];
perSystem =
{
checkCond,
rockhopper,
lib,
...
}:
{
checks.alice-hello-enabled-by-default = checkCond "added hello at user packages" (
let
progs = rockhopper.config.users.users.alice.packages;
expr = map lib.getName progs;
expected = [ "hello" ];
in
expr == expected
);
};
}

View file

@ -0,0 +1,29 @@
{ den, ... }:
{
den.aspects.alice.includes = [
# alice is always admin in all its hosts
den._.primary-user
];
den.aspects.will.includes = [
# will is primary user in WSL NixOS.
den._.primary-user
];
perSystem =
{
checkCond,
honeycrisp,
adelie,
...
}:
{
checks.alice-primary-on-macos = checkCond "den._.primary-user sets macos primary" (
honeycrisp.config.system.primaryUser == "alice"
);
checks.will-is-wsl-default = checkCond "wsl.defaultUser defined" (
adelie.config.wsl.defaultUser == "will"
);
};
}

View file

@ -0,0 +1,29 @@
{
den.default.includes =
let
# Example: parametric host aspect to automatically set hostName on any host.
set-host-name =
{ host, ... }:
{
${host.class}.networking.hostName = host.name;
};
in
[ set-host-name ];
perSystem =
{
checkCond,
rockhopper,
honeycrisp,
...
}:
{
checks.rockhopper-hostname = checkCond "den.default.host.includes sets hostName" (
rockhopper.config.networking.hostName == "rockhopper"
);
checks.honeycrisp-hostname = checkCond "den.default.host.includes sets hostName" (
honeycrisp.config.networking.hostName == "honeycrisp"
);
};
}

View file

@ -0,0 +1,31 @@
let
# Example: luke standalone home-manager has access to rockhopper osConfig specialArg.
os-conditional-hm =
{ home, ... }:
{
# access osConfig, wired via extraSpecialArgs in homes.nix.
homeManager =
{ osConfig, ... }:
{
programs.bat.enable = osConfig.programs.${home.programToDependOn}.enable;
};
};
in
{
# Example: standalone-hm config depends on osConfig (non-recursive)
# NOTE: this will only work for standalone hm, and not for hosted hm
# since a hosted hm configuration cannot depend on the os configuration.
den.aspects.luke.includes = [
os-conditional-hm
];
perSystem =
{ checkCond, luke, ... }:
{
checks.luke-hm-depends-on-osConfig = checkCond "standalone hm can depend on osConfig" (
luke.config.programs.bat.enable
);
};
}

View file

@ -0,0 +1,47 @@
# it is possible for top-level aspects directly under
# den.aspects to take a context argument.
{ den, lib, ... }:
let
# A module to test that toplevel had context.
topLevel = name: {
config.tops = name;
options.tops = lib.mkOption { type = lib.types.str; };
};
in
{
den.aspects.toplevel-user =
{ user, ... }:
{
nixos.imports = [ (topLevel user.name) ];
};
den.aspects.toplevel-host =
{ host, ... }:
{
homeManager.imports = [ (topLevel host.name) ];
};
den.aspects.alice.includes = [
den.aspects.toplevel-host
den.aspects.toplevel-user
];
perSystem =
{
checkCond,
alice-at-rockhopper,
rockhopper,
...
}:
{
checks.alice-toplevel-user = checkCond "alice toplevel param aspect" (
rockhopper.config.tops == "alice"
);
checks.alice-toplevel-host = checkCond "alice toplevel param aspect" (
alice-at-rockhopper.tops == "rockhopper"
);
};
}

View file

@ -0,0 +1,6 @@
{ den, ... }:
{
# cam uses unfree vscode.
den.aspects.cam.homeManager.programs.vscode.enable = true;
den.aspects.cam.includes = [ (den._.unfree [ "vscode" ]) ];
}

View file

@ -0,0 +1,12 @@
{
# Example: user provides static config to all its nixos hosts.
den.aspects.alice.nixos.users.users.alice.description = "Alice Q. User";
perSystem =
{ checkCond, rockhopper, ... }:
{
checks.user-contributes-to-host = checkCond "alice.nixos sets on rockhopper host" (
rockhopper.config.users.users.alice.description == "Alice Q. User"
);
};
}

View file

@ -0,0 +1,12 @@
{
# globally enable fish on all homes ever.
den.default.homeManager.programs.fish.enable = true;
perSystem =
{ checkCond, alice-at-rockhopper, ... }:
{
checks.alice-hm-fish-enabled-by-default = checkCond "home-managed fish for alice" (
alice-at-rockhopper.programs.fish.enable
);
};
}

View file

@ -0,0 +1,38 @@
{ lib, ... }:
let
# Example: configuration that depends on both host and user. provides anytime { user, host } is in context.
user-to-host-conditional =
{ user, host, ... }:
if user.userName == "alice" && !lib.hasSuffix "darwin" host.system then
{
nixos.programs.tmux.enable = true;
}
else
{ };
in
{
# Example: user provides parametric host configuration.
den.aspects.alice.includes = [
user-to-host-conditional
];
perSystem =
{
checkCond,
rockhopper,
honeycrisp,
...
}:
{
checks.alice-os-tmux-enabled-on = checkCond "os tmux for hosts having alice" (
rockhopper.config.programs.tmux.enable
);
checks.alice-os-tmux-enabled-off = checkCond "os tmux for hosts having alice" (
!honeycrisp.config.programs.tmux.enable
);
};
}

View file

@ -0,0 +1,17 @@
{ den, lib, ... }:
{
den.aspects.will.includes = [
# will has always loved red snappers
(den._.user-shell "fish")
];
perSystem =
{ checkCond, adelie, ... }:
{
checks.will-always-love-you = checkCond "red-snapper fish is default shell" (
"fish" == lib.getName adelie.config.users.users.will.shell
);
};
}

View file

@ -0,0 +1,13 @@
{
# Example: enable helix for alice on all its home-managed hosts.
den.aspects.alice.homeManager.programs.helix.enable = true;
perSystem =
{ checkCond, alice-at-rockhopper, ... }:
{
checks.alice-hm-helix-enabled-by-user = checkCond "home-managed helix for alice" (
alice-at-rockhopper.programs.helix.enable
);
};
}

View file

@ -0,0 +1,16 @@
let
# Example: A static aspect for vm installers.
vm-bootable = {
nixos =
{ modulesPath, ... }:
{
imports = [ (modulesPath + "/installer/cd-dvd/installation-cd-minimal.nix") ];
};
};
in
{
den.default.includes = [
# Example: static aspect
vm-bootable
];
}

View file

@ -0,0 +1,14 @@
# User TODO: Remove this file.
{
# default aspect can be used for global static settings.
den.default = {
# static values.
darwin.system.stateVersion = 6;
nixos.system.stateVersion = "25.05";
homeManager.home.stateVersion = "25.05";
# these defaults are set for checking with CI.
nixos.programs.vim.enable = true;
darwin.programs.zsh.enable = true;
};
}

View file

@ -0,0 +1,12 @@
{ den, ... }:
{
# see batteries/home-manager.nix
den.default.includes = [ den._.home-manager ];
# enable home-manager dependency.
flake-file.inputs.home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
}

View file

@ -0,0 +1,31 @@
# Example standalone home-manager configurations.
# These are independent of any host configuration.
# See documentation at <den>/nix/types.nix
{ inputs, ... }:
{
den.homes.x86_64-linux.cam = { };
den.homes.aarch64-darwin.bob = {
userName = "robert";
aspect = "developer";
};
# Example: custom home-manager instantiate for passing extraSpecialArgs.
den.homes.x86_64-linux.luke =
let
osConfig = inputs.self.nixosConfigurations.rockhopper.config;
in
{
# Example: luke standalone-homemanager needs access to rockhopper osConfig.
instantiate =
{ pkgs, modules }:
inputs.home-manager.lib.homeManagerConfiguration {
inherit pkgs modules;
extraSpecialArgs.osConfig = osConfig;
};
# Example: custom attribute instead of specialArgs
programToDependOn = "vim";
};
}

View file

@ -0,0 +1,50 @@
# This is a fully working example configuration.
# Feel free to remove it, adapt or split into several modules.
# See documentation at <den>/nix/types.nix
{ inputs, ... }:
{
den.hosts.aarch64-darwin.honeycrisp.users.alice = { };
den.hosts.aarch64-linux.emperor.users.alice = { };
den.hosts.x86_64-linux = {
rockhopper = {
description = "rockhopper is a kind of penguin";
users.alice = { };
};
adelie = {
description = "wsl on windows";
users.will = { };
intoAttr = "wslConfigurations";
# custom nixpkgs channel.
instantiate = inputs.nixpkgs-stable.lib.nixosSystem;
# custom attribute (see home-manager.nix)
hm-module = inputs.home-manager-stable.nixosModules.home-manager;
# custom attribute (see primary-user.nix)
wsl = { };
};
};
# move these inputs to any module you want.
# they are here for all our examples to work on CI.
flake-file.inputs = {
# these stable inputs are for wsl
nixpkgs-stable.url = "github:nixos/nixpkgs/release-25.05";
home-manager-stable.url = "github:nix-community/home-manager/release-25.05";
home-manager-stable.inputs.nixpkgs.follows = "nixpkgs-stable";
nixos-wsl = {
url = "github:nix-community/nixos-wsl";
inputs.nixpkgs.follows = "nixpkgs-stable";
inputs.flake-compat.follows = "";
};
darwin = {
url = "github:nix-darwin/nix-darwin";
inputs.nixpkgs.follows = "nixpkgs";
};
};
}

View file

@ -0,0 +1,10 @@
# USER TODO: remove this file.
# copy any desired module to your ./modules and let it be auto-imported.
{ inputs, ... }:
{
imports = [
# The _example directory contains CI tests for all den features.
# use it as reference of usage, but not of best practices.
(inputs.import-tree ./_example)
];
}

View file

@ -0,0 +1,7 @@
{ inputs, lib, ... }:
{
flake-file.inputs.flake-file.url = lib.mkDefault "github:vic/flake-file";
imports = [
inputs.flake-file.flakeModules.dendritic
];
}