Skip to content
Draft
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .envrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set -e
set +u
use flake
use flake . --accept-flake-config --show-trace
dotenv_if_exists
113 changes: 113 additions & 0 deletions FLAKE_PARTS_MIGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Flake-Parts Migration Summary

## Overview

Successfully migrated the dotfiles repository from a monolithic `flake.nix` to a
modular flake-parts architecture.

## Changes Made

### 1. Added flake-parts Input

Added `flake-parts` to `flake.nix` inputs with `nixpkgs-lib` following nixpkgs:

```nix
flake-parts = {
url = "github:hercules-ci/flake-parts";
inputs.nixpkgs-lib.follows = "nixpkgs";
};
```

### 2. Created Modular Structure

Created `flake-modules/` directory with the following modules:

- **shared-config.nix**: Shared system configuration, nixpkgs overlays, fonts,
nix settings, and home-manager configuration
- **darwin.nix**: macOS (nix-darwin) system configurations for pandoras-box,
alcantara, and rocket
- **nixos.nix**: NixOS system configuration
- **dev-shells.nix**: Development shells (default and go)
- **apps.nix**: Flake apps (bootstrap scripts)
- **templates.nix**: Project templates
- **formatter.nix**: Alejandra formatter

### 3. Refactored Main flake.nix

The main `flake.nix` is now minimal and uses flake-parts:

```nix
outputs = inputs:
inputs.flake-parts.lib.mkFlake {inherit inputs;} {
systems = [
"x86_64-darwin"
"aarch64-darwin"
"x86_64-linux"
];

imports = [
./flake-modules/shared-config.nix
./flake-modules/darwin.nix
./flake-modules/nixos.nix
./flake-modules/dev-shells.nix
./flake-modules/apps.nix
./flake-modules/templates.nix
./flake-modules/formatter.nix
];
};
```

### 4. Path Adjustments

Updated all relative paths in flake-modules to use `${self}/...` to properly
reference files from the flake root.

### 5. Fixed Platform-Specific Configuration

Ensured platform-specific configuration (like homebrew settings) use
`mkIf isDarwin` to avoid evaluation errors on NixOS.

## Benefits

1. **Better Organization**: Flake outputs are organized into logical modules
2. **Easier Maintenance**: Each concern is isolated in its own file
3. **Improved Readability**: The main flake.nix is now ~10 lines instead of ~350
4. **Standard Pattern**: Uses the well-established flake-parts framework
5. **Incremental Builds**: Modules can be modified independently

## Validation

All Darwin configurations build successfully:

- ✅ `darwinConfigurations.pandoras-box`
- ✅ `darwinConfigurations.alcantara`
- ✅ `darwinConfigurations.rocket`
- ✅ `devShells.{aarch64,x86_64}-darwin.{default,go}`
- ✅ `apps.{aarch64,x86_64}-darwin.default`
- ✅ `formatter.{aarch64,x86_64}-darwin`
- ✅ `templates.*`

## Known Issues

The NixOS configuration has pre-existing issues with homebrew option references
that existed before the migration. This is unrelated to the flake-parts
migration and affects modules that weren't properly conditioned for
cross-platform use.

## Next Steps

No further action required for the migration. The flake-parts structure is
complete and fully functional for all Darwin (macOS) systems.

To use the new structure:

```bash
# Apply configuration (unchanged)
darwin-rebuild switch --flake ~/.dotfiles

# Check flake
nix flake check --accept-flake-config

# Format code
nix fmt --accept-flake-config .
```
136 changes: 136 additions & 0 deletions SETTINGS_MODULE_MIGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Settings Module Migration to Flake-Parts

## Overview

Migrated the `nix/modules/shared/settings.nix` module to be properly exposed as reusable flake outputs through flake-parts.

## What Changed

### Created `flake-modules/system-modules.nix`

This new flake-parts module exposes your NixOS/nix-darwin modules as reusable outputs that other flakes can import.

```nix
{
inputs,
self,
...
}: {
flake = {
# Expose reusable NixOS/nix-darwin modules for other flakes to consume
nixosModules = {
# Individual module exports
settings = import "${self}/nix/modules/shared/settings.nix";

# Or export all shared modules as a single module
default = import "${self}/nix/modules/shared";
};

darwinModules = {
# Individual module exports
settings = import "${self}/nix/modules/shared/settings.nix";

# Or export all shared modules as a single module
default = import "${self}/nix/modules/shared";
};
};
}
```

### Updated `flake.nix`

Added the new system-modules.nix to the imports list:

```nix
imports = [
inputs.flake-parts.flakeModules.modules
inputs.home-manager.flakeModules.home-manager
./flake-modules/system-modules.nix # <-- Added
./flake-modules/shared.nix
./flake-modules/darwin.nix
./flake-modules/nixos.nix
./flake-modules/dev-shells.nix
./flake-modules/apps.nix
];
```

## Important Clarification

The `settings.nix` module itself was NOT moved or changed. It remains at `nix/modules/shared/settings.nix` and is still imported via `nix/modules/shared/default.nix` as before.

