The Complete Computing Environment

Generate a Dynamic Home Manager Configuration

LifeTechEmacsTopicsArcology

Home Manager is a basic system for managing a user environment using the Nix package manager together with the Nix libraries found in nixpkgs.

readmeWikiManual

Home Manager works anywhere that Nix does and populates a ~/.nix-profile which is added to various environment PATHs to expose a bunch of Nix packaged programs to the rest of my system. I plan to slowly fork all of my Ansible automation in to this system and when the bulk of it is moved I can evaluate building fully idempotent systems with NixOS and NixOps. oh what fun! See below a cool method to generate some foot-gun shaped code!

Emacs scaffolding via CCE

This document relies on some [[id:e050ed03-044f-4a48-912d-72579bef9a26][org-roam keyword caching]] this is handled by Arroyo Emacs now.

(with-eval-after-load 'org-roam-keywords
  (dolist (kw '("CCE_HOME_MODULE" "CCE_HOME_PACKAGES" "CCE_HOME_DERIVATIONS" "CCE_HOME_EPKGS"))
    (add-to-list 'org-roam-cached-keywords kw nil #'equal)))
(provide 'cce/home-manager)

CCE Modules Which This Loads

Here are files which will be included by home-manager:

(->>
 (org-roam-db-query [:select [file title]
                     :from keywords
                     :join titles :using [[file]]
                     :where (= keyword "CCE_HOME_MODULE")
                     :group-by file])
 (seq-map (lambda (item) (format "- [[file:%s][%s]]\n" (file-relative-name (first item) cce-directory) (second item))))
 (apply #'concat))

Quickly Install it

With a working Nix installation run this to install home-manager:

nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
nix-channel --update
nix-shell '<home-manager>' -A install

Additionally, Cachix can be used to skip compiling the Emacs GCC branch on NixOS systems. Here it's not so helpful

nix-env -iA cachix -f https://cachix.org/api/v1/install
cachix use nix-community

Generating home-manager.nix dynamically with noweb Literate Programming

This uses my org-roam keyword caching patch and the Shared CCE Helpers to dynamically generate a home.nix. some neat and tidy ELisp is nice to see. Every page with home manager code in it will carry a CCE_HOME_MODULE keyword with the location of the .nix file for that CCE module which will be inserted in to the home.nix template.

It's complicated because I need to define home.packages only in one place and I can't figure out a better way to compose this file. This relies on some implied code standards to work: home.packages will be populated with things hidden under lib.mypkgs.FOO, a list of packages concatenated with all the other lib.mypkgs but reliant on very particular shape and naming. Inherent limitation to the craft, I guess.

I also should define program modules for a lot of these over the long term so that they're more simple to harness and my configurations can become more stable. This references a lot of code in the Shared CCE Helpers, consider reading that if you're interested in understanding this.

for now, this is going to be kind of awkward. I have a Fedora Linux that is reliant on this home.nix, but i want nodes managed with NixOps to have access to this during a bootstrap.

{ config, pkgs, lib, ... }:

{
  imports = [
    <<generate_imports()>>
  ];  

  programs.home-manager.enable = true;
  home.stateVersion = "21.05";

  home.file.".config/nixpkgs/home.nix".source = ./home-manager.nix; # this file

  manual.html.enable = true;
  manual.json.enable = true;
  news.display = "silent";

  home.username = "rrix";
  home.homeDirectory = "/home/rrix";

  home.language.base = "en_US";
  home.language.time = "en_GB";

  # for KDE
  # https://userbase.kde.org/Session_Environment_Variables
  home.file.".config/plasma-workspace/env/profile.sh".text = ''
    source $HOME/.profile
  '';
}

Regenerating on command: M-x cce/dynamic-home-manager

To apply this quickly, I have a small helper function which will make it all the way in to my CCE init file. With elisp:(cce/dynamic-home-manager), available in M-x slash execute-extended-command, which will tangle and apply the home.nix file.

(cce/tangle-home-manager-inputs)
(setq cce/home-manager-org-name "~/org/cce/home-manager.org")
(setq cce/home-manager-nix-name "~/org/cce/nixlib/home-manager.nix")
(defun cce/dynamic-home-manager (&optional prefix)
  (interactive "p")
  (when (eq major-mode 'org-mode)
    (org-babel-tangle-file (buffer-file-name)))
  (when (org-babel-tangle-file cce/home-manager-org-name)
    (async-shell-command (concat "home-manager switch -f "
                                 cce/home-manager-nix-name
                                 (unless (eq 1 prefix) " --show-trace"))
                         "*home-manager*")))
(defun cce/tangle-home-manager-inputs ()
  (dolist (path (org-roam-db-query
                 [:select file
                  :from keywords
                  :where (= keyword "CCE_HOME_MODULE")
                  :or (= keyword "CCE_HOME_EPKGS")
                  :or (= keyword "CCE_HOME_DERIVATIONS")
                  :group-by file]))
    (org-babel-tangle-file (car path)))
  (org-babel-tangle-file cce/home-manager-org-name))

Literate Programming helpers

This uses Arroyo Home Manager.

(arroyo-home-manager-imports)
hm/prompt.nix
hm/qud.nix
hm/smac.nix
hm/msmtp.nix
hm/emacs-helpers.nix
hm/direnv.nix
hm/applications.nix
hm/tabfs.nix
hm/firefox.nix
hm/contacts.nix
hm/ruby.nix
hm/defexpr.nix
hm/xmonad.nix
hm/git.nix
hm/python.nix
hm/gnupg.nix
hm/syncthing.nix
hm/pass.nix
hm/org-protocol.nix
hm/ssh_client.nix
hm/kde-config-basics.nix
hm/vsketch.nix
hm/mbsync-endpoint.nix
hm/fehbg.nix
hm/org-roam.nix
hm/beets.nix
hm/dovecot-shell-access.nix
hm/mpd.nix
hm/emacs-pager.nix
hm/shell-helpers.nix
hm/kde-config-appearance.nix
hm/i3wm.nix
hm/spell-check.nix
hm/deadgrep.nix
hm/3d-printing.nix
hm/pantalaimon.nix
hm/profile.nix
hm/supercollider.nix
hm/axidraw.nix
hm/datasette.nix
hm/morph.nix
hm/emacs.nix
hm/occluded_files.nix
hm/nix-update.nix
hm/cogmind.nix
hm/picom.nix
hm/atuin.nix

Task list to port CCE_ANSIBLE to CCE_HOME_MODULE

Now This Is Podracing!

(apply #'concat
       (seq-map (lambda (row)
                  (message "%s" row)
                  (format "** NEXT port [[%s][%s]] to home-manager  :CCE:Dev:Nix:\n" (first row) (second row)))
                (org-roam-db-query [:select [file value]
                                    :from keywords
                                    :where (= keyword $s1)]
                                   "CCE_ANSIBLE")))

DONE port pass to home-manager CCE Dev Nix

DONE port applications to home-manager CCE Dev Nix

DONE port gnupg to home-manager CCE Dev Nix

DONE port deadgrep to home-manager CCE Dev Nix

DONE port picom to home-manager CCE Dev Nix

DONE port git to home-manager CCE Dev Nix

DONE port axidraw to home-manager CCE Dev Nix

DONE port code-base to home-manager CCE Dev Nix

DONE port org-roam to home-manager CCE Dev Nix

DONE port syncthing to home-manager CCE Dev Nix

DONE port msmtp to home-manager CCE Dev Nix

CANCELLED port emacs-sqlite3 to home-manager CCE Dev Nix

CANCELLED port ansible-bender to home-manager CCE Dev Nix

DONE port shell-loader to home-manager CCE Dev Nix

CANCELLED port yubikeys to home-manager CCE Dev Nix

NEXT port ruby to home-manager CCE Dev Nix

DONE port firefox-cust to home-manager CCE Dev Nix

DONE port org-protocol to home-manager CCE Dev Nix

DONE port vulfpeck to home-manager CCE Dev Nix

DONE port gnus to home-manager CCE Dev Nix

NEXT port hpi-kobo to home-manager CCE Dev Nix

DONE port code-modes to home-manager CCE Dev Nix

CANCELLED port weechat to home-manager CCE Dev Nix

NEXT port pam-u2f to home-manager CCE Dev Nix

NEXT port common-lisp to home-manager CCE Dev Nix

DONE port redshift to home-manager CCE Dev Nix

DONE port packaging to home-manager CCE Dev Nix

NEXT port obs-v4l2sink to home-manager CCE Dev Nix

NEXT port yubikey-otp to home-manager CCE Dev Nix

DONE port python to home-manager CCE Dev Nix

DONE port emacs-pager to home-manager CCE Dev Nix

DONE port universal-aggregator to home-manager CCE Dev Nix

DONE port elixir to home-manager CCE Dev Nix

CANCELLED port podman to home-manager CCE Dev Nix

DONE port atreus to home-manager CCE Dev Nix

CANCELLED port rpmfusion to home-manager CCE Dev Nix

DONE port kde-desktop to home-manager CCE Dev Nix

DONE port firefox-portal to home-manager CCE Dev Nix

NEXT port sitelen-pona-pona to home-manager CCE Dev Nix

DONE port mbsync to home-manager CCE Dev Nix

DONE port firefox to home-manager CCE Dev Nix

NEXT port hpi to home-manager CCE Dev Nix

CANCELLED port nixos to home-manager CCE Dev Nix

Support home-manaer in My NixOS configuration

This file is added to imports to get a home manager install in My NixOS configuration.

{ pkgs, ...}:

let
  opts = (import ../versions.nix {}).homeManager;
  hm = opts false;
in
{
  # this makes home-manager.users.rrix work
  imports = [ "${hm}/nixos" ];

  home-manager.useGlobalPkgs = true;

  # this makes pkgs.home-manager track my pins, i.e "home-manager build" uses the same version as nixos's home-manager-rrix service
  nixpkgs.overlays = [
    (import "${hm}/overlay.nix")
  ];
}