Skip to main content
Luca

Luca's nix configuration

Introduction

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)

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.

flake.nix

file structure

# NOTE: this file is tangled from readme.org
# DO NOT edit by hand
{
  description = "Luca Cambiaghi's darwin configuration";
  <<inputs>>

  # outputs = { self, darwin, home-manager, flake-utils, ... }@inputs:
  outputs = inputs@{ self, nixpkgs, darwin, home-manager, flake-utils, ... }:
    let
      inherit (darwin.lib) darwinSystem;
      inherit (inputs.nixpkgs-unstable.lib) attrValues makeOverridable optionalAttrs singleton;
      <<nixpkgs-config>>
      <<home-manager-config>>
      <<nix-darwin-config>>
    in {
      darwinConfigurations = rec {
        <<bootstrap-x86>>
        <<bootstrap-arm>>
        <<macbook-pro>>
        <<macbook-pro-m1>>
        <<github-ci>>
      };
      <<cloud-vm>>
      <<home-manager-modules>>
      overlays = {
        <<overlays>>
      };
    } //
    <<re-export-with-overlays>>
}

inputs

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

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

  # 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";
};

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 = {
  config = { allowUnfree = true; allowUnsupportedSystem = true;};
  overlays = attrValues self.overlays ++ singleton (
    # Sub in x86 version of packages that don't build on Apple Silicon yet
    final: prev: (optionalAttrs (prev.stdenv.system == "aarch64-darwin") {
      inherit (final.pkgs-x86)
        idris2
        nix-index
        niv;
    })
  );
};

home-manager config

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

nix-darwin config

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

bootstrap-x86

# Mininal configurations to bootstrap systems
bootstrap-x86 = makeOverridable darwinSystem {
  system = "x86_64-darwin";
  modules = [ ./darwin/bootstrap { nixpkgs = nixpkgsConfig; } ];
};

bootstrap-arm

bootstrap-arm = bootstrap-x86.override { system = "aarch64-darwin"; };

macbook-pro

# main macbook configuration
macbookpro = makeOverridable darwinSystem {
  system = "x86_64-darwin";
  modules = nixDarwinCommonModules ++ [
    {
      # users.primaryUser = "cambiaghiluca";
      networking = {
        knownNetworkServices = ["Wi-Fi" "Bluetooth PAN" "Thunderbolt Bridge"];
        # hostName =  "luca-macbookpro";
        # computerName = "luca-macbookpro";
        # localHostName = "luca-macbookpro";
      };
    }
  ];
  specialArgs = { inherit inputs nixpkgs; };
};

macbook-pro-m1

# My new Apple Silicon macOS laptop config
macbookpro-m1 = macbookpro.override { system = "aarch64-darwin"; };

github-ci

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

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;
# };

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;
  };
};

overlays

# Overlays to add different versions `nixpkgs` into package set
pkgs-master = final: prev: {
  pkgs-master = import inputs.nixpkgs-master {
    inherit (prev.stdenv) system;
    inherit (nixpkgsConfig) config;
  };
};
pkgs-stable = final: prev: {
  pkgs-stable = import inputs.nixpkgs-stable {
    inherit (prev.stdenv) system;
    inherit (nixpkgsConfig) config;
  };
};
pkgs-unstable = final: prev: {
  pkgs-unstable = import inputs.nixpkgs-unstable {
    inherit (prev.stdenv) system;
    inherit (nixpkgsConfig) config;
  };
};
apple-silicon = final: prev: optionalAttrs (prev.stdenv.system == "aarch64-darwin") {
  # Add access to x86 packages system is running Apple Silicon
  pkgs-x86 = import inputs.nixpkgs-unstable {
    system = "x86_64-darwin";
    inherit (nixpkgsConfig) config;
  };
};

re-export with overlays

flake-utils.lib.eachDefaultSystem (system: {
  legacyPackages = import inputs.nixpkgs-unstable {
    inherit system;
    inherit (nixpkgsConfig) config;
    overlays = with self.overlays; [
      pkgs-master
      pkgs-stable
      apple-silicon
    ];
  };
});

Practical commands

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.bootstrap-x86.system" && ./result/sw/bin/darwin-rebuild switch --flake .#luca-macbookpro

First build on new machine

First build:

nix --extra-experimental-features "nix-command flakes" build .#darwinConfigurations.macbookpro.system
./result/sw/bin/darwin-rebuild switch —flake .#macbookpro

If something goes wrong with synthetic volume:

echo -e "run\tprivate/var/run" | sudo tee -a /etc/synthetic.conf >/dev/null
/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t

Some files to backup:

sudo mv /etc/nix/nix.conf /etc/nix/nix.conf.bak
sudo mv /etc/shells /etc/shells.bak
mv ~/.zshrc ~/.zshrc.bak

Misc TODOs:

  • To use touch id for sudo (e.g. every time you reload configuration) follow this link: https://www.imore.com/how-use-sudo-your-mac-touch-id (open file with sudo vim)
  • Install FontAwesome
  • Configure Amethyst shortcuts (throw windows) and turn off "focus follows mouse"
  • Configure macOS ctrl to be caps

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

nix flake update

nix flake update --update-input nixpkgs

brew86, pyenv86

Reference: https://sixty-north.com/blog/pyenv-apple-silicon.html

arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
alias brew86="arch -x86_64 /usr/local/bin/brew"

# brew86 install openssl readline sqlite3 xz zlib python@3.9
brew86 install python@3.11