dark theme

Luca's nix configuration

Table of Contents

1 Introduction

1.1 This repository

This repository contains my system configuration. The main objective is to have a portable and reproducible system in order to for example bootstrap a new system in a quick and automated way. The ideal is to share packages and configuration across different operating systems. At the moment I only use a macOS system but I am prepared for the day I will switch to nixOS

Tools:

  • nix as a package manager
    • In particular, an experimental feature called flake to achieve complete reproducibility
  • home-manager to configure packages and dotfiles
  • nix-darwin to configure macOS systems (e.g. it has a great brew module)

1.2 This file

This file (readme.org) is used to generate (the correct term is tangle) my flake.nix file, where I specify the inputs and outputs of my system configuration. The tangled flake.nix file imports other .nix files (e.g. darwin/default.nix).

This file is better viewed in HTML format here or through org-mode (clone the repo and open in emacs). You can visit my blog at the same website.

2 flake.nix

2.1 file structure

# NOTE: this file is tangled from readme.org
# DO NOT edit by hand
{
  description = "Luca Cambiaghi's darwin configuration";
  <<inputs>>
  outputs = inputs@{ self, nixpkgs, darwin, home-manager, flake-utils, ... }:
    let
      <<nixpkgs-config>>
      <<home-manager-config>>
      <<nix-darwin-config>>
    in {
      darwinConfigurations = {
        <<luca-macbookpro>>
        <<github-ci>>
      };
      <<cloud-vm>>
      <<home-manager-modules>>
    } //
    <<dev-shell>>
}

2.2 inputs

inputs = {
  # Package sets
  nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
  nixpkgs-master.url = "github:nixos/nixpkgs/master";
  nixpkgs-stable-darwin.url = "github:nixos/nixpkgs/nixpkgs-20.09-darwin";
  nixos-stable.url = "github:nixos/nixpkgs/nixos-20.09";

  # Environment/system management
  # darwin.url = "github:lnl7/nix-darwin";
  darwin.url = "github:hardselius/nix-darwin";
  darwin.inputs.nixpkgs.follows = "nixpkgs";
  home-manager.url = "github:nix-community/home-manager";
  home-manager.inputs.nixpkgs.follows = "nixpkgs";

  # Other sources
  emacs.url = "github:nix-community/emacs-overlay";
  fish-done = { url = "github:franciscolourenco/done"; flake = false; };
  flake-compat = { url = "github:edolstra/flake-compat"; flake = false; };
  flake-utils.url = "github:numtide/flake-utils";
};

2.3 nixpkgs config

The trick in the overlays variable allows us to use the stable version of problematic packages. You can just use stable.pkg instead of pkg in home/default.nix

nixpkgsConfig = with inputs; {
  config = {
    allowUnfree = true;
    allowUnsupportedSystem = true;
  };
  overlays = [
    (
      final: prev:
      let
        system = prev.stdenv.system;
        nixpkgs-stable = if system == "x86_64-darwin" then nixpkgs-stable-darwin else nixos-stable;
      in {
        master = nixpkgs-master.legacyPackages.${system};
        stable = nixpkgs-stable.legacyPackages.${system};
      }
    )
    emacs.overlay
  ];
};

2.4 home-manager config

homeManagerCommonConfig = with self.homeManagerModules; {
  imports = [
    ./home
    # configs.git.aliases
    # configs.starship.symbols
    # programs.kitty.extras
  ];
};

2.5 nix-darwin config

nixDarwinCommonModules = { user }: [
  # Main `nix-darwin` config
  ./darwin
  # `home-manager` module
  home-manager.darwinModules.home-manager
  {
    nixpkgs = nixpkgsConfig;
    # Hack to support legacy worklows that use `<nixpkgs>` etc.
    # nix.nixPath = { nixpkgs = "$HOME/.config/nixpkgs/nixpkgs.nix"; };
    # `home-manager` config
    users.users.${user}.home = "/Users/${user}";
    home-manager.useGlobalPkgs = true;
    home-manager.users.${user} = homeManagerCommonConfig;
  }
];

2.6 luca-macbook-pro

luca-macbookpro = darwin.lib.darwinSystem {
  modules = nixDarwinCommonModules { user = "luca"; } ++ [
    {
      networking = {
        knownNetworkServices = ["Wi-Fi" "Bluetooth PAN" "Thunderbolt Bridge"];
        hostName =  "luca-macbookpro";
        computerName = "luca-macbookpro";
        localHostName = "luca-macbookpro";
      };
    }
  ];
  specialArgs = { inherit inputs nixpkgs; };
};

