predictable module locations

We introduce a few new mechanism in this commit:

flake-parts is used to wire things together.

./all-parts.nix looks for and imports all flake-part.nix files. This
makes it easier to co-locate the parts next to the targeted code.

We introduce a `modules` flake output to hold all modules. For example
instead of `nixosModules`, use `modules.nixos`.

In ./nixos we enforce a 1:1 mapping between the module filenames and the
attribute. For example ./nixos/mixins/telegraf.nix will translate to
`modules.nixos.mixins-telegraf`.

flake-compat ensures that the default.nix and flake.nix are in sync and have the same outputs.
This commit is contained in:
DavHau 2023-02-16 15:58:20 +07:00 committed by zimbatm
parent bbc55aaa74
commit 18031eb886
No known key found for this signature in database
GPG Key ID: 71BAF6D40C1D63D7
10 changed files with 356 additions and 193 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
result

22
all-parts.nix Normal file
View File

@ -0,0 +1,22 @@
# Find all the flake-part.nix files in this repo and import them
{ config, lib, ... }:
let
root = ./.;
getParts = path:
let dir = builtins.readDir path; in
lib.concatMap
(k:
let v = dir.${k}; in
if k == "flake-part.nix" && v == "regular" then
# Collect this
[ (path + "/${k}") ]
else if v == "directory" then
getParts (path + "/${k}")
else [ ]
)
(lib.attrNames dir);
in
{
imports = getParts ./.;
}

View File

@ -1,26 +1,14 @@
{
nixosModules = {
# General
common = import ./nixos/common;
desktop = import ./nixos/desktop;
server = import ./nixos/server;
# Hardware
hardware-amazon = import ./nixos/hardware/amazon;
hardware-hetzner-cloud = import ./nixos/hardware/hetzner-cloud;
hardware-hetzner-online-amd = import ./nixos/hardware/hetzner-online/amd.nix;
hardware-hetzner-online-intel = import ./nixos/hardware/hetzner-online/intel.nix;
# Mixins
mixins-cloud-init = import ./nixos/mixins/cloud-init.nix;
mixins-nginx = import ./nixos/mixins/nginx.nix;
mixins-systemd-boot = import ./nixos/mixins/systemd-boot.nix;
mixins-telegraf = import ./nixos/mixins/telegraf.nix;
mixins-terminfo = import ./nixos/mixins/terminfo.nix;
mixins-trusted-nix-caches = import ./nixos/mixins/trusted-nix-caches.nix;
# Roles
roles-github-actions-runner = import ./nixos/roles/github-actions-runner.nix;
roles-nix-remote-builder = import ./nixos/roles/nix-remote-builder.nix;
};
}
# This file provides backward compatibility to nix < 2.4 clients
let
flake =
import
(
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
)
{ src = ./.; };
in
flake.defaultNix

5
docs/flake-part.nix Normal file
View File

@ -0,0 +1,5 @@
{ self, lib, ... }: {
perSystem = { config, self', inputs', pkgs, ... }: {
packages.docs = pkgs.callPackage ./. { };
};
}

9
flake-part.nix Normal file
View File

@ -0,0 +1,9 @@
{ lib, ... }:
{
# We define a new prefix that includes *all* the types of modules.
#
# Eg: instead of nixosModules, use modules.nixos
options.flake.modules = lib.mkOption {
type = lib.types.anything;
};
}

View File

@ -1,5 +1,38 @@
{
"nodes": {
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1675933616,
"narHash": "sha256-/rczJkJHtx16IFxMmAWu5nNYcSXNg1YYXTHoGjLrLUA=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "47478a4a003e745402acf63be7f9a092d51b83d7",
"type": "github"
},
"original": {
"id": "flake-parts",
"type": "indirect"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1677098068,
@ -16,8 +49,28 @@
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"dir": "lib",
"lastModified": 1675183161,
"narHash": "sha256-Zq8sNgAxDckpn7tJo7V1afRSk2eoVbu3OjI1QklGLNg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e1e1b192c1a5aab2960bf0a0bd53a2e8124fa18e",
"type": "github"
},
"original": {
"dir": "lib",
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-compat": "flake-compat",
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs"
}
}

176
flake.nix
View File

@ -3,180 +3,22 @@
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable-small";
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
};
outputs = { self, nixpkgs, ... }:
let
forAllSystems = nixpkgs.lib.genAttrs [
outputs = inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [
"aarch64-darwin"
"aarch64-linux"
"x86_64-darwin"
"x86_64-linux"
];
in
(import ./.) //
{
packages = forAllSystems (system: {
docs = nixpkgs.legacyPackages.${system}.callPackage ./docs { };
});
nixosConfigurations =
let
fake-hardware = {
boot.loader.grub.devices = [ "/dev/sda" ];
fileSystems."/" = {
device = "/dev/sda";
};
};
# some example configuration to make it eval
dummy = { config, ... }: {
networking.hostName = "example-common";
system.stateVersion = config.system.nixos.version;
users.users.root.initialPassword = "fnord23";
};
in
{
# General
example-common = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.common
];
};
example-server = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.server
];
};
example-desktop = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.desktop
];
};
# Hardware
example-hardware-amazon = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
dummy
self.nixosModules.hardware-amazon
];
};
example-hardware-hetzner-cloud = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
dummy
self.nixosModules.hardware-hetzner-cloud
{
systemd.network.networks."10-uplink".networkConfig.Address = "::cafe:babe:feed:face:dead:beef";
}
];
};
# Mixins
example-mixins-cloud-init = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.mixins-cloud-init
];
};
example-mixins-systemd-boot = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.mixins-systemd-boot
];
};
example-mixins-telegraf = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.mixins-telegraf
];
};
example-mixins-terminfo = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.mixins-terminfo
];
};
example-mixins-trusted-nix-caches = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.mixins-trusted-nix-caches
];
};
example-mixins-nginx = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.mixins-nginx
];
};
# Roles
example-roles-github-actions-runner = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
self.nixosModules.roles-github-actions-runner
dummy
fake-hardware
{
roles.github-actions-runner.cachix.cacheName = "cache-name";
roles.github-actions-runner.cachix.tokenFile = "/run/cachix-token-file";
roles.github-actions-runner.tokenFile = "/run/gha-token-file";
roles.github-actions-runner.url = "https://fixup";
}
];
};
example-roles-github-actions-runner-github-app = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
self.nixosModules.roles-github-actions-runner
dummy
fake-hardware
{
roles.github-actions-runner.cachix.cacheName = "cache-name";
roles.github-actions-runner.cachix.tokenFile = "/run/cachix-token-file";
roles.github-actions-runner.githubApp = {
id = "1234";
login = "foo";
privateKeyFile = "/run/gha-token-file";
};
roles.github-actions-runner.url = "https://fixup";
}
];
};
example-roles-nix-remote-builder = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
self.nixosModules.roles-nix-remote-builder
dummy
fake-hardware
{
roles.nix-remote-builder.schedulerPublicKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOuiDoBOxgyer8vGcfAIbE6TC4n4jo8lhG9l01iJ0bZz zimbatm@no1"
];
}
];
};
};
imports = [ ./all-parts.nix ];
};
}

55
nixos/default.nix Normal file
View File

@ -0,0 +1,55 @@
let
inherit (builtins)
listToAttrs
replaceStrings
stringLength
substring
;
removeSuffix =
# Suffix to remove if it matches
suffix:
# Input string
str:
let
sufLen = stringLength suffix;
sLen = stringLength str;
in
if sufLen <= sLen && suffix == substring (sLen - sufLen) sufLen str then
substring 0 (sLen - sufLen) str
else
str;
# Map 1:1 between paths and modules
exposeModules = baseDir: paths:
let
prefix = stringLength (toString baseDir) + 1;
toPair = path: {
name = replaceStrings [ "/" ] [ "-" ] (removeSuffix ".nix" (substring prefix 1000000
(toString path)));
value = path;
};
in
listToAttrs (map toPair paths)
;
in
exposeModules ./. [
./common
./desktop
./hardware/amazon
./hardware/hetzner-cloud
./hardware/hetzner-online/amd.nix
./hardware/hetzner-online/intel.nix
./mixins/cloud-init.nix
./mixins/nginx.nix
./mixins/systemd-boot.nix
./mixins/telegraf.nix
./mixins/terminfo.nix
./mixins/tracing.nix
./mixins/trusted-nix-caches.nix
./roles/github-actions-runner.nix
./roles/nix-remote-builder.nix
./server
]

