From fea1370b52e570f67d2ba7b2bfb84df822da6f31 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Tue, 1 Jul 2025 17:27:45 -0700 Subject: [PATCH 01/23] 2025 07 01 --- chromebox/chromebox3/configuration.nix | 4 +- desktop/l/configuration.nix | 10 +- desktop/l/home.nix | 9 +- desktop/l/sysctl.nix | 13 +- desktop/l2/CPU_and_IRQ_optimization.md | 203 +++++++++++- desktop/l2/Makefile | 47 +-- desktop/l2/configuration.nix | 17 +- desktop/l2/crowdsec.nix | 89 +++++ desktop/l2/disko-l2.nix | 99 ++++++ desktop/l2/distributed-builds.nix | 28 -- desktop/l2/docker-daemon.nix | 27 -- desktop/l2/firewall-example.nix | 68 ++++ desktop/l2/firewall-security-analysis.md | 250 +++++++++++++++ desktop/l2/firewall-test.sh | 365 +++++++++++++++++++++ desktop/l2/firewall.md | 374 ++++++++++++++++++++++ desktop/l2/firewall.nix | 295 +++++++++++++++-- desktop/l2/flake.lock | 87 ++++- desktop/l2/flake.nix | 15 +- desktop/l2/hardware-configuration.nix | 24 +- desktop/l2/home.nix | 94 +++--- desktop/l2/hostapd-multi.nix | 15 +- desktop/l2/monitoring.nix | 373 --------------------- desktop/l2/network-optimization.nix | 6 +- desktop/l2/network.nix.not | 98 ------ desktop/l2/not.hostapd.nix | 173 ---------- desktop/l2/old.hardware-configuration.nix | 41 +++ desktop/l2/prometheus.nix | 63 +--- desktop/l2/systemd-slices.nix | 12 + desktop/l2/test-crowdsec.sh | 125 ++++++++ desktop/l2/wireless_desktop.nix | 20 -- 30 files changed, 2106 insertions(+), 938 deletions(-) create mode 100644 desktop/l2/crowdsec.nix create mode 100644 desktop/l2/disko-l2.nix delete mode 100644 desktop/l2/distributed-builds.nix delete mode 100644 desktop/l2/docker-daemon.nix create mode 100644 desktop/l2/firewall-example.nix create mode 100644 desktop/l2/firewall-security-analysis.md create mode 100755 desktop/l2/firewall-test.sh create mode 100644 desktop/l2/firewall.md delete mode 100644 desktop/l2/monitoring.nix delete mode 100644 desktop/l2/network.nix.not delete mode 100644 desktop/l2/not.hostapd.nix create mode 100644 desktop/l2/old.hardware-configuration.nix create mode 100755 desktop/l2/test-crowdsec.sh delete mode 100644 desktop/l2/wireless_desktop.nix diff --git a/chromebox/chromebox3/configuration.nix b/chromebox/chromebox3/configuration.nix index a45555b..25580cf 100644 --- a/chromebox/chromebox3/configuration.nix +++ b/chromebox/chromebox3/configuration.nix @@ -85,8 +85,8 @@ description = "das"; password = "admin123"; extraGroups = [ "wheel" "libvirtd" "docker" "kubernetes" ]; - packages = with pkgs; [ - ]; + # packages = with pkgs; [ + # ]; # https://nixos.wiki/wiki/SSH_public_key_authentication openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGMCFUMSCFJX95eLfm7P9r72NBp9I1FiXwNwJ+x/HGPV das@t" diff --git a/desktop/l/configuration.nix b/desktop/l/configuration.nix index 4bc55c8..07bdba7 100644 --- a/desktop/l/configuration.nix +++ b/desktop/l/configuration.nix @@ -139,11 +139,12 @@ services.pipewire = { enable = true; + audio.enable = true; alsa.enable = true; alsa.support32Bit = true; pulse.enable = true; - # Uncomment the following line if you want to use JACK applications - # jack.enable = true; + jack.enable = true; + wireplumber.enable = true; }; services.openssh.enable = true; @@ -250,6 +251,11 @@ config.common.default = "gtk"; }; + services.dbus.packages = with pkgs; [ + xdg-desktop-portal + xdg-desktop-portal-gtk + ]; + # # https://wiki.hyprland.org/Nix/Hyprland-on-NixOS/ # programs.hyprland = { # enable = true; diff --git a/desktop/l/home.nix b/desktop/l/home.nix index 638fd40..6002475 100644 --- a/desktop/l/home.nix +++ b/desktop/l/home.nix @@ -475,8 +475,7 @@ # Media vlc # ffmpeg moved to system package - #ffmpeg_7-full - #ffmpeg-full + ffmpeg_7-full # Go Development # https://nixos.wiki/wiki/Go @@ -680,6 +679,11 @@ #gpu monitoring lact + + # virtual camera control + # v4l2-ctl --list-devices + v4l-utils + libsForQt5.kdenlive ]; # vscode @@ -753,7 +757,6 @@ }; # https://nixos.wiki/wiki/OBS_Studio - # TODO add kernel module for virtual camera programs.obs-studio = { enable = true; plugins = with pkgs.obs-studio-plugins; [ diff --git a/desktop/l/sysctl.nix b/desktop/l/sysctl.nix index de472c7..aa45f18 100644 --- a/desktop/l/sysctl.nix +++ b/desktop/l/sysctl.nix @@ -17,6 +17,8 @@ "net.ipv4.tcp_wmem" = "4096 1000000 16000000"; #net.ipv4.tcp_rmem = 4096 131072 6291456 #net.ipv4.tcp_wmem = 4096 16384 4194304 + "net.ipv6.tcp_rmem" = "4096 1000000 16000000"; + "net.ipv6.tcp_wmem" = "4096 1000000 16000000"; # https://github.com/torvalds/linux/blob/master/Documentation/networking/ip-sysctl.rst?plain=1#L1042 # https://lwn.net/Articles/560082/ "net.ipv4.tcp_notsent_lowat" = "131072"; @@ -38,7 +40,7 @@ #net.core.rmem_max = 212992 #net.core.wmem_default = 212992 #net.core.wmem_max = 212992 - "net.ipv4.ip_local_port_range" = "1025 65535"; + "net.ipv4.ip_local_port_range" = "1026 65535"; #net.ipv4.ip_local_port_range ="32768 60999" # #net.ipv4.inet_peer_maxttl = 600 @@ -51,5 +53,14 @@ #net.ipv4.tcp_reflect_tos = 0 "net.ipv4.tcp_rto_min_us" = 50000; #50ms #net.ipv4.tcp_rto_min_us = 200000 #200ms + + # TCP optimizations for high performance + "net.ipv4.tcp_slow_start_after_idle" = 0; # Disable slow start after idle + "net.ipv4.tcp_fastopen" = 3; # Enable TCP Fast Open + + "net.ipv4.tcp_window_scaling" = 1; + "net.ipv4.tcp_sack" = 1; + "net.ipv4.tcp_fack" = 1; + "net.ipv4.tcp_fin_timeout" = 30; }; } \ No newline at end of file diff --git a/desktop/l2/CPU_and_IRQ_optimization.md b/desktop/l2/CPU_and_IRQ_optimization.md index 38e4aab..ed9b937 100644 --- a/desktop/l2/CPU_and_IRQ_optimization.md +++ b/desktop/l2/CPU_and_IRQ_optimization.md @@ -26,6 +26,7 @@ On this architecture, each physical core is split into two logical processors (S - **8 MSI-X vectors** distributed across cores 16-23 - **Current distribution**: Interrupts are clustered on cores 14, 15, 16, 17, 18, 20, 22, 23 - **Issue**: Competing with storage I/O and userland processes +- **Note**: LRO and GRO features are disabled due to compatibility issues with the Atlantic driver #### WiFi Interfaces (4x Intel iwlwifi) - **wlp35s0**: 16 MSI-X vectors, mostly on CPU 21 @@ -56,6 +57,11 @@ On this architecture, each physical core is split into two logical processors (S - Heavy network processing concentrated on cores 14, 15, 21, 23 - No dedicated cores for network processing +### 4. **Network Hardware Offload Limitations** +- **Atlantic NIC LRO/GRO Issues**: The Atlantic driver has compatibility issues with Large Receive Offload (LRO) and Generic Receive Offload (GRO) features +- **Impact**: Reduced CPU efficiency for packet processing, requiring software-based packet handling +- **Mitigation**: Optimized interrupt coalescing and ring buffer settings to compensate for disabled hardware offloads + ## Proposed Optimization Strategy ### Phase 1: Core Isolation and Dedication @@ -79,7 +85,7 @@ On this architecture, each physical core is split into two logical processors (S #### Userland Processing Cores (8-23) **Remaining cores for system services and userland:** - **Cores 8,20,9,21,10,22,11,23**: Userland processes, system services -- **Services**: hostapd, DHCP (Kea), DNS (PowerDNS), IPv6 RA (radvd) +- **Services**: hostapd, DHCP (Kea), DNS (PowerDNS), IPv6 RA (radvd), CrowdSec - **Slice**: system.slice and network-services.slice - **Benefits**: - Isolated from network interrupt processing @@ -152,7 +158,7 @@ done ```nix systemd.slices = { network-services = { - description = "Network services (DHCP, DNS, RA, hostapd)"; + description = "Network services (DHCP, DNS, RA, hostapd, CrowdSec)"; sliceConfig = { CPUAffinity = "8,20,9,21,10,22,11,23"; # Userland cores only Nice = -5; @@ -205,6 +211,18 @@ systemd.slices = { Slice = "network-services.slice"; }; }; + crowdsec = { + description = "CrowdSec threat detection engine slice"; + sliceConfig = { + Slice = "network-services.slice"; + }; + }; + crowdsec-firewall-bouncer = { + description = "CrowdSec firewall bouncer slice"; + sliceConfig = { + Slice = "network-services.slice"; + }; + }; }; ``` @@ -247,7 +265,157 @@ boot.kernel.sysctl = { }; ``` -### Phase 5: NUMA Optimization +### Phase 5: Network Hardware Optimization + +#### Atlantic NIC Optimizations +Due to compatibility issues with the Atlantic driver, certain hardware offload features are disabled: + +```bash +# Disabled features (causing issues with Atlantic driver) +# - LRO (Large Receive Offload): Causes packet corruption/drops +# - GRO (Generic Receive Offload): Causes stability issues + +# Enabled optimizations +ethtool -G enp1s0 rx 8184 tx 8184 # Maximum ring buffers +ethtool -K enp1s0 tx-checksum-ipv4 on # IPv4 checksum offload +ethtool -K enp1s0 tx-tcp-ecn-segmentation on # TCP ECN segmentation + +# Interrupt coalescing optimization +ethtool -C enp1s0 rx-usecs 512 rx-frames 32 +ethtool -C enp1s0 tx-usecs 1024 tx-frames 32 +``` + +**Impact and Mitigation:** +- **Performance Impact**: Disabled LRO/GRO reduces CPU efficiency for packet processing +- **Mitigation Strategy**: + - Optimized interrupt coalescing to reduce CPU overhead + - Maximum ring buffer sizes to handle burst traffic + - Dedicated network cores to compensate for software processing + - Enhanced interrupt distribution across isolated cores + +### Phase 6: CrowdSec Integration + +#### Dynamic Threat Detection +CrowdSec provides real-time threat detection and automatic blocking using nftables: + +```nix +# CrowdSec engine configuration +services.crowdsec = { + enable = true; + settings = { + api = { + server = { + listen_uri = "[::1]:8080"; # IPv6 localhost + trusted_ips = [ "127.0.0.1" "::1" ]; # No API key needed + }; + }; + db_config = { + type = "sqlite"; + db_path = "/var/lib/crowdsec/data/crowdsec.db"; + }; + }; +}; + +# Firewall bouncer for nftables integration +services.crowdsec-firewall-bouncer = { + enable = true; + settings = { + api_url = "http://[::1]:8080/"; + nftables = { + enabled = true; + table = "filter"; + chain = "input"; + set = "blacklist"; + ipv4 = true; + ipv6 = true; + }; + }; +}; +``` + +#### Resource Management for CrowdSec +Both CrowdSec services are assigned to the network-services slice with memory limits: + +```nix +systemd.services = { + # Network services (network-services slice, via per-daemon slices) + hostapd = { + serviceConfig = { + Slice = "hostapd.slice"; + Nice = -10; + IOSchedulingClass = 1; # Real-time I/O + IOSchedulingPriority = 4; + LimitNOFILE = 65536; + Restart = "always"; + RestartSec = "5s"; + }; + }; + + kea-dhcp4-server = { + serviceConfig = { + Slice = "kea.slice"; + Nice = -5; + LimitNOFILE = 65536; + Restart = "always"; + RestartSec = "10s"; + }; + }; + + pdns-recursor = { + serviceConfig = { + Slice = "pdns.slice"; + Nice = -5; + LimitNOFILE = 65536; + Restart = "always"; + RestartSec = "10s"; + }; + }; + + radvd = { + serviceConfig = { + Slice = "radvd.slice"; + Nice = -5; + Restart = "always"; + RestartSec = "10s"; + }; + }; + + # CrowdSec threat detection services + crowdsec = { + serviceConfig = { + Slice = "crowdsec.slice"; + Nice = -5; + LimitNOFILE = 65536; + MemoryHigh = "512M"; + MemoryMax = "1G"; + Environment = [ "GOMEMLIMIT=460M" ]; + Restart = "always"; + RestartSec = "5s"; + }; + }; + + crowdsec-firewall-bouncer = { + serviceConfig = { + Slice = "crowdsec-firewall-bouncer.slice"; + Nice = -5; + LimitNOFILE = 65536; + MemoryHigh = "256M"; + MemoryMax = "512M"; + Environment = [ "GOMEMLIMIT=230M" ]; + Restart = "always"; + RestartSec = "5s"; + }; + }; +}; +``` + +**Benefits:** +- **Real-time Protection**: Automatic blocking of malicious IPs +- **Community Intelligence**: Leverages global threat intelligence +- **Resource Efficiency**: Memory limits prevent resource exhaustion +- **Integration**: Seamless nftables integration with dynamic blacklist sets + +### Phase 7: NUMA Optimization #### Memory Allocation ```bash @@ -330,6 +498,33 @@ systemd.services = { RestartSec = "10s"; }; }; + + # CrowdSec threat detection services + crowdsec = { + serviceConfig = { + Slice = "crowdsec.slice"; + Nice = -5; + LimitNOFILE = 65536; + MemoryHigh = "512M"; + MemoryMax = "1G"; + Environment = [ "GOMEMLIMIT=460M" ]; + Restart = "always"; + RestartSec = "5s"; + }; + }; + + crowdsec-firewall-bouncer = { + serviceConfig = { + Slice = "crowdsec-firewall-bouncer.slice"; + Nice = -5; + LimitNOFILE = 65536; + MemoryHigh = "256M"; + MemoryMax = "512M"; + Environment = [ "GOMEMLIMIT=230M" ]; + Restart = "always"; + RestartSec = "5s"; + }; + }; }; ``` @@ -463,6 +658,8 @@ Core Allocation: | Kea | DHCP server | kea.slice (child of network-services.slice) | 8,20,9,21,10,22,11,23 | -5 | | PowerDNS | DNS resolver | pdns.slice (child of network-services.slice)| 8,20,9,21,10,22,11,23 | -5 | | radvd | IPv6 RA | radvd.slice (child of network-services.slice)| 8,20,9,21,10,22,11,23 | -5 | +| CrowdSec | Threat detection | crowdsec.slice (child of network-services.slice) | 8,20,9,21,10,22,11,23 | -5 | +| CrowdSec FW | Firewall bouncer | crowdsec-firewall-bouncer.slice (child of network-services.slice) | 8,20,9,21,10,22,11,23 | -5 | **Note:** All services inherit CPU affinity and resource limits from their assigned slice. Only the two main parent slices (network-services and system) need explicit CPU affinity settings. **Network cores (0,12,1,13,2,14,3,15,4,5,6,7) are isolated by `isolcpus` and can only be used for IRQ affinity, not for systemd slice CPU affinity.** Kernel-level components like nftables and CAKE (QoS) are not managed by systemd slices; their performance is influenced by CPU isolation, IRQ affinity, and kernel boot parameters, not by systemd. diff --git a/desktop/l2/Makefile b/desktop/l2/Makefile index da37477..fc431e6 100644 --- a/desktop/l2/Makefile +++ b/desktop/l2/Makefile @@ -1,5 +1,5 @@ # -# nixos/laptops/l/Makefile +# nixos/laptops/l2/Makefile # EXPECTED_HOSTNAME := l2 @@ -18,9 +18,15 @@ endif rebuild: sudo nixos-rebuild switch --flake . -rebuild_t: +rebuild_l2: sudo nixos-rebuild switch --flake .#l2 +anywhere: + nix run github:nix-community/nixos-anywhere -- \ + --generate-hardware-config nixos-generate-config ./hardware-configuration.nix \ + --target-host root@172.16.40.51 \ + --flake '.#l2' + #https://nixos.org/manual/nixos/unstable/index.html#sec-nix-network-issues #nixos-rebuild switch --option binary-caches http://my-cache.example.org/ @@ -36,40 +42,7 @@ update: sync: rsync -avz /home/das/nixos/ "${EXPECTED_HOSTNAME}":/home/das/nixos/ -rebuild_old: - # sudo cp ./flake.nix /etc/nixos/ - # sudo cp ./flake.lock /etc/nixos/ - # sudo cp ../../modules/* /etc/nixos/ - # sudo cp ./configuration.nix /etc/nixos/ - # #sudo cp ./home-manager.nix /etc/nixos/ - # sudo cp ./home.nix /etc/nixos/ - # sudo cp ./prometheus.nix /etc/nixos/ - # sudo cp ./*.nix /etc/nixos/ - # sudo nix-channel --update - # sudo nixos-rebuild switch - #sudo cp ./* /etc/nixos/ - sudo nix flake update; - #sudo nix-channel --update; - sudo nixos-rebuild switch --flake . - -update_oldm.: - sudo nix-channel --update - sudo nixos-rebuild switch - #nix-shell -p vim - -restart_display_manager: - sudo systemctl restart display-manager.service - -#ls -l /run/opengl-driver/lib/gbm/ -#readlink /run/opengl-driver/lib/gbm/dri_gbm.so -#glxinfo | grep -i 'renderer' - -#journalctl -b | grep -Ei 'X.*fatal|gdm|wayland|mesa|amdgpu' --no-pager -#less /var/log/Xorg.0.log - -#nix-shell -p mesa-demos -#glxinfo | grep -i opengl - -# cat configuration.nix | grep -A 20 "hardware.graphics =" +s: + rsync -avz /home/das/nixos/ 172.16.40.47:/home/das/nixos/ # end diff --git a/desktop/l2/configuration.nix b/desktop/l2/configuration.nix index bb4ab57..6b9bba2 100644 --- a/desktop/l2/configuration.nix +++ b/desktop/l2/configuration.nix @@ -16,6 +16,7 @@ # https://nixos-and-flakes.thiscute.world/nixos-with-flakes/start-using-home-manager imports = [ + ./disko-l2.nix ./hardware-configuration.nix #./hardware-graphics.nix ./sysctl.nix @@ -23,6 +24,7 @@ ./locale.nix ./hosts.nix ./firewall.nix + ./crowdsec.nix #./systemdSystem.nix ./systemPackages.nix # home manager is imported in the flake @@ -127,7 +129,16 @@ systemd.services.systemd-udev-settle.enable = false; - services.openssh.enable = true; + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + KbdInteractiveAuthentication = false; + PermitRootLogin = "yes"; # Change me to "no"!! + #AllowUsers = [ "das" ] + }; + }; + programs.ssh.extraConfig = '' Host hp4.home PubkeyAcceptedKeyTypes ssh-ed25519 @@ -156,6 +167,7 @@ users.users.das = { isNormalUser = true; description = "das"; + password = "admin123"; # FIX ME!! extraGroups = [ "wheel" "networkmanager" "kvm" "libvirtd" "docker" "video" ]; packages = with pkgs; [ ]; @@ -179,7 +191,8 @@ # ociSeccompBpfHook.enable = true; # }; - system.stateVersion = "24.11"; + #system.stateVersion = "24.11"; + system.stateVersion = "25.05"; systemd.extraConfig = "CPUAffinity=8,20,9,21,10,22,11,23"; systemd.user.extraConfig = "CPUAffinity=8,20,9,21,10,22,11,23"; diff --git a/desktop/l2/crowdsec.nix b/desktop/l2/crowdsec.nix new file mode 100644 index 0000000..37037e9 --- /dev/null +++ b/desktop/l2/crowdsec.nix @@ -0,0 +1,89 @@ +{ config, pkgs, ... }: + +{ + # Enable CrowdSec engine with nftables integration + services.crowdsec = { + enable = true; + + # Allow access to local systemd journal + allowLocalJournalAccess = true; + + # Configure data sources for threat detection + acquisitions = [ + { + source = "journalctl"; + journalctl_filter = ["_SYSTEMD_UNIT=sshd.service"]; + labels.type = "syslog"; + } + { + source = "journalctl"; + journalctl_filter = ["_SYSTEMD_UNIT=systemd-logind.service"]; + labels.type = "syslog"; + } + ]; + + # Use flake defaults for all configuration + settings = { + # Only override the API server to use IPv6 localhost + api = { + server = { + listen_uri = "[::1]:8080"; + # Trust localhost for API access (no API key needed for loopback) + trusted_ips = [ "127.0.0.1" "::1" ]; + }; + }; + }; + }; + + # Enable the firewall bouncer for CrowdSec with nftables support + services.crowdsec-firewall-bouncer = { + enable = true; + + # Use flake defaults for all configuration + settings = { + # Only override the API URL to use IPv6 localhost + api_url = "http://[::1]:8080/"; + + # Authentication settings for newer bouncer versions + api_key = "ui00eX/NzDpjb6+m/xC+us1/SFHFNxQdOAmOqZur+4Y"; # Inscure!! Need to come up with a better way to handle this + cert_path = ""; # Empty for localhost authentication + key_path = ""; # Empty for localhost authentication + + # Disable TLS for localhost communication + use_tls = false; + ca_cert_path = ""; + + # Use the same blacklist set names as our firewall + blacklists_ipv4 = "blacklist"; + blacklists_ipv6 = "blacklist6"; + }; + }; + + # Install CrowdSec CLI tools + environment.systemPackages = with pkgs; [ + crowdsec + crowdsec-firewall-bouncer + ]; + + # Add memory limits and Go memory environment variables to CrowdSec services + # These are not set by the flake modules, so we can add them safely + systemd.services.crowdsec = { + serviceConfig = { + # Memory limits for CrowdSec engine (log processing and threat detection) + MemoryHigh = "512M"; # high water mark + MemoryMax = "650M"; # hard limit + # Go memory limit (90% of systemd limit) + Environment = [ "GOMEMLIMIT=460MiB" ]; # 90% of 512MB + }; + }; + + systemd.services.crowdsec-firewall-bouncer = { + serviceConfig = { + # Memory limits for firewall bouncer (API polling and nftables management) + MemoryHigh = "256M"; # high water mark + MemoryMax = "400M"; # hard limit + # Go memory limit (90% of systemd limit) + Environment = [ "GOMEMLIMIT=230MiB" ]; # 90% of 256MB + }; + }; +} \ No newline at end of file diff --git a/desktop/l2/disko-l2.nix b/desktop/l2/disko-l2.nix new file mode 100644 index 0000000..715d2a5 --- /dev/null +++ b/desktop/l2/disko-l2.nix @@ -0,0 +1,99 @@ +# +# nixos/desktop/l2 +# +# Starting point was: +# https://github.com/nix-community/disko/blob/master/example/lvm-sizes-sort.nix +# +# swap +# https://github.com/nix-community/disko/blob/master/example/swap.nix +# +# tmpfs +# https://github.com/nix-community/disko/blob/master/example/tmpfs.nix +# +# Other templates +# https://github.com/nix-community/disko-templates/blob/main/zfs-impermanence/disko-config.nix + +{ + disko.devices = { + disk = { + one = { + type = "disk"; + device = "/dev/nvme0n1"; + content = { + type = "gpt"; + partitions = { + boot = { + size = "1M"; + type = "EF02"; # for grub MBR + }; + ESP = { + name = "ESP"; + size = "512M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ "umask=0077" ]; + }; + }; + primary = { + size = "100%"; + content = { + type = "lvm_pv"; + vg = "pool"; + }; + }; + }; + }; + }; + }; + lvm_vg = { + pool = { + type = "lvm_vg"; + lvs = { + swap = { + #size = "10%"; # --vm-test + size = "128G"; + content = { + type ="swap"; + #discardPolicy = "both"; + resumeDevice = true; # resume from hiberation from this device + }; + }; + root = { + size = "90%"; + content = { + type = "filesystem"; + format = "xfs"; # <---------- xfs! + mountpoint = "/"; + mountOptions = [ "defaults" ]; + #mountOptions = [ "defaults" "pquota" ]; + }; + }; + }; + }; + }; + # nodev = { + # "/tmp" = { + # fsType = "tmpfs"; + # mountOptions = [ "size=200M" ]; + # }; + # }; + }; +} + +# [das@l2:~]$ lsblk +# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS +# sda 8:0 1 0B 0 disk +# sdb 8:16 1 0B 0 disk +# sdc 8:32 1 0B 0 disk +# nvme0n1 259:0 0 1.9T 0 disk +# ├─nvme0n1p1 259:1 0 512M 0 part /boot +# ├─nvme0n1p2 259:2 0 1.7T 0 part +# │ └─luks-6fd137fa-aa82-4200-9ca1-cd049de90418 254:0 0 1.7T 0 crypt /nix/store +# │ / +# └─nvme0n1p3 259:3 0 138.2G 0 part +# nvme1n1 259:4 0 1.8T 0 disk + +# [das@l2:~]$ \ No newline at end of file diff --git a/desktop/l2/distributed-builds.nix b/desktop/l2/distributed-builds.nix deleted file mode 100644 index cd2717d..0000000 --- a/desktop/l2/distributed-builds.nix +++ /dev/null @@ -1,28 +0,0 @@ -# -# latops/t/distributed-builds.nix -# -# https://nix.dev/tutorials/nixos/distributed-builds-setup.html#set-up-distributed-builds -# https://docs.nixbuild.net/getting-started/#quick-nixos-configuration -{ pkgs, ... }: -{ - nix.distributedBuilds = true; - nix.settings.builders-use-substitutes = true; - - nix.buildMachines = [ - { - hostName = "hp4.home"; - sshUser = "remotebuild"; - sshKey = "/root/.ssh/remotebuild"; - system = pkgs.stdenv.hostPlatform.system; - maxJobs = 100; - supportedFeatures = [ "nixos-test" "big-parallel" "kvm" ]; - } - ]; -} - -# https://docs.nixbuild.net/getting-started/#your-first-build -# nix-build \ -# --max-jobs 0 \ -# --builders "ssh://hp4 x86_64-linux - 100 1 big-parallel,benchmark" \ -# -I nixpkgs=channel:nixos-20.03 \ -# --expr '((import {}).runCommand "test${toString builtins.currentTime}" {} "echo Hello nixbuild.net; touch $out")' \ No newline at end of file diff --git a/desktop/l2/docker-daemon.nix b/desktop/l2/docker-daemon.nix deleted file mode 100644 index fe72a86..0000000 --- a/desktop/l2/docker-daemon.nix +++ /dev/null @@ -1,27 +0,0 @@ - -{ config, pkgs, ... }: - -{ - # https://nixos.wiki/wiki/Docker - # https://search.nixos.org/options?from=0&size=50&sort=alpha_asc&query=virtualisation.docker - # https://search.nixos.org/options?channel=24.05&show=virtualisation.docker.extraOptions&from=0&size=50&sort=alpha_asc&type=packages&query=virtualisation.docker - # https://github.com/NixOS/nixpkgs/issues/68349 - virtualisation.docker.enable = true; - virtualisation.docker.daemon.settings = { - data-root = "/home/das/docker/"; - userland-proxy = false; - experimental = true; - ipv6 = true; - fixed-cidr-v6 = "fd00::/80"; - metrics-addr = "0.0.0.0:9323"; - # log-driver = "json-file"; - # log-opts.max-size = "10m"; - # log-opts.max-file = "10"; - }; - #this doesn't work - #virtualisation.docker.daemon.settings.log-opts.max-size = "10m"; - # https://docs.docker.com/reference/cli/dockerd/ - #virtualisation.docker.extraOptions = "--userland-proxy=false"; - #virtualisation.docker.extraOptions = "--log-opt=max-size=10m"; - #virtualisation.docker.extraOptions = "--ipv6"; -} \ No newline at end of file diff --git a/desktop/l2/firewall-example.nix b/desktop/l2/firewall-example.nix new file mode 100644 index 0000000..318d2e3 --- /dev/null +++ b/desktop/l2/firewall-example.nix @@ -0,0 +1,68 @@ +# Example firewall configurations for different machines +# Copy this file and customize the variables for your specific machine + +# Example 1: L2 WiFi Access Point (current configuration) +{ config, pkgs, ... }: + +let + # Interface configuration for L2 machine + wanInterface = "enp1s0"; # External/WAN interface + lanInterface = "br0"; # Internal/LAN bridge interface + upstreamLanPrefix = "172.16.0.0/16"; # Upstream LAN prefix for management access + internalIPv4Prefix = "192.168.1.0/24"; # Internal IPv4 subnet + internalIPv6Prefix = "fd00::/64"; # Internal IPv6 subnet +in { + # Import the main firewall configuration + imports = [ ./firewall.nix ]; +} + +# Example 2: Different machine with different interface names +/* +{ config, pkgs, ... }: + +let + # Interface configuration for different machine + wanInterface = "eth0"; # External/WAN interface (different name) + lanInterface = "wlan0"; # Internal/LAN interface (WiFi instead of bridge) + upstreamLanPrefix = "10.0.0.0/8"; # Different upstream LAN + internalIPv4Prefix = "192.168.100.0/24"; # Different internal subnet + internalIPv6Prefix = "fd01::/64"; # Different internal IPv6 subnet +in { + # Import the main firewall configuration + imports = [ ./firewall.nix ]; +} +*/ + +# Example 3: Server with multiple interfaces +/* +{ config, pkgs, ... }: + +let + # Interface configuration for server + wanInterface = "eno1"; # External/WAN interface + lanInterface = "eno2"; # Internal/LAN interface (separate NIC) + upstreamLanPrefix = "172.20.0.0/16"; # Different upstream network + internalIPv4Prefix = "10.10.0.0/24"; # Different internal subnet + internalIPv6Prefix = "fd02::/64"; # Different internal IPv6 subnet +in { + # Import the main firewall configuration + imports = [ ./firewall.nix ]; +} +*/ + +# Example 4: Virtual machine +/* +{ config, pkgs, ... }: + +let + # Interface configuration for VM + wanInterface = "ens3"; # External/WAN interface (VM naming) + lanInterface = "ens4"; # Internal/LAN interface + upstreamLanPrefix = "192.168.122.0/24"; # Libvirt default network + internalIPv4Prefix = "192.168.200.0/24"; # VM internal subnet + internalIPv6Prefix = "fd03::/64"; # VM internal IPv6 subnet +in { + # Import the main firewall configuration + imports = [ ./firewall.nix ]; +} +*/ \ No newline at end of file diff --git a/desktop/l2/firewall-security-analysis.md b/desktop/l2/firewall-security-analysis.md new file mode 100644 index 0000000..749d08c --- /dev/null +++ b/desktop/l2/firewall-security-analysis.md @@ -0,0 +1,250 @@ +# Firewall Security Analysis for L2 WiFi Access Point + +## Executive Summary + +The L2 WiFi access point firewall configuration demonstrates a solid security foundation with good principles including default-deny policies, stateful inspection, and comprehensive anti-spoofing measures. The recent improvements add rate limiting, enhanced ICMP handling, and better logging capabilities. + +## Security Assessment + +### Strengths + +1. **Strong Default-Deny Policy**: All chains use appropriate default policies (drop for input/forward, accept for output) +2. **Comprehensive Anti-Spoofing**: Loopback and special-purpose IP blocking on all interfaces +3. **Stateful Inspection**: Proper use of connection tracking for established/related traffic +4. **Network Segmentation**: Clear separation between internal (br0) and external (enp1s0) interfaces +5. **Service Access Control**: Services only accessible from internal interfaces +6. **IPv6 Support**: Comprehensive IPv6 filtering and NAT support + +### Security Improvements Implemented + +#### 1. Rate Limiting +- **SSH Rate Limiting**: 3 new connections per minute to prevent brute force attacks +- **ICMP Rate Limiting**: 10/second for internal, 5/second for external to prevent ping floods +- **Log Rate Limiting**: 5/minute to prevent log flooding during attacks + +#### 2. Enhanced ICMP/ICMPv6 Handling +- **Additional ICMP Types**: Added parameter-problem and echo-reply for proper operation +- **IPv6 Neighbor Discovery**: Comprehensive ND protocol support +- **Path MTU Discovery**: Proper ICMPv6 packet-too-big handling + +#### 3. Improved Forward Chain +- **ICMP Forwarding**: Essential ICMP/ICMPv6 messages for network operation +- **Bidirectional ICMP**: Proper handling of both directions for diagnostics + +#### 4. Enhanced Output Chain Protection +- **Internal Interface Filtering**: Blocks traffic to special-purpose addresses going out br0 interface +- **Subnet Exceptions**: Only allows traffic to allocated subnets (192.168.1.0/24, fd00::/64) +- **Network Isolation**: Prevents router from being used to reach other private networks + +#### 5. Performance Optimizations +- **nftables Sets**: Special-purpose address ranges defined as sets for better performance +- **Loopback Sets**: Dedicated sets for IPv4 and IPv6 loopback addresses for consistent filtering +- **Service Port Sets**: Common service ports (SSH, DNS, DHCP) defined as sets for readability +- **Logical Consolidation**: Loopback rules consolidated using OR operators (75% rule reduction) +- **Rule Ordering**: Optimized rule sequence for maximum performance +- **Intentional Exclusions**: 192.168.0.0/16 explicitly excluded from special-purpose set (allocated to 192.168.1.0/24) + +#### 6. Reusability and Configuration +- **Configurable Interfaces**: Interface names defined as variables for cross-machine deployment +- **Network Prefix Variables**: Subnet prefixes configurable for different network topologies +- **Modular Design**: Same firewall rules can be used on machines with different NIC naming schemes + +## Security Best Practices Compliance + +### ✅ Implemented Best Practices + +1. **Principle of Least Privilege**: Services only accessible where needed +2. **Defense in Depth**: Multiple layers of protection (anti-spoofing, rate limiting, logging) +3. **Fail-Safe Defaults**: Default-deny policies with explicit allow rules +4. **Comprehensive Logging**: All dropped packets logged with rate limiting +5. **Stateful Inspection**: Connection tracking for efficient and secure traffic handling +6. **Network Segmentation**: Clear interface separation and access control + +### 🔄 Areas for Further Enhancement + +#### 1. Advanced Threat Protection +```nft +# Consider adding these rules for enhanced security: + +# Drop fragmented packets (potential evasion technique) +ip frag-off & 0x1fff != 0 drop + +# Drop packets with invalid TCP flags +tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|syn|rst|psh|ack|urg) drop + +# Rate limit connection attempts per source IP +ct state new limit rate 30/second accept +``` + +#### 2. Application Layer Filtering +```nft +# Consider adding application-specific rules: + +# Block common attack ports +tcp dport { 23, 135, 137, 138, 139, 445, 1433, 1521, 3306, 3389 } drop + +# Allow only specific outbound protocols +tcp dport { 80, 443, 53, 123 } accept # HTTP, HTTPS, DNS, NTP +``` + +#### 3. Enhanced Monitoring +```bash +# Add these monitoring scripts: + +# Monitor connection tracking table +watch -n 5 'cat /proc/net/nf_conntrack | wc -l' + +# Monitor rate limit violations +journalctl -f -u nftables | grep "limit" + +# Monitor unusual traffic patterns +nft list ruleset -s +``` + +## Security Recommendations + +### 1. Immediate Improvements + +#### A. Add Fragment Protection +```nix +# Add to firewall.nix input chain: +# Drop fragmented packets (potential evasion) +ip frag-off & 0x1fff != 0 drop +``` + +#### B. Enhance TCP Flag Filtering +```nix +# Add to firewall.nix input chain: +# Drop invalid TCP flag combinations +tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|syn|rst|psh|ack|urg) drop +tcp flags & (fin|syn) == (fin|syn) drop # SYN+FIN +tcp flags & (syn|rst) == (syn|rst) drop # SYN+RST +``` + +#### C. Add Connection Rate Limiting +```nix +# Add to firewall.nix forward chain: +# Rate limit new connections per source +ct state new limit rate 30/second accept +``` + +### 2. Medium-term Enhancements + +#### A. Implement Geo-blocking +```nix +# Consider blocking traffic from known malicious countries +# Requires additional data sources and maintenance +``` + +#### B. Add Deep Packet Inspection +```nix +# Consider using nftables with payload matching for application filtering +# Example: Block specific HTTP User-Agent strings +``` + +#### C. Implement Intrusion Detection +```nix +# Consider integrating with Suricata or Snort for advanced threat detection +``` + +### 3. Long-term Security Strategy + +#### A. Security Monitoring Dashboard +- Implement centralized logging with ELK stack or similar +- Create alerts for unusual traffic patterns +- Regular security audits and penetration testing + +#### B. Automated Security Updates +- Regular firewall rule updates based on threat intelligence +- Automated vulnerability scanning +- Security patch management + +#### C. Incident Response Plan +- Document procedures for security incidents +- Regular security drills and testing +- Backup and recovery procedures + +## Configuration Validation + +### Testing Commands + +```bash +# Test rate limiting +for i in {1..10}; do ssh -o ConnectTimeout=1 user@192.168.1.1; done + +# Test ICMP filtering +ping -c 1 192.168.1.1 # Should work from br0 +ping -c 1 8.8.8.8 # Should be blocked from external + +# Test anti-spoofing +ping -I 127.0.0.1 8.8.8.8 # Should be blocked + +# Test connection tracking +curl -I https://example.com # Should work +# Return traffic should be automatically allowed + +# Monitor firewall logs +journalctl -f -u nftables +``` + +### Verification Checklist + +- [ ] Default-deny policies are active +- [ ] Rate limiting is working for SSH and ICMP +- [ ] Anti-spoofing rules are blocking invalid traffic +- [ ] Connection tracking is allowing return traffic +- [ ] Logging is capturing dropped packets +- [ ] IPv6 functionality is working correctly +- [ ] NAT is functioning for both IPv4 and IPv6 + +## Performance Considerations + +### Current Optimizations +- Connection tracking table size: 262,144 entries +- Efficient rule ordering (most common traffic first) +- Rate limiting prevents resource exhaustion + +### Monitoring Metrics +- Connection tracking table utilization +- Packet processing statistics +- Interface traffic patterns +- CPU usage during high traffic + +## Compliance and Standards + +### RFC Compliance +- RFC 6890: Special-Purpose Address Registry +- RFC 4861: IPv6 Neighbor Discovery +- RFC 4443: ICMPv6 + +### Security Standards +- NIST Cybersecurity Framework +- CIS Controls +- ISO 27001 (if applicable) + +## Conclusion + +The L2 WiFi access point firewall provides a solid security foundation with recent improvements adding important protections against common attack vectors. The implementation follows security best practices and provides comprehensive protection for both the router and its clients. + +The recommended enhancements will further strengthen the security posture while maintaining performance and functionality. Regular monitoring and testing should be implemented to ensure ongoing security effectiveness. + +## Maintenance Schedule + +### Daily +- Monitor firewall logs for unusual activity +- Check connection tracking table utilization + +### Weekly +- Review rate limit violations +- Analyze traffic patterns +- Update threat intelligence feeds + +### Monthly +- Security audit and penetration testing +- Review and update firewall rules +- Performance optimization review + +### Quarterly +- Comprehensive security assessment +- Update security policies and procedures +- Staff security training and awareness \ No newline at end of file diff --git a/desktop/l2/firewall-test.sh b/desktop/l2/firewall-test.sh new file mode 100755 index 0000000..bcecd36 --- /dev/null +++ b/desktop/l2/firewall-test.sh @@ -0,0 +1,365 @@ +#!/bin/bash + +# Firewall Security Testing Script for L2 WiFi Access Point +# This script validates the firewall configuration and security measures + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Configuration +ROUTER_IP="192.168.1.1" +ROUTER_IPV6="fd00::1" +INTERNAL_SUBNET="192.168.1.0/24" +INTERNAL_IPV6_SUBNET="fd00::/64" +EXTERNAL_IP="8.8.8.8" +EXTERNAL_IPV6="2001:4860:4860::8888" + +# Test counters +TESTS_PASSED=0 +TESTS_FAILED=0 +TOTAL_TESTS=0 + +# Function to print test results +print_result() { + local test_name="$1" + local result="$2" + local details="$3" + + TOTAL_TESTS=$((TOTAL_TESTS + 1)) + + if [ "$result" = "PASS" ]; then + echo -e "${GREEN}✓ PASS${NC}: $test_name" + if [ -n "$details" ]; then + echo -e " ${BLUE}Details:${NC} $details" + fi + TESTS_PASSED=$((TESTS_PASSED + 1)) + else + echo -e "${RED}✗ FAIL${NC}: $test_name" + if [ -n "$details" ]; then + echo -e " ${YELLOW}Details:${NC} $details" + fi + TESTS_FAILED=$((TESTS_FAILED + 1)) + fi + echo +} + +# Function to check if command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Function to check if we're running as root +check_root() { + if [ "$EUID" -ne 0 ]; then + echo -e "${RED}Error: This script must be run as root${NC}" + exit 1 + fi +} + +# Function to check nftables status +check_nftables_status() { + echo -e "${BLUE}=== Checking nftables Status ===${NC}" + + if systemctl is-active --quiet nftables; then + print_result "nftables service" "PASS" "Service is running" + else + print_result "nftables service" "FAIL" "Service is not running" + return 1 + fi + + if nft list ruleset >/dev/null 2>&1; then + print_result "nftables ruleset" "PASS" "Ruleset is loaded" + else + print_result "nftables ruleset" "FAIL" "Failed to load ruleset" + return 1 + fi +} + +# Function to test basic connectivity +test_basic_connectivity() { + echo -e "${BLUE}=== Testing Basic Connectivity ===${NC}" + + # Test internal connectivity + if ping -c 1 -W 2 "$ROUTER_IP" >/dev/null 2>&1; then + print_result "Internal IPv4 connectivity" "PASS" "Can reach router at $ROUTER_IP" + else + print_result "Internal IPv4 connectivity" "FAIL" "Cannot reach router at $ROUTER_IP" + fi + + # Test IPv6 connectivity + if command_exists ping6 && ping6 -c 1 -W 2 "$ROUTER_IPV6" >/dev/null 2>&1; then + print_result "Internal IPv6 connectivity" "PASS" "Can reach router at $ROUTER_IPV6" + else + print_result "Internal IPv6 connectivity" "FAIL" "Cannot reach router at $ROUTER_IPV6" + fi +} + +# Function to test SSH rate limiting +test_ssh_rate_limiting() { + echo -e "${BLUE}=== Testing SSH Rate Limiting ===${NC}" + + local failed_attempts=0 + local max_attempts=10 # Test more attempts to ensure we hit the rate limit + + # Test SSH rate limiting by attempting connections rapidly + # This should trigger the rate limiting rules + for i in $(seq 1 $max_attempts); do + # Use ssh with a non-existent user to trigger authentication failure + # This should hit the rate limiting before authentication + if timeout 1 ssh -o ConnectTimeout=1 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o PasswordAuthentication=yes nonexistent@"$ROUTER_IP" "exit" 2>/dev/null; then + failed_attempts=$((failed_attempts + 1)) + fi + # No sleep to trigger rate limiting faster + done + + if [ $failed_attempts -ge 6 ]; then + print_result "SSH rate limiting" "PASS" "$failed_attempts/$max_attempts attempts were blocked (rate limiting working)" + else + print_result "SSH rate limiting" "FAIL" "Only $failed_attempts/$max_attempts attempts were blocked (should block at least 6)" + fi +} + +# Function to test ICMP rate limiting +test_icmp_rate_limiting() { + echo -e "${BLUE}=== Testing ICMP Rate Limiting ===${NC}" + + # Test internal ICMP rate limiting (10/second limit with burst 5) + local ping_success=0 + for i in $(seq 1 30); do + if ping -c 1 -W 1 "$ROUTER_IP" >/dev/null 2>&1; then + ping_success=$((ping_success + 1)) + fi + # No sleep to trigger rate limiting faster + done + + # With 10/second limit and burst 5, we should see rate limiting with 30 rapid pings + if [ $ping_success -le 28 ]; then + print_result "Internal ICMP rate limiting" "PASS" "$ping_success/30 pings succeeded (rate limiting active)" + else + print_result "Internal ICMP rate limiting" "FAIL" "$ping_success/30 pings succeeded (no rate limiting detected, limit is 10/second with burst 5)" + fi +} + +# Function to test anti-spoofing +test_anti_spoofing() { + echo -e "${BLUE}=== Testing Anti-Spoofing ===${NC}" + + # Test loopback spoofing + if ping -I 127.0.0.1 -c 1 -W 2 "$EXTERNAL_IP" >/dev/null 2>&1; then + print_result "Loopback spoofing protection" "FAIL" "Loopback spoofed packets were allowed" + else + print_result "Loopback spoofing protection" "PASS" "Loopback spoofed packets were blocked" + fi + + # Test special-purpose IP spoofing + if ping -I 192.168.1.100 -c 1 -W 2 10.0.0.1 >/dev/null 2>&1; then + print_result "Special-purpose IP protection" "FAIL" "Special-purpose IP traffic was allowed" + else + print_result "Special-purpose IP protection" "PASS" "Special-purpose IP traffic was blocked" + fi +} + +# Function to test connection tracking +test_connection_tracking() { + echo -e "${BLUE}=== Testing Connection Tracking ===${NC}" + + # Test that return traffic is allowed + if curl -s --connect-timeout 5 --max-time 10 -I https://httpbin.org/status/200 >/dev/null 2>&1; then + print_result "Connection tracking" "PASS" "Outbound HTTPS connection and return traffic allowed" + else + print_result "Connection tracking" "FAIL" "Outbound HTTPS connection failed" + fi +} + +# Function to test service access control +test_service_access() { + echo -e "${BLUE}=== Testing Service Access Control ===${NC}" + + # Test DNS access (PowerDNS Recursor) from localhost + if nslookup google.com 127.0.0.1 >/dev/null 2>&1; then + print_result "DNS service access (localhost)" "PASS" "DNS queries to PowerDNS Recursor via localhost allowed" + else + print_result "DNS service access (localhost)" "FAIL" "DNS queries to PowerDNS Recursor via localhost blocked" + fi + + # Test DNS access from br0 interface + if nslookup google.com "$ROUTER_IP" >/dev/null 2>&1; then + print_result "DNS service access (br0)" "PASS" "DNS queries to PowerDNS Recursor via br0 allowed" + else + print_result "DNS service access (br0)" "FAIL" "DNS queries to PowerDNS Recursor via br0 blocked" + fi + + # Test DHCPv4 port access (should be open for DHCP clients) + if nc -z -w 2 "$ROUTER_IP" 67 2>/dev/null; then + print_result "DHCPv4 service access" "PASS" "DHCPv4 port 67 accessible" + else + print_result "DHCPv4 service access" "FAIL" "DHCPv4 port 67 not accessible" + fi + + # Test DHCPv6 port access (not running, should be blocked) + if nc -z -w 2 "$ROUTER_IP" 547 2>/dev/null; then + print_result "DHCPv6 service access" "FAIL" "DHCPv6 port 547 accessible (should be blocked, service not running)" + else + print_result "DHCPv6 service access" "PASS" "DHCPv6 port 547 blocked (service not running)" + fi +} + +# Function to test IPv6 functionality +test_ipv6_functionality() { + echo -e "${BLUE}=== Testing IPv6 Functionality ===${NC}" + + if ! command_exists ping6; then + print_result "IPv6 testing" "SKIP" "ping6 command not available" + return + fi + + # Test IPv6 connectivity + if ping6 -c 1 -W 2 "$ROUTER_IPV6" >/dev/null 2>&1; then + print_result "IPv6 internal connectivity" "PASS" "IPv6 connectivity to router working" + else + print_result "IPv6 internal connectivity" "FAIL" "IPv6 connectivity to router failed" + fi + + # Test IPv6 external connectivity (if available) + if ping6 -c 1 -W 5 "$EXTERNAL_IPV6" >/dev/null 2>&1; then + print_result "IPv6 external connectivity" "PASS" "IPv6 external connectivity working" + else + print_result "IPv6 external connectivity" "FAIL" "IPv6 external connectivity failed" + fi +} + +# Function to test NAT functionality +test_nat_functionality() { + echo -e "${BLUE}=== Testing NAT Functionality ===${NC}" + + # Get the external IP that the router sees + local external_ip=$(curl -s --connect-timeout 5 --max-time 10 https://ipinfo.io/ip 2>/dev/null || echo "unknown") + + if [ "$external_ip" != "unknown" ]; then + print_result "NAT functionality" "PASS" "External IP: $external_ip" + else + print_result "NAT functionality" "FAIL" "Could not determine external IP" + fi +} + +# Function to check firewall logs +check_firewall_logs() { + echo -e "${BLUE}=== Checking Firewall Logs ===${NC}" + + local log_entries=$(journalctl -u nftables --since "5 minutes ago" 2>/dev/null | wc -l) + + if [ $log_entries -gt 0 ]; then + print_result "Firewall logging" "PASS" "$log_entries log entries in last 5 minutes" + else + print_result "Firewall logging" "WARN" "No firewall log entries found (may be normal if no attacks)" + fi +} + +# Function to check connection tracking table +check_connection_tracking() { + echo -e "${BLUE}=== Checking Connection Tracking ===${NC}" + + if [ -f /proc/net/nf_conntrack ]; then + local conntrack_entries=$(cat /proc/net/nf_conntrack 2>/dev/null | wc -l) + print_result "Connection tracking table" "PASS" "$conntrack_entries active connections" + else + print_result "Connection tracking table" "FAIL" "Connection tracking not available" + fi +} + +# Function to display firewall rules summary +display_firewall_summary() { + echo -e "${BLUE}=== Firewall Rules Summary ===${NC}" + + echo "Input chain rules:" + nft list chain inet filter input 2>/dev/null | grep -E "(accept|drop)" | head -10 + + echo -e "\nForward chain rules:" + nft list chain inet filter forward 2>/dev/null | grep -E "(accept|drop)" | head -10 + + echo -e "\nOutput chain rules:" + nft list chain inet filter output 2>/dev/null | grep -E "(accept|drop)" | head -10 +} + +# Function to display test summary +display_summary() { + echo -e "${BLUE}=== Test Summary ===${NC}" + echo "Total tests: $TOTAL_TESTS" + echo -e "Passed: ${GREEN}$TESTS_PASSED${NC}" + echo -e "Failed: ${RED}$TESTS_FAILED${NC}" + + local success_rate=$(( (TESTS_PASSED * 100) / TOTAL_TESTS )) + echo "Success rate: $success_rate%" + + if [ $TESTS_FAILED -eq 0 ]; then + echo -e "${GREEN}All tests passed! Firewall configuration is secure.${NC}" + exit 0 + else + echo -e "${YELLOW}Some tests failed. Please review the firewall configuration.${NC}" + exit 1 + fi +} + +# Function to test output chain protection +test_output_chain_protection() { + echo -e "${BLUE}=== Testing Output Chain Protection ===${NC}" + + # Test that router can reach allocated subnets on internal interface + if ping -c 1 -W 2 -I br0 192.168.1.100 >/dev/null 2>&1; then + print_result "Output chain - allocated subnet access" "PASS" "Router can reach allocated subnet 192.168.1.0/24" + else + print_result "Output chain - allocated subnet access" "FAIL" "Router cannot reach allocated subnet 192.168.1.0/24" + fi + + # Test that router cannot reach other private networks through internal interface + if ping -c 1 -W 2 -I br0 10.0.0.1 >/dev/null 2>&1; then + print_result "Output chain - private network isolation" "FAIL" "Router can reach other private network 10.0.0.0/8" + else + print_result "Output chain - private network isolation" "PASS" "Router cannot reach other private network 10.0.0.0/8" + fi + + # Test that router cannot reach other private networks through internal interface (IPv6) + if command_exists ping6 && ping6 -c 1 -W 2 -I br0 fc00::1 >/dev/null 2>&1; then + print_result "Output chain - IPv6 private network isolation" "FAIL" "Router can reach other IPv6 private network fc00::/7" + else + print_result "Output chain - IPv6 private network isolation" "PASS" "Router cannot reach other IPv6 private network fc00::/7" + fi +} + +# Main execution +main() { + echo -e "${BLUE}Firewall Security Testing Script for L2 WiFi Access Point${NC}" + echo "================================================================" + echo + + # Check if running as root + check_root + + # Run all tests + check_nftables_status + test_basic_connectivity + test_ssh_rate_limiting + test_icmp_rate_limiting + test_anti_spoofing + test_connection_tracking + test_service_access + test_ipv6_functionality + test_nat_functionality + test_output_chain_protection + check_firewall_logs + check_connection_tracking + + echo + display_firewall_summary + echo + display_summary +} + +# Run main function +main "$@" \ No newline at end of file diff --git a/desktop/l2/firewall.md b/desktop/l2/firewall.md new file mode 100644 index 0000000..5e9b89a --- /dev/null +++ b/desktop/l2/firewall.md @@ -0,0 +1,374 @@ +# Firewall Design for L2 WiFi Access Point + +## 1. Overview + +This document outlines the design and principles of the `nftables` firewall configuration for the L2 WiFi access point. The primary goals are to provide robust security for the router and its clients, ensure correct network functionality, and maintain a clear, auditable ruleset with maximum performance. + +The firewall leverages `nftables` for its modern syntax, performance, and ability to handle both IPv4 and IPv6 within a unified `inet` table family where possible. The configuration is optimized for performance through extensive use of nftables sets and strategic rule ordering. + +### 1.1. Configuration Variables + +The firewall configuration is designed to be reusable across different machines by using configurable variables: + +* **Interface Names**: `wanInterface` and `lanInterface` can be customized for different NIC naming schemes +* **Network Prefixes**: `upstreamLanPrefix`, `internalIPv4Prefix`, and `internalIPv6Prefix` can be adjusted for different network topologies +* **Service Ports**: Defined as sets for easy modification and reuse + +This modular approach allows the same firewall rules to be deployed on machines with different interface names (e.g., `enp1s0`, `eth0`, `wlan0`) and network configurations. + +## 2. Core Design Principles + +The entire firewall is built upon the following security principles: + +* **Default-Deny Policy**: For traffic destined for the router (`input` chain) and traffic being routed through it (`forward` chain), the default policy is `drop`. Any traffic not explicitly permitted by a rule is silently discarded. +* **Stateful Packet Inspection**: The firewall uses the `nftables` connection tracking (`conntrack`) system. This allows it to understand the state of connections, automatically permitting return traffic for established sessions while blocking unsolicited incoming packets. +* **Defense in Depth & Rule Ordering**: Rules are ordered to drop malicious or invalid traffic as early as possible, improving both security and efficiency. The general order is: + 1. Drop invalid/malformed packets. + 2. Drop spoofed or explicitly denied traffic. + 3. Accept traffic for established connections (the "fast path"). + 4. Accept specific, legitimate new connections. +* **Principle of Least Privilege**: Services and clients are only granted the minimum access required for them to function correctly. +* **Rate Limiting**: Critical services are protected with rate limiting to prevent abuse and DoS attacks. +* **Comprehensive Logging**: All dropped packets are logged with rate limiting to prevent log flooding while maintaining audit trails. +* **Performance Optimization**: Extensive use of nftables sets and strategic rule ordering for maximum packet processing efficiency. + +## 3. Firewall Structure: Tables and Chains + +The ruleset is organized into three tables: + +* `table inet filter`: Contains all filtering rules for both IPv4 and IPv6. The `inet` family allows for a single set of rules to manage both protocols. +* `table ip nat`: Handles IPv4 Network Address Translation (NAT). +* `table ip6 nat`: Handles IPv6 Network Address Translation (NAT). + +### 3.1. Set-Based Architecture + +The firewall extensively uses nftables sets for optimal performance and maintainability: + +#### 3.1.1. Address Sets +* **`special_purpose_ipv4`**: Contains all RFC 6890 special-purpose IPv4 ranges (excluding 192.168.0.0/16 in which 192.168.1.0/24 is allocated to the br0 interface) +* **`special_purpose_ipv6`**: Contains all RFC 6890 special-purpose IPv6 ranges +* **`loopback_ipv4`**: IPv4 loopback addresses (127.0.0.0/8) +* **`loopback_ipv6`**: IPv6 loopback addresses (::1/128) +* **`blacklist`**: Dynamic blacklist for CrowdSec integration (timeout-based, auto-merge) + +#### 3.1.2. Service Port Sets +* **`ssh_ports`**: SSH service ports (22) +* **`dns_ports`**: DNS service ports (53) +* **`dhcp_ports`**: DHCP service ports (67, 547) + +#### 3.1.3. ICMP Type Sets +* **`icmp_allowed`**: Allowed ICMP types (echo-request, echo-reply, destination-unreachable, time-exceeded, parameter-problem) +* **`icmpv6_allowed`**: Allowed ICMPv6 types including Neighbor Discovery protocol types + +### 3.2. `input` Chain (Traffic to the Router) + +This chain protects the access point itself with optimized rule ordering: + +* **Early Invalid Packet Drops**: + * **Drops** invalid connection states immediately + * **Drops** fragmented packets (potential evasion technique) + * **Drops** packets with invalid TCP flag combinations +* **Fast Path for Established Connections**: + * **Accepts** established and related connections early for maximum performance +* **Loopback Protection**: + * **Accepts** all legitimate traffic on the loopback interface (`lo`) + * **Drops** any packet seen on a physical interface with loopback addresses using optimized set lookups +* **Global Anti-Spoofing**: + * **Drops** any incoming packet with a source address from special-purpose ranges using set-based filtering +* **Service Access Control**: + * **Allows** access to essential network services using set-based port matching + * **Rate limiting** is applied to SSH access to prevent brute force attacks +* **ICMP/ICMPv6 Handling**: + * **Allows** ICMP/ICMPv6 messages using consolidated set-based type matching + * **Rate limiting** is applied to echo requests to prevent ping floods +* **Logging and Default Drop**: + * Any packet that does not match an `accept` rule is logged with rate limiting and dropped + +### 3.3. `forward` Chain (Traffic Through the Router) + +This chain governs the traffic from WiFi clients to the internet and vice-versa with optimized performance: + +* **Early Invalid Packet Drops**: + * **Drops** invalid connection states and malformed packets immediately +* **Anti-Spoofing with Set-Based Filtering**: + * **Drops** any packet being forwarded that contains loopback addresses using set lookups + * **Drops** any packet from internal clients with spoofed upstream LAN addresses + * **Drops** any packet from internal clients destined for special-purpose ranges using set-based filtering +* **Fast Path for Return Traffic**: + * **Allows** return traffic from external to internal for established connections (most common case) +* **Connection Rate Limiting**: + * **Rate limits** new connections to prevent resource exhaustion +* **Client Forwarding**: + * **Allows** new connections from internal clients to external network with source address validation +* **ICMP Forwarding**: + * **Allows** essential ICMP/ICMPv6 messages using consolidated set-based type matching +* **Logging and Default Drop**: + * Any forwarded packet not matching an `accept` rule is logged and dropped + +### 3.4. `output` Chain (Traffic from the Router) + +This chain governs traffic generated by the access point itself with comprehensive egress filtering: + +* **Default-Accept Policy**: The policy is `accept`, but hardened with explicit `drop` rules +* **Early Invalid Packet Drops**: + * **Drops** invalid connection states, fragmented packets, and invalid TCP flags +* **Loopback Protection**: + * **Drops** any packet with loopback addresses on physical interfaces using set-based filtering +* **Global Egress Filtering**: + * **Drops** any packet destined for special-purpose ranges using set-based filtering +* **Interface-Specific Egress Filtering**: + * **Drops** internal subnet traffic from WAN interface to prevent network leakage + * **Allows** internal subnet traffic on internal interface for legitimate communication + +### 3.5. `nat` Tables (`ip` and `ip6`) + +These tables handle Network Address Translation for both IPv4 and IPv6: + +* **`postrouting` Chain**: Implements masquerading for traffic exiting the WAN interface +* **`masquerade` Rule**: Rewrites source addresses to the WAN interface address for both IPv4 and IPv6 + +### 3.6. Performance Optimization Techniques + +The firewall employs several advanced optimization techniques: + +#### 3.6.1. Set-Based Performance +* **Address Range Sets**: Special-purpose and loopback address ranges are defined as sets with `flags interval` for optimal prefix matching +* **Service Port Sets**: Common service ports are grouped into sets for efficient port matching +* **ICMP Type Sets**: ICMP and ICMPv6 types are consolidated into comprehensive sets for type matching +* **Dynamic Blacklist**: CrowdSec-managed blacklist set with timeout-based automatic cleanup + +#### 3.6.2. Rule Ordering Optimization +* **Early Drops**: Invalid packets and spoofed traffic are dropped as early as possible +* **Fast Path**: Established connections are accepted early to avoid expensive rule evaluation +* **Global Filters**: Non-interface-specific drops (like special-purpose IP blocking) are applied before interface-specific rules +* **Most Common Traffic First**: Return traffic and established connections are prioritized + +#### 3.6.3. Logical Consolidation +* **ICMP Type Consolidation**: Multiple ICMP types are grouped into comprehensive sets rather than individual rules +* **Service Port Consolidation**: Related service ports are grouped into sets for efficient matching +* **Address Range Consolidation**: Related address ranges are grouped into interval sets for optimal performance + +#### 3.6.4. Memory and CPU Optimization +* **Set Lookups**: Address and port matching uses optimized set lookups instead of individual rules +* **Reduced Rule Count**: Consolidation reduces the total number of rules, improving packet processing speed +* **Efficient Data Structures**: Interval sets use optimized data structures for prefix matching + +### 3.7. CrowdSec Integration + +The firewall integrates with CrowdSec for advanced threat detection and dynamic blocking: + +#### 3.7.1. CrowdSec Architecture +* **Threat Detection**: CrowdSec monitors system logs for suspicious behavior patterns +* **Community Intelligence**: Leverages global threat intelligence from the CrowdSec community +* **Real-time Blocking**: Automatically blocks malicious IPs using the nftables blacklist set +* **Performance**: Written in Go, providing 60x better performance than traditional solutions + +#### 3.7.2. Integration Components +* **CrowdSec Engine**: Monitors logs and detects threats using YAML-based scenarios +* **Firewall Bouncer**: Modern Go-based bouncer that manages the blacklist set in real-time +* **Dynamic Blacklist**: Timeout-based set that automatically removes expired blocks +* **Community Collections**: Pre-built detection rules for common services (SSH, web servers, etc.) + +#### 3.7.3. Benefits +* **Zero-Day Protection**: Community-driven threat detection catches new attack patterns +* **Reduced False Positives**: Machine learning and community curation improve accuracy +* **Automatic Updates**: Threat intelligence is continuously updated from the community +* **Scalable Architecture**: Decoupled detection and remediation for better performance +* **Resource Management**: Services run in the `network-services` slice with proper resource limits + +#### 3.7.4. Configuration Decisions + +The CrowdSec integration makes several deliberate architectural choices: + +**Flake Input Integration** +* **External Flake**: Uses `kampka/nix-flake-crowdsec` for official NixOS modules +* **Minimal Overrides**: Leverages flake defaults for most configuration +* **Selective Customization**: Only overrides necessary settings (API URLs, memory limits) +* **Maintainability**: Reduces configuration complexity and maintenance burden +* **Upstream Compatibility**: Benefits from upstream improvements and security updates + +**Default Configuration Strategy** +* **Flake Defaults**: Uses flake-provided default configurations for scenarios, parsers, and collections +* **Minimal Customization**: Only customizes API communication and resource management +* **Community Collections**: Leverages pre-built detection rules from the CrowdSec community +* **Automatic Updates**: Threat intelligence and detection rules updated via flake updates +* **Reduced Maintenance**: Less custom configuration means fewer potential issues + +**Log Monitoring Configuration** +* **SSH Monitoring**: Monitors `sshd.service` logs for brute force attacks and suspicious patterns +* **Login Monitoring**: Monitors `systemd-logind.service` for authentication failures and session anomalies +* **Journal Integration**: Uses systemd journal as data source for efficient log processing +* **Real-time Detection**: Processes logs in real-time for immediate threat response +* **Community Intelligence**: Combines local detection with global threat intelligence + +**API Communication Architecture** +* **Decoupled Design**: CrowdSec engine and firewall bouncer are separate services +* **Loopback Communication**: Services communicate via IPv6 loopback (`[::1]:8080`) +* **No API Keys**: Trusted IPs (`127.0.0.1`, `::1`) provide sufficient authentication for localhost +* **No Forwarded Headers**: Direct loopback communication eliminates need for proxy headers + +**Service Placement** +* **Network Services Slice**: Both services run in `network-services.slice` with other network components +* **High Priority**: Assigned `Nice = -5` for higher CPU priority than normal services +* **Resource Limits**: 4GB memory high, 8GB memory max (inherited from network-services slice) +* **File Descriptors**: Increased limit to 65,536 for high-traffic scenarios + +**IPv6-First Approach** +* **API Server**: Listens on IPv6 localhost (`[::1]:8080`) for better performance +* **Bouncer Connection**: Connects to IPv6 localhost for consistency +* **Future-Proof**: Ready for IPv6-only network environments +* **Performance**: IPv6 loopback has slightly lower overhead than IPv4 + +**Security Model** +* **Localhost-Only**: API server only accessible via loopback interface +* **No External Exposure**: Eliminates risk of external API access +* **Simplified Authentication**: Trusted IPs provide sufficient security for local communication +* **Reduced Attack Surface**: No API key management or complex authentication + +**Integration with nftables** +* **Dynamic Blacklist**: Uses timeout-based set with automatic cleanup +* **Early Drop**: Blacklisted IPs are dropped early in the input chain +* **Set-Based Performance**: Leverages nftables set lookups for optimal performance +* **Real-Time Updates**: Bouncer updates the blacklist set every 10 seconds + +**Memory Management Strategy** +* **Go Memory Limits**: GOMEMLIMIT set to 90% of systemd memory limits for proper garbage collection +* **CrowdSec Engine**: 512MB high water mark, 1GB hard limit (GOMEMLIMIT: 460MB) +* **Firewall Bouncer**: 256MB high water mark, 512MB hard limit (GOMEMLIMIT: 230MB) +* **Memory Estimation**: Engine needs more memory for log processing and threat detection +* **Bouncer Efficiency**: Bouncer is lightweight, only managing API polling and nftables updates +* **Preventive Limits**: Prevents memory leaks and ensures predictable resource usage + +## 4. Security Considerations + +### 4.1. Rate Limiting +- SSH access is rate-limited to 6 connections per minute to prevent brute force attacks +- ICMP echo requests are rate-limited to prevent ping floods (10/second internal, 5/second external) +- Logging is rate-limited to 5 entries per minute to prevent log flooding during attacks +- New connections are rate-limited to 500/second to prevent resource exhaustion + +### 4.2. Anti-Spoofing Measures +- Loopback address spoofing is blocked on all interfaces using set-based filtering +- Special-purpose IP ranges are blocked as source addresses using comprehensive set coverage +- Internal clients cannot spoof upstream LAN addresses +- Fragment and TCP flag filtering prevents evasion techniques + +### 4.3. Network Segmentation +- Clear separation between internal (br0) and external (enp1s0) interfaces +- Service access is restricted to internal interfaces only +- Upstream LAN access is explicitly controlled +- Egress filtering prevents internal network leakage + +### 4.4. IPv6 Security +- Comprehensive ICMPv6 filtering for proper IPv6 operation +- Neighbor Discovery Protocol protection +- Router Advertisement control +- Path MTU Discovery support + +## 5. Monitoring and Logging + +### 5.1. Log Analysis +Monitor firewall logs for: +- Repeated connection attempts (potential scanning) +- Spoofed packet attempts +- Rate limit violations +- Unusual traffic patterns + +### 5.2. Performance Monitoring +- Connection tracking table utilization +- Packet processing statistics +- Interface traffic patterns +- Set lookup performance + +### 5.3. Security Monitoring +- Failed authentication attempts +- Unusual source/destination patterns +- Protocol violations +- Anti-spoofing violations + +## 6. Summary of Protections + +| Protection Type | `input` Chain (Router) | `forward` Chain (Clients) | `output` Chain (Router) | +| ------------------------------- | :--------------------: | :-----------------------: | :---------------------: | +| **Default-Deny Policy** | ✓ | ✓ | ✗ | +| **Stateful Inspection** | ✓ | ✓ | ✓ | +| **Loopback Anti-Spoofing** | ✓ | ✓ | ✓ | +| **Special-Purpose IP Blocking** | ✓ | ✓ | ✓ | +| **Service Access Control** | ✓ | N/A | N/A | +| **Client Subnet Enforcement** | N/A | ✓ | N/A | +| **Rate-Limited Drop Logging** | ✓ | ✓ | N/A | +| **Rate Limiting Protection** | ✓ | N/A | N/A | +| **Set-Based Performance** | ✓ | ✓ | ✓ | +| **Optimized Rule Ordering** | ✓ | ✓ | ✓ | + +## 7. Verification + +The live, active ruleset can be inspected at any time using the following commands: + +```bash +# List all rules (most common) +sudo nft list ruleset + +# List specific table +sudo nft list table inet filter + +# List specific chain +sudo nft list chain inet filter input + +# Show rules with handles (useful for deleting specific rules) +sudo nft list ruleset -a + +# Monitor nftables events in real-time +sudo nft monitor + +# Show packet counters +sudo nft list ruleset -n + +# Show rules with statistics +sudo nft list ruleset -s +``` + +### 7.1. Testing Commands +```bash +# Test SSH rate limiting +for i in {1..10}; do ssh -o ConnectTimeout=1 user@192.168.1.1; done + +# Test ICMP filtering +ping -c 1 192.168.1.1 # Should work from br0 +ping -c 1 8.8.8.8 # Should be blocked from external + +# Test connection tracking +curl -I https://example.com # Should work +# Return traffic should be automatically allowed + +# Monitor firewall logs +journalctl -f -u nftables +``` + +### 7.2. Security Testing +```bash +# Test anti-spoofing +ping -I 127.0.0.1 8.8.8.8 # Should be blocked + +# Test special-purpose IP blocking +ping -I 192.168.1.100 10.0.0.1 # Should be blocked + +# Test IPv6 functionality +ping6 -c 1 fd00::1 # Should work from internal + +# Test set-based filtering performance +time ping -c 1000 192.168.1.1 # Measure performance impact +``` + +### 7.3. Performance Testing +```bash +# Test set lookup performance +sudo nft list set inet filter special_purpose_ipv4 +sudo nft list set inet filter icmp_allowed + +# Monitor packet processing statistics +sudo nft list ruleset -s + +# Test connection tracking performance +ss -s # Show connection statistics +``` \ No newline at end of file diff --git a/desktop/l2/firewall.nix b/desktop/l2/firewall.nix index 479db85..c901832 100644 --- a/desktop/l2/firewall.nix +++ b/desktop/l2/firewall.nix @@ -38,7 +38,15 @@ { config, pkgs, ... }: -{ +let + # Interface configuration - customize these for your machine + wanInterface = "enp1s0"; # External/WAN interface + lanInterface = "br0"; # Internal/LAN bridge interface + upstreamLanPrefix = "172.16.0.0/16"; # Upstream LAN prefix for management access + internalIPv4Prefix = "192.168.1.0/24"; # Internal IPv4 subnet + internalIPv6Prefix = "fd00::/64"; # Internal IPv6 subnet + +in { # Disable the default iptables firewall since we're using nftables networking.firewall.enable = false; @@ -47,49 +55,286 @@ enable = true; ruleset = '' table inet filter { + # Define sets for special-purpose address ranges (RFC 6890) + # These improve performance and readability + set special_purpose_ipv4 { + type ipv4_addr + flags interval + elements = { + 0.0.0.0/8, # "This" Network + 10.0.0.0/8, # Private-Use + 100.64.0.0/10, # Shared Address Space + 169.254.0.0/16, # Link Local + 192.0.0.0/24, # IETF Protocol Assignments + 192.0.2.0/24, # TEST-NET-1 + 192.88.99.0/24, # IPv6 to IPv4 Relay + # 192.168.0.0/16, # Private-Use (EXCLUDED - allocated to 192.168.1.0/24) + 198.18.0.0/15, # Device Benchmark + 198.51.100.0/24, # TEST-NET-2 + 203.0.113.0/24, # TEST-NET-3 + 224.0.0.0/3 # Multicast + } + } + + set special_purpose_ipv6 { + type ipv6_addr + flags interval + elements = { + ::/128, # Unspecified Address + ::ffff:0:0/96, # IPv4-mapped Address + 64:ff9b::/96, # IPv4-IPv6 Translation + 100::/64, # Discard-Only Address Block + 2001::/32, # TEREDO + 2001:2::/48, # Benchmarking + 2001:db8::/32, # Documentation + 2002::/16, # 6to4 + fc00::/7, # Unique Local + fe80::/10, # Link-Local + ff00::/8 # Multicast + } + } + + # Define sets for loopback addresses + set loopback_ipv4 { + type ipv4_addr + flags interval + elements = { + 127.0.0.0/8 # IPv4 Loopback + } + } + + set loopback_ipv6 { + type ipv6_addr + flags interval + elements = { + ::1/128 # IPv6 Loopback + } + } + + # Define sets for common service ports + set ssh_ports { + type inet_service + elements = { + 22 # SSH + } + } + + set dns_ports { + type inet_service + elements = { + 53 # DNS (TCP and UDP) + } + } + + set dhcp_ports { + type inet_service + elements = { + 67, # DHCPv4 Server + 547 # DHCPv6 Server + } + } + + # Define sets for ICMP types + set icmp_allowed { + type icmp_type + elements = { + echo-request, # Ping request + echo-reply, # Ping reply + destination-unreachable, # Host/network unreachable + time-exceeded, # TTL exceeded + parameter-problem # Parameter problem + } + } + + # Define sets for ICMPv6 types + set icmpv6_allowed { + type icmpv6_type + elements = { + echo-request, # Ping request + echo-reply, # Ping reply + destination-unreachable, # Host/network unreachable + time-exceeded, # TTL exceeded + parameter-problem, # Parameter problem + packet-too-big, # Path MTU Discovery + nd-router-solicit, # Router solicitation + nd-router-advert, # Router advertisement + nd-neighbor-solicit, # Neighbor solicitation + nd-neighbor-advert # Neighbor advertisement + } + } + + # CrowdSec blacklist set for dynamic threat blocking + set blacklist { + type ipv4_addr + flags timeout + } + + # CrowdSec IPv6 blacklist set + set blacklist6 { + type ipv6_addr + flags timeout + } + chain input { type filter hook input priority 0; policy drop; - # Enable connection tracking - ct state established,related accept + # Early drop for invalid packets ct state invalid drop - # Allow loopback + # Drop fragmented packets (potential evasion technique) + ip frag-off & 0x1fff != 0 drop + + # Drop packets with invalid TCP flag combinations + tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|syn|rst|psh|ack|urg) drop + tcp flags & (fin|syn) == (fin|syn) drop + tcp flags & (syn|rst) == (syn|rst) drop + + # Drop traffic from blacklisted IPs (CrowdSec integration) + ip saddr @blacklist drop + ip6 saddr @blacklist6 drop + + # Allow established and related connections + ct state established,related accept + + # Accept all traffic on the loopback interface, and drop spoofed + # loopback packets on any other interface. iif lo accept - oif lo accept + iif != "lo" ip saddr @loopback_ipv4 drop + iif != "lo" ip daddr @loopback_ipv4 drop + iif != "lo" ip6 saddr @loopback_ipv6 drop + iif != "lo" ip6 daddr @loopback_ipv6 drop + + # Drop incoming traffic from special-purpose/unroutable source addresses (RFC 6890) + # This provides strong anti-spoofing protection for the router itself. + ip saddr @special_purpose_ipv4 drop + ip6 saddr @special_purpose_ipv6 drop - # Allow SSH from anywhere - tcp dport 22 accept + # Allow management and network services from the internal interface (${lanInterface}) + # Rate limit SSH to prevent brute force attacks + iifname "${lanInterface}" tcp dport @ssh_ports ct state new limit rate 6/minute accept + iifname "${lanInterface}" tcp dport @ssh_ports ct state established,related accept - # Allow DNS queries - udp dport 53 accept - tcp dport 53 accept + # DNS and DHCP services + iifname "${lanInterface}" udp dport @dns_ports accept + iifname "${lanInterface}" tcp dport @dns_ports accept + iifname "${lanInterface}" udp dport @dhcp_ports accept - # Allow DHCP - udp dport 67 accept - udp dport 547 accept + # Allow all traffic from the trusted upstream LAN (${upstreamLanPrefix}) on the WAN port. + # This allows management of the router from the upstream LAN. + iifname "${wanInterface}" ip saddr ${upstreamLanPrefix} accept + # TODO: Add a similar rule to allow traffic from the upstream IPv6 LAN once its prefix is known. - # Allow ICMP (ping, etc.) - icmp type echo-request accept - icmpv6 type echo-request accept + # Allow essential ICMP/ICMPv6 traffic on internal and external interfaces + # Rate limit ICMP echo requests to prevent ping floods + iifname "${lanInterface}" icmp type echo-request limit rate 10/second accept + iifname "${lanInterface}" icmp type @icmp_allowed accept + iifname "${lanInterface}" icmpv6 type echo-request limit rate 10/second accept + iifname "${lanInterface}" icmpv6 type @icmpv6_allowed accept - # Allow RA (Router Advertisement) - icmpv6 type nd-router-advert accept + # External interface ICMP/ICMPv6 (rate limited) + iifname "${wanInterface}" icmp type echo-request limit rate 5/second accept + iifname "${wanInterface}" icmp type @icmp_allowed accept + iifname "${wanInterface}" icmpv6 type echo-request limit rate 5/second accept + iifname "${wanInterface}" icmpv6 type @icmpv6_allowed accept + + # Log and drop everything else + log prefix "[nft-input-drop] " limit rate 5/minute drop } chain forward { type filter hook forward priority 0; policy drop; - # Allow traffic from internal network to external - # Use meta iifname to avoid interface existence check at load time - meta iifname "br0" oifname "enp1s0" accept + # Early drop for invalid packets being forwarded + ct state invalid drop + + # Drop fragmented packets being forwarded + ip frag-off & 0x1fff != 0 drop + + # Drop packets with invalid TCP flag combinations + tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|syn|rst|psh|ack|urg) drop + tcp flags & (fin|syn) == (fin|syn) drop + tcp flags & (syn|rst) == (syn|rst) drop + + # Add explicit anti-spoofing drops for known-bad traffic. + # Drop any spoofed loopback traffic trying to be forwarded. + ip saddr @loopback_ipv4 drop + ip daddr @loopback_ipv4 drop + ip6 saddr @loopback_ipv6 drop + ip6 daddr @loopback_ipv6 drop + + # Drop traffic from internal clients pretending to be on the upstream LAN. + iifname "${lanInterface}" ip saddr ${upstreamLanPrefix} drop + + # Drop traffic from internal clients to private/reserved ranges. + # This prevents traffic from being forwarded to non-routable destinations. + # Based on IANA Special-Purpose Address Registry (RFC 6890) + iifname "${lanInterface}" oifname "${wanInterface}" ip daddr @special_purpose_ipv4 drop + iifname "${lanInterface}" oifname "${wanInterface}" ip6 daddr @special_purpose_ipv6 drop + + # Allow return traffic from external to internal (most common case, check first) + iifname "${wanInterface}" oifname "${lanInterface}" ct state established,related accept + + # Rate limit new connections to prevent resource exhaustion + ct state new limit rate 500/second accept - # Allow return traffic from external to internal - meta iifname "enp1s0" oifname "br0" ct state established,related accept + # Allow traffic from internal clients (known subnets) to external network + iifname "${lanInterface}" oifname "${wanInterface}" ip saddr ${internalIPv4Prefix} accept + iifname "${lanInterface}" oifname "${wanInterface}" ip6 saddr ${internalIPv6Prefix} accept + + # Allow essential ICMP/ICMPv6 forwarding for proper network operation + # ICMP for Path MTU Discovery and error reporting + iifname "${wanInterface}" oifname "${lanInterface}" icmp type @icmp_allowed accept + iifname "${lanInterface}" oifname "${wanInterface}" icmp type @icmp_allowed accept + + # ICMPv6 for IPv6 operation (including Path MTU Discovery) + iifname "${wanInterface}" oifname "${lanInterface}" icmpv6 type @icmpv6_allowed accept + iifname "${lanInterface}" oifname "${wanInterface}" icmpv6 type @icmpv6_allowed accept + + # Log and drop everything else + log prefix "[nft-forward-drop] " limit rate 5/minute drop } chain output { type filter hook output priority 0; policy accept; + + # Drop invalid packets originating from the local machine + ct state invalid drop + + # Drop fragmented packets from router + ip frag-off & 0x1fff != 0 drop + + # Drop packets with invalid TCP flag combinations + tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|syn|rst|psh|ack|urg) drop + tcp flags & (fin|syn) == (fin|syn) drop + tcp flags & (syn|rst) == (syn|rst) drop + + # Drop spoofed loopback packets on non-loopback interfaces. + # Legitimate traffic to/from loopback addresses should only be on the 'lo' interface. + oif != "lo" ip saddr @loopback_ipv4 drop + oif != "lo" ip daddr @loopback_ipv4 drop + oif != "lo" ip6 saddr @loopback_ipv6 drop + oif != "lo" ip6 daddr @loopback_ipv6 drop + + # Allow essential ICMPv6 traffic from router (Router Advertisement, Neighbor Advertisement, etc.) + oifname "${lanInterface}" icmpv6 type @icmpv6_allowed accept + oifname "${wanInterface}" icmpv6 type @icmpv6_allowed accept + + # Block sending traffic to private/reserved ranges (regardless of interface) + # with exceptions for allocated subnets to prevent IP leakage and network access + # Based on IANA Special-Purpose Address Registry (RFC 6890) + # Exclude our allocated subnets from the blocking + ip daddr != ${internalIPv4Prefix} ip daddr @special_purpose_ipv4 drop + ip6 daddr != ${internalIPv6Prefix} ip6 daddr @special_purpose_ipv6 drop + + # Block allocated subnets from going out the WAN interface (${wanInterface}) + # to prevent internal network leakage + oifname "${wanInterface}" ip daddr ${internalIPv4Prefix} drop + oifname "${wanInterface}" ip6 daddr ${internalIPv6Prefix} drop + + # Allow allocated subnets to go out the internal interface (${lanInterface}) + # for legitimate internal network communication + oifname "${lanInterface}" ip daddr ${internalIPv4Prefix} accept + oifname "${lanInterface}" ip6 daddr ${internalIPv6Prefix} accept } } @@ -101,7 +346,7 @@ chain postrouting { type nat hook postrouting priority srcnat; # IPv4 masquerading - meta oifname "enp1s0" masquerade + oifname "${wanInterface}" masquerade } } @@ -113,7 +358,7 @@ chain postrouting { type nat hook postrouting priority srcnat; # IPv6 masquerading - meta oifname "enp1s0" masquerade + oifname "${wanInterface}" masquerade } } ''; diff --git a/desktop/l2/flake.lock b/desktop/l2/flake.lock index cb18004..c20c691 100644 --- a/desktop/l2/flake.lock +++ b/desktop/l2/flake.lock @@ -1,5 +1,63 @@ { "nodes": { + "crowdsec": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1742920128, + "narHash": "sha256-VPjnjtAksihLezhc+ZmnqGu18mHr4QVKa1kSZQ8rJL4=", + "ref": "refs/heads/main", + "rev": "40e937689d318ee85b1d9763189a65e6f0b4028d", + "revCount": 40, + "type": "git", + "url": "https://codeberg.org/kampka/nix-flake-crowdsec.git" + }, + "original": { + "type": "git", + "url": "https://codeberg.org/kampka/nix-flake-crowdsec.git" + } + }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1750903843, + "narHash": "sha256-Ng9+f0H5/dW+mq/XOKvB9uwvGbsuiiO6HrPdAcVglCs=", + "owner": "nix-community", + "repo": "disko", + "rev": "83c4da299c1d7d300f8c6fd3a72ac46cb0d59aae", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "id": "flake-utils", + "type": "indirect" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -7,11 +65,11 @@ ] }, "locked": { - "lastModified": 1750798083, - "narHash": "sha256-DTCCcp6WCFaYXWKFRA6fiI2zlvOLCf5Vwx8+/0R8Wc4=", + "lastModified": 1751146119, + "narHash": "sha256-gvjG95TCnUVJkvQvLMlnC4NqiqFyBdJk3o8/RwuHeaU=", "owner": "nix-community", "repo": "home-manager", - "rev": "ff31a4677c1a8ae506aa7e003a3dba08cb203f82", + "rev": "76d0c31fce2aa0c71409de953e2f9113acd5b656", "type": "github" }, "original": { @@ -22,11 +80,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1750741721, - "narHash": "sha256-Z0djmTa1YmnGMfE9jEe05oO4zggjDmxOGKwt844bUhE=", + "lastModified": 1751011381, + "narHash": "sha256-krGXKxvkBhnrSC/kGBmg5MyupUUT5R6IBCLEzx9jhMM=", "owner": "nixos", "repo": "nixpkgs", - "rev": "4b1164c3215f018c4442463a27689d973cffd750", + "rev": "30e2e2857ba47844aa71991daa6ed1fc678bcbb7", "type": "github" }, "original": { @@ -38,9 +96,26 @@ }, "root": { "inputs": { + "crowdsec": "crowdsec", + "disko": "disko", "home-manager": "home-manager", "nixpkgs": "nixpkgs" } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/desktop/l2/flake.nix b/desktop/l2/flake.nix index 2d609cc..ece7294 100644 --- a/desktop/l2/flake.nix +++ b/desktop/l2/flake.nix @@ -13,9 +13,19 @@ url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; + + # https://github.com/nix-community/disko/ + disko.url = "github:nix-community/disko"; + disko.inputs.nixpkgs.follows = "nixpkgs"; + + # CrowdSec NixOS services + crowdsec = { + url = "git+https://codeberg.org/kampka/nix-flake-crowdsec.git"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; - outputs = { self, nixpkgs, home-manager, ... }: + outputs = { self, nixpkgs, disko, home-manager, crowdsec, ... }: let system = "x86_64-linux"; @@ -53,6 +63,9 @@ inherit system; modules = [ + disko.nixosModules.disko + crowdsec.nixosModules.crowdsec + crowdsec.nixosModules.crowdsec-firewall-bouncer ./configuration.nix { nixpkgs.pkgs = pkgs; diff --git a/desktop/l2/hardware-configuration.nix b/desktop/l2/hardware-configuration.nix index e1b1083..da20248 100644 --- a/desktop/l2/hardware-configuration.nix +++ b/desktop/l2/hardware-configuration.nix @@ -1,4 +1,4 @@ -# Do not modify this file! It was generated by 'nixos-generate-config' +# Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. { config, lib, pkgs, modulesPath, ... }: @@ -9,33 +9,17 @@ ]; boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" ]; - boot.initrd.kernelModules = [ ]; + boot.initrd.kernelModules = [ "dm-snapshot" ]; boot.kernelModules = [ "kvm-amd" ]; boot.extraModulePackages = [ ]; - fileSystems."/" = - { device = "/dev/disk/by-uuid/f72013eb-dba3-48d6-80cd-65a1684ba502"; - fsType = "ext4"; - }; - - boot.initrd.luks.devices."luks-6fd137fa-aa82-4200-9ca1-cd049de90418".device = "/dev/disk/by-uuid/6fd137fa-aa82-4200-9ca1-cd049de90418"; - - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/4C7A-4843"; - fsType = "vfat"; - options = [ "fmask=0077" "dmask=0077" ]; - }; - - swapDevices = - [ { device = "/dev/disk/by-uuid/979a4a5a-8724-4c06-8173-13e72cb49a9d"; } - ]; - # Enables DHCP on each ethernet and wireless interface. In case of scripted networking # (the default) this is the recommended approach. When using systemd-networkd it's # still possible to use this option, but it's recommended to use it in conjunction # with explicit per-interface declarations with `networking.interfaces..useDHCP`. - # networking.useDHCP = lib.mkDefault true; + networking.useDHCP = lib.mkDefault true; # networking.interfaces.enp1s0.useDHCP = lib.mkDefault true; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; } diff --git a/desktop/l2/home.nix b/desktop/l2/home.nix index f36f1bf..cf35200 100644 --- a/desktop/l2/home.nix +++ b/desktop/l2/home.nix @@ -16,14 +16,7 @@ # https://nix-community.github.io/home-manager/options.xhtml#opt-home.sessionVariables home.sessionVariables = { - #NIXPKGS_ALLOW_UNFREE = "1"; - ELECTRON_OZONE_PLATFORM_HINT = "auto"; - - QT_QPA_PLATFORM = "wayland"; - # GI_TYPELIB_PATH = "/run/current-system/sw/lib/girepository-1.0"; - # disable wayland - # NIXOS_OZONE_WL = "1"; - GOPRIVATE = "gitlab.com/sidenio/*"; + TERM = "xterm-256color"; #HTTP_PROXY = "http://hp4.home:3128"; @@ -44,67 +37,53 @@ neofetch file - # # Hyprland related - # waybar - # swaybg - # swaylock - # wl-clipboard - # wf-recorder - # grimblast - # hyprpaper - # hyprpicker - # hypridle - # hyprlock - # Terminal Multiplexers tmux screen - # LLVM/Clang toolchain (needed for race detection and C/C++ builds) - llvmPackages_20.clang-tools - llvmPackages_20.lld - - # Essential development libraries (minimal headers) - glibc.dev - stdenv.cc.cc.lib - zlib.dev - openssl.dev - ncurses.dev - libyaml.dev - - # Build Tools - libgcc - # https://nixos.wiki/wiki/C - # https://search.nixos.org/packages?channel=24.05&show=gcc&from=0&size=50&sort=relevance&type=packages&query=gcc - #gcc - automake - gnumake - #cmake - pkg-config - - # Scripting/Utils - perl - #3.12.8 on 12th of Feb 2025 - python3Full - gawk - jq + # # Essential development libraries (minimal headers) + # glibc.dev + # stdenv.cc.cc.lib + # zlib.dev + # openssl.dev + # ncurses.dev + # libyaml.dev + + # # Build Tools + # libgcc + # # https://nixos.wiki/wiki/C + # # https://search.nixos.org/packages?channel=24.05&show=gcc&from=0&size=50&sort=relevance&type=packages&query=gcc + # #gcc + # automake + # gnumake + gnumake42 + # #cmake + # pkg-config + + # # Scripting/Utils + # perl + # #3.12.8 on 12th of Feb 2025 + # python3Full + # gawk + # jq + git htop btop minicom - bc + # bc - # Compression - bzip2 - gzip - lz4 - zip - unzip + # # Compression + # bzip2 + # gzip + # lz4 + # zip + # unzip #xz #zstd - gnutar + #gnutar # File Transfer/Management rsync @@ -170,5 +149,6 @@ nixpkgs.config.allowUnfree = true; - home.stateVersion = "24.11"; + #home.stateVersion = "24.11"; + home.stateVersion = "25.05"; } diff --git a/desktop/l2/hostapd-multi.nix b/desktop/l2/hostapd-multi.nix index 7eea848..1fbcc09 100644 --- a/desktop/l2/hostapd-multi.nix +++ b/desktop/l2/hostapd-multi.nix @@ -168,6 +168,15 @@ in { ''; }; + # Add necessary capabilities to RADVD for ICMPv6 Router Advertisement + systemd.services.radvd = { + serviceConfig = { + # Add CAP_NET_RAW capability to allow sending ICMPv6 messages + CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" "CAP_NET_BROADCAST" "CAP_NET_RAW" ]; + AmbientCapabilities = [ "CAP_NET_RAW" ]; + }; + }; + # https://nixos.wiki/wiki/Systemd-networkd networking.useNetworkd = true; networking.useDHCP = false; @@ -204,6 +213,8 @@ systemd.network.networks."dummy0" = { matchConfig.Name = "enp1s0"; networkConfig = { DHCP = "ipv4"; + IPv4Forwarding = true; + IPv6Forwarding = true; IPv6AcceptRA = true; IPv6PrivacyExtensions = true; # IPMasquerade handled by nftables for better control @@ -219,6 +230,8 @@ systemd.network.networks."dummy0" = { "192.168.1.1/24" "fd00::1/64" ]; + IPv4Forwarding = true; + IPv6Forwarding = true; ConfigureWithoutCarrier = true; }; linkConfig = { @@ -247,7 +260,7 @@ systemd.network.networks."dummy0" = { networking.nameservers = [ "127.0.0.1" "::1" ]; environment.etc."resolv.conf".text = '' - # dnsmasq + # pdns nameserver 127.0.0.1 nameserver ::1 # emergency cloudflare diff --git a/desktop/l2/monitoring.nix b/desktop/l2/monitoring.nix deleted file mode 100644 index 5801a10..0000000 --- a/desktop/l2/monitoring.nix +++ /dev/null @@ -1,373 +0,0 @@ -# Monitoring Configuration for L2 WiFi Access Point -# Performance monitoring and logging for CPU/IRQ optimizations - -{ config, lib, pkgs, ... }: - -let - # Monitoring script for IRQ and CPU performance - monitoringScript = pkgs.writeShellScript "network-monitoring" '' - #!/bin/bash - set -euo pipefail - - LOG_DIR="/var/log/network-performance" - mkdir -p "$LOG_DIR" - - # Function to log with timestamp - log() { - echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_DIR/performance.log" - } - - # Function to monitor IRQ distribution - monitor_irqs() { - log "=== IRQ Distribution ===" - cat /proc/interrupts | grep -E "(enp1s0|iwlwifi)" | while read line; do - log "IRQ: $line" - done - } - - # Function to monitor CPU utilization - monitor_cpu() { - log "=== CPU Utilization ===" - mpstat -P ALL 1 1 | grep -E "(CPU|Average)" | while read line; do - log "CPU: $line" - done - } - - # Function to monitor network statistics - monitor_network() { - log "=== Network Statistics ===" - for interface in enp1s0 wlp35s0 wlp65s0 wlp66s0 wlp97s0; do - if [[ -e "/sys/class/net/$interface/statistics/rx_packets" ]]; then - rx_packets=$(cat "/sys/class/net/$interface/statistics/rx_packets") - tx_packets=$(cat "/sys/class/net/$interface/statistics/tx_packets") - rx_bytes=$(cat "/sys/class/net/$interface/statistics/rx_bytes") - tx_bytes=$(cat "/sys/class/net/$interface/statistics/tx_bytes") - log "Interface $interface: RX=$rx_packets pkts ($rx_bytes bytes), TX=$tx_packets pkts ($tx_bytes bytes)" - fi - done - } - - # Function to monitor memory usage - monitor_memory() { - log "=== Memory Usage ===" - free -h | while read line; do - log "Memory: $line" - done - } - - # Function to monitor cache performance - monitor_cache() { - log "=== Cache Performance ===" - if command -v perf >/dev/null 2>&1; then - # Monitor cache misses for network processes - for pid in $(pgrep -f "hostapd|nftables"); do - if [[ -n "$pid" ]]; then - cache_stats=$(perf stat -e cache-misses,cache-references -p "$pid" sleep 1 2>&1 | grep -E "(cache-misses|cache-references)" || true) - log "PID $pid cache stats: $cache_stats" - fi - done - fi - } - - # Function to monitor system load - monitor_load() { - log "=== System Load ===" - uptime | while read line; do - log "Load: $line" - done - } - - # Function to monitor network optimization status - monitor_optimization() { - log "=== Network Optimization Status ===" - - # Check IRQ affinity - log "IRQ Affinity Check:" - for irq in 168 169 170 171 172 173 174 175; do - if [[ -e "/proc/irq/$irq/smp_affinity_list" ]]; then - affinity=$(cat "/proc/irq/$irq/smp_affinity_list") - log " IRQ $irq -> CPU $affinity" - fi - done - - # Check CPU frequency - log "CPU Frequency Check:" - for cpu in {0..7}; do - if [[ -e "/sys/devices/system/cpu/cpu$cpu/cpufreq/scaling_cur_freq" ]]; then - freq=$(cat "/sys/devices/system/cpu/cpu$cpu/cpufreq/scaling_cur_freq") - governor=$(cat "/sys/devices/system/cpu/cpu$cpu/cpufreq/scaling_governor") - log " CPU $cpu: \$freq kHz (\$governor)" - fi - done - - # Check network optimization log - if [[ -e "/tmp/network-optimization.log" ]]; then - log "Network optimization log (last 10 lines):" - tail -10 "/tmp/network-optimization.log" | while read line; do - log " $line" - done - fi - } - - # Main monitoring function - main() { - log "Starting network performance monitoring" - - monitor_irqs - monitor_cpu - monitor_network - monitor_memory - monitor_cache - monitor_load - monitor_optimization - - log "Monitoring complete" - } - - # Run monitoring - main "$@" - ''; - - # Performance testing script - performanceTestScript = pkgs.writeShellScript "performance-test" '' - #!/bin/bash - set -euo pipefail - - LOG_DIR="/var/log/network-performance" - mkdir -p "$LOG_DIR" - - log() { - echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_DIR/performance-test.log" - } - - # Function to test network throughput - test_throughput() { - log "=== Network Throughput Test ===" - - # Start iperf3 server if not running - if ! pgrep -f "iperf3 -s" >/dev/null; then - log "Starting iperf3 server" - iperf3 -s -D - sleep 2 - fi - - # Test localhost throughput - log "Testing localhost throughput..." - iperf3 -c localhost -t 10 -J | jq -r '.end.sum_received.bits_per_second' | while read throughput; do - log "Localhost throughput: $throughput bps" - done - } - - # Function to test latency - test_latency() { - log "=== Latency Test ===" - - # Test ping to localhost - log "Testing ping latency to localhost..." - ping -c 10 localhost | grep -E "(min|avg|max)" | while read line; do - log "Ping: $line" - done - } - - # Function to test IRQ distribution - test_irq_distribution() { - log "=== IRQ Distribution Test ===" - - # Generate some network traffic - log "Generating network traffic for IRQ testing..." - - # Start background ping - ping -i 0.1 localhost >/dev/null 2>&1 & - ping_pid=$! - - # Wait and check IRQ distribution - sleep 5 - - log "IRQ distribution during traffic:" - cat /proc/interrupts | grep -E "(enp1s0|iwlwifi)" | head -10 | while read line; do - log " $line" - done - - # Stop ping - kill $ping_pid 2>/dev/null || true - } - - # Function to test CPU utilization - test_cpu_utilization() { - log "=== CPU Utilization Test ===" - - # Monitor CPU usage during network activity - log "Monitoring CPU usage for 10 seconds..." - mpstat -P ALL 1 10 | grep -E "(CPU|Average)" | while read line; do - log "CPU: $line" - done - } - - # Main test function - main() { - log "Starting performance tests" - - test_throughput - test_latency - test_irq_distribution - test_cpu_utilization - - log "Performance tests complete" - } - - main "$@" - ''; - -in { - # Monitoring service - systemd.services.network-monitoring = { - description = "Network performance monitoring"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" "irq-affinity.service" ]; - - serviceConfig = { - Type = "oneshot"; - ExecStart = "${monitoringScript}"; - StandardOutput = "journal"; - StandardError = "journal"; - Environment = "PATH=${lib.makeBinPath [ pkgs.coreutils pkgs.procps pkgs.sysstat pkgs.perf-tools pkgs.jq pkgs.gawk pkgs.gnugrep pkgs.gnused ]}"; - }; - }; - - # Periodic monitoring timer - systemd.timers.network-monitoring = { - description = "Periodic network performance monitoring"; - wantedBy = [ "timers.target" ]; - timerConfig = { - OnBootSec = "5min"; - OnUnitActiveSec = "15min"; - Persistent = true; - }; - }; - - # Performance testing service - systemd.services.performance-test = { - description = "Network performance testing"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" "irq-affinity.service" ]; - - serviceConfig = { - Type = "oneshot"; - ExecStart = "${performanceTestScript}"; - StandardOutput = "journal"; - StandardError = "journal"; - Environment = "PATH=${lib.makeBinPath [ pkgs.coreutils pkgs.procps pkgs.iperf3 pkgs.jq pkgs.gawk pkgs.gnugrep pkgs.gnused pkgs.iputils pkgs.sysstat ]}"; - }; - }; - - # Periodic performance testing timer - systemd.timers.performance-test = { - description = "Periodic network performance testing"; - wantedBy = [ "timers.target" ]; - timerConfig = { - OnBootSec = "10min"; - OnUnitActiveSec = "1h"; - Persistent = true; - }; - }; - - # Real-time monitoring service - systemd.services.realtime-monitoring = { - description = "Real-time network performance monitoring"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" "irq-affinity.service" ]; - - serviceConfig = { - Type = "simple"; - ExecStart = pkgs.writeShellScript "realtime-monitoring" '' - #!/bin/bash - set -euo pipefail - - LOG_DIR="/var/log/network-performance" - mkdir -p "$LOG_DIR" - - log() { - echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_DIR/realtime.log" - } - - # Monitor IRQ distribution every 30 seconds - while true; do - log "=== IRQ Distribution ===" - cat /proc/interrupts | grep -E "(enp1s0|iwlwifi)" | while read line; do - log "$line" - done - - log "=== CPU Utilization ===" - mpstat -P ALL 1 1 | grep -E "(CPU|Average)" | while read line; do - log "$line" - done - - sleep 30 - done - ''; - Restart = "always"; - RestartSec = "10"; - Environment = "PATH=${lib.makeBinPath [ pkgs.coreutils pkgs.sysstat pkgs.gnugrep ]}"; - }; - }; - - # Log rotation for monitoring logs - services.logrotate.settings."network-performance" = { - files = "/var/log/network-performance/*.log"; - rotate = 7; - daily = true; - compress = true; - missingok = true; - notifempty = true; - postrotate = "systemctl reload rsyslog"; - }; - - # Additional monitoring tools - environment.systemPackages = with pkgs; [ - # Performance monitoring tools - htop - iotop - iftop - nethogs - nload - nmon - sysstat - perf-tools - bpftrace - - # Network testing tools - iperf3 - netperf - wrk - - # System analysis tools - strace - ltrace - valgrind - gdb - - # JSON processing for logs - jq - - # Additional monitoring - glances - s-tui - stress-ng - ]; - - # Enable sysstat for historical monitoring - services.sysstat = { - enable = true; - }; - - # Configure rsyslog for monitoring - services.rsyslogd = { - enable = true; - extraConfig = '' - # Network performance monitoring - if $programname == 'network-monitoring' then /var/log/network-performance/monitoring.log - if $programname == 'performance-test' then /var/log/network-performance/test.log - if $programname == 'realtime-monitoring' then /var/log/network-performance/realtime.log - ''; - }; -} \ No newline at end of file diff --git a/desktop/l2/network-optimization.nix b/desktop/l2/network-optimization.nix index 2a9088d..c7634b6 100644 --- a/desktop/l2/network-optimization.nix +++ b/desktop/l2/network-optimization.nix @@ -32,10 +32,12 @@ let ${pkgs.ethtool}/bin/ethtool -G enp1s0 rx 8184 tx 8184 # Feature optimizations - ${pkgs.ethtool}/bin/ethtool -K enp1s0 lro on + # lro seems to cause issues on the Atlantic + #${pkgs.ethtool}/bin/ethtool -K enp1s0 lro on ${pkgs.ethtool}/bin/ethtool -K enp1s0 tx-checksum-ipv4 on ${pkgs.ethtool}/bin/ethtool -K enp1s0 tx-tcp-ecn-segmentation on - ${pkgs.ethtool}/bin/ethtool -K enp1s0 rx-gro-list on + # gro seems to cause issues on the Atlantic + #${pkgs.ethtool}/bin/ethtool -K enp1s0 rx-gro-list on # Interrupt coalescing optimizations # Defaults: rx-usecs=256 rx-frames=0 tx-usecs=1022 tx-frames=0 diff --git a/desktop/l2/network.nix.not b/desktop/l2/network.nix.not deleted file mode 100644 index 81d67df..0000000 --- a/desktop/l2/network.nix.not +++ /dev/null @@ -1,98 +0,0 @@ -{ config, pkgs, lib, ... }: - -{ - networking = { - useNetworkd = true; - useDHCP = false; - interfaces = { - enp1s0 = { - useDHCP = true; - ipv6 = { - enable = true; - acceptRA = true; - }; - }; - - wlp35s0 = { - ipv4.addresses = [{ - address = "10.0.35.1"; - prefixLength = 24; - }]; - ipv6.addresses = []; - }; - - wlp65s0 = { - ipv4.addresses = [{ - address = "10.0.65.1"; - prefixLength = 24; - }]; - ipv6.addresses = []; - }; - - wlp70s0 = { - ipv4.addresses = [{ - address = "10.0.70.1"; - prefixLength = 24; - }]; - ipv6.addresses = []; - }; - }; - - firewall = { - enable = true; - allowedTCPPorts = [ 22 53 67 ]; # SSH, DNS, DHCP - allowedUDPPorts = [ 53 67 68 ]; # DNS, DHCP client/server - }; - - enableIPv6 = true; - ipForward = true; - ipv6 = { - enable = true; - forward = true; - }; - }; - - # Enable kea DHCP server - services.kea = { - enable = true; - dhcp4 = { - enable = true; - settings = { - interfaces-config.interfaces = [ "wlp35s0" "wlp65s0" "wlp70s0" ]; - subnet4 = [ - { - subnet = "10.0.35.0/24"; - pools = [{ pool = "10.0.35.100 - 10.0.35.200"; }]; - option-data = [ - { name = "routers"; data = "10.0.35.1"; } - { name = "domain-name-servers"; data = "10.0.35.1"; } - ]; - } - { - subnet = "10.0.65.0/24"; - pools = [{ pool = "10.0.65.100 - 10.0.65.200"; }]; - option-data = [ - { name = "routers"; data = "10.0.65.1"; } - { name = "domain-name-servers"; data = "10.0.65.1"; } - ]; - } - { - subnet = "10.0.70.0/24"; - pools = [{ pool = "10.0.70.100 - 10.0.70.200"; }]; - option-data = [ - { name = "routers"; data = "10.0.70.1"; } - { name = "domain-name-servers"; data = "10.0.70.1"; } - ]; - } - ]; - }; - }; - }; - - # Enable PowerDNS recursor - services.pdns-recursor = { - enable = true; - localAddress = "127.0.0.1"; - allowFrom = [ "127.0.0.0/8" "10.0.35.0/24" "10.0.65.0/24" "10.0.70.0/24" ]; - }; -} diff --git a/desktop/l2/not.hostapd.nix b/desktop/l2/not.hostapd.nix deleted file mode 100644 index 56b7c3b..0000000 --- a/desktop/l2/not.hostapd.nix +++ /dev/null @@ -1,173 +0,0 @@ -# -# hostapd.nix -# - -# -# NOT using service.hostapd, because it has limited configuration capabilities -# https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/hostapd.nix -# -# Using custom systemd services to run hostapd per interface -# -# systemctl status hostapd-wlp35s0 -# systemctl status hostapd-wlp65s0 -# systemctl status hostapd-wlp70s0 -# -# nix pkgs source -# https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/ho/hostapd/package.nix -# https://w1.fi/hostapd/ -# https://github.com/latelee/hostapd -# -# Giant NixPkgs PR: https://github.com/NixOS/nixpkgs/pull/222536 -# -# -# hostapd.nix - -{ config, lib, pkgs, ... }: - -let - # List of Wi-Fi interfaces to manage - wifiInterfaces = [ "wlp35s0" "wlp65s0" "wlp70s0" ]; - - # Real MAC addresses for each interface (used for bssid=) - ifaceMacs = { - wlp35s0 = "28:A4:4A:27:E7:7D"; - wlp65s0 = "28:A4:4A:D7:86:74"; - wlp70s0 = "90:65:84:5E:6F:D2"; - }; - - # Common SSID and WPA3 settings - ssid = "myssid"; - psk = "supersecurepassword"; - - # Common AP parameters - commonParams = iface: '' - # - ##### Configuration for ${iface} ##### - # - ${if iface == builtins.elemAt wifiInterfaces 0 then "interface=${iface}" else "bss=${iface}"} - bssid=${ifaceMacs.${iface}} - ssid=${ssid} - hw_mode=g - channel=6 - ieee80211n=1 - ieee80211ac=1 - ieee80211ax=1 - wmm_enabled=1 - - # WMM tuning - wmm_ac_be_aifs=1 - wmm_ac_be_cwmin=4 - wmm_ac_be_cwmax=4 - wmm_ac_be_txop_limit=32 - wmm_ac_be_acm=0 - - # WPA3-SAE settings - wpa=2 - wpa_key_mgmt=SAE - rsn_pairwise=CCMP - sae_require_mfp=1 - ieee80211w=2 - ft_psk_generate_local=1 - mobility_domain=4f57 - ft_over_ds=1 - nas_identifier=${iface}-ap - sae_password=${psk} - bridge=br0 - macaddr_acl=0 - ''; - - # Generate a single hostapd.conf for all BSSes - hostapdConf = pkgs.writeText "hostapd.conf" ( - '' - ctrl_interface=/run/hostapd - country_code=US - ieee80211d=1 - logger_syslog=-1 - logger_syslog_level=2 - logger_stdout=-1 - logger_stdout_level=2 - '' + - lib.concatMapStringsSep "\n" commonParams wifiInterfaces - ); - -in { - systemd.services.hostapd = { - description = "Unified hostapd service for multi-interface Wi-Fi"; - wantedBy = [ "multi-user.target" ]; - after = [ "network-online.target" ]; - requires = [ "network-online.target" ]; - - preStart = '' - for iface in ${builtins.concatStringsSep " " wifiInterfaces}; do - ip link set dev "$iface" down || true - iw dev "$iface" set type __ap || true - ip link set dev "$iface" up - done - sleep 5 - ''; - - path = [ pkgs.iproute2 pkgs.iw ]; - - serviceConfig = { - ExecStart = "${pkgs.hostapd}/bin/hostapd -d ${hostapdConf}"; - Restart = "on-failure"; - RuntimeDirectory = "hostapd"; - Type = "simple"; - LimitNOFILE = 65535; - #CapabilityBoundingSet = [ "CAP_NET_ADMIN" "CAP_NET_BIND_SERVICE" ]; - #AmbientCapabilities = [ "CAP_NET_ADMIN" "CAP_NET_BIND_SERVICE" ]; - # ProtectSystem = "strict"; - # ProtectHome = true; - # PrivateTmp = true; - # NoNewPrivileges = true; - # ReadWritePaths = [ "/run/hostapd" ]; - # DeviceAllow = [ - # "/dev/wlp35s0" - # "/dev/wlp65s0" - # "/dev/wlp70s0" - # "/dev/rfkill" - # ]; - # DevicePolicy = "auto"; - # DevicePolicy = "closed"; - # RestrictAddressFamilies = [ - # "AF_UNIX" - # "AF_NETLINK" - # "AF_INET" - # "AF_INET6" - # ]; - # ProtectKernelModules = true; - # ProtectControlGroups = true; - # ProtectKernelTunables = true; - # ProtectClock = true; - # LockPersonality = true; - # RemoveIPC = true; - # RestrictRealtime = true; - # SystemCallArchitectures = "native"; - # RestrictNamespaces = true; - - MemoryMax = "1024M"; - CPUQuota = "100%"; - }; - }; - - networking = { - networkmanager.enable = false; - useDHCP = false; - - # Define empty bridge device, do not enslave wifi interfaces directly - bridges.br0.interfaces = [ ]; - - interfaces."br0" = { - ipv4.addresses = [{ address = "192.168.1.1"; prefixLength = 24; }]; - ipv6.addresses = [{ address = "fd00::1"; prefixLength = 64; }]; - }; - - interfaces."enp1s0".useDHCP = true; - - nat.enable = true; - nat.externalInterface = "enp1s0"; - nat.internalInterfaces = [ "br0" ]; - }; -} - -# end \ No newline at end of file diff --git a/desktop/l2/old.hardware-configuration.nix b/desktop/l2/old.hardware-configuration.nix new file mode 100644 index 0000000..e1b1083 --- /dev/null +++ b/desktop/l2/old.hardware-configuration.nix @@ -0,0 +1,41 @@ +# Do not modify this file! It was generated by 'nixos-generate-config' +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/f72013eb-dba3-48d6-80cd-65a1684ba502"; + fsType = "ext4"; + }; + + boot.initrd.luks.devices."luks-6fd137fa-aa82-4200-9ca1-cd049de90418".device = "/dev/disk/by-uuid/6fd137fa-aa82-4200-9ca1-cd049de90418"; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/4C7A-4843"; + fsType = "vfat"; + options = [ "fmask=0077" "dmask=0077" ]; + }; + + swapDevices = + [ { device = "/dev/disk/by-uuid/979a4a5a-8724-4c06-8173-13e72cb49a9d"; } + ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + # networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp1s0.useDHCP = lib.mkDefault true; + + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/desktop/l2/prometheus.nix b/desktop/l2/prometheus.nix index 24eabca..ec5ead1 100644 --- a/desktop/l2/prometheus.nix +++ b/desktop/l2/prometheus.nix @@ -8,63 +8,12 @@ enable = true; globalConfig.scrape_interval = "10s"; # "1m" scrapeConfigs = [ - { - job_name = "node"; - static_configs = [{ - targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ]; - }]; - } - { - job_name = "xtcp"; - static_configs = [{ - targets = [ "localhost:9088" ]; - }]; - } - { - job_name = "hp1_xtcp"; - static_configs = [{ - targets = [ "hp1:9088" ]; - }]; - } - { - job_name = "clickhouse"; - static_configs = [{ - #targets = [ "localhost:9363" ]; - targets = [ "localhost:19363" ]; - }]; - } - { - job_name = "hp1"; - static_configs = [{ - targets = [ "hp1:${toString config.services.prometheus.exporters.node.port}" ]; - }]; - } - { - job_name = "hp1_clickhouse"; - static_configs = [{ - #targets = [ "localhost:9363" ]; - targets = [ "hp1:19363" ]; - }]; - } - { - job_name = "hp2"; - static_configs = [{ - targets = [ "hp2:${toString config.services.prometheus.exporters.node.port}" ]; - }]; - } - { - job_name = "hp2_clickhouse"; - static_configs = [{ - #targets = [ "localhost:9363" ]; - targets = [ "hp2:19363" ]; - }]; - } - #{ - # job_name = "chromebox1"; - # static_configs = [{ - # targets = [ "172.16.40.179:9105" ]; - # }]; - #} + { + job_name = "node"; + static_configs = [{ + targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ]; + }]; + } ]; }; } \ No newline at end of file diff --git a/desktop/l2/systemd-slices.nix b/desktop/l2/systemd-slices.nix index 6351269..3926da9 100644 --- a/desktop/l2/systemd-slices.nix +++ b/desktop/l2/systemd-slices.nix @@ -53,6 +53,18 @@ in { Slice = "network-services.slice"; }; }; + crowdsec = { + description = "CrowdSec threat detection engine slice"; + sliceConfig = { + Slice = "network-services.slice"; + }; + }; + crowdsec-firewall-bouncer = { + description = "CrowdSec firewall bouncer slice"; + sliceConfig = { + Slice = "network-services.slice"; + }; + }; }; # CPU Affinity for Network Services diff --git a/desktop/l2/test-crowdsec.sh b/desktop/l2/test-crowdsec.sh new file mode 100755 index 0000000..e203fb6 --- /dev/null +++ b/desktop/l2/test-crowdsec.sh @@ -0,0 +1,125 @@ +#!/bin/bash + +# CrowdSec SSH Attack Simulation Test +# This script simulates SSH brute force attacks to test CrowdSec detection + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +CROWDSEC_CONFIG="/nix/store/r236yjfapykriw64g52mqih6fz3lis5l-crowdsec.yaml" +ROUTER_IP="192.168.1.1" + +echo -e "${BLUE}CrowdSec SSH Attack Simulation Test${NC}" +echo "==========================================" +echo + +# Function to print test results +print_result() { + local test_name="$1" + local result="$2" + local details="$3" + + if [ "$result" = "PASS" ]; then + echo -e "${GREEN}✓ PASS${NC}: $test_name" + if [ -n "$details" ]; then + echo -e " ${BLUE}Details:${NC} $details" + fi + else + echo -e "${RED}✗ FAIL${NC}: $test_name" + if [ -n "$details" ]; then + echo -e " ${YELLOW}Details:${NC} $details" + fi + fi + echo +} + +# Check if CrowdSec is running +echo -e "${BLUE}=== Checking CrowdSec Status ===${NC}" +if systemctl is-active --quiet crowdsec; then + print_result "CrowdSec Engine" "PASS" "Service is running" +else + print_result "CrowdSec Engine" "FAIL" "Service is not running" + exit 1 +fi + +if systemctl is-active --quiet crowdsec-firewall-bouncer; then + print_result "CrowdSec Firewall Bouncer" "PASS" "Service is running" +else + print_result "CrowdSec Firewall Bouncer" "FAIL" "Service is not running" + exit 1 +fi + +# Check initial state +echo -e "${BLUE}=== Initial State ===${NC}" +initial_decisions=$(sudo cscli decisions list -c "$CROWDSEC_CONFIG" | wc -l) +print_result "Initial decisions" "INFO" "$initial_decisions active decisions" + +# Simulate SSH brute force attack +echo -e "${BLUE}=== Simulating SSH Brute Force Attack ===${NC}" +echo "Attempting 20 SSH connections with invalid credentials..." + +for i in $(seq 1 20); do + echo -n "Attempt $i/20... " + if timeout 2 ssh -o ConnectTimeout=1 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o PasswordAuthentication=yes attacker@"$ROUTER_IP" "exit" 2>/dev/null; then + echo "FAILED (unexpected success)" + else + echo "BLOCKED (expected)" + fi + sleep 0.1 +done + +# Wait for CrowdSec to process the events +echo -e "\n${BLUE}=== Waiting for CrowdSec Processing ===${NC}" +echo "Waiting 10 seconds for CrowdSec to process events..." +sleep 10 + +# Check if decisions were created +echo -e "${BLUE}=== Checking for Decisions ===${NC}" +final_decisions=$(sudo cscli decisions list -c "$CROWDSEC_CONFIG" | wc -l) +decision_count=$((final_decisions - initial_decisions)) + +if [ $decision_count -gt 0 ]; then + print_result "SSH attack detection" "PASS" "CrowdSec detected $decision_count new decisions" + + # Show the decisions + echo -e "${BLUE}=== Active Decisions ===${NC}" + sudo cscli decisions list -c "$CROWDSEC_CONFIG" +else + print_result "SSH attack detection" "FAIL" "No new decisions created" +fi + +# Check if IPs were added to blacklist +echo -e "${BLUE}=== Checking nftables Blacklist ===${NC}" +blacklist_entries=$(sudo nft list set inet filter blacklist 2>/dev/null | grep -c "elements" || echo "0") + +if [ $blacklist_entries -gt 0 ]; then + print_result "nftables blacklist" "PASS" "Blacklist contains $blacklist_entries entries" + + # Show blacklist contents + echo -e "${BLUE}=== Blacklist Contents ===${NC}" + sudo nft list set inet filter blacklist +else + print_result "nftables blacklist" "FAIL" "No entries in blacklist" +fi + +# Test if the attacking IP is actually blocked +echo -e "${BLUE}=== Testing IP Blocking ===${NC}" +# We can't easily test this from the router itself, but we can check the logs +recent_logs=$(journalctl -u crowdsec --since "2 minutes ago" | grep -c "decision" || echo "0") + +if [ $recent_logs -gt 0 ]; then + print_result "CrowdSec logging" "PASS" "Found $recent_logs recent decision logs" +else + print_result "CrowdSec logging" "FAIL" "No recent decision logs found" +fi + +echo -e "${BLUE}=== Test Summary ===${NC}" +echo "CrowdSec SSH monitoring test completed." +echo "To verify blocking works, test from an external machine:" +echo " ssh attacker@$ROUTER_IP # Should be blocked if detection worked" \ No newline at end of file diff --git a/desktop/l2/wireless_desktop.nix b/desktop/l2/wireless_desktop.nix deleted file mode 100644 index c8f4a68..0000000 --- a/desktop/l2/wireless_desktop.nix +++ /dev/null @@ -1,20 +0,0 @@ -{ config, pkgs, ... }: - -{ - # networking.proxy.default = "http://user:password@proxy:port/"; - # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - - networking = { - networkmanager = { - enable = true; - #wifi.powersave = true; - wifi.powersave = false; - }; - }; - - #networking.hosts = { - # "172.16.50.216" = ["hp0"]; - # "172.16.40.35" = ["hp1"]; - # "172.16.40.71" = ["hp2"]; - #}; -} \ No newline at end of file From ab5d073428eada62d5362c6e2f539864ae2d7bdd Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Tue, 1 Jul 2025 17:27:54 -0700 Subject: [PATCH 02/23] 2025 07 01 --- desktop/l2/README.md | 30 ++++++++++- desktop/l2/firewall.md | 57 +++++++++++++++++---- desktop/l2/firewall.nix | 98 +++++++++++++++++++++++++++--------- desktop/l2/hostapd-multi.nix | 25 +++++++-- 4 files changed, 171 insertions(+), 39 deletions(-) diff --git a/desktop/l2/README.md b/desktop/l2/README.md index db16f7b..6a316b9 100644 --- a/desktop/l2/README.md +++ b/desktop/l2/README.md @@ -330,4 +330,32 @@ Internet (enp1s0) - `monitoring.nix` - Performance monitoring and testing services - `sysctl.nix` - Kernel network parameters - `configuration.nix` - Main system configuration -- `CPU_and_IRQ_optimization.md` - Detailed optimization documentation \ No newline at end of file +- `CPU_and_IRQ_optimization.md` - Detailed optimization documentation + + +## Netlink monitoring + +Hostapd communicates with the kernel via Netlink. To monitor the Netlink traffic, follow these instructions: + +``` +modprobe nlmon +sudo modprobe nlmon +lsmod | grep nlmon +sudo ip link add nlmon0 type nlmon +sudo ip link set dev nlmon0 up +sudo tcpdump -i nlmon0 -w netlink.pcap +sudo chown das:das *.pcap +``` + +See also: https://jvns.ca/blog/2017/09/03/debugging-netlink-requests/ + + +## ipv6 debugging notes + +``` +sudo tcpdump -i enp1s0 -n 'icmp6 and (icmp6[0] == 133 or icmp6[0] == 134)' +# triggger router solicitation (nix-shell -p ndisc6) +sudo rdisc6 enp1s0 +# another way +sudo ip -6 route flush dev enp1s0 +``` \ No newline at end of file diff --git a/desktop/l2/firewall.md b/desktop/l2/firewall.md index 5e9b89a..d84e1ae 100644 --- a/desktop/l2/firewall.md +++ b/desktop/l2/firewall.md @@ -4,7 +4,7 @@ This document outlines the design and principles of the `nftables` firewall configuration for the L2 WiFi access point. The primary goals are to provide robust security for the router and its clients, ensure correct network functionality, and maintain a clear, auditable ruleset with maximum performance. -The firewall leverages `nftables` for its modern syntax, performance, and ability to handle both IPv4 and IPv6 within a unified `inet` table family where possible. The configuration is optimized for performance through extensive use of nftables sets and strategic rule ordering. +The firewall leverages `nftables` for its modern syntax, performance, and ability to handle both IPv4 and IPv6 within a unified `inet` table family where possible. The configuration is optimized for performance through extensive use of nftables sets and strategic rule ordering, including early processing of trusted traffic like loopback communication. ### 1.1. Configuration Variables @@ -49,6 +49,9 @@ The firewall extensively uses nftables sets for optimal performance and maintain * **`special_purpose_ipv6`**: Contains all RFC 6890 special-purpose IPv6 ranges * **`loopback_ipv4`**: IPv4 loopback addresses (127.0.0.0/8) * **`loopback_ipv6`**: IPv6 loopback addresses (::1/128) +* **`link_local_ipv6`**: IPv6 link-local addresses (fe80::/10) - essential for IPv6 operation including Router Advertisements and Neighbor Discovery +* **`internal_ipv4`**: Internal IPv4 subnet (192.168.1.0/24) - our allocated private network +* **`internal_ipv6`**: Internal IPv6 subnet (fd00::/64) - our allocated private network * **`blacklist`**: Dynamic blacklist for CrowdSec integration (timeout-based, auto-merge) #### 3.1.2. Service Port Sets @@ -66,14 +69,18 @@ This chain protects the access point itself with optimized rule ordering: * **Early Invalid Packet Drops**: * **Drops** invalid connection states immediately - * **Drops** fragmented packets (potential evasion technique) + * **Allows** fragment reassembly - router reassembles fragments and applies security rules to reassembled packets +* **Loopback Protection** (Early): + * **Accepts** all legitimate traffic on the loopback interface (`lo`) immediately + * **Drops** any packet seen on a physical interface with loopback addresses using optimized set lookups + * **Performance**: Early placement ensures trusted loopback traffic bypasses expensive rule evaluation +* **TCP Flag Validation**: * **Drops** packets with invalid TCP flag combinations * **Fast Path for Established Connections**: * **Accepts** established and related connections early for maximum performance -* **Loopback Protection**: - * **Accepts** all legitimate traffic on the loopback interface (`lo`) - * **Drops** any packet seen on a physical interface with loopback addresses using optimized set lookups * **Global Anti-Spoofing**: + * **Exception**: Allows essential IPv6 link-local communication (Router Advertisements, Neighbor Discovery) using the `link_local_ipv6` set + * **Allows** legitimate internal traffic from our allocated subnets * **Drops** any incoming packet with a source address from special-purpose ranges using set-based filtering * **Service Access Control**: * **Allows** access to essential network services using set-based port matching @@ -90,9 +97,14 @@ This chain governs the traffic from WiFi clients to the internet and vice-versa * **Early Invalid Packet Drops**: * **Drops** invalid connection states and malformed packets immediately + * **Allows** fragment reassembly for forwarded packets * **Anti-Spoofing with Set-Based Filtering**: * **Drops** any packet being forwarded that contains loopback addresses using set lookups * **Drops** any packet from internal clients with spoofed upstream LAN addresses + * **Drops** any packet from internal clients with spoofed special-purpose addresses +* **Internal Traffic Forwarding**: + * **Allows** legitimate internal traffic from our allocated subnets to external network +* **Special-Purpose Destination Blocking**: * **Drops** any packet from internal clients destined for special-purpose ranges using set-based filtering * **Fast Path for Return Traffic**: * **Allows** return traffic from external to internal for established connections (most common case) @@ -111,9 +123,13 @@ This chain governs traffic generated by the access point itself with comprehensi * **Default-Accept Policy**: The policy is `accept`, but hardened with explicit `drop` rules * **Early Invalid Packet Drops**: - * **Drops** invalid connection states, fragmented packets, and invalid TCP flags -* **Loopback Protection**: + * **Drops** invalid connection states, fragmented packets + * **Allows** fragment reassembly for outgoing packets +* **Loopback Protection** (Early): * **Drops** any packet with loopback addresses on physical interfaces using set-based filtering + * **Performance**: Early placement ensures loopback spoofing is detected before expensive rule evaluation +* **TCP Flag Validation**: + * **Drops** packets with invalid TCP flag combinations * **Global Egress Filtering**: * **Drops** any packet destined for special-purpose ranges using set-based filtering * **Interface-Specific Egress Filtering**: @@ -139,6 +155,8 @@ The firewall employs several advanced optimization techniques: #### 3.6.2. Rule Ordering Optimization * **Early Drops**: Invalid packets and spoofed traffic are dropped as early as possible +* **Fragment Reassembly**: Fragments are accepted for reassembly before applying security rules +* **Loopback Fast Path**: Loopback traffic is accepted immediately as it's inherently trusted, bypassing expensive rule evaluation and providing maximum performance for localhost communication * **Fast Path**: Established connections are accepted early to avoid expensive rule evaluation * **Global Filters**: Non-interface-specific drops (like special-purpose IP blocking) are applied before interface-specific rules * **Most Common Traffic First**: Return traffic and established connections are prioritized @@ -253,17 +271,32 @@ The CrowdSec integration makes several deliberate architectural choices: - Internal clients cannot spoof upstream LAN addresses - Fragment and TCP flag filtering prevents evasion techniques -### 4.3. Network Segmentation +### 4.3. Fragment Handling Strategy +- **Fragment Reassembly**: Instead of dropping fragments, the router reassembles them and applies security rules to the complete packets +- **Security Benefits**: Prevents fragment-based attacks while maintaining compatibility with legitimate applications +- **Compatibility**: Supports applications that rely on fragmentation (VPNs, streaming, large packet transfers) +- **Performance**: Reassembly happens at the kernel level with minimal overhead +- **Attack Prevention**: Fragment-based evasion techniques are neutralized since security rules are applied to reassembled packets + +### 4.4. Network Segmentation - Clear separation between internal (br0) and external (enp1s0) interfaces - Service access is restricted to internal interfaces only - Upstream LAN access is explicitly controlled - Egress filtering prevents internal network leakage -### 4.4. IPv6 Security +### 4.5. IPv6 Security - Comprehensive ICMPv6 filtering for proper IPv6 operation - Neighbor Discovery Protocol protection -- Router Advertisement control +- Router Advertisement control via link-local address set (`link_local_ipv6`) - Path MTU Discovery support +- Essential link-local communication allowed for IPv6 operation + +### 4.6. Performance Considerations +- **Early Loopback Processing**: Loopback traffic is handled immediately to bypass expensive rule evaluation +- **Fragment Reassembly**: Kernel-level reassembly with minimal overhead +- **Set-Based Lookups**: Optimized address and port matching using nftables sets +- **Rule Ordering**: Most common traffic patterns are prioritized for maximum throughput +- **Connection Tracking**: Stateful inspection reduces rule evaluation for established connections ## 5. Monitoring and Logging @@ -292,6 +325,7 @@ Monitor firewall logs for: | ------------------------------- | :--------------------: | :-----------------------: | :---------------------: | | **Default-Deny Policy** | ✓ | ✓ | ✗ | | **Stateful Inspection** | ✓ | ✓ | ✓ | +| **Fragment Reassembly** | ✓ | ✓ | ✓ | | **Loopback Anti-Spoofing** | ✓ | ✓ | ✓ | | **Special-Purpose IP Blocking** | ✓ | ✓ | ✓ | | **Service Access Control** | ✓ | N/A | N/A | @@ -353,6 +387,9 @@ ping -I 127.0.0.1 8.8.8.8 # Should be blocked # Test special-purpose IP blocking ping -I 192.168.1.100 10.0.0.1 # Should be blocked +# Test fragment handling +ping -s 1500 -M do 192.168.1.1 # Test large packets that may fragment + # Test IPv6 functionality ping6 -c 1 fd00::1 # Should work from internal diff --git a/desktop/l2/firewall.nix b/desktop/l2/firewall.nix index c901832..8d3985e 100644 --- a/desktop/l2/firewall.nix +++ b/desktop/l2/firewall.nix @@ -111,6 +111,32 @@ in { } } + # Define set for link-local IPv6 addresses (essential for IPv6 operation) + set link_local_ipv6 { + type ipv6_addr + flags interval + elements = { + fe80::/10 # Link-Local Addresses + } + } + + # Define sets for our internal networks + set internal_ipv4 { + type ipv4_addr + flags interval + elements = { + ${internalIPv4Prefix} # Internal IPv4 subnet + } + } + + set internal_ipv6 { + type ipv6_addr + flags interval + elements = { + ${internalIPv6Prefix} # Internal IPv6 subnet + } + } + # Define sets for common service ports set ssh_ports { type inet_service @@ -181,8 +207,18 @@ in { # Early drop for invalid packets ct state invalid drop - # Drop fragmented packets (potential evasion technique) - ip frag-off & 0x1fff != 0 drop + # Allow fragment reassembly - let the router reassemble fragments + # and then apply security rules to the reassembled packets + # This prevents fragment-based attacks while maintaining compatibility + ip frag-off & 0x1fff != 0 accept + + # Accept all traffic on the loopback interface, and drop spoofed + # loopback packets on any other interface. + iif lo accept + iif != "lo" ip saddr @loopback_ipv4 drop + iif != "lo" ip daddr @loopback_ipv4 drop + iif != "lo" ip6 saddr @loopback_ipv6 drop + iif != "lo" ip6 daddr @loopback_ipv6 drop # Drop packets with invalid TCP flag combinations tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|syn|rst|psh|ack|urg) drop @@ -196,19 +232,23 @@ in { # Allow established and related connections ct state established,related accept - # Accept all traffic on the loopback interface, and drop spoofed - # loopback packets on any other interface. - iif lo accept - iif != "lo" ip saddr @loopback_ipv4 drop - iif != "lo" ip daddr @loopback_ipv4 drop - iif != "lo" ip6 saddr @loopback_ipv6 drop - iif != "lo" ip6 daddr @loopback_ipv6 drop - # Drop incoming traffic from special-purpose/unroutable source addresses (RFC 6890) # This provides strong anti-spoofing protection for the router itself. + # EXCEPTION: Allow essential IPv6 link-local communication (needed for IPv6 operation) + ip6 saddr @link_local_ipv6 icmpv6 type @icmpv6_allowed accept + + # Allow legitimate internal traffic from our networks + iifname "${lanInterface}" ip saddr @internal_ipv4 accept + iifname "${lanInterface}" ip6 saddr @internal_ipv6 accept + + # Block spoofed special-purpose addresses from all interfaces ip saddr @special_purpose_ipv4 drop ip6 saddr @special_purpose_ipv6 drop + # Block destination special-purpose addresses from all interfaces + ip daddr @special_purpose_ipv4 drop + ip6 daddr @special_purpose_ipv6 drop + # Allow management and network services from the internal interface (${lanInterface}) # Rate limit SSH to prevent brute force attacks iifname "${lanInterface}" tcp dport @ssh_ports ct state new limit rate 6/minute accept @@ -247,8 +287,9 @@ in { # Early drop for invalid packets being forwarded ct state invalid drop - # Drop fragmented packets being forwarded - ip frag-off & 0x1fff != 0 drop + # Allow fragment reassembly for forwarded packets + # Let the router reassemble fragments and apply security rules to reassembled packets + ip frag-off & 0x1fff != 0 accept # Drop packets with invalid TCP flag combinations tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|syn|rst|psh|ack|urg) drop @@ -265,6 +306,14 @@ in { # Drop traffic from internal clients pretending to be on the upstream LAN. iifname "${lanInterface}" ip saddr ${upstreamLanPrefix} drop + # Allow legitimate internal traffic to external network + iifname "${lanInterface}" oifname "${wanInterface}" ip saddr @internal_ipv4 accept + iifname "${lanInterface}" oifname "${wanInterface}" ip6 saddr @internal_ipv6 accept + + # Block spoofed special-purpose addresses from internal clients + iifname "${lanInterface}" ip saddr @special_purpose_ipv4 drop + iifname "${lanInterface}" ip6 saddr @special_purpose_ipv6 drop + # Drop traffic from internal clients to private/reserved ranges. # This prevents traffic from being forwarded to non-routable destinations. # Based on IANA Special-Purpose Address Registry (RFC 6890) @@ -300,13 +349,9 @@ in { # Drop invalid packets originating from the local machine ct state invalid drop - # Drop fragmented packets from router - ip frag-off & 0x1fff != 0 drop - - # Drop packets with invalid TCP flag combinations - tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|syn|rst|psh|ack|urg) drop - tcp flags & (fin|syn) == (fin|syn) drop - tcp flags & (syn|rst) == (syn|rst) drop + # Allow fragment reassembly for outgoing packets + # Let the router reassemble fragments before sending + ip frag-off & 0x1fff != 0 accept # Drop spoofed loopback packets on non-loopback interfaces. # Legitimate traffic to/from loopback addresses should only be on the 'lo' interface. @@ -315,6 +360,11 @@ in { oif != "lo" ip6 saddr @loopback_ipv6 drop oif != "lo" ip6 daddr @loopback_ipv6 drop + # Drop packets with invalid TCP flag combinations + tcp flags & (fin|syn|rst|psh|ack|urg) == (fin|syn|rst|psh|ack|urg) drop + tcp flags & (fin|syn) == (fin|syn) drop + tcp flags & (syn|rst) == (syn|rst) drop + # Allow essential ICMPv6 traffic from router (Router Advertisement, Neighbor Advertisement, etc.) oifname "${lanInterface}" icmpv6 type @icmpv6_allowed accept oifname "${wanInterface}" icmpv6 type @icmpv6_allowed accept @@ -328,13 +378,13 @@ in { # Block allocated subnets from going out the WAN interface (${wanInterface}) # to prevent internal network leakage - oifname "${wanInterface}" ip daddr ${internalIPv4Prefix} drop - oifname "${wanInterface}" ip6 daddr ${internalIPv6Prefix} drop + oifname "${wanInterface}" ip daddr @internal_ipv4 drop + oifname "${wanInterface}" ip6 daddr @internal_ipv6 drop # Allow allocated subnets to go out the internal interface (${lanInterface}) # for legitimate internal network communication - oifname "${lanInterface}" ip daddr ${internalIPv4Prefix} accept - oifname "${lanInterface}" ip6 daddr ${internalIPv6Prefix} accept + oifname "${lanInterface}" ip daddr @internal_ipv4 accept + oifname "${lanInterface}" ip6 daddr @internal_ipv6 accept } } @@ -357,7 +407,7 @@ in { chain postrouting { type nat hook postrouting priority srcnat; - # IPv6 masquerading + # IPv6 masquerading for private fd00::/64 network oifname "${wanInterface}" masquerade } } diff --git a/desktop/l2/hostapd-multi.nix b/desktop/l2/hostapd-multi.nix index 1fbcc09..bd31416 100644 --- a/desktop/l2/hostapd-multi.nix +++ b/desktop/l2/hostapd-multi.nix @@ -82,6 +82,7 @@ in { systemd.tmpfiles.rules = [ "L+ /lib/firmware/regulatory.db - - - - ${pkgs.wireless-regdb}/lib/firmware/regulatory.db" "L+ /lib/firmware/regulatory.db.p7s - - - - ${pkgs.wireless-regdb}/lib/firmware/regulatory.db.p7s" + "d /run/radvd 0755 radvd radvd - -" ]; systemd.services.set-regdom = { @@ -171,9 +172,19 @@ in { # Add necessary capabilities to RADVD for ICMPv6 Router Advertisement systemd.services.radvd = { serviceConfig = { + # Run as radvd user from the start + User = "radvd"; + Group = "radvd"; + # Override ExecStart to remove -u radvd flag since we're already running as radvd user + # Use -p flag to specify a writable PID file location + ExecStart = lib.mkForce "${pkgs.radvd}/bin/radvd -n -p /run/radvd/radvd.pid -d 0 -C ${pkgs.writeText "radvd.conf" config.services.radvd.config}"; + # Let systemd manage the PID file + PIDFile = "/run/radvd/radvd.pid"; # Add CAP_NET_RAW capability to allow sending ICMPv6 messages CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" "CAP_NET_BROADCAST" "CAP_NET_RAW" ]; AmbientCapabilities = [ "CAP_NET_RAW" ]; + # Ensure the process can bind to privileged ports if needed + NoNewPrivileges = false; }; }; @@ -213,14 +224,20 @@ systemd.network.networks."dummy0" = { matchConfig.Name = "enp1s0"; networkConfig = { DHCP = "ipv4"; - IPv4Forwarding = true; - IPv6Forwarding = true; + #IPv4Forwarding = true; + #IPv6Forwarding = true; IPv6AcceptRA = true; IPv6PrivacyExtensions = true; # IPMasquerade handled by nftables for better control LLDP = true; EmitLLDP = true; }; + # # Explicitly enable Router Advertisement acceptance + # ipv6AcceptRAConfig = { + # AcceptRA = true; + # UseDNS = false; # We handle DNS ourselves + # UseDomains = false; + # }; }; "br0" = { @@ -230,8 +247,8 @@ systemd.network.networks."dummy0" = { "192.168.1.1/24" "fd00::1/64" ]; - IPv4Forwarding = true; - IPv6Forwarding = true; + # IPv4Forwarding = true; + # IPv6Forwarding = true; ConfigureWithoutCarrier = true; }; linkConfig = { From 2b435c502d2855f0fc32ef289e5e57def02812ac Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Sat, 5 Jul 2025 18:15:54 -0700 Subject: [PATCH 03/23] grafana smokeping blackbox --- desktop/l2/systemPackages.nix | 1 - hp/hp2/configuration.nix | 4 +- hp/hp2/gather_nixos_migration_data.sh | 75 ++++ hp/hp4/blackbox.nix | 334 +++++++++++++++ hp/hp4/configuration.nix | 20 +- hp/hp4/hosts.nix | 6 + hp/hp4/nginx.nix | 33 ++ hp/hp4/pdns-recursor.nix | 42 ++ hp/hp4/prometheus.nix | 161 +++++++- hp/hp4/smokeping.nix | 570 ++++++++++++++++++++++++++ hp/hp4/sysctl.nix | 5 + 11 files changed, 1224 insertions(+), 27 deletions(-) create mode 100755 hp/hp2/gather_nixos_migration_data.sh create mode 100644 hp/hp4/blackbox.nix create mode 100644 hp/hp4/pdns-recursor.nix create mode 100644 hp/hp4/smokeping.nix diff --git a/desktop/l2/systemPackages.nix b/desktop/l2/systemPackages.nix index c3a9296..8719960 100644 --- a/desktop/l2/systemPackages.nix +++ b/desktop/l2/systemPackages.nix @@ -29,7 +29,6 @@ net-snmp neofetch - hostapd bridge-utils wireless-regdb diff --git a/hp/hp2/configuration.nix b/hp/hp2/configuration.nix index 3527238..9709246 100644 --- a/hp/hp2/configuration.nix +++ b/hp/hp2/configuration.nix @@ -35,10 +35,10 @@ ./nodeExporter.nix ./prometheus.nix ./grafana.nix - ./docker-daemon.nix + #./docker-daemon.nix #./k8s_node.nix #./k3s_master.nix - ./k3s_node.nix + #./k3s_node.nix ./systemd.services.ethtool-enp3s0f0.nix ./systemd.services.ethtool-enp3s0f1.nix ]; diff --git a/hp/hp2/gather_nixos_migration_data.sh b/hp/hp2/gather_nixos_migration_data.sh new file mode 100755 index 0000000..b7553f7 --- /dev/null +++ b/hp/hp2/gather_nixos_migration_data.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +set -euo pipefail + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "Example: $0 /tmp/nixos_migration.log" + exit 1 +fi + +OUTPUT_FILE=$1 + +# Commands that do NOT require sudo +NORMAL_COMMANDS=( + "uname -a" + "cat /etc/lsb-release" + "ifconfig -a" + "ip addr" + "ip -6 addr" + "ip route" + "ip -6 route" +) + +# Commands that require sudo +SUDO_COMMANDS=( + # Network + "cat /etc/netplan/*.yaml" + "iptables-save" + "for iface in \$(ls /sys/class/net); do ethtool \$iface >/dev/null 2>&1 && echo \"--- ethtool \$iface ---\" && ethtool \$iface; done" + + # Disk + "lsblk -f" + "lsblk -d -o NAME,MODEL,ROTA,SIZE,TYPE,TRAN" + "mount" + "df -h" + "cat /etc/fstab" + + # WireGuard + "wg show" + "systemctl status wg-quick@* || true" + "cat /etc/wireguard/*.conf 2>/dev/null || echo 'No WireGuard config files found'" + + # DHCP + "ps aux | grep [d]hcpd" + "cat /etc/dhcp/dhcpd.conf 2>/dev/null || echo 'No dhcpd.conf found'" + "systemctl status isc-dhcp-server 2>/dev/null || systemctl status dhcpd 2>/dev/null || echo 'DHCP service not found'" + + # Hardware + "lspci -nn" + "which hwloc-ls >/dev/null && hwloc-ls || which lstopo-no-graphics >/dev/null && lstopo-no-graphics || echo 'hwloc-ls not available'" +) + +{ + echo "=== Host: $(hostname) ===" + echo + echo "=== NON-SUDO COMMANDS ===" + echo + + for CMD in "${NORMAL_COMMANDS[@]}"; do + echo ">>> $CMD" + bash -c "$CMD" || echo "Command failed: $CMD" + echo + done + + echo "=== SUDO COMMANDS ===" + echo + + for CMD in "${SUDO_COMMANDS[@]}"; do + echo ">>> sudo $CMD" + sudo bash -c "$CMD" || echo "Command failed: $CMD" + echo + done +} > "$OUTPUT_FILE" + +echo "✅ Local info gathered to: $OUTPUT_FILE" diff --git a/hp/hp4/blackbox.nix b/hp/hp4/blackbox.nix new file mode 100644 index 0000000..f5869f0 --- /dev/null +++ b/hp/hp4/blackbox.nix @@ -0,0 +1,334 @@ +# +# https://gitlab.com/sidenio/nix/data_center/lax/dcops0_hp2/blackbox.nix +# + +# Blackbox Exporter is our primary tool for network monitoring, providing: +# - ICMP ping monitoring (IPv4/IPv6) +# - HTTP/HTTPS monitoring +# - DNS resolution testing +# - Comprehensive metrics for Prometheus +# +# This configuration mirrors the monitoring setup in smokeping.nix but provides +# better integration with Prometheus and more detailed metrics. +# +# Monitoring Categories: +# 1. DNSServers - ICMP ping to DNS server IPs (connectivity) +# 2. Internet - ICMP ping to internet hosts (connectivity) +# 3. NetworkDevices - ICMP ping to local network devices (connectivity) +# 4. HTTP - HTTP monitoring of websites (service availability) +# 5. DNSLookup - DNS resolution testing using specific DNS servers +# +# https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix + +{ config, lib, pkgs, ... }: + +let + # Import WireGuard configuration to get peer information + wireguardConfig = import ./wireguard.nix { inherit config lib pkgs; }; + + # Helper function to detect if an address is IPv6 + isIPv6 = host: lib.hasInfix ":" host; + + # Helper function to determine protocol based on host address + getProtocol = host: if isIPv6 host then "ip6" else "ip4"; + + # Helper function to add protocol to target if not specified + addProtocol = target: target // { + protocol = target.protocol or (getProtocol target.host); + }; + + # Helper function to extract /32 IPs from allowedIPs + extractSingleIPs = allowedIPs: lib.filter (ip: lib.hasSuffix "/32" ip) allowedIPs; + + # Helper function to convert CIDR to IP address + cidrToIP = cidr: lib.head (lib.splitString "/" cidr); + + # Generate WireGuard peer targets from the wireguard configuration + wireguardTargets = lib.mapAttrsToList (peerName: peer: + lib.mapAttrsToList (ipName: ip: { + name = "${peer.name} (${cidrToIP ip})"; + host = cidrToIP ip; + peerName = peerName; + cakePolicy = peer.cakePolicy; + }) (lib.listToAttrs (map (ip: { + name = ip; + value = ip; + }) (extractSingleIPs peer.allowedIPs))) + ) wireguardConfig.wireguardPeers; + + # Flatten the nested list structure + flatWireguardTargets = lib.flatten wireguardTargets; + + # Define targets in a structured way (matching smokeping.nix) + targets = { + # DNS Servers - ICMP ping testing + "DNSServers" = { + title = "DNS Server Connectivity (ICMP Ping)"; + menu = "DNS Servers"; + targets = { + "Google_DNS_IPv4" = { + name = "Google DNS IPv4"; + host = "8.8.8.8"; + }; + "Google_DNS_IPv6" = { + name = "Google DNS IPv6"; + host = "2001:4860:4860::8888"; + }; + "Cloudflare_DNS_IPv4" = { + name = "Cloudflare DNS IPv4"; + host = "1.1.1.1"; + }; + "Cloudflare_DNS_IPv6" = { + name = "Cloudflare DNS IPv6"; + host = "2606:4700:4700::1111"; + }; + "Cloudflare_DNS_Secondary_IPv4" = { + name = "Cloudflare DNS Secondary IPv4"; + host = "1.0.0.1"; + }; + "Cloudflare_DNS_Secondary_IPv6" = { + name = "Cloudflare DNS Secondary IPv6"; + host = "2606:4700:4700::1001"; + }; + }; + }; + + # Internet Connectivity + "Internet" = { + title = "Internet Connectivity Monitoring"; + menu = "Internet Connectivity"; + targets = { + "Google_IPv4" = { + name = "Google.com IPv4"; + host = "142.250.190.78"; + }; + "Google_IPv6" = { + name = "Google.com IPv6"; + host = "2607:f8b0:4007:811::200e"; + }; + "Facebook_IPv6" = { + name = "Facebook IPv6"; + host = "2a03:2880:f10d:183:face:b00c:0:25de"; + }; + "Yahoo_IPv6" = { + name = "Yahoo IPv6"; + host = "2001:4998:24:120d::1:0"; + }; + "crowncastle-ic-386848" = { + name = "crowncastle-ic-386848"; + host = "62.115.8.253"; + }; + "SidenLAX1" = { + name = "SidenLAX1"; + host = "160.72.7.68"; + }; + "SidenLAX1_Internal" = { + name = "SidenLAX1_Internal"; + host = "160.72.7.65"; + }; + "SidenLAX_dcops0_93" = { + name = "SidenLAX_dcops0_93"; + host = "160.72.7.93"; + }; + "SidenLAX_dcops1_94" = { + name = "SidenLAX_dcops1_94"; + host = "160.72.7.94"; + }; + }; + }; + + # Network Devices and Gateways + "NetworkDevices" = { + title = "Network Devices and Gateways"; + menu = "Network Devices"; + targets = { + "SpectrumLAG60_4" = { + name = "SpectrumLAG60_4"; + host = "76.167.31.29"; + }; + "SpectrumLAG60_6" = { + name = "SpectrumLAG60_6"; + host = "2605:e000:0:4::8:1d5"; + }; + "SpectrumGateway4" = { + name = "SpectrumGateway4"; + host = "172.88.16.1"; + }; + "SpectrumGateway6" = { + name = "SpectrumGateway6"; + host = "2605:e000:2fc0:f::1"; + }; + "RouterUSGdefault" = { + name = "RouterUSGdefault"; + host = "172.16.50.1"; + }; + "Juniper2300" = { + name = "Juniper2300"; + host = "172.16.50.12"; + }; + "Juniper2200_office" = { + name = "Juniper2200-office"; + host = "172.16.50.11"; + }; + }; + }; + + # HTTP Site Monitoring + "HTTP" = { + title = "HTTP Site Monitoring"; + menu = "HTTP Sites"; + targets = { + "Google_HTTP" = { + name = "Google HTTP"; + host = "google.com"; + probe = "http"; + }; + "IBM_HTTP" = { + name = "IBM HTTP"; + host = "ibm.com"; + probe = "http"; + }; + "Yahoo_HTTP" = { + name = "Yahoo HTTP"; + host = "yahoo.com"; + probe = "http"; + }; + "Facebook_HTTP" = { + name = "Facebook HTTP"; + host = "facebook.com"; + probe = "http"; + }; + }; + }; + + # DNS Resolution Testing + "DNSLookup" = { + title = "DNS Resolution Testing"; + menu = "DNS Resolution"; + targets = { + "Google_DNS_Lookup" = { + name = "Google DNS - google.com lookup"; + host = "8.8.8.8"; + probe = "dns"; + query = "google.com"; + }; + "Cloudflare_DNS_Lookup" = { + name = "Cloudflare DNS - google.com lookup"; + host = "1.1.1.1"; + probe = "dns"; + query = "google.com"; + }; + "Local_DNS_Lookup" = { + name = "Local DNS - google.com lookup"; + host = "::1"; + probe = "dns"; + query = "google.com"; + }; + }; + }; + }; + + # Helper function to generate blackbox modules for ICMP targets + generateICMPModules = categoryName: category: + lib.mapAttrsToList (targetName: target: + let targetWithProtocol = addProtocol target; + in { + name = "${categoryName}_${targetName}"; + prober = "icmp"; + icmp = { + preferred_ip_protocol = "ip6"; # Prefer IPv6 when available + count = 4; + }; + }) category.targets; + + # Helper function to generate blackbox modules for HTTP targets + generateHTTPModules = categoryName: category: + lib.mapAttrsToList (targetName: target: + if target ? probe && target.probe == "http" then { + name = "${categoryName}_${targetName}"; + prober = "http"; + http = { + preferred_ip_protocol = "ip6"; # Prefer IPv6 when available + valid_status_codes = [ 200 301 302 303 307 308 ]; + fail_if_ssl = false; + fail_if_not_ssl = false; + method = "GET"; + headers = { + User-Agent = "Prometheus/Blackbox Exporter"; + }; + }; + } else null) category.targets; + + # Helper function to generate blackbox modules for DNS targets + generateDNSModules = categoryName: category: + lib.mapAttrsToList (targetName: target: + if target ? probe && target.probe == "dns" then { + name = "${categoryName}_${targetName}"; + prober = "dns"; + dns = { + preferred_ip_protocol = "ip6"; # Prefer IPv6 when available + query_name = target.query; + query_type = "A"; + valid_rcodes = [ "NOERROR" ]; + }; + } else null) category.targets; + + # Generate all blackbox modules + icmpModules = lib.flatten (lib.mapAttrsToList generateICMPModules targets); + httpModules = lib.flatten (lib.mapAttrsToList generateHTTPModules targets); + dnsModules = lib.flatten (lib.mapAttrsToList generateDNSModules targets); + + # Filter out null values and combine all modules + allBlackboxModules = lib.filter (module: module != null) (icmpModules ++ httpModules ++ dnsModules); + + # Generate blackbox configuration + blackboxConfig = { + modules = { + # Simple ICMP module for testing + "icmp_v4" = { + prober = "icmp"; + icmp = { + preferred_ip_protocol = "ip4"; + }; + }; + "icmp_v6" = { + prober = "icmp"; + icmp = { + preferred_ip_protocol = "ip6"; + }; + }; + "http_2xx" = { + prober = "http"; + http = { + preferred_ip_protocol = "ip4"; + valid_status_codes = [ 200 301 302 303 307 308 ]; + }; + }; + "dns_udp_53" = { + prober = "dns"; + dns = { + preferred_ip_protocol = "ip4"; + query_name = "google.com"; + query_type = "A"; + valid_rcodes = [ "NOERROR" ]; + }; + }; + }; + }; + +in { + # Blackbox exporter configuration + services.prometheus.exporters.blackbox = { + enable = true; + port = 9115; + listenAddress = "::1"; + configFile = pkgs.writeText "blackbox.yml" (builtins.toJSON blackboxConfig); + }; + + # Export targets for use in prometheus.nix + _module.args.blackboxTargets = targets; + _module.args.wireguardTargets = flatWireguardTargets; + + # Firewall rules for blackbox exporter + networking.firewall.allowedTCPPorts = [ 9115 ]; +} \ No newline at end of file diff --git a/hp/hp4/configuration.nix b/hp/hp4/configuration.nix index ce74630..2ca95b7 100644 --- a/hp/hp4/configuration.nix +++ b/hp/hp4/configuration.nix @@ -48,6 +48,9 @@ ./athens.nix ./remote-builder.nix ./services.ssh.nix + ./smokeping.nix + ./blackbox.nix + ./pdns-recursor.nix ]; # Bootloader. @@ -116,14 +119,6 @@ networking.interfaces.enp1s0f0np0.useDHCP = false; networking.interfaces.enp1s0f1.useDHCP = false; networking.interfaces.enp1s0f1np1.useDHCP = false; - boot.kernel.sysctl."net.ipv6.conf.enp1s0f0.disable_ipv6" = true; - boot.kernel.sysctl."net.ipv6.conf.enp1s0f0np0.disable_ipv6" = true; - boot.kernel.sysctl."net.ipv6.conf.enp1s0f1.disable_ipv6" = true; - boot.kernel.sysctl."net.ipv6.conf.enp1s0f1np1.disable_ipv6" = true; - # networking.interfaces.enp1s0f0.ipv4.addresses = [{ - # address = "76.174.138.10"; - # prefixLength = 24; - # }]; # Set your time zone. time.timeZone = "America/Los_Angeles"; @@ -134,7 +129,7 @@ #ANOTHER_VARIABLE = "another-value"; }; - # Define a user account. Don't forget to set a password with ‘passwd’. + # Define a user account. Don't forget to set a password with 'passwd'. users.users.das = { isNormalUser = true; description = "das"; @@ -259,14 +254,9 @@ OOMScoreAdjust = 500; }; - services.pdns-recursor = { - enable = true; - # openFirewall = false; # Default - }; - # This value determines the NixOS release from which the default # settings for stateful data, like file locations and database versions - # on your system were taken. It‘s perfectly fine and recommended to leave + # on your system were taken. It's perfectly fine and recommended to leave # this value at the release version of the first install of this system. # Before changing this value read the documentation for this option # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). diff --git a/hp/hp4/hosts.nix b/hp/hp4/hosts.nix index b60a4f0..20e70af 100644 --- a/hp/hp4/hosts.nix +++ b/hp/hp4/hosts.nix @@ -2,6 +2,12 @@ { networking.hosts = { + # Prioritize IPv6 for localhost + "::1" = ["localhost" "hp4"]; + "127.0.0.1" = ["localhost"]; + "127.0.0.2" = ["hp4"]; + + # Other hosts "172.16.40.198" = ["hp0" "hp0eth"]; # adi's room "172.16.40.141" = ["hp0wifi"]; "172.16.40.142" = ["hp1" "hp1eth"]; diff --git a/hp/hp4/nginx.nix b/hp/hp4/nginx.nix index 9174cbe..3377ccd 100644 --- a/hp/hp4/nginx.nix +++ b/hp/hp4/nginx.nix @@ -1,3 +1,6 @@ +# +# nixos/hp/hp4/nginx.nix +# { pkgs, config, ... }: { @@ -45,6 +48,30 @@ deny all; ''; }; + + # Add smokeping to the default virtual host + locations."/smokeping/" = { + extraConfig = '' + root /var/lib; + index smokeping.fcgi; + ''; + }; + + locations."/smokeping/smokeping.fcgi" = { + extraConfig = '' + include ${pkgs.nginx}/conf/fastcgi_params; + fastcgi_pass unix:/run/fcgiwrap-smokeping.sock; + fastcgi_param SCRIPT_FILENAME /var/lib/smokeping/smokeping.fcgi; + fastcgi_param DOCUMENT_ROOT /var/lib/smokeping; + ''; + }; + + locations."/smokeping/cache/" = { + extraConfig = '' + root /var/lib; + autoindex off; + ''; + }; }; }; @@ -65,6 +92,12 @@ # port = 9113; # Default }; + # Enable fcgiwrap for smokeping + services.fcgiwrap.instances.smokeping = { + process.user = "smokeping"; + process.group = "smokeping"; + socket = { inherit (config.services.nginx) user group; }; + }; } # { # # https://nixos.wiki/wiki/Nginx diff --git a/hp/hp4/pdns-recursor.nix b/hp/hp4/pdns-recursor.nix new file mode 100644 index 0000000..e91a006 --- /dev/null +++ b/hp/hp4/pdns-recursor.nix @@ -0,0 +1,42 @@ +{ config, lib, pkgs, ... }: + +{ + # PowerDNS Recursor configuration + # This acts as a local DNS cache and forwards queries to 172.16.50.1 + services.pdns-recursor = { + enable = true; + + # Bind to localhost only for security + dns.address = [ "::1" "127.0.0.1" ]; + + # Allow queries from localhost only + dns.allowFrom = [ "127.0.0.0/8" "::1/128" ]; + + # API configuration (for monitoring) + api.address = "::1"; + api.port = 8082; + api.allowFrom = [ "127.0.0.1" "::1" ]; + + # Forward all zones to the upstream DNS server + forwardZones = { + "." = "172.16.50.1"; # Forward all queries to upstream DNS + }; + + # DNSSEC validation + dnssecValidation = "validate"; + + # Export /etc/hosts entries + exportHosts = true; + + # Serve RFC1918 reverse zones locally + serveRFC1918 = true; + }; + + # Firewall rules for pdns-recursor + networking.firewall.allowedUDPPorts = [ 53 ]; + networking.firewall.allowedTCPPorts = [ 53 8082 ]; + + # Configure system to use local pdns-recursor + networking.nameservers = [ "::1" "127.0.0.1" ]; + networking.resolvconf.useLocalResolver = true; +} \ No newline at end of file diff --git a/hp/hp4/prometheus.nix b/hp/hp4/prometheus.nix index e756933..b7827a2 100644 --- a/hp/hp4/prometheus.nix +++ b/hp/hp4/prometheus.nix @@ -1,5 +1,11 @@ -{ config, pkgs, ... }: -{ +{ config, pkgs, lib, ... }: + +let + # Blackbox exporter hostname + blackboxHost = "localhost:${toString config.services.prometheus.exporters.blackbox.port}"; + +in { + # Prometheus configuration with blackbox integration # https://wiki.nixos.org/wiki/Prometheus # https://nixos.org/manual/nixos/stable/#module-services-prometheus-exporters-configuration # https://github.com/NixOS/nixpkgs/blob/nixos-24.05/nixos/modules/services/monitoring/prometheus/default.nix @@ -7,14 +13,151 @@ services.prometheus = { enable = true; # openFirewall = true; # doesn't exist - globalConfig.scrape_interval = "10s"; # "1m" + globalConfig.scrape_interval = "10s"; # Keep node exporter at 10s scrapeConfigs = [ - { - job_name = "node"; - static_configs = [{ - targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ]; - }]; - } + { + job_name = "node"; + static_configs = [{ + targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ]; + }]; + } + { + job_name = "nginx"; + static_configs = [{ + targets = [ "localhost:9113" ]; + }]; + } + { + job_name = "blackbox_icmp_v4"; + metrics_path = "/probe"; + params = { + module = [ "icmp_v4" ]; + }; + static_configs = [ + { + targets = [ "8.8.8.8" "1.1.1.1" "142.250.190.78" ]; + labels = { + job = "blackbox"; + category = "ICMP_IPv4"; + }; + } + ]; + scrape_timeout = "10s"; + honor_labels = true; + relabel_configs = [ + { + source_labels = [ "__address__" ]; + target_label = "__param_target"; + } + { + source_labels = [ "__param_target" ]; + target_label = "instance"; + } + { + target_label = "__address__"; + replacement = blackboxHost; + } + ]; + } + { + job_name = "blackbox_icmp_v6"; + metrics_path = "/probe"; + params = { + module = [ "icmp_v6" ]; + }; + static_configs = [ + { + targets = [ "2001:4860:4860::8888" "2606:4700:4700::1111" "2607:f8b0:4007:811::200e" ]; + labels = { + job = "blackbox"; + category = "ICMP_IPv6"; + }; + } + ]; + scrape_timeout = "10s"; + honor_labels = true; + relabel_configs = [ + { + source_labels = [ "__address__" ]; + target_label = "__param_target"; + } + { + source_labels = [ "__param_target" ]; + target_label = "instance"; + } + { + target_label = "__address__"; + replacement = blackboxHost; + } + ]; + } + { + job_name = "blackbox_http"; + metrics_path = "/probe"; + params = { + module = [ "http_2xx" ]; + }; + static_configs = [ + { + targets = [ "google.com" "facebook.com" "yahoo.com" "ibm.com" ]; + labels = { + job = "blackbox"; + category = "HTTP"; + }; + } + ]; + scrape_timeout = "10s"; + honor_labels = true; + relabel_configs = [ + { + source_labels = [ "__address__" ]; + target_label = "__param_target"; + } + { + source_labels = [ "__param_target" ]; + target_label = "instance"; + } + { + target_label = "__address__"; + replacement = blackboxHost; + } + ]; + } + { + job_name = "blackbox_dns"; + metrics_path = "/probe"; + params = { + module = [ "dns_udp_53" ]; + }; + static_configs = [ + { + targets = [ "8.8.8.8" "1.1.1.1" "::1" ]; + labels = { + job = "blackbox"; + category = "DNS"; + }; + } + ]; + scrape_timeout = "10s"; + honor_labels = true; + relabel_configs = [ + { + source_labels = [ "__address__" ]; + target_label = "__param_target"; + } + { + source_labels = [ "__param_target" ]; + target_label = "instance"; + } + { + target_label = "__address__"; + replacement = blackboxHost; + } + ]; + } ]; }; + + # Firewall rules for Prometheus + networking.firewall.allowedTCPPorts = [ 9090 ]; } \ No newline at end of file diff --git a/hp/hp4/smokeping.nix b/hp/hp4/smokeping.nix new file mode 100644 index 0000000..02a8180 --- /dev/null +++ b/hp/hp4/smokeping.nix @@ -0,0 +1,570 @@ +# +# nixos/hp/hp4/smokeping.nix +# + +# Smokeping is a little redundant with blackbox.nix, but it's a good way to +# have a web interface to the data. Smokeping has it's own database, so if there is ever +# a problem with the blackbox exporter, we can still have a web interface to the data. + +# https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/smokeping.nix +# https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/monitoring/prometheus/exporters/smokeping.nix + +# https://oss.oetiker.ch/smokeping/doc/smokeping_examples.en.html +# https://oss.oetiker.ch/smokeping/probe/Curl.en.html +# https://oss.oetiker.ch/smokeping/probe/DNS.en.html + +{ config, lib, pkgs, ... }: + +let + # Define targets in a structured way + # Modern fping handles both IPv4 and IPv6 automatically + targets = { + # DNS Servers - ICMP ping testing + "DNSServers" = { + title = "DNS Server Connectivity (ICMP Ping)"; + menu = "DNS Servers"; + targets = { + "Google_DNS_IPv4" = { + name = "Google DNS IPv4"; + host = "8.8.8.8"; + }; + "Google_DNS_IPv6" = { + name = "Google DNS IPv6"; + host = "2001:4860:4860::8888"; + }; + "Cloudflare_DNS_IPv4" = { + name = "Cloudflare DNS IPv4"; + host = "1.1.1.1"; + }; + "Cloudflare_DNS_IPv6" = { + name = "Cloudflare DNS IPv6"; + host = "2606:4700:4700::1111"; + }; + "Cloudflare_DNS_Secondary_IPv4" = { + name = "Cloudflare DNS Secondary IPv4"; + host = "1.0.0.1"; + }; + "Cloudflare_DNS_Secondary_IPv6" = { + name = "Cloudflare DNS Secondary IPv6"; + host = "2606:4700:4700::1001"; + }; + }; + }; + + # Internet Connectivity + "Internet" = { + title = "Internet Connectivity Monitoring"; + menu = "Internet Connectivity"; + targets = { + "Google_IPv4" = { + name = "Google.com IPv4"; + host = "142.250.190.78"; + }; + "Google_IPv6" = { + name = "Google.com IPv6"; + host = "2607:f8b0:4007:811::200e"; + }; + "Facebook_IPv6" = { + name = "Facebook IPv6"; + host = "2a03:2880:f10d:183:face:b00c:0:25de"; + }; + "Yahoo_IPv6" = { + name = "Yahoo IPv6"; + host = "2001:4998:24:120d::1:0"; + }; + "crowncastle-ic-386848" = { + name = "crowncastle-ic-386848"; + host = "62.115.8.253"; + }; + "SidenLAX1" = { + name = "SidenLAX1"; + host = "160.72.7.68"; + }; + "SidenLAX1_Internal" = { + name = "SidenLAX1_Internal"; + host = "160.72.7.65"; + }; + "SidenLAX_dcops0_93" = { + name = "SidenLAX_dcops0_93"; + host = "160.72.7.93"; + }; + "SidenLAX_dcops1_94" = { + name = "SidenLAX_dcops1_94"; + host = "160.72.7.94"; + }; + }; + }; + + # Add more network devices and gateways + "NetworkDevices" = { + title = "Network Devices and Gateways"; + menu = "Network Devices"; + targets = { + "SpectrumLAG60_4" = { + name = "SpectrumLAG60_4"; + host = "76.167.31.29"; + }; + "SpectrumLAG60_6" = { + name = "SpectrumLAG60_6"; + host = "2605:e000:0:4::8:1d5"; + }; + "SpectrumGateway4" = { + name = "SpectrumGateway4"; + host = "172.88.16.1"; + }; + "SpectrumGateway6" = { + name = "SpectrumGateway6"; + host = "2605:e000:2fc0:f::1"; + }; + "RouterUSGdefault" = { + name = "RouterUSGdefault"; + host = "172.16.50.1"; + }; + "Juniper2300" = { + name = "Juniper2300"; + host = "172.16.50.12"; + }; + "Juniper2200_office" = { + name = "Juniper2200-office"; + host = "172.16.50.11"; + }; + }; + }; + + # Add HTTP category and targets + "HTTP" = { + title = "HTTP Site Monitoring"; + menu = "HTTP Sites"; + targets = { + "Google_HTTP" = { + name = "Google HTTP"; + host = "google.com"; + probe = "Curl"; + }; + "IBM_HTTP" = { + name = "IBM HTTP"; + host = "ibm.com"; + probe = "Curl"; + }; + "Yahoo_HTTP" = { + name = "Yahoo HTTP"; + host = "yahoo.com"; + probe = "Curl"; + }; + "Facebook_HTTP" = { + name = "Facebook HTTP"; + host = "facebook.com"; + probe = "Curl"; + }; + }; + }; + + # Add DNS lookup testing + "DNSLookup" = { + title = "DNS Resolution Testing (dig queries)"; + menu = "DNS Resolution"; + targets = { + "Google_DNS_Lookup" = { + name = "Google DNS - google.com lookup"; + host = "8.8.8.8"; + probe = "DNS"; + lookup = "google.com"; + }; + "Cloudflare_DNS_Lookup" = { + name = "Cloudflare DNS - google.com lookup"; + host = "1.1.1.1"; + probe = "DNS"; + lookup = "google.com"; + }; + "Local_DNS_Lookup" = { + name = "Local DNS - google.com lookup"; + host = "::1"; + probe = "DNS"; + lookup = "google.com"; + }; + }; + }; + }; + + # Helper function to generate smokeping target configuration + generateTargetConfig = categoryName: category: '' ++ ${categoryName} +menu = ${category.menu} +title = ${category.title} + +${lib.concatStringsSep "\n" (lib.mapAttrsToList (targetName: target: '' +++ ${targetName} +menu = ${target.name} +title = ${target.name}${lib.optionalString (target ? probe) "\nprobe = ${target.probe}"} +host = ${target.host}${lib.optionalString (target ? lookup) "\nlookup = ${target.lookup}"} +'' ) category.targets)}''; + + # Generate the complete target configuration + targetConfig = '' +probe = FPing + +menu = Top +title = Network Latency Grapher +remark = Welcome to the SmokePing website of Siden Network Operations. \ + Here you will learn all about the latency of our network. + +${lib.concatStringsSep "\n" (lib.mapAttrsToList generateTargetConfig targets)}''; + + # Generate prometheus targets from the same data structure + prometheusTargets = lib.flatten (lib.mapAttrsToList (categoryName: category: + lib.mapAttrsToList (targetName: target: + { + name = "${categoryName}_${targetName}"; + host = target.host; + }) category.targets + ) targets); + +in { + # Smokeping configuration for network monitoring + # https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/smokeping.nix + services.smokeping = { + enable = true; + webService = false; # Disable automatic nginx configuration to avoid conflicts + + # Basic configuration + owner = "Network Operations"; + ownerEmail = "ops@siden.io"; + hostName = "smokeping.localhost"; + + # Database configuration (5 minute intervals, 20 pings per step) + # Using AVERAGE as the consolidation function (MEDIAN is not supported) + databaseConfig = '' + step = 300 + pings = 20 + # consfn mrhb steps total + AVERAGE 0.5 1 1008 + AVERAGE 0.5 12 4320 + MIN 0.5 12 4320 + MAX 0.5 12 4320 + AVERAGE 0.5 144 720 + MAX 0.5 144 720 + MIN 0.5 144 720 + ''; + + # Probe configuration for both IPv4 and IPv6 + # Modern fping handles IPv6 addresses automatically + probeConfig = '' + + FPing + binary = ${config.security.wrapperDir}/fping + + + Curl + binary = ${pkgs.curl}/bin/curl + urlformat = http://%host%/ + timeout = 10 + step = 300 + extraargs = --silent + follow_redirects = yes + include_redirects = no + + + DNS + binary = ${pkgs.bind.dnsutils}/bin/dig + timeout = 15 + step = 300 + ''; + + # Target configuration generated from data structure + inherit targetConfig; + + # Alert configuration + alertConfig = '' + to = root@localhost + from = smokeping@localhost + + +someloss + type = loss + pattern = >0%,*12*,>0%,*12*,>0% + comment = Loss of connectivity + + +highloss + type = loss + pattern = >50%,*12*,>50%,*12*,>50% + comment = High loss of connectivity + + +highlatency + type = rtt + pattern = >100,*12*,>100,*12*,>100 + comment = High latency detected + ''; + + # Presentation configuration + presentationConfig = '' + + charts + menu = Charts + title = The most interesting destinations + ++ stddev + sorter = StdDev(entries=>4) + title = Top Standard Deviation + menu = Std Deviation + format = Standard Deviation %f + ++ max + sorter = Max(entries=>5) + title = Top Max Roundtrip Time + menu = by Max + format = Max Roundtrip Time %f seconds + ++ loss + sorter = Loss(entries=>5) + title = Top Packet Loss + menu = Loss + format = Packets Lost %f + ++ median + sorter = Median(entries=>5) + title = Top Median Roundtrip Time + menu = by Median + format = Median RTT %f seconds + + overview + width = 600 + height = 50 + range = 10h + + detail + width = 600 + height = 200 + unison_tolerance = 2 + "Last 3 Hours" 3h + "Last 30 Hours" 30h + "Last 10 Days" 10d + "Last 360 Days" 360d + ''; + }; + + # Prometheus smokeping prober - DISABLED: redundant with main smokeping service + # services.prometheus.exporters.smokeping = { + # enable = true; + # port = 9374; + # pingInterval = "300s"; # 5 minutes to match smokeping + # hosts = lib.flatten (lib.mapAttrsToList (categoryName: category: + # lib.mapAttrsToList (targetName: target: + # target.host + # ) category.targets + # ) targets); + # }; + + # Firewall rules for web interface + networking.firewall.allowedTCPPorts = [ 80 443 ]; + + # Ensure nginx can read cache/data for static file serving + users.users.nginx.extraGroups = [ "smokeping" ]; + + systemd.tmpfiles.rules = [ + # ... existing rules ... + "d /var/lib/smokeping/cache 0750 smokeping smokeping" + "d /var/lib/smokeping/data 0750 smokeping smokeping" + "Z /var/lib/smokeping 0750 smokeping smokeping" + ]; + + # Systemd security measures for smokeping + systemd.slices.smokeping = { + description = "Smokeping network monitoring slice"; + sliceConfig = { + MemoryHigh = "200M"; + MemoryMax = "300M"; + CPUQuota = "20%"; + TasksMax = 200; + }; + }; + + # Enhanced smokeping service configuration with security measures + # systemd-analyze security smokeping + systemd.services.smokeping = { + serviceConfig = { + # Resource limits + Slice = "smokeping.slice"; + MemoryHigh = "200M"; + MemoryMax = "300M"; + CPUQuota = "20%"; + TasksMax = 200; + + # Process limits + LimitNOFILE = 1024; + LimitNPROC = 100; + + # Security restrictions + NoNewPrivileges = true; + ProtectSystem = "strict"; + ProtectHome = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectControlGroups = true; + ProtectKernelLogs = true; + PrivateDevices = true; + RestrictRealtime = true; + # RestrictSUIDSGID = true; # Disabled - smokeping needs SUID wrapper for ping + RestrictNamespaces = true; + LockPersonality = true; + # MemoryDenyWriteExecute = true; # Disabled - interferes with DNS resolution + RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; + + # Additional security restrictions + RemoveIPC = true; # Clean up IPC objects + UMask = "0077"; # Restrict file permissions + SystemCallFilter = [ "@system-service" "~@privileged" "~@mount" "~@debug" "~@module" "~@reboot" "~@swap" "~@clock" "~@cpu-emulation" "~@obsolete" ]; # Allow raw-io for IPv6 ping + CapabilityBoundingSet = [ "CAP_NET_RAW" "CAP_NET_BIND_SERVICE" ]; # Only network capabilities needed + ProtectProc = "default"; # Allow access to process info for DNS resolution + ProcSubset = "all"; # Allow access to all process info + ProtectHostname = true; # Prevent hostname changes + ProtectClock = true; # Prevent clock changes + + # File system restrictions - allow access to dig + ReadWritePaths = [ + "/var/lib/smokeping" + "/var/log" + "/run" + ]; + ReadOnlyPaths = [ + "/etc/smokeping.conf" + "/nix/store" + "${pkgs.curl}" + "${config.services.smokeping.package}" + "${config.security.wrapperDir}" + "/etc/resolv.conf" + "/etc/hosts" + "/etc/nsswitch.conf" + "/etc/ssl" + "/etc/ca-bundle.crt" + "/etc/ssl/certs" + ]; + + # User/group restrictions + User = "smokeping"; + Group = "smokeping"; + SupplementaryGroups = [ "smokeping" ]; + + # Restart policy + Restart = "on-failure"; + RestartSec = "10s"; + + # Nice priority (lower number = higher priority) + Nice = 10; + + # Required by smokeping module + ExecStart = "${config.services.smokeping.package}/bin/smokeping --config=/etc/smokeping.conf --nodaemon"; + }; + + # Add curl package to the service environment + path = [ pkgs.curl pkgs.bind.dnsutils ]; + environment = { + # Ensure DNS resolution works + NSS_WRAPPER_PASSWD = "/etc/passwd"; + NSS_WRAPPER_GROUP = "/etc/group"; + LD_LIBRARY_PATH = "${pkgs.curl}/lib"; + }; + }; + + # Also secure the prometheus smokeping exporter - DISABLED + # systemd.services.prometheus-smokeping-exporter = { + # serviceConfig = { + # # Resource limits + # MemoryHigh = "512M"; + # MemoryMax = "1G"; + # CPUQuota = "25%"; + # + # # Security restrictions + # NoNewPrivileges = true; + # ProtectSystem = "strict"; + # ProtectHome = true; + # ProtectKernelTunables = true; + # ProtectKernelModules = true; + # ProtectControlGroups = true; + # ProtectKernelLogs = true; + # PrivateDevices = true; + # RestrictRealtime = true; + # RestrictSUIDSGID = true; + # RestrictNamespaces = true; + # LockPersonality = true; + # MemoryDenyWriteExecute = true; + # RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; + # + # # Additional security restrictions + # RemoveIPC = true; # Clean up IPC objects + # UMask = "0077"; # Restrict file permissions + # SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" "~@mount" "~@debug" "~@module" "~@reboot" "~@swap" "~@clock" "~@cpu-emulation" "~@obsolete" "~@raw-io" ]; + # CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ]; # Only binding capability needed + # ProtectProc = "invisible"; # Hide other processes + # ProcSubset = "pid"; # Only show own process info + # ProtectHostname = true; # Prevent hostname changes + # ProtectClock = true; # Prevent clock changes + # + # # File system restrictions + # ReadWritePaths = [ + # "/var/log" + # "/run" + # ]; + # ReadOnlyPaths = [ + # "/nix/store" + # ]; + # + # # Restart policy + # Restart = "on-failure"; + # RestartSec = "10s"; + # + # # Nice priority + # Nice = 15; + # }; + # }; +} + +# Available Probes in NixOS Smokeping 2.8.2: +# +# Network/Connectivity Probes: +# - FPing: Standard ping using fping binary (IPv4/IPv6) +# - FPing6: Legacy IPv6 ping (deprecated, use FPing) +# - FPingContinuous: Continuous ping monitoring +# - RemoteFPing: Ping through remote host +# - TCPPing: TCP connection testing +# - TraceroutePing: Traceroute-based ping +# +# HTTP/Web Probes: +# - Curl: HTTP/HTTPS testing using curl binary +# - EchoPingHttp: HTTP echo ping +# - EchoPingHttps: HTTPS echo ping +# - WebProxyFilter: Web proxy testing +# +# DNS Probes: +# - DNS: DNS query testing +# - AnotherDNS: Alternative DNS testing +# - EchoPingDNS: DNS echo ping +# - CiscoRTTMonDNS: Cisco DNS monitoring +# +# SSH/Telnet Probes: +# - SSH: SSH connection testing +# - AnotherSSH: Alternative SSH testing +# - TelnetIOSPing: Cisco IOS telnet ping +# - TelnetJunOSPing: Juniper telnet ping +# - OpenSSHEOSPing: OpenSSH to Cisco IOS +# - OpenSSHJunOSPing: OpenSSH to Juniper +# +# Application Probes: +# - LDAP: LDAP connection testing +# - EchoPingLDAP: LDAP echo ping +# - Radius: RADIUS authentication testing +# - TacacsPlus: TACACS+ authentication testing +# - FTPtransfer: FTP file transfer testing +# - NFSping: NFS mount testing +# - Qstat: Quake server status +# - SipSak: SIP protocol testing +# +# Network Equipment Probes: +# - CiscoRTTMonEchoICMP: Cisco ICMP echo monitoring +# - CiscoRTTMonTcpConnect: Cisco TCP connection monitoring +# - DismanPing: DISMAN-PING-MIB SNMP ping +# - IOSPing: Cisco IOS ping +# - IRTT: In-band Round Trip Time +# +# Email Probes: +# - EchoPingSmtp: SMTP echo ping +# - SendEmail: Email sending test +# +# Other Probes: +# - EchoPingChargen: Chargen echo ping +# - EchoPingDiscard: Discard echo ping +# - EchoPingIcp: ICP echo ping +# - EchoPingWhois: Whois echo ping +# - EchoPingPlugin: Plugin-based echo ping +# - passwordchecker: Password checking +# +# Note: The HTTP probe is NOT available in NixOS smokeping 2.8.2. +# Use Curl probe for HTTP/HTTPS testing instead. \ No newline at end of file diff --git a/hp/hp4/sysctl.nix b/hp/hp4/sysctl.nix index ed11dac..41da460 100644 --- a/hp/hp4/sysctl.nix +++ b/hp/hp4/sysctl.nix @@ -3,6 +3,11 @@ { # https://www.kernel.org/doc/html/latest/networking/ip-sysctl.html boot.kernel.sysctl = { + # IPv6 preference settings for localhost + "net.ipv6.conf.all.prefer_ipv6" = true; + "net.ipv6.conf.default.prefer_ipv6" = true; + "net.ipv6.conf.lo.prefer_ipv6" = true; + # detect dead connections more quickly "net.ipv4.tcp_keepalive_intvl" = 30; #net.ipv4.tcp_keepalive_intvl = 75 From 6b335280fd41c768bef3e6daa5c2f6abd2339fc0 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Sat, 5 Jul 2025 18:16:00 -0700 Subject: [PATCH 04/23] blackbox --- hp/hp4/blackbox.nix | 25 +++++++++++++++++++- hp/hp4/grafana.nix | 20 ++++++++++++++++ hp/hp4/nginx.nix | 18 ++++++++++++++ hp/hp4/pdns-recursor.nix | 51 +++++++++++++++++++++++++++++++++------- hp/hp4/prometheus.nix | 21 +++++++++++++++++ 5 files changed, 125 insertions(+), 10 deletions(-) diff --git a/hp/hp4/blackbox.nix b/hp/hp4/blackbox.nix index f5869f0..84ddeb6 100644 --- a/hp/hp4/blackbox.nix +++ b/hp/hp4/blackbox.nix @@ -318,13 +318,36 @@ let in { # Blackbox exporter configuration + # systemctl status prometheus-blackbox-exporter + # journalctl -u prometheus-blackbox-exporter -f -n 20 services.prometheus.exporters.blackbox = { enable = true; port = 9115; - listenAddress = "::1"; + listenAddress = "127.0.0.1"; configFile = pkgs.writeText "blackbox.yml" (builtins.toJSON blackboxConfig); }; + # Systemd service configuration for blackbox exporter with memory limits + systemd.services.prometheus-blackbox-exporter = { + serviceConfig = { + # Resource limits + MemoryMax = "300M"; + MemoryHigh = "280M"; + CPUQuota = "25%"; + TasksMax = 100; + + # Process limits + LimitNOFILE = 1024; + LimitNPROC = 50; + + # Environment variable for Go memory limit (260MB = ~90% of 300MB) + Environment = [ "GOMEMLIMIT=260MiB" ]; + + # Nice priority + Nice = 10; + }; + }; + # Export targets for use in prometheus.nix _module.args.blackboxTargets = targets; _module.args.wireguardTargets = flatWireguardTargets; diff --git a/hp/hp4/grafana.nix b/hp/hp4/grafana.nix index cf1b428..e9af81d 100644 --- a/hp/hp4/grafana.nix +++ b/hp/hp4/grafana.nix @@ -4,6 +4,7 @@ # https://search.nixos.org/options?query=services.grafana # https://xeiaso.net/blog/prometheus-grafana-loki-nixos-2020-11-20/ # https://grafana.com/grafana/dashboards/1860-node-exporter-full/ + # https://grafana.com/grafana/dashboards/7587-prometheus-blackbox-exporter/ services.grafana = { enable = true; #openFirewall = true; # this doesn't exist @@ -19,6 +20,25 @@ serve_from_sub_path = true; enable_gzip = true; }; + + # Security settings - set persistent admin password + security = { + admin_user = "admin"; + admin_password = "adin"; # Change this to your desired password + admin_email = "admin@localhost"; + # Disable initial admin creation to prevent password resets + disable_initial_admin_creation = false; + }; + + # User settings + users = { + # Allow sign up (optional - set to false for more security) + allow_sign_up = false; + # Auto assign new users to main organization + auto_assign_org = true; + # Default role for new users + auto_assign_org_role = "Viewer"; + }; }; }; } \ No newline at end of file diff --git a/hp/hp4/nginx.nix b/hp/hp4/nginx.nix index 3377ccd..efb422b 100644 --- a/hp/hp4/nginx.nix +++ b/hp/hp4/nginx.nix @@ -98,6 +98,24 @@ process.group = "smokeping"; socket = { inherit (config.services.nginx) user group; }; }; + + # Systemd service configuration for nginx with resource limits + systemd.services.nginx = { + serviceConfig = { + # Resource limits - moderate for web server + MemoryMax = "300M"; + MemoryHigh = "250M"; + CPUQuota = "20%"; + TasksMax = 200; + + # Process limits + LimitNOFILE = 65536; + LimitNPROC = 100; + + # Nice priority + Nice = 10; + }; + }; } # { # # https://nixos.wiki/wiki/Nginx diff --git a/hp/hp4/pdns-recursor.nix b/hp/hp4/pdns-recursor.nix index e91a006..b25fae6 100644 --- a/hp/hp4/pdns-recursor.nix +++ b/hp/hp4/pdns-recursor.nix @@ -1,8 +1,10 @@ { config, lib, pkgs, ... }: { - # PowerDNS Recursor configuration + # PowerDNS Recursor # This acts as a local DNS cache and forwards queries to 172.16.50.1 + # sudo lsof -i :53 + # systemctl status pdns-recursor services.pdns-recursor = { enable = true; @@ -10,21 +12,25 @@ dns.address = [ "::1" "127.0.0.1" ]; # Allow queries from localhost only - dns.allowFrom = [ "127.0.0.0/8" "::1/128" ]; + dns.allowFrom = [ "::1/128" "127.0.0.0/8" ]; # API configuration (for monitoring) api.address = "::1"; api.port = 8082; api.allowFrom = [ "127.0.0.1" "::1" ]; - # Forward all zones to the upstream DNS server - forwardZones = { - "." = "172.16.50.1"; # Forward all queries to upstream DNS + # Configure DNS settings for proper DNSSEC validation + settings = { + # Enable DNSSEC validation + dnssec = "validate"; + # Set query local address to enable IPv6 for outgoing queries + query-local-address = "::"; + # Disable security polling to avoid external queries + security-poll-suffix = ""; + # Configure forward zones for specific domains if needed + # forward-zones = "example.com=172.16.50.1"; }; - # DNSSEC validation - dnssecValidation = "validate"; - # Export /etc/hosts entries exportHosts = true; @@ -32,11 +38,38 @@ serveRFC1918 = true; }; + # Systemd service configuration for pdns-recursor with resource limits + systemd.services.pdns-recursor = { + serviceConfig = { + # Resource limits - conservative for DNS service + MemoryMax = "100M"; + MemoryHigh = "90M"; + CPUQuota = "15%"; + TasksMax = 50; + + # Process limits + LimitNPROC = 100; + + # Nice priority + Nice = 15; + }; + }; + # Firewall rules for pdns-recursor networking.firewall.allowedUDPPorts = [ 53 ]; networking.firewall.allowedTCPPorts = [ 53 8082 ]; # Configure system to use local pdns-recursor - networking.nameservers = [ "::1" "127.0.0.1" ]; + #networking.nameservers = [ "::1" "127.0.0.1" ]; + networking.nameservers = [ "172.16.50.1" ]; networking.resolvconf.useLocalResolver = true; + + environment.etc."resolv.conf".text = '' + # pdns + nameserver ::1 + nameserver 127.0.0.1 + # emergency cloudflare + nameserver 2606:4700:4700::1111 + nameserver 1.1.1.1 + ''; } \ No newline at end of file diff --git a/hp/hp4/prometheus.nix b/hp/hp4/prometheus.nix index b7827a2..bb4e6ec 100644 --- a/hp/hp4/prometheus.nix +++ b/hp/hp4/prometheus.nix @@ -158,6 +158,27 @@ in { ]; }; + # Systemd service configuration for Prometheus with security restrictions + systemd.services.prometheus = { + serviceConfig = { + # Resource limits - generous for time series storage + MemoryMax = "10G"; + MemoryHigh = "9.5G"; + CPUQuota = "50%"; + TasksMax = 500; + + # Process limits + LimitNOFILE = 65536; + LimitNPROC = 200; + + # Environment variable for Go memory limit (9GB = ~90% of 10GB limit) + Environment = [ "GOMEMLIMIT=9GiB" ]; + + # Nice priority + Nice = 5; + }; + }; + # Firewall rules for Prometheus networking.firewall.allowedTCPPorts = [ 9090 ]; } \ No newline at end of file From b5faa1edb05b9aedc02c1f52feec61520c36567d Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Fri, 25 Jul 2025 14:44:27 -0700 Subject: [PATCH 05/23] 2025_07_25 --- desktop/l/configuration.nix | 30 +++- desktop/l/flake.lock | 96 +++++----- desktop/l/home.nix | 5 +- desktop/l/hyprland.nix | 7 - desktop/l/systemPackages.nix | 7 + hp/hp1/Makefile | 5 +- hp/hp1/configuration.nix | 15 +- hp/hp1/firewall-test-phase1.nix | 166 ++++++++++++++++++ hp/hp1/flake.nix | 7 +- hp/hp1/systemd.services.ethtool-enp3s0f1.nix | 6 +- hp/hp1/systemd.services.ethtool-enp4s0f0.nix | 14 ++ ... => systemd.services.ethtool-enp4s0f1.nix} | 6 +- hp/hp4/configuration.nix | 1 + hp/hp4/grafana.nix | 1 + hp/hp4/home-assistant.nix | 52 ++++++ 15 files changed, 339 insertions(+), 79 deletions(-) create mode 100644 hp/hp1/firewall-test-phase1.nix create mode 100644 hp/hp1/systemd.services.ethtool-enp4s0f0.nix rename hp/hp1/{systemd.services.ethtool-enp3s0f0.nix => systemd.services.ethtool-enp4s0f1.nix} (73%) create mode 100644 hp/hp4/home-assistant.nix diff --git a/desktop/l/configuration.nix b/desktop/l/configuration.nix index 07bdba7..3e2853d 100644 --- a/desktop/l/configuration.nix +++ b/desktop/l/configuration.nix @@ -40,7 +40,7 @@ ./docker-daemon.nix #./smokeping.nix ./distributed-builds.nix - ./hyprland.nix + #./hyprland.nix ]; boot = { @@ -147,6 +147,16 @@ wireplumber.enable = true; }; + # Enable PipeWire screen capture + environment.sessionVariables = { + TERM = "xterm-256color"; + # PipeWire screen capture + PIPEWIRE_SCREEN_CAPTURE = "1"; + # Force Flameshot to use Wayland + QT_QPA_PLATFORM = "wayland"; + #MY_VARIABLE = "my-value"; + }; + services.openssh.enable = true; programs.ssh.extraConfig = '' Host hp4.home @@ -173,6 +183,7 @@ # https://nixos.wiki/wiki/Printing services.printing.enable = true; + # flameshot now in home.nix # https://wiki.nixos.org/wiki/Flameshot # services.flameshot = { # enable = true; @@ -188,15 +199,15 @@ services.clickhouse.enable = false; # environment.variables defined in hardware-graphics.nix - environment.sessionVariables = { - TERM = "xterm-256color"; - #MY_VARIABLE = "my-value"; - }; + # environment.sessionVariables = { + # TERM = "xterm-256color"; + # #MY_VARIABLE = "my-value"; + # }; users.users.das = { isNormalUser = true; description = "das"; - extraGroups = [ "wheel" "networkmanager" "kvm" "libvirtd" "docker" "video" ]; + extraGroups = [ "wheel" "networkmanager" "kvm" "libvirtd" "docker" "video" "pipewire" ]; packages = with pkgs; [ ]; # https://nixos.wiki/wiki/SSH_public_key_authentication @@ -247,8 +258,11 @@ xdg.portal = { enable = true; - extraPortals = with pkgs; [ xdg-desktop-portal-gtk ]; - config.common.default = "gtk"; + extraPortals = with pkgs; [ + xdg-desktop-portal-gnome + ]; + config.common.default = "gnome"; + config.gnome.default = "gnome"; }; services.dbus.packages = with pkgs; [ diff --git a/desktop/l/flake.lock b/desktop/l/flake.lock index dc661a5..fccd76e 100644 --- a/desktop/l/flake.lock +++ b/desktop/l/flake.lock @@ -20,11 +20,11 @@ ] }, "locked": { - "lastModified": 1747864449, - "narHash": "sha256-PIjVAWghZhr3L0EFM2UObhX84UQxIACbON0IC0zzSKA=", + "lastModified": 1751740947, + "narHash": "sha256-35040CHH7P3JGmhGVfEb2oJHL/A5mI2IXumhkxrBnao=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "389372c5f4dc1ac0e7645ed29a35fd6d71672ef5", + "rev": "dfc1db15a08c4cd234288f66e1199c653495301f", "type": "github" }, "original": { @@ -78,11 +78,11 @@ ] }, "locked": { - "lastModified": 1749160002, - "narHash": "sha256-IM3xKjsKxhu7Y1WdgTltrLKiOJS8nW7D4SUDEMNr7CI=", + "lastModified": 1752338520, + "narHash": "sha256-O1p5BwTwAqZ6sDrCxCxlZFaP/Jx4t1W8+ms9USyEcPQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "68cc9eeb3875ae9682c04629f20738e1e79d72aa", + "rev": "ae62fd8ad8347e6bb5b615057f39f33d595a1c47", "type": "github" }, "original": { @@ -107,11 +107,11 @@ ] }, "locked": { - "lastModified": 1745948457, - "narHash": "sha256-lzTV10FJTCGNtMdgW5YAhCAqezeAzKOd/97HbQK8GTU=", + "lastModified": 1749155331, + "narHash": "sha256-XR9fsI0zwLiFWfqi/pdS/VD+YNorKb3XIykgTg4l1nA=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "ac903e80b33ba6a88df83d02232483d99f327573", + "rev": "45fcc10b4c282746d93ec406a740c43b48b4ef80", "type": "github" }, "original": { @@ -136,11 +136,11 @@ ] }, "locked": { - "lastModified": 1745015490, - "narHash": "sha256-apEJ9zoSzmslhJ2vOKFcXTMZLUFYzh1ghfB6Rbw3Low=", + "lastModified": 1751808145, + "narHash": "sha256-OXgL0XaKMmfX2rRQkt9SkJw+QNfv0jExlySt1D6O72g=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "60754910946b4e2dc1377b967b7156cb989c5873", + "rev": "b841473a0bd4a1a74a0b64f1ec2ab199035c349f", "type": "github" }, "original": { @@ -165,11 +165,11 @@ "xdph": "xdph" }, "locked": { - "lastModified": 1749155341, - "narHash": "sha256-KE7qwOLzIsPFnXKh4Z72NwAzP8ZdRxxQKthLGJ30YHM=", + "lastModified": 1752337367, + "narHash": "sha256-kEumflYEdQSrZZQEr7kik2sBfFohEx0TsJB1rBVAQy4=", "owner": "hyprwm", "repo": "Hyprland", - "rev": "fb7548cb41d82f12db2d51b50af29abe4704a1a4", + "rev": "d0f58baf296a2cdd5df0f82212fe17dfbef8438e", "type": "github" }, "original": { @@ -195,11 +195,11 @@ ] }, "locked": { - "lastModified": 1748526041, - "narHash": "sha256-QyUACXhQJ2+K0YxwEuAfpyCXqbdCCHj1jNAWJy+vUxw=", + "lastModified": 1752254688, + "narHash": "sha256-XJJ+frO4NOxVkoSGc1Mag8ESumzx2FmVRspOgFlMqF8=", "owner": "hyprwm", "repo": "hyprland-plugins", - "rev": "2eee96fe52fa0923c0aae647eb7901b5b51df3db", + "rev": "d723e5b153b7990d36e62a425bda3768c41dd9eb", "type": "github" }, "original": { @@ -220,11 +220,11 @@ ] }, "locked": { - "lastModified": 1743714874, - "narHash": "sha256-yt8F7NhMFCFHUHy/lNjH/pjZyIDFNk52Q4tivQ31WFo=", + "lastModified": 1749046714, + "narHash": "sha256-kymV5FMnddYGI+UjwIw8ceDjdeg7ToDVjbHCvUlhn14=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "3a5c2bda1c1a4e55cc1330c782547695a93f05b2", + "rev": "613878cb6f459c5e323aaafe1e6f388ac8a36330", "type": "github" }, "original": { @@ -252,11 +252,11 @@ ] }, "locked": { - "lastModified": 1737634706, - "narHash": "sha256-nGCibkfsXz7ARx5R+SnisRtMq21IQIhazp6viBU8I/A=", + "lastModified": 1749154592, + "narHash": "sha256-DO7z5CeT/ddSGDEnK9mAXm1qlGL47L3VAHLlLXoCjhE=", "owner": "hyprwm", "repo": "hyprland-qt-support", - "rev": "8810df502cdee755993cb803eba7b23f189db795", + "rev": "4c8053c3c888138a30c3a6c45c2e45f5484f2074", "type": "github" }, "original": { @@ -288,11 +288,11 @@ ] }, "locked": { - "lastModified": 1745951494, - "narHash": "sha256-2dModE32doiyQMmd6EDAQeZnz+5LOs6KXyE0qX76WIg=", + "lastModified": 1750371812, + "narHash": "sha256-D868K1dVEACw17elVxRgXC6hOxY+54wIEjURztDWLk8=", "owner": "hyprwm", "repo": "hyprland-qtutils", - "rev": "4be1d324faf8d6e82c2be9f8510d299984dfdd2e", + "rev": "b13c7481e37856f322177010bdf75fccacd1adc8", "type": "github" }, "original": { @@ -317,11 +317,11 @@ ] }, "locked": { - "lastModified": 1747484975, - "narHash": "sha256-+LAQ81HBwG0lwshHlWe0kfWg4KcChIPpnwtnwqmnoEU=", + "lastModified": 1750371198, + "narHash": "sha256-/iuJ1paQOBoSLqHflRNNGyroqfF/yvPNurxzcCT0cAE=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "163c83b3db48a17c113729c220a60b94596c9291", + "rev": "cee01452bca58d6cadb3224e21e370de8bc20f0b", "type": "github" }, "original": { @@ -342,11 +342,11 @@ ] }, "locked": { - "lastModified": 1746635225, - "narHash": "sha256-W9G9bb0zRYDBRseHbVez0J8qVpD5QbizX67H/vsudhM=", + "lastModified": 1751888065, + "narHash": "sha256-F2SV9WGqgtRsXIdUrl3sRe0wXlQD+kRRZcSfbepjPJY=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "674ea57373f08b7609ce93baff131117a0dfe70d", + "rev": "a8229739cf36d159001cfc203871917b83fdf917", "type": "github" }, "original": { @@ -367,11 +367,11 @@ ] }, "locked": { - "lastModified": 1747584298, - "narHash": "sha256-PH9qZqWLHvSBQiUnA0NzAyQA3tu2no2z8kz0ZeHWj4w=", + "lastModified": 1751881472, + "narHash": "sha256-meB0SnXbwIe2trD041MLKEv6R7NZ759QwBcVIhlSBfE=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "e511882b9c2e1d7a75d45d8fddd2160daeafcbc3", + "rev": "8fb426b3e5452fd9169453fd6c10f8c14ca37120", "type": "github" }, "original": { @@ -382,11 +382,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1748460289, - "narHash": "sha256-7doLyJBzCllvqX4gszYtmZUToxKvMUrg45EUWaUYmBg=", + "lastModified": 1751792365, + "narHash": "sha256-J1kI6oAj25IG4EdVlg2hQz8NZTBNYvIS0l4wpr9KcUo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", + "rev": "1fd8bada0b6117e6c7eb54aad5813023eed37ccb", "type": "github" }, "original": { @@ -398,11 +398,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1748929857, - "narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=", + "lastModified": 1751984180, + "narHash": "sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X+xgOL0=", "owner": "nixos", "repo": "nixpkgs", - "rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4", + "rev": "9807714d6944a957c2e036f84b0ff8caf9930bc0", "type": "github" }, "original": { @@ -422,11 +422,11 @@ ] }, "locked": { - "lastModified": 1747372754, - "narHash": "sha256-2Y53NGIX2vxfie1rOW0Qb86vjRZ7ngizoo+bnXU9D9k=", + "lastModified": 1750779888, + "narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46", + "rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d", "type": "github" }, "original": { @@ -486,11 +486,11 @@ ] }, "locked": { - "lastModified": 1745871725, - "narHash": "sha256-M24SNc2flblWGXFkGQfqSlEOzAGZnMc9QG3GH4K/KbE=", + "lastModified": 1751300244, + "narHash": "sha256-PFuv1TZVYvQhha0ac53E3YgdtmLShrN0t4T6xqHl0jE=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "76bbf1a6b1378e4ab5230bad00ad04bc287c969e", + "rev": "6115f3fdcb2c1a57b4a80a69f3c797e47607b90a", "type": "github" }, "original": { diff --git a/desktop/l/home.nix b/desktop/l/home.nix index 6002475..305488f 100644 --- a/desktop/l/home.nix +++ b/desktop/l/home.nix @@ -611,8 +611,6 @@ # Screenshots/Screen Recording # https://wiki.nixos.org/wiki/Flameshot - flameshot - #(flameshot.override { enableWlrSupport = true; }) grim # screenshot functionality slurp # screenshot functionality simplescreenrecorder @@ -684,6 +682,9 @@ # v4l2-ctl --list-devices v4l-utils libsForQt5.kdenlive + + # Screenshot tool with Wayland support + (flameshot.override { enableWlrSupport = true; }) ]; # vscode diff --git a/desktop/l/hyprland.nix b/desktop/l/hyprland.nix index c4970d4..d8b1f7d 100644 --- a/desktop/l/hyprland.nix +++ b/desktop/l/hyprland.nix @@ -5,11 +5,4 @@ enable = true; xwayland.enable = true; }; - - # Enable XDG portal for Wayland - xdg.portal = { - enable = true; - extraPortals = with pkgs; [ xdg-desktop-portal-gtk ]; - config.common.default = "gtk"; - }; } \ No newline at end of file diff --git a/desktop/l/systemPackages.nix b/desktop/l/systemPackages.nix index c9fa23e..a652645 100644 --- a/desktop/l/systemPackages.nix +++ b/desktop/l/systemPackages.nix @@ -36,6 +36,13 @@ wayland-utils wl-clipboard + # Screen capture and PipeWire debugging + grim + slurp + wf-recorder + pipewire + xdg-desktop-portal-gnome + xscreensaver clinfo diff --git a/hp/hp1/Makefile b/hp/hp1/Makefile index 977cc7c..e93ebf4 100644 --- a/hp/hp1/Makefile +++ b/hp/hp1/Makefile @@ -22,7 +22,10 @@ rebuild: #sudo nixos-rebuild switch #sudo nix-channel --update; sudo nixos-rebuild switch --flake . - sudo systemctl restart ffmpeg-stream + #sudo systemctl restart ffmpeg-stream + +upgrade: + nixos-rebuild boot --flake . --upgrade rebuild_trace: sudo nixos-rebuild switch --show-trace --flake . diff --git a/hp/hp1/configuration.nix b/hp/hp1/configuration.nix index 4fe5180..8148006 100644 --- a/hp/hp1/configuration.nix +++ b/hp/hp1/configuration.nix @@ -29,14 +29,15 @@ ./nodeExporter.nix ./prometheus.nix ./grafana.nix - ./docker-daemon.nix + #./docker-daemon.nix #./k8s_master.nix #./k8s_node.nix - ./k3s_master.nix + #./k3s_master.nix #./k3s_node.nix - ./systemd.services.ethtool-enp3s0f0.nix - ./systemd.services.ethtool-enp3s0f1.nix - ./ffmpeg_systemd_service.nix + ./systemd.services.ethtool-enp4s0f0.nix + ./systemd.services.ethtool-enp4s0f1.nix + #./ffmpeg_systemd_service.nix + #./firewall-test-phase1.nix ]; # https://nixos.wiki/wiki/Kubernetes#reset_to_a_clean_state @@ -105,6 +106,10 @@ # https://nlewo.github.io/nixos-manual-sphinx/configuration/ipv4-config.xml.html networking.hostName = "hp1"; + # Disable DHCP on specific interfaces + networking.interfaces.enp4s0f0.useDHCP = false; + networking.interfaces.enp4s0f1.useDHCP = false; + services.lldpd.enable = true; # Configure network proxy if necessary diff --git a/hp/hp1/firewall-test-phase1.nix b/hp/hp1/firewall-test-phase1.nix new file mode 100644 index 0000000..a85c43f --- /dev/null +++ b/hp/hp1/firewall-test-phase1.nix @@ -0,0 +1,166 @@ +# +# https://gitlab.com/sidenio/nix/data_center/lax/dcops_combined/firewall-test-phase1.nix +# +# Phase 1 Setup Script Generator for Firewall Testing +# This generates a bash script that sets up network namespaces for testing +# + +{ config, lib, pkgs, ... }: + +let + # Import network data from the dcops configuration + networkData = import /home/das/Downloads/siden/nix/data_center/lax/dcops_combined/network-data.nix; + + # Helper function to extract IP address from CIDR notation + extractIP = cidr: lib.head (lib.splitString "/" cidr); + + # Helper function to extract network prefix from CIDR notation + extractPrefix = cidr: lib.last (lib.splitString "/" cidr); + + # Get bond0 VRRP IP for outside interface + bond0VrrpIP = extractIP networkData.bondConfig.vrrp_ip; + + # Generate the setup script + setupScript = pkgs.writeScriptBin "firewall-test-phase1-setup" '' + #!/bin/bash + # + # Firewall Test Phase 1 Setup Script + # Generated by Nix from firewall-test-phase1.nix + # + # This script sets up network namespaces for firewall testing + # + + set -e + + echo "Starting Firewall Test Phase 1 Setup..." + echo "======================================" + + # Array to track created namespaces + declare -a namespaces=() + + # Test node network interface configuration + OUTSIDE_NIC="enp4s0f0" + INSIDE_NIC="enp4s0f1" + + # Test node IP addresses + OUTSIDE_IP="160.72.7.66/27" # Test node on outside network + INSIDE_IP_SUFFIX=".50" # Test node IP suffix for VLANs + + echo "Configuring outside interface..." + echo "================================" + + # Setup outside interface (bond0) + namespace="outside_host" + namespaces+=("$namespace") + + echo "Creating namespace: net_$namespace" + ip netns add net_"$namespace" + + echo "Moving $OUTSIDE_NIC to namespace net_$namespace" + ip link set dev "$OUTSIDE_NIC" netns net_"$namespace" + + echo "Configuring IP address: $OUTSIDE_IP" + ip netns exec net_"$namespace" ip address add $OUTSIDE_IP dev "$OUTSIDE_NIC" + + echo "Bringing up interface" + ip netns exec net_"$namespace" ip link set dev "$OUTSIDE_NIC" up + + echo "Adding default route via bond0 VRRP IP: $bond0VrrpIP" + ip netns exec net_"$namespace" ip route add default via $bond0VrrpIP + + echo "Testing connectivity to default gateway..." + ip netns exec net_"$namespace" ping -c 3 -w 5 $bond0VrrpIP || echo "Warning: Ping to gateway failed" + + echo "" + echo "Outside interface configuration:" + ip netns exec net_"$namespace" ip link show + echo "" + ip netns exec net_"$namespace" ip addr show + echo "" + ip netns exec net_"$namespace" ip route show + echo "" + + echo "Configuring VLAN interfaces..." + echo "=============================" + + ${lib.concatMapStringsSep "\n" (vlanName: vlanConfig: '' + # Setup ${vlanName} interface + namespace="${vlanName}" + namespaces+=("$namespace") + vlan_id="${toString vlanConfig.id}" + vlan_dev="$INSIDE_NIC" + + echo "Creating namespace: net_$namespace" + ip netns add net_"$namespace" + + echo "Creating VLAN interface: $vlan_dev.$vlan_id" + ip link add link "$vlan_dev" name "$vlan_dev.$vlan_id" type vlan id "$vlan_id" + + echo "Moving VLAN interface to namespace net_$namespace" + ip link set dev "$vlan_dev.$vlan_id" netns net_"$namespace" + + # Calculate test node IP for this VLAN + vlan_vrrp_ip="${extractIP vlanConfig.vrrp_ip}" + vlan_network="${lib.head (lib.splitString "/" vlanConfig.vrrp_ip)}" + vlan_prefix="${lib.last (lib.splitString "/" vlanConfig.vrrp_ip)}" + + # Extract first 3 octets and add .50 suffix + vlan_base_ip="${lib.head (lib.splitString "." vlan_network)}.${lib.elemAt (lib.splitString "." vlan_network) 1}.${lib.elemAt (lib.splitString "." vlan_network) 2}$INSIDE_IP_SUFFIX/$vlan_prefix" + + echo "Configuring IP address: $vlan_base_ip" + ip netns exec net_"$namespace" ip address add $vlan_base_ip dev "$vlan_dev.$vlan_id" + + echo "Bringing up VLAN interface" + ip netns exec net_"$namespace" ip link set dev "$vlan_dev.$vlan_id" up + + echo "Adding default route via VLAN VRRP IP: $vlan_vrrp_ip" + ip netns exec net_"$namespace" ip route add default via $vlan_vrrp_ip + + echo "Testing connectivity to VLAN gateway..." + ip netns exec net_"$namespace" ping -c 3 -w 5 $vlan_vrrp_ip || echo "Warning: Ping to VLAN gateway failed" + + echo "" + echo "${vlanName} interface configuration:" + ip netns exec net_"$namespace" ip link show + echo "" + ip netns exec net_"$namespace" ip addr show + echo "" + ip netns exec net_"$namespace" ip route show + echo "" + '') (lib.mapAttrsToList (name: value: { inherit name; value = value; }) networkData.vlanConfigs)} + + echo "Setup complete!" + echo "===============" + echo "" + echo "Created network namespaces:" + echo "===========================" + find /run/netns/ -type l 2>/dev/null || echo "No network namespaces found" + echo "" + echo "Network namespace count: $(find /run/netns/ -type l 2>/dev/null | wc -l || echo 0)" + echo "" + + echo "Routing summary for all namespaces:" + echo "===================================" + for ns in "''${namespaces[@]}"; do + echo "" + echo "--- net_$ns ---" + ip netns exec net_"$ns" ip route show || echo "Failed to show routes for net_$ns" + done + + echo "" + echo "Phase 1 setup complete. Ready for Phase 2 (allow all) testing." + echo "" + echo "To clean up all namespaces, run:" + echo "for ns in \"''${namespaces[@]}\"; do ip netns delete net_\$ns; done" + echo "" + ''; + +in { + # Create the setup script + environment.systemPackages = [ setupScript ]; + + # Make the script executable + system.activationScripts.firewall-test-setup = '' + chmod +x ${setupScript}/bin/firewall-test-phase1-setup + ''; +} \ No newline at end of file diff --git a/hp/hp1/flake.nix b/hp/hp1/flake.nix index bee279a..fda6979 100644 --- a/hp/hp1/flake.nix +++ b/hp/hp1/flake.nix @@ -3,11 +3,14 @@ # https://nix.dev/manual/nix/2.24/command-ref/new-cli/nix3-flake.html#flake-inputs inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; + #nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; # https://nixos-and-flakes.thiscute.world/nixos-with-flakes/start-using-home-manager home-manager = { - url = "github:nix-community/home-manager/release-24.11"; + #rl = "github:nix-community/home-manager/release-24.11"; + #url = "github:nix-community/home-manager"; + url = "github:nix-community/home-manager/release-25.05"; # The `follows` keyword in inputs is used for inheritance. # Here, `inputs.nixpkgs` of home-manager is kept consistent with # the `inputs.nixpkgs` of the current flake, diff --git a/hp/hp1/systemd.services.ethtool-enp3s0f1.nix b/hp/hp1/systemd.services.ethtool-enp3s0f1.nix index b4b12e2..1ae882d 100644 --- a/hp/hp1/systemd.services.ethtool-enp3s0f1.nix +++ b/hp/hp1/systemd.services.ethtool-enp3s0f1.nix @@ -1,11 +1,11 @@ { pkgs, ... }: { - systemd.services.ethtool-enp3s0f1 = { - description = "ethtool-enp3s0f1"; + systemd.services.ethtool-enp4s0f1 = { + description = "ethtool-enp4s0f1"; serviceConfig = { Type = "oneshot"; User = "root"; - ExecStart = "${pkgs.ethtool}/bin/ethtool --set-ring enp3s0f1 rx 4096 tx 4096"; + ExecStart = "${pkgs.ethtool}/bin/ethtool --set-ring enp4s0f1 rx 4096 tx 4096"; }; # wantedBy = [ "multi-user.target" ]; # https://systemd.io/NETWORK_ONLINE/ diff --git a/hp/hp1/systemd.services.ethtool-enp4s0f0.nix b/hp/hp1/systemd.services.ethtool-enp4s0f0.nix new file mode 100644 index 0000000..215d965 --- /dev/null +++ b/hp/hp1/systemd.services.ethtool-enp4s0f0.nix @@ -0,0 +1,14 @@ +{ pkgs, ... }: +{ + systemd.services.ethtool-enp4s0f0 = { + description = "ethtool-enp4s0f0"; + serviceConfig = { + Type = "oneshot"; + User = "root"; + ExecStart = "${pkgs.ethtool}/bin/ethtool --set-ring enp4s0f0 rx 4096 tx 4096"; + }; + # wantedBy = [ "multi-user.target" ]; + # https://systemd.io/NETWORK_ONLINE/ + wantedBy = [ "network-pre.target" ]; + }; +} \ No newline at end of file diff --git a/hp/hp1/systemd.services.ethtool-enp3s0f0.nix b/hp/hp1/systemd.services.ethtool-enp4s0f1.nix similarity index 73% rename from hp/hp1/systemd.services.ethtool-enp3s0f0.nix rename to hp/hp1/systemd.services.ethtool-enp4s0f1.nix index 593654e..b4b12e2 100644 --- a/hp/hp1/systemd.services.ethtool-enp3s0f0.nix +++ b/hp/hp1/systemd.services.ethtool-enp4s0f1.nix @@ -1,11 +1,11 @@ { pkgs, ... }: { - systemd.services.ethtool-enp3s0f0 = { - description = "ethtool-enp3s0f0"; + systemd.services.ethtool-enp3s0f1 = { + description = "ethtool-enp3s0f1"; serviceConfig = { Type = "oneshot"; User = "root"; - ExecStart = "${pkgs.ethtool}/bin/ethtool --set-ring enp3s0f0 rx 4096 tx 4096"; + ExecStart = "${pkgs.ethtool}/bin/ethtool --set-ring enp3s0f1 rx 4096 tx 4096"; }; # wantedBy = [ "multi-user.target" ]; # https://systemd.io/NETWORK_ONLINE/ diff --git a/hp/hp4/configuration.nix b/hp/hp4/configuration.nix index 2ca95b7..481396b 100644 --- a/hp/hp4/configuration.nix +++ b/hp/hp4/configuration.nix @@ -51,6 +51,7 @@ ./smokeping.nix ./blackbox.nix ./pdns-recursor.nix + ./home-assistant.nix ]; # Bootloader. diff --git a/hp/hp4/grafana.nix b/hp/hp4/grafana.nix index e9af81d..1bb0efa 100644 --- a/hp/hp4/grafana.nix +++ b/hp/hp4/grafana.nix @@ -5,6 +5,7 @@ # https://xeiaso.net/blog/prometheus-grafana-loki-nixos-2020-11-20/ # https://grafana.com/grafana/dashboards/1860-node-exporter-full/ # https://grafana.com/grafana/dashboards/7587-prometheus-blackbox-exporter/ + # https://grafana.com/grafana/dashboards/14928-prometheus-blackbox-exporter/ services.grafana = { enable = true; #openFirewall = true; # this doesn't exist diff --git a/hp/hp4/home-assistant.nix b/hp/hp4/home-assistant.nix new file mode 100644 index 0000000..02177f0 --- /dev/null +++ b/hp/hp4/home-assistant.nix @@ -0,0 +1,52 @@ +# +# home-assistant.nix +# +# https://nixos.wiki/wiki/Home_Assistant +# https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/home-assistant/default.nix +# https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/home-assistant/component-packages.nix +# +{ config, pkgs, ... }: +{ + services.home-assistant = { + enable = true; + + package = (pkgs.home-assistant.override { + extraPackages = py: with py; [ psycopg2 ]; + }).overrideAttrs (oldAttrs: { + doInstallCheck = false; + }); + + extraComponents = [ + # Components required to complete the onboarding + "esphome" + "met" + "radio_browser" + "tuya" + "wemo" + ]; + + configDir = /var/lib/hass; + config = { + # Includes dependencies for a basic setup + # https://www.home-assistant.io/integrations/default_config/ + default_config = {}; + recorder.db_url = "postgresql://@/hass"; + }; + }; + + # https://nixos.wiki/wiki/Home_Assistant#Using_PostgreSQL + services.postgresql = { + enable = true; + ensureDatabases = [ "hass" ]; + ensureUsers = [{ + name = "hass"; + ensureDBOwnership = true; + }]; + }; + + systemd.tmpfiles.rules = [ + "C ${config.services.home-assistant.configDir}/custom_components/sonoff - - - - ${sources.sonoff-lan}/custom_components/sonoff" + "Z ${config.services.home-assistant.configDir}/custom_components 770 hass hass - -" + "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass" + ]; +} \ No newline at end of file From d797a8d2f80c74cd1890522a11c3afab6ea770ef Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Mon, 28 Jul 2025 10:59:58 -0700 Subject: [PATCH 06/23] remove hyprland --- desktop/l/configuration.nix | 2 +- desktop/l/flake.lock | 54 ++++++++++++++++++------------------ desktop/l/home.nix | 5 ++-- desktop/l2/flake.nix | 1 + desktop/l2/hostapd-multi.nix | 10 +++---- 5 files changed, 36 insertions(+), 36 deletions(-) diff --git a/desktop/l/configuration.nix b/desktop/l/configuration.nix index 3e2853d..df59ce4 100644 --- a/desktop/l/configuration.nix +++ b/desktop/l/configuration.nix @@ -39,7 +39,7 @@ #./docker-compose.nix ./docker-daemon.nix #./smokeping.nix - ./distributed-builds.nix + #./distributed-builds.nix #./hyprland.nix ]; diff --git a/desktop/l/flake.lock b/desktop/l/flake.lock index fccd76e..e841024 100644 --- a/desktop/l/flake.lock +++ b/desktop/l/flake.lock @@ -20,11 +20,11 @@ ] }, "locked": { - "lastModified": 1751740947, - "narHash": "sha256-35040CHH7P3JGmhGVfEb2oJHL/A5mI2IXumhkxrBnao=", + "lastModified": 1752743471, + "narHash": "sha256-4izhj1j7J4mE8LgljCXSIUDculqOsxxhdoC81VhqizM=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "dfc1db15a08c4cd234288f66e1199c653495301f", + "rev": "e31b575d19e7cf8a8f4398e2f9cffe27a1332506", "type": "github" }, "original": { @@ -78,11 +78,11 @@ ] }, "locked": { - "lastModified": 1752338520, - "narHash": "sha256-O1p5BwTwAqZ6sDrCxCxlZFaP/Jx4t1W8+ms9USyEcPQ=", + "lastModified": 1753709185, + "narHash": "sha256-fU0XPSNudRJHvbeMK2qWBXEbfd77t7r+e9V2L9ON5kI=", "owner": "nix-community", "repo": "home-manager", - "rev": "ae62fd8ad8347e6bb5b615057f39f33d595a1c47", + "rev": "20cf285e9f8e5e3968abca80081c03ea96e7ea73", "type": "github" }, "original": { @@ -136,11 +136,11 @@ ] }, "locked": { - "lastModified": 1751808145, - "narHash": "sha256-OXgL0XaKMmfX2rRQkt9SkJw+QNfv0jExlySt1D6O72g=", + "lastModified": 1752149140, + "narHash": "sha256-gbh1HL98Fdqu0jJIWN4OJQN7Kkth7+rbkFpSZLm/62A=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "b841473a0bd4a1a74a0b64f1ec2ab199035c349f", + "rev": "340494a38b5ec453dfc542c6226481f736cc8a9a", "type": "github" }, "original": { @@ -165,11 +165,11 @@ "xdph": "xdph" }, "locked": { - "lastModified": 1752337367, - "narHash": "sha256-kEumflYEdQSrZZQEr7kik2sBfFohEx0TsJB1rBVAQy4=", + "lastModified": 1753634783, + "narHash": "sha256-30VgiypL8l+LcficVPftVBfFnWG533NU99cfps/hnD0=", "owner": "hyprwm", "repo": "Hyprland", - "rev": "d0f58baf296a2cdd5df0f82212fe17dfbef8438e", + "rev": "c63d0003a1e5155248695f19778f815a8ad34c67", "type": "github" }, "original": { @@ -195,11 +195,11 @@ ] }, "locked": { - "lastModified": 1752254688, - "narHash": "sha256-XJJ+frO4NOxVkoSGc1Mag8ESumzx2FmVRspOgFlMqF8=", + "lastModified": 1753028264, + "narHash": "sha256-GbfsRZWW5uBAOeddLkmrYV2XmAbI0etVUTBXFH5thcw=", "owner": "hyprwm", "repo": "hyprland-plugins", - "rev": "d723e5b153b7990d36e62a425bda3768c41dd9eb", + "rev": "14f9a444793d6dd78c29033acf9c3c974ded708d", "type": "github" }, "original": { @@ -342,11 +342,11 @@ ] }, "locked": { - "lastModified": 1751888065, - "narHash": "sha256-F2SV9WGqgtRsXIdUrl3sRe0wXlQD+kRRZcSfbepjPJY=", + "lastModified": 1752252310, + "narHash": "sha256-06i1pIh6wb+sDeDmWlzuPwIdaFMxLlj1J9I5B9XqSeo=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "a8229739cf36d159001cfc203871917b83fdf917", + "rev": "bcabcbada90ed2aacb435dc09b91001819a6dc82", "type": "github" }, "original": { @@ -367,11 +367,11 @@ ] }, "locked": { - "lastModified": 1751881472, - "narHash": "sha256-meB0SnXbwIe2trD041MLKEv6R7NZ759QwBcVIhlSBfE=", + "lastModified": 1751897909, + "narHash": "sha256-FnhBENxihITZldThvbO7883PdXC/2dzW4eiNvtoV5Ao=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "8fb426b3e5452fd9169453fd6c10f8c14ca37120", + "rev": "fcca0c61f988a9d092cbb33e906775014c61579d", "type": "github" }, "original": { @@ -382,11 +382,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1751792365, - "narHash": "sha256-J1kI6oAj25IG4EdVlg2hQz8NZTBNYvIS0l4wpr9KcUo=", + "lastModified": 1752687322, + "narHash": "sha256-RKwfXA4OZROjBTQAl9WOZQFm7L8Bo93FQwSJpAiSRvo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1fd8bada0b6117e6c7eb54aad5813023eed37ccb", + "rev": "6e987485eb2c77e5dcc5af4e3c70843711ef9251", "type": "github" }, "original": { @@ -398,11 +398,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1751984180, - "narHash": "sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X+xgOL0=", + "lastModified": 1753549186, + "narHash": "sha256-Znl7rzuxKg/Mdm6AhimcKynM7V3YeNDIcLjBuoBcmNs=", "owner": "nixos", "repo": "nixpkgs", - "rev": "9807714d6944a957c2e036f84b0ff8caf9930bc0", + "rev": "17f6bd177404d6d43017595c5264756764444ab8", "type": "github" }, "original": { diff --git a/desktop/l/home.nix b/desktop/l/home.nix index 305488f..2f98b81 100644 --- a/desktop/l/home.nix +++ b/desktop/l/home.nix @@ -465,7 +465,6 @@ # Filesystem/Monitoring inotify-tools - # SDR gnuradio hackrf @@ -498,8 +497,8 @@ # https://github.com/aarzilli/gdlv gdlv buf - protobuf_27 - grpcurl + #protobuf_27 + #grpcurl # https://github.com/go-gorm/gen # https://github.com/infobloxopen/protoc-gen-gorm/blob/main/example/postgres_arrays/buf.gen.yaml gorm-gentool diff --git a/desktop/l2/flake.nix b/desktop/l2/flake.nix index ece7294..d627e94 100644 --- a/desktop/l2/flake.nix +++ b/desktop/l2/flake.nix @@ -7,6 +7,7 @@ # https://nix.dev/manual/nix/2.24/command-ref/new-cli/nix3-flake.html#flake-inputs inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + #nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; # https://nixos-and-flakes.thiscute.world/nixos-with-flakes/start-using-home-manager home-manager = { diff --git a/desktop/l2/hostapd-multi.nix b/desktop/l2/hostapd-multi.nix index bd31416..d3753ed 100644 --- a/desktop/l2/hostapd-multi.nix +++ b/desktop/l2/hostapd-multi.nix @@ -211,12 +211,12 @@ in { }; }; -systemd.network.networks."dummy0" = { - matchConfig.Name = "dummy0"; - networkConfig = { - Bridge = "br0"; + systemd.network.networks."dummy0" = { + matchConfig.Name = "dummy0"; + networkConfig = { + Bridge = "br0"; + }; }; -}; # https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html systemd.network.networks = { From d486e7bc097d1bf482942418e2fc4b7b9b310557 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Mon, 28 Jul 2025 11:00:05 -0700 Subject: [PATCH 07/23] hosts --- desktop/l/flake.lock | 459 +------------------------------------- desktop/l/flake.nix | 16 +- desktop/l/home.nix | 318 +------------------------- desktop/l/hosts.nix | 2 +- hp/hp4/home-assistant.nix | 132 +++++++++-- 5 files changed, 140 insertions(+), 787 deletions(-) diff --git a/desktop/l/flake.lock b/desktop/l/flake.lock index e841024..0f69cf8 100644 --- a/desktop/l/flake.lock +++ b/desktop/l/flake.lock @@ -1,76 +1,5 @@ { "nodes": { - "aquamarine": { - "inputs": { - "hyprutils": [ - "hyprland", - "hyprutils" - ], - "hyprwayland-scanner": [ - "hyprland", - "hyprwayland-scanner" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1752743471, - "narHash": "sha256-4izhj1j7J4mE8LgljCXSIUDculqOsxxhdoC81VhqizM=", - "owner": "hyprwm", - "repo": "aquamarine", - "rev": "e31b575d19e7cf8a8f4398e2f9cffe27a1332506", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "aquamarine", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "hyprland", - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, "home-manager": { "inputs": { "nixpkgs": [ @@ -91,312 +20,7 @@ "type": "github" } }, - "hyprcursor": { - "inputs": { - "hyprlang": [ - "hyprland", - "hyprlang" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1749155331, - "narHash": "sha256-XR9fsI0zwLiFWfqi/pdS/VD+YNorKb3XIykgTg4l1nA=", - "owner": "hyprwm", - "repo": "hyprcursor", - "rev": "45fcc10b4c282746d93ec406a740c43b48b4ef80", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprcursor", - "type": "github" - } - }, - "hyprgraphics": { - "inputs": { - "hyprutils": [ - "hyprland", - "hyprutils" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1752149140, - "narHash": "sha256-gbh1HL98Fdqu0jJIWN4OJQN7Kkth7+rbkFpSZLm/62A=", - "owner": "hyprwm", - "repo": "hyprgraphics", - "rev": "340494a38b5ec453dfc542c6226481f736cc8a9a", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprgraphics", - "type": "github" - } - }, - "hyprland": { - "inputs": { - "aquamarine": "aquamarine", - "hyprcursor": "hyprcursor", - "hyprgraphics": "hyprgraphics", - "hyprland-protocols": "hyprland-protocols", - "hyprland-qtutils": "hyprland-qtutils", - "hyprlang": "hyprlang", - "hyprutils": "hyprutils", - "hyprwayland-scanner": "hyprwayland-scanner", - "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks", - "systems": "systems", - "xdph": "xdph" - }, - "locked": { - "lastModified": 1753634783, - "narHash": "sha256-30VgiypL8l+LcficVPftVBfFnWG533NU99cfps/hnD0=", - "owner": "hyprwm", - "repo": "Hyprland", - "rev": "c63d0003a1e5155248695f19778f815a8ad34c67", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "Hyprland", - "type": "github" - } - }, - "hyprland-plugins": { - "inputs": { - "hyprland": [ - "hyprland" - ], - "nixpkgs": [ - "hyprland-plugins", - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland-plugins", - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1753028264, - "narHash": "sha256-GbfsRZWW5uBAOeddLkmrYV2XmAbI0etVUTBXFH5thcw=", - "owner": "hyprwm", - "repo": "hyprland-plugins", - "rev": "14f9a444793d6dd78c29033acf9c3c974ded708d", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprland-plugins", - "type": "github" - } - }, - "hyprland-protocols": { - "inputs": { - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1749046714, - "narHash": "sha256-kymV5FMnddYGI+UjwIw8ceDjdeg7ToDVjbHCvUlhn14=", - "owner": "hyprwm", - "repo": "hyprland-protocols", - "rev": "613878cb6f459c5e323aaafe1e6f388ac8a36330", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprland-protocols", - "type": "github" - } - }, - "hyprland-qt-support": { - "inputs": { - "hyprlang": [ - "hyprland", - "hyprland-qtutils", - "hyprlang" - ], - "nixpkgs": [ - "hyprland", - "hyprland-qtutils", - "nixpkgs" - ], - "systems": [ - "hyprland", - "hyprland-qtutils", - "systems" - ] - }, - "locked": { - "lastModified": 1749154592, - "narHash": "sha256-DO7z5CeT/ddSGDEnK9mAXm1qlGL47L3VAHLlLXoCjhE=", - "owner": "hyprwm", - "repo": "hyprland-qt-support", - "rev": "4c8053c3c888138a30c3a6c45c2e45f5484f2074", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprland-qt-support", - "type": "github" - } - }, - "hyprland-qtutils": { - "inputs": { - "hyprland-qt-support": "hyprland-qt-support", - "hyprlang": [ - "hyprland", - "hyprlang" - ], - "hyprutils": [ - "hyprland", - "hyprland-qtutils", - "hyprlang", - "hyprutils" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1750371812, - "narHash": "sha256-D868K1dVEACw17elVxRgXC6hOxY+54wIEjURztDWLk8=", - "owner": "hyprwm", - "repo": "hyprland-qtutils", - "rev": "b13c7481e37856f322177010bdf75fccacd1adc8", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprland-qtutils", - "type": "github" - } - }, - "hyprlang": { - "inputs": { - "hyprutils": [ - "hyprland", - "hyprutils" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1750371198, - "narHash": "sha256-/iuJ1paQOBoSLqHflRNNGyroqfF/yvPNurxzcCT0cAE=", - "owner": "hyprwm", - "repo": "hyprlang", - "rev": "cee01452bca58d6cadb3224e21e370de8bc20f0b", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprlang", - "type": "github" - } - }, - "hyprutils": { - "inputs": { - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1752252310, - "narHash": "sha256-06i1pIh6wb+sDeDmWlzuPwIdaFMxLlj1J9I5B9XqSeo=", - "owner": "hyprwm", - "repo": "hyprutils", - "rev": "bcabcbada90ed2aacb435dc09b91001819a6dc82", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprutils", - "type": "github" - } - }, - "hyprwayland-scanner": { - "inputs": { - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1751897909, - "narHash": "sha256-FnhBENxihITZldThvbO7883PdXC/2dzW4eiNvtoV5Ao=", - "owner": "hyprwm", - "repo": "hyprwayland-scanner", - "rev": "fcca0c61f988a9d092cbb33e906775014c61579d", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprwayland-scanner", - "type": "github" - } - }, "nixpkgs": { - "locked": { - "lastModified": 1752687322, - "narHash": "sha256-RKwfXA4OZROjBTQAl9WOZQFm7L8Bo93FQwSJpAiSRvo=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "6e987485eb2c77e5dcc5af4e3c70843711ef9251", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { "locked": { "lastModified": 1753549186, "narHash": "sha256-Znl7rzuxKg/Mdm6AhimcKynM7V3YeNDIcLjBuoBcmNs=", @@ -412,91 +36,10 @@ "type": "github" } }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": "flake-compat", - "gitignore": "gitignore", - "nixpkgs": [ - "hyprland", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1750779888, - "narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=", - "owner": "cachix", - "repo": "git-hooks.nix", - "rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "git-hooks.nix", - "type": "github" - } - }, "root": { "inputs": { "home-manager": "home-manager", - "hyprland": "hyprland", - "hyprland-plugins": "hyprland-plugins", - "nixpkgs": "nixpkgs_2" - } - }, - "systems": { - "locked": { - "lastModified": 1689347949, - "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", - "owner": "nix-systems", - "repo": "default-linux", - "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default-linux", - "type": "github" - } - }, - "xdph": { - "inputs": { - "hyprland-protocols": [ - "hyprland", - "hyprland-protocols" - ], - "hyprlang": [ - "hyprland", - "hyprlang" - ], - "hyprutils": [ - "hyprland", - "hyprutils" - ], - "hyprwayland-scanner": [ - "hyprland", - "hyprwayland-scanner" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1751300244, - "narHash": "sha256-PFuv1TZVYvQhha0ac53E3YgdtmLShrN0t4T6xqHl0jE=", - "owner": "hyprwm", - "repo": "xdg-desktop-portal-hyprland", - "rev": "6115f3fdcb2c1a57b4a80a69f3c797e47607b90a", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "xdg-desktop-portal-hyprland", - "type": "github" + "nixpkgs": "nixpkgs" } } }, diff --git a/desktop/l/flake.nix b/desktop/l/flake.nix index 947553c..d3df0c1 100644 --- a/desktop/l/flake.nix +++ b/desktop/l/flake.nix @@ -10,15 +10,16 @@ url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; - hyprland.url = "github:hyprwm/Hyprland"; - hyprland-plugins = { - url = "github:hyprwm/hyprland-plugins"; - inputs.hyprland.follows = "hyprland"; - }; + # hyprland.url = "github:hyprwm/Hyprland"; + # hyprland-plugins = { + # url = "github:hyprwm/hyprland-plugins"; + # inputs.hyprland.follows = "hyprland"; + # }; }; #outputs = inputs@{ nixpkgs, home-manager, hyprland, ... }: - outputs = { self, nixpkgs, home-manager, hyprland, ... }: + #outputs = { self, nixpkgs, home-manager, hyprland, ... }: + outputs = { self, nixpkgs, home-manager, ... }: let system = "x86_64-linux"; pkgs = import nixpkgs { @@ -41,12 +42,11 @@ l = lib.nixosSystem rec { inherit system; specialArgs = { - inherit hyprland; unstable = pkgs; }; modules = [ ./configuration.nix - hyprland.nixosModules.default + #hyprland.nixosModules.default home-manager.nixosModules.home-manager { # https://nix-community.github.io/home-manager/nixos-options.xhtml#nixos-opt-home-manager.useGlobalPkgs diff --git a/desktop/l/home.nix b/desktop/l/home.nix index 2f98b81..80ba6f8 100644 --- a/desktop/l/home.nix +++ b/desktop/l/home.nix @@ -1,305 +1,11 @@ { - hyprland, + #hyprland, config, pkgs, ... }: { - imports = [ - hyprland.homeManagerModules.default - ]; - - # Hyprland window manager configuration - wayland.windowManager.hyprland = { - enable = true; - xwayland.enable = true; - extraConfig = '' - # Monitor configuration - monitor=,preferred,auto,1 - - # Execute-once startup commands - exec-once = waybar - exec-once = swaybg -i ~/.config/hypr/wallpaper.jpg - exec-once = hypridle - exec-once = wl-paste --type text --watch cliphist store - exec-once = wl-paste --type image --watch cliphist store - - # Input configuration - input { - kb_layout = us - kb_variant = - kb_model = - kb_options = - kb_rules = - - follow_mouse = 1 - touchpad { - natural_scroll = true - scroll_factor = 0.3 - } - sensitivity = 0 # -1.0 - 1.0, 0 means no modification. - } - - # General settings - general { - gaps_in = 5 - gaps_out = 10 - border_size = 2 - col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg - col.inactive_border = rgba(595959aa) - layout = dwindle - no_cursor_warps = true - } - - # Decoration settings - decoration { - rounding = 10 - blur { - enabled = true - size = 3 - passes = 1 - } - drop_shadow = true - shadow_range = 4 - shadow_render_power = 3 - col.shadow = rgba(1a1a1aee) - } - - # Animation settings - animations { - enabled = true - bezier = myBezier, 0.05, 0.9, 0.1, 1.05 - animation = windows, 1, 7, myBezier - animation = windowsOut, 1, 7, default, popin 80% - animation = border, 1, 10, default - animation = borderangle, 1, 8, default - animation = fade, 1, 7, default - animation = workspaces, 1, 6, default - } - - # Layout settings - dwindle { - pseudotile = true - preserve_split = true - } - - # Gesture settings - gestures { - workspace_swipe = true - workspace_swipe_fingers = 3 - } - - # Keybindings - bind = SUPER, Q, killactive, - bind = SUPER, RETURN, exec, ${pkgs.alacritty}/bin/alacritty - bind = SUPER, D, exec, wofi --show drun - bind = SUPER, F, fullscreen - bind = SUPER, H, movefocus, l - bind = SUPER, L, movefocus, r - bind = SUPER, K, movefocus, u - bind = SUPER, J, movefocus, d - bind = SUPER, left, movewindow, l - bind = SUPER, right, movewindow, r - bind = SUPER, up, movewindow, u - bind = SUPER, down, movewindow, d - bind = SUPER SHIFT, H, movewindow, l - bind = SUPER SHIFT, L, movewindow, r - bind = SUPER SHIFT, K, movewindow, u - bind = SUPER SHIFT, J, movewindow, d - bind = SUPER, 1, workspace, 1 - bind = SUPER, 2, workspace, 2 - bind = SUPER, 3, workspace, 3 - bind = SUPER, 4, workspace, 4 - bind = SUPER, 5, workspace, 5 - bind = SUPER, 6, workspace, 6 - bind = SUPER, 7, workspace, 7 - bind = SUPER, 8, workspace, 8 - bind = SUPER, 9, workspace, 9 - bind = SUPER, 0, workspace, 10 - bind = SUPER SHIFT, 1, movetoworkspace, 1 - bind = SUPER SHIFT, 2, movetoworkspace, 2 - bind = SUPER SHIFT, 3, movetoworkspace, 3 - bind = SUPER SHIFT, 4, movetoworkspace, 4 - bind = SUPER SHIFT, 5, movetoworkspace, 5 - bind = SUPER SHIFT, 6, movetoworkspace, 6 - bind = SUPER SHIFT, 7, movetoworkspace, 7 - bind = SUPER SHIFT, 8, movetoworkspace, 8 - bind = SUPER SHIFT, 9, movetoworkspace, 9 - bind = SUPER SHIFT, 0, movetoworkspace, 10 - bind = SUPER, mouse_down, workspace, e+1 - bind = SUPER, mouse_up, workspace, e-1 - bind = SUPER, period, togglespecialworkspace, magic - bind = SUPER SHIFT, period, movetoworkspace, special:magic - bind = SUPER, S, togglesplit, - bind = SUPER, P, pseudo, - bind = SUPER, V, togglefloating, - bind = SUPER, R, exec, wofi --show run - bind = SUPER, Print, exec, grimblast --notify copysave area - bind = SUPER SHIFT, Print, exec, grimblast --notify copysave screen - bind = SUPER, X, exec, wl-clipboard-manager - bind = SUPER, C, exec, cliphist list | wofi --dmenu | cliphist decode | wl-copy - ''; - }; - - # Waybar configuration - programs.waybar = { - enable = true; - settings = { - mainBar = { - layer = "top"; - position = "top"; - height = 30; - spacing = 4; - modules-left = [ - "hyprland/workspaces" - "hyprland/submap" - ]; - modules-center = [ - "hyprland/window" - ]; - modules-right = [ - "pulseaudio" - "network" - "cpu" - "memory" - "battery" - "clock" - ]; - "hyprland/workspaces" = { - format = "{name}"; - on-click = "activate"; - sort-by-number = true; - }; - "hyprland/window" = { - format = "{}"; - separate-outputs = true; - }; - "pulseaudio" = { - format = "{icon} {volume}%"; - format-muted = "🔇"; - format-icons = { - headphone = "🎧"; - handsfree = "📱"; - headset = "🎧"; - phone = "☎️"; - portable = "📱"; - car = "🚗"; - default = ["🔈" "🔉" "🔊"]; - }; - on-click = "pavucontrol"; - }; - "network" = { - format-wifi = "📶 {essid}"; - format-ethernet = "🌐 {ipaddr}/{cidr}"; - format-linked = "🌐 {ifname} (No IP)"; - format-disconnected = "⚠️ Disconnected"; - format-alt = "{ifname}: {ipaddr}/{cidr}"; - }; - "cpu" = { - format = "🖥️ {usage}%"; - tooltip-format = "{usage}% used"; - }; - "memory" = { - format = "🧠 {percentage}%"; - tooltip-format = "{used:0.1f}GB/{total:0.1f}GB used"; - }; - "battery" = { - states = { - warning = 30; - critical = 15; - }; - format = "{icon} {capacity}%"; - format-charging = "⚡ {capacity}%"; - format-plugged = "🔌 {capacity}%"; - format-icons = ["🔋" "🔋" "🔋" "🔋" "🔋"]; - }; - "clock" = { - format = "🕒 {:%H:%M}"; - format-alt = "🕒 {:%Y-%m-%d %H:%M}"; - tooltip-format = "{:%Y %B}\n{calendar}"; - }; - }; - }; - style = '' - * { - border: none; - border-radius: 0; - font-family: "JetBrainsMono Nerd Font"; - font-size: 13px; - font-weight: bold; - min-height: 0; - } - - window#waybar { - background: rgba(21, 18, 27, 0.8); - color: #cdd6f4; - } - - #workspaces button { - padding: 0 5px; - background: transparent; - color: #cdd6f4; - } - - #workspaces button:hover { - background: rgba(0, 0, 0, 0.2); - } - - #workspaces button.active { - background: #7aa2f7; - color: #1e1e2e; - } - - #workspaces button.urgent { - background: #f38ba8; - color: #1e1e2e; - } - - #battery, - #cpu, - #memory, - #network, - #pulseaudio, - #clock { - padding: 0 10px; - margin: 0 5px; - } - - #battery { - color: #a6e3a1; - } - - #battery.warning { - color: #f9e2af; - } - - #battery.critical { - color: #f38ba8; - } - - #network { - color: #89b4fa; - } - - #pulseaudio { - color: #cba6f7; - } - - #cpu { - color: #f5c2e7; - } - - #memory { - color: #fab387; - } - - #clock { - color: #89dceb; - } - ''; - }; - # Ghostty configuration programs.ghostty = { enable = true; @@ -357,17 +63,17 @@ neofetch file - # Hyprland related - waybar - swaybg - swaylock - wl-clipboard - wf-recorder - grimblast - hyprpaper - hyprpicker - hypridle - hyprlock + # # Hyprland related + # waybar + # swaybg + # swaylock + # wl-clipboard + # wf-recorder + # grimblast + # hyprpaper + # hyprpicker + # hypridle + # hyprlock # Terminal Multiplexers tmux diff --git a/desktop/l/hosts.nix b/desktop/l/hosts.nix index ae89d39..8f66587 100644 --- a/desktop/l/hosts.nix +++ b/desktop/l/hosts.nix @@ -9,7 +9,7 @@ "172.16.40.146" = [ "hp3" "hp3eth" ]; # savi's room "172.16.40.130" = [ "hp3wifi" ]; "172.16.50.232" = [ "hp4" "hp4eth" ]; # rack - "172.16.40.70" = [ "hp5" "hp5eth" ]; + "172.16.40.72" = [ "hp5" "hp5eth" ]; "172.16.40.122" = [ "pi5-1" "pi5-1-eth" ]; "172.16.40.62" = [ "chromebox3" "chromebox3-eth" ]; "172.16.40.46" = [ "l2" ]; diff --git a/hp/hp4/home-assistant.nix b/hp/hp4/home-assistant.nix index 02177f0..37a978b 100644 --- a/hp/hp4/home-assistant.nix +++ b/hp/hp4/home-assistant.nix @@ -5,36 +5,110 @@ # https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/home-assistant/default.nix # https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/home-assistant/component-packages.nix # +# https://nathan.gs/2023/12/28/home-assistant-add-a-custom-component-in-nixos-revisited/ +# https://github.com/nathan-gs/nix-conf/blob/main/services/home-assistant.nix +# { config, pkgs, ... }: { + # sudo systemctl restart home-assistant.service services.home-assistant = { enable = true; - package = (pkgs.home-assistant.override { - extraPackages = py: with py; [ psycopg2 ]; - }).overrideAttrs (oldAttrs: { - doInstallCheck = false; - }); + # package = (pkgs.home-assistant.override { + # extraPackages = py: with py; [ psycopg2 ]; + # }).overrideAttrs (oldAttrs: { + # doInstallCheck = false; + # }); + + # nix package zigbee2mqtt_2 + # https://search.nixos.org/packages?channel=unstable&from=0&size=50&sort=relevance&type=packages&query=mqtt + + # https://github.com/NixOS/nixpkgs/tree/master/pkgs/servers/home-assistant/custom-components/ extraComponents = [ # Components required to complete the onboarding "esphome" - "met" + "homekit" + #"met" "radio_browser" "tuya" "wemo" + "api" + "apple_tv" + "bluetooth" + "http" + "html5" + "ping" + "scrape" + "sensor" + "smartthings" + "openweathermap" + "samsungtv" + "prometheus" + "roborock" + "litterrobot" + "nest" + "zeroconf" + "speedtestdotnet" + "unifi" + "unifi_direct" + "mqtt" + "mqtt_eventstream" + "mqtt_json" + "mqtt_room" + "mqtt_statestream" + "zha" + ]; + + # https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/home-assistant/python-modules/hass-web-proxy-lib/default.nix + extraPackages = python3Packages: with python3Packages; [ + # recorder postgresql support + psycopg2 + + aiohomekit + aiohttp + aiohttp-fast-zlib + + # Performance libraries for aiohttp + isal + zlib-ng + + # Optional extras that might be pulled by integrations + orjson + ciso8601 + yarl + multidict + + universal-silabs-flasher + zha-quirks + zigpy-deconz + zigpy-xbee + zigpy-zigate + zigpy-znp + + getmac + hap-python + pyipp + pyotp + pyqrcode ]; - configDir = /var/lib/hass; + #configDir = /var/lib/hass; config = { # Includes dependencies for a basic setup # https://www.home-assistant.io/integrations/default_config/ default_config = {}; - recorder.db_url = "postgresql://@/hass"; + recorder = { + db_url = "postgresql://@/hass"; + purge_keep_days = 3650; + auto_purge = true; + auto_repack = true; + }; }; }; # https://nixos.wiki/wiki/Home_Assistant#Using_PostgreSQL + # sudo systemctl restart postgresql.service services.postgresql = { enable = true; ensureDatabases = [ "hass" ]; @@ -44,9 +118,39 @@ }]; }; - systemd.tmpfiles.rules = [ - "C ${config.services.home-assistant.configDir}/custom_components/sonoff - - - - ${sources.sonoff-lan}/custom_components/sonoff" - "Z ${config.services.home-assistant.configDir}/custom_components 770 hass hass - -" - "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass" - ]; -} \ No newline at end of file + # systemd.tmpfiles.rules = [ + # #"C ${config.services.home-assistant.configDir}/custom_components/sonoff - - - - ${sources.sonoff-lan}/custom_components/sonoff" + # "Z ${config.services.home-assistant.configDir}/custom_components 770 hass hass - -" + # "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass" + # ]; +} + +#error: A definition for option `services.home-assistant.extraComponents."[definition 1-entry 15]"' is not of type `one of "3_day_blinds", "abode", "accuweather", "acer_projector", "acmeda", "acomax", "actiontec", "adax", "adguard", "ads", "advantage_air", "aemet", "aep_ohio", "aep_texas", "aftership", "agent_dvr", "air_quality", "airgradient", "airly", "airnow", "airq", "airthings", "airthings_ble", "airtouch4", "airtouch5", "airvisual", "airvisual_pro", "airzone", "airzone_cloud", "aladdin_connect", "alarm_control_panel", "alarmdecoder", "alert", "alexa", "alpha_vantage", "amazon_polly", "amberelectric", "ambient_network", "ambient_station", "amcrest", "amp_motorization", "ampio", "analytics", "analytics_insights", "android_ip_webcam", "androidtv", "androidtv_remote", "anel_pwrctrl", "anova", "anthemav", "anthropic", "anwb_energie", "aosmith", "apache_kafka", "apcupsd", "api", "appalachianpower", "apple_tv", "application_credentials", "apprise", "aprilaire", "aprs", "aps", "apsystems", "aquacell", "aqualogic", "aquostv", "aranet", "arcam_fmj", "arest", "arris_tg2492lg", "artsound", "aruba", "arve", "arwn", "aseko_pool_live", "assist_pipeline", "assist_satellite", "asuswrt", "atag", "aten_pe", "atlanticcityelectric", "atome", "august", "august_ble", "aurora", "aurora_abb_powerone", "aussie_broadband", "autarco", "auth", "automation", "avea", "avion", "awair", "aws", "axis", "azure_data_explorer", "azure_devops", "azure_event_hub", "azure_service_bus", "backup", "baf", "baidu", "balboa", "bang_olufsen", "bayesian", "bbox", "beewi_smartclim", "bge", "binary_sensor", "bitcoin", "bizkaibus", "blackbird", "blebox", "blink", "bliss_automation", "bloc_blinds", "blockchain", "blue_current", "bluemaestro", "blueprint", "bluesound", "bluetooth", "bluetooth_adapters", "bluetooth_le_tracker", "bluetooth_tracker", "bmw_connected_drive", "bond", "bosch_shc", "brandt", "braviatv", "brel_home", "bring", "broadlink", "brother", "brottsplatskartan", "browser", "brunt", "bryant_evolution", "bsblan", "bswitch", "bt_home_hub_5", "bt_smarthub", "bthome", "bticino", "bubendorff", "buienradar", "button", "caldav", "calendar", "cambridge_audio", "camera", "canary", "cast", "ccm15", "cert_expiry", "chacon_dio", "channels", "cisco_ios", "cisco_mobility_express", "cisco_webex_teams", "citybikes", "clementine", "clickatell", "clicksend", "clicksend_tts", "climate", "cloud", "cloudflare", "cmus", "co2signal", "coautilities", "coinbase", "color_extractor", "comed", "comed_hourly_pricing", "comelit", "comfoconnect", "command_line", "compensation", "concord232", "coned", "config", "configurator", "control4", "conversation", "coolmaster", "counter", "cover", "cozytouch", "cppm_tracker", "cpuspeed", "cribl", "crownstone", "cups", "currencylayer", "dacia", "daikin", "danfoss_air", "datadog", "date", "datetime", "ddwrt", "deako", "debugpy", "deconz", "decora", "decora_wifi", "default_config", "delijn", "delmarva", "deluge", "demo", "denon", "denonavr", "derivative", "devialet", "device_automation", "device_sun_light_trigger", "device_tracker", "devolo_home_control", "devolo_home_network", "dexcom", "dhcp", "diagnostics", "dialogflow", "diaz", "digital_loggers", "digital_ocean", "directv", "discogs", "discord", "discovergy", "dlib_face_detect", "dlib_face_identify", "dlink", "dlna_dmr", "dlna_dms", "dnsip", "dominos", "doods", "doorbird", "dooya", "dormakaba_dkey", "downloader", "dremel_3d_printer", "drop_connect", "dsmr", "dsmr_reader", "dte_energy_bridge", "dublin_bus_transport", "duckdns", "duke_energy", "dunehd", "duotecno", "duquesne_light", "dwd_weather_warnings", "dweet", "dynalite", "eafm", "eastron", "easyenergy", "ebox", "ebusd", "ecoal_boiler", "ecobee", "ecoforest", "econet", "ecovacs", "ecowitt", "eddystone_temperature", "edimax", "edl21", "efergy", "egardia", "eight_sleep", "electrasmart", "electric_kiwi", "elevenlabs", "elgato", "eliqonline", "elkm1", "elmax", "elv", "elvia", "emby", "emoncms", "emoncms_history", "emonitor", "emulated_hue", "emulated_kasa", "emulated_roku", "energenie_power_sockets", "energie_vanons", "energy", "energyzero", "enigma2", "enmax", "enocean", "enphase_envoy", "entur_public_transport", "environment_canada", "envisalink", "ephember", "epic_games_store", "epion", "epson", "eq3btsmart", "escea", "esera_onewire", "esphome", "etherscan", "eufy", "eufylife_ble", "event", "evergy", "everlights", "evil_genius_labs", "evohome", "ezviz", "faa_delays", "facebook", "fail2ban", "familyhub", "fan", "fastdotcom", "feedreader", "ffmpeg", "ffmpeg_motion", "ffmpeg_noise", "fibaro", "fido", "file", "file_upload", "filesize", "filter", "fints", "fire_tv", "fireservicerota", "firmata", "fitbit", "fivem", "fixer", "fjaraskupan", "fleetgo", "flexit", "flexit_bacnet", "flexom", "flic", "flick_electric", "flipr", "flo", "flock", "flume", "flux", "flux_led", "folder", "folder_watcher", "foobot", "forecast_solar", "forked_daapd", "fortios", "foscam", "foursquare", "free_mobile", "freebox", "freedns", "freedompro", "fritz", "fritzbox", "fritzbox_callmonitor", "fronius", "frontend", "frontier_silicon", "fujitsu_anywair", "fujitsu_fglair", "fully_kiosk", "futurenow", "fyta", "garadget", "garages_amsterdam", "gardena_bluetooth", "gaviota", "gc100", "gdacs", "generic", "generic_hygrostat", "generic_thermostat", "geniushub", "geo_json_events", "geo_location", "geo_rss_events", "geocaching", "geofency", "geonetnz_quakes", "geonetnz_volcano", "gios", "github", "gitlab_ci", "gitter", "glances", "go2rtc", "goalzero", "gogogate2", "goodwe", "google", "google_assistant", "google_assistant_sdk", "google_cloud", "google_generative_ai_conversation", "google_mail", "google_maps", "google_photos", "google_pubsub", "google_sheets", "google_tasks", "google_translate", "google_travel_time", "google_wifi", "govee_ble", "govee_light_local", "gpsd", "gpslogger", "graphite", "gree", "greeneye_monitor", "greenwave", "group", "growatt_server", "gstreamer", "gtfs", "guardian", "habitica", "hardkernel", "hardware", "harman_kardon_avr", "harmony", "hassio", "havana_shade", "haveibeenpwned", "hddtemp", "hdmi_cec", "heatmiser", "heiwa", "heos", "here_travel_time", "hexaom", "hi_kumo", "hikvision", "hikvisioncam", "hisense_aehw4a1", "history", "history_stats", "hitron_coda", "hive", "hko", "hlk_sw16", "holiday", "home_connect", "home_plus_control", "homeassistant", "homeassistant_alerts", "homeassistant_green", "homeassistant_hardware", "homeassistant_sky_connect", "homeassistant_yellow", "homekit", "homekit_controller", "homematic", "homematicip_cloud", "homewizard", "homeworks", "honeywell", "horizon", "hp_ilo", "html5", "http", "huawei_lte", "hue", "huisbaasje", "humidifier", "hunterdouglas_powerview", "hurrican_shutters_wholesale", "husqvarna_automower", "husqvarna_automower_ble", "huum", "hvv_departures", "hydrawise", "hyperion", "ialarm", "iammeter", "iaqualink", "ibeacon", "icloud", "idasen_desk", "idteck_prox", "ifttt", "iglo", "ign_sismologia", "ihc", "image", "image_processing", "image_upload", "imap", "imgw_pib", "improv_ble", "incomfort", "indianamichiganpower", "influxdb", "inkbird", "input_boolean", "input_button", "input_datetime", "input_number", "input_select", "input_text", "inspired_shades", "insteon", "integration", "intellifire", "intent", "intent_script", "intesishome", "ios", "iotawatt", "iotty", "iperf3", "ipma", "ipp", "iqvia", "irish_rail_transport", "iron_os", "isal", "iskra", "islamic_prayer_times", "ismartwindow", "israel_rail", "iss", "ista_ecotrend", "isy994", "itach", "itunes", "izone", "jellyfin", "jewish_calendar", "joaoapps_join", "juicenet", "justnimbus", "jvc_projector", "kaiterra", "kaleidescape", "kankun", "keba", "keenetic_ndms2", "kef", "kegtron", "kentuckypower", "keyboard", "keyboard_remote", "keymitt_ble", "kira", "kitchen_sink", "kiwi", "kmtronic", "knocki", "knx", "kodi", "konnected", "kostal_plenticore", "kraken", "krispol", "kulersky", "kwb", "lacrosse", "lacrosse_view", "lamarzocco", "lametric", "landisgyr_heat_meter", "lannouncer", "lastfm", "launch_library", "laundrify", "lawn_mower", "lcn", "ld2410_ble", "leaone", "led_ble", "legrand", "lektrico", "lg_netcast", "lg_soundbar", "lg_thinq", "lidarr", "life360", "lifx", "lifx_cloud", "light", "lightwave", "limitlessled", "linear_garage_door", "linkplay", "linksys_smart", "linode", "linux_battery", "lirc", "litejet", "litterrobot", "livisi", "llamalab_automate", "local_calendar", "local_file", "local_ip", "local_todo", "locative", "lock", "logbook", "logentries", "logger", "london_air", "london_underground", "lookin", "loqed", "lovelace", "luci", "luftdaten", "lupusec", "lutron", "lutron_caseta", "luxaflex", "lw12wifi", "lyric", "madeco", "madvr", "mailgun", "manual", "manual_mqtt", "marantz", "martec", "marytts", "mastodon", "matrix", "matter", "maxcube", "mazda", "mealie", "meater", "medcom_ble", "media_extractor", "media_player", "media_source", "mediaroom", "melcloud", "melissa", "melnor", "meraki", "mercury_nz", "message_bird", "met", "met_eireann", "meteo_france", "meteoalarm", "meteoclimatic", "metoffice", "mfi", "microbees", "microsoft", "microsoft_face", "microsoft_face_detect", "microsoft_face_identify", "mijndomein_energie", "mikrotik", "mill", "min_max", "minecraft_server", "mini_connected", "minio", "mjpeg", "moat", "mobile_app", "mochad", "modbus", "modem_callerid", "modern_forms", "moehlenhoff_alpha2", "mold_indicator", "monarch_money", "monessen", "monoprice", "monzo", "moon", "mopeka", "motion_blinds", "motionblinds_ble", "motioneye", "motionmount", "mpd", "mqtt", "mqtt_eventstream", "mqtt_json", "mqtt_room", "mqtt_statestream", "msteams", "mullvad", "mutesync", "my", "myq", "mysensors", "mystrom", "mythicbeastsdns", "myuplink", "nad", "nam", "namecheapdns", "nanoleaf", "neato", "nederlandse_spoorwegen", "ness_alarm", "nest", "netatmo", "netdata", "netgear", "netgear_lte", "netio", "network", "neurio_energy", "nexia", "nexity", "nextbus", "nextcloud", "nextdns", "nfandroidtv", "nibe_heatpump", "nice_go", "nightscout", "niko_home_control", "nilu", "nina", "nissan_leaf", "nmap_tracker", "nmbs", "no_ip", "noaa_tides", "nobo_hub", "norway_air", "notify", "notify_events", "notion", "nsw_fuel_station", "nsw_rural_fire_service_feed", "nuheat", "nuki", "numato", "number", "nut", "nutrichef", "nws", "nx584", "nyt_games", "nzbget", "oasa_telematics", "obihai", "octoprint", "oem", "ohmconnect", "ollama", "ombi", "omnilogic", "onboarding", "oncue", "ondilo_ico", "onewire", "onkyo", "onvif", "open_meteo", "openai_conversation", "openalpr_cloud", "openerz", "openevse", "openexchangerates", "opengarage", "openhardwaremonitor", "openhome", "opensensemap", "opensky", "opentherm_gw", "openuv", "openweathermap", "opnsense", "opower", "opple", "oralb", "oru", "oru_opower", "orvibo", "osoenergy", "osramlightify", "otbr", "otp", "ourgroceries", "overkiz", "ovo_energy", "owntracks", "p1_monitor", "palazzetti", "panasonic_bluray", "panasonic_viera", "pandora", "panel_custom", "pcs_lighting", "peco", "peco_opower", "pegel_online", "pencom", "pepco", "permobil", "persistent_notification", "person", "pge", "philips_js", "pi_hole", "picnic", "picotts", "pilight", "pinecil", "ping", "pioneer", "piper", "pjlink", "plaato", "plant", "plex", "plugwise", "plum_lightpad", "pocketcasts", "point", "poolsense", "portlandgeneral", "powerwall", "private_ble_device", "profiler", "progettihwsw", "proliphix", "prometheus", "prosegur", "prowl", "proximity", "proxmoxve", "proxy", "prusalink", "ps4", "pse", "psoklahoma", "pulseaudio_loopback", "pure_energie", "purpleair", "push", "pushbullet", "pushover", "pushsafer", "pvoutput", "pvpc_hourly_pricing", "pyload", "python_script", "qbittorrent", "qingping", "qld_bushfire", "qnap", "qnap_qsw", "qrcode", "quadrafire", "quantum_gateway", "qvr_pro", "qwikswitch", "rabbitair", "rachio", "radarr", "radio_browser", "radiotherm", "rainbird", "raincloud", "rainforest_eagle", "rainforest_raven", "rainmachine", "random", "rapt_ble", "raspberry_pi", "raspyrfm", "raven_rock_mfg", "rdw", "recollect_waste", "recorder", "recovery_mode", "recswitch", "reddit", "refoss", "rejseplanen", "remember_the_milk", "remote", "remote_rpi_gpio", "renault", "renson", "reolink", "repairs", "repetier", "rest", "rest_command", "rexel", "rflink", "rfxtrx", "rhasspy", "ridwell", "ring", "ripple", "risco", "rituals_perfume_genie", "rmvtransport", "roborock", "rocketchat", "roku", "romy", "roomba", "roon", "route53", "rova", "rpi_camera", "rpi_power", "rss_feed_template", "rtorrent", "rtsp_to_webrtc", "ruckus_unleashed", "russound_rio", "russound_rnet", "ruuvi_gateway", "ruuvitag_ble", "rympro", "sabnzbd", "saj", "samsam", "samsungtv", "sanix", "satel_integra", "scene", "schedule", "schlage", "schluter", "scl", "scrape", "screenaway", "screenlogic", "script", "scsgate", "search", "season", "select", "sendgrid", "sense", "sensibo", "sensirion_ble", "sensor", "sensorblue", "sensorpro", "sensorpush", "sensoterra", "sentry", "senz", "serial", "serial_pm", "sesame", "seven_segments", "seventeentrack", "sfr_box", "sharkiq", "shell_command", "shelly", "shodan", "shopping_list", "sia", "sigfox", "sighthound", "signal_messenger", "simplefin", "simplepush", "simplisafe", "simply_automated", "simu", "simulated", "sinch", "siren", "sisyphus", "sky_hub", "skybeacon", "skybell", "slack", "sleepiq", "slide", "slimproto", "sma", "smappee", "smart_blinds", "smart_home", "smart_meter_texas", "smarther", "smartthings", "smarttub", "smarty", "smhi", "smlight", "sms", "smtp", "smud", "snapcast", "snips", "snmp", "snooz", "solaredge", "solaredge_local", "solarlog", "solax", "soma", "somfy", "somfy_mylink", "sonarr", "songpal", "sonos", "sony_projector", "soundtouch", "spaceapi", "spc", "speedtestdotnet", "spider", "splunk", "spotify", "sql", "squeezebox", "srp_energy", "ssdp", "starline", "starlingbank", "starlink", "startca", "statistics", "statsd", "steam_online", "steamist", "stiebel_eltron", "stookalert", "stookwijzer", "stream", "streamlabswater", "stt", "subaru", "suez_water", "sun", "sunweg", "supervisord", "supla", "surepetcare", "swepco", "swiss_hydrological_data", "swiss_public_transport", "swisscom", "switch", "switch_as_x", "switchbee", "switchbot", "switchbot_cloud", "switcher_kis", "switchmate", "symfonisk", "syncthing", "syncthru", "synology_chat", "synology_dsm", "synology_srm", "syslog", "system_bridge", "system_health", "system_log", "systemmonitor", "tado", "tag", "tailscale", "tailwind", "tami4", "tank_utility", "tankerkoenig", "tapsaff", "tasmota", "tautulli", "tcp", "technove", "ted5000", "tedee", "telegram", "telegram_bot", "tellduslive", "tellstick", "telnet", "temper", "template", "tensorflow", "tesla_fleet", "tesla_wall_connector", "teslemetry", "tessie", "text", "thermobeacon", "thermoplus", "thermopro", "thethingsnetwork", "thingspeak", "thinkingcleaner", "thomson", "thread", "threshold", "tibber", "tikteck", "tile", "tilt_ble", "time", "time_date", "timer", "tmb", "tod", "todo", "todoist", "tolo", "tomato", "tomorrowio", "toon", "torque", "totalconnect", "touchline", "touchline_sl", "tplink", "tplink_lte", "tplink_omada", "tplink_tapo", "traccar", "traccar_server", "trace", "tractive", "tradfri", "trafikverket_camera", "trafikverket_ferry", "trafikverket_train", "trafikverket_weatherstation", "transmission", "transport_nsw", "travisci", "trend", "triggercmd", "tts", "tuya", "twentemilieu", "twilio", "twilio_call", "twilio_sms", "twinkly", "twitch", "twitter", "ubiwizz", "ubus", "uk_transport", "ukraine_alarm", "ultraloq", "unifi", "unifi_direct", "unifiled", "unifiprotect", "universal", "upb", "upc_connect", "upcloud", "update", "upnp", "uprise_smart_shades", "uptime", "uptimerobot", "usb", "usgs_earthquakes_feed", "utility_meter", "uvc", "v2c", "vacuum", "vallox", "valve", "vasttrafik", "velbus", "velux", "venstar", "vera", "verisure", "vermont_castings", "versasense", "version", "vesync", "viaggiatreno", "vicare", "vilfo", "vivotek", "vizio", "vlc", "vlc_telnet", "vodafone_station", "voicerss", "voip", "volkszaehler", "volumio", "volvooncall", "vulcan", "vultr", "w800rf32", "wake_on_lan", "wake_word", "wallbox", "waqi", "water_heater", "waterfurnace", "watson_iot", "watttime", "waze_travel_time", "weather", "weatherflow", "weatherflow_cloud", "weatherkit", "webhook", "webmin", "webostv", "websocket_api", "weheat", "wemo", "whirlpool", "whisper", "whois", "wiffi", "wilight", "wirelesstag", "withings", "wiz", "wled", "wmspro", "wolflink", "workday", "worldclock", "worldtidesinfo", "worxlandroid", "ws66i", "wsdot", "wyoming", "x10", "xbox", "xeoma", "xiaomi", "xiaomi_aqara", "xiaomi_ble", "xiaomi_miio", "xiaomi_tv", "xmpp", "xs1", "yale", "yale_home", "yale_smart_alarm", "yalexs_ble", "yamaha", "yamaha_musiccast", "yandex_transport", "yandextts", "yardian", "yeelight", "yeelightsunflower", "yi", "yolink", "youless", "youtube", "zabbix", "zamg", "zengge", "zeroconf", "zerproc", "zestimate", "zeversolar", "zha", "zhong_hong", "ziggo_mediabox_xl", "zodiac", "zondergas", "zone", "zoneminder", "zwave_js", "zwave_me"'. Definition values: + +# [7103383.054580] usb 2-10: new full-speed USB device number 2 using xhci_hcd +# [7103383.423224] usb 2-10: New USB device found, idVendor=10c4, idProduct=ea60, bcdDevice= 1.00 +# [7103383.423241] usb 2-10: New USB device strings: Mfr=1, Product=2, SerialNumber=3 +# [7103383.423249] usb 2-10: Product: Sonoff Zigbee 3.0 USB Dongle Plus V2 +# [7103383.423256] usb 2-10: Manufacturer: Itead +# [7103383.423262] usb 2-10: SerialNumber: 5cd6337ea3c2ef11ad08c9138148b910 +# [7103383.470000] usbcore: registered new interface driver cp210x +# [7103383.470039] usbserial: USB Serial support registered for cp210x +# [7103383.470109] cp210x 2-10:1.0: cp210x converter detected +# [7103383.489117] usb 2-10: cp210x converter now attached to ttyUSB0 +# [7185732.178015] Bluetooth: Core ver 2.22 +# [7185732.178044] NET: Registered PF_BLUETOOTH protocol family +# [7185732.178046] Bluetooth: HCI device and connection manager initialized +# [7185732.178052] Bluetooth: HCI socket layer initialized +# [7185732.178055] Bluetooth: L2CAP socket layer initialized +# [7185732.178060] Bluetooth: SCO socket layer initialized +# [7189311.168448] usb 2-10: USB disconnect, device number 2 +# [7189311.168794] cp210x ttyUSB0: cp210x converter now disconnected from ttyUSB0 +# [7189311.172114] cp210x 2-10:1.0: device disconnected +# [7189322.467946] usb 4-2: new full-speed USB device number 2 using xhci_hcd +# [7189322.617268] usb 4-2: New USB device found, idVendor=10c4, idProduct=ea60, bcdDevice= 1.00 +# [7189322.617281] usb 4-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 +# [7189322.617287] usb 4-2: Product: Sonoff Zigbee 3.0 USB Dongle Plus V2 +# [7189322.617293] usb 4-2: Manufacturer: Itead +# [7189322.617299] usb 4-2: SerialNumber: 5cd6337ea3c2ef11ad08c9138148b910 +# [7189322.619534] cp210x 4-2:1.0: cp210x converter detected +# [7189322.628801] usb 4-2: cp210x converter now attached to ttyUSB0 \ No newline at end of file From 2afcf0c87abbe35b67126c03402817308f1ff5f8 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Thu, 21 Aug 2025 04:57:09 -0700 Subject: [PATCH 08/23] 2025 08 21 --- desktop/l/Makefile | 2 +- laptops/t14/Makefile | 6 + laptops/t14/configuration.nix | 125 ++++++--- laptops/t14/flake.lock | 489 +-------------------------------- laptops/t14/flake.nix | 69 +++-- laptops/t14/home.nix | 375 ++++++++++++++----------- laptops/t14/hosts.nix | 24 +- laptops/t14/sysctl.nix | 27 +- laptops/t14/systemPackages.nix | 50 ++-- 9 files changed, 404 insertions(+), 763 deletions(-) diff --git a/desktop/l/Makefile b/desktop/l/Makefile index 1e544ae..07cdd2f 100644 --- a/desktop/l/Makefile +++ b/desktop/l/Makefile @@ -18,7 +18,7 @@ endif rebuild: sudo nixos-rebuild switch --flake . -rebuild_t: +rebuild_l: sudo nixos-rebuild switch --flake .#t #https://nixos.org/manual/nixos/unstable/index.html#sec-nix-network-issues diff --git a/laptops/t14/Makefile b/laptops/t14/Makefile index 7dd7a31..1474377 100644 --- a/laptops/t14/Makefile +++ b/laptops/t14/Makefile @@ -18,6 +18,9 @@ endif rebuild: sudo nixos-rebuild switch --flake . +rebuild_t14: + sudo nixos-rebuild switch --flake .#t14 + impure: sudo nixos-rebuild switch --impure --flake . @@ -48,4 +51,7 @@ update_oldm.: sudo nixos-rebuild switch #nix-shell -p vim +restart_display_manager: + sudo systemctl restart display-manager.service + # end diff --git a/laptops/t14/configuration.nix b/laptops/t14/configuration.nix index 3fcbb1f..42a1587 100644 --- a/laptops/t14/configuration.nix +++ b/laptops/t14/configuration.nix @@ -42,11 +42,10 @@ #./docker-compose.nix ./docker-daemon.nix #./smokeping.nix - ./x.nix + #./x.nix ]; boot = { - loader.systemd-boot = { enable = true; consoleMode = "max"; @@ -69,10 +68,10 @@ #"nomodeset" ]; - #blacklistedKernelModules = [ - # "nouveau" - # #"i915" - #]; + blacklistedKernelModules = [ + "nouveau" + #"i915" + ]; # https://wiki.nixos.org/wiki/NixOS_on_ARM/Building_Images#Compiling_through_binfmt_QEMU # https://nixos.org/manual/nixos/stable/options#opt-boot.binfmt.emulatedSystems @@ -107,21 +106,26 @@ # ]; }; + # Enable envfs for better compatibility with FHS expectations + services.envfs = { + enable = true; + }; + # For OBS security.polkit.enable = true; nix = { - gc = { - automatic = true; # Enable automatic execution of the task - dates = "weekly"; # Schedule the task to run weekly - options = "--delete-older-than 10d"; # Specify options for the task: delete files older than 10 days - randomizedDelaySec = "14m"; # Introduce a randomized delay of up to 14 minutes before executing the task - }; settings = { auto-optimise-store = true; experimental-features = [ "nix-command" "flakes" ]; download-buffer-size = "500000000"; }; + gc = { + automatic = true; # Enable automatic execution of the task + dates = "daily"; # Schedule the task to run daily + options = "--delete-older-than 10d"; # Specify options for the task: delete files older than 10 days + randomizedDelaySec = "14m"; # Introduce a randomized delay of up to 14 minutes before executing the task + }; }; # https://nixos.wiki/wiki/Networking @@ -133,21 +137,39 @@ # services.udev.packages = [ pkgs.gnome.gnome-settings-daemon ]; # https://nixos.wiki/wiki/NixOS_Wiki:Audio - hardware.pulseaudio.enable = false; # Use Pipewire, the modern sound subsystem + # hardware.pulseaudio.enable = false; # Use Pipewire, the modern sound subsystem security.rtkit.enable = true; # Enable RealtimeKit for audio purposes services.pipewire = { enable = true; + audio.enable = true; alsa.enable = true; alsa.support32Bit = true; pulse.enable = true; - # Uncomment the following line if you want to use JACK applications - # jack.enable = true; + jack.enable = true; + wireplumber.enable = true; + }; + + # Enable PipeWire screen capture + environment.sessionVariables = { + TERM = "xterm-256color"; + # PipeWire screen capture + PIPEWIRE_SCREEN_CAPTURE = "1"; + # Force Flameshot to use Wayland + QT_QPA_PLATFORM = "wayland"; + #MY_VARIABLE = "my-value"; }; - services.lldpd.enable = true; services.openssh.enable = true; + programs.ssh.extraConfig = '' + Host hp4.home + PubkeyAcceptedKeyTypes ssh-ed25519 + ServerAliveInterval 60 + IPQoS throughput + ''; + + services.lldpd.enable = true; services.timesyncd.enable = true; services.fstrim.enable = true; services.avahi = { @@ -160,7 +182,7 @@ services.bpftune.enable = true; # Enable touchpad support (enabled default in most desktopManager). - services.libinput.enable = true; + # services.libinput.enable = true; # https://nixos.wiki/wiki/Printing services.printing.enable = true; @@ -177,24 +199,17 @@ systemd.services.modem-manager.enable = false; systemd.services."dbus-org.freedesktop.ModemManager1".enable = false; - services.clickhouse.enable = false; + # services.clickhouse.enable = false; # https://nixos.wiki/wiki/PostgreSQL - services.postgresql.enable = true; + # services.postgresql.enable = true; # https://nixos.wiki/wiki/Mysql - services.mysql.package = pkgs.mariadb; - services.mysql.enable = true; - - # environment.variables defined in hardware-graphics.nix - environment.sessionVariables = { - TERM = "xterm-256color"; - #MY_VARIABLE = "my-value"; - #ANOTHER_VARIABLE = "another-value"; - }; + # services.mysql.package = pkgs.mariadb; + # services.mysql.enable = true; users.users.das = { isNormalUser = true; description = "das"; - extraGroups = [ "wheel" "networkmanager" "kvm" "libvirtd" "docker" "video" ]; + extraGroups = [ "wheel" "networkmanager" "kvm" "libvirtd" "docker" "video" "pipewire" ]; packages = with pkgs; [ ]; # https://nixos.wiki/wiki/SSH_public_key_authentication @@ -215,13 +230,55 @@ enableSSHSupport = true; }; - # # https://wiki.hyprland.org/Nix/Hyprland-on-NixOS/ - programs.hyprland = { + hardware.graphics = { + enable = true; # auto includes mesa + package = pkgs.mesa; + extraPackages = with pkgs; [ + libglvnd + libva-vdpau-driver + libvdpau-va-gl + rocmPackages.clr.icd + ]; + }; + services.xserver = { enable = true; - # Nvidia patches are no longer needed - #nvidiaPatches = true; - xwayland.enable = true; + videoDrivers = [ "amdgpu" ]; + xkb = { + layout = "us"; + variant = ""; + }; + }; + + services.desktopManager.gnome.enable = true; + services.displayManager.gdm.enable = true; + + # https://nixos.wiki/wiki/AMD_GPU + systemd.tmpfiles.rules = [ + "L+ /opt/rocm/hip - - - - ${pkgs.rocmPackages.clr}" + ]; + systemd.services.lactd.wantedBy = [ "multi-user.target" ]; + + xdg.portal = { + enable = true; + extraPortals = with pkgs; [ + xdg-desktop-portal-gnome + ]; + config.common.default = "gnome"; + config.gnome.default = "gnome"; }; + + services.dbus.packages = with pkgs; [ + xdg-desktop-portal + xdg-desktop-portal-gtk + ]; + + # # https://wiki.hyprland.org/Nix/Hyprland-on-NixOS/ + #programs.hyprland = { + # enable = true; + # # Nvidia patches are no longer needed + # #nvidiaPatches = true; + # xwayland.enable = true; + #}; # programs.hyprland = { # enable = true; # # set the flake package diff --git a/laptops/t14/flake.lock b/laptops/t14/flake.lock index 7557246..dc7265f 100644 --- a/laptops/t14/flake.lock +++ b/laptops/t14/flake.lock @@ -1,76 +1,5 @@ { "nodes": { - "aquamarine": { - "inputs": { - "hyprutils": [ - "hyprland", - "hyprutils" - ], - "hyprwayland-scanner": [ - "hyprland", - "hyprwayland-scanner" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1744289235, - "narHash": "sha256-ZFkHLdimtFzQACsVVyZkZlfYdj4iNy3PkzXfrwmlse8=", - "owner": "hyprwm", - "repo": "aquamarine", - "rev": "c8282f4982b56dfa5e9b9f659809da93f8d37e7a", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "aquamarine", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "hyprland", - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, "home-manager": { "inputs": { "nixpkgs": [ @@ -78,332 +7,26 @@ ] }, "locked": { - "lastModified": 1744743431, - "narHash": "sha256-iyn/WBYDc7OtjSawbegINDe/gIkok888kQxk3aVnkgg=", + "lastModified": 1753983724, + "narHash": "sha256-2vlAOJv4lBrE+P1uOGhZ1symyjXTRdn/mz0tZ6faQcg=", "owner": "nix-community", "repo": "home-manager", - "rev": "c61bfe3ae692f42ce688b5865fac9e0de58e1387", + "rev": "7035020a507ed616e2b20c61491ae3eaa8e5462c", "type": "github" }, "original": { "owner": "nix-community", - "ref": "release-24.11", "repo": "home-manager", "type": "github" } }, - "hyprcursor": { - "inputs": { - "hyprlang": [ - "hyprland", - "hyprlang" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1742215578, - "narHash": "sha256-zfs71PXVVPEe56WEyNi2TJQPs0wabU4WAlq0XV7GcdE=", - "owner": "hyprwm", - "repo": "hyprcursor", - "rev": "2fd36421c21aa87e2fe3bee11067540ae612f719", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprcursor", - "type": "github" - } - }, - "hyprgraphics": { - "inputs": { - "hyprutils": [ - "hyprland", - "hyprutils" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1743953322, - "narHash": "sha256-prQ5JKopXtzCMX2eT3dXbaVvGmzjMRE2bXStQDdazpM=", - "owner": "hyprwm", - "repo": "hyprgraphics", - "rev": "9d7f2687c84c729afbc3b13f7937655570f2978d", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprgraphics", - "type": "github" - } - }, - "hyprland": { - "inputs": { - "aquamarine": "aquamarine", - "hyprcursor": "hyprcursor", - "hyprgraphics": "hyprgraphics", - "hyprland-protocols": "hyprland-protocols", - "hyprland-qtutils": "hyprland-qtutils", - "hyprlang": "hyprlang", - "hyprutils": "hyprutils", - "hyprwayland-scanner": "hyprwayland-scanner", - "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks", - "systems": "systems", - "xdph": "xdph" - }, - "locked": { - "lastModified": 1744849150, - "narHash": "sha256-eaKqF4Oc7atN7Y2yTTeAOLN05q+G2YY0597ukgAD2Cs=", - "owner": "hyprwm", - "repo": "Hyprland", - "rev": "225e13c3cc83308175f0a9aa18cfa31324155034", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "Hyprland", - "type": "github" - } - }, - "hyprland-plugins": { - "inputs": { - "hyprland": [ - "hyprland" - ], - "nixpkgs": [ - "hyprland-plugins", - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland-plugins", - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1743950622, - "narHash": "sha256-8qjDapcQeDqxQUIm5gA0x6XZtowV/14bOs3K0tCSMoU=", - "owner": "hyprwm", - "repo": "hyprland-plugins", - "rev": "be6b9875dd5c586fb401d294bb98c31973849651", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprland-plugins", - "type": "github" - } - }, - "hyprland-protocols": { - "inputs": { - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1743714874, - "narHash": "sha256-yt8F7NhMFCFHUHy/lNjH/pjZyIDFNk52Q4tivQ31WFo=", - "owner": "hyprwm", - "repo": "hyprland-protocols", - "rev": "3a5c2bda1c1a4e55cc1330c782547695a93f05b2", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprland-protocols", - "type": "github" - } - }, - "hyprland-qt-support": { - "inputs": { - "hyprlang": [ - "hyprland", - "hyprland-qtutils", - "hyprlang" - ], - "nixpkgs": [ - "hyprland", - "hyprland-qtutils", - "nixpkgs" - ], - "systems": [ - "hyprland", - "hyprland-qtutils", - "systems" - ] - }, - "locked": { - "lastModified": 1737634706, - "narHash": "sha256-nGCibkfsXz7ARx5R+SnisRtMq21IQIhazp6viBU8I/A=", - "owner": "hyprwm", - "repo": "hyprland-qt-support", - "rev": "8810df502cdee755993cb803eba7b23f189db795", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprland-qt-support", - "type": "github" - } - }, - "hyprland-qtutils": { - "inputs": { - "hyprland-qt-support": "hyprland-qt-support", - "hyprlang": [ - "hyprland", - "hyprlang" - ], - "hyprutils": [ - "hyprland", - "hyprland-qtutils", - "hyprlang", - "hyprutils" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1739048983, - "narHash": "sha256-REhTcXq4qs3B3cCDtLlYDz0GZvmsBSh947Ub6pQWGTQ=", - "owner": "hyprwm", - "repo": "hyprland-qtutils", - "rev": "3504a293c8f8db4127cb0f7cfc1a318ffb4316f8", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprland-qtutils", - "type": "github" - } - }, - "hyprlang": { - "inputs": { - "hyprutils": [ - "hyprland", - "hyprutils" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1744468525, - "narHash": "sha256-9HySx+EtsbbKlZDlY+naqqOV679VdxP6x6fP3wxDXJk=", - "owner": "hyprwm", - "repo": "hyprlang", - "rev": "f1000c54d266e6e4e9d646df0774fac5b8a652df", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprlang", - "type": "github" - } - }, - "hyprutils": { - "inputs": { - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1743950287, - "narHash": "sha256-/6IAEWyb8gC/NKZElxiHChkouiUOrVYNq9YqG0Pzm4Y=", - "owner": "hyprwm", - "repo": "hyprutils", - "rev": "f2dc70e448b994cef627a157ee340135bd68fbc6", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprutils", - "type": "github" - } - }, - "hyprwayland-scanner": { - "inputs": { - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1739870480, - "narHash": "sha256-SiDN5BGxa/1hAsqhgJsS03C3t2QrLgBT8u+ENJ0Qzwc=", - "owner": "hyprwm", - "repo": "hyprwayland-scanner", - "rev": "206367a08dc5ac4ba7ad31bdca391d098082e64b", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprwayland-scanner", - "type": "github" - } - }, "nixpkgs": { "locked": { - "lastModified": 1744463964, - "narHash": "sha256-LWqduOgLHCFxiTNYi3Uj5Lgz0SR+Xhw3kr/3Xd0GPTM=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "2631b0b7abcea6e640ce31cd78ea58910d31e650", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-unstable": { - "locked": { - "lastModified": 1744463964, - "narHash": "sha256-LWqduOgLHCFxiTNYi3Uj5Lgz0SR+Xhw3kr/3Xd0GPTM=", + "lastModified": 1753939845, + "narHash": "sha256-K2ViRJfdVGE8tpJejs8Qpvvejks1+A4GQej/lBk5y7I=", "owner": "nixos", "repo": "nixpkgs", - "rev": "2631b0b7abcea6e640ce31cd78ea58910d31e650", + "rev": "94def634a20494ee057c76998843c015909d6311", "type": "github" }, "original": { @@ -413,108 +36,10 @@ "type": "github" } }, - "nixpkgs_2": { - "locked": { - "lastModified": 1744440957, - "narHash": "sha256-FHlSkNqFmPxPJvy+6fNLaNeWnF1lZSgqVCl/eWaJRc4=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "26d499fc9f1d567283d5d56fcf367edd815dba1d", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-24.11", - "repo": "nixpkgs", - "type": "github" - } - }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": "flake-compat", - "gitignore": "gitignore", - "nixpkgs": [ - "hyprland", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1742649964, - "narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=", - "owner": "cachix", - "repo": "git-hooks.nix", - "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "git-hooks.nix", - "type": "github" - } - }, "root": { "inputs": { "home-manager": "home-manager", - "hyprland": "hyprland", - "hyprland-plugins": "hyprland-plugins", - "nixpkgs": "nixpkgs_2", - "nixpkgs-unstable": "nixpkgs-unstable" - } - }, - "systems": { - "locked": { - "lastModified": 1689347949, - "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", - "owner": "nix-systems", - "repo": "default-linux", - "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default-linux", - "type": "github" - } - }, - "xdph": { - "inputs": { - "hyprland-protocols": [ - "hyprland", - "hyprland-protocols" - ], - "hyprlang": [ - "hyprland", - "hyprlang" - ], - "hyprutils": [ - "hyprland", - "hyprutils" - ], - "hyprwayland-scanner": [ - "hyprland", - "hyprwayland-scanner" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1744644585, - "narHash": "sha256-p0D/e4J6Sv6GSb+9u8OQcVHSE2gPNYB5ygIfGDyEiXQ=", - "owner": "hyprwm", - "repo": "xdg-desktop-portal-hyprland", - "rev": "be6771e754345f18244fb00aae5c9e5ab21ccc26", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "xdg-desktop-portal-hyprland", - "type": "github" + "nixpkgs": "nixpkgs" } } }, diff --git a/laptops/t14/flake.nix b/laptops/t14/flake.nix index 103c83c..42a0e29 100644 --- a/laptops/t14/flake.nix +++ b/laptops/t14/flake.nix @@ -3,67 +3,60 @@ # https://nix.dev/manual/nix/2.24/command-ref/new-cli/nix3-flake.html#flake-inputs inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; - nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; - # https://docs.github.com/en/rest/branches/branches?apiVersion=2022-11-28#get-a-branch - # nixpkgs-unstable.url = "github:randomizedcoder/nixpkgs/8f146535307f0168d758fe6fee6f52663cb11695";#iperf2_2.2.1 - # nixpkgs-unstable.url = "github:randomizedcoder/nixpkgs/c9580e24eb621d72eda63355d7c8dbfb1654d333"; - # https://github.com/NixOS/nix/issues/12022 - #nix flake lock --override-input nixpkgs /home/eelco/Dev/nixpkgs - #nix flake lock --override-input nixpkgs "/home/das/Downloads/nixpkgs - #nixpkgs.url = "/home/das/Downloads/nixpkgs"; - #nixpkgs = "../../../Downloads/nixpkgs/"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + # https://nixos-and-flakes.thiscute.world/nixos-with-flakes/start-using-home-manager home-manager = { - url = "github:nix-community/home-manager/release-24.11"; - # The `follows` keyword in inputs is used for inheritance. - # Here, `inputs.nixpkgs` of home-manager is kept consistent with - # the `inputs.nixpkgs` of the current flake, - # to avoid problems caused by different versions of nixpkgs. + url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; - hyprland.url = "github:hyprwm/Hyprland"; - hyprland-plugins = { - url = "github:hyprwm/hyprland-plugins"; - # https://github.com/hyprwm/hyprland-plugins - inputs.hyprland.follows = "hyprland"; - }; + # hyprland.url = "github:hyprwm/Hyprland"; + # hyprland-plugins = { + # url = "github:hyprwm/hyprland-plugins"; + # inputs.hyprland.follows = "hyprland"; + # }; }; #outputs = inputs@{ nixpkgs, home-manager, hyprland, ... }: - outputs = { self, nixpkgs, nixpkgs-unstable, home-manager, hyprland, ... }: + #outputs = { self, nixpkgs, home-manager, hyprland, ... }: + outputs = { self, nixpkgs, home-manager, ... }: let system = "x86_64-linux"; pkgs = import nixpkgs { inherit system; - config = { allowUnfree = true; }; - }; - # https://nixos.wiki/wiki/Flakes#Importing_packages_from_multiple_channels - # overlay-unstable = final: prev: { - # unstable = nixpkgs-unstable.legacyPackages.${prev.system}; - # }; - overlay-unstable = final: prev: { - unstable = import nixpkgs-unstable { - inherit system; - config = { allowUnfree = true; }; + config = { + allowUnfree = true; + allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ + # "nvidia-x11" + # "nvidia-settings" + # "nvidia-persistenced" + "google-chrome" + "android-studio" + "android-studio-stable" + ]; }; }; lib = nixpkgs.lib; in { nixosConfigurations = { t14 = lib.nixosSystem rec { - #system ="x86_64-linux"; inherit system; - specialArgs = { inherit hyprland; }; + specialArgs = { + unstable = pkgs; + }; modules = [ - ({ config, pkgs, ... }: { nixpkgs.overlays = [ overlay-unstable ]; }) ./configuration.nix - hyprland.nixosModules.default + #hyprland.nixosModules.default home-manager.nixosModules.home-manager { - home-manager.useGlobalPkgs = true; + # https://nix-community.github.io/home-manager/nixos-options.xhtml#nixos-opt-home-manager.useGlobalPkgs + #home-manager.useGlobalPkgs = true; # This disables the Home Manager options nixpkgs.*. home-manager.useUserPackages = true; - home-manager.users.das = import ./home.nix; + home-manager.users.das = { config, pkgs, ... }: { + imports = [ + ./home.nix + ]; + }; home-manager.extraSpecialArgs = specialArgs; # see also: https://github.com/HeinzDev/Hyprland-dotfiles/blob/main/flake.nix } diff --git a/laptops/t14/home.nix b/laptops/t14/home.nix index 8ea29d6..80ba6f8 100644 --- a/laptops/t14/home.nix +++ b/laptops/t14/home.nix @@ -1,20 +1,29 @@ { - hyprland, + #hyprland, config, pkgs, ... }: -#{ config, pkgs, ... }: -#{ config, inputs, pkgs, ... }: - -# sudo cp ./nixos/modules/* /etc/nixos/ -# sudo nixos-rebuild switch { - imports = [ - hyprland.homeManagerModules.default - # other imports to go here - ]; + # Ghostty configuration + programs.ghostty = { + enable = true; + # settings = { + # settings doesn't work + }; + # https://ghostty.zerebos.com/app/import-export + # no scorllback limit + # https://github.com/ghostty-org/ghostty/issues/111 + xdg.configFile."ghostty/config.toml".text = '' + term = xterm-256color + scrollback-limit = 10000001 + image-storage-limit = 320000001 + clipboard-write = allow + window-subtitle = working-directory + background-opacity = 0.91 + background-blur = 20 + ''; home = { username = "das"; @@ -26,127 +35,176 @@ # https://nix-community.github.io/home-manager/options.xhtml#opt-home.sessionVariables home.sessionVariables = { - QT_QPA_PLATFORM = "wayland"; - GI_TYPELIB_PATH = "/run/current-system/sw/lib/girepository-1.0"; - # disable wayland - NIXOS_OZONE_WL = "1"; - GOPRIVATE = "gitlab.com/sidenio/*"; - TERM = "xterm-256color"; + #NIXPKGS_ALLOW_UNFREE = "1"; + ELECTRON_OZONE_PLATFORM_HINT = "auto"; + + QT_QPA_PLATFORM = "wayland"; + # GI_TYPELIB_PATH = "/run/current-system/sw/lib/girepository-1.0"; + # disable wayland + # NIXOS_OZONE_WL = "1"; + GOPRIVATE = "gitlab.com/sidenio/*"; + TERM = "xterm-256color"; + + #HTTP_PROXY = "http://hp4.home:3128"; + #HTTPS_PROXY = "http://hp4.home:3128"; + #NO_PROXY = "localhost,127.0.0.1,::1,172.16.0.0/16"; + # You can also use ALL_PROXY or FTP_PROXY if needed + # ALL_PROXY = "http://hp4:3128"; }; home.packages = with pkgs; [ - # + # System/Info Tools killall hw-probe - # + lshw + hwloc gparted - # ncdu - # - hw-probe - lshw - # + neofetch + file + + # # Hyprland related + # waybar + # swaybg + # swaylock + # wl-clipboard + # wf-recorder + # grimblast + # hyprpaper + # hyprpicker + # hypridle + # hyprlock + + # Terminal Multiplexers tmux screen - # + + # # LLVM/Clang toolchain (needed for race detection and C/C++ builds) + # llvmPackages_20.clang-tools + # llvmPackages_20.lld + + # # LLVM C++ Standard Library, compiler runtime, and unwind library + # #llvmPackages_20.stdenv + # llvmPackages_20.libcxxStdenv + # llvmPackages_20.libcxxClang + # llvmPackages_20.libcxx # Provides libc++.so, libc++.a (libraries) + # llvmPackages_20.libcxx.dev # Provides C++ headers + # # do NOT include llvm.libc-full, because it will override glibc + # #llvm.libc-full + # llvmPackages_20.compiler-rt # Provides libclang_rt.builtins*.a + # llvmPackages_20.compiler-rt.dev # Provides libclang_rt headers + # llvmPackages_20.libunwind # Provides libunwind for exception handling + # llvmPackages_20.libunwind.dev # Provides libunwind headers + + # llvmPackages_20.libclang llvmPackages_20.libclang.dev llvmPackages_20.libclang.lib + + # Essential development libraries (minimal headers) + glibc glibc.dev glibc.static + libgcc libgcc.lib + gcc-unwrapped gcc-unwrapped.lib gcc-unwrapped.libgcc + stdenv.cc.cc.lib + zlib.dev + openssl openssl.dev openssl.out + ncurses.dev + libyaml.dev + + # Build Tools libgcc # https://nixos.wiki/wiki/C # https://search.nixos.org/packages?channel=24.05&show=gcc&from=0&size=50&sort=relevance&type=packages&query=gcc - gcc + #gcc automake gnumake #cmake pkg-config - # - # - # alsa-lib - # alsa-lib-with-plugins - # + gdb + + # Scripting/Utils perl #3.12.8 on 12th of Feb 2025 python3Full - # gawk jq git htop btop minicom - # + + bc + + # Compression bzip2 gzip lz4 zip unzip - xz - zstd - # + #xz + #zstd + + gnutar + + # File Transfer/Management rsync tree - file - # + + # Terminals alacritty kitty #https://ghostty.org/ ghostty - # + + # Networking ethtool iproute2 vlan tcpdump wireshark - unstable.iperf2 + iperf2 netperf flent bpftools fping - inetutils - # - hwloc - bpftools - # + inetutils # Includes telnet + netcat-gnu + + # Filesystem/Monitoring inotify-tools - # - # HP Printers - hplip - #hplipWithPlugin - # + + # SDR gnuradio hackrf gqrx cubicsdr - # - neofetch - # + + # Media vlc # ffmpeg moved to system package - #ffmpeg_7-full - #ffmpeg-full - # go + ffmpeg_7-full + + # Go Development # https://nixos.wiki/wiki/Go # https://nixos.org/manual/nixpkgs/stable/#sec-language-go # https://nixos.wiki/wiki/FAQ#How_can_I_install_a_package_from_unstable_while_remaining_on_the_stable_channel.3F libcap - gcc #gcc_multi #glibc_multi # thunderbird #go_1_23 - unstable.go - unstable.gopls - unstable.golint + go + gopls + golint golangci-lint - unstable.golangci-lint-langserver + golangci-lint-langserver # trunk is unfree, and i can't work out how to enable unfree #trunk-io # https://github.com/go-delve/delve - unstable.delve + delve # https://github.com/aarzilli/gdlv gdlv - unstable.buf - protobuf_27 - grpcurl + buf + #protobuf_27 + #grpcurl # https://github.com/go-gorm/gen # https://github.com/infobloxopen/protoc-gen-gorm/blob/main/example/postgres_arrays/buf.gen.yaml gorm-gentool @@ -154,34 +212,56 @@ #buf-language-server # https://tinygo.org/ #tinygo - # - graphviz - # + + # removing bazel and moving to the "nix develop" shell + # # https://github.com/bazelbuild/bazel/tags + # # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/development/tools/build-managers/bazel/bazel_7/default.nix#L524 + #bazel_7 + bazel-buildtools + bazelisk + + code-cursor + + # # https://github.com/bazel-contrib/bazel-gazelle/tags + # # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/by-name/ba/bazel-gazelle/package.nix#L26 + # bazel-gazelle + # bazel-buildtools + # bazelisk + # # https://github.com/buchgr/bazel-remote - maybe something to look at? + # # https://github.com/buildfarm/buildfarm?tab=readme-ov-file#helm-chart + + # Debugging/Profiling + graphviz # for pprof + strace + + # Diffing meld - # - # https://nixos.wiki/wiki/Helix + + # Editors helix - # rust + + # Rust Development # https://nixos.wiki/wiki/Rust - #pkgs.cargo - #pkgs.rustc cargo rustc rustfmt rust-analyzer clippy #clang_multi - # + + # Mobile Development flutter android-studio android-tools android-udev-rules - # - # debug - strace - # Gnome related / extensions + + nordic + gnome-themes-extra + #gnome-shell-extensions + + # Gnome Related / Extensions # gnomeExtensions.emoji-copy - # unstable.gnomeExtensions.workspace-switcher-manager + # gnomeExtensions.workspace-switcher-manager gnome-extension-manager gnome-usage dconf-editor @@ -207,13 +287,15 @@ # https://github.com/AstraExt/astra-monitor gnomeExtensions.astra-monitor libgtop - # + + # Office/Documents libreoffice-qt hunspell hunspellDicts.en_AU #hunspellDicts.en_US - # evince + + # Browsers # https://nixos.wiki/wiki/Firefox firefox # https://nixos.wiki/wiki/Chromium @@ -226,25 +308,28 @@ "--ozone-platform=wayland" ]; }) + + # Communication # https://nixos.wiki/wiki/Slack slack - # zoom-us - # + + # Screenshots/Screen Recording # https://wiki.nixos.org/wiki/Flameshot - (flameshot.override { enableWlrSupport = true; }) grim # screenshot functionality slurp # screenshot functionality - # - gimp-with-plugins - # simplescreenrecorder # https://wiki.nixos.org/wiki/Gpu-screen-recorder gpu-screen-recorder # CLI gpu-screen-recorder-gtk # GUI - # + + # Graphics + gimp-with-plugins + + # Text Editors gedit - # + + # Containers # https://nixos.wiki/wiki/Podman dive podman @@ -253,10 +338,8 @@ podman-tui podman-compose docker-buildx - # - rofi-wayland - wofi - # + + # Kubernetes #clickhouse #clickhouse-cli # https://github.com/int128/kubelogin @@ -274,19 +357,39 @@ kdash # k9s --kubeconfig=dev-d.kubeconfig k9s - # + + # Misc # https://github.com/jrincayc/ucblogo-code ucblogo # https://github.com/wagoodman/dive - dive + # dive # Duplicate removed # https://github.com/sharkdp/hyperfine hyperfine - # app launchers + + # App Launchers rofi-wayland wofi - # - # raspberry pi - rpi-imager + + # Raspberry Pi + #rpi-imager + + #silly + cmatrix + sl + vectoroids # game + # https://feralinteractive.github.io/gamemode/ + # sameboy + + #gpu monitoring + lact + + # virtual camera control + # v4l2-ctl --list-devices + v4l-utils + libsForQt5.kdenlive + + # Screenshot tool with Wayland support + (flameshot.override { enableWlrSupport = true; }) ]; # vscode @@ -297,47 +400,31 @@ programs.vscode = { enable = true; package = pkgs.vscode; - extensions = with pkgs.vscode-extensions; [ - bbenoist.nix + profiles.default.extensions = with pkgs.vscode-extensions; [ dart-code.dart-code dart-code.flutter golang.go hashicorp.terraform - #k6.k6 ms-azuretools.vscode-docker - # https://github.com/orgs/microsoft/repositories?q=vscode ms-vscode-remote.remote-containers ms-vscode-remote.remote-ssh - #ms-vscode-remote.remote-ssh-edit ms-vscode.makefile-tools ms-vscode.cmake-tools ms-vscode.cpptools - #ms-vscode.cpptools-extension-pack - #ms-vscode.cpptools-themes ms-vscode.hexeditor ms-vscode.makefile-tools ms-python.python ms-python.vscode-pylance - #ms-vscode.remote-explorer - #ms-vscode.remote-repositories - #ms-vscode.remote-server ms-kubernetes-tools.vscode-kubernetes-tools redhat.vscode-yaml rust-lang.rust-analyzer - #crates is depreciated - #serayuzgur.crates tamasfe.even-better-toml timonwong.shellcheck - #trunk.io zxh404.vscode-proto3 yzhang.markdown-all-in-one - #platformio.platformio-ide - github.copilot - # nix - #brettm12345.nixfmt.vscode jnoortheen.nix-ide - #jeff-hykin.better-nix-syntax rust-lang.rust-analyzer + bazelbuild.vscode-bazel ]; }; @@ -376,7 +463,6 @@ }; # https://nixos.wiki/wiki/OBS_Studio - # TODO add kernel module for virtual camera programs.obs-studio = { enable = true; plugins = with pkgs.obs-studio-plugins; [ @@ -408,7 +494,8 @@ font-antialiasing = "grayscale"; font-hinting = "slight"; gtk-theme = "Nordic"; - # toolkit-accessibility = true; + icon-theme = "Papirus-Dark"; + cursor-theme = "Adwaita"; toolkit-accessibility = false; }; "org/gnome/shell" = { @@ -423,6 +510,9 @@ "slack.desktop" "ghostty.desktop" ]; + # "org/gnome/shell/extensions/user-theme" = { + # name = "Nordic"; + # }; enabled-extensions = with pkgs.gnomeExtensions; [ blur-my-shell.extensionUuid gsconnect.extensionUuid @@ -430,38 +520,6 @@ }; }; - # disable wayland - # # https://nixos.wiki/wiki/Hyprland - # # https://josiahalenbrown.substack.com/p/installing-nixos-with-hyprland - # #programs.hyprland.enable = true; - # wayland.windowManager.hyprland = { - # # Whether to enable Hyprland wayland compositor - # enable = true; - # # The hyprland package to use - # package = pkgs.hyprland; - # # Whether to enable XWayland - # xwayland.enable = true; - - # https://wiki.hyprland.org/Nix/Hyprland-on-Home-Manager/ - # wayland.windowManager.hyprland.enable = true; # enable Hyprland - # Example: https://github.com/JaKooLit/NixOS-configs/blob/main/Ja-OS%20(configs%20using%20install%20script)/Asus-G15/hosts/G15-NixOS/config.nix#L144 - wayland.windowManager.hyprland = { - enable = true; - xwayland.enable = true; - #extraConfig = '' plugin = ${inputs.hy3.packages.${pkgs.system}.hy3}/lib/libhy3.so ''; - # plugins = [ - # inputs.hyprland-plugins.packages.${pkgs.system}.hyprbars - # # ... - #]; - }; - - # # Optional - # # Whether to enable hyprland-session.target on hyprland startup - # systemd.enable = true; - # }; - # # home.file.".config/hypr/hyprland.conf".text = '' - # # ''; - home.file."containers.conf" = { target = ".config/containers/containers.conf"; # https://docs.podman.io/en/v4.6.0/markdown/options/security-opt.html @@ -503,23 +561,10 @@ } ''; }; - home.file.".config/ghostty/ghostty.toml" = { - target = ".config/ghostty/ghostty.toml"; - text = '' - [window] - # Whether to show the scrollback sidebar. - sidebar = true - - # The width of the scrollback sidebar. - sidebar_width = 10 - - # Whether to show the scrollback sidebar on the left or right. - sidebar_position = "right" - ''; - }; + # https://github.com/colemickens/nixcfg/blob/1915d408ea28a5b7279f94df7a982dbf2cf692ef/mixins/ghostty.nix#L19 + # set at flake.nix level nixpkgs.config.allowUnfree = true; - #home.stateVersion = "23.11"; home.stateVersion = "24.11"; } diff --git a/laptops/t14/hosts.nix b/laptops/t14/hosts.nix index b60a4f0..e8f0a00 100644 --- a/laptops/t14/hosts.nix +++ b/laptops/t14/hosts.nix @@ -2,15 +2,17 @@ { networking.hosts = { - "172.16.40.198" = ["hp0" "hp0eth"]; # adi's room - "172.16.40.141" = ["hp0wifi"]; - "172.16.40.142" = ["hp1" "hp1eth"]; - "172.16.40.212" = ["hp2" "hp2eth"]; - "172.16.40.146" = ["hp3" "hp3eth"]; # savi's room - "172.16.40.130" = ["hp3wifi"]; - "172.16.50.232" = ["hp4" "hp4eth"]; # rack - "172.16.40.70" = ["hp5" "hp5eth"]; - "172.16.40.122" = ["pi5-1" "pi5-1-eth"]; - "172.16.40.62" = ["chromebox3" "chromebox3-eth"]; + "172.16.40.198" = [ "hp0" "hp0eth" ]; # adi's room + "172.16.40.141" = [ "hp0wifi" ]; + "172.16.40.142" = [ "hp1" "hp1eth" ]; + "172.16.40.212" = [ "hp2" "hp2eth" ]; + "172.16.40.146" = [ "hp3" "hp3eth" ]; # savi's room + "172.16.40.130" = [ "hp3wifi" ]; + "172.16.50.232" = [ "hp4" "hp4eth" ]; # rack + "172.16.40.72" = [ "hp5" "hp5eth" ]; + "172.16.40.122" = [ "pi5-1" "pi5-1-eth" ]; + "172.16.40.62" = [ "chromebox3" "chromebox3-eth" ]; + "172.16.40.46" = [ "l2" ]; + "127.0.0.1" = ["redpanda-0" ]; }; -} \ No newline at end of file +} diff --git a/laptops/t14/sysctl.nix b/laptops/t14/sysctl.nix index b6fa4a8..1b19452 100644 --- a/laptops/t14/sysctl.nix +++ b/laptops/t14/sysctl.nix @@ -2,6 +2,7 @@ { # https://www.kernel.org/doc/html/latest/networking/ip-sysctl.html + # https://www.l4sgear.com/ boot.kernel.sysctl = { # detect dead connections more quickly "net.ipv4.tcp_keepalive_intvl" = 30; @@ -16,6 +17,8 @@ "net.ipv4.tcp_wmem" = "4096 1000000 16000000"; #net.ipv4.tcp_rmem = 4096 131072 6291456 #net.ipv4.tcp_wmem = 4096 16384 4194304 + "net.ipv6.tcp_rmem" = "4096 1000000 16000000"; + "net.ipv6.tcp_wmem" = "4096 1000000 16000000"; # https://github.com/torvalds/linux/blob/master/Documentation/networking/ip-sysctl.rst?plain=1#L1042 # https://lwn.net/Articles/560082/ "net.ipv4.tcp_notsent_lowat" = "131072"; @@ -37,7 +40,27 @@ #net.core.rmem_max = 212992 #net.core.wmem_default = 212992 #net.core.wmem_max = 212992 - "net.ipv4.ip_local_port_range" = "1025 65535"; + "net.ipv4.ip_local_port_range" = "1026 65535"; #net.ipv4.ip_local_port_range ="32768 60999" + # + #net.ipv4.inet_peer_maxttl = 600 + #net.ipv4.inet_peer_minttl = 120 + #net.ipv4.ip_default_ttl = 64 + # we DO want to save the slow start in the route cache + "net.ipv4.tcp_no_ssthresh_metrics_save" = 0; + #net.ipv4.tcp_no_ssthresh_metrics_save = 1 + "net.ipv4.tcp_reflect_tos" = 1; + #net.ipv4.tcp_reflect_tos = 0 + "net.ipv4.tcp_rto_min_us" = 50000; #50ms + #net.ipv4.tcp_rto_min_us = 200000 #200ms + + # TCP optimizations for high performance + "net.ipv4.tcp_slow_start_after_idle" = 0; # Disable slow start after idle + "net.ipv4.tcp_fastopen" = 3; # Enable TCP Fast Open + + "net.ipv4.tcp_window_scaling" = 1; + "net.ipv4.tcp_sack" = 1; + "net.ipv4.tcp_fack" = 1; + "net.ipv4.tcp_fin_timeout" = 30; }; -} \ No newline at end of file +} diff --git a/laptops/t14/systemPackages.nix b/laptops/t14/systemPackages.nix index 7436b7f..a652645 100644 --- a/laptops/t14/systemPackages.nix +++ b/laptops/t14/systemPackages.nix @@ -4,12 +4,12 @@ ... }: { + # set at flake.nix level nixpkgs.config.allowUnfree = true; # $ nix search wget environment.systemPackages = with pkgs; [ - # vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. - # wget + # Basic system tools psmisc vim curl @@ -20,45 +20,35 @@ iptables pciutils usbutils - pciutils - virt-manager - pkgs.gnomeExtensions.appindicator iw wirelesstools wpa_supplicant - #wpa_supplicant_ro_ssids lldpd #snmp seems to be needed by lldpd net-snmp - unstable.neofetch + neofetch + libxml2 # Added for bazel/clang development - # https://wiki.nixos.org/wiki/Flameshot - #(flameshot.override { enableWlrSupport = true; }) - - # hyprland - unstable.hyprland - swww # for wallpapers - xdg-desktop-portal-gtk - xdg-desktop-portal-hyprland + # Wayland support xwayland meson wayland-protocols wayland-utils wl-clipboard - wlroots - # # - # #nvidia - # unstable.vdpauinfo # sudo vainfo - # unstable.libva-utils # sudo vainfo - # # https://discourse.nixos.org/t/nvidia-open-breaks-hardware-acceleration/58770/2 - # # - # unstable.ffmpeg-full - # # - # # https://nixos.wiki/wiki/CUDA - # unstable.cudatoolkit - # unstable.linuxPackages.nvidia_x11 - # unstable.libGLU - # unstable.libGL + # Screen capture and PipeWire debugging + grim + slurp + wf-recorder + pipewire + xdg-desktop-portal-gnome + + xscreensaver + + clinfo + lact + + # https://wiki.nixos.org/wiki/Flameshot + #(flameshot.override { enableWlrSupport = true; }) ]; -} \ No newline at end of file +} From 7ae72331c25ac369fb13e59ad2bc2a7d1ed21c68 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Fri, 22 Aug 2025 16:57:52 -0700 Subject: [PATCH 09/23] clickhouse service --- desktop/l/clickhouse-service.nix | 232 ++++++++++++++++++++++++++++++ desktop/l/configuration.nix | 3 +- desktop/l/flake.lock | 12 +- desktop/l/home.nix | 22 ++- desktop/l2/clickhouse-service.nix | 232 ++++++++++++++++++++++++++++++ desktop/l2/configuration.nix | 7 + desktop/l2/irq-affinity.nix | 64 ++++++--- 7 files changed, 545 insertions(+), 27 deletions(-) create mode 100644 desktop/l/clickhouse-service.nix create mode 100644 desktop/l2/clickhouse-service.nix diff --git a/desktop/l/clickhouse-service.nix b/desktop/l/clickhouse-service.nix new file mode 100644 index 0000000..c9e2dee --- /dev/null +++ b/desktop/l/clickhouse-service.nix @@ -0,0 +1,232 @@ +# +# ClickHouse service with enhanced security restrictions +# + +{ config, lib, pkgs, ... }: + +let + clickhouseDataDir = "/var/lib/clickhouse"; + clickhouseLogDir = "/var/log/clickhouse"; + clickhouseConfigDir = "/etc/clickhouse-server"; + clickhouseRunDir = "/run/clickhouse-server"; + +in { + # Enable ClickHouse service + services.clickhouse.enable = true; + + # Override the default ClickHouse service with enhanced security + systemd.services.clickhouse = { + + serviceConfig = { + # Resource limits - ClickHouse is memory and CPU intensive + Slice = "clickhouse.slice"; + MemoryHigh = "2G"; + MemoryMax = "4G"; + CPUQuota = "50%"; + TasksMax = 50000; # ClickHouse can spawn many threads (increased from 1000). Clickhouse warns if this is below 30k. + LimitNPROC = 50000; # Increased for concurrent operations (increased from 2000) + LimitNOFILE = 1048576; # 65536; # ClickHouse needs many file descriptors + Nice = 0; # -20 is the highest priority, 0 is the default + + # Security restrictions - ClickHouse needs minimal privileges + NoNewPrivileges = true; + ProtectSystem = "strict"; + ProtectHome = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectControlGroups = true; + ProtectKernelLogs = true; + PrivateDevices = true; + PrivateTmp = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + RestrictNamespaces = true; + PrivateUsers = true; # Create user namespace - service sees itself as root internally + LockPersonality = true; + ProtectHostname = true; + ProtectClock = true; + # MemoryDenyWriteExecute = true; # Disabled for ClickHouse JIT compilation + UMask = "0077"; # More restrictive: only owner can read/write ("0027" is the default, and allows group and other to read/write) + + # Network capabilities - ClickHouse needs network access for queries + # CAP_NET_BIND_SERVICE: Required for binding to ports (default 9000, 8123) + # CAP_SYS_NICE: Required for setting process priority + # CAP_SYS_RESOURCE: Required for resource limits and CPU affinity + CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" "CAP_SYS_NICE" "CAP_SYS_RESOURCE" ]; + + # Address families - ClickHouse needs IPv4 and IPv6 + RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; + + # System call architecture restrictions + SystemCallArchitectures = [ "native" ]; + + # System call filtering - ClickHouse needs database-related system calls + # Relaxed to allow CPU affinity and resource management + SystemCallFilter = [ + "@system-service" + "~@privileged" + "~@mount" + "~@debug" + "~@module" + "~@reboot" + "~@swap" + "~@cpu-emulation" + "~@obsolete" + "~@raw-io" + "~@resources" + # Allow specific system calls that ClickHouse needs for CPU affinity and scheduling + "sched_setaffinity" + "sched_getaffinity" + "setpriority" + "getpriority" + "sched_setparam" + "sched_getparam" + "sched_setscheduler" + "sched_getscheduler" + "sched_setattr" + "sched_getattr" + # Allow system calls needed for JIT compilation + "mprotect" + "mmap" + "munmap" + ]; + + # File system restrictions + ReadWritePaths = [ + clickhouseDataDir + clickhouseLogDir + clickhouseRunDir + "/tmp" + "/var/tmp" + "/proc/self" + ]; + ReadOnlyPaths = [ + "/nix/store" + "${pkgs.clickhouse}" + clickhouseConfigDir + "/etc/resolv.conf" + "/etc/hosts" + "/etc/nsswitch.conf" + "/etc/ssl" + "/etc/ca-bundle.crt" + "/etc/ssl/certs" + "/usr/share/zoneinfo" + "/etc/localtime" + ]; + + # User/group restrictions + User = "clickhouse"; + Group = "clickhouse"; + + # Runtime directory + RuntimeDirectory = "clickhouse-server"; + + # Restart policy + Restart = "always"; + RestartSec = "1s"; + + # Additional security measures + RemoveIPC = true; # Clean up IPC objects + ProtectProc = "default"; # Allow access to process info and /proc/net + ProcSubset = "pid"; # Only allow access to own process info + + # Environment + Environment = [ + "PATH=${pkgs.clickhouse}/bin" + "CLICKHOUSE_WATCHDOG_ENABLE=0" + ]; + PIDFile = "${clickhouseRunDir}/clickhouse-server.pid"; + + # Device access - ClickHouse doesn't need special device access + DeviceAllow = [ + "/dev/null rw" + "/dev/zero rw" + "/dev/random r" + "/dev/urandom r" + ]; + + # # IP address restrictions - Only allow local connections by default + # # Modify this if you need external access + # IPAddressAllow = [ + # "localhost" + # "127.0.0.1" + # "::1" + # ]; + # IPAddressDeny = [ + # "any" + # ]; + + # Supplementary groups - ClickHouse doesn't need additional groups + SupplementaryGroups = []; + + # Keyring mode - ClickHouse doesn't need keyring access + KeyringMode = "private"; + + # Delegate - ClickHouse doesn't need cgroup delegation + Delegate = false; + + # Notify access - Only main process can alter service state + NotifyAccess = "main"; + }; + }; + + # Create dedicated slice for ClickHouse with resource limits + systemd.slices.clickhouse = { + description = "ClickHouse database slice"; + sliceConfig = { + MemoryHigh = "2G"; + MemoryMax = "4G"; + CPUQuota = "50%"; + TasksMax = 50000; # ClickHouse can spawn many threads (increased from 1000). Clickhouse warns if this is below 30k. + }; + }; + + # Create required directories with correct ownership + systemd.tmpfiles.rules = [ + "d ${clickhouseDataDir} 0755 clickhouse clickhouse - -" + "d ${clickhouseLogDir} 0755 clickhouse clickhouse - -" + "d ${clickhouseRunDir} 0755 clickhouse clickhouse - -" + "d ${clickhouseConfigDir} 0755 clickhouse clickhouse - -" + ]; + + # Firewall rules for ClickHouse (only if you need external access) + # By default, ClickHouse only listens on localhost + # Uncomment and modify if you need external access + # networking.firewall.allowedTCPPorts = [ 9000 8123 ]; + + # # Additional security hardening + # security.apparmor.enable = true; + + # Optional: Create AppArmor profile for ClickHouse + # This would require additional configuration in a separate file + # security.apparmor.profiles = { + # "clickhouse" = { + # profile = '' + # #include + # profile clickhouse flags=(attach_disconnected) { + # #include + # #include + # + # ${clickhouseDataDir}/** rw, + # ${clickhouseLogDir}/** rw, + # ${clickhouseConfigDir}/** r, + # ${clickhouseRunDir}/** rw, + # + # /nix/store/** r, + # /tmp/** rw, + # /var/tmp/** rw, + # + # /proc/sys/kernel/hostname r, + # /proc/sys/kernel/random/uuid r, + # /proc/net/** r, + # /proc/self/** r, + # + # /dev/null rw, + # /dev/zero r, + # /dev/random r, + # /dev/urandom r, + # } + # ''; + # }; + # }; +} diff --git a/desktop/l/configuration.nix b/desktop/l/configuration.nix index df59ce4..d8e463f 100644 --- a/desktop/l/configuration.nix +++ b/desktop/l/configuration.nix @@ -36,6 +36,7 @@ ./prometheus.nix ./grafana.nix # clickhouse + ./clickhouse-service.nix #./docker-compose.nix ./docker-daemon.nix #./smokeping.nix @@ -196,7 +197,7 @@ systemd.services.modem-manager.enable = false; systemd.services."dbus-org.freedesktop.ModemManager1".enable = false; - services.clickhouse.enable = false; + # ClickHouse enabled in clickhouse-service.nix # environment.variables defined in hardware-graphics.nix # environment.sessionVariables = { diff --git a/desktop/l/flake.lock b/desktop/l/flake.lock index 0f69cf8..b0a3e41 100644 --- a/desktop/l/flake.lock +++ b/desktop/l/flake.lock @@ -7,11 +7,11 @@ ] }, "locked": { - "lastModified": 1753709185, - "narHash": "sha256-fU0XPSNudRJHvbeMK2qWBXEbfd77t7r+e9V2L9ON5kI=", + "lastModified": 1755755322, + "narHash": "sha256-spCxkNihCk3uT3LUrUwzdEAjLA/E0EtEgF3KVI05nlM=", "owner": "nix-community", "repo": "home-manager", - "rev": "20cf285e9f8e5e3968abca80081c03ea96e7ea73", + "rev": "282b4c98de97da6667cb03de4f427371734bc39c", "type": "github" }, "original": { @@ -22,11 +22,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1753549186, - "narHash": "sha256-Znl7rzuxKg/Mdm6AhimcKynM7V3YeNDIcLjBuoBcmNs=", + "lastModified": 1755615617, + "narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=", "owner": "nixos", "repo": "nixpkgs", - "rev": "17f6bd177404d6d43017595c5264756764444ab8", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", "type": "github" }, "original": { diff --git a/desktop/l/home.nix b/desktop/l/home.nix index 80ba6f8..da1d85b 100644 --- a/desktop/l/home.nix +++ b/desktop/l/home.nix @@ -128,7 +128,8 @@ jq git htop - btop + # using btop-romc + #btop minicom bc @@ -379,9 +380,28 @@ vectoroids # game # https://feralinteractive.github.io/gamemode/ # sameboy + # https://github.com/dreamchess/dreamchess + # dreamchess + # https://github.com/ccMSC/glava + # glava + # gzdoom needs .wad files + # https://github.com/colemickens/gzdoom + # gzdoom + + # https://github.com/sonald/blur-effect + # blur-effect #gpu monitoring + rocmPackages.rocm-smi lact + # https://github.com/aristocratos/btop + btop-rocm + + # https://github.com/ollama/ollama + ollama-rocm + rocmPackages.rccl + # https://jeffser.com/alpaca/ + alpaca # virtual camera control # v4l2-ctl --list-devices diff --git a/desktop/l2/clickhouse-service.nix b/desktop/l2/clickhouse-service.nix new file mode 100644 index 0000000..c9e2dee --- /dev/null +++ b/desktop/l2/clickhouse-service.nix @@ -0,0 +1,232 @@ +# +# ClickHouse service with enhanced security restrictions +# + +{ config, lib, pkgs, ... }: + +let + clickhouseDataDir = "/var/lib/clickhouse"; + clickhouseLogDir = "/var/log/clickhouse"; + clickhouseConfigDir = "/etc/clickhouse-server"; + clickhouseRunDir = "/run/clickhouse-server"; + +in { + # Enable ClickHouse service + services.clickhouse.enable = true; + + # Override the default ClickHouse service with enhanced security + systemd.services.clickhouse = { + + serviceConfig = { + # Resource limits - ClickHouse is memory and CPU intensive + Slice = "clickhouse.slice"; + MemoryHigh = "2G"; + MemoryMax = "4G"; + CPUQuota = "50%"; + TasksMax = 50000; # ClickHouse can spawn many threads (increased from 1000). Clickhouse warns if this is below 30k. + LimitNPROC = 50000; # Increased for concurrent operations (increased from 2000) + LimitNOFILE = 1048576; # 65536; # ClickHouse needs many file descriptors + Nice = 0; # -20 is the highest priority, 0 is the default + + # Security restrictions - ClickHouse needs minimal privileges + NoNewPrivileges = true; + ProtectSystem = "strict"; + ProtectHome = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectControlGroups = true; + ProtectKernelLogs = true; + PrivateDevices = true; + PrivateTmp = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + RestrictNamespaces = true; + PrivateUsers = true; # Create user namespace - service sees itself as root internally + LockPersonality = true; + ProtectHostname = true; + ProtectClock = true; + # MemoryDenyWriteExecute = true; # Disabled for ClickHouse JIT compilation + UMask = "0077"; # More restrictive: only owner can read/write ("0027" is the default, and allows group and other to read/write) + + # Network capabilities - ClickHouse needs network access for queries + # CAP_NET_BIND_SERVICE: Required for binding to ports (default 9000, 8123) + # CAP_SYS_NICE: Required for setting process priority + # CAP_SYS_RESOURCE: Required for resource limits and CPU affinity + CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" "CAP_SYS_NICE" "CAP_SYS_RESOURCE" ]; + + # Address families - ClickHouse needs IPv4 and IPv6 + RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; + + # System call architecture restrictions + SystemCallArchitectures = [ "native" ]; + + # System call filtering - ClickHouse needs database-related system calls + # Relaxed to allow CPU affinity and resource management + SystemCallFilter = [ + "@system-service" + "~@privileged" + "~@mount" + "~@debug" + "~@module" + "~@reboot" + "~@swap" + "~@cpu-emulation" + "~@obsolete" + "~@raw-io" + "~@resources" + # Allow specific system calls that ClickHouse needs for CPU affinity and scheduling + "sched_setaffinity" + "sched_getaffinity" + "setpriority" + "getpriority" + "sched_setparam" + "sched_getparam" + "sched_setscheduler" + "sched_getscheduler" + "sched_setattr" + "sched_getattr" + # Allow system calls needed for JIT compilation + "mprotect" + "mmap" + "munmap" + ]; + + # File system restrictions + ReadWritePaths = [ + clickhouseDataDir + clickhouseLogDir + clickhouseRunDir + "/tmp" + "/var/tmp" + "/proc/self" + ]; + ReadOnlyPaths = [ + "/nix/store" + "${pkgs.clickhouse}" + clickhouseConfigDir + "/etc/resolv.conf" + "/etc/hosts" + "/etc/nsswitch.conf" + "/etc/ssl" + "/etc/ca-bundle.crt" + "/etc/ssl/certs" + "/usr/share/zoneinfo" + "/etc/localtime" + ]; + + # User/group restrictions + User = "clickhouse"; + Group = "clickhouse"; + + # Runtime directory + RuntimeDirectory = "clickhouse-server"; + + # Restart policy + Restart = "always"; + RestartSec = "1s"; + + # Additional security measures + RemoveIPC = true; # Clean up IPC objects + ProtectProc = "default"; # Allow access to process info and /proc/net + ProcSubset = "pid"; # Only allow access to own process info + + # Environment + Environment = [ + "PATH=${pkgs.clickhouse}/bin" + "CLICKHOUSE_WATCHDOG_ENABLE=0" + ]; + PIDFile = "${clickhouseRunDir}/clickhouse-server.pid"; + + # Device access - ClickHouse doesn't need special device access + DeviceAllow = [ + "/dev/null rw" + "/dev/zero rw" + "/dev/random r" + "/dev/urandom r" + ]; + + # # IP address restrictions - Only allow local connections by default + # # Modify this if you need external access + # IPAddressAllow = [ + # "localhost" + # "127.0.0.1" + # "::1" + # ]; + # IPAddressDeny = [ + # "any" + # ]; + + # Supplementary groups - ClickHouse doesn't need additional groups + SupplementaryGroups = []; + + # Keyring mode - ClickHouse doesn't need keyring access + KeyringMode = "private"; + + # Delegate - ClickHouse doesn't need cgroup delegation + Delegate = false; + + # Notify access - Only main process can alter service state + NotifyAccess = "main"; + }; + }; + + # Create dedicated slice for ClickHouse with resource limits + systemd.slices.clickhouse = { + description = "ClickHouse database slice"; + sliceConfig = { + MemoryHigh = "2G"; + MemoryMax = "4G"; + CPUQuota = "50%"; + TasksMax = 50000; # ClickHouse can spawn many threads (increased from 1000). Clickhouse warns if this is below 30k. + }; + }; + + # Create required directories with correct ownership + systemd.tmpfiles.rules = [ + "d ${clickhouseDataDir} 0755 clickhouse clickhouse - -" + "d ${clickhouseLogDir} 0755 clickhouse clickhouse - -" + "d ${clickhouseRunDir} 0755 clickhouse clickhouse - -" + "d ${clickhouseConfigDir} 0755 clickhouse clickhouse - -" + ]; + + # Firewall rules for ClickHouse (only if you need external access) + # By default, ClickHouse only listens on localhost + # Uncomment and modify if you need external access + # networking.firewall.allowedTCPPorts = [ 9000 8123 ]; + + # # Additional security hardening + # security.apparmor.enable = true; + + # Optional: Create AppArmor profile for ClickHouse + # This would require additional configuration in a separate file + # security.apparmor.profiles = { + # "clickhouse" = { + # profile = '' + # #include + # profile clickhouse flags=(attach_disconnected) { + # #include + # #include + # + # ${clickhouseDataDir}/** rw, + # ${clickhouseLogDir}/** rw, + # ${clickhouseConfigDir}/** r, + # ${clickhouseRunDir}/** rw, + # + # /nix/store/** r, + # /tmp/** rw, + # /var/tmp/** rw, + # + # /proc/sys/kernel/hostname r, + # /proc/sys/kernel/random/uuid r, + # /proc/net/** r, + # /proc/self/** r, + # + # /dev/null rw, + # /dev/zero r, + # /dev/random r, + # /dev/urandom r, + # } + # ''; + # }; + # }; +} diff --git a/desktop/l2/configuration.nix b/desktop/l2/configuration.nix index 6b9bba2..688ab2a 100644 --- a/desktop/l2/configuration.nix +++ b/desktop/l2/configuration.nix @@ -197,6 +197,13 @@ systemd.extraConfig = "CPUAffinity=8,20,9,21,10,22,11,23"; systemd.user.extraConfig = "CPUAffinity=8,20,9,21,10,22,11,23"; + #systemd.settings.Manager = { + # CPUAffinity = "8,20,9,21,10,22,11,23"; + #}; + # systemd.user.settings.Manager = { + # CPUAffinity = "8,20,9,21,10,22,11,23"; + # }; + } # end \ No newline at end of file diff --git a/desktop/l2/irq-affinity.nix b/desktop/l2/irq-affinity.nix index 098c82b..41e3570 100644 --- a/desktop/l2/irq-affinity.nix +++ b/desktop/l2/irq-affinity.nix @@ -27,28 +27,43 @@ let # Distribute Ethernet IRQs across ethernet cores echo "Distributing Ethernet IRQs across cores: ${ethernetCores}" irq_index=0 + + # Get Ethernet interface PCI devices dynamically for interface in $(${pkgs.iproute2}/bin/ip link show | ${pkgs.gnugrep}/bin/grep -E "enp|eth" | ${pkgs.gawk}/bin/awk -F: '{print $2}' | ${pkgs.gnused}/bin/sed 's/ //g'); do - for irq in $(${pkgs.gnugrep}/bin/grep "$interface" /proc/interrupts | ${pkgs.gawk}/bin/awk '{print $1}' | ${pkgs.gnused}/bin/sed 's/://'); do - cpu_index=$((irq_index % 8)) - # Convert index to actual CPU number - case $cpu_index in - 0) cpu=0 ;; - 1) cpu=12 ;; - 2) cpu=1 ;; - 3) cpu=13 ;; - 4) cpu=2 ;; - 5) cpu=14 ;; - 6) cpu=3 ;; - 7) cpu=15 ;; - esac - if [[ -e "/proc/irq/$irq/smp_affinity_list" ]]; then - echo "$cpu" > "/proc/irq/$irq/smp_affinity_list" - echo "Ethernet IRQ $irq ($interface) -> CPU $cpu" + # Get PCI device for this interface using /sys/class/net/ + pci_device_path="/sys/class/net/$interface/device" + if [ -L "$pci_device_path" ]; then + pci_device=$(basename $(readlink "$pci_device_path")) + if [ -n "$pci_device" ]; then + echo "Processing Ethernet interface $interface (PCI: $pci_device)" + # Get IRQs for this PCI device + for irq in $(cat /proc/interrupts | ${pkgs.gnugrep}/bin/grep "$pci_device" | ${pkgs.gawk}/bin/awk '{print $1}' | ${pkgs.gnused}/bin/sed 's/://'); do + cpu_index=$((irq_index % 8)) + # Convert index to actual CPU number + case $cpu_index in + 0) cpu=0 ;; + 1) cpu=12 ;; + 2) cpu=1 ;; + 3) cpu=13 ;; + 4) cpu=2 ;; + 5) cpu=14 ;; + 6) cpu=3 ;; + 7) cpu=15 ;; + esac + if [[ -e "/proc/irq/$irq/smp_affinity_list" ]]; then + echo "$cpu" > "/proc/irq/$irq/smp_affinity_list" + echo "Ethernet IRQ $irq ($interface) -> CPU $cpu" + else + echo "Warning: Ethernet IRQ $irq not found" + fi + irq_index=$((irq_index + 1)) + done else - echo "Warning: Ethernet IRQ $irq not found" + echo "Warning: Could not determine PCI device for interface $interface" fi - irq_index=$((irq_index + 1)) - done + else + echo "Warning: Could not find device path for interface $interface" + fi done # Optimize WiFi default queues across dedicated L cores @@ -111,6 +126,17 @@ in { RemainAfterExit = true; StandardOutput = "journal"; StandardError = "journal"; + # Add capabilities needed for IRQ affinity + CapabilityBoundingSet = [ "SYS_RAWIO" "SYS_ADMIN" ]; + AmbientCapabilities = [ "SYS_RAWIO" "SYS_ADMIN" ]; + # Run as root with proper permissions + User = "root"; + Group = "root"; + # Allow new privileges (needed for IRQ affinity) + NoNewPrivileges = false; + # Add security options + ProtectProc = "no"; + ReadWritePaths = [ "/proc/irq" ]; }; }; } From 341cc848e0e866dfc843afc753b659c9b4038ed8 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Tue, 2 Sep 2025 07:44:49 -0700 Subject: [PATCH 10/23] 2025_09_02 --- desktop/l/configuration.nix | 8 + desktop/l/corsair-fan-control.nix | 76 +++++++++ desktop/l/flake.lock | 12 +- desktop/l/gpu-fan-control.nix | 105 +++++++++++++ desktop/l/hardware-configuration.nix | 6 +- desktop/l/home.nix | 90 ++++++++++- desktop/l/nginx.nix | 220 +++++++++++++++++++++++++++ desktop/l/ollama-service.nix | 74 +++++++++ desktop/l/systemPackages.nix | 4 + desktop/l2/configuration.nix | 11 +- desktop/l2/flake.lock | 26 ++-- desktop/l2/home.nix | 32 ++-- desktop/l2/systemPackages.nix | 1 + desktop/l2/systemd-slices.nix | 4 +- 14 files changed, 622 insertions(+), 47 deletions(-) create mode 100644 desktop/l/corsair-fan-control.nix create mode 100644 desktop/l/gpu-fan-control.nix create mode 100644 desktop/l/nginx.nix create mode 100644 desktop/l/ollama-service.nix diff --git a/desktop/l/configuration.nix b/desktop/l/configuration.nix index d8e463f..4f0b88a 100644 --- a/desktop/l/configuration.nix +++ b/desktop/l/configuration.nix @@ -37,11 +37,17 @@ ./grafana.nix # clickhouse ./clickhouse-service.nix + # GPU fan control + ./gpu-fan-control.nix + # Corsair fan control + ./corsair-fan-control.nix #./docker-compose.nix ./docker-daemon.nix #./smokeping.nix #./distributed-builds.nix #./hyprland.nix + ./nginx.nix + ./ollama-service.nix ]; boot = { @@ -67,6 +73,8 @@ # #"nomodeset" # ]; + kernelParams = [ "acpi_enforce_resources=lax" ]; + initrd.kernelModules = [ "amdgpu" ]; diff --git a/desktop/l/corsair-fan-control.nix b/desktop/l/corsair-fan-control.nix new file mode 100644 index 0000000..ecd1ed4 --- /dev/null +++ b/desktop/l/corsair-fan-control.nix @@ -0,0 +1,76 @@ +# +# Corsair Commander Fan Control Service +# +# This service sets the fan speed for Corsair Commander controlled fans at boot time. +# Uses liquidctl to control the fan speed. +# + +{ config, lib, pkgs, ... }: + +let + # Configuration - modify these values for your setup + fanNumber = "fan1"; # Change this to control different fans (fan1, fan2, fan3, etc.) + fanSpeed = 100; # Change this to desired fan speed (0-100) + + # Script to set fan speed using liquidctl + corsairFanControlScript = pkgs.writeShellScript "corsair-fan-control" '' + #!/bin/sh + set -eu + + FAN_NUMBER="${fanNumber}" + FAN_SPEED="${toString fanSpeed}" + + echo "Setting Corsair Commander ${fanNumber} speed to ${toString fanSpeed}%" + + # Check if liquidctl is available + if ! command -v liquidctl >/dev/null 2>&1; then + echo "Error: liquidctl not found. Please install it first." + exit 1 + fi + + # Set the fan speed + # Note: fanSpeed is interpolated by Nix, so we use toString to convert the integer to string + if liquidctl --match corsair set "$FAN_NUMBER" speed "$FAN_SPEED"; then + echo "Fan speed set successfully to ${toString fanSpeed}%" + exit 0 + else + echo "Failed to set fan speed" + exit 1 + fi + ''; + +in { + + systemd.services.corsair-fan-control = { + description = "Set Corsair Commander fan speed at boot"; + wantedBy = [ "multi-user.target" ]; + after = [ "multi-user.target" "udev.service" ]; + + serviceConfig = { + Type = "oneshot"; + ExecStart = "${corsairFanControlScript}"; + RemainAfterExit = true; + StandardOutput = "journal"; + StandardError = "journal"; + # Run as root since liquidctl needs elevated privileges + User = "root"; + Group = "root"; + }; + }; + + # Optional: Add a manual service for runtime fan control + systemd.user.services.corsair-fan-control-manual = { + description = "Manual Corsair fan control (user service)"; + wantedBy = [ "default.target" ]; + + serviceConfig = { + Type = "oneshot"; + ExecStart = "${corsairFanControlScript}"; + RemainAfterExit = true; + StandardOutput = "journal"; + StandardError = "journal"; + # Note: This will need sudo privileges to work + }; + }; + +} diff --git a/desktop/l/flake.lock b/desktop/l/flake.lock index b0a3e41..79c2ebf 100644 --- a/desktop/l/flake.lock +++ b/desktop/l/flake.lock @@ -7,11 +7,11 @@ ] }, "locked": { - "lastModified": 1755755322, - "narHash": "sha256-spCxkNihCk3uT3LUrUwzdEAjLA/E0EtEgF3KVI05nlM=", + "lastModified": 1756734952, + "narHash": "sha256-H6jmduj4QIncLPAPODPSG/8ry9lpr1kRq6fYytU52qU=", "owner": "nix-community", "repo": "home-manager", - "rev": "282b4c98de97da6667cb03de4f427371734bc39c", + "rev": "29ab63bbb3d9eee4a491f7ce701b189becd34068", "type": "github" }, "original": { @@ -22,11 +22,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1755615617, - "narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=", + "lastModified": 1756542300, + "narHash": "sha256-tlOn88coG5fzdyqz6R93SQL5Gpq+m/DsWpekNFhqPQk=", "owner": "nixos", "repo": "nixpkgs", - "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "rev": "d7600c775f877cd87b4f5a831c28aa94137377aa", "type": "github" }, "original": { diff --git a/desktop/l/gpu-fan-control.nix b/desktop/l/gpu-fan-control.nix new file mode 100644 index 0000000..4516490 --- /dev/null +++ b/desktop/l/gpu-fan-control.nix @@ -0,0 +1,105 @@ +# +# GPU Fan Control Service +# +# This service sets the fan speed for AMD GPUs at boot time. +# Configure the GPU bus address and desired fan speed below. +# + +{ config, lib, pkgs, ... }: + +let + # Configuration - modify these values for your setup + gpuBus = "0000:63:00.0"; # Change this to your GPU's bus address + + #[nix-shell:~]$ lspci | grep -i radeon + #44:00.0 Display controller: Advanced Micro Devices, Inc. [AMD/ATI] Vega 20 [Radeon Pro VII/Radeon Instinct MI50 32GB] + #63:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Navi 10 [Radeon Pro W5700] + + fanSpeedPercent = 50; # Change this to desired fan speed (0-100) + + # Calculate the actual PWM value based on percentage + fanSpeedPWM = builtins.toString (fanSpeedPercent * 255 / 100); + + # Script to set fan speed + fanControlScript = pkgs.writeShellScript "gpu-fan-control" '' + #!/bin/sh + set -eu + + BUS="${gpuBus}" + FAN_SPEED="${fanSpeedPWM}" + + echo "Setting GPU fan speed to ${toString fanSpeedPercent}% (PWM: $FAN_SPEED) for bus $BUS" + + # Find the GPU device and set fan speed + for dev in /sys/class/drm/card*/device; do + if grep -q "PCI_SLOT_NAME=$BUS" "$dev/uevent" 2>/dev/null; then + echo "Found GPU device at $dev" + + # Find the hwmon directory + for hwmon in "$dev"/hwmon/hwmon*; do + if [ -d "$hwmon" ]; then + echo "Found hwmon at $hwmon" + + # Check if fan control files exist + if [ -f "$hwmon/pwm1_enable" ] && [ -f "$hwmon/pwm1" ]; then + echo "Setting fan control mode to manual" + echo 1 > "$hwmon/pwm1_enable" + + # Get max PWM value + max_pwm=$(cat "$hwmon/pwm1_max" 2>/dev/null || echo 255) + echo "Max PWM: $max_pwm" + + # Calculate actual PWM value based on percentage + # Note: fanSpeedPercent is interpolated by Nix as a literal number, so we use it directly in Bash arithmetic + actual_pwm=$(( max_pwm * ${fanSpeedPercent} / 100 )) + echo "Setting PWM to $actual_pwm" + echo "$actual_pwm" > "$hwmon/pwm1" + + echo "Fan speed set successfully" + exit 0 + else + echo "Fan control files not found in $hwmon" + fi + fi + done + + echo "No hwmon directory found for device $dev" + exit 1 + fi + done + + echo "GPU with bus $BUS not found" + exit 1 + ''; + +in { + + systemd.services.gpu-fan-control = { + description = "Set AMD GPU fan speed at boot"; + wantedBy = [ "multi-user.target" ]; + after = [ "multi-user.target" "udev.service" ]; + + serviceConfig = { + Type = "oneshot"; + ExecStart = "${fanControlScript}"; + RemainAfterExit = true; + StandardOutput = "journal"; + StandardError = "journal"; + }; + }; + + # Optional: Add a manual service for runtime fan control + systemd.user.services.gpu-fan-control-manual = { + description = "Manual GPU fan control (user service)"; + wantedBy = [ "default.target" ]; + + serviceConfig = { + Type = "oneshot"; + ExecStart = "${fanControlScript}"; + RemainAfterExit = true; + StandardOutput = "journal"; + StandardError = "journal"; + }; + }; + +} diff --git a/desktop/l/hardware-configuration.nix b/desktop/l/hardware-configuration.nix index 6608cdd..49c83f0 100644 --- a/desktop/l/hardware-configuration.nix +++ b/desktop/l/hardware-configuration.nix @@ -10,7 +10,7 @@ boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" ]; boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-amd" ]; + boot.kernelModules = [ "kvm-amd" "nct6775" "it87" "acpi_ec_sensors" ]; boot.extraModulePackages = [ ]; fileSystems."/" = @@ -38,5 +38,9 @@ # networking.interfaces.enp1s0.useDHCP = lib.mkDefault true; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + + hardware.i2c.enable = true; + #hardware.sensor.hddtemp.enable = true; } diff --git a/desktop/l/home.nix b/desktop/l/home.nix index da1d85b..39a9462 100644 --- a/desktop/l/home.nix +++ b/desktop/l/home.nix @@ -45,11 +45,19 @@ GOPRIVATE = "gitlab.com/sidenio/*"; TERM = "xterm-256color"; + #HIP_VISIBLE_DEVICES=0 + #HTTP_PROXY = "http://hp4.home:3128"; #HTTPS_PROXY = "http://hp4.home:3128"; #NO_PROXY = "localhost,127.0.0.1,::1,172.16.0.0/16"; # You can also use ALL_PROXY or FTP_PROXY if needed # ALL_PROXY = "http://hp4:3128"; + + # Flutter development environment variables + JAVA_HOME = "${pkgs.jdk17}/lib/openjdk"; + #CHROME_EXECUTABLE = "/etc/profiles/per-user/das/bin/google-chrome-stable"; + CHROME_EXECUTABLE = "${pkgs.google-chrome}/bin/google-chrome-stable"; + GOOGLE_APPLICATION_CREDENTIALS="~/Downloads/dashboard-dev-3da32-83d127a0f9ba.json"; }; home.packages = with pkgs; [ @@ -130,6 +138,7 @@ htop # using btop-romc #btop + below minicom bc @@ -168,6 +177,7 @@ fping inetutils # Includes telnet netcat-gnu + net-tools # for netstat # Filesystem/Monitoring inotify-tools @@ -251,10 +261,14 @@ #clang_multi # Mobile Development - flutter + #flutter + flutter329 + firebase-tools android-studio android-tools android-udev-rules + # Java for Android development + jdk17 nordic gnome-themes-extra @@ -287,6 +301,7 @@ gnomeExtensions.space-bar # https://github.com/AstraExt/astra-monitor gnomeExtensions.astra-monitor + gnomeExtensions.obs-status libgtop # Office/Documents @@ -381,7 +396,19 @@ # https://feralinteractive.github.io/gamemode/ # sameboy # https://github.com/dreamchess/dreamchess - # dreamchess + chessx + chessdb + gnuchess + dreamchess + xboard + fairymax # required by xboard + stockfish # for xboard + #pychess + gnome-chess + arena + # Audio utilities for chess applications (xboard uses aplay for sound effects) + alsa-utils + # https://github.com/ccMSC/glava # glava # gzdoom needs .wad files @@ -392,7 +419,10 @@ # blur-effect #gpu monitoring + rocmPackages.rocminfo rocmPackages.rocm-smi + rocmPackages.rocm-core + rocmPackages.rocmPath lact # https://github.com/aristocratos/btop btop-rocm @@ -406,7 +436,12 @@ # virtual camera control # v4l2-ctl --list-devices v4l-utils - libsForQt5.kdenlive + kdePackages.kdenlive + + flightgear + + i2c-tools # sudo i2cdetect -l + #liquidctl # moved to systemPackages.nix # Screenshot tool with Wayland support (flameshot.override { enableWlrSupport = true; }) @@ -417,13 +452,14 @@ # https://github.com/thexyno/nixos-config/blob/main/hm-modules/vscode/default.nix # nix run github:nix-community/nix-vscode-extensions# -- --list-extensions # https://mynixos.com/home-manager/options/programs.vscode + # https://search.nixos.org/packages?channel=unstable&query=vscode-extensions programs.vscode = { enable = true; package = pkgs.vscode; profiles.default.extensions = with pkgs.vscode-extensions; [ + golang.go dart-code.dart-code dart-code.flutter - golang.go hashicorp.terraform ms-azuretools.vscode-docker ms-vscode-remote.remote-containers @@ -445,6 +481,9 @@ jnoortheen.nix-ide rust-lang.rust-analyzer bazelbuild.vscode-bazel + continue.continue + rooveterinaryinc.roo-cline + waderyan.gitblame ]; }; @@ -483,12 +522,55 @@ }; # https://nixos.wiki/wiki/OBS_Studio + # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/programs/obs-studio.nix programs.obs-studio = { enable = true; + # virtual camera is not a home manager option, and we have v4l2loopback enabled in extraModprobeConfig + #enableVirtualCamera = true; plugins = with pkgs.obs-studio-plugins; [ + obs-3d-effect wlrobs + #obs-vnc + obs-ndi + waveform + pixel-art + obs-vaapi + obs-noise + obs-teleport + obs-markdown + obs-webkitgtk + obs-gstreamer + input-overlay + obs-rgb-levels + obs-mute-filter + obs-source-clone + obs-shaderfilter + obs-source-record + obs-retro-effects + obs-replay-source + obs-freeze-filter + obs-color-monitor + #looking-glass-obs + obs-vintage-filter + obs-scale-to-sound + obs-media-controls + obs-composite-blur + obs-advanced-masks + #obs-vertical-canvas # not sure what this is, but it flickered + obs-source-switcher + obs-move-transition + obs-gradient-source + #obs-dvd-screensaver + #obs-dir-watch-media + obs-transition-table + obs-recursion-effect obs-backgroundremoval + obs-stroke-glow-shadow + obs-scene-as-transition + obs-browser-transition + advanced-scene-switcher obs-pipewire-audio-capture + ]; }; diff --git a/desktop/l/nginx.nix b/desktop/l/nginx.nix new file mode 100644 index 0000000..7ba3fd7 --- /dev/null +++ b/desktop/l/nginx.nix @@ -0,0 +1,220 @@ +# +# nixos/hp/hp4/nginx.nix +# +{ pkgs, config, ... }: + +{ + # https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/http/nginx/generic.nix + # https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/web-servers/nginx/default.nix + # acme: https://github.com/lovesegfault/nix-config/blob/f32ab485a45bf60c3d86aa4485254b087d8e0187/services/nginx.nix#L28 + # https://github.com/NixOS/nixpkgs/blob/47457869d5b12bdd72303d6d2ba4bfcc26fe8531/nixos/modules/services/security/oauth2-proxy-nginx.nix + # https://blog.matejc.com/blogs/myblog/nixos-hydra-nginx + # https://github.com/nixinator/cardano-ops/blob/8a7be334a476a80829e17c8a0ca6ec374347a937/roles/explorer.nix#L313 + # grep ExecStartPre /etc/systemd/system/nginx.service + services.nginx = { + enable = true; + defaultHTTPListenPort = 8080; + # statusPage = true; # Disabled to avoid conflicting server blocks + + recommendedProxySettings = true; + recommendedTlsSettings = true; + #recommendedZstdSettings = true; # The zstd module for Nginx has known bugs and is not maintained well. + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedBrotliSettings = true; + + # Minimal configuration for serving files + virtualHosts."_" = { + serverName = "_"; + root = "/var/www/html"; + default = true; + + locations."/" = { + extraConfig = '' + autoindex on; + autoindex_exact_size on; + autoindex_localtime on; + #index index.html; + ''; + }; + + locations."/nginx_status" = { + extraConfig = '' + stub_status on; + access_log off; + allow 127.0.0.1; + allow ::1; + allow 172.16.50.0/24; + deny all; + ''; + }; + + locations."/ollama/" = { + extraConfig = '' + # Strip the /ollama/ prefix from the request URI + rewrite ^/ollama/(.*)$ /$1 break; + + # Handle preflight OPTIONS requests + if ($request_method = OPTIONS) { + add_header Allow "POST, OPTIONS"; + add_header Access-Control-Allow-Origin "*"; + add_header Access-Control-Allow-Headers "authorization, content-type"; + add_header Access-Control-Allow-Methods "POST, OPTIONS"; + add_header Access-Control-Max-Age 86400; + return 204; + } + + # Remove or modify the Origin header before forwarding the request + proxy_set_header Origin ""; + + # Forward other requests to backend server + proxy_pass http://localhost:11434; + + # Include additional headers for CORS support in normal requests + add_header Access-Control-Allow-Origin "*"; + add_header Access-Control-Allow-Headers "authorization, content-type"; + add_header Access-Control-Allow-Methods "POST, OPTIONS"; + add_header Access-Control-Max-Age 86400; + ''; + }; + + # # Add smokeping to the default virtual host + # locations."/smokeping/" = { + # extraConfig = '' + # root /var/lib; + # index smokeping.fcgi; + # ''; + # }; + + # locations."/smokeping/smokeping.fcgi" = { + # extraConfig = '' + # include ${pkgs.nginx}/conf/fastcgi_params; + # fastcgi_pass unix:/run/fcgiwrap-smokeping.sock; + # fastcgi_param SCRIPT_FILENAME /var/lib/smokeping/smokeping.fcgi; + # fastcgi_param DOCUMENT_ROOT /var/lib/smokeping; + # ''; + # }; + + # locations."/smokeping/cache/" = { + # extraConfig = '' + # root /var/lib; + # autoindex off; + # ''; + # }; + }; + }; + + # Ensure the docRoot directory exists and has correct permissions + systemd.tmpfiles.rules = [ + "d /var/www/html 0755 nginx nginx - -" + ]; + + # journalctl --follow --namespace nginx + + systemd.services.nginx.serviceConfig.LogNamespace = "nginx"; + + services.prometheus.exporters.nginx = { + enable = true; + openFirewall = true; + # statusUrl = "http://localhost/stub_status"; # Default, should work with statusPage = true + # listenAddress = "0.0.0.0"; # Default + # port = 9113; # Default + }; + + # # Enable fcgiwrap for smokeping + # services.fcgiwrap.instances.smokeping = { + # process.user = "smokeping"; + # process.group = "smokeping"; + # socket = { inherit (config.services.nginx) user group; }; + # }; + + # Systemd service configuration for nginx with resource limits + systemd.services.nginx = { + serviceConfig = { + # Resource limits - moderate for web server + MemoryMax = "300M"; + MemoryHigh = "250M"; + CPUQuota = "50%"; + TasksMax = 200; + + # Process limits + LimitNOFILE = 8192; + LimitNPROC = 50; + + # Nice priority + Nice = 10; + + # NoNewPrivileges = true; + # ProtectSystem = "strict"; + # ProtectHome = true; + # ProtectKernelTunables = true; + # ProtectKernelModules = true; + # ProtectControlGroups = true; + # ProtectKernelLogs = true; + # PrivateDevices = true; + # PrivateTmp = true; + # RestrictRealtime = true; + # RestrictSUIDSGID = true; + # RestrictNamespaces = true; + # PrivateUsers = true; # Create user namespace - service sees itself as root internally + # LockPersonality = true; + # ProtectHostname = true; + # ProtectClock = true; + + # RemoveIPC = true; # Clean up IPC objects + # #ProtectProc = "default"; # Allow access to process info and /proc/net + # ProcSubset = "pid"; # Only allow access to own process info + + # RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; + + # DeviceAllow = [ + # "/dev/null rw" + # "/dev/zero rw" + # "/dev/random r" + # "/dev/urandom r" + # ]; + + # # Keyring mode - ClickHouse doesn't need keyring access + # KeyringMode = "private"; + + # # Delegate - ClickHouse doesn't need cgroup delegation + # Delegate = false; + + # # Notify access - Only main process can alter service state + # NotifyAccess = "main"; + }; + }; +} +# { +# # https://nixos.wiki/wiki/Nginx +# # https://mynixos.com/options/services.nginx +# # https://search.nixos.org/options?channel=24.11&from=0&size=50&sort=relevance&type=packages&query=services.nginx +# services.nginx = { +# enable = true; +# statusPage = true; + +# listen = 8080; + +# resolver.addresses = [ "1.1.1.1" "8.8.8.8" ] + +# recommendedZstdSettings = true; +# recommendedGzipSettings = true; +# recommendedOptimisation = true; +# recommendedProxySettings = true; +# recommendedBrotliSettings = true; + +# virtualHosts = { +# default = { +# serverName = "_"; +# default = true; +# rejectSSL = true; +# locations = { +# "/" = { +# resolver 1.1.1.1; +# proxyPass = "http://127.0.0.1:12345"; +# } +# } +# }; +# }; +# }; +# }; \ No newline at end of file diff --git a/desktop/l/ollama-service.nix b/desktop/l/ollama-service.nix new file mode 100644 index 0000000..6208b72 --- /dev/null +++ b/desktop/l/ollama-service.nix @@ -0,0 +1,74 @@ +# +# ollama +# +# HIP_VISIBLE_DEVICES=GPU-0e54792172da5eeb OLLAMA_CONTEXT_LENGTH=131072 ollama serve +# +# https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/services/misc/ollama.nix +# + +{ config, lib, pkgs, ... }: + +let + mi50euid = "GPU-0e54792172da5eeb"; + ctxLength = toString 131072; # 128k + +in { + + services.ollama = { + + enable = true; + host = "[::]"; + #port = 11434; # default + + acceleration = "rocm"; + + environmentVariables = { + HIP_VISIBLE_DEVICES = mi50euid; + OLLAMA_CONTEXT_LENGTH = ctxLength; + # OLLAMA_DEBUG = "1"; + # AMD_LOG_LEVEL = "3"; + }; + + # https://github.com/ollama/ollama/blob/main/docs/troubleshooting.md#amd-gpu-discovery + + loadModels = [ + "nomic-embed-text:latest" + "codellama:34b" + "llama3.2:latest" + "gpt-oss:20b" + "deepseek-r1:32b" + "llama3-groq-tool-use:70b-q2_K" + "qwen2.5-coder:32b" + ]; + + # https://github.com/ollama/ollama/tree/main?tab=readme-ov-file#model-library + # https://ollama.com/library + # + # https://www.marktechpost.com/2025/07/31/top-local-llms-for-coding-2025/ + # + # https://ollama.com/library/codellama + # https://www.hardware-corner.net/llm-database/CodeLlama/ + # + # https://ollama.com/library/llama3.2 + # + # https://ollama.com/library/gpt-oss + # + # https://ollama.com/library/deepseek-r1 + # + # https://ollama.com/library/llama3-groq-tool-use/tags + # + # https://ollama.com/library/qwen2.5-coder + # + # [das@l:~/nixos]$ ollama list + # NAME ID SIZE MODIFIED + # nomic-embed-text:latest 0a109f422b47 274 MB 20 hours ago + # codellama:latest 8fdf8f752f6e 3.8 GB 26 hours ago + # qwq:latest 009cb3f08d74 19 GB 2 days ago + # llama3.1:latest 46e0c10c039e 4.9 GB 2 days ago + # llama3.2:latest a80c4f17acd5 2.0 GB 2 days ago + # phi4-mini:latest 78fad5d182a7 2.5 GB 2 days ago + # phi4:latest ac896e5b8b34 9.1 GB 2 days ago + + }; + +} \ No newline at end of file diff --git a/desktop/l/systemPackages.nix b/desktop/l/systemPackages.nix index a652645..a07a439 100644 --- a/desktop/l/systemPackages.nix +++ b/desktop/l/systemPackages.nix @@ -50,5 +50,9 @@ # https://wiki.nixos.org/wiki/Flameshot #(flameshot.override { enableWlrSupport = true; }) + + # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/services/hardware/fancontrol.nix + lm_sensors + liquidctl ]; } diff --git a/desktop/l2/configuration.nix b/desktop/l2/configuration.nix index 688ab2a..a3aa461 100644 --- a/desktop/l2/configuration.nix +++ b/desktop/l2/configuration.nix @@ -33,6 +33,7 @@ ./prometheus.nix ./grafana.nix # clickhouse + ./clickhouse-service.nix #./docker-compose.nix #./docker-daemon.nix #./smokeping.nix @@ -194,12 +195,12 @@ #system.stateVersion = "24.11"; system.stateVersion = "25.05"; - systemd.extraConfig = "CPUAffinity=8,20,9,21,10,22,11,23"; - systemd.user.extraConfig = "CPUAffinity=8,20,9,21,10,22,11,23"; + # systemd.extraConfig = "CPUAffinity=8,20,9,21,10,22,11,23"; + # systemd.user.extraConfig = "CPUAffinity=8,20,9,21,10,22,11,23"; - #systemd.settings.Manager = { - # CPUAffinity = "8,20,9,21,10,22,11,23"; - #}; + # systemd.settings.Manager = { + # CPUAffinity = "8,20,9,21,10,22,11,23"; + # }; # systemd.user.settings.Manager = { # CPUAffinity = "8,20,9,21,10,22,11,23"; # }; diff --git a/desktop/l2/flake.lock b/desktop/l2/flake.lock index c20c691..b7cd10b 100644 --- a/desktop/l2/flake.lock +++ b/desktop/l2/flake.lock @@ -8,11 +8,11 @@ ] }, "locked": { - "lastModified": 1742920128, - "narHash": "sha256-VPjnjtAksihLezhc+ZmnqGu18mHr4QVKa1kSZQ8rJL4=", + "lastModified": 1752497357, + "narHash": "sha256-9epXn1+T6U4Kfyw8B9zMzbERxDB3VfaPXhVebtai6CE=", "ref": "refs/heads/main", - "rev": "40e937689d318ee85b1d9763189a65e6f0b4028d", - "revCount": 40, + "rev": "84db7dcea77f7f477d79e69e35fb0bb560232667", + "revCount": 42, "type": "git", "url": "https://codeberg.org/kampka/nix-flake-crowdsec.git" }, @@ -28,11 +28,11 @@ ] }, "locked": { - "lastModified": 1750903843, - "narHash": "sha256-Ng9+f0H5/dW+mq/XOKvB9uwvGbsuiiO6HrPdAcVglCs=", + "lastModified": 1755519972, + "narHash": "sha256-bU4nqi3IpsUZJeyS8Jk85ytlX61i4b0KCxXX9YcOgVc=", "owner": "nix-community", "repo": "disko", - "rev": "83c4da299c1d7d300f8c6fd3a72ac46cb0d59aae", + "rev": "4073ff2f481f9ef3501678ff479ed81402caae6d", "type": "github" }, "original": { @@ -65,11 +65,11 @@ ] }, "locked": { - "lastModified": 1751146119, - "narHash": "sha256-gvjG95TCnUVJkvQvLMlnC4NqiqFyBdJk3o8/RwuHeaU=", + "lastModified": 1755810213, + "narHash": "sha256-QdenO8f0PTg+tC6HuSvngKcbRZA5oZKmjUT+MXKOLQg=", "owner": "nix-community", "repo": "home-manager", - "rev": "76d0c31fce2aa0c71409de953e2f9113acd5b656", + "rev": "6911d3e7f475f7b3558b4f5a6aba90fa86099baa", "type": "github" }, "original": { @@ -80,11 +80,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1751011381, - "narHash": "sha256-krGXKxvkBhnrSC/kGBmg5MyupUUT5R6IBCLEzx9jhMM=", + "lastModified": 1755615617, + "narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=", "owner": "nixos", "repo": "nixpkgs", - "rev": "30e2e2857ba47844aa71991daa6ed1fc678bcbb7", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", "type": "github" }, "original": { diff --git a/desktop/l2/home.nix b/desktop/l2/home.nix index cf35200..8cf968a 100644 --- a/desktop/l2/home.nix +++ b/desktop/l2/home.nix @@ -49,16 +49,16 @@ # ncurses.dev # libyaml.dev - # # Build Tools - # libgcc - # # https://nixos.wiki/wiki/C - # # https://search.nixos.org/packages?channel=24.05&show=gcc&from=0&size=50&sort=relevance&type=packages&query=gcc - # #gcc - # automake - # gnumake + # Build Tools + libgcc + # https://nixos.wiki/wiki/C + # https://search.nixos.org/packages?channel=24.05&show=gcc&from=0&size=50&sort=relevance&type=packages&query=gcc + gcc + automake + gnumake gnumake42 - # #cmake - # pkg-config + cmake + pkg-config # # Scripting/Utils # perl @@ -75,13 +75,13 @@ # bc # # Compression - # bzip2 - # gzip - # lz4 - # zip - # unzip - #xz - #zstd + bzip2 + gzip + lz4 + zip + unzip + xz + zstd #gnutar diff --git a/desktop/l2/systemPackages.nix b/desktop/l2/systemPackages.nix index 8719960..1ea3bf5 100644 --- a/desktop/l2/systemPackages.nix +++ b/desktop/l2/systemPackages.nix @@ -41,6 +41,7 @@ ethtool sysstat htop + below iftop nethogs nload diff --git a/desktop/l2/systemd-slices.nix b/desktop/l2/systemd-slices.nix index 3926da9..005c453 100644 --- a/desktop/l2/systemd-slices.nix +++ b/desktop/l2/systemd-slices.nix @@ -88,8 +88,8 @@ in { Slice = "kea.slice"; Nice = -5; LimitNOFILE = 65536; - Restart = "always"; - RestartSec = "10s"; + #Restart = lib.mkForce "always"; + #RestartSec = "10s"; }; }; pdns-recursor = { From a37f88658f0dbfc9371f87693d7cb5aaa577e807 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Tue, 2 Sep 2025 07:44:58 -0700 Subject: [PATCH 11/23] fans --- desktop/l/corsair-fan-control.nix | 17 ++++++----------- desktop/l/gpu-fan-control.nix | 19 ++++++++++++++++--- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/desktop/l/corsair-fan-control.nix b/desktop/l/corsair-fan-control.nix index ecd1ed4..785e093 100644 --- a/desktop/l/corsair-fan-control.nix +++ b/desktop/l/corsair-fan-control.nix @@ -5,14 +5,16 @@ # Uses liquidctl to control the fan speed. # +# sudo liquidctl status --match corsair + { config, lib, pkgs, ... }: let # Configuration - modify these values for your setup fanNumber = "fan1"; # Change this to control different fans (fan1, fan2, fan3, etc.) - fanSpeed = 100; # Change this to desired fan speed (0-100) + fanSpeed = 50; # Change this to desired fan speed (0-100) - # Script to set fan speed using liquidctl + # Script to set fan speed using liquidctl corsairFanControlScript = pkgs.writeShellScript "corsair-fan-control" '' #!/bin/sh set -eu @@ -22,15 +24,8 @@ let echo "Setting Corsair Commander ${fanNumber} speed to ${toString fanSpeed}%" - # Check if liquidctl is available - if ! command -v liquidctl >/dev/null 2>&1; then - echo "Error: liquidctl not found. Please install it first." - exit 1 - fi - - # Set the fan speed - # Note: fanSpeed is interpolated by Nix, so we use toString to convert the integer to string - if liquidctl --match corsair set "$FAN_NUMBER" speed "$FAN_SPEED"; then + # Set the fan speed using the full path to liquidctl + if ${pkgs.liquidctl}/bin/liquidctl --match corsair set "$FAN_NUMBER" speed "$FAN_SPEED"; then echo "Fan speed set successfully to ${toString fanSpeed}%" exit 0 else diff --git a/desktop/l/gpu-fan-control.nix b/desktop/l/gpu-fan-control.nix index 4516490..dd0f294 100644 --- a/desktop/l/gpu-fan-control.nix +++ b/desktop/l/gpu-fan-control.nix @@ -5,6 +5,19 @@ # Configure the GPU bus address and desired fan speed below. # +# [nix-shell:~/nixos/desktop/l]$ rocm-smi + + +# =========================================== ROCm System Management Interface =========================================== +# ===================================================== Concise Info ===================================================== +# Device Node IDs Temp Power Partitions SCLK MCLK Fan Perf PwrCap VRAM% GPU% +# (DID, GUID) (Edge) (Socket) (Mem, Compute, ID) +# ======================================================================================================================== +# 0 2 0x66a1, 33678 35.0°C 19.0W N/A, N/A, 0 938Mhz 350Mhz 100.0% auto 225.0W 0% 0% +# 1 1 0x7312, 11012 45.0°C 33.0W N/A, N/A, 0 800Mhz 900Mhz 49.41% auto 140.0W 22% 2% +# ======================================================================================================================== +# ================================================= End of ROCm SMI Log ================================================== + { config, lib, pkgs, ... }: let @@ -15,7 +28,7 @@ let #44:00.0 Display controller: Advanced Micro Devices, Inc. [AMD/ATI] Vega 20 [Radeon Pro VII/Radeon Instinct MI50 32GB] #63:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Navi 10 [Radeon Pro W5700] - fanSpeedPercent = 50; # Change this to desired fan speed (0-100) + fanSpeedPercent = 40; # Change this to desired fan speed (0-100) # Calculate the actual PWM value based on percentage fanSpeedPWM = builtins.toString (fanSpeedPercent * 255 / 100); @@ -50,8 +63,8 @@ let echo "Max PWM: $max_pwm" # Calculate actual PWM value based on percentage - # Note: fanSpeedPercent is interpolated by Nix as a literal number, so we use it directly in Bash arithmetic - actual_pwm=$(( max_pwm * ${fanSpeedPercent} / 100 )) + # Note: fanSpeedPercent is interpolated by Nix, so we use toString to convert the integer to string + actual_pwm=$(( max_pwm * ${toString fanSpeedPercent} / 100 )) echo "Setting PWM to $actual_pwm" echo "$actual_pwm" > "$hwmon/pwm1" From 9f56370f474576e8586b415517ee998245875193 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Tue, 2 Sep 2025 07:46:53 -0700 Subject: [PATCH 12/23] overlapping make --- desktop/l2/Makefile | 3 +++ desktop/l2/home.nix | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/desktop/l2/Makefile b/desktop/l2/Makefile index fc431e6..7f5f524 100644 --- a/desktop/l2/Makefile +++ b/desktop/l2/Makefile @@ -45,4 +45,7 @@ sync: s: rsync -avz /home/das/nixos/ 172.16.40.47:/home/das/nixos/ +l2s: + rsync -avzd /home/das/nixos/ l2:/home/das/nixos/ + # end diff --git a/desktop/l2/home.nix b/desktop/l2/home.nix index 8cf968a..d72227f 100644 --- a/desktop/l2/home.nix +++ b/desktop/l2/home.nix @@ -57,7 +57,7 @@ automake gnumake gnumake42 - cmake + # cmake pkg-config # # Scripting/Utils From 0269c579dbd6abf74499b5d61d1ce424a8ed23b6 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Fri, 12 Sep 2025 09:12:59 -0700 Subject: [PATCH 13/23] broadcom rocev2 --- desktop/l2/configuration.nix | 8 ++++++++ desktop/l2/home.nix | 2 +- desktop/l2/systemPackages.nix | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/desktop/l2/configuration.nix b/desktop/l2/configuration.nix index a3aa461..85e1188 100644 --- a/desktop/l2/configuration.nix +++ b/desktop/l2/configuration.nix @@ -67,6 +67,13 @@ "amdgpu" ]; + kernelModules = [ + "bnxt_en" # Ethernet + "bnxt_re" # RoCEv2 RDMA provider + "ib_uverbs" # RDMA verbs + "rdma_ucm" + ]; + blacklistedKernelModules = [ "nouveau" #"i915" @@ -96,6 +103,7 @@ stdenv.cc.cc.lib zlib libxml2 + pciutils # for broadcom niccli ]; }; diff --git a/desktop/l2/home.nix b/desktop/l2/home.nix index d72227f..6c4ddad 100644 --- a/desktop/l2/home.nix +++ b/desktop/l2/home.nix @@ -56,7 +56,7 @@ gcc automake gnumake - gnumake42 + # gnumake42 # Removed to avoid version conflict with gnumake # cmake pkg-config diff --git a/desktop/l2/systemPackages.nix b/desktop/l2/systemPackages.nix index 1ea3bf5..c2062d8 100644 --- a/desktop/l2/systemPackages.nix +++ b/desktop/l2/systemPackages.nix @@ -52,6 +52,10 @@ tshark perf-tools linuxPackages_latest.perf + + rdma-core # ibv_devinfo, rdma + pciutils + libpciaccess ]; } From 2325dd5e309e1f291f95880da226b43cbdcf0a6b Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Fri, 12 Sep 2025 09:13:06 -0700 Subject: [PATCH 14/23] broadcom --- desktop/l/clickhouse-service.nix | 2 +- desktop/l/configuration.nix | 35 ++++++++++++++++++++++++++-- desktop/l/flake.lock | 12 +++++----- desktop/l/hardware-configuration.nix | 3 +++ desktop/l/home.nix | 3 ++- desktop/l/ollama-service.nix | 7 ++++++ desktop/l/systemPackages.nix | 4 ++++ desktop/l2/configuration.nix | 16 ++++++++++++- desktop/l2/systemPackages.nix | 5 +++- desktop/old.l/configuration.nix | 3 ++- 10 files changed, 77 insertions(+), 13 deletions(-) diff --git a/desktop/l/clickhouse-service.nix b/desktop/l/clickhouse-service.nix index c9e2dee..0559682 100644 --- a/desktop/l/clickhouse-service.nix +++ b/desktop/l/clickhouse-service.nix @@ -12,7 +12,7 @@ let in { # Enable ClickHouse service - services.clickhouse.enable = true; + services.clickhouse.enable = false; # Override the default ClickHouse service with enhanced security systemd.services.clickhouse = { diff --git a/desktop/l/configuration.nix b/desktop/l/configuration.nix index 4f0b88a..c2084c0 100644 --- a/desktop/l/configuration.nix +++ b/desktop/l/configuration.nix @@ -51,10 +51,12 @@ ]; boot = { + loader.systemd-boot = { enable = true; consoleMode = "max"; memtest86.enable = true; + configurationLimit = 20; }; loader.efi.canTouchEfiVariables = true; @@ -65,6 +67,14 @@ kernelPackages = pkgs.linuxPackages_latest; #boot.kernelPackages = pkgs.linuxPackages_rpi4 + # kernelPackages = pkgs.linuxPackages // { + # kernel = pkgs.linuxPackages.kernel.override { + # extraStructuredConfig = with lib.kernel; { + # CONFIG_DRM_NOUVEAU = no; + # }; + # }; + # }; + # # https://github.com/tolgaerok/nixos-2405-gnome/blob/main/core/boot/efi/efi.nix#L56C5-L56C21 # kernelParams = [ # "nvidia-drm.modeset=1" @@ -79,6 +89,13 @@ "amdgpu" ]; + kernelModules = [ + "bnxt_en" # Ethernet + "bnxt_re" # RoCEv2 RDMA provider + "ib_uverbs" # RDMA verbs + "rdma_ucm" + ]; + blacklistedKernelModules = [ "nouveau" #"i915" @@ -94,8 +111,9 @@ extraModprobeConfig = '' options kvm_intel nested=1 - options v4l2loopback devices=1 video_nr=1 card_label="OBS Cam" exclusive_caps=1 + options v4l2loopback devices=1 video_nr=1 card_label="v4l2loopback" exclusive_caps=1 ''; + # https://github.com/v4l2loopback/v4l2loopback#options }; # https://fzakaria.com/2025/02/26/nix-pragmatism-nix-ld-and-envfs @@ -107,7 +125,9 @@ stdenv.cc.cc.lib zlib libxml2 + pciutils # for broadcom niccli # Add more libraries as needed + #libpciaccess ]; }; @@ -263,7 +283,16 @@ systemd.tmpfiles.rules = [ "L+ /opt/rocm/hip - - - - ${pkgs.rocmPackages.clr}" ]; - systemd.services.lactd.wantedBy = [ "multi-user.target" ]; + + # Enable LACT GPU Control Daemon + # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/services/hardware/lact.nix + services.lact = { + enable = true; + # Optional: Add custom settings here if needed + # settings = { + # # Example settings + # }; + }; xdg.portal = { enable = true; @@ -329,3 +358,5 @@ }; } + +# end diff --git a/desktop/l/flake.lock b/desktop/l/flake.lock index 79c2ebf..ec57c50 100644 --- a/desktop/l/flake.lock +++ b/desktop/l/flake.lock @@ -7,11 +7,11 @@ ] }, "locked": { - "lastModified": 1756734952, - "narHash": "sha256-H6jmduj4QIncLPAPODPSG/8ry9lpr1kRq6fYytU52qU=", + "lastModified": 1757529548, + "narHash": "sha256-If5AT3dPXH0BM+q+pwyZvtWLTmlqJmGW6IDZ2MqlGRU=", "owner": "nix-community", "repo": "home-manager", - "rev": "29ab63bbb3d9eee4a491f7ce701b189becd34068", + "rev": "e0154ae41614e32a443c43ee51eee9eed3ad9a48", "type": "github" }, "original": { @@ -22,11 +22,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1756542300, - "narHash": "sha256-tlOn88coG5fzdyqz6R93SQL5Gpq+m/DsWpekNFhqPQk=", + "lastModified": 1757347588, + "narHash": "sha256-tLdkkC6XnsY9EOZW9TlpesTclELy8W7lL2ClL+nma8o=", "owner": "nixos", "repo": "nixpkgs", - "rev": "d7600c775f877cd87b4f5a831c28aa94137377aa", + "rev": "b599843bad24621dcaa5ab60dac98f9b0eb1cabe", "type": "github" }, "original": { diff --git a/desktop/l/hardware-configuration.nix b/desktop/l/hardware-configuration.nix index 49c83f0..a2c85e2 100644 --- a/desktop/l/hardware-configuration.nix +++ b/desktop/l/hardware-configuration.nix @@ -43,4 +43,7 @@ hardware.i2c.enable = true; #hardware.sensor.hddtemp.enable = true; + + # hardware.decklink.enable = true; + #https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/hardware/decklink.nix } diff --git a/desktop/l/home.nix b/desktop/l/home.nix index 39a9462..9b9d582 100644 --- a/desktop/l/home.nix +++ b/desktop/l/home.nix @@ -439,6 +439,7 @@ kdePackages.kdenlive flightgear + linuxConsoleTools #jscal https://wiki.flightgear.org/Input_device i2c-tools # sudo i2cdetect -l #liquidctl # moved to systemPackages.nix @@ -538,7 +539,7 @@ obs-noise obs-teleport obs-markdown - obs-webkitgtk + #obs-webkitgtk # seems to be removed obs-gstreamer input-overlay obs-rgb-levels diff --git a/desktop/l/ollama-service.nix b/desktop/l/ollama-service.nix index 6208b72..101fdb1 100644 --- a/desktop/l/ollama-service.nix +++ b/desktop/l/ollama-service.nix @@ -14,6 +14,13 @@ let in { + services.open-webui = { + enable = true; + port = 8086; # default 8080 + }; + # https://github.com/open-webui/open-webui + # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/services/misc/open-webui.nix + services.ollama = { enable = true; diff --git a/desktop/l/systemPackages.nix b/desktop/l/systemPackages.nix index a07a439..7ed35da 100644 --- a/desktop/l/systemPackages.nix +++ b/desktop/l/systemPackages.nix @@ -54,5 +54,9 @@ # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/services/hardware/fancontrol.nix lm_sensors liquidctl + + rdma-core # ibv_devinfo, rdma + pciutils + libpciaccess ]; } diff --git a/desktop/l2/configuration.nix b/desktop/l2/configuration.nix index 85e1188..31154fd 100644 --- a/desktop/l2/configuration.nix +++ b/desktop/l2/configuration.nix @@ -50,6 +50,7 @@ ]; boot = { + loader.systemd-boot = { enable = true; consoleMode = "max"; @@ -173,6 +174,9 @@ #MY_VARIABLE = "my-value"; }; + systemd.services.modem-manager.enable = false; + systemd.services."dbus-org.freedesktop.ModemManager1".enable = false; + users.users.das = { isNormalUser = true; description = "das"; @@ -191,6 +195,16 @@ enableSSHSupport = true; }; + # Enable LACT GPU Control Daemon + # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/services/hardware/lact.nix + services.lact = { + enable = true; + # Optional: Add custom settings here if needed + # settings = { + # # Example settings + # }; + }; + # # https://nixos.wiki/wiki/Virt-manager # virtualisation.libvirtd.enable = true; # #programs.virt-manager.enable = true; @@ -215,4 +229,4 @@ } -# end \ No newline at end of file +# end diff --git a/desktop/l2/systemPackages.nix b/desktop/l2/systemPackages.nix index c2062d8..5e0c5c8 100644 --- a/desktop/l2/systemPackages.nix +++ b/desktop/l2/systemPackages.nix @@ -53,10 +53,13 @@ perf-tools linuxPackages_latest.perf + clinfo + lact + rdma-core # ibv_devinfo, rdma pciutils libpciaccess ]; } -# end \ No newline at end of file +# end diff --git a/desktop/old.l/configuration.nix b/desktop/old.l/configuration.nix index 90684b7..8043be0 100644 --- a/desktop/old.l/configuration.nix +++ b/desktop/old.l/configuration.nix @@ -235,7 +235,8 @@ systemd.tmpfiles.rules = [ "L+ /opt/rocm/hip - - - - ${pkgs.rocmPackages.clr}" ]; - systemd.services.lactd.wantedBy = [ "multi-user.target" ]; + systemd.services.lact.wantedBy = [ "multi-user.target" ]; + # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/services/hardware/lact.nix # Configure keymap in X11 services.xserver.xkb = { From c21329ffcd401befe56e496843101e4ca00ca304 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Sat, 20 Sep 2025 13:59:17 -0700 Subject: [PATCH 15/23] before onnxruntime --- desktop/l/corsair-fan-control.nix | 2 +- desktop/l/flake.lock | 12 ++--- desktop/l/flake.nix | 5 ++ desktop/l/home.nix | 19 ++++--- desktop/l/ollama-service.nix | 73 ++++++++++++++++++++++++++- desktop/l2/configuration.nix | 4 +- desktop/l2/hardware-configuration.nix | 3 ++ 7 files changed, 101 insertions(+), 17 deletions(-) diff --git a/desktop/l/corsair-fan-control.nix b/desktop/l/corsair-fan-control.nix index 785e093..66b059d 100644 --- a/desktop/l/corsair-fan-control.nix +++ b/desktop/l/corsair-fan-control.nix @@ -12,7 +12,7 @@ let # Configuration - modify these values for your setup fanNumber = "fan1"; # Change this to control different fans (fan1, fan2, fan3, etc.) - fanSpeed = 50; # Change this to desired fan speed (0-100) + fanSpeed = 80; # Change this to desired fan speed (0-100) # Script to set fan speed using liquidctl corsairFanControlScript = pkgs.writeShellScript "corsair-fan-control" '' diff --git a/desktop/l/flake.lock b/desktop/l/flake.lock index ec57c50..ee1707d 100644 --- a/desktop/l/flake.lock +++ b/desktop/l/flake.lock @@ -7,11 +7,11 @@ ] }, "locked": { - "lastModified": 1757529548, - "narHash": "sha256-If5AT3dPXH0BM+q+pwyZvtWLTmlqJmGW6IDZ2MqlGRU=", + "lastModified": 1758375677, + "narHash": "sha256-BLtD+6qWz7fQjPk2wpwyXQLGI0E30Ikgf2ppn2nVadI=", "owner": "nix-community", "repo": "home-manager", - "rev": "e0154ae41614e32a443c43ee51eee9eed3ad9a48", + "rev": "edc7468e12be92e926847cb02418e649b02b59dd", "type": "github" }, "original": { @@ -22,11 +22,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1757347588, - "narHash": "sha256-tLdkkC6XnsY9EOZW9TlpesTclELy8W7lL2ClL+nma8o=", + "lastModified": 1758277210, + "narHash": "sha256-iCGWf/LTy+aY0zFu8q12lK8KuZp7yvdhStehhyX1v8w=", "owner": "nixos", "repo": "nixpkgs", - "rev": "b599843bad24621dcaa5ab60dac98f9b0eb1cabe", + "rev": "8eaee110344796db060382e15d3af0a9fc396e0e", "type": "github" }, "original": { diff --git a/desktop/l/flake.nix b/desktop/l/flake.nix index d3df0c1..adce43f 100644 --- a/desktop/l/flake.nix +++ b/desktop/l/flake.nix @@ -35,6 +35,11 @@ "android-studio-stable" ]; }; + overlays = [ + (final: prev: { + onnxruntime = final.callPackage /home/das/Downloads/nixpkgs/pkgs/by-name/on/onnxruntime/package.nix { }; + }) + ]; }; lib = nixpkgs.lib; in { diff --git a/desktop/l/home.nix b/desktop/l/home.nix index 9b9d582..11e60d2 100644 --- a/desktop/l/home.nix +++ b/desktop/l/home.nix @@ -130,8 +130,7 @@ # Scripting/Utils perl - #3.12.8 on 12th of Feb 2025 - python3Full + python314 gawk jq git @@ -158,6 +157,8 @@ rsync tree + nixpkgs-fmt + # Terminals alacritty kitty @@ -218,7 +219,7 @@ #grpcurl # https://github.com/go-gorm/gen # https://github.com/infobloxopen/protoc-gen-gorm/blob/main/example/postgres_arrays/buf.gen.yaml - gorm-gentool + #gorm-gentool # removed 24.11 #buf-language-server # https://tinygo.org/ @@ -261,8 +262,9 @@ #clang_multi # Mobile Development - #flutter - flutter329 + flutter #3.35.2 + #flutter329 + # https://search.nixos.org/packages?channel=unstable&query=flutter firebase-tools android-studio android-tools @@ -383,7 +385,7 @@ hyperfine # App Launchers - rofi-wayland + rofi wofi # Raspberry Pi @@ -446,6 +448,9 @@ # Screenshot tool with Wayland support (flameshot.override { enableWlrSupport = true; }) + + # Custom onnxruntime package + onnxruntime ]; # vscode @@ -565,7 +570,7 @@ #obs-dir-watch-media obs-transition-table obs-recursion-effect - obs-backgroundremoval + obs-backgroundremoval # https://github.com/royshil/obs-backgroundremoval obs-stroke-glow-shadow obs-scene-as-transition obs-browser-transition diff --git a/desktop/l/ollama-service.nix b/desktop/l/ollama-service.nix index 101fdb1..a3dd622 100644 --- a/desktop/l/ollama-service.nix +++ b/desktop/l/ollama-service.nix @@ -38,12 +38,23 @@ in { # https://github.com/ollama/ollama/blob/main/docs/troubleshooting.md#amd-gpu-discovery + + # sudo systemctl status ollama-model-loader.service + # sudo systemctl restart ollama-model-loader.service + + # ollama list + loadModels = [ "nomic-embed-text:latest" "codellama:34b" + "codellama:13b" + "codellama:7b" "llama3.2:latest" + "llama3.2:3b" # https://ollama.com/library/llama3.2 + #"llama4:latest" # too big! "gpt-oss:20b" "deepseek-r1:32b" + #"deepseek-r1:1.5b" "llama3-groq-tool-use:70b-q2_K" "qwen2.5-coder:32b" ]; @@ -78,4 +89,64 @@ in { }; -} \ No newline at end of file +} + +# rocminfo 2>&1 | grep -i -E '(agent|name|uuid)' + +# [das@l:~/nixos/desktop/l]$ systemctl restart ollama-model-loader.service + +# [das@l:~/nixos/desktop/l]$ systemctl status ollama-model-loader.service +# ○ ollama-model-loader.service - Download ollama models in the background +# Loaded: loaded (/etc/systemd/system/ollama-model-loader.service; enabled; preset: ignored) +# Active: inactive (dead) since Fri 2025-09-12 11:29:58 PDT; 5s ago +# Duration: 413ms +# Invocation: 54354297f7de43299bbebd26460adefe +# Process: 551044 ExecStart=/nix/store/if3rc0z8v3f1h468klz4varj3jgn7isc-unit-script-ollama-model-loader-start/bin/ollama-model-loader-start (code=exited, status=0/SUCCESS) +# Main PID: 551044 (code=exited, status=0/SUCCESS) +# IP: 16.9K in, 12.9K out +# IO: 0B read, 0B written +# Mem peak: 60.8M +# CPU: 184ms + +# Sep 12 11:29:58 l ollama-model-loader-start[551054]: [122B blob data] +# Sep 12 11:29:58 l ollama-model-loader-start[551054]: [122B blob data] +# Sep 12 11:29:58 l ollama-model-loader-start[551054]: [122B blob data] +# Sep 12 11:29:58 l ollama-model-loader-start[551054]: [122B blob data] +# Sep 12 11:29:58 l ollama-model-loader-start[551054]: [122B blob data] +# Sep 12 11:29:58 l ollama-model-loader-start[551054]: [27B blob data] +# Sep 12 11:29:58 l ollama-model-loader-start[551054]: [20B blob data] +# Sep 12 11:29:58 l ollama-model-loader-start[551054]: [25B blob data] +# Sep 12 11:29:58 l systemd[1]: ollama-model-loader.service: Deactivated successfully. +# Sep 12 11:29:58 l systemd[1]: ollama-model-loader.service: Consumed 184ms CPU time, 60.8M memory peak, 16.9K incoming IP traffic, 12.9K outgoing IP traffic. + +# [das@l:~/nixos/desktop/l]$ ollama list +# NAME ID SIZE MODIFIED +# llama3.2:3b a80c4f17acd5 2.0 GB 14 seconds ago +# llama3.2:latest a80c4f17acd5 2.0 GB 14 seconds ago +# nomic-embed-text:latest 0a109f422b47 274 MB 14 seconds ago +# qwen2.5-coder:32b b92d6a0bd47e 19 GB 14 seconds ago +# codellama:34b 685be00e1532 19 GB 14 seconds ago +# deepseek-r1:32b edba8017331d 19 GB 14 seconds ago +# gpt-oss:20b aa4295ac10c3 13 GB 14 seconds ago +# llama3-groq-tool-use:70b-q2_K dab8a158f092 26 GB 14 seconds ago + +# [das@l:~/nixos/desktop/l]$ + +# [das@l:~/nixos/desktop/l]$ rocm-smi --alldevices --showallinfo + + +# ============================ ROCm System Management Interface ============================ +# ============================== Version of System Component =============================== +# Driver version: 6.16.5 +# ========================================================================================== +# =========================================== ID =========================================== +# GPU[0] : Device Name: TBD VEGA20 CARD +# GPU[0] : Device ID: 0x66a1 +# GPU[0] : Device Rev: 0x00 +# GPU[0] : Subsystem ID: 0x1002 +# GPU[0] : GUID: 33678 +# GPU[1] : Device Name: 0x1002 +# GPU[1] : Device ID: 0x7312 +# GPU[1] : Device Rev: 0x00 +# GPU[1] : Subsystem ID: 0x1002 +# GPU[1] : GUID: 11012 diff --git a/desktop/l2/configuration.nix b/desktop/l2/configuration.nix index 31154fd..d96bde5 100644 --- a/desktop/l2/configuration.nix +++ b/desktop/l2/configuration.nix @@ -24,7 +24,7 @@ ./locale.nix ./hosts.nix ./firewall.nix - ./crowdsec.nix + #./crowdsec.nix #./systemdSystem.nix ./systemPackages.nix # home manager is imported in the flake @@ -43,7 +43,7 @@ ./hostapd-multi.nix ./network-optimization.nix # CPU and IRQ optimization modules - ./irq-affinity.nix + #./irq-affinity.nix ./systemd-slices.nix ./kernel-params.nix #./monitoring.nix diff --git a/desktop/l2/hardware-configuration.nix b/desktop/l2/hardware-configuration.nix index da20248..0b07fbe 100644 --- a/desktop/l2/hardware-configuration.nix +++ b/desktop/l2/hardware-configuration.nix @@ -22,4 +22,7 @@ nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + + hardware.infiniband.enable = true; + # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/hardware/infiniband.nix } From 75805f1f948422dbe181b8264e598ed2dea7db4a Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Sat, 20 Sep 2025 15:25:09 -0700 Subject: [PATCH 16/23] onnx testing --- desktop/l/flake.nix | 15 ++++++++++++++- desktop/l/home.nix | 9 ++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/desktop/l/flake.nix b/desktop/l/flake.nix index adce43f..b787b15 100644 --- a/desktop/l/flake.nix +++ b/desktop/l/flake.nix @@ -37,7 +37,20 @@ }; overlays = [ (final: prev: { - onnxruntime = final.callPackage /home/das/Downloads/nixpkgs/pkgs/by-name/on/onnxruntime/package.nix { }; + onnxruntime = final.callPackage /home/das/Downloads/nixpkgs/pkgs/by-name/on/onnxruntime/package.nix { + rocmSupport = true; + rcclSupport = true; + }; + python313Packages = prev.python313Packages.override (old: { + overrides = prev.lib.composeManyExtensions [ + (final: prev: { + onnxruntime = final.callPackage /home/das/Downloads/nixpkgs/pkgs/development/python-modules/onnxruntime/default.nix { + onnxruntime = final.onnxruntime; # Use the overlay version + }; + }) + old.overrides or (final: prev: { }) + ]; + }); }) ]; }; diff --git a/desktop/l/home.nix b/desktop/l/home.nix index 11e60d2..473bc74 100644 --- a/desktop/l/home.nix +++ b/desktop/l/home.nix @@ -58,6 +58,9 @@ #CHROME_EXECUTABLE = "/etc/profiles/per-user/das/bin/google-chrome-stable"; CHROME_EXECUTABLE = "${pkgs.google-chrome}/bin/google-chrome-stable"; GOOGLE_APPLICATION_CREDENTIALS="~/Downloads/dashboard-dev-3da32-83d127a0f9ba.json"; + + # Python path for onnxruntime + PYTHONPATH = "${pkgs.python313Packages.onnxruntime}/lib/python3.13/site-packages"; }; home.packages = with pkgs; [ @@ -130,7 +133,7 @@ # Scripting/Utils perl - python314 + python313 gawk jq git @@ -451,6 +454,9 @@ # Custom onnxruntime package onnxruntime + + # Custom Python onnxruntime module + python313Packages.onnxruntime ]; # vscode @@ -506,6 +512,7 @@ }; }; + programs.vim = { enable = true; plugins = with pkgs.vimPlugins; [ vim-airline ]; From 60f99e8665bd1ab734a24e2ac69f5ade4f762f45 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Sun, 21 Sep 2025 11:02:45 -0700 Subject: [PATCH 17/23] onnxruntime compiles --- desktop/l/configuration.nix | 4 - .../onnxruntime/nvcc-gsl.patch | 20 ++ .../l/custom-packages/onnxruntime/package.nix | 325 ++++++++++++++++++ .../python-onnxruntime/default.nix | 94 +++++ desktop/l/flake.nix | 50 ++- desktop/l/home.nix | 6 +- desktop/l/systemPackages.nix | 3 +- 7 files changed, 472 insertions(+), 30 deletions(-) create mode 100644 desktop/l/custom-packages/onnxruntime/nvcc-gsl.patch create mode 100644 desktop/l/custom-packages/onnxruntime/package.nix create mode 100644 desktop/l/custom-packages/python-onnxruntime/default.nix diff --git a/desktop/l/configuration.nix b/desktop/l/configuration.nix index c2084c0..d769755 100644 --- a/desktop/l/configuration.nix +++ b/desktop/l/configuration.nix @@ -353,10 +353,6 @@ system.stateVersion = "24.11"; - nixpkgs.config = { - allowUnfree = true; - }; - } # end diff --git a/desktop/l/custom-packages/onnxruntime/nvcc-gsl.patch b/desktop/l/custom-packages/onnxruntime/nvcc-gsl.patch new file mode 100644 index 0000000..11127d9 --- /dev/null +++ b/desktop/l/custom-packages/onnxruntime/nvcc-gsl.patch @@ -0,0 +1,20 @@ +diff --git a/cmake/external/onnxruntime_external_deps.cmake b/cmake/external/onnxruntime_external_deps.cmake +index ebf20ab21b..2aa5d9e908 100644 +--- a/cmake/external/onnxruntime_external_deps.cmake ++++ b/cmake/external/onnxruntime_external_deps.cmake +@@ -403,15 +403,6 @@ if (CPUINFO_SUPPORTED) + endif() + + if(onnxruntime_USE_CUDA) +- onnxruntime_fetchcontent_declare( +- GSL +- URL ${DEP_URL_microsoft_gsl} +- URL_HASH SHA1=${DEP_SHA1_microsoft_gsl} +- PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/gsl/1064.patch +- EXCLUDE_FROM_ALL +- FIND_PACKAGE_ARGS 4.0 NAMES Microsoft.GSL +- ) +-else() + onnxruntime_fetchcontent_declare( + GSL + URL ${DEP_URL_microsoft_gsl} diff --git a/desktop/l/custom-packages/onnxruntime/package.nix b/desktop/l/custom-packages/onnxruntime/package.nix new file mode 100644 index 0000000..3299efd --- /dev/null +++ b/desktop/l/custom-packages/onnxruntime/package.nix @@ -0,0 +1,325 @@ +{ config +, stdenv +, lib +, fetchFromGitHub +, abseil-cpp_202508 +, cmake +, cpuinfo +, eigen +, flatbuffers +, glibcLocales +, gtest +, howard-hinnant-date +, libpng +, nlohmann_json +, pkg-config +, python3Packages +, re2 +, zlib +, protobuf +, microsoft-gsl +, darwinMinVersionHook +, pythonSupport ? true +, cudaSupport ? config.cudaSupport +, ncclSupport ? config.cudaSupport +, cudaPackages ? { } +, rocmSupport ? false +, rcclSupport ? rocmSupport +, rocmPackages ? { } +, +}@inputs: + +let + version = "1.22.2"; + + src = fetchFromGitHub { + owner = "microsoft"; + repo = "onnxruntime"; + tag = "v${version}"; + fetchSubmodules = true; + hash = "sha256-X8Pdtc0eR0iU+Xi2A1HrNo1xqCnoaxNjj4QFm/E3kSE="; + }; + + stdenv = throw "Use effectiveStdenv instead"; + effectiveStdenv = if cudaSupport then cudaPackages.backendStdenv else inputs.stdenv; + + cudaArchitecturesString = cudaPackages.flags.cmakeCudaArchitecturesString; + + mp11 = fetchFromGitHub { + owner = "boostorg"; + repo = "mp11"; + tag = "boost-1.89.0"; + hash = "sha256-6dbfae01358be88ebefcdfb7707a2a68ba914c39dc83fdd85f556761fe0fafb4"; + }; + + safeint = fetchFromGitHub { + owner = "dcleblanc"; + repo = "safeint"; + tag = "3.0.28a"; + hash = "sha256-9e652d065a3cef80623287d5dc61edcf6a95ddab38a9dfeb34f155261fc9cef7"; + }; + + onnx = fetchFromGitHub { + owner = "onnx"; + repo = "onnx"; + tag = "v1.19.0"; + hash = "sha256-2c2ac5a078b0350a0723fac606be8cd9e9e8cbd4c99bab1bffe2623b188fd236"; + }; + + cutlass = fetchFromGitHub { + owner = "NVIDIA"; + repo = "cutlass"; + tag = "v3.5.1"; + hash = "sha256-sTGYN+bjtEqQ7Ootr/wvx3P9f8MCDSSj3qyCWjfdLEA="; + }; + + dlpack = fetchFromGitHub { + owner = "dmlc"; + repo = "dlpack"; + tag = "v1.1"; + hash = "sha256-2e3b94b55825c240cc58e6721e15b449978cbae21a2a4caa23058b0157ee2fb3"; + }; + + isCudaJetson = cudaSupport && cudaPackages.flags.isJetsonBuild; +in +effectiveStdenv.mkDerivation rec { + pname = "onnxruntime"; + inherit src version; + + patches = lib.optionals cudaSupport [ + # We apply the referenced 1064.patch ourselves to our nix dependency. + # FIND_PACKAGE_ARGS for CUDA was added in https://github.com/microsoft/onnxruntime/commit/87744e5 so it might be possible to delete this patch after upgrading to 1.17.0 + ./nvcc-gsl.patch + ]; + + nativeBuildInputs = [ + cmake + pkg-config + python3Packages.python + protobuf + ] + ++ lib.optionals pythonSupport ( + with python3Packages; + [ + pip + python + pythonOutputDistHook + setuptools + wheel + ] + ) + ++ lib.optionals cudaSupport [ + cudaPackages.cuda_nvcc + cudaPackages.cudnn-frontend + ] + ++ lib.optionals isCudaJetson [ + cudaPackages.autoAddCudaCompatRunpath + ] + ++ lib.optionals rocmSupport [ + rocmPackages.rocm-cmake + rocmPackages.hipcc + ]; + + buildInputs = [ + eigen + glibcLocales + howard-hinnant-date + libpng + nlohmann_json + microsoft-gsl + zlib + ] + ++ lib.optionals (lib.meta.availableOn effectiveStdenv.hostPlatform cpuinfo) [ + cpuinfo + ] + ++ lib.optionals pythonSupport ( + with python3Packages; + [ + numpy + pybind11 + packaging + ] + ) + ++ lib.optionals cudaSupport ( + with cudaPackages; + [ + cuda_cccl # cub/cub.cuh + libcublas # cublas_v2.h + libcurand # curand.h + libcusparse # cusparse.h + libcufft # cufft.h + cudnn # cudnn.h + cuda_cudart + ] + ++ lib.optionals (cudaSupport && ncclSupport) ( + with cudaPackages; + [ + nccl + ] + ) + ) + ++ lib.optionals rocmSupport ( + with rocmPackages; + [ + rocm-core + rocm-runtime + hipblas + rocblas + miopen + rocfft + rocsparse + ] + ++ lib.optionals (rocmSupport && rcclSupport) [ + rccl + ] + ) + ++ lib.optionals effectiveStdenv.hostPlatform.isDarwin [ + (darwinMinVersionHook "13.3") + ]; + + nativeCheckInputs = [ + gtest + ] + ++ lib.optionals pythonSupport ( + with python3Packages; + [ + pytest + sympy + onnx + ] + ); + + # TODO: build server, and move .so's to lib output + # Python's wheel is stored in a separate dist output + outputs = [ + "out" + "dev" + ] + ++ lib.optionals pythonSupport [ "dist" ]; + + enableParallelBuilding = true; + + cmakeDir = "../cmake"; + + cmakeFlags = [ + (lib.cmakeBool "ABSL_ENABLE_INSTALL" true) + (lib.cmakeBool "FETCHCONTENT_FULLY_DISCONNECTED" true) + (lib.cmakeBool "FETCHCONTENT_QUIET" false) + (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_ABSEIL_CPP" "${abseil-cpp_202508.src}") + (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_DLPACK" "${dlpack}") + (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_FLATBUFFERS" "${flatbuffers.src}") + (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_MP11" "${mp11}") + (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_ONNX" "${onnx}") + (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_RE2" "${re2.src}") + (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_SAFEINT" "${safeint}") + (lib.cmakeFeature "FETCHCONTENT_TRY_FIND_PACKAGE_MODE" "ALWAYS") + # fails to find protoc on darwin, so specify it + (lib.cmakeFeature "ONNX_CUSTOM_PROTOC_EXECUTABLE" (lib.getExe protobuf)) + (lib.cmakeBool "onnxruntime_BUILD_SHARED_LIB" true) + (lib.cmakeBool "onnxruntime_BUILD_UNIT_TESTS" doCheck) + (lib.cmakeBool "onnxruntime_USE_FULL_PROTOBUF" false) + (lib.cmakeBool "onnxruntime_USE_CUDA" cudaSupport) + (lib.cmakeBool "onnxruntime_USE_NCCL" (cudaSupport && ncclSupport)) + (lib.cmakeBool "onnxruntime_USE_ROCM" rocmSupport) + (lib.cmakeBool "onnxruntime_USE_RCCL" (rocmSupport && rcclSupport)) + (lib.cmakeBool "onnxruntime_ENABLE_LTO" (!cudaSupport || cudaPackages.cudaOlder "12.8")) + ] + ++ lib.optionals pythonSupport [ + (lib.cmakeBool "onnxruntime_ENABLE_PYTHON" true) + ] + ++ lib.optionals cudaSupport [ + (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_CUTLASS" "${cutlass}") + (lib.cmakeFeature "onnxruntime_CUDNN_HOME" "${cudaPackages.cudnn}") + (lib.cmakeFeature "CMAKE_CUDA_ARCHITECTURES" cudaArchitecturesString) + (lib.cmakeFeature "onnxruntime_NVCC_THREADS" "1") + ] + ++ lib.optionals rocmSupport [ + (lib.cmakeFeature "ROCM_PATH" "${rocmPackages.rocm-core}") + # Comprehensive AMD GPU architecture support: + # MI Cards: gfx900 (MI25/Vega 10), gfx906 (MI50/MI60/Vega 20), gfx908 (MI100/CDNA), gfx90a (MI200/CDNA2), gfx942 (MI300/CDNA3) + # RDNA Cards: gfx1010 (RX 5700/Navi 10), gfx1011 (Pro 5600M/Navi 12), gfx1012 (RX 5500/Navi 14), gfx1020 (Navi 21 early), gfx1030 (RX 6800/6900/Navi 21/22), gfx1100 (RX 7900/Navi 31) + (lib.cmakeFeature "CMAKE_HIP_ARCHITECTURES" "gfx900;gfx906;gfx908;gfx90a;gfx942;gfx1010;gfx1011;gfx1012;gfx1020;gfx1030;gfx1100") + (lib.cmakeFeature "HIP_COMPILER" "${rocmPackages.hipcc}/bin/hipcc") + (lib.cmakeFeature "CMAKE_CXX_COMPILER" "${rocmPackages.hipcc}/bin/hipcc") + ]; + + env = lib.optionalAttrs effectiveStdenv.cc.isClang { + NIX_CFLAGS_COMPILE = "-Wno-error"; + }; + + doCheck = + !( + cudaSupport + || builtins.elem effectiveStdenv.buildPlatform.system [ + # aarch64-linux fails cpuinfo test, because /sys/devices/system/cpu/ does not exist in the sandbox + "aarch64-linux" + # 1 - onnxruntime_test_all (Failed) + # 4761 tests from 311 test suites ran, 57 failed. + "loongarch64-linux" + ] + ); + + requiredSystemFeatures = lib.optionals cudaSupport [ "big-parallel" ]; + + hardeningEnable = lib.optionals (effectiveStdenv.hostPlatform.system == "loongarch64-linux") [ + "nostrictaliasing" + ]; + + postPatch = '' + substituteInPlace cmake/libonnxruntime.pc.cmake.in \ + --replace-fail '$'{prefix}/@CMAKE_INSTALL_ @CMAKE_INSTALL_ + echo "find_package(cudnn_frontend REQUIRED)" > cmake/external/cudnn_frontend.cmake + + # https://github.com/microsoft/onnxruntime/blob/c4f3742bb456a33ee9c826ce4e6939f8b84ce5b0/onnxruntime/core/platform/env.h#L249 + substituteInPlace onnxruntime/core/platform/env.h --replace-fail \ + "GetRuntimePath() const { return PathString(); }" \ + "GetRuntimePath() const { return PathString(\"$out/lib/\"); }" + '' + + lib.optionalString (effectiveStdenv.hostPlatform.system == "aarch64-linux") '' + # https://github.com/NixOS/nixpkgs/pull/226734#issuecomment-1663028691 + rm -v onnxruntime/test/optimizer/nhwc_transformer_test.cc + ''; + + postBuild = lib.optionalString pythonSupport '' + ${python3Packages.python.interpreter} ../setup.py bdist_wheel + ''; + + postInstall = '' + # perform parts of `tools/ci_build/github/linux/copy_strip_binary.sh` + install -m644 -Dt $out/include \ + ../include/onnxruntime/core/framework/provider_options.h \ + ../include/onnxruntime/core/providers/cpu/cpu_provider_factory.h \ + ../include/onnxruntime/core/session/onnxruntime_*.h + ''; + + passthru = { + inherit cudaSupport cudaPackages; # for the python module + inherit rocmSupport rocmPackages rcclSupport; # for the python module + inherit protobuf; + tests = lib.optionalAttrs pythonSupport { + python = python3Packages.onnxruntime; + }; + }; + + meta = { + description = "Cross-platform, high performance scoring engine for ML models"; + longDescription = '' + ONNX Runtime is a performance-focused complete scoring engine + for Open Neural Network Exchange (ONNX) models, with an open + extensible architecture to continually address the latest developments + in AI and Deep Learning. ONNX Runtime stays up to date with the ONNX + standard with complete implementation of all ONNX operators, and + supports all ONNX releases (1.2+) with both future and backwards + compatibility. + ''; + homepage = "https://github.com/microsoft/onnxruntime"; + changelog = "https://github.com/microsoft/onnxruntime/releases/tag/v${version}"; + # https://github.com/microsoft/onnxruntime/blob/master/BUILD.md#architectures + platforms = lib.platforms.unix; + license = lib.licenses.mit; + maintainers = with lib.maintainers; [ + puffnfresh + ck3d + ]; + }; +} diff --git a/desktop/l/custom-packages/python-onnxruntime/default.nix b/desktop/l/custom-packages/python-onnxruntime/default.nix new file mode 100644 index 0000000..36dd498 --- /dev/null +++ b/desktop/l/custom-packages/python-onnxruntime/default.nix @@ -0,0 +1,94 @@ +{ lib +, stdenv +, buildPythonPackage +, onnxruntime +, autoPatchelfHook +, # buildInputs + oneDNN +, re2 +, # dependencies + coloredlogs +, numpy +, packaging +, +}: + +# onnxruntime requires an older protobuf. +# Doing an override in protobuf in the python-packages set +# can give you a functioning Python package but note not +# all Python packages will be compatible then. +# +# Because protobuf is not always needed we remove it +# as a runtime dependency from our wheel. +# +# We do include here the non-Python protobuf so the shared libs +# link correctly. If you do also want to include the Python +# protobuf, you can add it to your Python env, but be aware +# the version likely mismatches with what is used here. + +buildPythonPackage { + inherit (onnxruntime) pname version; + format = "wheel"; + src = onnxruntime.dist; + + unpackPhase = '' + cp -r $src dist + chmod +w dist + ''; + + nativeBuildInputs = lib.optionals stdenv.hostPlatform.isLinux [ autoPatchelfHook ]; + + # This project requires fairly large dependencies such as sympy which we really don't always need. + pythonRemoveDeps = [ + "flatbuffers" + "protobuf" + "sympy" + ]; + + # Libraries are not linked correctly. + buildInputs = [ + oneDNN + re2 + onnxruntime.protobuf + + # https://github.com/NixOS/nixpkgs/pull/357656 patches the onnx lib to ${pkgs.onnxruntime}/lib + # but these files are copied into this package too. If the original non-python onnxruntime + # package is GC-ed, cuda support in this python package will break. + # Two options, rebuild onnxruntime twice with the different paths hard-coded, or just hold a runtime + # dependency between the two. Option 2, because onnxruntime takes forever to build with cuda support. + # Same applies to ROCm support - the Python package inherits ROCm support from the core package. + onnxruntime + ] + ++ lib.optionals onnxruntime.passthru.cudaSupport ( + with onnxruntime.passthru.cudaPackages; + [ + libcublas # libcublasLt.so.XX libcublas.so.XX + libcurand # libcurand.so.XX + libcufft # libcufft.so.XX + cudnn # libcudnn.soXX + cuda_cudart # libcudart.so.XX + nccl # libnccl.so.XX + ] + ) + ++ lib.optionals onnxruntime.passthru.rocmSupport ( + with onnxruntime.passthru.rocmPackages; + [ + rocm-core # ROCm core libraries + rocm-runtime # ROCm runtime libraries + hipblas # libhipblas.so.XX + rocblas # librocblas.so.XX + miopen # libMIOpen.so.XX + rocfft # librocfft.so.XX + rocsparse # librocsparse.so.XX + rccl # librccl.so.XX (when rcclSupport is enabled) + ] + ); + + dependencies = [ + coloredlogs + numpy + packaging + ]; + + meta = onnxruntime.meta; +} diff --git a/desktop/l/flake.nix b/desktop/l/flake.nix index b787b15..352c890 100644 --- a/desktop/l/flake.nix +++ b/desktop/l/flake.nix @@ -33,26 +33,9 @@ "google-chrome" "android-studio" "android-studio-stable" + "vscode" ]; }; - overlays = [ - (final: prev: { - onnxruntime = final.callPackage /home/das/Downloads/nixpkgs/pkgs/by-name/on/onnxruntime/package.nix { - rocmSupport = true; - rcclSupport = true; - }; - python313Packages = prev.python313Packages.override (old: { - overrides = prev.lib.composeManyExtensions [ - (final: prev: { - onnxruntime = final.callPackage /home/das/Downloads/nixpkgs/pkgs/development/python-modules/onnxruntime/default.nix { - onnxruntime = final.onnxruntime; # Use the overlay version - }; - }) - old.overrides or (final: prev: { }) - ]; - }); - }) - ]; }; lib = nixpkgs.lib; in { @@ -67,8 +50,37 @@ #hyprland.nixosModules.default home-manager.nixosModules.home-manager { + # Apply the overlay to NixOS + nixpkgs.overlays = [ + (final: prev: { + onnxruntime = final.callPackage ./custom-packages/onnxruntime/package.nix { + rocmSupport = true; + rcclSupport = true; + }; + python313Packages = prev.python313Packages.override (old: { + overrides = prev.lib.composeManyExtensions [ + (final: prev: { + onnxruntime = final.callPackage ./custom-packages/python-onnxruntime/default.nix { + onnxruntime = final.onnxruntime; + }; + }) + old.overrides or (final: prev: { }) + ]; + }); + }) + ]; + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ + "google-chrome" + "android-studio" + "android-studio-stable" + "vscode" + ]; + # https://nix-community.github.io/home-manager/nixos-options.xhtml#nixos-opt-home-manager.useGlobalPkgs - #home-manager.useGlobalPkgs = true; # This disables the Home Manager options nixpkgs.*. + home-manager.useGlobalPkgs = true; # This disables the Home Manager options nixpkgs.*. home-manager.useUserPackages = true; home-manager.users.das = { config, pkgs, ... }: { imports = [ diff --git a/desktop/l/home.nix b/desktop/l/home.nix index 473bc74..617b7a8 100644 --- a/desktop/l/home.nix +++ b/desktop/l/home.nix @@ -58,9 +58,6 @@ #CHROME_EXECUTABLE = "/etc/profiles/per-user/das/bin/google-chrome-stable"; CHROME_EXECUTABLE = "${pkgs.google-chrome}/bin/google-chrome-stable"; GOOGLE_APPLICATION_CREDENTIALS="~/Downloads/dashboard-dev-3da32-83d127a0f9ba.json"; - - # Python path for onnxruntime - PYTHONPATH = "${pkgs.python313Packages.onnxruntime}/lib/python3.13/site-packages"; }; home.packages = with pkgs; [ @@ -678,8 +675,7 @@ }; # https://github.com/colemickens/nixcfg/blob/1915d408ea28a5b7279f94df7a982dbf2cf692ef/mixins/ghostty.nix#L19 - # set at flake.nix level - nixpkgs.config.allowUnfree = true; + # nixpkgs.config.allowUnfree is set at flake.nix level home.stateVersion = "24.11"; } diff --git a/desktop/l/systemPackages.nix b/desktop/l/systemPackages.nix index 7ed35da..eb98dce 100644 --- a/desktop/l/systemPackages.nix +++ b/desktop/l/systemPackages.nix @@ -4,8 +4,7 @@ ... }: { - # set at flake.nix level - nixpkgs.config.allowUnfree = true; + # nixpkgs.config.allowUnfree is set at flake.nix level # $ nix search wget environment.systemPackages = with pkgs; [ From 26f6990dfeeb50b2912c07f93f2f5c27c6dafbd3 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Sun, 21 Sep 2025 11:29:47 -0700 Subject: [PATCH 18/23] works --- .../l/custom-packages/onnxruntime/package.nix | 41 +++++++++++++++---- .../python-onnxruntime/default.nix | 6 ++- desktop/l/flake.nix | 15 ++----- desktop/l/home.nix | 4 +- 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/desktop/l/custom-packages/onnxruntime/package.nix b/desktop/l/custom-packages/onnxruntime/package.nix index 3299efd..56e2d9b 100644 --- a/desktop/l/custom-packages/onnxruntime/package.nix +++ b/desktop/l/custom-packages/onnxruntime/package.nix @@ -2,11 +2,11 @@ , stdenv , lib , fetchFromGitHub -, abseil-cpp_202508 +, abseil-cpp_202407 , cmake , cpuinfo , eigen -, flatbuffers +, flatbuffers_23 , glibcLocales , gtest , howard-hinnant-date @@ -49,21 +49,21 @@ let owner = "boostorg"; repo = "mp11"; tag = "boost-1.89.0"; - hash = "sha256-6dbfae01358be88ebefcdfb7707a2a68ba914c39dc83fdd85f556761fe0fafb4"; + hash = "sha256-HcQJ/PXBQdWVjGZy28X2LxVRfjV2nkeLTusNjT9ssXI="; }; safeint = fetchFromGitHub { owner = "dcleblanc"; repo = "safeint"; tag = "3.0.28a"; - hash = "sha256-9e652d065a3cef80623287d5dc61edcf6a95ddab38a9dfeb34f155261fc9cef7"; + hash = "sha256-MT2nba15DDApNQZxOBkf0DPvc759rEhpwfcD6ERphl0="; }; onnx = fetchFromGitHub { owner = "onnx"; repo = "onnx"; - tag = "v1.19.0"; - hash = "sha256-2c2ac5a078b0350a0723fac606be8cd9e9e8cbd4c99bab1bffe2623b188fd236"; + tag = "v1.17.0"; + hash = "sha256-9oORW0YlQ6SphqfbjcYb0dTlHc+1gzy9quH/Lj6By8Q="; }; cutlass = fetchFromGitHub { @@ -77,7 +77,7 @@ let owner = "dmlc"; repo = "dlpack"; tag = "v1.1"; - hash = "sha256-2e3b94b55825c240cc58e6721e15b449978cbae21a2a4caa23058b0157ee2fb3"; + hash = "sha256-RoJxvlrt1QcGvB8m/kycziTbO367diOpsnro49hDl24="; }; isCudaJetson = cudaSupport && cudaPackages.flags.isJetsonBuild; @@ -118,6 +118,8 @@ effectiveStdenv.mkDerivation rec { ++ lib.optionals rocmSupport [ rocmPackages.rocm-cmake rocmPackages.hipcc + rocmPackages.llvm.clang + rocmPackages.rocm-device-libs ]; buildInputs = [ @@ -205,9 +207,9 @@ effectiveStdenv.mkDerivation rec { (lib.cmakeBool "ABSL_ENABLE_INSTALL" true) (lib.cmakeBool "FETCHCONTENT_FULLY_DISCONNECTED" true) (lib.cmakeBool "FETCHCONTENT_QUIET" false) - (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_ABSEIL_CPP" "${abseil-cpp_202508.src}") + (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_ABSEIL_CPP" "${abseil-cpp_202407.src}") (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_DLPACK" "${dlpack}") - (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_FLATBUFFERS" "${flatbuffers.src}") + (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_FLATBUFFERS" "${flatbuffers_23.src}") (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_MP11" "${mp11}") (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_ONNX" "${onnx}") (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_RE2" "${re2.src}") @@ -245,6 +247,17 @@ effectiveStdenv.mkDerivation rec { env = lib.optionalAttrs effectiveStdenv.cc.isClang { NIX_CFLAGS_COMPILE = "-Wno-error"; + } // lib.optionalAttrs rocmSupport { + # ROCm environment variables for HIP compiler + ROCM_PATH = "${rocmPackages.rocm-core}"; + HIP_PATH = "${rocmPackages.hipcc}"; + HIP_CLANG_PATH = "${rocmPackages.llvm.clang}/bin"; + HSA_PATH = "${rocmPackages.rocm-core}"; + HIP_PLATFORM = "amd"; + HIP_COMPILER = "clang"; + HIP_RUNTIME = "rocclr"; + # ROCm device library path + ROCM_DEVICE_LIB_PATH = "${rocmPackages.rocm-device-libs}/lib"; }; doCheck = @@ -280,6 +293,16 @@ effectiveStdenv.mkDerivation rec { rm -v onnxruntime/test/optimizer/nhwc_transformer_test.cc ''; + preConfigure = lib.optionalString rocmSupport '' + # Create symlinks for ROCm tools that HIP compiler expects + mkdir -p /tmp/rocm/bin /tmp/rocm/lib/llvm/bin + ln -sf ${rocmPackages.rocm-core}/bin/rocm_agent_enumerator /tmp/rocm/bin/rocm_agent_enumerator + ln -sf ${rocmPackages.llvm.clang}/bin/clang++ /tmp/rocm/lib/llvm/bin/clang++ + ln -sf ${rocmPackages.llvm.clang}/bin/clang /tmp/rocm/lib/llvm/bin/clang + export ROCM_PATH=/tmp/rocm + export ROCM_DEVICE_LIB_PATH=${rocmPackages.rocm-device-libs}/lib + ''; + postBuild = lib.optionalString pythonSupport '' ${python3Packages.python.interpreter} ../setup.py bdist_wheel ''; diff --git a/desktop/l/custom-packages/python-onnxruntime/default.nix b/desktop/l/custom-packages/python-onnxruntime/default.nix index 36dd498..22c6ce1 100644 --- a/desktop/l/custom-packages/python-onnxruntime/default.nix +++ b/desktop/l/custom-packages/python-onnxruntime/default.nix @@ -59,7 +59,9 @@ buildPythonPackage { # Same applies to ROCm support - the Python package inherits ROCm support from the core package. onnxruntime ] - ++ lib.optionals onnxruntime.passthru.cudaSupport ( + # Note: CUDA and ROCm support dependencies are handled by the core onnxruntime package + # The Python package inherits the same capabilities through the shared libraries + ++ lib.optionals (onnxruntime ? passthru && onnxruntime.passthru ? cudaSupport && onnxruntime.passthru.cudaSupport) ( with onnxruntime.passthru.cudaPackages; [ libcublas # libcublasLt.so.XX libcublas.so.XX @@ -70,7 +72,7 @@ buildPythonPackage { nccl # libnccl.so.XX ] ) - ++ lib.optionals onnxruntime.passthru.rocmSupport ( + ++ lib.optionals (onnxruntime ? passthru && onnxruntime.passthru ? rocmSupport && onnxruntime.passthru.rocmSupport) ( with onnxruntime.passthru.rocmPackages; [ rocm-core # ROCm core libraries diff --git a/desktop/l/flake.nix b/desktop/l/flake.nix index 352c890..fade3f6 100644 --- a/desktop/l/flake.nix +++ b/desktop/l/flake.nix @@ -53,20 +53,11 @@ # Apply the overlay to NixOS nixpkgs.overlays = [ (final: prev: { + # Custom onnxruntime with ROCm support (temporarily disabled) onnxruntime = final.callPackage ./custom-packages/onnxruntime/package.nix { - rocmSupport = true; - rcclSupport = true; + rocmSupport = false; + rcclSupport = false; }; - python313Packages = prev.python313Packages.override (old: { - overrides = prev.lib.composeManyExtensions [ - (final: prev: { - onnxruntime = final.callPackage ./custom-packages/python-onnxruntime/default.nix { - onnxruntime = final.onnxruntime; - }; - }) - old.overrides or (final: prev: { }) - ]; - }); }) ]; diff --git a/desktop/l/home.nix b/desktop/l/home.nix index 617b7a8..fa3ffc5 100644 --- a/desktop/l/home.nix +++ b/desktop/l/home.nix @@ -449,10 +449,10 @@ # Screenshot tool with Wayland support (flameshot.override { enableWlrSupport = true; }) - # Custom onnxruntime package + # Custom onnxruntime package with ROCm support onnxruntime - # Custom Python onnxruntime module + # Standard Python onnxruntime module (should work with custom C++ library) python313Packages.onnxruntime ]; From cdb9692f222e8b46d0941120af771fc5911aed3c Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Mon, 13 Oct 2025 13:32:15 -0700 Subject: [PATCH 19/23] 2025 10 13 --- .../onnxruntime/CMakeLists.txt | 1819 +++++++++++++++++ .../fix-composable-kernel-path.patch | 10 + .../l/custom-packages/onnxruntime/package.nix | 277 ++- desktop/l/flake.nix | 32 +- desktop/l/home.nix | 6 +- 5 files changed, 2098 insertions(+), 46 deletions(-) create mode 100644 desktop/l/custom-packages/onnxruntime/CMakeLists.txt create mode 100644 desktop/l/custom-packages/onnxruntime/fix-composable-kernel-path.patch diff --git a/desktop/l/custom-packages/onnxruntime/CMakeLists.txt b/desktop/l/custom-packages/onnxruntime/CMakeLists.txt new file mode 100644 index 0000000..a479ba3 --- /dev/null +++ b/desktop/l/custom-packages/onnxruntime/CMakeLists.txt @@ -0,0 +1,1819 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates +# Licensed under the MIT License. + +# Minimum CMake required +cmake_minimum_required(VERSION 3.28) + +# Don't let cmake set a default value for CMAKE_CUDA_ARCHITECTURES +cmake_policy(SET CMP0104 OLD) +# Project +project(onnxruntime C CXX ASM) + +# Disable fast-math for Intel oneAPI compiler +if("${CMAKE_CXX_COMPILER_ID}" MATCHES "IntelLLVM") + if("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC-like") + # Using icx-cl compiler driver with MSVC-like arguments + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fp:precise") + else() + # Using icpx compiler driver + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-fast-math") + endif() +endif() + +# Needed for Java +if (NOT CMAKE_CXX_STANDARD) + set(CMAKE_C_STANDARD 99) +endif() + +include(CheckCXXCompilerFlag) +include(CheckLanguage) +include(CMakeDependentOption) +include(FetchContent) +include(CheckFunctionExists) +include(CheckSymbolExists) +include(GNUInstallDirs) # onnxruntime_providers_* require CMAKE_INSTALL_* variables + +if (NOT CMAKE_CXX_STANDARD) + # TODO: update this once all system adapt c++20 + if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(CMAKE_CXX_STANDARD 20) + else() + set(CMAKE_CXX_STANDARD 17) + endif() +endif() + +if (MSVC) + # Make sure Visual Studio sets __cplusplus macro correctly: https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:__cplusplus") +endif() + +set_property(GLOBAL PROPERTY USE_FOLDERS ON) +# NOTE: POSITION INDEPENDENT CODE hurts performance, and it only make sense on POSIX systems +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +enable_testing() +if (NOT CMAKE_BUILD_TYPE) + message(STATUS "Build type not set - using RelWithDebInfo") + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose build type: Debug Release RelWithDebInfo MinSizeRel." FORCE) +endif() + +# Options +option(onnxruntime_USE_VCPKG "Build with the vcpkg package manager" OFF) +option(onnxruntime_RUN_ONNX_TESTS "Enable ONNX Compatibility Testing" OFF) +option(onnxruntime_GENERATE_TEST_REPORTS "Enable test report generation" OFF) +option(onnxruntime_ENABLE_STATIC_ANALYSIS "Enable static analysis" OFF) +option(onnxruntime_USE_CUSTOM_STATIC_ANALYSIS_RULES "Use a custom SDL Rule. It is mainly for our CI build" OFF) +option(onnxruntime_REDIRECT_STATIC_ANALYSIS_OUTPUTS_TO_FILE "Use a custom SDL Rule. It is mainly for our CI build" OFF) +option(onnxruntime_ENABLE_PYTHON "Enable python bindings" OFF) +# Enable it may cause LNK1169 error +option(onnxruntime_ENABLE_MEMLEAK_CHECKER "Experimental: Enable memory leak checker in Windows debug build" OFF) +option(onnxruntime_ENABLE_CONVSYMKERNELAVX2_SAT_CHECKER "Experimental: Enable ConvSymKernelAvx2 assembly saturation checker in build" OFF) +option(onnxruntime_USE_CUDA "Build with CUDA support" OFF) +# Enable ONNX Runtime CUDA EP's internal unit tests that directly access the EP's internal functions instead of through +# OpKernels. When the option is ON, we will have two copies of GTest library in the same process. It is not a typical +# use. If you hit any problem with that, please do not report it to GTest. Turn OFF the following build option instead. +cmake_dependent_option(onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS "Build with CUDA unit tests" OFF "onnxruntime_USE_CUDA;onnxruntime_BUILD_UNIT_TESTS" OFF) + +cmake_dependent_option(onnxruntime_USE_CUDA_NHWC_OPS "Build CUDA with NHWC op support" ON "onnxruntime_USE_CUDA" OFF) +option(onnxruntime_CUDA_MINIMAL "Build CUDA without any operations apart from memcpy ops. Usefuel for a very minial TRT build" OFF) +option(onnxruntime_ENABLE_CUDA_LINE_NUMBER_INFO "When building with CUDA support, generate device code line number information." OFF) +option(onnxruntime_USE_OPENVINO "Build with OpenVINO support" OFF) +option(onnxruntime_USE_COREML "Build with CoreML support" OFF) +option(onnxruntime_USE_NNAPI_BUILTIN "Build with builtin NNAPI lib for Android NNAPI support" OFF) +option(onnxruntime_USE_QNN "Build with QNN support" OFF) +option(onnxruntime_BUILD_QNN_EP_STATIC_LIB "Build with QNN EP as a static library" OFF) +option(onnxruntime_USE_SNPE "Build with SNPE support" OFF) +option(onnxruntime_USE_RKNPU "Build with RKNPU support" OFF) +option(onnxruntime_USE_DNNL "Build with DNNL support" OFF) +option(onnxruntime_USE_JSEP "Build with JavaScript implemented kernels support" OFF) +option(onnxruntime_USE_KLEIDIAI "Build with KleidiAI integration in MLAS" OFF) +# iOS simulator build explicitly builds targets with USE_KLEIDIAI=ON so attempting to force override if so +if(APPLE AND CMAKE_OSX_ARCHITECTURES MATCHES "x86_64") + message(WARNING "Disabling KleidiAI: not supported on Apple x86_64 platforms") + set(onnxruntime_USE_KLEIDIAI OFF CACHE BOOL "" FORCE) +endif() +option(onnxruntime_BUILD_UNIT_TESTS "Build ONNXRuntime unit tests" ON) +option(onnxruntime_BUILD_CSHARP "Build C# library" OFF) +option(onnxruntime_BUILD_OBJC "Build Objective-C library" OFF) +option(onnxruntime_USE_PREINSTALLED_EIGEN "Use pre-installed EIGEN. Need to provide eigen_SOURCE_PATH if turn this on." OFF) +option(onnxruntime_BUILD_BENCHMARKS "Build ONNXRuntime micro-benchmarks" OFF) +option(onnxruntime_USE_VSINPU "Build with VSINPU support" OFF) + +cmake_dependent_option(onnxruntime_USE_FLASH_ATTENTION "Build flash attention kernel for scaled dot product attention" ON "onnxruntime_USE_CUDA" OFF) +option(onnxruntime_USE_LEAN_ATTENTION "Build lean attention kernel for scaled dot product attention" OFF) +cmake_dependent_option(onnxruntime_USE_MEMORY_EFFICIENT_ATTENTION "Build memory efficient attention kernel for scaled dot product attention" ON "onnxruntime_USE_CUDA" OFF) +cmake_dependent_option(onnxruntime_USE_FPA_INTB_GEMM "Build FpA IntB gemm cuda kernels" ON "onnxruntime_USE_CUDA" OFF) + +option(onnxruntime_BUILD_FOR_NATIVE_MACHINE "Enable this option for turning on optimization specific to this machine" OFF) +option(onnxruntime_USE_AVX "Use AVX instructions" OFF) +option(onnxruntime_USE_AVX2 "Use AVX2 instructions" OFF) +option(onnxruntime_USE_AVX512 "Use AVX512 instructions" OFF) + +option(onnxruntime_BUILD_SHARED_LIB "Build a shared library" OFF) +option(onnxruntime_BUILD_APPLE_FRAMEWORK "Build a macOS/iOS framework" OFF) +option(onnxruntime_ENABLE_MICROSOFT_INTERNAL "Use this option to enable/disable microsoft internal only code" OFF) + +option(onnxruntime_USE_VITISAI "Build with Vitis-AI" OFF) +option(onnxruntime_USE_TENSORRT "Build with TensorRT support" OFF) +option(onnxruntime_USE_TENSORRT_BUILTIN_PARSER "Use TensorRT builtin parser" OFF) +option(onnxruntime_USE_NV "Build with TensorRT support" OFF) +option(onnxruntime_ENABLE_LTO "Enable link time optimization" OFF) +option(onnxruntime_CROSS_COMPILING "Cross compiling onnx runtime" OFF) +option(onnxruntime_GCOV_COVERAGE "Compile with options necessary to run code coverage" OFF) +option(onnxruntime_DONT_VECTORIZE "Do not vectorize operations in Eigen" OFF) + +option(onnxruntime_USE_FULL_PROTOBUF "Link to libprotobuf instead of libprotobuf-lite when this option is ON" OFF) +option(onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS "Dump debug information about node inputs and outputs when executing the model." OFF) +cmake_dependent_option(onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS_ENABLE_DUMP_TO_SQLDB "Build dump debug information about node inputs and outputs with support for sql database." OFF "onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS" OFF) + +# When loading a delay loaded DLL, Windows searches the main EXE's folder first. +cmake_dependent_option(onnxruntime_ENABLE_DELAY_LOADING_WIN_DLLS "Delay load some of the dependent DLls that are part of the OS" ON "WIN32;NOT GDK_PLATFORM" OFF) +option(onnxruntime_USE_DML "Build with DirectML support" OFF) +option(onnxruntime_USE_MIGRAPHX "Build with AMDMIGraphX support" OFF) +option(onnxruntime_USE_WINML "Build with WinML support" OFF) +option(onnxruntime_USE_ACL "Build with ACL support" OFF) +option(onnxruntime_USE_ARMNN "Build with ArmNN support" OFF) +option(onnxruntime_ARMNN_RELU_USE_CPU "Use the CPU implementation for the Relu operator for the ArmNN EP" ON) +option(onnxruntime_ARMNN_BN_USE_CPU "Use the CPU implementation for the Batch Normalization operator for the ArmNN EP" ON) +option(onnxruntime_ENABLE_INSTRUMENT "Enable Instrument with Event Tracing for Windows (ETW)" OFF) +option(onnxruntime_USE_TELEMETRY "Build with Telemetry" OFF) +cmake_dependent_option(onnxruntime_USE_MIMALLOC "Override new/delete and arena allocator with mimalloc" OFF "WIN32;NOT onnxruntime_USE_CUDA;NOT onnxruntime_USE_OPENVINO" OFF) +option(onnxruntime_USE_CANN "Build with CANN support" OFF) +option(onnxruntime_USE_XNNPACK "Build with XNNPACK support. Provides an alternative math library on ARM, WebAssembly and x86." OFF) +option(onnxruntime_USE_WEBNN "Build with WebNN support. Enable hardware acceleration in web browsers." OFF) +option(onnxruntime_USE_WEBGPU "Build with WebGPU support. Enable WebGPU via C/C++ interface." OFF) +option(onnxruntime_WGSL_TEMPLATE "Specify the code generator for WGSL template. Default is static." "static") +option(onnxruntime_USE_EXTERNAL_DAWN "Build with treating Dawn as external dependency. Will not link Dawn at build time." OFF) +option(onnxruntime_CUSTOM_DAWN_SRC_PATH "Path to custom Dawn src dir.") +option(onnxruntime_BUILD_DAWN_SHARED_LIBRARY "Build Dawn as a shared library" OFF) +option(onnxruntime_ENABLE_PIX_FOR_WEBGPU_EP "Adding frame present for PIX to capture a frame" OFF) +# The following 2 options are only for Windows +option(onnxruntime_ENABLE_DAWN_BACKEND_VULKAN "Enable Vulkan backend for Dawn (on Windows)" OFF) +option(onnxruntime_ENABLE_DAWN_BACKEND_D3D12 "Enable D3D12 backend for Dawn (on Windows)" ON) + +# Options related to reducing the binary size produced by the build +# XNNPACK EP requires the internal NHWC contrib ops to be available, so this option must be OFF when onnxruntime_USE_XNNPACK is ON +cmake_dependent_option(onnxruntime_DISABLE_CONTRIB_OPS "Disable contrib ops" OFF "NOT onnxruntime_USE_XNNPACK" OFF) +option(onnxruntime_DISABLE_ML_OPS "Disable traditional ML ops" OFF) +option(onnxruntime_DISABLE_SPARSE_TENSORS "Disable sparse tensors data types" OFF) +option(onnxruntime_DISABLE_OPTIONAL_TYPE "Disable optional type" OFF) +option(onnxruntime_DISABLE_FLOAT8_TYPES "Disable float 8 types" OFF) +option(onnxruntime_DISABLE_FLOAT4_TYPES "Disable float 4 types" OFF) +option(onnxruntime_MINIMAL_BUILD "Exclude as much as possible from the build. Support ORT format models. No support for ONNX format models." OFF) +option(onnxruntime_CLIENT_PACKAGE_BUILD "Enables default settings that are more appropriate for client/on-device workloads." OFF) +cmake_dependent_option(onnxruntime_DISABLE_RTTI "Disable RTTI" ON "NOT onnxruntime_ENABLE_PYTHON;NOT onnxruntime_USE_CUDA" OFF) +# For now onnxruntime_DISABLE_EXCEPTIONS will only work with onnxruntime_MINIMAL_BUILD, more changes (ONNX, non-CPU EP, ...) are required to run this standalone +cmake_dependent_option(onnxruntime_DISABLE_EXCEPTIONS "Disable exception handling. Requires onnxruntime_MINIMAL_BUILD currently." ON "onnxruntime_MINIMAL_BUILD;NOT onnxruntime_ENABLE_PYTHON" OFF) +# Even when onnxruntime_DISABLE_ABSEIL is ON, ONNX Runtime still needs to link to abseil. +option(onnxruntime_DISABLE_ABSEIL "Do not use Abseil data structures in ONNX Runtime source code. Redefine Inlined containers to STD containers." OFF) + +option(onnxruntime_EXTENDED_MINIMAL_BUILD "onnxruntime_MINIMAL_BUILD with support for execution providers that compile kernels." OFF) +option(onnxruntime_MINIMAL_BUILD_CUSTOM_OPS "Add custom operator kernels support to a minimal build." OFF) +option(onnxruntime_REDUCED_OPS_BUILD "Reduced set of kernels are registered in build via modification of the kernel registration source files." OFF) +option(onnxruntime_DISABLE_EXTERNAL_INITIALIZERS "Don't allow models to load external data" OFF) + +#A special option just for debugging and sanitize check. Please do not enable in option in retail builds. +#The option has no effect on Windows. +option(onnxruntime_USE_VALGRIND "Build with valgrind hacks" OFF) + +# A special build option only used for gathering code coverage info +option(onnxruntime_RUN_MODELTEST_IN_DEBUG_MODE "Run model tests even in debug mode" OFF) + +# options for security fuzzing +# build configuration for fuzz testing is in onnxruntime_fuzz_test.cmake +option(onnxruntime_FUZZ_TEST "Enable Fuzz testing" OFF) + +# training options +option(onnxruntime_ENABLE_NVTX_PROFILE "Enable NVTX profile." OFF) +option(onnxruntime_ENABLE_MEMORY_PROFILE "Enable memory profile." OFF) +option(onnxruntime_ENABLE_TRAINING "Enable full training functionality. Includes ORTModule and ORT Training APIs" OFF) +option(onnxruntime_ENABLE_TRAINING_APIS "Enable ort training apis." OFF) +option(onnxruntime_ENABLE_TRAINING_OPS "Include training operators but no training session support." OFF) +option(onnxruntime_ENABLE_TRAINING_E2E_TESTS "Enable training end-to-end tests." OFF) +option(onnxruntime_ENABLE_CPU_FP16_OPS "Build with advanced instruction sets" ON) +option(onnxruntime_USE_NCCL "Build with NCCL support" OFF) + +# WebAssembly options +option(onnxruntime_BUILD_WEBASSEMBLY_STATIC_LIB "Enable this option to create WebAssembly static library" OFF) +option(onnxruntime_ENABLE_WEBASSEMBLY_THREADS "Enable this option to create WebAssembly byte codes with multi-threads support" OFF) +option(onnxruntime_ENABLE_WEBASSEMBLY_EXCEPTION_CATCHING "Enable this option to turn on exception catching" OFF) +option(onnxruntime_ENABLE_WEBASSEMBLY_API_EXCEPTION_CATCHING "Enable this option to turn on api exception catching" OFF) +option(onnxruntime_ENABLE_WEBASSEMBLY_EXCEPTION_THROWING "Enable this option to turn on exception throwing even if the build disabled exceptions support" OFF) +option(onnxruntime_WEBASSEMBLY_RUN_TESTS_IN_BROWSER "Enable this option to run tests in browser instead of Node.js" OFF) +option(onnxruntime_ENABLE_WEBASSEMBLY_DEBUG_INFO "Enable this option to turn on DWARF format debug info" OFF) +option(onnxruntime_ENABLE_WEBASSEMBLY_PROFILING "Enable this option to turn on WebAssembly profiling and preserve function names" OFF) +option(onnxruntime_ENABLE_WEBASSEMBLY_OUTPUT_OPTIMIZED_MODEL "Enable this option to allow WebAssembly to output optimized model" OFF) +option(onnxruntime_ENABLE_WEBASSEMBLY_RELAXED_SIMD "Enable WebAssembly Relaxed SIMD" OFF) + +# Enable bitcode for iOS +option(onnxruntime_ENABLE_BITCODE "Enable bitcode for iOS only" OFF) + +# build Pytorch's LazyTensor support +cmake_dependent_option(onnxruntime_ENABLE_LAZY_TENSOR "Enable ORT as a LazyTensor backend in Pytorch." ON "onnxruntime_ENABLE_TRAINING" OFF) + +# build separate library of schemas of (custom) ops used by ORT (for ONNX to MLIR translation) +option(onnxruntime_BUILD_OPSCHEMA_LIB "Build op schema library" ON) + +# option to enable custom operators in onnxruntime-extensions +option(onnxruntime_USE_EXTENSIONS "Build with onnxruntime-extensions for more features" OFF) + +# option to enable custom operators in onnxruntime-extensions with a custom path +option(onnxruntime_EXTENSIONS_OVERRIDDEN, "Enable onnxruntime-extensions overridden" OFF) + +# Enable registering custom op schemas from shared libraries in python environment. +option(onnxruntime_ENABLE_EXTERNAL_CUSTOM_OP_SCHEMAS "Enable registering user defined custom op schemas dynamically" OFF) + +set(ONNX_CUSTOM_PROTOC_EXECUTABLE "" CACHE STRING "Specify custom protoc executable to build ONNX") + +# pre-build python path +option(onnxruntime_PREBUILT_PYTORCH_PATH "Path to pytorch installation dir") + +# external transformer src path +option(onnxruntime_EXTERNAL_TRANSFORMER_SRC_PATH "Path to external transformer src dir") + +option(onnxruntime_ENABLE_CUDA_PROFILING "Enable CUDA kernel profiling" OFF) + +option(onnxruntime_ENABLE_CPUINFO "Enable cpuinfo" ON) + +# ATen fallback support +option(onnxruntime_ENABLE_ATEN "Enable ATen fallback" OFF) + +# dlpack support +cmake_dependent_option(onnxruntime_ENABLE_DLPACK "Enable dlpack" ON "onnxruntime_ENABLE_TRAINING OR onnxruntime_ENABLE_ATEN OR onnxruntime_ENABLE_PYTHON" OFF) +option(onnxruntime_USE_AZURE "Build with azure inferencing support" OFF) +option(onnxruntime_USE_LOCK_FREE_QUEUE "Build with lock-free task queue for threadpool." OFF) +option(onnxruntime_FORCE_GENERIC_ALGORITHMS "Disable optimized arch-specific algorithms. Use only for testing and debugging generic algorithms." OFF) + +option(onnxruntime_USE_TENSORRT_INTERFACE "Build ONNXRuntime shared lib which is compatible with TensorRT EP interface" OFF) +option(onnxruntime_USE_NV_INTERFACE "Build ONNXRuntime shared lib which is compatible with NV EP interface" OFF) +option(onnxruntime_USE_CUDA_INTERFACE "Build ONNXRuntime shared lib which is compatible with Cuda EP interface" OFF) +option(onnxruntime_USE_OPENVINO_INTERFACE "Build ONNXRuntime shared lib which is compatible with OpenVINO EP interface" OFF) +option(onnxruntime_USE_VITISAI_INTERFACE "Build ONNXRuntime shared lib which is compatible with Vitis-AI EP interface" OFF) +option(onnxruntime_USE_QNN_INTERFACE "Build ONNXRuntime shared lib which is compatible with QNN EP interface" OFF) + +if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 11.1) + message(FATAL_ERROR "GCC version must be greater than or equal to 11.1") +endif() + +# ENABLE_TRAINING includes all training functionality +# The following 2 entry points +# 1. ORTModule +# 2. ORT Training APIs +# It includes all the feature additions as well like +# 1. Python OP +# 2. Aten Fallback +# 3. Strided Tensors +# 4. All training ops including communication and collectives ops +# 5. ONNXBlock (Front end for training preparation when using training apis) +# Some features are only enabled when onnxruntime_ENABLE_PYTHON is ON as they are only relevant +# when using python env +if (onnxruntime_ENABLE_TRAINING) + set(onnxruntime_ENABLE_TRAINING_APIS ON) + set(onnxruntime_ENABLE_TRAINING_OPS ON) + set(onnxruntime_ENABLE_ATEN ON) + set(onnxruntime_ENABLE_TRITON ON) + if (NOT APPLE) + set(onnxruntime_ENABLE_TRAINING_TORCH_INTEROP ON) + endif() +endif() + +if (onnxruntime_ENABLE_TRAINING_APIS) + set(onnxruntime_ENABLE_TRAINING_OPS ON) + if (onnxruntime_ENABLE_PYTHON AND NOT onnxruntime_ENABLE_TRAINING) + message(FATAL_ERROR "Standalone On-Device Training build is not supported with Python bindings! " + "Please use the --enable_training flag instead of the --enable_training_apis flag.") + endif() +endif() + + +# Single output director for all binaries +set(RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Single output directory for all binaries.") + + +include(FetchContent) + +function(set_msvc_c_cpp_compiler_warning_level warning_level) + if (NOT "${warning_level}" MATCHES "^[0-4]$") + message(FATAL_ERROR "Expected warning_level value of 0-4, got '${warning_level}'.") + endif() + + if (MSVC) + set(warning_flag "/W${warning_level}") + get_property(opts DIRECTORY PROPERTY COMPILE_OPTIONS) + # only match the generator expression added by this function + list(FILTER opts + EXCLUDE REGEX "^\\$<\\$:/W[0-4]>$") + list(APPEND opts "$<$:${warning_flag}>") + set_property(DIRECTORY PROPERTY COMPILE_OPTIONS "${opts}") + endif() +endfunction() + + +if(MSVC_Z7_OVERRIDE) + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") +endif(MSVC_Z7_OVERRIDE) + +# set default MSVC warning level to 3 for external dependencies +set_msvc_c_cpp_compiler_warning_level(3) + +# Fuzz test has only been tested with BUILD_SHARED_LIB option, +# using the MSVC compiler and on windows OS and clang/gcc compiler on Linux. +if (onnxruntime_FUZZ_TEST AND onnxruntime_BUILD_SHARED_LIB AND onnxruntime_USE_FULL_PROTOBUF) + # Fuzz test library dependency, protobuf-mutator, + # needs the onnx message to be compiled using "non-lite protobuf version" + set(onnxruntime_FUZZ_ENABLED ON) +endif() + +if (onnxruntime_USE_VALGRIND AND NOT WIN32) + add_definitions(-DRE2_ON_VALGRIND=1) +endif() + +if (onnxruntime_ENABLE_NVTX_PROFILE) + add_definitions(-DENABLE_NVTX_PROFILE=1) +endif() + +if (onnxruntime_ENABLE_BITCODE) + if (NOT (CMAKE_SYSTEM_NAME STREQUAL "iOS")) + message(FATAL_ERROR "iOS platform required for onnxruntime_ENABLE_BITCODE") + endif() + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE YES) + set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE "bitcode") +else() + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE NO) +endif() + +if (onnxruntime_ENABLE_MEMORY_PROFILE) + add_definitions(-DORT_MEMORY_PROFILE=1) +endif() + +set(ONNX_ML 1) + +if (NOT (UNIX AND onnxruntime_ENABLE_PYTHON AND onnxruntime_ENABLE_TRAINING AND (NOT onnxruntime_BUILD_SHARED_LIB))) + if (onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) + message(WARNING "onnxruntime_ENABLE_TRAINING_TORCH_INTEROP is turned OFF due to incompatible build combinations.") + endif() + set(onnxruntime_ENABLE_TRAINING_TORCH_INTEROP OFF) +endif() + +if (NOT (UNIX AND onnxruntime_USE_CUDA AND onnxruntime_ENABLE_PYTHON AND onnxruntime_ENABLE_TRAINING AND (NOT onnxruntime_BUILD_SHARED_LIB))) + if (onnxruntime_ENABLE_TRITON) + message(WARNING "onnxruntime_ENABLE_TRITON is turned OFF because it's designed to support CUDA training on Linux only currently.") + endif() + set(onnxruntime_ENABLE_TRITON OFF) +endif() + +set(onnxruntime_REQUIRE_PYTHON_EMBED_LIB OFF) +if (onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) + add_compile_definitions(ENABLE_TRAINING_TORCH_INTEROP) + + # Python::Python is required for building unit test executables. + if (onnxruntime_BUILD_UNIT_TESTS) + set(onnxruntime_REQUIRE_PYTHON_EMBED_LIB ON) + endif() +endif() + +if (onnxruntime_ENABLE_TRITON) + # Need SetOutputMLValue. + set(onnxruntime_ENABLE_ATEN ON) + add_compile_definitions(ENABLE_TRITON) + + # Python::Python is required for building unit test executables. + if (onnxruntime_BUILD_UNIT_TESTS) + set(onnxruntime_REQUIRE_PYTHON_EMBED_LIB ON) + endif() +endif() + +# General C# properties +if (onnxruntime_BUILD_CSHARP) + check_language(CSharp) + if (CMAKE_CSharp_COMPILER) + enable_language(CSharp) + set(CMAKE_CSharp_FLAGS ${CMAKE_CSharp_FLAGS} "/langversion:6") + message(STATUS "CMAKE_Csharp_Compiler = ${CMAKE_CSharp_COMPILER}") + else() + message(WARNING "Language Csharp is not found in the system") + endif() +endif() + +if (onnxruntime_BUILD_OBJC) + check_language(OBJC) + if(CMAKE_OBJC_COMPILER) + enable_language(OBJC) + else() + message(FATAL_ERROR "Objective-C is not supported.") + endif() + + check_language(OBJCXX) + if(CMAKE_OBJCXX_COMPILER) + enable_language(OBJCXX) + else() + message(FATAL_ERROR "Objective-C++ is not supported.") + endif() +endif() + +if (NOT WIN32) + #TODO: On Linux we may try https://github.com/microsoft/TraceLogging.git + if (onnxruntime_ENABLE_INSTRUMENT) + message(WARNING "Instrument is only supported on Windows now") + set(onnxruntime_ENABLE_INSTRUMENT OFF) + endif() +endif() + +# 'extended' implies minimal. +if (onnxruntime_EXTENDED_MINIMAL_BUILD AND NOT onnxruntime_MINIMAL_BUILD) + set(onnxruntime_MINIMAL_BUILD ON) +endif() + +set(REPO_ROOT ${PROJECT_SOURCE_DIR}/..) +set(ONNXRUNTIME_ROOT ${PROJECT_SOURCE_DIR}/../onnxruntime) +set(ORTTRAINING_ROOT ${PROJECT_SOURCE_DIR}/../orttraining) +set(ORTTRAINING_SOURCE_DIR ${ORTTRAINING_ROOT}/orttraining) + +include(adjust_global_compile_flags.cmake) + +if (APPLE) + if (NOT CMAKE_OSX_ARCHITECTURES) + message("Building ONNX Runtime for ${CMAKE_HOST_SYSTEM_PROCESSOR} CPU ARCH") + endif() +elseif (NOT WIN32 AND NOT APPLE) + message("Building ONNX Runtime for ${onnxruntime_target_platform} CPU ARCH") +endif() + +# We need to link with libatomic on systems that do not have built-in atomics, or +# don't have built-in support for 8 byte atomics +# Derived from https://github.com/protocolbuffers/protobuf/blob/master/cmake/CMakeLists.txt +set(onnxruntime_LINK_LIBATOMIC false) +# We don't need to link libatomic on iOS +if (NOT MSVC AND NOT (CMAKE_SYSTEM_NAME STREQUAL "iOS")) + include(CheckCXXSourceCompiles) + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} -std=c++11) + check_cxx_source_compiles(" + #include + int main() { + return std::atomic{}; + } + " onnxruntime_HAVE_BUILTIN_ATOMICS) + if (NOT onnxruntime_HAVE_BUILTIN_ATOMICS) + set(onnxruntime_LINK_LIBATOMIC true) + endif() + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) +endif() + + +file (STRINGS "${REPO_ROOT}/VERSION_NUMBER" ORT_VERSION) + +find_package(Threads) +# On Windows we directly use Windows APIs to do the job +# Android NDK doesn't provide the iconv lib. +if(NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android") + find_package(Iconv REQUIRED) + set(ICONV_LIB Iconv::Iconv) +endif() + +find_package(Patch) +if (CMAKE_HOST_WIN32 AND NOT Patch_FOUND) + # work around CI machines missing patch from the git install by falling back to the binary in this repo. + # replicate what happens in https://github.com/Kitware/CMake/blob/master/Modules/FindPatch.cmake but without + # the hardcoded suffixes in the path to the patch binary. + find_program(Patch_EXECUTABLE NAMES patch PATHS ${PROJECT_SOURCE_DIR}/external/git.Win32.2.41.03.patch) + if(Patch_EXECUTABLE) + set(Patch_FOUND 1) + if (NOT TARGET Patch::patch) + add_executable(Patch::patch IMPORTED) + set_property(TARGET Patch::patch PROPERTY IMPORTED_LOCATION ${Patch_EXECUTABLE}) + endif() + endif() +endif() +if(Patch_FOUND) + message("Patch found: ${Patch_EXECUTABLE}") +endif() + +if (CMAKE_CROSSCOMPILING) + message("Doing crosscompiling") +endif() + +#Need python to generate def file +if (onnxruntime_BUILD_SHARED_LIB OR onnxruntime_ENABLE_PYTHON) + if (onnxruntime_ENABLE_PYTHON) + if (onnxruntime_REQUIRE_PYTHON_EMBED_LIB) + find_package(Python 3.10 COMPONENTS Interpreter Development NumPy) + else() + find_package(Python 3.10 COMPONENTS Interpreter Development.Module NumPy) + endif() + message("Numpy version: ${Python_NumPy_VERSION}") + if(Python_NumPy_VERSION VERSION_LESS "2.0.0") + message(WARNING "The build binary will not be compatible with NumPy 2.0 because the NumPy installed on this machine is too low.") + endif() + else() + find_package(Python 3.10 COMPONENTS Interpreter) + endif() +endif() + +#Dependencies begin +get_filename_component(ONNXRUNTIME_ROOT "${ONNXRUNTIME_ROOT}" ABSOLUTE) +get_filename_component(ORTTRAINING_ROOT "${ORTTRAINING_ROOT}" ABSOLUTE) +get_filename_component(REPO_ROOT "${REPO_ROOT}" ABSOLUTE) +set(ONNXRUNTIME_INCLUDE_DIR ${REPO_ROOT}/include/onnxruntime) + +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/external) +include(external/onnxruntime_external_deps.cmake) + +set(ORT_WARNING_FLAGS) +if (WIN32) + # class needs to have dll-interface to be used by clients + list(APPEND ORT_WARNING_FLAGS "/wd4251") + # issued by thrust nonstandard extension used: nameless struct/union + list(APPEND ORT_WARNING_FLAGS "/wd4201") + # structure was padded due to __declspec(align()) + list(APPEND ORT_WARNING_FLAGS "/wd4324") + # warning C4800: Implicit conversion from 'X' to bool. Possible information loss + if (onnxruntime_USE_OPENVINO OR onnxruntime_USE_OPENVINO_INTERFACE) + list(APPEND ORT_WARNING_FLAGS "/wd4800") + endif() + # operator 'operator-name': deprecated between enumerations of different types + list(APPEND ORT_WARNING_FLAGS "/wd5054") + # Enable warning: data member 'member' will be initialized after data member 'member2' / base class 'base_class' + list(APPEND ORT_WARNING_FLAGS "/w15038") + + # set linker flags to minimize the binary size. + if (MSVC) + foreach(type EXE STATIC SHARED) + if (NOT type MATCHES STATIC) + # The WinML internal toolchain does not allow link's "additional options" to contain optimization + # flags (/OPT#); these are already specified using msbuild properties. + if (NOT DEFINED onnxruntime_DISABLE_LINKER_OPT_FLAGS) + set(CMAKE_${type}_LINKER_FLAGS_RELEASE "${CMAKE_${type}_LINKER_FLAGS_RELEASE} /OPT:REF,ICF,LBR") + set(CMAKE_${type}_LINKER_FLAGS_RELEASE "${CMAKE_${type}_LINKER_FLAGS_RELEASE} /INCREMENTAL:NO") + set(CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO} /OPT:REF,ICF,LBR") + set(CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO} /INCREMENTAL:NO") + set(CMAKE_${type}_LINKER_FLAGS_MINSIZEREL "${CMAKE_${type}_LINKER_FLAGS_MINSIZEREL} /OPT:REF,ICF,LBR") + set(CMAKE_${type}_LINKER_FLAGS_MINSIZEREL "${CMAKE_${type}_LINKER_FLAGS_MINSIZEREL} /INCREMENTAL:NO") + endif() + endif() + if (onnxruntime_ENABLE_LTO AND NOT onnxruntime_USE_CUDA) + set(CMAKE_${type}_LINKER_FLAGS_RELEASE "${CMAKE_${type}_LINKER_FLAGS_RELEASE} /LTCG") + set(CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_${type}_LINKER_FLAGS_RELWITHDEBINFO} /LTCG") + set(CMAKE_${type}_LINKER_FLAGS_MINSIZEREL "${CMAKE_${type}_LINKER_FLAGS_MINSIZEREL} /LTCG") + endif() + endforeach() + endif() + +else() + # Check for compiler flags + check_cxx_compiler_flag(-Wambiguous-reversed-operator HAS_AMBIGUOUS_REVERSED_OPERATOR) + # -Winterference-size was added in GCC 13 + check_cxx_compiler_flag(-Winterference-size HAS_INTERFERENCE_SIZE) + check_cxx_compiler_flag(-Warray-bounds HAS_ARRAY_BOUNDS) + check_cxx_compiler_flag(-Wbitwise-instead-of-logical HAS_BITWISE_INSTEAD_OF_LOGICAL) + check_cxx_compiler_flag(-Wcast-function-type HAS_CAST_FUNCTION_TYPE) + check_cxx_compiler_flag(-Wcatch-value HAS_CATCH_VALUE) + check_cxx_compiler_flag(-Wclass-memaccess HAS_CLASS_MEMACCESS) + check_cxx_compiler_flag(-Wcharacter-conversion HAS_CHARACTER_CONVERSION) + check_cxx_compiler_flag(-Wdangling-reference HAS_DANGLING_REFERENCE) + check_cxx_compiler_flag(-Wdeprecated-anon-enum-enum-conversion HAS_DEPRECATED_ANON_ENUM_ENUM_CONVERSION) + check_cxx_compiler_flag(-Wdeprecated-builtins HAS_DEPRECATED_BUILTINS) + check_cxx_compiler_flag(-Wdeprecated-copy HAS_DEPRECATED_COPY) + check_cxx_compiler_flag(-Wdeprecated-declarations HAS_DEPRECATED_DECLARATIONS) + check_cxx_compiler_flag(-Wdeprecated-literal-operator HAS_DEPRECATED_LITERAL_OPERATOR) + check_cxx_compiler_flag(-Wdeprecated-this-capture HAS_DEPRECATED_THIS_CAPTURE) + check_cxx_compiler_flag(-Wenum-constexpr-conversion HAS_ENUM_CONSTEXPR_CONVERSION) + check_cxx_compiler_flag(-Wformat-truncation HAS_FORMAT_TRUNCATION) + check_cxx_compiler_flag(-Wignored-attributes HAS_IGNORED_ATTRIBUTES) + check_cxx_compiler_flag(-Wmaybe-uninitialized HAS_MAYBE_UNINITIALIZED) + check_cxx_compiler_flag(-Wmissing-braces HAS_MISSING_BRACES) + check_cxx_compiler_flag(-Wnonnull-compare HAS_NONNULL_COMPARE) + check_cxx_compiler_flag(-Wparentheses HAS_PARENTHESES) + check_cxx_compiler_flag(-Wshorten-64-to-32 HAS_SHORTEN_64_TO_32) + check_cxx_compiler_flag(-Wstrict-aliasing HAS_STRICT_ALIASING) + check_nvcc_compiler_flag(-Wstrict-aliasing NVCC_HAS_STRICT_ALIASING) + check_cxx_compiler_flag(-Wstringop-overflow HAS_STRINGOP_OVERFLOW) + check_cxx_compiler_flag(-Wtautological-pointer-compare HAS_TAUTOLOGICAL_POINTER_COMPARE) + check_cxx_compiler_flag(-Wundefined-var-template HAS_UNDEFINED_VAR_TEMPLATE) + check_cxx_compiler_flag(-Wunused-but-set-parameter HAS_UNUSED_BUT_SET_PARAMETER) + check_cxx_compiler_flag(-Wunused-but-set-variable HAS_UNUSED_BUT_SET_VARIABLE) + check_cxx_compiler_flag(-Wunused-variable HAS_UNUSED_VARIABLE) + check_cxx_compiler_flag(-Wuseless-cast HAS_USELESS_CAST) + + if(onnxruntime_ENABLE_TRAINING_APIS) + if(HAS_DANGLING_REFERENCE) + list(APPEND ORT_WARNING_FLAGS -Wno-dangling-reference) + endif() + endif() + check_function_exists(reallocarray HAS_REALLOCARRAY) + if (NOT APPLE AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND onnxruntime_target_platform STREQUAL "aarch64") + check_cxx_compiler_flag(-march=armv8.2-a+bf16 HAS_ARM64_BFLOAT16) + if(NOT HAS_ARM64_BFLOAT16) + message(FATAL_ERROR "The compiler doesn't support BFLOAT16!!!") + endif() + check_cxx_compiler_flag(-march=armv8.2-a+fp16 HAS_ARM64_FLOAT16) + if(NOT HAS_ARM64_FLOAT16) + message(FATAL_ERROR "The compiler doesn't support FLOAT16!!!") + endif() + endif() + if (HAS_TAUTOLOGICAL_POINTER_COMPARE) + #we may have extra null pointer checkings in debug build, it's not an issue + list(APPEND ORT_WARNING_FLAGS -Wno-tautological-pointer-compare) + endif() + if (HAS_NONNULL_COMPARE) + #we may have extra null pointer checkings in debug build, it's not an issue + list(APPEND ORT_WARNING_FLAGS -Wno-nonnull-compare) + endif() + + if (HAS_AMBIGUOUS_REVERSED_OPERATOR) + list(APPEND ORT_WARNING_FLAGS -Wno-ambiguous-reversed-operator) + endif() + if (HAS_DEPRECATED_ANON_ENUM_ENUM_CONVERSION) + list(APPEND ORT_WARNING_FLAGS -Wno-deprecated-anon-enum-enum-conversion) + list(APPEND ORT_WARNING_FLAGS -Wno-deprecated-enum-enum-conversion) + endif() + if (HAS_UNDEFINED_VAR_TEMPLATE) + list(APPEND ORT_WARNING_FLAGS -Wno-undefined-var-template) + endif() + if (HAS_DEPRECATED_BUILTINS) + list(APPEND ORT_WARNING_FLAGS -Wno-deprecated-builtins) + endif() + if (HAS_DEPRECATED_LITERAL_OPERATOR) + list(APPEND ORT_WARNING_FLAGS -Wno-deprecated-literal-operator) + endif() + #see:https://reviews.llvm.org/D131307 + #It was intended that the 'enum-constexpr-conversion' type warnings can not be silenced by -w + if(HAS_ENUM_CONSTEXPR_CONVERSION AND NOT Protobuf_FOUND) + if (TARGET libprotobuf) + target_compile_options(libprotobuf PRIVATE "-Wno-enum-constexpr-conversion") + endif() + if (TARGET libprotobuf-lite) + target_compile_options(libprotobuf-lite PRIVATE "-Wno-enum-constexpr-conversion") + endif() + endif() + + if(HAS_INTERFERENCE_SIZE) + # The warning was from Eigen. Since we do not use Eigen in the public API, we can ignore it. + # However, it also means that part of our code was compiled based on the build machine's hardware spec. + # Specifically, the code was tuned based on the build machine's CPU cache line size, which can vary a lot. + list(APPEND ORT_WARNING_FLAGS -Wno-interference-size) + endif() + # enable warning(s) that may not be on by default + if (HAS_SHORTEN_64_TO_32) + list(APPEND ORT_WARNING_FLAGS -Wshorten-64-to-32) + endif() +endif() + +if (onnxruntime_USE_KLEIDIAI AND ( + (onnxruntime_target_platform STREQUAL "aarch64") OR + (onnxruntime_target_platform STREQUAL "ARM64") OR + (APPLE AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64"))) + + # TODO Add checks for MSVC Compilation + if(NOT MSVC) + check_cxx_compiler_flag(-march=armv8.2-a+dotprod HAS_ARM64_DOTPROD) + check_cxx_compiler_flag(-march=armv8.2-a+i8mm HAS_ARM64_I8MM) + if (NOT HAS_ARM64_DOTPROD) + message(FATAL_ERROR "The compiler doesn't support dotprod") + endif() + if (NOT HAS_ARM64_I8MM) + message(FATAL_ERROR "The compiler doesn't support i8mm") + endif() + else() + message(STATUS "Skipping -march= checks on MSVC (not supported), assuming dotprod/i8mm support manually.") + set(HAS_ARM64_DOTPROD TRUE) + set(HAS_ARM64_I8MM TRUE) + endif() +endif() + +#names in this var must match the directory names under onnxruntime/core/providers +#ONNXRUNTIME_PROVIDER_NAMES is the list of providers that needs to export additional symbols in the global namespace. +#For example CUDA EP exports "OrtSessionOptionsAppendExecutionProvider_CUDA", which is a global function. +#However, all these things are legacy and deprecated and should be replaced with functions in onnxruntime_c_api.h. +set(ONNXRUNTIME_PROVIDER_NAMES cpu) + +set(ORT_PROVIDER_FLAGS) + +if (onnxruntime_USE_CUDA) + include(cuda_configuration) + setup_cuda_compiler() + setup_cuda_architectures() + + enable_language(CUDA) + message( STATUS "CMAKE_CUDA_COMPILER_VERSION: ${CMAKE_CUDA_COMPILER_VERSION}") + + if (onnxruntime_DISABLE_CONTRIB_OPS) + set(onnxruntime_USE_FLASH_ATTENTION OFF) + set(onnxruntime_USE_LEAN_ATTENTION OFF) + set(onnxruntime_USE_MEMORY_EFFICIENT_ATTENTION OFF) + set(onnxruntime_USE_FPA_INTB_GEMM OFF) + endif() + + if (CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 11.6) + message( STATUS "Turn off flash attention since CUDA compiler version < 11.6") + set(onnxruntime_USE_FLASH_ATTENTION OFF) + set(onnxruntime_USE_LEAN_ATTENTION OFF) + set(onnxruntime_USE_MEMORY_EFFICIENT_ATTENTION OFF) + elseif(WIN32 AND CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 12) + message( STATUS "Flash-Attention unsupported in Windows with CUDA compiler version < 12.0") + set(onnxruntime_USE_FLASH_ATTENTION OFF) + endif() + + if (CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 12) + message( STATUS "FpA IntB Gemm unsupported for CUDA compiler version < 12.0") + set(onnxruntime_USE_FPA_INTB_GEMM OFF) + endif() + + if (WIN32) + message( STATUS "Lean Attention unsupported in Windows") + set(onnxruntime_USE_LEAN_ATTENTION OFF) + endif() +else() + set(onnxruntime_USE_FLASH_ATTENTION OFF) + set(onnxruntime_USE_LEAN_ATTENTION OFF) + set(onnxruntime_USE_MEMORY_EFFICIENT_ATTENTION OFF) +endif() + +if (onnxruntime_USE_CUDA) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_CUDA=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES cuda) + + if (onnxruntime_USE_FLASH_ATTENTION) + message( STATUS "Enable flash attention for CUDA EP") + list(APPEND ORT_PROVIDER_FLAGS -DUSE_FLASH_ATTENTION=1) + endif() + + if (onnxruntime_USE_LEAN_ATTENTION) + message( STATUS "Enable lean attention for CUDA EP") + list(APPEND ORT_PROVIDER_FLAGS -DUSE_LEAN_ATTENTION=1) + endif() + + if (onnxruntime_USE_MEMORY_EFFICIENT_ATTENTION) + message( STATUS "Enable memory efficient attention for CUDA EP") + list(APPEND ORT_PROVIDER_FLAGS -DUSE_MEMORY_EFFICIENT_ATTENTION=1) + endif() + + if (onnxruntime_USE_FPA_INTB_GEMM) + message( STATUS "Enable FpA IntB Gemm for CUDA EP") + list(APPEND ORT_PROVIDER_FLAGS -DUSE_FPA_INTB_GEMM=1) + endif() +endif() + +if (onnxruntime_USE_CUDA_INTERFACE AND (NOT onnxruntime_USE_CUDA)) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_CUDA_PROVIDER_INTERFACE=1) +endif() + +if (onnxruntime_USE_VITISAI) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_VITISAI=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES vitisai) +endif() + +if (onnxruntime_USE_VITISAI_INTERFACE AND (NOT onnxruntime_USE_VITISAI)) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_VITISAI_PROVIDER_INTERFACE=1) +endif() + +if (onnxruntime_USE_DNNL) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_DNNL=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES dnnl) +endif() + +if (onnxruntime_USE_OPENVINO) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_OPENVINO=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES openvino) +endif() + +if (onnxruntime_USE_OPENVINO_INTERFACE AND (NOT onnxruntime_USE_OPENVINO)) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_OPENVINO_PROVIDER_INTERFACE=1) +endif() + +if (onnxruntime_USE_TENSORRT) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_TENSORRT=1) + #TODO: remove the following line and change the test code in onnxruntime_shared_lib_test to use the new EP API. + list(APPEND ONNXRUNTIME_PROVIDER_NAMES tensorrt) +endif() + +if (onnxruntime_USE_TENSORRT_INTERFACE AND (NOT onnxruntime_USE_TENSORRT)) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_TENSORRT_PROVIDER_INTERFACE=1) +endif() + +if (onnxruntime_USE_NV) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_NV=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES nv_tensorrt_rtx) +endif() + +if (onnxruntime_USE_NV_INTERFACE AND (NOT onnxruntime_USE_NV)) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_NV_PROVIDER_INTERFACE=1) +endif() + +if (onnxruntime_USE_RKNPU) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_RKNPU=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES rknpu) +endif() +if (onnxruntime_USE_VSINPU) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_VSINPU=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES vsinpu) +endif() +if (onnxruntime_USE_NNAPI_BUILTIN) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_NNAPI=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES nnapi) +endif() +if (onnxruntime_USE_JSEP) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_JSEP=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES js) +endif() +if (onnxruntime_USE_QNN OR onnxruntime_USE_QNN_INTERFACE) + + if(onnxruntime_USE_QNN) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_QNN=1) + else() + list(APPEND ORT_PROVIDER_FLAGS -DUSE_QNN_PROVIDER_INTERFACE=1) + endif() + + list(APPEND ONNXRUNTIME_PROVIDER_NAMES qnn) + if (NOT QNN_ARCH_ABI) + string(TOLOWER ${onnxruntime_target_platform} GEN_PLATFORM) + if(MSVC) + message(STATUS "Building MSVC for architecture ${CMAKE_SYSTEM_PROCESSOR} with CMAKE_GENERATOR_PLATFORM as ${GEN_PLATFORM}") + if (${GEN_PLATFORM} STREQUAL "arm64") + set(QNN_ARCH_ABI aarch64-windows-msvc) + elseif (${GEN_PLATFORM} STREQUAL "arm64ec") + set(QNN_ARCH_ABI arm64x-windows-msvc) + else() + set(QNN_ARCH_ABI x86_64-windows-msvc) + endif() + else() + if (${CMAKE_SYSTEM_NAME} STREQUAL "Android") + set(QNN_ARCH_ABI aarch64-android-clang6.0) + elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + if (${GEN_PLATFORM} STREQUAL "x86_64") + set(QNN_ARCH_ABI x86_64-linux-clang) + else() + set(QNN_ARCH_ABI aarch64-android) + endif() + endif() + endif() + endif() + + if (onnxruntime_USE_QNN AND (MSVC OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")) + file(GLOB QNN_LIB_FILES LIST_DIRECTORIES false "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/libQnn*.so" + "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/Qnn*.dll" + "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/libHtpPrepare.so" + "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/HtpPrepare.dll") + if (${QNN_ARCH_ABI} STREQUAL "aarch64-windows-msvc" OR ${QNN_ARCH_ABI} STREQUAL "arm64x-windows-msvc") + file(GLOB EXTRA_HTP_LIB LIST_DIRECTORIES false "${onnxruntime_QNN_HOME}/lib/hexagon-v68/unsigned/libQnnHtpV68Skel.so" + "${onnxruntime_QNN_HOME}/lib/hexagon-v73/unsigned/libQnnHtpV73Skel.so" + "${onnxruntime_QNN_HOME}/lib/hexagon-v73/unsigned/libqnnhtpv73.cat") + list(APPEND QNN_LIB_FILES ${EXTRA_HTP_LIB}) + endif() + message(STATUS "QNN lib files: " ${QNN_LIB_FILES}) + endif() +endif() +if (onnxruntime_USE_SNPE) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_SNPE=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES snpe) +endif() +if (onnxruntime_USE_WINML) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_WINML=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES winml) +endif() +if (onnxruntime_USE_ACL) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_ACL=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES acl) +endif() +if (onnxruntime_USE_DML) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_DML=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES dml) + if(onnxruntime_ENABLE_NPU_ADAPTER_ENUMERATION) + list(APPEND ORT_PROVIDER_FLAGS -DENABLE_NPU_ADAPTER_ENUMERATION=1) + endif() +endif() +if (onnxruntime_USE_MIGRAPHX) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_MIGRAPHX=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES migraphx) +endif() + +if (onnxruntime_USE_MIGRAPHX_INTERFACE AND (NOT onnxruntime_USE_MIGRAPHX)) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_MIGRAPHX_PROVIDER_INTERFACE=1) +endif() + +if (onnxruntime_USE_ARMNN) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_ARMNN=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES armnn) +endif() +if (onnxruntime_USE_COREML) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_COREML=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES coreml) +endif() +if (onnxruntime_USE_XNNPACK) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_XNNPACK=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES xnnpack) +endif() +if (onnxruntime_USE_WEBNN) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_WEBNN=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES webnn) +endif() +if (onnxruntime_USE_WEBGPU) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_WEBGPU=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES webgpu) + + # TODO: the following code is used to disable building Dawn using vcpkg temporarily + # until we figure out how to resolve the packaging pipeline failures + # + # if (onnxruntime_USE_VCPKG AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + if (FALSE) + if (onnxruntime_BUILD_DAWN_SHARED_LIBRARY) + message(FATAL_ERROR "onnxruntime_USE_VCPKG is not supported with onnxruntime_BUILD_DAWN_SHARED_LIBRARY=ON") + endif() + if (onnxruntime_USE_EXTERNAL_DAWN) + message(FATAL_ERROR "onnxruntime_USE_VCPKG is not supported with onnxruntime_USE_EXTERNAL_DAWN=ON") + endif() + if (onnxruntime_CUSTOM_DAWN_SRC_PATH) + message(FATAL_ERROR "onnxruntime_USE_VCPKG is not supported with a custom dawn source path") + endif() + if (WIN32) + if (onnxruntime_ENABLE_DAWN_BACKEND_VULKAN) + message(FATAL_ERROR "onnxruntime_USE_VCPKG is not supported with onnxruntime_ENABLE_DAWN_BACKEND_VULKAN=ON") + endif() + if (NOT onnxruntime_ENABLE_DAWN_BACKEND_D3D12) + message(FATAL_ERROR "onnxruntime_USE_VCPKG is not supported with onnxruntime_ENABLE_DAWN_BACKEND_D3D12=OFF") + endif() + if (onnxruntime_ENABLE_PIX_FOR_WEBGPU_EP) + message(FATAL_ERROR "onnxruntime_USE_VCPKG is not supported with onnxruntime_ENABLE_PIX_FOR_WEBGPU_EP=ON") + endif() + endif() + endif() + + if (onnxruntime_BUILD_DAWN_SHARED_LIBRARY) + list(APPEND ORT_PROVIDER_FLAGS -DBUILD_DAWN_SHARED_LIBRARY=1) + endif() + if (onnxruntime_USE_EXTERNAL_DAWN) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_EXTERNAL_DAWN=1) + endif() + if (onnxruntime_ENABLE_DAWN_BACKEND_VULKAN) + list(APPEND ORT_PROVIDER_FLAGS -DDAWN_ENABLE_VULKAN=1) + endif() + if (onnxruntime_ENABLE_DAWN_BACKEND_D3D12) + list(APPEND ORT_PROVIDER_FLAGS -DDAWN_ENABLE_D3D12=1) + endif() + if (onnxruntime_ENABLE_PIX_FOR_WEBGPU_EP) + if (NOT onnxruntime_ENABLE_DAWN_BACKEND_D3D12 OR NOT WIN32) + message( + FATAL_ERROR + "Option onnxruntime_ENABLE_PIX_FOR_WEBGPU_EP can only be set on windows with onnxruntime_ENABLE_DAWN_BACKEND_D3D12 is enabled.") + endif() + add_compile_definitions(ENABLE_PIX_FOR_WEBGPU_EP) + endif() +endif() +if (onnxruntime_USE_CANN) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_CANN=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES cann) +endif() +if (onnxruntime_USE_AZURE) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_AZURE=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES azure) +endif() +if (onnxruntime_USE_LOCK_FREE_QUEUE) + add_compile_definitions(USE_LOCK_FREE_QUEUE) +endif() + +if (onnxruntime_FORCE_GENERIC_ALGORITHMS) + add_compile_definitions(FORCE_GENERIC_ALGORITHMS) +endif() + +if (onnxruntime_ENABLE_LAZY_TENSOR) + # To support LazyTensor, ORT needs to call Python function from C/C++. + # so onnxruntime_ENABLE_PYTHON is required. + if (NOT onnxruntime_ENABLE_TRAINING OR NOT onnxruntime_ENABLE_PYTHON) + message( + FATAL_ERROR + "Option onnxruntime_ENABLE_LAZY_TENSOR can only be set when onnxruntime_ENABLE_TRAINING and onnxruntime_ENABLE_PYTHON are enabled") + endif() + # TODO: In the future, we can compile LazyTensor into a standalone + # library target, onnxruntime_lazy_tensor, to make the buid + # cleaner. +endif() + +function(onnxruntime_set_compile_flags target_name) + if (CPUINFO_SUPPORTED) + onnxruntime_add_include_to_target(${target_name} cpuinfo::cpuinfo) + endif() + if(onnxruntime_ENABLE_LAZY_TENSOR) + target_compile_definitions(${target_name} PRIVATE ENABLE_LAZY_TENSOR) + endif() + # Enable stream for all the non-minimal build + if (NOT onnxruntime_MINIMAL_BUILD) + target_compile_definitions(${target_name} PRIVATE ORT_ENABLE_STREAM) + endif() + if (onnxruntime_REDUCED_OPS_BUILD) + target_compile_definitions(${target_name} PRIVATE REDUCED_OPS_BUILD) + endif() + if (onnxruntime_DISABLE_EXTERNAL_INITIALIZERS) + target_compile_definitions(${target_name} PRIVATE DISABLE_EXTERNAL_INITIALIZERS) + endif() + if (onnxruntime_ENABLE_CPU_FP16_OPS) + target_compile_definitions(${target_name} PRIVATE ENABLE_CPU_FP16_TRAINING_OPS) + endif() + if(onnxruntime_DISABLE_ABSEIL) + target_compile_definitions(${target_name} PRIVATE DISABLE_ABSEIL) + endif() + if(UNIX) + target_compile_definitions(${target_name} PRIVATE PLATFORM_POSIX) + endif() + target_compile_definitions(${target_name} PRIVATE EIGEN_USE_THREADS) + if (onnxruntime_DISABLE_CONTRIB_OPS) + target_compile_definitions(${target_name} PRIVATE DISABLE_CONTRIB_OPS) + endif() + + if (onnxruntime_DISABLE_ML_OPS) + target_compile_definitions(${target_name} PRIVATE DISABLE_ML_OPS) + endif() + + if (onnxruntime_DISABLE_SPARSE_TENSORS) + target_compile_definitions(${target_name} PRIVATE DISABLE_SPARSE_TENSORS) + endif() + + if (onnxruntime_DISABLE_OPTIONAL_TYPE) + target_compile_definitions(${target_name} PRIVATE DISABLE_OPTIONAL_TYPE) + endif() + + if (onnxruntime_DISABLE_FLOAT8_TYPES) + target_compile_definitions(${target_name} PRIVATE DISABLE_FLOAT8_TYPES) + endif() + + if (onnxruntime_DISABLE_FLOAT4_TYPES) + target_compile_definitions(${target_name} PRIVATE DISABLE_FLOAT4_TYPES) + endif() + + if (onnxruntime_ENABLE_ATEN) + target_compile_definitions(${target_name} PRIVATE ENABLE_ATEN) + endif() + # TODO: Narrow scope for Kleidiai compile + if (onnxruntime_USE_KLEIDIAI) + target_compile_definitions(${target_name} PRIVATE USE_KLEIDIAI) + endif() + + set_target_properties(${target_name} PROPERTIES COMPILE_WARNING_AS_ERROR ON) + if (onnxruntime_USE_CUDA) + # Suppress a "conversion_function_not_usable" warning in gsl/span + target_compile_options(${target_name} PRIVATE "$<$:SHELL:-Xcudafe \"--diag_suppress=conversion_function_not_usable\">") + target_compile_definitions(${target_name} PRIVATE -DDISABLE_CUSPARSE_DEPRECATED) + endif() + if (MSVC) + foreach(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORY ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) + target_compile_options(${target_name} PRIVATE "$<$:/external:I${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORY}>") + endforeach() + if(VCPKG_INSTALLED_DIR) + cmake_path(NATIVE_PATH VCPKG_INSTALLED_DIR NORMALIZE VCPKG_INSTALLED_DIR_native) + target_compile_options(${target_name} PRIVATE "$<$:SHELL:/external:I ${VCPKG_INSTALLED_DIR_native}>") + endif() + foreach(onnxruntime_external_lib IN LISTS onnxruntime_EXTERNAL_LIBRARIES) + #TODO: the list contains cmake keywords like "debug". We should exclude them. + if(TARGET ${onnxruntime_external_lib}) + get_target_property(onnxruntime_external_lib_include_dirs ${onnxruntime_external_lib} INTERFACE_INCLUDE_DIRECTORIES) + foreach(onnxruntime_external_lib_include_dir IN LISTS onnxruntime_external_lib_include_dirs) + if(onnxruntime_external_lib_include_dir MATCHES "^\\$") + if(onnxruntime_external_lib_include_dir MATCHES "^\\$]+)>$") + string(REGEX REPLACE "^\\$]+)>$" "\\1" onnxruntime_external_lib_include_dir_cmake "${onnxruntime_external_lib_include_dir}") + cmake_path(NATIVE_PATH onnxruntime_external_lib_include_dir_cmake NORMALIZE onnxruntime_external_lib_include_dir_native) + target_compile_options(${target_name} PRIVATE "$<$:/external:I${onnxruntime_external_lib_include_dir_native}>") + endif() + else() + cmake_path(NATIVE_PATH onnxruntime_external_lib_include_dir NORMALIZE onnxruntime_external_lib_include_dir_native) + target_compile_options(${target_name} PRIVATE "$<$:/external:I${onnxruntime_external_lib_include_dir_native}>") + endif() + endforeach() + endif() + endforeach() + target_compile_definitions(${target_name} PRIVATE -DPLATFORM_WINDOWS -DNOGDI -DNOMINMAX -D_USE_MATH_DEFINES -D_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) + if (onnxruntime_ENABLE_MEMLEAK_CHECKER) + target_compile_definitions(${target_name} PRIVATE -DONNXRUNTIME_ENABLE_MEMLEAK_CHECK) + endif() + target_compile_options(${target_name} PRIVATE "$<$:SHELL:--compiler-options /utf-8>" "$<$:/utf-8>") + target_compile_options(${target_name} PRIVATE "$<$:SHELL:--compiler-options /sdl>" "$<$:/sdl>") + set_target_properties(${target_name} + PROPERTIES VS_GLOBAL_CAExcludePath "${ORT_BINARY_DIR};${ORT_SOURCE_DIR}") + # We do not treat warnings from 3rd-party libraries as errors. In order to do that, we need to add their header files locations to /external:I. + target_compile_options(${target_name} PRIVATE "$<$:/experimental:external>" "$<$:SHELL:--compiler-options /experimental:external>") + target_compile_options(${target_name} PRIVATE "$<$:/external:W0>" "$<$:SHELL:--compiler-options /external:W0>") + #if(NOT onnxruntime_USE_VCPKG) + # target_compile_options(${target_name} PRIVATE "$<$:/external:templates->" "$<$:SHELL:--compiler-options /external:templates->") + #endif() + target_compile_options(${target_name} PRIVATE "$<$:/external:I${CMAKE_CURRENT_SOURCE_DIR}>" "$<$:SHELL:--compiler-options /external:I${CMAKE_CURRENT_SOURCE_DIR}>") + target_compile_options(${target_name} PRIVATE "$<$:/external:I${CMAKE_CURRENT_BINARY_DIR}>" "$<$:SHELL:--compiler-options /external:I${CMAKE_CURRENT_BINARY_DIR}>") + if (onnxruntime_ENABLE_STATIC_ANALYSIS) + target_compile_options(${target_name} PRIVATE "$<$:SHELL:--compiler-options /analyze>" "$<$:/analyze>") + if (onnxruntime_REDIRECT_STATIC_ANALYSIS_OUTPUTS_TO_FILE) + target_compile_options(${target_name} PRIVATE "$<$:SHELL:--compiler-options /analyze:autolog:ext.sarif>" "$<$:/analyze:autolog:ext.sarif>") + endif() + target_compile_options(${target_name} PRIVATE "$<$:SHELL:--compiler-options /analyze:external->" "$<$:/analyze:external->") + target_compile_options(${target_name} PRIVATE "$<$:SHELL:--compiler-options /wd6385>" ) + # There are many such warnings from STL: + # include\list(148): warning C6011: Dereferencing NULL pointer '_Mycont'. : Lines: 146, 147, 148 + target_compile_options(${target_name} PRIVATE "$<$:SHELL:--compiler-options /wd6011>" ) + endif() + else() + # Enable warning + target_compile_options(${target_name} PRIVATE "$<$:SHELL:--compiler-options -Wall>" "$<$>:-Wall>") + target_compile_options(${target_name} PRIVATE "$<$>:-Wextra>") + if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "IBMClang") + #external/protobuf/src/google/protobuf/arena.h:445:18: error: unused parameter 'p' + target_compile_options(${target_name} PRIVATE "-Wno-unused-parameter") + endif() + if (CMAKE_CXX_COMPILER_ID STREQUAL "IBMClang") + target_compile_options(${target_name} PRIVATE "-Wno-unused-function") + endif() + endif() + foreach(ORT_FLAG ${ORT_PROVIDER_FLAGS}) + target_compile_definitions(${target_name} PRIVATE ${ORT_FLAG}) + endforeach() + + if (HAS_DEPRECATED_COPY) + #too many such errors in eigen + target_compile_options(${target_name} PRIVATE "$<$:SHELL:--compiler-options -Wno-deprecated-copy>" "$<$:-Wno-deprecated-copy>") + endif() + foreach(FLAG ${ORT_WARNING_FLAGS}) + target_compile_options(${target_name} PRIVATE "$<$:${FLAG}>") + endforeach() + if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 13 AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12) + target_compile_options(${target_name} PRIVATE "$<$:-Wno-maybe-uninitialized>") + endif() + if (onnxruntime_USE_CUDA) + foreach(FLAG ${ORT_WARNING_FLAGS}) + target_compile_options(${target_name} PRIVATE "$<$:SHELL:--compiler-options ${FLAG}>") + endforeach() + if (NVCC_HAS_STRICT_ALIASING AND "${target_name}" MATCHES "cuda") + target_compile_options(${target_name} PRIVATE "$<$:-Wno-strict-aliasing>") + endif() + if (HAS_STRICT_ALIASING AND NOT "${target_name}" MATCHES "cuda") + target_compile_options(${target_name} PRIVATE "$<$:-Wno-strict-aliasing>") + endif() + endif() +endfunction() + +function(onnxruntime_set_source_file_properties target_name) + get_target_property(srcs ${target_name} SOURCES) + + # enable ARC for Objective-C/C++ + set(objective_c_cc_srcs ${srcs}) + list(FILTER objective_c_cc_srcs INCLUDE REGEX "\\.mm?$") + set_property(SOURCE ${objective_c_cc_srcs} APPEND PROPERTY COMPILE_OPTIONS "-fobjc-arc") +endfunction() + +function(onnxruntime_configure_target target_name) + target_link_directories(${target_name} PRIVATE ${onnxruntime_LINK_DIRS}) + onnxruntime_set_compile_flags(${target_name}) + onnxruntime_set_source_file_properties(${target_name}) + if(WIN32 AND onnxruntime_ENABLE_STATIC_ANALYSIS AND onnxruntime_USE_CUSTOM_STATIC_ANALYSIS_RULES) + set_target_properties(${target_name} PROPERTIES VS_USER_PROPS ${PROJECT_SOURCE_DIR}/EnableVisualStudioCodeAnalysis.props) + endif() + target_include_directories(${target_name} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT}) + if (onnxruntime_ENABLE_TRAINING_OPS) + target_include_directories(${target_name} PRIVATE ${ORTTRAINING_ROOT}) + endif() + if (onnxruntime_ENABLE_LTO) + set_target_properties(${target_name} PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE) + set_target_properties(${target_name} PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE) + set_target_properties(${target_name} PROPERTIES INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL TRUE) + endif() + + # Keep BinSkim happy + if(MSVC AND NOT onnxruntime_target_platform MATCHES "ARM") + target_link_options(${target_name} PRIVATE "/CETCOMPAT") + endif() + +endfunction() + +function(onnxruntime_add_shared_library target_name) + add_library(${target_name} SHARED ${ARGN}) + onnxruntime_configure_target(${target_name}) + if(WIN32) + target_compile_definitions(${target_name} PRIVATE VER_MAJOR=${VERSION_MAJOR_PART}) + target_compile_definitions(${target_name} PRIVATE VER_MINOR=${VERSION_MINOR_PART}) + target_compile_definitions(${target_name} PRIVATE VER_BUILD=${VERSION_BUILD_PART}) + target_compile_definitions(${target_name} PRIVATE VER_PRIVATE=${VERSION_PRIVATE_PART}) + target_compile_definitions(${target_name} PRIVATE VER_STRING=\"${VERSION_STRING}\") + endif() +endfunction() + +function(onnxruntime_add_static_library target_name) + add_library(${target_name} STATIC ${ARGN}) + onnxruntime_configure_target(${target_name}) +endfunction() + +#For plugins that are not linked into other targets but may be loaded dynamically at runtime using dlopen-like functionality. +function(onnxruntime_add_shared_library_module target_name) + if ((${CMAKE_SYSTEM_NAME} MATCHES "Darwin") OR (${CMAKE_SYSTEM_NAME} MATCHES "iOS")) + add_library(${target_name} SHARED ${ARGN}) + else() + #On Windows, this target shouldn't generate an import lib, but I don't know how to disable it. + add_library(${target_name} MODULE ${ARGN}) + if(WIN32) + target_compile_definitions(${target_name} PRIVATE VER_MAJOR=${VERSION_MAJOR_PART}) + target_compile_definitions(${target_name} PRIVATE VER_MINOR=${VERSION_MINOR_PART}) + target_compile_definitions(${target_name} PRIVATE VER_BUILD=${VERSION_BUILD_PART}) + target_compile_definitions(${target_name} PRIVATE VER_PRIVATE=${VERSION_PRIVATE_PART}) + target_compile_definitions(${target_name} PRIVATE VER_STRING=\"${VERSION_STRING}\") + endif() + endif() + + onnxruntime_configure_target(${target_name}) + if (MSVC AND onnxruntime_target_platform STREQUAL "x86") + target_link_options(${target_name} PRIVATE /SAFESEH) + endif() +endfunction() + +function(onnxruntime_add_object_library target_name) + add_library(${target_name} OBJECT ${ARGN}) + + onnxruntime_configure_target(${target_name}) + if (MSVC AND onnxruntime_target_platform STREQUAL "x86") + target_link_options(${target_name} PRIVATE /SAFESEH) + endif() +endfunction() + +function(onnxruntime_add_executable target_name) + add_executable(${target_name} ${ARGN}) + onnxruntime_configure_target(${target_name}) + if (MSVC AND onnxruntime_target_platform STREQUAL "x86") + target_link_options(${target_name} PRIVATE /SAFESEH) + endif() +endfunction() + +function(onnxruntime_add_include_to_target dst_target) + foreach(src_target ${ARGN}) + if(TARGET ${src_target}) + target_include_directories(${dst_target} PRIVATE $) + target_compile_definitions(${dst_target} PRIVATE $) + target_sources(${dst_target} PRIVATE $) + endif() + endforeach() +endfunction() + +# ACL +if (onnxruntime_USE_ACL) + set(onnxruntime_USE_ACL ON) + + if (NOT ${onnxruntime_ACL_LIBS} STREQUAL "") + add_library(arm_compute SHARED IMPORTED) + set_target_properties(arm_compute PROPERTIES + IMPORTED_NO_SONAME 1 + IMPORTED_LOCATION "${onnxruntime_ACL_LIBS}/libarm_compute.so") + + add_library(arm_compute_graph SHARED IMPORTED) + set_target_properties(arm_compute_graph PROPERTIES + IMPORTED_NO_SONAME 1 + IMPORTED_LOCATION "${onnxruntime_ACL_LIBS}/libarm_compute_graph.so") + endif() + + list(APPEND onnxruntime_EXTERNAL_LIBRARIES arm_compute arm_compute_graph) + +endif() + +# ArmNN +if (onnxruntime_USE_ARMNN) + if (NOT onnxruntime_ARMNN_RELU_USE_CPU) + add_definitions(-DRELU_ARMNN=1) + endif() + if (NOT onnxruntime_ARMNN_BN_USE_CPU) + add_definitions(-DBN_ARMNN=1) + endif() + + if (NOT onnxruntime_USE_ACL AND NOT ${onnxruntime_ACL_LIBS} STREQUAL "") + add_library(arm_compute SHARED IMPORTED) + set_target_properties(arm_compute PROPERTIES + IMPORTED_NO_SONAME 1 + IMPORTED_LOCATION "${onnxruntime_ACL_LIBS}/libarm_compute.so") + + add_library(arm_compute_graph SHARED IMPORTED) + set_target_properties(arm_compute_graph PROPERTIES + IMPORTED_NO_SONAME 1 + IMPORTED_LOCATION "${onnxruntime_ACL_LIBS}/libarm_compute_graph.so") + endif() + + if (NOT ${onnxruntime_ARMNN_LIBS} STREQUAL "") + add_library(armnn SHARED IMPORTED) + set_target_properties(armnn PROPERTIES + IMPORTED_NO_SONAME 1 + IMPORTED_LOCATION "${onnxruntime_ARMNN_LIBS}/libarmnn.so") + endif() + + list(APPEND onnxruntime_EXTERNAL_LIBRARIES armnn arm_compute arm_compute_graph) +endif() + +if (onnxruntime_USE_DNNL) + include(dnnl) + add_compile_definitions(DNNL_OPENMP) +endif() + +# onnxruntime-extensions +if (onnxruntime_USE_EXTENSIONS) + include(extensions) +endif() + +#Dependencies end. In the next we'll enable "treat warning as error" + +#Adjust warning flags +set_msvc_c_cpp_compiler_warning_level(4) + +set(onnxruntime_DELAYLOAD_FLAGS ) + +include_directories( + ${ONNXRUNTIME_INCLUDE_DIR} + ${REPO_ROOT}/include/onnxruntime/core/session +) + +if (onnxruntime_ENABLE_TRAINING_APIS) + include_directories( + ${REPO_ROOT}/orttraining/orttraining/training_api/include/ + ) +endif() + +if (onnxruntime_USE_OPENVINO) + + add_definitions(-DUSE_OPENVINO=1) + + if(onnxruntime_NPU_NO_FALLBACK) + add_definitions(-DOPENVINO_CONFIG_NPU=1) + add_definitions(-DOPENVINO_DISABLE_NPU_FALLBACK=1) + endif() + + if (onnxruntime_USE_OPENVINO_GPU) + add_definitions(-DOPENVINO_CONFIG_GPU=1) + endif() + + if (onnxruntime_USE_OPENVINO_CPU) + add_definitions(-DOPENVINO_CONFIG_CPU=1) + endif() + + if (onnxruntime_USE_OPENVINO_NPU) + add_definitions(-DOPENVINO_CONFIG_NPU=1) + endif() + + if (onnxruntime_USE_OPENVINO_GPU_NP) + add_definitions(-DOPENVINO_CONFIG_GPU=1) + add_definitions(-DOPENVINO_DISABLE_GRAPH_PARTITION=1) + endif() + + if (onnxruntime_USE_OPENVINO_CPU_NP) + add_definitions(-DOPENVINO_CONFIG_CPU=1) + add_definitions(-DOPENVINO_DISABLE_GRAPH_PARTITION=1) + endif() + + if (onnxruntime_USE_OPENVINO_NPU_NP) + add_definitions(-DOPENVINO_CONFIG_NPU=1) + add_definitions(-DOPENVINO_DISABLE_GRAPH_PARTITION=1) + endif() + + if (onnxruntime_USE_OPENVINO_HETERO) + add_definitions(-DOPENVINO_CONFIG_HETERO=1) + add_definitions(-DDEVICE_NAME="${onnxruntime_USE_OPENVINO_DEVICE}") + endif() + + if (onnxruntime_USE_OPENVINO_MULTI) + add_definitions(-DOPENVINO_CONFIG_MULTI=1) + add_definitions(-DDEVICE_NAME="${onnxruntime_USE_OPENVINO_DEVICE}") + endif() + + if(onnxruntime_USE_OPENVINO_AUTO) + add_definitions(-DOPENVINO_CONFIG_AUTO=1) + add_definitions(-DDEVICE_NAME="${onnxruntime_USE_OPENVINO_DEVICE}") + endif() + + if($ENV{FIL_ENABLED}) + add_definitions(-DOPENVINO_FIL_ENABLED=1) + endif() + +endif() + +if (onnxruntime_USE_VITISAI) + set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_LIST_DIR}") +endif() + +set(ORT_BUILD_INFO "ORT Build Info: ") +find_package(Git) +if (Git_FOUND) + execute_process(COMMAND ${GIT_EXECUTABLE} log -1 --format=%h + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE ORT_GIT_COMMIT) + string(STRIP "${ORT_GIT_COMMIT}" ORT_GIT_COMMIT) + execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE ORT_GIT_BRANCH) + string(STRIP "${ORT_GIT_BRANCH}" ORT_GIT_BRANCH) + string(APPEND ORT_BUILD_INFO "git-branch=${ORT_GIT_BRANCH}, git-commit-id=${ORT_GIT_COMMIT}, ") +endif() +string(APPEND ORT_BUILD_INFO "build type=${CMAKE_BUILD_TYPE}") +configure_file(onnxruntime_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/onnxruntime_config.h) +get_property(onnxruntime_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + +if (onnxruntime_USE_CUDA) + set(CMAKE_CUDA_RUNTIME_LIBRARY Shared) + set(CMAKE_CUDA_STANDARD 17) + if(onnxruntime_CUDA_HOME) + file(TO_CMAKE_PATH CUDAToolkit_ROOT ${onnxruntime_CUDA_HOME}) + endif() + find_package(CUDAToolkit REQUIRED) + + if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.8) + add_definitions("-DENABLE_FP8") + message(STATUS "CUDA Toolkit version is greater or equal than 11.8, enable -DENABLE_FP8 flag") + endif() + + if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12.8) + add_definitions("-DENABLE_FP4") + message(STATUS "CUDA Toolkit version is greater or equal than 12.8, enable -DENABLE_FP4 flag") + endif() + + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xfatbin=-compress-all") + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --expt-relaxed-constexpr") + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --Werror default-stream-launch") + if (NOT WIN32) + list(APPEND CUDA_NVCC_FLAGS --compiler-options -fPIC) + endif() + if(MSVC) + if(CUDA_NVCC_FLAGS MATCHES "Zi") + list(APPEND CUDA_NVCC_FLAGS "-Xcompiler" "-FS") + endif() + endif() + # Options passed to cudafe + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe \"--diag_suppress=bad_friend_decl\"") + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe \"--diag_suppress=unsigned_compare_with_zero\"") + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe \"--diag_suppress=expr_has_no_effect\"") + + if (onnxruntime_ENABLE_CUDA_LINE_NUMBER_INFO) + add_compile_options("$<$:--generate-line-info>") + endif() +endif() + +if (onnxruntime_USE_MIGRAPHX) + set(AMD_MIGRAPHX_HOME ${onnxruntime_MIGRAPHX_HOME}) +endif() + +if (onnxruntime_ENABLE_MICROSOFT_INTERNAL) + add_definitions(-DMICROSOFT_INTERNAL) +endif() + +if (onnxruntime_USE_DML) + if (NOT WIN32) + message(FATAL_ERROR "The DirectML execution provider is only supported when building for Windows.") + endif() + + include(dml) +endif() + +if (onnxruntime_ENABLE_TRAINING_APIS) + add_compile_definitions(ENABLE_TRAINING_CORE) + add_compile_definitions(ENABLE_TRAINING_APIS) +endif() + +if (onnxruntime_ENABLE_TRAINING_OPS) + add_compile_definitions(ENABLE_TRAINING_OPS) +endif() + +if (onnxruntime_ENABLE_CUDA_PROFILING) + add_compile_definitions(ENABLE_CUDA_PROFILING) +endif() + +if (onnxruntime_ENABLE_TRAINING) + add_compile_definitions(ENABLE_TRAINING_CORE) + add_compile_definitions(ENABLE_STRIDED_TENSORS) + add_compile_definitions(ENABLE_TRAINING) + + add_subdirectory(tensorboard EXCLUDE_FROM_ALL) + list(APPEND onnxruntime_EXTERNAL_LIBRARIES tensorboard) +endif() + +if (onnxruntime_ENABLE_DLPACK) + add_compile_definitions(ENABLE_DLPACK) +endif() + +if (onnxruntime_CALLER_FRAMEWORK) + add_definitions(-DORT_CALLER_FRAMEWORK="${onnxruntime_CALLER_FRAMEWORK}") +endif() + +if (UNIX OR onnxruntime_USE_NCCL) + # Find NCCL + if (onnxruntime_USE_NCCL) + if (onnxruntime_USE_CUDA) + set(NCCL_LIBNAME "nccl") + elseif (onnxruntime_USE_MIGRAPHX) + set(NCCL_LIBNAME "rccl") + endif() + find_path(NCCL_INCLUDE_DIR + NAMES ${NCCL_LIBNAME}.h + HINTS + ${onnxruntime_NCCL_HOME}/include/rccl + ${onnxruntime_NCCL_HOME}/include + $ENV{CUDA_ROOT}/include) + + find_library(NCCL_LIBRARY + NAMES ${NCCL_LIBNAME} + HINTS + ${onnxruntime_NCCL_HOME}/lib/x86_64-linux-gnu + ${onnxruntime_NCCL_HOME}/lib + $ENV{CUDA_ROOT}/lib64) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(NCCL DEFAULT_MSG NCCL_INCLUDE_DIR NCCL_LIBRARY) + + if (NCCL_FOUND) + set(NCCL_HEADER_FILE "${NCCL_INCLUDE_DIR}/${NCCL_LIBNAME}.h") + message( STATUS "Determining NCCL version from the header file: ${NCCL_HEADER_FILE}" ) + file (STRINGS ${NCCL_HEADER_FILE} NCCL_MAJOR_VERSION_DEFINED + REGEX "^[ \t]*#define[ \t]+NCCL_MAJOR[ \t]+[0-9]+.*$" LIMIT_COUNT 1) + if (NCCL_MAJOR_VERSION_DEFINED) + string (REGEX REPLACE "^[ \t]*#define[ \t]+NCCL_MAJOR[ \t]+" "" + NCCL_MAJOR_VERSION ${NCCL_MAJOR_VERSION_DEFINED}) + message( STATUS "NCCL_MAJOR_VERSION: ${NCCL_MAJOR_VERSION}" ) + endif() + file (STRINGS ${NCCL_HEADER_FILE} NCCL_MINOR_VERSION_DEFINED + REGEX "^[ \t]*#define[ \t]+NCCL_MINOR[ \t]+[0-9]+.*$" LIMIT_COUNT 1) + if (NCCL_MINOR_VERSION_DEFINED) + string (REGEX REPLACE "^[ \t]*#define[ \t]+NCCL_MINOR[ \t]+" "" + NCCL_MINOR_VERSION ${NCCL_MINOR_VERSION_DEFINED}) + message(STATUS "NCCL_MINOR_VERSION: ${NCCL_MINOR_VERSION}") + endif() + + if (NCCL_MAJOR_VERSION_DEFINED AND NCCL_MINOR_VERSION_DEFINED) + if ("${NCCL_MAJOR_VERSION}.${NCCL_MINOR_VERSION}" VERSION_GREATER_EQUAL "2.7") + add_definitions(-DUSE_NCCL_P2P=1) + message( STATUS "NCCL P2P is enabled for supporting ncclSend and ncclRecv." ) + endif() + endif() + + set(NCCL_INCLUDE_DIRS ${NCCL_INCLUDE_DIR}) + set(NCCL_LIBRARIES ${NCCL_LIBRARY}) + message( STATUS "NCCL (include: ${NCCL_INCLUDE_DIRS}, library: ${NCCL_LIBRARIES})" ) + mark_as_advanced(NCCL_INCLUDE_DIRS NCCL_LIBRARIES) + + list(APPEND onnxruntime_EXTERNAL_LIBRARIES ${NCCL_LIBRARIES}) + + + add_definitions(-DORT_USE_NCCL=1) + message( STATUS "NCCL is enabled in Linux GPU Build." ) + else () + set(onnxruntime_USE_NCCL OFF) + message( + FATAL_ERROR + "NCCL is not found. Please use --nccl_home to specify the path of NCCL. Otherwise, NCCL is disabled." + ) + endif() + endif() +else() + set(onnxruntime_USE_NCCL OFF) + message( WARNING "NCCL is disabled because build is on Windows or USE_NCCL is set to OFF." ) +endif() + + +# Default version parts for Microsoft.AI.MachineLearning.dll, onnxruntime.dll, onnxruntime_providers_openvino.dll and onnxruntime_providers_shared.dll in non-ADO pipeline local builds +set(VERSION_MAJOR_PART 0 CACHE STRING "First part of numeric file/product version.") +set(VERSION_MINOR_PART 0 CACHE STRING "Second part of numeric file/product version.") +set(VERSION_BUILD_PART 0 CACHE STRING "Third part of numeric file/product version.") +set(VERSION_PRIVATE_PART 0 CACHE STRING "Fourth part of numeric file/product version.") +set(VERSION_STRING "Internal Build" CACHE STRING "String representation of file/product version.") +if(VERSION_MAJOR_PART STREQUAL "0" AND VERSION_MINOR_PART STREQUAL "0" AND VERSION_BUILD_PART STREQUAL "0" AND VERSION_PRIVATE_PART STREQUAL "0") + string(REPLACE "." ";" ORT_VERSION_STRING_LIST ${ORT_VERSION}) + list(GET ORT_VERSION_STRING_LIST 0 VERSION_MAJOR_PART) + list(GET ORT_VERSION_STRING_LIST 1 VERSION_MINOR_PART) + list(GET ORT_VERSION_STRING_LIST 2 VERSION_BUILD_PART) + set(VERSION_STRING ${ORT_VERSION}) +endif() + + +if (WIN32) + if (onnxruntime_USE_MIMALLOC) + list(APPEND onnxruntime_EXTERNAL_LIBRARIES mimalloc-static) + endif() + list(APPEND onnxruntime_EXTERNAL_LIBRARIES ${SYS_PATH_LIB}) + list(APPEND onnxruntime_EXTERNAL_LIBRARIES debug Dbghelp) + # In a onecore build the umbrella libs already contains references to the APIs in advapi32, so in onecore build we do not need to link to advapi32 + # In a non-onecore build, usually we also do not need to link to advapi32 because VC++ by default should have provide everything we need, except when the build target is Windows ARM32. + # In the future we will add a build option to allow users disabling all API uses from advapi32 because some Windows environments do not have these APIs. For example, some Windows do not have + # Windows Registry so we cannot query Registry values. + if(onnxruntime_target_platform STREQUAL "ARM" AND CMAKE_CXX_STANDARD_LIBRARIES MATCHES kernel32.lib) + list(APPEND onnxruntime_EXTERNAL_LIBRARIES advapi32) + endif() +else() + list(APPEND onnxruntime_EXTERNAL_LIBRARIES ${ICONV_LIB} ${CMAKE_DL_LIBS} Threads::Threads) +endif() + +if (CMAKE_SYSTEM_NAME STREQUAL "Android") + list(APPEND onnxruntime_EXTERNAL_LIBRARIES log) +endif() + +# check if we need to link against librt on Linux +include(CheckLibraryExists) +include(CheckFunctionExists) +if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") + check_library_exists(rt clock_gettime "time.h" HAVE_CLOCK_GETTIME) + + if (NOT HAVE_CLOCK_GETTIME) + set(CMAKE_EXTRA_INCLUDE_FILES time.h) + check_function_exists(clock_gettime HAVE_CLOCK_GETTIME) + set(CMAKE_EXTRA_INCLUDE_FILES) + else() + list(APPEND onnxruntime_EXTERNAL_LIBRARIES rt) + endif() +endif() + +#Now the 'onnxruntime_EXTERNAL_LIBRARIES' variable should be sealed. It will be used in onnxruntime.cmake which will be included in the next. +#The order of the following targets matters. Right depends on left. If target A appears before target B. Then A.cmake can not use variables defined in B.cmake. +set(ONNXRUNTIME_CMAKE_FILES onnxruntime_flatbuffers onnxruntime_common onnxruntime_mlas onnxruntime_graph onnxruntime_lora onnxruntime_framework onnxruntime_util onnxruntime_providers onnxruntime_optimizer onnxruntime_session ${ONNXRUNTIME_EAGER_CMAKE_FILE_NAME}) + +if (onnxruntime_USE_WINML) + # WINML uses and depends on the shared lib. Note: You can build WINML without DML and you will get a + # CPU only WINML + if (NOT onnxruntime_BUILD_SHARED_LIB) + message( + FATAL_ERROR + "Option onnxruntime_USE_WINML can only be used when onnxruntime_BUILD_SHARED_LIB is also enabled") + endif() + list(APPEND ONNXRUNTIME_CMAKE_FILES winml) +endif() # if (onnxruntime_USE_WINML) + +list(APPEND ONNXRUNTIME_CMAKE_FILES onnxruntime) + +if (onnxruntime_BUILD_JAVA) + message(STATUS "Java Build is enabled") + list(APPEND ONNXRUNTIME_CMAKE_FILES onnxruntime_java) +endif() + +if (onnxruntime_BUILD_NODEJS) + message(STATUS "Node.js Build is enabled") + list(APPEND ONNXRUNTIME_CMAKE_FILES onnxruntime_nodejs) +endif() + +if (onnxruntime_ENABLE_PYTHON) + message(STATUS "Python Build is enabled") + list(APPEND ONNXRUNTIME_CMAKE_FILES onnxruntime_python) +endif() + +if (onnxruntime_BUILD_OBJC) + message(STATUS "Objective-C Build is enabled") + list(APPEND ONNXRUNTIME_CMAKE_FILES onnxruntime_objectivec) +endif() + +if (onnxruntime_BUILD_UNIT_TESTS) + list(APPEND ONNXRUNTIME_CMAKE_FILES onnxruntime_unittests) +endif() + +if (onnxruntime_BUILD_WINML_TESTS) + list(APPEND ONNXRUNTIME_CMAKE_FILES winml_unittests) +endif() + +# onnxruntime_training depends on onnxruntime_unittests since onnxruntime_training.cmake uses a variable `TEST_SRC_DIR` +# that is defined in onnxruntime_unittests.cmake +if (onnxruntime_ENABLE_TRAINING) + list(APPEND ONNXRUNTIME_CMAKE_FILES onnxruntime_training) + if (onnxruntime_ENABLE_TRAINING_E2E_TESTS) + list(APPEND ONNXRUNTIME_CMAKE_FILES onnxruntime_training_e2e_tests) + endif() +endif() + +if (onnxruntime_BUILD_CSHARP) + message(STATUS "CSharp Build is enabled") +# set_property(GLOBAL PROPERTY VS_DOTNET_TARGET_FRAMEWORK_VERSION "netstandard2.0") + list(APPEND ONNXRUNTIME_CMAKE_FILES onnxruntime_csharp) +endif() + +if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + message(STATUS "WebAssembly Build is enabled") + list(APPEND ONNXRUNTIME_CMAKE_FILES onnxruntime_webassembly) + + if (onnxruntime_ENABLE_WEBASSEMBLY_OUTPUT_OPTIMIZED_MODEL) + add_compile_definitions(ORT_ENABLE_WEBASSEMBLY_OUTPUT_OPTIMIZED_MODEL) + endif() +endif() + +# When GDK_PLATFORM is set then WINAPI_FAMILY is defined in gdk_toolchain.cmake (along with other relevant flags/definitions). +if (WIN32 AND NOT GDK_PLATFORM AND NOT CMAKE_CROSSCOMPILING) + if (NOT CMAKE_CXX_STANDARD_LIBRARIES MATCHES kernel32.lib) + # On onecore, link to the onecore build of the MSVC runtime + get_filename_component(msvc_path "${CMAKE_C_COMPILER}/../../../.." ABSOLUTE) + link_directories(BEFORE "${msvc_path}/lib/onecore/${onnxruntime_target_platform}") + # The .lib files in the MSVC runtime have a DEFAULITLIB entry for onecore.lib, but it shold not cause any conflict with onecoreuap.lib + endif() +endif() + +foreach(onnxruntime_cmake_file ${ONNXRUNTIME_CMAKE_FILES}) + include(${onnxruntime_cmake_file}.cmake) +endforeach() +if (UNIX) + option(BUILD_PKGCONFIG_FILES "Build and install pkg-config files" ON) +else() + option(BUILD_PKGCONFIG_FILES "Build and install pkg-config files" OFF) +endif() +if (BUILD_PKGCONFIG_FILES) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libonnxruntime.pc.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/libonnxruntime.pc @ONLY) + install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libonnxruntime.pc DESTINATION + ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) +endif() + +if (onnxruntime_BUILD_OPSCHEMA_LIB AND onnxruntime_ENABLE_TRAINING) + # opschema library requires training ops as well + include(onnxruntime_opschema_lib.cmake) +endif() + +if (onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS) + add_compile_definitions(DEBUG_NODE_INPUTS_OUTPUTS) +endif() + +if (onnxruntime_ENABLE_EXTERNAL_CUSTOM_OP_SCHEMAS) + if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") + message(FATAL_ERROR "External custom operator schemas feature is only supported on Linux") + endif() + + if (NOT ${ONNX_CUSTOM_PROTOC_EXECUTABLE} STREQUAL "") + message(FATAL_ERROR "External custom operator schemas is not supported with the user specified protoc executable") + endif() + + if (NOT onnxruntime_ENABLE_TRAINING) + message(FATAL_ERROR "External custom operator schemas is supported only with --enable-training option") + endif() + + add_custom_target(install_protobuf ALL DEPENDS ${PROTOBUF_LIB} protobuf::protoc) + add_custom_command( + TARGET install_protobuf + COMMAND ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR} -P cmake_install.cmake + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/external/protobuf/cmake + COMMENT "Installing protobuf" + ) +endif() + +if(NOT onnxruntime_BUILD_SHARED_LIB AND onnxruntime_USE_WEBGPU) + message(WARNING "CMake target files will not be generated for static onnxruntime builds with webgpu support") +else() + # Install + include(CMakePackageConfigHelpers) + + set(PROJECT_CONFIG_CONTENT "@PACKAGE_INIT@\n") + + if (NOT onnxruntime_BUILD_SHARED_LIB) + string(APPEND PROJECT_CONFIG_CONTENT + "include(CMakeFindDependencyMacro)\n\ + find_dependency(absl)\n\ + find_dependency(date)\n\ + find_dependency(Eigen3)\n\ + find_dependency(nlohmann_json)\n\ + find_dependency(ONNX)\n\ + find_dependency(re2)\n\ + find_dependency(flatbuffers)\n\ + find_dependency(cpuinfo)\n\ + find_dependency(protobuf)\n\ + find_dependency(Boost COMPONENTS mp11)\n\ + find_dependency(Microsoft.GSL 4.0)\n\ + if(NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL \"Android\")\n\ + find_dependency(Iconv)\n\ + endif()\n\ + if(WIN32)\n\ + find_dependency(wil)\n\ + endif()\n\ + find_path(safeint_SOURCE_DIR NAMES \"SafeInt.hpp\" REQUIRED)\n\ + add_library(safeint_interface IMPORTED INTERFACE)\n\ + target_include_directories(safeint_interface INTERFACE ${safeint_SOURCE_DIR})\n\ + ") + endif() + + string(APPEND PROJECT_CONFIG_CONTENT + "include(\"\${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}Targets.cmake\")\n") + + + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/PROJECT_CONFIG_FILE" ${PROJECT_CONFIG_CONTENT}) + install(EXPORT ${PROJECT_NAME}Targets + NAMESPACE ${PROJECT_NAME}:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) + + # Create config for find_package() + configure_package_config_file( + "${CMAKE_CURRENT_BINARY_DIR}/PROJECT_CONFIG_FILE" ${PROJECT_NAME}Config.cmake + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + + write_basic_package_version_file( + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + VERSION ${ORT_VERSION} + COMPATIBILITY SameMajorVersion) + + install( + FILES + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + + if(DEFINED BUILD_AS_ARM64X) + set(ARM64X_TARGETS onnxruntime) + + # Add additional ARM64X build targets + if (onnxruntime_USE_QNN AND NOT onnxruntime_BUILD_QNN_EP_STATIC_LIB) + list(APPEND ARM64X_TARGETS onnxruntime_providers_shared) + list(APPEND ARM64X_TARGETS onnxruntime_providers_qnn) + endif() + + include("${CMAKE_CURRENT_SOURCE_DIR}/arm64x.cmake") + endif() +endif() + +if(onnxruntime_BUILD_UNIT_TESTS) + include("${CMAKE_CURRENT_SOURCE_DIR}/onnxruntime_test_pch.cmake") +endif() + +# Include precompiled header configuration for providers +if(TARGET onnxruntime_providers) + include("${CMAKE_CURRENT_SOURCE_DIR}/onnxruntime_providers_pch.cmake") +endif() diff --git a/desktop/l/custom-packages/onnxruntime/fix-composable-kernel-path.patch b/desktop/l/custom-packages/onnxruntime/fix-composable-kernel-path.patch new file mode 100644 index 0000000..7a9e619 --- /dev/null +++ b/desktop/l/custom-packages/onnxruntime/fix-composable-kernel-path.patch @@ -0,0 +1,10 @@ +--- a/external/composable_kernel.cmake ++++ b/external/composable_kernel.cmake +@@ -12,6 +12,7 @@ FetchContent_Declare( + GIT_REPOSITORY https://github.com/ROCm/composable_kernel.git + GIT_TAG rocm-6.3.3 + SOURCE_DIR ${FETCHCONTENT_SOURCE_DIR_COMPOSABLE_KERNEL} ++ PATCH_COMMAND ${CMAKE_COMMAND} -E echo "Using composable_kernel from: ${FETCHCONTENT_SOURCE_DIR_COMPOSABLE_KERNEL}" + ) + + FetchContent_Populate(composable_kernel) diff --git a/desktop/l/custom-packages/onnxruntime/package.nix b/desktop/l/custom-packages/onnxruntime/package.nix index 56e2d9b..5259d2c 100644 --- a/desktop/l/custom-packages/onnxruntime/package.nix +++ b/desktop/l/custom-packages/onnxruntime/package.nix @@ -19,6 +19,7 @@ , protobuf , microsoft-gsl , darwinMinVersionHook +, git , pythonSupport ? true , cudaSupport ? config.cudaSupport , ncclSupport ? config.cudaSupport @@ -32,6 +33,13 @@ let version = "1.22.2"; + # IMPORTANT: CUDA and ROCm support are mutually exclusive in onnxruntime + # - cudaSupport: Enable CUDA support for NVIDIA GPUs + # - ncclSupport: Enable NCCL for CUDA multi-GPU support (requires cudaSupport) + # - rocmSupport: Enable ROCm support for AMD GPUs + # - rcclSupport: Enable RCCL for ROCm multi-GPU support (requires rocmSupport) + # Only one of (cudaSupport, rocmSupport) can be true at a time + src = fetchFromGitHub { owner = "microsoft"; repo = "onnxruntime"; @@ -40,6 +48,7 @@ let hash = "sha256-X8Pdtc0eR0iU+Xi2A1HrNo1xqCnoaxNjj4QFm/E3kSE="; }; + stdenv = throw "Use effectiveStdenv instead"; effectiveStdenv = if cudaSupport then cudaPackages.backendStdenv else inputs.stdenv; @@ -80,9 +89,35 @@ let hash = "sha256-RoJxvlrt1QcGvB8m/kycziTbO367diOpsnro49hDl24="; }; - isCudaJetson = cudaSupport && cudaPackages.flags.isJetsonBuild; -in -effectiveStdenv.mkDerivation rec { + composable_kernel = fetchFromGitHub { + owner = "ROCm"; + repo = "composable_kernel"; + tag = "rocm-6.3.3"; + hash = "sha256-XIzoiFkUyQ8VsqsQFg8HVbDRdP8vZF527OpBGbBU2j0="; + }; + + isCudaJetson = cudaSupport && cudaPackages.flags.isJetsonBuild; + + # Validate that CUDA and ROCm are not both enabled + _ = if cudaSupport && rocmSupport then + throw '' + onnxruntime: CUDA and ROCm support cannot be enabled simultaneously. + + Current configuration: + - cudaSupport = ${toString cudaSupport} + - rocmSupport = ${toString rocmSupport} + + Please choose either: + - For NVIDIA GPUs: cudaSupport = true, rocmSupport = false + - For AMD GPUs: cudaSupport = false, rocmSupport = true + '' + else if cudaSupport && rcclSupport then + throw "onnxruntime: RCCL support requires ROCm support, but CUDA is enabled. Please disable CUDA or enable ROCm." + else if rocmSupport && ncclSupport then + throw "onnxruntime: NCCL support requires CUDA support, but ROCm is enabled. Please disable ROCm or enable CUDA." + else null; + in + effectiveStdenv.mkDerivation rec { pname = "onnxruntime"; inherit src version; @@ -97,6 +132,7 @@ effectiveStdenv.mkDerivation rec { pkg-config python3Packages.python protobuf + git ] ++ lib.optionals pythonSupport ( with python3Packages; @@ -117,6 +153,12 @@ effectiveStdenv.mkDerivation rec { ] ++ lib.optionals rocmSupport [ rocmPackages.rocm-cmake + rocmPackages.rocm-core + rocmPackages.rocmPath + rocmPackages.rocminfo + rocmPackages.clr + rocmPackages.rocm-comgr + rocmPackages.hip-common rocmPackages.hipcc rocmPackages.llvm.clang rocmPackages.rocm-device-libs @@ -165,11 +207,20 @@ effectiveStdenv.mkDerivation rec { [ rocm-core rocm-runtime + clr + rocm-comgr + hip-common + hipcub + rocprim hipblas rocblas miopen rocfft rocsparse + hiprand + rocrand + hipfft + roctracer ] ++ lib.optionals (rocmSupport && rcclSupport) [ rccl @@ -235,30 +286,49 @@ effectiveStdenv.mkDerivation rec { (lib.cmakeFeature "CMAKE_CUDA_ARCHITECTURES" cudaArchitecturesString) (lib.cmakeFeature "onnxruntime_NVCC_THREADS" "1") ] - ++ lib.optionals rocmSupport [ - (lib.cmakeFeature "ROCM_PATH" "${rocmPackages.rocm-core}") - # Comprehensive AMD GPU architecture support: - # MI Cards: gfx900 (MI25/Vega 10), gfx906 (MI50/MI60/Vega 20), gfx908 (MI100/CDNA), gfx90a (MI200/CDNA2), gfx942 (MI300/CDNA3) - # RDNA Cards: gfx1010 (RX 5700/Navi 10), gfx1011 (Pro 5600M/Navi 12), gfx1012 (RX 5500/Navi 14), gfx1020 (Navi 21 early), gfx1030 (RX 6800/6900/Navi 21/22), gfx1100 (RX 7900/Navi 31) - (lib.cmakeFeature "CMAKE_HIP_ARCHITECTURES" "gfx900;gfx906;gfx908;gfx90a;gfx942;gfx1010;gfx1011;gfx1012;gfx1020;gfx1030;gfx1100") - (lib.cmakeFeature "HIP_COMPILER" "${rocmPackages.hipcc}/bin/hipcc") - (lib.cmakeFeature "CMAKE_CXX_COMPILER" "${rocmPackages.hipcc}/bin/hipcc") - ]; + ++ lib.optionals rocmSupport [ + # ROCm version information for CMake + (lib.cmakeFeature "ROCM_VERSION" "6.3.3") + (lib.cmakeFeature "ROCM_VERSION_MAJOR" "6") + (lib.cmakeFeature "ROCM_VERSION_MINOR" "3") + (lib.cmakeFeature "ROCM_VERSION_PATCH" "3") + # Point onnxruntime to our custom ROCm build directory using absolute path + (lib.cmakeFeature "onnxruntime_ROCM_HOME" "/build/source/rocm-6.3.3") + # Comprehensive AMD GPU architecture support: + # MI Cards: gfx900 (MI25/Vega 10), gfx906 (MI50/MI60/Vega 20), gfx908 (MI100/CDNA), gfx90a (MI200/CDNA2), gfx942 (MI300/CDNA3) + # RDNA Cards: gfx1010 (RX 5700/Navi 10), gfx1011 (Pro 5600M/Navi 12), gfx1012 (RX 5500/Navi 14), gfx1020 (Navi 21 early), gfx1030 (RX 6800/6900/Navi 21/22), gfx1100 (RX 7900/Navi 31) + (lib.cmakeFeature "CMAKE_HIP_ARCHITECTURES" "gfx900;gfx906;gfx908;gfx90a;gfx942;gfx1010;gfx1011;gfx1012;gfx1020;gfx1030;gfx1100") + (lib.cmakeFeature "HIP_COMPILER" "${rocmPackages.hipcc}/bin/hipcc") + (lib.cmakeFeature "CMAKE_CXX_COMPILER" "${rocmPackages.hipcc}/bin/hipcc") + (lib.cmakeFeature "CMAKE_HIP_COMPILER" "${rocmPackages.llvm.clang}/bin/clang++") + # External dependencies for ROCm + (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_COMPOSABLE_KERNEL" "${composable_kernel}") + # Fix composable_kernel path for generate.py script + (lib.cmakeFeature "CK_TILE_FMHA_GENERATE_PY" "${composable_kernel}/example/ck_tile/01_fmha/generate.py") + ]; - env = lib.optionalAttrs effectiveStdenv.cc.isClang { - NIX_CFLAGS_COMPILE = "-Wno-error"; - } // lib.optionalAttrs rocmSupport { - # ROCm environment variables for HIP compiler - ROCM_PATH = "${rocmPackages.rocm-core}"; - HIP_PATH = "${rocmPackages.hipcc}"; - HIP_CLANG_PATH = "${rocmPackages.llvm.clang}/bin"; - HSA_PATH = "${rocmPackages.rocm-core}"; - HIP_PLATFORM = "amd"; - HIP_COMPILER = "clang"; - HIP_RUNTIME = "rocclr"; - # ROCm device library path - ROCM_DEVICE_LIB_PATH = "${rocmPackages.rocm-device-libs}/lib"; - }; + env = lib.optionalAttrs effectiveStdenv.cc.isClang { + NIX_CFLAGS_COMPILE = "-Wno-error"; + } // lib.optionalAttrs rocmSupport { + # ROCm environment variables for HIP compiler - using Nix store paths + ROCM_PATH = "${rocmPackages.rocm-core}"; + ROCM_HOME = "${rocmPackages.rocm-core}"; + HIP_PATH = "${rocmPackages.hipcc}"; + HIP_CLANG_PATH = "${rocmPackages.llvm.clang}/bin"; + HSA_PATH = "${rocmPackages.rocm-core}"; + HIP_PLATFORM = "amd"; + HIP_COMPILER = "clang"; + HIP_RUNTIME = "rocclr"; + # ROCm device library path + ROCM_DEVICE_LIB_PATH = "${rocmPackages.rocm-device-libs}/lib"; + # ROCm version information for CMake detection + ROCM_VERSION = "6.3.3"; + ROCM_VERSION_MAJOR = "6"; + ROCM_VERSION_MINOR = "3"; + ROCM_VERSION_PATCH = "3"; + # Additional paths for HIP compiler - using Nix store paths + PATH = "${rocmPackages.rocmPath}/bin:${rocmPackages.rocm-core}/bin:${rocmPackages.llvm.clang}/bin:$PATH"; + }; doCheck = !( @@ -293,15 +363,152 @@ effectiveStdenv.mkDerivation rec { rm -v onnxruntime/test/optimizer/nhwc_transformer_test.cc ''; - preConfigure = lib.optionalString rocmSupport '' - # Create symlinks for ROCm tools that HIP compiler expects - mkdir -p /tmp/rocm/bin /tmp/rocm/lib/llvm/bin - ln -sf ${rocmPackages.rocm-core}/bin/rocm_agent_enumerator /tmp/rocm/bin/rocm_agent_enumerator - ln -sf ${rocmPackages.llvm.clang}/bin/clang++ /tmp/rocm/lib/llvm/bin/clang++ - ln -sf ${rocmPackages.llvm.clang}/bin/clang /tmp/rocm/lib/llvm/bin/clang - export ROCM_PATH=/tmp/rocm - export ROCM_DEVICE_LIB_PATH=${rocmPackages.rocm-device-libs}/lib - ''; + preConfigure = lib.optionalString rocmSupport '' + # Debug: Show ROCm environment variables (set via env attribute) + echo "ROCm environment variables:" + echo "ROCM_PATH=$ROCM_PATH" + echo "ROCM_DEVICE_LIB_PATH=$ROCM_DEVICE_LIB_PATH" + echo "HIP_PATH=$HIP_PATH" + echo "HIP_CLANG_PATH=$HIP_CLANG_PATH" + echo "HSA_PATH=$HSA_PATH" + echo "PATH=$PATH" + + # Create a custom ROCm directory structure in the build directory + # since we can't write to the Nix store + ROCM_BUILD_DIR=$PWD/rocm-6.3.3 + mkdir -p $ROCM_BUILD_DIR/share/rocm/.info + mkdir -p $ROCM_BUILD_DIR/.info + mkdir -p $ROCM_BUILD_DIR/lib/cmake/rocm + mkdir -p $ROCM_BUILD_DIR/include/rocm + mkdir -p $ROCM_BUILD_DIR/include/rocm-core + + # Create version files in the build directory (onnxruntime looks for these specific files) + echo "6.3.3" > $ROCM_BUILD_DIR/version + echo "6.3.3-0" > $ROCM_BUILD_DIR/.info/version + echo "6.3.3" > $ROCM_BUILD_DIR/share/rocm/version + echo "6.3.3" > $ROCM_BUILD_DIR/share/rocm/.info/version + + # Create CMake version file + cat > $ROCM_BUILD_DIR/lib/cmake/rocm/rocm-config-version.cmake << 'EOF' + set(PACKAGE_VERSION "6.3.3") + set(PACKAGE_VERSION_MAJOR "6") + set(PACKAGE_VERSION_MINOR "3") + set(PACKAGE_VERSION_PATCH "3") + EOF + + # Create rocm-config.cmake file + cat > $ROCM_BUILD_DIR/lib/cmake/rocm/rocm-config.cmake << 'EOF' + set(ROCM_VERSION "6.3.3") + set(ROCM_VERSION_MAJOR "6") + set(ROCM_VERSION_MINOR "3") + set(ROCM_VERSION_PATCH "3") + EOF + + # Create symlinks to ROCm CMake modules + mkdir -p $ROCM_BUILD_DIR/share/rocm/cmake + ln -sf "${rocmPackages.rocm-cmake}/share/rocm/cmake"/* $ROCM_BUILD_DIR/share/rocm/cmake/ 2>/dev/null || true + + # Debug: Show ROCm CMake modules + echo "Debug: ROCm CMake modules from rocm-cmake package:" + ls -la "${rocmPackages.rocm-cmake}/share/rocm/cmake/" || echo "No ROCm CMake modules found" + echo "Debug: ROCm CMake modules in our build directory:" + ls -la $ROCM_BUILD_DIR/share/rocm/cmake/ || echo "No ROCm CMake modules in build directory" + + # Debug: Show composable_kernel structure + echo "Debug: Composable kernel source structure:" + find "${composable_kernel}" -name "generate.py" -type f || echo "No generate.py found" + find "${composable_kernel}" -path "*/example/ck_tile/01_fmha/*" -type f || echo "No 01_fmha files found" + + # Fix composable_kernel path issue - create symlink to expected location + echo "Debug: Creating symlink for composable_kernel generate.py in preConfigure" + mkdir -p $PWD/cmake/example/ck_tile/01_fmha + ln -sf "${composable_kernel}/example/ck_tile/01_fmha/generate.py" $PWD/cmake/example/ck_tile/01_fmha/generate.py + echo "Debug: Symlink created in preConfigure:" + ls -la $PWD/cmake/example/ck_tile/01_fmha/generate.py || echo "Symlink creation failed in preConfigure" + + # Create rocm_version.h header files (onnxruntime looks for these) + cat > $ROCM_BUILD_DIR/include/rocm_version.h << 'EOF' +#ifndef ROCM_VERSION_H +#define ROCM_VERSION_H +#define ROCM_VERSION_MAJOR 6 +#define ROCM_VERSION_MINOR 3 +#define ROCM_VERSION_PATCH 3 +#define ROCM_VERSION_STRING "6.3.3" +#endif +EOF + + # Also create the rocm-core version + cat > $ROCM_BUILD_DIR/include/rocm-core/rocm_version.h << 'EOF' +#ifndef ROCM_VERSION_H +#define ROCM_VERSION_H +#define ROCM_VERSION_MAJOR 6 +#define ROCM_VERSION_MINOR 3 +#define ROCM_VERSION_PATCH 3 +#define ROCM_VERSION_STRING "6.3.3" +#endif +EOF + + # Create MIOPEN version.h file (onnxruntime looks for this) + mkdir -p $ROCM_BUILD_DIR/include/miopen + cat > $ROCM_BUILD_DIR/include/miopen/version.h << 'EOF' +#ifndef MIOPEN_VERSION_H +#define MIOPEN_VERSION_H +#define MIOPEN_VERSION_MAJOR 6 +#define MIOPEN_VERSION_MINOR 3 +#define MIOPEN_VERSION_PATCH 3 +#define MIOPEN_VERSION_STRING "6.3.3" +#endif +EOF + + # Debug: Show what's in our include directory + echo "Debug: Contents of include directory:" + ls -la $ROCM_BUILD_DIR/include/ || echo "include directory not found" + echo "Debug: Contents of include/rocm-core directory:" + ls -la $ROCM_BUILD_DIR/include/rocm-core/ || echo "include/rocm-core directory not found" + echo "Debug: Contents of include/miopen directory:" + ls -la $ROCM_BUILD_DIR/include/miopen/ || echo "miopen directory not found" + + # Create symlinks to the actual ROCm tools in the Nix store + mkdir -p $ROCM_BUILD_DIR/bin + mkdir -p $ROCM_BUILD_DIR/llvm/bin + ln -sf "${rocmPackages.hipcc}/bin/hipcc" $ROCM_BUILD_DIR/bin/hipcc + ln -sf "${rocmPackages.llvm.clang}/bin/clang++" $ROCM_BUILD_DIR/llvm/bin/clang++ + ln -sf "${rocmPackages.llvm.clang}/bin/clang" $ROCM_BUILD_DIR/llvm/bin/clang + ln -sf "${rocmPackages.rocmPath}/bin/rocm_agent_enumerator" $ROCM_BUILD_DIR/bin/rocm_agent_enumerator + + # Update environment variables to point to our build directory + export ROCM_PATH=$ROCM_BUILD_DIR + export CMAKE_PREFIX_PATH=$ROCM_BUILD_DIR:$CMAKE_PREFIX_PATH + + # Set the ROCM_HOME environment variable for CMake to use + export ROCM_HOME=$ROCM_BUILD_DIR + + echo "Created ROCm build directory at: $ROCM_BUILD_DIR" + echo "Updated ROCM_PATH to: $ROCM_PATH" + echo "Set ROCM_HOME to: $ROCM_HOME" + + # Debug: Show the files we created + echo "Debug: ROCm version files created:" + ls -la $ROCM_BUILD_DIR/version || echo "version file not found" + ls -la $ROCM_BUILD_DIR/.info/version || echo ".info/version file not found" + ls -la $ROCM_BUILD_DIR/include/rocm-core/rocm_version.h || echo "rocm_version.h not found" + + # Debug: Show the symlinks we created + echo "Debug: ROCm tool symlinks created:" + ls -la $ROCM_BUILD_DIR/bin/hipcc || echo "hipcc symlink not found" + ls -la $ROCM_BUILD_DIR/llvm/bin/clang++ || echo "clang++ symlink not found" + ls -la $ROCM_BUILD_DIR/bin/rocm_agent_enumerator || echo "rocm_agent_enumerator symlink not found" + + # Debug: Show what onnxruntime will look for + echo "Debug: onnxruntime_ROCM_HOME will be set to: /build/source/rocm-6.3.3" + echo "Debug: This should point to our ROCm directory with version files" + + # Verify ROCm tools are accessible + echo "Checking ROCm tools:" + command -v rocm_agent_enumerator || echo "rocm_agent_enumerator not found" + command -v hipcc || echo "hipcc not found" + command -v clang++ || echo "clang++ not found" + ''; postBuild = lib.optionalString pythonSupport '' ${python3Packages.python.interpreter} ../setup.py bdist_wheel diff --git a/desktop/l/flake.nix b/desktop/l/flake.nix index fade3f6..de94741 100644 --- a/desktop/l/flake.nix +++ b/desktop/l/flake.nix @@ -50,16 +50,28 @@ #hyprland.nixosModules.default home-manager.nixosModules.home-manager { - # Apply the overlay to NixOS - nixpkgs.overlays = [ - (final: prev: { - # Custom onnxruntime with ROCm support (temporarily disabled) - onnxruntime = final.callPackage ./custom-packages/onnxruntime/package.nix { - rocmSupport = false; - rcclSupport = false; - }; - }) - ]; + # # Apply the overlay to NixOS + # nixpkgs.overlays = [ + # (final: prev: { + # # Custom onnxruntime with ROCm support + # # Note: CUDA and ROCm are mutually exclusive - only one can be enabled + # onnxruntime = final.callPackage ./custom-packages/onnxruntime/package.nix { + # cudaSupport = false; # Disable CUDA when using ROCm + # ncclSupport = false; # NCCL requires CUDA, so disable with ROCm + # rocmSupport = true; # Enable ROCm support for AMD GPUs + # rcclSupport = true; # Enable RCCL for ROCm multi-GPU support + # }; + + # # Custom Python onnxruntime module that uses our custom onnxruntime + # python313Packages = prev.python313Packages.override (old: { + # overrides = prev.lib.composeExtensions (old.overrides or (_: _: {})) (pyfinal: pyprev: { + # onnxruntime = pyfinal.callPackage ./custom-packages/python-onnxruntime/default.nix { + # onnxruntime = final.onnxruntime; + # }; + # }); + # }); + # }) + # ]; # Allow unfree packages nixpkgs.config.allowUnfree = true; diff --git a/desktop/l/home.nix b/desktop/l/home.nix index fa3ffc5..1e3d417 100644 --- a/desktop/l/home.nix +++ b/desktop/l/home.nix @@ -125,6 +125,7 @@ gnumake #cmake pkg-config + shellcheck gdb @@ -249,6 +250,9 @@ # Diffing meld + # tcl/expect + expect + # Editors helix @@ -541,7 +545,7 @@ obs-3d-effect wlrobs #obs-vnc - obs-ndi + #obs-ndi waveform pixel-art obs-vaapi From 51df916bb9556fe54b01aa01398d3cfb34dd750c Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Mon, 13 Oct 2025 13:32:18 -0700 Subject: [PATCH 20/23] commit --- desktop/l/home.nix | 12 +- super/a/Makefile | 2 + super/a/configuration.nix | 90 +++++++++ super/a/hardware-configuration.nix | 41 ++++ super/b/Makefile | 2 + super/b/configuration.nix | 90 +++++++++ super/b/hardware-configuration.nix | 41 ++++ super/c/Makefile | 2 + super/c/configuration.nix | 90 +++++++++ super/c/hardware-configuration.nix | 41 ++++ super/d/Makefile | 2 + super/d/configuration.nix | 94 ++++++++++ super/d/hardware-configuration.nix | 41 ++++ super/macs | 51 +++++ super/zfs_design_2025_10_08 | 289 +++++++++++++++++++++++++++++ 15 files changed, 882 insertions(+), 6 deletions(-) create mode 100644 super/a/Makefile create mode 100644 super/a/configuration.nix create mode 100644 super/a/hardware-configuration.nix create mode 100644 super/b/Makefile create mode 100644 super/b/configuration.nix create mode 100644 super/b/hardware-configuration.nix create mode 100644 super/c/Makefile create mode 100644 super/c/configuration.nix create mode 100644 super/c/hardware-configuration.nix create mode 100644 super/d/Makefile create mode 100644 super/d/configuration.nix create mode 100644 super/d/hardware-configuration.nix create mode 100644 super/macs create mode 100644 super/zfs_design_2025_10_08 diff --git a/desktop/l/home.nix b/desktop/l/home.nix index 1e3d417..97eec71 100644 --- a/desktop/l/home.nix +++ b/desktop/l/home.nix @@ -184,16 +184,16 @@ # Filesystem/Monitoring inotify-tools - # SDR - gnuradio - hackrf - gqrx - cubicsdr + # SDR #cmake errors + # gnuradio + # hackrf + # gqrx + # cubicsdr # Media vlc # ffmpeg moved to system package - ffmpeg_7-full + ffmpeg_8-full # Go Development # https://nixos.wiki/wiki/Go diff --git a/super/a/Makefile b/super/a/Makefile new file mode 100644 index 0000000..0b44652 --- /dev/null +++ b/super/a/Makefile @@ -0,0 +1,2 @@ +all: + scp 172.16.40.135:/etc/nixos/* ./ diff --git a/super/a/configuration.nix b/super/a/configuration.nix new file mode 100644 index 0000000..2e205e9 --- /dev/null +++ b/super/a/configuration.nix @@ -0,0 +1,90 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: + +{ + imports = + [ # Include the results of the hardware scan. + ./hardware-configuration.nix + ]; + + # Bootloader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + networking.hostName = "nodeA"; # Define your hostname. + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Enable networking + networking.networkmanager.enable = true; + + # Set your time zone. + time.timeZone = "America/Los_Angeles"; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + + i18n.extraLocaleSettings = { + LC_ADDRESS = "en_US.UTF-8"; + LC_IDENTIFICATION = "en_US.UTF-8"; + LC_MEASUREMENT = "en_US.UTF-8"; + LC_MONETARY = "en_US.UTF-8"; + LC_NAME = "en_US.UTF-8"; + LC_NUMERIC = "en_US.UTF-8"; + LC_PAPER = "en_US.UTF-8"; + LC_TELEPHONE = "en_US.UTF-8"; + LC_TIME = "en_US.UTF-8"; + }; + + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.das = { + isNormalUser = true; + description = "das"; + extraGroups = [ "networkmanager" "wheel" ]; + packages = with pkgs; []; + }; + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; [ + vim + # wget + ]; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + networking.firewall.enable = false; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "25.05"; # Did you read the comment? + +} diff --git a/super/a/hardware-configuration.nix b/super/a/hardware-configuration.nix new file mode 100644 index 0000000..4b5109d --- /dev/null +++ b/super/a/hardware-configuration.nix @@ -0,0 +1,41 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "ehci_pci" "megaraid_sas" "usb_storage" "usbhid" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/366626db-1e77-413c-a353-aa788bae570a"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/83C7-A8FA"; + fsType = "vfat"; + options = [ "fmask=0077" "dmask=0077" ]; + }; + + swapDevices = + [ { device = "/dev/disk/by-uuid/6f7b0ac3-4f55-431c-adf3-39eeba6dd527"; } + ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.eno1.useDHCP = lib.mkDefault true; + # networking.interfaces.eno2.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/super/b/Makefile b/super/b/Makefile new file mode 100644 index 0000000..229bd9c --- /dev/null +++ b/super/b/Makefile @@ -0,0 +1,2 @@ +all: + scp 172.16.40.97:/etc/nixos/* ./ diff --git a/super/b/configuration.nix b/super/b/configuration.nix new file mode 100644 index 0000000..7e1c156 --- /dev/null +++ b/super/b/configuration.nix @@ -0,0 +1,90 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: + +{ + imports = + [ # Include the results of the hardware scan. + ./hardware-configuration.nix + ]; + + # Bootloader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + networking.hostName = "nodeB"; # Define your hostname. + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Enable networking + networking.networkmanager.enable = true; + + # Set your time zone. + time.timeZone = "America/Los_Angeles"; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + + i18n.extraLocaleSettings = { + LC_ADDRESS = "en_US.UTF-8"; + LC_IDENTIFICATION = "en_US.UTF-8"; + LC_MEASUREMENT = "en_US.UTF-8"; + LC_MONETARY = "en_US.UTF-8"; + LC_NAME = "en_US.UTF-8"; + LC_NUMERIC = "en_US.UTF-8"; + LC_PAPER = "en_US.UTF-8"; + LC_TELEPHONE = "en_US.UTF-8"; + LC_TIME = "en_US.UTF-8"; + }; + + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.das = { + isNormalUser = true; + description = "das"; + extraGroups = [ "networkmanager" "wheel" ]; + packages = with pkgs; []; + }; + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; [ + vim + # wget + ]; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + programs.gnupg.agent = { + enable = true; + enableSSHSupport = true; + }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + networking.firewall.enable = false; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "25.05"; # Did you read the comment? + +} diff --git a/super/b/hardware-configuration.nix b/super/b/hardware-configuration.nix new file mode 100644 index 0000000..90bfa57 --- /dev/null +++ b/super/b/hardware-configuration.nix @@ -0,0 +1,41 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "ehci_pci" "megaraid_sas" "nvme" "usb_storage" "usbhid" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/4d6b81d7-28cd-452c-a4ec-78128b36fb60"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/0787-337D"; + fsType = "vfat"; + options = [ "fmask=0077" "dmask=0077" ]; + }; + + swapDevices = + [ { device = "/dev/disk/by-uuid/a729e9cb-d827-42da-b1a8-ac5bb4d0eac9"; } + ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.eno1.useDHCP = lib.mkDefault true; + # networking.interfaces.eno2.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/super/c/Makefile b/super/c/Makefile new file mode 100644 index 0000000..c7acd25 --- /dev/null +++ b/super/c/Makefile @@ -0,0 +1,2 @@ +all: + scp 172.16.40.151:/etc/nixos/* ./ diff --git a/super/c/configuration.nix b/super/c/configuration.nix new file mode 100644 index 0000000..890b149 --- /dev/null +++ b/super/c/configuration.nix @@ -0,0 +1,90 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: + +{ + imports = + [ # Include the results of the hardware scan. + ./hardware-configuration.nix + ]; + + # Bootloader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + networking.hostName = "nodeC"; + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Enable networking + networking.networkmanager.enable = true; + + # Set your time zone. + time.timeZone = "America/Los_Angeles"; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + + i18n.extraLocaleSettings = { + LC_ADDRESS = "en_US.UTF-8"; + LC_IDENTIFICATION = "en_US.UTF-8"; + LC_MEASUREMENT = "en_US.UTF-8"; + LC_MONETARY = "en_US.UTF-8"; + LC_NAME = "en_US.UTF-8"; + LC_NUMERIC = "en_US.UTF-8"; + LC_PAPER = "en_US.UTF-8"; + LC_TELEPHONE = "en_US.UTF-8"; + LC_TIME = "en_US.UTF-8"; + }; + + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.das = { + isNormalUser = true; + description = "das"; + extraGroups = [ "networkmanager" "wheel" ]; + packages = with pkgs; []; + }; + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; [ + vim + # wget + ]; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + programs.gnupg.agent = { + enable = true; + enableSSHSupport = true; + }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + networking.firewall.enable = false; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "25.05"; # Did you read the comment? + +} diff --git a/super/c/hardware-configuration.nix b/super/c/hardware-configuration.nix new file mode 100644 index 0000000..6c1d940 --- /dev/null +++ b/super/c/hardware-configuration.nix @@ -0,0 +1,41 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "ehci_pci" "megaraid_sas" "usb_storage" "usbhid" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/a751a6a6-55b9-4911-a176-cfd62a02a375"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/CABE-31FC"; + fsType = "vfat"; + options = [ "fmask=0077" "dmask=0077" ]; + }; + + swapDevices = + [ { device = "/dev/disk/by-uuid/0bd599ea-9a9b-4466-8f71-9085dde1823b"; } + ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.eno1.useDHCP = lib.mkDefault true; + # networking.interfaces.eno2.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/super/d/Makefile b/super/d/Makefile new file mode 100644 index 0000000..2ee4339 --- /dev/null +++ b/super/d/Makefile @@ -0,0 +1,2 @@ +all: + scp 172.16.40.129:/etc/nixos/* ./ diff --git a/super/d/configuration.nix b/super/d/configuration.nix new file mode 100644 index 0000000..6e6b4ee --- /dev/null +++ b/super/d/configuration.nix @@ -0,0 +1,94 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: + +{ + imports = + [ # Include the results of the hardware scan. + ./hardware-configuration.nix + ]; + + # Bootloader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + networking.hostName = "nodeD"; # Define your hostname. + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Enable networking + networking.networkmanager.enable = true; + + # Set your time zone. + time.timeZone = "America/Los_Angeles"; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + + i18n.extraLocaleSettings = { + LC_ADDRESS = "en_US.UTF-8"; + LC_IDENTIFICATION = "en_US.UTF-8"; + LC_MEASUREMENT = "en_US.UTF-8"; + LC_MONETARY = "en_US.UTF-8"; + LC_NAME = "en_US.UTF-8"; + LC_NUMERIC = "en_US.UTF-8"; + LC_PAPER = "en_US.UTF-8"; + LC_TELEPHONE = "en_US.UTF-8"; + LC_TIME = "en_US.UTF-8"; + }; + + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.das = { + isNormalUser = true; + description = "das"; + extraGroups = [ "networkmanager" "wheel" ]; + packages = with pkgs; []; + }; + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; [ + vim + # wget + ]; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + programs.gnupg.agent = { + enable = true; + enableSSHSupport = true; + }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + networking.firewall.enable = false; + + services.lldpd.enable = true; + services.timesyncd.enable = true; + #services.fstrim.enabled = true; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "25.05"; # Did you read the comment? + +} diff --git a/super/d/hardware-configuration.nix b/super/d/hardware-configuration.nix new file mode 100644 index 0000000..14e65a5 --- /dev/null +++ b/super/d/hardware-configuration.nix @@ -0,0 +1,41 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "ehci_pci" "megaraid_sas" "usb_storage" "usbhid" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/1031c223-1d8b-4226-87ba-d3fc949b8f0f"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/A9D9-C6CF"; + fsType = "vfat"; + options = [ "fmask=0077" "dmask=0077" ]; + }; + + swapDevices = + [ { device = "/dev/disk/by-uuid/e1242083-bbe5-4532-93d0-b5682aab68f4"; } + ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.eno1.useDHCP = lib.mkDefault true; + # networking.interfaces.eno2.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/super/macs b/super/macs new file mode 100644 index 0000000..b2c53e3 --- /dev/null +++ b/super/macs @@ -0,0 +1,51 @@ + devices ac:1f:6b:15:cf:1e Learn 0 ge-0/0/2.0 + devices ac:1f:6b:15:d0:29 Learn 0 ge-0/0/3.0 + devices ac:1f:6b:15:d0:a4 Learn 0 ge-0/0/1.0 + devices ac:1f:6b:15:d0:b7 Learn 1:23 ge-0/0/0.0 + devices ac:1f:6b:15:d5:4e Learn 3:52 ge-0/0/10.0 + devices ac:1f:6b:15:d5:4f Learn 3:41 ge-0/0/6.0 + devices ac:1f:6b:15:d7:64 Learn 0 ge-0/0/11.0 + devices ac:1f:6b:15:d7:65 Learn 0 ge-0/0/7.0 + devices ac:1f:6b:15:d8:80 Learn 0 ge-0/0/8.0 + devices ac:1f:6b:15:d8:81 Learn 0 ge-0/0/4.0 + devices ac:1f:6b:15:d8:5b Learn 0 ge-0/0/5.0 + devices ac:1f:6b:15:d8:5a Learn 0 ge-0/0/9.0 + +ge-0/0/0 ac:1f:6b:15:d0:b7 nodeA IPMI 172.16.40.155 good buffered +ge-0/0/1 ac:1f:6b:15:d0:a4 nodeB IPMI 172.16.40.136 good buffered +ge-0/0/2 ac:1f:6b:15:cf:1e nodeC IPMI 172.16.40.235 good buffered +ge-0/0/3 ac:1f:6b:15:d0:29 nodeD IPMI 172.16.40.224 good + +ge-0/0/4 ac:1f:6b:15:d8:81 nodeA NIC0 172.16.40.135 +ge-0/0/5 ac:1f:6b:15:d8:5b nodeB NIC0 172.16.40.97 +ge-0/0/6 ac:1f:6b:15:d5:4f nodeC NIC0 172.16.40.151 +ge-0/0/7 ac:1f:6b:15:d7:65 nodeD NIC0 172.16.40.129 + +ge-0/0/8 ac:1f:6b:15:d8:80 nodeA NIC1 172.16.40.137 +ge-0/0/9 ac:1f:6b:15:d8:5a nodeB NIC1 172.16.40.98 +ge-0/0/10 ac:1f:6b:15:d5:4f nodeC NIC1 172.16.40.152 +ge-0/0/11 ac:1f:6b:15:d7:64 nodeD NIC1 172.16.40.130 + +[das@nodeA:~]$ lsblk +NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS +sda 8:0 0 1.7T 0 disk +├─sda1 8:1 0 1G 0 part /boot +├─sda2 8:2 0 1.6T 0 part /nix/store +│ / +└─sda3 8:3 0 138.3G 0 part [SWAP] +sdb 8:16 0 1.8T 0 disk +nvme0n1 259:0 0 931.5G 0 disk + +[das@nodeA:~]$ + +[das@nodeB:~]$ lsblk +NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS +sda 8:0 0 1.7T 0 disk +├─sda1 8:1 0 1G 0 part /boot +├─sda2 8:2 0 1.6T 0 part /nix/store +│ / +└─sda3 8:3 0 138.3G 0 part [SWAP] +sdb 8:16 0 953.3G 0 disk +nvme0n1 259:0 0 931.5G 0 disk + +[das@nodeB:~]$ diff --git a/super/zfs_design_2025_10_08 b/super/zfs_design_2025_10_08 new file mode 100644 index 0000000..afb957f --- /dev/null +++ b/super/zfs_design_2025_10_08 @@ -0,0 +1,289 @@ +{ config, lib, pkgs, ... }: + +{ + ############################################################################## + # ZFS/ARC sizing note (128 GiB RAM): + # ZFS ARC should not starve ClickHouse/Redpanda. A good starting point is + # ~20–35% of RAM. For 128 GiB: 26–45 GiB. We’ll pin ARC ≈ 32 GiB here: + # + # 128 GiB * 0.25 ≈ 32 GiB => zfs_arc_max = 32 * 1024^3 bytes + # + # Tune up/down after observing workload (CH memory usage, OS cache, etc.). + ############################################################################## + boot.extraModprobeConfig = '' + options zfs zfs_arc_max=$((32 * 1024 * 1024 * 1024)) + # Optional: allow sequential prefetch into L2ARC if your analytics benefit: + # options zfs l2arc_noprefetch=0 + ''; + + # Ensure ZFS modules/userspace: + boot.supportedFilesystems = [ "zfs" ]; + services.zfs.trim.enable = true; + services.zfs.autoScrub.enable = true; + + # Required for stable ZFS host identity (generate once; must be 8 hex chars). + # e.g. networking.hostId = "a1b2c3d4"; + networking.hostId = lib.mkDefault "REPLACE8H"; + + disko.devices = { + ############################################################################ + # Disks + ############################################################################ + disk = { + # --- System disk → rpool + sda = { + type = "disk"; + device = "/dev/disk/by-id/REPLACE-WITH-ID-of-sda"; + content = { + type = "gpt"; + partitions = { + ESP = { + name = "ESP"; + size = "1G"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ "umask=0077" ]; + }; + }; + rpool = { + name = "rpool"; + start = "1G"; + end = "100%"; + type = "BF01"; # ZFS + content = { type = "zfs"; pool = "rpool"; }; + }; + }; + }; + }; + + # --- Data disk → tank + sdb = { + type = "disk"; + device = "/dev/disk/by-id/REPLACE-WITH-ID-of-sdb"; + content = { + type = "gpt"; + partitions = { + tank = { + name = "tank"; + start = "1M"; + end = "100%"; + type = "BF01"; + content = { type = "zfs"; pool = "tank"; }; + }; + }; + }; + }; + + # --- NVMe split across tank + rpool (cache/log/special vdevs) + nvme0n1 = { + type = "disk"; + device = "/dev/disk/by-id/REPLACE-WITH-ID-of-nvme0n1"; + content = { + type = "gpt"; + partitions = { + nvme_cache_tank = { + name = "nvme_cache_tank"; + start = "1M"; + end = "50%"; + type = "BF01"; + content = { type = "zfs"; pool = "tank"; vdev = "cache"; }; # L2ARC + }; + nvme_slog_tank = { + name = "nvme_slog_tank"; + start = "50%"; + end = "70%"; + type = "BF01"; + content = { type = "zfs"; pool = "tank"; vdev = "log"; }; # SLOG + }; + nvme_special_tank = { + name = "nvme_special_tank"; + start = "70%"; + end = "80%"; + type = "BF01"; + content = { type = "zfs"; pool = "tank"; vdev = "special"; }; # metadata/small blocks + }; + nvme_special_rpool = { + name = "nvme_special_rpool"; + start = "80%"; + end = "100%"; + type = "BF01"; + content = { type = "zfs"; pool = "rpool"; vdev = "special"; };# speed up OS pool + }; + }; + }; + }; + }; + + ############################################################################ + # Pools + ############################################################################ + zpool = { + # ---------------------- rpool (OS) -------------------------------------- + rpool = { + type = "zpool"; + options = { + ashift = "12"; + autoreplace = "on"; + }; + rootFsOptions = { + mountpoint = "none"; + compression = "zstd"; + atime = "off"; + xattr = "sa"; + acltype = "posixacl"; + redundant_metadata = "most"; + # Place small blocks/metadata on NVMe special vdev: + special_small_blocks = "16K"; # 8K–16K good start + }; + datasets = { + "root" = { + type = "zfs_fs"; + mountpoint = "/"; + options.mountpoint = "legacy"; + }; + "nix" = { + type = "zfs_fs"; + mountpoint = "/nix"; + options = { + mountpoint = "legacy"; + atime = "off"; + recordsize = "128K"; + }; + }; + "var" = { + type = "zfs_fs"; + mountpoint = "/var"; + options.mountpoint = "legacy"; + }; + "home" = { + type = "zfs_fs"; + mountpoint = "/home"; + options.mountpoint = "legacy"; + }; + + # zvol-backed swap (adjust size as desired; your prior swap ~138 GiB) + "swap" = { + type = "zfs_zvol"; + size = "128G"; + options = { + compression = "zle"; + logbias = "throughput"; + sync = "always"; + primarycache = "metadata"; + }; + swap.enabled = true; # auto-added to /etc/swaps + }; + }; + }; + + # ---------------------- tank (data) ------------------------------------- + tank = { + type = "zpool"; + options = { + ashift = "12"; + autoreplace = "on"; + }; + rootFsOptions = { + mountpoint = "none"; + compression = "zstd"; + atime = "off"; + xattr = "sa"; + acltype = "posixacl"; + redundant_metadata = "most"; + # Default policy; specific datasets can override as needed: + special_small_blocks = "16K"; + # If your workload is very sync-heavy and you value latency: + # logbias = "latency"; + }; + datasets = { + # General root for convenience + "zfs" = { + type = "zfs_fs"; + mountpoint = "/zfs"; + options.mountpoint = "legacy"; + }; + + # ClickHouse primary data + "ch-data" = { + type = "zfs_fs"; + mountpoint = "/zfs/clickhouse"; + options = { + mountpoint = "legacy"; + recordsize = "1M"; + logbias = "throughput"; + compression = "zstd"; + primarycache = "all"; + secondarycache = "all"; # allow L2ARC to help CH reads + special_small_blocks = "16K"; # push metadata/small blocks to NVMe special + }; + }; + + # ClickHouse tmp/scratch (OK to lose on power loss) + "ch-tmp" = { + type = "zfs_fs"; + mountpoint = "/zfs/clickhouse-tmp"; + options = { + mountpoint = "legacy"; + recordsize = "1M"; + compression = "lz4"; + sync = "disabled"; # tmp only + primarycache = "metadata"; + secondarycache = "none"; + special_small_blocks = "16K"; + }; + }; + + # Redpanda (Kafka) log store + "kafka" = { + type = "zfs_fs"; + mountpoint = "/zfs/kafka"; + options = { + mountpoint = "legacy"; + recordsize = "1M"; # large sequential log segments + compression = "lz4"; # or "off" to reduce CPU + logbias = "throughput"; + sync = "standard"; # let app/fsync decide durability + primarycache = "metadata"; # avoid polluting ARC with write-only data + secondarycache = "none"; # keep it out of L2ARC + special_small_blocks = "16K"; + }; + }; + }; + }; + }; + }; + + ############################################################################## + # Mounts for legacy mountpoints + ############################################################################## + fileSystems."/boot" = { device = "/dev/disk/by-partlabel/ESP"; fsType = "vfat"; }; + fileSystems."/" = { device = "rpool/root"; fsType = "zfs"; }; + fileSystems."/nix" = { device = "rpool/nix"; fsType = "zfs"; }; + fileSystems."/var" = { device = "rpool/var"; fsType = "zfs"; }; + fileSystems."/home" = { device = "rpool/home"; fsType = "zfs"; }; + + fileSystems."/zfs" = { device = "tank/zfs"; fsType = "zfs"; }; + fileSystems."/zfs/clickhouse" = { device = "tank/ch-data"; fsType = "zfs"; }; + fileSystems."/zfs/clickhouse-tmp" = { device = "tank/ch-tmp"; fsType = "zfs"; }; + fileSystems."/zfs/kafka" = { device = "tank/kafka"; fsType = "zfs"; }; + + ############################################################################## + # Boot loader (example: systemd-boot; switch to GRUB if needed) + ############################################################################## + boot.loader.systemd-boot.enable = lib.mkDefault true; + boot.loader.efi.canTouchEfiVariables = lib.mkDefault true; + + ############################################################################## + # Safety notes: + # - Special vdev is *critical*: if the NVMe fails, pools using it may be + # unavailable (metadata resides there). For production, mirror the special + # vdev (requires another NVMe). + # - SLOG sized at 20% of NVMe is very large. Typical SLOG sizes are 16–32 GiB + # unless you sustain huge sync write rates. If you don’t need a massive SLOG, + # consider reallocating some of that space to the special vdev(s). + ############################################################################## +} + From df946c9145b6dd852f410b7703bc3477688098d1 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Mon, 13 Oct 2025 19:11:02 -0700 Subject: [PATCH 21/23] fan2go.nix --- desktop/l/configuration.nix | 5 +- desktop/l/fan2go.nix | 111 ++++ desktop/l/fan2go.yml | 61 ++ desktop/l/fan2go_readme.md | 865 +++++++++++++++++++++++++++ desktop/l/gpu_info.md | 457 ++++++++++++++ desktop/l/hardware-configuration.nix | 3 + 6 files changed, 1500 insertions(+), 2 deletions(-) create mode 100644 desktop/l/fan2go.nix create mode 100644 desktop/l/fan2go.yml create mode 100644 desktop/l/fan2go_readme.md create mode 100644 desktop/l/gpu_info.md diff --git a/desktop/l/configuration.nix b/desktop/l/configuration.nix index d769755..76f5319 100644 --- a/desktop/l/configuration.nix +++ b/desktop/l/configuration.nix @@ -38,9 +38,9 @@ # clickhouse ./clickhouse-service.nix # GPU fan control - ./gpu-fan-control.nix + #./gpu-fan-control.nix # Corsair fan control - ./corsair-fan-control.nix + #./corsair-fan-control.nix #./docker-compose.nix ./docker-daemon.nix #./smokeping.nix @@ -48,6 +48,7 @@ #./hyprland.nix ./nginx.nix ./ollama-service.nix + ./fan2go.nix ]; boot = { diff --git a/desktop/l/fan2go.nix b/desktop/l/fan2go.nix new file mode 100644 index 0000000..cde21b8 --- /dev/null +++ b/desktop/l/fan2go.nix @@ -0,0 +1,111 @@ +# +# fan2go.nix +# +# sudo systemctl status fan2go +# sudo ls /var/lib/fan2go +# +# See also: https://github.com/arnarg/config/blob/8de65cf5f1649a4fe6893102120ede4363de9bfa/hosts/terra/fan2go.nix +# +{ + lib, + config, + pkgs, + ... +}: +let + cfg = config.hardware.fan2go; + + fan2goConfig = pkgs.writeText "fan2go.yaml" '' + # + # fan2go.yaml + # + dbPath: ${cfg.dbPath} + + fans: + # Define the fan to be controlled. This is Fan 1 on the Corsair Commander Core XT. + - id: corsair_fan1 + # Use liquidctl to set the fan speed. + # The fan type for external commands is `cmd`. + # Assumes the Corsair Commander Core XT is the first device liquidctl finds. + cmd: + # The `setPwm` command is required. It receives a value from 0-255. + # We use a shell command to convert the 0-255 PWM value from fan2go + # into a 0-100 percentage for liquidctl. + setPwm: + exec: "/run/current-system/sw/bin/bash" + args: ["-c", "percent=$((%pwm% * 100 / 255)); /run/current-system/sw/bin/liquidctl set fan1 speed $percent"] + # The `getPwm` command is optional but good practice. + # It should return a value from 0-255. + getPwm: + exec: "/run/current-system/sw/bin/bash" + args: ["-c", "percent=$(/run/current-system/sw/bin/liquidctl status --json | ${pkgs.jq}/bin/jq '.[0].status[] | select(.key == \"Fan speed 1\").value | tonumber'); echo $((percent * 255 / 100))"] + # Fan speed is a percentage for liquidctl + min: 20 + max: 100 + ## Ensures the fan never fully stops, maintaining minimum airflow. + #neverStop: true + # The curve ID that should be used to determine the speed of this fan. + curve: gpu_cooling_curve + + sensors: + # Define the temperature sensor to monitor. This is the Radeon Pro VII/MI50. + # From `fan2go detect`, this is platform `amdgpu-pci-04400`. + # The sensor type is `hwmon`. + - id: gpu_mi50_temp + hwmon: + platform: amdgpu-pci-04400 + # Use the junction temperature (temp2_input) as it's a good indicator of core heat. + index: 2 + + curves: + # Link the GPU temperature to the case fan speed. + - id: gpu_cooling_curve + # Use a linear interpolation curve based on the defined points. + linear: + # The sensor ID to use as a temperature input for this curve. + sensor: gpu_mi50_temp + # Define the temperature-to-fan-speed mapping. + # Temps are in Celsius, fan speed is in percent. + points: + - [40, 20] # At 40°C, run fan at 20% + - [50, 40] # At 50°C, run fan at 40% + - [60, 60] # At 60°C, run fan at 60% + - [70, 80] # At 70°C, run fan at 80% + - [80, 100] # At 80°C and above, run fan at 100% + + statistics: + # Whether to enable the prometheus exporter or not + enabled: true + # The port to expose the exporter on + port: 9900 + ''; +in +{ + options.hardware.fan2go = with lib; { + enable = mkEnableOption "fan2go"; + + dbPath = mkOption { + type = types.str; + default = "/var/lib/fan2go/fan2go.db"; + description = "The path of the database file"; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.fan2go = { + description = "A simple daemon providing dynamic fan speed control based on temperature sensors"; + wantedBy = [ "multi-user.target" ]; + after = [ "lm_sensors.service" ]; + + serviceConfig = { + ExecStart = lib.concatStringsSep " " [ + "${pkgs.fan2go}/bin/fan2go" + "-c" + "${fan2goConfig}" + "--no-style" + ]; + LimitNOFILE = 8192; + }; + }; + }; +} \ No newline at end of file diff --git a/desktop/l/fan2go.yml b/desktop/l/fan2go.yml new file mode 100644 index 0000000..9f41e61 --- /dev/null +++ b/desktop/l/fan2go.yml @@ -0,0 +1,61 @@ +# fan2go configuration for controlling a Corsair case fan based on the +# temperature of the Radeon Pro VII / Instinct MI50 GPU, which has no fan. + +fans: + # Define the fan to be controlled. This is Fan 1 on the Corsair Commander Core XT. + - id: corsair_fan1 + # Use liquidctl to set the fan speed. + # The fan type for external commands is `cmd`. + # Assumes the Corsair Commander Core XT is the first device liquidctl finds. + cmd: + # The `setPwm` command is required. It receives a value from 0-255. + # We use a shell command to convert the 0-255 PWM value from fan2go + # into a 0-100 percentage for liquidctl. + setPwm: + exec: "/run/current-system/sw/bin/bash" + args: ["-c", "percent=$((%pwm% * 100 / 255)); /run/current-system/sw/bin/liquidctl set fan1 speed $percent"] + # The `getPwm` command is optional but good practice. + # It should return a value from 0-255. + getPwm: + exec: "/run/current-system/sw/bin/bash" + args: ["-c", "percent=$(/run/current-system/sw/bin/liquidctl status --json | ${pkgs.jq}/bin/jq '.[0].status[] | select(.key == \"Fan speed 1\").value | tonumber'); echo $((percent * 255 / 100))"] + # Fan speed is a percentage for liquidctl + min: 20 + max: 100 + # Ensures the fan never fully stops, maintaining minimum airflow. + neverStop: true + # The curve ID that should be used to determine the speed of this fan. + curve: gpu_cooling_curve + +sensors: + # Define the temperature sensor to monitor. This is the Radeon Pro VII/MI50. + # From `fan2go detect`, this is platform `amdgpu-pci-04400`. + # The sensor type is `hwmon`. + - id: gpu_mi50_temp + hwmon: + platform: amdgpu-pci-04400 + # Use the junction temperature (temp2_input) as it's a good indicator of core heat. + index: 2 + +curves: + # Link the GPU temperature to the case fan speed. + - id: gpu_cooling_curve + # Use a linear interpolation curve based on the defined points. + linear: + # The sensor ID to use as a temperature input for this curve. + sensor: gpu_mi50_temp + # Define the temperature-to-fan-speed mapping. + # Temps are in Celsius, fan speed is in percent. + points: + - [40, 20] # At 40°C, run fan at 20% + - [50, 40] # At 50°C, run fan at 40% + - [60, 60] # At 60°C, run fan at 60% + - [70, 80] # At 70°C, run fan at 80% + - [80, 100] # At 80°C and above, run fan at 100% + +statistics: + # Whether to enable the prometheus exporter or not + enabled: true + # The port to expose the exporter on + port: 9900 + diff --git a/desktop/l/fan2go_readme.md b/desktop/l/fan2go_readme.md new file mode 100644 index 0000000..f1ce69e --- /dev/null +++ b/desktop/l/fan2go_readme.md @@ -0,0 +1,865 @@ +

+ fan2go icon +
+ fan2go +
+

+ +

A daemon to control the fans of your computer.

+ +
+ +[![Programming Language](https://img.shields.io/badge/Go-00ADD8?logo=go&logoColor=white)]() +[![Latest Release](https://img.shields.io/github/release/markusressel/fan2go.svg)](https://github.com/markusressel/fan2go/releases) +[![License](https://img.shields.io/badge/license-AGPLv3-blue.svg)](/LICENSE) + +
+ +

Screenshot of Pyrra

+ +# Features + +* [x] Intuitive YAML based configuration +* [x] Massive range of supported devices + * [x] lm-sensors (hwmon) based sensors and fans + * [x] Fans and temperature sensor on NVIDIA GPUs ([nvml](https://developer.nvidia.com/management-library-nvml)) + * [x] File based fan/sensor for control/measurement of custom devices + * [x] Command based fan/sensor +* [x] Per fan user-defined speed curves +* [x] Fully customizable and composable curve definitions +* [x] Works after resume from suspend +* [x] **Stable** device paths after reboot +* [x] Automatic analysis of fan properties, like: + * [x] RPM curve + * [x] minimum and maximum PWM +* [x] Error notifications +* [x] Prometheus exporter +* [x] (optional) REST Api + +# UI + +fan2go is first and foremost a daemon that runs in the background. However, it also provides +a small set of CLI commands (see [CLI Commands](#cli-commands)) as well as an optional local HTTP API to allow +external programs to interact with it. This API can be used to create UI clients or other tools. + +## UI Clients + +[fan2go-tui](https://github.com/markusressel/fan2go-tui) - (Official) Terminal UI for fan2go. + +[![asciicast](https://asciinema.org/a/612087.svg)](https://asciinema.org/a/612087) + +# How to use + +fan2go relies on [lm-sensors](https://github.com/lm-sensors/lm-sensors) to get both temperature and RPM sensor readings, +as well as PWM controls, so you will have +to [set it up first](https://wiki.archlinux.org/index.php/Lm_sensors#Installation). + +## Installation + +### Arch Linux ![](https://img.shields.io/badge/Arch_Linux-1793D1?logo=arch-linux&logoColor=white) + +```shell +yay -S fan2go-git +``` + +
+Community Maintained Packages + +### Nix OS ![](https://img.shields.io/badge/nixpkgs-5277C3?logo=nixos&logoColor=white) + +- Nix with [Flakes](https://nixos.wiki/wiki/Flakes): + +```shell +nix profile install nixpkgs#fan2go +``` + +- Nix stable: + +```shell +nix-env -f '' -iA fan2go +``` + +### Debian + +See: https://github.com/johnwbyrd/fan2go-package/ + +
+ +### Manual + +Download the latest release from GitHub: + +```shell +# Install dependencies +sudo pacman -S libnotify + +curl -L -o fan2go https://github.com/markusressel/fan2go/releases/latest/download/fan2go-linux-amd64 +chmod +x fan2go +sudo cp ./fan2go /usr/bin/fan2go +fan2go -h +``` + +Or compile yourself: + +```shell +git clone https://github.com/markusressel/fan2go.git +cd fan2go +make build +sudo cp ./bin/fan2go /usr/bin/fan2go +sudo chmod ug+x /usr/bin/fan2go +``` + +## Configuration + +Then configure fan2go by creating a YAML configuration file in **one** of the following locations: + +* `/etc/fan2go/fan2go.yaml` (recommended) +* `/root/.fan2go/fan2go.yaml` +* `./fan2go.yaml` + +```shell +sudo mkdir /etc/fan2go +sudo nano /etc/fan2go/fan2go.yaml +``` + +The most important configuration options you need to define are the `fans:`, `sensors:` and `curves:` sections. + +### Fans + +Under `fans:` you need to define a list of fan devices that you want to control using fan2go. To detect fans on your +system run `fan2go detect`, which will print a list of devices exposed by the hwmon filesystem backend: + +```shell +$ fan2go detect +=========== hwmon: ============ + +> Platform: nct6798-isa-0290 + Fans Index Channel Label RPM PWM Mode + 1 1 hwmon4/fan1 0 153 Manual + 2 2 hwmon4/fan2 1223 104 Manual + 3 3 hwmon4/fan3 677 107 Manual + Sensors Index Label Value + 1 SYSTIN 41000 + 2 CPUTIN 64000 + +> Platform: amdgpu-pci-0031 + Fans Index Channel Label RPM PWM Mode + 1 1 hwmon8/fan1 561 43 Manual + Sensors Index Label Value + 1 edge 58000 + 2 junction 61000 + 3 mem 56000 + +=========== nvidia: =========== + +> Device: nvidia-10DE2489-0800 + Fans Index Label PWM RPM Mode + 1 Fan 1 36 1300 Auto + 2 Fan 2 36 1298 Auto + Sensors Index Label Value + 1 Temperature 59000 +``` + +The `hwmon` fan index is based on device enumeration and is not stable for a given fan if hardware configuration +changes. +The Linux kernel hwmon channel is a better identifier for configuration as it is largely based on the fan headers +in use. + +Fan RPM, PWM, and temperature sensors are independent and Linux does not associate them automatically. A given PWM +may control more than one fan, and a fan may not be under the control of a PWM. By default, fan2go guesses and sets +the pwm channel number for a given fan to the fan's RPM sensor channel. You can override this in the config. + +For `nvidia` devices, the fan index *is* stable. + +Note that it can happen that the hardware only gives limited control over a fan and it, for example, +always runs with at least 30% speed - even if in automatic mode the hardware may make it stop entirely +if the temperature is low enough. + +#### HwMon + +To use detected hwmon devices in your configuration, use the `hwmon` fan type: + +```yaml +# A list of fans to control +fans: + # A user defined ID. + # Used for logging only + - id: cpu + # The type of fan configuration, one of: hwmon | file + hwmon: + # A regex matching a controller platform displayed by `fan2go detect`, f.ex.: + # "nouveau", "coretemp", "it8620", "corsaircpro-.*" etc. + platform: nct6798 + # The channel of this fan's RPM sensor as displayed by `fan2go detect` + rpmChannel: 1 + # The pwm channel that controls this fan; fan2go defaults to same channel number as fan RPM + pwmChannel: 1 + # Indicates whether this fan should never stop rotating, regardless of + # how low the curve value is + neverStop: true + # The curve ID that should be used to determine the + # speed of this fan + curve: cpu_curve +``` + +#### NVIDIA + +To use detected NVIDIA GPUs in your configuration, use the `nvidia` fan type: + +```yaml +fans: + - id: gpufan1 + nvidia: + # A regex matching a nvidia device as displayed by `fan2go detect` + # the following matches all nvidia devices in your system + # (good enough if you only have one), otherwise you could + # also use nvidia-10DE2489-0800 or similar + device: nvidia + # The fan's index as shown by `fan2go detect` + index: 1 + curve: gpu_curve + + # same for the second fan + - id: gpufan2 + nvidia: + device: nvidia + index: 2 + curve: gpu_curve +``` + +Note that the fan speed can only be controlled for GPUs of the "Maxwell" generation +(Geforce 9xx) and newer, and that reading the fan speed in RPM requires nvidia driver 565 +or newer. + +#### File + +```yaml +fans: + - id: file_fan + file: + # Path to a file to get/set the PWM target for this fan + path: /tmp/file_fan + # Path to a file to read the current RPM value of this fan + rpmPath: /tmp/file_fan_rpm +``` + +```shell +> cat /tmp/file_fan +255 +> cat /tmp/file_fan_rpm +3421 +``` + +#### CMD + +Please also make sure to read the section about +[considerations for using the cmd sensor/fan](#using-external-commands-for-sensorsfans). + +```yaml +fans: + - id: cmd_fan + cmd: + # Command to apply a new PWM value (0..255) + # Use "%pwm%" to specify where the target pwm value should be used within the arguments + setPwm: + exec: /usr/bin/some-program + args: [ "--set", "%pwm%" ] + # Command to retrieve the current PWM value (0..255) + getPwm: + exec: /usr/bin/nvidia-settings + args: [ "-a", "someargument" ] + # (optional) Command to retrieve the current RPM value + getRpm: + exec: /usr/bin/nvidia-settings + args: [ "-a", "someargument" ] +``` + +#### Advanced Options + +If the automatic fan curve analysis doesn't provide a good enough estimation +for how the fan behaves, you can use the following configuration options (per fan definition) +to correct it: + +```yaml +fans: + - id: ... + ... + # (Optional) Override for the lowest PWM value at which the + # fan is able to maintain rotation if it was spinning previously. + minPwm: 30 + # (Optional) Override for the lowest PWM value at which the + # fan will still be able to start rotating. + # Note: Settings this to a value that is too small + # may damage your fans. Use at your own risk! + startPwm: 30 + # (Optional) Override for the highest PWM value which still yields + # an increased rotational speed compared to lower values. + # Note: you can also use this to limit the max speed of a fan. + maxPwm: 255 + # (Optional) Override for the PWM map used by fan2go for + # mapping the expected [0..255] value range to values actually supported by this fan. + # This can be used to compensate for fans with a very limited set of supported values + # (f.ex. off, low, high). If not set manually, fan2go will try to compute this mapping + # automatically during fan initialization. This process is not perfect though and may + # result in suboptimal fan control. + # Note: The values of the mapping must be strictly monotonically increasing. The Key-Set must + # be in [0..255] but may omit values. If keys are missing, fan2go will select a key that most + # closely matches the required target value (computed by the referenced curve) during operation. + pwmMap: + 0: 0 + 64: 128 + 192: 255 + # (Optional) Configuration options for sanity checks + sanityCheck: + # (Optional) Control the behavior of the "pwmValueChangedByThirdParty" sanity check + # This check is used to detect if the PWM value of a fan has changed between two consecutive + # control loop cycles, which is usually an indication that an external program is trying to control the fan + # at the same time as fan2go. This can lead to unexpected behavior and is usually not desired, so + # fan2go will log a warning if this happens. + pwmValueChangedByThirdParty: + # (Optional) Whether to enable this check or not + enabled: true +``` + +### Sensors + +Under `sensors:` you need to define a list of temperature sensor devices that you want to monitor and use to adjust +fanspeeds. Like with fans, you can find usable devices using `fan2go detect`. + +#### HwMon + +```yaml +# A list of sensors to monitor +sensors: + # A user defined ID, which is used to reference + # a sensor in a curve configuration (see below) + - id: cpu_package + # The type of sensor configuration, one of: hwmon | nvidia | file | cmd + hwmon: + # A regex matching a controller platform displayed by `fan2go detect`, f.ex.: + # "coretemp", "it8620", "corsaircpro-*" etc. + platform: coretemp + # The index of this sensor as displayed by `fan2go detect` + index: 1 +``` + +#### NVIDIA + +```yaml +sensors: + - id: gpu_temp + nvidia: + # A regex matching a nvidia device as displayed by `fan2go detect` + device: nvidia-10DE2489-0800 + # The index of this sensor as displayed by `fan2go detect` + # (currently NVIDIA/nvml exposes only a single temperature sensor per GPU) + index: 1 +``` + +#### File + +```yaml +sensors: + - id: file_sensor + file: + # Path to the file containing sensor values + path: /tmp/file_sensor +``` + +The file contains a value in milli-units, like f.ex. milli-degrees. + +```bash +> cat /tmp/file_sensor +10000 +``` + +#### CMD + +Please also make sure to read the section about +[considerations for using the cmd sensor/fan](#using-external-commands-for-sensorsfans). + +Just like the `file` sensor, the command must output the sensor value in milli-units, +like f.ex. milli-degrees. + +```yaml +sensors: + - id: cmd_fan + cmd: + # Path to the executable to run to retrieve the current sensor value + exec: /usr/bin/bash + # (optional) arguments to pass to the executable + args: [ '/home/markus/myscript.sh' ] +``` + +### Curves + +Under `curves:` you need to define a list of fan speed curves, which represent the speed of a fan based on one or more +temperature sensors. + +#### Linear + +To create a simple, linear speed curve, use a curve of type `linear`. + +This curve type can be used with a min/max sensor value, where the min temp will result in a curve value of `0` and the +max temp will result in a curve value of `255`: + +```yaml +curves: + - id: cpu_curve + # The type of the curve, one of: linear | function + linear: + # The sensor ID to use as a temperature input + sensor: cpu_package + # Sensor input value (in degrees Celsius) + # at which the curve is at minimum speed + min: 40 + # Sensor input value at which the curve is at maximum speed + max: 80 +``` + +You can also define the curve in multiple, linear sections using the `steps` parameter: + +```yaml +curves: + - id: cpu_curve + # The type of the curve + linear: + # The sensor ID to use as a temperature input + sensor: cpu_package + # Steps to define a section-wise defined speed curve function. + steps: + # Sensor value (in degrees Celsius) -> Speed (0-255) + - 40: 0 + - 50: 50 + - 80: 255 +``` + +#### PID + +If you want to get your hands dirty and use a PID based curve, you can use `pid`: + +```yaml +curves: + - id: pid_curve + pid: + sensor: cpu_package + setPoint: 60 + p: -0.05 + i: -0.005 + d: -0.005 +``` + +Unlike the other curve types, this one does not use the average of the sensor data +to calculate its value, which allows you to create a completely custom behaviour. +Keep in mind though that the fan controller may also be PID based (depending on the +specified `controlAlgorithm`) which would also affect how the curve is applied to the fan. + +See: [PID controller on Wikipedia](https://en.wikipedia.org/wiki/Proportional%E2%80%93integral%E2%80%93derivative_controller) +for more information on what a PID controller is. + +#### Function + +To create more complex curves you can combine existing curves using a curve of type `function`: + +```yaml +curves: + - id: case_avg_curve + function: + # Type of aggregation function to use, one of: minimum | maximum | average | delta | sum | difference + type: average + # A list of curve IDs to use + curves: + - cpu_curve + - mainboard_curve + - ssd_curve +``` + +### Example + +An example configuration file including more detailed documentation can be found in [fan2go.yaml](/fan2go.yaml). + +### Verify your Configuration + +To check whether your configuration is correct before actually running fan2go you can use: + +```shell +> sudo fan2go config validate + INFO Using configuration file at: /etc/fan2go/fan2go.yaml + SUCCESS Config looks good! :) +``` + +or to validate a specific config file: + +```shell +> fan2go -c "./my_config.yaml" config validate + INFO Using configuration file at: ./my_config.yaml + WARNING Unused curve configuration: m2_first_ssd_curve + ERROR Validation failed: Curve m2_ssd_curve: no curve definition with id 'm2_first_ssd_curve123' found +``` + +## Using external commands for sensors/fans + +fan2go supports using external executables for use as both sensor input, as well as fan output (and rpm input). There +are some considerations you should take into account before using this feature though: + +### Security + +Since fan2go requires root permissions to interact with lm-sensors, executables run by fan2go are also executed as root. +To prevent some malicious actor from taking advantage of this fan2go will only allow the execution of files that only +allow the root user (UID 0) to modify the file. + +### Side effects + +Running external commands repeatedly through fan2go can have unintended side effects. F.ex., on a laptop using hybrid +graphics, running `nvidia-settings` can cause the dedicated GPU to wake up, resulting in substantial increase in power +consumption while on battery. Also, fan2go expects to be able to update sensor values with a minimal delay, so using a +long running script or some network call with a long timeout could also cause problems. With great power comes great +responsibility, always remember that :) + +## Run + +After successfully verifying your configuration you can launch fan2go from the CLI and make sure the initial setup is +working as expected. Assuming you put your configuration file in `/etc/fan2go/fan2go.yaml` run: + +```shell +> fan2go help +fan2go is a simple daemon that controls the fans +on your computer based on temperature sensors. + +Usage: + fan2go [flags] + fan2go [command] + +Available Commands: + completion Generate the autocompletion script for the specified shell + config Configuration related commands + curve Curve related commands + detect Detect fans and sensors + fan Fan related commands + help Help about any command + sensor Sensor related commands + version Print the version number of fan2go + +Flags: + -c, --config string config file (default is $HOME/.fan2go.yaml) + -h, --help help for fan2go + --no-color Disable all terminal output coloration + --no-style Disable all terminal output styling + -v, --verbose More verbose output + +Use "fan2go [command] --help" for more information about a command. +> sudo fan2go +``` + +Alternatively you can specify the path to your configuration file like this: + +```shell +> sudo fan2go -c /home/markus/my_fan2go_config.yaml +``` + +## As a Service + +### Systemd + +When installing fan2go using a package, it comes with a [systemd unit file](./fan2go.service). To enable it simply run: + +```shell +sudo systemctl daemon-reload +sudo systemctl enable --now fan2go +# follow logs +journalctl -u fan2go -f +``` + +> NOTE: If you want to use a config path that differs from the default one, make sure to edit the +> unit file and point the `-c` flag to the correct path. + +## CLI Commands + +Although fan2go is a fan controller daemon at heart, it also provides some handy cli commands to interact with the +devices that you have specified within your config. + +### Fans interaction + +```shell +> fan2go fan --id cpu speed 100 + +> fan2go fan --id cpu speed +255 + +> fan2go fan --id cpu rpm +546 + +> fan2go fan --id cpu mode +No control, 100% all the time (0) + +> fan2go fan --id cpu mode auto +Automatic control by integrated hardware (2) +``` + +### Sensors + +```shell +> fan2go sensor --id cpu_package +46000 +``` + +### Print fan curve data + +For each newly configured fan **fan2go** measures its fan curve and stores it in a db for future reference. You can take +a look at this measurement using the following command: + +```shell +> sudo fan2go fan --id cpu curve +cpu + + Min PWM 30 + Start PWM 30 + Max PWM 255 + +No fan curve data yet... + +> sudo fan2go fan --id in_front curve +nct6798 -> pwm2 + + Min PWM 0 + Start PWM 0 + Max PWM 194 + + 1994 ┤ ╭──────────────────────── + 1900 ┤ ╭──╯ + 1805 ┤ ╭────╯ + 1711 ┤ ╭────╯ + 1616 ┤ ╭────╯ + 1522 ┤ ╭───╯ + 1427 ┤ ╭────╯ + 1333 ┤ ╭────╯ + 1238 ┤ ╭─────╯ + 1144 ┤ ╭────╯ + 1049 ┤ ╭─────╯ + 955 ┤ ╭─────╯ + 860 ┤ ╭─────╯ + 766 ┤ ╭─────╯ + 671 ┤ ╭─────╯ + 577 ┼─╯ + RPM / PWM +``` + +## Statistics + +fan2go has a prometheus exporter built in, which you can use to extract data over time. Simply enable it in your +configuration and you are good to go: + +```yaml +statistics: + # Whether to enable the prometheus exporter or not + enabled: true + # The port to expose the exporter on + port: 9000 +``` + +You can then see the metrics on [http://localhost:9000/metrics](http://localhost:9000/metrics) while the fan2go daemon +is +running. + +## API + +fan2go comes with a built-in REST Api. This API can be used by third party tools to display (and in the future possibly +modify) the state of fans, sensors and curves within fan2go. + +```yaml +api: + # Whether to enable the API or not + enabled: false + # The host to listen for connections + host: localhost + # The port to listen for connections + port: 9001 +``` + +### Endpoints + +Currently, this API is read-only and only provides REST endpoints. If there is demand for it, this might be expanded to +also support realtime +communication via websockets. + +#### Fans + +| Endpoint | Type | Description | +|-------------|------|---------------------------------------------------| +| `/fan` | GET | Returns a list of all currently configured fans | +| `/fan/` | GET | Returns the fan with the given `id`, if it exists | + +#### Sensors + +| Endpoint | Type | Description | +|----------------|------|------------------------------------------------------| +| `/sensor` | GET | Returns a list of all currently configured sensors | +| `/sensor/` | GET | Returns the sensor with the given `id`, if it exists | + +#### Curves + +| Endpoint | Type | Description | +|---------------|------|-----------------------------------------------------| +| `/curve` | GET | Returns a list of all currently configured curves | +| `/curve/` | GET | Returns the curve with the given `id`, if it exists | + +# How it works + +## Device detection + +fan2go uses [gosensors](https://github.com/md14454/gosensors) to directly interact with lm-sensors. + +## Initialization + +To properly control a fan which fan2go has not seen before, its speed curve is analyzed. This means + +* spinning down the fans to 0 +* slowly ramping up the speed and monitoring RPM changes along the way + +**Note that this takes approx. 8 1/2 minutes**, since we have to wait for the fan speed to settle before taking +measurements. Measurements taken during this process will then be used to determine the lowest PWM value at which the +fan is still running, as well as the highest PWM value that still yields a change in RPM. + +All of this is saved to a local database (path given by the `dbPath` config option), so it is only needed once per fan +configuration. + +To reduce the risk of running the whole system on low fan speeds for such a long period of time, you can force fan2go to +initialize only one fan at a time, using the `runFanInitializationInParallel: false` config option. + +Some PWM controllers or fans may require more time to react to PWM changes. If fan2go is failing to characterize a fan, +you can try increasing the fan response delay by passing `--fan-response-delay ` to the `fan init` command or +by setting `fanResponseDelay` in the config. The default value is 2 seconds. + +## Monitoring + +Temperature and RPM sensors are polled continuously at the rate specified by the `tempSensorPollingRate` config option. +`tempRollingWindowSize`/`rpmRollingWindowSize` amount of measurements are always averaged and stored as the average +sensor value. + +## Fan Controllers + +The speed of a Fan is controlled using a combination of its curve, a control algorithm and the properties of +the fan controller itself. + +The curve is used as the target value for the control algorithm to reach. The control algorithm then calculates the +next PWM value to apply to the fan to reach this target value. The fan controller then applies this PWM value to the +fan, while respecting constraints like the minimum and maximum PWM values, as well as the `neverStop` flag. + +### Control Algorithms + +A control algorithm +is a function that returns the next PWM value to apply based on the target value calculated by the curve. The simplest +control algorithm is the direct control algorithm, which simply forwards the target value to the fan. + +#### Direct Control Algorithm + +The simplest control algorithm is the direct control algorithm. It simply forwards the curve value to the fan +controller. + +```yaml +fans: + - id: some_fan + ... + controlAlgorithm: direct +``` + +This control algorithm can also be used to approach the curve value more slowly: + +```yaml +fans: + - id: some_fan + ... + controlAlgorithm: + direct: + maxPwmChangePerCycle: 10 +``` + +### PID Control Algorithm + +The PID control algorithm uses a PID loop to approach the target value. The default +configuration is pretty non-aggressive using the following values: + +| P | I | D | +|-------|--------|---------| +| `0.3` | `0.02` | `0.005` | + +If you don't like the default behaviour you can configure your own in the config: + +```yaml +fans: + - id: some_fan + ... + controlAlgorithm: + pid: + p: 0.3 + i: 0.02 + d: 0.005 +``` + +The loop is advanced at a constant rate, specified by the `controllerAdjustmentTickRate` config option, which +defaults to `200ms`. + +See [PID controller on Wikipedia](https://en.wikipedia.org/wiki/Proportional%E2%80%93integral%E2%80%93derivative_controller) +for more information on what a PID controller is. + +# FAQ + +## Why are my SATA HDD drives not detected? + +**TL;DR**: `modprobe drivetemp` + +While _lm-sensors_ doesn't provide temperature sensors of SATA drives by default, you can use the kernel module +`drivetemp` to enable this. See [here](https://wiki.archlinux.org/title/Lm_sensors#S.M.A.R.T._drive_temperature) + +## WARNING: PWM of `` was changed by third party! + +If you see this log message while running fan2go, fan2go detected a change of the PWM value for the given fan +that was not caused by fan2go itself. This usually means that fan2go is not the only program controlling the fan +and something else (like f.ex. the mainboard or another fan control software) is also running and changing the speed +of the fan, competing with fan2go. Since fan2go cannot figure out what other software is, you have to investigate +this yourself. + +Another common reason this message can occur is when the driver of the fan in question does not actually support +setting the PWM directly and uses some kind of virtual PWM instead. This has been a problem mostly on AMD graphics +cards but is probably not limited to them. See #64 for more detail. + +If you are sure that this warning is not justified, you can disable this check on a per-fan basis. +See the `sanityCheck` section in the [fan configuration](#advanced-options) for more details. + +## My components are overheating during initialization, what can I do about this? + +**TL;DR**: Skip the initialization and configure your fans manually. + +The initialization phase measures the RPM curve of each fan and tries to estimate the minimum and maximum +boundaries. This can take quite a while though and can lead to overheating of components if they are +under load. To avoid this use the `minPwm` and `maxPwm` fan config options to set the boundaries yourself. +That way the initialization phase will be skipped and the control algorithm will start right away. + +# Dependencies + +See [go.mod](go.mod) + +# Similar Projects + +* [nbfc-linux](https://github.com/nbfc-linux/nbfc-linux) +* [thinkfan](https://github.com/vmatare/thinkfan) + +# License + +``` +fan2go +Copyright (C) 2021 Markus Ressel + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +``` diff --git a/desktop/l/gpu_info.md b/desktop/l/gpu_info.md new file mode 100644 index 0000000..fb681cd --- /dev/null +++ b/desktop/l/gpu_info.md @@ -0,0 +1,457 @@ +The system has x2 GPUs: +- [Radeon Pro W5700] which has temperature sensors and an attached PWM fan. The pid-fan-controller service is suitable for controlling this fan. +- [Radeon Pro VII/Radeon Instinct MI50 32GB] which has temperature sensors, but NO FAN. Need to control the Corsair Commander Core Fan 1 to cool down this card. The challenge is that liquidctl is required to set the fan speed, so pid-fan-controller service won't work. Going to need to creata a fan2go configuration file for this. + +I want to use the NixOS services pid-fan-controller to control the fan for Radeon Pro W5700. + +https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/services/hardware/pid-fan-controller.nix +``` +{ + lib, + config, + pkgs, + ... +}: +let + cfg = config.services.pid-fan-controller; + heatSource = { + options = { + name = lib.mkOption { + type = lib.types.uniq lib.types.nonEmptyStr; + description = "Name of the heat source."; + }; + wildcardPath = lib.mkOption { + type = lib.types.nonEmptyStr; + description = '' + Path of the heat source's `hwmon` `temp_input` file. + This path can contain multiple wildcards, but has to resolve to + exactly one result. + ''; + }; + pidParams = { + setPoint = lib.mkOption { + type = lib.types.ints.unsigned; + description = "Set point of the controller in °C."; + }; + P = lib.mkOption { + description = "K_p of PID controller."; + type = lib.types.float; + }; + I = lib.mkOption { + description = "K_i of PID controller."; + type = lib.types.float; + }; + D = lib.mkOption { + description = "K_d of PID controller."; + type = lib.types.float; + }; + }; + }; + }; + + fan = { + options = { + wildcardPath = lib.mkOption { + type = lib.types.str; + description = '' + Wildcard path of the `hwmon` `pwm` file. + If the fans are not to be found in `/sys/class/hwmon/hwmon*` the corresponding + kernel module (like `nct6775`) needs to be added to `boot.kernelModules`. + See the [`hwmon` Documentation](https://www.kernel.org/doc/html/latest/hwmon/index.html). + ''; + }; + minPwm = lib.mkOption { + default = 0; + type = lib.types.ints.u8; + description = "Minimum PWM value."; + }; + maxPwm = lib.mkOption { + default = 255; + type = lib.types.ints.u8; + description = "Maximum PWM value."; + }; + cutoff = lib.mkOption { + default = false; + type = lib.types.bool; + description = "Whether to stop the fan when `minPwm` is reached."; + }; + heatPressureSrcs = lib.mkOption { + type = lib.types.nonEmptyListOf lib.types.str; + description = "Heat pressure sources affected by the fan."; + }; + }; + }; +in +{ + options.services.pid-fan-controller = { + enable = lib.mkEnableOption "the PID fan controller, which controls the configured fans by running a closed-loop PID control loop"; + package = lib.mkPackageOption pkgs "pid-fan-controller" { }; + settings = { + interval = lib.mkOption { + default = 500; + type = lib.types.int; + description = "Interval between controller cycles in milliseconds."; + }; + heatSources = lib.mkOption { + type = lib.types.listOf (lib.types.submodule heatSource); + description = "List of heat sources to be monitored."; + example = '' + [ + { + name = "cpu"; + wildcardPath = "/sys/devices/pci0000:00/0000:00:18.3/hwmon/hwmon*/temp1_input"; + pidParams = { + setPoint = 60; + P = -5.0e-3; + I = -2.0e-3; + D = -6.0e-3; + }; + } + ]; + ''; + }; + fans = lib.mkOption { + type = lib.types.listOf (lib.types.submodule fan); + description = "List of fans to be controlled."; + example = '' + [ + { + wildcardPath = "/sys/devices/platform/nct6775.2592/hwmon/hwmon*/pwm1"; + minPwm = 60; + maxPwm = 255; + heatPressureSrcs = [ + "cpu" + "gpu" + ]; + } + ]; + ''; + }; + }; + }; + config = lib.mkIf cfg.enable { + #map camel cased attrs into snake case for config + environment.etc."pid-fan-settings.json".text = builtins.toJSON { + interval = cfg.settings.interval; + heat_srcs = map (heatSrc: { + name = heatSrc.name; + wildcard_path = heatSrc.wildcardPath; + PID_params = { + set_point = heatSrc.pidParams.setPoint; + P = heatSrc.pidParams.P; + I = heatSrc.pidParams.I; + D = heatSrc.pidParams.D; + }; + }) cfg.settings.heatSources; + fans = map (fan: { + wildcard_path = fan.wildcardPath; + min_pwm = fan.minPwm; + max_pwm = fan.maxPwm; + cutoff = fan.cutoff; + heat_pressure_srcs = fan.heatPressureSrcs; + }) cfg.settings.fans; + }; + + systemd.services.pid-fan-controller = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "simple"; + ExecStart = [ (lib.getExe cfg.package) ]; + ExecStopPost = [ "${lib.getExe cfg.package} disable" ]; + Restart = "always"; + #This service needs to run as root to write to /sys. + #therefore it should operate with the least amount of privileges needed + ProtectHome = "yes"; + #strict is not possible as it needs /sys + ProtectSystem = "full"; + ProtectProc = "invisible"; + PrivateNetwork = "yes"; + NoNewPrivileges = "yes"; + MemoryDenyWriteExecute = "yes"; + RestrictNamespaces = "~user pid net uts mnt"; + ProtectKernelModules = "yes"; + RestrictRealtime = "yes"; + SystemCallFilter = "@system-service"; + CapabilityBoundingSet = "~CAP_KILL CAP_WAKE_ALARM CAP_IPC_LOC CAP_BPF CAP_LINUX_IMMUTABLE CAP_BLOCK_SUSPEND CAP_MKNOD"; + }; + # restart unit if config changed + restartTriggers = [ config.environment.etc."pid-fan-settings.json".source ]; + }; + #sleep hook to restart the service as it breaks otherwise + systemd.services.pid-fan-controller-sleep = { + before = [ "sleep.target" ]; + wantedBy = [ "sleep.target" ]; + unitConfig = { + StopWhenUnneeded = "yes"; + }; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = [ "systemctl stop pid-fan-controller.service" ]; + ExecStop = [ "systemctl restart pid-fan-controller.service" ]; + }; + }; + }; + meta.maintainers = with lib.maintainers; [ zimward ]; +} +``` + + +``` +[das@l:~/nixos]$ lspci | grep -i radeon +44:00.0 Display controller: Advanced Micro Devices, Inc. [AMD/ATI] Vega 20 [Radeon Pro VII/Radeon Instinct MI50 32GB] +63:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Navi 10 [Radeon Pro W5700] + +[das@l:~/nixos]$ +``` + +``` +[das@l:~/nixos]$ rocm-smi + + +=========================================== ROCm System Management Interface =========================================== +===================================================== Concise Info ===================================================== +Device Node IDs Temp Power Partitions SCLK MCLK Fan Perf PwrCap VRAM% GPU% + (DID, GUID) (Edge) (Socket) (Mem, Compute, ID) +======================================================================================================================== +0 2 0x66a1, 33678 39.0°C 19.0W N/A, N/A, 0 938Mhz 350Mhz 14.51% auto 225.0W 0% 0% +1 1 0x7312, 11012 48.0°C 36.0W N/A, N/A, 0 800Mhz 900Mhz 40.0% auto 140.0W 36% 4% +======================================================================================================================== +================================================= End of ROCm SMI Log ================================================== + +[das@l:~/nixos]$ +``` + +rocm-smi --alldevices --showallinfo + + +``` +[das@l:~/nixos]$ rocm-smi --alldevices --showallinfo 2>&1 | grep -E '(Device|ID)' +=========================================== ID =========================================== +GPU[0] : Device Name: TBD VEGA20 CARD +GPU[0] : Device ID: 0x66a1 +GPU[0] : Device Rev: 0x00 +GPU[0] : Subsystem ID: 0x1002 +GPU[0] : GUID: 33678 +GPU[1] : Device Name: 0x1002 +GPU[1] : Device ID: 0x7312 +GPU[1] : Device Rev: 0x00 +GPU[1] : Subsystem ID: 0x1002 +GPU[1] : GUID: 11012 +======================================= Unique ID ======================================== +GPU[0] : Unique ID: 0xe54792172da5eeb +GPU[1] : Unique ID: N/A +GPU[0] : 2. Available power profile (#2 of 7): VIDEO +GPU[1] : 2. Available power profile (#2 of 7): VIDEO +PID PROCESS NAME GPU(s) VRAM USED SDMA USED CU OCCUPANCY +================================== GPUs Indexed by PID =================================== +PID 2210 is using 0 DRM device(s) +======================================= PCI Bus ID ======================================= +GPU[0] : Subsystem ID: 0x1002 +GPU[0] : Device Rev: 0x00 +GPU[0] : Node ID: 2 +GPU[0] : GUID: 33678 +GPU[1] : Subsystem ID: 0x1002 +GPU[1] : Device Rev: 0x00 +GPU[1] : Node ID: 1 +GPU[1] : GUID: 11012 + +[das@l:~/nixos]$ +``` + +``` +[das@l:~/nixos]$ rocm-smi --showtemp --showfan + + +============================ ROCm System Management Interface ============================ +====================================== Temperature ======================================= +GPU[0] : Temperature (Sensor edge) (C): 39.0 +GPU[0] : Temperature (Sensor junction) (C): 40.0 +GPU[0] : Temperature (Sensor memory) (C): 38.0 +GPU[1] : Temperature (Sensor edge) (C): 47.0 +GPU[1] : Temperature (Sensor junction) (C): 50.0 +GPU[1] : Temperature (Sensor memory) (C): 62.0 +========================================================================================== +=================================== Current Fan Metric =================================== +GPU[0] : Fan Level: 37 (15%) +GPU[0] : Fan RPM: 0 +GPU[1] : Fan Level: 102 (40%) +GPU[1] : Fan RPM: 2380 +========================================================================================== +================================== End of ROCm SMI Log =================================== + +[das@l:~/nixos]$ +``` + +``` +[das@l:~/nixos]$ for x in /sys/class/hwmon/hwmon*; do + echo "$x: $(cat $x/name 2>/dev/null)" +done +/sys/class/hwmon/hwmon0: amdgpu +/sys/class/hwmon/hwmon1: amdgpu +/sys/class/hwmon/hwmon10: hidpp_battery_3 +/sys/class/hwmon/hwmon2: nvme +/sys/class/hwmon/hwmon3: nvme +/sys/class/hwmon/hwmon4: bnxt_en +/sys/class/hwmon/hwmon5: bnxt_en +/sys/class/hwmon/hwmon6: k10temp +/sys/class/hwmon/hwmon7: ucsi_source_psy_18_00081 +/sys/class/hwmon/hwmon8: ucsi_source_psy_18_00082 +/sys/class/hwmon/hwmon9: enp1s0 + +[das@l:~/nixos]$ +``` + + +MI50 card +``` +[das@l:~/nixos]$ cat /sys/class/hwmon/hwmon1/device/device +0x66a1 +``` + + +``` +[das@l:~/nixos]$ cat /sys/class/hwmon/hwmon0/device/device +0x7312 + +[das@l:~/nixos]$ +``` + +``` +[das@l:~/nixos]$ sudo liquidctl status +[sudo] password for das: +Corsair Commander Core XT (broken) +├── Fan speed 1 4427 rpm +├── Fan speed 2 0 rpm +├── Fan speed 3 0 rpm +├── Fan speed 4 0 rpm +├── Fan speed 5 0 rpm +└── Fan speed 6 0 rpm + + +[das@l:~/nixos]$ +``` + +Fan2go can be used to read the temperature from the MI50 card, and then use liquidctl to set the fan1 speed based on the temperature for the GPU. + +``` +[das@l:~/nixos]$ sudo liquidctl list +[sudo] password for das: +Device #0: Corsair Commander Core XT (broken) +``` + +``` +[das@l:~/nixos]$ lsusb | grep -i corsair +Bus 007 Device 004: ID 1b1c:0c2a Corsair CORSAIR iCUE COMMANDER CORE XT + +[das@l:~/nixos]$ +``` + +``` +[das@l:~/nixos]$ sudo liquidctl status | grep "Fan speed 1" +sudo liquidctl set fan1 speed 30 +├── Fan speed 1 4314 rpm + +[das@l:~/nixos]$ sudo liquidctl set fan1 speed 30 + +[das@l:~/nixos]$ sudo liquidctl status | grep "Fan speed 1" +├── Fan speed 1 3938 rpm + +[das@l:~/nixos]$ sudo liquidctl set fan1 speed 10 + +[das@l:~/nixos]$ +``` + + +``` +[nix-shell:~/nixos]$ fan2go detect +=========== hwmon: ============ + +> Platform: k10temp-pci-00c3 + Sensors Index Label Value + 1 Tctl (temp1_input) 82000 + 2 Tccd3 (temp5_input) 70000 + 3 Tccd5 (temp7_input) 80500 + +> Platform: bnxt_en-pci-04100 + Sensors Index Label Value + 1 hwmon4/temp1 (temp1_input) 85000 + +> Platform: nvme-pci-02100 + Sensors Index Label Value + 1 Composite (temp1_input) 32850 + 2 Sensor 1 (temp2_input) 35850 + 3 Sensor 2 (temp3_input) 32850 + +> Platform: amdgpu-pci-06300 + Fans Index PWM Channel RPM Channel Label RPM PWM Mode + 1 1 1 hwmon0/fan1 2376 102 Manual + 2 1 N/A hwmon0/pwm1 N/A 102 Manual + Sensors Index Label Value + 1 edge (temp1_input) 48000 + 2 junction (temp2_input) 50000 + 3 mem (temp3_input) 62000 + +> Platform: enp1s0-pci-0100 + Sensors Index Label Value + 1 PHY Temperature (temp1_input) 69285 + 2 MAC Temperature (temp2_input) 70995 + +> Platform: bnxt_en-pci-04101 + Sensors Index Label Value + 1 hwmon5/temp1 (temp1_input) 85000 + +> Platform: nvme-pci-02200 + Sensors Index Label Value + 1 Composite (temp1_input) 33850 + 2 Sensor 1 (temp2_input) 34850 + 3 Sensor 2 (temp3_input) 33850 + +> Platform: amdgpu-pci-04400 + Fans Index PWM Channel RPM Channel Label RPM PWM Mode + 1 1 1 hwmon1/fan1 0 37 Manual + 2 1 N/A hwmon1/pwm1 N/A 37 Manual + Sensors Index Label Value + 1 edge (temp1_input) 45000 + 2 junction (temp2_input) 46000 + 3 mem (temp3_input) 44000 + + +[nix-shell:~/nixos]$ +``` + +Summary + +``` +Radeon Instinct MI50 32GB +PCIe = 44:00.0 +DID = 0x66a1 +GUID = 33678 +GPU = 0 +hwmon device = /sys/class/hwmon/hwmon1 +fan2go detect +> Platform: amdgpu-pci-04400 + Fans Index PWM Channel RPM Channel Label RPM PWM Mode + 1 1 1 hwmon1/fan1 0 37 Manual + 2 1 N/A hwmon1/pwm1 N/A 37 Manual + Sensors Index Label Value + 1 edge (temp1_input) 45000 + 2 junction (temp2_input) 46000 + 3 mem (temp3_input) 44000 + +Radeon Pro W5700 +PCIe = 63:00.0 +DID = 0x7312 +GUID = 11012 +GPU = 1 +hwmon device = /sys/class/hwmon/hwmon0 +fan2go detect +> Platform: amdgpu-pci-06300 + Fans Index PWM Channel RPM Channel Label RPM PWM Mode + 1 1 1 hwmon0/fan1 2376 102 Manual + 2 1 N/A hwmon0/pwm1 N/A 102 Manual + Sensors Index Label Value + 1 edge (temp1_input) 48000 + 2 junction (temp2_input) 50000 + 3 mem (temp3_input) 62000 +``` \ No newline at end of file diff --git a/desktop/l/hardware-configuration.nix b/desktop/l/hardware-configuration.nix index a2c85e2..72bf8fc 100644 --- a/desktop/l/hardware-configuration.nix +++ b/desktop/l/hardware-configuration.nix @@ -46,4 +46,7 @@ # hardware.decklink.enable = true; #https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/hardware/decklink.nix + + # see also fan2go.nix + hardware.fan2go.enable = true; } From 206845527108a03e462f4f2fc46869932fafe10b Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Wed, 15 Oct 2025 09:35:54 -0700 Subject: [PATCH 22/23] give up on fan2go with Corsair Commander Core XT --- desktop/l/fan2go.nix | 140 +++++++++++++++++-- desktop/l/fan2go.yml | 34 ++++- desktop/l/gpu_info.md | 196 +-------------------------- desktop/l/hardware-configuration.nix | 1 + desktop/l/systemPackages.nix | 1 + desktop/l/test_fan_commands.sh | 84 ++++++++++++ 6 files changed, 251 insertions(+), 205 deletions(-) create mode 100755 desktop/l/test_fan_commands.sh diff --git a/desktop/l/fan2go.nix b/desktop/l/fan2go.nix index cde21b8..3321002 100644 --- a/desktop/l/fan2go.nix +++ b/desktop/l/fan2go.nix @@ -1,11 +1,35 @@ # # fan2go.nix # +# Not controlling the Radeon Pro W5700, because lact is doing this +# The config controls the corsair fan1 based on the temperatur of the Radeon Pro VII/MI50 +# # sudo systemctl status fan2go +# sudo journalctl -u fan2go --follow # sudo ls /var/lib/fan2go # +# CLEAN IMPLEMENTATION: +# 1. setPwm: Converts 0-255 PWM to 0-100% for liquidctl +# 2. getPwm: Uses pure bash string manipulation to extract fan speed and convert to PWM (0-255) +# 3. getRpm: Uses pure bash string manipulation to extract RPM value for fan2go monitoring +# 4. No external tools (grep, awk, jq, sed) - pure bash string operations +# 5. Bash variables escaped with \$ to prevent Nix interpolation +# 6. Uses bash parameter expansion: ${var#pattern} and ${var%%pattern} +# 7. No temporary files or delays needed since fan2go is the only liquidctl user +# # See also: https://github.com/arnarg/config/blob/8de65cf5f1649a4fe6893102120ede4363de9bfa/hosts/terra/fan2go.nix # +# +# [das@l:~/nixos/desktop/l]$ sudo liquidctl status +# [sudo] password for das: +# Corsair Commander Core XT (broken) +# ├── Fan speed 1 1360 rpm +# ├── Fan speed 2 0 rpm +# ├── Fan speed 3 0 rpm +# ├── Fan speed 4 0 rpm +# ├── Fan speed 5 0 rpm +# └── Fan speed 6 0 rpm +# { lib, config, @@ -13,8 +37,59 @@ ... }: let + cfg = config.hardware.fan2go; + # Create the bash scripts for fan control + setPwmScript = pkgs.writeText "setPwm.bash" '' + #!${pkgs.bash}/bin/bash + # Convert fan2go PWM (0-255) to liquidctl percentage (0-100) + percent=$((%pwm% * 100 / 255)) + ${pkgs.liquidctl}/bin/liquidctl set fan1 speed $percent + ''; + + getPwmScript = pkgs.writeText "getPwm.bash" '' + #!${pkgs.bash}/bin/bash + # Get current fan RPM and convert to PWM value + output=$(${pkgs.liquidctl}/bin/liquidctl status 2>/dev/null) + if [[ $output =~ Fan\ speed\ 1[^0-9]+([0-9]+) ]]; then + rpm=${BASH_REMATCH[1]} + echo $((rpm * 255 / 2000)) + else + echo 0 + fi + ''; + + getRpmScript = pkgs.writeText "getRpm.bash" '' + #!${pkgs.bash}/bin/bash + # Get current fan RPM value + output=$(${pkgs.liquidctl}/bin/liquidctl status 2>/dev/null) + if [[ $output =~ Fan\ speed\ 1[^0-9]+([0-9]+) ]]; then + rpm=${BASH_REMATCH[1]} + echo $rpm + else + echo 0 + fi + ''; + + # Create a shellcheck validation script + shellcheckScript = pkgs.writeText "check-fan-scripts.sh" '' + #!${pkgs.bash}/bin/bash + # Shellcheck validation for fan control scripts + echo "Running shellcheck on fan control scripts..." + + echo "Checking setPwm script..." + ${pkgs.shellcheck}/bin/shellcheck ${setPwmScript} || exit 1 + + echo "Checking getPwm script..." + ${pkgs.shellcheck}/bin/shellcheck ${getPwmScript} || exit 1 + + echo "Checking getRpm script..." + ${pkgs.shellcheck}/bin/shellcheck ${getRpmScript} || exit 1 + + echo "All scripts passed shellcheck validation!" + ''; + fan2goConfig = pkgs.writeText "fan2go.yaml" '' # # fan2go.yaml @@ -32,21 +107,37 @@ let # We use a shell command to convert the 0-255 PWM value from fan2go # into a 0-100 percentage for liquidctl. setPwm: - exec: "/run/current-system/sw/bin/bash" - args: ["-c", "percent=$((%pwm% * 100 / 255)); /run/current-system/sw/bin/liquidctl set fan1 speed $percent"] - # The `getPwm` command is optional but good practice. - # It should return a value from 0-255. + exec: "${setPwmScript}" + # The `getPwm` command should return the current PWM value. + # Since liquidctl doesn't provide PWM directly, we convert from the RPM value. getPwm: - exec: "/run/current-system/sw/bin/bash" - args: ["-c", "percent=$(/run/current-system/sw/bin/liquidctl status --json | ${pkgs.jq}/bin/jq '.[0].status[] | select(.key == \"Fan speed 1\").value | tonumber'); echo $((percent * 255 / 100))"] + exec: "${getPwmScript}" + # The `getRpm` command gets the current RPM value from liquidctl. + # This helps fan2go understand the fan's current state. + getRpm: + exec: "${getRpmScript}" # Fan speed is a percentage for liquidctl - min: 20 + min: 10 max: 100 ## Ensures the fan never fully stops, maintaining minimum airflow. #neverStop: true # The curve ID that should be used to determine the speed of this fan. curve: gpu_cooling_curve + # # + # # Define the fan for the Radeon Pro W5700 (amdgpu-pci-06300). + # # This GPU has its own controllable fan via hwmon. + # - id: gpu_w5700_fan + # hwmon: + # # From `fan2go detect`, this is the platform for the W5700. + # platform: amdgpu-pci-06300 + # # The channel for the fan's RPM sensor. + # rpmChannel: 1 + # # The PWM channel that controls this fan's speed. + # pwmChannel: 1 + # neverStop: true + # curve: gpu_w5700_curve + sensors: # Define the temperature sensor to monitor. This is the Radeon Pro VII/MI50. # From `fan2go detect`, this is platform `amdgpu-pci-04400`. @@ -57,6 +148,15 @@ let # Use the junction temperature (temp2_input) as it's a good indicator of core heat. index: 2 + # # + # # Define the temperature sensor for the Radeon Pro W5700. + # - id: gpu_w5700_temp + # hwmon: + # # From `fan2go detect`, this is the platform for the W5700. + # platform: amdgpu-pci-06300 + # # Use the junction temperature (temp2_input). + # index: 2 + curves: # Link the GPU temperature to the case fan speed. - id: gpu_cooling_curve @@ -73,10 +173,23 @@ let - [70, 80] # At 70°C, run fan at 80% - [80, 100] # At 80°C and above, run fan at 100% + # # + # # Define the curve for the Radeon Pro W5700's own fan. + # - id: gpu_w5700_curve + # linear: + # # The sensor ID to use as a temperature input for this curve. + # sensor: gpu_w5700_temp + # # Define the temperature-to-PWM-value mapping. + # # Temps are in Celsius, output is a PWM value (0-255). + # points: + # - [45, 51] # At 45°C, run fan at ~20% (51/255) + # - [55, 102] # At 55°C, run fan at 40% + # - [65, 153] # At 65°C, run fan at 60% + # - [75, 204] # At 75°C, run fan at 80% + # - [85, 255] # At 85°C and above, run fan at 100% + statistics: - # Whether to enable the prometheus exporter or not enabled: true - # The port to expose the exporter on port: 9900 ''; in @@ -98,13 +211,22 @@ in after = [ "lm_sensors.service" ]; serviceConfig = { + ExecStartPre = "${shellcheckScript}"; ExecStart = lib.concatStringsSep " " [ "${pkgs.fan2go}/bin/fan2go" "-c" "${fan2goConfig}" "--no-style" ]; + + MemoryHigh = "48M"; + MemoryMax = "64M"; + CPUQuota = "50%"; + #RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; + #Delegate = false; + LimitNOFILE = 8192; + }; }; }; diff --git a/desktop/l/fan2go.yml b/desktop/l/fan2go.yml index 9f41e61..67414a0 100644 --- a/desktop/l/fan2go.yml +++ b/desktop/l/fan2go.yml @@ -26,6 +26,18 @@ fans: neverStop: true # The curve ID that should be used to determine the speed of this fan. curve: gpu_cooling_curve + # Define the fan for the Radeon Pro W5700 (amdgpu-pci-06300). + # This GPU has its own controllable fan via hwmon. + - id: gpu_w5700_fan + hwmon: + # From `fan2go detect`, this is the platform for the W5700. + platform: amdgpu-pci-06300 + # The channel for the fan's RPM sensor. + rpmChannel: 1 + # The PWM channel that controls this fan's speed. + pwmChannel: 1 + neverStop: true + curve: gpu_w5700_curve sensors: # Define the temperature sensor to monitor. This is the Radeon Pro VII/MI50. @@ -36,6 +48,14 @@ sensors: platform: amdgpu-pci-04400 # Use the junction temperature (temp2_input) as it's a good indicator of core heat. index: 2 + # Define the temperature sensor for the Radeon Pro W5700. + - id: gpu_w5700_temp + hwmon: + # From `fan2go detect`, this is the platform for the W5700. + platform: amdgpu-pci-06300 + # Use the junction temperature (temp2_input). + index: 2 + curves: # Link the GPU temperature to the case fan speed. @@ -52,10 +72,22 @@ curves: - [60, 60] # At 60°C, run fan at 60% - [70, 80] # At 70°C, run fan at 80% - [80, 100] # At 80°C and above, run fan at 100% + # Define the curve for the Radeon Pro W5700's own fan. + - id: gpu_w5700_curve + linear: + # The sensor ID to use as a temperature input for this curve. + sensor: gpu_w5700_temp + # Define the temperature-to-PWM-value mapping. + # Temps are in Celsius, output is a PWM value (0-255). + points: + - [45, 51] # At 45°C, run fan at ~20% (51/255) + - [55, 102] # At 55°C, run fan at 40% + - [65, 153] # At 65°C, run fan at 60% + - [75, 204] # At 75°C, run fan at 80% + - [85, 255] # At 85°C and above, run fan at 100% statistics: # Whether to enable the prometheus exporter or not enabled: true # The port to expose the exporter on port: 9900 - diff --git a/desktop/l/gpu_info.md b/desktop/l/gpu_info.md index fb681cd..aa604b6 100644 --- a/desktop/l/gpu_info.md +++ b/desktop/l/gpu_info.md @@ -1,201 +1,7 @@ The system has x2 GPUs: -- [Radeon Pro W5700] which has temperature sensors and an attached PWM fan. The pid-fan-controller service is suitable for controlling this fan. +- [Radeon Pro W5700] which has temperature sensors and an attached PWM fan. The fan2go can control this. This config should be pretty simple, becasue fan2go can read the temperature and RPM all from the same card. - [Radeon Pro VII/Radeon Instinct MI50 32GB] which has temperature sensors, but NO FAN. Need to control the Corsair Commander Core Fan 1 to cool down this card. The challenge is that liquidctl is required to set the fan speed, so pid-fan-controller service won't work. Going to need to creata a fan2go configuration file for this. -I want to use the NixOS services pid-fan-controller to control the fan for Radeon Pro W5700. - -https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/services/hardware/pid-fan-controller.nix -``` -{ - lib, - config, - pkgs, - ... -}: -let - cfg = config.services.pid-fan-controller; - heatSource = { - options = { - name = lib.mkOption { - type = lib.types.uniq lib.types.nonEmptyStr; - description = "Name of the heat source."; - }; - wildcardPath = lib.mkOption { - type = lib.types.nonEmptyStr; - description = '' - Path of the heat source's `hwmon` `temp_input` file. - This path can contain multiple wildcards, but has to resolve to - exactly one result. - ''; - }; - pidParams = { - setPoint = lib.mkOption { - type = lib.types.ints.unsigned; - description = "Set point of the controller in °C."; - }; - P = lib.mkOption { - description = "K_p of PID controller."; - type = lib.types.float; - }; - I = lib.mkOption { - description = "K_i of PID controller."; - type = lib.types.float; - }; - D = lib.mkOption { - description = "K_d of PID controller."; - type = lib.types.float; - }; - }; - }; - }; - - fan = { - options = { - wildcardPath = lib.mkOption { - type = lib.types.str; - description = '' - Wildcard path of the `hwmon` `pwm` file. - If the fans are not to be found in `/sys/class/hwmon/hwmon*` the corresponding - kernel module (like `nct6775`) needs to be added to `boot.kernelModules`. - See the [`hwmon` Documentation](https://www.kernel.org/doc/html/latest/hwmon/index.html). - ''; - }; - minPwm = lib.mkOption { - default = 0; - type = lib.types.ints.u8; - description = "Minimum PWM value."; - }; - maxPwm = lib.mkOption { - default = 255; - type = lib.types.ints.u8; - description = "Maximum PWM value."; - }; - cutoff = lib.mkOption { - default = false; - type = lib.types.bool; - description = "Whether to stop the fan when `minPwm` is reached."; - }; - heatPressureSrcs = lib.mkOption { - type = lib.types.nonEmptyListOf lib.types.str; - description = "Heat pressure sources affected by the fan."; - }; - }; - }; -in -{ - options.services.pid-fan-controller = { - enable = lib.mkEnableOption "the PID fan controller, which controls the configured fans by running a closed-loop PID control loop"; - package = lib.mkPackageOption pkgs "pid-fan-controller" { }; - settings = { - interval = lib.mkOption { - default = 500; - type = lib.types.int; - description = "Interval between controller cycles in milliseconds."; - }; - heatSources = lib.mkOption { - type = lib.types.listOf (lib.types.submodule heatSource); - description = "List of heat sources to be monitored."; - example = '' - [ - { - name = "cpu"; - wildcardPath = "/sys/devices/pci0000:00/0000:00:18.3/hwmon/hwmon*/temp1_input"; - pidParams = { - setPoint = 60; - P = -5.0e-3; - I = -2.0e-3; - D = -6.0e-3; - }; - } - ]; - ''; - }; - fans = lib.mkOption { - type = lib.types.listOf (lib.types.submodule fan); - description = "List of fans to be controlled."; - example = '' - [ - { - wildcardPath = "/sys/devices/platform/nct6775.2592/hwmon/hwmon*/pwm1"; - minPwm = 60; - maxPwm = 255; - heatPressureSrcs = [ - "cpu" - "gpu" - ]; - } - ]; - ''; - }; - }; - }; - config = lib.mkIf cfg.enable { - #map camel cased attrs into snake case for config - environment.etc."pid-fan-settings.json".text = builtins.toJSON { - interval = cfg.settings.interval; - heat_srcs = map (heatSrc: { - name = heatSrc.name; - wildcard_path = heatSrc.wildcardPath; - PID_params = { - set_point = heatSrc.pidParams.setPoint; - P = heatSrc.pidParams.P; - I = heatSrc.pidParams.I; - D = heatSrc.pidParams.D; - }; - }) cfg.settings.heatSources; - fans = map (fan: { - wildcard_path = fan.wildcardPath; - min_pwm = fan.minPwm; - max_pwm = fan.maxPwm; - cutoff = fan.cutoff; - heat_pressure_srcs = fan.heatPressureSrcs; - }) cfg.settings.fans; - }; - - systemd.services.pid-fan-controller = { - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - Type = "simple"; - ExecStart = [ (lib.getExe cfg.package) ]; - ExecStopPost = [ "${lib.getExe cfg.package} disable" ]; - Restart = "always"; - #This service needs to run as root to write to /sys. - #therefore it should operate with the least amount of privileges needed - ProtectHome = "yes"; - #strict is not possible as it needs /sys - ProtectSystem = "full"; - ProtectProc = "invisible"; - PrivateNetwork = "yes"; - NoNewPrivileges = "yes"; - MemoryDenyWriteExecute = "yes"; - RestrictNamespaces = "~user pid net uts mnt"; - ProtectKernelModules = "yes"; - RestrictRealtime = "yes"; - SystemCallFilter = "@system-service"; - CapabilityBoundingSet = "~CAP_KILL CAP_WAKE_ALARM CAP_IPC_LOC CAP_BPF CAP_LINUX_IMMUTABLE CAP_BLOCK_SUSPEND CAP_MKNOD"; - }; - # restart unit if config changed - restartTriggers = [ config.environment.etc."pid-fan-settings.json".source ]; - }; - #sleep hook to restart the service as it breaks otherwise - systemd.services.pid-fan-controller-sleep = { - before = [ "sleep.target" ]; - wantedBy = [ "sleep.target" ]; - unitConfig = { - StopWhenUnneeded = "yes"; - }; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - ExecStart = [ "systemctl stop pid-fan-controller.service" ]; - ExecStop = [ "systemctl restart pid-fan-controller.service" ]; - }; - }; - }; - meta.maintainers = with lib.maintainers; [ zimward ]; -} -``` - ``` [das@l:~/nixos]$ lspci | grep -i radeon diff --git a/desktop/l/hardware-configuration.nix b/desktop/l/hardware-configuration.nix index 72bf8fc..7b2ea6a 100644 --- a/desktop/l/hardware-configuration.nix +++ b/desktop/l/hardware-configuration.nix @@ -49,4 +49,5 @@ # see also fan2go.nix hardware.fan2go.enable = true; + } diff --git a/desktop/l/systemPackages.nix b/desktop/l/systemPackages.nix index eb98dce..97f88a2 100644 --- a/desktop/l/systemPackages.nix +++ b/desktop/l/systemPackages.nix @@ -53,6 +53,7 @@ # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/services/hardware/fancontrol.nix lm_sensors liquidctl + jq rdma-core # ibv_devinfo, rdma pciutils diff --git a/desktop/l/test_fan_commands.sh b/desktop/l/test_fan_commands.sh new file mode 100755 index 0000000..5ddaae7 --- /dev/null +++ b/desktop/l/test_fan_commands.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +echo "=== Testing Fan Commands ===" +echo + +# Test getPwm function +echo "1. Testing getPwm (should return PWM value 0-255):" +getPwm() { + output=$(/run/current-system/sw/bin/liquidctl status 2>/dev/null) + echo "Full output: $output" + # Simple regex: look for "Fan speed 1" followed by non-digits, then capture the number + if [[ $output =~ Fan\ speed\ 1[^0-9]+([0-9]+) ]]; then + rpm=${BASH_REMATCH[1]} + echo "Raw RPM: $rpm" + pwm=$((rpm * 255 / 2000)) + echo "Calculated PWM: $pwm" + else + echo "No fan speed found, returning 0" + pwm=0 + fi + echo $pwm +} + +current_pwm=$(getPwm) +echo "Current PWM: $current_pwm" +echo + +# Test getRpm function +echo "2. Testing getRpm (should return RPM value):" +getRpm() { + output=$(/run/current-system/sw/bin/liquidctl status 2>/dev/null) + # Simple regex: look for "Fan speed 1" followed by non-digits, then capture the number + if [[ $output =~ Fan\ speed\ 1[^0-9]+([0-9]+) ]]; then + rpm=${BASH_REMATCH[1]} + echo $rpm + else + echo "0" + fi +} + +current_rpm=$(getRpm) +echo "Current RPM: $current_rpm" +echo + +# Test setPwm function +echo "3. Testing setPwm (setting fan to 50% = PWM 127):" +setPwm() { + local pwm=$1 + percent=$((pwm * 100 / 255)) + echo "Setting fan to $percent% (PWM: $pwm)" + /run/current-system/sw/bin/liquidctl set fan1 speed $percent +} + +echo "Setting fan to 50%..." +setPwm 127 +sleep 2 + +echo "Checking PWM after setting to 50%..." +new_pwm=$(getPwm) +echo "New PWM: $new_pwm" +echo + +echo "Checking RPM after setting to 50%..." +new_rpm=$(getRpm) +echo "New RPM: $new_rpm" +echo + +# Test another PWM value +echo "4. Testing setPwm (setting fan to 25% = PWM 64):" +echo "Setting fan to 25%..." +setPwm 64 +sleep 2 + +echo "Checking PWM after setting to 25%..." +final_pwm=$(getPwm) +echo "Final PWM: $final_pwm" +echo + +echo "Checking RPM after setting to 25%..." +final_rpm=$(getRpm) +echo "Final RPM: $final_rpm" +echo + +echo "=== Test Complete ===" From 055488209437bfe8b2f6eaa2a3442074df95aa87 Mon Sep 17 00:00:00 2001 From: "randomizedcoder dave.seddon.ca@gmail.com" Date: Wed, 15 Oct 2025 09:36:03 -0700 Subject: [PATCH 23/23] give up --- desktop/l/configuration.nix | 4 +- desktop/l/example.txt | 1 + desktop/l/fan2go.nix | 220 +++++++++++++++++++++++---- desktop/l/hardware-configuration.nix | 2 +- 4 files changed, 192 insertions(+), 35 deletions(-) create mode 100644 desktop/l/example.txt diff --git a/desktop/l/configuration.nix b/desktop/l/configuration.nix index 76f5319..fa94bcc 100644 --- a/desktop/l/configuration.nix +++ b/desktop/l/configuration.nix @@ -40,7 +40,7 @@ # GPU fan control #./gpu-fan-control.nix # Corsair fan control - #./corsair-fan-control.nix + ./corsair-fan-control.nix #./docker-compose.nix ./docker-daemon.nix #./smokeping.nix @@ -48,7 +48,7 @@ #./hyprland.nix ./nginx.nix ./ollama-service.nix - ./fan2go.nix + #/fan2go.nix ]; boot = { diff --git a/desktop/l/example.txt b/desktop/l/example.txt new file mode 100644 index 0000000..de04a97 --- /dev/null +++ b/desktop/l/example.txt @@ -0,0 +1 @@ +This is the content of the file. \ No newline at end of file diff --git a/desktop/l/fan2go.nix b/desktop/l/fan2go.nix index 3321002..2f92ad9 100644 --- a/desktop/l/fan2go.nix +++ b/desktop/l/fan2go.nix @@ -17,6 +17,11 @@ # 6. Uses bash parameter expansion: ${var#pattern} and ${var%%pattern} # 7. No temporary files or delays needed since fan2go is the only liquidctl user # +# Nix string literals: +# https://nix.dev/manual/nix/2.28/language/string-literals.html#string-literals +# https://nix.dev/manual/nix/2.28/language/string-interpolation.html +# https://github.com/NixOS/nix/blob/master/doc/manual/source/language/string-interpolation.md +# # See also: https://github.com/arnarg/config/blob/8de65cf5f1649a4fe6893102120ede4363de9bfa/hosts/terra/fan2go.nix # # @@ -30,6 +35,16 @@ # ├── Fan speed 5 0 rpm # └── Fan speed 6 0 rpm # +# [das@l:~/nixos/desktop/l]$ liquidctl list -v +# Device #0: Corsair Commander Core XT (broken) +# ├── Vendor ID: 0x1b1c +# ├── Product ID: 0x0c2a +# ├── Release number: 0x0100 +# ├── Serial number: 210430f00a0857baae689a262091005f +# ├── Bus: hid +# ├── Address: /dev/hidraw5 +# └── Driver: CommanderCore +# { lib, config, @@ -40,55 +55,182 @@ let cfg = config.hardware.fan2go; + # Path for the lock file to serialize access to liquidctl. + liquidctlLockFile = "/run/lock/fan2go-liquidctl.lock"; + + # Vendor ID for the Corsair device to speed up liquidctl commands. + liquidctlVendorId = "0x1b1c"; + + # Sleep duration between retries for liquidctl commands. + retrySleepDuration = 0.1; + + # Debug level for the scripts (0=off, 7=max debug). + debugLevel = 7; + + # A reusable bash helper function for logging. + # It checks the DEBUG_LEVEL and prints messages to stderr. + debugLogger = '' + # Set default debug level if not provided. + : "''${DEBUG_LEVEL:=0}" # Use quoted expansion to satisfy shellcheck + : "''${DEBUG_LEVEL:=0}" + LOG_FILE="/tmp/fan2go-debug-$(date +%Y%m%d%H).log" + log_debug() { + # Append message to the log file if debug level is 7 or higher. + if [[ ''${DEBUG_LEVEL} -ge 7 ]]; then echo "[$(date +%T)] DEBUG: $*" >> "$LOG_FILE"; fi + if [[ ''${DEBUG_LEVEL} -ge 7 ]]; then echo "[$(date +%T)] [$$] DEBUG: $*" >> "$LOG_FILE"; fi + } + ''; + # Create the bash scripts for fan control - setPwmScript = pkgs.writeText "setPwm.bash" '' - #!${pkgs.bash}/bin/bash + setPwmScript = pkgs.writeShellApplication { + name = "setPwm.bash"; + # A single, unified script to wrap all liquidctl interactions, + # preventing race conditions by design. + liquidctlWrapperScript = pkgs.writeShellApplication { + name = "liquidctl-wrapper.bash"; + runtimeInputs = [ pkgs.liquidctl pkgs.util-linux pkgs.coreutils ]; + text = '' # Convert fan2go PWM (0-255) to liquidctl percentage (0-100) - percent=$((%pwm% * 100 / 255)) - ${pkgs.liquidctl}/bin/liquidctl set fan1 speed $percent - ''; + # PWM value is passed as the first argument + ${debugLogger} + log_debug "setPwm started with argument: $1" + ${debugLogger} + ACTION="$1" + log_debug "Wrapper called with action: $ACTION" - getPwmScript = pkgs.writeText "getPwm.bash" '' - #!${pkgs.bash}/bin/bash + # Check if the pwm_value argument was provided. + : "''${1:?PWM value not provided as an argument}" + percent=$(( $1 * 100 / 255 )) + log_debug "Calculated percent: $percent" + for i in {1..3}; do + ( + log_debug "Attempt #$i: Acquiring lock and setting fan speed..." + liquidctl --vendor ${liquidctlVendorId} set fan1 speed "$percent" 2>> "$LOG_FILE" + ) 200>${liquidctlLockFile} && break + log_debug "Attempt #$i failed. Sleeping for ${toString retrySleepDuration}s." + sleep ${toString retrySleepDuration} + done + ''; + }; + case "$ACTION" in + set-pwm) + PWM_VALUE="$2" + : "''${PWM_VALUE:?PWM value not provided for set-pwm action}" + percent=$((PWM_VALUE * 100 / 255)) + log_debug "Calculated percent: $percent" + for i in {1..3}; do + ( flock 200; liquidctl --vendor ${liquidctlVendorId} set fan1 speed "$percent" 2>> "$LOG_FILE" ) 200>${liquidctlLockFile} && break + log_debug "Attempt #$i failed. Sleeping." + sleep ${toString retrySleepDuration} + done + ;; + get-pwm|get-rpm) + output="" + for i in {1..3}; do + output=$( ( flock -s 200; liquidctl --vendor ${liquidctlVendorId} status 2>> "$LOG_FILE" ) 200>${liquidctlLockFile} ) + [ -n "$output" ] && break + log_debug "Attempt #$i failed (no output). Sleeping." + sleep ${toString retrySleepDuration} + done + log_debug "Raw liquidctl output: $output" + + getPwmScript = pkgs.writeShellApplication { + name = "getPwm.bash"; + runtimeInputs = [ pkgs.liquidctl pkgs.util-linux pkgs.coreutils ]; + text = '' # Get current fan RPM and convert to PWM value - output=$(${pkgs.liquidctl}/bin/liquidctl status 2>/dev/null) - if [[ $output =~ Fan\ speed\ 1[^0-9]+([0-9]+) ]]; then - rpm=${BASH_REMATCH[1]} + output="" + ${debugLogger} + log_debug "getPwm started." + + for i in {1..3}; do + output=$( ( + log_debug "Attempt #$i: Acquiring lock and getting status..." + flock -s 200 # Use a shared lock for read-only operations + liquidctl --vendor ${liquidctlVendorId} status 2>> "$LOG_FILE" + ) 200>${liquidctlLockFile} ) + [ -n "$output" ] && break + log_debug "Attempt #$i failed (no output). Sleeping for ${toString retrySleepDuration}s." + sleep ${toString retrySleepDuration} + done + log_debug "Raw liquidctl output: $output" + if [[ $output =~ Fan\ speed\ 1[^0-9]+([0-9]+) ]]; then + rpm=''${BASH_REMATCH[1]} echo $((rpm * 255 / 2000)) - else - echo 0 + exit 0 fi - ''; + echo 0 + if [[ $output =~ Fan\ speed\ 1[^0-9]+([0-9]+) ]]; then + rpm=''${BASH_REMATCH[1]} + if [[ "$ACTION" == "get-pwm" ]]; then + echo $((rpm * 255 / 2000)) + else # get-rpm + echo "$rpm" + fi + else + echo 0 + fi + ;; + *) + log_debug "Unknown action: $ACTION" + exit 1 + ;; + esac + ''; + }; - getRpmScript = pkgs.writeText "getRpm.bash" '' - #!${pkgs.bash}/bin/bash + getRpmScript = pkgs.writeShellApplication { + name = "getRpm.bash"; + runtimeInputs = [ pkgs.liquidctl pkgs.util-linux pkgs.coreutils ]; + text = '' # Get current fan RPM value - output=$(${pkgs.liquidctl}/bin/liquidctl status 2>/dev/null) - if [[ $output =~ Fan\ speed\ 1[^0-9]+([0-9]+) ]]; then - rpm=${BASH_REMATCH[1]} - echo $rpm - else - echo 0 + output="" + ${debugLogger} + log_debug "getRpm started." + + for i in {1..3}; do + output=$( ( + log_debug "Attempt #$i: Acquiring lock and getting status..." + flock -s 200 # Use a shared lock for read-only operations + liquidctl --vendor ${liquidctlVendorId} status 2>> "$LOG_FILE" + ) 200>${liquidctlLockFile} ) + [ -n "$output" ] && break + log_debug "Attempt #$i failed (no output). Sleeping for ${toString retrySleepDuration}s." + sleep ${toString retrySleepDuration} + done + log_debug "Raw liquidctl output: $output" + if [[ $output =~ Fan\ speed\ 1[^0-9]+([0-9]+) ]]; then + rpm=''${BASH_REMATCH[1]} + echo "$rpm" + exit 0 fi - ''; + echo 0 + ''; + }; # Create a shellcheck validation script - shellcheckScript = pkgs.writeText "check-fan-scripts.sh" '' - #!${pkgs.bash}/bin/bash + shellcheckScript = pkgs.writeShellApplication { + name = "check-fan-scripts.sh"; + runtimeInputs = [ pkgs.shellcheck ]; + text = '' # Shellcheck validation for fan control scripts echo "Running shellcheck on fan control scripts..." echo "Checking setPwm script..." - ${pkgs.shellcheck}/bin/shellcheck ${setPwmScript} || exit 1 + shellcheck ${setPwmScript}/bin/setPwm.bash || exit 1 + shellcheck ${liquidctlWrapperScript}/bin/liquidctl-wrapper.bash || exit 1 echo "Checking getPwm script..." - ${pkgs.shellcheck}/bin/shellcheck ${getPwmScript} || exit 1 + shellcheck ${getPwmScript}/bin/getPwm.bash || exit 1 + shellcheck ${liquidctlWrapperScript}/bin/liquidctl-wrapper.bash || exit 1 echo "Checking getRpm script..." - ${pkgs.shellcheck}/bin/shellcheck ${getRpmScript} || exit 1 + shellcheck ${getRpmScript}/bin/getRpm.bash || exit 1 + shellcheck ${liquidctlWrapperScript}/bin/liquidctl-wrapper.bash || exit 1 echo "All scripts passed shellcheck validation!" - ''; + ''; + }; fan2goConfig = pkgs.writeText "fan2go.yaml" '' # @@ -107,15 +249,28 @@ let # We use a shell command to convert the 0-255 PWM value from fan2go # into a 0-100 percentage for liquidctl. setPwm: - exec: "${setPwmScript}" + exec: "${setPwmScript}/bin/setPwm.bash" + args: ["%pwm%"] + exec: "${liquidctlWrapperScript}/bin/liquidctl-wrapper.bash" + args: ["set-pwm", "%pwm%"] + env: + DEBUG_LEVEL: "${toString debugLevel}" # The `getPwm` command should return the current PWM value. # Since liquidctl doesn't provide PWM directly, we convert from the RPM value. getPwm: - exec: "${getPwmScript}" + exec: "${getPwmScript}/bin/getPwm.bash" + exec: "${liquidctlWrapperScript}/bin/liquidctl-wrapper.bash" + args: ["get-pwm"] + env: + DEBUG_LEVEL: "${toString debugLevel}" # The `getRpm` command gets the current RPM value from liquidctl. # This helps fan2go understand the fan's current state. getRpm: - exec: "${getRpmScript}" + exec: "${getRpmScript}/bin/getRpm.bash" + exec: "${liquidctlWrapperScript}/bin/liquidctl-wrapper.bash" + args: ["get-rpm"] + env: + DEBUG_LEVEL: "${toString debugLevel}" # Fan speed is a percentage for liquidctl min: 10 max: 100 @@ -211,7 +366,7 @@ in after = [ "lm_sensors.service" ]; serviceConfig = { - ExecStartPre = "${shellcheckScript}"; + ExecStartPre = "${shellcheckScript}/bin/check-fan-scripts.sh"; ExecStart = lib.concatStringsSep " " [ "${pkgs.fan2go}/bin/fan2go" "-c" @@ -219,6 +374,7 @@ in "--no-style" ]; + Environment = [ "GOMEMLIMIT=45MiB" ]; MemoryHigh = "48M"; MemoryMax = "64M"; CPUQuota = "50%"; diff --git a/desktop/l/hardware-configuration.nix b/desktop/l/hardware-configuration.nix index 7b2ea6a..acab827 100644 --- a/desktop/l/hardware-configuration.nix +++ b/desktop/l/hardware-configuration.nix @@ -48,6 +48,6 @@ #https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/hardware/decklink.nix # see also fan2go.nix - hardware.fan2go.enable = true; + #hardware.fan2go.enable = true; }