{ config, pkgs, lib, ... }: let importedVars = import ./variables.nix { inherit config pkgs lib; }; in with importedVars; { nixpkgs.config = { allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ # "claude-code" "obsidian" "packer" "reaper" # "n8n" "vscode" "terraform" "zoom" # "charlatan3" # "steam" # "steam-original" # "steam-unwrapped" # "steam-run" # "tokenizer.json" # goose-cli ]; }; nixpkgs.overlays = [ (self: super: { # n8n = unstable.n8n; ansible = super.ansible.overrideAttrs (oldAttrs: { propagatedBuildInputs = oldAttrs.propagatedBuildInputs ++ [ super.python312Packages.jmespath ]; }); # Add jmespath to ansible build inputs # https://blaukraut.info/ # charlatan3 = super.callPackage ./overlays/clap/charlatan3.nix { }; }) ]; imports = [ ./hardware-configuration.nix ]; boot = { loader = { systemd-boot.enable = true; efi.canTouchEfiVariables = true; }; }; hardware = { bluetooth.enable = true; keyboard.qmk.enable = true; graphics = { # https://wiki.nixos.org/wiki/Accelerated_Video_Playback enable = true; extraPackages = with pkgs; [ intel-media-driver ]; }; }; networking = { hostName = "${host_name}"; firewall.enable = false; interfaces = { enp100s0.ipv4.addresses = [{ address = "192.168.1.35"; prefixLength = 24; }]; }; defaultGateway = { address = "192.168.1.1"; interface = "enp100s0"; }; # TODO https://nixos.wiki/wiki/Encrypted_DNS nameservers = [ "1.1.1.1" "8.8.8.8" ]; extraHosts = '' 192.168.1.1 shinx.${host_fqdn} ''; localCommands = '' ip route add 10.19.21.11/32 dev ${config.networking.defaultGateway.interface} via ${config.networking.defaultGateway.address} || true # timburr ip route add 10.19.21.34/32 dev ${config.networking.defaultGateway.interface} via ${config.networking.defaultGateway.address} || true # weavile ''; }; time.timeZone = "America/Los_Angeles"; i18n.defaultLocale = "en_US.UTF-8"; console = { font = "Lat2-Terminus16"; # keyMap = "us"; useXkbConfig = true; # use xkbOptions in tty. }; users = { groups = { glance = {}; }; users = { root = { openssh.authorizedKeys.keyFiles = [ /etc/nixos/ssh/authorized_keys ]; }; blee = { openssh.authorizedKeys.keyFiles = [ /etc/nixos/ssh/authorized_keys ]; isNormalUser = true; extraGroups = [ "wheel" "adbusers" "docker" "glance" ]; packages = with pkgs; [ # unstable.goose-cli mariadb notify-client gh brave chromium element-desktop firefox haruna gimp gnumake home-manager jellyfin-media-player kdePackages.kate #kwrite kdePackages.kdenlive kdePackages.kcalc # libsForQt5.kcalc # unstable.logseq # warning: https://github.com/logseq/logseq/issues/10851#issuecomment-2402925912 # unstable.ghostty moonlight-qt nmap obs-studio obsidian # pavucontrol qbittorrent rclone # rtorrent sq # synergy tenacity thunderbird tor-browser via vlc vscode yt-dlp zoom-us # Build vim huge with clipboard support (vim_configurable.overrideAttrs (oldAttrs: { features = "huge"; })) awscli2 aws-sam-cli packer terraform ansible python311 python311Packages.pip python311Packages.ipython libreoffice-qt hunspell hunspellDicts.en-us # postman # nope, auth is broken nodejs_20 yarn deno nix-init nix-tree nurl # music apps reaper spek ]; }; glance = { isSystemUser = true; group = "glance"; home = "/var/lib/glance"; createHome = true; description = "Glance service user"; # shell = pkgs.bash; }; }; }; # home-manager.users.blee = { imports = [ ./home.nix ]; }; environment = { systemPackages = with pkgs; [ arp-scan binutils coreutils cryptsetup curl difftastic dig dnscontrol dnsutils doas exiftool ffmpeg file fzf git go htop iftop imagemagick iperf jq lego libressl lm_sensors mediainfo net-snmp # snmpwalk netcat nettools nix-output-monitor parted pass pciutils # lspci psmisc qrencode rsync screen tcpdump tmux tree unzip vim vulkan-tools wget whois wireguard-tools zbar zip ]; shellInit = '' pheonix() { systemctl restart "$1" journalctl -fu "$1" } ''; # vscode on Wayland sessionVariables.NIXOS_OZONE_WL = "1"; # TODO: https://github.com/nix-community/plasma-manager plasma6.excludePackages = with pkgs.kdePackages; [ plasma-browser-integration ]; etc."gitconfig".text = '' [init] defaultBranch = main ''; }; programs = { adb.enable = true; appimage = { enable = true; binfmt = true; package = pkgs.appimage-run.override { extraPkgs = pkgs: [ pkgs.libthai # lume ]; }; }; # hyprland = { # enable = true; # xwayland.enable = true; # }; fish.enable = true; vim = { enable = true; defaultEditor = true; }; bash = { shellAliases = { ll = "ls -lAF --classify --group-directories-first"; l = "ls -lF --classify --group-directories-first"; }; # https://nixos.wiki/wiki/Fish interactiveShellInit = '' if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]] then shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION="" exec ${pkgs.fish}/bin/fish $LOGIN_OPTION fi ''; }; mtr.enable = true; gnupg.agent = { enable = true; enableSSHSupport = true; }; kdeconnect.enable = true; chromium = { enable = true; extraOpts = { "SpellcheckEnabled" = false; "DefaultSearchProviderEnabled" = true; "DefaultSearchProviderName" = "Kagi"; "DefaultSearchProviderSearchURL" = "https://kagi.com/search?q={searchTerms}"; "SearchSuggestEnabled" = false; "DefaultSearchProviderSuggestURL" = ""; }; }; }; security = { sudo.enable = false; doas = { enable = true; extraRules = [ { users = [ "blee" ]; persist = true; } ]; }; }; services = { openssh.enable = true; udev.packages = [ pkgs.via ]; # https://discourse.nixos.org/t/bluetooth-a2dp-sink-not-showing-up-in-pulseaudio-on-nixos/32447/4?u=bleetube pipewire = { enable = true; pulse.enable = true; alsa.enable = true; # for tenacity # jack.enable = true; # this might be useful for reaper, but enabling it breaks stereo audio for some reason }; # avahi = { # for resolving start9 hostname # enable = true; # nssmdns4 = true; # Enable NSS support for mDNS # }; syncthing = { enable = true; user = "blee"; dataDir = "/home/blee/Documents"; }; journald.extraConfig = "MaxRetentionSec=30day"; # https://github.com/NixOS/nixpkgs/blob/nixos-23.05/nixos/modules/services/monitoring/prometheus/exporters.nix prometheus.exporters.node = { enable = true; port = 8030; # openFirewall = true; enabledCollectors = [ "cpu.info" "interrupts" "netstat" "vmstat" "systemd" "tcpstat" "processes" ]; }; caddy = { enable = true; package = caddyWithPlugins; # logFormat = "output discard"; logFormat = "level DEBUG"; extraConfig = let tlsConfig = '' tls { dns namecheap { api_key {env.NAMECHEAP_API_KEY} user {env.NAMECHEAP_API_USER} api_endpoint https://api.namecheap.com/xml.response } } ''; in '' ${host_fqdn} { ${tlsConfig} reverse_proxy http://127.0.0.1:8034 # open-webui # handle /files/* { # root /mnt/usb/ # file_server browse # } } ${host_fqdn}:4430 { ${tlsConfig} reverse_proxy http://127.0.0.1:8030 # node_exporter } ${host_fqdn}:4432 { ${tlsConfig} reverse_proxy http://127.0.0.1:8032 # glance } ${host_fqdn}:4434 { ${tlsConfig} reverse_proxy http://127.0.0.1:8034 # open-webui } ${host_fqdn}:4435 { ${tlsConfig} reverse_proxy http://127.0.0.1:8035 # mealie } ${host_fqdn}:4436 { ${tlsConfig} reverse_proxy http://127.0.0.1:8036 # litellm } :9999 { respond "success" } ''; }; open-webui = { enable = true; port = 8034; }; litellm = { enable = true; port = 8036; environmentFile = litellmEnvFile; settings = { litellm_settings = { set_verbose = true; }; model_list = [ { model_name = "grok-3"; litellm_params = { model = "xai/grok-3-latest"; api_key = "os.environ/XAI_API_KEY"; # LiteLLM reads this env var }; } { model_name = "deepseek-r1-distill-llama-70b"; litellm_params = { model = "groq/deepseek-r1-distill-llama-70b"; api_key = "os.environ/GROK_API_KEY"; # LiteLLM reads this env var }; } { model_name = "claude-3.5-sonnet"; litellm_params = { model = "anthropic/claude-3-5-sonnet-latest"; api_key = "os.environ/ANTHROPIC_API_KEY"; # LiteLLM reads this env var }; } { model_name = "gemini-2.0-flash"; litellm_params = { model = "gemini/gemini-2.0-flash-exp"; api_key = "os.environ/GOOGLE_API_KEY"; # LiteLLM reads this env var safety_settings = [ { category = "HARM_CATEGORY_HARASSMENT"; threshold = "BLOCK_NONE"; } { category = "HARM_CATEGORY_HATE_SPEECH"; threshold = "BLOCK_NONE"; } { category = "HARM_CATEGORY_SEXUALLY_EXPLICIT"; threshold = "BLOCK_NONE"; } { category = "HARM_CATEGORY_DANGEROUS_CONTENT"; threshold = "BLOCK_NONE"; } ]; }; } ]; }; }; mealie = { enable = true; port = 8035; # listenAddress = "127.0.0.1"; listenAddress = "0.0.0.0"; # package = unstable.mealie; }; # n8n.enable = true; strongswan = { enable = false; secrets = [ "/etc/nixos/ipsec.secrets" ]; connections = { "aws-vpn" = { type = "tunnel"; authby = "secret"; left = "%defaultroute"; leftsubnet = "0.0.0.0/0"; right = "${secrets.aws-vpn.tunnel-address}"; rightsubnet = "10.0.64.0/24"; # subnet-0f2b39fd2ed6a88d7 "private-lambda-us-west-2d" ike = "aes256-sha2_256-modp2048!"; esp = "aes256-sha2_256!"; ikelifetime = "8h"; keylife = "1h"; keyingtries = "3"; auto = "start"; installpolicy = "yes"; # Install IPsec policies routing = "yes"; # Install routes dpdaction = "restart"; # Restart connection if peer is unreachable dpddelay = "30s"; # Dead peer detection delay closeaction = "restart"; # Restart connection if it drops }; }; setup = { charondebug = "esp 2, ike 2, cfg 2, net 2, enc 2"; }; }; desktopManager.plasma6.enable = true; displayManager = { sddm.enable = true; sddm.wayland.enable = true; #defaultSession = "plasmawayland"; }; xserver.enable = true; }; systemd = { services.glance = { wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; serviceConfig = { User = "glance"; Group = "glance"; WorkingDirectory = "/var/lib/glance"; # Environment = "LOG_LEVEL=debug"; # https://github.com/glanceapp/glance/issues/196 ExecStart = "${pkgs.glance}/bin/glance --config config.yaml"; }; }; services.ena-vpn = { description = "ENA Corp VPN"; # wantedBy = [ "multi-user.target" ]; # 2fa required, avoid startup after = [ "network-online.target" ]; wants = [ "network-online.target" ]; serviceConfig = { Type = "simple"; User = "root"; ExecStart = "${pkgs.openfortivpn}/bin/openfortivpn -c /etc/openfortivpn/config"; }; }; services.mealie.environment = { # https://docs.mealie.io/documentation/getting-started/installation/open-ai/ OPENAI_API_KEY = "${secrets.mealie.openai-api-key}"; }; # services.n8n.environment = { # N8N_EDITOR_BASE_URL = "https://${host_fqdn}:4433"; # N8N_DIAGNOSTICS_ENABLED = "false"; # Also disables "Ask AI" in the code node # N8N_HIRING_BANNER_ENABLED = "false"; # N8N_METRICS = "true"; # N8N_PORT = "8033"; # }; tmpfiles.rules = [ "d /srv/src 0775 root users - -" ]; }; # Create the OpenFortiVPN config directory and file environment.etc = { "openfortivpn/config" = { text = '' host = fortivpn.ena.net port = 443 username = ${secrets.ena-vpn.username} password = ${secrets.ena-vpn.password} set-dns = 0 set-routes = 1 trusted-cert = fa59c235354ec625b0e560e4263b1eff793480f399a39b7f80b18fb865184ecd ''; mode = "0600"; }; "ipsec.secrets" = { text = '' ${secrets.aws-vpn.tunnel-address} : PSK "${secrets.aws-vpn.psk}" ''; mode = "0600"; }; }; virtualisation.docker = { enable = true; rootless = { enable = true; setSocketVariable = true; }; autoPrune = { enable = true; dates = "monthly"; }; }; system.stateVersion = "23.05"; }