diff --git a/configs/flake-parts/default.nix b/configs/flake-parts/default.nix new file mode 100644 index 00000000..94cce650 --- /dev/null +++ b/configs/flake-parts/default.nix @@ -0,0 +1,77 @@ +{ inputs, lib, ... }: { + imports = [ + ./dev.nix + ./packages.nix + ./templates.nix + + # The environment configurations. + ./home-manager.nix + ./nixos.nix + ]; + + _module.args = { + # This will be shared among NixOS and home-manager configurations. + defaultNixConf = { config, lib, pkgs, ... }: { + # I want to capture the usual flakes to its exact version so we're + # making them available to our system. This will also prevent the + # annoying downloads since it always get the latest revision. + nix.registry = + lib.mapAttrs' + (name: flake: + let + name' = if (name == "self") then "config" else name; + in + lib.nameValuePair name' { inherit flake; }) + inputs; + + # Set the package for generating the configuration. + nix.package = lib.mkDefault pkgs.nixStable; + + # Set the configurations for the package manager. + nix.settings = { + # Set several binary caches. + substituters = [ + "https://nix-community.cachix.org" + "https://foo-dogsquared.cachix.org" + ]; + trusted-public-keys = [ + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + "foo-dogsquared.cachix.org-1:/2fmqn/gLGvCs5EDeQmqwtus02TUmGy0ZlAEXqRE70E=" + ]; + + # Sane config for the package manager. + # TODO: Remove this after nix-command and flakes has been considered + # stable. + # + # Since we're using flakes to make this possible, we need it. Plus, the + # UX of Nix CLI is becoming closer to Guix's which is a nice bonus. + experimental-features = [ "nix-command" "flakes" "repl-flake" ]; + auto-optimise-store = lib.mkDefault true; + }; + + # Stallman-senpai will be disappointed. + nixpkgs.config.allowUnfree = true; + + # Extend nixpkgs with our overlays except for the NixOS-focused modules + # here. + nixpkgs.overlays = lib.attrValues inputs.self.overlays; + }; + + defaultSystem = "x86_64-linux"; + defaultOverlays = lib.attrValues inputs.self.overlays; + defaultExtraArgs = { + inherit (inputs) nix-colors; + }; + }; + + perSystem = { lib, system, ... }: { + _module.args = { + pkgs = import inputs.nixpkgs { + inherit system; + overlays = lib.attrValues inputs.self.overlays ++ [ + inputs.nur.overlay + ]; + }; + }; + }; +} diff --git a/configs/flake-parts/dev.nix b/configs/flake-parts/dev.nix new file mode 100644 index 00000000..ab20fb8a --- /dev/null +++ b/configs/flake-parts/dev.nix @@ -0,0 +1,38 @@ +# All of the development-related shtick for this project is over here. +{ inputs, ... }: { + flake.lib = import ../../lib { lib = inputs.nixpkgs.lib; }; + + perSystem = { config, lib, pkgs, ... }: { + apps = { + run-workflow-with-vm = + let + inputsArgs = lib.mapAttrsToList + (name: source: + let + name' = if (name == "self") then "config" else name; + in + "'${name'}=${source}'") + inputs; + script = pkgs.callPackage ../../apps/run-workflow-with-vm { + inputs = inputsArgs; + }; + in + { + type = "app"; + program = "${script}/bin/run-workflow-with-vm"; + }; + }; + + # No amount of formatters will make this codebase nicer but it sure does + # feel like it does. + formatter = pkgs.treefmt; + + # My several development shells for usual type of projects. This is much + # more preferable than installing all of the packages at the system + # configuration (or even home environment). + devShells = import ../../shells { inherit pkgs; } // { + default = import ../../shell.nix { inherit pkgs; }; + docs = import ../../docs/shell.nix { inherit pkgs; }; + }; + }; +} diff --git a/configs/flake-parts/home-manager.nix b/configs/flake-parts/home-manager.nix new file mode 100644 index 00000000..fc6ae360 --- /dev/null +++ b/configs/flake-parts/home-manager.nix @@ -0,0 +1,151 @@ +{ inputs +, lib + +, defaultSystem +, defaultExtraArgs +, defaultNixConf + +, ... +}: + +let + homeManagerConfigs = import ../../setups/home-manager.nix { inherit lib inputs; }; + + # The default config for our home-manager configurations. This is also to + # be used for sharing modules among home-manager users from NixOS + # configurations with `nixpkgs.useGlobalPkgs` set to `true` so avoid + # setting nixpkgs-related options here. + defaultHomeManagerConfig = + { pkgs, config, lib, ... }: { + imports = + # Import our own custom modules from here.. + import ../../modules/home-manager { inherit lib; isInternal = true; } + + # ...plus a bunch of third-party modules. + ++ [ + inputs.nur.hmModules.nur + inputs.sops-nix.homeManagerModules.sops + inputs.nix-index-database.hmModules.nix-index + inputs.nix-colors.homeManagerModules.default + ]; + + # Set some extra, yeah? + _module.args = defaultExtraArgs; + + # Hardcoding this is not really great especially if you consider using + # other locales but its default values are already hardcoded so what + # the hell. For other users, they would have to do set these manually. + xdg.userDirs = + let + # The home directory-related options should be already taken care + # of at this point. It is an ABSOLUTE MUST that it is set properly + # since other parts of the home-manager config relies on it being + # set properly. + # + # Here are some of the common cases for setting the home directory + # options. + # + # * For exporting home-manager configurations, this is done in this + # flake definition. + # * For NixOS configs, this is done automatically by the + # home-manager NixOS module. + # * Otherwise, you'll have to manually set them. + appendToHomeDir = path: "${config.home.homeDirectory}/${path}"; + in + { + desktop = appendToHomeDir "Desktop"; + documents = appendToHomeDir "Documents"; + download = appendToHomeDir "Downloads"; + music = appendToHomeDir "Music"; + pictures = appendToHomeDir "Pictures"; + publicShare = appendToHomeDir "Public"; + templates = appendToHomeDir "Templates"; + videos = appendToHomeDir "Videos"; + }; + + programs.home-manager.enable = true; + + manual = lib.mkDefault { + html.enable = true; + json.enable = true; + manpages.enable = true; + }; + + home.stateVersion = lib.mkDefault "23.11"; + }; + + # A function that generates a home-manager module from a given user + # metadata. + userSpecificModule = user: metadata: + let + name = metadata.username or metadata._name or user; + modules = metadata.modules or [ ]; + in + { lib, pkgs, config, ... }: { + imports = modules ++ [ + defaultHomeManagerConfig + defaultNixConf + ../home-manager/${name} + ]; + + # Don't create the user directories since they are assumed to + # be already created by a pre-installed system (which should + # already handle them). + xdg.userDirs.createDirectories = lib.mkForce false; + + # Setting the homely options. + home.username = lib.mkForce name; + home.homeDirectory = lib.mkForce (metadata.home-directory or "/home/${config.home.username}"); + + programs.home-manager.enable = lib.mkForce true; + targets.genericLinux.enable = true; + }; +in +{ + flake = { + # Extending home-manager with my custom modules, if anyone cares. + homeModules.default = import ../../modules/home-manager { inherit lib; }; + + # Put them home-manager configurations. + homeConfigurations = + let + inherit (import ../../lib/extras/flake-helpers.nix { inherit lib inputs; }) mkHome listImagesWithSystems; + in + lib.mapAttrs + (user: metadata: + mkHome { + pkgs = import inputs.${metadata.nixpkgs-channel or "nixpkgs"} { + system = metadata._system; + }; + extraModules = [ (userSpecificModule user metadata) ]; + home-manager-channel = metadata.home-manager-channel or "home-manager"; + }) + (listImagesWithSystems homeManagerConfigs); + + # Include these as part of the deploy-rs nodes because why not. + deploy.nodes = + lib.mapAttrs' + (name: value: + let + metadata = homeManagerConfigs.${name}; + username = metadata.deploy.username or name; + in + lib.nameValuePair "home-manager-${name}" { + hostname = metadata.deploy.hostname or name; + autoRollback = metadata.deploy.auto-rollback or true; + magicRollback = metadata.deploy.magic-rollback or true; + fastConnection = metadata.deploy.fast-connection or true; + remoteBuild = metadata.deploy.remote-build or false; + profiles.home = { + sshUser = metadata.deploy.ssh-user or username; + user = metadata.deploy.user or username; + path = inputs.deploy.lib.${metadata.system or defaultSystem}.activate.home-manager value; + }; + }) + inputs.self.homeConfigurations; + }; + + _module.args = { + inherit homeManagerConfigs defaultHomeManagerConfig; + }; +} diff --git a/configs/flake-parts/nixos.nix b/configs/flake-parts/nixos.nix new file mode 100644 index 00000000..3dd31e7a --- /dev/null +++ b/configs/flake-parts/nixos.nix @@ -0,0 +1,180 @@ +{ inputs +, lib + +, defaultSystem +, defaultExtraArgs +, defaultNixConf +, defaultHomeManagerConfig + +, ... +}: + +let + nixosConfigs = import ../../setups/nixos.nix { inherit lib inputs; }; + + # A function that generates a NixOS module setting up the baseline + # configuration for this project (or at least for this subset of NixOS + # configurations). + hostSpecificModule = host: metadata: + let + modules = metadata.modules or [ ]; + name = metadata._name or host; + in + { lib, ... }: { + imports = modules ++ [ + inputs.${metadata.home-manager-channel or "home-manager"}.nixosModules.home-manager + + defaultNixOSConfig + defaultNixConf + ../nixos/${host} + ]; + + config = lib.mkMerge [ + { + networking.hostName = lib.mkForce metadata.hostname or name; + nixpkgs.hostPlatform = metadata._system or defaultSystem; + + # The global configuration for the home-manager module. + home-manager.useUserPackages = lib.mkDefault true; + home-manager.useGlobalPkgs = lib.mkDefault true; + home-manager.sharedModules = [ defaultHomeManagerConfig ]; + } + + (lib.mkIf (metadata ? domain) + { networking.domain = lib.mkForce metadata.domain; }) + ]; + }; + + # The shared configuration for the entire list of hosts for this cluster. + # Take note to only set as minimal configuration as possible since we're + # also using this with the stable version of nixpkgs. + defaultNixOSConfig = { options, config, lib, pkgs, ... }: { + # Initialize some of the XDG base directories ourselves since it is + # used by NIX_PROFILES to properly link some of them. + environment.sessionVariables = { + XDG_CACHE_HOME = "$HOME/.cache"; + XDG_CONFIG_HOME = "$HOME/.config"; + XDG_DATA_HOME = "$HOME/.local/share"; + XDG_STATE_HOME = "$HOME/.local/state"; + }; + + # Only use imports as minimally as possible with the absolute + # requirements of a host. On second thought, only on flakes with + # optional NixOS modules. + imports = + # Append with our custom NixOS modules from the modules folder. + import ../../modules/nixos { inherit lib; isInternal = true; } + + # Then, make the most with the modules from the flake inputs. Take + # note importing some modules such as home-manager are as part of the + # declarative host config so be sure to check out + # `hostSpecificModule` function as well as the declarative host setup. + ++ [ + inputs.nix-index-database.nixosModules.nix-index + inputs.sops-nix.nixosModules.sops + inputs.disko.nixosModules.disko + ]; + + _module.args = defaultExtraArgs; + + # Find Nix files with these! Even if nix-index is already enabled, it + # is better to make it explicit. + programs.command-not-found.enable = false; + programs.nix-index.enable = true; + + # BOOOOOOOOOOOOO! Somebody give me a tomato! + services.xserver.excludePackages = with pkgs; [ xterm ]; + + # Append with the default time servers. It is becoming more unresponsive as + # of 2023-10-28. + networking.timeServers = [ + "europe.pool.ntp.org" + "asia.pool.ntp.org" + "time.cloudflare.com" + ] ++ options.networking.timeServers.default; + + # Disable channel state files. This shouldn't break any existing + # programs as long as we manage them NIX_PATH ourselves. + nix.channel.enable = lib.mkDefault false; + + # Set several paths for the traditional channels. + nix.nixPath = lib.mkIf config.nix.channel.enable + (lib.mapAttrsToList + (name: source: + let + name' = if (name == "self") then "config" else name; + in + "${name'}=${source}") + inputs + ++ [ + "/nix/var/nix/profiles/per-user/root/channels" + ]); + + # Please clean your temporary crap. + boot.tmp.cleanOnBoot = lib.mkDefault true; + + # We live in a Unicode world and dominantly English in technical fields so we'll + # have to go with it. + i18n.defaultLocale = lib.mkDefault "en_US.UTF-8"; + + # Enabling some things for sops. + programs.gnupg.agent = lib.mkDefault { + enable = true; + enableSSHSupport = true; + }; + services.openssh.enable = lib.mkDefault true; + + # It's following the 'nixpkgs' flake input which should be in unstable + # branches. Not to mention, most of the system configurations should + # have this attribute set explicitly by default. + system.stateVersion = lib.mkDefault "23.11"; + }; +in +{ + flake = { + # Listing my public NixOS modules if anyone cares. + nixosModules.default = import ../../modules/nixos { inherit lib; }; + + # A list of NixOS configurations from the `./configs/nixos` folder starting + # from project root. It also has some sensible default configurations. + nixosConfigurations = + let + inherit (import ../../lib/extras/flake-helpers.nix { inherit lib inputs; }) mkHost listImagesWithSystems; + in + lib.mapAttrs + (user: metadata: + mkHost { + nixpkgs-channel = metadata.nixpkgs-channel or "nixpkgs"; + extraModules = [ (hostSpecificModule user metadata) ]; + }) + (listImagesWithSystems nixosConfigs); + + # Deploy them server configs like a lazy bum-bum. + # + # Anyways, don't forget to flush out your shell history regularly or make + # it ignored which is a more ergonomic option. + deploy.nodes = + lib.mapAttrs' + (name: value: + let + metadata = nixosConfigs.${name}; + in + lib.nameValuePair "nixos-${name}" { + hostname = metadata.deploy.hostname or name; + autoRollback = metadata.deploy.auto-rollback or true; + magicRollback = metadata.deploy.magic-rollback or true; + fastConnection = metadata.deploy.fast-connection or true; + remoteBuild = metadata.deploy.remote-build or false; + profiles.system = { + sshUser = metadata.deploy.ssh-user or "admin"; + user = "root"; + path = inputs.deploy.lib.${metadata.system or defaultSystem}.activate.nixos value; + }; + }) + inputs.self.nixosConfigurations; + }; + + _module.args = { + inherit defaultNixOSConfig nixosConfigs; + }; +} diff --git a/configs/flake-parts/packages.nix b/configs/flake-parts/packages.nix new file mode 100644 index 00000000..d341690e --- /dev/null +++ b/configs/flake-parts/packages.nix @@ -0,0 +1,19 @@ +# All of the things concerning the custom packages from this flake are put over +# here. +{ inputs, ... }: { + # In case somebody wants to use my stuff to be included in nixpkgs. + flake.overlays = import ../../overlays // { + default = final: prev: import ../../pkgs { pkgs = prev; }; + firefox-addons = final: prev: { + inherit (final.nur.repos.rycee.firefox-addons) buildFirefoxXpiAddon; + firefox-addons = final.callPackage ../../pkgs/firefox-addons { }; + }; + }; + + perSystem = { system, pkgs, ... }: { + # My custom packages, available in here as well. Though, I mainly support + # "x86_64-linux". I just want to try out supporting other systems. + packages = + inputs.flake-utils.lib.flattenTree (import ../../pkgs { inherit pkgs; }); + }; +} diff --git a/configs/flake-parts/templates.nix b/configs/flake-parts/templates.nix new file mode 100644 index 00000000..d302b698 --- /dev/null +++ b/configs/flake-parts/templates.nix @@ -0,0 +1,22 @@ +# Cookiecutter templates for your mama. +{ inputs, ... }: { + flake.templates = { + default = inputs.self.templates.basic-devshell; + basic-devshell = { + path = ../templates/basic-devshell; + description = "Basic development shell template"; + }; + basic-overlay-flake = { + path = ../templates/basic-overlay-flake; + description = "Basic overlay as a flake"; + }; + sample-nixos-template = { + path = ../templates/sample-nixos-template; + description = "Simple sample Nix flake with NixOS and home-manager"; + }; + local-ruby-nix = { + path = ../templates/local-ruby-nix; + description = "Local Ruby app development with ruby-nix"; + }; + }; +} diff --git a/flake.lock b/flake.lock index 28e7347f..3d3119e7 100644 --- a/flake.lock +++ b/flake.lock @@ -185,6 +185,24 @@ } }, "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1704982712, + "narHash": "sha256-2Ptt+9h8dczgle2Oo6z5ni5rt/uLMG47UFTR1ry/wgg=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "07f6395285469419cf9d078f59b5b49993198c00", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { "inputs": { "nixpkgs-lib": [ "neovim-nightly-overlay", @@ -205,7 +223,7 @@ "type": "github" } }, - "flake-parts_2": { + "flake-parts_3": { "inputs": { "nixpkgs-lib": [ "neovim-nightly-overlay", @@ -359,7 +377,7 @@ }, "hercules-ci-effects": { "inputs": { - "flake-parts": "flake-parts_2", + "flake-parts": "flake-parts_3", "nixpkgs": [ "neovim-nightly-overlay", "nixpkgs" @@ -443,7 +461,7 @@ "neovim-nightly-overlay": { "inputs": { "flake-compat": "flake-compat_2", - "flake-parts": "flake-parts", + "flake-parts": "flake-parts_2", "hercules-ci-effects": "hercules-ci-effects", "neovim-flake": "neovim-flake", "nixpkgs": [ @@ -467,7 +485,7 @@ "nix-colors": { "inputs": { "base16-schemes": "base16-schemes", - "nixpkgs-lib": "nixpkgs-lib" + "nixpkgs-lib": "nixpkgs-lib_2" }, "locked": { "lastModified": 1695388192, @@ -626,6 +644,24 @@ } }, "nixpkgs-lib": { + "locked": { + "dir": "lib", + "lastModified": 1703961334, + "narHash": "sha256-M1mV/Cq+pgjk0rt6VxoyyD+O8cOUiai8t9Q6Yyq4noY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b0d36bd0a420ecee3bc916c91886caca87c894e9", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib_2": { "locked": { "lastModified": 1694911725, "narHash": "sha256-8YqI+YU1DGclEjHsnrrGfqsQg3Wyga1DfTbJrN3Ud0c=", @@ -726,6 +762,7 @@ "disko": "disko", "emacs-overlay": "emacs-overlay", "flake-compat-fds": "flake-compat-fds", + "flake-parts": "flake-parts", "flake-utils": "flake-utils_3", "helix-editor": "helix-editor", "home-manager": [ diff --git a/flake.nix b/flake.nix index 2119754c..49021787 100644 --- a/flake.nix +++ b/flake.nix @@ -78,501 +78,21 @@ # Make a default.nix compatible stuff. flake-compat-fds.url = "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"; + + # Someone had the idea to make the flake outputs be configured as a Nix + # module and I love them for it. + flake-parts.url = "github:hercules-ci/flake-parts"; }; outputs = inputs@{ self, nixpkgs, ... }: - let - # A set of image-related utilities for the flake outputs. - inherit (import ./lib/extras/flake-helpers.nix { inherit lib inputs; }) mkHost mkHome mkImage listImagesWithSystems; - - # We're considering this as the variant since we'll export the custom - # library as `lib` in the output attribute. - lib = nixpkgs.lib.extend (import ./lib/extras/extend-lib.nix); - - # Just add systems here and it should add systems to the outputs. - defaultSystem = "x86_64-linux"; + inputs.flake-parts.lib.mkFlake { inherit inputs; } { systems = [ "x86_64-linux" "aarch64-linux" ]; - forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system); - # A set of images with their metadata that is usually built for usual - # purposes. The format used here is whatever formats nixos-generators - # support. - images = import ./setups/nixos.nix { inherit lib inputs; }; - images' = listImagesWithSystems images; - - # A set of users with their metadata to be deployed with home-manager. - users = import ./setups/home-manager.nix { inherit lib inputs; }; - - # The order here is important(?). - overlays = lib.attrValues self.overlays; - - extraArgs = { - inherit (inputs) nix-colors; - }; - - # The shared configuration for the entire list of hosts for this cluster. - # Take note to only set as minimal configuration as possible since we're - # also using this with the stable version of nixpkgs. - hostSharedConfig = { options, config, lib, pkgs, ... }: { - # Initialize some of the XDG base directories ourselves since it is - # used by NIX_PROFILES to properly link some of them. - environment.sessionVariables = { - XDG_CACHE_HOME = "$HOME/.cache"; - XDG_CONFIG_HOME = "$HOME/.config"; - XDG_DATA_HOME = "$HOME/.local/share"; - XDG_STATE_HOME = "$HOME/.local/state"; - }; - - # Only use imports as minimally as possible with the absolute - # requirements of a host. On second thought, only on flakes with - # optional NixOS modules. - imports = - # Append with our custom NixOS modules from the modules folder. - import ./modules/nixos { inherit lib; isInternal = true; } - - # Then, make the most with the modules from the flake inputs. Take - # note importing some modules such as home-manager are as part of the - # declarative host config so be sure to check out - # `hostSpecificModule` function as well as the declarative host setup. - ++ [ - inputs.nix-index-database.nixosModules.nix-index - inputs.sops-nix.nixosModules.sops - inputs.disko.nixosModules.disko - ]; - - # Set some extra, yeah? - _module.args = extraArgs; - - # Find Nix files with these! Even if nix-index is already enabled, it - # is better to make it explicit. - programs.command-not-found.enable = false; - programs.nix-index.enable = true; - - # BOOOOOOOOOOOOO! Somebody give me a tomato! - services.xserver.excludePackages = with pkgs; [ xterm ]; - - # Append with the default time servers. It is becoming more unresponsive as - # of 2023-10-28. - networking.timeServers = [ - "europe.pool.ntp.org" - "asia.pool.ntp.org" - "time.cloudflare.com" - ] ++ options.networking.timeServers.default; - - # Disable channel state files. This shouldn't break any existing - # programs as long as we manage them NIX_PATH ourselves. - nix.channel.enable = lib.mkDefault false; - - # Set several paths for the traditional channels. - nix.nixPath = lib.mkIf config.nix.channel.enable - (lib.mapAttrsToList - (name: source: - let - name' = if (name == "self") then "config" else name; - in - "${name'}=${source}") - inputs - ++ [ - "/nix/var/nix/profiles/per-user/root/channels" - ]); - - # Please clean your temporary crap. - boot.tmp.cleanOnBoot = lib.mkDefault true; - - # We live in a Unicode world and dominantly English in technical fields so we'll - # have to go with it. - i18n.defaultLocale = lib.mkDefault "en_US.UTF-8"; - - # Enabling some things for sops. - programs.gnupg.agent = lib.mkDefault { - enable = true; - enableSSHSupport = true; - }; - services.openssh.enable = lib.mkDefault true; - - # It's following the 'nixpkgs' flake input which should be in unstable - # branches. Not to mention, most of the system configurations should - # have this attribute set explicitly by default. - system.stateVersion = lib.mkDefault "23.11"; - }; - - # The default config for our home-manager configurations. This is also to - # be used for sharing modules among home-manager users from NixOS - # configurations with `nixpkgs.useGlobalPkgs` set to `true` so avoid - # setting nixpkgs-related options here. - userSharedConfig = { pkgs, config, lib, ... }: { - imports = - # Import our own custom modules from here.. - import ./modules/home-manager { inherit lib; isInternal = true; } - - # ...plus a bunch of third-party modules. - ++ [ - inputs.nur.hmModules.nur - inputs.sops-nix.homeManagerModules.sops - inputs.nix-index-database.hmModules.nix-index - inputs.nix-colors.homeManagerModules.default - ]; - - # Set some extra, yeah? - _module.args = extraArgs; - - # Hardcoding this is not really great especially if you consider using - # other locales but its default values are already hardcoded so what - # the hell. For other users, they would have to do set these manually. - xdg.userDirs = - let - # The home directory-related options should be already taken care - # of at this point. It is an ABSOLUTE MUST that it is set properly - # since other parts of the home-manager config relies on it being - # set properly. - # - # Here are some of the common cases for setting the home directory - # options. - # - # * For exporting home-manager configurations, this is done in this - # flake definition. - # * For NixOS configs, this is done automatically by the - # home-manager NixOS module. - # * Otherwise, you'll have to manually set them. - appendToHomeDir = path: "${config.home.homeDirectory}/${path}"; - in - { - desktop = appendToHomeDir "Desktop"; - documents = appendToHomeDir "Documents"; - download = appendToHomeDir "Downloads"; - music = appendToHomeDir "Music"; - pictures = appendToHomeDir "Pictures"; - publicShare = appendToHomeDir "Public"; - templates = appendToHomeDir "Templates"; - videos = appendToHomeDir "Videos"; - }; - - programs.home-manager.enable = true; - - manual = lib.mkDefault { - html.enable = true; - json.enable = true; - manpages.enable = true; - }; - - home.stateVersion = lib.mkDefault "23.11"; - }; - - # This will be shared among NixOS and home-manager configurations. - nixSettingsSharedConfig = { config, lib, pkgs, ... }: { - # I want to capture the usual flakes to its exact version so we're - # making them available to our system. This will also prevent the - # annoying downloads since it always get the latest revision. - nix.registry = - lib.mapAttrs' - (name: flake: - let - name' = if (name == "self") then "config" else name; - in - lib.nameValuePair name' { inherit flake; }) - inputs; - - # Set the package for generating the configuration. - nix.package = lib.mkDefault pkgs.nixStable; - - # Set the configurations for the package manager. - nix.settings = { - # Set several binary caches. - substituters = [ - "https://nix-community.cachix.org" - "https://foo-dogsquared.cachix.org" - ]; - trusted-public-keys = [ - "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" - "foo-dogsquared.cachix.org-1:/2fmqn/gLGvCs5EDeQmqwtus02TUmGy0ZlAEXqRE70E=" - ]; - - # Sane config for the package manager. - # TODO: Remove this after nix-command and flakes has been considered - # stable. - # - # Since we're using flakes to make this possible, we need it. Plus, the - # UX of Nix CLI is becoming closer to Guix's which is a nice bonus. - experimental-features = [ "nix-command" "flakes" "repl-flake" ]; - auto-optimise-store = lib.mkDefault true; - }; - - # Stallman-senpai will be disappointed. - nixpkgs.config.allowUnfree = true; - - # Extend nixpkgs with our overlays except for the NixOS-focused modules - # here. - nixpkgs.overlays = overlays; - }; - - # A function that generates a Nix module from host metadata. - hostSpecificModule = host: metadata: - let - modules = metadata.modules or [ ]; - host = metadata._name or host; - in - { lib, ... }: { - imports = modules ++ [ - inputs.${metadata.home-manager-channel or "home-manager"}.nixosModules.home-manager - - hostSharedConfig - nixSettingsSharedConfig - ./configs/nixos/${host} - ]; - - config = lib.mkMerge [ - { - networking.hostName = lib.mkForce metadata.hostname or host; - nixpkgs.hostPlatform = metadata._system; - - # The global configuration for the home-manager module. - home-manager.useUserPackages = lib.mkDefault true; - home-manager.useGlobalPkgs = lib.mkDefault true; - home-manager.sharedModules = [ userSharedConfig ]; - } - - (lib.mkIf (metadata ? domain) - { networking.domain = lib.mkForce metadata.domain; }) - ]; - }; - - # A function that generates a home-manager module from a given user - # metadata. - userSpecificModule = user: metadata: - let - name = metadata.username or metadata._name or user; - modules = metadata.modules or [ ]; - in - { lib, pkgs, config, ... }: { - imports = modules ++ [ - userSharedConfig - nixSettingsSharedConfig - ./configs/home-manager/${name} - ]; - - # Don't create the user directories since they are assumed to - # be already created by a pre-installed system (which should - # already handle them). - xdg.userDirs.createDirectories = lib.mkForce false; - - # Setting the homely options. - home.username = lib.mkForce name; - home.homeDirectory = lib.mkForce (metadata.home-directory or "/home/${config.home.username}"); - - programs.home-manager.enable = lib.mkForce true; - targets.genericLinux.enable = true; - }; - in - { - apps = forAllSystems (system: - let - pkgs = nixpkgs.legacyPackages.${system}; - in - { - run-workflow-with-vm = - let - inputsArgs = lib.mapAttrsToList - (name: source: - let - name' = if (name == "self") then "config" else name; - in - "'${name'}=${source}'") - inputs; - script = pkgs.callPackage ./apps/run-workflow-with-vm { - inputs = inputsArgs; - }; - in - { - type = "app"; - program = "${script}/bin/run-workflow-with-vm"; - }; - }); - - # Exposes only my library with the custom functions to make it easier to - # include in other flakes for whatever reason may be. - lib = import ./lib { lib = nixpkgs.lib; }; - - # A list of NixOS configurations from the `./configs/nixos` folder. It - # also has some sensible default configurations. - nixosConfigurations = - let - validImages = lib.filterAttrs - (name: metadata: - metadata.format == null || metadata ? deploy) - images; - in - lib.mapAttrs - (host: metadata: - mkHost { - extraModules = [ (hostSpecificModule host metadata) ]; - nixpkgs-channel = metadata.nixpkgs-channel or "nixpkgs"; - }) - (listImagesWithSystems validImages); - - # We're going to make our custom modules available for our flake. Whether - # or not this is a good thing is debatable, I just want to test it. - nixosModules.default = import ./modules/nixos { inherit lib; }; - - # I can now install home-manager users in non-NixOS systems. - # NICE! - homeConfigurations = - lib.mapAttrs - (user: metadata: - mkHome { - pkgs = import inputs.${metadata.nixpkgs-channel or "nixpkgs"} { - system = metadata._system; - }; - extraModules = [ (userSpecificModule user metadata) ]; - home-manager-channel = metadata.home-manager-channel or "home-manager"; - }) - (listImagesWithSystems users); - - # Extending home-manager with my custom modules, if anyone cares. - homeModules.default = import ./modules/home-manager { inherit lib; }; - - # In case somebody wants to use my stuff to be included in nixpkgs. - overlays = import ./overlays // { - default = final: prev: import ./pkgs { pkgs = prev; }; - firefox-addons = final: prev: { - inherit (final.nur.repos.rycee.firefox-addons) buildFirefoxXpiAddon; - firefox-addons = final.callPackage ./pkgs/firefox-addons { }; - }; - }; - - # My custom packages, available in here as well. Though, I mainly support - # "x86_64-linux". I just want to try out supporting other systems. - packages = forAllSystems (system: - inputs.flake-utils.lib.flattenTree (import ./pkgs { - pkgs = import nixpkgs { inherit system; }; - })); - - # This contains images that are meant to be built and distributed - # somewhere else including those NixOS configurations that are built as - # an ISO. - images = forAllSystems (system: - let - validImages = lib.filterAttrs - (host: metadata: - system == metadata._system && metadata.format != null) - images'; - in - lib.mapAttrs' - (host: metadata: - let - name = metadata._name; - nixpkgs-channel = metadata.nixpkgs-channel or "nixpkgs"; - format = metadata.format or "iso"; - in - lib.nameValuePair name (mkImage { - inherit nixpkgs-channel format; - extraModules = [ (hostSpecificModule host metadata) ]; - })) - validImages); - - # My several development shells for usual type of projects. This is much - # more preferable than installing all of the packages at the system - # configuration (or even home environment). - devShells = forAllSystems (system: - let - pkgs = import nixpkgs { - inherit system; - overlays = overlays ++ [ - inputs.nur.overlay - ]; - }; - in - import ./shells { inherit pkgs; } // { - default = import ./shell.nix { inherit pkgs; }; - docs = import ./docs/shell.nix { inherit pkgs; }; - }); - - # Cookiecutter templates for your mama. - templates = { - default = self.templates.basic-devshell; - basic-devshell = { - path = ./templates/basic-devshell; - description = "Basic development shell template"; - }; - basic-overlay-flake = { - path = ./templates/basic-overlay-flake; - description = "Basic overlay as a flake"; - }; - sample-nixos-template = { - path = ./templates/sample-nixos-template; - description = "Simple sample Nix flake with NixOS and home-manager"; - }; - local-ruby-nix = { - path = ./templates/local-ruby-nix; - description = "Local Ruby app development with ruby-nix"; - }; - }; - - # No amount of formatters will make this codebase nicer but it sure does - # feel like it does. - formatter = - forAllSystems (system: nixpkgs.legacyPackages.${system}.treefmt); - - # nixops-lite (that is much more powerful than nixops itself)... in - # here!?! We got it all, son! - # - # Also, don't forget to always clean your shell history when overriding - # sensitive info such as the hostname and such. A helpful tip would be - # ignoring the shell entry by simply prefixing it with a space which most - # command-line shells have support for (e.g., Bash, zsh, fish). - deploy.nodes = - let - nixosConfigurations = lib.mapAttrs' - (name: value: - let - metadata = images.${name}; - in - lib.nameValuePair "nixos-${name}" { - hostname = metadata.deploy.hostname or name; - autoRollback = metadata.deploy.auto-rollback or true; - magicRollback = metadata.deploy.magic-rollback or true; - fastConnection = metadata.deploy.fast-connection or true; - remoteBuild = metadata.deploy.remote-build or false; - profiles.system = { - sshUser = metadata.deploy.ssh-user or "admin"; - user = "root"; - path = inputs.deploy.lib.${metadata.system or defaultSystem}.activate.nixos value; - }; - }) - self.nixosConfigurations; - homeConfigurations = lib.mapAttrs' - (name: value: - let - metadata = users.${name}; - username = metadata.deploy.username or name; - in - lib.nameValuePair "home-manager-${name}" { - hostname = metadata.deploy.hostname or name; - autoRollback = metadata.deploy.auto-rollback or true; - magicRollback = metadata.deploy.magic-rollback or true; - fastConnection = metadata.deploy.fast-connection or true; - remoteBuild = metadata.deploy.remote-build or false; - profiles.home = { - sshUser = metadata.deploy.ssh-user or username; - user = metadata.deploy.user or username; - path = inputs.deploy.lib.${metadata.system or defaultSystem}.activate.home-manager value; - }; - }) - self.homeConfigurations; - in - nixosConfigurations // homeConfigurations; - - # How to make yourself slightly saner than before. So far the main checks - # are for deploy nodes. - checks = lib.mapAttrs - (system: deployLib: deployLib.deployChecks self.deploy) - inputs.deploy.lib; - - # I'm cut off from the rest of my setup with no Hydra instance yet but - # I'm sure it will grow some of them as long as you didn't put it under a - # rock. - hydraJobs.build-packages = forAllSystems (system: self.packages.${system}); + imports = [ + ./configs/flake-parts + ]; }; }