This project works best if the following tools are installed:
If you use nix
and direnv
on your host machine, then all required tooling and packages will be automatically installed for you in your development shell.
In addition, this project uses pre-commit
. If you are not using Nix + direnv
, you can install the Git hooks manually in your project by installing pre-commit
and running:
pre-commit install
The directory structure of this project is optimized for sharing configuration as much as possible.
The /hosts
directory contains all systems that are managed by NixOS. Each host has its own directory (with the same name as the machine's hostname).
In addition, the /hosts
directory contains a /common
subdirectory. This directory contains configuration that can be shared across all hosts. Within the /common
subdirectory, we have the following:
/common/global
-> global configuration that is shared between all hosts/common/presets
-> presets that are applied to specific host types (i.e.nixos
,darwin
,desktop
, etc.)/common/users
-> user-specific configuration that is shared between hosts
The /home
directory contains per-user, per-host Home Manager configurations. The directory hierarchy corresponds to the user-specific Home Manager configurations for a particular host.
/home/<username>/<hostname>
In addition, the /home
directory contains a /common
subdirectory. This directory contains Home Manager configurations that can be shared across all hosts. Within the /common
subdirectory, we have the following:
/common/global
-> global configuration that is shared between all hosts/common/presets
-> presets that are applied to specific host types (i.e.nixos
,darwin
,desktop
, etc.)
The /modules
directory contains shared NixOS and Home Manager modules.
For infrastructure that is unable to be maintained by Nix (i.e. external services such as GitHub), we leverage HashiCorp Terraform.
You can provision the infrastructure in AWS required to host Terraform state using the boostrap.sh
script:
./terraform/scripts/bootstrap.sh --bucket <bucket-name> --region <aws-region> --table <dynamodb-table>
cd terraform/github
terraform init
terraform plan
To lock provider versions for different operating systems / architectures:
terraform providers lock -platform=linux_amd64 -platform=darwin_amd64 -platform=linux_arm64 -platform=darwin_arm64
This project makes use of Mozilla SOPS (Secrets OPerationS)
The .sops.yaml
file at the root of the repository defines creation rules for secrets to be encrypted with sops
. Any files matching the defined creation rule paths will be encrypted with the specified public keys.
To update secret files after making changes to the .sops.yaml
file, run the snippet below:
find . -regex $(yq -r '[.creation_rules[] | "./" + .path_regex] | join("\\|")' "$(pwd)/.sops.yaml") | \
xargs -i sops updatekeys -y {}
The project uses sops-nix
for automatically decrypting and injecting secrets into our NixOS configurations.
The project uses the [carlpett/sops
] Terraform provider for automatically decrypting and injecting secrets into our Terraform configurations.
The easiest way to add new machines is by using SSH host keys (this requires OpenSSH to be enabled).
We use age
to encrypt secrets. To obtain an age
public key, you can use the ssh-to-age
tool to convert a host SSH Ed25519 key to the age format.
nix run nixpkgs#ssh-to-age -- ssh-to-age < /etc/ssh/ssh_host_ed25519_key.pub
Then add the age
public key to the .sops.yaml
file, apply it to the desired key groups, and then re-encrypt the secret files (see Updating Secrets).