186
nixos/flake-part.nix Normal file
View File

@ -0,0 +1,186 @@
{ lib, self, config, inputs, ... }:
{
# generates future flake outputs: `modules.<kind>.<module-name>`
config.flake.modules.nixos = import ./.;
# compat to current schema: `nixosModules` / `darwinModules`
config.flake.nixosModules = config.flake.modules.nixos or { };
# the test NixOS configurations
config.flake.nixosConfigurations =
let
nixosSystem = args:
# TODO: flake-parts does not expose lib.nixosSystems.
# Fix this upstream at flake-parts or nixpkgs.
# (Why are there even two different libs ?)
import (inputs.nixpkgs + /nixos/lib/eval-config.nix) (
args // {
modules = args.modules ++ [{
system.nixos.versionSuffix =
".${lib.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}.${self.shortRev or "dirty"}";
system.nixos.revision = lib.mkIf (self ? rev) self.rev;
}];
} // lib.optionalAttrs (! args?system) {
# Allow system to be set modularly in nixpkgs.system.
# We set it to null, to remove the "legacy" entrypoint's
# non-hermetic default.
system = null;
}
);
fake-hardware = {
boot.loader.grub.devices = [ "/dev/sda" ];
fileSystems."/" = {
device = "/dev/sda";
};
};
# some example configuration to make it eval
dummy = { config, ... }: {
networking.hostName = "example-common";
system.stateVersion = config.system.nixos.version;
users.users.root.initialPassword = "fnord23";
};
in
{
# General
example-common = nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.common
];
};
example-server = nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.server
];
};
example-desktop = nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.desktop
];
};
# Hardware
example-hardware-amazon = nixosSystem {
system = "x86_64-linux";
modules = [
dummy
self.nixosModules.hardware-amazon
];
};
example-hardware-hetzner-cloud = nixosSystem {
system = "x86_64-linux";
modules = [
dummy
self.nixosModules.hardware-hetzner-cloud
{
systemd.network.networks."10-uplink".networkConfig.Address = "::cafe:babe:feed:face:dead:beef";
}
];
};
# Mixins
example-mixins-cloud-init = nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.mixins-cloud-init
];
};
example-mixins-systemd-boot = nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.mixins-systemd-boot
];
};
example-mixins-telegraf = nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.mixins-telegraf
];
};
example-mixins-terminfo = nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.mixins-terminfo
];
};
example-mixins-trusted-nix-caches = nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.mixins-trusted-nix-caches
];
};
example-mixins-nginx = nixosSystem {
system = "x86_64-linux";
modules = [
dummy
fake-hardware
self.nixosModules.mixins-nginx
];
};
# Roles
example-roles-github-actions-runner = nixosSystem {
system = "x86_64-linux";
modules = [
self.nixosModules.roles-github-actions-runner
dummy
fake-hardware
{
roles.github-actions-runner.cachix.cacheName = "cache-name";
roles.github-actions-runner.cachix.tokenFile = "/run/cachix-token-file";
roles.github-actions-runner.tokenFile = "/run/gha-token-file";
roles.github-actions-runner.url = "https://fixup";
}
];
};
example-roles-github-actions-runner-github-app = nixosSystem {
system = "x86_64-linux";
modules = [
self.nixosModules.roles-github-actions-runner
dummy
fake-hardware
{
roles.github-actions-runner.cachix.cacheName = "cache-name";
roles.github-actions-runner.cachix.tokenFile = "/run/cachix-token-file";
roles.github-actions-runner.githubApp = {
id = "1234";
login = "foo";
privateKeyFile = "/run/gha-token-file";
};
roles.github-actions-runner.url = "https://fixup";
}
];
};
example-roles-nix-remote-builder = nixosSystem {
system = "x86_64-linux";
modules = [
self.nixosModules.roles-nix-remote-builder
dummy
fake-hardware
{
roles.nix-remote-builder.schedulerPublicKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOuiDoBOxgyer8vGcfAIbE6TC4n4jo8lhG9l01iJ0bZz zimbatm@no1"
];
}
];
};
};
}

2
shell.nix Normal file
View File

@ -0,0 +1,2 @@
(import ./default.nix {}).devShells.${builtins.currentSystem}.default
or throw "dev-shell not defined. Cannot find flake attribute devShell.${builtins.currentSystem}.default"