dustinlyons / nixos-config

General purpose Nix configuration for macOS / NixOS with starter templates + step-by-step guides ✨
BSD 3-Clause "New" or "Revised" License
1.79k stars 113 forks source link
agenix dotfiles emacs home-manager literate-configuration macos nix nix-config nix-darwin nix-flake nixos nixos-configuration

General Purpose Nix Config for macOS + NixOS

Build Starter Template Statix Lint

Overview

Hey, you made it! Welcome. 🤓

Nix is a powerful package manager for Linux and Unix systems that ensures reproducible, declarative, and reliable software management.

This repository contains configuration for a general-purpose development environment that runs Nix on macOS, NixOS, or both simultaneously.

I use it daily on my 🧑🏻‍💻 Macbook Pro and an x86 PC in my home office. It also runs as a VM on your Mac. Many others have reported that it's working for them too.

Check out the step-by-step commands below to get started!

Table of Contents

Features

Testimonials

Screenshot 2024-10-31 at 9 32 38 AM

Screenshot 2024-10-31 at 11 07 07 AM

Screenshot 2024-10-31 at 9 33 27 AM

Screenshot 2024-10-31 at 11 00 11 AM

Videos

macOS

Updating dependencies with one command

https://github.com/dustinlyons/nixos-config/assets/1292576/2168d482-6eea-4b51-adc1-2ef1291b6598

Instant Emacs 29 thanks to daemon mode

https://github.com/dustinlyons/nixos-config/assets/1292576/66001066-2bbf-4492-bc9e-60ea1abeb987

https://github.com/dustinlyons/nixos-config/assets/1292576/d96f59ce-f540-4f14-bc61-6126a74f9f52

NixOS

https://github.com/dustinlyons/nixos-config/assets/1292576/fa54a87f-5971-41ee-98ce-09be048018b8

Disclaimer

Installing Nix on macOS will create an entirely separate volume. It may exceed many gigabytes in size.

Some folks don't like this. If this is you, turn back now!

[!NOTE] Don't worry, you can always uninstall Nix later.

Layout

.
├── apps         # Nix commands used to bootstrap and build configuration
├── hosts        # Host-specific configuration
├── modules      # macOS and nix-darwin, NixOS, and shared configuration
├── overlays     # Drop an overlay file in this dir, and it runs. So far, mainly patches.
├── templates    # Starter versions of this configuration

Installing

For macOS (November 2024)

This configuration supports both Intel and Apple Silicon Macs.

1. Install dependencies

xcode-select --install

2. Install Nix

Thank you for the installer, Determinate Systems!

curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install

After installation, open a new terminal session to make the nix executable available in your $PATH. You'll need this in the steps ahead.

[!IMPORTANT]

If using the official installation instructions instead, flakes and nix-command aren't available by default.

You'll need to enable them.

Add this line to your /etc/nix/nix.conf file

experimental-features = nix-command flakes

OR

Specify experimental features when using nix run below

nix --extra-experimental-features 'nix-command flakes' run .#<command>

3. Initialize a starter template

Choose one of two options

Simplified version without secrets management

mkdir -p nixos-config && cd nixos-config && nix flake --extra-experimental-features 'nix-command flakes' init -t github:dustinlyons/nixos-config#starter

Full version with secrets management

mkdir -p nixos-config && cd nixos-config && nix flake --extra-experimental-features 'nix-command flakes' init -t github:dustinlyons/nixos-config#starter-with-secrets

4. Make apps executable

find apps/$(uname -m | sed 's/arm64/aarch64/')-darwin -type f \( -name apply -o -name build -o -name build-switch -o -name create-keys -o -name copy-keys -o -name check-keys \) -exec chmod +x {} \;

5. Apply your current user info

Run this Nix command to replace stub values with your system properties, username, full name, and email.

Your email is only used in the git configuration.

nix run .#apply

[!NOTE] If you're using a git repository, only files in the working tree will be copied to the Nix Store.

You must run git add . first.

6. Decide what packages to install

You can search for packages on the official NixOS website.

Review these files

7. Review your shell configuration

Add anything from your existing ~/.zshrc, or just review the new configuration.

Review these files

8. Optional: Setup secrets

If you are using the starter with secrets, there are a few additional steps.

8a. Create a private Github repo to hold your secrets

In Github, create a private nix-secrets repository with at least one file (like a README). You'll enter this name during installation.

8b. Install keys

Before generating your first build, these keys must exist in your ~/.ssh directory. Don't worry, I provide a few commands to help you.

Key Name Platform Description
id_ed25519 macOS / NixOS Download secrets from Github. Used only during bootstrap.
id_ed25519_agenix macOS / NixOS Copied over, used to encrypt and decrypt secrets.

Run one of these commands:

Copy keys from USB drive

This command auto-detects a USB drive connected to the current system.

Keys must be named id_ed25519 and id_ed25519_agenix.

nix run .#copy-keys
Create new keys
nix run .#create-keys

[!NOTE] If you choose this option, make sure to save the value of id_ed25519.pub to Github.

cat /Users/$USER/.ssh/id_ed25519.pub | pbcopy # Copy key to clipboard
Check existing keys

If you're rolling your own, just check they are installed correctly.

nix run .#check-keys

9. Install configuration

Ensure the build works before deploying the configuration, run:

nix run .#build

[!NOTE] If you're using a git repository, only files in the working tree will be copied to the Nix Store.

You must run git add . first.

[!WARNING] You may encounter error: Unexpected files in /etc, aborting activation if nix-darwin detects it will overwrite an existing /etc/ file. The error will list the files like this:

The following files have unrecognized content and would be overwritten:

  /etc/nix/nix.conf
  /etc/bashrc

