Structured flake-based NixOS configuration (https://github.com/bqv/nixos)

root

#+title: NixOS System Configuration
#+author: Tony O.
#+email: nixos@fron.io
#+OPTIONS: toc:nil num:nil

* What's this?

A NixOS configuration repository using the experimental flakes mechanism.
Its aim is to provide a generic repository which neatly separates concerns
and allows one to get up and running with NixOS faster than ever.

A configuration.nix is provided for compatibility with nixos-option.

* Build

A rebuild script is provided in the nix shell. If you don't have direnv/lorri,
you can use it as below.

#+BEGIN_SRC sh
  nix-shell --run "rebuild [--show-trace] [-vv] {switch|boot|dry-activate|...}"
#+END_SRC

If you're on NixOS but your system nix does not support flakes, you can force a
working version into scope, as well as the `rebuild` script with the following:

#+BEGIN_SRC sh
  nix-shell --run nixFlakes-shell
#+END_SRC

* Flake Inputs:

  - master: github:nixos/nixpkgs (master)
  - staged: github:nixos/nixpkgs (staging)
  - small: github:nixos/nixpkgs (nixos-unstable-small)
  - large: github:nixos/nixpkgs (nixos-unstable)
  - home: github:rycee/home-manager (bqv-flakes)
  - nur: github:nix-community/nur
  - dwarffs: github:edolstra/dwarffs
  - naersk: github:nmattia/naersk
  - emacs: github:nix-community/emacs-overlay [ non-flake! ]
  - mozilla: github:mozilla/nixpkgs-mozilla [ non-flake! ]
  - snack: github:nmattia/snack [ non-flake! ]
  - napalm: github:nmattia/napalm [ non-flake! ]

* Flake Structure:

** Hosts
   :PROPERTIES:
   :CUSTOM_ID: hosts
   :END:

Module declarations dependant on particular machines should be stored in
the [[file:hosts]] directory. Every file in this directory will be added
automatically to the the =nixosConfigurations= flake output and thus
becomes deployable via =nixos-rebuild= and =rebuild=.

See [[file:hosts/default.nix][=hosts/default.nix=]] for the
implementation.

** Profiles
   :PROPERTIES:
   :CUSTOM_ID: profiles
   :END:

A profile is any directory under [[file:profiles]] containing a
=default.nix= defining a valid NixOS module, with the added restriction
that no new delclarations to the =options= /or/ =config= attributes are
allowed (use [[file:modules]] instead). Their purpose is to provide
abstract expressions suitable for reuse by multiple deployments. They
are perhaps /the/ key mechanism by which we keep this repo maintainable.

Profiles can have subprofiles which are themselves just profiles that
live under another. There's no hard rule that everything in the folder
must be imported by its =default.nix=, so you can also store relevant
code that is useful but not wanted by default in, say, an =alt.nix=.
Importantly, every subdirectory in a profile should be independent of
its parent. i.e:

#+BEGIN_EXAMPLE
  {
    # importing `profile` without implicitly importing `some`
    imports = [ ./profiles/some/profile ];
  }
#+END_EXAMPLE

It is okay for profiles to depend on other profiles so long as they are
explicitly loaded via =imports=.

Optionally, you may choose to export your profiles via the flake output.
If you include it in the list defined in [[file:profiles/list.nix]], it
will be available to other flakes via =nixosModules.profiles=.

** Users
   :PROPERTIES:
   :CUSTOM_ID: users
   :END:

User declarations belong in the =users= directory.

These are actually just a special case of [[#profiles][profiles]]
attached to a particular interactive user. Its primarily for
declarations to =users.users.<new-user>= where =<new-user>.isNormalUser=
is true.

This is a convenient place to import your profiles such that a
particular user always has a reliable stack.

For convenience, [[https://github.com/rycee/home-manager][home-manager]]
is available automatically for home directory setup and should only be
used from this directory.

** Lib
   :PROPERTIES:
   :CUSTOM_ID: lib
   :END:

The [[file:lib]] directory contains a file =utils.nix= which is an
attribute set meant to consist mainly of utility functions you might
want to write and use throughout the configuration. They are available
via a new =usr= attribute passed to every NixOS module, eg:

#+BEGIN_EXAMPLE
  # hosts/some-host.nix
  { usr, ... }:
  let
    inherit (usr) utils;

    data = usr.utils.myFunction # ...
  in
  {
    # NixOS configuration
  }
#+END_EXAMPLE

** Secrets
   :PROPERTIES:
   :CUSTOM_ID: secrets
   :END:

Anything you wish to keep encrypted goes in the =secrets= directory,
which is created on first entering a =nix-shell=.

Be sure to run =git crypt init=, before committing anything to this
directory. Be sure to check out git-crypt's
[[https://github.com/AGWA/git-crypt][documentation]] if your not
familiar. The filter is already set up to encrypt everything in this
folder by default.

To keep [[file:profiles]] reusable across configurations, secrets should
only be imported from the =users= or [[file:hosts][=hosts=]] directory.

** Modules, Packages and Overlays
   :PROPERTIES:
   :CUSTOM_ID: modules-packages-and-overlays
   :END:

All expressions in both [[file:modules/list.nix]] and
[[file:pkgs/default.nix]] are available globally, anywhere else in the
repo. They are additionally included in the =nixosModules= and =overlay=
flake outputs, respectively. Packages can manually be added to
[[file:flake.nix]] for inclusion in the =packages= output as well.

The directory structure is identical to nixpkgs to provide a kind of
staging area for any modules or packages we might be wanting to merge
there later. If your not familiar or can't be bothered, simply dropping
a valid nix file and pointing the =default.nix= to it, is all that's
really required.

As for overlays, they should be defined in the [[file:overlays]]
directory. They will be automatically pulled in for use by all
configurations. Nix command line tools will be able to read overlays
from here as well since it is set as =nixpkgs-overlays= in =NIX_PATH=.
And of course they will be exported via the flake output =overlays= as
well.