Skip to content
Merged
25 changes: 22 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ NIX_TRUSTED_KEYS := cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShj
NIX_CACHIX_CONF := /etc/nix/cachix.conf
# Check if user is trusted (to avoid "ignoring untrusted substituter" warnings)
NIX_USER_TRUSTED := $(shell grep -qE "trusted-users.*=.*(\\*|$(shell whoami))" /etc/nix/nix.conf 2>/dev/null && echo "yes" || echo "no")
NAMED_HOSTS := galactica kyber matic viper
NIXOS_NAMED_HOSTS := $(filter matic viper,$(NAMED_HOSTS))
ISO_NAMED_HOSTS := $(filter matic viper,$(NAMED_HOSTS))

# Nix configuration system
NIX_SYSTEM := $(shell if [ "$(OS)" = "Darwin" ] && [ "$(ARCH)" = "arm64" ]; then \
Expand Down Expand Up @@ -137,7 +140,7 @@ default: help ## Default target (shows help).
help: ## Show this help message.
@echo "Usage: make <target>"
@echo
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9_-]+:.*?## / {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9_%-]+:.*?## / {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The help target parses $(MAKEFILE_LIST) (the files on disk) using awk. Since the new host-specific targets (e.g., build-matic) are generated dynamically using eval (lines 656-657), they do not exist as literal lines in the Makefile and will not be captured by this awk command. Consequently, they won't appear in the make help output. If you want them to be discoverable, consider using pattern rules (e.g., build-%:) instead of eval, or manually adding a help entry.


##@ General

Expand Down Expand Up @@ -638,6 +641,21 @@ nix-setup-offline: ## Set up offline environment.

##@ Named Hosts Specific Targets

define MAKE_NIXOS_HOST_BUILD_TARGET
.PHONY: build-$(1)
build-$(1): ## Build the $(1) named host configuration.
@$(MAKE) build HOST=$(1)
endef

define MAKE_NIXOS_HOST_ISO_TARGET
.PHONY: build-$(1)-iso
build-$(1)-iso: ## Build the $(1) named host live/install ISO.
@$(MAKE) build-iso HOST=$(1)
endef

$(foreach host,$(NIXOS_NAMED_HOSTS),$(eval $(call MAKE_NIXOS_HOST_BUILD_TARGET,$(host))))
$(foreach host,$(ISO_NAMED_HOSTS),$(eval $(call MAKE_NIXOS_HOST_ISO_TARGET,$(host))))

.PHONY: build-vm
build-vm: ## Build a named host VM launcher (set HOST=<name>, e.g. make build-vm HOST=viper).
@host="$(HOST)"; \
Expand Down Expand Up @@ -671,7 +689,8 @@ run-vm: ## Run a named host VM launcher (set HOST=<name>, e.g. make run-vm HOST=

.PHONY: build-iso
build-iso: ## Build a named host live/install ISO and copy it to ./<host>.iso (set HOST=<name>, e.g. make build-iso HOST=viper).
@host="$(HOST)"; \
@set -e; \
host="$(HOST)"; \
if [ -z "$$host" ]; then \
host="$(DETECTED_HOST)"; \
fi; \
Expand All @@ -681,7 +700,7 @@ build-iso: ## Build a named host live/install ISO and copy it to ./<host>.iso (s
fi; \
echo "💿 Building ISO for $$host"; \
$(NIX_ALLOW_UNFREE) $(NIX_EXEC) build .#nixosConfigurations.$$host"Iso".config.system.build.isoImage $(NIX_FLAGS) --impure --show-trace; \
iso_path=$$(find ./result -type f -name '*.iso' | head -n 1); \
iso_path=$$(bash ./scripts/find-built-iso.sh ./result); \
if [ -z "$$iso_path" ]; then \
echo "❌ Could not find a built ISO under ./result"; \
exit 1; \
Expand Down
3 changes: 2 additions & 1 deletion bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion config/hyprland/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
extraConfig = ''
exec-once = ${pkgs.hyprpanel}/bin/hyprpanel
exec-once = ${pkgs.hyprshell}/bin/hyprshell run &
exec-once = ${pkgs.lib.getExe pkgs.hyprpolkitagent}
exec-once = ${pkgs.hyprpolkitagent}/libexec/hyprpolkitagent
exec-once = sleep 3 && ${pkgs.eww}/bin/eww open clock-widget
exec-once = ${pkgs.nwg-dock-hyprland}/bin/nwg-dock-hyprland -d -i 48 -hd 0
''
Expand Down
10 changes: 10 additions & 0 deletions config/rofi/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -119,5 +119,15 @@ in
];
noDisplay = false;
};
battery-settings = {
name = "Battery Settings";
exec = "auto-cpufreq-gtk";
icon = "battery";
categories = [
"System"
"Settings"
];
noDisplay = false;
};
};
}
33 changes: 30 additions & 3 deletions home-manager/modules/uv-globals/install-uv-globals.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,38 @@ echo "$DEPS" | while read -r pkg; do
if [ -n "$installed_version" ] && [ -n "$req_version" ]; then
if printf '%s\n%s\n' "$req_version" "$installed_version" | sort -V | head -n1 | grep -qx "$req_version"; then
echo "$name $installed_version already installed, skipping"
continue
else
echo "Installing $pkg..."
uv tool install "$pkg" --python "$PYTHON_VERSION" --force 2>/dev/null || echo "Failed to install $pkg, skipping..."
fi
else
echo "Installing $pkg..."
uv tool install "$pkg" --python "$PYTHON_VERSION" --force 2>/dev/null || echo "Failed to install $pkg, skipping..."
fi
echo "Installing $pkg..."
uv tool install "$pkg" --python "$PYTHON_VERSION" --force 2>/dev/null || echo "Failed to install $pkg, skipping..."

