GitHub - bqv/rc: Structured system configuration (I moved from NixOS to GuixSD)
{ description = "A highly structured configuration database."; inputs = { priv.url = "hg+ssh://bao@delta/../../srv/hg/nixpriv"; master.url = "github:nixos/nixpkgs/master"; #|. staged.url = "github:nixos/nixpkgs/staging"; #| |-- Nix small.url = "github:nixos/nixpkgs/nixos-unstable-small"; #| |-- pkgs large.url = "github:nixos/nixpkgs/nixos-unstable"; #|' rel2009.url = "github:nixos/nixpkgs/nixos-20.09"; #| Stable rel2003.url = "github:nixos/nixpkgs/nixos-20.03"; #| Old Stable rel1909 = { url = "github:nixos/nixpkgs/nixos-19.09"; flake = false; }; rel1903 = { url = "github:nixos/nixpkgs/nixos-19.03"; flake = false; }; rel1809 = { url = "github:nixos/nixpkgs/nixos-18.09"; flake = false; }; rel1803 = { url = "github:nixos/nixpkgs/18.03"; flake = false; }; pr75800.url = "github:nixos/nixpkgs/517b290754f6a7cc487ce11932a8b750f868324d"; #|\ Pull pr93659.url = "github:ju1m/nixpkgs/security.pass"; #|/ Reqs nix.url = "github:nixos/nix"; #|- Nix nix-ipfs.url = "github:obsidiansystems/nix/ipfs-develop"; #| ^^^IPFS dwarffs.url = "github:edolstra/dwarffs"; #|- Dwarffs dwarffs.inputs.nix.follows = "/nix"; #| dwarffs.inputs.nixpkgs.follows = "/nix/nixpkgs"; #| home.url = "github:nix-community/home-manager"; #|- Home-manager home.inputs.nixpkgs.follows = "/master"; #| naersk.url = "github:nmattia/naersk"; #|- Naersk naersk.inputs.nixpkgs.follows = "/master"; #| guix.url = "github:emiller88/guix"; #|- Guix guix.inputs.nixpkgs.follows = "/master"; #| construct.url = "github:matrix-construct/construct"; #|- Construct construct.inputs.nixpkgs.follows = "/large"; #| hydra.url = "github:nixos/hydra/f64230b45edf07d1"; #|- Hydra emacs.url = "github:nix-community/emacs-overlay"; # Emacs-overlay lisp.url = "github:nix-lisp/lisp-overlay"; # Lisp-overlay funkwhale.url = "github:mmai/funkwhale-flake"; # Funkwhale devshell.url = "github:numtide/devshell"; # Devshell wayland.url = "github:colemickens/nixpkgs-wayland"; #|- Nixpkgs-wayland wayland.inputs.nixpkgs.follows = "/small"; #| agenix.url = "github:ryantm/agenix"; #|- AgeNix agenix.inputs.nixpkgs.follows = "/small"; #| agenix.inputs.flake-utils.follows = "/utils"; #| haskell.url = "github:input-output-hk/haskell.nix"; # Haskell.nix utils.url = "github:numtide/flake-utils"; # Flake-utils hardware.url = "github:nixos/nixos-hardware"; # Nixos-hardware android.url = "github:tadfisher/android-nixpkgs"; # Android SDK xontribs.url = "github:bqv/xontribs"; #|- Xontribs xontribs.inputs = { nixpkgs.follows = "/master"; prompt-bar = { url = "github:anki-code/xontrib-prompt-bar/68b3487e156ed3dce80578ebe552b6afa94c7eb8"; flake = false; }; pipeliner = { url = "github:anki-code/xontrib-pipeliner/daccb6c8a67bbda799dfa2d6d8d829b5e9151c92"; flake = false; }; }; nyxt = { url = "github:atlas-engineer/nyxt"; flake = false; }; # Nyxt processmgmt = { url = "github:svanderburg/nix-processmgmt"; flake = false; }; # ProcessMgmt hnix-overlay = { url = "github:haskell-nix/hnix"; flake = false; }; # Hnix impermanence = { url = "github:nix-community/impermanence"; flake = false; }; # Impermanence mozilla = { url = "github:mozilla/nixpkgs-mozilla"; flake = false; }; # Nixpkgs-mozilla baduk = { url = "github:dustinlacewell/baduk.nix"; flake = false; }; # Baduk snack = { url = "github:nmattia/snack"; flake = false; }; # Snack napalm = { url = "github:nmattia/napalm"; flake = false; }; # Napalm statichask = { url = "github:nh2/static-haskell-nix"; flake = false; }; # Static Haskell #anki-sync = { url = "github:ankicommunity/anki-sync-server/125f7bb1"; flake = false; }; # Anki Server android-nix = { url = "github:tmcl/minimal-android-nix-example"; flake = false; }; conix = { url = "github:thenerd247/conix"; flake = false; }; matrix-nio = { url = "github:poljar/matrix-nio/98f0c244"; flake = false; }; weechat-matrix = { url = "github:poljar/weechat-matrix/d4158416"; flake = false; }; sqlcmdline = { url = "github:sebasmonia/sqlcmdline"; flake = false; }; fish-bass = { url = "github:edc/bass"; flake = false; }; spotify-adblock = { url = "github:x0uid/spotifyadblock"; flake = false; }; bottom = { url = "github:clementtsang/bottom/0.4.5"; flake = false; }; twitterpub = { url = "github:bqv/twitterpub"; flake = false; }; zsh-pure = { url = "github:sindresorhus/pure"; flake = false; }; fsnoop = { url = "github:jeffwalter/fsnoop"; flake = false; }; shflags = { url = "github:kward/shflags"; flake = false; }; git-remote-ipfs = { url = "github:bqv/git-remote-ipfs"; flake = false; }; git-get = { url = "github:grdl/git-get"; flake = false; }; git-pullrequest = { url = "github:google/git-pull-request-mirror"; flake = false; }; dgit = { url = "github:quorumcontrol/dgit/v0.0.14-alpha"; flake = false; }; wld = { url = "github:michaelforney/wld"; flake = false; }; swc = { url = "github:bqv/swc"; flake = false; }; velox = { url = "github:michaelforney/velox"; flake = false; }; st-wl = { url = "github:michaelforney/st"; flake = false; }; dmenu = { url = "github:michaelforney/dmenu"; flake = false; }; emacs-bitwarden = { url = "github:seanfarley/emacs-bitwarden"; flake = false; }; ivy-exwm = { url = "github:pjones/ivy-exwm"; flake = false; }; flycheck-purescript = { url = "github:bsermons/flycheck-purescript"; flake = false; }; eterm-256color = { url = "github:dieggsy/eterm-256color"; flake = false; }; emacsbridge = { url = "github:aardsoft/emacsbridge"; flake = false; }; font-lock-ext = { url = "github:sensorflo/font-lock-ext"; flake = false; }; sln-mode = { url = "github:sensorflo/sln-mode"; flake = false; }; emacs-ffi = { url = "github:tromey/emacs-ffi"; flake = false; }; explain-pause-mode = { url = "github:lastquestion/explain-pause-mode"; flake = false; }; gnome-network-displays = { url = "git+https://gitlab.gnome.org/gnome/gnome-network-displays"; flake = false; }; emacs-webkit = { url = "github:akirakyle/emacs-webkit"; flake = false; }; ini2json = { url = "github:anubisss/ini2json"; flake = false; }; mfs-replace-root = { url = "github:hsanjuan/mfs-replace-root"; flake = false; }; brig = { url = "github:sahib/brig/develop"; flake = false; }; emacs-straight = { url = "github:raxod502/straight.el"; flake = false; }; cloudflare-cli = { url = "github:danielpigott/cloudflare-cli"; flake = false; }; wgvanity = { url = "github:warner/wireguard-vanity-address"; flake = false; }; wold = { url = "github:pauliuszaleckas/wold"; flake = false; }; mactelnet = { url = "github:haakonnessjoen/mac-telnet"; flake = false; }; gh-notify = { url = "github:anticomputer/gh-notify"; flake = false; }; dendrite = { url = "github:matrix-org/dendrite"; flake = false; }; matrix-client = { url = "github:alphapapa/matrix-client.el"; flake = false; }; git-bug = { url = "github:michaelmure/git-bug"; flake = false; }; }; outputs = inputs: with builtins; let allSystems = [ "x86_64-linux" "i686-linux" "aarch64-linux" ]; # Nixos Config config = { allowUnfree = true; android_sdk.accept_license = true; }; patchNixpkgs = basePkgs: let pullReqs = map (meta: { url = meta.url or "https://github.com/nixos/nixpkgs/pull/${toString meta.id}.diff"; name = "nixpkgs-pull-request-${toString meta.id}"; inherit meta; sha256 = meta.hash; }) [ { description = "nixos/anbox: use mainline drivers when available"; id = 102341; hash = "rHKK1id+DHug+4drCfNuPBcGNT3bhQ/bvqYZxf+TVuI="; } { description = "nixos/nat: substitute iptables for compat under nftables"; id = 085462; hash = "vU53uZUhhO6U2RGElAnZqAy3KForw/yyPiU5Rg1hL74="; } # see also #81172 #{ # description = "matrix-dendrite: init at 0.3.9"; # id = 109561; hash = "+lTYEXjiMGh6hsYAWU+y5Cn0nFfzeW0yD84AZKsyHT4="; #} # broken, for now ]; patches = [ #(basePkgs.fetchurl { # name = "grub-use-xkb-config"; # url = "https://github.com/NixOS/nixpkgs/compare/master...mdevlamynck:4a709715e3de83bfc34b880b8044af41a558316e.diff"; # sha256 = "1bkbr2znnwi5yc210vhnj638i1ls1w35sdhh3hfh6fnxlbjlmfbn"; #}) ] ++ map basePkgs.fetchpatch pullReqs; patchedTree = basePkgs.applyPatches { name = "nixpkgs-patched"; src = basePkgs.path; inherit patches; postPatch = '' patch=$(printf '%s\n' ${builtins.concatStringsSep " " (map (p: p.outputHash or (builtins.baseNameOf p)) patches)} | sort | sha256sum | cut -c -7) echo "+patch-$patch" >.version-suffix ''; }; import_nixpkgs = args: import patchedTree ({ inherit (basePkgs) system config overlays; } // args); in import_nixpkgs {} // patchedTree // { lib = (import_nixpkgs {}).lib; legacyPackages = basePkgs.lib.genAttrs allSystems (system: _: import_nixpkgs { inherit system; }); }; patchedPkgs = forAllSystems ({ system, ... }: patchNixpkgs (channels.modules.legacyPackages.${system}) ); channels = with inputs; { patched = lib.mapAttrs (_: nixpkgs: forAllSystems ({ system, ... }: patchNixpkgs nixpkgs.legacyPackages.${system} )) channels; pkgs = small; # For packages modules = master; # For nixos modules lib = master; # For flake-wide lib }; inherit (channels.lib) lib; # this ^ # Packages for nixos configs pkgsForSystem = system: patchNixpkgs (import channels.pkgs rec { inherit system config; overlays = builtins.map (o: o // { value = lib.fix o.__functor; }) [{ # Project each overlay through recursive subsets __functor = self: final: prev: let overlaySets = lib.mapAttrs' (ident: overlay: { name = "with" + (with lib.strings; let ch = stringToCharacters ident; ch' = [(toUpper (head ch))] ++ tail ch; in concatStringsSep "" ch'); value = import prev.path { inherit (prev) system config; overlays = prev.overlays ++ [{ value = _final: _prev: { inherit overlay; pkgsParent = final; } // overlay _final _prev; __functor = x: x.value; name = ident; }]; }; }) inputs.self.overlays; in overlaySets // { inherit overlaySets; overlay = self; overlaysBase = overlays; pkgsParent = prev // { overlays = []; }; appendOverlays = extensions: prev.appendOverlays [{ inherit extensions; value = lib.fold lib.composeExtensions (self: lib.id) extensions; __functor = x: _final: _prev: x.value _final _prev // { pkgsParent = final; }; provides = builtins.listToAttrs (lib.imap0 (n: ext: { name = "_${toString n}"; value = builtins.attrNames (ext {} {}); }) extensions); name = "config"; }]; withPins = import prev.path { inherit (prev) system config; overlays = prev.overlays ++ [{ # Flatten pkgs architecture superficially for convenient maintenance value = _final: _prev: let overlayPkgs = with final; { # hack to prioritize config overlays appendOverlays = exts: (final.appendOverlays exts).withPins; # this is one light breeze away from infrec inherit (withDevshellFlake) devshell; mkDevShell = configuration: (withDevshellFlake.devshell.eval { inherit configuration; }).shell; inherit (withGuixFlake) guix; inherit (withFunkwhaleFlake) funkwhale; inherit (withEmacsFlake.withSelfFlake.withEmacs) emacsPgtkGcc emacsPgtkGccClient emacsPgtkGccPackages; inherit (withCordless) cordless; inherit (withNix) nixFlakes nix-static nix-ipfs; inherit (withInsecureSSL) epsxe; inherit (withHydraFlake.withNix.withHydra) hydra hydra-unstable; inherit (withSelfFlake) velox electronmail; dotnetPackages = dotnetPackages // { inherit (withSelfFlake.dotnetPackages) azure-functions-core-tools; }; haskellPackages = haskellPackages // { inherit (withRel2009.haskellPackages) pointfree-fancy; }; inherit (withSelfFlake) dejavu_nerdfont; emacsPackagesFor = emacs: let inherit (withEmacsFlake) emacsPackagesFor; epkgs = withEmacsFlake.withSelfFlake.withEmacs.emacsPackagesFor emacs; in (emacsPackagesFor emacs).overrideScope' (_: _: { inherit (epkgs) bitwarden ivy-exwm emacs-webkit matrix-client; inherit (epkgs) flycheck-purescript eterm-256color gh-notify; inherit (epkgs) emacsbridge font-lock-ext sln-mode; inherit (epkgs) emacs-ffi explain-pause-mode weechat-patched; }); inherit (withSelfFlake) git-pr-mirror git-remote-ipfs git-get ipfscat; inherit (import path { inherit system; }) notmuch; # ouch inherit (withSelfFlake) guix-ns twitterpub; inherit (withConstructFlake.withConstruct) matrix-construct; inherit (withSelfFlake) yacy; inherit (withRel2003.withSelfFlake) vervis; inherit (withSelfFlake) cfcli dgit fsnoop pure shflags taiwins; inherit (withIni2json) ini2json; inherit (withNix.withDwarffsFlake) dwarffs; inherit (withNaersk) naersk; inherit (withXonsh.withXontribsFlake) xonsh; inherit (withWeechat) weechatScripts; inherit (withRel2003) bcachefs-tools; # to match kernel ver inherit (withNaersk.withSelfFlake) wgvanity wold mactelnet; inherit (withNix.withSelfFlake) nix-bundle; inherit (withSelfFlake) matrix-dendrite; inherit (withGit-bug) git-bug; inherit (withMaster) discord; #inherit (withLarge.withHnix) hnix; #inherit (withLarge.withNyxt) nyxt; plasma5 = plasma5Packages; inherit (libsForQt5) kdeFrameworks; }; in overlaySets // overlayPkgs // { inherit overlaySets overlayPkgs; pkgsParent = final; }; __functor = x: x.value; name = "pins"; }]; }; }; name = "index"; }]; }); forAllSystems = f: lib.genAttrs allSystems (system: f { inherit system; pkgs = (pkgsForSystem system).withPins; inherit (pkgs) lib; }); inputMap = let tryGetValue = res: if res.success then res.value else null; in { n1 = lib.mapAttrsToList lib.nameValuePair inputs; n2 = let s0 = inputs // { self = {}; }; s1 = lib.mapAttrs (k: v: v.inputs) (lib.filterAttrs (k: v: v ? inputs) s0); s2 = lib.mapAttrsRecursiveCond (s: !(s ? outPath)) (n: i: lib.nameValuePair (lib.concatStringsSep "." n) i) s1; in lib.concatMap lib.attrValues (lib.attrValues s2); n3 = lib.const [] (let # broken (but why?) s0 = inputs // { self = {}; }; s1 = lib.mapAttrs (k: v: v.inputs) (lib.filterAttrs (k: v: v ? inputs) s0); s2 = lib.mapAttrsRecursiveCond (s: !(s ? outPath)) (n: i: lib.nameValuePair (lib.concatStringsSep "." n) i) s1; s3 = lib.concatMap lib.attrValues (lib.attrValues s2); s4 = lib.mapAttrs (k: v: v.inputs) (lib.filterAttrs (k: v: v ? inputs) (lib.listToAttrs s3)); s5 = lib.mapAttrsRecursiveCond (s: !(s ? outPath)) (n: i: lib.nameValuePair (lib.concatStringsSep "." n) i) s4; s6 = lib.concatMap lib.attrValues (lib.attrValues s5); in tryGetValue (builtins.tryEval (lib.concatMap lib.attrValues (lib.attrValues s6)))); }; inherit (inputs.self.passthru) secrets; in { nixosConfigurations = builtins.mapAttrs (host: node: { config = node.configuration; }) inputs.self.defaultPackage.x86_64-linux.config.nodes; homeConfigurations = lib.genAttrs (builtins.attrNames inputs.self.nixosConfigurations) (host: inputs.self.nixosConfigurations.${host}.config.home-manager.users) // { epsilon = forAllSystems ({ pkgs, system, ... }: let inherit (pkgs) pkgsStatic nix nix-static termonad-with-packages; flakeModules = import ./modules/home-manager.nix; in inputs.home.lib.homeManagerConfiguration rec { pkgs = pkgsStatic // { nixFlakes = nix; termonad = termonad-with-packages; }; configuration = { _module.args = rec { pkgsPath = pkgs.path; inherit pkgs; nixosConfig = { services.aria2.rpcSecret = ""; networking.hostName = "epsilon"; }; flake = inputs.self; }; nixpkgs = { inherit config system; }; home.packages = with pkgs; [ nixFlakes termonad ]; imports = flakeModules ++ [ ./users/aion.nix ]; }; inherit system; homeDirectory = "/home/${username}"; username = "aion"; } ); }; legacyPackages = forAllSystems ({ pkgs, ... }: pkgs); overlay = import ./pkgs; overlays = let diffTrace = left: right: string: value: if left != right then trace string value else value; silentKeys = [ "config" "system" "path" "stdenv" "lib" ]; channelOverlay = { flake, branch }: { ${flake} = final: prev: let mapWarn = mapAttrs (k: v: if lib.elem k silentKeys then v else if lib.elem k ([ "overlaySets" ] ++ builtins.attrNames prev.overlaySets) then mapWarn v else diffTrace (baseNameOf inputs.${flake}) (baseNameOf prev.path) "pkgs.${k} pinned to nixpkgs/${branch}" v); in mapWarn (import inputs.${flake} { inherit (prev) config system; overlays = [(builtins.head prev.overlays)]; }); }; flakeOverlay = { flake, name }: { ${flake} = final: prev: let mapWarn = mapAttrs (k: v: if lib.elem k silentKeys then v else if lib.elem k ([ "overlaySets" ] ++ builtins.attrNames prev.overlaySets) then mapWarn v else diffTrace (baseNameOf inputs.${flake}) (baseNameOf prev.path) "pkgs.${k} pinned to ${name}" v); in mapWarn inputs.${flake}.legacyPackages.${prev.system}; }; inputsOverlay = builtins.listToAttrs (builtins.filter (v: v != null) (builtins.map (name: if inputs.${name} ? overlay then { name = "${name}Flake"; value = inputs.${name}.overlay; } else null) (builtins.attrNames inputs))); configOverlay = config: final: prev: import prev.path { inherit (prev) system; overlays = [(builtins.head prev.overlays)]; config = prev.config // config; }; in lib.fold (lib.mergeAttrsNoOverride {}) {} [ { broken = configOverlay { allowBroken = true; }; insecureSSL = configOverlay { permittedInsecurePackages = [ "openssl-1.0.2u" ]; }; sources = final: prev: inputs; lib = final: prev: { inherit lib; }; } { mozilla = final: prev: import inputs.mozilla final prev; naersk = final: prev: { naersk = inputs.naersk.lib.${prev.system}; }; snack = final: prev: { snack = final.callPackage "${inputs.snack}/snack-lib"; }; napalm = final: prev: { napalm = final.callPackage inputs.napalm; }; nix = final: prev: let inherit (prev) system; in rec { nixFlakes = nix; nixUnstable = nix; nix = inputs.nix.packages.${system}.nix.overrideAttrs (drv: { patches = (drv.patches or []) ++ [ #(final.fetchpatch { # name = "libfetcher-file.patch"; # url = "https://github.com/nixos/nix/pull/4153.diff"; # sha256 = "JfcswqOG0V5qlolxxYFOpqXJgENC4Adfk4J8r//tgfA="; #}) (final.fetchpatch { name = "log-all-ifd.patch"; url = "https://github.com/NixOS/nix/pull/3494.diff"; sha256 = "OMDCAc3GalFZwdDsaOfcM07e08334yPE+e8KiyVUWYo="; }) ]; passthru = { inherit (inputs.nix.packages.${system}.nix) perl-bindings; }; }); nix-static = inputs.nix.packages.${system}.nix-static or null; nix-ipfs = inputs.nix-ipfs.packages.${system}.nix; #nix-ipfs-static = inputs.nix-ipfs.packages.${system}.nix-static; }; hydra = final: prev: { hydra-unstable = final.hydra; }; construct = final: prev: { riot-web = final.element-web; matrix-construct = (final.callPackage "${inputs.construct}/default.nix" { pkgs = final; }).overrideAttrs (_: { EXTRA_CXXFLAGS = "-mabm -mbmi"; patchPhase = '' sed '/RB_INC_EXECUTION/d' -i ./include/ircd/stdinc.h ''; preAutoreconf = let VERSION_COMMIT_CMD = "git rev-parse --short HEAD"; VERSION_BRANCH_CMD = "git rev-parse --abbrev-ref HEAD"; VERSION_TAG_CMD = "git describe --tags --abbrev=0 --dirty --always --broken"; VERSION_CMD = "git describe --tags --always"; in '' substituteInPlace configure.ac --replace "${VERSION_COMMIT_CMD}" "echo ${inputs.construct.rev}" substituteInPlace configure.ac --replace "${VERSION_BRANCH_CMD}" "echo master" substituteInPlace configure.ac --replace "${VERSION_TAG_CMD}" "echo ${inputs.construct.rev}" substituteInPlace configure.ac --replace "${VERSION_CMD}" "echo ${inputs.construct.rev}" ''; src = builtins.toPath "${inputs.construct}/."; }); }; } #(flakeOverlay { flake = "lg400"; name = "delta/system-400-link"; }) (channelOverlay { flake = "master"; branch = "master"; }) (channelOverlay { flake = "staged"; branch = "staging"; }) (channelOverlay { flake = "small"; branch = "nixos-unstable-small"; }) (channelOverlay { flake = "large"; branch = "nixos-unstable"; }) (channelOverlay { flake = "rel2009"; branch = "nixos-20.09"; }) (channelOverlay { flake = "rel2003"; branch = "nixos-20.03"; }) (channelOverlay { flake = "rel1909"; branch = "nixos-19.09"; }) (channelOverlay { flake = "rel1903"; branch = "nixos-19.03"; }) (channelOverlay { flake = "rel1809"; branch = "nixos-18.09"; }) (channelOverlay { flake = "rel1803"; branch = "nixos-18.03"; }) (listToAttrs (map (name: { name = lib.removeSuffix ".nix" name; value = import (./overlays + "/${name}") inputs; }) (builtins.filter (file: lib.hasSuffix ".nix" file || file == "default.nix") (attrNames (readDir ./overlays))))) inputsOverlay ]; packages = forAllSystems ({ pkgs, ... }: lib.filterAttrs (_: p: (lib.isDerivation p) && (p.meta.broken or null) != true ) pkgs.overlayPkgs); defaultPackage = forAllSystems ({ pkgs, system, ... }: let deployment = import ./deploy { nixpkgs = channels.patched.modules.${system}; deploySystem = system; # By habit, system is deployer, platform is target } ({ config, lib, ... }: let inherit (config) nodes; in { defaults = { name, config, ... }: let evalConfig = import "${patchNixpkgs pkgs}/nixos/lib/eval-config.nix"; getPlatform = with lib.modules; { modules, specialArgs, ... }: let args = { config = null; options = null; inherit lib; } // specialArgs; in (mergeModules [] (collectModules "" modules args)).matchedOptions.platform.value; nixos = with inputs.self.nixosModules; let base = hosts.${system}.${name} or null; platform = getPlatform base; in if base == null then hosts.${system}.image else hosts.${platform}.${name}; vmsystem = { modules, pkgs, specialArgs, ... }: { system.build.vm = (evalConfig { inherit specialArgs; inherit (pkgs) system; modules = modules ++ [ (import "${channels.modules}/nixos/modules/virtualisation/qemu-vm.nix") ]; }).config.system.build.toplevel; }; linkage = { config, pkgs, ... }: let systems = builtins.mapAttrs (host: _: with inputs.self; let platform = getPlatform nixosModules.hosts.${system}.${host}; in defaultPackage.${platform}.config.nodes.${host}.configuration ) nodes; in { options.system.linkOtherSystems = lib.mkOption { type = lib.types.bool; default = true; description = "Whether to link other flake nodes to the system derivation."; }; # Link raw hosts on each host (non-recursively) config.system = { extraSystemBuilderCmds = lib.mkIf config.system.linkOtherSystems ('' mkdir -p $out/flake/hosts # Link other hosts (nonrecursively) ${lib.concatMapStringsSep "\n" ({ name, value }: '' ln -s '${value.system.build.toplevel}' "$out/flake/hosts/${name}" '') (lib.mapAttrsToList lib.nameValuePair systems)} # Link host containers ${lib.concatMapStringsSep "\n" (host@{ name, value }: '' mkdir -p $out/flake/container/${name} ${lib.concatMapStringsSep "\n" (container@{ name, value }: '' ln -s '${value.config.system.build.toplevel}' "$out/flake/container/${host.name}/${name}" '') (lib.mapAttrsToList lib.nameValuePair value.containers)} '') (lib.mapAttrsToList lib.nameValuePair systems)} ''); }; }; ifdroots = { config, pkgs, ... }: { config.system.extraDependencies = [ channels.patched.modules.${system} ]; }; in { options = { configuration = lib.mkOption { type = lib.types.submoduleWith { inherit (nixos) modules; }; }; }; config = { host = "root@${nixos.specialArgs.hosts.wireguard.ipv4.${name}}"; configuration = { imports = [ ifdroots #linkage # TODO: figure out how to make this work vmsystem ]; config = { secrets.baseDirectory = "/var/lib/secrets"; _module.args = nixos.specialArgs; }; }; # Filter out "added to list of known hosts" spam from output deployScriptPhases.filter-known-hosts = lib.dag.entryBefore ["copy-closure"] '' # Remove known hosts spam pipeline -w { ${pkgs.gnugrep}/bin/grep --line-buffered -v "list of known hosts" } fdswap 1 2 pipeline -w { ${pkgs.gnugrep}/bin/grep --line-buffered -v "list of known hosts" } fdswap 2 1 ''; # Git tag all systems and deployments deployScriptPhases.git-tag = let inherit (config.configuration) system; in lib.dag.entryAfter ["trigger-switch"] '' foreground { backtick -i -n systemstorepath { basename "${system.build.toplevel.outPath}" } importas -i systemstorepath systemstorepath define systempath "nix/store/''${systemstorepath}" importas -i id ID define systemnum "${name}/system-''${id}" fdswap 1 2 foreground { echo Tagging $systempath } foreground { ${pkgs.git}/bin/git tag $systempath "${system.configurationRevision}" } foreground { echo Tagging $systemnum } foreground { ${pkgs.git}/bin/git tag $systemnum "${system.configurationRevision}" } exit 0 } ''; privilegeEscalationCommand = []; # already root successTimeout = lib.mkDefault 120; switchTimeout = lib.mkDefault 120; ignoreFailingSystemdUnits = true; systemSwitcherDir = "/nix/node/"; dirty = ! (inputs.self ? rev); }; }; nodes = let hosts = builtins.attrNames inputs.self.nixosModules.hosts.${system}; in (lib.genAttrs hosts (_: {})) // { delta.hasFastConnection = true; # it's local! delta.rollbackOnFailure = false; # accidentally rebooting this gets annoying image.enabled = false; zeta.panicAction = "false"; # we shouldn't reboot this carelessly zeta.hasFastConnection = true; zeta.successTimeout = 240; # Zeta seems very slow... zeta.switchTimeout = 240; # maybe due to wireguard reloading? }; ssh.access = let collapse = attrs: lib.fold (a: b: a // b) {} (builtins.concatMap builtins.attrValues (builtins.attrValues (lib.mapAttrs (u: lib.mapAttrs (t: v: { "${u}-${t}" = v; })) attrs))); in lib.mkIf false { delta = { hostKeys = lib.genAttrs [ "rsa" "ecdsa" "ed25519" "dsa" ] (type: lib.removeSuffix "\n" (builtins.readFile "${secrets.keyDir}/deltassh/ssh_host_${type}_key.pub") ); keys = collapse { bao = { rsa = { publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAEAQC/Ca5MUwmHMZt4sH/xLAq20X12xDj2bSqg88thxWLvpqnLpLEJmpasaHKRRh9O6E/NE0Zsn45dsTuvB9/otoDGdstYX2VZyi3UBIWp3BjxdbvmMrbhvpihiZl6rAFXU45/LM/4PvraLic2ZXuOGFqoLcnKDAvCATJsQfUGcEnM0YJVcFLjA4sSPHarSoSHFxZ90RXVmW8m5sfNCsMMo3jCMgE49zlWhcrKfp/FfpIlKMytTDdb+JE0JIsR+28oxJtL63wTbO9p2zFS8geNPVMfj8+Ge4bb0YWroBNGaMo3cHcdtquWWvTzZxWJu+AiSlZIWcP6aOhOoRiFrCWIYBP91dtARm2+OXIpUNAT+yPR+YQ4BAUNxYyBZO3hTH47cq2dC4NAQVcjuUb5VLoRAOAl+DzHSj7FNFGo49CxE/eDlhoXzmgP28N5tDktZYYstrr4j/KAZPYzGW8tB6s/VhhiCGFgZQXq2irH2UtU3Amr7cw0Wiiuyoe4x67dUB+sy3yT5jle/dLe0U9qgAiFTptix1QpjDaT8dFYQsi0kzXlSUEB05pmnCjM2n9eksdtF5kggLDNQ3VKH+LRN/rd5JKJsMJn9Lxr9nO3x+x+fhBurthumrDB2S3oqEOWQDxJ+JaZi5mshzZ2bB4lSXGB5aYjaBSk49EmlrNo8dUUXpZFT9mePx8BIC73XtoEsFgH9kpvHqHxOaBBO3wsxWekbS5bzi2KkBWxMAHq/fVV37iNaDHnldEn9DGDIQb6fQnjLkWbwNRBsdZxqfJGBqVpUNVbsS4BOFoa7yxnCZ6OgxzXpScoyeTxgM1nDALRnwee2d+3GrKHzE23Db6tIwUUeHEkcNwY2L6MW6Z2Onv2T9+V0IITe16EV+TcTc04DQ2XtnVEqUfqK5NZX0wpDuO0Bw0cJrbxJy3lk1PbnUnP/slfRgB4yOvkA0zRrer27EiyRsQe9QSfcmcpIK66+UncYqTFZ/qJFBdupn2ruYaDfCq/G8HyNsm7fXJLgsnGrAfEqUlBabbmLBdSvPqWpkMCjmmX7tMvTTWV5/IdFo0NVPQ7VBdZrRoPbYOQetZqr6S1tkKvpISrBKMRXXgaCcegnqWKqomZsFWcTnhyV0vCJM16IaNp++2rqw426hvpm2F+hhUzDa7CP/+HKvo0ucwC1u24CX75eT/pEP7WuINNMEx1y+/VxyeWscAK89NYa2YGBzqBEJ9+0QVFNYye/baaNn1dNEuPk49bkM7g3LTp8ae+J+5dAb3QsKMxL/bssFzAc+7M5+LFQDFpWtxkzkB5+X9HzMtVbsgDk9CDgn56OfkpzjFR7PeDUcKeFWeccWHRMOyXVX1daoUTeDIpESID2FnR bao@delta"; hasAccessTo.zeta.bao = true; }; ecdsa = { publicKey = "ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAEY1DRzmt77NPp64/DEkuPwdOd5yzchRBDmZJBvu+ip42tV3c1FdDNs/7ictpROqfm/Nkh6D/mmbQV+MI2Aa1H66AC+8/wMJl/fkfSEeX6Z6thVM7oC6a2kXuJjlZNF5wQngTP5AWydEFacuZduW+Ir2++IVFyjtIVOR/lumtdzuvi5/A== bao@delta"; hasAccessTo.zeta.bao = true; }; ed25519 = { publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOvcvk1nLYImKqjhL8HdAb1sM2vXcEGu+rMZJ8XIG4H7 bao@delta"; hasAccessTo.zeta.bao = true; }; gpg = { publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDX40Dm37dDdxreqQxQ+bd9c9mNXfSqC5k3Rrf4iQHy7OdzsQD0qngHFdcq2dG0d4sYeHeyJGYHPbtwNYb0AED/zDVgfuiW6+xYSW+apg5Hc2EfktxxmVbRXqq8SoWUP9CtwJLIw0Q4vBiWBKT367VlXnWJ5ob8bwhfRlK7Sk4595Mm2Wp98sgMXdcQbFc+nQ+TYyYnkIYv63g3Lyxi8NQKWGwh2zspGl2rbDVJrtr196bSd3leZhD/v+YquqO2Saf9DZCmDMJmw4rUWZ84rkUZ0lB5eSICfQZAl5UxpnorWutLDxjuFOc/7H6iSGFRNjQ/fM8Jh2dxDm3XWxWp+E+F9q5Q9bsziL+zwxkAL2SvWULhmAALbLMqEC2qkPU9ccqRRBteGIRt/ix+J87lImz6Zp2UqSYFe2GpwP+NtMB8TyMaDUOni+L/NGw7o/EvAm7K7tH6OJW5vSC7e8P5lLc825SHlJdfn5L2aAfD+vr8rZv4L9uy1isJTMvVDRp4CLHwsw+xn4XfnfvsNtWNyVoAfi7NN3+jtCGlpNckj+5ylaQcgGuFbQUJ7jhsUGDYRSvX3wWaRBD94Pi+XS1jUTLyRmIbgcbiSeyzx2fZm1saQAb3MSF9yf0ibCJlTJ3JMLfqlDYP6Yl64bQ67T8QcYvDSUurqh+T6AN83SF6aHT3HQ== gpg"; hasAccessTo.zeta.bao = true; }; }; }; }; zeta = { hostKeys = lib.genAttrs [ "rsa" "ecdsa" "ed25519" "dsa" ] (type: lib.removeSuffix "\n" (builtins.readFile "${secrets.keyDir}/zetassh/ssh_host_${type}_key.pub") ); keys = collapse { }; }; }; vpn.networks = { # TBC }; }); in pkgs.runCommandLocal "deployment" { outputs = [ "out" "systems" ] ++ builtins.attrNames ( lib.filterAttrs (_: n: n.enabled) deployment.config.nodes ); passthru = deployment; } '' mkdir -p $(dirname $out) ln -s ${deployment.config.deployScript} $out ${lib.concatStringsSep "" (lib.mapAttrsToList (host: node: if node.enabled then '' ln -s ${node.nodeDeployScript} ''$${host} mkdir -p $systems ln -s ${node.configuration.system.build.toplevel} $systems/${host} '' else "") deployment.config.nodes)} ''); apps = forAllSystems ({ pkgs, system, ... }: { epsilon = rec { type = "app"; inherit (inputs.self.homeConfigurations.epsilon.${system}) activationPackage; program = (pkgs.writeShellScript "reconfigure-epsilon" '' echo Deploying ${activationPackage} export HOST=epsilon export NIX_SSHOPTS="-o StrictHostKeyChecking=no" nix copy --to ssh://$HOST '${activationPackage}' \ && ssh $NIX_SSHOPTS $HOST -t \ sh -c ". $HOME/.nix-profile/etc/profile.d/nix.sh && \ exec ${activationPackage}/activate $@" '').outPath; }; zeta = rec { type = "app"; inherit (inputs.self.nixosConfigurations.zeta.config.system.build) toplevel; program = (pkgs.writeShellScript "test-zeta" '' echo Deploying ${toplevel} export HOST=${inputs.self.passthru.secrets.hosts.wireguard.ipv4.zeta} export NIX_SSHOPTS="-o StrictHostKeyChecking=no" nix copy --to ssh://root@$HOST '${toplevel}' \ && ssh $NIX_SSHOPTS root@$HOST -t \ exec ${toplevel}/bin/switch-to-configuration test $@ '').outPath; }; delta = rec { type = "app"; inherit (inputs.self.nixosConfigurations.delta.config.system.build) toplevel; program = (pkgs.writeShellScript "test-delta" '' echo Deploying ${toplevel} exec doas ${toplevel}/bin/switch-to-configuration test $@ '').outPath; bao = rec { type = "app"; inherit (inputs.self.homeConfigurations.delta.bao.home) activationPackage; program = (pkgs.writeShellScript "test-delta-bao" '' echo Deploying ${activationPackage} exec ${activationPackage}/activate $@ '').outPath; }; }; }); defaultApp = forAllSystems ({ system, ... }: inputs.self.apps.${system}.delta); nixosModules = let mergeAll = lib.fold lib.recursiveUpdate {}; pathsToAttrs = map (file: let cleanFile = lib.removeSuffix ".nix" (lib.removePrefix "${toString ./.}/" (toString file)); in lib.setAttrByPath (lib.splitString "/" cleanFile) (import file) ); nixFilesOf = builtins.filter (lib.hasSuffix ".nix"); moduleList = (import ./modules/nixos.nix) ++ (import ./modules/home-manager.nix); profilesList = (lib.filesystem.listFilesRecursive ./profiles) ++ (builtins.filter (f: ! builtins.hasAttr (builtins.baseNameOf f) (builtins.readDir ./users)) (lib.filesystem.listFilesRecursive ./users)); in (mergeAll (pathsToAttrs (nixFilesOf moduleList))) // (mergeAll (pathsToAttrs (nixFilesOf profilesList))) // { hosts = forAllSystems ({ pkgs, system, ... }: (let usr = { tools = import ./lib/utils.nix { inherit lib; }; elisp = import ./lib/elisp.nix { inherit lib; pkgs = channels.lib.legacyPackages.${system}; }; dag = let dagLib = import ./lib/dag.nix lib lib; in dagLib.dag // { inherit (dagLib) types; }; units = { kilobytes = b: b * 1024; megabytes = k: k * 1024; gigabytes = m: m * 1024; }; inherit (inputs.self.passthru) secrets; }; modulesFor = hostName: appendModules: let specialArgs = { inherit usr; flake = inputs.self; inherit (secrets) hosts domains; modules = modules ++ [ { _module.args = specialArgs; } ]; inherit extraModules; }; # External modules inherit (inputs.home.nixosModules) home-manager; inherit (inputs.dwarffs.nixosModules) dwarffs; inherit (inputs.guix.nixosModules) guix; inherit (inputs.construct.nixosModules) matrix-construct; inherit (inputs.agenix.nixosModules) age; hydra = "${inputs.hydra}/hydra-module.nix"; funkwhale = inputs.funkwhale.nixosModule; # Some common basic stuff core = ./profiles/core.nix; # The flake-ier common basic stuff global = { environment.pathsToLink = [ "/share/bios" ]; documentation.nixos.extraModuleSources = [./.] ++ lib.mapAttrsToList (_: x: x.outPath) inputs; nix.package = lib.mkDefault pkgs.nixFlakes; nix.registry = lib.mapAttrs (id: flake: { inherit flake; from = { inherit id; type = "indirect"; }; }) (inputs // { nixpkgs = inputs.master; }); nix.nixPath = lib.mapAttrsToList (k: v: "${k}=${toString v}") { nixpkgs = "${channels.pkgs}/"; nixos = "${inputs.self}/"; home-manager = "${inputs.home}/"; self = "/run/current-system/flake/input/self/"; flake = "/srv/git/github.com/bqv/nixrc"; }; system.configurationRevision = inputs.self.rev or "dirty"; system.nixos.versionSuffix = let inherit (inputs) self; date = lib.substring 0 8 (self.lastModifiedDate or "19700101"); rev = self.shortRev or "dirty"; in lib.mkForce ".${date}.${rev}"; system.extraSystemBuilderCmds = ('' mkdir -p $out/flake/input # Link first-class inputs ${lib.concatMapStringsSep "\n" ({ name, value }: '' ln -s '${value}' "$out/flake/input/${name}" '') inputMap.n1} # Link second-class inputs ${(lib.concatMapStringsSep "\n" ({ name, value }: '' ln -s '${value}' "$out/flake/input/${name}" '') inputMap.n2)} # Link third-class inputs (skipped) ${lib.concatMapStringsSep "\n" ({ name, value }: '' ln -s '${value}' "$out/flake/input/${name}" '') inputMap.n3} ''); system.activationScripts.etcnixos = '' rm -f /etc/nixos && \ ln -sfn /run/current-system/flake/input/self /etc/nixos || \ true ''; }; # Host-specific basic stuff host = { environment.etc."machine-id".text = builtins.hashString "md5" hostName; networking = { inherit hostName; }; }; # Nixos eval settings nixpkgs = { config, ... }: { config.nixpkgs = { inherit pkgs; system = config.platform; }; }; # Amend home-manager (inject modules, set common stuff) home = { config, ... }: { options.home-manager.users = lib.mkOption { type = with lib.types; attrsOf (submoduleWith { inherit specialArgs; modules = let flakeModules = import ./modules/home-manager.nix; nixProfile = { lib, ... }: { home.activation.disableNixEnv = lib.hm.dag.entryBefore ["installPackages"] '' alias nix-env=true ''; home.activation.installPackages = lib.mapAttrs (k: v: lib.mkForce v) (lib.hm.dag.entryAnywhere "true"); }; baduk = { imports = [ (import inputs.baduk) ]; #baduk.sabaki.enable = false; # needs flake-ification patches baduk.sabaki.engines = lib.mkDefault []; #baduk.gnugo.enable = false; #baduk.katago.enable = false; #baduk.leela-zero.enable = false; }; impermanence = import "${inputs.impermanence}/home-manager.nix"; in flakeModules ++ [ nixProfile baduk ]; }); }; config.home-manager = { useUserPackages = true; useGlobalPkgs = true; verbose = true; }; }; # Hack in the gnupg secrets module (fix docbook) gnupg = import "${inputs.pr93659}/nixos/modules/security/gnupg.nix"; # Plug in the impermanence module (not a flake :<) impermanence = import "${inputs.impermanence}/nixos.nix"; # Set up any other pull request modules iwd = { config, ... }: let iwdModule = "services/networking/iwd.nix"; in { disabledModules = [ iwdModule ]; imports = [ (import "${inputs.pr75800}/nixos/modules/${iwdModule}" { inherit config pkgs; lib = let iwdLib = import "${inputs.pr75800}/lib/default.nix"; in lib // { types = { inherit (iwdLib.types) fixedLengthString lengthCheckedString; } // lib.types; }; }) ]; }; # Our modules flakeModules = import ./modules/nixos.nix; # Actual host config configuration = import "${toString ./hosts}/${hostName}"; # Modules to propagate to containers extraModules = [ core global ]; # Final modules set modules = flakeModules ++ extraModules ++ [ home nixpkgs iwd gnupg home-manager dwarffs matrix-construct hydra impermanence age guix funkwhale ]; in { inherit system specialArgs; modules = modules ++ [ host configuration ] ++ appendModules; }; forEachHost = do: usr.tools.recImport { # Build a nixos system for each dir in ./hosts using modulesFor dir = ./hosts; _import = do; }; in forEachHost (host: let pkgs = channels.modules.legacyPackages.${system}; in modulesFor host []))); }; devShell = forAllSystems ({ system, ... }: let pkgs = import channels.pkgs { inherit system; overlays = [ inputs.devshell.overlay ]; }; mkDevShell = configuration: (pkgs.devshell.eval { inherit configuration; }).shell; in mkDevShell { packages = with pkgs; let git-crypt = pkgs.git-crypt.overrideAttrs (attrs: rec { worktreePatch = fetchurl { name = "support-worktree-simple-version.patch"; url = "https://github.com/AGWA/git-crypt/files/2771938/git-crypt-support-worktree-simple-version-patch.txt"; sha256 = "1k477m6g3zjdarjr38lndh0kpgkp0yi8lg2iqdispfd4c85krrax"; # date = 2021-01-29T23:45:21+0000; }; patches = [ worktreePatch ]; }); in [ git git-crypt git-secrets nixfmt ]; env = with pkgs; let nixConf = '' ${lib.optionalString (builtins.pathExists /etc/nix/nix.conf) (builtins.readFile /etc/nix/nix.conf)} experimental-features = nix-command flakes ca-references print-build-logs = true access-tokens = "github.com=${secrets.git.github.oauth-token}" ''; in [{ name = "NIX_CONF_DIR"; value = "${linkFarm "nix-conf-dir" ( [ { name = "nix.conf"; path = writeText "flakes-nix.conf" nixConf; } { name = "registry.json"; path = /etc/nix/registry.json; } { name = "machines"; path = /etc/nix/machines; } ] )}"; }]; commands = [{ name = "forecast"; category = "automation"; command = '' export ARGS="$*" REPO=$( nix build --impure --json --no-link '.#lib.forecast' \ | jq '.[] | .outputs.out' -r \ ) git fetch $REPO substrate:substrate git branch -f substrate FETCH_HEAD ''; }]; motd = ""; } ); passthru = rec { inherit inputs channels config allSystems inputMap patchNixpkgs; patchedPkgs = forAllSystems ({ system, ... }: patchNixpkgs (channels.modules.legacyPackages.${system}) ); #$ git config secrets.providers "nix eval --raw .#passthru.textFilter" textFilter = with inputs.priv.lib.textFilter { inherit lib; }; lines; inherit (inputs.priv.lib) secrets; forecast = let inherit (channels.pkgs.legacyPackages.${builtins.currentSystem}) pkgs; date = builtins.readFile (pkgs.runCommandLocal "forecast-name" { nonce = builtins.currentTime; } "date -Iminutes | tr 'T\\-:' '---' | cut -d+ -f1 | tr -d '\n' > $out"); in pkgs.runCommandLocal "forecast-${date}" rec { repo = builtins.getEnv "PWD"; inputs = builtins.getEnv "ARGS"; buildInputs = [ pkgs.git pkgs.nixUnstable pkgs.cacert ]; PAGER = "cat"; GIT_AUTHOR_NAME = "ci"; GIT_AUTHOR_EMAIL = "nix@system"; GIT_COMMITTER_NAME = "systemd"; GIT_COMMITTER_EMAIL = "timer@service"; __noChroot = true; } '' git clone $repo $out export NIX_REMOTE=local?real=$PWD/nix/store\&store=/nix/store export NIX_STATE_DIR=$PWD/nix/var NIX_LOG_DIR=$PWD/nix/var/log export HOME=$PWD cd $out git switch -c substrate live git commit-tree -m "merge: live" -p HEAD -p origin/live origin/live: git reset --hard origin/live for INPUT in $inputs; do nix flake update --update-input $INPUT \ --experimental-features "nix-command flakes ca-references" git commit -m "flake(lock): autoupdate $INPUT" flake.lock done ''; }; hydraJobs = rec { deployment = forAllSystems ({ system, ... }: inputs.self.defaultPackage.${system} ); }; }; }