:PROPERTIES: :ID: 26ecd52b-1c5c-46b8-8eb9-fe827a753f0a :ROAM_ALIASES: sydnix :END: #+title: Guix-rebound 2 #+tags: nix Current name of ~guix-rebound~ ought to be changed. This is a rewrite from scratch. }:3 A second try at NixOS, now that I have a better idea of what I'm doing. The effort is largely inspired by my darling Faye's glorious ~wishsys~. * Inbox * Conventions ** User configuration In order of descending preference, user programs should be configured by... 1. home-manager's modules. 2. Wrappers, with config files optionally living somewhere under =/persist/dots=. 3. ~home.file~ and similar. 4. Mutable symlinks using ~home.file~ and ~mkOutOfStoreSymlink~. ** Repo structure *** =hosts/= Each directory =hosts/«HOST»= is expected to configure a single specific device, where =«HOST»= is the device's exact hostname. Said directory =«HOST»= should have at least the following structure: #+begin_example hosts └── «HOST» ├── configuration.nix └── system.nix #+end_example Where =configuration.nix= is the main entry point imported by the top-level flake, and =system.nix= evaluates to a string corresponding to the =system= option to be used. *** =users/= Similarly to the =hosts= directory, each subdirectory =users/«USER»= is assumed to have some structure, and that =«USER»= is the precise username desired. #+begin_example users └── «USER» └── default.nix #+end_example Where =default.nix= returns an attrset of form #+begin_src nix { # The NixOS option `users.users.«USER»` will be set to result of # `systemConfiguration`. systemConfiguration = { config, pkgs, lib, ... }: { # isNormalUser = true; # extraGroups = [ "wheel" ]; # ... }; # Home-manager configuration homeConfiguration = { config, pkgs, lib, ... }: { # home.packages = [ pkgs.hello ]; # ... }; } #+end_src *** ~modules/~ #+begin_example modules ├── home │   └── «Various home-manager modules»… └── nixos ├── defaults │   └── «NixOS modules that are *enabled by default*»… ├── deertopia │   └── «NixOS modules that are *specific to Deertopia*»… └── «Various NixOS modules»… #+end_example ** Impermanence and persistence I use impermanence to wipe most of my filesystem on boot. *** Boot process What follows is an overview of [[file:modules/nixos/impermanence/rollback.nix][modules/nixos/impermanence/rollback.nix]]. On boot, ... - The existing subvolume root filesystem will be moved to a 'death row' directory, where it will live for about three days before deletion. Precisely, =«btrfs-filesystem»/«root-subvolume»= is moved to =«btrfs-filesystem»/old-roots/«timestamp»=. The brief grace period allows for easy recovery in the (very common) case where files are unintentionally deleted due to the user's silly human negligence. - A new, blank subvolume is created in place of the previous. Precisely, the subvolume =«btrfs-filesystem»/«root-subvolume»= is created. - Any subvolumes under =«btrfs-filesystem»/old-roots= older than three days are deleted. *** The =/persist= directory - =/persist/root= :: Persistent files to be linked into the real root, =/=. These are managed by Impermanence. - =/persist/home/«user»= :: Persistent files to be linked into the analogous location under the real home, =/home/«user»=. These are managed by Impermanence. - =/persist/vault/«user»= :: Persistent files belonging to specific users. This differs from the persistent home directories in that files are not necessarily linked anywhere. ** Deferring Emacs packages Nearly all configuration of Emacs packages happens under the ~use-package~ macro. ~use-package~ has various keywords with special syntax for common tasks, such as instrumenting hooks, setting keybindings, and customising variables. You may be surprised to learn that these are not /just/ syntactic sugar }:) (I was). As an example, this #+begin_src emacs-lisp (use-package which-key :hook (on-first-input . which-key-mode) :custom (which-key-allow-evil-operators t) (which-key-show-operator-state-maps t) #+end_src is not the same as this #+begin_src emacs-lisp (use-package which-key :config (add-hook 'on-first-input #'which-key-mode) (setq which-key-allow-evil-operators t) (setq which-key-show-operator-state-maps t) #+end_src The difference connects to another silly obsession of the Emacs hacker: startup time. ~use-package~'s special keywords will /defer/ the loading of the package ([cite:@systemcrafters2021how]) . E.g., instead of loading ~which-key~ on startup, it will be loaded when the ~on-first-input~ hook is first called. ~on-first-input~ is one of many useful hooks provided by the package [[https://github.com/emacsmirror/on][on.el]] specialised for fine-grained control of package loading. ** Naming conventions in my Emacs config As with the rest of the config, these are largely adapted from Doom's ([cite:@lissner2022contributing]). }:3 - ~syd-[-]«NAME»~ :: Typical 'namespaced' Elisp convention ([cite:@gnu2020conventions]). - ~syd/«NAME»~ :: Commands intended for interactive use. - ~+syd-[-]«NAME»~ (f) :: Indicates a [[https://en.wikipedia.org/wiki/Strategy_pattern][strategy]] function. - ~+syd-[-]«NAME»~ (v) :: Indicates a variable holding various stategies available to a specific strategy function. - ~syd-«NAME»-initialise~, where ~modules/«NAME» ∈ modules/*.el~ :: Instead of using top-level side-effects, (bar e.g. ~use-package~ invocations) should be wrapped in this kind of initialisation procedure. - ~«NAME»-h~ :: Procedure defined specifically to be added to a hook. * Hosts ** nixos-testbed Configuration for the VM I'm currently using as a testbed, before moving to my real desktop. ** deertopia My home server. * Users ** crumb Me }:). My primary user for programming and playing TF2. ** lain A bit on the nose for a transfemme into computers, but my chosen name is also Madeleine. Used as a server admin account with little configuration. * ~sydnix-cli~ sydnix-cli is a command-line utility written in Clojure wrapping various sydnix-related scripts. * Tasks ** Emacs from scratch *** DONE Daemon CLOSED: [2025-01-03 Fri 20:00] *** DONE Encryption *** DONE Mutable config CLOSED: [2025-01-03 Fri 20:01] Path is currently hardcoded to =/persist/dots/users/crumb/programs/emacs=. An immutable file (created by home-manager's =programs.emacs.extraConfig=) loads =init.el= from the hardcoded path. *** KILL Packages via Nixpkgs CLOSED: [2025-01-03 Fri 20:40] *** TODO Org-mode **** TODO Roam ***** TODO Dailies ***** TODO Tags: project, readinglist Disassemble project-ideas.org and reading-list.org into a individual roam nodes. **** TODO Capture templates ***** IDEA Export to GitLab issue? ***** TODO Config TODO list / pain-point list *** DONE Default fonts CLOSED: [2025-02-02 Sun 14:06] - fixed-pitch: Victor Mono NF - variable-pitch: Overpass - backup: Julia Mono *** TODO Lisp editing **** TODO [[https://github.com/promethial/paxedit][Paxedit]] Seems old and broken? **** TODO Evil stuff **** TODO Text objects **** TODO [[https://github.com/Malabarba/speed-of-thought-lisp][speed-of-thought]] **** TODO [[https://github.com/Lindydancer/lisp-extra-font-lock][lisp-extra-font-lock]] **** TODO rainbow-delimiters **** TODO [[https://github.com/Wilfred/emacs-refactor][emacs-refactor]] **** TODO [[https://github.com/Malabarba/aggressive-indent-mode][aggressive-indent-mode]] **** TODO [[https://github.com/riscy/elfmt][elfmt]] **** TODO [[https://github.com/magnars/string-edit.el][string-edit]] **** TODO [[https://github.com/Fuco1/elisp-docstring-mod][elisp-docstring]] *** TODO [[https://github.com/purcell/page-break-lines][page-break-lines]] *** DONE project.el CLOSED: [2025-01-16 Thu 18:19] *** TODO Workspaces *** TODO Prose minor mode **** TODO Grammar-checking **** TODO Spell-checking *** DONE Lookup handlers CLOSED: [2025-02-01 Sat 16:56] *** DONE Repl-handling CLOSED: [2025-01-31 Fri] *** DONE Popup-handling CLOSED: [2025-02-02 Sun 14:05] *** TODO Comint *** TODO Eshell **** TODO Prompt **** TODO Greeting **** TODO Aliases **** TODO Evil **** TODO Project integration **** TODO Syntax highlighting **** TODO ~C-d~ *** TODO Snippets *** TODO File templates *** TODO Project templates *** TODO Magit **** TODO Forges *** TODO Prettier Vertico Doom has some nice output when viewing files in Vertico. I'm not sure how this is achieved. *** TODO Dired/Dirvish *** TODO [[kbd:][SPC i]] *** TODO [[kbd:][SPC o]] *** TODO [[kbd:][SPC t]] *** TODO Vertico repeat *** TODO so-long-mode *** TODO Consult icons **** TODO compile-multi-all-the-icons *** Language support **** TODO Clojure **** TODO Haskell **** TODO Nix **** TODO Elisp *** TODO Tune GC w/ ~gcmh~ *** IDEA Email? *** IDEA =map!= macro *** IDEA Module system? ** Emacs config *** [#A] One-off environment changes without direnv I would like the ability to ergonomically e.g. add HLS to my current environment without setting up an entire project. Perhaps something like "create new workspace under a nix-shell invocation" could work? *** minibuffer **** DONE jk to escape CLOSED: [2024-11-20 Wed 12:11] **** DONE history navigation in insert mode w/ [[kbd:][C-j]] / [[kbd:][C-k]] CLOSED: [2024-11-20 Wed 12:11] **** [[kbd:][RET]] to send whilst in normal mode *** dired **** DONE use [[kbd:][/]] to live narrow CLOSED: [2024-11-14 Thu 04:46] *** set up JuliaMono for use with ipa: links *** text-mode **** grammar **** spellcheck and dictionaries **** org-mode ***** init.org for beorg ***** IPA links ***** capture templates ****** journal entry ****** todo ***** fancy headline stars ***** DONE better colour for inline code CLOSED: [2024-11-21 Thu 09:04] **** DONE variable pitch CLOSED: [2024-11-30 Sat 19:06] *** form and element text objects à la vim-sexp *** customise the eshell prompt *** jump to prev/next hole in haskell *** make a bind for inserting hrules *** KILL set up emms CLOSED: [2024-12-11 Wed 13:46] - BLOCKER: [[*download my music library][download my music library]] it kinda sucks. }:\ *** set up JuliaMono for use with IPA glyphs *** KILL literate config CLOSED: [2024-12-27 Fri 19:35] Just kind of a pain in the ass. }:) *** evil-cp fixes **** [[kbd:][(]] / [[kbd:][)]] When [[kbd:][)]] is hit whilst the cursor is at ~↓1~, it should move to the matching bracket, ~↓2~, *not* the right bracket of the ~save-excursion~ call. #+begin_src elisp (save-excursion ;; ↓1 ↓2 (re-search-forward)) #+end_src **** element text objects *** automatically close compilation buffer *** fix =[e= / =]e= *** unmap =TAB= in normal mode *** eshell trail à la M-x calc #+begin_quote I really like how you re-examined shells and terminals. I hadn't thought of how they're kinda unrelated. What I then don't understand is why eshell stuck to the paradigm of interleaving input and output. It's a relic left over from terminals. ie: >>> input [tonnes of output] >>> input [tonnes of output] to me it seems the input should be entered in the minibuffer (or some separate frame/window) and the outputs should be in a separate window/frame with separate read-only buffers. #+end_quote [[https://www.reddit.com/r/emacs/comments/6y3q4k/comment/dml16vq/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button][source]] ** TODO Securely store credentials for glab/gh CLIs ** TODO Dotfiles - [[https://rgoulter.com/blog/posts/programming/2022-02-20-using-home-manager-to-manage-symlinks-to-dotfiles.html][link]] - [[https://www.bekk.christmas/post/2021/16/dotfiles-with-nix-and-home-manager][link]] *** TODO Emacs *** TODO Bash **** TODO =shopt -s histverify= Don’t execute expanded result immediately. *** DONE (neo)vim CLOSED: [2024-12-29 Sun 17:53] *** TODO readline ** DONE disko CLOSED: [2024-12-28 Sat 18:13] ** IDEA refactor disko configs to be more reusable ** IDEA replace uses of gpg with age I don't know anything about either. ** TODO password store 4 firefox ** DONE password store w/ age CLOSED: [2024-12-29 Sun 02:34] https://github.com/FiloSottile/passage ** TODO Automatically sync password store ** DONE secrets CLOSED: [2024-12-29 Sun 01:41] ** DONE git config CLOSED: [2024-12-30 Mon 17:01] ** TODO niri Or Qtile ** TODO qtile Or Niri ** TODO Convenient way to wrap programs [[https://github.com/viperML/wrapper-manager][wrapper-manager]] looks like it will be really annoying to integrate into my config without a NixOS/HM module. ** TODO tf2.nix - declaratively configure tf2 - tf2Packages? - mastercomfig integration? - define aliases / bindings from nix? ** TODO mpd *** TODO mpdscribble ** TODO syncthing ** HOLD impermanence ** DONE ~sydnix.defaults~ module CLOSED: [2024-12-31 Tue 01:05] ** DONE Split up ~flake.nix~ into a file per output CLOSED: [2024-12-31 Tue 01:04] ** TODO default package sets Some examples of what I mean: - ~defaultPackages.essential = true~ to install ~neovim~ and ~git~; - ~defaultPackages.development = true~ for ~jj~ and Emacs. - ~defaultPackages.desktop = true~ for ~cantata~, ~obs~, ~vlc~, ~vesktop~, ~soulseek~; Naturally, one would expect some way to say "all these, except this and that." ** TODO Set envvars *** =$EDITOR= See [[id:5b4ee1e4-fad7-4783-8e98-301b41579a63][~choose-editor~]]. ** System maintenance scripts It might be a good idea to namespace these as subcommands of a single binary. *** TODO ~nix-clean~ Collect garbage, clean up boot entries, delete old generations... https://discourse.nixos.org/t/what-to-do-with-a-full-boot-partition/2049 *** TODO ~choose-editor~ :PROPERTIES: :ID: 5b4ee1e4-fad7-4783-8e98-301b41579a63 :END: - If the Emacs daemon is running... - ...then run ~emacsclient~. - ...otherwise, prompt the user to choose between Emacs and Vim - If Emacs: run ~emacs~. - If Vim: In order, try ~nvim~, ~vim~, then ~vi~. - If neither are available, use ~nix run nixpkgs#nvim~ - If this fails, try ~nano~. - Support ~--pager~ *** TODO =rage-edit= *** TODO ~forget-host HOST~ Remove a given host from =~/.ssh/known_hosts=. Something like =sed -i -e '/192.168.122.54/d' .ssh/known_hosts=. Confirm by printing diff. *** TODO =lets-temp [NAME]= Create a new tempdir called ~[NAME]~, and cd into it. *** TODO =doctor= / =status= Run various checks on the system. - Sizes of caches. perhaps those listed by ~sydnix.impermanence.cache.{files,directories}~? Offer to clean them if they're getting old or large. - Check for available upgrades. Flake inputs, overlays, emacs packages, etc. *** TODO ~persist status~ List persistent files per user, and show their mount strategy. * References Following is a subset of the many places I've learnt from. Most important of all are Doom Emacs and Faye's Wishsys. Doom Emacs was my gateway drug to Emacs, as well as continually supportive parent as I've begun to move out — of course, that's a flowerism obfuscating the more direct statement "I've stolen a great deal of their code" }:). Beloved Faye's Wishsys is an incredibly impressive 3-kloc NixOS config with several hosts, users, and a beautiful level of modularity. Her system has a number of quirks that initially raise eyebrows, but the questioning turns to awe once you understand she really knows what she's doing }:). Faye and her config are entirely responsible for inspiring and motivating my effort expent here, as well as being a wonderful reference as I re-learnt Nix from the ground up. - My darling dearest Faye's =wishsys= }:D - [[https://github.com/rasendubi/dotfiles][rasendubi/dotfiles]] - [[https://git.mangoiv.com/mangoiv/dotfiles][mangoiv/dotfiles]] - [[https://github.com/hlissner/dotfiles/][hlissner/dotfiles]] - [[https://github.com/Shawn8901/nix-configuration/tree/af71d51998a6772a300f842795b947e27202fa73][Shawn8901/nix-configuration]] - [cite:@christensen2020erase] - [cite:@ayats2024dropping] - [cite:@zaynetdinov2024you] - [cite:@schafer2017advanced] - [[https://prelude.emacsredux.com/en/stable/][Emacs Prelude]] - [[https://github.com/doomemacs/doomemacs][Doom Emacs]] - [[https://cce.whatthefuck.computer/cce][Ryan Rix's Complete Computing Environment]] - [cite:@wünsch2024setting] - [[https://github.com/neeasade/emacs.d][neeasade/emacs.d]] — Has an interesting 'module' system. - [[https://github.com/oantolin/emacs-config][oantolin/emacs-config]] — Has some internal packages.