2026-05-02 10:54:33 +02:00
# m3ta-home — Portable User Profiles for NixOS
feat: initial m3ta-home structure
- flake.nix with nixpkgs, home-manager, nix-colors, m3ta-nixpkgs, agenix, NUR inputs
- lib/mkHome.nix: compose HM config from user + identity + context + sets
- profiles/base: shell, cli-tools, secrets (always loaded)
- profiles/contexts/desktop: WM, apps, theme, ghostty
- profiles/contexts/server: minimal headless
- profiles/sets/coding: core (git, direnv, jq, rg), editor, lsp, languages, agents
- profiles/sets/gaming: steam, gamescope, gpu
- profiles/sets/media: obs, ffmpeg, kdenlive, handbrake, yt-dlp
- users/m3tam3re/identities: private.nix, work.nix (git, jj, ssh per identity)
- users/m3tam3re/preferences: cliphist, difftastic, base packages
2026-05-02 09:08:40 +02:00
2026-05-02 10:54:33 +02:00
Centralized, portable Home-Manager configurations. Manages user identities, preferences, feature sets, and assets across multiple NixOS hosts — from desktops and laptops to headless servers.
feat: initial m3ta-home structure
- flake.nix with nixpkgs, home-manager, nix-colors, m3ta-nixpkgs, agenix, NUR inputs
- lib/mkHome.nix: compose HM config from user + identity + context + sets
- profiles/base: shell, cli-tools, secrets (always loaded)
- profiles/contexts/desktop: WM, apps, theme, ghostty
- profiles/contexts/server: minimal headless
- profiles/sets/coding: core (git, direnv, jq, rg), editor, lsp, languages, agents
- profiles/sets/gaming: steam, gamescope, gpu
- profiles/sets/media: obs, ffmpeg, kdenlive, handbrake, yt-dlp
- users/m3tam3re/identities: private.nix, work.nix (git, jj, ssh per identity)
- users/m3tam3re/preferences: cliphist, difftastic, base packages
2026-05-02 09:08:40 +02:00
2026-05-02 10:54:33 +02:00
One repo, all your machines. Change once, deploy everywhere.
## Architecture
feat: initial m3ta-home structure
- flake.nix with nixpkgs, home-manager, nix-colors, m3ta-nixpkgs, agenix, NUR inputs
- lib/mkHome.nix: compose HM config from user + identity + context + sets
- profiles/base: shell, cli-tools, secrets (always loaded)
- profiles/contexts/desktop: WM, apps, theme, ghostty
- profiles/contexts/server: minimal headless
- profiles/sets/coding: core (git, direnv, jq, rg), editor, lsp, languages, agents
- profiles/sets/gaming: steam, gamescope, gpu
- profiles/sets/media: obs, ffmpeg, kdenlive, handbrake, yt-dlp
- users/m3tam3re/identities: private.nix, work.nix (git, jj, ssh per identity)
- users/m3tam3re/preferences: cliphist, difftastic, base packages
2026-05-02 09:08:40 +02:00
```
m3ta-home/
2026-05-02 10:54:33 +02:00
├── flake.nix ← Entry point: inputs, lib, homeManagerModules
├── lib/
│ ├── default.nix ← Re-exports mkHome
│ └── mkHome.nix ← Composition engine (WHO + WHERE + WHAT)
├── modules/
│ ├── default.nix ← Module aggregation for flake export
│ └── paths.nix ← "m3ta-home".paths.srcRoot (pure eval compatibility)
├── profiles/
│ ├── base/ ← Always loaded: shell, CLI tools, secrets, nix settings
│ ├── contexts/
│ │ ├── desktop/ ← GUI host: WM, apps, theme, terminal, XDG
│ │ └── server/ ← Headless: minimal
│ └── sets/ ← Optional feature bundles
│ ├── coding/ ← core, editors, languages, LSP, agents
│ ├── gaming/ ← Steam, Gamescope, GPU tools
│ └── media/ ← OBS, ffmpeg, kdenlive, yt-dlp
├── users/
│ └── m3tam3re/
│ ├── identities/
│ │ ├── private.nix ← Personal: git (m3tm3re), SSH, JJ
│ │ └── work.nix ← Work: git (sascha.koenig), SSH, JJ
│ └── preferences/ ← Identity-independent: cliphist, difftastic
└── assets/
└── wallpapers/ ← Wallpaper collection (referenced via srcRoot)
feat: initial m3ta-home structure
- flake.nix with nixpkgs, home-manager, nix-colors, m3ta-nixpkgs, agenix, NUR inputs
- lib/mkHome.nix: compose HM config from user + identity + context + sets
- profiles/base: shell, cli-tools, secrets (always loaded)
- profiles/contexts/desktop: WM, apps, theme, ghostty
- profiles/contexts/server: minimal headless
- profiles/sets/coding: core (git, direnv, jq, rg), editor, lsp, languages, agents
- profiles/sets/gaming: steam, gamescope, gpu
- profiles/sets/media: obs, ffmpeg, kdenlive, handbrake, yt-dlp
- users/m3tam3re/identities: private.nix, work.nix (git, jj, ssh per identity)
- users/m3tam3re/preferences: cliphist, difftastic, base packages
2026-05-02 09:08:40 +02:00
```
2026-05-02 10:54:33 +02:00
## The Three Dimensions
`mkHome` composes a complete Home-Manager configuration from three axes:
| Dimension | Options | Description |
|-----------|---------|-------------|
| **WHO ** | `user` + `identity` | Which user, which identity (private/work) |
| **WHERE ** | `context` | `desktop` or `server` — mutually exclusive |
| **WHAT ** | `sets` | `coding` , `gaming` , `media` — freely combinable |
```nix
mkHome {
user = "m3tam3re";
identity = "private"; # ← "private" or "work"
context = "desktop"; # ← "desktop" or "server"
sets = ["coding" "gaming" "media"];
}
```
### How it Works
1. **Base ** is always imported (shell, CLI tools, nix settings, nix-colors/dracula theme)
2. **Context ** is loaded based on `context` — exactly one of `desktop` or `server`
3. **Sets ** are loaded on top — any combination of `coding` , `gaming` , `media`
4. **Identity ** overrides git username/email, SSH match blocks, and Jujutsu config
5. **Feature flags ** in the consuming host selectively enable/disable individual modules
### Assertions
- `gaming` and `media` sets require `desktop` context (enforced via Nix assertions)
- `coding` works in both `desktop` and `server` contexts
## Usage
### In nixos-config (flake.nix)
feat: initial m3ta-home structure
- flake.nix with nixpkgs, home-manager, nix-colors, m3ta-nixpkgs, agenix, NUR inputs
- lib/mkHome.nix: compose HM config from user + identity + context + sets
- profiles/base: shell, cli-tools, secrets (always loaded)
- profiles/contexts/desktop: WM, apps, theme, ghostty
- profiles/contexts/server: minimal headless
- profiles/sets/coding: core (git, direnv, jq, rg), editor, lsp, languages, agents
- profiles/sets/gaming: steam, gamescope, gpu
- profiles/sets/media: obs, ffmpeg, kdenlive, handbrake, yt-dlp
- users/m3tam3re/identities: private.nix, work.nix (git, jj, ssh per identity)
- users/m3tam3re/preferences: cliphist, difftastic, base packages
2026-05-02 09:08:40 +02:00
```nix
inputs.m3ta-home = {
2026-05-02 10:54:33 +02:00
url = "git+ssh://gitea@code .m3ta.dev/m3tam3re/m3ta-home";
feat: initial m3ta-home structure
- flake.nix with nixpkgs, home-manager, nix-colors, m3ta-nixpkgs, agenix, NUR inputs
- lib/mkHome.nix: compose HM config from user + identity + context + sets
- profiles/base: shell, cli-tools, secrets (always loaded)
- profiles/contexts/desktop: WM, apps, theme, ghostty
- profiles/contexts/server: minimal headless
- profiles/sets/coding: core (git, direnv, jq, rg), editor, lsp, languages, agents
- profiles/sets/gaming: steam, gamescope, gpu
- profiles/sets/media: obs, ffmpeg, kdenlive, handbrake, yt-dlp
- users/m3tam3re/identities: private.nix, work.nix (git, jj, ssh per identity)
- users/m3tam3re/preferences: cliphist, difftastic, base packages
2026-05-02 09:08:40 +02:00
inputs.nixpkgs.follows = "nixpkgs";
};
```
2026-05-02 10:54:33 +02:00
### Per-Host Configuration
The consuming repo (`nixos-config` ) maps hosts to profiles:
feat: initial m3ta-home structure
- flake.nix with nixpkgs, home-manager, nix-colors, m3ta-nixpkgs, agenix, NUR inputs
- lib/mkHome.nix: compose HM config from user + identity + context + sets
- profiles/base: shell, cli-tools, secrets (always loaded)
- profiles/contexts/desktop: WM, apps, theme, ghostty
- profiles/contexts/server: minimal headless
- profiles/sets/coding: core (git, direnv, jq, rg), editor, lsp, languages, agents
- profiles/sets/gaming: steam, gamescope, gpu
- profiles/sets/media: obs, ffmpeg, kdenlive, handbrake, yt-dlp
- users/m3tam3re/identities: private.nix, work.nix (git, jj, ssh per identity)
- users/m3tam3re/preferences: cliphist, difftastic, base packages
2026-05-02 09:08:40 +02:00
```nix
# hosts/common/users/m3tam3re.nix
2026-05-02 10:54:33 +02:00
hostProfiles = {
m3-kratos = { context = "desktop"; sets = ["coding" "gaming" "media"]; };
m3-atlas = { context = "server"; sets = ["coding"]; };
m3-helios = { context = "server"; sets = []; };
};
```
Then enables specific feature flags per host:
```nix
feat: initial m3ta-home structure
- flake.nix with nixpkgs, home-manager, nix-colors, m3ta-nixpkgs, agenix, NUR inputs
- lib/mkHome.nix: compose HM config from user + identity + context + sets
- profiles/base: shell, cli-tools, secrets (always loaded)
- profiles/contexts/desktop: WM, apps, theme, ghostty
- profiles/contexts/server: minimal headless
- profiles/sets/coding: core (git, direnv, jq, rg), editor, lsp, languages, agents
- profiles/sets/gaming: steam, gamescope, gpu
- profiles/sets/media: obs, ffmpeg, kdenlive, handbrake, yt-dlp
- users/m3tam3re/identities: private.nix, work.nix (git, jj, ssh per identity)
- users/m3tam3re/preferences: cliphist, difftastic, base packages
2026-05-02 09:08:40 +02:00
home-manager.users.m3tam3re = {
imports = [
2026-05-02 10:54:33 +02:00
(m3ta-lib.mkHome {
feat: initial m3ta-home structure
- flake.nix with nixpkgs, home-manager, nix-colors, m3ta-nixpkgs, agenix, NUR inputs
- lib/mkHome.nix: compose HM config from user + identity + context + sets
- profiles/base: shell, cli-tools, secrets (always loaded)
- profiles/contexts/desktop: WM, apps, theme, ghostty
- profiles/contexts/server: minimal headless
- profiles/sets/coding: core (git, direnv, jq, rg), editor, lsp, languages, agents
- profiles/sets/gaming: steam, gamescope, gpu
- profiles/sets/media: obs, ffmpeg, kdenlive, handbrake, yt-dlp
- users/m3tam3re/identities: private.nix, work.nix (git, jj, ssh per identity)
- users/m3tam3re/preferences: cliphist, difftastic, base packages
2026-05-02 09:08:40 +02:00
user = "m3tam3re";
identity = "private";
2026-05-02 10:54:33 +02:00
inherit (profile) context sets;
feat: initial m3ta-home structure
- flake.nix with nixpkgs, home-manager, nix-colors, m3ta-nixpkgs, agenix, NUR inputs
- lib/mkHome.nix: compose HM config from user + identity + context + sets
- profiles/base: shell, cli-tools, secrets (always loaded)
- profiles/contexts/desktop: WM, apps, theme, ghostty
- profiles/contexts/server: minimal headless
- profiles/sets/coding: core (git, direnv, jq, rg), editor, lsp, languages, agents
- profiles/sets/gaming: steam, gamescope, gpu
- profiles/sets/media: obs, ffmpeg, kdenlive, handbrake, yt-dlp
- users/m3tam3re/identities: private.nix, work.nix (git, jj, ssh per identity)
- users/m3tam3re/preferences: cliphist, difftastic, base packages
2026-05-02 09:08:40 +02:00
})
2026-05-02 10:54:33 +02:00
hostFlags # ← per-host enable/disable of individual modules
feat: initial m3ta-home structure
- flake.nix with nixpkgs, home-manager, nix-colors, m3ta-nixpkgs, agenix, NUR inputs
- lib/mkHome.nix: compose HM config from user + identity + context + sets
- profiles/base: shell, cli-tools, secrets (always loaded)
- profiles/contexts/desktop: WM, apps, theme, ghostty
- profiles/contexts/server: minimal headless
- profiles/sets/coding: core (git, direnv, jq, rg), editor, lsp, languages, agents
- profiles/sets/gaming: steam, gamescope, gpu
- profiles/sets/media: obs, ffmpeg, kdenlive, handbrake, yt-dlp
- users/m3tam3re/identities: private.nix, work.nix (git, jj, ssh per identity)
- users/m3tam3re/preferences: cliphist, difftastic, base packages
2026-05-02 09:08:40 +02:00
];
};
```
2026-05-02 10:54:33 +02:00
### Host-Specific Overrides
Monitor layouts, window rules, and XDG/MIME settings stay in `nixos-config` :
- `hosts/m3-kratos/home.nix` — dual DP monitors, Hyprland workspaces
- `hosts/m3-ares/home.nix` — laptop eDP + HDMI, tuxedo-backlight
- Server hosts need no `home.nix` (no desktop config)
## Identity System: Private vs. Work
The identity system allows switching between personal and work contexts on any machine — same dotfiles, different git identity, SSH config, and Jujutsu settings.
### How Identities Work
| | **Private ** | **Work ** |
|---|---|---|
| **Git user ** | m3tm3re | sascha.koenig |
| **Git email ** | p@m3ta .dev | sascha.koenig@azintec .com |
| **JJ email ** | m@m3tam3re .com | sascha.koenig@azintec .com |
| **SSH hosts ** | code.m3ta.dev, github.com, private infra | git.az-gruppe.com, AZ servers |
### Use Case: Work Laptop
If you bring a work NixOS machine into your fleet, you can use the same `m3ta-home` repo with a different identity:
```nix
# On the work machine's nixos-config:
(m3ta-lib.mkHome {
user = "m3tam3re";
identity = "work"; # ← switches git, SSH, JJ to work profile
context = "desktop";
sets = ["coding"];
})
```
This gives you:
- Your familiar shell setup (fish, starship, nushell)
- Your CLI tools (fzf, bat, eza, zoxide, etc.)
- Your editor configs (neovim, zed)
- Work git identity and SSH configuration automatically
- No gaming, media, or personal apps
### Adding a New Identity
1. Create `users/<username>/identities/<identity>.nix`
2. Define git, SSH, and JJ settings for that identity
3. Reference it via `identity = "<identity>"` in mkHome
## Feature Flags
Every module in m3ta-home has an `enable` option. Base modules default to `true` , everything else defaults to `false` . Flags are set per-host in the consuming repo.
### Available Flags
```
base.shell.fish.enable # Fish shell
base.shell.nushell.enable # Nushell
base.shell.starship.enable # Starship prompt
base.cliTools.fzf.enable # Fuzzy finder
base.cliTools.bat.enable # Cat replacement
base.cliTools.eza.enable # Ls replacement
base.cliTools.zellij.enable # Terminal multiplexer
base.cliTools.zoxide.enable # Smarter cd
base.cliTools.direnv.enable # Directory-based env
base.cliTools.television.enable # TV fuzzy finder
base.cliTools.nitch.enable # System info
base.secrets.enable # pass-wayland, pinentry
desktop.wm.hyprland.enable # Hyprland window manager
desktop.wm.rofi.enable # Rofi launcher
desktop.wm.wayland.enable # Wayland tools (grim, slurp, etc.)
desktop.apps.obsidian.enable # Obsidian
desktop.apps.office.enable # LibreOffice
desktop.apps.crypto.enable # Bisq2, Monero, Trezor
desktop.theme.fonts.enable # Desktop fonts
desktop.theme.wallpapers.enable # Wallpaper collection
coding.editors.neovim.enable # Neovim
coding.editors.zed.enable # Zed editor (desktop only)
coding.lsp.enable # Language servers
coding.packages.enable # Bruno, Insomnia
coding.languages.python.enable
coding.languages.javascript.enable
coding.languages.typescript.enable
coding.languages.rustToolchain.enable
coding.languages.go.enable
profiles.gaming.steam.enable
profiles.gaming.gamescope.enable
profiles.gaming.gpu.enable
profiles.media.obs.enable
profiles.media.ffmpeg.enable
profiles.media.kdenlive.enable
profiles.media.ytDlp.enable
profiles.media.handbrake.enable
```
## Adding a New Module
1. Create the `.nix` file in the appropriate directory under `profiles/`
2. Define an `options` block with `mkEnableOption`
3. Define a `config` block with `mkIf cfg.enable`
4. Add the import to the parent `default.nix`
Example:
```nix
# profiles/sets/coding/languages/elixir.nix
{ config, lib, pkgs, ... }:
with lib; let
cfg = config.coding.languages.elixir;
in {
options.coding.languages.elixir.enable = mkEnableOption "Elixir language support";
config = mkIf cfg.enable {
home.packages = with pkgs; [ elixir ];
};
}
```
Then add `./elixir` to `profiles/sets/coding/languages/default.nix` .
## Assets
Static assets (wallpapers, etc.) live in `assets/` . They are referenced via the `"m3ta-home".paths.srcRoot` option, which points to the flake source root and works in pure evaluation mode:
```nix
source = "${config."m3ta-home".paths.srcRoot}/assets/wallpapers";
```
## Dependencies
| Input | Purpose |
|-------|---------|
| `nixpkgs` | Package set (follows nixos-config's nixpkgs) |
| `home-manager` | Home-Manager modules |
| `nix-colors` | Dracula theme palette (used everywhere) |
| `m3ta-nixpkgs` | Custom packages (zellij-ps, rofi-project-opener) and HM modules |
| `agenix` | Secret management |
| `NUR` | Additional packages |
## Important Notes
- **Overlays** are managed at the NixOS level in `nixos-config` , not here. `home-manager.useGlobalPkgs = true` ensures HM sees them.
- **Host-specific config** (monitor layouts, window rules, XDG/MIME) belongs in `nixos-config/hosts/<name>/home.nix` , not here.
- **Pure evaluation**: All file references use `"m3ta-home".paths.srcRoot` instead of relative `../..` paths.