# Symlink each tool's python3 for per-tool access: `python3-<tool> -m <tool>`
tool_python="${HOME}/.local/share/uv/tools/${name}/bin/python3"
if [ -f "$tool_python" ]; then
ln -sf "$tool_python" "${HOME}/.local/bin/python3-${name}"
fi
Comment on lines +71 to +75

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Ensure the target directory ${HOME}/.local/bin exists before attempting to create symlinks. Also, consider removing 2>/dev/null from the uv tool install command (line 64) to allow error messages to be visible if a tool fails to install, which is helpful for troubleshooting.

Suggested change
# Symlink each tool's python3 for per-tool access: `python3-<tool> -m <tool>`
tool_python="${HOME}/.local/share/uv/tools/${name}/bin/python3"
if [ -f "$tool_python" ]; then
ln -sf "$tool_python" "${HOME}/.local/bin/python3-${name}"
fi
# Symlink each tool's python3 for per-tool access: python3-<tool> -m <tool>
mkdir -p "${HOME}/.local/bin"
tool_python="${HOME}/.local/share/uv/tools/${name}/bin/python3"
if [ -f "$tool_python" ]; then
ln -sf "$tool_python" "${HOME}/.local/bin/python3-${name}"
fi

done

# Write a dispatcher so `python3 -m <tool>` uses that tool's isolated Python
cat > "${HOME}/.local/bin/python3" << 'EOF'
#!/usr/bin/env bash
prev=""
for arg in "$@"; do
if [ "$prev" = "-m" ]; then
per_tool="${HOME}/.local/bin/python3-${arg}"
if [ -x "$per_tool" ]; then
exec "$per_tool" "$@"
fi
break
fi
prev="$arg"
done
exec /etc/profiles/per-user/"${USER}"/bin/python3 "$@"
EOF
Comment on lines +78 to +93

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The dispatcher logic has two main issues:

  1. Portability: The fallback path /etc/profiles/per-user/"${USER}"/bin/python3 is NixOS-specific and will fail on other platforms (like macOS, which the Makefile suggests is supported).
  2. Correctness: The loop through all arguments might incorrectly trigger if a script being run happens to have a -m argument (e.g., python3 script.py -m arg).

A more robust approach is to check for -m as the first argument and use a portable way to find the 'real' python3 by temporarily excluding the wrapper's directory from PATH.

Suggested change
# Write a dispatcher so `python3 -m <tool>` uses that tool's isolated Python
cat > "${HOME}/.local/bin/python3" << 'EOF'
#!/usr/bin/env bash
prev=""
for arg in "$@"; do
if [ "$prev" = "-m" ]; then
per_tool="${HOME}/.local/bin/python3-${arg}"
if [ -x "$per_tool" ]; then
exec "$per_tool" "$@"
fi
break
fi
prev="$arg"
done
exec /etc/profiles/per-user/"${USER}"/bin/python3 "$@"
EOF
# Write a dispatcher so python3 -m <tool> uses that tool's isolated Python
cat > "${HOME}/.local/bin/python3" << 'EOF'
#!/usr/bin/env bash
# If the first argument is -m, check if we have an isolated tool for it
if [[ "$1" == "-m" && -n "$2" ]]; then
per_tool="${HOME}/.local/bin/python3-$2"
if [[ -x "$per_tool" ]]; then
exec "$per_tool" "$@"
fi
fi
# Fallback to the real python3 (excluding this wrapper from PATH)
REAL_PYTHON3=$(PATH=$(echo "$PATH" | tr ':' '\n' | grep -vx "${HOME}/.local/bin" | paste -sd: -) command -v python3)
if [[ -n "$REAL_PYTHON3" ]]; then
exec "$REAL_PYTHON3" "$@"
else
echo "python3 not found in PATH (excluding wrapper)" >&2
exit 1
fi
EOF