2.7 github-ci

githubCI = darwin.lib.darwinSystem {
  modules = nixDarwinCommonModules { user = "runner"; } ++ [
    ({ lib, ... }: { homebrew.enable = lib.mkForce false; })
  ];
};

2.8 home-manager-modules

# homeManagerModules = {
#   configs.git.aliases = import ./home/configs/git-aliases.nix;
#   configs.gh.aliases = import ./home/configs/gh-aliases.nix;
#   configs.starship.symbols = import ./home/configs/starship-symbols.nix;
#   programs.neovim.extras = import ./home/modules/programs/neovim/extras.nix;
#   programs.kitty.extras = import ./home/modules/programs/kitty/extras.nix;
# };

2.9 cloud-vm

Build and activate with nix build .#cloudVM.activationPackage; ./result/activate

cloudVM = home-manager.lib.homeManagerConfiguration {
  system = "x86_64-linux";
  homeDirectory = "/home/luca";
  username = "luca";
  configuration = {
    imports = [ homeManagerCommonConfig ];
    nixpkgs = nixpkgsConfig;
  };
};

2.10 dev-shell

inputs.flake-utils.lib.eachDefaultSystem (system:
  let
    pkgs = nixpkgs.legacyPackages.${system};
  in {
    devShell = import ./shell.nix { inherit pkgs; };
  });

3 Practical commands

3.1 Install nix (flakes)

thanks https://github.com/kclejeune/system

# 1.
if [[ $(uname -s) == 'Darwin' ]]; then
    # sh <(curl -L https://nixos.org/nix/install) --daemon --darwin-use-unencrypted-nix-store-volume
    sh <(curl -L https://github.com/numtide/nix-flakes-installer/releases/download/nix-2.4pre20210126_f15f0b8/install) --daemon --darwin-use-unencrypted-nix-store-volume
else
    sh <(curl -L https://nixos.org/nix/install) --daemon
fi

# 2.
git clone git@github.com:lccambiaghi/nixpkgs.git ~/git/nixpkgs

# 3.
cd ~/git/nixpkgs && nix build ".#darwinConfigurations.luca-macbookpro.system" && ./result/sw/bin/darwin-rebuild switch --flake .#luca-macbookpro

3.2 darwin-rebuild

darwin-rebuild build --flake .#luca-macbookpro
# nix build ".#darwinConfigurations.luca-macbookpro.system"
darwin-rebuild switch --flake .#luca-macbookpro
# ./result/sw/bin/darwin-rebuild switch --flake .#luca-macbookpro

3.3 nix flake update

nix flake update --update-input nixpkgs

4 Nix

4.1 Fundamentals

Set:

{ "a b" = "c"; count = 2; }

List:

[42 "a b" (3 + 6) [2 3 4] {x = 2;}]

Lambda:

(x: x + x) 21
# 42

let hi = {name, place}: "Hi ${name} in ${place}!";
in hi { name = "Michael"; place = "Austria";  }

Parameter with default value:

{ pkgs ? import <nixpkgs> {} }:

<nixpkgs> refers to the value of the nixpkgs attribute declared in the NIXPATH environment variable

4.2 Config

A config takes an attribute as parameter and returns an attribute set

{ pkgs }:

{
  packageOverrides = pkgs: {
    emacs = pkgs.emacs.override {
      withGTK2 = false;
      withGTK3 = false;
      withXwidgets = false;
    };
  };

  allowUnfree = true;
}

4.3 Derivation

A derivation takes inputs and produces output. A derivation is lazy, so it will only be evaluated when it is input to other derivations.

derivation {
  name = "hello-world";
  system = "x86_64-linux";
  outputs = [ "out" ];  # This is the default, and can be omitted.
  builder = "${pkgs.bash}/bin/bash";
  args = [ "-c" "echo 'Hello world!' > $out" ];
}

Derviation outputs are stored in the nix store. Each derivation's output is defined by an hash which encodes all input derivations. If something changes even slightly in the inputs, the hash output will change.

4.4 Escaping in strings

  • You can use ' to escape double quotes
  • You can use '' to escape dollar

5 References