This repository contains the sources for deploying my personal workstation environment on OSX.
The repository is deployed with home-manager which is built on Nix.
Install the Nix package manager to your workstation:
curl https://nixos.org/nix/install | shThis will create /nix as well as some system-wide profile scripts which will
integrate your shell with Nix.
Clone this repo to $HOME/.config/nixpkgs/:
git clone https://github.com/dustinlacewell/dotfiles.git ~/.config/nixpkgsSymlink the bin/hm script somewhere on your $PATH:
ln -s ~/.config/nixpkgs/bin/hm ~/bin/hm(make sure ~$HOME/bin~ is on your ~$PATH~!)
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
A wrapper-script $HOME/.config/nixpkgs/bin/hm is provided which you should
symlink somewhere on your path:
usage: hm <command> <env>
Commands:
build - build env to ./result/
switch - build env to ~/
Environments:
Loads ~/.config/nixpkgs/envs/<env>.nix
To perform a dry-run use the build command. It creates a ./result/
directory with the files that would be symlinked into your home directory:
#> hm build osx
...#> tree ./result/
./result/
├── activate
├── home-files -> /nix/store/5x3dxzivrnh0lks5sc3fgfkcg4884xb1-home-manager-files
└── home-path -> /nix/store/2scx60dwvx9fvi55cwcjmg39gd2ymvvl-home-manager-path
2 directories, 1 fileOnce you’re satisfied with the dry-run output, use the switch command to
actually install symlinks into your home directory.
#> hm switch osx
...#> find ~/ -type l -ls | grep "nix/store"
lrwxr-xr-x ~/.config/zsh/.zshenv -> /nix/store/5x3dxzivrnh0lks5sc3fgfkcg4884xb1-home-manager-files/.config/zsh/.zshenv
lrwxr-xr-x ~/.config/zsh/.zshrc -> /nix/store/5x3dxzivrnh0lks5sc3fgfkcg4884xb1-home-manager-files/.config/zsh/.zshrc
lrwxr-xr-x ~/.emacs.d/init.el -> /nix/store/5x3dxzivrnh0lks5sc3fgfkcg4884xb1-home-manager-files/.emacs.d/init.el
lrwxr-xr-x ~/.emacs.d/init.html -> /nix/store/5x3dxzivrnh0lks5sc3fgfkcg4884xb1-home-manager-files/.emacs.d/init.html
lrwxr-xr-x ~/.ssh/config -> /nix/store/5x3dxzivrnh0lks5sc3fgfkcg4884xb1-home-manager-files/.ssh/config
lrwxr-xr-x ~/.zshenv -> /nix/store/5x3dxzivrnh0lks5sc3fgfkcg4884xb1-home-manager-files/.zshenvPlugins are defined in $HOME/.config/nixpkgs/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 are a top-level Nix expressions that live in $HOME/.config/nixpkgs/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 are Nix expressions that actually make up your
configuration. I organize these underneath $HOME/.config/nixpkgs/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";
};
}The module is expressed as a function that accepts pkgs and returns an attrset.
The expression at $HOME/.config/nixpkgs/plugins.nix is imported so that we
can refer to the plugin packages.
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.
This line declares the programs.emacs.enable option to be true. This will
ensure Emacs gets installed the Nix profile.
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.
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/