Initial checkin
This commit is contained in:
commit
23351e725d
7
flake.nix
Normal file
7
flake.nix
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
description = "Fudo Nix Helper Functions";
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, ... }: {
|
||||||
|
overlay = import ./overlay.nix;
|
||||||
|
};
|
||||||
|
}
|
70
lib/dns.nix
Normal file
70
lib/dns.nix
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
with pkgs.lib;
|
||||||
|
let
|
||||||
|
join-lines = concatStringsSep "\n";
|
||||||
|
|
||||||
|
dump = obj: builtins.trace obj obj;
|
||||||
|
|
||||||
|
makeSrvRecords = protocol: service: records: let
|
||||||
|
service-blah = (dump service);
|
||||||
|
record-blah = (dump records);
|
||||||
|
in
|
||||||
|
join-lines (map (record:
|
||||||
|
"_${service}._${protocol} IN SRV ${toString record.priority} ${
|
||||||
|
toString record.weight
|
||||||
|
} ${toString record.port} ${record.host}.") records);
|
||||||
|
|
||||||
|
makeSrvProtocolRecords = protocol: services:
|
||||||
|
join-lines (mapAttrsToList (makeSrvRecords protocol) services);
|
||||||
|
|
||||||
|
srvRecordOpts = with types; {
|
||||||
|
options = {
|
||||||
|
weight = mkOption {
|
||||||
|
type = int;
|
||||||
|
description = "Weight relative to other records.";
|
||||||
|
default = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
priority = mkOption {
|
||||||
|
type = int;
|
||||||
|
description = "Priority to give this record.";
|
||||||
|
default = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = port;
|
||||||
|
description = "Port to use when connecting.";
|
||||||
|
};
|
||||||
|
|
||||||
|
host = mkOption {
|
||||||
|
type = str;
|
||||||
|
description = "Host to contact for this service.";
|
||||||
|
example = "my-host.my-domain.com.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
srvRecordPair = domain: protocol: service: record: {
|
||||||
|
"_${service}._${protocol}.${domain}" =
|
||||||
|
"${toString record.priority} ${toString record.weight} ${
|
||||||
|
toString record.port
|
||||||
|
} ${record.host}.";
|
||||||
|
};
|
||||||
|
|
||||||
|
in rec {
|
||||||
|
|
||||||
|
srvRecords = with types; attrsOf (attrsOf (listOf (submodule srvRecordOpts)));
|
||||||
|
|
||||||
|
srvRecordsToBindZone = srvRecords:
|
||||||
|
join-lines (mapAttrsToList makeSrvProtocolRecords srvRecords);
|
||||||
|
|
||||||
|
concatMapAttrs = f: attrs:
|
||||||
|
concatMap (x: x) (mapAttrsToList (key: val: f key val) attrs);
|
||||||
|
|
||||||
|
srvRecordsToPairs = domain: srvRecords:
|
||||||
|
listToAttrs (concatMapAttrs (protocol: services:
|
||||||
|
concatMapAttrs
|
||||||
|
(service: records: map (srvRecordPair domain protocol service) records) services)
|
||||||
|
srvRecords);
|
||||||
|
}
|
32
lib/filesystem.nix
Normal file
32
lib/filesystem.nix
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
with pkgs.lib;
|
||||||
|
let
|
||||||
|
head-or-null = lst: if (lst == []) then null else head lst;
|
||||||
|
is-regular-file = filename: type: type == "regular" || type == "link";
|
||||||
|
regular-files = path: filterAttrs is-regular-file (builtins.readDir path);
|
||||||
|
matches-ext = ext: filename: type: (builtins.match ".+[.]${ext}$" filename) != null;
|
||||||
|
is-nix-file = matches-ext "nix";
|
||||||
|
strip-ext = ext: filename: head-or-null (builtins.match "(.+)[.]${ext}$" filename);
|
||||||
|
get-ext = filename: head-or-null (builtins.match "^.+[.](.+)$" filename);
|
||||||
|
hostname-from-file = filename: strip-ext "nix";
|
||||||
|
nix-files = path:
|
||||||
|
attrNames
|
||||||
|
(filterAttrs is-nix-file
|
||||||
|
(filterAttrs is-regular-file
|
||||||
|
(builtins.readDir path)));
|
||||||
|
|
||||||
|
basename-to-file-map = path: let
|
||||||
|
files = nix-files path;
|
||||||
|
in listToAttrs
|
||||||
|
(map (file:
|
||||||
|
nameValuePair (strip-ext "nix" file)
|
||||||
|
(path + "/${file}"))
|
||||||
|
files);
|
||||||
|
|
||||||
|
import-by-basename = path:
|
||||||
|
mapAttrs (attr: attr-file: import attr-file)
|
||||||
|
(basename-to-file path);
|
||||||
|
in {
|
||||||
|
inherit basename-to-file-map import-by-basename;
|
||||||
|
}
|
78
lib/ip.nix
Normal file
78
lib/ip.nix
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
with pkgs.lib;
|
||||||
|
let
|
||||||
|
pow = x: e: if (e == 0) then 1 else x * (pow x (e - 1));
|
||||||
|
|
||||||
|
generateNBits = n:
|
||||||
|
let
|
||||||
|
helper = n: c:
|
||||||
|
if (c == n) then pow 2 c else (pow 2 c) + (helper n (c + 1));
|
||||||
|
in if (n <= 0) then
|
||||||
|
throw "Can't generate 0 or fewer bits"
|
||||||
|
else
|
||||||
|
helper (n - 1) 0;
|
||||||
|
|
||||||
|
rightPadBits = int: bits: bitOr int (generateNBits bits);
|
||||||
|
|
||||||
|
reverseIpv4 = ip: concatStringsSep "." (reverseList (splitString "." ip));
|
||||||
|
|
||||||
|
intToBinaryList = int:
|
||||||
|
let
|
||||||
|
helper = int: cur:
|
||||||
|
let curExp = pow 2 cur;
|
||||||
|
in if (curExp > int) then
|
||||||
|
[ ]
|
||||||
|
else
|
||||||
|
[ (if ((bitAnd curExp int) > 0) then 1 else 0) ]
|
||||||
|
++ (helper int (cur + 1));
|
||||||
|
in reverseList (helper int 0);
|
||||||
|
|
||||||
|
leftShift = int: n: int * (pow 2 n);
|
||||||
|
|
||||||
|
rightShift = int: n: int / (pow 2 n);
|
||||||
|
|
||||||
|
in rec {
|
||||||
|
|
||||||
|
ipv4ToInt = ip:
|
||||||
|
let els = map toInt (reverseList (splitString "." ip));
|
||||||
|
in foldr (a: b: a + b) 0 (imap0 (i: el: (leftShift el (i * 8))) els);
|
||||||
|
|
||||||
|
intToIpv4 = int:
|
||||||
|
concatStringsSep "."
|
||||||
|
(map (i: toString (bitAnd (rightShift int (i * 8)) 255)) [ 3 2 1 0 ]);
|
||||||
|
|
||||||
|
maskFromV32Network = network:
|
||||||
|
let
|
||||||
|
fullMask = ipv4ToInt "255.255.255.255";
|
||||||
|
insignificantBits = 32 - (getNetworkMask network);
|
||||||
|
in intToIpv4
|
||||||
|
(leftShift (rightShift fullMask insignificantBits) insignificantBits);
|
||||||
|
|
||||||
|
networkMinIp = network: intToIpv4 (1 + (ipv4ToInt (getNetworkBase network)));
|
||||||
|
|
||||||
|
networkMaxIp = network:
|
||||||
|
intToIpv4 (rightPadBits (ipv4ToInt (getNetworkBase network))
|
||||||
|
(32 - (getNetworkMask network)));
|
||||||
|
|
||||||
|
# To avoid broadcast IP...
|
||||||
|
networkMaxButOneIp = network:
|
||||||
|
intToIpv4 ((rightPadBits (ipv4ToInt (getNetworkBase network))
|
||||||
|
(32 - (getNetworkMask network))) - 1);
|
||||||
|
|
||||||
|
ipv4OnNetwork = ip: network:
|
||||||
|
let
|
||||||
|
ip-int = ipv4ToInt ip;
|
||||||
|
net-min = networkMinIp network;
|
||||||
|
net-max = networkMaxIp network;
|
||||||
|
in (ip-int >= networkMinIp) && (ip-int <= networkMaxIp);
|
||||||
|
|
||||||
|
getNetworkMask = network: toInt (elemAt (splitString "/" network) 1);
|
||||||
|
|
||||||
|
getNetworkBase = network:
|
||||||
|
let
|
||||||
|
ip = elemAt (splitString "/" network) 0;
|
||||||
|
insignificantBits = 32 - (getNetworkMask network);
|
||||||
|
in intToIpv4
|
||||||
|
(leftShift (rightShift (ipv4ToInt ip) insignificantBits) insignificantBits);
|
||||||
|
}
|
8
lib/lisp.nix
Normal file
8
lib/lisp.nix
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
with pkgs.lib;
|
||||||
|
rec {
|
||||||
|
gather-dependencies = pkg: unique (pkg.propagatedBuildInputs ++ (concatMap gather-dependencies pkg.propagatedBuildInputs));
|
||||||
|
|
||||||
|
lisp-source-registry = pkg: concatStringsSep ":" (map (p: "${p}//") (gather-dependencies pkg));
|
||||||
|
}
|
53
lib/network.nix
Normal file
53
lib/network.nix
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
with pkgs.lib;
|
||||||
|
let
|
||||||
|
generate-mac-address = hostname: interface: pkgs.stdenv.mkDerivation {
|
||||||
|
name = "mk-mac-${hostname}-${interface}";
|
||||||
|
phases = [ "installPhase" ];
|
||||||
|
installPhase = ''
|
||||||
|
echo ${hostname}-${interface} | sha1sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/' > $out
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# dropUntil = pred: lst: let
|
||||||
|
# drop-until-helper = pred: lst:
|
||||||
|
# if (length lst) == 0 then [] else
|
||||||
|
# if (pred (head lst)) then lst else (drop-until-helper pred (tail lst));
|
||||||
|
# in drop-until-helper pred lst;
|
||||||
|
|
||||||
|
# dropWhile = pred: dropUntil (el: !(pred el));
|
||||||
|
|
||||||
|
# is-whitespace = str: (builtins.match "^[[:space:]]*$" str) != null;
|
||||||
|
|
||||||
|
# stripWhitespace = str: let
|
||||||
|
# lines = builtins.split "\n" str;
|
||||||
|
# lines-front-stripped = dropWhile is-whitespace lines;
|
||||||
|
# lines-rear-stripped = lib.reverseList
|
||||||
|
# (dropWhile is-whitespace
|
||||||
|
# (lib.reverseList lines-front-stripped));
|
||||||
|
# in concatStringsSep "\n" lines-rear-stripped;
|
||||||
|
|
||||||
|
host-ipv4 = config: hostname: let
|
||||||
|
domain = config.fudo.hosts.${hostname}.domain;
|
||||||
|
host-network = config.fudo.networks.${domain};
|
||||||
|
in host-network.hosts.${hostname}.ipv4-address;
|
||||||
|
|
||||||
|
host-ipv6 = config: hostname: let
|
||||||
|
domain = config.fudo.hosts.${hostname}.domain;
|
||||||
|
host-network = config.fudo.networks.${domain};
|
||||||
|
in host-network.hosts.${hostname}.ipv6-address;
|
||||||
|
|
||||||
|
host-ips = config: hostname: let
|
||||||
|
ipv4 = host-ipv4 config hostname;
|
||||||
|
ipv6 = host-ipv6 config hostname;
|
||||||
|
not-null = o: o != null;
|
||||||
|
in filter not-null [ ipv4 ipv6 ];
|
||||||
|
|
||||||
|
in {
|
||||||
|
inherit host-ipv4 host-ipv6 host-ips;
|
||||||
|
|
||||||
|
generate-mac-address = hostname: interface: let
|
||||||
|
pkg = generate-mac-address hostname interface;
|
||||||
|
in removeSuffix "\n" (builtins.readFile "${pkg}");
|
||||||
|
}
|
54
lib/passwd.nix
Normal file
54
lib/passwd.nix
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
|
||||||
|
with pkgs.lib;
|
||||||
|
let
|
||||||
|
hash-ldap-passwd-pkg = name: passwd-file: pkgs.stdenv.mkDerivation {
|
||||||
|
name = "${name}-ldap-passwd";
|
||||||
|
|
||||||
|
phases = [ "installPhase" ];
|
||||||
|
|
||||||
|
buildInputs = with pkgs; [ openldap ];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
slappasswd -T ${passwd-file} > $out
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
hash-ldap-passwd = name: passwd-file:
|
||||||
|
builtins.readFile "${hash-ldap-passwd-pkg name passwd-file}";
|
||||||
|
|
||||||
|
generate-random-passwd = name: length: pkgs.stdenv.mkDerivation {
|
||||||
|
name = "${name}-random-passwd";
|
||||||
|
|
||||||
|
phases = [ "installPhase" ];
|
||||||
|
|
||||||
|
buildInputs = with pkgs; [ pwgen ];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
pwgen --secure --num-passwords=1 ${toString length} > $out
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
generate-stablerandom-passwd = name: { seed, length ? 20, ... }:
|
||||||
|
pkgs.stdenv.mkDerivation {
|
||||||
|
name = "${name}-stablerandom-passwd";
|
||||||
|
|
||||||
|
phases = [ "installPhase" ];
|
||||||
|
|
||||||
|
buildInputs = with pkgs; [ pwgen ];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
echo "${name}-${seed}" > seedfile
|
||||||
|
pwgen --secure --num-passwords=1 -H seedfile ${toString length} > $out
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
in {
|
||||||
|
hash-ldap-passwd = hash-ldap-passwd;
|
||||||
|
|
||||||
|
random-passwd-file = name: length:
|
||||||
|
builtins.toPath "${generate-random-passwd name length}";
|
||||||
|
|
||||||
|
stablerandom-passwd-file = name: seed:
|
||||||
|
builtins.toPath "${generate-stablerandom-passwd name { seed = seed; }}";
|
||||||
|
}
|
14
overlay.nix
Normal file
14
overlay.nix
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
(final: prev: with builtins; {
|
||||||
|
lib = let
|
||||||
|
pkgs = prev;
|
||||||
|
lib = prev.lib;
|
||||||
|
in
|
||||||
|
lib // {
|
||||||
|
ip = import ./lib/ip.nix { inherit pkgs; };
|
||||||
|
dns = import ./lib/dns.nix { inherit pkgs; };
|
||||||
|
passwd = import ./lib/passwd.nix { inherit pkgs; };
|
||||||
|
lisp = import ./lib/lisp.nix { inherit pkgs; };
|
||||||
|
network = import ./lib/network.nix { inherit pkgs; };
|
||||||
|
fs = import ./lib/filesystem.nix { inherit pkgs; };
|
||||||
|
};
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user