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!
configuration.nix
entry point, no Nix channels─ just flake.nix
nix-darwin
and nix-homebrew
disko
, say goodbye to disk utilsagenix
for SSH, PGP, syncthing, and other toolshome-manager
module for seamless configuration (no extra clunky CLI steps)https://github.com/dustinlyons/nixos-config/assets/1292576/2168d482-6eea-4b51-adc1-2ef1291b6598
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
https://github.com/dustinlyons/nixos-config/assets/1292576/fa54a87f-5971-41ee-98ce-09be048018b8
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.
.
├── 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
This configuration supports both Intel and Apple Silicon Macs.
xcode-select --install
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
andnix-command
aren't available by default.You'll need to enable them.
Add this line to your
/etc/nix/nix.conf
fileexperimental-features = nix-command flakes
OR
Specify experimental features when using
nix run
belownix --extra-experimental-features 'nix-command flakes' run .#<command>
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
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 {} \;
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.
You can search for packages on the official NixOS website.
Review these files
Add anything from your existing ~/.zshrc
, or just review the new configuration.
Review these files
If you are using the starter with secrets, there are a few additional steps.
In Github, create a private nix-secrets
repository with at least one file (like a README
). You'll enter this name during installation.
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:
This command auto-detects a USB drive connected to the current system.
Keys must be named
id_ed25519
andid_ed25519_agenix
.nix run .#copy-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
If you're rolling your own, just check they are installed correctly.
nix run .#check-keys
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
ifnix-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.
Finally, alter your system with this command:
nix run .#build-switch
[!CAUTION]
~/.zshrc
will be replaced with thezsh
configuration from this repository. Make sure this is what you want.
This configuration supports both x86_64
and aarch64
platforms.
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
If you are using the starter with secrets, there are a few additional steps.
In Github, create a private nix-secrets
repository with at least one file (like a README
). You'll enter this name during installation.
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:
This command auto-detects a USB drive connected to the current system.
Keys must be named
id_ed25519
andid_ed25519_agenix
.sudo nix run --extra-experimental-features 'nix-command flakes' github:dustinlyons/nixos-config#copy-keys
sudo nix run --extra-experimental-features 'nix-command flakes' github:dustinlyons/nixos-config#create-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
[!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
sudo nix run --extra-experimental-features 'nix-command flakes' github:dustinlyons/nixos-config#install
With secrets
sudo nix run --extra-experimental-features 'nix-command flakes' github:dustinlyons/nixos-config#install-with-secrets
On first boot at the login screen:
Ctrl-Alt-F2
(or Fn-Ctrl-Option-F2
if on a Mac) to move to a terminal sessionroot
using the password created during installationpasswd <user>
Ctrl-Alt-F7
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 imperativeagenix
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 yourid_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:
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.
With Nix, changes to your system are made by
This is all wrapped up in the build-switch
run command.
So, in general, the workflow for managing your environment will look like
nix run .#build-switch
nix-darwin
, home-manager
, etc do their thingFor quickly trying a package without installing it, I usually run
nix shell nixpkgs#hello
where hello
is the package name from nixpkgs.
This configuration has been tested and confirmed to work on the following platforms:
Have feedback or questions? Feel free to use the discussion forum.
Interested in contributing to this project? Here's how you can help:
Code Contributions: If you're interested in contributing code, please start by looking at open issues or feature requests. Fork the repository, make your changes, and submit a pull request. Make sure your code adheres to the existing style. For significant changes, consider opening an issue for discussion before starting work.
Reporting Bugs: If you encounter bugs or issues, please help by reporting them. Open a GitHub Issue and include as much detail as possible: what you were doing when the bug occurred, steps to reproduce the issue, and any relevant logs or error messages.
Reasons to jump into flakes and skip nix-env
, Nix channels, etc
npm
, cargo
, poetry
, composer
, etc. Channels work more like traditional Linux distributions (like Ubuntu), which most devs don't know.nixpkgs
version. Flakes lock each individual package to a version, which is more precise and makes it much easier to manage overall.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 |
This project is released under the BSD-3-Clause license.
Did you find my project useful? Your support is appreciated.
"All we have to decide is what to do with the time that is given us." - J.R.R. Tolkien