feat: implement modular foundation and core system services

- Update flake.nix with 25.11 release and core inputs
- Add dedicated modules for audio (Pipewire), bluetooth, and networking
- Update GEMINI.md with the new Modular Merging Architecture blueprint
- Configure graphical installer ISO and test VM outputs
This commit is contained in:
Bernardo Magri
2026-04-03 21:06:42 +01:00
parent 33deeb494b
commit 29cc0d2547
49 changed files with 1628 additions and 855 deletions

View File

@@ -0,0 +1,33 @@
{ config, pkgs, ... }:
{
programs.alacritty = {
enable = true;
settings = {
general.import = [ "~/.config/nomarchy/current/theme/alacritty.toml" ];
env = {
TERM = "xterm-256color";
};
terminal = {
osc52 = "CopyPaste";
};
font = {
normal = { family = config.nomarchy.fonts.monospace; style = "Regular"; };
bold = { family = config.nomarchy.fonts.monospace; style = "Bold"; };
italic = { family = config.nomarchy.fonts.monospace; style = "Italic"; };
size = 9;
};
window = {
padding = { x = 14; y = 14; };
decorations = "None";
};
keyboard = {
bindings = [
{ key = "Insert"; mods = "Shift"; action = "Paste"; }
{ key = "Insert"; mods = "Control"; action = "Copy"; }
{ key = "Return"; mods = "Shift"; chars = "\\u001B\\r"; }
];
};
};
};
}

View File

@@ -2,7 +2,6 @@
{
xdg.configFile = {
"alacritty".source = ../../config/alacritty;
"btop".source = ../../config/btop;
"chromium".source = ../../config/chromium;
"fastfetch".source = ../../config/fastfetch;

View File

@@ -7,12 +7,23 @@ let
activeThemeName = if builtins.pathExists stateFile then
lib.removeSuffix "\n" (builtins.readFile stateFile)
else "dracula";
userPackagesFile = "${config.home.homeDirectory}/.config/home-manager/user-packages.json";
userPackages = if builtins.pathExists userPackagesFile then
let
pkgNames = builtins.fromJSON (builtins.readFile userPackagesFile);
# Filter to only packages that exist in pkgs to prevent build failures
validPkgs = builtins.filter (name: builtins.hasAttr name pkgs) pkgNames;
in builtins.map (name: pkgs.${name}) validPkgs
else [];
in
{
imports = [
inputs.nix-colors.homeManagerModules.default
inputs.walker.homeManagerModules.default
./fonts.nix
./alacritty.nix
./nightlight.nix
./idle.nix
./stylix.nix
./hyprland.nix
./waybar.nix
@@ -25,8 +36,25 @@ in
colorScheme = palettes.${activeThemeName} or palettes.dracula;
home.packages = with pkgs; [
alacritty
];
firefox
thunar
imv
mpv
neovim
wl-clipboard
grim
slurp
brightnessctl
playerctl
pamixer
mise
jq
xmlstarlet
nerd-fonts.jetbrains-mono
nerd-fonts.roboto-mono
nerd-fonts.fira-code
nerd-fonts.ubuntu-mono
] ++ userPackages;
home.shellAliases = {
sys-update = "sudo nixos-rebuild switch --flake /etc/nixos#default";

View File

@@ -1,9 +1,11 @@
{ config, pkgs, lib, ... }:
let
stateFile = "${config.home.homeDirectory}/.config/home-manager/font-state.nix";
activeFont = if builtins.pathExists stateFile then
lib.removeSuffix "\n" (builtins.readFile stateFile)
# Standardize state files to a common directory
stateDir = "${config.home.homeDirectory}/.config/home-manager";
fontStateFile = "${stateDir}/font-state.nix";
activeFont = if builtins.pathExists fontStateFile then
lib.removeSuffix "\n" (builtins.readFile fontStateFile)
else "JetBrainsMono Nerd Font";
in
{
@@ -14,4 +16,9 @@ in
description = "Monospace font for the system";
};
};
config = {
fonts.fontconfig.enable = true;
xdg.dataFile."fonts/nomarchy.ttf".source = ../../config/nomarchy.ttf;
};
}

View File

@@ -5,20 +5,30 @@ let
activeWallpaper = if builtins.pathExists wallpaperStateFile then
lib.removeSuffix "\n" (builtins.readFile wallpaperStateFile)
else "";
hyprlandStateFile = "${config.home.homeDirectory}/.config/home-manager/hyprland-state.json";
hyprlandState = if builtins.pathExists hyprlandStateFile then
builtins.fromJSON (builtins.readFile hyprlandStateFile)
else { gaps_out = 10; gaps_in = 5; border_size = 2; };
in
{
wayland.windowManager.hyprland = {
enable = true;
settings = {
"general" = {
"gaps_in" = hyprlandState.gaps_in;
"gaps_out" = hyprlandState.gaps_out;
"border_size" = hyprlandState.border_size;
"col.active_border" = "rgb(${config.colorScheme.palette.base0E})";
"col.inactive_border" = "rgb(${config.colorScheme.palette.base03})";
};
"exec-once" = [
"swww init && swww fill ${activeWallpaper}"
"swww-daemon & sleep 0.5 && swww img ${activeWallpaper} --transition-type none"
"waybar"
"nomarchy-on-boot"
"nomarchy-welcome"
];
"bind" = [
"SUPER, Space, exec, walker"
"SUPER ALT, Space, exec, nomarchy-theme-selector"
"SUPER CTRL, Space, exec, nomarchy-font-selector"
"SUPER SHIFT, Space, exec, nomarchy-wallpaper-selector"

13
modules/home/idle.nix Normal file
View File

@@ -0,0 +1,13 @@
{ config, pkgs, ... }:
let
stateFile = "${config.home.homeDirectory}/.config/home-manager/idle-state.json";
idleState = if builtins.pathExists stateFile then
builtins.fromJSON (builtins.readFile stateFile)
else { enabled = true; };
in
{
services.hypridle = {
enable = idleState.enabled;
};
}

View File

@@ -0,0 +1,14 @@
{ config, pkgs, ... }:
let
stateFile = "${config.home.homeDirectory}/.config/home-manager/hyprsunset-state.json";
hyprsunsetState = if builtins.pathExists stateFile then
builtins.fromJSON (builtins.readFile stateFile)
else { enabled = false; temperature = 4000; };
in
{
services.hyprsunset = {
enable = true; # Always enabled, we control via IPC and state
temperature = if hyprsunsetState.enabled then hyprsunsetState.temperature else 6500;
};
}

View File

@@ -15,6 +15,12 @@ let
jq
swww
xmlstarlet
wl-clipboard
grim
slurp
brightnessctl
playerctl
pamixer
# Add any others commonly used in bin/
];

5
modules/home/swayosd.nix Normal file
View File

@@ -0,0 +1,5 @@
{ config, pkgs, ... }:
{
services.swayosd.enable = true;
}

View File

@@ -9,7 +9,13 @@ let
STATE_DIR="$HOME/.config/home-manager"
THEME_STATE_FILE="$STATE_DIR/theme-state.nix"
WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix"
THEMES_DIR="/etc/nixos/themes" # This depends on where the repo is cloned
if [ -d "/etc/nixos/nomarchy/themes" ]; then
THEMES_DIR="/etc/nixos/nomarchy/themes"
elif [ -d "/etc/nomarchy/themes" ]; then
THEMES_DIR="/etc/nomarchy/themes"
else
THEMES_DIR="/etc/nixos/themes"
fi # This depends on where the repo is cloned
mkdir -p "$STATE_DIR"
@@ -24,6 +30,7 @@ let
BG=$(ls "$BG_DIR" | head -n 1)
if [ -n "$BG" ]; then
echo "$BG_DIR/$BG" > "$WALLPAPER_STATE_FILE"
swww img "$BG_DIR/$BG" --transition-type outer --transition-pos 0.85,0.97 --transition-step 90 &
fi
fi
@@ -48,7 +55,13 @@ let
nomarchy-wallpaper-selector = pkgs.writeShellScriptBin "nomarchy-wallpaper-selector" ''
STATE_DIR="$HOME/.config/home-manager"
WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix"
THEMES_DIR="/etc/nixos/themes"
if [ -d "/etc/nixos/nomarchy/themes" ]; then
THEMES_DIR="/etc/nixos/nomarchy/themes"
elif [ -d "/etc/nomarchy/themes" ]; then
THEMES_DIR="/etc/nomarchy/themes"
else
THEMES_DIR="/etc/nixos/themes"
fi
mkdir -p "$STATE_DIR"
@@ -58,6 +71,7 @@ let
if [ -n "$SELECTED_WP" ]; then
echo "$SELECTED_WP" > "$WALLPAPER_STATE_FILE"
swww img "$SELECTED_WP" --transition-type outer --transition-pos 0.85,0.97 --transition-step 90 &
env-update
fi
'';

14
modules/home/vscode.nix Normal file
View File

@@ -0,0 +1,14 @@
{ config, pkgs, ... }:
{
programs.vscode = {
enable = true;
package = pkgs.vscode;
userSettings = {
"update.mode" = "none";
"workbench.colorTheme" = "Nomarchy Theme"; # Example, would need to be generated
"window.titleBarStyle" = "custom";
};
# extensions = with pkgs.vscode-extensions; [ ... ];
};
}

68
modules/options.nix Normal file
View File

@@ -0,0 +1,68 @@
{ config, lib, pkgs, ... }:
with lib;
{
options.nomarchy = {
# System-level options
system = {
enable = mkEnableOption "Nomarchy core system features";
# Allow users to add extra system packages
extraPackages = mkOption {
type = types.listOf types.package;
default = [];
description = "Additional system-wide packages to install";
};
# Allow overriding system defaults
hostname = mkOption {
type = types.str;
default = "nomarchy";
description = "The system hostname";
};
# Allow user to inject their own NixOS modules
extraModules = mkOption {
type = types.listOf types.deferredModule;
default = [];
description = "Extra NixOS modules to include";
};
};
# Home-level options
home = {
enable = mkEnableOption "Nomarchy home environment features";
# Allow users to add extra user packages
extraPackages = mkOption {
type = types.listOf types.package;
default = [];
description = "Additional user-level packages to install";
};
# Configuration for the environment
terminal = mkOption {
type = types.enum [ "alacritty" "kitty" "ghostty" ];
default = "alacritty";
description = "Preferred terminal emulator";
};
# Allow user to inject their own Home Manager modules
extraModules = mkOption {
type = types.listOf types.deferredModule;
default = [];
description = "Extra Home Manager modules to include";
};
# Theming overrides
themeOverride = mkOption {
type = types.nullOr types.str;
default = null;
description = "Force a specific theme (ignoring state files)";
};
};
# Hardware flags (already exists in hardware.nix, but good to keep in mind)
};
}

12
modules/system/audio.nix Normal file
View File

@@ -0,0 +1,12 @@
{ config, pkgs, ... }:
{
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
jack.enable = true;
};
}

View File

@@ -0,0 +1,7 @@
{ config, pkgs, ... }:
{
hardware.bluetooth.enable = true;
hardware.bluetooth.powerOnBoot = true;
services.blueman.enable = true;
}

View File

@@ -1,9 +1,13 @@
{ config, pkgs, ... }:
{ config, lib, pkgs, ... }:
{
imports = [
./plymouth.nix
./sddm.nix
./hardware.nix
./audio.nix
./bluetooth.nix
./network.nix
./impermanence.nix
];
}

View File

@@ -0,0 +1,58 @@
{ config, lib, pkgs, inputs, ... }:
let
cfg = config.nomarchy.system.impermanence;
in
{
imports = [
inputs.impermanence.nixosModules.impermanence
];
options.nomarchy.system.impermanence = {
enable = lib.mkEnableOption "Erase Your Darlings (Impermanence) root wipe on boot";
};
config = lib.mkIf cfg.enable {
# 1. The Rollback Script: Runs in initrd before filesystems are mounted
boot.initrd.postDeviceCommands = lib.mkAfter ''
mkdir -p /btrfs_tmp
mount -o subvol=/ /dev/mapper/crypted /btrfs_tmp
if [[ -e /btrfs_tmp/@ ]]; then
mkdir -p /btrfs_tmp/old_roots
timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/@)" "+%Y-%m-%-d_%H:%M:%S")
mv /btrfs_tmp/@ "/btrfs_tmp/old_roots/$timestamp"
fi
delete_subvolume_recursively() {
IFS=$'\n'
for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
delete_subvolume_recursively "/btrfs_tmp/$i"
done
btrfs subvolume delete "$1"
}
for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +30); do
delete_subvolume_recursively "$i"
done
btrfs subvolume snapshot /btrfs_tmp/root-blank /btrfs_tmp/@
umount /btrfs_tmp
'';
# 2. Persistence Configuration: What survives the wipe
environment.persistence."/persist" = {
hideMounts = true;
directories = [
"/var/log"
"/var/lib/nixos"
"/var/lib/systemd/coredump"
"/var/lib/bluetooth"
"/etc/NetworkManager/system-connections"
];
files = [
"/etc/machine-id"
];
};
};
}

View File

@@ -0,0 +1,5 @@
{ config, pkgs, ... }:
{
networking.networkmanager.enable = true;
}

View File

@@ -0,0 +1,6 @@
{ config, pkgs, ... }:
{
services.supergfxd.enable = true;
# NixOS handles the configuration of supergfxd
}