feat(modules): users, scripts, menus, fastfetch, walker, cache, colors, bootstrap
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
2289f91048
commit
b16707b2ab
9 changed files with 2521 additions and 0 deletions
45
modules/cache.nix
Normal file
45
modules/cache.nix
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Binary cache configuration.
|
||||||
|
#
|
||||||
|
# Substituters and trusted public keys for cache.nixos.org and
|
||||||
|
# nix-community, plus a stub for the aiolabs cache (uncomment when
|
||||||
|
# configured). Imported by every host that wants pre-built artifacts
|
||||||
|
# instead of compiling from source.
|
||||||
|
#
|
||||||
|
# Why this exists as its own module: the optimize-deploys/unified flake
|
||||||
|
# notes that host1/host3/host2 share ~90% of derivations, so the second
|
||||||
|
# and third deploys would be near-instant once a cache is set up. Same
|
||||||
|
# applies for the dev box rebuilds. Rather than scatter substituter
|
||||||
|
# configuration across every host, define it once.
|
||||||
|
#
|
||||||
|
# Pushing to the cache is one Makefile target (`make cache`) — see the
|
||||||
|
# top-level Makefile.
|
||||||
|
|
||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
nix.settings = {
|
||||||
|
substituters = [
|
||||||
|
"https://cache.nixos.org"
|
||||||
|
"https://nix-community.cachix.org"
|
||||||
|
# Uncomment when the aiolabs cache is configured.
|
||||||
|
# "https://aiolabs-nix.cachix.org"
|
||||||
|
];
|
||||||
|
|
||||||
|
trusted-public-keys = [
|
||||||
|
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||||
|
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||||
|
# Add the aiolabs cache public key here once we generate it:
|
||||||
|
# cachix authtoken <token>
|
||||||
|
# cachix create aiolabs-nix
|
||||||
|
# The public key is shown after `cachix create`.
|
||||||
|
# "aiolabs-nix.cachix.org-1:..."
|
||||||
|
];
|
||||||
|
|
||||||
|
# Allow more substituters at runtime via `--option extra-substituters`
|
||||||
|
# without editing this file. Useful for one-off testing.
|
||||||
|
trusted-substituters = [
|
||||||
|
"https://cache.nixos.org"
|
||||||
|
"https://nix-community.cachix.org"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
165
modules/colors.nix
Normal file
165
modules/colors.nix
Normal file
|
|
@ -0,0 +1,165 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib)
|
||||||
|
mkIf
|
||||||
|
mkMerge
|
||||||
|
optionals
|
||||||
|
optionalString
|
||||||
|
;
|
||||||
|
cfg = config.omni;
|
||||||
|
|
||||||
|
# Function to generate colors from wallpaper using imagemagick
|
||||||
|
generateColorsFromWallpaper =
|
||||||
|
wallpaperPath:
|
||||||
|
pkgs.writeShellScriptBin "generate-colors" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Extract dominant colors from wallpaper using imagemagick
|
||||||
|
colors=$(${pkgs.imagemagick}/bin/convert "${wallpaperPath}" -resize 1x1 -format "%[pixel:u]" info:)
|
||||||
|
|
||||||
|
# Generate a simple color scheme based on the dominant color
|
||||||
|
# This is a simplified approach - ideally would use a more sophisticated algorithm
|
||||||
|
echo "# Generated color scheme from wallpaper: ${wallpaperPath}"
|
||||||
|
echo "# Dominant color: $colors"
|
||||||
|
|
||||||
|
# For now, we'll use predefined schemes that match common wallpaper types
|
||||||
|
# In a real implementation, this would analyze the image and generate appropriate colors
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Default color schemes for common wallpaper types
|
||||||
|
fallbackColorSchemes = {
|
||||||
|
dark = inputs.nix-colors.colorSchemes.tokyo-night-dark or null;
|
||||||
|
light = inputs.nix-colors.colorSchemes.tokyo-night-light or null;
|
||||||
|
blue = inputs.nix-colors.colorSchemes.nord or null;
|
||||||
|
purple = inputs.nix-colors.colorSchemes.catppuccin-mocha or null;
|
||||||
|
green = inputs.nix-colors.colorSchemes.gruvbox-dark-medium or null;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Select color scheme based on wallpaper or user preference
|
||||||
|
selectedColorScheme =
|
||||||
|
if cfg.colorScheme != null then
|
||||||
|
cfg.colorScheme
|
||||||
|
else if cfg.wallpaper != null && cfg.features.autoColors then
|
||||||
|
# TODO: Implement actual color analysis
|
||||||
|
# For now, use a sensible default based on theme
|
||||||
|
fallbackColorSchemes.${cfg.theme} or fallbackColorSchemes.dark
|
||||||
|
else
|
||||||
|
# Use theme-based color scheme
|
||||||
|
fallbackColorSchemes.${cfg.theme} or fallbackColorSchemes.dark;
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
config = mkIf (cfg.enable or true) (mkMerge [
|
||||||
|
# User-specific configuration using shared helpers
|
||||||
|
({
|
||||||
|
home-manager.users.${cfg.user} = mkIf (selectedColorScheme != null) {
|
||||||
|
colorScheme = selectedColorScheme;
|
||||||
|
|
||||||
|
# Add packages for color management
|
||||||
|
home.packages =
|
||||||
|
with pkgs;
|
||||||
|
[
|
||||||
|
imagemagick # For color extraction from images
|
||||||
|
]
|
||||||
|
++ optionals (cfg.features.customThemes or false || cfg.features.wallpaperEffects or false) [
|
||||||
|
# Additional packages for advanced color analysis
|
||||||
|
python3Packages.pillow # For more sophisticated image analysis
|
||||||
|
python3Packages.colorthief # For extracting color palettes
|
||||||
|
]
|
||||||
|
++ optionals (cfg.wallpaper != null) [
|
||||||
|
# Generate wallpaper setter script that respects colors
|
||||||
|
(pkgs.writeShellScriptBin "set-omni-wallpaper" ''
|
||||||
|
WALLPAPER_PATH="${cfg.wallpaper}"
|
||||||
|
|
||||||
|
echo "Setting wallpaper: $WALLPAPER_PATH"
|
||||||
|
|
||||||
|
# Set wallpaper with awww
|
||||||
|
if command -v awww &> /dev/null; then
|
||||||
|
awww img "$WALLPAPER_PATH" --transition-type wipe --transition-angle 30 --transition-step 90
|
||||||
|
else
|
||||||
|
echo "awww not found, please install awww for wallpaper support"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Optionally generate new colors from wallpaper
|
||||||
|
${optionalString (cfg.features.wallpaperEffects or false) ''
|
||||||
|
echo "Generating colors from wallpaper..."
|
||||||
|
# This would trigger a system rebuild with new colors
|
||||||
|
# For now, just notify the user
|
||||||
|
echo "Note: Automatic color generation requires system rebuild"
|
||||||
|
echo "Consider adding this wallpaper to your configuration and rebuilding"
|
||||||
|
''}
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
|
# System-level configuration
|
||||||
|
{
|
||||||
|
|
||||||
|
# System-level packages for color management
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
# Color utilities
|
||||||
|
imagemagick
|
||||||
|
|
||||||
|
# Wallpaper utilities
|
||||||
|
awww # Wayland wallpaper daemon
|
||||||
|
|
||||||
|
# Script to help users set up automatic colors
|
||||||
|
(writeShellScriptBin "omni-setup-colors" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
echo "Omnixient Color Setup"
|
||||||
|
echo "=================="
|
||||||
|
echo ""
|
||||||
|
echo "Current configuration:"
|
||||||
|
echo " Theme: ${cfg.theme}"
|
||||||
|
echo " Preset: ${if cfg.preset != null then cfg.preset else "none"}"
|
||||||
|
echo " Custom Themes: ${if cfg.features.customThemes or false then "enabled" else "disabled"}"
|
||||||
|
echo " Wallpaper Effects: ${
|
||||||
|
if cfg.features.wallpaperEffects or false then "enabled" else "disabled"
|
||||||
|
}"
|
||||||
|
echo " Wallpaper: ${if cfg.wallpaper != null then toString cfg.wallpaper else "not set"}"
|
||||||
|
echo " Color Scheme: ${if cfg.colorScheme != null then "custom" else "theme-based"}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
${optionalString (!(cfg.features.wallpaperEffects or false)) ''
|
||||||
|
echo "To enable automatic color generation:"
|
||||||
|
echo " 1. Set omni.features.wallpaperEffects = true; in your configuration"
|
||||||
|
echo " 2. Set omni.wallpaper = /path/to/your/wallpaper.jpg;"
|
||||||
|
echo " 3. Rebuild your system with: omni-rebuild"
|
||||||
|
echo ""
|
||||||
|
''}
|
||||||
|
|
||||||
|
${optionalString ((cfg.features.wallpaperEffects or false) && cfg.wallpaper == null) ''
|
||||||
|
echo "Wallpaper effects are enabled but no wallpaper is set."
|
||||||
|
echo "Set omni.wallpaper = /path/to/your/wallpaper.jpg; in your configuration."
|
||||||
|
echo ""
|
||||||
|
''}
|
||||||
|
|
||||||
|
echo "Available nix-colors schemes:"
|
||||||
|
echo " - tokyo-night-dark, tokyo-night-light"
|
||||||
|
echo " - catppuccin-mocha, catppuccin-latte"
|
||||||
|
echo " - gruvbox-dark-medium, gruvbox-light-medium"
|
||||||
|
echo " - nord"
|
||||||
|
echo " - everforest-dark-medium"
|
||||||
|
echo " - rose-pine, rose-pine-dawn"
|
||||||
|
echo ""
|
||||||
|
echo "To use a specific scheme:"
|
||||||
|
echo ' omni.colorScheme = inputs.nix-colors.colorSchemes.SCHEME_NAME;'
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
|
||||||
|
# Export color information for other modules to use
|
||||||
|
environment.variables = mkIf (selectedColorScheme != null) {
|
||||||
|
OMNI_COLOR_SCHEME = selectedColorScheme.slug or "unknown";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}
|
||||||
221
modules/fastfetch.nix
Normal file
221
modules/fastfetch.nix
Normal file
|
|
@ -0,0 +1,221 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
# Fastfetch system information display for Omnixient
|
||||||
|
# Beautiful system information with Omnixient branding
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) mkIf;
|
||||||
|
cfg = config.omni;
|
||||||
|
omni = config.omni.lib;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
config = mkIf (cfg.enable or true) {
|
||||||
|
# Add fastfetch and convenience scripts to system packages
|
||||||
|
environment.systemPackages =
|
||||||
|
(with pkgs; [
|
||||||
|
fastfetch
|
||||||
|
])
|
||||||
|
++ [
|
||||||
|
# Convenience scripts
|
||||||
|
(omni.makeScript "omni-info" "Show Omnixient system information" ''
|
||||||
|
fastfetch --config /etc/omni/fastfetch/config.jsonc
|
||||||
|
'')
|
||||||
|
|
||||||
|
(omni.makeScript "omni-about" "Show Omnixient about screen" ''
|
||||||
|
clear
|
||||||
|
cat /etc/omni/branding/about.txt
|
||||||
|
echo
|
||||||
|
echo "Theme: ${cfg.theme}"
|
||||||
|
echo "Preset: ${cfg.preset or "custom"}"
|
||||||
|
echo "User: ${cfg.user}"
|
||||||
|
echo "NixOS Version: $(nixos-version)"
|
||||||
|
echo
|
||||||
|
echo "Visit: https://github.com/TheArctesian/omnixy"
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
|
||||||
|
# Create Omnixient branding directory
|
||||||
|
environment.etc."omni/branding/logo.txt".text = ''
|
||||||
|
|
||||||
|
███████╗███╗ ███╗███╗ ██╗██╗██╗ ██╗██╗ ██╗
|
||||||
|
██╔════╝████╗ ████║████╗ ██║██║╚██╗██╔╝╚██╗ ██╔╝
|
||||||
|
██║ ██╔████╔██║██╔██╗ ██║██║ ╚███╔╝ ╚████╔╝
|
||||||
|
██║ ██║╚██╔╝██║██║╚██╗██║██║ ██╔██╗ ╚██╔╝
|
||||||
|
███████╗██║ ╚═╝ ██║██║ ╚████║██║██╔╝ ██╗ ██║
|
||||||
|
╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═╝ ╚═╝
|
||||||
|
|
||||||
|
Declarative NixOS Configuration
|
||||||
|
'';
|
||||||
|
|
||||||
|
environment.etc."omni/branding/about.txt".text = ''
|
||||||
|
╭─────────────────────────────────────────────────────╮
|
||||||
|
│ │
|
||||||
|
│ ██████╗ ███╗ ███╗███╗ ██╗██╗██╗ ██╗██╗ ██╗│
|
||||||
|
│ ██╔═══██╗████╗ ████║████╗ ██║██║╚██╗██╔╝╚██╗ ██╔╝│
|
||||||
|
│ ██║ ██║██╔████╔██║██╔██╗ ██║██║ ╚███╔╝ ╚████╔╝ │
|
||||||
|
│ ██║ ██║██║╚██╔╝██║██║╚██╗██║██║ ██╔██╗ ╚██╔╝ │
|
||||||
|
│ ╚██████╔╝██║ ╚═╝ ██║██║ ╚████║██║██╔╝ ██╗ ██║ │
|
||||||
|
│ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═╝ ╚═╝ │
|
||||||
|
│ │
|
||||||
|
│ 🚀 Declarative • 🎨 Beautiful • ⚡ Fast │
|
||||||
|
│ │
|
||||||
|
╰─────────────────────────────────────────────────────╯
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Create fastfetch configuration
|
||||||
|
environment.etc."omni/fastfetch/config.jsonc".text = ''
|
||||||
|
{
|
||||||
|
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||||
|
"logo": {
|
||||||
|
"type": "file",
|
||||||
|
"source": "/etc/omni/branding/about.txt",
|
||||||
|
"color": {
|
||||||
|
"1": "cyan",
|
||||||
|
"2": "blue"
|
||||||
|
},
|
||||||
|
"padding": {
|
||||||
|
"top": 1,
|
||||||
|
"right": 4,
|
||||||
|
"left": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"modules": [
|
||||||
|
"break",
|
||||||
|
{
|
||||||
|
"type": "custom",
|
||||||
|
"format": "\u001b[90m┌─────────────────── Hardware ───────────────────┐"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "host",
|
||||||
|
"key": " Host",
|
||||||
|
"keyColor": "cyan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "cpu",
|
||||||
|
"key": " CPU",
|
||||||
|
"keyColor": "cyan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "gpu",
|
||||||
|
"key": " GPU",
|
||||||
|
"keyColor": "cyan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "memory",
|
||||||
|
"key": " Memory",
|
||||||
|
"keyColor": "cyan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "disk",
|
||||||
|
"key": " Disk (/)",
|
||||||
|
"keyColor": "cyan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "custom",
|
||||||
|
"format": "\u001b[90m├─────────────────── Software ───────────────────┤"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "os",
|
||||||
|
"key": " OS",
|
||||||
|
"keyColor": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "kernel",
|
||||||
|
"key": " Kernel",
|
||||||
|
"keyColor": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "de",
|
||||||
|
"key": " DE",
|
||||||
|
"keyColor": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "wm",
|
||||||
|
"key": " WM",
|
||||||
|
"keyColor": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "wmtheme",
|
||||||
|
"key": " Theme",
|
||||||
|
"keyColor": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"key": " Shell",
|
||||||
|
"keyColor": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "terminal",
|
||||||
|
"key": " Terminal",
|
||||||
|
"keyColor": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "custom",
|
||||||
|
"format": "\u001b[90m├─────────────────── Omnixient ─────────────────────┤"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "custom",
|
||||||
|
"format": " Theme: ${cfg.theme}",
|
||||||
|
"keyColor": "magenta"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "custom",
|
||||||
|
"format": " Preset: ${cfg.preset or "custom"}",
|
||||||
|
"keyColor": "magenta"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "custom",
|
||||||
|
"format": " User: ${cfg.user}",
|
||||||
|
"keyColor": "magenta"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "packages",
|
||||||
|
"key": " Packages",
|
||||||
|
"keyColor": "magenta"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "custom",
|
||||||
|
"format": "\u001b[90m└─────────────────────────────────────────────────┘"
|
||||||
|
},
|
||||||
|
"break"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Convenience scripts are now consolidated above
|
||||||
|
|
||||||
|
# Add to user environment
|
||||||
|
home-manager.users.${config.omni.user} = {
|
||||||
|
# Set XDG config dir for fastfetch
|
||||||
|
xdg.configFile."fastfetch/config.jsonc".source =
|
||||||
|
config.environment.etc."omni/fastfetch/config.jsonc".source;
|
||||||
|
|
||||||
|
# Add shell aliases
|
||||||
|
programs.bash.shellAliases = {
|
||||||
|
neofetch = "omni-info";
|
||||||
|
screenfetch = "omni-info";
|
||||||
|
sysinfo = "omni-info";
|
||||||
|
about = "omni-about";
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.zsh.shellAliases = {
|
||||||
|
neofetch = "omni-info";
|
||||||
|
screenfetch = "omni-info";
|
||||||
|
sysinfo = "omni-info";
|
||||||
|
about = "omni-about";
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.fish.shellAliases = {
|
||||||
|
neofetch = "omni-info";
|
||||||
|
screenfetch = "omni-info";
|
||||||
|
sysinfo = "omni-info";
|
||||||
|
about = "omni-about";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
69
modules/home-manager-bootstrap.nix
Normal file
69
modules/home-manager-bootstrap.nix
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
# modules/home-manager-bootstrap.nix
|
||||||
|
#
|
||||||
|
# Pre-create the directory tree that the home-manager activation
|
||||||
|
# script expects to exist on a fresh first boot. Without these
|
||||||
|
# rules, `home-manager-user.service` crashes in (at least) three
|
||||||
|
# different places — each one only visible after fixing the
|
||||||
|
# previous — making first-boot of any clean install fail with a
|
||||||
|
# misleading error.
|
||||||
|
#
|
||||||
|
# This module is imported by both:
|
||||||
|
# - lib/mksystem.nix (for normal hosts), and
|
||||||
|
# - iso.nix (for the live ISO),
|
||||||
|
# so the bootstrap is consistent across both code paths. It is
|
||||||
|
# intentionally a separate module rather than inlined in mksystem
|
||||||
|
# so the ISO — which bypasses mksystem — does not silently miss
|
||||||
|
# the fix.
|
||||||
|
#
|
||||||
|
# Reads `config.omni.user`, which is the canonical "main user"
|
||||||
|
# option set by modules/core.nix. Does nothing if that option is
|
||||||
|
# unset (e.g. during a flake check that does not set up users).
|
||||||
|
#
|
||||||
|
# The bugs this fixes:
|
||||||
|
#
|
||||||
|
# 1. The "find a profile dir" check in
|
||||||
|
# home-manager-generation/activate (around line 90 of the
|
||||||
|
# generated script) needs $HOME/.local/state/nix/profiles
|
||||||
|
# OR /nix/var/nix/profiles/per-user/$USER to exist. The
|
||||||
|
# nix-daemon only creates the per-user dir lazily on the
|
||||||
|
# user's first nix command, so on a fresh boot neither path
|
||||||
|
# exists. Symptom: "Could not find suitable profile
|
||||||
|
# directory" → service fails.
|
||||||
|
#
|
||||||
|
# 2. After (1) is fixed, `nix-store --realise ... --add-root
|
||||||
|
# $HOME/.local/state/home-manager/gcroots/new-home` fails
|
||||||
|
# because the activate script declares `hmGcrootsDir` but
|
||||||
|
# never `mkdir -p`s it. nix-store will not create parent
|
||||||
|
# dirs for --add-root. Symptom: silent exit, status 1, no
|
||||||
|
# error in journal.
|
||||||
|
#
|
||||||
|
# 3. After (2) is fixed, `linkGeneration` fails with
|
||||||
|
# "Permission denied" creating `~/.local/share/dev-env/...`.
|
||||||
|
# modules/lib.nix declares `d /home/$USER/.local/share/
|
||||||
|
# omni ...` and systemd-tmpfiles auto-creates the missing
|
||||||
|
# intermediate `.local/share` parent as root:root, which
|
||||||
|
# then blocks the user-running activation. Pinning the
|
||||||
|
# `.local/share` parent here keeps it user-owned regardless
|
||||||
|
# of declaration order.
|
||||||
|
#
|
||||||
|
# tmpfiles `d` rules do not recursively create parents, so each
|
||||||
|
# level of the tree is spelled out explicitly.
|
||||||
|
|
||||||
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
user = config.omni.user or null;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
config = lib.mkIf (user != null) {
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d /nix/var/nix/profiles/per-user/${user} 0755 ${user} users -"
|
||||||
|
"d /nix/var/nix/gcroots/per-user/${user} 0755 ${user} users -"
|
||||||
|
"d /home/${user}/.local 0755 ${user} users -"
|
||||||
|
"d /home/${user}/.local/share 0755 ${user} users -"
|
||||||
|
"d /home/${user}/.local/state 0755 ${user} users -"
|
||||||
|
"d /home/${user}/.local/state/home-manager 0755 ${user} users -"
|
||||||
|
"d /home/${user}/.local/state/home-manager/gcroots 0755 ${user} users -"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
534
modules/menus.nix
Normal file
534
modules/menus.nix
Normal file
|
|
@ -0,0 +1,534 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
# Interactive menu system for Omnixient
|
||||||
|
# Terminal-based menus for system management and productivity
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) mkIf mkDefault;
|
||||||
|
cfg = config.omni;
|
||||||
|
omni = config.omni.lib;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
config = mkIf (cfg.enable or true) {
|
||||||
|
# Interactive menu scripts
|
||||||
|
environment.systemPackages = [
|
||||||
|
# Main Omnixient menu
|
||||||
|
(omni.makeScript "omni-menu" "Interactive Omnixient system menu" ''
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Colors for terminal output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
PURPLE='\033[0;35m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
WHITE='\033[1;37m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
show_header() {
|
||||||
|
clear
|
||||||
|
echo -e "''${CYAN}"
|
||||||
|
echo " ███████╗███╗ ███╗███╗ ██╗██╗██╗ ██╗██╗ ██╗"
|
||||||
|
echo " ██╔════╝████╗ ████║████╗ ██║██║╚██╗██╔╝╚██╗ ██╔╝"
|
||||||
|
echo " ██║ ██╔████╔██║██╔██╗ ██║██║ ╚███╔╝ ╚████╔╝"
|
||||||
|
echo " ██║ ██║╚██╔╝██║██║╚██╗██║██║ ██╔██╗ ╚██╔╝"
|
||||||
|
echo " ███████╗██║ ╚═╝ ██║██║ ╚████║██║██╔╝ ██╗ ██║"
|
||||||
|
echo " ╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═╝ ╚═╝"
|
||||||
|
echo -e "''${NC}"
|
||||||
|
echo -e "''${WHITE} 🚀 Declarative • 🎨 Beautiful • ⚡ Fast''${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "''${BLUE}═══════════════════════════════════════════════════════''${NC}"
|
||||||
|
echo -e "''${WHITE} Theme: ''${YELLOW}${cfg.theme}''${WHITE} │ User: ''${GREEN}${cfg.user}''${WHITE} │ Preset: ''${PURPLE}${cfg.preset or "custom"}''${NC}"
|
||||||
|
echo -e "''${BLUE}═══════════════════════════════════════════════════════''${NC}"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
show_main_menu() {
|
||||||
|
show_header
|
||||||
|
echo -e "''${WHITE}🎛️ Main Menu''${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "''${GREEN}1.''${NC} 📦 System Management"
|
||||||
|
echo -e "''${GREEN}2.''${NC} 🎨 Theme & Appearance"
|
||||||
|
echo -e "''${GREEN}3.''${NC} ⚙️ Configuration"
|
||||||
|
echo -e "''${GREEN}4.''${NC} 🔧 Development Tools"
|
||||||
|
echo -e "''${GREEN}5.''${NC} 📊 System Information"
|
||||||
|
echo -e "''${GREEN}6.''${NC} 🛠️ Maintenance & Utilities"
|
||||||
|
echo -e "''${GREEN}7.''${NC} 📋 Help & Documentation"
|
||||||
|
echo
|
||||||
|
echo -e "''${RED}0.''${NC} Exit"
|
||||||
|
echo
|
||||||
|
echo -ne "''${CYAN}Select an option: ''${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_system_menu() {
|
||||||
|
show_header
|
||||||
|
echo -e "''${WHITE}📦 System Management''${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "''${GREEN}1.''${NC} 🔄 Update System"
|
||||||
|
echo -e "''${GREEN}2.''${NC} 🔨 Rebuild Configuration"
|
||||||
|
echo -e "''${GREEN}3.''${NC} 🧪 Test Configuration"
|
||||||
|
echo -e "''${GREEN}4.''${NC} 🧹 Clean System"
|
||||||
|
echo -e "''${GREEN}5.''${NC} 📊 Service Status"
|
||||||
|
echo -e "''${GREEN}6.''${NC} 💾 Create Backup"
|
||||||
|
echo -e "''${GREEN}7.''${NC} 🔍 Search Packages"
|
||||||
|
echo
|
||||||
|
echo -e "''${YELLOW}8.''${NC} ← Back to Main Menu"
|
||||||
|
echo
|
||||||
|
echo -ne "''${CYAN}Select an option: ''${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_theme_menu() {
|
||||||
|
show_header
|
||||||
|
echo -e "''${WHITE}🎨 Theme & Appearance''${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "''${WHITE}Current Theme: ''${YELLOW}${cfg.theme}''${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "''${GREEN}Available Themes:''${NC}"
|
||||||
|
echo -e "''${GREEN}1.''${NC} 🌃 tokyo-night - Dark theme with vibrant colors"
|
||||||
|
echo -e "''${GREEN}2.''${NC} 🎀 catppuccin - Pastel theme with modern aesthetics"
|
||||||
|
echo -e "''${GREEN}3.''${NC} 🟤 gruvbox - Retro theme with warm colors"
|
||||||
|
echo -e "''${GREEN}4.''${NC} ❄️ nord - Arctic theme with cool colors"
|
||||||
|
echo -e "''${GREEN}5.''${NC} 🌲 everforest - Green forest theme"
|
||||||
|
echo -e "''${GREEN}6.''${NC} 🌹 rose-pine - Cozy theme with muted colors"
|
||||||
|
echo -e "''${GREEN}7.''${NC} 🌊 kanagawa - Japanese-inspired theme"
|
||||||
|
echo -e "''${GREEN}8.''${NC} ☀️ catppuccin-latte - Light catppuccin variant"
|
||||||
|
echo -e "''${GREEN}9.''${NC} ⚫ matte-black - Minimalist dark theme"
|
||||||
|
echo -e "''${GREEN}a.''${NC} 💎 osaka-jade - Jade green accent theme"
|
||||||
|
echo -e "''${GREEN}b.''${NC} ☕ ristretto - Coffee-inspired warm theme"
|
||||||
|
echo
|
||||||
|
echo -e "''${YELLOW}0.''${NC} ← Back to Main Menu"
|
||||||
|
echo
|
||||||
|
echo -ne "''${CYAN}Select theme or option: ''${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_config_menu() {
|
||||||
|
show_header
|
||||||
|
echo -e "''${WHITE}⚙️ Configuration''${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "''${GREEN}1.''${NC} 📝 Edit Main Configuration"
|
||||||
|
echo -e "''${GREEN}2.''${NC} 🪟 Edit Hyprland Configuration"
|
||||||
|
echo -e "''${GREEN}3.''${NC} 🎨 Edit Theme Configuration"
|
||||||
|
echo -e "''${GREEN}4.''${NC} 📦 Edit Package Configuration"
|
||||||
|
echo -e "''${GREEN}5.''${NC} 🔒 Security Settings"
|
||||||
|
echo -e "''${GREEN}6.''${NC} 📂 Open Configuration Directory"
|
||||||
|
echo -e "''${GREEN}7.''${NC} 🔗 View Git Status"
|
||||||
|
echo
|
||||||
|
echo -e "''${YELLOW}0.''${NC} ← Back to Main Menu"
|
||||||
|
echo
|
||||||
|
echo -ne "''${CYAN}Select an option: ''${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_dev_menu() {
|
||||||
|
show_header
|
||||||
|
echo -e "''${WHITE}🔧 Development Tools''${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "''${GREEN}1.''${NC} 💻 Open Terminal"
|
||||||
|
echo -e "''${GREEN}2.''${NC} 📝 Open Code Editor"
|
||||||
|
echo -e "''${GREEN}3.''${NC} 🌐 Open Browser"
|
||||||
|
echo -e "''${GREEN}4.''${NC} 📁 Open File Manager"
|
||||||
|
echo -e "''${GREEN}5.''${NC} 🚀 Launch Applications"
|
||||||
|
echo -e "''${GREEN}6.''${NC} 🐙 Git Operations"
|
||||||
|
echo
|
||||||
|
echo -e "''${YELLOW}0.''${NC} ← Back to Main Menu"
|
||||||
|
echo
|
||||||
|
echo -ne "''${CYAN}Select an option: ''${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_info_menu() {
|
||||||
|
show_header
|
||||||
|
echo -e "''${WHITE}📊 System Information''${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "''${GREEN}1.''${NC} 🖥️ System Overview"
|
||||||
|
echo -e "''${GREEN}2.''${NC} 💻 Hardware Information"
|
||||||
|
echo -e "''${GREEN}3.''${NC} 📈 Performance Monitor"
|
||||||
|
echo -e "''${GREEN}4.''${NC} 🔧 Service Status"
|
||||||
|
echo -e "''${GREEN}5.''${NC} 💾 Disk Usage"
|
||||||
|
echo -e "''${GREEN}6.''${NC} 🌐 Network Information"
|
||||||
|
echo -e "''${GREEN}7.''${NC} 📊 Omnixient About"
|
||||||
|
echo
|
||||||
|
echo -e "''${YELLOW}0.''${NC} ← Back to Main Menu"
|
||||||
|
echo
|
||||||
|
echo -ne "''${CYAN}Select an option: ''${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_maintenance_menu() {
|
||||||
|
show_header
|
||||||
|
echo -e "''${WHITE}🛠️ Maintenance & Utilities''${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "''${GREEN}1.''${NC} 🧹 System Cleanup"
|
||||||
|
echo -e "''${GREEN}2.''${NC} 🔄 Restart Services"
|
||||||
|
echo -e "''${GREEN}3.''${NC} 📋 View Logs"
|
||||||
|
echo -e "''${GREEN}4.''${NC} 💾 Backup Configuration"
|
||||||
|
echo -e "''${GREEN}5.''${NC} 🔧 System Diagnostics"
|
||||||
|
echo -e "''${GREEN}6.''${NC} 🖼️ Screenshot Tools"
|
||||||
|
echo
|
||||||
|
echo -e "''${YELLOW}0.''${NC} ← Back to Main Menu"
|
||||||
|
echo
|
||||||
|
echo -ne "''${CYAN}Select an option: ''${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_help_menu() {
|
||||||
|
show_header
|
||||||
|
echo -e "''${WHITE}📋 Help & Documentation''${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "''${GREEN}1.''${NC} 📖 Omnixient Commands"
|
||||||
|
echo -e "''${GREEN}2.''${NC} 🔑 Keyboard Shortcuts"
|
||||||
|
echo -e "''${GREEN}3.''${NC} 🌐 Open GitHub Repository"
|
||||||
|
echo -e "''${GREEN}4.''${NC} 📧 Report Issue"
|
||||||
|
echo -e "''${GREEN}5.''${NC} ℹ️ About Omnixient"
|
||||||
|
echo
|
||||||
|
echo -e "''${YELLOW}0.''${NC} ← Back to Main Menu"
|
||||||
|
echo
|
||||||
|
echo -ne "''${CYAN}Select an option: ''${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_system_menu() {
|
||||||
|
case "$1" in
|
||||||
|
1) echo -e "''${GREEN}Updating system...''${NC}"; omni-update ;;
|
||||||
|
2) echo -e "''${GREEN}Rebuilding configuration...''${NC}"; omni-rebuild ;;
|
||||||
|
3) echo -e "''${GREEN}Testing configuration...''${NC}"; omni-test ;;
|
||||||
|
4) echo -e "''${GREEN}Cleaning system...''${NC}"; omni-clean ;;
|
||||||
|
5) echo -e "''${GREEN}Checking service status...''${NC}"; omni-services status ;;
|
||||||
|
6) echo -e "''${GREEN}Creating backup...''${NC}"; omni-backup ;;
|
||||||
|
7)
|
||||||
|
echo -ne "''${CYAN}Enter package name to search: ''${NC}"
|
||||||
|
read -r package
|
||||||
|
if [ -n "$package" ]; then
|
||||||
|
omni-search "$package"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
8) return 0 ;;
|
||||||
|
*) echo -e "''${RED}Invalid option!''${NC}" ;;
|
||||||
|
esac
|
||||||
|
echo
|
||||||
|
echo -ne "''${YELLOW}Press Enter to continue...''${NC}"
|
||||||
|
read -r
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_theme_menu() {
|
||||||
|
case "$1" in
|
||||||
|
1) omni-theme tokyo-night ;;
|
||||||
|
2) omni-theme catppuccin ;;
|
||||||
|
3) omni-theme gruvbox ;;
|
||||||
|
4) omni-theme nord ;;
|
||||||
|
5) omni-theme everforest ;;
|
||||||
|
6) omni-theme rose-pine ;;
|
||||||
|
7) omni-theme kanagawa ;;
|
||||||
|
8) omni-theme catppuccin-latte ;;
|
||||||
|
9) omni-theme matte-black ;;
|
||||||
|
a|A) omni-theme osaka-jade ;;
|
||||||
|
b|B) omni-theme ristretto ;;
|
||||||
|
0) return 0 ;;
|
||||||
|
*) echo -e "''${RED}Invalid option!''${NC}" ;;
|
||||||
|
esac
|
||||||
|
echo
|
||||||
|
echo -ne "''${YELLOW}Press Enter to continue...''${NC}"
|
||||||
|
read -r
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_config_menu() {
|
||||||
|
case "$1" in
|
||||||
|
1) omni-config main ;;
|
||||||
|
2) omni-config hyprland ;;
|
||||||
|
3) omni-config theme ;;
|
||||||
|
4) omni-config packages ;;
|
||||||
|
5)
|
||||||
|
echo -e "''${CYAN}Security Settings:''${NC}"
|
||||||
|
echo -e "''${WHITE}1. Security Status 2. Fingerprint Setup 3. FIDO2 Setup''${NC}"
|
||||||
|
echo -ne "''${CYAN}Select: ''${NC}"
|
||||||
|
read -r security_choice
|
||||||
|
case "$security_choice" in
|
||||||
|
1) omni-security status ;;
|
||||||
|
2) omni-fingerprint setup ;;
|
||||||
|
3) omni-fido2 setup ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
6) cd /etc/nixos && ''${TERMINAL:-ghostty} ;;
|
||||||
|
7) cd /etc/nixos && git status ;;
|
||||||
|
0) return 0 ;;
|
||||||
|
*) echo -e "''${RED}Invalid option!''${NC}" ;;
|
||||||
|
esac
|
||||||
|
echo
|
||||||
|
echo -ne "''${YELLOW}Press Enter to continue...''${NC}"
|
||||||
|
read -r
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_dev_menu() {
|
||||||
|
case "$1" in
|
||||||
|
1) ''${TERMINAL:-ghostty} ;;
|
||||||
|
2) code ;;
|
||||||
|
3) ''${BROWSER:-firefox} ;;
|
||||||
|
4) thunar ;;
|
||||||
|
5) walker ;;
|
||||||
|
6)
|
||||||
|
echo -e "''${CYAN}Git Operations:''${NC}"
|
||||||
|
echo -e "''${WHITE}1. Status 2. Log 3. Commit 4. Push''${NC}"
|
||||||
|
echo -ne "''${CYAN}Select: ''${NC}"
|
||||||
|
read -r git_choice
|
||||||
|
cd /etc/nixos
|
||||||
|
case "$git_choice" in
|
||||||
|
1) git status ;;
|
||||||
|
2) git log --oneline -10 ;;
|
||||||
|
3) echo -ne "''${CYAN}Commit message: ''${NC}"; read -r msg; git add -A && git commit -m "$msg" ;;
|
||||||
|
4) git push ;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
0) return 0 ;;
|
||||||
|
*) echo -e "''${RED}Invalid option!''${NC}" ;;
|
||||||
|
esac
|
||||||
|
echo
|
||||||
|
echo -ne "''${YELLOW}Press Enter to continue...''${NC}"
|
||||||
|
read -r
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_info_menu() {
|
||||||
|
case "$1" in
|
||||||
|
1) omni-sysinfo ;;
|
||||||
|
2) omni-hardware ;;
|
||||||
|
3) htop ;;
|
||||||
|
4) omni-services status ;;
|
||||||
|
5) df -h && echo && du -sh /nix/store ;;
|
||||||
|
6) ip addr show ;;
|
||||||
|
7) omni-about ;;
|
||||||
|
0) return 0 ;;
|
||||||
|
*) echo -e "''${RED}Invalid option!''${NC}" ;;
|
||||||
|
esac
|
||||||
|
echo
|
||||||
|
echo -ne "''${YELLOW}Press Enter to continue...''${NC}"
|
||||||
|
read -r
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_maintenance_menu() {
|
||||||
|
case "$1" in
|
||||||
|
1) omni-clean ;;
|
||||||
|
2)
|
||||||
|
echo -ne "''${CYAN}Enter service name: ''${NC}"
|
||||||
|
read -r service
|
||||||
|
if [ -n "$service" ]; then
|
||||||
|
omni-services restart "$service"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
echo -ne "''${CYAN}Enter service name for logs: ''${NC}"
|
||||||
|
read -r service
|
||||||
|
if [ -n "$service" ]; then
|
||||||
|
omni-services logs "$service"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
4) omni-backup ;;
|
||||||
|
5) echo -e "''${GREEN}Running diagnostics...''${NC}"; journalctl -p 3 -xb ;;
|
||||||
|
6) grim -g "$(slurp)" - | satty -f - --output-filename ~/Pictures/Screenshots/screenshot_$(date +'%Y-%m-%d-%H%M%S.png') ;;
|
||||||
|
0) return 0 ;;
|
||||||
|
*) echo -e "''${RED}Invalid option!''${NC}" ;;
|
||||||
|
esac
|
||||||
|
echo
|
||||||
|
echo -ne "''${YELLOW}Press Enter to continue...''${NC}"
|
||||||
|
read -r
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_help_menu() {
|
||||||
|
case "$1" in
|
||||||
|
1)
|
||||||
|
echo -e "''${WHITE}Omnixient Commands:''${NC}"
|
||||||
|
echo -e "''${GREEN}omni-menu''${NC} - This interactive menu"
|
||||||
|
echo -e "''${GREEN}omni-info''${NC} - System information display"
|
||||||
|
echo -e "''${GREEN}omni-about''${NC} - About screen"
|
||||||
|
echo -e "''${GREEN}omni-theme''${NC} - Switch themes"
|
||||||
|
echo -e "''${GREEN}omni-rebuild''${NC} - Rebuild configuration"
|
||||||
|
echo -e "''${GREEN}omni-update''${NC} - Update system"
|
||||||
|
echo -e "''${GREEN}omni-clean''${NC} - Clean system"
|
||||||
|
echo -e "''${GREEN}omni-search''${NC} - Search packages"
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
echo -e "''${WHITE}Hyprland Keyboard Shortcuts:''${NC}"
|
||||||
|
echo -e "''${GREEN}Super + Return''${NC} - Open terminal"
|
||||||
|
echo -e "''${GREEN}Super + R''${NC} - Open launcher"
|
||||||
|
echo -e "''${GREEN}Super + Q''${NC} - Close window"
|
||||||
|
echo -e "''${GREEN}Super + F''${NC} - Fullscreen"
|
||||||
|
echo -e "''${GREEN}Super + 1-0''${NC} - Switch workspaces"
|
||||||
|
;;
|
||||||
|
3) ''${BROWSER:-firefox} https://github.com/TheArctesian/omnixy ;;
|
||||||
|
4) ''${BROWSER:-firefox} https://github.com/TheArctesian/omnixy/issues ;;
|
||||||
|
5) omni-about ;;
|
||||||
|
0) return 0 ;;
|
||||||
|
*) echo -e "''${RED}Invalid option!''${NC}" ;;
|
||||||
|
esac
|
||||||
|
echo
|
||||||
|
echo -ne "''${YELLOW}Press Enter to continue...''${NC}"
|
||||||
|
read -r
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main menu loop
|
||||||
|
while true; do
|
||||||
|
show_main_menu
|
||||||
|
read -r choice
|
||||||
|
|
||||||
|
case "$choice" in
|
||||||
|
1)
|
||||||
|
while true; do
|
||||||
|
show_system_menu
|
||||||
|
read -r sub_choice
|
||||||
|
handle_system_menu "$sub_choice"
|
||||||
|
[ "$?" -eq 0 ] && break
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
while true; do
|
||||||
|
show_theme_menu
|
||||||
|
read -r sub_choice
|
||||||
|
handle_theme_menu "$sub_choice"
|
||||||
|
[ "$?" -eq 0 ] && break
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
while true; do
|
||||||
|
show_config_menu
|
||||||
|
read -r sub_choice
|
||||||
|
handle_config_menu "$sub_choice"
|
||||||
|
[ "$?" -eq 0 ] && break
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
4)
|
||||||
|
while true; do
|
||||||
|
show_dev_menu
|
||||||
|
read -r sub_choice
|
||||||
|
handle_dev_menu "$sub_choice"
|
||||||
|
[ "$?" -eq 0 ] && break
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
5)
|
||||||
|
while true; do
|
||||||
|
show_info_menu
|
||||||
|
read -r sub_choice
|
||||||
|
handle_info_menu "$sub_choice"
|
||||||
|
[ "$?" -eq 0 ] && break
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
6)
|
||||||
|
while true; do
|
||||||
|
show_maintenance_menu
|
||||||
|
read -r sub_choice
|
||||||
|
handle_maintenance_menu "$sub_choice"
|
||||||
|
[ "$?" -eq 0 ] && break
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
7)
|
||||||
|
while true; do
|
||||||
|
show_help_menu
|
||||||
|
read -r sub_choice
|
||||||
|
handle_help_menu "$sub_choice"
|
||||||
|
[ "$?" -eq 0 ] && break
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
0|q|Q)
|
||||||
|
echo -e "''${GREEN}Goodbye! 👋''${NC}"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "''${RED}Invalid option! Press Enter to continue...''${NC}"
|
||||||
|
read -r
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
'')
|
||||||
|
|
||||||
|
# Quick theme selector
|
||||||
|
(omni.makeScript "omni-theme-picker" "Quick theme picker with preview" ''
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
WHITE='\033[1;37m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
themes=(
|
||||||
|
"tokyo-night:🌃:Dark theme with vibrant colors"
|
||||||
|
"catppuccin:🎀:Pastel theme with modern aesthetics"
|
||||||
|
"gruvbox:🟤:Retro theme with warm colors"
|
||||||
|
"nord:❄️ :Arctic theme with cool colors"
|
||||||
|
"everforest:🌲:Green forest theme"
|
||||||
|
"rose-pine:🌹:Cozy theme with muted colors"
|
||||||
|
"kanagawa:🌊:Japanese-inspired theme"
|
||||||
|
"catppuccin-latte:☀️ :Light catppuccin variant"
|
||||||
|
"matte-black:⚫:Minimalist dark theme"
|
||||||
|
"osaka-jade:💎:Jade green accent theme"
|
||||||
|
"ristretto:☕:Coffee-inspired warm theme"
|
||||||
|
)
|
||||||
|
|
||||||
|
clear
|
||||||
|
echo -e "''${CYAN}🎨 Omnixient Theme Picker''${NC}"
|
||||||
|
echo -e "''${WHITE}Current Theme: ''${YELLOW}${cfg.theme}''${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "''${WHITE}Available Themes:''${NC}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
for i in "''${!themes[@]}"; do
|
||||||
|
IFS=':' read -ra theme_info <<< "''${themes[$i]}"
|
||||||
|
theme_name="''${theme_info[0]}"
|
||||||
|
theme_icon="''${theme_info[1]}"
|
||||||
|
theme_desc="''${theme_info[2]}"
|
||||||
|
|
||||||
|
printf "''${GREEN}%2d.''${NC} %s %-15s - %s\n" "$((i+1))" "$theme_icon" "$theme_name" "$theme_desc"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "''${RED} 0.''${NC} Cancel"
|
||||||
|
echo
|
||||||
|
echo -ne "''${CYAN}Select theme (1-''${#themes[@]}): ''${NC}"
|
||||||
|
read -r choice
|
||||||
|
|
||||||
|
if [[ "$choice" -ge 1 && "$choice" -le "''${#themes[@]}" ]]; then
|
||||||
|
IFS=':' read -ra theme_info <<< "''${themes[$((choice-1))]}"
|
||||||
|
selected_theme="''${theme_info[0]}"
|
||||||
|
|
||||||
|
echo -e "''${GREEN}Switching to ''${selected_theme}...''${NC}"
|
||||||
|
omni-theme "$selected_theme"
|
||||||
|
elif [[ "$choice" == "0" ]]; then
|
||||||
|
echo -e "''${YELLOW}Cancelled.''${NC}"
|
||||||
|
else
|
||||||
|
echo -e "''${RED}Invalid selection!''${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
|
||||||
|
# Shell aliases for easy access
|
||||||
|
home-manager.users.${config.omni.user} = {
|
||||||
|
programs.bash.shellAliases = {
|
||||||
|
menu = "omni-menu";
|
||||||
|
themes = "omni-theme-picker";
|
||||||
|
rebuild = mkDefault "omni-rebuild";
|
||||||
|
update = mkDefault "omni-update";
|
||||||
|
info = "omni-info";
|
||||||
|
clean = mkDefault "omni-clean";
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.zsh.shellAliases = {
|
||||||
|
menu = "omni-menu";
|
||||||
|
themes = "omni-theme-picker";
|
||||||
|
rebuild = mkDefault "omni-rebuild";
|
||||||
|
update = mkDefault "omni-update";
|
||||||
|
info = "omni-info";
|
||||||
|
clean = mkDefault "omni-clean";
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.fish.shellAliases = {
|
||||||
|
menu = "omni-menu";
|
||||||
|
themes = "omni-theme-picker";
|
||||||
|
rebuild = mkDefault "omni-rebuild";
|
||||||
|
update = mkDefault "omni-update";
|
||||||
|
info = "omni-info";
|
||||||
|
clean = mkDefault "omni-clean";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
540
modules/partitioning.sh
Executable file
540
modules/partitioning.sh
Executable file
|
|
@ -0,0 +1,540 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Omnixient Disk Partitioning Module
|
||||||
|
# Comprehensive partitioning with LUKS encryption support
|
||||||
|
# Follows NixOS Installation Guide recommendations
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Color setup for output
|
||||||
|
setup_colors() {
|
||||||
|
RED=$(printf '\033[38;2;247;118;142m')
|
||||||
|
GREEN=$(printf '\033[38;2;158;206;106m')
|
||||||
|
YELLOW=$(printf '\033[38;2;224;175;104m')
|
||||||
|
CYAN=$(printf '\033[38;2;125;207;255m')
|
||||||
|
BLUE=$(printf '\033[38;2;122;162;247m')
|
||||||
|
PURPLE=$(printf '\033[38;2;187;154;247m')
|
||||||
|
FG=$(printf '\033[38;2;192;202;245m')
|
||||||
|
BOLD=$(printf '\033[1m')
|
||||||
|
DIM=$(printf '\033[2m')
|
||||||
|
RESET=$(printf '\033[0m')
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_colors
|
||||||
|
|
||||||
|
# Utility functions
|
||||||
|
log_info() {
|
||||||
|
echo -e "${CYAN}[INFO]${RESET} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_success() {
|
||||||
|
echo -e "${GREEN}[✓]${RESET} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error() {
|
||||||
|
echo -e "${RED}[ERROR]${RESET} $1" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
log_warn() {
|
||||||
|
echo -e "${YELLOW}[WARN]${RESET} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# VM Detection
|
||||||
|
detect_vm() {
|
||||||
|
if systemd-detect-virt >/dev/null 2>&1; then
|
||||||
|
local virt_type=$(systemd-detect-virt)
|
||||||
|
if [ "$virt_type" != "none" ]; then
|
||||||
|
log_info "Running in virtualized environment: $virt_type"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# List available disks
|
||||||
|
list_disks() {
|
||||||
|
log_info "Available disks:"
|
||||||
|
echo
|
||||||
|
lsblk -d -n -o NAME,SIZE,TYPE,MODEL | while read -r name size type model; do
|
||||||
|
# Include both sd* and vd* devices
|
||||||
|
if [[ "$name" =~ ^(sd|vd|nvme) ]]; then
|
||||||
|
echo " ${CYAN}/dev/$name${RESET} - $size - $model"
|
||||||
|
# Show existing partitions if any
|
||||||
|
lsblk /dev/$name -n -o NAME,SIZE,FSTYPE,MOUNTPOINT 2>/dev/null | tail -n +2 | while read -r part psize fstype mount; do
|
||||||
|
echo " └─ $part - $psize - ${fstype:-none} ${mount:+(mounted: $mount)}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Disk selection with VM support
|
||||||
|
select_disk() {
|
||||||
|
list_disks
|
||||||
|
|
||||||
|
local selected_disk=""
|
||||||
|
while [ -z "$selected_disk" ]; do
|
||||||
|
read -p "${CYAN}Enter disk device (e.g., /dev/sda, /dev/vda, /dev/nvme0n1): ${RESET}" disk_input
|
||||||
|
|
||||||
|
# Normalize input
|
||||||
|
if [[ ! "$disk_input" =~ ^/dev/ ]]; then
|
||||||
|
disk_input="/dev/$disk_input"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate disk exists
|
||||||
|
if [ -b "$disk_input" ]; then
|
||||||
|
# Confirm destructive operation
|
||||||
|
echo
|
||||||
|
log_warn "WARNING: All data on $disk_input will be destroyed!"
|
||||||
|
read -p "${YELLOW}Type 'yes' to confirm: ${RESET}" confirm
|
||||||
|
if [ "$confirm" = "yes" ]; then
|
||||||
|
selected_disk="$disk_input"
|
||||||
|
else
|
||||||
|
log_info "Disk selection cancelled"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_error "Device $disk_input does not exist or is not a block device"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "$selected_disk"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Partition scheme selection
|
||||||
|
select_partition_scheme() {
|
||||||
|
echo
|
||||||
|
log_info "Select partition scheme:"
|
||||||
|
echo " 1) Automatic - Standard layout with optional encryption"
|
||||||
|
echo " 2) Manual - Use existing partitions"
|
||||||
|
echo " 3) Custom - Interactive partitioning"
|
||||||
|
echo
|
||||||
|
|
||||||
|
local scheme=""
|
||||||
|
while [ -z "$scheme" ]; do
|
||||||
|
read -p "${CYAN}Choice (1-3): ${RESET}" choice
|
||||||
|
case $choice in
|
||||||
|
1) scheme="automatic";;
|
||||||
|
2) scheme="manual";;
|
||||||
|
3) scheme="custom";;
|
||||||
|
*) log_error "Invalid choice";;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "$scheme"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Detect boot mode (UEFI or BIOS)
|
||||||
|
detect_boot_mode() {
|
||||||
|
if [ -d /sys/firmware/efi/efivars ]; then
|
||||||
|
echo "uefi"
|
||||||
|
else
|
||||||
|
echo "bios"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Automatic partitioning with LUKS support
|
||||||
|
automatic_partition() {
|
||||||
|
local disk="$1"
|
||||||
|
local encrypt="${2:-false}"
|
||||||
|
local boot_mode=$(detect_boot_mode)
|
||||||
|
|
||||||
|
log_info "Starting automatic partitioning on $disk"
|
||||||
|
log_info "Boot mode: $boot_mode"
|
||||||
|
|
||||||
|
# Wipe disk
|
||||||
|
log_info "Wiping disk..."
|
||||||
|
wipefs -af "$disk" >/dev/null 2>&1
|
||||||
|
sgdisk -Z "$disk" >/dev/null 2>&1
|
||||||
|
|
||||||
|
# Create partition table
|
||||||
|
if [ "$boot_mode" = "uefi" ]; then
|
||||||
|
log_info "Creating GPT partition table..."
|
||||||
|
parted -s "$disk" mklabel gpt
|
||||||
|
|
||||||
|
# Create partitions
|
||||||
|
log_info "Creating EFI partition..."
|
||||||
|
parted -s "$disk" mkpart ESP fat32 1MiB 512MiB
|
||||||
|
parted -s "$disk" set 1 esp on
|
||||||
|
|
||||||
|
log_info "Creating boot partition..."
|
||||||
|
parted -s "$disk" mkpart primary ext4 512MiB 1GiB
|
||||||
|
|
||||||
|
log_info "Creating root partition..."
|
||||||
|
parted -s "$disk" mkpart primary 1GiB 100%
|
||||||
|
|
||||||
|
# Wait for kernel to recognize partitions
|
||||||
|
partprobe "$disk"
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Determine partition naming
|
||||||
|
if [[ "$disk" =~ nvme ]]; then
|
||||||
|
local efi_part="${disk}p1"
|
||||||
|
local boot_part="${disk}p2"
|
||||||
|
local root_part="${disk}p3"
|
||||||
|
else
|
||||||
|
local efi_part="${disk}1"
|
||||||
|
local boot_part="${disk}2"
|
||||||
|
local root_part="${disk}3"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_info "Creating MBR partition table..."
|
||||||
|
parted -s "$disk" mklabel msdos
|
||||||
|
|
||||||
|
log_info "Creating boot partition..."
|
||||||
|
parted -s "$disk" mkpart primary ext4 1MiB 512MiB
|
||||||
|
parted -s "$disk" set 1 boot on
|
||||||
|
|
||||||
|
log_info "Creating root partition..."
|
||||||
|
parted -s "$disk" mkpart primary 512MiB 100%
|
||||||
|
|
||||||
|
# Wait for kernel to recognize partitions
|
||||||
|
partprobe "$disk"
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Determine partition naming
|
||||||
|
if [[ "$disk" =~ nvme ]]; then
|
||||||
|
local boot_part="${disk}p1"
|
||||||
|
local root_part="${disk}p2"
|
||||||
|
else
|
||||||
|
local boot_part="${disk}1"
|
||||||
|
local root_part="${disk}2"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Setup encryption if requested
|
||||||
|
if [ "$encrypt" = "true" ]; then
|
||||||
|
log_info "Setting up LUKS encryption..."
|
||||||
|
|
||||||
|
# Get passphrase
|
||||||
|
local passphrase=""
|
||||||
|
local passphrase_confirm=""
|
||||||
|
while true; do
|
||||||
|
read -s -p "${CYAN}Enter LUKS passphrase: ${RESET}" passphrase
|
||||||
|
echo
|
||||||
|
read -s -p "${CYAN}Confirm passphrase: ${RESET}" passphrase_confirm
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [ "$passphrase" = "$passphrase_confirm" ]; then
|
||||||
|
if [ ${#passphrase} -ge 8 ]; then
|
||||||
|
break
|
||||||
|
else
|
||||||
|
log_error "Passphrase must be at least 8 characters"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_error "Passphrases do not match"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Encrypt root partition
|
||||||
|
log_info "Encrypting root partition..."
|
||||||
|
echo -n "$passphrase" | cryptsetup luksFormat --type luks2 "$root_part" -
|
||||||
|
|
||||||
|
log_info "Opening encrypted partition..."
|
||||||
|
echo -n "$passphrase" | cryptsetup open "$root_part" cryptroot -
|
||||||
|
|
||||||
|
# Update root partition reference
|
||||||
|
root_part="/dev/mapper/cryptroot"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Format partitions
|
||||||
|
log_info "Formatting partitions..."
|
||||||
|
|
||||||
|
if [ "$boot_mode" = "uefi" ]; then
|
||||||
|
mkfs.fat -F32 -n ESP "$efi_part"
|
||||||
|
mkfs.ext4 -L boot "$boot_part"
|
||||||
|
else
|
||||||
|
mkfs.ext4 -L boot "$boot_part"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Format root - offer filesystem choice
|
||||||
|
echo
|
||||||
|
log_info "Select root filesystem:"
|
||||||
|
echo " 1) ext4 (recommended, stable)"
|
||||||
|
echo " 2) btrfs (snapshots, compression)"
|
||||||
|
echo " 3) zfs (advanced features, requires setup)"
|
||||||
|
echo
|
||||||
|
|
||||||
|
local fs_type="ext4"
|
||||||
|
read -p "${CYAN}Choice (1-3) [default: 1]: ${RESET}" fs_choice
|
||||||
|
case $fs_choice in
|
||||||
|
2) fs_type="btrfs";;
|
||||||
|
3) fs_type="zfs";;
|
||||||
|
*) fs_type="ext4";;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case $fs_type in
|
||||||
|
ext4)
|
||||||
|
mkfs.ext4 -L nixos "$root_part"
|
||||||
|
;;
|
||||||
|
btrfs)
|
||||||
|
mkfs.btrfs -L nixos "$root_part"
|
||||||
|
;;
|
||||||
|
zfs)
|
||||||
|
log_warn "ZFS requires additional setup"
|
||||||
|
# Create ZFS pool
|
||||||
|
zpool create -f -o ashift=12 -O compression=lz4 -O xattr=sa -O acltype=posixacl -O mountpoint=none rpool "$root_part"
|
||||||
|
zfs create -o mountpoint=legacy rpool/root
|
||||||
|
zfs create -o mountpoint=legacy rpool/home
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Mount partitions
|
||||||
|
log_info "Mounting partitions..."
|
||||||
|
|
||||||
|
# Mount root
|
||||||
|
if [ "$fs_type" = "zfs" ]; then
|
||||||
|
mount -t zfs rpool/root /mnt
|
||||||
|
mkdir -p /mnt/home
|
||||||
|
mount -t zfs rpool/home /mnt/home
|
||||||
|
else
|
||||||
|
mount "$root_part" /mnt
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Mount boot
|
||||||
|
mkdir -p /mnt/boot
|
||||||
|
mount "$boot_part" /mnt/boot
|
||||||
|
|
||||||
|
# Mount EFI if UEFI
|
||||||
|
if [ "$boot_mode" = "uefi" ]; then
|
||||||
|
mkdir -p /mnt/boot/efi
|
||||||
|
mount "$efi_part" /mnt/boot/efi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create swap file
|
||||||
|
log_info "Creating swap file..."
|
||||||
|
local ram_size=$(free -g | awk '/^Mem:/{print $2}')
|
||||||
|
local swap_size=$((ram_size < 8 ? ram_size * 2 : ram_size))
|
||||||
|
|
||||||
|
if [ "$fs_type" = "btrfs" ]; then
|
||||||
|
# Btrfs requires special handling for swap
|
||||||
|
btrfs subvolume create /mnt/swap
|
||||||
|
truncate -s 0 /mnt/swap/swapfile
|
||||||
|
chattr +C /mnt/swap/swapfile
|
||||||
|
fallocate -l ${swap_size}G /mnt/swap/swapfile
|
||||||
|
else
|
||||||
|
fallocate -l ${swap_size}G /mnt/swapfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod 600 /mnt/swapfile
|
||||||
|
mkswap /mnt/swapfile
|
||||||
|
swapon /mnt/swapfile
|
||||||
|
|
||||||
|
log_success "Automatic partitioning complete"
|
||||||
|
|
||||||
|
# Return partition information
|
||||||
|
cat <<EOF
|
||||||
|
PARTITION_INFO
|
||||||
|
DISK=$disk
|
||||||
|
BOOT_MODE=$boot_mode
|
||||||
|
ROOT_PART=$root_part
|
||||||
|
BOOT_PART=$boot_part
|
||||||
|
${boot_mode:+EFI_PART=$efi_part}
|
||||||
|
FS_TYPE=$fs_type
|
||||||
|
ENCRYPTED=$encrypt
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# Manual partition selection
|
||||||
|
manual_partition() {
|
||||||
|
log_info "Manual partition selection"
|
||||||
|
echo
|
||||||
|
log_info "Available partitions:"
|
||||||
|
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Get root partition
|
||||||
|
local root_part=""
|
||||||
|
while [ -z "$root_part" ]; do
|
||||||
|
read -p "${CYAN}Enter root partition (e.g., /dev/sda2): ${RESET}" root_part
|
||||||
|
if [ ! -b "$root_part" ]; then
|
||||||
|
log_error "Partition $root_part does not exist"
|
||||||
|
root_part=""
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check if encrypted
|
||||||
|
local encrypted="false"
|
||||||
|
if cryptsetup isLuks "$root_part" 2>/dev/null; then
|
||||||
|
log_info "Detected LUKS encrypted partition"
|
||||||
|
encrypted="true"
|
||||||
|
read -s -p "${CYAN}Enter passphrase: ${RESET}" passphrase
|
||||||
|
echo
|
||||||
|
echo -n "$passphrase" | cryptsetup open "$root_part" cryptroot -
|
||||||
|
root_part="/dev/mapper/cryptroot"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get boot partition
|
||||||
|
local boot_part=""
|
||||||
|
read -p "${CYAN}Enter boot partition (leave empty if combined with root): ${RESET}" boot_part
|
||||||
|
|
||||||
|
# Get EFI partition if UEFI
|
||||||
|
local efi_part=""
|
||||||
|
if [ "$(detect_boot_mode)" = "uefi" ]; then
|
||||||
|
read -p "${CYAN}Enter EFI partition: ${RESET}" efi_part
|
||||||
|
if [ ! -b "$efi_part" ]; then
|
||||||
|
log_error "EFI partition required for UEFI systems"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Mount partitions
|
||||||
|
log_info "Mounting partitions..."
|
||||||
|
mount "$root_part" /mnt
|
||||||
|
|
||||||
|
if [ -n "$boot_part" ]; then
|
||||||
|
mkdir -p /mnt/boot
|
||||||
|
mount "$boot_part" /mnt/boot
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$efi_part" ]; then
|
||||||
|
mkdir -p /mnt/boot/efi
|
||||||
|
mount "$efi_part" /mnt/boot/efi
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "Manual partition setup complete"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Custom interactive partitioning
|
||||||
|
custom_partition() {
|
||||||
|
local disk="$1"
|
||||||
|
|
||||||
|
log_info "Starting custom partitioning with gdisk/fdisk"
|
||||||
|
log_warn "This will launch an interactive partitioning tool"
|
||||||
|
echo
|
||||||
|
echo "Guidelines:"
|
||||||
|
echo " - UEFI systems: Create EFI (512MB), boot (512MB), and root partitions"
|
||||||
|
echo " - BIOS systems: Create boot (512MB) and root partitions"
|
||||||
|
echo " - Consider leaving space for swap or using a swap file"
|
||||||
|
echo
|
||||||
|
read -p "${CYAN}Press Enter to continue...${RESET}"
|
||||||
|
|
||||||
|
# Launch appropriate tool
|
||||||
|
if command -v gdisk >/dev/null; then
|
||||||
|
gdisk "$disk"
|
||||||
|
elif command -v fdisk >/dev/null; then
|
||||||
|
fdisk "$disk"
|
||||||
|
else
|
||||||
|
log_error "No partitioning tool available"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# After partitioning, guide through formatting
|
||||||
|
log_info "Partitioning complete. Now format and mount partitions."
|
||||||
|
manual_partition
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validate mount points
|
||||||
|
validate_mounts() {
|
||||||
|
log_info "Validating mount points..."
|
||||||
|
|
||||||
|
# Check root is mounted
|
||||||
|
if ! mountpoint -q /mnt; then
|
||||||
|
log_error "Root filesystem not mounted at /mnt"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check boot for UEFI
|
||||||
|
if [ "$(detect_boot_mode)" = "uefi" ]; then
|
||||||
|
if ! mountpoint -q /mnt/boot/efi && ! mountpoint -q /mnt/boot; then
|
||||||
|
log_error "EFI partition not mounted"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "Mount points validated"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate hardware configuration
|
||||||
|
generate_hardware_config() {
|
||||||
|
log_info "Generating NixOS hardware configuration..."
|
||||||
|
nixos-generate-config --root /mnt
|
||||||
|
log_success "Hardware configuration generated"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main partitioning flow
|
||||||
|
main() {
|
||||||
|
echo
|
||||||
|
log_info "${BOLD}Omnixient Disk Partitioning Module${RESET}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
log_error "This script must be run as root"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Detect VM environment
|
||||||
|
if detect_vm; then
|
||||||
|
log_info "VM environment detected - looking for vda devices"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if already mounted
|
||||||
|
if mountpoint -q /mnt; then
|
||||||
|
log_warn "/mnt is already mounted"
|
||||||
|
read -p "${YELLOW}Unmount and continue? (y/N): ${RESET}" unmount
|
||||||
|
if [ "$unmount" = "y" ]; then
|
||||||
|
umount -R /mnt 2>/dev/null || true
|
||||||
|
swapoff -a 2>/dev/null || true
|
||||||
|
else
|
||||||
|
log_info "Using existing mount points"
|
||||||
|
validate_mounts && generate_hardware_config
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Select partitioning method
|
||||||
|
local scheme=$(select_partition_scheme)
|
||||||
|
|
||||||
|
case $scheme in
|
||||||
|
automatic)
|
||||||
|
local disk=$(select_disk)
|
||||||
|
|
||||||
|
# Ask about encryption
|
||||||
|
local encrypt="false"
|
||||||
|
read -p "${CYAN}Enable LUKS encryption? (y/N): ${RESET}" use_encryption
|
||||||
|
if [ "$use_encryption" = "y" ]; then
|
||||||
|
encrypt="true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
automatic_partition "$disk" "$encrypt"
|
||||||
|
;;
|
||||||
|
|
||||||
|
manual)
|
||||||
|
manual_partition
|
||||||
|
;;
|
||||||
|
|
||||||
|
custom)
|
||||||
|
local disk=$(select_disk)
|
||||||
|
custom_partition "$disk"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Validate and generate config
|
||||||
|
if validate_mounts; then
|
||||||
|
generate_hardware_config
|
||||||
|
|
||||||
|
echo
|
||||||
|
log_success "${BOLD}Partitioning complete!${RESET}"
|
||||||
|
echo
|
||||||
|
log_info "Next steps:"
|
||||||
|
echo " 1. Install Omnixient configuration to /mnt/etc/nixos"
|
||||||
|
echo " 2. Run nixos-install"
|
||||||
|
echo " 3. Set root password when prompted"
|
||||||
|
echo " 4. Reboot into your new system"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Save partition info for installer
|
||||||
|
if [ -n "$PARTITION_INFO" ]; then
|
||||||
|
echo "$PARTITION_INFO" > /tmp/omni-partition-info
|
||||||
|
log_info "Partition information saved to /tmp/omni-partition-info"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_error "Mount validation failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run if executed directly
|
||||||
|
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
|
||||||
|
main "$@"
|
||||||
|
fi
|
||||||
373
modules/scripts.nix
Normal file
373
modules/scripts.nix
Normal file
|
|
@ -0,0 +1,373 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
# Essential system utility scripts for Omnixient
|
||||||
|
# Convenient scripts for system management and productivity
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) mkIf;
|
||||||
|
cfg = config.omni;
|
||||||
|
omni = config.omni.lib;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
config = mkIf (cfg.enable or true) {
|
||||||
|
# System utility scripts
|
||||||
|
environment.systemPackages = [
|
||||||
|
# System information and monitoring
|
||||||
|
(omni.makeScript "omni-sysinfo" "Show comprehensive system information" ''
|
||||||
|
echo "╭─────────────────── Omnixient System Info ───────────────────╮"
|
||||||
|
echo "│"
|
||||||
|
echo "│ 💻 System: $(hostname) ($(uname -m))"
|
||||||
|
echo "│ 🐧 OS: NixOS $(nixos-version)"
|
||||||
|
echo "│ 🎨 Theme: ${cfg.theme}"
|
||||||
|
echo "│ 👤 User: ${cfg.user}"
|
||||||
|
echo "│ 🏠 Preset: ${cfg.preset or "custom"}"
|
||||||
|
echo "│"
|
||||||
|
echo "│ 🔧 Uptime: $(uptime -p)"
|
||||||
|
echo "│ 💾 Memory: $(free -h | awk 'NR==2{printf "%.1f/%.1fGB (%.0f%%)", $3/1024/1024, $2/1024/1024, $3*100/$2}')"
|
||||||
|
echo "│ 💽 Disk: $(df -h / | awk 'NR==2{printf "%s/%s (%s)", $3, $2, $5}')"
|
||||||
|
echo "│ 🌡️ Load: $(uptime | sed 's/.*load average: //')"
|
||||||
|
echo "│"
|
||||||
|
echo "│ 📦 Packages: $(nix-env -qa --installed | wc -l) installed"
|
||||||
|
echo "│ 🗂️ Generations: $(sudo nix-env -p /nix/var/nix/profiles/system --list-generations | wc -l) total"
|
||||||
|
echo "│"
|
||||||
|
echo "╰───────────────────────────────────────────────────────────╯"
|
||||||
|
'')
|
||||||
|
|
||||||
|
# Quick system maintenance
|
||||||
|
(omni.makeScript "omni-clean" "Clean system (garbage collect, optimize)" ''
|
||||||
|
echo "🧹 Cleaning Omnixient system..."
|
||||||
|
|
||||||
|
echo " ├─ Collecting garbage..."
|
||||||
|
sudo nix-collect-garbage -d
|
||||||
|
|
||||||
|
echo " ├─ Optimizing store..."
|
||||||
|
sudo nix-store --optimize
|
||||||
|
|
||||||
|
echo " ├─ Clearing user caches..."
|
||||||
|
rm -rf ~/.cache/thumbnails/*
|
||||||
|
rm -rf ~/.cache/mesa_shader_cache/*
|
||||||
|
rm -rf ~/.cache/fontconfig/*
|
||||||
|
|
||||||
|
echo " ├─ Clearing logs..."
|
||||||
|
sudo journalctl --vacuum-time=7d
|
||||||
|
|
||||||
|
echo " └─ Cleaning complete!"
|
||||||
|
|
||||||
|
# Show space saved
|
||||||
|
echo
|
||||||
|
echo "💾 Disk usage:"
|
||||||
|
df -h / | awk 'NR==2{printf " Root: %s/%s (%s used)\n", $3, $2, $5}'
|
||||||
|
du -sh /nix/store | awk '{printf " Nix Store: %s\n", $1}'
|
||||||
|
'')
|
||||||
|
|
||||||
|
# Update system and flake
|
||||||
|
(omni.makeScript "omni-update" "Update system and flake inputs" ''
|
||||||
|
echo "📦 Updating Omnixient system..."
|
||||||
|
|
||||||
|
cd /etc/nixos || { echo "❌ Not in /etc/nixos directory"; exit 1; }
|
||||||
|
|
||||||
|
echo " ├─ Updating flake inputs..."
|
||||||
|
sudo nix flake update
|
||||||
|
|
||||||
|
echo " ├─ Rebuilding system..."
|
||||||
|
nh os switch /etc/nixos
|
||||||
|
|
||||||
|
echo " └─ Update complete!"
|
||||||
|
|
||||||
|
# Show new generation
|
||||||
|
echo
|
||||||
|
echo "🎯 Current generation:"
|
||||||
|
sudo nix-env -p /nix/var/nix/profiles/system --list-generations | tail -1
|
||||||
|
'')
|
||||||
|
|
||||||
|
# Rebuild system configuration
|
||||||
|
(omni.makeScript "omni-rebuild" "Rebuild NixOS configuration" ''
|
||||||
|
echo "🔨 Rebuilding Omnixient configuration..."
|
||||||
|
|
||||||
|
cd /etc/nixos || { echo "❌ Not in /etc/nixos directory"; exit 1; }
|
||||||
|
|
||||||
|
# Pull latest changes if the tree is clean
|
||||||
|
if git diff --quiet && git diff --cached --quiet; then
|
||||||
|
echo "📥 Pulling latest changes..."
|
||||||
|
sudo git pull --ff-only || echo "⚠️ Pull failed — continuing with local config"
|
||||||
|
else
|
||||||
|
echo "⚠️ Uncommitted changes — skipping pull"
|
||||||
|
echo " Commit or stash them to pull on next rebuild"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build and switch via nh (Rust nixos-rebuild frontend; elevates itself)
|
||||||
|
nh os switch /etc/nixos
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "✅ Rebuild successful!"
|
||||||
|
echo "🎯 Active generation: $(sudo nix-env -p /nix/var/nix/profiles/system --list-generations | tail -1)"
|
||||||
|
else
|
||||||
|
echo "❌ Rebuild failed!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
'')
|
||||||
|
|
||||||
|
# Test build without switching
|
||||||
|
(omni.makeScript "omni-test" "Test build configuration without switching" ''
|
||||||
|
echo "🧪 Testing Omnixient configuration..."
|
||||||
|
|
||||||
|
cd /etc/nixos || { echo "❌ Not in /etc/nixos directory"; exit 1; }
|
||||||
|
|
||||||
|
# Build without switching
|
||||||
|
sudo nixos-rebuild build --flake .#omni
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "✅ Build test successful!"
|
||||||
|
echo " Configuration is valid and ready for deployment"
|
||||||
|
else
|
||||||
|
echo "❌ Build test failed!"
|
||||||
|
echo " Fix configuration errors before rebuilding"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
'')
|
||||||
|
|
||||||
|
# Search for packages
|
||||||
|
(omni.makeScript "omni-search" "Search for NixOS packages" ''
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
echo "Usage: omni-search <package-name>"
|
||||||
|
echo "Search for packages in nixpkgs"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "🔍 Searching for packages matching '$1'..."
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Search in nixpkgs
|
||||||
|
nix search nixpkgs "$1" | head -20
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "💡 Install with: nix-env -iA nixpkgs.<package>"
|
||||||
|
echo " Or add to your configuration.nix"
|
||||||
|
'')
|
||||||
|
|
||||||
|
# Theme management
|
||||||
|
(omni.makeScript "omni-theme" "Switch Omnixient theme" ''
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
echo "🎨 Available Omnixient themes:"
|
||||||
|
echo " tokyo-night - Dark theme with vibrant colors"
|
||||||
|
echo " catppuccin - Pastel theme with modern aesthetics"
|
||||||
|
echo " gruvbox - Retro theme with warm colors"
|
||||||
|
echo " nord - Arctic theme with cool colors"
|
||||||
|
echo " everforest - Green forest theme"
|
||||||
|
echo " rose-pine - Cozy theme with muted colors"
|
||||||
|
echo " kanagawa - Japanese-inspired theme"
|
||||||
|
echo " catppuccin-latte - Light catppuccin variant"
|
||||||
|
echo " matte-black - Minimalist dark theme"
|
||||||
|
echo " osaka-jade - Jade green accent theme"
|
||||||
|
echo " ristretto - Coffee-inspired warm theme"
|
||||||
|
echo
|
||||||
|
echo "Usage: omni-theme <theme-name>"
|
||||||
|
echo "Current theme: ${cfg.theme}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
THEME="$1"
|
||||||
|
CONFIG_FILE="/etc/nixos/configuration.nix"
|
||||||
|
|
||||||
|
echo "🎨 Switching to theme: $THEME"
|
||||||
|
|
||||||
|
# Validate theme exists
|
||||||
|
if [ ! -f "/etc/nixos/modules/themes/$THEME.nix" ]; then
|
||||||
|
echo "❌ Theme '$THEME' not found!"
|
||||||
|
echo " Available themes listed above"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Update configuration.nix
|
||||||
|
sudo sed -i "s/currentTheme = \".*\";/currentTheme = \"$THEME\";/" "$CONFIG_FILE"
|
||||||
|
|
||||||
|
echo " ├─ Updated configuration..."
|
||||||
|
echo " ├─ Rebuilding system..."
|
||||||
|
|
||||||
|
# Rebuild with new theme
|
||||||
|
cd /etc/nixos && nh os switch /etc/nixos
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo " ├─ Theme switched successfully!"
|
||||||
|
echo " └─ Updating Plymouth boot theme..."
|
||||||
|
|
||||||
|
# Update Plymouth theme to match
|
||||||
|
sudo omni-plymouth-theme "$THEME" 2>/dev/null || echo " (Plymouth theme update may require reboot)"
|
||||||
|
|
||||||
|
echo "✅ Now using theme: $THEME"
|
||||||
|
echo "💡 Reboot to see the new boot splash screen"
|
||||||
|
else
|
||||||
|
echo "❌ Failed to apply theme!"
|
||||||
|
# Revert change
|
||||||
|
sudo sed -i "s/currentTheme = \"$THEME\";/currentTheme = \"${cfg.theme}\";/" "$CONFIG_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
'')
|
||||||
|
|
||||||
|
# Hardware information
|
||||||
|
(omni.makeScript "omni-hardware" "Show detailed hardware information" ''
|
||||||
|
echo "🖥️ Omnixient Hardware Information"
|
||||||
|
echo "═══════════════════════════════════"
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "💻 System:"
|
||||||
|
echo " Model: $(cat /sys/class/dmi/id/product_name 2>/dev/null || echo 'Unknown')"
|
||||||
|
echo " Manufacturer: $(cat /sys/class/dmi/id/sys_vendor 2>/dev/null || echo 'Unknown')"
|
||||||
|
echo " BIOS: $(cat /sys/class/dmi/id/bios_version 2>/dev/null || echo 'Unknown')"
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "🧠 CPU:"
|
||||||
|
lscpu | grep -E "Model name|Architecture|CPU\(s\)|Thread|Core|MHz"
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "💾 Memory:"
|
||||||
|
free -h
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "💽 Storage:"
|
||||||
|
lsblk -f
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "📺 Graphics:"
|
||||||
|
lspci | grep -i vga
|
||||||
|
lspci | grep -i 3d
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "🔊 Audio:"
|
||||||
|
lspci | grep -i audio
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "🌐 Network:"
|
||||||
|
ip addr show | grep -E "inet |link/"
|
||||||
|
'')
|
||||||
|
|
||||||
|
# Service management
|
||||||
|
(omni.makeScript "omni-services" "Manage Omnixient services" ''
|
||||||
|
case "$1" in
|
||||||
|
"status")
|
||||||
|
echo "📊 Omnixient Service Status"
|
||||||
|
echo "═══════════════════════"
|
||||||
|
|
||||||
|
services=(
|
||||||
|
"display-manager"
|
||||||
|
"networkmanager"
|
||||||
|
"pipewire"
|
||||||
|
"bluetooth"
|
||||||
|
"hypridle"
|
||||||
|
)
|
||||||
|
|
||||||
|
for service in "''${services[@]}"; do
|
||||||
|
status=$(systemctl is-active $service 2>/dev/null || echo "inactive")
|
||||||
|
case $status in
|
||||||
|
"active") icon="✅" ;;
|
||||||
|
"inactive") icon="❌" ;;
|
||||||
|
*) icon="⚠️ " ;;
|
||||||
|
esac
|
||||||
|
printf " %s %s: %s\n" "$icon" "$service" "$status"
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
"restart")
|
||||||
|
if [ -z "$2" ]; then
|
||||||
|
echo "Usage: omni-services restart <service-name>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "🔄 Restarting $2..."
|
||||||
|
sudo systemctl restart "$2"
|
||||||
|
;;
|
||||||
|
"logs")
|
||||||
|
if [ -z "$2" ]; then
|
||||||
|
echo "Usage: omni-services logs <service-name>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
journalctl -u "$2" -f
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "📋 Omnixient Service Management"
|
||||||
|
echo
|
||||||
|
echo "Usage: omni-services <command> [service]"
|
||||||
|
echo
|
||||||
|
echo "Commands:"
|
||||||
|
echo " status - Show status of key services"
|
||||||
|
echo " restart <name> - Restart a service"
|
||||||
|
echo " logs <name> - View service logs"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
'')
|
||||||
|
|
||||||
|
# Quick configuration editing
|
||||||
|
(omni.makeScript "omni-config" "Quick access to configuration files" ''
|
||||||
|
case "$1" in
|
||||||
|
"main"|"")
|
||||||
|
echo "📝 Opening main configuration..."
|
||||||
|
''${EDITOR:-nano} /etc/nixos/configuration.nix
|
||||||
|
;;
|
||||||
|
"hyprland")
|
||||||
|
echo "📝 Opening Hyprland configuration..."
|
||||||
|
''${EDITOR:-nano} /etc/nixos/modules/desktop/hyprland.nix
|
||||||
|
;;
|
||||||
|
"theme")
|
||||||
|
echo "📝 Opening theme configuration..."
|
||||||
|
''${EDITOR:-nano} /etc/nixos/modules/themes/${cfg.theme}.nix
|
||||||
|
;;
|
||||||
|
"packages")
|
||||||
|
echo "📝 Opening package configuration..."
|
||||||
|
''${EDITOR:-nano} /etc/nixos/modules/packages.nix
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "📝 Omnixient Configuration Files"
|
||||||
|
echo
|
||||||
|
echo "Usage: omni-config <target>"
|
||||||
|
echo
|
||||||
|
echo "Targets:"
|
||||||
|
echo " main - Main configuration.nix file"
|
||||||
|
echo " hyprland - Hyprland window manager config"
|
||||||
|
echo " theme - Current theme configuration"
|
||||||
|
echo " packages - Package configuration"
|
||||||
|
echo
|
||||||
|
echo "Files will open in: ''${EDITOR:-nano}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
'')
|
||||||
|
|
||||||
|
# Backup and restore
|
||||||
|
(omni.makeScript "omni-backup" "Backup Omnixient configuration" ''
|
||||||
|
BACKUP_DIR="$HOME/omni-backups"
|
||||||
|
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||||
|
BACKUP_FILE="$BACKUP_DIR/omni_$TIMESTAMP.tar.gz"
|
||||||
|
|
||||||
|
echo "💾 Creating Omnixient configuration backup..."
|
||||||
|
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
|
||||||
|
# Create backup archive
|
||||||
|
sudo tar -czf "$BACKUP_FILE" \
|
||||||
|
-C /etc \
|
||||||
|
nixos/ \
|
||||||
|
--exclude=nixos/hardware-configuration.nix
|
||||||
|
|
||||||
|
# Also backup user configs that matter
|
||||||
|
if [ -d "$HOME/.config" ]; then
|
||||||
|
tar -czf "$BACKUP_DIR/userconfig_$TIMESTAMP.tar.gz" \
|
||||||
|
-C "$HOME" \
|
||||||
|
.config/hypr/ \
|
||||||
|
.config/waybar/ \
|
||||||
|
.config/mako/ \
|
||||||
|
.config/walker/ 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ Backup created:"
|
||||||
|
echo " System: $BACKUP_FILE"
|
||||||
|
echo " User: $BACKUP_DIR/userconfig_$TIMESTAMP.tar.gz"
|
||||||
|
echo
|
||||||
|
echo "📊 Backup size:"
|
||||||
|
du -sh "$BACKUP_DIR"/*"$TIMESTAMP"* | sed 's/^/ /'
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
124
modules/users.nix
Normal file
124
modules/users.nix
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
settings,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.omni;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# User account configuration
|
||||||
|
users.users.${cfg.user} = {
|
||||||
|
isNormalUser = true;
|
||||||
|
description = "Omnixient User";
|
||||||
|
extraGroups = [
|
||||||
|
"wheel"
|
||||||
|
"networkmanager"
|
||||||
|
"audio"
|
||||||
|
"video"
|
||||||
|
"docker"
|
||||||
|
"libvirtd"
|
||||||
|
"input"
|
||||||
|
"dialout"
|
||||||
|
];
|
||||||
|
shell = pkgs.bash;
|
||||||
|
|
||||||
|
# Set initial password (should be changed on first login)
|
||||||
|
# pragma: allowlist secret
|
||||||
|
initialPassword = "omni";
|
||||||
|
|
||||||
|
# SSH public keys authorized for this account — add yours in settings.nix.
|
||||||
|
openssh.authorizedKeys.keys = settings.sshKeys;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Additional user-related configurations
|
||||||
|
users = {
|
||||||
|
# Allow users in wheel group to use sudo
|
||||||
|
mutableUsers = true;
|
||||||
|
|
||||||
|
# Default shell
|
||||||
|
defaultUserShell = pkgs.bash;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Security settings for users
|
||||||
|
security.pam.services = {
|
||||||
|
# Enable fingerprint authentication
|
||||||
|
login.fprintAuth = false;
|
||||||
|
sudo.fprintAuth = false;
|
||||||
|
|
||||||
|
# Enable U2F authentication (for YubiKey etc.)
|
||||||
|
login.u2fAuth = false;
|
||||||
|
sudo.u2fAuth = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Home directory encryption (optional)
|
||||||
|
# security.pam.enableEcryptfs = true;
|
||||||
|
|
||||||
|
# Automatic login (disable for production)
|
||||||
|
services.displayManager.autoLogin = {
|
||||||
|
enable = false;
|
||||||
|
user = cfg.user;
|
||||||
|
};
|
||||||
|
|
||||||
|
# User environment
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
# User management tools
|
||||||
|
shadow # provides passwd, useradd, etc.
|
||||||
|
|
||||||
|
# Session management
|
||||||
|
systemd # provides loginctl
|
||||||
|
|
||||||
|
# User info
|
||||||
|
bsd-finger
|
||||||
|
idutils
|
||||||
|
];
|
||||||
|
|
||||||
|
# User-specific services
|
||||||
|
systemd.user.services = {
|
||||||
|
# Example: Syncthing for the user
|
||||||
|
# syncthing = {
|
||||||
|
# description = "Syncthing for ${cfg.user}";
|
||||||
|
# wantedBy = [ "default.target" ];
|
||||||
|
# serviceConfig = {
|
||||||
|
# ExecStart = "${pkgs.syncthing}/bin/syncthing serve --no-browser --no-restart --logflags=0";
|
||||||
|
# Restart = "on-failure";
|
||||||
|
# RestartSec = 10;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
};
|
||||||
|
|
||||||
|
# Shell initialization for all users
|
||||||
|
programs.bash.interactiveShellInit = ''
|
||||||
|
# User-specific aliases
|
||||||
|
alias profile='nvim ~/.bashrc'
|
||||||
|
alias reload='source ~/.bashrc'
|
||||||
|
|
||||||
|
# Safety aliases
|
||||||
|
alias rm='rm -i'
|
||||||
|
alias cp='cp -i'
|
||||||
|
alias mv='mv -i'
|
||||||
|
|
||||||
|
# Directory shortcuts
|
||||||
|
alias home='cd ~'
|
||||||
|
alias downloads='cd ~/Downloads'
|
||||||
|
alias documents='cd ~/Documents'
|
||||||
|
alias projects='cd ~/Projects'
|
||||||
|
|
||||||
|
# Create standard directories if they don't exist
|
||||||
|
mkdir -p ~/Downloads ~/Documents ~/Projects ~/Pictures ~/Videos ~/Music
|
||||||
|
'';
|
||||||
|
|
||||||
|
# XDG Base Directory specification
|
||||||
|
environment.variables = {
|
||||||
|
XDG_CACHE_HOME = "$HOME/.cache";
|
||||||
|
XDG_CONFIG_HOME = "$HOME/.config";
|
||||||
|
XDG_DATA_HOME = "$HOME/.local/share";
|
||||||
|
XDG_STATE_HOME = "$HOME/.local/state";
|
||||||
|
};
|
||||||
|
|
||||||
|
# User quotas (optional)
|
||||||
|
# fileSystems."/home".options = [ "usrquota" ];
|
||||||
|
}
|
||||||
450
modules/walker.nix
Normal file
450
modules/walker.nix
Normal file
|
|
@ -0,0 +1,450 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
# Walker app launcher configuration for Omnixient
|
||||||
|
# Modern replacement for Rofi with better Wayland integration
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) mkIf;
|
||||||
|
cfg = config.omni;
|
||||||
|
omni = {
|
||||||
|
makeScript =
|
||||||
|
name: description: script:
|
||||||
|
pkgs.writeShellScriptBin name ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# ${description}
|
||||||
|
set -euo pipefail
|
||||||
|
${script}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
config = mkIf (cfg.enable or true) {
|
||||||
|
# Add convenience scripts to system packages
|
||||||
|
environment.systemPackages = [
|
||||||
|
# Convenience scripts
|
||||||
|
(omni.makeScript "omni-launcher" "Launch Omnixient app launcher" ''
|
||||||
|
walker --config ~/.config/walker/config.json --css ~/.config/walker/themes/style.css
|
||||||
|
'')
|
||||||
|
|
||||||
|
(omni.makeScript "omni-run" "Quick command runner" ''
|
||||||
|
walker --modules runner --config ~/.config/walker/config.json --css ~/.config/walker/themes/style.css
|
||||||
|
'')
|
||||||
|
|
||||||
|
(omni.makeScript "omni-apps" "Application launcher" ''
|
||||||
|
walker --modules applications --config ~/.config/walker/config.json --css ~/.config/walker/themes/style.css
|
||||||
|
'')
|
||||||
|
|
||||||
|
(omni.makeScript "omni-files" "File finder" ''
|
||||||
|
walker --modules finder --config ~/.config/walker/config.json --css ~/.config/walker/themes/style.css
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
|
||||||
|
# Create Walker configuration
|
||||||
|
environment.etc."omni/walker/config.json".text = builtins.toJSON {
|
||||||
|
# General configuration
|
||||||
|
placeholder = "Search applications, files, and more...";
|
||||||
|
fullscreen = false;
|
||||||
|
layer = "overlay";
|
||||||
|
modules = [
|
||||||
|
{
|
||||||
|
name = "applications";
|
||||||
|
src = "applications";
|
||||||
|
transform = "uppercase";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "runner";
|
||||||
|
src = "runner";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "websearch";
|
||||||
|
src = "websearch";
|
||||||
|
engines = [
|
||||||
|
{
|
||||||
|
name = "Google";
|
||||||
|
url = "https://www.google.com/search?q=%s";
|
||||||
|
icon = "web-browser";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "GitHub";
|
||||||
|
url = "https://github.com/search?q=%s";
|
||||||
|
icon = "github";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "NixOS Packages";
|
||||||
|
url = "https://search.nixos.org/packages?query=%s";
|
||||||
|
icon = "nix-snowflake";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "finder";
|
||||||
|
src = "finder";
|
||||||
|
dirs = [
|
||||||
|
"/home/${cfg.user}"
|
||||||
|
"/home/${cfg.user}/Documents"
|
||||||
|
"/home/${cfg.user}/Downloads"
|
||||||
|
"/home/${cfg.user}/Desktop"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "calc";
|
||||||
|
src = "calc";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
# UI Configuration
|
||||||
|
ui = {
|
||||||
|
anchors = {
|
||||||
|
top = false;
|
||||||
|
left = true;
|
||||||
|
right = false;
|
||||||
|
bottom = false;
|
||||||
|
};
|
||||||
|
margin = {
|
||||||
|
top = 100;
|
||||||
|
bottom = 0;
|
||||||
|
left = 100;
|
||||||
|
right = 0;
|
||||||
|
};
|
||||||
|
width = 600;
|
||||||
|
height = 500;
|
||||||
|
show_initial_entries = true;
|
||||||
|
show_search_text = true;
|
||||||
|
scroll_height = 300;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Search configuration
|
||||||
|
search = {
|
||||||
|
delay = 100;
|
||||||
|
placeholder = "Type to search...";
|
||||||
|
force_keyboard_focus = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# List configuration
|
||||||
|
list = {
|
||||||
|
height = 200;
|
||||||
|
always_show = true;
|
||||||
|
max_entries = 50;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Icons
|
||||||
|
icons = {
|
||||||
|
theme = "Papirus";
|
||||||
|
size = 32;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Theming based on current theme
|
||||||
|
theme =
|
||||||
|
if cfg.theme == "gruvbox" then
|
||||||
|
"gruvbox"
|
||||||
|
else if cfg.theme == "nord" then
|
||||||
|
"nord"
|
||||||
|
else if cfg.theme == "catppuccin" then
|
||||||
|
"catppuccin"
|
||||||
|
else if cfg.theme == "tokyo-night" then
|
||||||
|
"tokyo-night"
|
||||||
|
else
|
||||||
|
"default";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Create Walker CSS theme files
|
||||||
|
environment.etc."omni/walker/themes/gruvbox.css".text = ''
|
||||||
|
* {
|
||||||
|
color: #ebdbb2;
|
||||||
|
font-family: "JetBrainsMono Nerd Font", monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#window {
|
||||||
|
background-color: rgba(40, 40, 40, 0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
window {
|
||||||
|
background-color: rgba(40, 40, 40, 0.95);
|
||||||
|
border: 2px solid #a89984;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
box {
|
||||||
|
background-color: rgba(40, 40, 40, 0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
#search {
|
||||||
|
background-color: #3c3836;
|
||||||
|
border: 1px solid #665c54;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
margin: 12px;
|
||||||
|
color: #ebdbb2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search:focus {
|
||||||
|
border-color: #d79921;
|
||||||
|
}
|
||||||
|
|
||||||
|
#list {
|
||||||
|
background-color: rgba(40, 40, 40, 0.95);
|
||||||
|
padding: 0 12px 12px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:selected {
|
||||||
|
background-color: #504945;
|
||||||
|
color: #fbf1c7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:hover {
|
||||||
|
background-color: #3c3836;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item .icon {
|
||||||
|
margin-right: 12px;
|
||||||
|
min-width: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item .text {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item .sub {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #a89984;
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
environment.etc."omni/walker/themes/nord.css".text = ''
|
||||||
|
* {
|
||||||
|
color: #eceff4;
|
||||||
|
background-color: #2e3440;
|
||||||
|
font-family: "JetBrainsMono Nerd Font", monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
window {
|
||||||
|
background-color: rgba(46, 52, 64, 0.95);
|
||||||
|
border: 2px solid #4c566a;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search {
|
||||||
|
background-color: #3b4252;
|
||||||
|
border: 1px solid #4c566a;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
margin: 12px;
|
||||||
|
color: #eceff4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search:focus {
|
||||||
|
border-color: #5e81ac;
|
||||||
|
}
|
||||||
|
|
||||||
|
#list {
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 0 12px 12px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:selected {
|
||||||
|
background-color: #434c5e;
|
||||||
|
color: #eceff4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:hover {
|
||||||
|
background-color: #3b4252;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item .icon {
|
||||||
|
margin-right: 12px;
|
||||||
|
min-width: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item .text {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item .sub {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #81a1c1;
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
environment.etc."omni/walker/themes/catppuccin.css".text = ''
|
||||||
|
* {
|
||||||
|
color: #cdd6f4;
|
||||||
|
background-color: #1e1e2e;
|
||||||
|
font-family: "JetBrainsMono Nerd Font", monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
window {
|
||||||
|
background-color: rgba(30, 30, 46, 0.95);
|
||||||
|
border: 2px solid #6c7086;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search {
|
||||||
|
background-color: #313244;
|
||||||
|
border: 1px solid #45475a;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
margin: 12px;
|
||||||
|
color: #cdd6f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search:focus {
|
||||||
|
border-color: #89b4fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
#list {
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 0 12px 12px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:selected {
|
||||||
|
background-color: #45475a;
|
||||||
|
color: #cdd6f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:hover {
|
||||||
|
background-color: #313244;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item .icon {
|
||||||
|
margin-right: 12px;
|
||||||
|
min-width: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item .text {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item .sub {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #89dceb;
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
environment.etc."omni/walker/themes/tokyo-night.css".text = ''
|
||||||
|
* {
|
||||||
|
color: #c0caf5;
|
||||||
|
background-color: #1a1b26;
|
||||||
|
font-family: "JetBrainsMono Nerd Font", monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
window {
|
||||||
|
background-color: rgba(26, 27, 38, 0.95);
|
||||||
|
border: 2px solid #414868;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search {
|
||||||
|
background-color: #24283b;
|
||||||
|
border: 1px solid #414868;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
margin: 12px;
|
||||||
|
color: #c0caf5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search:focus {
|
||||||
|
border-color: #7aa2f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
#list {
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 0 12px 12px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:selected {
|
||||||
|
background-color: #414868;
|
||||||
|
color: #c0caf5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:hover {
|
||||||
|
background-color: #24283b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item .icon {
|
||||||
|
margin-right: 12px;
|
||||||
|
min-width: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item .text {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item .sub {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #7dcfff;
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Add to user environment
|
||||||
|
home-manager.users.${config.omni.user} = {
|
||||||
|
# Walker launcher via official home-manager module
|
||||||
|
programs.walker = {
|
||||||
|
enable = true;
|
||||||
|
runAsService = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Walker config and theme CSS
|
||||||
|
xdg.configFile."walker/config.json".source =
|
||||||
|
config.environment.etc."omni/walker/config.json".source;
|
||||||
|
xdg.configFile."walker/themes/style.css".source =
|
||||||
|
config.environment.etc."omni/walker/themes/${cfg.theme}.css".source;
|
||||||
|
|
||||||
|
# Add shell aliases
|
||||||
|
programs.bash.shellAliases = {
|
||||||
|
launcher = "walker";
|
||||||
|
run = "walker --modules runner";
|
||||||
|
apps = "walker --modules applications";
|
||||||
|
files = "walker --modules finder";
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.zsh.shellAliases = {
|
||||||
|
launcher = "walker";
|
||||||
|
run = "walker --modules runner";
|
||||||
|
apps = "walker --modules applications";
|
||||||
|
files = "walker --modules finder";
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.fish.shellAliases = {
|
||||||
|
launcher = "walker";
|
||||||
|
run = "walker --modules runner";
|
||||||
|
apps = "walker --modules applications";
|
||||||
|
files = "walker --modules finder";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Convenience scripts are now consolidated above
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue