What is Nixpkgs, home-manager and nix-darwin

Nix is a powerful package manager for Unix systems. Nixpkgs is a channel of it. Anaconda users should be familar with this term.

I'd like to have dotfiles, configurations, Applications hardcoded in order to make the environment of my machines reproducible. Before using Nixpkgs, I had to use several tools to serve this purpose. home-manager makes use of nixpkgs and provides some other functionalities that makes this easier. Because I mainly use macOS, nix-darwin is also part of this.

Installation

Single User Installation for NixOS

因为在 macOS 10.15 中, 目录 "/" 变成了只读,所以需要额外的设置。source: issue #2925: /nix will not be writable on macOS Catalina

  1. Ask for a mountpoint: sudo bash -c "echo nix >> /etc/synthetic.conf" and then reboot.
  2. Run sudo diskutil apfs addVolume disk1 APFSX Nix -mountpoint /nix to create a volume and mount it on /nix.
  3. Run sudo bash -c 'echo "LABEL=Nix /nix apfs rw" >> /etc/fstab' to instruct macOS to remount on reboot.
  4. diskutil ap encryptVolume Nix -user disk and then reboot.
  5. Run bash <(curl https://nixos.org/nix/install) to install.

Nix-Darwin

nix-build https://github.com/LnL7/nix-darwin/archive/master.tar.gz -A installer
./result/bin/darwin-installer

Choose to change configuration file during installation.

environment.darwinConfig = "$HOME/.config/nixpkgs/configuration.nix";

programs.zsh.enable = true;

Structure

nixpkgs
channels
config
home-manager
...
alacritty.nix
hosts
modules
nix
auto-host.nix
hostname.nix
hostname.nix
nix-path.nix
overlays
profiles
configuration.nix
❯ lt -L1 nixpkgs
 nixpkgs
├──  channels
├──  config
│  ├──  home-manager
│  │  ├──  alacritty.nix
│  │  ├──  fzf.nix
│  │  ├──  gpg.nix
│  │  ├──  lsd.nix
│  │  ├──  xdg.nix
│  │  └──  zsh.nix
│  ├──  home-manager.nix
│  └──  zsh.nix
├──  configuration.nix
├──  hosts
├──  modules
├──  nix
│  ├──  auto-host.nix
│  ├──  hostname.nix
│  ├──  nix-path.nix
│  └──  username.nix
├──  overlays
├──  profiles
│  ├──  users.nix
│  └──  common.nix
└──  services

nixpkgs

Uninstallation

nix-build https://github.com/LnL7/nix-darwin/archive/master.tar.gz -A uninstaller
./result/bin/darwin-uninstaller
sudo rm -rf /etc/nix /nix /var/root/.nix-profile /var/root/.nix-defexpr /var/root/.nix-channels ~/.nix*

sudo launchctl unload /Library/LaunchDaemons/org.nixos.nix-daemon.plist
sudo rm /Library/LaunchDaemons/org.nixos.nix-daemon.plist

Introduction

nix-shell

➜ nix-shell -p python3 --run "python3"
Python 3.7.4 (default, Sep 15 2019, 22:23:53)
[Clang 7.1.0 (tags/RELEASE_710/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.executable
'/nix/store/611gq7s9s11w5ri95fbq2adi9ifrhkmn-python3-3.7.4/bin/python3'
>>>

If we don't parse the parameter for --run, nix-shell -p python3 will enter a shell with /nix/store/611gq7s9s11w5ri95fbq2adi9ifrhkmn-python3-3.7.4/bin/python.

Configuration

配置可以参考 dotfiles。下面说一下怎么根据自己的需要跟新官方仓库里的包或者添加不存在的包。

bin

方法就是手动添加一个 default.nix 直接安装可执行文件。比如 starship,我是直接安装可执行文件。

{ stdenv, fetchurl }:

stdenv.mkDerivation rec {
  name = "starship-v${version}";
  version = "0.19.0";

  src = fetchurl {
    url = "https://github.com/starship/starship/releases/download/v${
      version
    }/starship-v${version}-x86_64-apple-darwin.tar.gz";
    sha256 = "1fxpr5j6icr38isp77cg8xan0kr9d79ff00q4dn8qrh8zr2cmbmg";
  };

  unpackPhase = ''
    mkdir -p $out/bin
    tar -xzf $src
    cp x86_64-apple-darwin/starship $out/bin/starship
  '';

  dontInstall = true;
}

compile

这是比较复杂的情况,不过有利于了解 NixOS。拿 navi 来打比方:

with import <nixpkgs> {};

stdenv.mkDerivation rec {
  name = "navi-v${version}";
  version = "0.10.1";

  src = fetchFromGitHub {
    owner = "denisidoro";
    repo = "navi";
    rev = "d55b5725d46212b87864ad4bbf3ca4188553d0bc";
    sha256 = "1arrjdmmbdqfcpgl54a8p9izp5mi8qm6jmjpydrrjimnpm8k5m1v";
  };
}

先写上这么个 default.nix,然后在当前目录运行 nix-shell,在 shell 里面可以通过 echo $nameecho $srcls $srcecho $out来熟悉环境,这些变量可以在 starshipunpackPhase 里看到。

然后稍作修改

{ stdenv, fetchFromGitHub }:

stdenv.mkDerivation rec {
  name = "navi-v${version}";
  version = "0.10.1";

  src = fetchFromGitHub {
    owner = "denisidoro";
    repo = "navi";
    rev = "d55b5725d46212b87864ad4bbf3ca4188553d0bc";
    sha256 = "1arrjdmmbdqfcpgl54a8p9izp5mi8qm6jmjpydrrjimnpm8k5m1v";
  };

  installPhase = ''
    mkdir -p $out/bin
    echo '${src}/navi "$@"' > $out/bin/navi
    chmod +x $out/bin/navi
  '';
}

Links