:PROPERTIES: :ID: 26ecd52b-1c5c-46b8-8eb9-fe827a753f0a :ROAM_ALIASES: sydnix :END: #+title: Guix-rebound 2 #+author: Madeleine Sydney Ślaga #+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~. doge ** 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 sub-directory =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 test-bed, 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 *** TODO [#A] [[id:6141dc5c-2232-4bc0-9464-410c21135c86][Strategies]] *** TODO Completions w/ [[https://github.com/minad/corfu][Corfu]] *** TODO Overlay org-mode links with the domain name For some websites, abbreviations are welcome. e.g. a link to Wikipedia could appear as Article^W (where the «^W» is a superscript W) *** DONE [[https://github.com/awth13/org-appear][Hide Org-mode markup only when not editing]] *** TODO [[https://github.com/io12/org-fragtog][Preview LaTeX fragments in Org-mode when not editing]] *** TODO Show jj commit name in modeline *** TODO Block escaping with ~jk~ whilst recording a macro *** TODO Many editing commands should re-indent after use Particularly in Lisps where indentation is reliable. - ~evil-join~ *** TODO ~(lambda (x) ...)~ → ~(λ (x) ...)~ *** TODO Ligatures *** TODO ~SPC i u~ *** DONE ~syd-open-sexp-above~ should understand comments If a comment immediately proceeds a sexp, open the new sexp /before/ the comment. Transpose/drag commands should probably have the same behaviour. *** DONE ESC should ~:nohl~ *** TODO Implement ~evil-cleverparens~'s ~evil-cp--guard-point~ - Emacs and Vim have differing views on where the point is w.r.t. the on-screen cursor. The ~evil-cp--guard-point~ macro is used to adapt Emacsy expectations to Vimmy ones. *** TODO Fix ~syd-get-enclosing-sexp~ - Undesireable behaviour when point is in a comment. *** TODO Scratch buffer: ~SPC x~ to open as popup, ~SPC u SPC x~ to not *** IDEA A new popup system that uses popup /windows/ rather than popup /buffers/ - Would allow you to open arbitrary buffers in a popup view. *** DONE Evil operators like ~=~ should not move point *** TODO ESC should immediately close minibuffer, even whilst in insert state *** 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 **** KILL [[https://github.com/promethial/paxedit][Paxedit]] Seems old and broken? **** DONE Text objects **** DONE [[https://github.com/Malabarba/speed-of-thought-lisp][speed-of-thought]] **** DONE rainbow-delimiters **** TODO [[https://github.com/Wilfred/emacs-refactor][emacs-refactor]] **** 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 **** HOLD Grammar-checking **** DONE 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 **** DONE Prompt **** DONE Greeting **** DONE Aliases **** DONE Evil **** DONE Project integration **** TODO Syntax highlighting **** DONE ~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? *** [#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 **** DONE spellcheck and dictionaries **** org-mode ***** DONE init.org for beorg ***** KILL IPA links ***** capture templates ****** journal entry ****** todo ***** DONE 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] *** TODO 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. }:) *** KILL 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 *** TODO fix =[e= / =]e= *** 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 Syncthing module shouldn't expose ~devices~ Define ~services.syncthing.settings.devices~ as constant. Folders can still list devices by name, but not ID. ** 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]] *** DONE 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 ** TODO Declaratively install Jellyfin plugins ** 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? ** DONE mpd CLOSED: [2025-02-09 Sun 14:59] *** DONE mpdscribble CLOSED: [2025-02-09 Sun 14:59] ** DONE syncthing CLOSED: [2025-02-09 Sun 14:59] ** DONE impermanence CLOSED: [2025-02-09 Sun 14:59] ** 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 ~scratch-dir [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 a 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" }:). The 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 expended here, as well as being a wonderful reference as I re-learnt Nix from the ground up. In the most nerdy moment of my life, I've genuinely /swooned/ over this damn config. - 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] - [cite:@bosio2023beautifying] - [cite:@zamboni2018beautifying] - [[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. - [[https://github.com/noctuid/evil-guide][noctuid/evil-guide]] - [[https://github.com/drym-org/symex.el][symex.el]] - [[https://github.com/Fuco1/smartparens][Smartparens]] # Local Variables: # jinx-local-words: "Wishsys" # End: