From db5fc8269e6cfc1d59e0bd3c03b3869451ea2f0e Mon Sep 17 00:00:00 2001 From: Gabriel Arazas Date: Mon, 29 Nov 2021 13:30:57 +0800 Subject: [PATCH] Update user-specific config Oh no, now I'm content with creating my own framework instead of using something like digga or flake-utils. --- .gitmodules | 3 + README.adoc | 48 +++--- flake.lock | 279 ++----------------------------- flake.nix | 27 ++- hosts/ni/README.adoc | 34 ++++ lib/default.nix | 18 ++ modules/README.adoc | 62 +++++++ modules/agenix.nix | 2 +- modules/editors.nix | 1 + modules/users.nix | 32 +++- users/README.adoc | 20 ++- users/config | 1 + users/foo-dogsquared/default.nix | 13 +- 13 files changed, 237 insertions(+), 303 deletions(-) create mode 100644 .gitmodules create mode 100644 hosts/ni/README.adoc create mode 100644 modules/README.adoc create mode 160000 users/config diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..985885bd --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "users/config"] + path = users/config + url = https://github.com/foo-dogsquared/dotfiles.git diff --git a/README.adoc b/README.adoc index 037cf654..14cead54 100644 --- a/README.adoc +++ b/README.adoc @@ -18,8 +18,9 @@ This primarily uses Nix flakes so you can have a preview of what's available in nix flake show github:foo-dogsquared/nixos-config ---- -It should only export my NixOS configurations of my different hosts (of only one so far excluding VMs and VPSs ;p). - +It should export my NixOS configurations of my different hosts (of only one so far excluding VMs and VPSs ;p) among other things. +To install it, run the `nixos-install --flake github:foo-dogsquared/nixos-config#ni`. +(Please see the respective appropriate host README for more information.) @@ -28,24 +29,16 @@ It should only export my NixOS configurations of my different hosts (of only one In order of priority: -* Create custom modules. -** Create a themes system similar to link:https://github.com/hlissner/dotfiles[this NixOS config]. - -* Manage secrets with agenix. - -* Automate backups with NixOS config. - -* Create custom packages and export it to flakes. (Maybe consider making it to upstream) - -* Create cluser-wide configs. - -* Create host-wide configs. - -* Create user-specific configs with home-manager. - -* ~Steal~ Get some ideas from link:https://github.com/divnix/devos[this overengineered template]. - -* Make use of other established utilities such as link:https://github.com/divnix/digga/[digga], link:https://github.com/gytis-ivaskevicius/flake-utils-plus[flake-utils-plus], and link:https://github.com/nix-community/home-manager[home-manager] once I'm familiar to create my own Nix programs. +* [x] Create custom modules. +* [x] Create a themes system similar to link:https://github.com/hlissner/dotfiles[this NixOS config]. +* [ ] Manage secrets with agenix. +* [x] Automate backups with NixOS config. +* [ ] Create custom packages and export it to flakes. (Maybe consider making it to upstream) +* [x] Create cluser-wide configs. +* [x] Create host-wide configs. +* [ ] Create user-specific configs with home-manager. +* [ ] ~Steal~ Get some ideas from link:https://github.com/divnix/devos[this overengineered template]. +* [ ] Make use of other established utilities such as link:https://github.com/divnix/digga/[digga], link:https://github.com/gytis-ivaskevicius/flake-utils-plus[flake-utils-plus], and link:https://github.com/nix-community/home-manager[home-manager] once I'm familiar to create my own Nix programs. Out of scope: @@ -55,3 +48,18 @@ They are often updated. I don't want to rebuild it every time I change it. * Migration of my link:https://github.com/foo-dogsquared/dotfiles[dotfiles]. I still use it on other non-NixOS systems. + + + +== Frequently asked questions (FAQ) + +[qanda] +Hello! I'm new to Nix and NixOS, where should I start?:: +Oh no, you've seen the multiple configurations from other systems, didn't you? +I hope you're ready for some time understanding because the learning curve is steeper than the link:https://en.wikipedia.org/wiki/Troll_Wall[Troll Wall]. +I've written link:https://foo-dogsquared.github.io/blog/posts/moving-into-nixos/[a blog post regarding my experience with Nix] with a bunch of links for getting started. +(Un)Fortunately, it is mostly the same experience now that I've revisited it. + +Any requirements for this setup?:: +You only need Nix 2.4 installed with the experimental features for Nix command and flakes enabled (i.e., `experimental-features = nix-command flakes`). + diff --git a/flake.lock b/flake.lock index e9b93c2a..09a0bd1d 100644 --- a/flake.lock +++ b/flake.lock @@ -7,11 +7,11 @@ ] }, "locked": { - "lastModified": 1637625975, - "narHash": "sha256-ByDgmhpLykhAVeaFggjqoSRdl2OzTDODnxjPuu97fL4=", + "lastModified": 1637793790, + "narHash": "sha256-oPXavjxETEWGXq8g7kQHyRLKUmLX2yPtGn+t3V0mrTY=", "owner": "ryantm", "repo": "agenix", - "rev": "a0e9ca505c82e762d39e9477a428b537a0aab022", + "rev": "f85eea0e29fa9a8924571d0e398215e175f80d55", "type": "github" }, "original": { @@ -20,178 +20,18 @@ "type": "github" } }, - "blank": { - "locked": { - "lastModified": 1625557891, - "narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=", - "owner": "divnix", - "repo": "blank", - "rev": "5a5d2684073d9f563072ed07c871d577a6c614a8", - "type": "github" - }, - "original": { - "owner": "divnix", - "repo": "blank", - "type": "github" - } - }, - "deploy": { - "inputs": { - "flake-compat": "flake-compat", - "nixpkgs": [ - "digga", - "latest" - ], - "utils": [ - "digga", - "flake-utils" - ] - }, - "locked": { - "lastModified": 1632822684, - "narHash": "sha256-lt7eayYmgsD5OQwpb1XYfHpxttn43bWo7G7hIJs+zJw=", - "owner": "serokell", - "repo": "deploy-rs", - "rev": "9a02de4373e0ec272d08a417b269a28ac8b961b4", - "type": "github" - }, - "original": { - "owner": "serokell", - "repo": "deploy-rs", - "type": "github" - } - }, - "devshell": { - "locked": { - "lastModified": 1632436039, - "narHash": "sha256-OtITeVWcKXn1SpVEnImpTGH91FycCskGBPqmlxiykv4=", - "owner": "numtide", - "repo": "devshell", - "rev": "7a7a7aa0adebe5488e5abaec688fd9ae0f8ea9c6", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "devshell", - "type": "github" - } - }, - "digga": { - "inputs": { - "blank": "blank", - "deploy": "deploy", - "devshell": "devshell", - "flake-utils": "flake-utils", - "flake-utils-plus": "flake-utils-plus", - "home-manager": "home-manager", - "latest": "latest", - "nix": "nix", - "nixlib": [ - "digga", - "nixpkgs" - ], - "nixos-generators": "nixos-generators", - "nixpkgs": "nixpkgs" - }, - "locked": { - "lastModified": 1634161492, - "narHash": "sha256-7OZz7DqAhO+3axY68xsMXAyD+b5gJgVXuKjslTSCM3Y=", - "owner": "divnix", - "repo": "digga", - "rev": "a55450a16d362b6e1c50bb4025aaa604b385d3ba", - "type": "github" - }, - "original": { - "owner": "divnix", - "repo": "digga", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1627913399, - "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-utils": { - "locked": { - "lastModified": 1623875721, - "narHash": "sha256-A8BU7bjS5GirpAUv4QA+QnJ4CceLHkcXdRp4xITDB0s=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "f7e004a55b120c02ecb6219596820fcd32ca8772", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils-plus": { - "inputs": { - "flake-utils": [ - "digga", - "flake-utils" - ] - }, - "locked": { - "lastModified": 1630859749, - "narHash": "sha256-qkoU2rIbbP2+T0dfcqXW35GCWNsi0Y1IgN9BELmt4Zo=", - "owner": "divnix", - "repo": "flake-utils-plus", - "rev": "a4e267e3fc87e60c5029c6c3855935ff1ff3018e", - "type": "github" - }, - "original": { - "owner": "divnix", - "repo": "flake-utils-plus", - "type": "github" - } - }, "home-manager": { - "inputs": { - "nixpkgs": [ - "digga", - "nixlib" - ] - }, - "locked": { - "lastModified": 1629347633, - "narHash": "sha256-FGZJ7lmTAMIkjdrh6dIPck5HuB4KMT2GgDV5ZjiCWoc=", - "owner": "nix-community", - "repo": "home-manager", - "rev": "bf6b85136b47ab1a76df4a90ea4850871147494a", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "home-manager", - "type": "github" - } - }, - "home-manager_2": { "inputs": { "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1637721183, - "narHash": "sha256-4CAKKxrt9l0Hbl57Uypo7ol93Ko+5Yn+7xWWCMUyHQ8=", + "lastModified": 1638150501, + "narHash": "sha256-aWH3MRmjUtx8ciSGLegBJC5mhymsuroHPs74ZldrNTU=", "owner": "nix-community", "repo": "home-manager", - "rev": "df931a59a5864d6ff0c5d83598135816f8593647", + "rev": "9de77227d7780518cfeaee5a917970247f3ecc56", "type": "github" }, "original": { @@ -200,109 +40,13 @@ "type": "github" } }, - "latest": { - "locked": { - "lastModified": 1632660378, - "narHash": "sha256-sjA8eQlnyDjDLyAyq3XlJmN0nqW0ftl/pb7VnMg86L0=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "31ffc50c571e6683e9ecc9dbcbd4a8e9914b4497", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "lowdown-src": { - "flake": false, - "locked": { - "lastModified": 1617481909, - "narHash": "sha256-SqnfOFuLuVRRNeVJr1yeEPJue/qWoCp5N6o5Kr///p4=", - "owner": "kristapsdz", - "repo": "lowdown", - "rev": "148f9b2f586c41b7e36e73009db43ea68c7a1a4d", - "type": "github" - }, - "original": { - "owner": "kristapsdz", - "ref": "VERSION_0_8_4", - "repo": "lowdown", - "type": "github" - } - }, - "nix": { - "inputs": { - "lowdown-src": "lowdown-src", - "nixpkgs": [ - "digga", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1630335771, - "narHash": "sha256-eljjEPJdLK3aDskF7qX4YM/6KCq+w9nr+IKhrKW/AIQ=", - "owner": "nixos", - "repo": "nix", - "rev": "50a35860ee9237d341948437c5f70a7f0987d393", - "type": "github" - }, - "original": { - "owner": "nixos", - "repo": "nix", - "type": "github" - } - }, - "nixos-generators": { - "inputs": { - "nixlib": [ - "digga", - "nixlib" - ], - "nixpkgs": [ - "digga", - "blank" - ] - }, - "locked": { - "lastModified": 1624973746, - "narHash": "sha256-11JbJRduNwyf556gndGErR5/12ceyHOHBfEuha5Vws4=", - "owner": "nix-community", - "repo": "nixos-generators", - "rev": "022ef440af8dc237ab1f59fa363cb1e25783ec3e", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nixos-generators", - "type": "github" - } - }, "nixpkgs": { "locked": { - "lastModified": 1628203131, - "narHash": "sha256-jQgXeJ9NQQS0Eobb/qQOvS+RRULkqRikAeXkkFKOPDA=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "178da37860823d35e801c7df2f73d7866d3d598a", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "release-21.05", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1637593665, - "narHash": "sha256-R7jKS7A+0tZS8qD5pBr1UFcMiTdsw5bfoxgXbYsoWhM=", + "lastModified": 1638097282, + "narHash": "sha256-EXCzj9b8X/lqDPJapxZThIOKL5ASbpsJZ+8L1LnY1ig=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "98747f27ecfee70c8c97b195cbb94df80a074dda", + "rev": "78cb77b29d37a9663e05b61abb4fa09465da4b70", "type": "github" }, "original": { @@ -315,9 +59,8 @@ "root": { "inputs": { "agenix": "agenix", - "digga": "digga", - "home-manager": "home-manager_2", - "nixpkgs": "nixpkgs_2" + "home-manager": "home-manager", + "nixpkgs": "nixpkgs" } } }, diff --git a/flake.nix b/flake.nix index 790ce798..7c80e2e2 100644 --- a/flake.nix +++ b/flake.nix @@ -8,11 +8,9 @@ agenix.url = "github:ryantm/agenix"; agenix.inputs.nixpkgs.follows = "nixpkgs"; - - digga.url = "github:divnix/digga"; }; - outputs = inputs@{ self, nixpkgs, ... }: + outputs = inputs@{ self, nixpkgs, home-manager, ... }: let libExtended = nixpkgs.lib.extend (final: prev: (import ./lib { inherit inputs; lib = final; })); @@ -33,10 +31,17 @@ }; # 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. nix.extraOptions = '' experimental-features = nix-command flakes ''; }; + + userDefaultConfig = { + system = "x86_64-linux"; + }; in { # Exposes only my library with the custom functions to make it easier to include in other flakes. lib = import ./lib { inherit inputs; lib = nixpkgs.lib; }; @@ -50,5 +55,21 @@ # or not this is a good thing is debatable, I just want to test it. nixosModules = libExtended.mapAttrs (_: path: import path) (libExtended.filesToAttr ./modules); + + homeConfigurations = + let + excludedModules = [ + "config" # The common user-specific configurations. + "modules" # User-specific Nix modules. + ]; + in + libExtended.mapAttrs (user: path: + home-manager.lib.homeManagerConfiguration { + system = "x86_64-linux"; + configuration = import path; + homeDirectory = "/home/${user}"; + username = user; + }) + (libExtended.filterAttrs (n: v: !libExtended.elem n excludedModules) (libExtended.filesToAttr ./users)); }; } diff --git a/hosts/ni/README.adoc b/hosts/ni/README.adoc new file mode 100644 index 00000000..0aaf99ff --- /dev/null +++ b/hosts/ni/README.adoc @@ -0,0 +1,34 @@ += ni, my (only) workstation +:toc: + +My laptop. +I was about to have two computers but my desktop is broken ever since. +Whoops! + +I try to be minimal with my dependencies unlike last time. +`direnv`, `lorri`, and Flatpak are mostly enough for desktop needs. +(Which is Fedora Silverblue is good at! :)) + +I know partitioning is not your favorite part so here's one way to prepare the laptop with this config. + +[source, shell] +---- +# Preparing the partitions. +parted /dev/sda -- mklabel gpt +parted /dev/sda -- mkpart primary 512MiB -4GB +parted /dev/sda -- mkpart primary linux-swap -4GB 100% +parted /dev/sda -- mkpart ESP fat32 1MiB 512MiB +parted /dev/sda -- set 3 esp on + +# Setting up the filesystems. +mkfs.ext4 -L nixos /dev/sda1 +mkswap -L swap /dev/sda2 +mkfs.fat -F 32 -n boot /dev/sda3 + +# Mount the partitions before installation. +mount /dev/disk/by-label/nixos /mnt +mkdir -p /mnt/boot +mount /dev/disk/by-label/boot /mnt/boot +swapon /dev/disk/by-label/swap +---- + diff --git a/lib/default.nix b/lib/default.nix index 9102c617..55a3000b 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -117,6 +117,24 @@ in rec { ++ (lib.mapAttrsToList (n: v: import v) (filesToAttr ../modules)); }; + /* Return an attribute set of valid users from a given list of users. + + Signature: + list -> attrset + Where: + - `list` is a list of usernames as strings + - `attrset` is a set of valid users with the name as the key and the path as the value. + Example: + # Assuming only 'foo-dogsquared' is the existing user. + getUsers [ "foo-dogsquared" "archie" "brad" ] + => { foo-dogsquared = /home/foo-dogsquared/projects/nixos-config/users/foo-dogsquared; } + */ + getUsers = users: + let + userModules = filesToAttr ../users; + validUsers = lib.filter (user: lib.elem user (lib.attrNames userModules)) users; + in lib.filterAttrs (n: _: lib.elem n validUsers) userModules; + /* Create an attribute set from two lists (or a zip). Examples: diff --git a/modules/README.adoc b/modules/README.adoc new file mode 100644 index 00000000..d1bd2046 --- /dev/null +++ b/modules/README.adoc @@ -0,0 +1,62 @@ += Modules +:toc: + +These are the modules to be used for the system configuration. +For easier modularization, any user-specific configurations such as from link:https://github.com/nix-community/home-manager[home-manager] should be placed in link:../users/[`../users/` directory]. + +The modules are imported usually through `lib.filesToAttr`, allowing for easier structuring without modifying the index file of each module (i.e., `default.nix`). +(See the implementation for more details.) + +For example, take the following module folder structure... + +[source, tree] +---- +modules/ +├── themes/ +│   ├── a-happy-gnome/ +│   │   ├── default.nix +│   │   └── README.adoc +│   ├── a-sad-gnome/ +│   │   ├── default.nix +│   │   └── README.adoc +│   └── default.nix +├── specific/ +│   ├── borg.nix +│   └── prometheus.nix +├── agenix.nix +├── archiving.nix +├── desktop.nix +├── dev.nix +├── editors.nix +└── users.nix +---- + +...should have the following attribute set. + +[source, nix] +---- +{ + agenix = path/to/agenix.nix; + archiving = path/to/archiving.nix; + desktop = path/to/desktop.nix; + dev = path/to/dev.nix; + editors = path/to/editors.nix; + specific = { + borg = path/to/specific/borg.nix + prometheus = path/to/specific/prometheus.nix + }; + themes = path/to/themes; # Since it has a 'default.nix' detected, we're using it instead. + users = path/to/users.nix; +} +---- + +The resulting attribute set can be easily be used for importing. +Here's an example of a NixOS system created with the modules which can used for shared configuration between hosts. + +[source, nix] +---- +lib.nixosSystem { + system = "x86_64-linux"; + modules = lib.mapAttrsToList (name: path: import path) (lib.filesToAttr ./modules); +} +---- diff --git a/modules/agenix.nix b/modules/agenix.nix index 90f7ea83..ec37c1d2 100644 --- a/modules/agenix.nix +++ b/modules/agenix.nix @@ -4,7 +4,7 @@ let cfg = config.modules.agenix; in { options.modules.agenix.enable = - lib.mkEnableOption "Enable agenix on your system"; + lib.mkEnableOption "Automate agenix-related config on your system"; imports = [ inputs.agenix.nixosModules.age ]; config = lib.mkIf cfg.enable { diff --git a/modules/editors.nix b/modules/editors.nix index 00c8b2d7..2ce0743e 100644 --- a/modules/editors.nix +++ b/modules/editors.nix @@ -1,3 +1,4 @@ +# Your text editor war arsenal. { config, options, lib, pkgs, ... }: let cfg = config.modules.editors; diff --git a/modules/users.nix b/modules/users.nix index 45c0cdcc..7733e4ba 100644 --- a/modules/users.nix +++ b/modules/users.nix @@ -1,3 +1,4 @@ +# This enables home-manager specific configs and an easier modularization for user-specific configurations. { inputs, config, options, lib, ... }: let @@ -6,7 +7,22 @@ let users = lib.attrNames userModules; nonexistentUsers = lib.filter (name: !lib.elem name users) cfg.users; - validUsers = lib.filterAttrs (n: v: lib.elem n users) userModules; + + mkUser = user: path: + let + defaultConfig = { + home.username = user; + home.homeDirectory = "/home/${user}"; + }; + in + { + users.users.${user} = { + isNormalUser = true; + extraGroups = [ "wheel" ]; + }; + + home-manager.users.${user} = defaultConfig // import path; + }; in { options.modules.users = { @@ -17,7 +33,19 @@ in }; }; - imports = [ inputs.home-manager.nixosModules.home-manager ] ++ (lib.attrValues validUsers); + # FIXME: Recursion error when using `lib.getUsers cfg.users`. + # Time to study how Nix modules really work. + # The assertion is basically enough for this case. + imports = [ + # home-manager to enable user-specific config. + inputs.home-manager.nixosModules.home-manager + + # The global configuration for the home-manager module. + { + home-manager.useUserPackages = true; + home-manager.useGlobalPkgs = true; + } + ] ++ (lib.mapAttrsToList mkUser userModules); config = { assertions = [{ diff --git a/users/README.adoc b/users/README.adoc index 22fd1ff7..5fcab3fe 100644 --- a/users/README.adoc +++ b/users/README.adoc @@ -1,5 +1,21 @@ -= Users += Users configuration :toc: This is where user-specific configurations comes in. -Ideally, +Ideally, the configurations are link:https://nix-community.github.io/home-manager/[home-manager config]. +The configs should assume to be used as a configuration as `.config/nixpkgs/home.nix` (i.e., `home-manager.lib.homeManagerConfiguration`, `home-manager.users.${user}`, in your ordinary home-manager setup in a foreign distro). + +Here's an example of a sample user config placed in `users/hello.nix`. + +[source, nix] +---- +{ config, options, pkgs, lib, ... }: + +{ + programs.home-manager.enable = true; + programs.direnv.enable = true; + home.file.".npmrc".source = ./config/npmrc; +} +---- + +This is to be imported to `homeManagerConfiguration` in the flake outputs and when indicated from `config.modules.users.users` (e.g., `modules.users.users = [ "hello" ];`). diff --git a/users/config b/users/config new file mode 160000 index 00000000..9af98f21 --- /dev/null +++ b/users/config @@ -0,0 +1 @@ +Subproject commit 9af98f21d21f5118c241a7c4809ae3d2a390846d diff --git a/users/foo-dogsquared/default.nix b/users/foo-dogsquared/default.nix index 16d9be51..ccc9079e 100644 --- a/users/foo-dogsquared/default.nix +++ b/users/foo-dogsquared/default.nix @@ -1,12 +1,11 @@ { config, options, lib, pkgs, ... }: { - # Define a user account. Don't forget to set a password with ‘passwd’. - users.users.foo-dogsquared = { - isNormalUser = true; - extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. + programs.direnv.enable = true; + programs.git = { + enable = true; + lfs.enable = true; + userName = "foo-dogsquared"; + userEmail = "foo.dogsquared@gmail.com"; }; - - home-manager.useUserPackages = true; - home-manager.useGlobalPkgs = true; }