chmod +x "${HOME}/.local/bin/python3"

echo "uv globals installation complete"
18 changes: 18 additions & 0 deletions home-manager/programs/fish/functions/_pixelh_function.fish
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
function _pixelh_function --description "Run Pi headlessly with the local Qwen model"
# Prompt for input and run Pi in print mode with the local Qwen model
# Usage: pixelh

set -l prompt
if test (count $argv) -gt 0
set prompt (string join " " $argv)
else
read -P "Prompt: " prompt
end

if test -z "$prompt"
echo "No prompt provided, aborting." >&2
return 1
end

pi --model 'lmstudio/qwen3.5-0.8b-optiq' -p "$prompt"
end
2 changes: 2 additions & 0 deletions home-manager/services/make-updater/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ in
pkgs.bash
pkgs.coreutils
pkgs.gnumake
pkgs.jq
]
}:/opt/homebrew/bin:/usr/local/bin";
};
Expand Down Expand Up @@ -49,6 +50,7 @@ in
pkgs.gnumake
pkgs.gnused
pkgs.go
pkgs.jq
pkgs.libtool
pkgs.neovim
pkgs.nix
Expand Down
7 changes: 7 additions & 0 deletions named-hosts/matic/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ import ../../hosts/nixos {
security.pam.services.sudo = {
fprintAuth = true;
};
security.pam.services.polkit-1 = {
fprintAuth = true;
};

# Firmware updates
services.fwupd.enable = true;
Expand All @@ -217,6 +220,10 @@ import ../../hosts/nixos {
};
};
};
# auto-cpufreq-gtk writes turbo overrides to /opt/auto-cpufreq/
systemd.tmpfiles.rules = [
"d /opt/auto-cpufreq 0755 root root -"
];

# Power button behavior - lock screen instead of shutdown
services.logind.settings.Login.HandlePowerKey = "lock";
Expand Down
10 changes: 7 additions & 3 deletions named-hosts/matic/falcon.nix
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,15 @@ in
systemd.services.falcon-sensor = {
description = "CrowdStrike Falcon Sensor";
wantedBy = [ "multi-user.target" ];
# Falcon does not stop cleanly during nixos-rebuild switch, leaving
# vendor processes behind and causing restart attempts to fail with
# "Device or resource busy". Keep the running sensor in place during
# switch and apply unit changes on the next boot or manual restart.
restartIfChanged = false;

unitConfig.DefaultDependencies = false;
# Start-limit directives belong in [Unit], not [Service].
unitConfig.StartLimitIntervalSec = 0;
after = [ "local-fs.target" ];
conflicts = [ "shutdown.target" ];
before = [
Expand All @@ -48,9 +55,6 @@ in
Restart = "on-failure";
RestartSec = "15s";

# Avoid systemd giving up during flapping
StartLimitIntervalSec = 0;

TimeoutStopSec = "60s";
KillMode = "process";
Delegate = true;
Expand Down
16 changes: 13 additions & 3 deletions named-hosts/matic/kolide.nix
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
# sudo sh -c 'cat /tmp/kolide-deb/etc/kolide-k2/secret > /etc/kolide-k2/secret'
# sudo chown root:root /etc/kolide-k2/secret
# sudo chmod 600 /etc/kolide-k2/secret
{ pkgs, ... }:
{ lib, pkgs, ... }:

let
falconInstalled = builtins.pathExists /etc/nixos/falcon-sensor.deb;

# Official Kolide NixOS module
# Pin to specific commit to avoid hash mismatches when upstream pushes to main.
# To update: get latest commit from https://github.com/kolide/nix-agent
Expand All @@ -37,8 +39,16 @@ in
"f /var/lib/dpkg/status 0644 root root - Package: falcon-sensor\\nStatus: install ok installed\\nPriority: optional\\nSection: misc\\nInstalled-Size: 0\\nMaintainer: CrowdStrike\\nArchitecture: amd64\\nVersion: 7.31.0-18410\\nDescription: CrowdStrike Falcon Sensor (shim for Kolide/osquery on NixOS)\\n"
];

# Add dpkg to Kolide service PATH for deb_packages table
systemd.services.kolide-launcher.path = with pkgs; [ dpkg ];
systemd.services.kolide-launcher = {
# Kolide shells out to both dpkg-backed package checks and gsettings-based
# screen-lock checks, neither of which are on PATH by default on NixOS.
path = with pkgs; [ dpkg glib ];

# When Falcon is installed, start Kolide after it so the initial CrowdStrike
# compliance query does not race the sensor startup during boot/switch.
after = lib.optional falconInstalled "falcon-sensor.service";
wants = lib.optional falconInstalled "falcon-sensor.service";
};

# Enable Kolide launcher
services.kolide-launcher.enable = true;
Expand Down
43 changes: 43 additions & 0 deletions scripts/find-built-iso.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash

set -euo pipefail

result_path="${1:-./result}"

if [ ! -e "$result_path" ]; then
exit 1
fi

case "$result_path" in
*.iso)
if [ -f "$result_path" ]; then
printf '%s\n' "$result_path"
exit 0
fi
;;
esac

