5.6 KiB
Adding Modules Guide
How to add new NixOS and Home Manager modules to m3ta-nixpkgs.
Overview
Modules extend your system or user configuration with reusable, declarative options. m3ta-nixpkgs uses the standard NixOS module system with a m3ta.* namespace.
Quick Start
Use a template for quick setup:
# NixOS module
nix flake init -t .#nixos-module my-module
# Home Manager module
nix flake init -t .#home-manager-module my-module
This copies the template into templates/ — move it to the appropriate location and customize.
Adding a NixOS Module
1. Create the Module File
Create modules/nixos/<my-module>.nix:
{config, lib, pkgs, ...}:
with lib; let
cfg = config.m3ta.myModule;
in {
options.m3ta.myModule = {
enable = mkEnableOption "my module description";
# Add custom options here
someOption = mkOption {
type = types.str;
default = "default-value";
description = "Description of this option";
};
};
config = mkIf cfg.enable {
# System configuration goes here
environment.systemPackages = [pkgs.some-package];
# Or systemd services
systemd.services.my-service = {
enable = true;
description = "My service";
wantedBy = ["multi-user.target"];
serviceConfig = {
ExecStart = "${pkgs.some-package}/bin/some-daemon";
};
};
};
}
2. Register in the Aggregator
Add to modules/nixos/default.nix:
{
imports = [
./ports.nix
./mem0.nix
./<my-module>.nix # ← add your module
];
}
3. Export from flake.nix
Add to the nixosModules output in flake.nix (optional, for direct import):
nixosModules = {
default = ./modules/nixos;
ports = ./modules/nixos/ports.nix;
mem0 = ./modules/nixos/mem0.nix;
my-module = ./modules/nixos/<my-module>.nix; # ← add this
};
Adding a Home Manager Module
Home Manager modules are organized by category under modules/home-manager/.
Categories
| Category | Purpose | Location |
|---|---|---|
cli/ |
Command-line tools and utilities | modules/home-manager/cli/ |
coding/ |
Development tools, editors, agents | modules/home-manager/coding/ |
| Root | Cross-cutting concerns (e.g., ports) | modules/home-manager/ |
1. Choose a Category
- CLI tools (zsh plugins, tmux config, etc.) →
cli/ - Development tools (editor config, linters, etc.) →
coding/ - System-wide settings (ports, environment) → root level
2. Create the Module File
Create modules/home-manager/<category>/<my-module>.nix:
{config, lib, pkgs, ...}:
with lib; let
cfg = config.m3ta.myModule;
in {
options.m3ta.myModule = {
enable = mkEnableOption "my user module description";
someOption = mkOption {
type = types.str;
default = "value";
description = "An option for this module";
};
};
config = mkIf cfg.enable {
home.packages = [pkgs.some-package];
# Or Home Manager-specific options
programs.zsh.enable = true;
};
}
3. Register in the Category Aggregator
For cli/ modules, add to modules/home-manager/cli/default.nix:
{
imports = [
./rofi-project-opener.nix
./stt-ptt.nix
./zellij-ps.nix
./<my-module>.nix # ← add your module
];
}
For coding/ modules, add to modules/home-manager/coding/default.nix:
{
imports = [
./editors.nix
./opencode.nix
./agents
./<my-module>.nix # ← add your module
];
}
4. Export from flake.nix
Add to homeManagerModules in flake.nix:
homeManagerModules = {
default = import ./modules/home-manager;
my-module = import ./modules/home-manager/<category>/<my-module>.nix; # ← add this
};
Module Patterns
Standard Enable Option
Always start with mkEnableOption:
options.m3ta.myModule = {
enable = mkEnableOption "my module";
};
Conditional Configuration
Use mkIf for conditional config:
config = mkIf cfg.enable {
# Only applied when enabled
};
Multiple Conditions
Use mkMerge when combining multiple conditional blocks:
config = mkMerge [
(mkIf cfg.feature1.enable { ... })
(mkIf cfg.feature2.enable { ... })
];
Nested Namespaces
For logically grouped options, use nested namespaces:
options.m3ta.coding = {
myTool = {
enable = mkEnableOption "my coding tool";
# ...
};
};
Usage: m3ta.coding.myTool.enable = true;
Shared Library Functions
For shared utilities (port helpers, etc.), import from lib/:
let
portsLib = import ../../lib/ports.nix {inherit lib;};
portHelpers = portsLib.mkPortHelpers { /* ... */ };
in {
# use portHelpers
}
Documentation
Add documentation for your module:
- Create
docs/modules/nixos/<my-module>.md(NixOS) ordocs/modules/home-manager/<category>/<my-module>.md(HM) - Follow the existing format in
docs/modules/ - Add it to the appropriate overview page's "Available Modules" list
- Link it from
docs/guides/using-modules.md
Testing
# Validate the module loads correctly
nix flake check
# Test with a minimal configuration (NixOS)
nixos-rebuild dry-build -I nixpkgs=. --option experimental-features flakes
# Format before commit
nix fmt
Related
- Using Modules - How to use existing modules
- Port Management - Centralized port management
- Development Workflow - Local development
- Adding Packages - Adding packages (not modules)
- Architecture - Repository structure