dotfiles icon indicating copy to clipboard operation
dotfiles copied to clipboard

NixOS + home-manager, Emacs (vanilla + doom), herbstluftwm, i3

#+TITLE: My User Environment #+AUTHOR: Johannes Maier #+EMAIL: [email protected] #+STARTUP: showeverything

  • Overview

This repository represents the state of the environment(s) I'm currently using for development, learning and, to some degree, entertainment. Currently there are only NixOS machines (plus one WSL2 environment that I need to include at some point) I manage this way:

  • [[file:nixos/atuan/][atuan]]: my home PC

  • [[file:nixos/tehanu/][tehanu]]: my new work laptop

  • [[file:nixos/angband/][angband]]: a tiny notebook (64 GB of disk space only) I use when traveling

  • [[file:nixos/paln/][paln]]: a tiny [[https://www.hetzner.com/cloud][Hetzner Cloud]] VM I use for synchronization and small backups

    The actual (development) environments are managed with [[https://github.com/nix-community/home-manager][home-manager]]. =home-manager= makes it possible and easy to bundle binaries / packages with their respective configuration (usually files inside the home directory or =$XDG_CONFIG_HOME=).

    In the past I was using macOS as well as Ubuntu, but have since fully transitioned. Note that using a nearly identical setup powered by the Nix package manager and =home-manager= is not that different. Only a handful of things are actually managed by the underlying system anymore. (If you're interested, you should look up how to create a =homeConfigurations.= output in your =flake.nix=, replacing the =nixosConfigurations.= one.)

** Repository and flake structure *** NixOS systems

The [[file:nixos/][nixos]] directory contains the machine/host-specific pieces of configuration. Every subdirectory will lead to a flake output under =nixosConfigurations=, with the attribute name being the name of the directory.

The directories itself follow a fixed convention:

  • =configuration.nix= and =hardware-configuration.nix= (automatically created when installing NixOS on the machine for the first time) together constitute the NixOS configuration
  • =home.nix= is the home manager configuration
  • =custom.nix= contains everything that should be passed to all the NixOS and home manager modules as arguments; usually this (only) means things that should be known everywhere, like my username

The [[file:modules/][modules]] directory contains the home manager NixOS modules that all my configurations share (but might choose to disable or enable on a per-machine basis).

*** Home-manager on non-NixOS

The [[file:users][users]] directory contains =home-manager=-only configurations for my non-NixOS machines. At the moment my work laptop runs both NixOS and Void Linux, and on the latter I use =home-manager= first-class.

Install a new generation with

#+begin_src shell home-manager switch --flake ~/dotfiles --impure #+end_src

(The =--impure= argument is due to the fact that on non-NixOS systems, applications using OpenGL (or similar) often fail on startup; [[https://github.com/nix-community/nixGL][nixGL]] helps with this problem, but installing it requires this parameter).

** Building/switching to a new generation

I usually use an [[file:modules/shell-aliases.nix][alias]] in my shell to switch to the next generation after changing things in my configuration. The actual command is the following:

#+begin_src shell nixos-rebuild switch --use-remote-sudo --flake ~/dotfiles #+end_src

The =--flake ~/dotfiles= part works because of two reasons:

  • I always clone this repository into my =$HOME=.
  • The command performs a lookup on the hostname of the machine; if the =flake.nix= contains an output =nixosConfigurations.=, this is the configuration that will be used.

It's also possible to only switch into the next =home-manager= generation for the current user without adding a new system generation using the following command (which is yet another shell alias):

#+begin_src shell nix shell "~/dotfiles/#nixosConfigurations.$(hostname).config.home-manager.users.$USER.home.activationPackage"
--command home-manager-generation #+end_src

Note, however, that without creating a new system generation these changes will not be "activated" upon next boot.

  • Emacs configuration

A special case of a program with a relatively huge accompanying configuration is GNU Emacs. My literate Emacs configuration (very much a work-in-progress, as I've only recently started going back to using [[https://orgmode.org/][Org Mode]] to configure Emacs itself) can be found [[file:modules/emacs/emacs.d/config.org][here]].

Note that there is a corresponding [[file:modules/emacs/default.nix][default.nix]] which specifies the version of Emacs I use (usually a quite recent one, made possible by [[https://github.com/nix-community/emacs-overlay][emacs-overlay]]), as well as some pre-built packages, all "obeying" my current pin of =nixpkgs= (see [[file:flake.lock][flake.lock]]). I used to use Nix to manage all of my Emacs packages, but have since switched to [[https://github.com/radian-software/straight.el][straight.el]], as it allows me to more quickly change my config, try out new packages on the fly without cluttering anything, and even debug packages.