diff --git a/LICENSE.org b/LICENSE.org new file mode 100644 index 0000000..523f707 --- /dev/null +++ b/LICENSE.org @@ -0,0 +1,17 @@ +* Licensing +The source code you can find in various programming languages in this +repository including, but not limited to, Javascript and CSS source +code is under the [[https://www.gnu.org/licenses/agpl-3.0.html][AGPL-3.0]] licence. + +The creative work contained in [[https://labs.phundrak.com/phundrak/langue-phundrak-com][the main code repository]], on my [[https://github.com/Phundrak/langue-phundrak-fr/][Github +mirror]], and on my website [[https://langue.phundrak.com][langue.phundrak.com]] is dual-licenced +between the [[https://www.gnu.org/licenses/#FDL][GNU Free Documentation License]] ([[file:fdl-1.3.md][legal code]]) for the text +and the /Creative Commons Attribution-NonCommercial-ShareAlike 4.0 +International/ ([[https://creativecommons.org/licenses/by-nc-sa/4.0/][CC BY-NC-SA 4.0]], [[https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode][legal code]]) license. + +Copies of all the mentionned licenses can be found in this code +repository. + +If you wish to obtain a special license that is incompatible with the +current ones, please contact me at [[mailto:lucien@phundrak.com][lucien@phundrak.com]] so we can +discuss it. diff --git a/modules/boot/hardened.nix b/modules/boot/hardened.nix index 0a939b6..1606f2d 100644 --- a/modules/boot/hardened.nix +++ b/modules/boot/hardened.nix @@ -1,44 +1,26 @@ { flake.modules.nixos.hardened = { - lib, - config, - ... - }: - with lib; let - cfg = config.mySystem.boot.kernel; - in { - options.mySystem.boot.kernel.hardened = mkEnableOption "Enables hardened Linux kernel"; - - config.boot = { - kernelModules = lists.optional cfg.hardened "tcp_bbr"; - kernel.sysctl = mkIf cfg.hardened { - "kernel.sysrq" = 0; # Disable magic SysRq key - # Ignore ICMP broadcasts to avoid participating in Smurf attacks - "net.ipv4.icmp_echo_ignore_broadcasts" = 1; - # Ignore bad ICMP errors - "net.ipv4.icmp_ignore_bogus_error_responses" = 1; - # SYN flood protection - "net.ipv4.tcp_syncookies" = 1; - # Do not accept ICMP redirects (prevent MITM attacks) - "net.ipv4.conf.all.accept_redirects" = 0; - "net.ipv4.conf.default_accept_redirects" = 0; - "net.ipv4.conf.all.secure_redirects" = 0; - "net.ipv4.conf.default.secure_redirects" = 0; - "net.ipv6.conf.all.accept_redirects" = 0; - "net.ipv6.conf.default.accept_redirects" = 0; - # Do not send ICMP redirects (we are not a router) - "net.ipv4.conf.all.send_redirects" = 0; - # Do not accept IP source route packets (we are not a router) - "net.ipv4.conf.all.accept_source_route" = 0; - "net.ipv6.conf.all.accept_source_route" = 0; - # Protect against tcp time-wait assassination hazards - "net.ipv4.tcp_rfc1337" = 1; - # Latency reduction - "net.ipv4.tcp_fastopen" = 3; - # Bufferfloat mitigations - "net.ipv4.tcp_congestion_control" = "bbr"; - "net.core.default_qdisc" = "cake"; - }; + boot = { + kernelModules = ["tcp_bbr"]; + kernel.sysctl = { + "kernel.sysrq" = 0; + "net.ipv4.icmp_echo_ignore_broadcasts" = 1; + "net.ipv4.icmp_ignore_bogus_error_responses" = 1; + "net.ipv4.conf.all.accept_redirects" = 0; + "net.ipv4.conf.default_accept_redirects" = 0; + "net.ipv4.conf.all.secure_redirects" = 0; + "net.ipv4.conf.default.secure_redirects" = 0; + "net.ipv6.conf.all.accept_redirects" = 0; + "net.ipv6.conf.default.accept_redirects" = 0; + "net.ipv4.conf.all.send_redirects" = 0; + "net.ipv4.conf.all.accept_source_route" = 0; + "net.ipv6.conf.all.accept_source_route" = 0; + "net.ipv4.tcp_syncookies" = 1; + "net.ipv4.tcp_rfc1337" = 1; + "net.ipv4.tcp_congestion_control" = "bbr"; + "net.core.default_qdisc" = "cake"; + "net.ipv4.tcp_fastopen" = 3; }; }; + }; } diff --git a/modules/boot/hardened.org b/modules/boot/hardened.org new file mode 100644 index 0000000..2920440 --- /dev/null +++ b/modules/boot/hardened.org @@ -0,0 +1,116 @@ +#+title: Kernel Hardening +#+setupfile: ../headers + +* Kernel Hardening +Some of my machines are exposed to the Internet, and therefore get +their kernel hardened. First, let me declare the Nix file’s skeleton, +with the =nixos.hardened= module. + +#+begin_src nix :tangle yes +{ + flake.modules.nixos.hardened = { + boot = { + <> + <> + }; + }; +} +#+end_src + +** Kernel Modules +The very first thing to do is to load the =tcp_bbr= kernel module. It +increases the connection speed of the system with a better congestion +control. It is particularly interesting for my servers, as they may +have to deal with high traffic if a crawler ever decides to explore +all webpages offered by some websites I host. See [[https://www.cyberciti.biz/cloud-computing/increase-your-linux-server-internet-speed-with-tcp-bbr-congestion-control/][this article]] by +Nixcraft for more details. +#+name: kernel-modules +#+begin_src nix +kernelModules = ["tcp_bbr"]; +#+end_src + +** Kernel Options +Next are a series of kernel options. +#+name: kernel-options +#+begin_src nix +kernel.sysctl = { + <> + <> + <> + <> + <> + <> + <> + <> + <> +}; +#+end_src + +First, we’ll disable the magic SysRq key. Not that I expect anyone to +have physical access to my servers, but it is a really powerful tool +that I’d rather have off. +#+name: sysrq-key +#+begin_src nix +"kernel.sysrq" = 0; +#+end_src + +Next, we’ll ignore ICMP broadcasts to avoid participating in Smurf +attacks, and we’ll also ignore ICMP errors. +#+name: icmp +#+begin_src nix +"net.ipv4.icmp_echo_ignore_broadcasts" = 1; +"net.ipv4.icmp_ignore_bogus_error_responses" = 1; +#+end_src + +Speaking of ICMP, we won’t accept ICMP redirects to prevent some MITM +attacks. +#+name: icmp-no-accept-redirects +#+begin_src nix +"net.ipv4.conf.all.accept_redirects" = 0; +"net.ipv4.conf.default_accept_redirects" = 0; +"net.ipv4.conf.all.secure_redirects" = 0; +"net.ipv4.conf.default.secure_redirects" = 0; +"net.ipv6.conf.all.accept_redirects" = 0; +"net.ipv6.conf.default.accept_redirects" = 0; +#+end_src + +And we won’t send ICMP redirects (we’re not a router). +#+name: icmp-no-send-redirects +#+begin_src nix +"net.ipv4.conf.all.send_redirects" = 0; +#+end_src + +We’re stil not a router, so we’ll refuse IP source route packets, both +on IPV4 and IPV6. +#+name: ip-source-route-packets +#+begin_src nix +"net.ipv4.conf.all.accept_source_route" = 0; +"net.ipv6.conf.all.accept_source_route" = 0; +#+end_src + +Now, let’s get some SYN flood protection. +#+name: syn +#+begin_src nix +"net.ipv4.tcp_syncookies" = 1; +#+end_src + +And protection against TCP time-wait assassination hazards. +#+name: tcp-time-wait +#+begin_src nix +"net.ipv4.tcp_rfc1337" = 1; +#+end_src + +We will also mitigate bufferfloat, including with BBR (hey, we enabled that above!) +#+name: bufferfloat +#+begin_src nix +"net.ipv4.tcp_congestion_control" = "bbr"; +"net.core.default_qdisc" = "cake"; +#+end_src + +And lastly, we’ll reduce latency on IPV4. +#+name: latency +#+begin_src nix +"net.ipv4.tcp_fastopen" = 3; +#+end_src + +And we should be good to go! diff --git a/modules/boot/loader.org b/modules/boot/loader.org new file mode 100644 index 0000000..b342b2c --- /dev/null +++ b/modules/boot/loader.org @@ -0,0 +1,74 @@ +#+title: Bootloaders and Filesystems +#+setupfile: ../headers + +* Bootloaders and Filesystems +This page sets up the bootloader of my machines. Whilst I generally +prefer to use [[https://systemd.io/BOOT/][systemd-boot]], some of my VPS use GRUB, and some use ZFS. +All that gets exposed with my module =nixos.loader=. + +#+begin_src nix :tangle loader.new.nix +{ + flake.modules.nixos.loader = { + lib, + config, + ... + }: + with lib; let + cfg = config.mySystem.boot; + in { + + }; +} +#+end_src + +** Bootloaders +By default, I want to use systemd-boot on my machines, but I need it +to be disabled whenever I use something else. For now, this “something +else” is only GRUB, but I’m not excluding using something else on yet +another machine such as [[https://www.rodsbooks.com/refind/][rEFInd]]. To ensure a single source of truth +regarding whether systemd-boot is to be used, I have an option for +that. +#+name: systemd-boot-options +#+begin_src nix +options.mySystem.boot.systemd-boot = mkOption { + type = types.bool; + default = !cfg.grub.enable; + description = "Does the system use systemd-boot?"; +}; +#+end_src + +I can now set some options depending on that, such as whether to +enable systemd-boot itself (duh), and whether the installation process +can touch my EFI variables. +#+name: systemd-boot-config +#+begin_src nix +config.boot.loader = { + systemd-boot.enable = cfg.systemd-boot; + efi.canTouchEfiVariables = cfg.systemd-boot; +}; +#+end_src + +But, I have a VPS that requires me to use GRUB. For this, I also have +an option to enable it. +#+name: grub-options +#+begin_src nix +options.mySystem.boot.grub = { + enable = mkEnableOption "Does the system use GRUB? (Disables systemd-boot)"; + device = mkOption { + type = types.path; + description = "The GRUB device"; + default = ""; + }; +}; +#+end_src + +I can no pass these options to the boot configuration of my machine. +#+name: grub-config +#+begin_src nix +config.boot.loader.grub = mkIf cfg.grub.enable { + inherit (cfg.grub) enable device; +}; +#+end_src + +** ZFS +Now, this is where I enable diff --git a/modules/default.nix b/modules/default.nix index cb041bf..f2e90d1 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -25,7 +25,6 @@ inputs.nixpkgsUnstable.follows = "nixpkgsPinetab2Kernel"; }; }; - systems = ["x86_64-linux" "aarch64-linux"]; flake.lib = { @@ -37,7 +36,6 @@ ]; }; }; - mkHome = system: userName: hostName: { "${userName}@${hostName}" = inputs.home-manager.lib.homeManagerConfiguration { pkgs = inputs.nixpkgs.legacyPackages.${system}; @@ -48,7 +46,6 @@ modules = [config.flake.modules.homeManager."${userName}-${hostName}"]; }; }; - mkPinetab = buildPlatform: variantModule: { pinetab2 = inputs.nixpkgs.lib.nixosSystem { system = "aarch64-linux"; @@ -72,24 +69,23 @@ }; flake.nixosConfigurations = lib.mkMerge [ - (config.flake.lib.mkNixos "x86_64-linux" "elcafe") - (config.flake.lib.mkNixos "x86_64-linux" "gampo") (config.flake.lib.mkNixos "x86_64-linux" "marpa") - (config.flake.lib.mkNixos "x86_64-linux" "NaroMk3") + (config.flake.lib.mkNixos "x86_64-linux" "gampo") (config.flake.lib.mkNixos "x86_64-linux" "tilo") + (config.flake.lib.mkNixos "x86_64-linux" "elcafe") + (config.flake.lib.mkNixos "x86_64-linux" "NaroMk3") (config.flake.lib.mkPinetab "x86_64-linux" config.flake.modules.nixos.pinetab2-gnome) ]; - + flake.homeConfigurations = lib.mkMerge [ - (config.flake.lib.mkHome "x86_64-linux" "phundrak" "elcafe") - (config.flake.lib.mkHome "x86_64-linux" "phundrak" "gampo") (config.flake.lib.mkHome "x86_64-linux" "phundrak" "marpa") - (config.flake.lib.mkHome "x86_64-linux" "phundrak" "NaroMk3") - (config.flake.lib.mkHome "x86_64-linux" "phundrak" "pinetab2") + (config.flake.lib.mkHome "x86_64-linux" "phundrak" "gampo") (config.flake.lib.mkHome "x86_64-linux" "phundrak" "tilo") + (config.flake.lib.mkHome "x86_64-linux" "phundrak" "elcafe") (config.flake.lib.mkHome "x86_64-linux" "creug" "elcafe") + (config.flake.lib.mkHome "x86_64-linux" "phundrak" "NaroMk3") + (config.flake.lib.mkHome "aarch64-linux" "phundrak" "pinetab2") ]; - perSystem = { pkgs, system, diff --git a/modules/headers b/modules/headers new file mode 100644 index 0000000..6398e47 --- /dev/null +++ b/modules/headers @@ -0,0 +1,22 @@ +# -*- mode: org -*- +#+AUTHOR: Lucien Cartier-Tilet +#+EMAIL: lucien@phundrak.com +#+CREATOR: Lucien Cartier-Tilet +#+LANGUAGE: en + +# ### ORG OPTIONS ############################################################## + +#+options: H:4 broken_links:mark email:t ^:{} tex:dvisvgm toc:nil +#+KEYWORDS: dotfiles, linux, emacs, configuration, phundrak, drakpa +#+startup: content align hideblocks +#+property: header-args:emacs-lisp :noweb yes :exports none :eval yes :cache yes +#+property: header-args:nix :exports code :tangle no :noweb no-export +#+property: header-args:dot :dir img :exports results :eval yes :cache yes :class gentree + +# ### MACROS ################################################################### +#+macro: phon @@html:/$1/@@ +#+macro: newline @@html:
@@ +#+macro: latex-html @@latex:$1@@@@html:$2@@ +#+macro: v @@html:$1@@ +#+macro: begin-largetable @@html:
@@ +#+macro: end-largetable @@html:
@@ diff --git a/modules/index.org b/modules/index.org new file mode 100644 index 0000000..e3306d4 --- /dev/null +++ b/modules/index.org @@ -0,0 +1,343 @@ +#+title: P’undrak’s Litterate Nix Config +#+setupfile: headers +#+property: header-args:emacs-lisp :lexical t :exports none :tangle no + +* Index +Hi, I’m P’undrak (pronounced /PUN-drak/, or more exactly {{{phon(pʰynɖak̚)}}}), +also known as Lucien Cartier-Tilet. If you want to know more about me, +you can head to my [[https://phundrak.com/en][main website]]. + +This website documents my entire Linux configuration, managed through +NixOS. Most of my programs are configured through Nix, following the +[[https://github.com/Doc-Steve/dendritic-design-with-flake-parts][dendritic pattern]]. + +To give you a tl;dr, this basically means that each aspect of my +configuration (be it a concept or an application) tries to only have a +single source of truth. But as you can see with my Emacs +configuration, some aspects can be quite extensive and require several +pages to be properly organised. + +** License +See [[https://labs.phundrak.com/phundrak/dotfiles/src/branch/master/LICENSE.org][the repository’s license file]]. + +** Note on What a Literate Configuration Is +As implied by the title of this website, my configuration is a +litterate one. This means that every page of this website comes from +an Emacs org-mode file, and the code you see as code blocks are the +actual source of my configuration. + +Org-mode offers to “tangle” these code blocks into full files, which +can then be used as any other source file. If you visit this website’s +repository, you will find the source org files alongside their +resulting Nix file if any is generated by said file. For instance, +this very page generates my =modules/default.nix= file, as we’ll see +below. + +This also implies heavy usage of the [[https://orgmode.org/manual/Noweb-Reference-Syntax.html][noweb]] syntax. If you encounter +some code that looks ~<>~, org-mode will replace this snippet +with another code snippet declared elsewhere in my configuration. If +you see some code that looks ~<>~, some generating code +will run and replace this piece of text with the text generated. A +quick example: +#+begin_src elisp +(defun hello () + <> + <>) +#+end_src + +Will instead appear as +#+begin_src emacs-lisp :noweb yes +(defun hello () + <> + <>) +#+end_src + +This is because I have the block of code below named +~generate-docstring~ which generates an output, which replaces its noweb +tag. You can recognize noweb snippets generating code with the +parenthesis. Often, such blocks aren’t visible in my HTML exports, but +you can still see them if you open the actual org source file. +#+name: generate-docstring +#+begin_src emacs-lisp +(concat "\"" + "Print \\\"Hello World!\\\" in the minibuffer." + "\"") +#+end_src + +On the other hand, noweb snippets without parenthesis simply replace +the snippet with the equivalent named code block. For instance the one +below is named ~print-hello~ and is placed as-is in the target source +block. +#+name: print-hello +#+begin_src emacs-lisp +(message "Hello World!") +#+end_src + +** Root Nix Configuration +As this configuration uses [[https://flake.parts/][flake-parts]] and [[https://flake-file.denful.dev/][flake-file]], I need a +=modules/default.nix= which defines how to manage my config. + +For the record, I use [[https://github.com/nix-community/nh][nh]] to compile my configuration and switch to +newer generations of my OS and home. This allows me to simply run =nh +os switch= to upgrade my system, or =nh home switch= to upgrade my +[[https://nix-community.github.io/home-manager/][home-manager]] configuration. This, therefore, requires to have [[https://nixos.wiki/wiki/flakes][flakes]] +outputs in the form of =nixosConfigurations.marpa= (with =marpa= being the +hostname of a machine) and =homeConfigurations.phundrak= or +=homeConfigurations.phundrak@marpa= (with =phundrak= being the username of +one of the users of a machine). + +But first things first, let’s declare the closure that will +encapsulate the rest of the file: +#+begin_src nix :tangle default.nix +{ + inputs, + lib, + config, + ... +}: { + <> + + <> + + config = { + <> + <> + + flake.lib = { + <> + <> + <> + }; + + <> + <> + }; +} +#+end_src + +To get our configuration to work, we need to import the modules from +flake-parts and flake-file. +#+name: modules-imports +#+begin_src nix +imports = [ + inputs.flake-parts.flakeModules.modules + inputs.flake-file.flakeModules.default +]; +#+end_src + +Now, we can declare an option to make =homeConfigurations= available as +an output for our flakes. +#+name: options-home +#+begin_src nix +options.flake.homeConfigurations = lib.mkOption { + type = lib.types.lazyAttrsOf lib.types.raw; + default = {}; +}; +#+end_src + +*** Setting Things Up +We need to declare a few inputs for our flake, thanks to +flake-file. The first one is =flake-utils=, which allows me to easily +declare my development shell for this repository both for my x86-64 +machines and my aarch64 tablet, a PineTab 2. Then, speaking of the +PineTab, I need some specific nixpkgs input, to handle a bug in the +compilation of the kernel, as well as the flake =rockchip= to support +said kernel. +#+name: flake-inputs +#+begin_src nix +flake-file.inputs = { + flake-utils.url = "github:numtide/flake-utils"; + nixpkgsPinetab2Kernel.url = "github:nixos/nixpkgs/e73de5be04e0eff4190a1432b946d469c794e7b4"; + rockchip = { + url = "github:raboof/nixos-rockchip/pinetab-linux-7.0"; + inputs.utils.follows = "flake-utils"; + inputs.nixpkgsStable.follows = "nixpkgsStable"; + inputs.nixpkgsUnstable.follows = "nixpkgsPinetab2Kernel"; + }; +}; +#+end_src + +As I said, I support two architectures for my development shell, so +let’s declare them. +#+name: dev-arch +#+begin_src nix +systems = ["x86_64-linux" "aarch64-linux"]; +#+end_src + +Now, we can declare some functions for our flake. These three +functions’ role is to create the output of each machine and user as +required. First, let’s create the function to get a machine’s +configuration based on its name. +#+name: lib-mkNixos +#+begin_src nix +mkNixos = system: name: { + ${name} = inputs.nixpkgs.lib.nixosSystem { + modules = [ + config.flake.modules.nixos.${name} + {nixpkgs.hostPlatform = lib.mkDefault system;} + ]; + }; +}; +#+end_src + +What this does is basically declare a Nix system named after the +host’s name, created with its module (located in =modules/hosts/=) and +the related nixpkgs with the appropriate architecture. For now, the +only architecture used with this function is x86-64, but I’m not +excluding the posibility to have other hosts using an ARM CPU. + +=mkHome= is somewhat similar: it declares a home-manager module, +importing the module related to the user and the machine it will be +deployed on. +#+name: lib-mkHome +#+begin_src nix +mkHome = system: userName: hostName: { + "${userName}@${hostName}" = inputs.home-manager.lib.homeManagerConfiguration { + pkgs = inputs.nixpkgs.legacyPackages.${system}; + extraSpecialArgs = { + inherit inputs; + bunBaseline = config.flake.packages.${system}.bun-baseline; + }; + modules = [config.flake.modules.homeManager."${userName}-${hostName}"]; + }; +}; +#+end_src + +You may notice the declaration of =bunBaseline=. This is because of my +Thinkpad x220; the default binary distributed for Bun uses CPU +instructions that are more recent than this laptop’s CPU, which +results in fatal errors trying to run it. Therefore, =bunBaseline= is +here to either compile Bun on my Thinkpad with the correct instruction +set, or simply use a prepackaged Bun if the host supports it. + +Lastly, I have a function dedicated to building NixOS on my PineTab 2. +#+name: lib-mkPinetab +#+begin_src nix +mkPinetab = buildPlatform: variantModule: { + pinetab2 = inputs.nixpkgs.lib.nixosSystem { + system = "aarch64-linux"; + modules = [ + inputs.rockchip.nixosModules.sdImageRockchip + inputs.rockchip.nixosModules.dtOverlayPCIeFix + inputs.rockchip.nixosModules.noZFS + config.flake.modules.nixos.pinetab2-base + variantModule + { + rockchip.uBoot = inputs.rockchip.packages.${buildPlatform}.uBootPineTab2; + boot.kernelPackages = + inputs.rockchip.legacyPackages.${buildPlatform}.kernel_linux_7_0_pinetab_unstable; + hardware.firmware = [inputs.rockchip.packages.aarch64-linux.bes2600]; + nixpkgs.config.allowUnfreePredicate = pkg: + builtins.elem (inputs.nixpkgs.lib.getName pkg) ["bes2600-firmware"]; + } + ]; + }; +}; +#+end_src + +I won’t go into too much details here, but it mostly imports the +modules required to run NixOS on the Pinetab as well as explicitly +import the bes2600 firmware module to make Bluetooth and Wi-Fi +available on the tablet. + +*** Declaring the Actual Outputs +With all that being said, we can now actually declare our +configurations. You can see below the table of hosts I have, with +their CPU architecture, and which users are present on the system. + +#+name: table-hosts +| Host | Architecture | Users | Comment | +|----------+---------------+-----------------+------------------| +| marpa | x86_64-linux | phundrak | Main workstation | +| gampo | x86_64-linux | phundrak | Thinkpad x220 | +| tilo | x86_64-linux | phundrak | Home Server | +| elcafe | x86_64-linux | phundrak, creug | Server | +| NaroMk3 | x86_64-linux | phundrak | Cloud Server | +| pinetab2 | aarch64-linux | phundrak | PineTab 2 tablet | + +#+name: make-hosts +#+begin_src emacs-lisp :exports none :var hosts=table-hosts :cache yes +(mapconcat + (lambda (line) + (let ((hostname (car line)) + (arch (nth 1 line))) + (format "(config.flake.lib.mkNixos \"%s\" \"%s\")" + arch + hostname))) + (-filter (lambda (host) (not (string= "pinetab2" (car host)))) + hosts) + "\n") +#+end_src + +#+RESULTS[f5f8b3a89622e7526a83cbf722c4b7c77ff7bd86]: make-hosts +: (config.flake.lib.mkNixos "x86_64-linux" "marpa") +: (config.flake.lib.mkNixos "x86_64-linux" "gampo") +: (config.flake.lib.mkNixos "x86_64-linux" "tilo") +: (config.flake.lib.mkNixos "x86_64-linux" "elcafe") +: (config.flake.lib.mkNixos "x86_64-linux" "NaroMk3") + +#+name: make-home +#+begin_src emacs-lisp :exports none :var hosts=table-hosts :cache yes +(require 's) + +(mapconcat + (lambda (line) + (let ((hostname (car line)) + (arch (nth 1 line)) + (users (mapcar #'s-trim (s-split "," (nth 2 line) t)))) + (mapconcat (lambda (user) + (format "(config.flake.lib.mkHome \"%s\" \"%s\" \"%s\")" + arch user hostname)) + users + "\n"))) + hosts + "\n") +#+end_src + +#+RESULTS[301fccb07591fffc8d7bdfd7d2958602150aa688]: make-home +: (config.flake.lib.mkHome "x86_64-linux" "phundrak" "marpa") +: (config.flake.lib.mkHome "x86_64-linux" "phundrak" "gampo") +: (config.flake.lib.mkHome "x86_64-linux" "phundrak" "tilo") +: (config.flake.lib.mkHome "x86_64-linux" "phundrak" "elcafe") +: (config.flake.lib.mkHome "x86_64-linux" "creug" "elcafe") +: (config.flake.lib.mkHome "x86_64-linux" "phundrak" "NaroMk3") +: (config.flake.lib.mkHome "aarch64-linux" "phundrak" "pinetab2") + +This translates into this Nix code. +#+name: configs-decl +#+begin_src nix :noweb yes +flake.nixosConfigurations = lib.mkMerge [ + <> + (config.flake.lib.mkPinetab "x86_64-linux" config.flake.modules.nixos.pinetab2-gnome) +]; + +flake.homeConfigurations = lib.mkMerge [ + <> +]; +#+end_src + +*** Development Shell +Lastly, here is the declaration of my development shell. It really is +only useful if I’m on a new machine or a machine that is not quite up +to date and misses some packages I rely on to work on my dotfiles. +Namely, these are =nh= (which I mentioned above), Jujutsu, =jj-cz= (a +Commitizen alternative for Jujutsu I’m working on), and Git itself as +a fallback. +#+name: devshell +#+begin_src nix +perSystem = { + pkgs, + system, + ... +}: { + formatter = pkgs.alejandra; + devShells.default = pkgs.mkShell { + buildInputs = [ + pkgs.nh + pkgs.jujutsu + pkgs.git + inputs.jj-cz.packages.${system}.default + ]; + }; +}; +#+end_src diff --git a/modules/inputs.nix b/modules/inputs.nix index 622d875..1761653 100644 --- a/modules/inputs.nix +++ b/modules/inputs.nix @@ -11,5 +11,5 @@ }; }; flake-file.outputs = "dendritic"; - flake-file.description = "NixOS and Home Manager configuration of phundrak"; + flake-file.description = "NixOS and Home Manager configuration of P'undrak"; } diff --git a/modules/inputs.org b/modules/inputs.org new file mode 100644 index 0000000..e27426e --- /dev/null +++ b/modules/inputs.org @@ -0,0 +1,82 @@ +#+title: Flake File Setup +#+setupfile: headers + +* Flake File Setup +This configuration uses [[https://flake-file.denful.dev/][flake-file]]. This means my =flake.nix= file is +modular, as it allows me to define my inputs where I need them, and +not necessarily all at the same place. This can be a bit unusual for +people who are new to it, but trust me, it’s well worth it. + +I’ll simply set up the outputs, a single one named =dendritic=, and the +description here, as nothing is too complicated. +#+begin_src nix :tangle yes +{ + <> + flake-file.outputs = "dendritic"; + flake-file.description = "NixOS and Home Manager configuration of P'undrak"; +} +#+end_src + +** Inputs +Some flake imputs are required globally, as they are used by default +by this configuration and some hosts. + +#+name: inputs +#+begin_src nix +flake-file.inputs = { + <> + <> + <> + <> + <> +}; +#+end_src + +First, we get to nixpkgs, which +is quite necessary to get NixOS up and running: it gives access to +Nix’s packages. I also have a =nixpkgsStable= input for the kernel of my +PineTab 2 tablet. Otherwise, I use Nix unstable. + +#+name: inputs-nixpkgs +#+begin_src nix +nixpkgsStable.url = "nixpkgs/nixos-25.11"; +nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; +#+end_src + +Next, I need some inputs for my dendritic config. =flake-parts= is the +heart of it: it’s a framework for writing flake modules that can +easily be put together as a single module defining an entire system, +such as a home configuration or a host configuration. +#+name: inputs-flake-parts +#+begin_src nix +flake-parts.url = "github:hercules-ci/flake-parts"; +#+end_src + +Next, we have flake-file, which permits the modularisation of my +=flake.nix= file itself, as mentioned abve. +#+name: inputs-flake-file +#+begin_src nix +flake-file.url = "github:vic/flake-file"; +#+end_src + +Next, we have =import-tree=, which automatically imports my Nix files, +making all modules globally known. +#+name: inputs-import-tree +#+begin_src nix +import-tree.url = "github:vic/import-tree"; +#+end_src + +And last but not least, =home-manager=. This allows me to manage the +programs of me as the user of my machine and not necessarily the +machine itself, as well as their configuration. As such, I can upgrade +a machine’s system without touching my environment, and the inverse is +true. However, it’s important to keep them in sync when it comes to +major upgrades of NixOS, so home-manager will follow the system’s +version. +#+name: inputs-home-manager +#+begin_src nix +home-manager = { + url = "github:nix-community/home-manager"; + inputs.nixpkgs.follows = "nixpkgs"; +}; +#+end_src diff --git a/modules/misc.nix b/modules/misc.nix index 3ecf0d4..10a1622 100644 --- a/modules/misc.nix +++ b/modules/misc.nix @@ -7,31 +7,27 @@ with lib; let cfg = config.mySystem.misc; in { - options.mySystem.misc = { - timezone = mkOption { - type = types.str; - default = "Europe/Paris"; - }; - keymap = mkOption { - type = types.str; - default = "fr"; - example = "fr-bepo"; - description = "Keymap to use in the TTY console"; - }; + options.mySystem.misc.timezone = mkOption { + type = types.str; + default = "Europe/Paris"; + }; + options.mySystem.misc.keymap = mkOption { + type = types.str; + default = "fr"; + example = "fr-bepo"; + description = "Keymap to use in the TTY console"; }; config = { - boot.tmp.cleanOnBoot = true; console.keyMap = cfg.keymap; time.timeZone = cfg.timezone; + services.envfs.enable = true; + services.orca.enable = false; + boot.tmp.cleanOnBoot = true; environment.pathsToLink = [ "/share/bash-completion" "/share/zsh" ]; - services = { - orca.enable = false; - envfs.enable = true; - }; }; }; } diff --git a/modules/misc.org b/modules/misc.org new file mode 100644 index 0000000..659f8f0 --- /dev/null +++ b/modules/misc.org @@ -0,0 +1,109 @@ +#+title: Misc NixOS Configurations +#+setupfile: headers + +* Misc NixOS Configurations + +This module hosts some misc configuration I am unsure where to put +elsewhere than here. Don’t expect this file to be coherent, but expect +it to be quite short. + +This module declares the aspect =nixos.misc=, which is used by all my +hosts. + +#+begin_src nix :tangle yes +{ + flake.modules.nixos.misc = { + lib, + config, + ... + }: + with lib; let + cfg = config.mySystem.misc; + in { + <> + <> + + config = { + <> + <> + <> + <> + <> + <> + }; + }; +} +#+end_src + +** System Timezone +First, let me declare the timezone. I’ll set it as an option, as not +all my machines live in the same place, but I’ll default to +Metropolitan France’s timezone. +#+name: timezone-option +#+begin_src nix +options.mySystem.misc.timezone = mkOption { + type = types.str; + default = "Europe/Paris"; +}; +#+end_src + +Now, I can set it for my system. +#+name: timezone-config +#+begin_src nix +time.timeZone = cfg.timezone; +#+end_src + +** TTY Keyboard Layout +Now, I can set the TTY’s keyboard config. Most of my machines use the +Bépo layout everywhere, but I do share one whose owner doesn’t use it, +so I’ll let this as an option to be set, defaulting to the default +French layout. +#+name: layout-option +#+begin_src nix +options.mySystem.misc.keymap = mkOption { + type = types.str; + default = "fr"; + example = "fr-bepo"; + description = "Keymap to use in the TTY console"; +}; +#+end_src + +Now, I can set it on my system. +#+name: layout-config +#+begin_src nix +console.keyMap = cfg.keymap; +#+end_src + +** Truly Miscelaneous Config +First, some scripts are written with the assumption that some +utilities are always in the same place, such as =/bin/bash=. It is, +however, not always the case with NixOS. Mic92’s [[https://github.com/Mic92/envfs][envfs]] solves that. +#+name: envfs +#+begin_src nix +services.envfs.enable = true; +#+end_src + +I have no idea why, but sometimes, [[https://orca.gnome.org/][Orca]] get activated without my +consent. So I hard-disable it here. +#+name: orca +#+begin_src nix +services.orca.enable = false; +#+end_src + +I was surprised to see =/tmp= still hold the same files after my first +reboot in NixOS, I always assumed it was cleared on every reboot on +every system. But I can enable this behaviour back. +#+name: clean-tmp +#+begin_src nix +boot.tmp.cleanOnBoot = true; +#+end_src + +Lastly, I want to make sure my shell completions work, so I’ll enable +this. +#+name: completion +#+begin_src nix +environment.pathsToLink = [ + "/share/bash-completion" + "/share/zsh" +]; +#+end_src diff --git a/modules/nix-config.nix b/modules/nix-config.nix index a2b7040..2e20932 100644 --- a/modules/nix-config.nix +++ b/modules/nix-config.nix @@ -1,5 +1,5 @@ -{...}: let - cacheSettings = { +let + cacheSettings = rec { substituters = [ "https://phundrak.cachix.org?priority=10" "https://nix-community.cachix.org?priority=20" @@ -10,28 +10,22 @@ "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ]; + commonConf = { + extra-trusted-public-keys = trustedPublicKeys; + extra-substituters = substituters; + extra-experimental-features = ["nix-command" "flakes"]; + http-connections = 128; + }; }; in { - flake-file.nixConfig = { - extra-trusted-public-keys = cacheSettings.trustedPublicKeys; - extra-substituters = cacheSettings.substituters; - extra-experimental-features = ["nix-command" "flakes"]; - http-connections = 128; - }; - - flake.nixConfig = { - extra-trusted-public-keys = cacheSettings.trustedPublicKeys; - extra-substituters = cacheSettings.substituters; - extra-experimental-features = ["nix-command" "flakes"]; - http-connections = 128; - }; - + flake-file.nixConfig = cacheSettings; + flake.nixConfig = cacheSettings; flake.modules.nixos.nix-cache-settings = { nix.settings = { - substituters = cacheSettings.substituters; + inherit (cacheSettings) substituters; trusted-public-keys = cacheSettings.trustedPublicKeys; - http-connections = 128; experimental-features = ["nix-command" "flakes"]; + http-connections = 128; }; }; } diff --git a/modules/nix-config.org b/modules/nix-config.org new file mode 100644 index 0000000..17b6856 --- /dev/null +++ b/modules/nix-config.org @@ -0,0 +1,81 @@ +#+title: Nix Configuration +#+setupfile: headers +#+property: header-args:emacs-lisp :lexical t :exports none :tangle no + +* Nix Configuration +Something that I want to enable everywhere is, first and foremost, the +support for Nix commands and Nix flakes. I also want to make sure I +can use some caches, also known as substituters, including one of mine +from Cachix, to avoid compiling stuff as much as possible. + +So first, here are my caches with their public key. + +#+name: substituters +| Substituter's URL | Public Key | +|----------------------------------------------+-------------------------------------------------------------------------| +| https://phundrak.cachix.org?priority=10 | =phundrak.cachix.org-1:osJAkYO0ioTOPqaQCIXMfIRz1/+YYlVFkup3R2KSexk== | +| https://nix-community.cachix.org?priority=20 | =nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs== | +| https://cache.nixos.org?priority=40 | =cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY== | + +#+name: substituters-urls +#+begin_src emacs-lisp :var subs=substituters :cache yes +(mapconcat (lambda (sub) (format "\"%s\"" (car sub))) subs "\n") +#+end_src + +#+RESULTS[99d05698d7e8ca90b34823f4dd4858224be8d007]: substituters-urls +: "https://phundrak.cachix.org?priority=10" +: "https://nix-community.cachix.org?priority=20" +: "https://cache.nixos.org?priority=40" + +#+name: substituters-keys +#+begin_src emacs-lisp :var subs=substituters :cache yes +(require 's) +(mapconcat (lambda (sub) (format "\"%s\"" + (s-chop-prefix "=" (s-chop-suffix "=" (cadr sub))))) + subs + "\n") +#+end_src + +#+RESULTS[6f5e709a7b1c1dd55e4187dfaf8be945138c68ec]: substituters-keys +: "phundrak.cachix.org-1:osJAkYO0ioTOPqaQCIXMfIRz1/+YYlVFkup3R2KSexk=" +: "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" +: "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" + +This results in the following substituters and trusted public keys. +#+name: config-vars +#+begin_src nix :noweb yes +substituters = [ + <> +]; +trustedPublicKeys = [ + <> +]; +#+end_src + +Now, we can declare the rest of the file. You’ll see, it repeats +itself a bit. + +#+begin_src nix :tangle yes +let + cacheSettings = rec { + <> + commonConf = { + extra-trusted-public-keys = trustedPublicKeys; + extra-substituters = substituters; + extra-experimental-features = ["nix-command" "flakes"]; + http-connections = 128; + }; + }; +in { + flake-file.nixConfig = cacheSettings; + flake.nixConfig = cacheSettings; + flake.modules.nixos.nix-cache-settings = { + nix.settings = { + inherit (cacheSettings) substituters; + trusted-public-keys = cacheSettings.trustedPublicKeys; + experimental-features = ["nix-command" "flakes"]; + http-connections = 128; + }; + }; +} +#+end_src