Please check there is nothing critical in these files, rename them by adding .before-nix-darwin to the end, and then try again.

Backup and move the files out of the way and/or edit your Nix configuration before continuing.

10. Make changes

Finally, alter your system with this command:

nix run .#build-switch

[!CAUTION] ~/.zshrc will be replaced with the zsh configuration from this repository. Make sure this is what you want.

For NixOS

This configuration supports both x86_64 and aarch64 platforms.

1. Burn and use the latest ISO

Download and burn the minimal ISO image to a USB, or create a new VM with the ISO as base. Boot the installer.

If you're building a VM on an Apple Silicon Mac, choose 64-bit ARM.

Quick Links

2. Optional: Setup secrets

If you are using the starter with secrets, there are a few additional steps.

2a. Create a private Github repo to hold your secrets

In Github, create a private nix-secrets repository with at least one file (like a README). You'll enter this name during installation.

2b. Install keys

Before generating your first build, these keys must exist in your ~/.ssh directory. Don't worry, I provide a few commands to help you.

Key Name Platform Description
id_ed25519 macOS / NixOS Download secrets from Github. Used only during bootstrap.
id_ed25519_agenix macOS / NixOS Copied over, used to encrypt and decrypt secrets.

Run one of these commands:

Copy keys from USB drive

This command auto-detects a USB drive connected to the current system.

Keys must be named id_ed25519 and id_ed25519_agenix.

sudo nix run --extra-experimental-features 'nix-command flakes' github:dustinlyons/nixos-config#copy-keys
Create new keys
sudo nix run --extra-experimental-features 'nix-command flakes' github:dustinlyons/nixos-config#create-keys
Check existing keys

If you're rolling your own, just check they are installed correctly.

sudo nix run --extra-experimental-features 'nix-command flakes' github:dustinlyons/nixos-config#check-keys

3. Install configuration

Pick your template

[!IMPORTANT] For Nvidia cards, select the second option, nomodeset, when booting the installer, or you will see a blank screen.

[!CAUTION] Running this will reformat your drive to the ext4 filesystem.

Simple

With secrets

4. Set user password

On first boot at the login screen:

How to create secrets

To create a new secret secret.age, first create a secrets.nix file at the root of your nix-secrets repository. Use this code:

[!NOTE] secrets.nix is interpreted by the imperative agenix commands to pick the "right" keys for your secrets.

Think of this file as the config file for agenix. It's not part of your system configuration.

secrets.nix

let
  user1 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL0idNvgGiucWgup/mP78zyC23uFjYq0evcWdjGQUaBH";
  users = [ user1 ];

  system1 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPJDyIr/FSz1cJdcoW69R+NrWzwGK/+3gJpqD1t8L2zE";
  systems = [ system1 ];
in
{
  "secret.age".publicKeys = [ user1 system1 ];
}

Values for user1 should be your public key, or if you prefer to have keys attached to hosts, use the system1 declaration.

Now that we've configured agenix with our secrets.nix, it's time to create our first secret.

Run the command below.

EDITOR=vim nix run github:ryantm/agenix -- -e secret.age

This opens an editor to accept, encrypt, and write your secret to disk.

The command will look up the public key for secret.age, defined in your secrets.nix, and check for its private key in ~/.ssh/.

To override the SSH path, provide the -i flag with a path to your id_ed25519 key.

Write your secret in the editor, save, and commit the file to your nix-secrets repo.

Now we have two files: secrets.nix and our secret.age.

Here's a more step-by-step example:

Secrets Example

Let's say I wanted to create a new secret to hold my Github SSH key.

I would cd into my nix-secrets repo directory, verify the agenix configuration (named secrets.nix) exists, then run

EDITOR=vim nix run github:ryantm/agenix -- -e github-ssh-key.age

This would start a vim session.

I would enter insert mode :i, copy+paste the key, hit Esc and then type :w to save it, resulting in the creation of a new file, github-ssh-key.age.

Then, I would edit secrets.nix to include a line specifying the public key to use for my new secret. I specify a user key, but I could just as easily specify a host key.

secrets.nix

let
  dustin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL0idNvgGiucWgup/mP78zyC23uFjYq0evcWdjGQUaBH";
  users = [ dustin ];
  systems = [ ];
in
{
  "github-ssh-key.age".publicKeys = [ dustin ];
}

Finally, I'd commit all changes to the nix-secrets repository, go back to my nixos-config and run nix flake update to update the lock file.

The secret is now ready to use. Here's an example from my configuration. In the end, this creates a symlink to a decrypted file in the Nix Store that reflects my original file.

Making changes

With Nix, changes to your system are made by

This is all wrapped up in the build-switch run command.

Development workflow

So, in general, the workflow for managing your environment will look like

Trying packages

For quickly trying a package without installing it, I usually run

nix shell nixpkgs#hello

where hello is the package name from nixpkgs.

Compatibility and Feedback

Platforms

This configuration has been tested and confirmed to work on the following platforms:

Feedback and Questions

Have feedback or questions? Feel free to use the discussion forum.

Contributing

Interested in contributing to this project? Here's how you can help:

Appendix

Why Nix Flakes

Reasons to jump into flakes and skip nix-env, Nix channels, etc

NixOS Components

Component Description
Window Manager Xorg + bspwm
Terminal Emulator alacritty
Bar polybar
Application Launcher rofi
Notification Daemon dunst
Display Manager lightdm
File Manager thunar
Text Editor emacs daemon mode
Media Player cider
Image Viewer feh
Screenshot Software flameshot

License

This project is released under the BSD-3-Clause license.

Support

Did you find my project useful? Your support is appreciated.

Buy Me A Coffee

Stars

"All we have to decide is what to do with the time that is given us." - J.R.R. Tolkien

Star History Chart