├── .gitignore ├── LICENSE.md ├── README.md ├── flake.lock ├── flake.nix ├── lib ├── network │ ├── default.nix │ └── test.nix ├── umports │ ├── default.nix │ └── test.nix └── users │ ├── default.nix │ └── test.nix ├── modules ├── allow-unfree │ ├── README.md │ └── default.nix ├── home-merger │ ├── README.md │ └── default.nix └── networking-privacy │ ├── default.nix │ ├── fixed.nix │ └── random.nix ├── pipelight.toml ├── public └── images │ └── nixos-tidy.png └── templates ├── commons ├── configuration.nix └── hardware-configuration.nix ├── home-merger ├── flake.lock ├── flake.nix └── my_module │ ├── default.nix │ └── home.nix ├── networking-privacy ├── flake.lock └── flake.nix └── umports ├── flake.lock ├── flake.nix └── my_module ├── default.nix └── home.nix /.gitignore: -------------------------------------------------------------------------------- 1 | # nixos artifacts 2 | .direnv 3 | .envrc 4 | result 5 | 6 | # cicd 7 | .pipelight 8 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | 61 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 62 | 63 | 0. This License applies to any program or other work which contains 64 | a notice placed by the copyright holder saying it may be distributed 65 | under the terms of this General Public License. The "Program", below, 66 | refers to any such program or work, and a "work based on the Program" 67 | means either the Program or any derivative work under copyright law: 68 | that is to say, a work containing the Program or a portion of it, 69 | either verbatim or with modifications and/or translated into another 70 | language. (Hereinafter, translation is included without limitation in 71 | the term "modification".) Each licensee is addressed as "you". 72 | 73 | Activities other than copying, distribution and modification are not 74 | covered by this License; they are outside its scope. The act of 75 | running the Program is not restricted, and the output from the Program 76 | is covered only if its contents constitute a work based on the 77 | Program (independent of having been made by running the Program). 78 | Whether that is true depends on what the Program does. 79 | 80 | 1. You may copy and distribute verbatim copies of the Program's 81 | source code as you receive it, in any medium, provided that you 82 | conspicuously and appropriately publish on each copy an appropriate 83 | copyright notice and disclaimer of warranty; keep intact all the 84 | notices that refer to this License and to the absence of any warranty; 85 | and give any other recipients of the Program a copy of this License 86 | along with the Program. 87 | 88 | You may charge a fee for the physical act of transferring a copy, and 89 | you may at your option offer warranty protection in exchange for a fee. 90 | 91 | 2. You may modify your copy or copies of the Program or any portion 92 | of it, thus forming a work based on the Program, and copy and 93 | distribute such modifications or work under the terms of Section 1 94 | above, provided that you also meet all of these conditions: 95 | 96 | a) You must cause the modified files to carry prominent notices 97 | stating that you changed the files and the date of any change. 98 | 99 | b) You must cause any work that you distribute or publish, that in 100 | whole or in part contains or is derived from the Program or any 101 | part thereof, to be licensed as a whole at no charge to all third 102 | parties under the terms of this License. 103 | 104 | c) If the modified program normally reads commands interactively 105 | when run, you must cause it, when started running for such 106 | interactive use in the most ordinary way, to print or display an 107 | announcement including an appropriate copyright notice and a 108 | notice that there is no warranty (or else, saying that you provide 109 | a warranty) and that users may redistribute the program under 110 | these conditions, and telling the user how to view a copy of this 111 | License. (Exception: if the Program itself is interactive but 112 | does not normally print such an announcement, your work based on 113 | the Program is not required to print an announcement.) 114 | 115 | These requirements apply to the modified work as a whole. If 116 | identifiable sections of that work are not derived from the Program, 117 | and can be reasonably considered independent and separate works in 118 | themselves, then this License, and its terms, do not apply to those 119 | sections when you distribute them as separate works. But when you 120 | distribute the same sections as part of a whole which is a work based 121 | on the Program, the distribution of the whole must be on the terms of 122 | this License, whose permissions for other licensees extend to the 123 | entire whole, and thus to each and every part regardless of who wrote it. 124 | 125 | Thus, it is not the intent of this section to claim rights or contest 126 | your rights to work written entirely by you; rather, the intent is to 127 | exercise the right to control the distribution of derivative or 128 | collective works based on the Program. 129 | 130 | In addition, mere aggregation of another work not based on the Program 131 | with the Program (or with a work based on the Program) on a volume of 132 | a storage or distribution medium does not bring the other work under 133 | the scope of this License. 134 | 135 | 3. You may copy and distribute the Program (or a work based on it, 136 | under Section 2) in object code or executable form under the terms of 137 | Sections 1 and 2 above provided that you also do one of the following: 138 | 139 | a) Accompany it with the complete corresponding machine-readable 140 | source code, which must be distributed under the terms of Sections 141 | 1 and 2 above on a medium customarily used for software interchange; or, 142 | 143 | b) Accompany it with a written offer, valid for at least three 144 | years, to give any third party, for a charge no more than your 145 | cost of physically performing source distribution, a complete 146 | machine-readable copy of the corresponding source code, to be 147 | distributed under the terms of Sections 1 and 2 above on a medium 148 | customarily used for software interchange; or, 149 | 150 | c) Accompany it with the information you received as to the offer 151 | to distribute corresponding source code. (This alternative is 152 | allowed only for noncommercial distribution and only if you 153 | received the program in object code or executable form with such 154 | an offer, in accord with Subsection b above.) 155 | 156 | The source code for a work means the preferred form of the work for 157 | making modifications to it. For an executable work, complete source 158 | code means all the source code for all modules it contains, plus any 159 | associated interface definition files, plus the scripts used to 160 | control compilation and installation of the executable. However, as a 161 | special exception, the source code distributed need not include 162 | anything that is normally distributed (in either source or binary 163 | form) with the major components (compiler, kernel, and so on) of the 164 | operating system on which the executable runs, unless that component 165 | itself accompanies the executable. 166 | 167 | If distribution of executable or object code is made by offering 168 | access to copy from a designated place, then offering equivalent 169 | access to copy the source code from the same place counts as 170 | distribution of the source code, even though third parties are not 171 | compelled to copy the source along with the object code. 172 | 173 | 4. You may not copy, modify, sublicense, or distribute the Program 174 | except as expressly provided under this License. Any attempt 175 | otherwise to copy, modify, sublicense or distribute the Program is 176 | void, and will automatically terminate your rights under this License. 177 | However, parties who have received copies, or rights, from you under 178 | this License will not have their licenses terminated so long as such 179 | parties remain in full compliance. 180 | 181 | 5. You are not required to accept this License, since you have not 182 | signed it. However, nothing else grants you permission to modify or 183 | distribute the Program or its derivative works. These actions are 184 | prohibited by law if you do not accept this License. Therefore, by 185 | modifying or distributing the Program (or any work based on the 186 | Program), you indicate your acceptance of this License to do so, and 187 | all its terms and conditions for copying, distributing or modifying 188 | the Program or works based on it. 189 | 190 | 6. Each time you redistribute the Program (or any work based on the 191 | Program), the recipient automatically receives a license from the 192 | original licensor to copy, distribute or modify the Program subject to 193 | these terms and conditions. You may not impose any further 194 | restrictions on the recipients' exercise of the rights granted herein. 195 | You are not responsible for enforcing compliance by third parties to 196 | this License. 197 | 198 | 7. If, as a consequence of a court judgment or allegation of patent 199 | infringement or for any other reason (not limited to patent issues), 200 | conditions are imposed on you (whether by court order, agreement or 201 | otherwise) that contradict the conditions of this License, they do not 202 | excuse you from the conditions of this License. If you cannot 203 | distribute so as to satisfy simultaneously your obligations under this 204 | License and any other pertinent obligations, then as a consequence you 205 | may not distribute the Program at all. For example, if a patent 206 | license would not permit royalty-free redistribution of the Program by 207 | all those who receive copies directly or indirectly through you, then 208 | the only way you could satisfy both it and this License would be to 209 | refrain entirely from distribution of the Program. 210 | 211 | If any portion of this section is held invalid or unenforceable under 212 | any particular circumstance, the balance of the section is intended to 213 | apply and the section as a whole is intended to apply in other 214 | circumstances. 215 | 216 | It is not the purpose of this section to induce you to infringe any 217 | patents or other property right claims or to contest validity of any 218 | such claims; this section has the sole purpose of protecting the 219 | integrity of the free software distribution system, which is 220 | implemented by public license practices. Many people have made 221 | generous contributions to the wide range of software distributed 222 | through that system in reliance on consistent application of that 223 | system; it is up to the author/donor to decide if he or she is willing 224 | to distribute software through any other system and a licensee cannot 225 | impose that choice. 226 | 227 | This section is intended to make thoroughly clear what is believed to 228 | be a consequence of the rest of this License. 229 | 230 | 8. If the distribution and/or use of the Program is restricted in 231 | certain countries either by patents or by copyrighted interfaces, the 232 | original copyright holder who places the Program under this License 233 | may add an explicit geographical distribution limitation excluding 234 | those countries, so that distribution is permitted only in or among 235 | countries not thus excluded. In such case, this License incorporates 236 | the limitation as if written in the body of this License. 237 | 238 | 9. The Free Software Foundation may publish revised and/or new versions 239 | of the General Public License from time to time. Such new versions will 240 | be similar in spirit to the present version, but may differ in detail to 241 | address new problems or concerns. 242 | 243 | Each version is given a distinguishing version number. If the Program 244 | specifies a version number of this License which applies to it and "any 245 | later version", you have the option of following the terms and conditions 246 | either of that version or of any later version published by the Free 247 | Software Foundation. If the Program does not specify a version number of 248 | this License, you may choose any version ever published by the Free Software 249 | Foundation. 250 | 251 | 10. If you wish to incorporate parts of the Program into other free 252 | programs whose distribution conditions are different, write to the author 253 | to ask for permission. For software which is copyrighted by the Free 254 | Software Foundation, write to the Free Software Foundation; we sometimes 255 | make exceptions for this. Our decision will be guided by the two goals 256 | of preserving the free status of all derivatives of our free software and 257 | of promoting the sharing and reuse of software generally. 258 | 259 | NO WARRANTY 260 | 261 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 262 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 263 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 264 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 265 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 266 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 267 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 268 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 269 | REPAIR OR CORRECTION. 270 | 271 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 272 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 273 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 274 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 275 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 276 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 277 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 278 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 279 | POSSIBILITY OF SUCH DAMAGES. 280 | 281 | END OF TERMS AND CONDITIONS 282 | 283 | How to Apply These Terms to Your New Programs 284 | 285 | If you develop a new program, and you want it to be of the greatest 286 | possible use to the public, the best way to achieve this is to make it 287 | free software which everyone can redistribute and change under these terms. 288 | 289 | To do so, attach the following notices to the program. It is safest 290 | to attach them to the start of each source file to most effectively 291 | convey the exclusion of warranty; and each file should have at least 292 | the "copyright" line and a pointer to where the full notice is found. 293 | 294 | 295 | Copyright (C) 296 | 297 | This program is free software; you can redistribute it and/or modify 298 | it under the terms of the GNU General Public License as published by 299 | the Free Software Foundation; either version 2 of the License, or 300 | (at your option) any later version. 301 | 302 | This program is distributed in the hope that it will be useful, 303 | but WITHOUT ANY WARRANTY; without even the implied warranty of 304 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 305 | GNU General Public License for more details. 306 | 307 | You should have received a copy of the GNU General Public License along 308 | with this program; if not, write to the Free Software Foundation, Inc., 309 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Lesser General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nixos-tidy - Make filesystem based configurations. 2 | 3 | 4 | 5 | Modules and library for filesystem based configuration. 6 | 7 | ## Install (add to your config). 8 | 9 | Add the flake to your existing configuration. 10 | 11 | ```nix 12 | # flake.nix 13 | inputs = { 14 | nixos-tidy = { 15 | url = "github:pipelight/nixos-tidy"; 16 | inputs.nixpkgs.follows = "nixpkgs"; 17 | }; 18 | }; 19 | ``` 20 | 21 | ```nix 22 | # flake.nix 23 | outputs = { 24 | self, 25 | nixpkgs, 26 | ... 27 | }: { 28 | nixosConfiguration = { 29 | default = pkgs.lib.nixosSystem { 30 | modules = [ 31 | # pick some modules 32 | inputs.nixos-tidy.nixosModules.home-merger 33 | ({ 34 | config, 35 | pkgs, 36 | lib, 37 | inputs, 38 | ... 39 | }: let 40 | # Use functions from library. 41 | slib = inputs.nixos-tidy.lib; 42 | in { 43 | 44 | }) 45 | ]; 46 | }; 47 | } 48 | }; 49 | ``` 50 | 51 | ## Examples 52 | 53 | - Minimalist 54 | 55 | Find many minimalists examples self-contained in a single `flake.nix` file, 56 | in the [templates directory](https://github.com/pipelight/nixos-tidy/blob/master/templates/). 57 | 58 | - Real world 59 | 60 | And a complete working example at [crocuda.nixos](https://github.com/pipelight/crocuda.nixos). 61 | Where all the magic happens in `default.nix`. 62 | 63 | ## A single Top-level imports 🤌 (umports). 64 | 65 | Use `slib = inputs.nixos-tidy.lib` 66 | 67 | Get rid of **imports** statements everywhere. 68 | You only need **one top-level imports** statement. 69 | 70 | It imports recursively all the files from inside a directory. 71 | 72 | ### Nix only (without home-manager) 73 | 74 | ```nix 75 | # flake.nix 76 | imports = let 77 | slib = inputs.nixos-tidy.lib; 78 | in 79 | [] 80 | # Import all nixos modules recursively 81 | ++ slib.umportNixModules { 82 | paths = [ 83 | inputs.anOtherFlake.nixosModules.default 84 | ./. 85 | ]; 86 | exclude = [ 87 | # Do not forget to exclude current file 88 | # and flake definition. 89 | ./default.nix 90 | ./flake.nix 91 | ]; 92 | }; 93 | ``` 94 | 95 | ### With home-manager 96 | 97 | It enables a most wanted separation of concerns, 98 | where home-manager modules and nix modules 99 | can lay in the same directory. 100 | 101 | ```sh 102 | . 103 | ├── gnome 104 | │   ├── default.nix 105 | │   ├── test.nix 106 | │   └── home.nix 107 | ├── hyprland 108 | │  ├── default.nix 109 | │   ├── test.nix 110 | │  └── home.nix 111 | └── flake.nix # put boilerplate code at the flake top-level. 112 | ``` 113 | 114 | ```nix 115 | imports = let 116 | slib = inputs.nixos-tidy.lib; 117 | in 118 | [] 119 | # Import all nixos modules recursively 120 | ++ slib.umportNixModules { 121 | paths = [ 122 | inputs.anOtherFlake.nixosModules.default 123 | ./. 124 | ]; 125 | exclude = [ 126 | # Do not forget to exclude current file 127 | # and flake definition. 128 | ./default.nix 129 | ./flake.nix 130 | ] 131 | } 132 | ++ slib.umportHomeModules { 133 | paths = [ 134 | inputs.nur.modules.homeManager.default 135 | ./. 136 | ]; 137 | } 138 | # Home-merger options 139 | { 140 | users = ["anon"]; 141 | }; 142 | ``` 143 | 144 | ### File naming constraints. 145 | 146 | See the [template flake with umports](https://github.com/pipelight/nixos-tidy/blob/master/templates/umports/flake.nix) for a working example (with home-manager). 147 | 148 | Umports makes the distinctions between module types based on 149 | filenames. 150 | So be sure to have your filenames checked. 151 | 152 | Nix: \*.nix 153 | Home-manager: home.nix || home.\*.nix || home\_\*.nix 154 | Unit-tests: test.nix || test.\*.nix || test\_\*.nix. 155 | 156 | ## A flexible home-manager (Home-merger). 157 | 158 | Use `inputs.nixos-tidy.nixosModules.home-merger`. 159 | Checkout module definition for 160 | [options list](https://github.com/pipelight/nixos-tidy/blob/master/modules/home-merger/default.nix). 161 | 162 | Home-merger is a wrapper around home-manager that you can call multiple times, 163 | in order to scatter user definitions in separate files. 164 | 165 | ### Top-level import (Umports) 166 | 167 | - Use it to split user definition. 168 | 169 | ```nix 170 | # file_1.nix 171 | home-merger = { 172 | users = ["alice"]; 173 | umports.paths = [ 174 | ./alice_modules 175 | ]; 176 | }; 177 | ``` 178 | 179 | ```nix 180 | # file_2.nix 181 | home-merger = { 182 | users = ["bob"]; 183 | extraSpecialArgs = {inherit inputs;}; 184 | imports = [ 185 | inputs.anOtherModule.homeManagerModules.default 186 | ]; 187 | umports.paths = [ 188 | ./bob_modules 189 | ]; 190 | }; 191 | ``` 192 | 193 | - Or use it 194 | to import a `home.nix` module 195 | from an adjacent `default.nix` module. 196 | 197 | ```sh 198 | . 199 | └── fish 200 |    ├── default.nix 201 |     └── home.nix 202 | ``` 203 | 204 | ```nix 205 | # fish/default.nix 206 | programs.fish.enable = true; 207 | 208 | home-merger = { 209 | users = ["bob"]; 210 | umports.paths = [ 211 | ./home.nix 212 | ]; 213 | }; 214 | ``` 215 | 216 | ```nix 217 | # fish/home.nix 218 | home.programs.fish.enable = true; 219 | ``` 220 | 221 | ## Allow-unfree 222 | 223 | Use `inputs.nixos-tidy.nixosModules.allow-unfree` 224 | 225 | Cherry-pick unfree software exceptions with regexes. 226 | 227 | ```nix 228 | #default.nix 229 | allow-unfree = [ 230 | # use regexes 231 | "nvidia-.*" 232 | "cuda.*" 233 | ]; 234 | ``` 235 | 236 | ## Network privacy (ipv6) 237 | 238 | Use `inputs.nixos-tidy.nixosModules.networking-privacy` 239 | 240 | Not released yet. 241 | Only on dev branch. 242 | 243 | Strengthen ipv6 privacy configuration for 244 | Linux kernel, 245 | NetworkManager, 246 | openvswitch, 247 | static configuration 248 | and systemd-networkd. 249 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "inputs": { 5 | "systems": "systems" 6 | }, 7 | "locked": { 8 | "lastModified": 1731533236, 9 | "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", 10 | "owner": "numtide", 11 | "repo": "flake-utils", 12 | "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "numtide", 17 | "repo": "flake-utils", 18 | "type": "github" 19 | } 20 | }, 21 | "home-manager": { 22 | "inputs": { 23 | "nixpkgs": [ 24 | "nixpkgs" 25 | ] 26 | }, 27 | "locked": { 28 | "lastModified": 1741955947, 29 | "narHash": "sha256-2lbURKclgKqBNm7hVRtWh0A7NrdsibD0EaWhahUVhhY=", 30 | "owner": "nix-community", 31 | "repo": "home-manager", 32 | "rev": "4e12151c9e014e2449e0beca2c0e9534b96a26b4", 33 | "type": "github" 34 | }, 35 | "original": { 36 | "owner": "nix-community", 37 | "repo": "home-manager", 38 | "type": "github" 39 | } 40 | }, 41 | "lix": { 42 | "flake": false, 43 | "locked": { 44 | "lastModified": 1732112222, 45 | "narHash": "sha256-H7GN4++a4vE49SUNojZx+FSk4mmpb2ifJUtJMJHProI=", 46 | "ref": "refs/heads/main", 47 | "rev": "66f6dbda32959dd5cf3a9aaba15af72d037ab7ff", 48 | "revCount": 16513, 49 | "type": "git", 50 | "url": "https://git.lix.systems/lix-project/lix.git" 51 | }, 52 | "original": { 53 | "type": "git", 54 | "url": "https://git.lix.systems/lix-project/lix.git" 55 | } 56 | }, 57 | "lix-unit": { 58 | "inputs": { 59 | "lix": "lix", 60 | "nix-github-actions": "nix-github-actions", 61 | "nixpkgs": [ 62 | "nixpkgs" 63 | ], 64 | "treefmt-nix": "treefmt-nix" 65 | }, 66 | "locked": { 67 | "lastModified": 1733631578, 68 | "narHash": "sha256-9R24jNsEFAnwouTxC+UH/cVqyyNgeXsdYwRd6CBDgYk=", 69 | "owner": "adisbladis", 70 | "repo": "lix-unit", 71 | "rev": "ff4bfb24cf423c1427adbf62a28f76796f96de7d", 72 | "type": "github" 73 | }, 74 | "original": { 75 | "owner": "adisbladis", 76 | "repo": "lix-unit", 77 | "type": "github" 78 | } 79 | }, 80 | "nix-github-actions": { 81 | "inputs": { 82 | "nixpkgs": [ 83 | "lix-unit", 84 | "nixpkgs" 85 | ] 86 | }, 87 | "locked": { 88 | "lastModified": 1731952509, 89 | "narHash": "sha256-p4gB3Rhw8R6Ak4eMl8pqjCPOLCZRqaehZxdZ/mbFClM=", 90 | "owner": "nix-community", 91 | "repo": "nix-github-actions", 92 | "rev": "7b5f051df789b6b20d259924d349a9ba3319b226", 93 | "type": "github" 94 | }, 95 | "original": { 96 | "owner": "nix-community", 97 | "repo": "nix-github-actions", 98 | "type": "github" 99 | } 100 | }, 101 | "nixpkgs": { 102 | "locked": { 103 | "lastModified": 1742136038, 104 | "narHash": "sha256-DDe16FJk18sadknQKKG/9FbwEro7A57tg9vB5kxZ8kY=", 105 | "owner": "nixos", 106 | "repo": "nixpkgs", 107 | "rev": "a1185f4064c18a5db37c5c84e5638c78b46e3341", 108 | "type": "github" 109 | }, 110 | "original": { 111 | "owner": "nixos", 112 | "ref": "nixos-24.11", 113 | "repo": "nixpkgs", 114 | "type": "github" 115 | } 116 | }, 117 | "root": { 118 | "inputs": { 119 | "flake-utils": "flake-utils", 120 | "home-manager": "home-manager", 121 | "lix-unit": "lix-unit", 122 | "nixpkgs": "nixpkgs" 123 | } 124 | }, 125 | "systems": { 126 | "locked": { 127 | "lastModified": 1681028828, 128 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 129 | "owner": "nix-systems", 130 | "repo": "default", 131 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 132 | "type": "github" 133 | }, 134 | "original": { 135 | "owner": "nix-systems", 136 | "repo": "default", 137 | "type": "github" 138 | } 139 | }, 140 | "treefmt-nix": { 141 | "inputs": { 142 | "nixpkgs": [ 143 | "lix-unit", 144 | "nixpkgs" 145 | ] 146 | }, 147 | "locked": { 148 | "lastModified": 1732111664, 149 | "narHash": "sha256-XWHuPWcP59QnHEewdZJXBX1TA2lAP78Vz4daG6tfIr4=", 150 | "owner": "numtide", 151 | "repo": "treefmt-nix", 152 | "rev": "62003fdad7a5ab7b6af3ea9bd7290e4c220277d0", 153 | "type": "github" 154 | }, 155 | "original": { 156 | "owner": "numtide", 157 | "repo": "treefmt-nix", 158 | "type": "github" 159 | } 160 | } 161 | }, 162 | "root": "root", 163 | "version": 7 164 | } 165 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Nixos modules utilities"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; 6 | flake-utils.url = "github:numtide/flake-utils"; 7 | home-manager = { 8 | url = "github:nix-community/home-manager"; 9 | inputs.nixpkgs.follows = "nixpkgs"; 10 | }; 11 | # Testing 12 | lix-unit = { 13 | url = "github:adisbladis/lix-unit"; 14 | inputs.nixpkgs.follows = "nixpkgs"; 15 | }; 16 | }; 17 | 18 | outputs = { 19 | self, 20 | nixpkgs, 21 | ... 22 | } @ inputs: rec { 23 | templates = { 24 | default = { 25 | path = ./templates/umports/default.nix; 26 | description = '' 27 | Top-level umports for static config generation. 28 | ''; 29 | }; 30 | }; 31 | 32 | lib = slib; 33 | slib = 34 | {} 35 | // (import ./lib/umports { 36 | inherit (nixpkgs) lib; 37 | }) 38 | // (import ./lib/users { 39 | inherit (nixpkgs) lib; 40 | }) 41 | // (import ./lib/network { 42 | inherit (nixpkgs) lib; 43 | }); 44 | 45 | nixosModules = { 46 | home-merger = ./modules/home-merger/default.nix; 47 | allow-unfree = ./modules/allow-unfree/default.nix; 48 | # networking-privacy = ./modules/networking-privacy/default.nix; 49 | }; 50 | 51 | ## Unit tests 52 | tests = 53 | (import ./lib/umports/test.nix { 54 | inherit slib; 55 | inherit (nixpkgs) lib; 56 | }) 57 | // (import ./lib/users/test.nix { 58 | inherit slib; 59 | inherit (nixpkgs) lib; 60 | }) 61 | // (import ./lib/network/test.nix { 62 | inherit slib; 63 | inherit (nixpkgs) lib; 64 | }); 65 | }; 66 | } 67 | -------------------------------------------------------------------------------- /lib/network/default.nix: -------------------------------------------------------------------------------- 1 | {lib, ...}: 2 | with lib; let 3 | ## Functions 4 | # Generate a 128bits hash from a secret 5 | _str_to_hash = string: 6 | builtins.substring 0 32 (builtins.hashString "sha256" string); 7 | 8 | # Add a ":" each n(step) characters 9 | _hash_to_address = string: step: 10 | lib.concatStringsSep ":" ( 11 | lib.forEach (lib.range 0 (lib.stringLength string / step - 1)) ( 12 | i: builtins.substring (i * step) step string 13 | ) 14 | ); 15 | # Generate a mac address from a sting 16 | str_to_mac = string: let 17 | hash = builtins.substring 0 12 (_str_to_hash string); 18 | vec_hash = stringToCharacters hash; 19 | 20 | sanitized_hash = concatStrings ( 21 | imap0 (i: v: 22 | if i == 1 23 | then "2" # SLAP quadrant (AAI) 24 | else v) (stringToCharacters hash) 25 | ); 26 | step = 2; 27 | mac = _hash_to_address sanitized_hash step; 28 | in 29 | mac; 30 | 31 | # Generate an ipv6 from a string 32 | str_to_ipv6 = string: let 33 | hash = _str_to_hash string; 34 | step = 4; 35 | ipv6 = _hash_to_address hash step; 36 | in 37 | ipv6; 38 | 39 | # Generate an ipv6 iid from a string 40 | str_to_iid = string: let 41 | # Take only the iid part of the ipv6 42 | hash = builtins.substring 16 16 (_str_to_hash string); 43 | step = 4; 44 | iid = _hash_to_address hash step; 45 | in 46 | iid; 47 | # ## Globals 48 | # iid = cfg.network.privacy.ipv6.iid; 49 | # computed_iid = str_to_iid cfg.network.privacy.ipv6.secret; 50 | # token = 51 | # if (!isNull iid) 52 | # then iid 53 | # else computed_iid; 54 | # 55 | # computed_mac = str_to_mac cfg.network.privacy.ipv6.secret; 56 | in rec { 57 | inherit _str_to_hash; 58 | 59 | inherit str_to_mac; 60 | inherit str_to_ipv6; 61 | } 62 | -------------------------------------------------------------------------------- /lib/network/test.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | slib, 4 | ... 5 | }: 6 | with slib; let 7 | secret = "vm-nixos"; 8 | hash = "70cc2860c2371bf7872597545f76774c"; 9 | in { 10 | testStrToHash = { 11 | expr = _str_to_hash secret; 12 | expected = hash; 13 | }; 14 | testHashToMac = { 15 | expr = str_to_mac secret; 16 | expected = "72:cc:28:60:c2:37"; 17 | }; 18 | testHashToIpv6 = { 19 | expr = str_to_ipv6 secret; 20 | expected = "70cc:2860:c237:1bf7:8725:9754:5f76:774c"; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /lib/umports/default.nix: -------------------------------------------------------------------------------- 1 | /* 2 | Fork of **Yunfachi's Umport** module. 3 | https://github.com/yunfachi/nypkgs/blob/master/lib/umport.nix 4 | 5 | This fork is a heavy rework of yunfachi's umport function. 6 | Mainly, it has been splited into understandable chunks. 7 | 8 | Features: 9 | - integrates home_merger. 10 | */ 11 | {lib}: let 12 | ## Filters 13 | /* 14 | Remove everything that is not a path from list. 15 | */ 16 | _getPaths = list: 17 | with lib; 18 | unique ( 19 | filter isPath list 20 | ); 21 | 22 | /* 23 | Remove everything that is a path from list. 24 | */ 25 | _getModules = list: 26 | with lib; 27 | unique ( 28 | filter _isNotPath list 29 | ); 30 | _isNotPath = raw: 31 | with lib; 32 | !isPath raw; 33 | 34 | /* 35 | Check if path is in the excluded file list. 36 | */ 37 | _isExcluded = { 38 | path, 39 | exclude ? [], 40 | } @ args: 41 | with lib; 42 | with fileset; let 43 | excludedFiles = filter (path: pathIsRegularFile path) exclude; 44 | excludedDirs = filter (path: pathIsDirectory path) exclude; 45 | in 46 | if isNull exclude 47 | then false 48 | else if elem path excludedFiles 49 | then true 50 | else (filter (excludedDir: lib.path.hasPrefix excludedDir path) excludedDirs) != []; 51 | 52 | /* 53 | A filter for nix modules files only. 54 | - follow this globbing pattern *.nix 55 | - rejects home modules *.home.*.nix 56 | */ 57 | _filterNixModules = {exclude ? []} @ args: path: 58 | with lib; 59 | with fileset; 60 | pathIsRegularFile path 61 | && hasSuffix ".nix" (builtins.toString path) 62 | # Reject home modules 63 | && !(hasInfix "home." (builtins.toString path) 64 | || hasInfix "home_" (builtins.toString path)) 65 | && !_isExcluded { 66 | inherit exclude; 67 | inherit path; 68 | }; 69 | 70 | /* 71 | A filter for home modules files only 72 | - follows this globbing pattern home.*.nix 73 | */ 74 | _filterHomeModules = {exclude ? []} @ args: path: 75 | with lib; 76 | with fileset; 77 | pathIsRegularFile path 78 | && hasSuffix ".nix" (builtins.toString path) 79 | && (hasInfix "home." (builtins.toString path) 80 | || hasInfix "home_" (builtins.toString path)) 81 | && !_isExcluded { 82 | inherit exclude; 83 | inherit path; 84 | }; 85 | 86 | /* 87 | A filter for home modules files only 88 | - follows this globbing pattern test.*.nix 89 | */ 90 | _filterTestModules = {exclude ? []} @ args: path: 91 | with lib; 92 | with fileset; 93 | pathIsRegularFile path 94 | && hasSuffix ".nix" (builtins.toString path) 95 | && (hasInfix "test." (builtins.toString path) 96 | || hasInfix "test_" (builtins.toString path)) 97 | # Reject home modules 98 | && (!hasInfix "home." (builtins.toString path) 99 | || !hasInfix "home_" (builtins.toString path)) 100 | && !_isExcluded { 101 | inherit exclude; 102 | inherit path; 103 | }; 104 | 105 | ## Getters 106 | 107 | /* 108 | Return a list of every files from paths. 109 | 110 | Usually you want top level import with. 111 | 112 | - import every path from calling site 113 | `paths = [./.]` 114 | - ignore current file to avoid infinite recursion 115 | `exclude = [./default.nix]` 116 | 117 | ```nix 118 | import = getNixModules { paths = [./.] exclude = [./default.nix]} 119 | ```` 120 | */ 121 | getNixModules = { 122 | paths ? [], 123 | exclude ? [], 124 | } @ args: 125 | with lib; 126 | with fileset; 127 | unique ( 128 | filter 129 | (_filterNixModules { 130 | inherit exclude; 131 | }) 132 | (concatMap (path: toList path) paths) 133 | ); 134 | 135 | umportNixModules = { 136 | paths ? [], 137 | exclude ? [], 138 | } @ args: 139 | with lib; 140 | with fileset; let 141 | sanitized_paths = _getPaths paths; 142 | modules = _getModules paths; 143 | full_list = 144 | [] 145 | ++ getNixModules { 146 | inherit exclude; 147 | paths = sanitized_paths; 148 | } 149 | ++ modules; 150 | in 151 | full_list; 152 | 153 | /* 154 | Return a list of every home files from paths. 155 | 156 | Ignores `default.nix` and *.nix by default 157 | so no need to add `exclude = [./default.nix]` 158 | 159 | ```nix 160 | import = getHomeModules { paths = [./.]} 161 | ```` 162 | */ 163 | getHomeModules = { 164 | paths ? [], 165 | exclude ? [], 166 | } @ args: 167 | with lib; 168 | with fileset; 169 | unique ( 170 | filter 171 | (_filterHomeModules { 172 | inherit exclude; 173 | }) 174 | (concatMap (path: toList path) paths) 175 | ); 176 | 177 | umportHomeModules = { 178 | paths ? [], 179 | exclude ? [], 180 | } @ getArgs: { 181 | users ? ["anon"], 182 | stateVersion ? "25.05", 183 | useGlobalPkgs ? true, 184 | extraSpecialArgs ? {}, 185 | imports ? [], 186 | } @ homeArgs: 187 | with lib; 188 | with fileset; let 189 | sanitized_paths = _getPaths paths; 190 | modules = _getModules paths; 191 | full_list = 192 | [] 193 | ++ (getHomeModules { 194 | inherit exclude; 195 | paths = sanitized_paths; 196 | }) 197 | ++ modules; 198 | in 199 | [] 200 | ++ [(_mkHydratedHomeModuleWrapper homeArgs full_list)]; 201 | 202 | _mkHydratedHomeModuleWrapper = { 203 | users ? ["anon"], 204 | stateVersion ? "25.05", 205 | useGlobalPkgs ? true, 206 | extraSpecialArgs ? {}, 207 | imports ? [], 208 | } @ homeArgs: list: 209 | _mkHomeModuleWrapper 210 | { 211 | inherit users stateVersion useGlobalPkgs extraSpecialArgs; 212 | imports = 213 | [] 214 | ++ imports 215 | ++ list; 216 | }; 217 | 218 | /* 219 | Make a top level module to: 220 | - import every home-manager modules files. 221 | - apply modules to user list. 222 | */ 223 | _mkHomeModuleWrapper = { 224 | users ? ["anon"], 225 | stateVersion ? "25.05", 226 | useGlobalPkgs ? true, 227 | extraSpecialArgs ? {}, 228 | imports ? [], 229 | } @ homeArgs: { 230 | home-manager = 231 | { 232 | inherit useGlobalPkgs extraSpecialArgs; 233 | } 234 | // builtins.listToAttrs ( 235 | builtins.map (u: { 236 | name = "users"; 237 | value = { 238 | ${u} = { 239 | inherit imports; 240 | home.stateVersion = stateVersion; 241 | }; 242 | }; 243 | }) 244 | users 245 | ); 246 | }; 247 | 248 | /* 249 | Return a list of every test files from paths. 250 | 251 | ```nix 252 | import = getTestModules { paths = [./.]} 253 | ```` 254 | */ 255 | umportTestModules = getTestModules; 256 | getTestModules = { 257 | paths ? [], 258 | exclude ? [], 259 | } @ args: 260 | with lib; 261 | with fileset; 262 | unique ( 263 | filter 264 | (_filterNixModules { 265 | inherit exclude; 266 | }) 267 | (concatMap (path: toList path) paths) 268 | ); 269 | in { 270 | inherit _isExcluded; 271 | inherit _getPaths; 272 | inherit _getModules; 273 | 274 | inherit getNixModules; 275 | inherit getHomeModules; 276 | inherit getTestModules; 277 | 278 | inherit _mkHydratedHomeModuleWrapper; 279 | inherit _mkHomeModuleWrapper; 280 | 281 | inherit umportNixModules; 282 | inherit umportTestModules; 283 | 284 | inherit umportHomeModules; 285 | } 286 | -------------------------------------------------------------------------------- /lib/umports/test.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | slib, 4 | ... 5 | }: 6 | with slib; { 7 | testGetPaths = { 8 | expr = _getPaths [../../templates/umports]; 9 | expected = [ 10 | ../../templates/umports 11 | ]; 12 | }; 13 | testGetModules = { 14 | expr = _getModules [../../templates/umports]; 15 | expected = []; 16 | }; 17 | /* 18 | Test umport with a top directory. 19 | */ 20 | testGetNixModules = { 21 | expr = getNixModules { 22 | paths = [../../templates/umports]; 23 | }; 24 | expected = [ 25 | ../../templates/umports/flake.nix 26 | ../../templates/umports/my_module/default.nix 27 | ]; 28 | }; 29 | 30 | /* 31 | Test umport with a top directory and exclude list. 32 | */ 33 | testGetNixModulesExclude = { 34 | expr = getNixModules { 35 | paths = [../../templates/umports]; 36 | exclude = [../../templates/umports/my_module]; 37 | }; 38 | expected = [ 39 | ../../templates/umports/flake.nix 40 | ]; 41 | }; 42 | 43 | /* 44 | Test umport home with a top directory. 45 | */ 46 | testGetHomeModules = { 47 | expr = getHomeModules { 48 | paths = [../../templates/umports]; 49 | }; 50 | expected = [ 51 | ../../templates/umports/my_module/home.nix 52 | ]; 53 | }; 54 | 55 | testMkHomeModuleWrapper = { 56 | expr = _mkHomeModuleWrapper {}; 57 | expected = { 58 | home-manager = { 59 | useGlobalPkgs = true; 60 | extraSpecialArgs = {}; 61 | users = { 62 | anon = { 63 | imports = []; 64 | home.stateVersion = "25.05"; 65 | }; 66 | }; 67 | }; 68 | }; 69 | }; 70 | testMkHydratedHomeModuleWrapper = { 71 | expr = 72 | _mkHydratedHomeModuleWrapper 73 | {} 74 | [../../templates/umports/my_module/home.nix]; 75 | expected = { 76 | home-manager = { 77 | useGlobalPkgs = true; 78 | extraSpecialArgs = {}; 79 | users = { 80 | anon = { 81 | imports = [ 82 | ../../templates/umports/my_module/home.nix 83 | ]; 84 | home.stateVersion = "25.05"; 85 | }; 86 | }; 87 | }; 88 | }; 89 | }; 90 | } 91 | -------------------------------------------------------------------------------- /lib/users/default.nix: -------------------------------------------------------------------------------- 1 | {lib}: let 2 | userAddMany = user_list: { 3 | users.users = 4 | {} 5 | // builtins.listToAttrs ( 6 | builtins.map (user: { 7 | name = user; 8 | value = { 9 | isNormalUser = true; 10 | }; 11 | }) 12 | user_list 13 | ); 14 | }; 15 | userAddMany_system = user_list: { 16 | users.users = 17 | {} 18 | // builtins.listToAttrs ( 19 | builtins.map (user: { 20 | name = user; 21 | value = { 22 | isSystemUser = true; 23 | }; 24 | }) 25 | user_list 26 | ); 27 | }; 28 | 29 | add_users_to_groups = user_list: group_list: { 30 | users.groups = 31 | {} 32 | // builtins.listToAttrs ( 33 | builtins.map (group: { 34 | name = group; 35 | value = { 36 | members = user_list; 37 | }; 38 | }) 39 | group_list 40 | ); 41 | }; 42 | 43 | ensureUsers = cfg: users: let 44 | mustCreate = 45 | builtins.filter 46 | ( 47 | username: 48 | # if true 49 | if !builtins.hasAttr "${username}" cfg.users.users 50 | then true 51 | else false 52 | ) 53 | users; 54 | in 55 | userAddMany mustCreate; 56 | in { 57 | inherit userAddMany; 58 | inherit userAddMany_system; 59 | inherit add_users_to_groups; 60 | inherit ensureUsers; 61 | } 62 | -------------------------------------------------------------------------------- /lib/users/test.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | slib, 4 | ... 5 | }: 6 | with slib; { 7 | testMkUser = { 8 | expr = userAddMany ["alice" "bob"]; 9 | expected = { 10 | users.users = { 11 | alice = { 12 | isNormalUser = true; 13 | }; 14 | bob = { 15 | isNormalUser = true; 16 | }; 17 | }; 18 | }; 19 | }; 20 | testMkSystemUser = { 21 | expr = userAddMany_system ["alice" "bob"]; 22 | expected = { 23 | users.users = { 24 | alice = { 25 | isSystemUser = true; 26 | }; 27 | bob = { 28 | isSystemUser = true; 29 | }; 30 | }; 31 | }; 32 | }; 33 | testAddUserToGroup = { 34 | expr = add_users_to_groups ["alice" "bob"] ["wheel" "audio"]; 35 | expected = { 36 | users.groups.wheel.members = ["alice" "bob"]; 37 | users.groups.audio.members = ["alice" "bob"]; 38 | }; 39 | }; 40 | testEnsureUsers = { 41 | expr = ensureUsers { 42 | users.users = { 43 | anon = { 44 | isNormalUser = true; 45 | }; 46 | }; 47 | } ["alice" "bob" "anon"]; 48 | expected = { 49 | users.users = { 50 | alice = { 51 | isNormalUser = true; 52 | }; 53 | bob = { 54 | isNormalUser = true; 55 | }; 56 | }; 57 | }; 58 | }; 59 | } 60 | -------------------------------------------------------------------------------- /modules/allow-unfree/README.md: -------------------------------------------------------------------------------- 1 | ## Allow unfree software (with regex) 2 | 3 | Cherry-pick the unfree software you want to allow with regexes. 4 | 5 | ### Problem 6 | 7 | You can either allow every unfree software, or you must set it per package. 8 | This can become very annoying when facing big dependency trees like with 9 | printers, scanners, graphics cards... you know the drill. 10 | 11 | ```nix 12 | #default.nix 13 | config.allowUnfree = true; 14 | # or 15 | config.allowUnfreePredicate = [ 16 | "package_name" 17 | "other_similar_package_name" 18 | "on_and_on" 19 | ]; 20 | ``` 21 | 22 | ### Solution 23 | 24 | Fortunately some packages have the same prefix in their names (nvidia_this, nvidia_that,...) 25 | Through the allow-unfree function you can define the package to allow with regexes. 26 | 27 | ## Misc 28 | 29 | A allow-unfree options that supports regex. 30 | 31 | ```nix 32 | #default.nix 33 | allow-unfree = [ 34 | # use regexes 35 | "nvidia-.*" 36 | "cuda.*" 37 | ]; 38 | ``` 39 | -------------------------------------------------------------------------------- /modules/allow-unfree/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | ... 5 | }: let 6 | cfg = config.allow-unfree; 7 | in { 8 | # Set the module options 9 | options = with lib; { 10 | allow-unfree = mkOption { 11 | default = []; 12 | type = with types; listOf str; 13 | description = "List of unfree packages allowed to be installed"; 14 | example = lib.literalExpression ''[ "steam" ]''; 15 | }; 16 | }; 17 | config = { 18 | nixpkgs.config.allowUnfreePredicate = pkg: let 19 | pkgName = lib.getName pkg; 20 | matchPackges = reg: ! builtins.isNull (builtins.match reg pkgName); 21 | in 22 | builtins.any matchPackges cfg; 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /modules/home-merger/README.md: -------------------------------------------------------------------------------- 1 | # Home-merger (better separation of concerns) 2 | 3 | Merge a nixOs module and its home-manager equivalent module in a single module. 4 | _Internaly uses home-manager_. 5 | 6 | ## Problem 7 | 8 | **When using home-manager** you can find yourself 9 | with an unflexible configuration that can't be shared without 10 | substential rewritting efforts because: 11 | 12 | - You can get away with **hardcoded user names** (and some other variables). 13 | 14 | ```nix 15 | users.users. = { 16 | some_stuffs = {}; 17 | } 18 | ``` 19 | 20 | - For a same program, you have to import standard modules and home-manager modules separately, 21 | resulting in file duplication and **awkward dependency management**. 22 | 23 | ```sh 24 | . 25 | ├── nixos 26 | │   ├── gnome.nix 27 | │   └── hyprland.nix 28 | └── home-manager 29 |    ├── gnome.nix #should be grouped with its homologous. 30 |    └── hyprland.nix 31 | ``` 32 | 33 | and **unwelcoming top-level module declaration**. 34 | 35 | ```nix 36 | # flake.nix 37 | nixosConfiguration = { 38 | default = pkgs.lib.nixosSystem { 39 | inherit system; 40 | modules = [ 41 | ./nixos/gnome.nix 42 | home-manager.nixosModules.home-manager { 43 | home-manager.users. = {pkgs,...}: { 44 | imports = [ 45 | ./home-manager/gnome.nix 46 | ]; 47 | }; 48 | }; 49 | ]; 50 | }; 51 | }; 52 | 53 | ``` 54 | 55 | ## Solution 56 | 57 | To circumvent this issues, you may want to 58 | either make your own functions, 59 | ditch home-manager (pretty radical), 60 | or simply use the home-merger module. 61 | 62 | - This results in **tidy filetrees**, with separation of concerns. 63 | 64 | ```sh 65 | . 66 | ├── gnome 67 | │   ├── default.nix 68 | │   └── home.nix 69 | └── hyprland 70 |    ├── default.nix 71 |    └── home.nix 72 | ``` 73 | 74 | - And **friendly top-level module declaration**. 75 | 76 | You then only need to import one file for both 77 | standard module and home-manager module. 78 | 79 | ```nix 80 | # flake.nix 81 | 82 | nixosConfiguration = { 83 | default = pkgs.lib.nixosSystem { 84 | inherit system; 85 | modules = [ 86 | ./gnome/default.nix 87 | ./hyprland/default.nix 88 | ]; 89 | 90 | }; 91 | }; 92 | ``` 93 | 94 | The magic happens in the standard module file (here `default.nix`). 95 | You can import a home-manager modules through home-merger. 96 | 97 | ```nix 98 | # default.nix 99 | home-merger = { 100 | # A list of users username for which to apply the modules. 101 | users = ["alice", "bob"]; 102 | # Arguments to pass to the module 103 | extraSpecialArgs = { inherit inputs cfg; }; 104 | # A list of modules to be applied to the users 105 | modules = [ 106 | ./home.nix 107 | ]; 108 | } 109 | ``` 110 | 111 | ### How it works 112 | 113 | Calling home-manager directly would raise an error 114 | because you can only declare the home-manager module once. 115 | 116 | The home-merger function simply aggregates every home-manager nixosModules 117 | to declare them at once. 118 | 119 | _It is just a 60 lines function but oh boy does it do good!_ 120 | 121 | ## Usage in your configuration files 122 | 123 | Time to glow by your nix aptitudes. 124 | 125 | You may want to declare your users only once 126 | at the top-level of your configuration. 127 | 128 | Just create a global variable. 129 | 130 | ```nix 131 | # flake.nix 132 | options = with lib; { 133 | my_config = { 134 | users = mkOption { 135 | type = with types; listOf str; 136 | default = []; 137 | example = literalExpression "[\"alice\",\"bob\"]"; 138 | description = '' 139 | The name of users to apply modules to. 140 | ''; 141 | }; 142 | }; 143 | }; 144 | config.my_config.users = ["anon"]; 145 | 146 | ``` 147 | 148 | And use it as an argument value in home-merger. 149 | 150 | ```nix 151 | # default.nix 152 | home-merger = { 153 | users = config.my_config.users; 154 | extraSpecialArgs = { inherit inputs; }; 155 | modules = [ 156 | ./home.nix 157 | ]; 158 | } 159 | ``` 160 | 161 | Head to the template directory for a boilerplate 162 | -> [example](https://github.com/pipelight/nixos-tidy/example). 163 | -------------------------------------------------------------------------------- /modules/home-merger/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | inputs, 4 | config, 5 | ... 6 | }: let 7 | slib = import ../../lib/umports/default.nix {inherit lib;}; 8 | in { 9 | # Set the module options 10 | options = with lib; { 11 | home-merger = { 12 | users = mkOption { 13 | type = with types; listOf str; 14 | default = []; 15 | example = literalExpression "[\"alice\",\"bob\"]"; 16 | description = '' 17 | The name of users for whome to add this module. 18 | ''; 19 | }; 20 | stateVersion = mkOption { 21 | type = with types; str; 22 | default = config.system.stateVersion; 23 | description = '' 24 | In general you want it to be the same as your system. 25 | stateVersion = config.system.stateVersion; 26 | ''; 27 | example = literalExpression "'25.05'"; 28 | }; 29 | useGlobalPkgs = mkOption { 30 | type = with types; bool; 31 | default = true; 32 | description = '' 33 | By default, 34 | Home Manager uses a private pkgs instance 35 | that is configured via the home-manager.users..nixpkgs options. 36 | 37 | Enable to instead use the global pkgs 38 | that is configured via the system level nixpkgs options 39 | ''; 40 | example = true; 41 | }; 42 | extraSpecialArgs = mkOption { 43 | type = with types; attrs; 44 | default = {}; 45 | example = literalExpression "{ inherit inputs; }"; 46 | description = '' 47 | Extra `specialArgs` passed to Home Manager. This 48 | option can be used to pass additional arguments to all modules. 49 | ''; 50 | }; 51 | imports = mkOption { 52 | type = with types; listOf raw; 53 | default = []; 54 | example = literalExpression "[ ./home.nix, otherModule ]"; 55 | description = '' 56 | Modules to add to the user configuration. 57 | ''; 58 | }; 59 | umports = { 60 | paths = mkOption { 61 | type = with types; listOf raw; 62 | default = []; 63 | example = literalExpression "[ ./. ]"; 64 | description = '' 65 | Modules to add to the user configuration. 66 | ''; 67 | }; 68 | exclude = mkOption { 69 | type = with types; listOf raw; 70 | default = []; 71 | example = literalExpression "[ ./. ]"; 72 | description = '' 73 | Modules path to exclude from the user configuration. 74 | ''; 75 | }; 76 | }; 77 | }; 78 | }; 79 | 80 | imports = with slib; let 81 | homeManagerModule = inputs.home-manager.nixosModules.home-manager; 82 | cfg = config.home-merger; 83 | users = ensureUsers config config.home-merger.users; 84 | in 85 | [ 86 | homeManagerModule 87 | ] 88 | # One should not duplicate paths in umport and import. 89 | ++ (umportHomeModules { 90 | paths = _getPaths cfg.umports.paths; 91 | exclude = _getPaths cfg.umports.exclude; 92 | } 93 | # ++ umportHomeModules {paths = cfg.umports;} 94 | { 95 | inherit (cfg) users stateVersion useGlobalPkgs extraSpecialArgs; 96 | imports = 97 | _getModules cfg.umports.paths 98 | ++ _getModules cfg.imports; 99 | }); 100 | } 101 | -------------------------------------------------------------------------------- /modules/networking-privacy/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | inputs, 4 | config, 5 | ... 6 | }: let 7 | slib = import ../../lib/network/default.nix {inherit lib;}; 8 | in { 9 | # Set the module options 10 | options = with lib; { 11 | networking = { 12 | privacy = { 13 | enable = mkEnableOption '' 14 | Enable ipv6 privacy features. 15 | Quad9 dns. 16 | ''; 17 | ipv6 = { 18 | secret = mkOption { 19 | type = with types; str; 20 | description = '' 21 | A string to generate the inbound ipv6 interface identifier from. 22 | Only used if strategy is set to "fixed". 23 | ''; 24 | default = config.networking.hostName; 25 | }; 26 | iid = mkOption { 27 | type = with types; str; 28 | description = '' 29 | A dummy ipv6 interface identifier (the last 64bits) 30 | to generate default inbound address from. 31 | Only used if strategy is set to "fixed". 32 | ''; 33 | example = lib.literalExpression '' 34 | babe:feed:b0ba:fett 35 | ''; 36 | }; 37 | strategy = mkOption { 38 | type = with types; enum ["fixed" "random"]; 39 | description = '' 40 | Set the level of privacy. 41 | 42 | - fixed: Recommended for servers. 43 | Set fixed ipv6 based on a secret whether than on device macaddress. 44 | 45 | - random: Recommended for desktops. 46 | Set random ipv6 for outgoing traffic on each network with rotation every few hours. 47 | 48 | ''; 49 | default = "fixed"; 50 | }; 51 | }; 52 | }; 53 | }; 54 | }; 55 | 56 | /* 57 | Create a default network manager connection 58 | Or a default vswitch. 59 | 60 | Prohibit systemd-networkd usage. 61 | (Because it is lagging behind in terms of privacy features as of 22/05/2025) 62 | But still force some parameters just in case. 63 | 64 | */ 65 | imports = [ 66 | # Set a fixed inbound ipv6 + random outbounds 67 | ./fixed.nix 68 | # Set random ipv6 inbound/outbound 69 | ./random.nix 70 | ]; 71 | } 72 | -------------------------------------------------------------------------------- /modules/networking-privacy/fixed.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs, 3 | config, 4 | pkgs, 5 | lib, 6 | ... 7 | }: 8 | with lib; let 9 | cfg = config.crocuda; 10 | 11 | unboundEnabled = config.services.unbound.enable; 12 | 13 | ## Globals 14 | iid = cfg.network.privacy.ipv6.iid; 15 | # computed_iid = slib.ip.str_to_iid cfg.network.privacy.ipv6.secret; 16 | # token = 17 | # if (!isNull iid) 18 | # then iid 19 | # else computed_iid; 20 | # computed_mac = slib.ip.str_to_mac cfg.network.privacy.ipv6.secret; 21 | in 22 | mkIf (cfg.network.privacy.enable 23 | && cfg.network.privacy.ipv6.strategy 24 | == "fixed") { 25 | ########################## 26 | # Force usage of ipv6 privacy extension in 27 | # - kernel parameters (low level) 28 | # - networkmanager (high level) 29 | # - systemd-networkd (high level) 30 | # + dhcp (high level) 31 | 32 | ## Kernel 33 | boot = { 34 | kernelParams = ["IPv6PrivacyExtensions=1"]; 35 | # More information about keys possible values at: 36 | # https://sysctl-explorer.net/net/ipv6/ 37 | kernel.sysctl = { 38 | # Enable maximal privacy extensions 39 | "net.ipv6.conf.default.use_tempaddr" = mkForce 2; 40 | "net.ipv6.conf.all.use_tempaddr" = 2; 41 | 42 | # Generate random ipv6 43 | # 0 = "eui64" 44 | # 1 = "eui64" 45 | # 2 = "stable-privacy" with secret 46 | # 3 = "stable-privacy" with random secret 47 | "net.ipv6.conf.default.addr_gen_mode" = 2; 48 | "net.ipv6.conf.all.addr_gen_mode" = 2; 49 | 50 | # Set secret to hashed string 51 | # "net.ipv6.conf.default.stable_secret" = "::${token}"; 52 | }; 53 | }; 54 | 55 | ########################## 56 | ## dhcpcd 57 | networking = { 58 | # Force dhcpcd usage with networkmanager (not working) 59 | # for tool concistency with servers that do not use networkmanager. 60 | # useDHCP = mkForce true; 61 | dhcpcd = { 62 | # enable = true; #default 63 | extraConfig = '' 64 | # nohook resolv.conf 65 | # slaac token ::${token} 66 | ''; 67 | }; 68 | }; 69 | 70 | ########################## 71 | # You should use either systemd-networkd OR NetworkManager. 72 | 73 | ## system-networkd 74 | systemd.network.config = '' 75 | [Network] 76 | DHCP=yes 77 | # IPv6Token=::${token} 78 | ''; 79 | 80 | networking.interfaces = mkIf (!config.networking.networkmanager.enable) { 81 | # end0.macAddress = computed_mac; 82 | # eno1.macAddress = computed_mac; 83 | # ens3.macAddress = computed_mac; 84 | }; 85 | 86 | ## NetworkManager 87 | # https://www.networkmanager.dev/docs/api/latest 88 | networking.networkmanager = mkIf config.networking.networkmanager.enable { 89 | logLevel = "INFO"; 90 | 91 | ## Use external dns -> unbound 92 | dns = 93 | if unboundEnabled 94 | then "none" 95 | else "default"; 96 | 97 | ## Use external dhcp -> dhcpcd (not working) 98 | # Not working because of concurency error. 99 | # dhcp = "dhcpcd"; 100 | dhcp = "internal"; 101 | 102 | connectionConfig = { 103 | # MAC address randomization 104 | # Random on cable link 105 | "ethernet.cloned-mac-address" = mkForce "random"; 106 | # Random on wifi 107 | "wifi.cloned-mac-address" = mkForce "random"; 108 | }; 109 | 110 | ensureProfiles.profiles = { 111 | default = { 112 | connection = { 113 | id = "wired-fixed"; 114 | type = "ethernet"; 115 | }; 116 | ethernet = { 117 | # cloned-mac-address = computed_mac; 118 | }; 119 | ipv4 = { 120 | dns-search = "lan"; 121 | # dns-priority default = 100, vpn = 50 122 | dns-priority = 20; 123 | method = "auto"; 124 | }; 125 | ipv6 = { 126 | dns-search = "lan"; 127 | # dns-priority default = 100, vpn = 50 128 | dns-priority = 20; 129 | method = "auto"; 130 | 131 | # Fixed inbound ip 132 | addr-gen-mode = "eui64"; 133 | # token = "::${token}"; 134 | 135 | # Random outbound ip 136 | ip6-privacy = 2; 137 | }; 138 | }; 139 | }; 140 | }; 141 | } 142 | -------------------------------------------------------------------------------- /modules/networking-privacy/random.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs, 3 | config, 4 | pkgs, 5 | lib, 6 | ... 7 | }: 8 | with lib; let 9 | cfg = config.crocuda; 10 | in 11 | mkIf (cfg.network.privacy.enable 12 | && cfg.network.privacy.ipv6.strategy 13 | == "random") { 14 | ########################## 15 | # Force usage of ipv6 privacy extension in 16 | # - kernel parameters (low level) 17 | # - networkmanager (high level) 18 | 19 | ## Kernel 20 | boot = { 21 | kernelParams = ["IPv6PrivacyExtensions=1"]; 22 | # More information about keys possible values at: 23 | # https://sysctl-explorer.net/net/ipv6/ 24 | kernel.sysctl = { 25 | # Enable maximal privacy extensions 26 | "net.ipv6.conf.default.use_tempaddr" = mkForce 2; 27 | "net.ipv6.conf.all.use_tempaddr" = 2; 28 | 29 | # Generate random ipv6 30 | # 0 = "eui64" 31 | # 1 = "eui64" 32 | # 2 = "stable-privacy" with secret 33 | # 3 = "stable-privacy" with random secret 34 | "net.ipv6.conf.default.addr_gen_mode" = 3; 35 | "net.ipv6.conf.all.addr_gen_mode" = 3; 36 | }; 37 | }; 38 | 39 | ## dhcpcd 40 | networking.dhcpcd = { 41 | enable = true; #default 42 | extraConfig = '' 43 | nohook resolve.conf 44 | slaac private 45 | ''; 46 | }; 47 | 48 | ########################## 49 | # You should use either systemd-networkd OR NetworkManager. 50 | 51 | ## system-networkd 52 | systemd.network.config = '' 53 | [Network] 54 | DHCP=yes 55 | IPv6PrivacyExtensions=kernel 56 | ''; 57 | 58 | ## NetworkManager 59 | # https://www.networkmanager.dev/docs/api/latest 60 | networking.networkmanager = { 61 | logLevel = "INFO"; 62 | 63 | ## Use external dns -> unbound 64 | dns = "none"; 65 | 66 | ## Use external dhcp -> dhcpcd 67 | dhcp = "dhcpcd"; 68 | # dhcp = "internal"; 69 | 70 | connectionConfig = { 71 | # MAC address randomization 72 | # Random on cable link 73 | "ethernet.cloned-mac-address" = mkForce "random"; 74 | # Random on wifi 75 | "wifi.cloned-mac-address" = mkForce "random"; 76 | }; 77 | 78 | ensureProfiles.profiles = { 79 | default = { 80 | connection = { 81 | id = "wired-random"; 82 | type = "ethernet"; 83 | }; 84 | ipv4 = { 85 | method = "auto"; 86 | }; 87 | ipv6 = { 88 | # Random inbound ip 89 | method = "auto"; 90 | addr-gen-mode = "stable-privacy"; 91 | 92 | # Random outbound ip 93 | ip6-privacy = 2; 94 | }; 95 | }; 96 | }; 97 | }; 98 | } 99 | -------------------------------------------------------------------------------- /pipelight.toml: -------------------------------------------------------------------------------- 1 | [[pipelines]] 2 | name = "tests" 3 | 4 | [[pipelines.steps]] 5 | name = "test library" 6 | commands = [""" 7 | pipelight run test-lib --attach 8 | """] 9 | [[pipelines.steps]] 10 | name = "test modules" 11 | commands = [""" 12 | pipelight run test-modules --attach 13 | """] 14 | 15 | [[pipelines]] 16 | name = "test-lib" 17 | [[pipelines.steps]] 18 | name = "run lix-unit tests" 19 | commands = [""" 20 | nix-unit --flake '.#tests' 21 | """] 22 | 23 | [[pipelines]] 24 | name = "test-modules" 25 | 26 | [[pipelines.steps]] 27 | name = "build home-merger template flake" 28 | commands = [""" 29 | pipelight run test-module_home-merger --attach 30 | """] 31 | 32 | [[pipelines.steps]] 33 | name = "build umports template flake" 34 | commands = [""" 35 | pipelight run test-module_umports --attach 36 | """] 37 | 38 | [[pipelines.steps]] 39 | name = "build networking-privacy template flake" 40 | commands = [""" 41 | pipelight run test-module_network-privacy --attach 42 | """] 43 | 44 | [[pipelines]] 45 | name = "test-module_home-merger" 46 | 47 | [[pipelines.steps]] 48 | name = "run home-merger module tests" 49 | commands = [""" 50 | nix flake update --flake ./templates/home-merger 51 | """, """ 52 | nixos-rebuild build \ 53 | --flake './templates/home-merger#default' \ 54 | --override-input nixos-tidy ./ 55 | """] 56 | 57 | [[pipelines]] 58 | name = "test-module_umports" 59 | 60 | [[pipelines.steps]] 61 | name = "run umports module tests" 62 | commands = [""" 63 | nix flake update --flake ./templates/umports 64 | """, """ 65 | nixos-rebuild build \ 66 | --flake './templates/umports#default' \ 67 | --override-input nixos-tidy ./ 68 | """] 69 | 70 | [[pipelines]] 71 | name = "test-module_network-privacy" 72 | 73 | [[pipelines.steps]] 74 | name = "run networking-privacy module tests" 75 | commands = [""" 76 | nix flake update --flake ./templates/networking-privacy 77 | """, """ 78 | nixos-rebuild build \ 79 | --flake './templates/networking-privacy#default' \ 80 | --override-input nixos-tidy ./ 81 | """] 82 | -------------------------------------------------------------------------------- /public/images/nixos-tidy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pipelight/nixos-tidy/6a8edfac7d448d004502a467acf83c2e46c2f683/public/images/nixos-tidy.png -------------------------------------------------------------------------------- /templates/commons/configuration.nix: -------------------------------------------------------------------------------- 1 | ## This is a random system configuration. 2 | ## You should use your custom configuration file instead. 3 | { 4 | pkgs, 5 | lib, 6 | ... 7 | }: { 8 | # Use the systemd-boot EFI boot loader. 9 | # boot.kernelPackages = pkgs.linuxPackages; 10 | boot = { 11 | kernelPackages = pkgs.linuxPackages_latest; 12 | loader = { 13 | systemd-boot = { 14 | enable = true; 15 | graceful = true; 16 | }; 17 | efi.canTouchEfiVariables = true; 18 | }; 19 | # Extend supported filesystems 20 | supportedFilesystems = ["ntfs"]; 21 | }; 22 | # Set your time zone. 23 | time.timeZone = "Europe/Paris"; 24 | 25 | # Select internationalisation properties. 26 | i18n.defaultLocale = "en_US.UTF-8"; 27 | 28 | # system.stateVersion = "24.11"; 29 | system.stateVersion = "24.05"; 30 | # Channel 31 | # system.autoUpgrade.channel = "https://nixos.org/channels/nixos-unstable/"; 32 | system.autoUpgrade.channel = "https://nixos.org/channels/nixos-24.05/"; 33 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 34 | } 35 | -------------------------------------------------------------------------------- /templates/commons/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | ## This is a random hardware configuration. 2 | ## You should use your custom hardware configuration file instead. 3 | { 4 | config, 5 | lib, 6 | pkgs, 7 | modulesPath, 8 | ... 9 | }: { 10 | imports = [ 11 | (modulesPath + "/installer/scan/not-detected.nix") 12 | ]; 13 | 14 | boot.initrd.availableKernelModules = ["nvme" "xhci_pci" "ahci" "usb_storage" "sd_mod"]; 15 | boot.initrd.kernelModules = []; 16 | boot.kernelModules = ["kvm-amd" "amdgpu"]; 17 | boot.extraModulePackages = []; 18 | 19 | fileSystems."/boot" = { 20 | device = "/dev/disk/by-uuid/xxx-xxx-xx"; 21 | fsType = "vfat"; 22 | }; 23 | fileSystems."/" = { 24 | device = "/dev/disk/by-uuid/xxx-xxx-xxx"; 25 | fsType = "ext4"; 26 | }; 27 | 28 | swapDevices = []; 29 | 30 | networking.hostName = "nixos"; 31 | networking.useDHCP = lib.mkDefault true; 32 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 33 | hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 34 | } 35 | -------------------------------------------------------------------------------- /templates/home-merger/flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-parts": { 4 | "inputs": { 5 | "nixpkgs-lib": [ 6 | "nur", 7 | "nixpkgs" 8 | ] 9 | }, 10 | "locked": { 11 | "lastModified": 1733312601, 12 | "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", 13 | "owner": "hercules-ci", 14 | "repo": "flake-parts", 15 | "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", 16 | "type": "github" 17 | }, 18 | "original": { 19 | "owner": "hercules-ci", 20 | "repo": "flake-parts", 21 | "type": "github" 22 | } 23 | }, 24 | "home-manager": { 25 | "inputs": { 26 | "nixpkgs": [ 27 | "nixpkgs" 28 | ] 29 | }, 30 | "locked": { 31 | "lastModified": 1742588233, 32 | "narHash": "sha256-Fi5g8H5FXMSRqy+mU6gPG0v+C9pzjYbkkiePtz8+PpA=", 33 | "owner": "nix-community", 34 | "repo": "home-manager", 35 | "rev": "296ddc64627f4a6a4eb447852d7346b9dd16197d", 36 | "type": "github" 37 | }, 38 | "original": { 39 | "owner": "nix-community", 40 | "repo": "home-manager", 41 | "type": "github" 42 | } 43 | }, 44 | "home-manager_2": { 45 | "inputs": { 46 | "nixpkgs": [ 47 | "nixos-tidy", 48 | "nixpkgs" 49 | ] 50 | }, 51 | "locked": { 52 | "lastModified": 1710532761, 53 | "narHash": "sha256-SUXGZNrXX05YA9G6EmgupxhOr3swI1gcxLUeDMUhrEY=", 54 | "owner": "nix-community", 55 | "repo": "home-manager", 56 | "rev": "206f457fffdb9a73596a4cb2211a471bd305243d", 57 | "type": "github" 58 | }, 59 | "original": { 60 | "owner": "nix-community", 61 | "repo": "home-manager", 62 | "type": "github" 63 | } 64 | }, 65 | "nixos-tidy": { 66 | "inputs": { 67 | "home-manager": "home-manager_2", 68 | "nixpkgs": [ 69 | "nixpkgs" 70 | ] 71 | }, 72 | "locked": { 73 | "lastModified": 1734346232, 74 | "narHash": "sha256-SAWNYaKaVgfIltlz/SJgkBylhNoJTQqNMKDUykOsX9Y=", 75 | "owner": "pipelight", 76 | "repo": "nixos-tidy", 77 | "rev": "d33eb8777a672dcffa0b88120d24b717ddbd96b3", 78 | "type": "github" 79 | }, 80 | "original": { 81 | "owner": "pipelight", 82 | "repo": "nixos-tidy", 83 | "type": "github" 84 | } 85 | }, 86 | "nixpkgs": { 87 | "locked": { 88 | "lastModified": 1742512142, 89 | "narHash": "sha256-8XfURTDxOm6+33swQJu/hx6xw1Tznl8vJJN5HwVqckg=", 90 | "owner": "nixos", 91 | "repo": "nixpkgs", 92 | "rev": "7105ae3957700a9646cc4b766f5815b23ed0c682", 93 | "type": "github" 94 | }, 95 | "original": { 96 | "owner": "nixos", 97 | "ref": "nixos-24.11", 98 | "repo": "nixpkgs", 99 | "type": "github" 100 | } 101 | }, 102 | "nixpkgs_2": { 103 | "locked": { 104 | "lastModified": 1742422364, 105 | "narHash": "sha256-mNqIplmEohk5jRkqYqG19GA8MbQ/D4gQSK0Mu4LvfRQ=", 106 | "owner": "nixos", 107 | "repo": "nixpkgs", 108 | "rev": "a84ebe20c6bc2ecbcfb000a50776219f48d134cc", 109 | "type": "github" 110 | }, 111 | "original": { 112 | "owner": "nixos", 113 | "ref": "nixos-unstable", 114 | "repo": "nixpkgs", 115 | "type": "github" 116 | } 117 | }, 118 | "nur": { 119 | "inputs": { 120 | "flake-parts": "flake-parts", 121 | "nixpkgs": "nixpkgs_2", 122 | "treefmt-nix": "treefmt-nix" 123 | }, 124 | "locked": { 125 | "lastModified": 1742639006, 126 | "narHash": "sha256-g4aNYcqPJJ63/15ACtVZosChOQRAV89+BNXPdAH3Oio=", 127 | "owner": "nix-community", 128 | "repo": "NUR", 129 | "rev": "1d93c884f94993958d5f7da1a851ce10a324c539", 130 | "type": "github" 131 | }, 132 | "original": { 133 | "owner": "nix-community", 134 | "repo": "NUR", 135 | "type": "github" 136 | } 137 | }, 138 | "root": { 139 | "inputs": { 140 | "home-manager": "home-manager", 141 | "nixos-tidy": "nixos-tidy", 142 | "nixpkgs": "nixpkgs", 143 | "nur": "nur" 144 | } 145 | }, 146 | "treefmt-nix": { 147 | "inputs": { 148 | "nixpkgs": [ 149 | "nur", 150 | "nixpkgs" 151 | ] 152 | }, 153 | "locked": { 154 | "lastModified": 1733222881, 155 | "narHash": "sha256-JIPcz1PrpXUCbaccEnrcUS8jjEb/1vJbZz5KkobyFdM=", 156 | "owner": "numtide", 157 | "repo": "treefmt-nix", 158 | "rev": "49717b5af6f80172275d47a418c9719a31a78b53", 159 | "type": "github" 160 | }, 161 | "original": { 162 | "owner": "numtide", 163 | "repo": "treefmt-nix", 164 | "type": "github" 165 | } 166 | } 167 | }, 168 | "root": "root", 169 | "version": 7 170 | } 171 | -------------------------------------------------------------------------------- /templates/home-merger/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "A flake that uses nixos-tidy home-merger"; 3 | inputs = { 4 | nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; 5 | 6 | nixos-tidy = { 7 | url = "github:pipelight/nixos-tidy"; 8 | inputs.nixpkgs.follows = "nixpkgs"; 9 | }; 10 | 11 | ################################### 12 | ## NixOs-tidy and dependencies 13 | home-manager = { 14 | url = "github:nix-community/home-manager"; 15 | inputs.nixpkgs.follows = "nixpkgs"; 16 | }; 17 | ################################### 18 | ## Testing 19 | # NUR - Nix User Repository 20 | nur.url = "github:nix-community/NUR"; 21 | }; 22 | 23 | outputs = { 24 | self, 25 | nixpkgs, 26 | ... 27 | } @ inputs: let 28 | system = "x86_64-linux"; 29 | pkgs = nixpkgs; 30 | in rec { 31 | nixosConfigurations = { 32 | # Default module 33 | default = pkgs.lib.nixosSystem { 34 | specialArgs = {inherit inputs;}; 35 | modules = [ 36 | ../commons/configuration.nix 37 | ../commons/hardware-configuration.nix 38 | 39 | inputs.nixos-tidy.nixosModules.home-merger 40 | 41 | ################################### 42 | # Top level home-merger 43 | 44 | # No need to import home-manager 45 | # as it is already imported by home-merger. 46 | ({ 47 | lib, 48 | inpus, 49 | config, 50 | ... 51 | }: { 52 | # Create user if you want. 53 | # Home-merger will create a user if you don't (practical!) 54 | users.users."anon" = { 55 | isNormalUser = true; 56 | }; 57 | home-merger = { 58 | users = ["anon"]; 59 | extraSpecialArgs = {inherit inputs;}; 60 | # You can use default import or the recursive one (umport). 61 | imports = [ 62 | inputs.nur.modules.homeManager.default 63 | ]; 64 | umports.paths = [ 65 | ./. 66 | ]; 67 | }; 68 | }) 69 | ]; 70 | }; 71 | }; 72 | }; 73 | } 74 | -------------------------------------------------------------------------------- /templates/home-merger/my_module/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | pkgs, 4 | lib, 5 | utils, 6 | inputs, 7 | ... 8 | }: { 9 | environment.etc = { 10 | "test/umport".text = '' 11 | This is a random test file to check if umport module works. 12 | ''; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /templates/home-merger/my_module/home.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | pkgs, 4 | lib, 5 | ... 6 | }: { 7 | home.packages = with pkgs; [ 8 | ]; 9 | 10 | home.file = { 11 | "test/umport".text = '' 12 | This is a random test file to check if umport-home module works. 13 | ''; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /templates/networking-privacy/flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-parts": { 4 | "inputs": { 5 | "nixpkgs-lib": [ 6 | "nur", 7 | "nixpkgs" 8 | ] 9 | }, 10 | "locked": { 11 | "lastModified": 1733312601, 12 | "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", 13 | "owner": "hercules-ci", 14 | "repo": "flake-parts", 15 | "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", 16 | "type": "github" 17 | }, 18 | "original": { 19 | "owner": "hercules-ci", 20 | "repo": "flake-parts", 21 | "type": "github" 22 | } 23 | }, 24 | "home-manager": { 25 | "inputs": { 26 | "nixpkgs": [ 27 | "nixpkgs" 28 | ] 29 | }, 30 | "locked": { 31 | "lastModified": 1742588233, 32 | "narHash": "sha256-Fi5g8H5FXMSRqy+mU6gPG0v+C9pzjYbkkiePtz8+PpA=", 33 | "owner": "nix-community", 34 | "repo": "home-manager", 35 | "rev": "296ddc64627f4a6a4eb447852d7346b9dd16197d", 36 | "type": "github" 37 | }, 38 | "original": { 39 | "owner": "nix-community", 40 | "repo": "home-manager", 41 | "type": "github" 42 | } 43 | }, 44 | "home-manager_2": { 45 | "inputs": { 46 | "nixpkgs": [ 47 | "nixos-tidy", 48 | "nixpkgs" 49 | ] 50 | }, 51 | "locked": { 52 | "lastModified": 1710532761, 53 | "narHash": "sha256-SUXGZNrXX05YA9G6EmgupxhOr3swI1gcxLUeDMUhrEY=", 54 | "owner": "nix-community", 55 | "repo": "home-manager", 56 | "rev": "206f457fffdb9a73596a4cb2211a471bd305243d", 57 | "type": "github" 58 | }, 59 | "original": { 60 | "owner": "nix-community", 61 | "repo": "home-manager", 62 | "type": "github" 63 | } 64 | }, 65 | "nixos-tidy": { 66 | "inputs": { 67 | "home-manager": "home-manager_2", 68 | "nixpkgs": [ 69 | "nixpkgs" 70 | ] 71 | }, 72 | "locked": { 73 | "lastModified": 1734346232, 74 | "narHash": "sha256-SAWNYaKaVgfIltlz/SJgkBylhNoJTQqNMKDUykOsX9Y=", 75 | "owner": "pipelight", 76 | "repo": "nixos-tidy", 77 | "rev": "d33eb8777a672dcffa0b88120d24b717ddbd96b3", 78 | "type": "github" 79 | }, 80 | "original": { 81 | "owner": "pipelight", 82 | "repo": "nixos-tidy", 83 | "type": "github" 84 | } 85 | }, 86 | "nixpkgs": { 87 | "locked": { 88 | "lastModified": 1742512142, 89 | "narHash": "sha256-8XfURTDxOm6+33swQJu/hx6xw1Tznl8vJJN5HwVqckg=", 90 | "owner": "nixos", 91 | "repo": "nixpkgs", 92 | "rev": "7105ae3957700a9646cc4b766f5815b23ed0c682", 93 | "type": "github" 94 | }, 95 | "original": { 96 | "owner": "nixos", 97 | "ref": "nixos-24.11", 98 | "repo": "nixpkgs", 99 | "type": "github" 100 | } 101 | }, 102 | "nixpkgs_2": { 103 | "locked": { 104 | "lastModified": 1742422364, 105 | "narHash": "sha256-mNqIplmEohk5jRkqYqG19GA8MbQ/D4gQSK0Mu4LvfRQ=", 106 | "owner": "nixos", 107 | "repo": "nixpkgs", 108 | "rev": "a84ebe20c6bc2ecbcfb000a50776219f48d134cc", 109 | "type": "github" 110 | }, 111 | "original": { 112 | "owner": "nixos", 113 | "ref": "nixos-unstable", 114 | "repo": "nixpkgs", 115 | "type": "github" 116 | } 117 | }, 118 | "nur": { 119 | "inputs": { 120 | "flake-parts": "flake-parts", 121 | "nixpkgs": "nixpkgs_2", 122 | "treefmt-nix": "treefmt-nix" 123 | }, 124 | "locked": { 125 | "lastModified": 1742639006, 126 | "narHash": "sha256-g4aNYcqPJJ63/15ACtVZosChOQRAV89+BNXPdAH3Oio=", 127 | "owner": "nix-community", 128 | "repo": "NUR", 129 | "rev": "1d93c884f94993958d5f7da1a851ce10a324c539", 130 | "type": "github" 131 | }, 132 | "original": { 133 | "owner": "nix-community", 134 | "repo": "NUR", 135 | "type": "github" 136 | } 137 | }, 138 | "root": { 139 | "inputs": { 140 | "home-manager": "home-manager", 141 | "nixos-tidy": "nixos-tidy", 142 | "nixpkgs": "nixpkgs", 143 | "nur": "nur" 144 | } 145 | }, 146 | "treefmt-nix": { 147 | "inputs": { 148 | "nixpkgs": [ 149 | "nur", 150 | "nixpkgs" 151 | ] 152 | }, 153 | "locked": { 154 | "lastModified": 1733222881, 155 | "narHash": "sha256-JIPcz1PrpXUCbaccEnrcUS8jjEb/1vJbZz5KkobyFdM=", 156 | "owner": "numtide", 157 | "repo": "treefmt-nix", 158 | "rev": "49717b5af6f80172275d47a418c9719a31a78b53", 159 | "type": "github" 160 | }, 161 | "original": { 162 | "owner": "numtide", 163 | "repo": "treefmt-nix", 164 | "type": "github" 165 | } 166 | } 167 | }, 168 | "root": "root", 169 | "version": 7 170 | } 171 | -------------------------------------------------------------------------------- /templates/networking-privacy/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "A flake that uses nixos-tidy networking privacy module"; 3 | inputs = { 4 | nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; 5 | 6 | nixos-tidy = { 7 | url = "github:pipelight/nixos-tidy"; 8 | inputs.nixpkgs.follows = "nixpkgs"; 9 | }; 10 | 11 | ################################### 12 | ## NixOs-tidy and dependencies 13 | home-manager = { 14 | url = "github:nix-community/home-manager"; 15 | inputs.nixpkgs.follows = "nixpkgs"; 16 | }; 17 | 18 | ################################### 19 | ## Testing purpose only 20 | # NUR - Nix User Repository 21 | nur.url = "github:nix-community/NUR"; 22 | }; 23 | 24 | outputs = { 25 | self, 26 | nixpkgs, 27 | ... 28 | } @ inputs: let 29 | system = "x86_64-linux"; 30 | pkgs = nixpkgs; 31 | in rec { 32 | nixosConfigurations = { 33 | # Default module 34 | default = pkgs.lib.nixosSystem { 35 | specialArgs = {inherit inputs;}; 36 | modules = [ 37 | ../commons/configuration.nix 38 | ../commons/hardware-configuration.nix 39 | 40 | inputs.nixos-tidy.nixosModules.networking-privacy 41 | 42 | ################################### 43 | # You may move this module into its own file. 44 | ({ 45 | lib, 46 | inpus, 47 | config, 48 | ... 49 | }: let 50 | slib = inputs.nixos-tidy.lib; 51 | in { 52 | networking.privacy = { 53 | enable = true; 54 | }; 55 | }) 56 | ################################### 57 | ]; 58 | }; 59 | }; 60 | packages."${system}" = { 61 | default = nixosConfigurations.default.config.system.build.toplevel; 62 | }; 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /templates/umports/flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-parts": { 4 | "inputs": { 5 | "nixpkgs-lib": [ 6 | "nur", 7 | "nixpkgs" 8 | ] 9 | }, 10 | "locked": { 11 | "lastModified": 1733312601, 12 | "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", 13 | "owner": "hercules-ci", 14 | "repo": "flake-parts", 15 | "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", 16 | "type": "github" 17 | }, 18 | "original": { 19 | "owner": "hercules-ci", 20 | "repo": "flake-parts", 21 | "type": "github" 22 | } 23 | }, 24 | "home-manager": { 25 | "inputs": { 26 | "nixpkgs": [ 27 | "nixpkgs" 28 | ] 29 | }, 30 | "locked": { 31 | "lastModified": 1742588233, 32 | "narHash": "sha256-Fi5g8H5FXMSRqy+mU6gPG0v+C9pzjYbkkiePtz8+PpA=", 33 | "owner": "nix-community", 34 | "repo": "home-manager", 35 | "rev": "296ddc64627f4a6a4eb447852d7346b9dd16197d", 36 | "type": "github" 37 | }, 38 | "original": { 39 | "owner": "nix-community", 40 | "repo": "home-manager", 41 | "type": "github" 42 | } 43 | }, 44 | "home-manager_2": { 45 | "inputs": { 46 | "nixpkgs": [ 47 | "nixos-tidy", 48 | "nixpkgs" 49 | ] 50 | }, 51 | "locked": { 52 | "lastModified": 1710532761, 53 | "narHash": "sha256-SUXGZNrXX05YA9G6EmgupxhOr3swI1gcxLUeDMUhrEY=", 54 | "owner": "nix-community", 55 | "repo": "home-manager", 56 | "rev": "206f457fffdb9a73596a4cb2211a471bd305243d", 57 | "type": "github" 58 | }, 59 | "original": { 60 | "owner": "nix-community", 61 | "repo": "home-manager", 62 | "type": "github" 63 | } 64 | }, 65 | "nixos-tidy": { 66 | "inputs": { 67 | "home-manager": "home-manager_2", 68 | "nixpkgs": [ 69 | "nixpkgs" 70 | ] 71 | }, 72 | "locked": { 73 | "lastModified": 1734346232, 74 | "narHash": "sha256-SAWNYaKaVgfIltlz/SJgkBylhNoJTQqNMKDUykOsX9Y=", 75 | "owner": "pipelight", 76 | "repo": "nixos-tidy", 77 | "rev": "d33eb8777a672dcffa0b88120d24b717ddbd96b3", 78 | "type": "github" 79 | }, 80 | "original": { 81 | "owner": "pipelight", 82 | "repo": "nixos-tidy", 83 | "type": "github" 84 | } 85 | }, 86 | "nixpkgs": { 87 | "locked": { 88 | "lastModified": 1742512142, 89 | "narHash": "sha256-8XfURTDxOm6+33swQJu/hx6xw1Tznl8vJJN5HwVqckg=", 90 | "owner": "nixos", 91 | "repo": "nixpkgs", 92 | "rev": "7105ae3957700a9646cc4b766f5815b23ed0c682", 93 | "type": "github" 94 | }, 95 | "original": { 96 | "owner": "nixos", 97 | "ref": "nixos-24.11", 98 | "repo": "nixpkgs", 99 | "type": "github" 100 | } 101 | }, 102 | "nixpkgs_2": { 103 | "locked": { 104 | "lastModified": 1742422364, 105 | "narHash": "sha256-mNqIplmEohk5jRkqYqG19GA8MbQ/D4gQSK0Mu4LvfRQ=", 106 | "owner": "nixos", 107 | "repo": "nixpkgs", 108 | "rev": "a84ebe20c6bc2ecbcfb000a50776219f48d134cc", 109 | "type": "github" 110 | }, 111 | "original": { 112 | "owner": "nixos", 113 | "ref": "nixos-unstable", 114 | "repo": "nixpkgs", 115 | "type": "github" 116 | } 117 | }, 118 | "nur": { 119 | "inputs": { 120 | "flake-parts": "flake-parts", 121 | "nixpkgs": "nixpkgs_2", 122 | "treefmt-nix": "treefmt-nix" 123 | }, 124 | "locked": { 125 | "lastModified": 1742639006, 126 | "narHash": "sha256-g4aNYcqPJJ63/15ACtVZosChOQRAV89+BNXPdAH3Oio=", 127 | "owner": "nix-community", 128 | "repo": "NUR", 129 | "rev": "1d93c884f94993958d5f7da1a851ce10a324c539", 130 | "type": "github" 131 | }, 132 | "original": { 133 | "owner": "nix-community", 134 | "repo": "NUR", 135 | "type": "github" 136 | } 137 | }, 138 | "root": { 139 | "inputs": { 140 | "home-manager": "home-manager", 141 | "nixos-tidy": "nixos-tidy", 142 | "nixpkgs": "nixpkgs", 143 | "nur": "nur" 144 | } 145 | }, 146 | "treefmt-nix": { 147 | "inputs": { 148 | "nixpkgs": [ 149 | "nur", 150 | "nixpkgs" 151 | ] 152 | }, 153 | "locked": { 154 | "lastModified": 1733222881, 155 | "narHash": "sha256-JIPcz1PrpXUCbaccEnrcUS8jjEb/1vJbZz5KkobyFdM=", 156 | "owner": "numtide", 157 | "repo": "treefmt-nix", 158 | "rev": "49717b5af6f80172275d47a418c9719a31a78b53", 159 | "type": "github" 160 | }, 161 | "original": { 162 | "owner": "numtide", 163 | "repo": "treefmt-nix", 164 | "type": "github" 165 | } 166 | } 167 | }, 168 | "root": "root", 169 | "version": 7 170 | } 171 | -------------------------------------------------------------------------------- /templates/umports/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "A flake that uses nixos-tidy umports"; 3 | inputs = { 4 | nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; 5 | 6 | nixos-tidy = { 7 | url = "github:pipelight/nixos-tidy"; 8 | inputs.nixpkgs.follows = "nixpkgs"; 9 | }; 10 | 11 | ################################### 12 | ## NixOs-tidy and dependencies 13 | home-manager = { 14 | url = "github:nix-community/home-manager"; 15 | inputs.nixpkgs.follows = "nixpkgs"; 16 | }; 17 | 18 | ################################### 19 | ## Testing purpose only 20 | # NUR - Nix User Repository 21 | nur.url = "github:nix-community/NUR"; 22 | }; 23 | 24 | outputs = { 25 | self, 26 | nixpkgs, 27 | ... 28 | } @ inputs: let 29 | system = "x86_64-linux"; 30 | pkgs = nixpkgs; 31 | in rec { 32 | nixosConfigurations = { 33 | # Default module 34 | default = pkgs.lib.nixosSystem { 35 | specialArgs = {inherit inputs;}; 36 | modules = [ 37 | ../commons/configuration.nix 38 | ../commons/hardware-configuration.nix 39 | 40 | ################################### 41 | # You may move this module into its own file. 42 | ({ 43 | lib, 44 | inpus, 45 | config, 46 | ... 47 | }: let 48 | slib = inputs.nixos-tidy.lib; 49 | in { 50 | # Create a user. 51 | users.users."anon" = { 52 | isNormalUser = true; 53 | }; 54 | 55 | imports = 56 | [ 57 | inputs.home-manager.nixosModules.home-manager 58 | ] 59 | /* 60 | Import all nixos modules recursively 61 | */ 62 | ++ slib.umportNixModules { 63 | paths = [ 64 | ./. 65 | ]; 66 | exclude = [ 67 | # Do not forget to exclude current file 68 | # and flake definition. 69 | ./default.nix 70 | ./flake.nix 71 | ]; 72 | } 73 | /* 74 | Import all home-manager modules recursively 75 | Uses home-merger under the hood. 76 | */ 77 | ++ slib.umportHomeModules 78 | # Function's first argument: 79 | # Umports parameters 80 | { 81 | paths = [ 82 | ./. 83 | ]; 84 | exclude = [ 85 | ./flake.nix 86 | ]; 87 | } 88 | # Function's second argument: 89 | # Home-merger options 90 | { 91 | users = ["anon"]; 92 | imports = [ 93 | inputs.nur.modules.homeManager.default 94 | ]; 95 | }; 96 | }) 97 | ################################### 98 | ]; 99 | }; 100 | }; 101 | packages."${system}" = { 102 | default = nixosConfigurations.default.config.system.build.toplevel; 103 | }; 104 | }; 105 | } 106 | -------------------------------------------------------------------------------- /templates/umports/my_module/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | pkgs, 4 | lib, 5 | utils, 6 | inputs, 7 | ... 8 | }: { 9 | environment.etc = { 10 | "test/umport".text = '' 11 | This is a random test file to check if umport module works. 12 | ''; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /templates/umports/my_module/home.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | pkgs, 4 | lib, 5 | ... 6 | }: { 7 | home.packages = with pkgs; [ 8 | ## Password managers 9 | keepassxc 10 | gnupg 11 | cryptsetup 12 | ]; 13 | 14 | home.file = { 15 | "test/umport".text = '' 16 | This is a random test file to check if umport-home module works. 17 | ''; 18 | }; 19 | } 20 | --------------------------------------------------------------------------------