Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
84 changes: 61 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,85 @@
# dotfiles

My personal NixOS configurations designed with focus on usability, aesthetics and productivity :)
My personal nix configurations designed with focus on usability, aesthetics and productivity :) \
Includes configurations for desktop NixOS, server NixOS, nix-darwin, and home-manager following the [dendritic pattern](https://discourse.nixos.org/t/the-dendritic-pattern/61271) using [flake-parts](https://github.com/hercules-ci/flake-parts) + [import-tree](https://github.com/vic/import-tree).

## Install instructions
## Architecture

To get these configurations running, first set up a NixOS system with a user account. \
Then copy your age key to `~/.config/sops/age/keys.txt`. This is needed in order to decrypt the secrets which are used in the system and the home configuration. \
Now we can start actually installing the configurations. Go into a shell with `git` installed:
`import-tree` auto-imports every `.nix` file under `components/` into the flake. No manual registration needed when adding new modules.\
Modules are namespaced by flake-parts module class and accessed via `self.modules.<class>.<name>`:

| Class | Used for |
|-------|---------|
| `nixos` | NixOS system modules |
| `homeManager` | Home Manager modules |
| `darwin` | nix-darwin system modules |
| `generic` | host-specific configs (usable in any namespace) |
| `system` | cross-platform modules for the use in NixOS and Darwin |

### `resolveSystemModules`

`system`-class modules can't be passed directly to `nixosSystem`/`darwinSystem` (wrong `_class`).\
`self.lib.resolveSystemModules` maps over a module list and converts `system` → target class

### pkgs via `perSystem` / `withSystem`

`nixpkgs` is instantiated once in `perSystem` (with overlays, `allowUnfree`, etc.). The hosts consume the appropriate pkgs set via `withSystem` in their system and home-manager configs — ensuring consistent `nixpkgs` across multiple hosts.

### Hosts

Each host lives in `components/hosts/<hostname>/` and consists of:

| File | Purpose |
|------|---------|
| `_settings-base.nix` | Pure attrset for top-level settings |
| `settings.nix` | Flake module: exposes `nixos.host<Name>SystemConfig` + `generic.host<Name>UserConfig` |
| `default.nix` | Wires `nixosConfigurations` / `homeConfigurations` together |
| `_hardware-configuration.nix` | Machine-specific hardware config |
| `extra-config.nix` | Optional host-specific overrides |

## Secrets

Secrets are managed with [sops-nix](https://github.com/Mic92/sops-nix). The AGE key must be present at `~/.config/sops/age/keys.txt` before activating any configuration that uses secrets.

## Installation

**1. Bootstrap NixOS and clone:**
```bash
nix-shell -p git
git clone https://github.com/leon-erd/dotfiles.git ~/dotfiles
cd ~/dotfiles
```

Then clone the repo:
**2. Copy AGE key** (needed for sops-nix secrets):
```bash
git clone https://github.com/leon-erd/dotfiles.git ~/dotfiles
mkdir -p ~/.config/sops/age
cp /path/to/keys.txt ~/.config/sops/age/keys.txt
```

To get the hardware configuration on a new system, either copy from `/etc/nixos/hardware-configuration.nix` or run:
**3. Generate hardware config** (if new machine):
```bash
cd ~/dotfiles
sudo nixos-generate-config --show-hardware-config > hosts/<host>/hardware-configuration.nix
sudo nixos-generate-config --show-hardware-config \
> components/hosts/<host>/_hardware-configuration.nix
```

Make sure to update the `systemSettings` and `userSettings` in `hosts/<host>/flakeConfiguration.nix` to your needs:
```nix
...
let
systemSettings = {
hostname = "leon-inspiron";
timezone = "Europe/Vienna";
defaultLocale = "en_US.UTF-8";
...
```

Once the variables are set, switch into the system configuration by running:
**4. Build system configuration:**
```bash
cd ~/dotfiles
sudo nixos-rebuild switch --flake ./#<systemConfigurationName>
```
where `systemConfigurationName` corresponds to the value set in `hosts/<host>/flakeConfiguration.nix`.

The home-manager configuration can be installed with (might need to logout/login once before):
**5. Build home configuration** (might need logout/login once):
```bash
cd ~/dotfiles
home-manager switch --flake ./#<userConfigurationName>
```

## Raspberry Pi

The raspberrypi has its own `flake.nix` + `flake.lock` for independent `nixpkgs` update cycles (server stability). Build from its subdirectory:
```bash
cd components/hosts/raspberrypi
sudo nixos-rebuild switch --flake .#raspberrypi
home-manager switch --flake .#leon@raspberrypi
```
192 changes: 192 additions & 0 deletions components/config-options.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
{ ... }:

{
flake.modules.generic.configSystemOptions =
{ lib, ... }:

let
inherit (lib.types)
listOf
str
submodule
;
inherit (lib.options) mkOption;
in
{
options.mySystemConfig = {
hostname = mkOption {
type = str;
description = "Hostname, unique identifier for building the flake";
example = "inspiron-laptop";
};
timezone = mkOption {
type = str;
default = "Europe/Vienna";
};
defaultLocale = mkOption {
type = str;
default = "en_US.UTF-8";
};
extraLocale = mkOption {
type = str;
default = "de_AT.UTF-8";
description = "Extra locale (for measurement, numeric, time, …)";
};
kblayout = mkOption {
type = str;
default = "de";
description = "Keyboard layout";
};
localIp = mkOption {
type = str;
description = "Local IP address of the machine";
example = "192.168.179.200";
};
acmeEmail = mkOption {
type = str;
description = "Email address for ACME/Let's Encrypt certificates";
};
nextcloud = {
drives = {
main = mkOption {
type = str;
description = "udev disk ID for the main Nextcloud drive";
example = "usb-TOSHIBA_External_USB_3.0_20200714006512F-0:0-part1";
};
backup = mkOption {
type = str;
description = "udev disk ID for the Nextcloud backup drive";
example = "usb-Intenso_External_USB_3.0_20161230160B8-0:0-part1";
};
};
hostName = mkOption {
type = str;
description = "Public hostname for the Nextcloud instance";
example = "cloud.example.com";
};
trustedDomains = mkOption {
type = listOf str;
description = "Additional trusted domains for Nextcloud";
example = [ "192.168.179.200" ];
};
};
pihole = {
hosts = mkOption {
type = listOf str;
default = [ ];
description = "Extra host entries for Pi-hole";
example = [ "192.168.179.200 raspberry.pi" ];
};
};
wireguard = {
externalInterface = mkOption {
type = str;
description = "Network interface facing the internet (use `ip a`)";
example = "enu1u1u1";
};
clientPeers = mkOption {
type = listOf (submodule {
options = {
name = mkOption { type = str; };
publicKey = mkOption { type = str; };
allowedIPs = mkOption { type = listOf str; };
};
});
default = [ ];
description = "WireGuard client peers";
example = [
{
name = "laptop";
publicKey = "dLHb13EIwUM1HJoEPojOskp18c87Ciu/ZYUZmIkQMBA=";
allowedIPs = [ "10.100.0.2/32" ];
}
];
};
};
};
};

flake.modules.generic.configUserOptions =
{ lib, config, ... }:

let
inherit (lib.types)
listOf
path
str
submodule
;
inherit (lib.options) mkOption;

user = submodule {
options = {
username = mkOption {
type = str;
};
systemConfigurationName = mkOption {
type = str;
description = "Name of the NixOS configuration this user belongs to";
};
userConfigurationName = mkOption {
type = str;
description = "Key used in homeConfigurations, typically username@systemConfigurationName";
default = "${config.username}@${config.systemConfigurationName}";
defaultText = lib.literalExpression ''"''${config.username}@''${config.systemConfigurationName}"'';
};
name = mkOption {
type = str;
description = "Display name, used for e.g. git";
};
email = mkOption {
type = str;
description = "Email address, used for e.g. git";
};
extraGroups = mkOption {
type = listOf str;
default = [
"networkmanager"
"wheel"
"video"
"libvirtd"
];
};
kblayout = mkOption {
type = str;
default = "de";
description = "Keyboard layout";
};
flakeDirectory = mkOption {
type = str;
description = "Absolute path to the dotfiles flake on the machine";
example = "/home/leon/dotfiles";
};
wallpaperFolder = mkOption {
type = str;
description = "Absolute path to the wallpaper folder";
example = "/home/leon/Nextcloud/Pictures";
};
wireguardConfig = mkOption {
type = path;
description = "Path to the WireGuard client config file";
example = lib.literalExpression "../secrets/files/wireguard_clients/my-wireguard.conf";
};
};
};
in
{
options.myUsers = mkOption {
type = listOf user;
description = "List of users";
};
};

flake.modules.homeManager.configCurrentUserOptions =
{ config, lib, ... }:
{
options.myUserConfig = lib.mkOption {
type = lib.types.unspecified;
description = "The user config of the current user, automatically set by the home manager configuration";
};
config.myUserConfig = lib.mkDefault (lib.head config.myUsers);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@
{ device = "/dev/disk/by-uuid/2d14d1e5-3db7-402c-a272-9a2d2e380106"; }
];

nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
# nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; # nixpkgs.hostPlatform is derived from pkgs by readOnlyPkgs
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}
8 changes: 8 additions & 0 deletions components/hosts/barbara-laptop/_settings-base.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
rec {
system = "x86_64-linux"; # system arch (see hardware-configuration.nix -> nixpkgs.hostPlatform);
hostname = "mamas-laptop";
systemConfigurationName = hostname;

username = "barbara";
userConfigurationName = "${username}@${systemConfigurationName}";
}
Loading
Loading