home-manager-helper
Table of Contents
home-manager is an excelent Nix based dotfile management system. Not only can it manage symlinks in your home-directory, as a package manager, it can also install the related software. Win!
This project provides a wrapper around home-manager that makes it a little easier to use.
My personal configuration used with home-manager-helper can be found here.
Quickstart
Install Nix
Install the Nix package manager to your workstation:
curl https://nixos.org/nix/install | sh
This will create /nix
as well as some system-wide profile scripts which will
integrate your shell with Nix.
Install home-manager-helper
Use nix-env
to install the package straight from GitHub into your Nix profile:
#> nix-env -i -f https://github.com/dustinlacewell/home-manager-helper/archive/master.tar.gz downloading ‘https://github.com/dustinlacewell/dotfiles/archive/master.tar.gz’... unpacking ‘https://github.com/dustinlacewell/dotfiles/archive/master.tar.gz’... installing ‘home-manager-helper’ building path(s) ‘/nix/store/h1bb5hybayvkzbhg49kadd2s9irxrbxh-user-environment’ created 1 symlinks in user environment
First-run Bootstrap
The hm
command is now available. On the first run, it will install
home-manager
:
#> hm /Users/dustinlacewell/.nix-profile/bin/hm:hash:67: no such command: home-manager Home-manager was not found. It will now be installed. Press any key to continue... downloading ‘https://github.com/rycee/home-manager/archive/master.tar.gz’... [0/0 KiB, 0.0 KiB/s] unpacking ‘https://github.com/rycee/home-manager/archive/master.tar.gz’... installing ‘home-manager’ these derivations will be built: /nix/store/c8an7rvww7ykqh7nnc8cdzgnlgwgflkz-home-manager.drv building path(s) ‘/nix/store/h4gjwiwqqm4db7qf0rpqr6711bjcdkli-home-manager’ installing install: creating directory '/nix/store/h4gjwiwqqm4db7qf0rpqr6711bjcdkli-home-manager' install: creating directory '/nix/store/h4gjwiwqqm4db7qf0rpqr6711bjcdkli-home-manager/bin' '/nix/store/agb74b8gmwcfwlq1nk708vi6jrkvviwc-home-manager' -> '/nix/store/h4gjwiwqqm4db7qf0rpqr6711bjcdkli-home-manager/bin/home-manager' building path(s) ‘/nix/store/wrfwl5rh0n3934wyj8pq7s79xc74a5df-user-environment’ created 3 symlinks in user environment Bootstrap successful!
Woo.
Using hm
hm
is super simple. It has two commands build
and switch
. Both take a
single argument, the name of an envfile.
usage: hm <command> <env> Commands: build - build env to ./result/ switch - build env to ~/ Environments: Loads ~/.home-manager/envs/<env>.nix
Hello World!
During the bootstrap, some example files were installed to your home directory:
#> tree ~/.home-manager ├── envs │ ├── example.nix ├── hello │ ├── default.nix │ └── hello.conf
Go ahead and build a dry-run:
#> hm build example /nix/store/fv3j0cn5np78wdl4bybfnb52mvqrrwjk-home-manager-generation
#> tree result/ result/ ├── activate ├── home-files -> /nix/store/cv68n6291xzdwqz3f7whlp3qg5vzm60g-home-manager-files └── home-path -> /nix/store/sq9x4x0k5va4fwr7q91wk7w74fp8jv1k-home-manager-path
ls -la result/home-files lrwxr-xr-x 1 root wheel 62 Dec 31 1969 result/home-files -> /nix/store/cv68n6291xzdwqz3f7whlp3qg5vzm60g-home-manager-files
Now go ahead and actually install these files to your home directory:
#> hm switch example *** Downloading ‘https://cache.nixos.org/nar/0p2lrqwwy78m9i60zz4gnhbkhr461s39d75wq3zk901kcl8cw5ck.nar.xz’ (signed by ‘cache.nixos.org-1’) to ‘/nix/store/31hsbhw2y0x82yzim18rff4pvbp410f2-stdenv-darwin’... % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 9348 100 9348 0 0 9348 0 0:00:01 --:--:-- 0:00:01 76000 Starting home manager activation Activating checkLinkTargets Activating writeBoundary Activating installPackages installing ‘home-manager-path’ building path(s) ‘/nix/store/b1ag2rsy281525xsg3rka0v3j7hn1k6v-user-environment’ created 26 symlinks in user environment Activating linkGeneration No change so reusing latest profile generation 168 Cleaning up orphan links from /Users/dustinlacewell
#> cat ~/.hello.conf This doesn't do anything!
#> hello Hello, World!
Woo.
Protect your Secrets
So that you don't need to keep secrets in your configuration hm
will source
$HOME/.secrets
. This file should export any environment variables that you
utilize while building your configuration.
This file should probably not directly contain your secrets. We recommend instead, utilizing a a tool to manage your secrets. The tool can be used to interpolate secret values when the file is sourced. Some options might be:
- GNU Pass: https://www.passwordstore.org/
- Mozilla SOPS: https://github.com/mozilla/sops
- LastPass CLI: https://github.com/lastpass/lastpass-cli
Plugins
Plugins are defined in $HOME/.home-manager/plugins.nix
.
This expression contains a simple attrset. Each attribute is the name of a plugin. Its value should be a NixOS package. The package can be fetched dynamically using any of the following helpers:
pkgs.fetchFromBitbucket pkgs.fetchFromGitHub pkgs.fetchFromGitLab pkgs.fetchFromRepoOrCz pkgs.fetchFromSavannah pkgs.fetchHex pkgs.fetchMavenArtifact pkgs.fetchNuGet pkgs.fetchRepoProject pkgs.fetchadc pkgs.fetchbower pkgs.fetchbzr pkgs.fetchcvs pkgs.fetchdarcs pkgs.fetchegg pkgs.fetchfossil pkgs.fetchgit pkgs.fetchgitLocal pkgs.fetchgitPrivate pkgs.fetchgitrevision pkgs.fetchgx pkgs.fetchhg pkgs.fetchmail pkgs.fetchmtn pkgs.fetchpatch pkgs.fetchs3 pkgs.fetchsvn pkgs.fetchsvnrevision pkgs.fetchsvnssh pkgs.fetchurl pkgs.fetchurlBoot pkgs.fetchzip
Envfiles
Envfiles are a top-level Nix expressions that live in $HOME/.home-manager/envs/
.
Their job is to import the other expressions which make up the environment. You
can have multiple envfiles, one for each unique environment. Take look at
envs/osx.nix
to see how I write mine:
{ imports = [ ../src/ssh ../src/emacs ../src/zsh ../src/httpie ../src/aws ../src/fasd ]; }
The expression is an attrset. The only attribute is imports
set to a list of
paths of other expressions to load.
Expression Sources
Expression Sources are Nix expressions that actually make up your
configuration. I organize these underneath $HOME/.home-manager/src/
. For
each tool I typically create a folder with a default.nix
and any data files.
This is src/emacs/default.nix
at the time of this writing:
{ pkgs, ... }: ① let plugins = import <plugins>; ② in { imports = [ ③ plugins.org-build plugins.org-export ]; programs.emacs = { enable = true; }; ④ home.file.".emacs.d/init.el".source = pkgs.org-build { ⑤ source = ./init.org; }; home.file.".emacs.d/init.html".source = pkgs.org-export { ⑥ source = ./init.org; user = "dustinlacewell"; repo = "emacs.d"; }; }
① Module function
The module is expressed as a function that accepts pkgs
and returns an attrset.
② Import plugins.nix
The expression at $HOME/.home-manager/plugins.nix
is imported so that we
can refer to the plugin packages.
③ Add plugins to imports
One of the attributes of our module's returned attrset is imports
. This takes
a list of modules that should be merged by the module system. This has the
effect of making available any Options declared or defined by the plugins. It
also makes any package overrides provided by the plugins available under
pkgs
.
④ Install Emacs
This line declares the programs.emacs.enable
option to be true. This will
ensure Emacs gets installed the Nix profile.
⑤ Build init.org
Emacs configuration is done with Emacs-Lisp. But I choose to write my
configuration as an Orgmode document. This section calls pkgs.org-build
function which builds an Orgmode document into Emacs-Lisp. This returns the
path of the built .el
file in the store. We assign that to
home.file.".emacs.d/init.el".source
which will cause the file to be symlinked
into our home directory.
⑥ Export init.org
Similar to ⑤ this calls a plugin function. This time it is pkgs.org-export
which builds init.org
as HTML. This line writes out the HTML file to
.emacs.d/init.html
but org-export
will also publish the HTML file to
http://dustinlacewell.github.com/emacs.d/