Giter Club home page Giter Club logo

lite-config's Introduction

lite-config

flakestry.dev

Note

lite-config is the new name of lite-system. This rename is to avoid confusion on the word 'system', which is commonly used to refer to platform string, like "x86_64-linux", in context of Nix.

lite-config offers a convinient appraoch to build NixOS, nix-darwin and Home Manager configurations, to create a consistent environment across different devices. It addresses common patterns when creating personal system configurations, which includes:

  1. Configure pkgs with overlays and config, and use it across all system configurations.
  2. Build NixOS and nix-darwin configurations in a unified way.
  3. Export standalone homeConfigurations to be used in non-NixOS Linux distributions.
  4. Export packages from overlays for easy debugging.

An example:

{
  inputs = {
    nixpkgs.url = "nixpkgs/nixos-unstable";
    flake-parts.url = "github:hercules-ci/flake-parts";
    lite-config.url = "github:yelite/lite-config";
    nix-darwin = {
      url = "github:lnl7/nix-darwin";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };
  outputs = inputs @ {flake-parts, ...}:
    flake-parts.lib.mkFlake {inherit inputs;} ({inputs, ...}: {
      imports = [
        inputs.lite-config.flakeModule
      ];

      config.lite-config = {
        # Configure the nixpkgs that is used in all configurations created by `lite-config`.
        nixpkgs = {
          config = {
            allowUnfree = true;
          };
          overlays = [
            (import ./overlay)
          ];
        };

        # System modules will be imported for all host configurations.
        systemModules = [ ./system ];
        # Home modules are imported by Home Manager in all host configurations.
        homeModules = [ ./home ];
        # This directory contains per-host system module.
        hostModuleDir = ./hosts;

        hosts = {
          # This generates `nixosConfigurations.my-desktop` with NixOS module
          # `./system`, `./hosts/my-desktop` and Home Manager module `./home`.
          my-desktop = {
            system = "x86_64-linux";
          };

          # This generates `darwinConfigurations.my-macbook` with nix-darwin module
          # `./system`, `./hosts/my-desktop` and Home Manager module `./home`.
          #
          # Note that `./system` module is used in both NixOS and nix-darwin configurations.
          # A `hostPlatform` special arg is added to both system modules
          # and home manager modules, enabling conditional confiIt offers only a fundamental framework for building flakes of system configurations. guration based on
          # the system type.
          my-macbook = {
            system = "aarch64-darwin";
          };
        };
      };
    });
}

lite-config aims to be light weight, as the name suggests. It offers only a fundamental framework for building flakes of system configurations. Users still need to write NixOS (or nix-darwin) modules and home manager modules on their own, as in vanilla flake.

It requires a system module shared across all hosts, a set of per-host modules to customize each host, and optionally a home manager module used by all hosts.

To enable the creation of unified modules for both NixOS and nix-darwin, lite-config adds hostPlatform as a special arg to the module system. This allows modules to be conditionally imported based on system type.

Why?

Why flake?

From https://nixos.wiki/wiki/Flakes,

Flake improves reproducibility, composability and usability in the Nix ecosystem.

When it comes to building system configurations, the most significant advantage offered by flakes is reproducibility. By utilizing flakes, it's ensured that environments across all systems achieve the highest degree of consistency possible.

Why flake module (flake-parts)?

From https://github.com/hercules-ci/flake-parts#why-modules,

Flakes are configuration. The module system lets you refactor configuration into modules that can be shared. It reduces the proliferation of custom Nix glue code, similar to what the module system has done for NixOS configurations.

While the flexibility provided by flake-parts may not provide significant advantages when creating system configurations, it comes in handy when there is need to integrate various other components within the same flake.

Why lite-config?

The features offered by flake and flake-parts are rather primitive. lite-config provides features that are commonly needed when building system configurations. Since it's a flake module, it can also be easily customized and overridden when users have more complex tasks to accomplish within the flake.

Full example

{
  outputs = inputs @ {flake-parts, ...}:
    flake-parts.lib.mkFlake {inherit inputs;} ({inputs, ...}: {
      imports = [
        inputs.lite-config.flakeModule
      ];

      config.lite-config = {
        # Configure the nixpkgs that is used in all configurations created by `lite-config`.
        nixpkgs = {
          # The nixpkgs flake to use. Default to `inputs.nixpkgs`.
          # This option needs to set if the nixpkgs that you want to use is under a
          # different name in flake inputs.
          nixpkgs = inputs.nixpkgs;
          # nixpkgs global config https://nixos.org/manual/nixpkgs/stable/#chap-packageconfig
          config = {};
          # List of overlays to use with the nixpkgs.
          overlays = [];
          # Whether packages in the overlays should be exported as packages of this flake.
          exportOverlayPackages = true;
          # Whether the nixpkgs used in lite-config should also be set as the `pkgs` arg for
          # the perSystem module.
          setPerSystemPkgs = true;
        };

        # The home-manager flake to use.
        # This should be set if home-manager isn't named as `home-manager` in flake inputs.
        # This has no effect if {option}`lite-config.homeModule` is null.
        homeManagerFlake = inputs.home-manager;

        builder = {
          # The builder function for darwin system.
          # Default to `inputs.nix-darwin.lib.darwinSystem`.
          # This option should be set if the `nix-darwin` flake is under a different name
          # in flake inputs.
          darwin = inputs.nix-darwin.lib.darwinSystem;
        };

        # System modules will be imported for all host configurations.
        systemModules = [ ./system ];
        # Home modules are imported by Home Manager in all host configurations.
        homeModules = [ ./home ];
        # This directory contains per-host system module.
        hostModuleDir = ./hosts;

        hosts = {
          host-name = {
            system = "x86_64-linux";
            # Overrides the default host module based on `hostModuleDir`.
            hostModule = ./hosts/common-desktop
          };
        };

        # Per-user Home Manager module used for exporting homeConfigurations to be used
        # by systems other than NixOS and nix-darwin.
        #
        # The exported homeConfigurations will import both `lite-config.homeModule` and the value of
        # this attrset.
        #
        # This has no effect if `lite-config.homeModule` is null.
        homeConfigurations = {
          joe = {
            myConfig = {
              neovim.enable = true;
            };
          };
        };
      };
    });
}

https://github.com/yelite/system-config is a practical, real-world example on how to use lite-config.

lite-config's People

Contributors

yelite avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

jcf

lite-config's Issues

Incompatiblity with nix-community/emacs-overlay

Hello Lite Ye,

Thank you for open sourcing lite-system. It's exactly what I'm looking for and will DRY up my personal Nix configuration that I plan to open source very soon.

I have unfortunately run into an issue when adding the nix-community/emacs-overlay to my work-in-progress configuration. I've pushed a minimal example to jcf/lite-system-emacs-overlay in case it's helpful.

With nothing more than empty host, home, and system modules, I'm able to produce the following error when checking/building from my flake.nix.

{
  outputs = inputs @ { flake-parts, ... }:
    flake-parts.lib.mkFlake { inherit inputs; } ({ inputs, ... }: {
      imports = [
        inputs.lite-system.flakeModule
      ];

      config.lite-system = {
        nixpkgs = {
          overlays = [ inputs.emacs-overlay.overlays.emacs ];
        };

        systemModule = ./system;
        homeModule = ./home;
        hostModuleDir = ./host;

        hosts = {
          example = {
            system = "aarch64-darwin";
          };
        };
      };
    });

  inputs = {
    nixpkgs.url = "nixpkgs/nixos-unstable";
    flake-parts.url = "github:hercules-ci/flake-parts";
    lite-system.url = "github:yelite/lite-system";

    # [...]

    # https://github.com/nix-community/emacs-overlay
    emacs-overlay = {
      url = "github:nix-community/emacs-overlay/ead33b53bddac6d9e4e01d1e80e6dc1d8d30d2a3";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };
}
$ nix run nix-darwin -- --flake $(PWD) check
[...]
error:
       … while evaluating the attribute 'optionalValue.value'

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/modules.nix:854:5:

          853|
          854|     optionalValue =
             |     ^
          855|       if isDefined then { value = mergedValue; }

       … while evaluating a branch condition

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/modules.nix:855:7:

          854|     optionalValue =
          855|       if isDefined then { value = mergedValue; }
             |       ^
          856|       else {};

       (stack trace truncated; use '--show-trace' to show the full trace)

       error: value is null while a set was expected
nix run nix-darwin -- --flake $(PWD) check --show-trace
building the system configuration...
error:
       … while calling anonymous lambda

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/types.nix:565:29:

          564|       merge = loc: defs:
          565|         zipAttrsWith (name: defs:
             |                             ^
          566|           let merged = mergeDefinitions (loc ++ [name]) elemType defs;

       … while calling anonymous lambda

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/modules.nix:822:28:

          821|         # Process mkMerge and mkIf properties.
          822|         defs' = concatMap (m:
             |                            ^
          823|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))

       … while evaluating definitions from `/nix/store/2gkqfvzq2j0vbrlkx3y0k8qxyn4px989-source/modules/transposition.nix':

       … from call site

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/modules.nix:823:137:

          822|         defs' = concatMap (m:
          823|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
             |                                                                                                                                         ^
          824|         ) defs;

       … while calling 'dischargeProperties'

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/modules.nix:894:25:

          893|   */
          894|   dischargeProperties = def:
             |                         ^
          895|     if def._type or "" == "merge" then

       … while calling anonymous lambda

         at /nix/store/2gkqfvzq2j0vbrlkx3y0k8qxyn4px989-source/modules/transposition.nix:62:22:

           61|           mapAttrs
           62|             (system: v: v.${attrName})
             |                      ^
           63|             config.allSystems

       … while calling 'g'

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/attrsets.nix:643:19:

          642|           g =
          643|             name: value:
             |                   ^
          644|             if isAttrs value && cond value

       … from call site

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/attrsets.nix:646:20:

          645|               then recurse (path ++ [name]) value
          646|               else f (path ++ [name]) value;
             |                    ^
          647|         in mapAttrs g;

       … while calling anonymous lambda

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/modules.nix:242:72:

          241|           # For definitions that have an associated option
          242|           declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
             |                                                                        ^
          243|

       … while evaluating the option `perSystem.aarch64-darwin.packages':

       … while calling anonymous lambda

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/modules.nix:822:28:

          821|         # Process mkMerge and mkIf properties.
          822|         defs' = concatMap (m:
             |                            ^
          823|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))

       … while evaluating definitions from `/nix/store/3n54gjkr6vgcj5vbagiacsq218pm0mim-source':

       … from call site

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/modules.nix:823:137:

          822|         defs' = concatMap (m:
          823|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
             |                                                                                                                                         ^
          824|         ) defs;

       … while calling 'dischargeProperties'

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/modules.nix:894:25:

          893|   */
          894|   dischargeProperties = def:
             |                         ^
          895|     if def._type or "" == "merge" then

       … while calling 'dischargeProperties'

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/modules.nix:894:25:

          893|   */
          894|   dischargeProperties = def:
             |                         ^
          895|     if def._type or "" == "merge" then

       … from call site

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/modules.nix:900:11:

          899|         if def.condition then
          900|           dischargeProperties def.content
             |           ^
          901|         else

       … while calling 'dischargeProperties'

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/modules.nix:894:25:

          893|   */
          894|   dischargeProperties = def:
             |                         ^
          895|     if def._type or "" == "merge" then

       … from call site

         at /nix/store/3n54gjkr6vgcj5vbagiacsq218pm0mim-source/flake-module.nix:286:16:

          285|   in
          286|     attrNames (overlay null null);
             |                ^
          287|

       … while calling 'composeExtensions'

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/fixed-points.nix:149:18:

          148|   composeExtensions =
          149|     f: g: final: prev:
             |                  ^
          150|       let fApplied = f final prev;

       … from call site

         at /nix/store/cjvwy2rr87ir1nb6wvs9n6lvbnzlqrdg-source/lib/fixed-points.nix:150:22:

          149|     f: g: final: prev:
          150|       let fApplied = f final prev;
             |                      ^
          151|           prev' = prev // fApplied;

       … while calling 'emacs'

         at /nix/store/1q6mi6lzvgd6ip7rn0i21p4r64cqwsxr-source/flake.nix:31:24:

           30|         default = final: prev: import ./overlays final prev;
           31|         emacs = final: prev: import ./overlays/emacs.nix final prev;
             |                        ^
           32|         package = final: prev: import ./overlays/package.nix final prev;

       … from call site

         at /nix/store/1q6mi6lzvgd6ip7rn0i21p4r64cqwsxr-source/flake.nix:31:30:

           30|         default = final: prev: import ./overlays final prev;
           31|         emacs = final: prev: import ./overlays/emacs.nix final prev;
             |                              ^
           32|         package = final: prev: import ./overlays/package.nix final prev;

       … while calling anonymous lambda

         at /nix/store/1q6mi6lzvgd6ip7rn0i21p4r64cqwsxr-source/overlays/emacs.nix:1:7:

            1| self: super:
             |       ^
            2| let

       error: value is null while a set was expected

Home modules not installed

Hello again Ye Lite,

I've come up against another issue that seems to stem from Home Manager not being configured out of the box.

I can reproduce this issue with a trivial system zsh module and home git module where I conditionally enable each via a mkEnableOption.

{ config
, lib
, ...
}:
let
  inherit (lib) mkEnableOption mkIf;
  cfg = config.my.system.zsh;
in
{
  options.my.system.zsh = {
    enable = mkEnableOption "zsh";
  };

  config = mkIf cfg.enable {
    programs.zsh.enable = true;
  };
}
{ config
, lib
, ...
}:
let
  inherit (lib) mkEnableOption mkIf;
  cfg = config.my.home.git;
in
{
  options.my.home.git = {
    enable = mkEnableOption "git";
  };

  config = mkIf cfg.enable {
    programs.git.enable = true;
  };
}

I toggle these on in my host configuration and only see the system module taking affect.

{ ... }: {
  my = {
    system = {
      zsh.enable = true;
    };

    home = {
      git.enable = true;
    };
  };
}

I might be missing something; maybe I have more work to do with Home Manager to get modules showing up in the host config?

https://github.com/jcf/lite-system-emacs-overlay/tree/main#home-modules

Thank You!

This is exactly the type of tool I was looking for!
There are other "frameworks" to make using nixos/HM easier, but they can have additional complexity and, ironically, more boilerplate nix code.
Or they simply don't look as clean.
Good job!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.