resolved_path=""
if command -v readlink >/dev/null 2>&1; then
resolved_path="$(readlink -f "$result_path" 2>/dev/null || true)"
fi
if [ -z "$resolved_path" ] && command -v realpath >/dev/null 2>&1; then
resolved_path="$(realpath "$result_path" 2>/dev/null || true)"
fi

case "$resolved_path" in
*.iso)
if [ -f "$resolved_path" ]; then
printf '%s\n' "$resolved_path"
exit 0
fi
;;
esac

iso_path="$(find -L "$result_path" -type f -name '*.iso' | sort | head -n 1)"
if [ -n "$iso_path" ]; then
printf '%s\n' "$iso_path"
exit 0
fi

exit 1
47 changes: 42 additions & 5 deletions scripts/llm-update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@ MODELS="$ROOT/models.json"
exit 1
}

require_command() {
local cmd="$1"
command -v "$cmd" >/dev/null 2>&1 || {
echo "ERROR: required command '$cmd' not found" >&2
exit 1
}
}

require_command jq
require_command sed
require_command mktemp
require_command mv

# jq function: derive display name from a model ID
# claude-opus-4.6 → "Claude Opus 4.6", claude-sonnet-4.5-20250929 → "Claude Sonnet 4.5"
# shellcheck disable=SC2016
Expand All @@ -33,15 +46,28 @@ JQ_PRETTY='def pretty:
# Build sed args from models.json
# Order: PRETTY, NONDOT, then base — longer patterns must be replaced first
sed_args=()
model_rows="$(
jq -r "$JQ_PRETTY"'
to_entries[] |
[.key, .value, (.value | pretty), (.value | gsub("\\.";"-"))] |
@tsv' "$MODELS"
)" || {
echo "ERROR: failed to parse models.json" >&2
exit 1
}

[[ -n "$model_rows" ]] || {
echo "ERROR: no model rows generated from $MODELS" >&2
exit 1
}

while IFS=$'\t' read -r key value pretty nondot; do
[[ -n "$key" ]] || continue
placeholder="__$(echo "$key" | tr 'a-z-' 'A-Z_')__"
sed_args+=(-e "s|${placeholder%__}_PRETTY__|${pretty}|g")
sed_args+=(-e "s|${placeholder%__}_NONDOT__|${nondot}|g")
sed_args+=(-e "s|${placeholder}|${value}|g")
done < <(jq -r "$JQ_PRETTY"'
to_entries[] |
[.key, .value, (.value | pretty), (.value | gsub("\\.";"-"))] |
@tsv' "$MODELS")
done <<< "$model_rows"

# Template → output pairs
declare -A TEMPLATES=(
Expand Down Expand Up @@ -82,7 +108,18 @@ for src in "${!TEMPLATES[@]}"; do
echo "SKIP: $src"
continue
}
sed "${sed_args[@]}" "$ROOT/$src" >"$ROOT/$dst"

tmp=$(mktemp "$ROOT/.llm-update.XXXXXX")
if ! sed "${sed_args[@]}" "$ROOT/$src" >"$tmp"; then
rm -f "$tmp"
echo "ERROR: sed failed for $src" >&2
exit 1
fi
if ! mv -f "$tmp" "$ROOT/$dst"; then
rm -f "$tmp"
echo "ERROR: failed to update $dst" >&2
exit 1
fi
echo "OK: $dst"
done

Expand Down
4 changes: 4 additions & 0 deletions spec/coverage_spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ It 'has spec file for scripts/check-nix-inline-scripts.sh'
The path "spec/check_nix_inline_scripts_spec.sh" should be exist
End

It 'has spec file for scripts/find-built-iso.sh'
The path "spec/find_built_iso_spec.sh" should be exist
End

It 'has spec file for home-manager/services/cliproxyapi/scripts/docker-start.sh'
The path "spec/cliproxyapi_docker_start_spec.sh" should be exist
End
Expand Down
Loading
Loading