diff --git a/bin/nomarchy-setup-dns b/bin/nomarchy-setup-dns index 7a60b64..b2eb7ac 100755 --- a/bin/nomarchy-setup-dns +++ b/bin/nomarchy-setup-dns @@ -1,27 +1,9 @@ -#!/bin/bash +#!/usr/bin/env bash -lock_dns_to_resolved() { - for file in /etc/systemd/network/*.network; do - [[ -f $file ]] || continue - if ! grep -q "^\[DHCPv4\]" "$file"; then continue; fi +# Configure DNS declaratively for Nomarchy NixOS. +# Hybrid: updates /etc/nixos/state.json and runs sys-update. - if ! sed -n '/^\[DHCPv4\]/,/^\[/p' "$file" | grep -q "^UseDNS="; then - sudo sed -i '/^\[DHCPv4\]/a UseDNS=no' "$file" - fi - - if grep -q "^\[IPv6AcceptRA\]" "$file" && ! sed -n '/^\[IPv6AcceptRA\]/,/^\[/p' "$file" | grep -q "^UseDNS="; then - sudo sed -i '/^\[IPv6AcceptRA\]/a UseDNS=no' "$file" - fi - done -} - -unlock_dns_to_dhcp() { - for file in /etc/systemd/network/*.network; do - [[ -f $file ]] || continue - sudo sed -i '/^\[DHCPv4\]/{n;/^UseDNS=no$/d}' "$file" - sudo sed -i '/^\[IPv6AcceptRA\]/{n;/^UseDNS=no$/d}' "$file" - done -} +STATE_FILE="/etc/nixos/state.json" if [[ -z $1 ]]; then dns=$(gum choose --height 6 --header "Select DNS provider" Cloudflare Google DHCP Custom) @@ -30,32 +12,8 @@ else fi case "$dns" in -Cloudflare) - sudo tee /etc/systemd/resolved.conf >/dev/null <<'EOF' -[Resolve] -DNS=1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com -FallbackDNS=9.9.9.9 149.112.112.112 -DNSOverTLS=opportunistic -EOF - lock_dns_to_resolved - ;; - -Google) - sudo tee /etc/systemd/resolved.conf >/dev/null <<'EOF' -[Resolve] -DNS=8.8.8.8#dns.google 8.8.4.4#dns.google -FallbackDNS=9.9.9.9 149.112.112.112 -DNSOverTLS=opportunistic -EOF - lock_dns_to_resolved - ;; - -DHCP) - sudo tee /etc/systemd/resolved.conf >/dev/null <<'EOF' -[Resolve] -DNSOverTLS=no -EOF - unlock_dns_to_dhcp +Cloudflare|Google|DHCP) + sudo jq ".dns = \"$dns\"" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE" ;; Custom) @@ -66,14 +24,12 @@ Custom) echo "Error: No DNS servers provided." exit 1 fi - - sudo tee /etc/systemd/resolved.conf >/dev/null < /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE" ;; esac -sudo systemctl restart systemd-networkd systemd-resolved +echo "DNS configured to $dns. Applying changes..." +sudo sys-update diff --git a/bin/nomarchy-setup-fido2 b/bin/nomarchy-setup-fido2 index dd3e291..64c28b3 100755 --- a/bin/nomarchy-setup-fido2 +++ b/bin/nomarchy-setup-fido2 @@ -2,38 +2,18 @@ # Configure FIDO2 support declaratively for Nomarchy NixOS. -FEATURE_FILE="/etc/nixos/nomarchy-features/fido2.nix" +STATE_FILE="/etc/nixos/state.json" if [[ "--remove" == $1 ]]; then - if [ -f "$FEATURE_FILE" ]; then - sudo rm "$FEATURE_FILE" - echo "Removed $FEATURE_FILE." - echo "IMPORTANT: Remove './nomarchy-features/fido2.nix' from your imports and run 'sys-update'." - else - echo "FIDO2 support not found." - fi + sudo jq ".features.fido2 = false" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE" + echo "FIDO2 support disabled. Applying changes..." + sudo sys-update exit 0 fi -if [ -f "$FEATURE_FILE" ]; then - echo "FIDO2 support is already configured in $FEATURE_FILE" -else - sudo mkdir -p "/etc/nixos/nomarchy-features" - cat < /dev/null -{ config, pkgs, ... }: -{ - security.pam.u2f = { - enable = true; - control = "sufficient"; - cue = true; - # authFile = "/etc/fido2/fido2"; # Default is ~/.config/Yubico/u2f_keys - }; -} -EOF - echo "Created $FEATURE_FILE." - echo "IMPORTANT: To finish enabling FIDO2 support, add './nomarchy-features/fido2.nix' to your imports list in /etc/nixos/system.nix or /etc/nixos/flake.nix," - echo "then run 'sys-update'." -fi +sudo jq ".features.fido2 = true" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE" +echo "FIDO2 support enabled. Applying changes..." +sudo sys-update # Enrollment is still an imperative action if command -v pamu2fcfg &> /dev/null; then @@ -42,5 +22,5 @@ if command -v pamu2fcfg &> /dev/null; then pamu2fcfg > ~/.config/Yubico/u2f_keys echo "FIDO2 key registered." else - echo "pamu2fcfg not found. Please run 'nomarchy-pkg-add pam-u2f' or 'sys-update' if you just enabled it." + echo "pamu2fcfg not found. It will be available after the next reboot or sys-update." fi diff --git a/bin/nomarchy-setup-fingerprint b/bin/nomarchy-setup-fingerprint index 568d513..92d1f46 100755 --- a/bin/nomarchy-setup-fingerprint +++ b/bin/nomarchy-setup-fingerprint @@ -1,40 +1,25 @@ #!/usr/bin/env bash -# Configure Fingerprint support declaratively for Nomarchy NixOS. +# Configure fingerprint support declaratively for Nomarchy NixOS. -FEATURE_FILE="/etc/nixos/nomarchy-features/fingerprint.nix" +STATE_FILE="/etc/nixos/state.json" if [[ "--remove" == $1 ]]; then - if [ -f "$FEATURE_FILE" ]; then - sudo rm "$FEATURE_FILE" - echo "Removed $FEATURE_FILE." - echo "IMPORTANT: Remove './nomarchy-features/fingerprint.nix' from your imports and run 'sys-update'." - else - echo "Fingerprint support not found." - fi + sudo jq ".features.fingerprint = false" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE" + echo "Fingerprint support disabled. Applying changes..." + sudo sys-update exit 0 fi -if [ -f "$FEATURE_FILE" ]; then - echo "Fingerprint support is already configured in $FEATURE_FILE" -else - sudo mkdir -p "/etc/nixos/nomarchy-features" - cat < /dev/null -{ config, pkgs, ... }: -{ - services.fprintd.enable = true; - # NixOS's fprintd module automatically configures PAM for login/sudo if enabled. -} -EOF - echo "Created $FEATURE_FILE." - echo "IMPORTANT: To finish enabling fingerprint support, add './nomarchy-features/fingerprint.nix' to your imports list in /etc/nixos/system.nix or /etc/nixos/flake.nix," - echo "then run 'sys-update'." -fi +sudo jq ".features.fingerprint = true" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE" +echo "Fingerprint support enabled. Applying changes..." +sudo sys-update # Enrollment is still an imperative action if command -v fprintd-enroll &> /dev/null; then echo "Let's enroll your fingerprint now." - fprintd-enroll "$USER" + fprintd-enroll + echo "Fingerprint enrolled." else - echo "fprintd-enroll not found. Please run 'sys-update' first if you just enabled it." + echo "fprintd not found. It will be available after the next reboot or sys-update." fi diff --git a/bin/nomarchy-theme-set b/bin/nomarchy-theme-set index dff3ae9..2fe2b6e 100755 --- a/bin/nomarchy-theme-set +++ b/bin/nomarchy-theme-set @@ -32,6 +32,12 @@ fi TMP_JSON=$(mktemp) jq ".theme = \"$THEME_NAME\"" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE" +# Sync to system state if we have permissions (for system-level theming like browser policies) +SYSTEM_STATE_FILE="/etc/nixos/state.json" +if [ -w "$SYSTEM_STATE_FILE" ] || [ -w "/etc/nixos" ]; then + sudo jq ".theme = \"$THEME_NAME\"" "$SYSTEM_STATE_FILE" > /tmp/system-state.json 2>/dev/null && sudo mv /tmp/system-state.json "$SYSTEM_STATE_FILE" 2>/dev/null || true +fi + # Try to find a background for this theme BG_DIR="$THEMES_DIR/$THEME_NAME/backgrounds" if [ -d "$BG_DIR" ]; then diff --git a/bin/nomarchy-theme-set-browser b/bin/nomarchy-theme-set-browser deleted file mode 100755 index f29916b..0000000 --- a/bin/nomarchy-theme-set-browser +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -CHROMIUM_THEME=~/.config/nomarchy/current/theme/chromium.theme - -if nomarchy-cmd-present chromium || nomarchy-cmd-present brave; then - if [[ -f $CHROMIUM_THEME ]]; then - THEME_RGB_COLOR=$(<$CHROMIUM_THEME) - THEME_HEX_COLOR=$(printf '#%02x%02x%02x' ${THEME_RGB_COLOR//,/ }) - else - # Use a default, neutral grey if theme doesn't have a color - THEME_RGB_COLOR="28,32,39" - THEME_HEX_COLOR="#1c2027" - fi - - if nomarchy-cmd-present chromium; then - echo "{\"BrowserThemeColor\": \"$THEME_HEX_COLOR\", \"BrowserColorScheme\": \"device\"}" | tee "/etc/chromium/policies/managed/color.json" >/dev/null - chromium --refresh-platform-policy --no-startup-window >/dev/null - fi - - if nomarchy-cmd-present brave; then - echo "{\"BrowserThemeColor\": \"$THEME_HEX_COLOR\", \"BrowserColorScheme\": \"device\"}" | tee "/etc/brave/policies/managed/color.json" >/dev/null - brave --refresh-platform-policy --no-startup-window >/dev/null - fi -fi diff --git a/bin/nomarchy-toggle-hybrid-gpu b/bin/nomarchy-toggle-hybrid-gpu index 04b49d3..31cb351 100755 --- a/bin/nomarchy-toggle-hybrid-gpu +++ b/bin/nomarchy-toggle-hybrid-gpu @@ -3,20 +3,23 @@ # Toggle dedicated vs integrated GPU mode via supergfxd (for hybrid gpu laptops, like Asus G14). # Declarative enablement + Runtime mode switching for Nomarchy NixOS. -FEATURE_FILE="/etc/nixos/nomarchy-features/supergfxd.nix" +STATE_FILE="/etc/nixos/state.json" + +# Check if supergfxd is enabled in config +if [[ $(sudo jq -r '.features.hybridGPU // false' "$STATE_FILE") != "true" ]]; then + if gum confirm "Hybrid GPU support is not enabled. Enable it now? (Requires sys-update)"; then + sudo jq ".features.hybridGPU = true" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE" + echo "Hybrid GPU support enabled in configuration. Applying changes..." + sudo sys-update + echo "Please run this command again after the update." + exit 0 + fi + exit 1 +fi if ! command -v supergfxctl &> /dev/null; then - sudo mkdir -p "/etc/nixos/nomarchy-features" - cat < /dev/null -{ config, pkgs, ... }: -{ - services.supergfxd.enable = true; -} -EOF - echo "Created $FEATURE_FILE to enable supergfxd." - echo "IMPORTANT: To finish enabling hybrid GPU support, add './nomarchy-features/supergfxd.nix' to your imports list in /etc/nixos/system.nix or /etc/nixos/flake.nix," - echo "then run 'sys-update'." - exit 0 + echo "supergfxctl not found. Is the system updated?" + exit 1 fi gpu_mode=$(supergfxctl -g) diff --git a/bin/nomarchy-tz-select b/bin/nomarchy-tz-select index 5fff725..b5ff3b6 100755 --- a/bin/nomarchy-tz-select +++ b/bin/nomarchy-tz-select @@ -1,6 +1,12 @@ -#!/bin/bash +#!/usr/bin/env bash + +# Select system timezone declaratively for Nomarchy NixOS. + +STATE_FILE="/etc/nixos/state.json" timezone=$(timedatectl list-timezones | gum filter --height 20 --header "Set timezone") || exit 1 -sudo timedatectl set-timezone "$timezone" -echo "Timezone is now set to $timezone" -nomarchy-restart-waybar + +sudo jq ".timezone = \"$timezone\"" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE" + +echo "Timezone is now set to $timezone. Applying changes..." +sudo sys-update diff --git a/bin/nomarchy-update b/bin/nomarchy-update index cf0ce1b..81e7e55 100755 --- a/bin/nomarchy-update +++ b/bin/nomarchy-update @@ -22,7 +22,7 @@ sudo nix --extra-experimental-features "nix-command flakes" flake update --flake # 2. Rebuild System echo "Applying system-level updates..." -sudo nixos-rebuild switch --flake "$REPO_DIR#default" +sudo nixos-rebuild switch --flake "$REPO_DIR#default" --impure # 3. Rebuild Home Environment echo "Applying user-level updates..." diff --git a/bin/nomarchy-wifi-powersave b/bin/nomarchy-wifi-powersave index 9e1c5bb..6ecc68c 100755 --- a/bin/nomarchy-wifi-powersave +++ b/bin/nomarchy-wifi-powersave @@ -1,5 +1,17 @@ -#!/bin/bash -for iface in /sys/class/net/*/wireless; do - iface="$(basename "$(dirname "$iface")")" - iw dev "$iface" set power_save "$1" 2>/dev/null -done +#!/usr/bin/env bash + +# Toggles wifi power saving declaratively. +# Usage: nomarchy-wifi-powersave + +STATE_FILE="/etc/nixos/state.json" + +case "$1" in +on) value="true" ;; +off) value="false" ;; +*) echo "Usage: nomarchy-wifi-powersave "; exit 1 ;; +esac + +sudo jq ".wifi.powersave = $value" "$STATE_FILE" > /tmp/state.json && sudo mv /tmp/state.json "$STATE_FILE" + +echo "Wifi powersave set to $1. Applying changes..." +sudo sys-update diff --git a/modules/home/default.nix b/modules/home/default.nix index ba98bef..7934276 100644 --- a/modules/home/default.nix +++ b/modules/home/default.nix @@ -58,7 +58,7 @@ in ] ++ userPackages; home.shellAliases = { - sys-update = "sudo nixos-rebuild switch --flake /etc/nixos#default"; + sys-update = "sudo nixos-rebuild switch --flake /etc/nixos#default --impure"; env-update = "home-manager switch --flake /etc/nixos#default --impure"; }; } diff --git a/modules/system/browser.nix b/modules/system/browser.nix new file mode 100644 index 0000000..370d323 --- /dev/null +++ b/modules/system/browser.nix @@ -0,0 +1,22 @@ +{ config, pkgs, lib, ... }: + +let + palettes = import ../../themes/nomarchy-palettes.nix; + activeThemeName = config.nomarchy.system.theme; + currentPalette = (palettes.${activeThemeName} or palettes.nord).palette; + + # Hex color for browser theme (base00 is background) + themeColor = "#${currentPalette.base00}"; + + policy = { + BrowserThemeColor = themeColor; + BrowserColorScheme = if lib.strings.hasInfix "light" activeThemeName then "light" else "dark"; + }; +in +{ + # Chromium policies + programs.chromium.extraOpts = policy; + + # Brave policies (Brave on NixOS also respects some chromium policies if set via extraOpts) + # But better to use the specific brave module if available or just the same policy. +} diff --git a/modules/system/default.nix b/modules/system/default.nix index 0dc6442..ef745bb 100644 --- a/modules/system/default.nix +++ b/modules/system/default.nix @@ -2,12 +2,17 @@ { imports = [ + ./options.nix + ./state.nix ./plymouth.nix ./sddm.nix ./hardware.nix ./audio.nix ./bluetooth.nix ./network.nix + ./browser.nix ./impermanence.nix ]; + + time.timeZone = config.nomarchy.system.timezone; } diff --git a/modules/system/hardware.nix b/modules/system/hardware.nix index 9db0e29..89595ec 100644 --- a/modules/system/hardware.nix +++ b/modules/system/hardware.nix @@ -46,5 +46,22 @@ in options brcmfmac feature_disable=0x82000 ''; }) + + # System Features + (mkIf config.nomarchy.system.features.fingerprint { + services.fprintd.enable = true; + }) + + (mkIf config.nomarchy.system.features.fido2 { + security.pam.u2f = { + enable = true; + control = "sufficient"; + cue = true; + }; + }) + + (mkIf config.nomarchy.system.features.hybridGPU { + services.supergfxd.enable = true; + }) ]; } diff --git a/modules/system/network.nix b/modules/system/network.nix index 34b6b7c..42d58c5 100644 --- a/modules/system/network.nix +++ b/modules/system/network.nix @@ -1,5 +1,26 @@ -{ config, pkgs, ... }: +{ config, pkgs, lib, ... }: +let + cfg = config.nomarchy.system; +in { networking.networkmanager.enable = true; + + networking.networkmanager.wifi.powersave = cfg.wifi.powersave; + + # DNS Configuration + networking.nameservers = if cfg.dns == "Cloudflare" then [ "1.1.1.1" "1.0.0.1" ] + else if cfg.dns == "Google" then [ "8.8.8.8" "8.8.4.4" ] + else if cfg.dns == "Custom" then cfg.customDns + else []; # DHCP lets NM handle it + + services.resolved = { + enable = cfg.dns != "DHCP"; + dnssec = "allow-downgrade"; + domains = [ "~." ]; + fallbackDns = [ "9.9.9.9" "149.112.112.112" ]; + extraConfig = '' + DNSOverTLS=opportunistic + ''; + }; } diff --git a/modules/system/options.nix b/modules/system/options.nix new file mode 100644 index 0000000..25f5c8f --- /dev/null +++ b/modules/system/options.nix @@ -0,0 +1,50 @@ +{ lib, ... }: + +{ + options.nomarchy.system = { + dns = lib.mkOption { + type = lib.types.enum [ "Cloudflare" "Google" "DHCP" "Custom" ]; + default = "DHCP"; + description = "Selected DNS provider."; + }; + customDns = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = []; + description = "List of custom DNS servers."; + }; + wifi = { + powersave = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Whether to enable wifi power saving."; + }; + }; + timezone = lib.mkOption { + type = lib.types.str; + default = "UTC"; + description = "System timezone."; + }; + features = { + fingerprint = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Whether to enable fingerprint support."; + }; + fido2 = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Whether to enable FIDO2 support."; + }; + hybridGPU = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Whether to enable hybrid GPU support (supergfxd)."; + }; + }; + theme = lib.mkOption { + type = lib.types.str; + default = "nord"; + description = "Selected system theme."; + }; + }; +} diff --git a/modules/system/state.nix b/modules/system/state.nix new file mode 100644 index 0000000..4091420 --- /dev/null +++ b/modules/system/state.nix @@ -0,0 +1,28 @@ +{ lib, ... }: + +let + stateFile = "/etc/nixos/state.json"; + + # Helper to read state from a file, with a default + readState = file: default: + if builtins.pathExists file then + builtins.fromJSON (builtins.readFile file) + else + default; + + systemState = readState stateFile {}; +in +{ + config.nomarchy.system = { + dns = systemState.dns or "DHCP"; + customDns = systemState.customDns or []; + wifi.powersave = systemState.wifi.powersave or true; + timezone = systemState.timezone or "UTC"; + features = { + fingerprint = systemState.features.fingerprint or false; + fido2 = systemState.features.fido2 or false; + hybridGPU = systemState.features.hybridGPU or false; + }; + theme = systemState.theme or "nord"; + }; +} diff --git a/modules/system/supergfxd.nix b/modules/system/supergfxd.nix deleted file mode 100644 index bbd1a90..0000000 --- a/modules/system/supergfxd.nix +++ /dev/null @@ -1,6 +0,0 @@ -{ config, pkgs, ... }: - -{ - services.supergfxd.enable = true; - # NixOS handles the configuration of supergfxd -}