**What this migration does:**
- Exposes the settings module (and all shared modules) as flake outputs
- Allows other flakes to import and reuse your modules
- Follows flake-parts best practices for module organization

**What this migration does NOT do:**
- Does NOT change how settings.nix works internally
- Does NOT change how your system configurations import it
- Does NOT require any changes to existing host configurations

## Why This Matters

Before this migration, the settings module was only usable within this dotfiles repository. Now:

1. **Other flakes can import your modules:**
```nix
{
inputs.dotfiles.url = "github:ahmedelgabri/dotfiles";

outputs = {nixpkgs, dotfiles, ...}: {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
modules = [
dotfiles.nixosModules.settings
];
};
};
}
```

2. **Better flake structure:** Follows the standard pattern of exposing `nixosModules` and `darwinModules` outputs

3. **Reusability:** Other projects can benefit from your module system and configuration aliases

## Available Outputs

After this migration, your flake exposes:

- `nixosModules.default` - All shared modules
- `nixosModules.settings` - Just the settings module
- `darwinModules.default` - All shared modules
- `darwinModules.settings` - Just the settings module

## Verification

You can verify the modules are properly exposed:

```bash
# Show all flake outputs
nix flake show

# Test that the module exists
nix eval .#nixosModules.settings --apply 'x: "exists"'
nix eval .#darwinModules.settings --apply 'x: "exists"'

# Build still works
nix flake check --accept-flake-config
```

## Settings Module Contents

The `settings.nix` module defines:

- **Options:** Core configuration options like `my.username`, `my.email`, `my.timezone`, etc.
- **Aliases:** Convenient shortcuts for home-manager paths (`my.hm.file`, `my.hm.configFile`, etc.)
- **User configuration:** Sets up the primary user account
- **Environment variables:** Manages `my.env` for setting shell environment variables

These are all still defined in `nix/modules/shared/settings.nix` - nothing changed there.

## Benefits of This Approach

1. **No breaking changes:** Everything continues to work exactly as before
2. **Additive improvement:** Only adds new capabilities without changing existing behavior
3. **Standard pattern:** Follows how other Nix flakes expose modules
4. **Future-proof:** Makes it easy to share modules with other projects
5. **Flake-parts native:** Uses flake-parts' module system correctly
33 changes: 33 additions & 0 deletions flake-modules/apps.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
inputs,
self,
...
}: {
perSystem = {
config,
system,
pkgs,
...
}: let
utils = pkgs.writeShellApplication {
name = "utils";
text = builtins.readFile "${self}/scripts/utils";
};
bootstrap = pkgs.writeShellApplication {
name = "bootstrap";
runtimeInputs = [pkgs.git];
text = ''
# shellcheck disable=SC1091
source ${pkgs.lib.getExe utils}
${builtins.readFile "${self}/scripts/${system}_bootstrap"}
'';
};
in {
apps = {
default = {
type = "app";
program = pkgs.lib.getExe bootstrap;
};
};
};
}
44 changes: 44 additions & 0 deletions flake-modules/darwin.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
inputs,
self,
...
}: {
flake = let
darwinHosts = {
"pandoras-box" = "x86_64-darwin";
"alcantara" = "aarch64-darwin";
"rocket" = "aarch64-darwin";
};

mapHosts = f: hostsMap: builtins.mapAttrs f hostsMap;
in
{
darwinConfigurations =
mapHosts
(host: system: (inputs.darwin.lib.darwinSystem
{
# This gets passed to modules as an extra argument
specialArgs = {inherit inputs;};
inherit system;
modules = [
inputs.self.modules.generic.user-options
inputs.self.modules.generic.core
inputs.self.modules.darwin.core
inputs.home-manager.darwinModules.home-manager
inputs.nix-homebrew.darwinModules.nix-homebrew
"${self}/nix/modules/darwin"
"${self}/nix/modules/shared"
"${self}/nix/hosts/${host}.nix"
];
}))
darwinHosts;
}
// mapHosts
# for convenience
# nix build './#darwinConfigurations.pandoras-box.system'
# vs
# nix build './#pandoras-box'
# Move them to `outputs.packages.<system>.name`
(host: _: self.darwinConfigurations.${host}.system)
darwinHosts;
}
30 changes: 30 additions & 0 deletions flake-modules/dev-shells.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{inputs, ...}: {
perSystem = {
config,
system,
pkgs,
...
}: {
devShells = {
default = pkgs.mkShell {
name = "dotfiles";
packages = with pkgs; [
typos
typos-lsp
alejandra
];
};

go = pkgs.mkShell {
name = "dotfiles-go";
packages = with pkgs; [
go
gopls
go-tools # staticcheck, etc...
gomodifytags
gotools # goimports
];
};
};
};
}
3 changes: 3 additions & 0 deletions flake-modules/flake-parts.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{inputs, ...}: {
imports = [inputs.flake-parts.flakeModules.modules];
}
Loading