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