From 201041b835d17ed21e53ff2699611fad43b1a1c6 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 4 Nov 2024 13:00:32 +1100 Subject: [PATCH 001/213] docs: fix colors readme --- modules/nixos/appearance/palettes/readme.md | 26 ++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/modules/nixos/appearance/palettes/readme.md b/modules/nixos/appearance/palettes/readme.md index 7fb9e86..c2a9527 100644 --- a/modules/nixos/appearance/palettes/readme.md +++ b/modules/nixos/appearance/palettes/readme.md @@ -4,19 +4,19 @@ ### Shades -- (https://coolors.co/1a1a1a-212121-282828-343232-3f3b3b-4d4947-585350-645f59-716860-7d6f64)[Dark] -- (https://coolors.co/dfd2b3-d9c7a5-d4be98-c6b395-b4a288-a49384-99897a-8b7c6f)[light] +- [Dark](https://coolors.co/1a1a1a-212121-282828-343232-3f3b3b-4d4947-585350-645f59-716860-7d6f64) +- [Light](https://coolors.co/dfd2b3-d9c7a5-d4be98-c6b395-b4a288-a49384-99897a-8b7c6f) ### Colors -- [https://coolors.co/69713f-737c45-7f884c-8c9654-9aa55c-a9b665-b1be74-b8c481-bec98c-c4ce96](Green) -- [https://coolors.co/e57b76-ea6962-e95149-e33e35](Red) -- [https://coolors.co/e69965-e78a4e-e07b38-de732b](Orange) -- [https://coolors.co/d9b06d-d8a657-d09a43-c99136](Yellow) -- [https://coolors.co/beb874-b9b25f-ada652-9b944b](Olive) -- [https://coolors.co/9abb95-89b482-7aa573-6c9a65](Teal) -- [https://coolors.co/91b6ae-7daea3-6ea096-63978d](Blue) -- [https://coolors.co/dba3c7-d892c1-cd7eb3-c86faa](Violet) -- [https://coolors.co/d9a0af-d3869b-ca778d-c26680](Purple) -- [https://coolors.co/d8abcc-cf91be-c47eb1-bc71a8](Pink) -- [https://coolors.co/b18568-a87757-976b4e-896248](Brown) +- [Green](https://coolors.co/69713f-737c45-7f884c-8c9654-9aa55c-a9b665-b1be74-b8c481-bec98c-c4ce96) +- [Red](https://coolors.co/e57b76-ea6962-e95149-e33e35) +- [Orange](https://coolors.co/e69965-e78a4e-e07b38-de732b) +- [Yellow](https://coolors.co/d9b06d-d8a657-d09a43-c99136) +- [Olive](https://coolors.co/beb874-b9b25f-ada652-9b944b) +- [Teal](https://coolors.co/9abb95-89b482-7aa573-6c9a65) +- [Blue](https://coolors.co/91b6ae-7daea3-6ea096-63978d) +- [Violet](https://coolors.co/dba3c7-d892c1-cd7eb3-c86faa) +- [Purple](https://coolors.co/d9a0af-d3869b-ca778d-c26680) +- [Pink](https://coolors.co/d8abcc-cf91be-c47eb1-bc71a8) +- [Brown](https://coolors.co/b18568-a87757-976b4e-896248) From 71e0903e63cd80e7e9fb7de3bf89667106eaa0db Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 4 Nov 2024 19:51:23 +1100 Subject: [PATCH 002/213] nixos: temp nix_path fix --- modules/nixos/base/nix.nix | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/nixos/base/nix.nix b/modules/nixos/base/nix.nix index 411a097..1ea9590 100644 --- a/modules/nixos/base/nix.nix +++ b/modules/nixos/base/nix.nix @@ -7,8 +7,11 @@ ... }: let inherit (builtins) attrValues; - inherit (lib) mkIf mapAttrsToList; + inherit (lib) mkIf mapAttrs mapAttrsToList filterAttrs isType; inherit (config.ooknet.host) role admin; + + flakeInputs = filterAttrs (_: v: isType "flake" v) inputs; + paths = { FLAKE = "/home/${admin.name}/.config/ooknet"; WEBSITE = "${paths.FLAKE}/outputs/pkgs/website"; @@ -35,11 +38,9 @@ in { dates = "Sun *-*-* 14:00"; options = "--delete-older-than 14d"; }; - registry = { - nixpkgs.flake = inputs.nixpkgs; - default.flake = inputs.nixpkgs; - }; - nixPath = mapAttrsToList (name: _: "${name}=${name}") config.nix.registry; + # from github:fufexan + registry = mapAttrs (_: v: {flake = v;}) flakeInputs; + nixPath = mapAttrsToList (key: _: "${key}=flake:${key}") config.nix.registry; settings = { trusted-users = ["@wheel" "root" "builder"]; experimental-features = ["nix-command" "flakes"]; From c51a2d7fd49a10ec3c7df5afb3775a7cdf39c855 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 4 Nov 2024 19:51:47 +1100 Subject: [PATCH 003/213] fix: minimal theme colorscheme name --- modules/nixos/workstation/themes/minimal.nix | 2 +- outputs/lib/default.nix | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/nixos/workstation/themes/minimal.nix b/modules/nixos/workstation/themes/minimal.nix index 5fd8dcc..9ca1680 100644 --- a/modules/nixos/workstation/themes/minimal.nix +++ b/modules/nixos/workstation/themes/minimal.nix @@ -32,7 +32,7 @@ in { }; colorscheme = { - name = "gruvbox-material-medium"; + name = "gruvbox-material"; variant = "dark"; }; }; diff --git a/outputs/lib/default.nix b/outputs/lib/default.nix index d458ab7..3fcc9bc 100644 --- a/outputs/lib/default.nix +++ b/outputs/lib/default.nix @@ -2,7 +2,6 @@ lib, self, inputs, - pkgs, ... }: let # My person functions From 3773a25ef13393b9b3d3edf2c35918f12a8097f0 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 5 Nov 2024 20:54:12 +1100 Subject: [PATCH 004/213] colors: fix module option --- modules/nixos/appearance/options.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/nixos/appearance/options.nix b/modules/nixos/appearance/options.nix index b774998..c36d657 100644 --- a/modules/nixos/appearance/options.nix +++ b/modules/nixos/appearance/options.nix @@ -54,8 +54,8 @@ in { # Credit to github:misterio77/nix-colors colorscheme = { name = mkOption { - type = enum ["gruvbox-material-medium"]; - default = "gruvbox-material-medium"; + type = enum ["gruvbox-material"]; + default = "gruvbox-material"; }; variant = mkOption { type = enum ["dark" "light"]; From 9d5fcc0668396ee8c7729204326694d8857b7104 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 6 Nov 2024 18:49:36 +1100 Subject: [PATCH 005/213] lib: add color function collection --- outputs/lib/color/check.nix | 65 ++++++++++ outputs/lib/color/translate.nix | 207 ++++++++++++++++++++++++++++++++ outputs/lib/color/types.nix | 51 ++++++++ outputs/lib/color/utils.nix | 122 +++++++++++++++++++ outputs/lib/default.nix | 22 +++- outputs/lib/math.nix | 46 +++++++ 6 files changed, 512 insertions(+), 1 deletion(-) create mode 100644 outputs/lib/color/check.nix create mode 100644 outputs/lib/color/translate.nix create mode 100644 outputs/lib/color/types.nix create mode 100644 outputs/lib/color/utils.nix create mode 100644 outputs/lib/math.nix diff --git a/outputs/lib/color/check.nix b/outputs/lib/color/check.nix new file mode 100644 index 0000000..cb78c4b --- /dev/null +++ b/outputs/lib/color/check.nix @@ -0,0 +1,65 @@ +{lib, ...}: let + inherit (lib) toInt all min max; + inherit (builtins) isInt isFloat match getAttr hasAttr; + + # basic checks + range = a: b: v: (v <= max a b) && (v >= min a b); + number = v: isInt v || isFloat v; + unary = range 0.0 1.0; + hue = range 0.0 360.0; + + # type checking + hex = { + string = color: let + hexPatternWithHash = match "#[[:xdigit:]]{6}" color; + hexPatternNoHash = match "[[:xdigit:]]{6}" color; + isValid = hexPatternWithHash != null || hexPatternNoHash != null; + in + assert isValid || throw "Invalid hex color format: ${color}"; + hexPatternWithHash != null || hexPatternNoHash != null; + set = color: let + hasAttributes = all (k: hasAttr k color) ["r" "g" "b"]; + validPattern = all (k: let + v = getAttr k color; + in + match "[[:xdigit:]]{2}" v != null) ["r" "g" "b"]; + in + hasAttributes && validPattern; + }; + + rgb = { + string = color: let + rgbPattern = match "([0-9]{1,3}),([0-9]{1,3}),([0-9]{1,3})" color; + toNum = str: let + num = toInt str; + in + num != null && range 0 255 num; + isValid = rgbPattern != null && all toNum rgbPattern; + in + isValid; + set = color: let + hasAttributes = all (k: hasAttr k color) ["r" "g" "b"]; + validRanges = all ( + k: let + v = getAttr k color; + in + number v && range 0 255 v + ) ["r" "g" "b"]; + in + hasAttributes && validRanges; + }; + + hsl = { + # TODO: add range checks + string = color: let + hslPattern = match "([0-9]{1,3}),[ ]*([0-9]{1,3})%,[ ]*([0-9]{1,3})%" color; + in + hslPattern != null; + + set = color: let + hasAttributes = all (k: hasAttr k color) ["h" "s" "l"]; + validRanges = hue color.h && all (k: unary (getAttr k color)) ["s" "l"]; + in + hasAttributes && validRanges; + }; +in {inherit range number unary hue hex rgb hsl;} diff --git a/outputs/lib/color/translate.nix b/outputs/lib/color/translate.nix new file mode 100644 index 0000000..9ad22a8 --- /dev/null +++ b/outputs/lib/color/translate.nix @@ -0,0 +1,207 @@ +{ + math, + types, + lib, +}: let + inherit (builtins) substring; + inherit (lib) min max; + hex = { + toSet = string: + types.hex.set { + r = substring 0 2 string; + g = substring 2 2 string; + b = substring 4 2 string; + }; + toRGB = let + dictionary = { + "0" = 0; + "1" = 1; + "2" = 2; + "3" = 3; + "4" = 4; + "5" = 5; + "6" = 6; + "7" = 7; + "8" = 8; + "9" = 9; + "a" = 10; + "b" = 11; + "c" = 12; + "d" = 13; + "e" = 14; + "f" = 15; + "A" = 10; + "B" = 11; + "C" = 12; + "D" = 13; + "E" = 14; + "F" = 15; + }; + in { + # Converts a hex pair directly to RGB value (0-255) + pair = hexPair: let + high = dictionary.${substring 0 1 hexPair}; + low = dictionary.${substring 1 1 hexPair}; + in + (high * 16) + low; + + # Converts a hex set to RGB set + set = hexSet: + types.rgb.set { + r = hex.toRGB.pair hexSet.r; + g = hex.toRGB.pair hexSet.g; + b = hex.toRGB.pair hexSet.b; + }; + string = hexStr: let + rgbSet = hex.toRGB.set (hex.toSet hexStr); + in + types.rgb.string rgbSet.r rgbSet.g rgbSet.b; + }; + toHSL = { + set = hexStr: let + rgbSet = hex.toRGB.set (hex.toSet hexStr); + in + rgb.toHSL.set rgbSet; + + string = hexStr: let + hslSet = hex.toHSL.set hexStr; + in + types.hsl.string hslSet.h hslSet.s hslSet.l; + }; + }; + rgb = { + toHex = { + set = rgbSet: let + # Convert decimal to two-digit hex + toHexPair = num: let + hex = lib.toLower (lib.toHexString num); + # Pad with leading zero if single digit + padded = + if (builtins.stringLength hex) == 1 + then "0${hex}" + else hex; + in + padded; + in + types.hex.set { + r = toHexPair rgbSet.r; + g = toHexPair rgbSet.g; + b = toHexPair rgbSet.b; + }; + + string = rgbStr: let + hexSet = rgb.toHex.set rgbStr; + in + types.hex.string hexSet.r hexSet.g hexSet.b; + }; + toHSL = { + set = rgbSet: let + # Normalize RGB values to 0-1 range + r = rgbSet.r / 255.0; + g = rgbSet.g / 255.0; + b = rgbSet.b / 255.0; + + # Find min, max and delta + c_max = max (max r g) b; + c_min = min (min r g) b; + delta = c_max - c_min; + + # Calculate HSL values + h = + if delta == 0.0 + then 0.0 + else if c_max == r + then 60.0 * (math.mod ((g - b) / delta) 6) + else if c_max == g + then 60.0 * ((b - r) / delta + 2) + else 60.0 * ((r - g) / delta + 4); + + l = (c_max + c_min) / 2; + + s = + if delta == 0.0 + then 0.0 + else delta / (1 - (math.abs (2 * l - 1))); + in + types.hsl.set { + inherit h; + s = math.clamp 0.0 1.0 s; + l = math.clamp 0.0 1.0 l; + }; + + string = rgbStr: let + hslSet = rgb.toHSL.set (hex.toRGB.set (hex.toSet rgbStr)); + in + types.hsl.string hslSet.h hslSet.s hslSet.l; + }; + }; + hsl = { + toRGB = { + set = hslSet: let + inherit (hslSet) h s l; + + # Calculate chroma + c = (1 - (math.abs (2 * l - 1))) * s; + # Calculate h prime (h') + hp = h / 60.0; + # Calculate x + x = c * (1 - math.abs ((math.mod hp 2) - 1)); + # Calculate m + m = l - c / 2; + + # Get initial RGB values based on h' + rgb' = + if hp <= 1 + then { + r = c; + g = x; + b = 0; + } + else if hp <= 2 + then { + r = x; + g = c; + b = 0; + } + else if hp <= 3 + then { + r = 0; + g = c; + b = x; + } + else if hp <= 4 + then { + r = 0; + g = x; + b = c; + } + else if hp <= 5 + then { + r = x; + g = 0; + b = c; + } + else { + r = c; + g = 0; + b = x; + }; + # Final RGB values + in + types.rgb.set { + r = math.round ((rgb'.r + m) * 255); + g = math.round ((rgb'.g + m) * 255); + b = math.round ((rgb'.b + m) * 255); + }; + + string = hslStr: let + rgbSet = hsl.toRGB.set hslStr; + in + types.rgb.string rgbSet.r rgbSet.g rgbSet.b; + }; + toHex = { + set = {}; + string = color: color; + }; + }; +in {inherit hex hsl rgb;} diff --git a/outputs/lib/color/types.nix b/outputs/lib/color/types.nix new file mode 100644 index 0000000..850e647 --- /dev/null +++ b/outputs/lib/color/types.nix @@ -0,0 +1,51 @@ +{ + check, + math, + ... +}: let + inherit (math) round; + hex = { + set = { + r, + g, + b, + }: let + attrs = {inherit r g b;}; + in + assert check.hex.set attrs || throw "Invalid Hex values: r=${toString r}, g=${toString g}, b=${toString b}"; attrs; + + string = r: g: b: let + str = "${r}${g}${b}"; + in + assert check.hex.string str || throw "Invalid Hex value: ${str}"; str; + }; + + rgb = { + string = r: g: b: let + str = "${toString r},${toString g},${toString b}"; + in + assert check.rgb.string str || throw "Invalid RBG string format: ${str}"; str; + set = { + r, + g, + b, + }: let + attrs = {inherit r g b;}; + in + assert check.rgb.set attrs || throw "Invalid RGB values: r=${toString r}, g=${toString g}, b=${toString b}"; attrs; + }; + hsl = { + string = h: s: l: let + str = "${toString (round h)}, ${toString (round (s * 100))}%, ${toString (round (l * 100))}%"; + in + assert check.hsl.string str || throw "Invalid HSL values: ${str}"; str; + set = { + h, + s, + l, + }: let + attrs = {inherit h s l;}; + in + assert check.hsl.set attrs || throw "Invalid HSL values: h=${toString h}, s=${toString s}, l=${toString l}"; attrs; + }; +in {inherit hex hsl rgb;} diff --git a/outputs/lib/color/utils.nix b/outputs/lib/color/utils.nix new file mode 100644 index 0000000..1fa6938 --- /dev/null +++ b/outputs/lib/color/utils.nix @@ -0,0 +1,122 @@ +{ + math, + types, + translate, +}: let + # base modification function + modifyHSL = hexStr: modifications: let + # convert hex to HSL + hslSet = translate.hex.toHSL.set hexStr; + # apply modifications to get new HSL values + newHSL = types.hsl.set { + inherit (hslSet) h; # keep hue + l = math.clamp 0.0 1.0 (hslSet.l + (modifications.l or 0.0)); + s = math.clamp 0.0 1.0 (hslSet.s + (modifications.s or 0.0)); + }; + # convert back to hex + rgbSet = translate.hsl.toRGB.set newHSL; + in + translate.rgb.toHex.string rgbSet; + + lighten = amount: hexStr: + modifyHSL hexStr {l = amount / 100.0;}; + + darken = amount: hexStr: + modifyHSL hexStr {l = (amount * -1) / 100.0;}; + + saturate = amount: hexStr: + modifyHSL hexStr {s = amount / 100.0;}; + + desaturate = amount: hexStr: + modifyHSL hexStr {s = (amount * -1) / 100.0;}; + + mkDarkColorScale = base: { + up4 = desaturate 24 (lighten 12 base); + up3 = desaturate 18 (lighten 9 base); + up2 = desaturate 12 (lighten 6 base); + up1 = desaturate 6 (lighten 3 base); + inherit base; + down1 = desaturate 6 (darken 3 base); + down2 = desaturate 12 (darken 6 base); + down3 = desaturate 18 (darken 9 base); + down4 = desaturate 24 (darken 12 base); + }; + + mkLightColorScale = base: { + down4 = desaturate 24 (lighten 12 base); + down3 = desaturate 18 (lighten 9 base); + down2 = desaturate 12 (lighten 6 base); + down1 = desaturate 6 (lighten 3 base); + inherit base; + up1 = desaturate 6 (darken 3 base); + up2 = desaturate 12 (darken 6 base); + up3 = desaturate 18 (darken 9 base); + up4 = desaturate 24 (darken 12 base); + }; + + mkDarkColorScheme = { + shades, + primary, + secondary, + red, + orange, + yellow, + olive, + green, + teal, + blue, + violet, + purple, + pink, + brown, + } @ args: { + shade-50 = args.shades."50"; + shade-100 = args.shades."100"; + shade-150 = args.shades."150"; + shade-200 = args.shades."200"; + shade-250 = args.shades."250"; + shade-300 = args.shades."300"; + shade-350 = args.shades."350"; + shade-400 = args.shades."400"; + shade-450 = args.shades."450"; + shade-500 = args.shades."500"; + shade-550 = args.shades."550"; + shade-600 = args.shades."600"; + shade-650 = args.shades."650"; + shade-700 = args.shades."700"; + shade-750 = args.shades."750"; + shade-800 = args.shades."800"; + shade-850 = args.shades."850"; + shade-900 = args.shades."900"; + + primary = mkDarkColorScale args.primary; + secondary = { + up-1 = args.shade."550"; + up-2 = args.shade."500"; + up-3 = args.shade."450"; + up-4 = args.shade."400"; + up-5 = args.shade."350"; + up-6 = args.shade."300"; + up-7 = args.shade."250"; + up-8 = args.shade."200"; + up-9 = args.shade."150"; + up-10 = args.shade."100"; + base = args.shade."700"; + down-1 = args.shade."650"; + down-2 = args.shade."700"; + }; + red = mkDarkColorScale args.red; + orange = mkDarkColorScale args.orange; + yellow = mkDarkColorScale args.yellow; + olive = mkDarkColorScale args.olive; + green = mkDarkColorScale args.green; + teal = mkDarkColorScale args.teal; + blue = mkDarkColorScale args.blue; + violet = mkDarkColorScale args.violet; + purple = mkDarkColorScale args.purple; + pink = mkDarkColorScale args.pink; + brown = mkDarkColorScale args.brown; + }; +in { + inherit lighten darken saturate desaturate mkLightColorScale mkDarkColorScale mkDarkColorScheme; +} diff --git a/outputs/lib/default.nix b/outputs/lib/default.nix index 3fcc9bc..e2505b5 100644 --- a/outputs/lib/default.nix +++ b/outputs/lib/default.nix @@ -4,10 +4,30 @@ inputs, ... }: let - # My person functions + # my scuffed lib ook-lib = { builders = import ./builders.nix {inherit self lib inputs;}; mkNeovim = import ./mkNeovim.nix {inherit inputs;}; + math = import ./math.nix {inherit lib;}; + color = let + check = import ./color/check.nix {inherit lib;}; + types = import ./color/types.nix { + inherit (ook-lib) math; + inherit check; + }; + translate = import ./color/translate.nix { + inherit lib; + inherit (ook-lib) math; + inherit types; + }; + utils = import ./color/utils.nix { + inherit (ook-lib) math; + inherit types translate; + }; + in { + inherit check types translate; + inherit (utils) lighten darken saturate desaturate mkColorScale; + }; }; in { _module.args.ook.lib = ook-lib; diff --git a/outputs/lib/math.nix b/outputs/lib/math.nix new file mode 100644 index 0000000..ae66b6f --- /dev/null +++ b/outputs/lib/math.nix @@ -0,0 +1,46 @@ +{lib}: let + inherit (lib) min max; + inherit (builtins) floor ceil; + + # basic math functions + # credits to github:xddxdd/nix-math + + abs = x: + if x < 0 + then 0 - x + else x; + + clamp = a: b: v: min (max v (min a b)) (max a b); + + round = x: + if (x - floor x) < 0.5 + then floor x + else ceil x; + + hasFraction = x: let + splitted = lib.splitString "." (builtins.toString x); + in + builtins.length splitted >= 2 && builtins.length (builtins.filter (ch: ch != "0") (lib.stringToCharacters (builtins.elemAt splitted 1))) > 0; + + div = a: b: let + divideExactly = !(hasFraction (1.0 * a / b)); + offset = + if divideExactly + then 0 + else (0 - 1); + in + if b < 0 + then offset - div a (0 - b) + else if a < 0 + then offset - div (0 - a) b + else floor (1.0 * a / b); + + mod = a: b: + if b < 0 + then 0 - mod (0 - a) (0 - b) + else if a < 0 + then mod (b - mod (0 - a) b) b + else a - b * (div a b); +in { + inherit round mod abs hasFraction clamp; +} From 133b184e7087fd62f8cbcc88f13e20f3f9b21f1f Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 7 Nov 2024 13:27:06 +1100 Subject: [PATCH 006/213] test: generated docs --- outputs/hozen/default.nix | 10 + outputs/hozen/readme.md | 536 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 546 insertions(+) create mode 100644 outputs/hozen/default.nix create mode 100644 outputs/hozen/readme.md diff --git a/outputs/hozen/default.nix b/outputs/hozen/default.nix new file mode 100644 index 0000000..049f527 --- /dev/null +++ b/outputs/hozen/default.nix @@ -0,0 +1,10 @@ +{ook, ...}: let + style = { + color = import ./dark.nix {inherit ook;}; + light.color = import ./light.nix {inherit ook;}; + dark.color = import ./dark.nix {inherit ook;}; + }; +in { + _module.args.sytle = style; + flake.style = style; +} diff --git a/outputs/hozen/readme.md b/outputs/hozen/readme.md new file mode 100644 index 0000000..20e83a4 --- /dev/null +++ b/outputs/hozen/readme.md @@ -0,0 +1,536 @@ +# Color Scheme Documentation + +## Color Preview + +### Base Colors + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| base00 | + + | #282828 | +| base01 | + + | #3f3b3b | +| base02 | + + | #585350 | +| base03 | + + | #7d6f64 | +| base04 | + + | #a49384 | +| base05 | + + | #d4be98 | +| base06 | + + | #d9c7a5 | +| base07 | + + | #dfd2b3 | +| base08 | + + | #ea6962 | +| base09 | + + | #e78a4e | +| base0A | + + | #d8a657 | +| base0B | + + | #a9b665 | +| base0C | + + | #89b482 | +| base0D | + + | #7daea3 | +| base0E | + + | #d3869b | +| base0F | + + | #a87757 | + +### Syntax Highlighting + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| boolean | + + | #d3869b | +| comment | + + | #a49384 | +| constant | + + | #89b482 | +| define | + + | #d3869b | +| exception | + + | #ea6962 | +| float | + + | #d3869b | +| function | + + | #a9b665 | +| identifier | + + | #7daea3 | +| include | + + | #d3869b | +| label | + + | #e78a4e | +| macro | + + | #89b482 | +| number | + + | #d3869b | +| operator | + + | #e78a4e | +| preCondit | + + | #d3869b | +| preproc | + + | #d3869b | +| special | + + | #d8a657 | +| specialChar | + + | #d8a657 | +| statement | + + | #ea6962 | +| storageClass | + + | #e78a4e | +| string | + + | #a9b665 | +| structure | + + | #e78a4e | +| tag | + + | #89b482 | +| todo | + + | #d3869b | +| type | + + | #d8a657 | + +### Semantic Colors + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| body | + + | #3f3b3b | +| border | + + | #d4be98 | +| border-active | + + | #d4be98 | +| border-inactive | + + | #585350 | +| footer | + + | #282828 | +| header | + + | #282828 | +| menu | + + | #282828 | +| subtext | + + | #a49384 | +| text | + + | #d4be98 | +| text-bright | + + | #d9c7a5 | + +## Color Scales + +### Color Scale: red + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| base | + + | #ea6962 | +| down1 | + + | #e2615b | +| down2 | + + | #d95a54 | +| down3 | + + | #d1544e | +| down4 | + + | #c64f49 | +| up1 | + + | #e77a74 | +| up2 | + + | #e58b86 | +| up3 | + + | #e39b96 | +| up4 | + + | #e3a9a6 | + +### Color Scale: orange + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| base | + + | #e78a4e | +| down1 | + + | #df8247 | +| down2 | + + | #d57b41 | +| down3 | + + | #cc743c | +| down4 | + + | #bc6e3c | +| up1 | + + | #e39461 | +| up2 | + + | #e19e73 | +| up3 | + + | #dea884 | +| up4 | + + | #ddb195 | + +### Color Scale: yellow + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| base | + + | #d8a657 | +| down1 | + + | #ce9e52 | +| down2 | + + | #c4964c | +| down3 | + + | #b88d49 | +| down4 | + + | #a7834b | +| up1 | + + | #d5ac69 | +| up2 | + + | #d3b17b | +| up3 | + + | #d3b78a | +| up4 | + + | #d3bc9a | + +### Color Scale: olive + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| base | + + | #b9b25f | +| down1 | + + | #ada75b | +| down2 | + + | #9e995b | +| down3 | + + | #8e8a5c | +| down4 | + + | #7e7b5d | +| up1 | + + | #b8b270 | +| up2 | + + | #b6b280 | +| up3 | + + | #b6b390 | +| up4 | + + | #b8b69e | + +### Color Scale: green + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| base | + + | #a9b665 | +| down1 | + + | #9eaa62 | +| down2 | + + | #939c60 | +| down3 | + + | #858c61 | +| down4 | + + | #787b62 | +| up1 | + + | #abb575 | +| up2 | + + | #adb486 | +| up3 | + + | #afb594 | +| up4 | + + | #b3b6a3 | + +### Color Scale: teal + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| base | + + | #89b482 | +| down1 | + + | #85a87e | +| down2 | + + | #819b7d | +| down3 | + + | #7e8d7b | +| down4 | + + | #7b7e7b | +| up1 | + + | #96b492 | +| up2 | + + | #a2b59f | +| up3 | + + | #aeb7ad | +| up4 | + + | #b9bab9 | + +### Color Scale: blue + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| base | + + | #7daea3 | +| down1 | + + | #7ba198 | +| down2 | + + | #79938e | +| down3 | + + | #788582 | +| down4 | + + | #777777 | +| up1 | + + | #8caea7 | +| up2 | + + | #9bafaa | +| up3 | + + | #a8b1af | +| up4 | + + | #b4b4b4 | + +### Color Scale: violet + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| base | + + | #d892c1 | +| down1 | + + | #cf8cb9 | +| down2 | + + | #c586b0 | +| down3 | + + | #bb81a8 | +| down4 | + + | #af7e9f | +| up1 | + + | #d8a1c6 | +| up2 | + + | #d9b0cc | +| up3 | + + | #dbbdd1 | +| up4 | + + | #dec9d7 | + +### Color Scale: purple + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| base | + + | #d3869b | +| down1 | + + | #ca8094 | +| down2 | + + | #bf7c8e | +| down3 | + + | #b47788 | +| down4 | + + | #a87482 | +| up1 | + + | #d395a6 | +| up2 | + + | #d3a4b1 | +| up3 | + + | #d4b3bc | +| up4 | + + | #d7bfc6 | + +### Color Scale: pink + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| base | + + | #cf91be | +| down1 | + + | #c58bb6 | +| down2 | + + | #bb87ac | +| down3 | + + | #af83a3 | +| down4 | + + | #a28099 | +| up1 | + + | #d0a0c2 | +| up2 | + + | #d0aec7 | +| up3 | + + | #d3bbcc | +| up4 | + + | #d6c8d2 | + +### Color Scale: brown + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| base | + + | #a87757 | +| down1 | + + | #977259 | +| down2 | + + | #876c5a | +| down3 | + + | #77665a | +| down4 | + + | #695f59 | +| up1 | + + | #a68168 | +| up2 | + + | #a58a79 | +| up3 | + + | #a59388 | +| up4 | + + | #a69d96 | From 0621d2c448781646bf8d64fd8800136baa37525b Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 7 Nov 2024 13:30:00 +1100 Subject: [PATCH 007/213] test: generated docs --- outputs/hozen/readme.md | 598 ++++++++++++++++++++-------------------- 1 file changed, 300 insertions(+), 298 deletions(-) diff --git a/outputs/hozen/readme.md b/outputs/hozen/readme.md index 20e83a4..5a02560 100644 --- a/outputs/hozen/readme.md +++ b/outputs/hozen/readme.md @@ -1,5 +1,7 @@ # Color Scheme Documentation +Generated documentation for the color scheme. + ## Color Preview ### Base Colors @@ -7,168 +9,168 @@ | Name | Preview | Hex | | ---- | ------- | --- | -| base00 | +| `base00` | ![282828]( - | #282828 | -| base01 | +) | `#282828` | +| `base01` | ![3f3b3b]( - | #3f3b3b | -| base02 | +) | `#3f3b3b` | +| `base02` | ![585350]( - | #585350 | -| base03 | +) | `#585350` | +| `base03` | ![7d6f64]( - | #7d6f64 | -| base04 | +) | `#7d6f64` | +| `base04` | ![a49384]( - | #a49384 | -| base05 | +) | `#a49384` | +| `base05` | ![d4be98]( - | #d4be98 | -| base06 | +) | `#d4be98` | +| `base06` | ![d9c7a5]( - | #d9c7a5 | -| base07 | +) | `#d9c7a5` | +| `base07` | ![dfd2b3]( - | #dfd2b3 | -| base08 | +) | `#dfd2b3` | +| `base08` | ![ea6962]( - | #ea6962 | -| base09 | +) | `#ea6962` | +| `base09` | ![e78a4e]( - | #e78a4e | -| base0A | +) | `#e78a4e` | +| `base0A` | ![d8a657]( - | #d8a657 | -| base0B | +) | `#d8a657` | +| `base0B` | ![a9b665]( - | #a9b665 | -| base0C | +) | `#a9b665` | +| `base0C` | ![89b482]( - | #89b482 | -| base0D | +) | `#89b482` | +| `base0D` | ![7daea3]( - | #7daea3 | -| base0E | +) | `#7daea3` | +| `base0E` | ![d3869b]( - | #d3869b | -| base0F | +) | `#d3869b` | +| `base0F` | ![a87757]( - | #a87757 | +) | `#a87757` | ### Syntax Highlighting | Name | Preview | Hex | | ---- | ------- | --- | -| boolean | +| `boolean` | ![d3869b]( - | #d3869b | -| comment | +) | `#d3869b` | +| `comment` | ![a49384]( - | #a49384 | -| constant | +) | `#a49384` | +| `constant` | ![89b482]( - | #89b482 | -| define | +) | `#89b482` | +| `define` | ![d3869b]( - | #d3869b | -| exception | +) | `#d3869b` | +| `exception` | ![ea6962]( - | #ea6962 | -| float | +) | `#ea6962` | +| `float` | ![d3869b]( - | #d3869b | -| function | +) | `#d3869b` | +| `function` | ![a9b665]( - | #a9b665 | -| identifier | +) | `#a9b665` | +| `identifier` | ![7daea3]( - | #7daea3 | -| include | +) | `#7daea3` | +| `include` | ![d3869b]( - | #d3869b | -| label | +) | `#d3869b` | +| `label` | ![e78a4e]( - | #e78a4e | -| macro | +) | `#e78a4e` | +| `macro` | ![89b482]( - | #89b482 | -| number | +) | `#89b482` | +| `number` | ![d3869b]( - | #d3869b | -| operator | +) | `#d3869b` | +| `operator` | ![e78a4e]( - | #e78a4e | -| preCondit | +) | `#e78a4e` | +| `preCondit` | ![d3869b]( - | #d3869b | -| preproc | +) | `#d3869b` | +| `preproc` | ![d3869b]( - | #d3869b | -| special | +) | `#d3869b` | +| `special` | ![d8a657]( - | #d8a657 | -| specialChar | +) | `#d8a657` | +| `specialChar` | ![d8a657]( - | #d8a657 | -| statement | +) | `#d8a657` | +| `statement` | ![ea6962]( - | #ea6962 | -| storageClass | +) | `#ea6962` | +| `storageClass` | ![e78a4e]( - | #e78a4e | -| string | +) | `#e78a4e` | +| `string` | ![a9b665]( - | #a9b665 | -| structure | +) | `#a9b665` | +| `structure` | ![e78a4e]( - | #e78a4e | -| tag | +) | `#e78a4e` | +| `tag` | ![89b482]( - | #89b482 | -| todo | +) | `#89b482` | +| `todo` | ![d3869b]( - | #d3869b | -| type | +) | `#d3869b` | +| `type` | ![d8a657]( - | #d8a657 | +) | `#d8a657` | ### Semantic Colors | Name | Preview | Hex | | ---- | ------- | --- | -| body | +| `body` | ![3f3b3b]( - | #3f3b3b | -| border | +) | `#3f3b3b` | +| `border` | ![d4be98]( - | #d4be98 | -| border-active | +) | `#d4be98` | +| `border-active` | ![d4be98]( - | #d4be98 | -| border-inactive | +) | `#d4be98` | +| `border-inactive` | ![585350]( - | #585350 | -| footer | +) | `#585350` | +| `footer` | ![282828]( - | #282828 | -| header | +) | `#282828` | +| `header` | ![282828]( - | #282828 | -| menu | +) | `#282828` | +| `menu` | ![282828]( - | #282828 | -| subtext | +) | `#282828` | +| `subtext` | ![a49384]( - | #a49384 | -| text | +) | `#a49384` | +| `text` | ![d4be98]( - | #d4be98 | -| text-bright | +) | `#d4be98` | +| `text-bright` | ![d9c7a5]( - | #d9c7a5 | +) | `#d9c7a5` | ## Color Scales @@ -177,360 +179,360 @@ | Name | Preview | Hex | | ---- | ------- | --- | -| base | +| `base` | ![ea6962]( - | #ea6962 | -| down1 | +) | `#ea6962` | +| `down1` | ![e2615b]( - | #e2615b | -| down2 | +) | `#e2615b` | +| `down2` | ![d95a54]( - | #d95a54 | -| down3 | +) | `#d95a54` | +| `down3` | ![d1544e]( - | #d1544e | -| down4 | +) | `#d1544e` | +| `down4` | ![c64f49]( - | #c64f49 | -| up1 | +) | `#c64f49` | +| `up1` | ![e77a74]( - | #e77a74 | -| up2 | +) | `#e77a74` | +| `up2` | ![e58b86]( - | #e58b86 | -| up3 | +) | `#e58b86` | +| `up3` | ![e39b96]( - | #e39b96 | -| up4 | +) | `#e39b96` | +| `up4` | ![e3a9a6]( - | #e3a9a6 | +) | `#e3a9a6` | ### Color Scale: orange | Name | Preview | Hex | | ---- | ------- | --- | -| base | +| `base` | ![e78a4e]( - | #e78a4e | -| down1 | +) | `#e78a4e` | +| `down1` | ![df8247]( - | #df8247 | -| down2 | +) | `#df8247` | +| `down2` | ![d57b41]( - | #d57b41 | -| down3 | +) | `#d57b41` | +| `down3` | ![cc743c]( - | #cc743c | -| down4 | +) | `#cc743c` | +| `down4` | ![bc6e3c]( - | #bc6e3c | -| up1 | +) | `#bc6e3c` | +| `up1` | ![e39461]( - | #e39461 | -| up2 | +) | `#e39461` | +| `up2` | ![e19e73]( - | #e19e73 | -| up3 | +) | `#e19e73` | +| `up3` | ![dea884]( - | #dea884 | -| up4 | +) | `#dea884` | +| `up4` | ![ddb195]( - | #ddb195 | +) | `#ddb195` | ### Color Scale: yellow | Name | Preview | Hex | | ---- | ------- | --- | -| base | +| `base` | ![d8a657]( - | #d8a657 | -| down1 | +) | `#d8a657` | +| `down1` | ![ce9e52]( - | #ce9e52 | -| down2 | +) | `#ce9e52` | +| `down2` | ![c4964c]( - | #c4964c | -| down3 | +) | `#c4964c` | +| `down3` | ![b88d49]( - | #b88d49 | -| down4 | +) | `#b88d49` | +| `down4` | ![a7834b]( - | #a7834b | -| up1 | +) | `#a7834b` | +| `up1` | ![d5ac69]( - | #d5ac69 | -| up2 | +) | `#d5ac69` | +| `up2` | ![d3b17b]( - | #d3b17b | -| up3 | +) | `#d3b17b` | +| `up3` | ![d3b78a]( - | #d3b78a | -| up4 | +) | `#d3b78a` | +| `up4` | ![d3bc9a]( - | #d3bc9a | +) | `#d3bc9a` | ### Color Scale: olive | Name | Preview | Hex | | ---- | ------- | --- | -| base | +| `base` | ![b9b25f]( - | #b9b25f | -| down1 | +) | `#b9b25f` | +| `down1` | ![ada75b]( - | #ada75b | -| down2 | +) | `#ada75b` | +| `down2` | ![9e995b]( - | #9e995b | -| down3 | +) | `#9e995b` | +| `down3` | ![8e8a5c]( - | #8e8a5c | -| down4 | +) | `#8e8a5c` | +| `down4` | ![7e7b5d]( - | #7e7b5d | -| up1 | +) | `#7e7b5d` | +| `up1` | ![b8b270]( - | #b8b270 | -| up2 | +) | `#b8b270` | +| `up2` | ![b6b280]( - | #b6b280 | -| up3 | +) | `#b6b280` | +| `up3` | ![b6b390]( - | #b6b390 | -| up4 | +) | `#b6b390` | +| `up4` | ![b8b69e]( - | #b8b69e | +) | `#b8b69e` | ### Color Scale: green | Name | Preview | Hex | | ---- | ------- | --- | -| base | +| `base` | ![a9b665]( - | #a9b665 | -| down1 | +) | `#a9b665` | +| `down1` | ![9eaa62]( - | #9eaa62 | -| down2 | +) | `#9eaa62` | +| `down2` | ![939c60]( - | #939c60 | -| down3 | +) | `#939c60` | +| `down3` | ![858c61]( - | #858c61 | -| down4 | +) | `#858c61` | +| `down4` | ![787b62]( - | #787b62 | -| up1 | +) | `#787b62` | +| `up1` | ![abb575]( - | #abb575 | -| up2 | +) | `#abb575` | +| `up2` | ![adb486]( - | #adb486 | -| up3 | +) | `#adb486` | +| `up3` | ![afb594]( - | #afb594 | -| up4 | +) | `#afb594` | +| `up4` | ![b3b6a3]( - | #b3b6a3 | +) | `#b3b6a3` | ### Color Scale: teal | Name | Preview | Hex | | ---- | ------- | --- | -| base | +| `base` | ![89b482]( - | #89b482 | -| down1 | +) | `#89b482` | +| `down1` | ![85a87e]( - | #85a87e | -| down2 | +) | `#85a87e` | +| `down2` | ![819b7d]( - | #819b7d | -| down3 | +) | `#819b7d` | +| `down3` | ![7e8d7b]( - | #7e8d7b | -| down4 | +) | `#7e8d7b` | +| `down4` | ![7b7e7b]( - | #7b7e7b | -| up1 | +) | `#7b7e7b` | +| `up1` | ![96b492]( - | #96b492 | -| up2 | +) | `#96b492` | +| `up2` | ![a2b59f]( - | #a2b59f | -| up3 | +) | `#a2b59f` | +| `up3` | ![aeb7ad]( - | #aeb7ad | -| up4 | +) | `#aeb7ad` | +| `up4` | ![b9bab9]( - | #b9bab9 | +) | `#b9bab9` | ### Color Scale: blue | Name | Preview | Hex | | ---- | ------- | --- | -| base | +| `base` | ![7daea3]( - | #7daea3 | -| down1 | +) | `#7daea3` | +| `down1` | ![7ba198]( - | #7ba198 | -| down2 | +) | `#7ba198` | +| `down2` | ![79938e]( - | #79938e | -| down3 | +) | `#79938e` | +| `down3` | ![788582]( - | #788582 | -| down4 | +) | `#788582` | +| `down4` | ![777777]( - | #777777 | -| up1 | +) | `#777777` | +| `up1` | ![8caea7]( - | #8caea7 | -| up2 | +) | `#8caea7` | +| `up2` | ![9bafaa]( - | #9bafaa | -| up3 | +) | `#9bafaa` | +| `up3` | ![a8b1af]( - | #a8b1af | -| up4 | +) | `#a8b1af` | +| `up4` | ![b4b4b4]( - | #b4b4b4 | +) | `#b4b4b4` | ### Color Scale: violet | Name | Preview | Hex | | ---- | ------- | --- | -| base | +| `base` | ![d892c1]( - | #d892c1 | -| down1 | +) | `#d892c1` | +| `down1` | ![cf8cb9]( - | #cf8cb9 | -| down2 | +) | `#cf8cb9` | +| `down2` | ![c586b0]( - | #c586b0 | -| down3 | +) | `#c586b0` | +| `down3` | ![bb81a8]( - | #bb81a8 | -| down4 | +) | `#bb81a8` | +| `down4` | ![af7e9f]( - | #af7e9f | -| up1 | +) | `#af7e9f` | +| `up1` | ![d8a1c6]( - | #d8a1c6 | -| up2 | +) | `#d8a1c6` | +| `up2` | ![d9b0cc]( - | #d9b0cc | -| up3 | +) | `#d9b0cc` | +| `up3` | ![dbbdd1]( - | #dbbdd1 | -| up4 | +) | `#dbbdd1` | +| `up4` | ![dec9d7]( - | #dec9d7 | +) | `#dec9d7` | ### Color Scale: purple | Name | Preview | Hex | | ---- | ------- | --- | -| base | +| `base` | ![d3869b]( - | #d3869b | -| down1 | +) | `#d3869b` | +| `down1` | ![ca8094]( - | #ca8094 | -| down2 | +) | `#ca8094` | +| `down2` | ![bf7c8e]( - | #bf7c8e | -| down3 | +) | `#bf7c8e` | +| `down3` | ![b47788]( - | #b47788 | -| down4 | +) | `#b47788` | +| `down4` | ![a87482]( - | #a87482 | -| up1 | +) | `#a87482` | +| `up1` | ![d395a6]( - | #d395a6 | -| up2 | +) | `#d395a6` | +| `up2` | ![d3a4b1]( - | #d3a4b1 | -| up3 | +) | `#d3a4b1` | +| `up3` | ![d4b3bc]( - | #d4b3bc | -| up4 | +) | `#d4b3bc` | +| `up4` | ![d7bfc6]( - | #d7bfc6 | +) | `#d7bfc6` | ### Color Scale: pink | Name | Preview | Hex | | ---- | ------- | --- | -| base | +| `base` | ![cf91be]( - | #cf91be | -| down1 | +) | `#cf91be` | +| `down1` | ![c58bb6]( - | #c58bb6 | -| down2 | +) | `#c58bb6` | +| `down2` | ![bb87ac]( - | #bb87ac | -| down3 | +) | `#bb87ac` | +| `down3` | ![af83a3]( - | #af83a3 | -| down4 | +) | `#af83a3` | +| `down4` | ![a28099]( - | #a28099 | -| up1 | +) | `#a28099` | +| `up1` | ![d0a0c2]( - | #d0a0c2 | -| up2 | +) | `#d0a0c2` | +| `up2` | ![d0aec7]( - | #d0aec7 | -| up3 | +) | `#d0aec7` | +| `up3` | ![d3bbcc]( - | #d3bbcc | -| up4 | +) | `#d3bbcc` | +| `up4` | ![d6c8d2]( - | #d6c8d2 | +) | `#d6c8d2` | ### Color Scale: brown | Name | Preview | Hex | | ---- | ------- | --- | -| base | +| `base` | ![a87757]( - | #a87757 | -| down1 | +) | `#a87757` | +| `down1` | ![977259]( - | #977259 | -| down2 | +) | `#977259` | +| `down2` | ![876c5a]( - | #876c5a | -| down3 | +) | `#876c5a` | +| `down3` | ![77665a]( - | #77665a | -| down4 | +) | `#77665a` | +| `down4` | ![695f59]( - | #695f59 | -| up1 | +) | `#695f59` | +| `up1` | ![a68168]( - | #a68168 | -| up2 | +) | `#a68168` | +| `up2` | ![a58a79]( - | #a58a79 | -| up3 | +) | `#a58a79` | +| `up3` | ![a59388]( - | #a59388 | -| up4 | +) | `#a59388` | +| `up4` | ![a69d96]( - | #a69d96 | +) | `#a69d96` | From 723bf4d3675947e61d3c7ff90e061c6170387955 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 7 Nov 2024 13:35:07 +1100 Subject: [PATCH 008/213] test: generated docs --- outputs/hozen/readme.md | 668 +++++++++++++--------------------------- 1 file changed, 220 insertions(+), 448 deletions(-) diff --git a/outputs/hozen/readme.md b/outputs/hozen/readme.md index 5a02560..e0d2163 100644 --- a/outputs/hozen/readme.md +++ b/outputs/hozen/readme.md @@ -1,176 +1,116 @@ # Color Scheme Documentation -Generated documentation for the color scheme. +Generated on: 1730946863 + +## Table of Contents + +- [Neutral Shades](#neutral-shades) +- [Base Colors](#base-colors) +- [Syntax Highlighting](#syntax-highlighting) +- [Semantic Colors](#semantic-colors) +- [Color Scales](#color-scales) ## Color Preview +### Neutral Shades + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| `100` | | `#d9c7a5` | +| `150` | | `#d4be98` | +| `200` | | `#c6b395` | +| `250` | | `#b4a288` | +| `300` | | `#a49384` | +| `350` | | `#99897a` | +| `400` | | `#8b7c6f` | +| `450` | | `#7d6f64` | +| `50` | | `#dfd2b3` | +| `500` | | `#716860` | +| `550` | | `#645f59` | +| `600` | | `#585350` | +| `650` | | `#4d4947` | +| `700` | | `#3f3b3b` | +| `750` | | `#343232` | +| `800` | | `#282828` | +| `850` | | `#212121` | +| `900` | | `#1a1a1a` | + ### Base Colors | Name | Preview | Hex | | ---- | ------- | --- | -| `base00` | ![282828]( - -) | `#282828` | -| `base01` | ![3f3b3b]( - -) | `#3f3b3b` | -| `base02` | ![585350]( - -) | `#585350` | -| `base03` | ![7d6f64]( - -) | `#7d6f64` | -| `base04` | ![a49384]( - -) | `#a49384` | -| `base05` | ![d4be98]( - -) | `#d4be98` | -| `base06` | ![d9c7a5]( - -) | `#d9c7a5` | -| `base07` | ![dfd2b3]( - -) | `#dfd2b3` | -| `base08` | ![ea6962]( - -) | `#ea6962` | -| `base09` | ![e78a4e]( - -) | `#e78a4e` | -| `base0A` | ![d8a657]( - -) | `#d8a657` | -| `base0B` | ![a9b665]( - -) | `#a9b665` | -| `base0C` | ![89b482]( - -) | `#89b482` | -| `base0D` | ![7daea3]( - -) | `#7daea3` | -| `base0E` | ![d3869b]( - -) | `#d3869b` | -| `base0F` | ![a87757]( - -) | `#a87757` | +| `base00` | | `#282828` | +| `base01` | | `#3f3b3b` | +| `base02` | | `#585350` | +| `base03` | | `#7d6f64` | +| `base04` | | `#a49384` | +| `base05` | | `#d4be98` | +| `base06` | | `#d9c7a5` | +| `base07` | | `#dfd2b3` | +| `base08` | | `#ea6962` | +| `base09` | | `#e78a4e` | +| `base0A` | | `#d8a657` | +| `base0B` | | `#a9b665` | +| `base0C` | | `#89b482` | +| `base0D` | | `#7daea3` | +| `base0E` | | `#d3869b` | +| `base0F` | | `#a87757` | +| `base10` | | `#212121` | +| `base11` | | `#1a1a1a` | +| `base12` | | `#e58b86` | +| `base13` | | `#d3b17b` | +| `base14` | | `#adb486` | +| `base15` | | `#a2b59f` | +| `base16` | | `#9bafaa` | +| `base17` | | `#d3a4b1` | ### Syntax Highlighting | Name | Preview | Hex | | ---- | ------- | --- | -| `boolean` | ![d3869b]( - -) | `#d3869b` | -| `comment` | ![a49384]( - -) | `#a49384` | -| `constant` | ![89b482]( - -) | `#89b482` | -| `define` | ![d3869b]( - -) | `#d3869b` | -| `exception` | ![ea6962]( - -) | `#ea6962` | -| `float` | ![d3869b]( - -) | `#d3869b` | -| `function` | ![a9b665]( - -) | `#a9b665` | -| `identifier` | ![7daea3]( - -) | `#7daea3` | -| `include` | ![d3869b]( - -) | `#d3869b` | -| `label` | ![e78a4e]( - -) | `#e78a4e` | -| `macro` | ![89b482]( - -) | `#89b482` | -| `number` | ![d3869b]( - -) | `#d3869b` | -| `operator` | ![e78a4e]( - -) | `#e78a4e` | -| `preCondit` | ![d3869b]( - -) | `#d3869b` | -| `preproc` | ![d3869b]( - -) | `#d3869b` | -| `special` | ![d8a657]( - -) | `#d8a657` | -| `specialChar` | ![d8a657]( - -) | `#d8a657` | -| `statement` | ![ea6962]( - -) | `#ea6962` | -| `storageClass` | ![e78a4e]( - -) | `#e78a4e` | -| `string` | ![a9b665]( - -) | `#a9b665` | -| `structure` | ![e78a4e]( - -) | `#e78a4e` | -| `tag` | ![89b482]( - -) | `#89b482` | -| `todo` | ![d3869b]( - -) | `#d3869b` | -| `type` | ![d8a657]( - -) | `#d8a657` | +| `boolean` | | `#d3869b` | +| `comment` | | `#a49384` | +| `constant` | | `#89b482` | +| `define` | | `#d3869b` | +| `exception` | | `#ea6962` | +| `float` | | `#d3869b` | +| `function` | | `#a9b665` | +| `identifier` | | `#7daea3` | +| `include` | | `#d3869b` | +| `label` | | `#e78a4e` | +| `macro` | | `#89b482` | +| `number` | | `#d3869b` | +| `operator` | | `#e78a4e` | +| `preCondit` | | `#d3869b` | +| `preproc` | | `#d3869b` | +| `special` | | `#d8a657` | +| `specialChar` | | `#d8a657` | +| `statement` | | `#ea6962` | +| `storageClass` | | `#e78a4e` | +| `string` | | `#a9b665` | +| `structure` | | `#e78a4e` | +| `tag` | | `#89b482` | +| `todo` | | `#d3869b` | +| `type` | | `#d8a657` | ### Semantic Colors | Name | Preview | Hex | | ---- | ------- | --- | -| `body` | ![3f3b3b]( - -) | `#3f3b3b` | -| `border` | ![d4be98]( - -) | `#d4be98` | -| `border-active` | ![d4be98]( - -) | `#d4be98` | -| `border-inactive` | ![585350]( - -) | `#585350` | -| `footer` | ![282828]( - -) | `#282828` | -| `header` | ![282828]( - -) | `#282828` | -| `menu` | ![282828]( - -) | `#282828` | -| `subtext` | ![a49384]( - -) | `#a49384` | -| `text` | ![d4be98]( - -) | `#d4be98` | -| `text-bright` | ![d9c7a5]( - -) | `#d9c7a5` | +| `body` | | `#3f3b3b` | +| `border` | | `#d4be98` | +| `border-active` | | `#d4be98` | +| `border-inactive` | | `#585350` | +| `footer` | | `#282828` | +| `header` | | `#282828` | +| `menu` | | `#282828` | +| `subtext` | | `#a49384` | +| `text` | | `#d4be98` | +| `text-bright` | | `#d9c7a5` | ## Color Scales @@ -179,360 +119,192 @@ Generated documentation for the color scheme. | Name | Preview | Hex | | ---- | ------- | --- | -| `base` | ![ea6962]( - -) | `#ea6962` | -| `down1` | ![e2615b]( - -) | `#e2615b` | -| `down2` | ![d95a54]( - -) | `#d95a54` | -| `down3` | ![d1544e]( - -) | `#d1544e` | -| `down4` | ![c64f49]( - -) | `#c64f49` | -| `up1` | ![e77a74]( - -) | `#e77a74` | -| `up2` | ![e58b86]( - -) | `#e58b86` | -| `up3` | ![e39b96]( - -) | `#e39b96` | -| `up4` | ![e3a9a6]( - -) | `#e3a9a6` | +| `base` | | `#ea6962` | +| `down1` | | `#e2615b` | +| `down2` | | `#d95a54` | +| `down3` | | `#d1544e` | +| `down4` | | `#c64f49` | +| `up1` | | `#e77a74` | +| `up2` | | `#e58b86` | +| `up3` | | `#e39b96` | +| `up4` | | `#e3a9a6` | ### Color Scale: orange | Name | Preview | Hex | | ---- | ------- | --- | -| `base` | ![e78a4e]( - -) | `#e78a4e` | -| `down1` | ![df8247]( - -) | `#df8247` | -| `down2` | ![d57b41]( - -) | `#d57b41` | -| `down3` | ![cc743c]( - -) | `#cc743c` | -| `down4` | ![bc6e3c]( - -) | `#bc6e3c` | -| `up1` | ![e39461]( - -) | `#e39461` | -| `up2` | ![e19e73]( - -) | `#e19e73` | -| `up3` | ![dea884]( - -) | `#dea884` | -| `up4` | ![ddb195]( - -) | `#ddb195` | +| `base` | | `#e78a4e` | +| `down1` | | `#df8247` | +| `down2` | | `#d57b41` | +| `down3` | | `#cc743c` | +| `down4` | | `#bc6e3c` | +| `up1` | | `#e39461` | +| `up2` | | `#e19e73` | +| `up3` | | `#dea884` | +| `up4` | | `#ddb195` | ### Color Scale: yellow | Name | Preview | Hex | | ---- | ------- | --- | -| `base` | ![d8a657]( - -) | `#d8a657` | -| `down1` | ![ce9e52]( - -) | `#ce9e52` | -| `down2` | ![c4964c]( - -) | `#c4964c` | -| `down3` | ![b88d49]( - -) | `#b88d49` | -| `down4` | ![a7834b]( - -) | `#a7834b` | -| `up1` | ![d5ac69]( - -) | `#d5ac69` | -| `up2` | ![d3b17b]( - -) | `#d3b17b` | -| `up3` | ![d3b78a]( - -) | `#d3b78a` | -| `up4` | ![d3bc9a]( - -) | `#d3bc9a` | +| `base` | | `#d8a657` | +| `down1` | | `#ce9e52` | +| `down2` | | `#c4964c` | +| `down3` | | `#b88d49` | +| `down4` | | `#a7834b` | +| `up1` | | `#d5ac69` | +| `up2` | | `#d3b17b` | +| `up3` | | `#d3b78a` | +| `up4` | | `#d3bc9a` | ### Color Scale: olive | Name | Preview | Hex | | ---- | ------- | --- | -| `base` | ![b9b25f]( - -) | `#b9b25f` | -| `down1` | ![ada75b]( - -) | `#ada75b` | -| `down2` | ![9e995b]( - -) | `#9e995b` | -| `down3` | ![8e8a5c]( - -) | `#8e8a5c` | -| `down4` | ![7e7b5d]( - -) | `#7e7b5d` | -| `up1` | ![b8b270]( - -) | `#b8b270` | -| `up2` | ![b6b280]( - -) | `#b6b280` | -| `up3` | ![b6b390]( - -) | `#b6b390` | -| `up4` | ![b8b69e]( - -) | `#b8b69e` | +| `base` | | `#b9b25f` | +| `down1` | | `#ada75b` | +| `down2` | | `#9e995b` | +| `down3` | | `#8e8a5c` | +| `down4` | | `#7e7b5d` | +| `up1` | | `#b8b270` | +| `up2` | | `#b6b280` | +| `up3` | | `#b6b390` | +| `up4` | | `#b8b69e` | ### Color Scale: green | Name | Preview | Hex | | ---- | ------- | --- | -| `base` | ![a9b665]( - -) | `#a9b665` | -| `down1` | ![9eaa62]( - -) | `#9eaa62` | -| `down2` | ![939c60]( - -) | `#939c60` | -| `down3` | ![858c61]( - -) | `#858c61` | -| `down4` | ![787b62]( - -) | `#787b62` | -| `up1` | ![abb575]( - -) | `#abb575` | -| `up2` | ![adb486]( - -) | `#adb486` | -| `up3` | ![afb594]( - -) | `#afb594` | -| `up4` | ![b3b6a3]( - -) | `#b3b6a3` | +| `base` | | `#a9b665` | +| `down1` | | `#9eaa62` | +| `down2` | | `#939c60` | +| `down3` | | `#858c61` | +| `down4` | | `#787b62` | +| `up1` | | `#abb575` | +| `up2` | | `#adb486` | +| `up3` | | `#afb594` | +| `up4` | | `#b3b6a3` | ### Color Scale: teal | Name | Preview | Hex | | ---- | ------- | --- | -| `base` | ![89b482]( - -) | `#89b482` | -| `down1` | ![85a87e]( - -) | `#85a87e` | -| `down2` | ![819b7d]( - -) | `#819b7d` | -| `down3` | ![7e8d7b]( - -) | `#7e8d7b` | -| `down4` | ![7b7e7b]( - -) | `#7b7e7b` | -| `up1` | ![96b492]( - -) | `#96b492` | -| `up2` | ![a2b59f]( - -) | `#a2b59f` | -| `up3` | ![aeb7ad]( - -) | `#aeb7ad` | -| `up4` | ![b9bab9]( - -) | `#b9bab9` | +| `base` | | `#89b482` | +| `down1` | | `#85a87e` | +| `down2` | | `#819b7d` | +| `down3` | | `#7e8d7b` | +| `down4` | | `#7b7e7b` | +| `up1` | | `#96b492` | +| `up2` | | `#a2b59f` | +| `up3` | | `#aeb7ad` | +| `up4` | | `#b9bab9` | ### Color Scale: blue | Name | Preview | Hex | | ---- | ------- | --- | -| `base` | ![7daea3]( - -) | `#7daea3` | -| `down1` | ![7ba198]( - -) | `#7ba198` | -| `down2` | ![79938e]( - -) | `#79938e` | -| `down3` | ![788582]( - -) | `#788582` | -| `down4` | ![777777]( - -) | `#777777` | -| `up1` | ![8caea7]( - -) | `#8caea7` | -| `up2` | ![9bafaa]( - -) | `#9bafaa` | -| `up3` | ![a8b1af]( - -) | `#a8b1af` | -| `up4` | ![b4b4b4]( - -) | `#b4b4b4` | +| `base` | | `#7daea3` | +| `down1` | | `#7ba198` | +| `down2` | | `#79938e` | +| `down3` | | `#788582` | +| `down4` | | `#777777` | +| `up1` | | `#8caea7` | +| `up2` | | `#9bafaa` | +| `up3` | | `#a8b1af` | +| `up4` | | `#b4b4b4` | ### Color Scale: violet | Name | Preview | Hex | | ---- | ------- | --- | -| `base` | ![d892c1]( - -) | `#d892c1` | -| `down1` | ![cf8cb9]( - -) | `#cf8cb9` | -| `down2` | ![c586b0]( - -) | `#c586b0` | -| `down3` | ![bb81a8]( - -) | `#bb81a8` | -| `down4` | ![af7e9f]( - -) | `#af7e9f` | -| `up1` | ![d8a1c6]( - -) | `#d8a1c6` | -| `up2` | ![d9b0cc]( - -) | `#d9b0cc` | -| `up3` | ![dbbdd1]( - -) | `#dbbdd1` | -| `up4` | ![dec9d7]( - -) | `#dec9d7` | +| `base` | | `#d892c1` | +| `down1` | | `#cf8cb9` | +| `down2` | | `#c586b0` | +| `down3` | | `#bb81a8` | +| `down4` | | `#af7e9f` | +| `up1` | | `#d8a1c6` | +| `up2` | | `#d9b0cc` | +| `up3` | | `#dbbdd1` | +| `up4` | | `#dec9d7` | ### Color Scale: purple | Name | Preview | Hex | | ---- | ------- | --- | -| `base` | ![d3869b]( - -) | `#d3869b` | -| `down1` | ![ca8094]( - -) | `#ca8094` | -| `down2` | ![bf7c8e]( - -) | `#bf7c8e` | -| `down3` | ![b47788]( - -) | `#b47788` | -| `down4` | ![a87482]( - -) | `#a87482` | -| `up1` | ![d395a6]( - -) | `#d395a6` | -| `up2` | ![d3a4b1]( - -) | `#d3a4b1` | -| `up3` | ![d4b3bc]( - -) | `#d4b3bc` | -| `up4` | ![d7bfc6]( - -) | `#d7bfc6` | +| `base` | | `#d3869b` | +| `down1` | | `#ca8094` | +| `down2` | | `#bf7c8e` | +| `down3` | | `#b47788` | +| `down4` | | `#a87482` | +| `up1` | | `#d395a6` | +| `up2` | | `#d3a4b1` | +| `up3` | | `#d4b3bc` | +| `up4` | | `#d7bfc6` | ### Color Scale: pink | Name | Preview | Hex | | ---- | ------- | --- | -| `base` | ![cf91be]( - -) | `#cf91be` | -| `down1` | ![c58bb6]( - -) | `#c58bb6` | -| `down2` | ![bb87ac]( - -) | `#bb87ac` | -| `down3` | ![af83a3]( - -) | `#af83a3` | -| `down4` | ![a28099]( - -) | `#a28099` | -| `up1` | ![d0a0c2]( - -) | `#d0a0c2` | -| `up2` | ![d0aec7]( - -) | `#d0aec7` | -| `up3` | ![d3bbcc]( - -) | `#d3bbcc` | -| `up4` | ![d6c8d2]( - -) | `#d6c8d2` | +| `base` | | `#cf91be` | +| `down1` | | `#c58bb6` | +| `down2` | | `#bb87ac` | +| `down3` | | `#af83a3` | +| `down4` | | `#a28099` | +| `up1` | | `#d0a0c2` | +| `up2` | | `#d0aec7` | +| `up3` | | `#d3bbcc` | +| `up4` | | `#d6c8d2` | ### Color Scale: brown | Name | Preview | Hex | | ---- | ------- | --- | -| `base` | ![a87757]( - -) | `#a87757` | -| `down1` | ![977259]( - -) | `#977259` | -| `down2` | ![876c5a]( - -) | `#876c5a` | -| `down3` | ![77665a]( - -) | `#77665a` | -| `down4` | ![695f59]( - -) | `#695f59` | -| `up1` | ![a68168]( - -) | `#a68168` | -| `up2` | ![a58a79]( - -) | `#a58a79` | -| `up3` | ![a59388]( - -) | `#a59388` | -| `up4` | ![a69d96]( - -) | `#a69d96` | +| `base` | | `#a87757` | +| `down1` | | `#977259` | +| `down2` | | `#876c5a` | +| `down3` | | `#77665a` | +| `down4` | | `#695f59` | +| `up1` | | `#a68168` | +| `up2` | | `#a58a79` | +| `up3` | | `#a59388` | +| `up4` | | `#a69d96` | + +### Color Scale: primary + +| Name | Preview | Hex | +| ---- | ------- | --- | + +| `base` | | `#ea6962` | +| `down1` | | `#e2615b` | +| `down2` | | `#d95a54` | +| `down3` | | `#d1544e` | +| `down4` | | `#c64f49` | +| `up1` | | `#e77a74` | +| `up2` | | `#e58b86` | +| `up3` | | `#e39b96` | +| `up4` | | `#e3a9a6` | + +## Usage + +This color scheme is generated using Nix. To use these colors, you can: + +1. Import the color scheme directly in your Nix configuration +2. Generate theme files for your preferred applications +3. Use the hex values in your CSS/HTML + +## Notes + +- All colors are in hexadecimal format +- Preview squares show approximate colors (may vary by display) +- Neutral shades provide a range from lightest (50) to darkest (900) +- Color scales provide variations for UI elements From 11bd9a3671c49540a8675203d8b6f32a0b03421c Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 8 Nov 2024 16:35:01 +1100 Subject: [PATCH 009/213] hozen: add new color system --- outputs/default.nix | 1 + outputs/hozen/default.nix | 81 +++++++++- outputs/hozen/readme.md | 310 ------------------------------------ outputs/lib/builders.nix | 4 +- outputs/lib/color/utils.nix | 306 ++++++++++++++++++++++++++++------- outputs/lib/default.nix | 3 +- 6 files changed, 332 insertions(+), 373 deletions(-) delete mode 100644 outputs/hozen/readme.md diff --git a/outputs/default.nix b/outputs/default.nix index e662224..e82fb55 100644 --- a/outputs/default.nix +++ b/outputs/default.nix @@ -2,6 +2,7 @@ imports = [ ./apps.nix ./lib + ./hozen ./hosts ./keys.nix ./pkgs diff --git a/outputs/hozen/default.nix b/outputs/hozen/default.nix index 049f527..6360d82 100644 --- a/outputs/hozen/default.nix +++ b/outputs/hozen/default.nix @@ -1,10 +1,81 @@ {ook, ...}: let + inherit (ook.lib.color.utils) mkLightColorScheme mkDarkColorScheme; + + darkScheme = mkDarkColorScheme { + neutrals = { + "50" = "dfd2b3"; + "100" = "d9c7a5"; + "150" = "d4be98"; + "200" = "c6b395"; + "250" = "b4a288"; + "300" = "a49384"; + "350" = "99897a"; + "400" = "8b7c6f"; + "450" = "7d6f64"; + "500" = "716860"; + "550" = "645f59"; + "600" = "585350"; + "650" = "4d4947"; + "700" = "3f3b3b"; + "750" = "343232"; + "800" = "282828"; + "850" = "212121"; + "900" = "1a1a1a"; + }; + primary = "ea6962"; + red = "ea6962"; + orange = "e78a4e"; + yellow = "d8a657"; + olive = "b9b25f"; + green = "a9b665"; + teal = "89b482"; + blue = "7daea3"; + violet = "d892c1"; + purple = "d3869b"; + pink = "cf91be"; + brown = "a87757"; + }; + + lightScheme = mkLightColorScheme { + neutrals = { + "50" = "f7efda"; + "100" = "f4eac8"; + "150" = "f2e5bc"; + "200" = "e7d9b1"; + "250" = "ddcca6"; + "300" = "d3c19c"; + "350" = "c5b496"; + "400" = "b7a78f"; + "450" = "a89984"; + "500" = "a08e79"; + "550" = "9a826a"; + "600" = "91785f"; + "650" = "8a7056"; + "700" = "745a44"; + "750" = "6d4e3c"; + "800" = "654735"; + "850" = "5e4131"; + "900" = "51372a"; + }; + primary = "45707a"; + red = "be4141"; # contrast 4.55 + orange = "ad540b"; # contrast 4.52 + yellow = "966208"; # contrast 4.51 + olive = "707029"; # contrast 4.51 + green = "67732b"; # contrast 4.51 + teal = "497459"; # contrast 4.67 + blue = "45707a"; # contrast 4.75 + violet = "7d6198"; # contrast 4.54 + purple = "8f5b7c"; # contrast 4.63 + pink = "925d66"; # contrast 4.6 + brown = "654735"; # contrast 7.31 + }; style = { - color = import ./dark.nix {inherit ook;}; - light.color = import ./light.nix {inherit ook;}; - dark.color = import ./dark.nix {inherit ook;}; + color = darkScheme; + light.color = lightScheme; + dark.color = darkScheme; }; in { - _module.args.sytle = style; - flake.style = style; + _module.args.hozen = style; + flake.hozen = style; } diff --git a/outputs/hozen/readme.md b/outputs/hozen/readme.md deleted file mode 100644 index e0d2163..0000000 --- a/outputs/hozen/readme.md +++ /dev/null @@ -1,310 +0,0 @@ -# Color Scheme Documentation - -Generated on: 1730946863 - -## Table of Contents - -- [Neutral Shades](#neutral-shades) -- [Base Colors](#base-colors) -- [Syntax Highlighting](#syntax-highlighting) -- [Semantic Colors](#semantic-colors) -- [Color Scales](#color-scales) - -## Color Preview - -### Neutral Shades - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `100` | | `#d9c7a5` | -| `150` | | `#d4be98` | -| `200` | | `#c6b395` | -| `250` | | `#b4a288` | -| `300` | | `#a49384` | -| `350` | | `#99897a` | -| `400` | | `#8b7c6f` | -| `450` | | `#7d6f64` | -| `50` | | `#dfd2b3` | -| `500` | | `#716860` | -| `550` | | `#645f59` | -| `600` | | `#585350` | -| `650` | | `#4d4947` | -| `700` | | `#3f3b3b` | -| `750` | | `#343232` | -| `800` | | `#282828` | -| `850` | | `#212121` | -| `900` | | `#1a1a1a` | - -### Base Colors - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `base00` | | `#282828` | -| `base01` | | `#3f3b3b` | -| `base02` | | `#585350` | -| `base03` | | `#7d6f64` | -| `base04` | | `#a49384` | -| `base05` | | `#d4be98` | -| `base06` | | `#d9c7a5` | -| `base07` | | `#dfd2b3` | -| `base08` | | `#ea6962` | -| `base09` | | `#e78a4e` | -| `base0A` | | `#d8a657` | -| `base0B` | | `#a9b665` | -| `base0C` | | `#89b482` | -| `base0D` | | `#7daea3` | -| `base0E` | | `#d3869b` | -| `base0F` | | `#a87757` | -| `base10` | | `#212121` | -| `base11` | | `#1a1a1a` | -| `base12` | | `#e58b86` | -| `base13` | | `#d3b17b` | -| `base14` | | `#adb486` | -| `base15` | | `#a2b59f` | -| `base16` | | `#9bafaa` | -| `base17` | | `#d3a4b1` | - -### Syntax Highlighting - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `boolean` | | `#d3869b` | -| `comment` | | `#a49384` | -| `constant` | | `#89b482` | -| `define` | | `#d3869b` | -| `exception` | | `#ea6962` | -| `float` | | `#d3869b` | -| `function` | | `#a9b665` | -| `identifier` | | `#7daea3` | -| `include` | | `#d3869b` | -| `label` | | `#e78a4e` | -| `macro` | | `#89b482` | -| `number` | | `#d3869b` | -| `operator` | | `#e78a4e` | -| `preCondit` | | `#d3869b` | -| `preproc` | | `#d3869b` | -| `special` | | `#d8a657` | -| `specialChar` | | `#d8a657` | -| `statement` | | `#ea6962` | -| `storageClass` | | `#e78a4e` | -| `string` | | `#a9b665` | -| `structure` | | `#e78a4e` | -| `tag` | | `#89b482` | -| `todo` | | `#d3869b` | -| `type` | | `#d8a657` | - -### Semantic Colors - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `body` | | `#3f3b3b` | -| `border` | | `#d4be98` | -| `border-active` | | `#d4be98` | -| `border-inactive` | | `#585350` | -| `footer` | | `#282828` | -| `header` | | `#282828` | -| `menu` | | `#282828` | -| `subtext` | | `#a49384` | -| `text` | | `#d4be98` | -| `text-bright` | | `#d9c7a5` | - -## Color Scales - -### Color Scale: red - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `base` | | `#ea6962` | -| `down1` | | `#e2615b` | -| `down2` | | `#d95a54` | -| `down3` | | `#d1544e` | -| `down4` | | `#c64f49` | -| `up1` | | `#e77a74` | -| `up2` | | `#e58b86` | -| `up3` | | `#e39b96` | -| `up4` | | `#e3a9a6` | - -### Color Scale: orange - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `base` | | `#e78a4e` | -| `down1` | | `#df8247` | -| `down2` | | `#d57b41` | -| `down3` | | `#cc743c` | -| `down4` | | `#bc6e3c` | -| `up1` | | `#e39461` | -| `up2` | | `#e19e73` | -| `up3` | | `#dea884` | -| `up4` | | `#ddb195` | - -### Color Scale: yellow - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `base` | | `#d8a657` | -| `down1` | | `#ce9e52` | -| `down2` | | `#c4964c` | -| `down3` | | `#b88d49` | -| `down4` | | `#a7834b` | -| `up1` | | `#d5ac69` | -| `up2` | | `#d3b17b` | -| `up3` | | `#d3b78a` | -| `up4` | | `#d3bc9a` | - -### Color Scale: olive - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `base` | | `#b9b25f` | -| `down1` | | `#ada75b` | -| `down2` | | `#9e995b` | -| `down3` | | `#8e8a5c` | -| `down4` | | `#7e7b5d` | -| `up1` | | `#b8b270` | -| `up2` | | `#b6b280` | -| `up3` | | `#b6b390` | -| `up4` | | `#b8b69e` | - -### Color Scale: green - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `base` | | `#a9b665` | -| `down1` | | `#9eaa62` | -| `down2` | | `#939c60` | -| `down3` | | `#858c61` | -| `down4` | | `#787b62` | -| `up1` | | `#abb575` | -| `up2` | | `#adb486` | -| `up3` | | `#afb594` | -| `up4` | | `#b3b6a3` | - -### Color Scale: teal - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `base` | | `#89b482` | -| `down1` | | `#85a87e` | -| `down2` | | `#819b7d` | -| `down3` | | `#7e8d7b` | -| `down4` | | `#7b7e7b` | -| `up1` | | `#96b492` | -| `up2` | | `#a2b59f` | -| `up3` | | `#aeb7ad` | -| `up4` | | `#b9bab9` | - -### Color Scale: blue - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `base` | | `#7daea3` | -| `down1` | | `#7ba198` | -| `down2` | | `#79938e` | -| `down3` | | `#788582` | -| `down4` | | `#777777` | -| `up1` | | `#8caea7` | -| `up2` | | `#9bafaa` | -| `up3` | | `#a8b1af` | -| `up4` | | `#b4b4b4` | - -### Color Scale: violet - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `base` | | `#d892c1` | -| `down1` | | `#cf8cb9` | -| `down2` | | `#c586b0` | -| `down3` | | `#bb81a8` | -| `down4` | | `#af7e9f` | -| `up1` | | `#d8a1c6` | -| `up2` | | `#d9b0cc` | -| `up3` | | `#dbbdd1` | -| `up4` | | `#dec9d7` | - -### Color Scale: purple - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `base` | | `#d3869b` | -| `down1` | | `#ca8094` | -| `down2` | | `#bf7c8e` | -| `down3` | | `#b47788` | -| `down4` | | `#a87482` | -| `up1` | | `#d395a6` | -| `up2` | | `#d3a4b1` | -| `up3` | | `#d4b3bc` | -| `up4` | | `#d7bfc6` | - -### Color Scale: pink - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `base` | | `#cf91be` | -| `down1` | | `#c58bb6` | -| `down2` | | `#bb87ac` | -| `down3` | | `#af83a3` | -| `down4` | | `#a28099` | -| `up1` | | `#d0a0c2` | -| `up2` | | `#d0aec7` | -| `up3` | | `#d3bbcc` | -| `up4` | | `#d6c8d2` | - -### Color Scale: brown - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `base` | | `#a87757` | -| `down1` | | `#977259` | -| `down2` | | `#876c5a` | -| `down3` | | `#77665a` | -| `down4` | | `#695f59` | -| `up1` | | `#a68168` | -| `up2` | | `#a58a79` | -| `up3` | | `#a59388` | -| `up4` | | `#a69d96` | - -### Color Scale: primary - -| Name | Preview | Hex | -| ---- | ------- | --- | - -| `base` | | `#ea6962` | -| `down1` | | `#e2615b` | -| `down2` | | `#d95a54` | -| `down3` | | `#d1544e` | -| `down4` | | `#c64f49` | -| `up1` | | `#e77a74` | -| `up2` | | `#e58b86` | -| `up3` | | `#e39b96` | -| `up4` | | `#e3a9a6` | - -## Usage - -This color scheme is generated using Nix. To use these colors, you can: - -1. Import the color scheme directly in your Nix configuration -2. Generate theme files for your preferred applications -3. Use the hex values in your CSS/HTML - -## Notes - -- All colors are in hexadecimal format -- Preview squares show approximate colors (may vary by display) -- Neutral shades provide a range from lightest (50) to darkest (900) -- Color scales provide variations for UI elements diff --git a/outputs/lib/builders.nix b/outputs/lib/builders.nix index f088b69..cd7822e 100644 --- a/outputs/lib/builders.nix +++ b/outputs/lib/builders.nix @@ -7,7 +7,7 @@ inherit (inputs) nixpkgs; inherit (lib) singleton recursiveUpdate mkDefault; inherit (builtins) concatLists; - inherit (self) keys; + inherit (self) hozen keys; hm = inputs.home-manager.nixosModules.home-manager; agenix = inputs.agenix.nixosModules.default; nixosModules = "${self}/modules/nixos"; @@ -44,7 +44,7 @@ mkNixos { specialArgs = recursiveUpdate { - inherit keys lib inputs self inputs' self'; + inherit hozen keys lib inputs self inputs' self'; } specialArgs; modules = concatLists [ diff --git a/outputs/lib/color/utils.nix b/outputs/lib/color/utils.nix index 1fa6938..7014169 100644 --- a/outputs/lib/color/utils.nix +++ b/outputs/lib/color/utils.nix @@ -3,17 +3,14 @@ types, translate, }: let - # base modification function + # Base modification functions modifyHSL = hexStr: modifications: let - # convert hex to HSL hslSet = translate.hex.toHSL.set hexStr; - # apply modifications to get new HSL values newHSL = types.hsl.set { - inherit (hslSet) h; # keep hue + inherit (hslSet) h; l = math.clamp 0.0 1.0 (hslSet.l + (modifications.l or 0.0)); s = math.clamp 0.0 1.0 (hslSet.s + (modifications.s or 0.0)); }; - # convert back to hex rgbSet = translate.hsl.toRGB.set newHSL; in translate.rgb.toHex.string rgbSet; @@ -30,6 +27,8 @@ desaturate = amount: hexStr: modifyHSL hexStr {s = (amount * -1) / 100.0;}; + # opinionated scale generators for light/dark themes + # lighter/darker shades always desaturate mkDarkColorScale = base: { up4 = desaturate 24 (lighten 12 base); up3 = desaturate 18 (lighten 9 base); @@ -54,10 +53,11 @@ up4 = desaturate 24 (darken 12 base); }; - mkDarkColorScheme = { - shades, + # core color scheme generator + mkColorScheme = { + type ? "dark", + neutrals ? {}, primary, - secondary, red, orange, yellow, @@ -69,54 +69,252 @@ purple, pink, brown, - } @ args: { - shade-50 = args.shades."50"; - shade-100 = args.shades."100"; - shade-150 = args.shades."150"; - shade-200 = args.shades."200"; - shade-250 = args.shades."250"; - shade-300 = args.shades."300"; - shade-350 = args.shades."350"; - shade-400 = args.shades."400"; - shade-450 = args.shades."450"; - shade-500 = args.shades."500"; - shade-550 = args.shades."550"; - shade-600 = args.shades."600"; - shade-650 = args.shades."650"; - shade-700 = args.shades."700"; - shade-750 = args.shades."750"; - shade-800 = args.shades."800"; - shade-850 = args.shades."850"; - shade-900 = args.shades."900"; + } @ args: let + # Select scale function based on theme type + colorScale = + if type == "dark" + then mkDarkColorScale + else mkLightColorScale; - primary = mkDarkColorScale args.primary; - secondary = { - up-1 = args.shade."550"; - up-2 = args.shade."500"; - up-3 = args.shade."450"; - up-4 = args.shade."400"; - up-5 = args.shade."350"; - up-6 = args.shade."300"; - up-7 = args.shade."250"; - up-8 = args.shade."200"; - up-9 = args.shade."150"; - up-10 = args.shade."100"; - base = args.shade."700"; - down-1 = args.shade."650"; - down-2 = args.shade."700"; + # Generate color scales + colorScales = { + red = colorScale args.red; + orange = colorScale args.orange; + yellow = colorScale args.yellow; + olive = colorScale args.olive; + green = colorScale args.green; + teal = colorScale args.teal; + blue = colorScale args.blue; + violet = colorScale args.violet; + purple = colorScale args.purple; + pink = colorScale args.pink; + brown = colorScale args.brown; }; - red = mkDarkColorScale args.red; - orange = mkDarkColorScale args.orange; - yellow = mkDarkColorScale args.yellow; - olive = mkDarkColorScale args.olive; - green = mkDarkColorScale args.green; - teal = mkDarkColorScale args.teal; - blue = mkDarkColorScale args.blue; - violet = mkDarkColorScale args.violet; - purple = mkDarkColorScale args.purple; - pink = mkDarkColorScale args.pink; - brown = mkDarkColorScale args.brown; + + # Theme-specific configurations + themeConfig = + if type == "dark" + then { + semantic = { + body = args.neutrals."700"; + header = args.neutrals."800"; + footer = args.neutrals."800"; + menu = args.neutrals."800"; + border = args.neutrals."150"; + border-active = args.neutrals."150"; + border-inactive = args.neutrals."600"; + text = args.neutrals."150"; + text-bright = args.neutrals."100"; + subtext = args.neutrals."300"; + }; + secondary = { + up-4 = args.neutrals."400"; + up-3 = args.neutrals."450"; + up-2 = args.neutrals."500"; + up-1 = args.neutrals."550"; + base = args.neutrals."700"; + down-1 = args.neutrals."750"; + down-2 = args.neutrals."800"; + down-3 = args.neutrals."850"; + down-4 = args.neutrals."900"; + }; + base00 = args.neutrals."800"; + base01 = args.neutrals."700"; + base02 = args.neutrals."600"; + base03 = args.neutrals."450"; + base04 = args.neutrals."300"; + base05 = args.neutrals."150"; + base06 = args.neutrals."100"; + base07 = args.neutrals."50"; + base10 = args.neutrals."850"; + base11 = args.neutrals."900"; + } + else { + semantic = { + body = args.neutrals."50"; + header = args.neutrals."150"; + footer = args.neutrals."150"; + menu = args.neutrals."150"; + border = args.neutrals."800"; + border-active = args.neutrals."800"; + border-inactive = args.neutrals."300"; + text = args.neutrals."800"; + text-bright = args.neutrals."850"; + subtext = args.neutrals."600"; + }; + secondary = { + up-4 = args.neutrals."400"; + up-3 = args.neutrals."350"; + up-2 = args.neutrals."300"; + up-1 = args.neutrals."250"; + base = args.neutrals."200"; + down-1 = args.neutrals."150"; + down-2 = args.neutrals."100"; + down-3 = args.neutrals."50"; + down-4 = args.neutrals."50"; + }; + base00 = args.neutrals."150"; + base01 = args.neutrals."250"; + base02 = args.neutrals."450"; + base03 = args.neutrals."550"; + base04 = args.neutrals."650"; + base05 = args.neutrals."800"; + base06 = args.neutrals."850"; + base07 = args.neutrals."900"; + base10 = args.neutrals."100"; + base11 = args.neutrals."50"; + }; + in { + # Common structure for both themes + neutrals = { + inherit + (args.neutrals) + "50" + "100" + "150" + "200" + "250" + "300" + "350" + "400" + "450" + "500" + "550" + "600" + "650" + "700" + "750" + "800" + "850" + "900" + ; + }; + + inherit + (colorScales) + red + orange + yellow + olive + green + teal + blue + violet + purple + pink + brown + ; + + primary = colorScale args.primary; + + inherit (themeConfig) semantic secondary; + + # Status colors (same structure for both themes) + error = { + bg = "${colorScales.red.base}"; + bg-active = "${colorScales.red.down1}"; + bg-hover = "${colorScales.red.down2}"; + text = "${themeConfig.semantic.text-bright}"; + border = "${colorScales.red.up2}"; + }; + + success = { + bg = "${colorScales.green.base}"; + bg-active = "${colorScales.green.down1}"; + bg-hover = "${colorScales.green.down2}"; + text = "${themeConfig.semantic.text-bright}"; + border = "${colorScales.green.up2}"; + }; + + warning = { + bg = "${colorScales.yellow.base}"; + bg-active = "${colorScales.yellow.down1}"; + bg-hover = "${colorScales.yellow.down2}"; + text = "${themeConfig.semantic.text-bright}"; + border = "${colorScales.yellow.up2}"; + }; + + info = { + bg = "${colorScales.blue.base}"; + bg-active = "${colorScales.blue.down1}"; + bg-hover = "${colorScales.blue.down2}"; + text = "${themeConfig.semantic.text-bright}"; + border = "${colorScales.blue.up2}"; + }; + + tip = { + bg = "${colorScales.teal.base}"; + bg-active = "${colorScales.teal.down1}"; + bg-hover = "${colorScales.teal.down2}"; + text = "${themeConfig.semantic.text-bright}"; + border = "${colorScales.teal.up2}"; + }; + + # Syntax highlighting (same for both themes) + syntax = { + string = args.green; + number = args.purple; + float = args.purple; + boolean = args.purple; + type = args.yellow; + structure = args.orange; + statement = args.red; + label = args.orange; + operator = args.orange; + identifier = args.blue; + function = args.green; + storageClass = args.orange; + constant = args.teal; + exception = args.red; + preproc = args.purple; + include = args.purple; + define = args.purple; + macro = args.teal; + preCondit = args.purple; + special = args.yellow; + specialChar = args.yellow; + comment = "${themeConfig.semantic.subtext}"; + todo = args.purple; + tag = args.teal; + }; + + # Base16/24 colors + inherit + (themeConfig) + base00 + base01 + base02 + base03 + base04 + base05 + base06 + base07 + base10 + base11 + ; + + # Generated base colors + base08 = args.red; + base09 = args.orange; + base0A = args.yellow; + base0B = args.green; + base0C = args.teal; + base0D = args.blue; + base0E = args.purple; + base0F = args.brown; + base12 = "${colorScales.red.up2}"; + base13 = "${colorScales.yellow.up2}"; + base14 = "${colorScales.green.up2}"; + base15 = "${colorScales.teal.up2}"; + base16 = "${colorScales.blue.up2}"; + base17 = "${colorScales.purple.up2}"; }; + + # wrappers + mkDarkColorScheme = args: mkColorScheme (args // {type = "dark";}); + mkLightColorScheme = args: mkColorScheme (args // {type = "light";}); in { - inherit lighten darken saturate desaturate mkLightColorScale mkDarkColorScale mkDarkColorScheme; + inherit lighten darken saturate desaturate; + inherit mkDarkColorScale mkLightColorScale; + inherit mkColorScheme mkDarkColorScheme mkLightColorScheme; } diff --git a/outputs/lib/default.nix b/outputs/lib/default.nix index e2505b5..a6a7c1e 100644 --- a/outputs/lib/default.nix +++ b/outputs/lib/default.nix @@ -25,8 +25,7 @@ inherit types translate; }; in { - inherit check types translate; - inherit (utils) lighten darken saturate desaturate mkColorScale; + inherit check types translate utils; }; }; in { From 8e217a37689753285486cedaba61b8f89fa3ca62 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 8 Nov 2024 16:35:17 +1100 Subject: [PATCH 010/213] workstation: add waydroid --- modules/nixos/workstation/programs/default.nix | 1 + modules/nixos/workstation/programs/waydroid.nix | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 modules/nixos/workstation/programs/waydroid.nix diff --git a/modules/nixos/workstation/programs/default.nix b/modules/nixos/workstation/programs/default.nix index 3caa312..b8be726 100644 --- a/modules/nixos/workstation/programs/default.nix +++ b/modules/nixos/workstation/programs/default.nix @@ -3,5 +3,6 @@ ./1password.nix ./dconf.nix ./kdeconnect.nix + ./waydroid.nix ]; } diff --git a/modules/nixos/workstation/programs/waydroid.nix b/modules/nixos/workstation/programs/waydroid.nix new file mode 100644 index 0000000..45d1c3d --- /dev/null +++ b/modules/nixos/workstation/programs/waydroid.nix @@ -0,0 +1,7 @@ +{ + virtualisation = { + waydroid = { + enable = true; + }; + }; +} From dfc0084dd8067c12dadf8ef4d0fda949b3b71ae6 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 9 Nov 2024 22:49:38 +1100 Subject: [PATCH 011/213] home: increase mako warning width --- modules/home/workstation/hyprland/components/mako.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/home/workstation/hyprland/components/mako.nix b/modules/home/workstation/hyprland/components/mako.nix index e0bfe08..1f710de 100644 --- a/modules/home/workstation/hyprland/components/mako.nix +++ b/modules/home/workstation/hyprland/components/mako.nix @@ -28,7 +28,7 @@ in { height=100 [urgency=critical] padding=3,3 - width=100 + width=300 height=100 anchor=top-center border-color=#${palette.base08}dd From 5688d97e0c83d4491c8f7992f00423690b8d943e Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 9 Nov 2024 22:49:57 +1100 Subject: [PATCH 012/213] home: move foot color configuration -> hozen --- modules/home/workstation/terminal/foot.nix | 50 +++++++++++----------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/modules/home/workstation/terminal/foot.nix b/modules/home/workstation/terminal/foot.nix index b095dea..f1714eb 100644 --- a/modules/home/workstation/terminal/foot.nix +++ b/modules/home/workstation/terminal/foot.nix @@ -1,10 +1,12 @@ { osConfig, lib, + hozen, ... }: let inherit (osConfig.ooknet.appearance) colorscheme fonts; inherit (colorscheme) palette; + inherit (hozen) color; inherit (lib) mkMerge mkIf; inherit (osConfig.ooknet.workstation) default; cfg = osConfig.ooknet.workstation.programs.foot; @@ -41,30 +43,30 @@ in { colors = { alpha = 1.0; - foreground = "${palette.base05}"; - background = "${palette.base00}"; - regular0 = "${palette.base00}"; # black - regular1 = "${palette.red}"; # red - regular2 = "${palette.green}"; # green - regular3 = "${palette.yellow}"; # yellow - regular4 = "${palette.blue}"; # blue - regular5 = "${palette.purple}"; # magenta - regular6 = "${palette.cyan}"; # cyan - regular7 = "${palette.base05}"; # white - bright0 = "${palette.base03}"; # bright black - bright1 = "${palette.bright-red}"; # bright red - bright2 = "${palette.bright-green}"; # bright green - bright3 = "${palette.bright-yellow}"; # bright yellow - bright4 = "${palette.bright-blue}"; # bright blue - bright5 = "${palette.bright-purple}"; # bright magenta - bright6 = "${palette.bright-cyan}"; # bright cyan - bright7 = "${palette.base07}"; # bright white - "16" = "${palette.base09}"; - "17" = "${palette.base0F}"; - "18" = "${palette.base01}"; - "19" = "${palette.base02}"; - "20" = "${palette.base04}"; - "21" = "${palette.base06}"; + foreground = "${color.base05}"; + background = "${color.base00}"; + regular0 = "${color.base00}"; # black + regular1 = "${color.base08}"; # red + regular2 = "${color.base0B}"; # green + regular3 = "${color.base0A}"; # yellow + regular4 = "${color.base0D}"; # blue + regular5 = "${color.base0E}"; # magenta + regular6 = "${color.base0C}"; # cyan + regular7 = "${color.base05}"; # white + bright0 = "${color.base03}"; # bright black + bright1 = "${color.base08}"; # bright red + bright2 = "${color.base0B}"; # bright green + bright3 = "${color.base0A}"; # bright yellow + bright4 = "${color.base0D}"; # bright blue + bright5 = "${color.base0E}"; # bright magenta + bright6 = "${color.base0C}"; # bright cyan + bright7 = "${color.base07}"; # bright white + "16" = "${color.base09}"; + "17" = "${color.base0F}"; + "18" = "${color.base01}"; + "19" = "${color.base02}"; + "20" = "${color.base04}"; + "21" = "${color.base06}"; }; }; }; From e490c6be8e2a80422345f715dec49faf04efd0b9 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 9 Nov 2024 22:50:34 +1100 Subject: [PATCH 013/213] home: pass hozen arg to home-manager --- modules/nixos/base/home-manager.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/nixos/base/home-manager.nix b/modules/nixos/base/home-manager.nix index ceed372..ae6e4ee 100644 --- a/modules/nixos/base/home-manager.nix +++ b/modules/nixos/base/home-manager.nix @@ -5,6 +5,7 @@ self', lib, config, + hozen, ... }: let inherit (lib) mkIf; @@ -16,7 +17,7 @@ in { useUserPackages = true; backupFileExtension = "hm.old"; verbose = true; - extraSpecialArgs = {inherit inputs inputs' self self';}; + extraSpecialArgs = {inherit hozen inputs inputs' self self';}; users.${admin.name} = { imports = ["${self}/modules/home/base"]; }; From 44d58268acb5ff67910d034e2f86f80011bfd8fd Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 10 Nov 2024 23:06:27 +1100 Subject: [PATCH 014/213] nixos: add virtualization module --- modules/home/console/tools/default.nix | 1 + modules/home/console/tools/virtualization.nix | 19 ++++++ modules/nixos/workstation/default.nix | 1 + modules/nixos/workstation/options.nix | 2 +- .../workstation/virtualization/default.nix | 5 ++ .../virtualization/virt-manager.nix | 58 +++++++++++++++++++ 6 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 modules/home/console/tools/virtualization.nix create mode 100644 modules/nixos/workstation/virtualization/default.nix create mode 100644 modules/nixos/workstation/virtualization/virt-manager.nix diff --git a/modules/home/console/tools/default.nix b/modules/home/console/tools/default.nix index a65e3b4..b2f1a5f 100644 --- a/modules/home/console/tools/default.nix +++ b/modules/home/console/tools/default.nix @@ -1,5 +1,6 @@ { imports = [ + ./virtualization.nix ./bat.nix ./btop.nix ./git.nix diff --git a/modules/home/console/tools/virtualization.nix b/modules/home/console/tools/virtualization.nix new file mode 100644 index 0000000..18b96f7 --- /dev/null +++ b/modules/home/console/tools/virtualization.nix @@ -0,0 +1,19 @@ +{ + lib, + osConfig, + ... +}: let + inherit (lib) elem mkIf; + inherit (osConfig.ooknet.workstation) profiles; +in { + config = mkIf (elem "virtualization" profiles) { + # setup connections for virt-manager + # see + dconf.settings = { + "org/virt-manager/virt-manager/connections" = { + autoconnect = ["qemu:///system"]; + uris = ["qemu:///system"]; + }; + }; + }; +} diff --git a/modules/nixos/workstation/default.nix b/modules/nixos/workstation/default.nix index 8e3032b..fe1f519 100644 --- a/modules/nixos/workstation/default.nix +++ b/modules/nixos/workstation/default.nix @@ -14,6 +14,7 @@ in { ./programs ./gaming ./environment + ./virtualization ]; home-manager.users.${admin.name} = mkIf admin.homeManager { diff --git a/modules/nixos/workstation/options.nix b/modules/nixos/workstation/options.nix index aa01f16..f4e72a4 100644 --- a/modules/nixos/workstation/options.nix +++ b/modules/nixos/workstation/options.nix @@ -8,7 +8,7 @@ in { default = null; }; profiles = mkOption { - type = listOf (enum ["gaming" "communication" "productivity" "creative" "media"]); + type = listOf (enum ["gaming" "communication" "productivity" "creative" "media" "virtualization"]); default = []; }; environment = mkOption { diff --git a/modules/nixos/workstation/virtualization/default.nix b/modules/nixos/workstation/virtualization/default.nix new file mode 100644 index 0000000..9c7be83 --- /dev/null +++ b/modules/nixos/workstation/virtualization/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./virt-manager.nix + ]; +} diff --git a/modules/nixos/workstation/virtualization/virt-manager.nix b/modules/nixos/workstation/virtualization/virt-manager.nix new file mode 100644 index 0000000..3875726 --- /dev/null +++ b/modules/nixos/workstation/virtualization/virt-manager.nix @@ -0,0 +1,58 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (builtins) attrValues; + inherit (lib) mkIf elem; + inherit (config.ooknet.workstation) profiles; +in { + config = mkIf (elem "virtualization" profiles) { + environment.systemPackages = attrValues { + inherit + (pkgs) + virt-viewer + qemu_kvm + qemu + spice + spice-protocol + # for windows virtualization + + win-virtio + win-spice + ; + # virt-manager needs this + inherit (pkgs.gnome) adwaita-icon-theme; + }; + # sets up dconf settins for qemu and add virt-manager to systemPackages + programs.virt-manager = { + enable = true; + package = pkgs.virt-manager; + }; + virtualisation = { + # allow unprivileged users to pass usb devices to vm + spiceUSBRedirection.enable = true; + + # our virtualization daemon + libvirtd = { + enable = true; + + qemu = { + # by default this uses pkgs.qemu but since i do not need to emulate aarch64 currently i use + # qemu_kvm which only supports the hosts system architecture. + package = pkgs.qemu_kvm; + + # for emulating TPM + swtpm.enable = true; + + # UEFI secure boot + ovmf = { + enable = true; + packages = [pkgs.OVMFFull.fd]; + }; + }; + }; + }; + }; +} From 0329f7e4857b3ce5f398ac8a97a7699d25664f19 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 13 Nov 2024 12:51:39 +1100 Subject: [PATCH 015/213] ooksdesk: add virtualization profile --- hosts/ooksdesk/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/ooksdesk/default.nix b/hosts/ooksdesk/default.nix index 3ff6573..2437158 100644 --- a/hosts/ooksdesk/default.nix +++ b/hosts/ooksdesk/default.nix @@ -19,7 +19,7 @@ workstation = { environment = "hyprland"; theme = "minimal"; - profiles = ["gaming" "media" "communication" "productivity"]; + profiles = ["virtualization" "gaming" "media" "communication" "productivity"]; default = { browser = "firefox"; terminal = "foot"; From e84922c5f911a08acd12a9c244d11a64bed1dc24 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 13 Nov 2024 12:51:58 +1100 Subject: [PATCH 016/213] home: add btop theme --- modules/home/console/tools/btop.nix | 58 +++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/modules/home/console/tools/btop.nix b/modules/home/console/tools/btop.nix index f23188f..7ea9550 100644 --- a/modules/home/console/tools/btop.nix +++ b/modules/home/console/tools/btop.nix @@ -1,14 +1,72 @@ { lib, osConfig, + hozen, ... }: let inherit (lib) mkIf; + inherit (hozen) color; cfg = osConfig.ooknet.console.tools.btop; in { config = mkIf cfg.enable { programs.btop = { enable = true; + settings = { + theme_background = false; + color_theme = "${color.slug}"; + rounded_corners = false; + proc_gradient = false; + }; }; + xdg.configFile."btop/themes/${color.slug}.theme".text = '' + theme[main_bg]="#${color.layout.body}" + theme[main_fg]="#${color.typography.text}" + + theme[title]="#${color.typography.text}" + theme[hi_fg]="#${color.primary.base}" + theme[selected_bg]="#${color.typography.text}" + theme[selected_fg]="#${color.typography.contrast-text}" + theme[inactive_fg]="#${color.typography.contrast-text}" + + theme[graph_text]="#${color.typography.text}" + theme[proc_misc]="#${color.green.base}" + + theme[cpu_box]="#${color.secondary.base}" + theme[mem_box]="#${color.secondary.base}" + theme[proc_box]="#${color.secondary.base}" + theme[net_box]="#${color.secondary.base}" + + theme[temp_start]="#${color.green.base}" + theme[temp_mid]="#${color.orange.base}" + theme[temp_end]="#${color.red.base}" + + theme[cpu_start]="#${color.teal.base}" + theme[cpu_mid]="#${color.teal.hard1}" + theme[cpu_end]="#${color.teal.hard2}" + + theme[free_start]="#${color.blue.base}" + theme[free_mid]="#${color.blue.hard1}" + theme[free_end]="#${color.blue.hard2}" + + theme[available_start]="#${color.orange.base}" + theme[available_mid]="#${color.orange.hard1}" + theme[available_end]="#${color.orange.hard2}" + + theme[used_start]="#${color.green.base}" + theme[used_mid]="#${color.green.soft1}" + theme[used_end]="#${color.green.soft2}" + + theme[download_start]="#${color.purple.base}" + theme[download_mid]="#${color.purple.hard1}" + theme[download_end]="#${color.purple.hard2}" + + theme[upload_start]="#${color.yellow.base}" + theme[upload_mid]="#${color.yellow.hard1}" + theme[upload_end]="#${color.yellow.hard2}" + + theme[process_start]="#${color.green.base}" + theme[process_mid]="#${color.orange.base}" + theme[process_end]="#${color.red.base}" + ''; }; } From 0be36da274d58ae5389b17e4e797301d8df5a6db Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 13 Nov 2024 12:52:16 +1100 Subject: [PATCH 017/213] home: add networking tools to console --- modules/home/console/tools/default.nix | 1 + modules/home/console/tools/networking.nix | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 modules/home/console/tools/networking.nix diff --git a/modules/home/console/tools/default.nix b/modules/home/console/tools/default.nix index b2f1a5f..c29bf86 100644 --- a/modules/home/console/tools/default.nix +++ b/modules/home/console/tools/default.nix @@ -2,6 +2,7 @@ imports = [ ./virtualization.nix ./bat.nix + ./networking.nix ./btop.nix ./git.nix ./fzf.nix diff --git a/modules/home/console/tools/networking.nix b/modules/home/console/tools/networking.nix new file mode 100644 index 0000000..b776e42 --- /dev/null +++ b/modules/home/console/tools/networking.nix @@ -0,0 +1,13 @@ +{pkgs, ...}: let + inherit (builtins) attrValues; +in { + home.packages = attrValues { + inherit + (pkgs) + traceroute + mtr + dig + nmap + ; + }; +} From 86b4adb6e21d29acf0443575f1a45e1ff90863f7 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 13 Nov 2024 12:52:48 +1100 Subject: [PATCH 018/213] hyprland: add swaync init config --- .../hyprland/components/default.nix | 3 +- .../hyprland/components/swaync.nix | 48 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 modules/home/workstation/hyprland/components/swaync.nix diff --git a/modules/home/workstation/hyprland/components/default.nix b/modules/home/workstation/hyprland/components/default.nix index 493b34a..5e09b81 100644 --- a/modules/home/workstation/hyprland/components/default.nix +++ b/modules/home/workstation/hyprland/components/default.nix @@ -2,7 +2,8 @@ imports = [ ./rofi.nix ./hyprcapture.nix - ./mako.nix + # ./mako.nix + ./swaync.nix ./tools.nix ./waybar.nix ./hypridle.nix diff --git a/modules/home/workstation/hyprland/components/swaync.nix b/modules/home/workstation/hyprland/components/swaync.nix new file mode 100644 index 0000000..d1a8c44 --- /dev/null +++ b/modules/home/workstation/hyprland/components/swaync.nix @@ -0,0 +1,48 @@ +{ + hozen, + lib, + pkgs, + osConfig, + ... +}: let + inherit (osConfig.ooknet.appearance) fonts; + inherit (hozen) color; +in { + services.swaync = { + enable = true; + settings = { + positionX = "right"; + positionY = "top"; + layer = "overlay"; + control-center-layer = "top"; + layer-shell = true; + control-center-margin-top = 0; + control-center-margin-bottom = 0; + control-center-margin-right = 0; + control-center-margin-left = 0; + + notification-2fa-action = true; + notification-inline-replies = false; + notification-icon-size = 32; + notification-body-image-height = 100; + notification-body-image-width = 200; + }; + style = + /* + css + */ + '' + * { + font-family: ${fonts.monospace.family}; + font-size: 14px; + } + + .notification.critical { + border: 3px solid #${color.error.border}; + background-color: #${color.error.bg}; + color: #${color.error.fg}; + } + + ''; + }; +} From 0b671a475299ef1c19b1fe8991a164e9ffae840a Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 13 Nov 2024 12:53:11 +1100 Subject: [PATCH 019/213] hyprland: update shadow configuration --- .../hyprland/settings/appearance.nix | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/modules/home/workstation/hyprland/settings/appearance.nix b/modules/home/workstation/hyprland/settings/appearance.nix index 0b75aa7..2f06c55 100644 --- a/modules/home/workstation/hyprland/settings/appearance.nix +++ b/modules/home/workstation/hyprland/settings/appearance.nix @@ -1,6 +1,10 @@ -{osConfig, ...}: let - inherit (osConfig.ooknet.appearance) colorscheme cursor; - inherit (colorscheme) palette; +{ + osConfig, + hozen, + ... +}: let + inherit (osConfig.ooknet.appearance) cursor; + inherit (hozen) color; in { wayland.windowManager.hyprland = { settings = { @@ -11,8 +15,8 @@ in { gaps_in = 10; gaps_out = 10; border_size = 2; - "col.active_border" = "0xff${palette.base05}"; - "col.inactive_border" = "0xff${palette.base02}"; + "col.active_border" = "0xff${color.border.active}"; + "col.inactive_border" = "0xff${color.border.inactive}"; }; exec-once = [ @@ -30,14 +34,13 @@ in { enabled = false; ignore_opacity = true; }; - - drop_shadow = true; - shadow_range = 12; - shadow_offset = "3 3"; - "col.shadow" = "0x44000000"; - "col.shadow_inactive" = "0x66000000"; + shadow = { + range = 12; + offset = "3 3"; + color = "0x44000000"; + color_inactive = "0x66000000"; + }; }; - animations = { enabled = false; }; From 0d83bc4c2c3ffe4927eed8aec7be6fb006accaa8 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 13 Nov 2024 12:53:54 +1100 Subject: [PATCH 020/213] hyprland: add 1password quick access bind hyprland: add 1password quick access bind --- modules/home/workstation/binds.nix | 1 + modules/home/workstation/hyprland/settings/binds.nix | 1 + modules/home/workstation/tools/1password.nix | 5 ++++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/home/workstation/binds.nix b/modules/home/workstation/binds.nix index 589ff86..5e906a7 100644 --- a/modules/home/workstation/binds.nix +++ b/modules/home/workstation/binds.nix @@ -20,6 +20,7 @@ in { powerMenu = mkBind "No power menu is enabled"; lock = mkBind "No screen locker enabled"; password = mkBind "No password manager enabled"; + quickpass = mkBind "1Password module is not enabled"; zellijMenu = mkBind "Zellij Menu is not enabled"; factorio = mkBind "Gaming module is not enabled"; volume = { diff --git a/modules/home/workstation/hyprland/settings/binds.nix b/modules/home/workstation/hyprland/settings/binds.nix index f579687..4040286 100644 --- a/modules/home/workstation/hyprland/settings/binds.nix +++ b/modules/home/workstation/hyprland/settings/binds.nix @@ -8,6 +8,7 @@ in { "SUPER, return, exec, ${binds.terminal}" "SUPER, e, exec, ${binds.terminalLaunch} $EDITOR" "SUPERSHIFT, P, exec, ${binds.password}" + "SUPERCTRL, P, exec, ${binds.quickpass}" "SUPER, d, exec, ${binds.discord}" "SUPERSHIFT, e, exec, ${binds.fileManager}" "SUPERSHIFT, S, exec, ${binds.steam}" diff --git a/modules/home/workstation/tools/1password.nix b/modules/home/workstation/tools/1password.nix index 735a67e..4b8a57d 100644 --- a/modules/home/workstation/tools/1password.nix +++ b/modules/home/workstation/tools/1password.nix @@ -7,6 +7,9 @@ cfg = osConfig.programs._1password; in { config = mkIf cfg.enable { - ooknet.binds.password = "1password"; + ooknet.binds = { + password = "1password"; + quickpass = "1password --quick-access"; + }; }; } From 5284f668a277c3a0cff6ef7738c62a61e9b8adc2 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 13 Nov 2024 12:54:25 +1100 Subject: [PATCH 021/213] home: add nemo file-manager --- modules/home/workstation/tools/default.nix | 1 + modules/home/workstation/tools/nemo.nix | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 modules/home/workstation/tools/nemo.nix diff --git a/modules/home/workstation/tools/default.nix b/modules/home/workstation/tools/default.nix index ae307e7..bdf7eb3 100644 --- a/modules/home/workstation/tools/default.nix +++ b/modules/home/workstation/tools/default.nix @@ -6,5 +6,6 @@ ./kdeconnect.nix ./ookbrightness.nix ./zellijMenu.nix + ./nemo.nix ]; } diff --git a/modules/home/workstation/tools/nemo.nix b/modules/home/workstation/tools/nemo.nix new file mode 100644 index 0000000..9c5a88a --- /dev/null +++ b/modules/home/workstation/tools/nemo.nix @@ -0,0 +1,12 @@ +{pkgs, ...}: let + nemoMime = { + "inode/directory" = ["nemo.desktop"]; + }; +in { + home.packages = [pkgs.nemo-with-extensions]; + xdg.mimeApps = { + associations.added = nemoMime; + defaultApplications = nemoMime; + }; + ooknet.binds.fileManager = "nemo"; +} From c92c5be40102779f020fabbafbd3bfa7f96b1061 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 13 Nov 2024 12:54:46 +1100 Subject: [PATCH 022/213] nixos: swap to google dns from quad --- modules/nixos/base/networking.nix | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/modules/nixos/base/networking.nix b/modules/nixos/base/networking.nix index 6dfd0d9..fa9bffe 100644 --- a/modules/nixos/base/networking.nix +++ b/modules/nixos/base/networking.nix @@ -7,13 +7,8 @@ in { useDHCP = mkForce false; usePredictableInterfaceNames = mkDefault true; nameservers = [ - #quad9 IPv6 - "2620:fe::fe" - "2620:fe::9" - - #quad9 IPv4 - "9.9.9.9" - "149.112.112.112" + "8.8.8.8" + "8.8.4.4" ]; networkmanager = { enable = true; @@ -32,7 +27,7 @@ in { enable = true; domains = ["~."]; - fallbackDns = ["9.9.9.9"]; #quad9 + fallbackDns = ["8.8.8.8"]; # google dns }; }; systemd.services.NetworkManager-wait-online.enable = false; From 1874a33f840d3d3f983702547c129d3afc20e34c Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 13 Nov 2024 12:55:01 +1100 Subject: [PATCH 023/213] flake: update all --- flake.lock | 793 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 454 insertions(+), 339 deletions(-) diff --git a/flake.lock b/flake.lock index 3c92d63..a4552e9 100644 --- a/flake.lock +++ b/flake.lock @@ -41,11 +41,11 @@ ] }, "locked": { - "lastModified": 1729527199, - "narHash": "sha256-D5/YksfRga8Akd04ZtIkuYSIOjXVrAzQIQBSeplokzU=", + "lastModified": 1730968822, + "narHash": "sha256-NocDjINsh6ismkhb0Xr6xPRksmhuB2WGf8ZmXMhxu7Y=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "8d732fa8aff8b12ef2b1e2f00fc8153e41312b72", + "rev": "a49bc3583ff223f426cb3526fdaa4bcaa247ec14", "type": "github" }, "original": { @@ -56,11 +56,11 @@ }, "crane": { "locked": { - "lastModified": 1727974419, - "narHash": "sha256-WD0//20h+2/yPGkO88d2nYbb23WMWYvnRyDQ9Dx4UHg=", + "lastModified": 1730652660, + "narHash": "sha256-+XVYfmVXAiYA0FZT7ijHf555dxCe+AoAT5A6RU+6vSo=", "owner": "ipetkov", "repo": "crane", - "rev": "37e4f9f0976cb9281cd3f0c70081e5e0ecaee93f", + "rev": "a4ca93905455c07cb7e3aca95d4faf7601cba458", "type": "github" }, "original": { @@ -100,11 +100,11 @@ }, "locked": { "dir": "pkgs/firefox-addons", - "lastModified": 1730013417, - "narHash": "sha256-nZ6ylS3/FAjsi9wwdZJpzIV0+bgJDAurZAi0w9q1Nxw=", + "lastModified": 1731297786, + "narHash": "sha256-YC+FPREQqPF2HNSu1PkvVps5mBzexxvCV6NXfTf/kQI=", "owner": "rycee", "repo": "nur-expressions", - "rev": "e9ec8d2766bbe4d242c9255247197372ac64f885", + "rev": "85c8db7e7e901f656072b01f89c8fffcab26bfa6", "type": "gitlab" }, "original": { @@ -135,11 +135,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1727826117, - "narHash": "sha256-K5ZLCyfO/Zj9mPFldf3iwS6oZStJcU4tSpiXTMYaaL0=", + "lastModified": 1730504689, + "narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "3d04084d54bedc3d6b8b736c70ef449225c361b1", + "rev": "506278e768c2a08bec68eb62932193e341f55c90", "type": "github" }, "original": { @@ -153,11 +153,11 @@ "nixpkgs-lib": "nixpkgs-lib_2" }, "locked": { - "lastModified": 1715865404, - "narHash": "sha256-/GJvTdTpuDjNn84j82cU6bXztE0MSkdnTWClUCRub78=", + "lastModified": 1730504689, + "narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "8dc45382d5206bd292f9c2768b8058a8fd8311d9", + "rev": "506278e768c2a08bec68eb62932193e341f55c90", "type": "github" }, "original": { @@ -204,11 +204,11 @@ "systems": "systems_3" }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", "type": "github" }, "original": { @@ -285,11 +285,11 @@ ] }, "locked": { - "lastModified": 1730016908, - "narHash": "sha256-bFCxJco7d8IgmjfNExNz9knP8wvwbXU4s/d53KOK6U0=", + "lastModified": 1731235328, + "narHash": "sha256-NjavpgE9/bMe/ABvZpyHIUeYF1mqR5lhaep3wB79ucs=", "owner": "nix-community", "repo": "home-manager", - "rev": "e83414058edd339148dc142a8437edb9450574c8", + "rev": "60bb110917844d354f3c18e05450606a435d2d10", "type": "github" }, "original": { @@ -347,11 +347,11 @@ ] }, "locked": { - "lastModified": 1729679960, - "narHash": "sha256-RoFKwZsx4RHKUwO8LhEZtmI08VBVrWt3TdzoJgx1HJ0=", + "lastModified": 1730561387, + "narHash": "sha256-esE2L7+9CsmlSjTIHwU9VAhzvsFSMC3kO7EiutCPQpg=", "owner": "hyprwm", "repo": "hypridle", - "rev": "4d2fb9e73eb6b75336ed3eb198e900f94ada24f4", + "rev": "26780ac51f6e7273e3934885036b7a7ed1a5af01", "type": "github" }, "original": { @@ -374,11 +374,11 @@ "xdph": "xdph" }, "locked": { - "lastModified": 1730054738, - "narHash": "sha256-xU5DxVMZXFLcypIo6PvrLRI0+74kOrFTdEykDDEaEkQ=", + "lastModified": 1731340175, + "narHash": "sha256-qhkP+XRa1AuKkVrxKDLdK4gby363vH6wEie5tb6rz2E=", "owner": "hyprwm", "repo": "hyprland", - "rev": "5d4b54b01286c10d4b6bf402a772b5938b054ce6", + "rev": "f5fa84554ffe55e29a397014964238be89ffa54d", "type": "github" }, "original": { @@ -395,11 +395,11 @@ ] }, "locked": { - "lastModified": 1729224425, - "narHash": "sha256-w9dNUedNe2qnhHuhcRf7A1l29+/6DxdMfwN6g4U3c/w=", + "lastModified": 1730743354, + "narHash": "sha256-gU4NySYyXeAzVaF5bI6BKmj2CdgiwGFnuPjXUId3Dx0=", "owner": "hyprwm", "repo": "contrib", - "rev": "d72bc8b1cd30d448bd438e8328f8eeb4c0f2ddb6", + "rev": "792f6b83dc719214e0e2a0b380c34f147b28ece2", "type": "github" }, "original": { @@ -425,11 +425,11 @@ ] }, "locked": { - "lastModified": 1729596320, - "narHash": "sha256-sBPr6O2Ad916f+L7biAjmJVx4TLDITC4joKgeOT47V8=", + "lastModified": 1731169722, + "narHash": "sha256-hOljwsXpY4Y6guvcr51tWCnXo6c56yaBknnLXk1m3Vk=", "owner": "hyprwm", "repo": "hyprland-plugins", - "rev": "4d7f0b5d8b952f31f7d2e29af22ab0a55ca5c219", + "rev": "844eb98250da448e17471f20beed23a5f5d33a3a", "type": "github" }, "original": { @@ -512,11 +512,11 @@ ] }, "locked": { - "lastModified": 1730053985, - "narHash": "sha256-jh7PhejwT+XqkkYnpZ6K/Gkqy4tvjN7g/ZBTvlS+Q9Y=", + "lastModified": 1731340729, + "narHash": "sha256-xM+dVOJ5MXjaVfaZeUD2LHVaQXJUZfXhUCfEGEDW7rc=", "owner": "hyprwm", "repo": "hyprlock", - "rev": "edbecc87081756b45bdbea16b63e413473659dcd", + "rev": "c3c28feb4c6469269d049185e9427bf4a33c8c40", "type": "github" }, "original": { @@ -571,11 +571,11 @@ ] }, "locked": { - "lastModified": 1728941256, - "narHash": "sha256-WRypmcZ2Bw94lLmcmxYokVOHPJSZ7T06V49QZ4tkZeQ=", + "lastModified": 1731163338, + "narHash": "sha256-Qflei0JBeqQ0c8jxA8e982xAxJvfMwfx4Aci2eJi84s=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "fd4be8b9ca932f7384e454bcd923c5451ef2aa85", + "rev": "60d3dece30f98e8ad85131829c8529950630d6bc", "type": "github" }, "original": { @@ -636,11 +636,11 @@ }, "mnw": { "locked": { - "lastModified": 1726188505, - "narHash": "sha256-3dkxJo6y/aKfwkAg6YnpdiQAoZKgHhWHz7ilGJHCoVU=", + "lastModified": 1731182209, + "narHash": "sha256-yftvwv8bHEKjmSKREdkGLWTDhf7vA2Ssvl/XMpykigg=", "owner": "Gerg-L", "repo": "mnw", - "rev": "ea00b3d2162d85dd085a6ba6d49aa2a186e588e7", + "rev": "0a5e50286ca9f1b70eb4fa29ce84304cad657700", "type": "github" }, "original": { @@ -684,11 +684,11 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1714571717, - "narHash": "sha256-o4tqlTzi9kcVub167kTGXgCac9jM3kW4+v9MH/ue4Hk=", + "lastModified": 1726716330, + "narHash": "sha256-mIuOP4I51eFLquRaxMKx67pHmhatZrcVPjfHL98v/M8=", "owner": "oxalica", "repo": "nil", - "rev": "2f3ed6348bbf1440fcd1ab0411271497a0fbbfa4", + "rev": "c8e8ce72442a164d89d3fdeaae0bcc405f8c015a", "type": "github" }, "original": { @@ -719,11 +719,11 @@ ] }, "locked": { - "lastModified": 1729999765, - "narHash": "sha256-LYsavZXitFjjyETZoij8usXjTa7fa9AIF3Sk3MJSX+Y=", + "lastModified": 1731209121, + "narHash": "sha256-BF7FBh1hIYPDihdUlImHGsQzaJZVLLfYqfDx41wjuF0=", "owner": "nix-community", "repo": "nix-index-database", - "rev": "0e3a8778c2ee218eff8de6aacf3d2fa6c33b2d4f", + "rev": "896019f04b22ce5db4c0ee4f89978694f44345c3", "type": "github" }, "original": { @@ -750,26 +750,26 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1727825735, - "narHash": "sha256-0xHYkMkeLVQAMa7gvkddbPqpxph+hDzdu1XdGPJR+Os=", + "lastModified": 1730504152, + "narHash": "sha256-lXvH/vOfb4aGYyvFmZK/HlsNsr/0CVWlwYvo2rxJk3s=", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/fb192fec7cc7a4c26d51779e9bab07ce6fa5597a.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz" }, "original": { "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/fb192fec7cc7a4c26d51779e9bab07ce6fa5597a.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz" } }, "nixpkgs-lib_2": { "locked": { - "lastModified": 1714640452, - "narHash": "sha256-QBx10+k6JWz6u7VsohfSw8g8hjdBZEf8CFzXH1/1Z94=", + "lastModified": 1730504152, + "narHash": "sha256-lXvH/vOfb4aGYyvFmZK/HlsNsr/0CVWlwYvo2rxJk3s=", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/50eb7ecf4cd0a5756d7275c8ba36790e5bd53e33.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz" }, "original": { "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/50eb7ecf4cd0a5756d7275c8ba36790e5bd53e33.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz" } }, "nixpkgs-lib_3": { @@ -786,11 +786,11 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1720386169, - "narHash": "sha256-NGKVY4PjzwAa4upkGtAMz1npHGoRzWotlSnVlqI40mo=", + "lastModified": 1730741070, + "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "194846768975b7ad2c4988bdb82572c00222c0d7", + "rev": "d063c1dd113c91ab27959ba540c0d9753409edf3", "type": "github" }, "original": { @@ -802,11 +802,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1729413321, - "narHash": "sha256-I4tuhRpZFa6Fu6dcH9Dlo5LlH17peT79vx1y1SpeKt0=", + "lastModified": 1730785428, + "narHash": "sha256-Zwl8YgTVJTEum+L+0zVAWvXAGbWAuXHax3KzuejaDyo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "1997e4aa514312c1af7e2bda7fad1644e778ff26", + "rev": "4aa36568d413aca0ea84a1684d2d46f55dbabad7", "type": "github" }, "original": { @@ -818,11 +818,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1729880355, - "narHash": "sha256-RP+OQ6koQQLX5nw0NmcDrzvGL8HDLnyXt/jHhL1jwjM=", + "lastModified": 1731139594, + "narHash": "sha256-IigrKK3vYRpUu+HEjPL/phrfh7Ox881er1UEsZvw9Q4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "18536bf04cd71abd345f9579158841376fdd0c5a", + "rev": "76612b17c0ce71689921ca12d9ffdc9c23ce40b2", "type": "github" }, "original": { @@ -834,11 +834,11 @@ }, "nixpkgs_4": { "locked": { - "lastModified": 1726871744, - "narHash": "sha256-V5LpfdHyQkUF7RfOaDPrZDP+oqz88lTJrMT1+stXNwo=", + "lastModified": 1730958623, + "narHash": "sha256-JwQZIGSYnRNOgDDoIgqKITrPVil+RMWHsZH1eE1VGN0=", "owner": "nixos", "repo": "nixpkgs", - "rev": "a1d92660c6b3b7c26fb883500a80ea9d33321be2", + "rev": "85f7e662eda4fa3a995556527c87b2524b691933", "type": "github" }, "original": { @@ -866,11 +866,11 @@ }, "nixpkgs_6": { "locked": { - "lastModified": 1728061008, - "narHash": "sha256-qjyJDtwmJckqDyXHmBIiN04kzby/TX/kPYmclBXlROA=", + "lastModified": 1730272153, + "narHash": "sha256-B5WRZYsRlJgwVHIV6DvidFN7VX7Fg9uuwkRW9Ha8z+w=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8bca501bf31b54ae2022fe5065ab475d75f7560e", + "rev": "2d2a9ddbe3f2c00747398f3dc9b05f7f2ebb0f53", "type": "github" }, "original": { @@ -923,6 +923,7 @@ "plugin-copilot-cmp": "plugin-copilot-cmp", "plugin-copilot-lua": "plugin-copilot-lua", "plugin-crates-nvim": "plugin-crates-nvim", + "plugin-csharpls-extended": "plugin-csharpls-extended", "plugin-dashboard-nvim": "plugin-dashboard-nvim", "plugin-diffview-nvim": "plugin-diffview-nvim", "plugin-dracula": "plugin-dracula", @@ -949,6 +950,8 @@ "plugin-lua-utils-nvim": "plugin-lua-utils-nvim", "plugin-lualine": "plugin-lualine", "plugin-luasnip": "plugin-luasnip", + "plugin-lz-n": "plugin-lz-n", + "plugin-lzn-auto-require": "plugin-lzn-auto-require", "plugin-mind-nvim": "plugin-mind-nvim", "plugin-minimap-vim": "plugin-minimap-vim", "plugin-modes-nvim": "plugin-modes-nvim", @@ -978,6 +981,7 @@ "plugin-nvim-neoclip": "plugin-nvim-neoclip", "plugin-nvim-nio": "plugin-nvim-nio", "plugin-nvim-notify": "plugin-nvim-notify", + "plugin-nvim-scrollbar": "plugin-nvim-scrollbar", "plugin-nvim-session-manager": "plugin-nvim-session-manager", "plugin-nvim-surround": "plugin-nvim-surround", "plugin-nvim-tree-lua": "plugin-nvim-tree-lua", @@ -985,21 +989,24 @@ "plugin-nvim-ts-autotag": "plugin-nvim-ts-autotag", "plugin-nvim-web-devicons": "plugin-nvim-web-devicons", "plugin-obsidian-nvim": "plugin-obsidian-nvim", + "plugin-omnisharp-extended": "plugin-omnisharp-extended", "plugin-onedark": "plugin-onedark", "plugin-orgmode-nvim": "plugin-orgmode-nvim", "plugin-otter-nvim": "plugin-otter-nvim", "plugin-oxocarbon": "plugin-oxocarbon", "plugin-pathlib-nvim": "plugin-pathlib-nvim", "plugin-plenary-nvim": "plugin-plenary-nvim", + "plugin-precognition-nvim": "plugin-precognition-nvim", "plugin-project-nvim": "plugin-project-nvim", "plugin-registers": "plugin-registers", "plugin-rose-pine": "plugin-rose-pine", + "plugin-rtp-nvim": "plugin-rtp-nvim", "plugin-rustaceanvim": "plugin-rustaceanvim", - "plugin-scrollbar-nvim": "plugin-scrollbar-nvim", "plugin-smartcolumn": "plugin-smartcolumn", "plugin-sqls-nvim": "plugin-sqls-nvim", "plugin-tabular": "plugin-tabular", "plugin-telescope": "plugin-telescope", + "plugin-tiny-devicons-auto-colors": "plugin-tiny-devicons-auto-colors", "plugin-todo-comments": "plugin-todo-comments", "plugin-toggleterm-nvim": "plugin-toggleterm-nvim", "plugin-tokyonight": "plugin-tokyonight", @@ -1016,11 +1023,11 @@ "systems": "systems_4" }, "locked": { - "lastModified": 1729695103, - "narHash": "sha256-1nesOKIa7zAQ3LVbWzvoxRE9PG0P9SAzBi2Ye1K3SWU=", + "lastModified": 1731279011, + "narHash": "sha256-+U7Ew49J79l0mVfvPdyMnlFISVIgQTAKpdpipTKYQ2Q=", "owner": "notashelf", "repo": "nvf", - "rev": "da86e554a6433fe4ebdb390494c072b12b0b624b", + "rev": "12b650fea7bddcdf9773f3b6f831c59c7b660a75", "type": "github" }, "original": { @@ -1076,11 +1083,11 @@ "plugin-alpha-nvim": { "flake": false, "locked": { - "lastModified": 1708891191, - "narHash": "sha256-kTVPKZ/e1us/uHfSwFwR38lFYN8EotJq2jKz6xm/eqg=", + "lastModified": 1727720738, + "narHash": "sha256-33lhPP1C4TGo0UQJ61bwRHaiOMAB7XNehcZGaFXOPjQ=", "owner": "goolord", "repo": "alpha-nvim", - "rev": "41283fb402713fc8b327e60907f74e46166f4cfd", + "rev": "bf3c8bb8c02ed3d9644cc5bbc48e2bdc39349cd7", "type": "github" }, "original": { @@ -1124,11 +1131,11 @@ "plugin-catppuccin": { "flake": false, "locked": { - "lastModified": 1728131011, - "narHash": "sha256-j6F078taxuGzr3jngrc+Pc5I1kDdxTLMETgq6Xn4w/4=", + "lastModified": 1731169755, + "narHash": "sha256-lsnePejThsEygTCKV/rfJJ/h+RSrro91am841iznJe4=", "owner": "catppuccin", "repo": "nvim", - "rev": "7be452ee067978cdc8b2c5f3411f0c71ffa612b9", + "rev": "637d99e638bc6f1efedac582f6ccab08badac0c6", "type": "github" }, "original": { @@ -1140,11 +1147,11 @@ "plugin-ccc": { "flake": false, "locked": { - "lastModified": 1714299582, - "narHash": "sha256-QRq9hQF5vLnOTzQGbOWC2ykMdMsQDlDlb6XC17dJG7Q=", + "lastModified": 1727935067, + "narHash": "sha256-OhdR2sAQV5PvlhaKQ6rYneMmvQiN3QfymOeanpAs9wY=", "owner": "uga-rosa", "repo": "ccc.nvim", - "rev": "f388f1981d222967c741fe9927edf9ba5fa3bcbe", + "rev": "7c639042583c7bdc7ce2e37e5a0e0aa6d0659c6a", "type": "github" }, "original": { @@ -1156,11 +1163,11 @@ "plugin-cellular-automaton": { "flake": false, "locked": { - "lastModified": 1693589931, - "narHash": "sha256-szbd6m7hH7NFI0UzjWF83xkpSJeUWCbn9c+O8F8S/Fg=", + "lastModified": 1719777869, + "narHash": "sha256-nIv7ISRk0+yWd1lGEwAV6u1U7EFQj/T9F8pU6O0Wf0s=", "owner": "Eandrju", "repo": "cellular-automaton.nvim", - "rev": "b7d056dab963b5d3f2c560d92937cb51db61cb5b", + "rev": "11aea08aa084f9d523b0142c2cd9441b8ede09ed", "type": "github" }, "original": { @@ -1172,11 +1179,11 @@ "plugin-chatgpt": { "flake": false, "locked": { - "lastModified": 1709721561, - "narHash": "sha256-vD3NEsYmPRWlxBSOxyIMIQiJXQXxx0hhsw4zIxxXB3o=", + "lastModified": 1728720509, + "narHash": "sha256-+YVXAkG4pp7RGs8lGnNFc0kQcUV3O3kYBQaQ5Qa4wB0=", "owner": "jackMort", "repo": "ChatGPT.nvim", - "rev": "df53728e05129278d6ea26271ec086aa013bed90", + "rev": "5b6d296eefc75331e2ff9f0adcffbd7d27862dd6", "type": "github" }, "original": { @@ -1204,11 +1211,11 @@ "plugin-cinnamon-nvim": { "flake": false, "locked": { - "lastModified": 1714107684, - "narHash": "sha256-cMP9WRZzevxaWgpILyDh1JwNukm3Jl3JKJYPT2HnFns=", + "lastModified": 1722992123, + "narHash": "sha256-kccQ4iFMSQ8kvE7hYz90hBrsDLo7VohFj/6lEZZiAO8=", "owner": "declancm", "repo": "cinnamon.nvim", - "rev": "a011e84b624cd7b609ea928237505d31b987748a", + "rev": "450cb3247765fed7871b41ef4ce5fa492d834215", "type": "github" }, "original": { @@ -1236,11 +1243,11 @@ "plugin-cmp-luasnip": { "flake": false, "locked": { - "lastModified": 1696878902, - "narHash": "sha256-nUJJl2zyK/oSwz5RzI9j3gf9zpDfCImCYbPbVsyXgz8=", + "lastModified": 1730707109, + "narHash": "sha256-86lKQPPyqFz8jzuLajjHMKHrYnwW6+QOcPyQEx6B+gw=", "owner": "saadparwaiz1", "repo": "cmp_luasnip", - "rev": "05a9ab28b53f71d1aece421ef32fee2cb857a843", + "rev": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90", "type": "github" }, "original": { @@ -1300,11 +1307,11 @@ "plugin-codewindow-nvim": { "flake": false, "locked": { - "lastModified": 1695487629, - "narHash": "sha256-/u2Zjbd9m3/iJU3I3HzFzXWxuvoycwJoIq7UFeHNtKM=", + "lastModified": 1717593052, + "narHash": "sha256-HAqVTAkFZ1/vBiBP/QDE1fmwOl/PbznAxz/jmUFxs88=", "owner": "gorbit99", "repo": "codewindow.nvim", - "rev": "8c8f5ff66e123491c946c04848d744fcdc7cac6c", + "rev": "dd7017617962943eb1d152fc58940f11c6775a4a", "type": "github" }, "original": { @@ -1316,11 +1323,11 @@ "plugin-comment-nvim": { "flake": false, "locked": { - "lastModified": 1691409559, - "narHash": "sha256-+dF1ZombrlO6nQggufSb0igXW5zwU++o0W/5ZA07cdc=", + "lastModified": 1717957420, + "narHash": "sha256-h0kPue5Eqd5aeu4VoLH45pF0DmWWo1d8SnLICSQ63zc=", "owner": "numToStr", "repo": "Comment.nvim", - "rev": "0236521ea582747b58869cb72f70ccfa967d2e89", + "rev": "e30b7f2008e52442154b66f7c519bfd2f1e32acb", "type": "github" }, "original": { @@ -1332,11 +1339,11 @@ "plugin-copilot-cmp": { "flake": false, "locked": { - "lastModified": 1694286652, - "narHash": "sha256-srgNohm/aJpswNJ5+T7p+zi9Jinp9e5FA8/wdk6VRiY=", + "lastModified": 1718601710, + "narHash": "sha256-8w9go2SBkI+BrXNadWM8ZxDDfrAnZZJx6RbVHAK4+Pg=", "owner": "zbirenbaum", "repo": "copilot-cmp", - "rev": "72fbaa03695779f8349be3ac54fa8bd77eed3ee3", + "rev": "b6e5286b3d74b04256d0a7e3bd2908eabec34b44", "type": "github" }, "original": { @@ -1348,11 +1355,11 @@ "plugin-copilot-lua": { "flake": false, "locked": { - "lastModified": 1709095198, - "narHash": "sha256-JX3sdsnOnjkY7r9fCtC2oauo0PXF3SQ+SHUo8ifBvAc=", + "lastModified": 1729295476, + "narHash": "sha256-UY6N2Q+egh+Cn4REZXrSGH9ElWQBedl0n8tWJvGe7vs=", "owner": "zbirenbaum", "repo": "copilot.lua", - "rev": "f7612f5af4a7d7615babf43ab1e67a2d790c13a6", + "rev": "f8d8d872bb319f640d5177dad5fbf01f7a16d7d0", "type": "github" }, "original": { @@ -1364,11 +1371,11 @@ "plugin-crates-nvim": { "flake": false, "locked": { - "lastModified": 1715690194, - "narHash": "sha256-R1y1OIep4tcFd4mhylZ/A2zdwOmEQtCzuVBOBYu0qUI=", + "lastModified": 1727384188, + "narHash": "sha256-DIG0MXRTit4iEVoLlgsTK4znjam/QDjeZEpIDn6KHiE=", "owner": "Saecki", "repo": "crates.nvim", - "rev": "d556c00d60c9421c913ee54ff690df2a34f6264e", + "rev": "8bf8358ee326d5d8c11dcd7ac0bcc9ff97dbc785", "type": "github" }, "original": { @@ -1377,14 +1384,30 @@ "type": "github" } }, + "plugin-csharpls-extended": { + "flake": false, + "locked": { + "lastModified": 1730857197, + "narHash": "sha256-eKkFpEB7ZXNttXz62y3GaKptt4n0xRY+iuTI8RU5z0Q=", + "owner": "Decodetalkers", + "repo": "csharpls-extended-lsp.nvim", + "rev": "ef02017d80b1cd914d61285b1fb063cb7fe0aa8f", + "type": "github" + }, + "original": { + "owner": "Decodetalkers", + "repo": "csharpls-extended-lsp.nvim", + "type": "github" + } + }, "plugin-dashboard-nvim": { "flake": false, "locked": { - "lastModified": 1715952164, - "narHash": "sha256-mLQHRzt9vUJLOO15+u7EaE2FGzIm1Ba7fqwdu5zaTYA=", + "lastModified": 1730526793, + "narHash": "sha256-Qi8kmC3U8Tvxh0pWIBtN3DuWJioEGWn7FqQ8lQwauRo=", "owner": "glepnir", "repo": "dashboard-nvim", - "rev": "5182c09ac8085dc73b78ad0ea9f5479c9a866fc4", + "rev": "ae309606940d26d8c9df8b048a6e136b6bbec478", "type": "github" }, "original": { @@ -1396,11 +1419,11 @@ "plugin-diffview-nvim": { "flake": false, "locked": { - "lastModified": 1716569036, - "narHash": "sha256-sCrswSN/ERirije4hukg81t+X8sVG6EnG8SPK/P1Bts=", + "lastModified": 1718279802, + "narHash": "sha256-SX+ybIzL/w6uyCy4iZKnWnzTFwqB1oXSgyYVAdpdKi8=", "owner": "sindrets", "repo": "diffview.nvim", - "rev": "1ec7b56b959dab18f7030f541c33ae60e18a6f88", + "rev": "4516612fe98ff56ae0415a259ff6361a89419b0a", "type": "github" }, "original": { @@ -1412,11 +1435,11 @@ "plugin-dracula": { "flake": false, "locked": { - "lastModified": 1708834650, - "narHash": "sha256-I3rtbJYv1D+kniOLL9hmTF3ucp/qSNewnO2GmYAERko=", + "lastModified": 1729038981, + "narHash": "sha256-3jFOaFtH+EIx4mUKV0U/cFkUo8By0JgorTYgFUKEs/s=", "owner": "Mofiqul", "repo": "dracula.nvim", - "rev": "8d8bddb8814c3e7e62d80dda65a9876f97eb699c", + "rev": "94fa7885a06a67f0a8bfa03e064619d05d1ba496", "type": "github" }, "original": { @@ -1428,11 +1451,11 @@ "plugin-dressing-nvim": { "flake": false, "locked": { - "lastModified": 1716410905, - "narHash": "sha256-AXY1+nA6Q/kWbuwOAqwVdd3QrjkHGVdVMHShvSIfLwM=", + "lastModified": 1730759661, + "narHash": "sha256-F9mdyANs9QTzlB/VAXt+9GXJUiA5th7Fj79WArdUmRE=", "owner": "stevearc", "repo": "dressing.nvim", - "rev": "3c38ac861e1b8d4077ff46a779cde17330b29f3a", + "rev": "6ef1ca479d37d4ff66f13eed44d08912caff483a", "type": "github" }, "original": { @@ -1444,11 +1467,11 @@ "plugin-elixir-tools": { "flake": false, "locked": { - "lastModified": 1716478469, - "narHash": "sha256-ESL/H/l5Yarcuo3MjBplKwox8E6CBxvWrpciyJeaES0=", + "lastModified": 1727872243, + "narHash": "sha256-7gIvoV6myqbkjLnIhHuyNPix1DFkKEeeND2o6VDxDWc=", "owner": "elixir-tools", "repo": "elixir-tools.nvim", - "rev": "815cf0b0aab0421f8490199c0dd7442d22a7c1b7", + "rev": "b465f6aff50257fa466de3886fc3e7de2dcff0de", "type": "github" }, "original": { @@ -1460,11 +1483,11 @@ "plugin-fastaction-nvim": { "flake": false, "locked": { - "lastModified": 1721396662, - "narHash": "sha256-L7na78FsE+QHlEwxMpiwQcoOPhtmrknvdTZfzUoDANI=", + "lastModified": 1731000037, + "narHash": "sha256-oNLKwWj2lze/ZCcwT98ucw6oT4765EiW1CB0BAjox8A=", "owner": "Chaitanyabsprip", "repo": "fastaction.nvim", - "rev": "2384dea7ba81d2709d0bee0e4bc7a8831ff13a9d", + "rev": "a55feac91f39b83aa21b9ef3df1e465d9122753c", "type": "github" }, "original": { @@ -1476,11 +1499,11 @@ "plugin-fidget-nvim": { "flake": false, "locked": { - "lastModified": 1716093309, - "narHash": "sha256-Gpk/G0ByOAIE8uX4Xr94CvAjJBSJMEOwBuvrhmYYGsg=", + "lastModified": 1730221432, + "narHash": "sha256-fQBrkHV54TaOeLYQJ1DE+lr7SFDPN1yqSlzhFm26NAY=", "owner": "j-hui", "repo": "fidget.nvim", - "rev": "ef99df04a1c53a453602421bc0f756997edc8289", + "rev": "e2a175c2abe2d4f65357da1c98c59a5cfb2b543f", "type": "github" }, "original": { @@ -1492,11 +1515,11 @@ "plugin-flutter-tools": { "flake": false, "locked": { - "lastModified": 1716114535, - "narHash": "sha256-dRcWCqFHtDMOEGjKji3lxYQZKBhlhss/i51pX6FZxuI=", + "lastModified": 1730275333, + "narHash": "sha256-fKsC+ouSfW07dLipXP+RPMzQfCQ70oGknSdVo7dMAxw=", "owner": "akinsho", "repo": "flutter-tools.nvim", - "rev": "990a1349c29f7d474a0cd51355aba773ccc9deea", + "rev": "7e6d8611d8606efca64cb8cf1ca07550b7087d1c", "type": "github" }, "original": { @@ -1508,11 +1531,11 @@ "plugin-friendly-snippets": { "flake": false, "locked": { - "lastModified": 1727061933, - "narHash": "sha256-yTsuV5unoujY0mhLINssYYBWCeefe+nJaxQHJKm7hlk=", + "lastModified": 1728273759, + "narHash": "sha256-H94Ryad0ZsSg/gioUgW+7sowij7GgtEUMNFi1IOZAys=", "owner": "rafamadriz", "repo": "friendly-snippets", - "rev": "00ba9dd3df89509f95437b8d595553707c46d5ea", + "rev": "de8fce94985873666bd9712ea3e49ee17aadb1ed", "type": "github" }, "original": { @@ -1524,11 +1547,11 @@ "plugin-gesture-nvim": { "flake": false, "locked": { - "lastModified": 1715776261, - "narHash": "sha256-XgF5BTKR5IiELNqYDvOPIGMw3HtkyNd3K5SOGfYFizY=", + "lastModified": 1726696689, + "narHash": "sha256-d1+czQXyJUyNlMhPjRzb6cEiCJVTFrkYnv7XXh2BLNs=", "owner": "notomo", "repo": "gesture.nvim", - "rev": "3750313a40a752629e3e90f3c3e591969fdab388", + "rev": "a63d81325a1f84ad87a7d9e1a36e4eeb4e786fc1", "type": "github" }, "original": { @@ -1540,11 +1563,11 @@ "plugin-gitsigns-nvim": { "flake": false, "locked": { - "lastModified": 1716453598, - "narHash": "sha256-TTC3uvRsq4v6PBdS/3YAGpyhVt0w3/SGkPE3fu1zW94=", + "lastModified": 1730713501, + "narHash": "sha256-FHzufzeVrPnbU5j3UabVTCYXP+QNcb7gMgef0BmuclA=", "owner": "lewis6991", "repo": "gitsigns.nvim", - "rev": "cdfcd9d39d23c46ae9a040de2c6a8b8bf868746e", + "rev": "4daf7022f1481edf1e8fb9947df13bb07c18e89a", "type": "github" }, "original": { @@ -1572,11 +1595,11 @@ "plugin-gruvbox": { "flake": false, "locked": { - "lastModified": 1716072809, - "narHash": "sha256-BLhZGijGF03UFiyMJ66C1ZLDRqAo1C80ekHcBm1PGoY=", + "lastModified": 1727809136, + "narHash": "sha256-/kgZuNJ1vHyOpvFHiJKCb1HzjSPgqis9Ng4aT7jHXG4=", "owner": "ellisonleao", "repo": "gruvbox.nvim", - "rev": "96a8ec336fb48a11cefbd57508888361431aac26", + "rev": "49d9c0b150ba70efcd831ec7b3cb8ee740067045", "type": "github" }, "original": { @@ -1588,11 +1611,11 @@ "plugin-highlight-undo": { "flake": false, "locked": { - "lastModified": 1714982601, - "narHash": "sha256-yGw1SxcUmGQxqKhMb2SJAai07g+rOpEJy2CqIX2h9dM=", + "lastModified": 1729426343, + "narHash": "sha256-zNzVmt4WJcspuloePhc6HbDvNA7B92NscE+fEYvCumc=", "owner": "tzachar", "repo": "highlight-undo.nvim", - "rev": "1ea1c79372d7d93c88fd97543880927b7635e3d2", + "rev": "c87a6ec1ded241ef223269077cbd5f97a6f0d5bf", "type": "github" }, "original": { @@ -1636,11 +1659,11 @@ "plugin-image-nvim": { "flake": false, "locked": { - "lastModified": 1716308282, - "narHash": "sha256-6nFzUchDQIvaTOv4lZ10q66m/ntU3dgVnlfBRodW+0Y=", + "lastModified": 1730854538, + "narHash": "sha256-G7Nqs8BqLCR46vw6VVazvdGOpan6Wkkv/PfJB+nBbGE=", "owner": "3rd", "repo": "image.nvim", - "rev": "2a618c86d9f8fd9f7895d12b55ec2f31fd14fa05", + "rev": "9c9dbed0cdb4dbd199ebfc678a881f5745a36f50", "type": "github" }, "original": { @@ -1652,11 +1675,11 @@ "plugin-indent-blankline": { "flake": false, "locked": { - "lastModified": 1716449809, - "narHash": "sha256-K5y0UQAXc0N6+1kqncX2eClpvZb7jlg7GhSerHQVZX0=", + "lastModified": 1730170343, + "narHash": "sha256-odv43EyZ3gMg410eBFAkye/SdAj+LcVVZPaZm8w0biM=", "owner": "lukas-reineke", "repo": "indent-blankline.nvim", - "rev": "d98f537c3492e87b6dc6c2e3f66ac517528f406f", + "rev": "04e44b09ee3ff189c69ab082edac1ef7ae2e256c", "type": "github" }, "original": { @@ -1668,11 +1691,11 @@ "plugin-leap-nvim": { "flake": false, "locked": { - "lastModified": 1716207448, - "narHash": "sha256-O/wN5v8GhlEECBIhJQvWhKcpQrqT7J+BNkd/fIh0TIQ=", + "lastModified": 1722337962, + "narHash": "sha256-PFD/UliAHKk2ga+7p/GmoZGqZFWenIVLkzmO+FkhvrY=", "owner": "ggandor", "repo": "leap.nvim", - "rev": "8f4d3ab9fe5c906c5745150191831c5ee0a427a0", + "rev": "c6bfb191f1161fbabace1f36f578a20ac6c7642c", "type": "github" }, "original": { @@ -1700,11 +1723,11 @@ "plugin-lsp-signature": { "flake": false, "locked": { - "lastModified": 1716637798, - "narHash": "sha256-4Abo4HGwzZtqEHcS9lsQdw+Dsn7tkQoeq5QyfTEEwnA=", + "lastModified": 1726445971, + "narHash": "sha256-W6bN3R10B84noK7MOzvUOIc82WwyojIS97iFL/dO5yk=", "owner": "ray-x", "repo": "lsp_signature.nvim", - "rev": "529e8861d0410389f0163a5e5c2199d4a4ef5bf6", + "rev": "fc38521ea4d9ec8dbd4c2819ba8126cea743943b", "type": "github" }, "original": { @@ -1716,11 +1739,11 @@ "plugin-lspkind": { "flake": false, "locked": { - "lastModified": 1704982040, - "narHash": "sha256-/QLdBU/Zwmkw1NGuLBD48tvrmIP9d9WHhgcLEQgRTWo=", + "lastModified": 1729872608, + "narHash": "sha256-/ifgjqqCQw67l3+gUs00tt860pa92M1WYdjdZ0lhxak=", "owner": "onsails", "repo": "lspkind-nvim", - "rev": "1735dd5a5054c1fb7feaf8e8658dbab925f4f0cf", + "rev": "a700f1436d4a938b1a1a93c9962dc796afbaef4d", "type": "github" }, "original": { @@ -1764,11 +1787,11 @@ "plugin-lualine": { "flake": false, "locked": { - "lastModified": 1723473562, - "narHash": "sha256-gCm7m96PkZyrgjmt7Efc+NMZKStAq1zr7JRCYOgGDuE=", + "lastModified": 1731050126, + "narHash": "sha256-IN6Qz3jGxUcylYiRTyd8j6me3pAoqJsJXtFUvph/6EI=", "owner": "hoob3rt", "repo": "lualine.nvim", - "rev": "b431d228b7bbcdaea818bdc3e25b8cdbe861f056", + "rev": "2a5bae925481f999263d6f5ed8361baef8df4f83", "type": "github" }, "original": { @@ -1780,11 +1803,11 @@ "plugin-luasnip": { "flake": false, "locked": { - "lastModified": 1726165831, - "narHash": "sha256-nkaa1NGOI28Et2QitQB+Spv+J42QVdHE1oywteLcJJw=", + "lastModified": 1730895001, + "narHash": "sha256-Vb4unHnhppcM1HZtd8oohJHPlkUHORoYUjKUWyhRM6g=", "owner": "L3MON4D3", "repo": "LuaSnip", - "rev": "e808bee352d1a6fcf902ca1a71cee76e60e24071", + "rev": "2737edc9e674e537dc0a97e3405658d57d2d31ed", "type": "github" }, "original": { @@ -1793,6 +1816,39 @@ "type": "github" } }, + "plugin-lz-n": { + "flake": false, + "locked": { + "lastModified": 1730598851, + "narHash": "sha256-L7og7ZTo5Soyn6pvBHkJcgGuON96eV0V5QC3J1uz/ko=", + "owner": "nvim-neorocks", + "repo": "lz.n", + "rev": "c8675c983e0682c49a13f17fc7ff9353bcb32120", + "type": "github" + }, + "original": { + "owner": "nvim-neorocks", + "repo": "lz.n", + "type": "github" + } + }, + "plugin-lzn-auto-require": { + "flake": false, + "locked": { + "lastModified": 1731009187, + "narHash": "sha256-KC1z+zC9vKODllZVpBu+udzM12oYJaS8e6LdXWtQ89U=", + "owner": "horriblename", + "repo": "lzn-auto-require", + "rev": "a075ed51976323fd7fc44ccfca89fe0449a08cca", + "type": "github" + }, + "original": { + "owner": "horriblename", + "ref": "require-rewrite", + "repo": "lzn-auto-require", + "type": "github" + } + }, "plugin-mind-nvim": { "flake": false, "locked": { @@ -1828,11 +1884,11 @@ "plugin-modes-nvim": { "flake": false, "locked": { - "lastModified": 1702245923, - "narHash": "sha256-Kd2hf5obrPvCVLtRcFjLd75byyrB2o3uYCSEMW6IeCc=", + "lastModified": 1717693302, + "narHash": "sha256-z1XD0O+gG2/+g/skdWGC64Zv4dXvvhWesaK/8DcPF/E=", "owner": "mvllow", "repo": "modes.nvim", - "rev": "4035a46aaabe43faf1b54740575af9dd5bb03809", + "rev": "326cff3282419b3bcc745061978c1e592cae055d", "type": "github" }, "original": { @@ -1860,11 +1916,11 @@ "plugin-neocord": { "flake": false, "locked": { - "lastModified": 1713923379, - "narHash": "sha256-oVWdnQlgXIMzMiybMq7yR/WfEW+Fm5RmhWx0RWprlfQ=", + "lastModified": 1729369963, + "narHash": "sha256-4dVaxigJ8eOXpgiqcxUYIF4SoC1CPFvNHYKT0zxIYo0=", "owner": "IogaMaster", "repo": "neocord", - "rev": "aa7a58023166533da83ca7b11c0d2569e45d7381", + "rev": "587e03390a355e9c364d48638e0e0db2a8431d73", "type": "github" }, "original": { @@ -1876,11 +1932,11 @@ "plugin-neodev-nvim": { "flake": false, "locked": { - "lastModified": 1711715247, - "narHash": "sha256-mAJOMVN7/xO7ykVNAeTeX+z2A/7yB8zdqlEKHL6Pb74=", + "lastModified": 1720260306, + "narHash": "sha256-hOjzlo/IqmV8tYjGwfmcCPEmHYsWnEIwtHZdhpwA1kM=", "owner": "folke", "repo": "neodev.nvim", - "rev": "ce9a2e8eaba5649b553529c5498acb43a6c317cd", + "rev": "46aa467dca16cf3dfe27098042402066d2ae242d", "type": "github" }, "original": { @@ -1892,11 +1948,11 @@ "plugin-neorg": { "flake": false, "locked": { - "lastModified": 1727821831, - "narHash": "sha256-yfWQ6yKytu1jkWUtRZTVICslUWej6jVYv7frmSB7/6Q=", + "lastModified": 1730333767, + "narHash": "sha256-qTo8rxwvANrgP8UccFhzsNsH+Jbmqv2iOlw0ccLNYm4=", "owner": "nvim-neorg", "repo": "neorg", - "rev": "afc9a37bf021acb0853e95714c4c6436e1588286", + "rev": "488507bb996f75ee29073f50dec32fa220867ca5", "type": "github" }, "original": { @@ -1940,11 +1996,11 @@ "plugin-noice-nvim": { "flake": false, "locked": { - "lastModified": 1716502618, - "narHash": "sha256-GrgFjVDIQcCfg5qyO6FnhlGUCrz6rwAFh81yZXUJra4=", + "lastModified": 1731163840, + "narHash": "sha256-zT+fJ88V/LfmibXs4QpIyxCu1HHSjbqsrcQK/vadeRA=", "owner": "folke", "repo": "noice.nvim", - "rev": "f119045f38792ad5311e5f9be7a879e4c1a95fe0", + "rev": "2087bbf8cd64482b47fb5f33b5e0eabf329ab14b", "type": "github" }, "original": { @@ -1973,11 +2029,11 @@ "plugin-nui-nvim": { "flake": false, "locked": { - "lastModified": 1716019714, - "narHash": "sha256-JRVVRT1CZZTjr58L+gAer7eCg9/fMdAD0YD5ljNwl0Q=", + "lastModified": 1726376728, + "narHash": "sha256-90Wq+vT361mTaGU/SvAezqJkX9HHmZ2GI2fKBDxPn04=", "owner": "MunifTanjim", "repo": "nui.nvim", - "rev": "b1b3dcd6ed8f355c78bad3d395ff645be5f8b6ae", + "rev": "b58e2bfda5cea347c9d58b7f11cf3012c7b3953f", "type": "github" }, "original": { @@ -1989,11 +2045,11 @@ "plugin-nvim-autopairs": { "flake": false, "locked": { - "lastModified": 1716158088, - "narHash": "sha256-YEAqjlzVrS/VLrkwGo3L7cNOE1LuyLYlBtkR2HA5oVk=", + "lastModified": 1727742362, + "narHash": "sha256-pqYOaEjKUd5YLVWX0Bf/kYT+sBlN1D24rOBuIz2BIqk=", "owner": "windwp", "repo": "nvim-autopairs", - "rev": "c15de7e7981f1111642e7e53799e1211d4606cb9", + "rev": "ee297f215e95a60b01fde33275cc3c820eddeebe", "type": "github" }, "original": { @@ -2005,11 +2061,11 @@ "plugin-nvim-bufferline-lua": { "flake": false, "locked": { - "lastModified": 1716555412, - "narHash": "sha256-8PCkY1zrlMrPGnQOb7MjqDXNlkeX46jrT4ScIL+MOwM=", + "lastModified": 1729768480, + "narHash": "sha256-MpSX8a51Avc9O1XxfWIDOVLiqD7omwAFIwSa02oXNs0=", "owner": "akinsho", "repo": "nvim-bufferline.lua", - "rev": "99337f63f0a3c3ab9519f3d1da7618ca4f91cffe", + "rev": "5cc447cb2b463cb499c82eaeabbed4f5fa6a0a44", "type": "github" }, "original": { @@ -2021,11 +2077,11 @@ "plugin-nvim-cmp": { "flake": false, "locked": { - "lastModified": 1715954188, - "narHash": "sha256-GhXfnWqpXFVM7Yi9+qEXHfA6LIMILcMG9pP4VYXuptE=", + "lastModified": 1730523275, + "narHash": "sha256-iNEoMl/X0nh2sAio1h+dkuobeOXRBXKFJCcElUyyW54=", "owner": "hrsh7th", "repo": "nvim-cmp", - "rev": "5260e5e8ecadaf13e6b82cf867a909f54e15fd07", + "rev": "f17d9b4394027ff4442b298398dfcaab97e40c4f", "type": "github" }, "original": { @@ -2037,11 +2093,11 @@ "plugin-nvim-colorizer-lua": { "flake": false, "locked": { - "lastModified": 1703321305, - "narHash": "sha256-oKvFN2K+ASlPNwj2rhptR/ErYgo6XKBPhXSZotDdCP0=", + "lastModified": 1730855006, + "narHash": "sha256-jDnTDUzslVa+4S2vAwqUZeJN+9Fxf5Naunf6uG54HLI=", "owner": "NvChad", "repo": "nvim-colorizer.lua", - "rev": "85855b38011114929f4058efc97af1059ab3e41d", + "rev": "f134063618a65cad4d7415fddbd96ff7e0c5b4ae", "type": "github" }, "original": { @@ -2069,11 +2125,11 @@ "plugin-nvim-dap": { "flake": false, "locked": { - "lastModified": 1716747841, - "narHash": "sha256-uzivFy0ZNLxAXDqkYNrNy1SSHPRrGv3OLVCNCRDiikU=", + "lastModified": 1730842757, + "narHash": "sha256-WiypPzEQnModkzgI7ikq2C9OKc/DBeGLZ8ZaKmzHt2c=", "owner": "mfussenegger", "repo": "nvim-dap", - "rev": "922ebc75c2fa9305e36402fbd8c984c8638770a0", + "rev": "8517126e9323e346f6a99b3b594c5a940b914dcd", "type": "github" }, "original": { @@ -2085,11 +2141,11 @@ "plugin-nvim-dap-go": { "flake": false, "locked": { - "lastModified": 1716775637, - "narHash": "sha256-B8A+ven18YgePLxAN3Q/j5NFb0FeTHCQak1uzaNDX9c=", + "lastModified": 1727922873, + "narHash": "sha256-wcGp5df1ER5T5oLVitWE02OywgJs3V4pazcGU5qVaUY=", "owner": "leoluz", "repo": "nvim-dap-go", - "rev": "a0c5a2b991d7e9304a9a032cf177e22a4b0acda1", + "rev": "6aa88167ea1224bcef578e8c7160fe8afbb44848", "type": "github" }, "original": { @@ -2101,11 +2157,11 @@ "plugin-nvim-dap-ui": { "flake": false, "locked": { - "lastModified": 1716237606, - "narHash": "sha256-paiyLNzqUq9G3U8qn8yl1AjHJzTTa17exA05QO09nGA=", + "lastModified": 1727897692, + "narHash": "sha256-kg7lyVBeuBqPCVzvt3pBoonQupgf1nGh3EvCF/astf4=", "owner": "rcarriga", "repo": "nvim-dap-ui", - "rev": "334cf3038c4756e6ab999cbac67c847fb654c190", + "rev": "ffa89839f97bad360e78428d5c740fdad9a0ff02", "type": "github" }, "original": { @@ -2117,11 +2173,11 @@ "plugin-nvim-docs-view": { "flake": false, "locked": { - "lastModified": 1705711563, - "narHash": "sha256-N5PrJKhF6pHkel4EyAllNdEYQRninfSyaAXPbuAiD+s=", + "lastModified": 1723781320, + "narHash": "sha256-6kd3IWsD72eYe+q1w78gcFcK9LalCQHCqtSwwqQR3Ew=", "owner": "amrbashir", "repo": "nvim-docs-view", - "rev": "78d88bca16f32a430572758677f9246f6d7f7b94", + "rev": "365593534e0acd762bfddce6e8313315ffa4fa36", "type": "github" }, "original": { @@ -2133,11 +2189,11 @@ "plugin-nvim-lightbulb": { "flake": false, "locked": { - "lastModified": 1689887436, - "narHash": "sha256-Meoop66jINllnxN6aohuPmU7DEjn64FMq/b8zuy9FEQ=", + "lastModified": 1729134062, + "narHash": "sha256-JfXSuOBwyxgH/PzzcBQ7OqoXHkLGZSCYutYHLocbTto=", "owner": "kosayoda", "repo": "nvim-lightbulb", - "rev": "8f00b89dd1b1dbde16872bee5fbcee2e58c9b8e9", + "rev": "33d4c95e0e853956bc9468b70b3064c87d5abaca", "type": "github" }, "original": { @@ -2149,11 +2205,11 @@ "plugin-nvim-lspconfig": { "flake": false, "locked": { - "lastModified": 1727085470, - "narHash": "sha256-IPpUZEMIL7+4mmqQLy9JeT0cW15/SH3Hx8kyksVcqC0=", + "lastModified": 1730978746, + "narHash": "sha256-N1vqosgHHVUWoszhdGImH//mb7hiSWWsG1Pq9WNnQxk=", "owner": "neovim", "repo": "nvim-lspconfig", - "rev": "dd329912c8d446240584a2dbcd3802af3a19105a", + "rev": "d01864641c6e43c681c3e9f6cf4745c75fdd9dcc", "type": "github" }, "original": { @@ -2213,11 +2269,11 @@ "plugin-nvim-neoclip": { "flake": false, "locked": { - "lastModified": 1701664728, - "narHash": "sha256-QtqLKdrDGzIiSEo3DZtv0C7wx3KlrcyePoIYdvH6vpk=", + "lastModified": 1725927226, + "narHash": "sha256-GHkTIGPgX5j1wUS9EW/fGOp3NSRjfVaz+6o1Aehy2Xw=", "owner": "AckslD", "repo": "nvim-neoclip.lua", - "rev": "798cd0592a81c185465db3a091a0ff8a21af60fd", + "rev": "32e05f2d23dc5b6a284a688c0535a83d1bfc633f", "type": "github" }, "original": { @@ -2229,11 +2285,11 @@ "plugin-nvim-nio": { "flake": false, "locked": { - "lastModified": 1716391538, - "narHash": "sha256-UffuTu7mF96LHk0MQRNrsgDyo1QWa/1i5eJKjZkuG8k=", + "lastModified": 1720707425, + "narHash": "sha256-i6imNTb1xrfBlaeOyxyIwAZ/+o6ew9C4/z34a7/BgFg=", "owner": "nvim-neotest", "repo": "nvim-nio", - "rev": "632024157d01e8bc48fd7df6a7de8ffe3fdd4f3a", + "rev": "a428f309119086dc78dd4b19306d2d67be884eee", "type": "github" }, "original": { @@ -2245,11 +2301,11 @@ "plugin-nvim-notify": { "flake": false, "locked": { - "lastModified": 1715959703, - "narHash": "sha256-wxyHwL/uFdp6w32CVHgSOWkzRrIRuFvWh+J2401RAAA=", + "lastModified": 1727022370, + "narHash": "sha256-Sd7IR5roXHOKRCxhqtYMhWfEltyRJMDEMDO/ecSKenE=", "owner": "rcarriga", "repo": "nvim-notify", - "rev": "d333b6f167900f6d9d42a59005d82919830626bf", + "rev": "fbef5d32be8466dd76544a257d3f3dce20082a07", "type": "github" }, "original": { @@ -2258,14 +2314,30 @@ "type": "github" } }, + "plugin-nvim-scrollbar": { + "flake": false, + "locked": { + "lastModified": 1729162132, + "narHash": "sha256-/nB7eP2Rz/A9zMXrNEH4FReo6eZS0C/SEGvKhxV7AUA=", + "owner": "petertriho", + "repo": "nvim-scrollbar", + "rev": "6994eb9f73d5fdc36ee2c8717940e8c853e51a49", + "type": "github" + }, + "original": { + "owner": "petertriho", + "repo": "nvim-scrollbar", + "type": "github" + } + }, "plugin-nvim-session-manager": { "flake": false, "locked": { - "lastModified": 1716560093, - "narHash": "sha256-A6oHIg8PG84L7QIRpo9WXKzMq4EUe92jQIxObOxpFmg=", + "lastModified": 1728423652, + "narHash": "sha256-W9jtfVXHC8MQJwdbxakNqhd+xh/auQb3U09XKdN2Wzw=", "owner": "Shatur", "repo": "neovim-session-manager", - "rev": "b552ee8667037be5d0291229279a35af25e515fb", + "rev": "ce43f2eb2a52492157d7742e5f684b9a42bb3e5c", "type": "github" }, "original": { @@ -2277,11 +2349,11 @@ "plugin-nvim-surround": { "flake": false, "locked": { - "lastModified": 1715892699, - "narHash": "sha256-Mg60htwXPqNKu+JnexKiKF3Huvr7pBNdvc6f3Kt2FRA=", + "lastModified": 1730136751, + "narHash": "sha256-XVwvoM3Id9lCi9EgK/Y944UuCXj9niTnZ5I5+d1yVqQ=", "owner": "kylechui", "repo": "nvim-surround", - "rev": "79aaa42da1f698ed31bcbe7f83081f69dca7ba17", + "rev": "dca2e998ff26681ee422b92c6ed39b3d2908d8a9", "type": "github" }, "original": { @@ -2293,11 +2365,11 @@ "plugin-nvim-tree-lua": { "flake": false, "locked": { - "lastModified": 1716687243, - "narHash": "sha256-E6J9d0LJMK+Owj/iWbGVZBiVL/NI1xd5P0NNQpUmXj4=", + "lastModified": 1731123986, + "narHash": "sha256-zt04Q3Mr1k9x6X6l3F9iy3C1edQYha4pQhDsOX5atPM=", "owner": "nvim-tree", "repo": "nvim-tree.lua", - "rev": "517e4fbb9ef3c0986da7047f44b4b91a2400f93c", + "rev": "c7639482a1598f4756798df1b2d72f79fe5bb34f", "type": "github" }, "original": { @@ -2309,11 +2381,11 @@ "plugin-nvim-treesitter-context": { "flake": false, "locked": { - "lastModified": 1726947805, - "narHash": "sha256-5oN/vyhSqDqjLEzECj01A7A+Yq7U1H1HXLbzkC1Ljqw=", + "lastModified": 1731163983, + "narHash": "sha256-oRmhwRIynCNmgKpTtwUIliYf0Qo+zP3ymEWYs+vzx8A=", "owner": "nvim-treesitter", "repo": "nvim-treesitter-context", - "rev": "3d5390c49e3f8fe457b376df2a49aa39d75b7911", + "rev": "158377d700596367a91ea41818f76abdbf75a232", "type": "github" }, "original": { @@ -2325,11 +2397,11 @@ "plugin-nvim-ts-autotag": { "flake": false, "locked": { - "lastModified": 1716420040, - "narHash": "sha256-gy6OVR2iH361XMDDo0dqxJsAxo+5nXr3wP42pieeCUg=", + "lastModified": 1724798540, + "narHash": "sha256-QEzUKvT+ChYSa9F4zg3Lw+7Sj0JzJem9nh2mWmS8Y+I=", "owner": "windwp", "repo": "nvim-ts-autotag", - "rev": "8ae54b90e36ef1fc5267214b30c2cbff71525fe4", + "rev": "e239a560f338be31337e7abc3ee42515daf23f5e", "type": "github" }, "original": { @@ -2341,11 +2413,11 @@ "plugin-nvim-web-devicons": { "flake": false, "locked": { - "lastModified": 1716609001, - "narHash": "sha256-fmbsnNVZ6nBorBILwPfEgcDDWZCkh9YZH/aC343FxP4=", + "lastModified": 1728608318, + "narHash": "sha256-SUWEOp+QcfHjYaqqr4Zwvh0x91IAJXvrdMkQtuWMlGc=", "owner": "nvim-tree", "repo": "nvim-web-devicons", - "rev": "b77921fdc44833c994fdb389d658ccbce5490c16", + "rev": "19d257cf889f79f4022163c3fbb5e08639077bd8", "type": "github" }, "original": { @@ -2357,11 +2429,11 @@ "plugin-obsidian-nvim": { "flake": false, "locked": { - "lastModified": 1716489161, - "narHash": "sha256-R7q3PmDMYQtDTE1JZgQtvArBq55MnvNdcChOsuivSCo=", + "lastModified": 1722536347, + "narHash": "sha256-mbq7fAPmlwOAbWlN3lGX9WGBKTV8cAPZx8pnRCyszJc=", "owner": "epwalsh", "repo": "obsidian.nvim", - "rev": "0890a3f4e1711d98b5aa78bf40d2c5b81ef3c39f", + "rev": "14e0427bef6c55da0d63f9a313fd9941be3a2479", "type": "github" }, "original": { @@ -2370,14 +2442,30 @@ "type": "github" } }, + "plugin-omnisharp-extended": { + "flake": false, + "locked": { + "lastModified": 1719701797, + "narHash": "sha256-P1ZCaW8w+e3H3oBhbEjDc7vuR+XuxJmb/7IbPL3KWi4=", + "owner": "Hoffs", + "repo": "omnisharp-extended-lsp.nvim", + "rev": "aad7bf06b4ca0de816b919d475a75b30f5f62b61", + "type": "github" + }, + "original": { + "owner": "Hoffs", + "repo": "omnisharp-extended-lsp.nvim", + "type": "github" + } + }, "plugin-onedark": { "flake": false, "locked": { - "lastModified": 1715454207, - "narHash": "sha256-GERMsVNELbeRrKsiPeSKcwNI+bH4C79koTBRtRMGqvc=", + "lastModified": 1731171496, + "narHash": "sha256-NLHq9SUUo81m50NPQe8852uZbo4Mo4No10N3ptX43t0=", "owner": "navarasu", "repo": "onedark.nvim", - "rev": "8e4b79b0e6495ddf29552178eceba1e147e6cecf", + "rev": "67a74c275d1116d575ab25485d1bfa6b2a9c38a6", "type": "github" }, "original": { @@ -2389,11 +2477,11 @@ "plugin-orgmode-nvim": { "flake": false, "locked": { - "lastModified": 1716750850, - "narHash": "sha256-3xsdklkUuJwUzUieZT6eGIgDZUdVEGeyhxxUe99TOAA=", + "lastModified": 1730794385, + "narHash": "sha256-Rt/qhulJjNolQLz9OdP25U2+3KButPHgHc886yFpLpE=", "owner": "nvim-orgmode", "repo": "orgmode", - "rev": "cb3c9bf6caf3411af88a9a1a0b7eb9be57b9741c", + "rev": "fafb8f14d85a68d8f0fca812444cc0fd594f0168", "type": "github" }, "original": { @@ -2421,11 +2509,11 @@ "plugin-oxocarbon": { "flake": false, "locked": { - "lastModified": 1701119822, - "narHash": "sha256-++JALLPklok9VY2ChOddTYDvDNVadmCeB98jCAJYCZ0=", + "lastModified": 1724853107, + "narHash": "sha256-Hi/nATEvZ4a6Yxc66KtuJqss6kQV19cmtIlhCw6alOI=", "owner": "nyoom-engineering", "repo": "oxocarbon.nvim", - "rev": "c5846d10cbe4131cc5e32c6d00beaf59cb60f6a2", + "rev": "004777819ba294423b638a35a75c9f0c7be758ed", "type": "github" }, "original": { @@ -2453,11 +2541,11 @@ "plugin-plenary-nvim": { "flake": false, "locked": { - "lastModified": 1716230027, - "narHash": "sha256-5Jf2mWFVDofXBcXLbMa417mqlEPWLA+cQIZH/vNEV1g=", + "lastModified": 1726602776, + "narHash": "sha256-bmmPekAvuBvLQmrnnX0n+FRBqfVxBsObhxIEkDGAla4=", "owner": "nvim-lua", "repo": "plenary.nvim", - "rev": "a3e3bc82a3f95c5ed0d7201546d5d2c19b20d683", + "rev": "2d9b06177a975543726ce5c73fca176cedbffe9d", "type": "github" }, "original": { @@ -2466,6 +2554,22 @@ "type": "github" } }, + "plugin-precognition-nvim": { + "flake": false, + "locked": { + "lastModified": 1730325090, + "narHash": "sha256-onY1Aa+dwLR1wRua52hpSXj6zZOZXjkUlDjDa0xEEcE=", + "owner": "tris203", + "repo": "precognition.nvim", + "rev": "0189e8d6f96275a079b2805d68d49414871885cd", + "type": "github" + }, + "original": { + "owner": "tris203", + "repo": "precognition.nvim", + "type": "github" + } + }, "plugin-project-nvim": { "flake": false, "locked": { @@ -2485,11 +2589,11 @@ "plugin-registers": { "flake": false, "locked": { - "lastModified": 1703954003, - "narHash": "sha256-/MwIOR7H6ZkH/uLZOcMgg9XOWQB0yYYonbSKl51bXzo=", + "lastModified": 1730794647, + "narHash": "sha256-M7uR3yXYUQ4I8Gt8P6k25q67UNwksRDPKGrS/FCqrt0=", "owner": "tversteeg", "repo": "registers.nvim", - "rev": "22bb98f93a423252fffeb3531f7bc12a3e07b63f", + "rev": "c217f8f369e0886776cda6c94eab839b30a8940d", "type": "github" }, "original": { @@ -2501,11 +2605,11 @@ "plugin-rose-pine": { "flake": false, "locked": { - "lastModified": 1716691958, - "narHash": "sha256-mpBx0R9tR4KrOMO9J0gg2aOeHtiU9zK8xoa7Ebkx0n8=", + "lastModified": 1729724348, + "narHash": "sha256-/a4pwuVJ5odm3Iio2MeoqAm8GlWIPI91mM4cVnSy/gE=", "owner": "rose-pine", "repo": "neovim", - "rev": "87aa437172357ad8f916942bca249ceadc6c68b1", + "rev": "07a887a7bef4aacea8c7caebaf8cbf808cdc7a8e", "type": "github" }, "original": { @@ -2514,14 +2618,30 @@ "type": "github" } }, + "plugin-rtp-nvim": { + "flake": false, + "locked": { + "lastModified": 1724409589, + "narHash": "sha256-lmJbiD7I7MTEEpukESs67uAmLyn+p66hrUKLbEHp0Kw=", + "owner": "nvim-neorocks", + "repo": "rtp.nvim", + "rev": "494ddfc888bb466555d90ace731856de1320fe45", + "type": "github" + }, + "original": { + "owner": "nvim-neorocks", + "repo": "rtp.nvim", + "type": "github" + } + }, "plugin-rustaceanvim": { "flake": false, "locked": { - "lastModified": 1720595685, - "narHash": "sha256-Mx8pB9ECjFpbfmZPuXfpwoE5pUZ363M53f27ht7MBmA=", + "lastModified": 1731172933, + "narHash": "sha256-B2AdSgGPANCBbVN+Sd7gvJ16ODZZwv4WSOxnRs3SWnk=", "owner": "mrcjkb", "repo": "rustaceanvim", - "rev": "047f9c9d8cd2861745eb9de6c1570ee0875aa795", + "rev": "244443311f1c4e34ec1ea7f219a4b682b6ec066e", "type": "github" }, "original": { @@ -2530,22 +2650,6 @@ "type": "github" } }, - "plugin-scrollbar-nvim": { - "flake": false, - "locked": { - "lastModified": 1684886154, - "narHash": "sha256-zLBexSxQCn9HPY04a9w/UCJP1F5ShI2X12I9xE9H0cM=", - "owner": "petertriho", - "repo": "nvim-scrollbar", - "rev": "35f99d559041c7c0eff3a41f9093581ceea534e8", - "type": "github" - }, - "original": { - "owner": "petertriho", - "repo": "nvim-scrollbar", - "type": "github" - } - }, "plugin-smartcolumn": { "flake": false, "locked": { @@ -2581,11 +2685,11 @@ "plugin-tabular": { "flake": false, "locked": { - "lastModified": 1550598128, - "narHash": "sha256-irolBA/m3YIaezl+90h5G+xUOpad+3u44uJqDs4JCUs=", + "lastModified": 1720022617, + "narHash": "sha256-qmDpdg3Tl3W4JSovRb4ODlrKMjRL5CaVI05YBn0Q0LI=", "owner": "godlygeek", "repo": "tabular", - "rev": "339091ac4dd1f17e225fe7d57b48aff55f99b23a", + "rev": "12437cd1b53488e24936ec4b091c9324cafee311", "type": "github" }, "original": { @@ -2597,11 +2701,11 @@ "plugin-telescope": { "flake": false, "locked": { - "lastModified": 1716732931, - "narHash": "sha256-JXdpKfrSvrzpTqy+g9Bg85/vIDTUZfDr+ZhxH8wJDxA=", + "lastModified": 1730164948, + "narHash": "sha256-Qa/f+0asQvA8mhIUajC4BGZCI92OqA6ySVoQSC3ZY3s=", "owner": "nvim-telescope", "repo": "telescope.nvim", - "rev": "349660c0d35da06459ee8589af77de2086b652ce", + "rev": "85922dde3767e01d42a08e750a773effbffaea3e", "type": "github" }, "original": { @@ -2610,14 +2714,30 @@ "type": "github" } }, + "plugin-tiny-devicons-auto-colors": { + "flake": false, + "locked": { + "lastModified": 1724403745, + "narHash": "sha256-Ndkbvxn/x7+fxEYD7JIygqUiItuhoY+4+DaL/pJGKdc=", + "owner": "rachartier", + "repo": "tiny-devicons-auto-colors.nvim", + "rev": "a39fa4c92268832f6034306793b8acbfec2a7549", + "type": "github" + }, + "original": { + "owner": "rachartier", + "repo": "tiny-devicons-auto-colors.nvim", + "type": "github" + } + }, "plugin-todo-comments": { "flake": false, "locked": { - "lastModified": 1716400082, - "narHash": "sha256-ZJp0emoHogSdhXPIH74MH4CznxhCmMbO243dqxAZMJo=", + "lastModified": 1726481242, + "narHash": "sha256-EH4Sy7qNkzOgA1INFzrtsRfD79TgMqSbKUdundyw22w=", "owner": "folke", "repo": "todo-comments.nvim", - "rev": "e1549807066947818113a7d7ed48f637e49620d3", + "rev": "ae0a2afb47cf7395dc400e5dc4e05274bf4fb9e0", "type": "github" }, "original": { @@ -2629,11 +2749,11 @@ "plugin-toggleterm-nvim": { "flake": false, "locked": { - "lastModified": 1716115307, - "narHash": "sha256-h82zisizLm0FOt4l8lzgC/spFk3R5Gx25A5YgULwW8U=", + "lastModified": 1731162901, + "narHash": "sha256-g1FwgCc3a8Fak0Nb0gQQ+SI44uyAGaH1tIk1qpaAPEY=", "owner": "akinsho", "repo": "toggleterm.nvim", - "rev": "fee58a0473fd92b28c34f8f724e4918b15ba30a3", + "rev": "87b2d6a3cab8e2bd9a0255427074285f0365398d", "type": "github" }, "original": { @@ -2645,11 +2765,11 @@ "plugin-tokyonight": { "flake": false, "locked": { - "lastModified": 1716732360, - "narHash": "sha256-ZWxK0q8kUYHOk+ykH1m4901trnuHN8O9hkOZR6HdC+Y=", + "lastModified": 1730826006, + "narHash": "sha256-BkSkC9UKcDExpIx91air280soPa8QIa3eK/e/E5QYLc=", "owner": "folke", "repo": "tokyonight.nvim", - "rev": "0fae425aaab04a5f97666bd431b96f2f19c36935", + "rev": "ce91ba480070c95f40753e4663e32b4632ac6db3", "type": "github" }, "original": { @@ -2661,11 +2781,11 @@ "plugin-trouble": { "flake": false, "locked": { - "lastModified": 1716133735, - "narHash": "sha256-D3dqI4NRgEG4BCDLQ3ci9lgYxt90XyWDQXlk4/uuR6M=", + "lastModified": 1730928038, + "narHash": "sha256-zUh0o+piRVDMSXLjBj+IygZj3VX7i5nXsaNn2pPu1fg=", "owner": "folke", "repo": "trouble.nvim", - "rev": "a8264a65a0b894832ea642844f5b7c30112c458f", + "rev": "3dc00c0447c016cd43e03054c3d49436a1f2076d", "type": "github" }, "original": { @@ -2677,11 +2797,11 @@ "plugin-ts-error-translator": { "flake": false, "locked": { - "lastModified": 1712269172, - "narHash": "sha256-NJ0qfKvkwZ/0GolAeATlQLyQ7nGN6Z6q3uRqI+73wPk=", + "lastModified": 1727112009, + "narHash": "sha256-8eUDQJYfhEsqv9G1QU96k5tTIcVa8oR8/SAoFN1XZ5I=", "owner": "dmmulroy", "repo": "ts-error-translator.nvim", - "rev": "11ae55b28bde02663b5f983f59b0e3fd9c4e845b", + "rev": "3bd23c4cfe4c2edc99278e01b75cdb2a26f03152", "type": "github" }, "original": { @@ -2709,11 +2829,11 @@ "plugin-vim-fugitive": { "flake": false, "locked": { - "lastModified": 1716130336, - "narHash": "sha256-nyNtb3nsS/zFdSNRyXabcGIabAwgivJIUFB2c62vXmA=", + "lastModified": 1725670815, + "narHash": "sha256-ArYerBws+MBY4BpKh16J5TfVTrA0OFKPoZq7c2YQjp0=", "owner": "tpope", "repo": "vim-fugitive", - "rev": "4f59455d2388e113bd510e85b310d15b9228ca0d", + "rev": "d4877e54cef67f5af4f950935b1ade19ed6b7370", "type": "github" }, "original": { @@ -2741,11 +2861,11 @@ "plugin-vim-markdown": { "flake": false, "locked": { - "lastModified": 1709279705, - "narHash": "sha256-eKwWdyvMZ7FV3FvOtqWVD7pulXNnhbEEjHq7MYg1woU=", + "lastModified": 1726813437, + "narHash": "sha256-ZCCSjZ5Xok4rnIwfa4VUEaz6d3oW9066l0EkoqiTppM=", "owner": "preservim", "repo": "vim-markdown", - "rev": "a657e697376909c41475a686eeef7fc7a4972d94", + "rev": "8f6cb3a6ca4e3b6bcda0730145a0b700f3481b51", "type": "github" }, "original": { @@ -2757,11 +2877,11 @@ "plugin-vim-repeat": { "flake": false, "locked": { - "lastModified": 1611544268, - "narHash": "sha256-8rfZa3uKXB3TRCqaDHZ6DfzNbm7WaYnLvmTNzYtnKHg=", + "lastModified": 1720473942, + "narHash": "sha256-G/dmkq1KtSHIl+I5p3LfO6mGPS3eyLRbEEsuLbTpGlk=", "owner": "tpope", "repo": "vim-repeat", - "rev": "24afe922e6a05891756ecf331f39a1f6743d3d5a", + "rev": "65846025c15494983dafe5e3b46c8f88ab2e9635", "type": "github" }, "original": { @@ -2789,11 +2909,11 @@ "plugin-which-key": { "flake": false, "locked": { - "lastModified": 1697801635, - "narHash": "sha256-uvghPj/teWrRMm09Gh8iQ/LV2nYJw0lmoiZK6L4+1cY=", + "lastModified": 1730919714, + "narHash": "sha256-5t6UnOP2+CXB55/C4YWbp2pE+xKDLMvCJK8m085Fk4w=", "owner": "folke", "repo": "which-key.nvim", - "rev": "4433e5ec9a507e5097571ed55c02ea9658fb268a", + "rev": "68e37e12913a66b60073906f5d3f14dee0de19f2", "type": "github" }, "original": { @@ -2813,11 +2933,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1729104314, - "narHash": "sha256-pZRZsq5oCdJt3upZIU4aslS9XwFJ+/nVtALHIciX/BI=", + "lastModified": 1730814269, + "narHash": "sha256-fWPHyhYE6xvMI1eGY3pwBTq85wcy1YXqdzTZF+06nOg=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "3c3e88f0f544d6bb54329832616af7eb971b6be6", + "rev": "d70155fdc00df4628446352fc58adc640cd705c2", "type": "github" }, "original": { @@ -2869,11 +2989,6 @@ }, "rust-overlay": { "inputs": { - "flake-utils": [ - "nvf", - "nil", - "flake-utils" - ], "nixpkgs": [ "nvf", "nil", @@ -2881,11 +2996,11 @@ ] }, "locked": { - "lastModified": 1714529851, - "narHash": "sha256-YMKJW880f7LHXVRzu93xa6Ek+QLECIu0IRQbXbzZe38=", + "lastModified": 1726453838, + "narHash": "sha256-pupsow4L79SBfNwT6vh/5RAbVZuhngIA0RTCZksXmZY=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "9ca720fdcf7865385ae3b93ecdf65f1a64cb475e", + "rev": "ca2e79cd22625d214b8437c2c4080ce79bd9f7d2", "type": "github" }, "original": { @@ -2902,11 +3017,11 @@ ] }, "locked": { - "lastModified": 1728095260, - "narHash": "sha256-X62hA5ivYLY5G5+mXI6l9eUDkgi6Wu/7QUrwXhJ09oo=", + "lastModified": 1730687492, + "narHash": "sha256-xQVadjquBA/tFxDt5A55LJ1D1AvkVWsnrKC2o+pr8F4=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "d1d2532ab267cfe6e40dff73fbaf34436c406d26", + "rev": "41814763a2c597755b0755dbe3e721367a5e420f", "type": "github" }, "original": { @@ -3063,11 +3178,11 @@ ] }, "locked": { - "lastModified": 1728166987, - "narHash": "sha256-w6dVTguAn9zJ+7aPOhBQgDz8bn6YZ7b56cY8Kg5HJRI=", + "lastModified": 1730743262, + "narHash": "sha256-iTLqj3lU8kFehPm5tXpctzkD274t/k1nwSSq3qCWXeg=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "fb9c8d665af0588bb087f97d0f673ddf0d501787", + "rev": "09b23cef06fe248e61cec8862c04b9bcb62f4b6d", "type": "github" }, "original": { @@ -3084,11 +3199,11 @@ "rust-overlay": "rust-overlay_2" }, "locked": { - "lastModified": 1729787428, - "narHash": "sha256-kGSM7b4+X5LObd6AdgQZABU241ZzHGm24xaiy33kwBI=", + "lastModified": 1730748983, + "narHash": "sha256-72uoWm/34SU5aHgvUJgKqYMhvt4Y9X39bFhcDwVS+P0=", "owner": "dj95", "repo": "zjstatus", - "rev": "c74e310c35fb7ec6b59a1c73720db4d6d8e236a1", + "rev": "d5794fbec93860ead015b0beee70489f50cd87b1", "type": "github" }, "original": { From e00a70ca53cdde218845e0e6ea663c0db7e2f15e Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 13 Nov 2024 12:55:24 +1100 Subject: [PATCH 024/213] hozen: add slug arg --- outputs/hozen/default.nix | 6 +- outputs/lib/color/utils.nix | 249 ++++++++++++++++++------------------ 2 files changed, 126 insertions(+), 129 deletions(-) diff --git a/outputs/hozen/default.nix b/outputs/hozen/default.nix index 6360d82..f7db3fd 100644 --- a/outputs/hozen/default.nix +++ b/outputs/hozen/default.nix @@ -2,6 +2,7 @@ inherit (ook.lib.color.utils) mkLightColorScheme mkDarkColorScheme; darkScheme = mkDarkColorScheme { + slug = "gruvbox-material-dark-medium"; neutrals = { "50" = "dfd2b3"; "100" = "d9c7a5"; @@ -17,12 +18,12 @@ "600" = "585350"; "650" = "4d4947"; "700" = "3f3b3b"; - "750" = "343232"; + "750" = "32302f"; "800" = "282828"; "850" = "212121"; "900" = "1a1a1a"; }; - primary = "ea6962"; + primary = "a9b665"; red = "ea6962"; orange = "e78a4e"; yellow = "d8a657"; @@ -37,6 +38,7 @@ }; lightScheme = mkLightColorScheme { + slug = "gruvbox-material-light-soft"; neutrals = { "50" = "f7efda"; "100" = "f4eac8"; diff --git a/outputs/lib/color/utils.nix b/outputs/lib/color/utils.nix index 7014169..a6abb35 100644 --- a/outputs/lib/color/utils.nix +++ b/outputs/lib/color/utils.nix @@ -8,8 +8,14 @@ hslSet = translate.hex.toHSL.set hexStr; newHSL = types.hsl.set { inherit (hslSet) h; - l = math.clamp 0.0 1.0 (hslSet.l + (modifications.l or 0.0)); - s = math.clamp 0.0 1.0 (hslSet.s + (modifications.s or 0.0)); + l = + if modifications ? absoluteL + then modifications.l + else math.clamp 0.0 1.0 (hslSet.l + (modifications.l or 0.0)); + s = + if modifications ? absoluteS + then modifications.l + else math.clamp 0.0 1.0 (hslSet.s + (modifications.s or 0.0)); }; rgbSet = translate.hsl.toRGB.set newHSL; in @@ -27,35 +33,47 @@ desaturate = amount: hexStr: modifyHSL hexStr {s = (amount * -1) / 100.0;}; - # opinionated scale generators for light/dark themes - # lighter/darker shades always desaturate + absoluteLum = amount: hexStr: + modifyHSL hexStr { + absoluteL = true; + l = amount / 100.0; + }; + mkDarkColorScale = base: { - up4 = desaturate 24 (lighten 12 base); - up3 = desaturate 18 (lighten 9 base); - up2 = desaturate 12 (lighten 6 base); - up1 = desaturate 6 (lighten 3 base); + hard4 = lighten 12 base; + hard3 = lighten 9 base; + hard2 = lighten 6 base; + hard1 = lighten 3 base; inherit base; - down1 = desaturate 6 (darken 3 base); - down2 = desaturate 12 (darken 6 base); - down3 = desaturate 18 (darken 9 base); - down4 = desaturate 24 (darken 12 base); + soft1 = darken 3 base; + soft2 = darken 6 base; + soft3 = darken 9 base; + soft4 = darken 12 base; }; mkLightColorScale = base: { - down4 = desaturate 24 (lighten 12 base); - down3 = desaturate 18 (lighten 9 base); - down2 = desaturate 12 (lighten 6 base); - down1 = desaturate 6 (lighten 3 base); + soft4 = lighten 12 base; + soft3 = lighten 9 base; + soft2 = lighten 6 base; + soft1 = lighten 3 base; inherit base; - up1 = desaturate 6 (darken 3 base); - up2 = desaturate 12 (darken 6 base); - up3 = desaturate 18 (darken 9 base); - up4 = desaturate 24 (darken 12 base); + hard1 = darken 3 base; + hard2 = darken 6 base; + hard3 = darken 9 base; + hard4 = darken 12 base; + }; + + mkAlert = color: { + fg = absoluteLum 19 color; + bg = absoluteLum 79 color; + border = color; + base = color; }; # core color scheme generator mkColorScheme = { type ? "dark", + slug, neutrals ? {}, primary, red, @@ -71,52 +89,59 @@ brown, } @ args: let # Select scale function based on theme type - colorScale = + mkColorScale = if type == "dark" then mkDarkColorScale else mkLightColorScale; # Generate color scales - colorScales = { - red = colorScale args.red; - orange = colorScale args.orange; - yellow = colorScale args.yellow; - olive = colorScale args.olive; - green = colorScale args.green; - teal = colorScale args.teal; - blue = colorScale args.blue; - violet = colorScale args.violet; - purple = colorScale args.purple; - pink = colorScale args.pink; - brown = colorScale args.brown; + colors = { + red = mkColorScale args.red; + orange = mkColorScale args.orange; + yellow = mkColorScale args.yellow; + olive = mkColorScale args.olive; + green = mkColorScale args.green; + teal = mkColorScale args.teal; + blue = mkColorScale args.blue; + violet = mkColorScale args.violet; + purple = mkColorScale args.purple; + pink = mkColorScale args.pink; + brown = mkColorScale args.brown; }; # Theme-specific configurations - themeConfig = + theme = if type == "dark" then { semantic = { - body = args.neutrals."700"; - header = args.neutrals."800"; - footer = args.neutrals."800"; - menu = args.neutrals."800"; - border = args.neutrals."150"; - border-active = args.neutrals."150"; - border-inactive = args.neutrals."600"; - text = args.neutrals."150"; - text-bright = args.neutrals."100"; - subtext = args.neutrals."300"; + layout = { + body = args.neutrals."750"; + header = args.neutrals."800"; + footer = args.neutrals."800"; + menu = args.neutrals."800"; + }; + border = { + base = args.neutrals."150"; + active = args.neutrals."150"; + inactive = args.neutrals."600"; + }; + typography = { + text = args.neutrals."150"; + text-bright = args.neutrals."100"; + subtext = args.neutrals."300"; + contrast-text = args.neutrals."800"; + }; }; secondary = { - up-4 = args.neutrals."400"; - up-3 = args.neutrals."450"; - up-2 = args.neutrals."500"; - up-1 = args.neutrals."550"; - base = args.neutrals."700"; - down-1 = args.neutrals."750"; - down-2 = args.neutrals."800"; - down-3 = args.neutrals."850"; - down-4 = args.neutrals."900"; + hard4 = args.neutrals."300"; + hard3 = args.neutrals."350"; + hard2 = args.neutrals."400"; + hard1 = args.neutrals."450"; + base = args.neutrals."500"; + soft1 = args.neutrals."550"; + soft2 = args.neutrals."600"; + soft3 = args.neutrals."650"; + soft4 = args.neutrals."700"; }; base00 = args.neutrals."800"; base01 = args.neutrals."700"; @@ -131,27 +156,34 @@ } else { semantic = { - body = args.neutrals."50"; - header = args.neutrals."150"; - footer = args.neutrals."150"; - menu = args.neutrals."150"; - border = args.neutrals."800"; - border-active = args.neutrals."800"; - border-inactive = args.neutrals."300"; - text = args.neutrals."800"; - text-bright = args.neutrals."850"; - subtext = args.neutrals."600"; + layout = { + body = args.neutrals."50"; + header = args.neutrals."150"; + footer = args.neutrals."150"; + menu = args.neutrals."150"; + }; + border = { + base = args.neutrals."800"; + active = args.neutrals."800"; + inactive = args.neutrals."300"; + }; + typography = { + text = args.neutrals."800"; + text-bright = args.neutrals."850"; + subtext = args.neutrals."600"; + text-contrast = args.neutrals."50"; + }; }; secondary = { - up-4 = args.neutrals."400"; - up-3 = args.neutrals."350"; - up-2 = args.neutrals."300"; - up-1 = args.neutrals."250"; + hard4 = args.neutrals."400"; + hard3 = args.neutrals."350"; + hard2 = args.neutrals."300"; + hard1 = args.neutrals."250"; base = args.neutrals."200"; - down-1 = args.neutrals."150"; - down-2 = args.neutrals."100"; - down-3 = args.neutrals."50"; - down-4 = args.neutrals."50"; + soft1 = args.neutrals."150"; + soft2 = args.neutrals."100"; + soft3 = args.neutrals."50"; + soft4 = args.neutrals."50"; }; base00 = args.neutrals."150"; base01 = args.neutrals."250"; @@ -165,6 +197,7 @@ base11 = args.neutrals."50"; }; in { + inherit slug; # Common structure for both themes neutrals = { inherit @@ -190,8 +223,14 @@ ; }; + error = mkAlert args.red; + warning = mkAlert args.yellow; + success = mkAlert args.green; + note = mkAlert args.blue; + tip = mkAlert args.teal; + inherit - (colorScales) + (colors) red orange yellow @@ -205,52 +244,11 @@ brown ; - primary = colorScale args.primary; + primary = mkColorScale args.primary; - inherit (themeConfig) semantic secondary; + inherit (theme) secondary; + inherit (theme.semantic) layout border typography; - # Status colors (same structure for both themes) - error = { - bg = "${colorScales.red.base}"; - bg-active = "${colorScales.red.down1}"; - bg-hover = "${colorScales.red.down2}"; - text = "${themeConfig.semantic.text-bright}"; - border = "${colorScales.red.up2}"; - }; - - success = { - bg = "${colorScales.green.base}"; - bg-active = "${colorScales.green.down1}"; - bg-hover = "${colorScales.green.down2}"; - text = "${themeConfig.semantic.text-bright}"; - border = "${colorScales.green.up2}"; - }; - - warning = { - bg = "${colorScales.yellow.base}"; - bg-active = "${colorScales.yellow.down1}"; - bg-hover = "${colorScales.yellow.down2}"; - text = "${themeConfig.semantic.text-bright}"; - border = "${colorScales.yellow.up2}"; - }; - - info = { - bg = "${colorScales.blue.base}"; - bg-active = "${colorScales.blue.down1}"; - bg-hover = "${colorScales.blue.down2}"; - text = "${themeConfig.semantic.text-bright}"; - border = "${colorScales.blue.up2}"; - }; - - tip = { - bg = "${colorScales.teal.base}"; - bg-active = "${colorScales.teal.down1}"; - bg-hover = "${colorScales.teal.down2}"; - text = "${themeConfig.semantic.text-bright}"; - border = "${colorScales.teal.up2}"; - }; - - # Syntax highlighting (same for both themes) syntax = { string = args.green; number = args.purple; @@ -273,14 +271,13 @@ preCondit = args.purple; special = args.yellow; specialChar = args.yellow; - comment = "${themeConfig.semantic.subtext}"; + comment = "${theme.semantic.typography.subtext}"; todo = args.purple; tag = args.teal; }; - # Base16/24 colors inherit - (themeConfig) + (theme) base00 base01 base02 @@ -292,8 +289,6 @@ base10 base11 ; - - # Generated base colors base08 = args.red; base09 = args.orange; base0A = args.yellow; @@ -302,12 +297,12 @@ base0D = args.blue; base0E = args.purple; base0F = args.brown; - base12 = "${colorScales.red.up2}"; - base13 = "${colorScales.yellow.up2}"; - base14 = "${colorScales.green.up2}"; - base15 = "${colorScales.teal.up2}"; - base16 = "${colorScales.blue.up2}"; - base17 = "${colorScales.purple.up2}"; + base12 = "${colors.red.hard2}"; + base13 = "${colors.yellow.hard2}"; + base14 = "${colors.green.hard2}"; + base15 = "${colors.teal.hard2}"; + base16 = "${colors.blue.hard2}"; + base17 = "${colors.purple.hard2}"; }; # wrappers From c2f10e1c47f2053ded765dfc53eba55e11de013b Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 13 Nov 2024 12:56:52 +1100 Subject: [PATCH 025/213] virtualization: gnome.adwaita -> pkgs.adwaita --- modules/nixos/workstation/virtualization/virt-manager.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/nixos/workstation/virtualization/virt-manager.nix b/modules/nixos/workstation/virtualization/virt-manager.nix index 3875726..aa45f1e 100644 --- a/modules/nixos/workstation/virtualization/virt-manager.nix +++ b/modules/nixos/workstation/virtualization/virt-manager.nix @@ -21,9 +21,8 @@ in { win-virtio win-spice + adwaita-icon-theme # virt-manager needs this ; - # virt-manager needs this - inherit (pkgs.gnome) adwaita-icon-theme; }; # sets up dconf settins for qemu and add virt-manager to systemPackages programs.virt-manager = { From 8e7cd348b105c2de5965fb2e2a190cfcc9ae984e Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 14 Nov 2024 15:18:09 +1100 Subject: [PATCH 026/213] hyprland: swap back to mako from swaync --- .../hyprland/components/default.nix | 3 +- .../workstation/hyprland/components/mako.nix | 21 ++++---- .../hyprland/components/swaync.nix | 48 ------------------- 3 files changed, 14 insertions(+), 58 deletions(-) delete mode 100644 modules/home/workstation/hyprland/components/swaync.nix diff --git a/modules/home/workstation/hyprland/components/default.nix b/modules/home/workstation/hyprland/components/default.nix index 5e09b81..493b34a 100644 --- a/modules/home/workstation/hyprland/components/default.nix +++ b/modules/home/workstation/hyprland/components/default.nix @@ -2,8 +2,7 @@ imports = [ ./rofi.nix ./hyprcapture.nix - # ./mako.nix - ./swaync.nix + ./mako.nix ./tools.nix ./waybar.nix ./hypridle.nix diff --git a/modules/home/workstation/hyprland/components/mako.nix b/modules/home/workstation/hyprland/components/mako.nix index 1f710de..74467b0 100644 --- a/modules/home/workstation/hyprland/components/mako.nix +++ b/modules/home/workstation/hyprland/components/mako.nix @@ -1,37 +1,42 @@ { osConfig, + hozen, lib, ... }: let - inherit (osConfig.ooknet.appearance) colorscheme fonts; - inherit (colorscheme) palette; + inherit (osConfig.ooknet.appearance) fonts; inherit (osConfig.ooknet.workstation) environment; + inherit (hozen) color; inherit (lib) mkIf; in { config = mkIf (environment == "hyprland") { services.mako = { enable = true; + layer = "overlay"; font = "${fonts.regular.family} 12"; - padding = "10,10"; anchor = "top-right"; width = 300; height = 100; borderSize = 2; defaultTimeout = 3000; - backgroundColor = "#${palette.base00}dd"; - borderColor = "#${palette.base05}dd"; - textColor = "#${palette.base05}dd"; + backgroundColor = "#${color.layout.menu}"; + borderColor = "#${color.border.active}"; + textColor = "#${color.typography.text}"; extraConfig = '' [app-name="system-notify"] - padding=3,3 + text-alignment=center + font=${fonts.regular.family} 16 + anchor=top-center width=100 height=100 + [app-name="spotify_player"] + border-color=#${color.green.base} [urgency=critical] padding=3,3 width=300 height=100 anchor=top-center - border-color=#${palette.base08}dd + border-color=#${color.red.base}dd ''; }; }; diff --git a/modules/home/workstation/hyprland/components/swaync.nix b/modules/home/workstation/hyprland/components/swaync.nix deleted file mode 100644 index d1a8c44..0000000 --- a/modules/home/workstation/hyprland/components/swaync.nix +++ /dev/null @@ -1,48 +0,0 @@ -{ - hozen, - lib, - pkgs, - osConfig, - ... -}: let - inherit (osConfig.ooknet.appearance) fonts; - inherit (hozen) color; -in { - services.swaync = { - enable = true; - settings = { - positionX = "right"; - positionY = "top"; - layer = "overlay"; - control-center-layer = "top"; - layer-shell = true; - control-center-margin-top = 0; - control-center-margin-bottom = 0; - control-center-margin-right = 0; - control-center-margin-left = 0; - - notification-2fa-action = true; - notification-inline-replies = false; - notification-icon-size = 32; - notification-body-image-height = 100; - notification-body-image-width = 200; - }; - style = - /* - css - */ - '' - * { - font-family: ${fonts.monospace.family}; - font-size: 14px; - } - - .notification.critical { - border: 3px solid #${color.error.border}; - background-color: #${color.error.bg}; - color: #${color.error.fg}; - } - - ''; - }; -} From a99ae9e8b8e45d6d76463ab360e017230dcc21b8 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 14 Nov 2024 15:18:34 +1100 Subject: [PATCH 027/213] home: fix zellij menu to reflect changes to zellij cmd --- modules/home/workstation/tools/zellijMenu.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/home/workstation/tools/zellijMenu.nix b/modules/home/workstation/tools/zellijMenu.nix index 3bf4f76..7bdad83 100644 --- a/modules/home/workstation/tools/zellijMenu.nix +++ b/modules/home/workstation/tools/zellijMenu.nix @@ -10,7 +10,7 @@ inherit (config.ooknet) binds; zellijmenu = pkgs.writeShellApplication { name = "zellijmenu"; - runtimeInputs = with pkgs; [coreutils rofi-wayland]; + runtimeInputs = with pkgs; [zellij coreutils rofi-wayland]; text = /* bash @@ -91,7 +91,7 @@ echo "No layout given" continue fi - zellij_cmd -s "$session_name" --layout "$layout" + zellij_cmd --layout "$layout" attach -c "$session_name" break ;; "select") From 0251c7883b8d6ce74b31dc40546253db78e592bf Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 15 Nov 2024 15:20:11 +1100 Subject: [PATCH 028/213] firefox: rework useChrome theme --- .../workstation/browser/firefox/default.nix | 3 +- .../browser/firefox/theme/ooksfox.nix | 290 ++++++++++-------- 2 files changed, 171 insertions(+), 122 deletions(-) diff --git a/modules/home/workstation/browser/firefox/default.nix b/modules/home/workstation/browser/firefox/default.nix index c9ffb27..3deb0b8 100644 --- a/modules/home/workstation/browser/firefox/default.nix +++ b/modules/home/workstation/browser/firefox/default.nix @@ -3,6 +3,7 @@ lib, inputs', osConfig, + hozen, ... }: let inherit (lib) mkIf mkMerge; @@ -45,7 +46,7 @@ in { # onepassword-password-manager # cannot get this to work unfree issue. ]; settings = import ./settings/ooksJs.nix; - userChrome = import ./theme/ooksfox.nix {inherit fonts palette;}; + userChrome = import ./theme/ooksfox.nix {inherit fonts hozen;}; userContent = import ./theme/penguinFoxContent.nix; }; profiles.testing = { diff --git a/modules/home/workstation/browser/firefox/theme/ooksfox.nix b/modules/home/workstation/browser/firefox/theme/ooksfox.nix index 7445351..e10baf0 100644 --- a/modules/home/workstation/browser/firefox/theme/ooksfox.nix +++ b/modules/home/workstation/browser/firefox/theme/ooksfox.nix @@ -1,152 +1,200 @@ { - palette, + hozen, fonts, ... -}: -with palette; -#css +}: let + inherit (hozen) color; +in + #css '' - /* minimal firefox css ooks */ + :root { - /* ===== Color Variables and Root Styles ===== */ - :root { - /* Fonts */ - --font-mono: ${fonts.monospace.family}, monospace; - } + --clr-menu: #${color.layout.menu}; + --clr-fg: #${color.typography.text}; + --clr-secondary: #${color.secondary.base}; - /* ===== General UI Modifications ===== */ - /* Hide status panel */ - #statuspanel { display: none !important; } - /* Remove border radius from menus */ - menupopup, panel { --panel-border-radius: 0px !important; } - menu, menuitem, menucaption { border-radius: 0px !important; } + --border: 1px solid var(--clr-fg); + --border-active: 1px solid var(--clr-fg); + --border-inactive: 1px solid var(--clr-secondary); - /* Hide navigation context menu items */ - menupopup > #context-navigation, - menupopup > #context-sep-navigation { display: none !important; } + --font-base: ${fonts.monospace.family}; - /* Hide various toolbar buttons */ - #forward-button, - #reload-button, - #stop-button, - #home-button, - #library-button, - #PanelUI-button, - #unified-extensions-button, - #star-button, - #reader-mode-button, - #save-to-pocket-button, - #tracking-protection-icon-container, - #page-action-buttons, - #fxa-toolbar-menu-button, - #identity-box { display: none !important; } + } - /* Hide customizable UI springs */ - #customizableui-special-spring1, - #customizableui-special-spring2 { display: none; } + * { + border-radius: 0 !important; + font-family: ${fonts.monospace.family}; + } - /* Hide Personal Toolbar */ - #PersonalToolbar { display: none !important; } + #nav-bar { + border: var(--border) !important; + background-color: var(--clr-menu) !important; + } + #urlbar { + text-align: center; + } - /* ===== URL Bar Styling ===== */ + #urlbar-background { + background-color: transparent !important; + border: unset !important; + box-shadow: unset !important; + } - #urlbar-container { - margin-left: 0 !important; - margin-right: 0 !important; - padding-top: 0 !important; - padding-bottom: 0!important; - } + #urlbar-container { + padding: 0 !important; + } - #urlbar-background { - border: solid 1px !important; - border-radius: 0 !important; - outline: none !important; - background: #${crust} !important; - } + .urlbarView { + text-align: start; + border: var(--border) !important; + margin: 0; + padding: 0 !important; + background-color: var(--clr-menu); + } - #navigator-toolbox { - border: none !important; - border-bottom: solid 1px !important;\ - } + .urlbar-input-container { + margin: 0px !important; + } - /* Hide URL bar go button */ - .urlbar-go-button { display: none !important; } - /* Remove navigation bar background */ - #nav-bar.browser-toolbar { background: none !important; } + #identity-icon { + color: red !important; + } - /* Position and style navigation bar */ + #forward-button, + #stop-button, + #star-button-box, + #translations-button, + #reload-button, + #identity-box, + #tracking-protection-icon-container, + #save-to-pocket-button, + .urlbar-page-action, + .urlbar-go-button, + /* firefox account button */ + #fxa-toolbar-menu-button, + /* hamburger menu icon */ + #PanelUI-button, + #PersonalToolbar + { + display: none; + } - #nav-bar { - text-align: center; - min-height: 0 !important; - max-height: 0 !important; - height: 0 !important; - } + .titlebar-buttonbox-container, + .tab-close-button, + .titlebar-spacer, + #tabs-newtab-button, + #alltabs-button, + #firefox-view-button, + #new-tab-button { + display: none; + } - /* Expand navigation bar on focus */ - #nav-bar:focus-within { - max-height: 40px !important; - height: 60px !important; - min-height: 15px !important; - } - /* ===== Tab Bar Styling ===== */ - /* Hide title bar buttons and spacer */ - .titlebar-close, - .titlebar-spacer { display: none !important; } + #tabbrowser-tabs { + margin: 0 !important; + padding: 0 !important; - /* Remove tab margin */ - #titlebar { - --proton-tab-block-margin: 0px !important; - --tab-block-margin: 0px !important; - } + margin-inline: 0px !important; + border: unset !important; + border-bottom: var(--border-inactive) !important; + } - /* Remove tab shadows */ - #tabbrowser-tabs:not([noshadowfortests]) .tab-background:is([selected], [multiselected]) { - box-shadow: none !important; - } + .tabbrowser-tab { + padding: 5px !important; + padding-left: 5px !important; + } - /* Hide tab-related buttons */ - #alltabs-button, - #tabs-newtab-button, - #firefox-view-button, - #new-tab-button, - .tab-close-button { display: none !important; } + .tabbrowser-tab[pinned] { + margin: 0px !important; + padding: 5px !important; + } - /* Style tabs */ - tab { - font-family: var(--font-mono); - font-weight: bold; - } + #tabbrowser-tabs[haspinnedtabs]:not([positionpinnedtabs])[orient="horizontal"] > #tabbrowser-arrowscrollbox > .tabbrowser-tab:nth-child(1 of :not([pinned], [hidden])) { + margin-inline-start: 0px !important; + } - /* Set tab and tab bar height */ - #TabsToolbar, .tabbrowser-tab { - max-height: 35px !important; - background: #${crust} !important; - border: none; - } + .tab-stack { + margin-inline: 0 !important; + } + .tab-background { + border-radius: 0px; + border: var(--border-inactive); + } + .tab-background[selected] { + border: var(--border-active); + } - /* Center tabs when not overflowing */ - #tabbrowser-arrowscrollbox:not([overflowing]) { - --uc-flex-justify: center; - } + #TabsToolbar { + padding-left: 0px !important; + margin: 0; + padding: 0; + } - scrollbox[orient="horizontal"] { - justify-content: var(--uc-flex-justify, initial); - } + root{ + --uc-navbar-transform: -40px; + } + :root[uidensity="compact"]{ --uc-navbar-transform: -34px } - /* Style selected tabs */ - #tabbrowser-tabs .tabbrowser-tab[selected] .tab-content { - border: solid 1px var(--base05) !important; - color: var(--base07); - background: var(--base02) - } + #navigator-toolbox > div{ display: contents; } + :root[sessionrestored] :where(#nav-bar,#PersonalToolbar,#tab-notification-deck,.global-notificationbox){ + transform: translateY(var(--uc-navbar-transform)) + } + :root:is([customizing],[chromehidden*="toolbar"]) :where(#nav-bar,#PersonalToolbar,#tab-notification-deck,.global-notificationbox){ + transform: none !important; + opacity: 1 !important; + } - /* Style non-selected tabs */ - tab:not([selected="true"]) { - /* border: solid 1px var(--base05) !important; */ - background: var(--base01) !important; - } + #nav-bar:not([customizing]){ + opacity: 0; + position: relative; + z-index: 2; + } + #titlebar{ position: relative; z-index: 3 } + + #navigator-toolbox, + #sidebar-box, + #sidebar-main, + #sidebar-splitter, + #tabbrowser-tabbox{ + z-index: auto !important; + } + #navigator-toolbox:focus-within > .browser-toolbar{ + transform: translateY(0); + opacity: 1; + } + #titlebar:hover ~ .browser-toolbar, + .browser-titlebar:hover ~ :is(#nav-bar,#PersonalToolbar), + #nav-bar:hover, + #nav-bar:hover + #PersonalToolbar{ + transform: translateY(0); + opacity: 1; + } + :root[sessionrestored] #urlbar[popover]{ + opacity: 0; + pointer-events: none; + transform: translateY(var(--uc-navbar-transform)); + } + #mainPopupSet:has(> [role="group"][panelopen]) ~ toolbox #urlbar[popover], + .browser-titlebar:is(:hover,:focus-within) ~ #nav-bar #urlbar[popover], + #nav-bar:is(:hover,:focus-within) #urlbar[popover], + #urlbar-container > #urlbar[popover]:is([focused],[open]){ + opacity: 1; + pointer-events: auto; + transform: translateY(0); + } + #mainPopupSet:has(> [role="group"][panelopen]) ~ #navigator-toolbox > .browser-toolbar{ + transform: translateY(0); + opacity: 1; + } + #nav-bar.browser-titlebar{ + background: inherit; + } + #toolbar-menubar:not([autohide="true"]) ~ #nav-bar.browser-titlebar{ + background-position-y: -28px; /* best guess, could vary */ + border-top: none !important; + } + /* Move up the content view */ + :root[sessionrestored]:not([inFullscreen],[chromehidden~="toolbar"]) > body > #browser{ margin-top: var(--uc-navbar-transform); } '' From 15a2488af933c56d74ed9bed5edc4b9b3ffc8add Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 15 Nov 2024 15:20:43 +1100 Subject: [PATCH 029/213] home: tweaks to cover image scaling spoiler, its still scuffed --- modules/home/workstation/media/music.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/home/workstation/media/music.nix b/modules/home/workstation/media/music.nix index f4b75e7..ca04d3b 100644 --- a/modules/home/workstation/media/music.nix +++ b/modules/home/workstation/media/music.nix @@ -58,8 +58,6 @@ in { pause_icon = "▌▌"; liked_icon = "♥"; playback_window_position = "Top"; - cover_img_length = 9; - cover_img_width = 5; playback_window_width = 6; device = { From df751735d34a0aafee93f416d934d23242cc586a Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 16 Nov 2024 22:50:59 +1100 Subject: [PATCH 030/213] ooksdesk: add creative profile --- hosts/ooksdesk/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/ooksdesk/default.nix b/hosts/ooksdesk/default.nix index 2437158..ccb862e 100644 --- a/hosts/ooksdesk/default.nix +++ b/hosts/ooksdesk/default.nix @@ -19,7 +19,7 @@ workstation = { environment = "hyprland"; theme = "minimal"; - profiles = ["virtualization" "gaming" "media" "communication" "productivity"]; + profiles = ["creative" "virtualization" "gaming" "media" "communication" "productivity"]; default = { browser = "firefox"; terminal = "foot"; From 10c1ed7ecb7e85125c7b99d0c216157e8130477e Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 17 Nov 2024 21:57:53 +1100 Subject: [PATCH 031/213] home: swap to hozen color system --- .../hyprland/components/hyprlock.nix | 14 +++++---- .../workstation/hyprland/components/rofi.nix | 13 +++++---- .../hyprland/components/waybar.nix | 29 ++++++++++--------- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/modules/home/workstation/hyprland/components/hyprlock.nix b/modules/home/workstation/hyprland/components/hyprlock.nix index a829f9b..337a097 100644 --- a/modules/home/workstation/hyprland/components/hyprlock.nix +++ b/modules/home/workstation/hyprland/components/hyprlock.nix @@ -2,11 +2,13 @@ lib, osConfig, inputs', + hozen, ... }: let inherit (osConfig.ooknet.appearance) colorscheme fonts; inherit (colorscheme) palette; inherit (osConfig.ooknet.workstation) environment; + inherit (hozen) color; inherit (lib) mkIf; in { config = mkIf (environment == "hyprland") { @@ -29,7 +31,7 @@ in { background = { monitor = ""; path = ""; - color = "0xff${palette.base01}"; + color = "0xff${color.layout.body}"; }; input-field = { @@ -42,18 +44,18 @@ in { rounding = 0; fade_on_empty = false; placeholder_text = ""; - outer_color = "0xff${palette.base03}"; - inner_color = "0xff${palette.base00}"; - font_color = "0xff${palette.base05}"; + outer_color = "0xff${color.secondary.base}"; + inner_color = "0xff${color.layout.menu}"; + font_color = "0xff${color.typography.text}"; }; label = { monitor = ""; - text = " LOCKED"; + text = " \ "; position = "0, 150"; valign = "center"; halign = "center"; - color = "0xff${palette.base08}"; + color = "0xff${color.red.base}"; font_size = 30; font_family = "${fonts.monospace.family}"; }; diff --git a/modules/home/workstation/hyprland/components/rofi.nix b/modules/home/workstation/hyprland/components/rofi.nix index 70b7ce3..e63aea1 100644 --- a/modules/home/workstation/hyprland/components/rofi.nix +++ b/modules/home/workstation/hyprland/components/rofi.nix @@ -2,13 +2,14 @@ lib, config, osConfig, + hozen, pkgs, ... }: let inherit (lib) mkIf; - inherit (osConfig.ooknet.appearance) colorscheme fonts; - inherit (colorscheme) palette; + inherit (osConfig.ooknet.appearance) fonts; inherit (osConfig.ooknet.workstation) environment; + inherit (hozen) color; inherit (config.lib.formats.rasi) mkLiteral; in { config = mkIf (environment == "hyprland") { @@ -19,10 +20,10 @@ in { terminal = "${config.home.sessionVariables.TERMINAL}"; theme = { "*" = { - background = mkLiteral "#${palette.base00}"; - foreground = mkLiteral "#${palette.base05}"; - selected = mkLiteral "#${palette.base0B}"; - message = mkLiteral "#${palette.base0D}"; + background = mkLiteral "#${color.layout.menu}"; + foreground = mkLiteral "#${color.typography.text}"; + selected = mkLiteral "#${color.primary.base}"; + message = mkLiteral "#${color.blue.base}"; background-color = mkLiteral "@background"; border-color = mkLiteral "@foreground"; diff --git a/modules/home/workstation/hyprland/components/waybar.nix b/modules/home/workstation/hyprland/components/waybar.nix index 7213faf..89ac6b0 100644 --- a/modules/home/workstation/hyprland/components/waybar.nix +++ b/modules/home/workstation/hyprland/components/waybar.nix @@ -3,10 +3,11 @@ lib, pkgs, osConfig, + hozen, ... }: let - inherit (osConfig.ooknet.appearance) colorscheme fonts; - inherit (colorscheme) palette; + inherit (osConfig.ooknet.appearance) fonts; + inherit (hozen) color; inherit (osConfig.ooknet.hardware) monitors; inherit (osConfig.ooknet.workstation) environment; inherit (lib) mkIf head; @@ -90,7 +91,7 @@ in { * { font-family: "${fonts.monospace.family}"; font-size: 19px; - border: solid #${palette.base05}; + border: solid #${color.border.base}; } window#waybar { @@ -101,32 +102,32 @@ in { #clock, #battery, #workspaces { - background-color: #${palette.base00}; + background-color: #${color.layout.header}; padding-right: 10px; } #clock { padding-left: 10px; - border: 2px solid #${palette.base05}; + border: 2px solid #${color.border.base}; border-right: 0px; border-top-left-radius: 10px; } #battery { padding-left: 10px; - border-top: 2px solid #${palette.base05}; - border-bottom: 2px solid #${palette.base05}; + border-top: 2px solid #${color.border.base}; + border-bottom: 2px solid #${color.border.base}; border-left: 0px; } #battery.good { - color: #${palette.base0B}; + color: #${color.success.base}; } #battery.warning { - color: #${palette.base0A}; + color: #${color.warning.base}; } #battery.critical { - color: #${palette.base08}; + color: #${color.error.base}; } #tray { @@ -137,7 +138,7 @@ in { } #workspaces { - border: 2px solid #${palette.base05}; + border: 2px solid #${color.border.base}; border-left: 0; border-top-right-radius: 10px; } @@ -145,15 +146,15 @@ in { #workspace button, #workspaces button.active, #workspaces button.visible { - color: #${palette.base0B}; + color: #${color.primary.base}; } #workspaces button.urgent { - color: #${palette.base08}; + color: #${color.orange.base}; } #custom-hyprrecord { - color: #${palette.base08}; + color: #${color.red.base}; padding-right: 20px; } ''; From a30e2a0bc1eb8fc314057696069e34a92036b504 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 18 Nov 2024 11:28:33 +1100 Subject: [PATCH 032/213] lib: improve types/checks --- outputs/lib/color/check.nix | 72 ++++++++++++++++++++++++++++++------- outputs/lib/color/types.nix | 13 ++++--- outputs/lib/color/utils.nix | 5 ++- outputs/lib/default.nix | 2 +- outputs/lib/icon/utils.nix | 16 +++++++++ 5 files changed, 87 insertions(+), 21 deletions(-) create mode 100644 outputs/lib/icon/utils.nix diff --git a/outputs/lib/color/check.nix b/outputs/lib/color/check.nix index cb78c4b..d76738e 100644 --- a/outputs/lib/color/check.nix +++ b/outputs/lib/color/check.nix @@ -1,6 +1,6 @@ {lib, ...}: let inherit (lib) toInt all min max; - inherit (builtins) isInt isFloat match getAttr hasAttr; + inherit (builtins) mapAttrs elemAt isInt isFloat match getAttr hasAttr; # basic checks range = a: b: v: (v <= max a b) && (v >= min a b); @@ -15,8 +15,10 @@ hexPatternNoHash = match "[[:xdigit:]]{6}" color; isValid = hexPatternWithHash != null || hexPatternNoHash != null; in - assert isValid || throw "Invalid hex color format: ${color}"; - hexPatternWithHash != null || hexPatternNoHash != null; + if !isValid + then abort "Invalid hex color format: ${color}" + else color; + set = color: let hasAttributes = all (k: hasAttr k color) ["r" "g" "b"]; validPattern = all (k: let @@ -24,7 +26,9 @@ in match "[[:xdigit:]]{2}" v != null) ["r" "g" "b"]; in - hasAttributes && validPattern; + if !(hasAttributes && validPattern) + then abort "Invalid Hex values: r=${toString color.r}, g=${toString color.g}, b=${toString color.b}" + else color; }; rgb = { @@ -36,7 +40,10 @@ num != null && range 0 255 num; isValid = rgbPattern != null && all toNum rgbPattern; in - isValid; + if !isValid + then abort "Invalid RGB string: ${color}" + else color; + set = color: let hasAttributes = all (k: hasAttr k color) ["r" "g" "b"]; validRanges = all ( @@ -46,20 +53,61 @@ number v && range 0 255 v ) ["r" "g" "b"]; in - hasAttributes && validRanges; + if !(hasAttributes && validRanges) + then abort "Invalid RGB set: r=${toString color.r}, g=${toString color.g}, b=${toString color.b}" + else color; }; - hsl = { - # TODO: add range checks string = color: let hslPattern = match "([0-9]{1,3}),[ ]*([0-9]{1,3})%,[ ]*([0-9]{1,3})%" color; + # Convert matched values to numbers and check ranges + validateHSL = groups: let + h = toInt (elemAt groups 0); + s = toInt (elemAt groups 1); + l = toInt (elemAt groups 2); + in + h + != null + && h >= 0 + && h <= 360 + && s != null + && s >= 0 + && s <= 100 + && l != null + && l >= 0 + && l <= 100; + isValid = hslPattern != null && validateHSL hslPattern; in - hslPattern != null; + if !isValid + then abort "Invalid HSL string: ${color} (expected format: h(0-360),s(0-100%),l(0-100%))" + else color; set = color: let hasAttributes = all (k: hasAttr k color) ["h" "s" "l"]; - validRanges = hue color.h && all (k: unary (getAttr k color)) ["s" "l"]; + validRanges = + color.h + >= 0 + && color.h <= 360 + && color.s >= 0 + && color.s <= 1.0 + && color.l >= 0 + && color.l <= 1.0; in - hasAttributes && validRanges; + if !(hasAttributes && validRanges) + then + abort '' + Invalid HSL set: h=${toString color.h}, s=${toString color.s}, l=${toString color.l} + Expected: + h: 0-360 + s: 0.0-1.0 + l: 0.0-1.0 + '' + else color; }; -in {inherit range number unary hue hex rgb hsl;} + + # validate neutral hex values + neutrals = {neutrals, ...}: + mapAttrs (_: value: + hex.string value) + neutrals; +in {inherit neutrals range number unary hue hex rgb hsl;} diff --git a/outputs/lib/color/types.nix b/outputs/lib/color/types.nix index 850e647..c3b9806 100644 --- a/outputs/lib/color/types.nix +++ b/outputs/lib/color/types.nix @@ -1,7 +1,6 @@ { check, math, - ... }: let inherit (math) round; hex = { @@ -12,19 +11,19 @@ }: let attrs = {inherit r g b;}; in - assert check.hex.set attrs || throw "Invalid Hex values: r=${toString r}, g=${toString g}, b=${toString b}"; attrs; + check.hex.set attrs; string = r: g: b: let str = "${r}${g}${b}"; in - assert check.hex.string str || throw "Invalid Hex value: ${str}"; str; + check.hex.string str; }; rgb = { string = r: g: b: let str = "${toString r},${toString g},${toString b}"; in - assert check.rgb.string str || throw "Invalid RBG string format: ${str}"; str; + check.rgb.string str; set = { r, g, @@ -32,13 +31,13 @@ }: let attrs = {inherit r g b;}; in - assert check.rgb.set attrs || throw "Invalid RGB values: r=${toString r}, g=${toString g}, b=${toString b}"; attrs; + check.rgb.set attrs; }; hsl = { string = h: s: l: let str = "${toString (round h)}, ${toString (round (s * 100))}%, ${toString (round (l * 100))}%"; in - assert check.hsl.string str || throw "Invalid HSL values: ${str}"; str; + check.hsl.string str; set = { h, s, @@ -46,6 +45,6 @@ }: let attrs = {inherit h s l;}; in - assert check.hsl.set attrs || throw "Invalid HSL values: h=${toString h}, s=${toString s}, l=${toString l}"; attrs; + check.hsl.set attrs; }; in {inherit hex hsl rgb;} diff --git a/outputs/lib/color/utils.nix b/outputs/lib/color/utils.nix index a6abb35..dc0e160 100644 --- a/outputs/lib/color/utils.nix +++ b/outputs/lib/color/utils.nix @@ -2,6 +2,7 @@ math, types, translate, + check, }: let # Base modification functions modifyHSL = hexStr: modifications: let @@ -94,6 +95,8 @@ then mkDarkColorScale else mkLightColorScale; + validNeutrals = check.neutrals args; + # Generate color scales colors = { red = mkColorScale args.red; @@ -201,7 +204,7 @@ # Common structure for both themes neutrals = { inherit - (args.neutrals) + (validNeutrals) "50" "100" "150" diff --git a/outputs/lib/default.nix b/outputs/lib/default.nix index a6a7c1e..42ee09f 100644 --- a/outputs/lib/default.nix +++ b/outputs/lib/default.nix @@ -22,7 +22,7 @@ }; utils = import ./color/utils.nix { inherit (ook-lib) math; - inherit types translate; + inherit check types translate; }; in { inherit check types translate utils; diff --git a/outputs/lib/icon/utils.nix b/outputs/lib/icon/utils.nix new file mode 100644 index 0000000..57ac62c --- /dev/null +++ b/outputs/lib/icon/utils.nix @@ -0,0 +1,16 @@ +{ + lib, + pkgs, + ... +}: let + inherit (lib) concatStrings; + + mkIcon = { + svg, + colors, {}, + height ? 24, + width ? 24 + }: let + + in + in From edc99e84efed3e77abb169c90bf0bae50902d46b Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 18 Nov 2024 11:31:16 +1100 Subject: [PATCH 033/213] neovim: update plugin module names --- outputs/pkgs/ook-vim/plugins/ui.nix | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/outputs/pkgs/ook-vim/plugins/ui.nix b/outputs/pkgs/ook-vim/plugins/ui.nix index f709199..31512fa 100644 --- a/outputs/pkgs/ook-vim/plugins/ui.nix +++ b/outputs/pkgs/ook-vim/plugins/ui.nix @@ -14,14 +14,12 @@ }; # < https://github.com/NotAShelf/nvf/tree/main/modules/plugins/visuals > visuals = { - enable = true; - # icons that other plugins depend on. - nvimWebDevicons.enable = true; + nvim-web-devicons.enable = true; fidget-nvim.enable = true; # indent lines - indentBlankline = { + indent-blankline = { enable = true; setupOpts = { scope = { From ecbb5c8700290b14a9e8b428f99ee3f1ac190160 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 18 Nov 2024 17:47:27 +1100 Subject: [PATCH 034/213] home: coloscheme module -> hozen arg --- .../tools/multiplexer/zellij/default.nix | 35 ++-- .../zellij/layouts/defaultLayout.nix | 41 ++-- .../zellij/layouts/flakeLayout.nix | 41 ++-- .../zellij/layouts/scriptLayout.nix | 41 ++-- modules/home/workstation/appearance/gtk.nix | 8 +- .../home/workstation/appearance/gtkCss.nix | 196 ++++++++++-------- .../workstation/browser/firefox/default.nix | 3 +- .../browser/firefox/theme/ooksfox.nix | 14 +- .../workstation/browser/firefox/tridactyl.nix | 27 +-- .../communication/vesktop/default.nix | 25 +-- modules/home/workstation/media/music.nix | 23 +- .../home/workstation/productivity/zathura.nix | 43 ++-- modules/home/workstation/terminal/foot.nix | 3 +- 13 files changed, 263 insertions(+), 237 deletions(-) diff --git a/modules/home/console/tools/multiplexer/zellij/default.nix b/modules/home/console/tools/multiplexer/zellij/default.nix index fa85919..de5de56 100644 --- a/modules/home/console/tools/multiplexer/zellij/default.nix +++ b/modules/home/console/tools/multiplexer/zellij/default.nix @@ -3,9 +3,10 @@ config, lib, pkgs, + hozen, ... }: let - inherit (osConfig.ooknet.appearance.colorscheme) slug palette; + inherit (hozen) color; inherit (osConfig.ooknet) console; inherit (osConfig.ooknet.host) admin; inherit (lib) mkIf; @@ -16,24 +17,24 @@ in { programs.zellij = { enable = true; settings = { - theme = "${slug}"; + theme = "${color.slug}"; default_shell = "${admin.shell}"; default_layout = "default"; pane_frames = false; scrollback_editor = "${console.editor}"; themes = { - "${slug}" = { - fg = "#${palette.base05}"; - bg = "#${palette.base00}"; - black = "#${palette.base00}"; - red = "#${palette.base08}"; - green = "#${palette.base0B}"; - yellow = "#${palette.base0A}"; - blue = "#${palette.base0D}"; - magenta = "#${palette.base0E}"; - cyan = "#${palette.base0C}"; - white = "#${palette.base05}"; - orange = "#${palette.base09}"; + "${color.slug}" = { + fg = "#${color.base05}"; + bg = "#${color.base00}"; + black = "#${color.base00}"; + red = "#${color.base08}"; + green = "#${color.base0B}"; + yellow = "#${color.base0A}"; + blue = "#${color.base0D}"; + magenta = "#${color.base0E}"; + cyan = "#${color.base0C}"; + white = "#${color.base05}"; + orange = "#${color.base09}"; }; }; }; @@ -42,11 +43,11 @@ in { # Layouts xdg.configFile = { # Default layout - "zellij/layouts/default.kdl" = import ./layouts/defaultLayout.nix {inherit pkgs config osConfig;}; + "zellij/layouts/default.kdl" = import ./layouts/defaultLayout.nix {inherit pkgs config osConfig hozen;}; # Layout for bash scripts - "zellij/layouts/script.kdl" = import ./layouts/scriptLayout.nix {inherit pkgs config osConfig;}; + "zellij/layouts/script.kdl" = import ./layouts/scriptLayout.nix {inherit pkgs config osConfig hozen;}; # Layout for configuring my flake - "zellij/layouts/flake.kdl" = import ./layouts/flakeLayout.nix {inherit pkgs config osConfig;}; + "zellij/layouts/flake.kdl" = import ./layouts/flakeLayout.nix {inherit pkgs config osConfig hozen;}; # Additional keybinds "zellij/config.kdl".text = # kdl diff --git a/modules/home/console/tools/multiplexer/zellij/layouts/defaultLayout.nix b/modules/home/console/tools/multiplexer/zellij/layouts/defaultLayout.nix index 81ecb4b..10d842a 100644 --- a/modules/home/console/tools/multiplexer/zellij/layouts/defaultLayout.nix +++ b/modules/home/console/tools/multiplexer/zellij/layouts/defaultLayout.nix @@ -1,9 +1,10 @@ { pkgs, osConfig, + hozen, ... }: let - inherit (osConfig.ooknet.appearance.colorscheme) palette; + inherit (hozen) color; in { text = # kdl @@ -14,40 +15,40 @@ in { plugin location="file:${pkgs.zjstatus}/bin/zjstatus.wasm" { format_left "{mode}" format_right "{session} {command_git_branch} {datetime}" - format_center "#[fg=#${palette.base0D},bold] {tabs}" + format_center "#[fg=#${color.base0D},bold] {tabs}" format_space "" border_enabled "true" border_char "─" - border_format "#[fg=#${palette.base05}]{char}" + border_format "#[fg=#${color.base05}]{char}" border_position "bottom" hide_frame_for_single_pane "true" - mode_normal "#[fg=#${palette.base0D}] " - mode_tmux "#[fg=#${palette.base0E}] " - mode_pane "#[fg=#${palette.base08}] " - mode_tab "#[fg=#${palette.base08}] " - mode_rename_tab "#[fg=#${palette.base08}] " - mode_rename_pane "#[fg=#${palette.base08}] " - mode_session "#[fg=#${palette.base08}] " - mode_locked "#[fg=#${palette.base05}] " - mode_move "#[fg=#${palette.base0B}] " - mode_resize "#[fg=#${palette.base0B}] " - mode_prompt "#[fg=#${palette.base0A}] " - mode_search "#[fg=#${palette.base0A}] " - mode_enter_search "#[fg=#${palette.base0A}] " + mode_normal "#[fg=#${color.base0D}] " + mode_tmux "#[fg=#${color.base0E}] " + mode_pane "#[fg=#${color.base08}] " + mode_tab "#[fg=#${color.base08}] " + mode_rename_tab "#[fg=#${color.base08}] " + mode_rename_pane "#[fg=#${color.base08}] " + mode_session "#[fg=#${color.base08}] " + mode_locked "#[fg=#${color.base05}] " + mode_move "#[fg=#${color.base0B}] " + mode_resize "#[fg=#${color.base0B}] " + mode_prompt "#[fg=#${color.base0A}] " + mode_search "#[fg=#${color.base0A}] " + mode_enter_search "#[fg=#${color.base0A}] " - tab_normal "#[bg=#${palette.base01}] {name} " - tab_active "#[bg=#${palette.base02}] {name} " + tab_normal "#[bg=#${color.base01}] {name} " + tab_active "#[bg=#${color.base02}] {name} " tab_separator " " command_git_branch_command "git rev-parse --abbrev-ref HEAD" - command_git_branch_format "#[fg=#${palette.base0C}] {stdout} " + command_git_branch_format "#[fg=#${color.base0C}] {stdout} " command_git_branch_interval "10" command_git_branch_rendermode "static" - datetime "#[fg=#${palette.base05},bold] {format} " + datetime "#[fg=#${color.base05},bold] {format} " datetime_format "%I:%M %p" datetime_timezone "${osConfig.time.timeZone}" } diff --git a/modules/home/console/tools/multiplexer/zellij/layouts/flakeLayout.nix b/modules/home/console/tools/multiplexer/zellij/layouts/flakeLayout.nix index 565ba13..4a50b5b 100644 --- a/modules/home/console/tools/multiplexer/zellij/layouts/flakeLayout.nix +++ b/modules/home/console/tools/multiplexer/zellij/layouts/flakeLayout.nix @@ -1,9 +1,10 @@ { pkgs, + hozen, osConfig, ... }: let - inherit (osConfig.ooknet.appearance.colorscheme) palette; + inherit (hozen) color; in { text = /* @@ -16,40 +17,40 @@ in { plugin location="file:${pkgs.zjstatus}/bin/zjstatus.wasm" { format_left "{mode}" format_right "{session} {command_git_branch} {datetime}" - format_center "#[fg=#${palette.base0D},bold] {tabs}" + format_center "#[fg=#${color.base0D},bold] {tabs}" format_space "" border_enabled "true" border_char "─" - border_format "#[fg=#${palette.base05}]{char}" + border_format "#[fg=#${color.base05}]{char}" border_position "bottom" hide_frame_for_single_pane "true" - mode_normal "#[fg=#${palette.base0D}] " - mode_tmux "#[fg=#${palette.base0E}] " - mode_pane "#[fg=#${palette.base08}] " - mode_tab "#[fg=#${palette.base08}] " - mode_rename_tab "#[fg=#${palette.base08}] " - mode_rename_pane "#[fg=#${palette.base08}] " - mode_session "#[fg=#${palette.base08}] " - mode_locked "#[fg=#${palette.base05}] " - mode_move "#[fg=#${palette.base0B}] " - mode_resize "#[fg=#${palette.base0B}] " - mode_prompt "#[fg=#${palette.base0A}] " - mode_search "#[fg=#${palette.base0A}] " - mode_enter_search "#[fg=#${palette.base0A}] " + mode_normal "#[fg=#${color.base0D}] " + mode_tmux "#[fg=#${color.base0E}] " + mode_pane "#[fg=#${color.base08}] " + mode_tab "#[fg=#${color.base08}] " + mode_rename_tab "#[fg=#${color.base08}] " + mode_rename_pane "#[fg=#${color.base08}] " + mode_session "#[fg=#${color.base08}] " + mode_locked "#[fg=#${color.base05}] " + mode_move "#[fg=#${color.base0B}] " + mode_resize "#[fg=#${color.base0B}] " + mode_prompt "#[fg=#${color.base0A}] " + mode_search "#[fg=#${color.base0A}] " + mode_enter_search "#[fg=#${color.base0A}] " - tab_normal "#[bg=#${palette.base01}] {name} " - tab_active "#[bg=#${palette.base02}] {name} " + tab_normal "#[bg=#${color.base01}] {name} " + tab_active "#[bg=#${color.base02}] {name} " tab_separator " " command_git_branch_command "git rev-parse --abbrev-ref HEAD" - command_git_branch_format "#[fg=#${palette.base0C}] {stdout} " + command_git_branch_format "#[fg=#${color.base0C}] {stdout} " command_git_branch_interval "10" command_git_branch_rendermode "static" - datetime "#[fg=#${palette.base05},bold] {format} " + datetime "#[fg=#${color.base05},bold] {format} " datetime_format "%I:%M %p" datetime_timezone "${osConfig.time.timeZone}" } diff --git a/modules/home/console/tools/multiplexer/zellij/layouts/scriptLayout.nix b/modules/home/console/tools/multiplexer/zellij/layouts/scriptLayout.nix index a1c7e9a..835b8ee 100644 --- a/modules/home/console/tools/multiplexer/zellij/layouts/scriptLayout.nix +++ b/modules/home/console/tools/multiplexer/zellij/layouts/scriptLayout.nix @@ -1,9 +1,10 @@ { pkgs, + hozen, osConfig, ... }: let - inherit (osConfig.ooknet.appearance.colorscheme) palette; + inherit (hozen) color; in { text = /* @@ -16,40 +17,40 @@ in { plugin location="file:${pkgs.zjstatus}/bin/zjstatus.wasm" { format_left "{mode}" format_right "{session} {command_git_branch} {datetime}" - format_center "#[fg=#${palette.base0D},bold] {tabs}" + format_center "#[fg=#${color.base0D},bold] {tabs}" format_space "" border_enabled "true" border_char "─" - border_format "#[fg=#${palette.base05}]{char}" + border_format "#[fg=#${color.base05}]{char}" border_position "bottom" hide_frame_for_single_pane "true" - mode_normal "#[fg=#${palette.base0D}] " - mode_tmux "#[fg=#${palette.base0E}] " - mode_pane "#[fg=#${palette.base08}] " - mode_tab "#[fg=#${palette.base08}] " - mode_rename_tab "#[fg=#${palette.base08}] " - mode_rename_pane "#[fg=#${palette.base08}] " - mode_session "#[fg=#${palette.base08}] " - mode_locked "#[fg=#${palette.base05}] " - mode_move "#[fg=#${palette.base0B}] " - mode_resize "#[fg=#${palette.base0B}] " - mode_prompt "#[fg=#${palette.base0A}] " - mode_search "#[fg=#${palette.base0A}] " - mode_enter_search "#[fg=#${palette.base0A}] " + mode_normal "#[fg=#${color.base0D}] " + mode_tmux "#[fg=#${color.base0E}] " + mode_pane "#[fg=#${color.base08}] " + mode_tab "#[fg=#${color.base08}] " + mode_rename_tab "#[fg=#${color.base08}] " + mode_rename_pane "#[fg=#${color.base08}] " + mode_session "#[fg=#${color.base08}] " + mode_locked "#[fg=#${color.base05}] " + mode_move "#[fg=#${color.base0B}] " + mode_resize "#[fg=#${color.base0B}] " + mode_prompt "#[fg=#${color.base0A}] " + mode_search "#[fg=#${color.base0A}] " + mode_enter_search "#[fg=#${color.base0A}] " - tab_normal "#[bg=#${palette.base01}] {name} " - tab_active "#[bg=#${palette.base02}] {name} " + tab_normal "#[bg=#${color.base01}] {name} " + tab_active "#[bg=#${color.base02}] {name} " tab_separator " " command_git_branch_command "git rev-parse --abbrev-ref HEAD" - command_git_branch_format "#[fg=#${palette.base0C}] {stdout} " + command_git_branch_format "#[fg=#${color.base0C}] {stdout} " command_git_branch_interval "10" command_git_branch_rendermode "static" - datetime "#[fg=#${palette.base05},bold] {format} " + datetime "#[fg=#${color.base05},bold] {format} " datetime_format "%I:%M %p" datetime_timezone "${osConfig.time.timeZone}" } diff --git a/modules/home/workstation/appearance/gtk.nix b/modules/home/workstation/appearance/gtk.nix index e6229d4..35ed7b5 100644 --- a/modules/home/workstation/appearance/gtk.nix +++ b/modules/home/workstation/appearance/gtk.nix @@ -1,11 +1,12 @@ { osConfig, + hozen, pkgs, ... }: let inherit (osConfig.ooknet.appearance) fonts; - gtkCss = import ./gtkCss.nix {inherit osConfig;}; + gtkCss = import ./gtkCss.nix {inherit hozen;}; in { config = rec { gtk = { @@ -30,7 +31,10 @@ in { gtk4.extraConfig.gtk-application-prefer-dark-theme = true; }; - dconf.settings."org/gnome/desktop/interface".color-scheme = "prefer-dark"; + dconf.settings = { + "org/gnome/desktop/interface".color-scheme = "prefer-dark"; + "org/gtk/Settings/Debug".enable-inspector-keybinding = true; + }; #TODO: add gtk css configuration diff --git a/modules/home/workstation/appearance/gtkCss.nix b/modules/home/workstation/appearance/gtkCss.nix index 6f72f40..ee93d39 100644 --- a/modules/home/workstation/appearance/gtkCss.nix +++ b/modules/home/workstation/appearance/gtkCss.nix @@ -1,94 +1,106 @@ -{osConfig}: let - inherit (osConfig.ooknet.appearance.colorscheme) palette; +{hozen}: let + inherit (hozen) color; in - with palette; - #css - '' + /* + css + */ + '' - @define-color accent_color #${green}; - @define-color accent_bg_color #${text}; - @define-color accent_fg_color #${mantle}; - @define-color destructive_color #${blue}; - @define-color destructive_bg_color #${dull-blue}; - @define-color destructive_fg_color #${text}; - @define-color success_color #${cyan}; - @define-color success_bg_color #${green}; - @define-color success_fg_color #${text}; - @define-color warning_color #${yellow}; - @define-color warning_bg_color #${red}; - @define-color warning_fg_color #${text}; - @define-color error_color #${red}; - @define-color error_bg_color #${dull-red}; - @define-color error_fg_color #${text}; - @define-color window_bg_color #${crust}; - @define-color window_fg_color #${text}; - @define-color view_bg_color #${mantle}; - @define-color view_fg_color #${text}; - @define-color sidebar_bg_color #${crust}; - @define-color sidebar_fg_color #${text}; - @define-color sidebar_backdrop_color @window_bg_color; - @define-color sidebar_shade_color rgba(0, 0, 0, 0.07); - @define-color secondary_sidebar_bg_color @sidebar_bg_color; - @define-color secondary_sidebar_fg_color @sidebar_fg_color; - @define-color secondary_sidebar_backdrop_color @sidebar_backdrop_color; - @define-color secondary_sidebar_shade_color @sidebar_shade_color; - @define-color headerbar_bg_color #${base}; - @define-color headerbar_fg_color #${text}; - @define-color headerbar_border_color #${text}; - @define-color headerbar_backdrop_color @window_bg_color; - @define-color headerbar_shade_color rgba(0, 0, 0, 0.36); - @define-color card_bg_color rgba(255, 255, 255, 0.08); - @define-color card_fg_color #${text}; - @define-color card_shade_color rgba(0, 0, 0, 0.36); - @define-color dialog_bg_color #${mantle}; - @define-color dialog_fg_color #${text}; - @define-color popover_bg_color #${mantle}; - @define-color popover_fg_color #${text}; - @define-color shade_color rgba(0,0,0,0.36); - @define-color scrollbar_outline_color rgba(0,0,0,0.5); - @define-color blue_1 #${blue}; - @define-color blue_2 #${blue}; - @define-color blue_3 #${blue}; - @define-color blue_4 #${blue}; - @define-color blue_5 #${blue}; - @define-color green_1 #b8bb26; - @define-color green_2 #b8bb26; - @define-color green_3 #b8bb26; - @define-color green_4 #b8bb26; - @define-color green_5 #b8bb26; - @define-color yellow_1 #fabd2f; - @define-color yellow_2 #fabd2f; - @define-color yellow_3 #fabd2f; - @define-color yellow_4 #fabd2f; - @define-color yellow_5 #fabd2f; - @define-color orange_1 #fe8019; - @define-color orange_2 #fe8019; - @define-color orange_3 #fe8019; - @define-color orange_4 #fe8019; - @define-color orange_5 #fe8019; - @define-color red_1 #fb4934; - @define-color red_2 #fb4934; - @define-color red_3 #fb4934; - @define-color red_4 #fb4934; - @define-color red_5 #fb4934; - @define-color purple_1 #d3869b; - @define-color purple_2 #d3869b; - @define-color purple_3 #d3869b; - @define-color purple_4 #d3869b; - @define-color purple_5 #d3869b; - @define-color brown_1 #d65d0e; - @define-color brown_2 #d65d0e; - @define-color brown_3 #d65d0e; - @define-color brown_4 #d65d0e; - @define-color brown_5 #d65d0e; - @define-color light_1 #${base05}; - @define-color light_2 #${base06}; - @define-color light_3 #${base07}; - @define-color light_4 #${base07}; - @define-color light_5 #${base07}; - @define-color dark_1 #${base00}; - @define-color dark_2 #${base01}; - @define-color dark_3 #${base02}; - @define-color dark_4 #${base03}; - @define-color dark_5 #${base04}; - '' + @define-color accent_color #${color.primary.base}; + @define-color accent_bg_color #${color.primary.soft1}; + @define-color accent_fg_color #${color.layout.menu}; + + @define-color destructive_color #${color.blue.base}; + @define-color destructive_bg_color #${color.blue.soft2}; + @define-color destructive_fg_color #${color.typography.text}; + + @define-color success_color #${color.success.base}; + @define-color success_bg_color #${color.success.bg}; + @define-color success_fg_color #${color.success.fg}; + + @define-color warning_color #${color.warning.base}; + @define-color warning_bg_color #${color.warning.bg}; + @define-color warning_fg_color #${color.warning.fg}; + + @define-color error_color #${color.error.base}; + @define-color error_bg_color #${color.error.bg}; + @define-color error_fg_color #${color.error.fg}; + + @define-color window_bg_color #${color.layout.menu}; + @define-color window_fg_color #${color.typography.text}; + + @define-color view_bg_color #${color.layout.body}; + @define-color view_fg_color #${color.typography.text}; + + @define-color sidebar_bg_color #${color.layout.menu}; + @define-color sidebar_fg_color #${color.typography.text}; + @define-color sidebar_backdrop_color @window_bg_color; + @define-color sidebar_shade_color rgba(0, 0, 0, 0.07); + @define-color secondary_sidebar_bg_color @sidebar_bg_color; + @define-color secondary_sidebar_fg_color @sidebar_fg_color; + @define-color secondary_sidebar_backdrop_color @sidebar_backdrop_color; + @define-color secondary_sidebar_shade_color @sidebar_shade_color; + @define-color headerbar_bg_color #${color.layout.header}; + @define-color headerbar_fg_color #${color.typography.text}; + @define-color headerbar_border_color #${color.border.base}; + @define-color headerbar_backdrop_color @window_bg_color; + @define-color headerbar_shade_color rgba(0, 0, 0, 0.36); + @define-color card_bg_color rgba(255, 255, 255, 0.08); + @define-color card_fg_color #${color.typography.text}; + @define-color card_shade_color rgba(0, 0, 0, 0.36); + @define-color dialog_bg_color #${color.layout.body}; + @define-color dialog_fg_color #${color.typography.text}; + @define-color popover_bg_color #${color.layout.menu}; + @define-color popover_fg_color #${color.typography.text}; + @define-color shade_color rgba(0,0,0,0.36); + @define-color scrollbar_outline_color rgba(0,0,0,0.5); + @define-color blue_1 #${color.blue.base}; + @define-color blue_2 #${color.blue.base}; + @define-color blue_3 #${color.blue.base}; + @define-color blue_4 #${color.blue.base}; + @define-color blue_5 #${color.blue.base}; + @define-color green_1 #${color.green.base}; + @define-color green_2 #${color.green.base}; + @define-color green_3 #${color.green.base}; + @define-color green_4 #${color.green.base}; + @define-color green_5 #${color.green.base}; + @define-color yellow_1 #${color.yellow.base}; + @define-color yellow_2 #${color.yellow.base}; + @define-color yellow_3 #${color.yellow.base}; + @define-color yellow_4 #${color.yellow.base}; + @define-color yellow_5 #${color.yellow.base}; + @define-color orange_1 #${color.orange.base}; + @define-color orange_2 #${color.orange.base}; + @define-color orange_3 #${color.orange.base}; + @define-color orange_4 #${color.orange.base}; + @define-color orange_5 #${color.orange.base}; + @define-color red_1 #${color.red.base}; + @define-color red_2 #${color.red.base}; + @define-color red_3 #${color.red.base}; + @define-color red_4 #${color.red.base}; + @define-color red_5 #${color.red.base}; + @define-color purple_1 #${color.purple.base}; + @define-color purple_2 #${color.purple.base}; + @define-color purple_3 #${color.purple.base}; + @define-color purple_4 #${color.purple.base}; + @define-color purple_5 #${color.purple.base}; + @define-color brown_1 #${color.brown.base}; + @define-color brown_2 #${color.brown.base}; + @define-color brown_3 #${color.brown.base}; + @define-color brown_4 #${color.brown.base}; + @define-color brown_5 #${color.brown.base}; + @define-color light_1 #${color.neutrals."250"}; + @define-color light_2 #${color.neutrals."200"}; + @define-color light_3 #${color.neutrals."150"}; + @define-color light_4 #${color.neutrals."100"}; + @define-color light_5 #${color.neutrals."50"}; + @define-color dark_1 #${color.neutrals."700"}; + @define-color dark_2 #${color.neutrals."750"}; + @define-color dark_3 #${color.neutrals."800"}; + @define-color dark_4 #${color.neutrals."850"}; + @define-color dark_5 #${color.neutrals."900"}; + + * { + border-radius: 0; + } + '' diff --git a/modules/home/workstation/browser/firefox/default.nix b/modules/home/workstation/browser/firefox/default.nix index 3deb0b8..560ed0e 100644 --- a/modules/home/workstation/browser/firefox/default.nix +++ b/modules/home/workstation/browser/firefox/default.nix @@ -8,8 +8,7 @@ }: let inherit (lib) mkIf mkMerge; inherit (osConfig.ooknet.host) admin; - inherit (osConfig.ooknet.appearance) colorscheme fonts; - inherit (colorscheme) palette; + inherit (osConfig.ooknet.appearance) fonts; inherit (osConfig.ooknet.workstation) default; addons = inputs'.firefox-addons.packages; diff --git a/modules/home/workstation/browser/firefox/theme/ooksfox.nix b/modules/home/workstation/browser/firefox/theme/ooksfox.nix index e10baf0..1526974 100644 --- a/modules/home/workstation/browser/firefox/theme/ooksfox.nix +++ b/modules/home/workstation/browser/firefox/theme/ooksfox.nix @@ -26,15 +26,19 @@ in border-radius: 0 !important; font-family: ${fonts.monospace.family}; } - #nav-bar { border: var(--border) !important; background-color: var(--clr-menu) !important; + margin-top: 0px !important; } #urlbar { text-align: center; } + .browser-toolbar { + padding-bottom: 1px !important; + } + #urlbar-background { background-color: transparent !important; border: unset !important; @@ -102,13 +106,13 @@ in } .tabbrowser-tab { - padding: 5px !important; - padding-left: 5px !important; + padding: 3px !important; + padding-left: 3px !important; + --tab-label-mask-size: unset !important; } .tabbrowser-tab[pinned] { - margin: 0px !important; - padding: 5px !important; + padding: 3px !important; } #tabbrowser-tabs[haspinnedtabs]:not([positionpinnedtabs])[orient="horizontal"] > #tabbrowser-arrowscrollbox > .tabbrowser-tab:nth-child(1 of :not([pinned], [hidden])) { diff --git a/modules/home/workstation/browser/firefox/tridactyl.nix b/modules/home/workstation/browser/firefox/tridactyl.nix index 761ae2f..86a6e31 100644 --- a/modules/home/workstation/browser/firefox/tridactyl.nix +++ b/modules/home/workstation/browser/firefox/tridactyl.nix @@ -1,11 +1,12 @@ { lib, osConfig, + hozen, ... }: let inherit (lib) mkIf; - inherit (osConfig.ooknet.appearance) colorscheme fonts; - inherit (colorscheme) palette; + inherit (osConfig.ooknet.appearance) fonts; + inherit (hozen) color; inherit (osConfig.ooknet.workstation) default; cfg = osConfig.ooknet.workstation.programs.firefox; in { @@ -55,17 +56,17 @@ in { '' :root { --font: ${fonts.monospace.family}; - --bg: #${palette.base00}; - --fg: #${palette.base05}; - --red: #${palette.base08}; - --green: #${palette.base0B}; - --blue: #${palette.base0D}; - --yellow: #${palette.base0A}; - --purple: #${palette.base0E}; - --orange: #${palette.base09}; - --cyan: #${palette.base0C}; - --comment: #${palette.base04}; - --selectedline: #${palette.base02}; + --bg: #${color.layout.menu}; + --fg: #${color.typography.text}; + --red: #${color.red.base}; + --green: #${color.green.base}; + --blue: #${color.blue.base}; + --yellow: #${color.yellow.base}; + --purple: #${color.purple.base}; + --orange: #${color.orange.base}; + --cyan: #${color.teal.base}; + --comment: #${color.typography.subtext}; + --selectedline: #${color.secondary.base}; --tridactyl-fg: var(--fg); diff --git a/modules/home/workstation/communication/vesktop/default.nix b/modules/home/workstation/communication/vesktop/default.nix index 00564aa..4ca0ce3 100644 --- a/modules/home/workstation/communication/vesktop/default.nix +++ b/modules/home/workstation/communication/vesktop/default.nix @@ -1,13 +1,13 @@ { - config, osConfig, + hozen, lib, pkgs, ... }: let inherit (lib) mkIf elem; - inherit (osConfig.ooknet.appearance) colorscheme fonts; - inherit (colorscheme) palette; + inherit (hozen) color; + inherit (osConfig.ooknet.appearance) fonts; inherit (osConfig.ooknet.workstation) profiles; vesktopMime = {"x-scheme-handler/discord" = ["vesktop.desktop"];}; @@ -18,6 +18,7 @@ in { (pkgs.vesktop.overrideAttrs (old: { patches = (old.patches or []) ++ [./vesktop-patch.patch]; })) + pkgs.equibop ]; xdg.configFile."vesktop/themes/nix.css".text = @@ -32,17 +33,17 @@ in { */ :root { - --nix-bg1: #${palette.base00}; - --nix-bg2: #${palette.base01}; - --nix-bg3: #${palette.base02}; + --nix-bg1: #${color.base00}; + --nix-bg2: #${color.base01}; + --nix-bg3: #${color.base02}; - --nix-fg1: #${palette.base05}; - --nix-fg2: #${palette.base07}; - --nix-fg3: #${palette.base03}; - --nix-link: #${palette.base0D}; + --nix-fg1: #${color.base05}; + --nix-fg2: #${color.base07}; + --nix-fg3: #${color.base03}; + --nix-link: #${color.base0D}; - --nix-accent: #${palette.base08}; - --nix-hi: #${palette.base0B}; + --nix-accent: #${color.base08}; + --nix-hi: #${color.base0B}; --font-mono: ${fonts.monospace.family}, monospace; --font-regular: ${fonts.regular.family}, sans serif; diff --git a/modules/home/workstation/media/music.nix b/modules/home/workstation/media/music.nix index ca04d3b..5ed6151 100644 --- a/modules/home/workstation/media/music.nix +++ b/modules/home/workstation/media/music.nix @@ -3,17 +3,18 @@ pkgs, config, lib, + hozen, ... }: let inherit (lib) mkIf getExe elem; inherit (builtins) attrValues; - inherit (osConfig.ooknet.appearance.colorscheme) palette; inherit (osConfig.networking) hostName; inherit (osConfig.ooknet.console.tools) zellij; inherit (osConfig.ooknet.console) multiplexer; inherit (osConfig.ooknet.workstation) profiles; inherit (osConfig.age.secrets) spotify_key; inherit (config.ooknet) binds; + inherit (hozen) color; in { config = mkIf (elem "media" profiles) { home.packages = attrValues { @@ -78,11 +79,11 @@ in { color = { gradient = 1; gradient_count = 5; - gradient_color_1 = "'#${palette.base0A}'"; - gradient_color_2 = "'#${palette.base0B}'"; - gradient_color_3 = "'#${palette.base0C}'"; - gradient_color_4 = "'#${palette.base0D}'"; - gradient_color_5 = "'#${palette.base0E}'"; + gradient_color_1 = "'#${color.primary.base}'"; + gradient_color_2 = "'#${color.primary.hard1}'"; + gradient_color_3 = "'#${color.primary.hard2}'"; + gradient_color_4 = "'#${color.primary.hard3}'"; + gradient_color_5 = "'#${color.primary.hard4}'"; }; }; }; @@ -105,18 +106,18 @@ in { border_enabled "true" border_char "─" - border_format "#[fg=#${palette.base0D}]{char}" + border_format "#[fg=#${color.base0D}]{char}" border_position "bottom" hide_frame_for_single_pane "true" - mode_normal "#[fg=${palette.base0D}]󰝚" + mode_normal "#[fg=${color.base0D}]󰝚" - tab_normal "#[bg=#${palette.base01}] {name} " - tab_active "#[bg=#${palette.base02}] {name} " + tab_normal "#[bg=#${color.base01}] {name} " + tab_active "#[bg=#${color.base02}] {name} " tab_separator " " - datetime "#[fg=#${palette.base05},bold] {format} " + datetime "#[fg=#${color.base05},bold] {format} " datetime_format "%I:%M %p" datetime_timezone "${osConfig.time.timeZone}" } diff --git a/modules/home/workstation/productivity/zathura.nix b/modules/home/workstation/productivity/zathura.nix index cbec03d..e8fee5a 100644 --- a/modules/home/workstation/productivity/zathura.nix +++ b/modules/home/workstation/productivity/zathura.nix @@ -1,12 +1,13 @@ { lib, osConfig, + hozen, ... }: let inherit (lib) mkIf elem; - inherit (osConfig.ooknet.appearance.colorscheme) palette; inherit (osConfig.ooknet.appearance) fonts; inherit (osConfig.ooknet.workstation) profiles; + inherit (hozen) color; zathuraMime = {"application/pdf" = ["org.pwmt.zathura.desktop"];}; in { @@ -17,26 +18,26 @@ in { font = "${fonts.regular.family} 14"; recolor = true; selection-clipboard = "clipboard"; - default-bg = "#${palette.base00}"; - default-fg = "#${palette.base01}"; - statusbar-bg = "#${palette.base02}"; - statusbar-fg = "#${palette.base04}"; - inputbar-bg = "#${palette.base00}"; - inputbar-fg = "#${palette.base07}"; - notification-bg = "#${palette.base00}"; - notification-fg = "#${palette.base07}"; - notification-error-bg = "#${palette.base00}"; - notification-error-fg = "#${palette.base08}"; - notification-warning-bg = "#${palette.base00}"; - notification-warning-fg = "#${palette.base08}"; - highlight-color = "#${palette.base0A}"; - highlight-active-color = "#${palette.base0D}"; - completion-bg = "#${palette.base01}"; - completion-fg = "#${palette.base05}"; - completions-highlight-bg = "#${palette.base0D}"; - completions-highlight-fg = "#${palette.base07}"; - recolor-lightcolor = "#${palette.base00}"; - recolor-darkcolor = "#${palette.base06}"; + default-bg = "#${color.layout.body}"; + default-fg = "#${color.typography.text}"; + statusbar-bg = "#${color.layout.header}"; + statusbar-fg = "#${color.typography.text}"; + inputbar-bg = "#${color.layout.menu}"; + inputbar-fg = "#${color.typography.text-bright}"; + notification-bg = "#${color.layout.menu}"; + notification-fg = "#${color.typography.text}"; + notification-error-bg = "#${color.layout.menu}"; + notification-error-fg = "#${color.error.base}"; + notification-warning-bg = "#${color.layout.menu}"; + notification-warning-fg = "#${color.warning.base}"; + highlight-color = "#${color.primary.base}"; + highlight-active-color = "#${color.primary.hard1}"; + completion-bg = "#${color.layout.menu}"; + completion-fg = "#${color.typography.text}"; + completion-highlight-bg = "#${color.primary.base}"; + completion-highlight-fg = "#${color.typography.contrast-text}"; + recolor-lightcolor = "#${color.typography.text}"; + recolor-darkcolor = "#${color.layout.body}"; }; }; xdg.mimeApps = { diff --git a/modules/home/workstation/terminal/foot.nix b/modules/home/workstation/terminal/foot.nix index f1714eb..2c481cf 100644 --- a/modules/home/workstation/terminal/foot.nix +++ b/modules/home/workstation/terminal/foot.nix @@ -4,8 +4,7 @@ hozen, ... }: let - inherit (osConfig.ooknet.appearance) colorscheme fonts; - inherit (colorscheme) palette; + inherit (osConfig.ooknet.appearance) fonts; inherit (hozen) color; inherit (lib) mkMerge mkIf; inherit (osConfig.ooknet.workstation) default; From 151da369a065292ef3ac5d9024a1235d8a198f71 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 19 Nov 2024 11:26:21 +1100 Subject: [PATCH 035/213] templates: initial templates config --- outputs/default.nix | 1 + outputs/templates/basic/flake.nix | 15 +++++++++++++++ outputs/templates/basic/outputs/default.nix | 6 ++++++ outputs/templates/basic/outputs/pkgs.nix | 18 ++++++++++++++++++ outputs/templates/basic/outputs/shell.nix | 10 ++++++++++ outputs/templates/default.nix | 12 ++++++++++++ outputs/templates/go/flake.nix | 15 +++++++++++++++ outputs/templates/go/outputs/default.nix | 6 ++++++ outputs/templates/go/outputs/pkgs.nix | 20 ++++++++++++++++++++ outputs/templates/go/outputs/shell.nix | 10 ++++++++++ 10 files changed, 113 insertions(+) create mode 100644 outputs/templates/basic/flake.nix create mode 100644 outputs/templates/basic/outputs/default.nix create mode 100644 outputs/templates/basic/outputs/pkgs.nix create mode 100644 outputs/templates/basic/outputs/shell.nix create mode 100644 outputs/templates/default.nix create mode 100644 outputs/templates/go/flake.nix create mode 100644 outputs/templates/go/outputs/default.nix create mode 100644 outputs/templates/go/outputs/pkgs.nix create mode 100644 outputs/templates/go/outputs/shell.nix diff --git a/outputs/default.nix b/outputs/default.nix index e82fb55..2a45066 100644 --- a/outputs/default.nix +++ b/outputs/default.nix @@ -8,5 +8,6 @@ ./pkgs ./images.nix ./devshells + ./templates ]; } diff --git a/outputs/templates/basic/flake.nix b/outputs/templates/basic/flake.nix new file mode 100644 index 0000000..9db2f0c --- /dev/null +++ b/outputs/templates/basic/flake.nix @@ -0,0 +1,15 @@ +{ + description = "Description for the project"; + + inputs = { + flake-parts.url = "github:hercules-ci/flake-parts"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + systems.url = "github:nix-systems/default-linux"; + }; + + outputs = inputs @ {flake-parts, ...}: + flake-parts.lib.mkFlake {inherit inputs;} { + systems = import inputs.systems; + imports = [./outputs]; + }; +} diff --git a/outputs/templates/basic/outputs/default.nix b/outputs/templates/basic/outputs/default.nix new file mode 100644 index 0000000..ad0ccde --- /dev/null +++ b/outputs/templates/basic/outputs/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + ./shell.nix + ./pkgs.nix + ]; +} diff --git a/outputs/templates/basic/outputs/pkgs.nix b/outputs/templates/basic/outputs/pkgs.nix new file mode 100644 index 0000000..da50d0e --- /dev/null +++ b/outputs/templates/basic/outputs/pkgs.nix @@ -0,0 +1,18 @@ +{self, ...}: { + perSystem = { + pkgs, + self', + ... + }: { + packages.default = pkgs.stdenvNoCC.mkDerivation { + pname = "my package"; + version = "0.1.0"; + src = "${self}/src"; + nativeBuildInputs = []; + + buildPhase = ""; + dontInstall = true; + }; + apps.default = self'.packages.default; + }; +} diff --git a/outputs/templates/basic/outputs/shell.nix b/outputs/templates/basic/outputs/shell.nix new file mode 100644 index 0000000..97f9514 --- /dev/null +++ b/outputs/templates/basic/outputs/shell.nix @@ -0,0 +1,10 @@ +{ + perSystem = {pkgs, ...}: { + devShells.default = pkgs.mkShellNoCC { + name = "project devshell"; + packages = + builtins.attrValues { + }; + }; + }; +} diff --git a/outputs/templates/default.nix b/outputs/templates/default.nix new file mode 100644 index 0000000..86152ca --- /dev/null +++ b/outputs/templates/default.nix @@ -0,0 +1,12 @@ +{ + flake.templates = { + default = { + path = ./basic; + description = "Default project template"; + }; + go = { + path = ./go; + description = "Basic go template"; + }; + }; +} diff --git a/outputs/templates/go/flake.nix b/outputs/templates/go/flake.nix new file mode 100644 index 0000000..9db2f0c --- /dev/null +++ b/outputs/templates/go/flake.nix @@ -0,0 +1,15 @@ +{ + description = "Description for the project"; + + inputs = { + flake-parts.url = "github:hercules-ci/flake-parts"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + systems.url = "github:nix-systems/default-linux"; + }; + + outputs = inputs @ {flake-parts, ...}: + flake-parts.lib.mkFlake {inherit inputs;} { + systems = import inputs.systems; + imports = [./outputs]; + }; +} diff --git a/outputs/templates/go/outputs/default.nix b/outputs/templates/go/outputs/default.nix new file mode 100644 index 0000000..ad0ccde --- /dev/null +++ b/outputs/templates/go/outputs/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + ./shell.nix + ./pkgs.nix + ]; +} diff --git a/outputs/templates/go/outputs/pkgs.nix b/outputs/templates/go/outputs/pkgs.nix new file mode 100644 index 0000000..32ebf2a --- /dev/null +++ b/outputs/templates/go/outputs/pkgs.nix @@ -0,0 +1,20 @@ +{self, ...}: { + perSystem = { + pkgs, + self', + lib, + ... + }: { + packages.default = pkgs.buildGoModule { + pname = "hello"; + version = "0.0.1"; + src = "${self}/src"; + meta.mainProgram = "hello"; + vendorHash = null; + }; + apps.default = { + type = "app"; + program = "${lib.getExe self'.packages.default}"; + }; + }; +} diff --git a/outputs/templates/go/outputs/shell.nix b/outputs/templates/go/outputs/shell.nix new file mode 100644 index 0000000..ccf8508 --- /dev/null +++ b/outputs/templates/go/outputs/shell.nix @@ -0,0 +1,10 @@ +{ + perSystem = {pkgs, ...}: { + devShells.default = pkgs.mkShellNoCC { + name = "project devshell"; + packages = builtins.attrValues { + inherit (pkgs) go gopls gotools go-tools; + }; + }; + }; +} From 7a4216ae431cb05e2572d83836f9276db0dc57c7 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 19 Nov 2024 17:13:59 +1100 Subject: [PATCH 036/213] nixos: use hozen colors for generated wallpaper --- .../themes/generated-wallpaper.nix | 19 ++++++++----------- modules/nixos/workstation/themes/minimal.nix | 8 ++------ 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/modules/nixos/workstation/themes/generated-wallpaper.nix b/modules/nixos/workstation/themes/generated-wallpaper.nix index 7009f07..f1c920c 100644 --- a/modules/nixos/workstation/themes/generated-wallpaper.nix +++ b/modules/nixos/workstation/themes/generated-wallpaper.nix @@ -2,9 +2,10 @@ { pkgs, config, + hozen, }: let inherit (config.ooknet.hardware) monitors; - inherit (config.ooknet.appearance) colorscheme; + inherit (hozen) color; largest = f: xs: builtins.head (builtins.sort (a: b: a > b) (map f xs)); largestWidth = largest (x: x.width) monitors; largestHeight = largest (x: x.height) monitors; @@ -13,21 +14,17 @@ in width ? largestWidth, height ? largestHeight, logoScale ? 4, - backgroundColor ? colorscheme.palette.mantle, - logoColor1 ? colorscheme.palette.yellow, - logoColor2 ? colorscheme.palette.green, + backgroundColor ? color.layout.body, + logoColor1 ? color.green.base, + logoColor2 ? color.yellow.base, }: pkgs.stdenv.mkDerivation { - name = "generated-nix-wallpaper-${colorscheme.slug}.png"; + name = "generated-nix-wallpaper-${color.slug}.png"; src = pkgs.writeTextFile { name = "template.svg"; text = '' - - + + diff --git a/modules/nixos/workstation/themes/minimal.nix b/modules/nixos/workstation/themes/minimal.nix index 9ca1680..1050dce 100644 --- a/modules/nixos/workstation/themes/minimal.nix +++ b/modules/nixos/workstation/themes/minimal.nix @@ -2,11 +2,12 @@ config, lib, pkgs, + hozen, ... }: let inherit (lib) mkIf; inherit (config.ooknet.workstation) theme; - generatedWallpaper = import ./generated-wallpaper.nix {inherit config pkgs;} {}; + generatedWallpaper = import ./generated-wallpaper.nix {inherit hozen config pkgs;} {}; in { config = mkIf (theme == "minimal") { ooknet.appearance = { @@ -30,11 +31,6 @@ in { wallpaper = { path = "${generatedWallpaper}"; }; - - colorscheme = { - name = "gruvbox-material"; - variant = "dark"; - }; }; }; } From a83b2f7fa5eaf106cdf51adf9ff541a95e094012 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 19 Nov 2024 17:14:58 +1100 Subject: [PATCH 037/213] templates: add go files to go template --- outputs/templates/go/src/go.mod | 3 +++ outputs/templates/go/src/main.go | 7 +++++++ 2 files changed, 10 insertions(+) create mode 100644 outputs/templates/go/src/go.mod create mode 100644 outputs/templates/go/src/main.go diff --git a/outputs/templates/go/src/go.mod b/outputs/templates/go/src/go.mod new file mode 100644 index 0000000..37ae5b3 --- /dev/null +++ b/outputs/templates/go/src/go.mod @@ -0,0 +1,3 @@ +module hello + +go 1.23.2 diff --git a/outputs/templates/go/src/main.go b/outputs/templates/go/src/main.go new file mode 100644 index 0000000..b0ab032 --- /dev/null +++ b/outputs/templates/go/src/main.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("Hello World!") +} From 757f268a106b5d72a1ff91c69146d4537f50857b Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 19 Nov 2024 17:15:06 +1100 Subject: [PATCH 038/213] flake: bump nvf --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index a4552e9..f71f1f5 100644 --- a/flake.lock +++ b/flake.lock @@ -636,11 +636,11 @@ }, "mnw": { "locked": { - "lastModified": 1731182209, - "narHash": "sha256-yftvwv8bHEKjmSKREdkGLWTDhf7vA2Ssvl/XMpykigg=", + "lastModified": 1731821965, + "narHash": "sha256-QiGi/HBQRnIRGY4gQPuH7T3hr7NznOpEO7qNpF5ldmE=", "owner": "Gerg-L", "repo": "mnw", - "rev": "0a5e50286ca9f1b70eb4fa29ce84304cad657700", + "rev": "5fe5c41975ed0af55f55dc37cd28ba906a5d015e", "type": "github" }, "original": { @@ -1023,11 +1023,11 @@ "systems": "systems_4" }, "locked": { - "lastModified": 1731279011, - "narHash": "sha256-+U7Ew49J79l0mVfvPdyMnlFISVIgQTAKpdpipTKYQ2Q=", + "lastModified": 1731920974, + "narHash": "sha256-7y5tGSntFAq82A8fv7N8R6BBEmyXBigCxRrSbxK+iMU=", "owner": "notashelf", "repo": "nvf", - "rev": "12b650fea7bddcdf9773f3b6f831c59c7b660a75", + "rev": "b6785f8218bf8a9813881de421ef468b512d9cea", "type": "github" }, "original": { From 7274434d34da506452119be95027a08e89723678 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 19 Nov 2024 17:15:22 +1100 Subject: [PATCH 039/213] ook-vim: add go language module --- outputs/pkgs/ook-vim/plugins/languages/default.nix | 1 + outputs/pkgs/ook-vim/plugins/languages/go.nix | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 outputs/pkgs/ook-vim/plugins/languages/go.nix diff --git a/outputs/pkgs/ook-vim/plugins/languages/default.nix b/outputs/pkgs/ook-vim/plugins/languages/default.nix index a87b632..3ef2c00 100644 --- a/outputs/pkgs/ook-vim/plugins/languages/default.nix +++ b/outputs/pkgs/ook-vim/plugins/languages/default.nix @@ -6,6 +6,7 @@ ./treesitter.nix ./html.nix ./ts.nix + ./go.nix ]; vim.languages = { diff --git a/outputs/pkgs/ook-vim/plugins/languages/go.nix b/outputs/pkgs/ook-vim/plugins/languages/go.nix new file mode 100644 index 0000000..e208103 --- /dev/null +++ b/outputs/pkgs/ook-vim/plugins/languages/go.nix @@ -0,0 +1,5 @@ +{ + vim.languages.go = { + enable = true; + }; +} From 9023bd2b6473e226ee9a10712058f6e3eedcd261 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 19 Nov 2024 17:15:41 +1100 Subject: [PATCH 040/213] nixos: remove colorscheme module --- modules/nixos/appearance/options.nix | 37 +-- modules/nixos/appearance/palettes/dark.nix | 285 ------------------ .../palettes/gruvbox-material-medium-dark.nix | 65 ---- modules/nixos/appearance/palettes/readme.md | 22 -- 4 files changed, 3 insertions(+), 406 deletions(-) delete mode 100644 modules/nixos/appearance/palettes/dark.nix delete mode 100644 modules/nixos/appearance/palettes/gruvbox-material-medium-dark.nix delete mode 100644 modules/nixos/appearance/palettes/readme.md diff --git a/modules/nixos/appearance/options.nix b/modules/nixos/appearance/options.nix index c36d657..da0de81 100644 --- a/modules/nixos/appearance/options.nix +++ b/modules/nixos/appearance/options.nix @@ -1,16 +1,6 @@ -{ - config, - lib, - ... -}: let - inherit (lib) isString hasPrefix removePrefix mkOption mkOptionType; - inherit (lib.types) enum str nullOr package path int attrsOf coercedTo; - hexColorType = mkOptionType { - name = "hex-color"; - descriptionClass = "noun"; - description = "RGB color in hex format"; - check = x: isString x && !(hasPrefix "#" x); - }; +{lib, ...}: let + inherit (lib) mkOption; + inherit (lib.types) str package path int; mkFontOption = { family = mkOption { @@ -22,8 +12,6 @@ default = null; }; }; - - cfg = config.ooknet.appearance; in { # imports = [./palettes]; options.ooknet.appearance = { @@ -51,24 +39,5 @@ in { default = 22; }; }; - # Credit to github:misterio77/nix-colors - colorscheme = { - name = mkOption { - type = enum ["gruvbox-material"]; - default = "gruvbox-material"; - }; - variant = mkOption { - type = enum ["dark" "light"]; - default = "dark"; - }; - slug = mkOption { - type = str; - default = "${toString cfg.colorscheme.name}-${toString cfg.colorscheme.variant}"; - }; - palette = mkOption { - type = attrsOf (coercedTo str (removePrefix "#") hexColorType); - default = (import ./palettes/${config.ooknet.appearance.colorscheme.slug}.nix).colorscheme.palette; - }; - }; }; } diff --git a/modules/nixos/appearance/palettes/dark.nix b/modules/nixos/appearance/palettes/dark.nix deleted file mode 100644 index ca9285d..0000000 --- a/modules/nixos/appearance/palettes/dark.nix +++ /dev/null @@ -1,285 +0,0 @@ -let - /* - extended version of gruvbox/gruvbox material to support multiple frameworks: - - - tailwind - - base16/24 - - semantic - - references: - - shades - - - - colors - - - - */ - colors = { - #shades - - shade-50 = "#dfd2b3"; - shade-100 = "#d9c7a5"; - shade-150 = "#d4be98"; - shade-200 = "#c6b395"; - shade-250 = "#b4a288"; - shade-300 = "#a49384"; - shade-350 = "#99897a"; - shade-400 = "#8b7c6f"; - shade-450 = "#7d6f64"; - shade-500 = "#716860"; - shade-550 = "#645f59"; - shade-600 = "#585350"; - shade-650 = "#4d4947"; - shade-700 = "#3f3b3b"; - shade-750 = "#343232"; - shade-800 = "#282828"; - shade-850 = "#212121"; - shade-900 = "#1a1a1a"; - - # we use green as the primary color here. - primary = "#a9b665"; - - # color scale for our primary accent color. - primary-dark-1 = "#b1be74"; - primary-dark-2 = "${colors.primary-dark-1}"; - primary-dark-3 = "#b8c481"; - primary-dark-4 = "${colors.primary-dark-3}"; - primary-dark-5 = "#bec98c"; - primary-dark-6 = "${colors.primary-dark-4}"; - primary-dark-7 = "#c4ce96"; - - primary-light-1 = "#9aa55c"; - primary-light-2 = "${colors.primary-light-1}"; - primary-light-3 = "#8c9654"; - primary-light-4 = "${colors.primary-dark-3}"; - primary-light-5 = "#7f884c"; - primary-light-6 = "${colors.primary-dark-5}"; - primary-light-7 = "#69713f"; - - primary-alpha-10 = "${colors.primary}19"; - primary-alpha-20 = "${colors.primary}33"; - primary-alpha-30 = "${colors.primary}4b"; - primary-alpha-40 = "${colors.primary}66"; - primary-alpha-50 = "${colors.primary}80"; - primary-alpha-60 = "${colors.primary}99"; - primary-alpha-70 = "${colors.primary}b3"; - primary-alpha-80 = "${colors.primary}cc"; - primary-alpha-90 = "${colors.primary}e1"; - - primary-hover = "${colors.primary-light-2}"; - primary-active = "${colors.primary-light-4}"; - - # we use green as the secondary color here. - secondary = "${colors.shade-700}"; - - # color scale for our secondary accent color. - secondary-dark-1 = "${colors.shade-550}"; - secondary-dark-2 = "${colors.shade-500}"; - secondary-dark-3 = "${colors.shade-450}"; - secondary-dark-4 = "${colors.shade-400}"; - secondary-dark-5 = "${colors.shade-350}"; - secondary-dark-6 = "${colors.shade-300}"; - secondary-dark-7 = "${colors.shade-250}"; - secondary-dark-8 = "${colors.shade-200}"; - secondary-dark-9 = "${colors.shade-150}"; - secondary-dark-10 = "${colors.shade-100}"; - secondary-dark-11 = "${colors.shade-100}"; - secondary-dark-12 = "${colors.shade-100}"; - secondary-dark-13 = "${colors.shade-100}"; - - secondary-light-1 = "${colors.shade-650}"; - secondary-light-2 = "${colors.shade-700}"; - secondary-light-3 = "${colors.shade-750}"; - secondary-light-4 = "${colors.shade-800}"; - - secondary-alpha-10 = "${colors.secondary}19"; - secondary-alpha-20 = "${colors.secondary}33"; - secondary-alpha-30 = "${colors.secondary}4b"; - secondary-alpha-40 = "${colors.secondary}66"; - secondary-alpha-50 = "${colors.secondary}80"; - secondary-alpha-60 = "${colors.secondary}99"; - secondary-alpha-70 = "${colors.secondary}b3"; - secondary-alpha-80 = "${colors.secondary}cc"; - secondary-alpha-90 = "${colors.secondary}e1"; - - secondary-hover = "${colors.secondary-light-1}"; - secondary-active = "${colors.secondary-light-2}"; - - red-light = "#e57b76"; - red = "#ea6962"; - red-dark-1 = "#e7534b"; - red-dark-2 = "#e33e35"; - - orange-light = "#e69965"; - orange = "#e78a4e"; - orange-dark-1 = "#e07b38"; - orange-dark-2 = "#de732b"; - - yellow-light = "#d9b06d"; - yellow = "#d8a657"; - yellow-dark-1 = "#d09a43"; - yellow-dark-2 = "#c99136"; - - olive-light = "#beb874"; - olive = "#b9b25f"; - olive-dark-1 = "#ada652"; - olive-dark-2 = "#9b944b"; - - green-light = "#b1be74"; - green = "#a9b665"; - green-dark-1 = "#9aa55c"; - green-dark-2 = "#8c9654"; - - teal-light = "#9abb95"; - teal = "#89b482"; - teal-dark-1 = "#7aa573"; - teal-dark-2 = "#6c9a65"; - - blue-light = "#91b6ae"; - blue = "#7daea3"; - blue-dark-1 = "#6ea096"; - blue-dark-2 = "#63978d"; - - violet-light = "#dba3c7"; - violet = "#d892c1"; - violet-dark-1 = "#cd7eb3"; - violet-dark-2 = "#c86faa"; - - purple-light = "#d9a0af"; - purple = "#d3869b"; - purple-dark-1 = "#ca778d"; - purple-dark-2 = "#c26680"; - - pink-light = "#d8abcc"; - pink = "#cf91be"; - pink-dark-1 = "#c47eb1"; - pink-dark-2 = "#bc71a8"; - - brown-light = "#b18568"; - brown = "#a87757"; - brown-dark-1 = "#976b4e"; - brown-dark-2 = "#896248"; - - grey-light = "${colors.shade-350}"; - grey = "${colors.shade-450}"; - grey-dark-1 = "${colors.shade-500}"; - grey-dark-2 = "${colors.shade-550}"; - - black-light = "${colors.shade-700}"; - black = "${colors.shade-800}"; - black-dark-1 = "${colors.shade-850}"; - black-dark-2 = "${colors.shade-900}"; - - # semantic - body = "${colors.shade-700}"; - header = "${colors.shade-800}"; - text = "${colors.shade-150}"; - text-light = "${colors.shade-100}"; - text-lighter = "${colors.shade-50}"; - texter-dark = "${colors.shade-200}"; - text-darker = "${colors.shade-350}"; - footer = "${colors.shade-800}"; - menu = "${colors.shade-800}"; - border-active = "${colors.shade-150}"; - border-inactive = "${colors.shade-600}"; - - error-bg = "${colors.red}"; - error-bg-active = "${colors.red-dark-1}"; - error-bg-hover = "${colors.red-dark-2}"; - error-text = "${colors.shade-800}"; - error-border = "${colors.red-light}"; - - success-bg = "${colors.green}"; - success-bg-active = "${colors.green-dark-1}"; - success-bg-hover = "${colors.green-dark-2}"; - success-text = "${colors.shade-800}"; - success-border = "${colors.green-light}"; - - warning-bg = "${colors.yellow}"; - warning-bg-active = "${colors.yellow-dark-1}"; - warning-bg-hover = "${colors.yellow-dark-2}"; - warning-text = "${colors.shade-800}"; - warning-border = "${colors.yellow-light}"; - - info-bg = "${colors.blue}"; - info-bg-active = "${colors.blue-dark-1}"; - info-bg-hover = "${colors.blue-dark-2}"; - info-text = "${colors.shade-800}"; - info-border = "${colors.blue-light}"; - - tip-bg = "${colors.teal}"; - tip-bg-active = "${colors.teal-dark-1}"; - tip-bg-hover = "${colors.teal-dark-2}"; - tip-text = "${colors.shade-800}"; - tip-border = "${colors.teal-light}"; - - input-text = "${colors.text-light}"; - - # syntax - - syntax = { - string = "${colors.green}"; - number = "${colors.purple}"; - float = "${colors.purple}"; - boolean = "${colors.purple}"; - type = "${colors.yellow}"; - structure = "${colors.orange}"; - statement = "${colors.red}"; - label = "${colors.orange}"; - operator = "${colors.orange}"; - identifier = "${colors.blue}"; - function = "${colors.green}"; - storageClass = "${colors.orange}"; - constant = "${colors.teal}"; - exception = "${colors.red}"; - preproc = "${colors.purple}"; - include = "${colors.purple}"; - define = "${colors.purple}"; - macro = "${colors.teal}"; - preCondit = "${colors.purple}"; - special = "${colors.yellow}"; - specialChar = "${colors.yellow}"; - comment = "${colors.text-darker}"; - todo = "${colors.purple}"; - tag = "${colors.tag}"; - - mdH1 = "${colors.red}"; - mdH2 = "${colors.orange}"; - mdH3 = "${colors.yellow}"; - mdH4 = "${colors.green}"; - mdH5 = "${colors.blue}"; - mdH6 = "${colors.purple}"; - }; - - # base 16/24 - base00 = "${colors.shade-800}"; - base01 = "${colors.shade-700}"; - base02 = "${colors.shade-600}"; - base03 = "${colors.shade-450}"; - base04 = "${colors.shade-300}"; - base05 = "${colors.shade-150}"; - base06 = "${colors.shade-100}"; - base07 = "${colors.shade-50}"; - base08 = "${colors.red}"; - base09 = "${colors.orange}"; - base0A = "${colors.yellow}"; - base0B = "${colors.green}"; - base0C = "${colors.teal}"; - base0D = "${colors.blue}"; - base0E = "${colors.purple}"; - base0F = "${colors.brown}"; - base10 = "${colors.shade-850}"; - base11 = "${colors.shade-900}"; - base12 = "${colors.red-light}"; - base13 = "${colors.yellow-light}"; - base14 = "${colors.green-light}"; - base15 = "${colors.teal-light}"; - base16 = "${colors.blue-light}"; - base17 = "${colors.purple-light}"; - }; -in { - inherit colors; -} diff --git a/modules/nixos/appearance/palettes/gruvbox-material-medium-dark.nix b/modules/nixos/appearance/palettes/gruvbox-material-medium-dark.nix deleted file mode 100644 index a42c3ec..0000000 --- a/modules/nixos/appearance/palettes/gruvbox-material-medium-dark.nix +++ /dev/null @@ -1,65 +0,0 @@ -{ - colorscheme = { - palette = { - crust = "#282828"; - mantle = "#32302f"; - base = "#3a3735"; - surface-0 = "#45403d"; - surface-1 = "#504945"; - surface-2 = "#5A524C"; - overlay-0 = "#696059"; - overlay-1 = "#70665C"; - overlay-2 = "#7C6F64"; - subtext-0 = "#928374"; - subtext-1 = "#A89984"; - text = "#d4be98"; - - red = "#ea6962"; - dull-red = "#D87974"; - bright-red = "#F47771"; - orange = "#e78a4e"; - dull-orange = "#D39063"; - bright-orange = "#F3995E"; - yellow = "#d8a657"; - dull-yellow = "#c2A16B"; - bright-yellow = "#E5B361"; - green = "#a9b665"; - dull-green = "#989F7A"; - bright-green = "#B8C86A"; - cyan = "#89b482"; - dull-cyan = "#93A790"; - bright-cyan = "#92C78A"; - blue = "#7daea3"; - dull-blue = "#939A98"; - bright-blue = "#85C1B4"; - purple = "#d3869b"; - dull-purple = "#C397A3"; - bright-purple = "#E193A8"; - - base00 = "#282828"; - base01 = "#32302f"; - base02 = "#504945"; - base03 = "#7C6F64"; - base04 = "#A89984"; - base05 = "#D4BE98"; - base06 = "#DDc7a1"; - base07 = "#FBF1C7"; - base08 = "#EA6962"; - base09 = "#E78A4E"; - base0A = "#d8a657"; - base0B = "#A9B665"; - base0C = "#89B482"; - base0D = "#7DAEA3"; - base0E = "#D3869B"; - base0F = "#E37B35"; - base10 = "#141617"; - base11 = "#050505"; - base12 = "#F47771"; - base13 = "#D8A657"; - base14 = "#B7C86A"; - base15 = "#92C78A"; - base16 = "#85C1B4"; - base17 = "#E193A8"; - }; - }; -} diff --git a/modules/nixos/appearance/palettes/readme.md b/modules/nixos/appearance/palettes/readme.md deleted file mode 100644 index c2a9527..0000000 --- a/modules/nixos/appearance/palettes/readme.md +++ /dev/null @@ -1,22 +0,0 @@ -# References: - -## Dark - -### Shades - -- [Dark](https://coolors.co/1a1a1a-212121-282828-343232-3f3b3b-4d4947-585350-645f59-716860-7d6f64) -- [Light](https://coolors.co/dfd2b3-d9c7a5-d4be98-c6b395-b4a288-a49384-99897a-8b7c6f) - -### Colors - -- [Green](https://coolors.co/69713f-737c45-7f884c-8c9654-9aa55c-a9b665-b1be74-b8c481-bec98c-c4ce96) -- [Red](https://coolors.co/e57b76-ea6962-e95149-e33e35) -- [Orange](https://coolors.co/e69965-e78a4e-e07b38-de732b) -- [Yellow](https://coolors.co/d9b06d-d8a657-d09a43-c99136) -- [Olive](https://coolors.co/beb874-b9b25f-ada652-9b944b) -- [Teal](https://coolors.co/9abb95-89b482-7aa573-6c9a65) -- [Blue](https://coolors.co/91b6ae-7daea3-6ea096-63978d) -- [Violet](https://coolors.co/dba3c7-d892c1-cd7eb3-c86faa) -- [Purple](https://coolors.co/d9a0af-d3869b-ca778d-c26680) -- [Pink](https://coolors.co/d8abcc-cf91be-c47eb1-bc71a8) -- [Brown](https://coolors.co/b18568-a87757-976b4e-896248) From f3895ce019a346524f07936c19debe2b2dc5984d Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 19 Nov 2024 17:21:41 +1100 Subject: [PATCH 041/213] pkgs: remove instawow --- .../workstation/gaming/world-of-warcraft.nix | 55 ------------------- modules/home/workstation/gaming/wow.nix | 1 - outputs/pkgs/default.nix | 1 - outputs/pkgs/instawow/default.nix | 54 ------------------ outputs/pkgs/instawow/plugins/tsm.nix | 43 --------------- 5 files changed, 154 deletions(-) delete mode 100644 modules/home/workstation/gaming/world-of-warcraft.nix delete mode 100644 outputs/pkgs/instawow/default.nix delete mode 100644 outputs/pkgs/instawow/plugins/tsm.nix diff --git a/modules/home/workstation/gaming/world-of-warcraft.nix b/modules/home/workstation/gaming/world-of-warcraft.nix deleted file mode 100644 index 5bb944c..0000000 --- a/modules/home/workstation/gaming/world-of-warcraft.nix +++ /dev/null @@ -1,55 +0,0 @@ -{ - lib, - config, - pkgs, - ... -}: let - inherit (lib) mkIf mkEnableOption mkOption; - inherit (lib.types) str package; - inherit (config.ooknet) gaming; - gamesDir = config.xdg.userDirs.extraConfig.XDG_GAMES_DIR; - cfg = config.ooknet.gaming.world-of-warcraft; -in { - options.ooknet.gaming.world-of-warcraft = { - enable = mkEnableOption "Enable the World of Warcraft module"; - - proton = { - package = mkOption { - type = package; - default = pkgs.proton-ge-custom; - }; - prefix = { - path = mkOption { - type = str; - default = "${gaming.prefixPath}/WoW"; - }; - }; - compatDataPath = mkOption { - type = str; - default = "${gaming.compatDataPath}/"; - }; - }; - - gamePrefixPath = mkOption { - type = str; - default = "${cfg.winePrefixesPath}/WoW"; - description = "Location where the World of Warcraft prefix will be stored."; - }; - - gamePath = mkOption { - type = str; - default = "${cfg.world-of-warcraft.gamePrefixPath}/drive_c/Program Files (x86)/World of Warcraft"; - description = "Location where the World of Warcraft installation will be symlinked."; - }; - - gameSharedPath = mkOption { - type = str; - default = "${cfg.wineProgramsPath}/World Of Warcraft"; - description = "Location where World of Warcraft game files are stored."; - }; - }; - config = - mkIf cfg.enable { - }; -} - diff --git a/modules/home/workstation/gaming/wow.nix b/modules/home/workstation/gaming/wow.nix index 9ca101e..0c82934 100644 --- a/modules/home/workstation/gaming/wow.nix +++ b/modules/home/workstation/gaming/wow.nix @@ -2,7 +2,6 @@ lib, osConfig, pkgs, - self', ... }: let inherit (lib) mkIf elem; diff --git a/outputs/pkgs/default.nix b/outputs/pkgs/default.nix index 7290bf9..037b1b3 100644 --- a/outputs/pkgs/default.nix +++ b/outputs/pkgs/default.nix @@ -7,7 +7,6 @@ packages = { repopack = callPackage ./repopack {}; live-buds-cli = callPackage ./live-buds-cli {}; - instawow-tsm = callPackage ./instawow/plugins/tsm.nix {}; website = callPackage ./website {}; ook-vim = mkNeovim pkgs [ook-vim-config]; diff --git a/outputs/pkgs/instawow/default.nix b/outputs/pkgs/instawow/default.nix deleted file mode 100644 index 9584fab..0000000 --- a/outputs/pkgs/instawow/default.nix +++ /dev/null @@ -1,54 +0,0 @@ -# Credit github:seirl -# -{ - lib, - python3, - fetchFromGitHub, - plugins ? [], -}: -python3.pkgs.buildPythonApplication rec { - pname = "instawow"; - version = "4.7.0"; - pyproject = true; - - src = fetchFromGitHub { - owner = "layday"; - repo = pname; - rev = "refs/tags/v${version}"; - sha256 = "sha256-tk/Lugjdzufl8VPcpj7R2q81SBE/+KtS3VhsXQ2VKZM="; - }; - - extras = []; # Disable GUI, most dependencies are not packaged. - - nativeBuildInputs = with python3.pkgs; [ - hatchling - hatch-vcs - ]; - propagatedBuildInputs = with python3.pkgs; - [ - aiohttp - aiohttp-client-cache - attrs - cattrs - click - diskcache - iso8601 - loguru - packaging - pluggy - prompt-toolkit - rapidfuzz - truststore - typing-extensions - yarl - ] - ++ plugins; - - meta = with lib; { - homepage = "https://github.com/layday/instawow"; - description = "World of Warcraft add-on manager CLI and GUI"; - mainProgram = "instawow"; - license = licenses.gpl3; - maintainers = with maintainers; [seirl]; - }; -} diff --git a/outputs/pkgs/instawow/plugins/tsm.nix b/outputs/pkgs/instawow/plugins/tsm.nix deleted file mode 100644 index c26068a..0000000 --- a/outputs/pkgs/instawow/plugins/tsm.nix +++ /dev/null @@ -1,43 +0,0 @@ -# Credit github:seirl -# -{ - lib, - python3, - fetchFromGitHub, - instawow, -}: let - inherit (builtins) attrValues; -in - python3.pkgs.buildPythonPackage rec { - pname = "instawow-tsm"; - version = "72edf2ba3850eaaa5041d5aa1f55166aeee81409"; - - src = fetchFromGitHub { - owner = "seirl"; - repo = "instawow-tsm"; - rev = version; - sha256 = "sha256-+ojxVwPOfy3/3/raROEDS5pWCONAiALCdg7li+K6ZjI="; - }; - - pythonRemoveDeps = [ - "instawow" # Reverse the dependency - ]; - doCheck = false; # tests require dependencies - - nativeBuildInputs = [python3.pkgs.setuptools]; - propagatedBuildInputs = attrValues { - inherit - (python3.pkgs) - aiohttp - click - loguru - ; - }; - - meta = with lib; { - homepage = "https://github.com/seirl/instawow-tsm"; - description = "Instawow plugin for TradeSkillMaster"; - license = lib.licenses.gpl3; - maintainers = with maintainers; [seirl]; - }; - } From 10816d1a0ae2a79f535f85fa8546d613e62cdbfe Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 21 Nov 2024 12:24:04 +1100 Subject: [PATCH 042/213] hosts: add ooksmedia --- hosts/ooknode/default.nix | 9 -- hosts/ooksmedia/default.nix | 28 ++++ hosts/ooksmedia/file-system.nix | 29 +++++ modules/nixos/base/options.nix | 2 +- .../nixos/server/services/forgejo/options.nix | 22 ++++ outputs/hosts/servers.nix | 7 + outputs/lib/builders.nix | 38 +++--- outputs/lib/icon/mkLogo.nix | 122 ++++++++++++++++++ .../pkgs/wallpapers/generated-wallpaper.nix | 69 ++++++++++ outputs/pkgs/website/src/templates/home.html | 2 +- 10 files changed, 301 insertions(+), 27 deletions(-) delete mode 100644 hosts/ooknode/default.nix create mode 100644 hosts/ooksmedia/default.nix create mode 100644 hosts/ooksmedia/file-system.nix create mode 100644 modules/nixos/server/services/forgejo/options.nix create mode 100644 outputs/lib/icon/mkLogo.nix create mode 100644 outputs/pkgs/wallpapers/generated-wallpaper.nix diff --git a/hosts/ooknode/default.nix b/hosts/ooknode/default.nix deleted file mode 100644 index 45572ef..0000000 --- a/hosts/ooknode/default.nix +++ /dev/null @@ -1,9 +0,0 @@ -{ - ooknet.host = { - admin = { - name = "ooks"; - shell = "fish"; - homeManager = true; - }; - }; -} diff --git a/hosts/ooksmedia/default.nix b/hosts/ooksmedia/default.nix new file mode 100644 index 0000000..2af78cf --- /dev/null +++ b/hosts/ooksmedia/default.nix @@ -0,0 +1,28 @@ +{ + pkgs, + lib, + ... +}: { + imports = [ + ./file-system.nix + ./hardware.nix + ]; + + ooknet = { + host = { + admin = { + name = "ooks"; + shell = "fish"; + homeManager = true; + }; + }; + console = { + profile = "standard"; + editor = "nvim"; + multiplexer = "zellij"; + }; + }; + boot.kernelPackages = pkgs.linuxPackages_xanmod_latest; + + system.stateVersion = lib.mkDefault "24.11"; +} diff --git a/hosts/ooksmedia/file-system.nix b/hosts/ooksmedia/file-system.nix new file mode 100644 index 0000000..64bb4a1 --- /dev/null +++ b/hosts/ooksmedia/file-system.nix @@ -0,0 +1,29 @@ +{ + fileSystems = { + "/" = { + device = "/dev/disk/by-uuid/50617edf-e788-49cc-9e0c-85a2f90a5550"; + fsType = "btrfs"; + options = ["subvol=root"]; + }; + "/nix" = { + device = "/dev/disk/by-uuid/50617edf-e788-49cc-9e0c-85a2f90a5550"; + fsType = "btrfs"; + options = ["subvol=nix"]; + }; + "/persist" = { + device = "/dev/disk/by-uuid/50617edf-e788-49cc-9e0c-85a2f90a5550"; + fsType = "btrfs"; + options = ["subvol=persist"]; + }; + "/swap" = { + device = "/dev/disk/by-uuid/50617edf-e788-49cc-9e0c-85a2f90a5550"; + fsType = "btrfs"; + options = ["subvol=swap"]; + }; + "/boot" = { + device = "/dev/disk/by-uuid/B511-09E2"; + fsType = "vfat"; + }; + }; + swapDevices = []; +} diff --git a/modules/nixos/base/options.nix b/modules/nixos/base/options.nix index 1eb9acf..6683e48 100644 --- a/modules/nixos/base/options.nix +++ b/modules/nixos/base/options.nix @@ -12,7 +12,7 @@ in { default = "ooks-generic"; }; type = mkOption { - type = enum ["desktop" "laptop"]; + type = enum ["vm" "desktop" "laptop"]; }; role = mkOption { type = enum ["workstation" "server"]; diff --git a/modules/nixos/server/services/forgejo/options.nix b/modules/nixos/server/services/forgejo/options.nix new file mode 100644 index 0000000..ce2fcd6 --- /dev/null +++ b/modules/nixos/server/services/forgejo/options.nix @@ -0,0 +1,22 @@ +{ + lib, + config, + ... +}: let + inherit (config.services) forgejo; + inherit (lib) mkEnableOption mkOption; + inherit (lib.types) str; + mkColorOption = description: + mkOption { + type = str; + default = ""; + inherit description; + }; +in { + options.ooknet.server.forgejo.customTheme = { + enable = mkEnableOption; + light = { + primary = mkColorOption; + }; + }; +} diff --git a/outputs/hosts/servers.nix b/outputs/hosts/servers.nix index 70af570..a05b3cf 100644 --- a/outputs/hosts/servers.nix +++ b/outputs/hosts/servers.nix @@ -15,5 +15,12 @@ in { profile = "linode"; services = ["website" "forgejo"]; }; + ookmedia = mkServer { + inherit withSystem; + system = "x86_64-linux"; + hostname = "ooksmedia"; + type = "desktop"; + services = []; + }; }; } diff --git a/outputs/lib/builders.nix b/outputs/lib/builders.nix index cd7822e..4c954a3 100644 --- a/outputs/lib/builders.nix +++ b/outputs/lib/builders.nix @@ -87,27 +87,33 @@ hostname, system, type, - profile, services, + profile ? null, domain ? "", additionalModules ? [], specialArgs ? {}, }: - mkBaseSystem { - inherit withSystem hostname system type specialArgs; - role = "server"; - additionalModules = concatLists [ - (singleton { - ooknet.server = { - inherit domain services; - }; - }) - core - [(serverModules + "/profiles/${profile}")] - [serverModules] - additionalModules - ]; - }; + assert lib.assertMsg (!(type == "vm" && profile == null)) + "Profile must be specified for VM servers"; + mkBaseSystem { + inherit withSystem hostname system type specialArgs; + role = "server"; + additionalModules = concatLists [ + (singleton { + ooknet.server = { + inherit domain services; + }; + }) + core + ( + if type == "vm" + then [(serverModules + "/profiles/${profile}")] + else [(hostModules + "/${hostname}")] + ) + [serverModules] + additionalModules + ]; + }; mkImage = { profile, diff --git a/outputs/lib/icon/mkLogo.nix b/outputs/lib/icon/mkLogo.nix new file mode 100644 index 0000000..2fb7303 --- /dev/null +++ b/outputs/lib/icon/mkLogo.nix @@ -0,0 +1,122 @@ +{ + lib, + pkgs, + hozen, + ... +}: let + inherit (lib) makeExtensible; + inherit (hozen) color; +in + makeExtensible (self: { + # Base logo derivation + mkLogo = { + name ? "ooknet-logo", + width ? 512, + height ? 512, + dark ? color.neutrals."800", + mid ? color.neutrals."650", + light ? color.neutrals."550", + shadow ? color.neutrals."700", + highlight ? color.neutrals."300", + }: + pkgs.stdenv.mkDerivation { + inherit name width height; + + # Use your SVG content here + src = pkgs.writeTextFile { + name = "logo.svg"; + text = + /* + html + */ + '' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ''; + }; + + nativeBuildInputs = [pkgs.inkscape]; + + # Proper build phases + buildPhase = '' + # Ensure output directory exists + mkdir -p $out/share/icons + + # Convert SVG to PNG + inkscape --export-type="png" \ + --export-filename="$out/share/icons/${name}.png" \ + --export-width=${toString width} \ + --export-height=${toString height} \ + $src + + # Also keep the SVG + cp $src "$out/share/icons/${name}.svg" + ''; + + # Meta information is always good practice + meta = { + description = "OokNet Logo"; + mainProgram = name; + }; + }; + + # Wallpaper derivation that uses the logo + mkWallpaper = { + width, + height, + logo ? self.mkLogo {}, + backgroundColor ? "282828", + }: + pkgs.stdenv.mkDerivation { + name = "ooknet-wallpaper"; + + buildInputs = [pkgs.imagemagick]; + + buildPhase = '' + # Create background + convert -size ${toString width}x${toString height} \ + xc:#${backgroundColor} \ + background.png + + # Composite logo onto center of background + composite -gravity center \ + ${logo}/share/icons/*.png \ + background.png \ + $out + ''; + }; + }) diff --git a/outputs/pkgs/wallpapers/generated-wallpaper.nix b/outputs/pkgs/wallpapers/generated-wallpaper.nix new file mode 100644 index 0000000..b8c994b --- /dev/null +++ b/outputs/pkgs/wallpapers/generated-wallpaper.nix @@ -0,0 +1,69 @@ +{ + pkgs, + config, +}: let + inherit (config.ooknet.hardware) monitors; + inherit (config.ooknet.appearance) colorscheme; + largest = f: xs: builtins.head (builtins.sort (a: b: a > b) (map f xs)); + largestWidth = largest (x: x.width) monitors; + largestHeight = largest (x: x.height) monitors; +in + { + width ? largestWidth, + height ? largestHeight, + logoScale ? 4, + backgroundColor ? colorscheme.palette.mantle, + logoColor1 ? colorscheme.palette.yellow, + logoColor2 ? colorscheme.palette.green, + }: + pkgs.stdenv.mkDerivation { + name = "generated-nix-wallpaper-${colorscheme.slug}.png"; + src = pkgs.writeTextFile { + name = "template.svg"; + text = '' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ''; + }; + buildInputs = [pkgs.inkscape]; + unpackPhase = "true"; + buildPhase = '' + inkscape --export-type="png" $src -w ${toString width} -h ${toString height} -o wallpaper.png + ''; + installPhase = "install -Dm0644 wallpaper.png $out"; + } diff --git a/outputs/pkgs/website/src/templates/home.html b/outputs/pkgs/website/src/templates/home.html index 0a192dd..704127e 100644 --- a/outputs/pkgs/website/src/templates/home.html +++ b/outputs/pkgs/website/src/templates/home.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% block home %}
@@ -35,6 +36,5 @@ -{% block home %} {{ section.content | safe }} {% endblock home %} From 033588cb193e46894490c2d19028bf8598ddc78d Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 22 Nov 2024 11:13:22 +1100 Subject: [PATCH 043/213] ooksmedia: hardware config --- hosts/ooksmedia/default.nix | 1 + hosts/ooksmedia/hardware.nix | 17 +++++++++++++++++ modules/home/console/tools/default.nix | 1 - modules/home/workstation/tools/default.nix | 1 + .../tools/virt-manager.nix} | 0 5 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 hosts/ooksmedia/hardware.nix rename modules/home/{console/tools/virtualization.nix => workstation/tools/virt-manager.nix} (100%) diff --git a/hosts/ooksmedia/default.nix b/hosts/ooksmedia/default.nix index 2af78cf..e1457bd 100644 --- a/hosts/ooksmedia/default.nix +++ b/hosts/ooksmedia/default.nix @@ -22,6 +22,7 @@ multiplexer = "zellij"; }; }; + boot.kernelPackages = pkgs.linuxPackages_xanmod_latest; system.stateVersion = lib.mkDefault "24.11"; diff --git a/hosts/ooksmedia/hardware.nix b/hosts/ooksmedia/hardware.nix new file mode 100644 index 0000000..bc4629e --- /dev/null +++ b/hosts/ooksmedia/hardware.nix @@ -0,0 +1,17 @@ +{ + ooknet.hardware = { + cpu.type = "intel"; + gpu.type = "nvidia"; + features = ["ssd" "audio" "video" "bluetooth"]; + monitors = [ + { + name = "DP-3"; + primary = true; + width = 1920; + height = 1080; + refreshRate = 180; + workspace = "1"; + } + ]; + }; +} diff --git a/modules/home/console/tools/default.nix b/modules/home/console/tools/default.nix index c29bf86..45a4b5a 100644 --- a/modules/home/console/tools/default.nix +++ b/modules/home/console/tools/default.nix @@ -1,6 +1,5 @@ { imports = [ - ./virtualization.nix ./bat.nix ./networking.nix ./btop.nix diff --git a/modules/home/workstation/tools/default.nix b/modules/home/workstation/tools/default.nix index bdf7eb3..7a1545e 100644 --- a/modules/home/workstation/tools/default.nix +++ b/modules/home/workstation/tools/default.nix @@ -1,6 +1,7 @@ { imports = [ ./ookpower.nix + ./virt-manager.nix ./1password.nix ./ookvolume.nix ./kdeconnect.nix diff --git a/modules/home/console/tools/virtualization.nix b/modules/home/workstation/tools/virt-manager.nix similarity index 100% rename from modules/home/console/tools/virtualization.nix rename to modules/home/workstation/tools/virt-manager.nix From 4ac9af3ca8ba0e70b3173090b1d0432c468c59c9 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 22 Nov 2024 11:14:55 +1100 Subject: [PATCH 044/213] ookst480s: update host modules --- hosts/ookst480s/default.nix | 27 +++-------- hosts/ookst480s/file-system.nix | 80 +++++++++++---------------------- hosts/ookst480s/hardware.nix | 23 ++++++++++ hosts/ookst480s/host.nix | 0 hosts/ookst480s/workstation.nix | 12 ----- 5 files changed, 54 insertions(+), 88 deletions(-) create mode 100644 hosts/ookst480s/hardware.nix delete mode 100644 hosts/ookst480s/host.nix delete mode 100644 hosts/ookst480s/workstation.nix diff --git a/hosts/ookst480s/default.nix b/hosts/ookst480s/default.nix index cba1b03..1d1b5af 100644 --- a/hosts/ookst480s/default.nix +++ b/hosts/ookst480s/default.nix @@ -3,7 +3,11 @@ lib, ... }: { - imports = [./file-system.nix]; + imports = [ + ./file-system.nix + ./hardware.nix + ]; + ooknet = { host = { admin = { @@ -20,27 +24,6 @@ console = { profile = "standard"; }; - hardware = { - cpu.type = "intel"; - gpu.type = "intel"; - features = [ - "bluetooth" - "backlight" - "battery" - "ssd" - "audio" - "video" - ]; - monitors = [ - { - primary = true; - name = "eDP-1"; - width = 1920; - height = 1080; - workspace = "1"; - } - ]; - }; }; boot.kernelPackages = pkgs.linuxKernel.packages.linux_zen; system.stateVersion = lib.mkDefault "23.11"; diff --git a/hosts/ookst480s/file-system.nix b/hosts/ookst480s/file-system.nix index 8516afa..30dbf89 100644 --- a/hosts/ookst480s/file-system.nix +++ b/hosts/ookst480s/file-system.nix @@ -1,63 +1,35 @@ -# 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, - modulesPath, - ... -}: { - imports = [ - (modulesPath + "/installer/scan/not-detected.nix") - ]; - - boot.initrd.availableKernelModules = ["xhci_pci" "nvme" "usb_storage" "sd_mod"]; - boot.initrd.kernelModules = []; - boot.kernelModules = ["kvm-intel"]; - boot.extraModulePackages = []; - - fileSystems."/" = { - device = "/dev/disk/by-uuid/19e4cf0f-b5ac-4544-a44b-c017b23fd283"; - fsType = "btrfs"; - options = ["subvol=root"]; - }; - boot.initrd.luks.devices."cryptnix".device = "/dev/disk/by-uuid/014d725c-bf13-40a2-a9ab-0dd6185a95f6"; - fileSystems."/nix" = { - device = "/dev/disk/by-uuid/19e4cf0f-b5ac-4544-a44b-c017b23fd283"; - fsType = "btrfs"; - options = ["subvol=nix"]; - }; + fileSystems = { + "/" = { + device = "/dev/disk/by-uuid/19e4cf0f-b5ac-4544-a44b-c017b23fd283"; + fsType = "btrfs"; + options = ["subvol=root"]; + }; - fileSystems."/persist" = { - device = "/dev/disk/by-uuid/19e4cf0f-b5ac-4544-a44b-c017b23fd283"; - fsType = "btrfs"; - options = ["subvol=persist"]; - }; + "/nix" = { + device = "/dev/disk/by-uuid/19e4cf0f-b5ac-4544-a44b-c017b23fd283"; + fsType = "btrfs"; + options = ["subvol=nix"]; + }; - fileSystems."/swap" = { - device = "/dev/disk/by-uuid/19e4cf0f-b5ac-4544-a44b-c017b23fd283"; - fsType = "btrfs"; - options = ["subvol=swap"]; - }; + "/persist" = { + device = "/dev/disk/by-uuid/19e4cf0f-b5ac-4544-a44b-c017b23fd283"; + fsType = "btrfs"; + options = ["subvol=persist"]; + }; - fileSystems."/boot" = { - device = "/dev/disk/by-uuid/F356-6F9C"; - fsType = "vfat"; - }; + "/swap" = { + device = "/dev/disk/by-uuid/19e4cf0f-b5ac-4544-a44b-c017b23fd283"; + fsType = "btrfs"; + options = ["subvol=swap"]; + }; + "/boot" = { + device = "/dev/disk/by-uuid/F356-6F9C"; + fsType = "vfat"; + }; + }; swapDevices = []; - - # 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.enp0s31f6.useDHCP = lib.mkDefault true; - # networking.interfaces.wlp61s0.useDHCP = lib.mkDefault true; - # networking.interfaces.wwan0.useDHCP = lib.mkDefault true; - - powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; - hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; } diff --git a/hosts/ookst480s/hardware.nix b/hosts/ookst480s/hardware.nix new file mode 100644 index 0000000..d67061d --- /dev/null +++ b/hosts/ookst480s/hardware.nix @@ -0,0 +1,23 @@ +{ + ooknet.hardware = { + cpu.type = "intel"; + gpu.type = "intel"; + features = [ + "bluetooth" + "backlight" + "battery" + "ssd" + "audio" + "video" + ]; + monitors = [ + { + primary = true; + name = "eDP-1"; + width = 1920; + height = 1080; + workspace = "1"; + } + ]; + }; +} diff --git a/hosts/ookst480s/host.nix b/hosts/ookst480s/host.nix deleted file mode 100644 index e69de29..0000000 diff --git a/hosts/ookst480s/workstation.nix b/hosts/ookst480s/workstation.nix deleted file mode 100644 index 39fce43..0000000 --- a/hosts/ookst480s/workstation.nix +++ /dev/null @@ -1,12 +0,0 @@ -{ - config = { - ooknet.workstation = { - appearance = { - theme = "minimal"; - }; - desktop = { - environment = "hyprland"; - }; - }; - }; -} From 6652e534a43a6476160174ed76b8fd686d4abdcc Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 22 Nov 2024 11:15:25 +1100 Subject: [PATCH 045/213] home: disable cava until build failure is fixed --- modules/home/workstation/media/music.nix | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/home/workstation/media/music.nix b/modules/home/workstation/media/music.nix index 5ed6151..fa181b4 100644 --- a/modules/home/workstation/media/music.nix +++ b/modules/home/workstation/media/music.nix @@ -73,7 +73,7 @@ in { }; cava = { - enable = true; + enable = false; # FIX ME!!! settings = { general.framerate = 60; color = { @@ -131,12 +131,12 @@ in { command "${getExe pkgs.spotify-player}" focus true } - pane name="Visualizer" { - borderless false - split_direction "horizontal" - size "20%" - command "${getExe pkgs.cava}" - } + //pane name="Visualizer" { + // borderless false + // split_direction "horizontal" + // size "20%" + // command "cava" + //} } } ''; From 794fb1644577465888124f3a402cab1772727c44 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 22 Nov 2024 11:15:36 +1100 Subject: [PATCH 046/213] flake: update all inputs --- flake.lock | 84 +++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/flake.lock b/flake.lock index f71f1f5..fdbcfd3 100644 --- a/flake.lock +++ b/flake.lock @@ -41,11 +41,11 @@ ] }, "locked": { - "lastModified": 1730968822, - "narHash": "sha256-NocDjINsh6ismkhb0Xr6xPRksmhuB2WGf8ZmXMhxu7Y=", + "lastModified": 1731774881, + "narHash": "sha256-1Dxryiw8u2ejntxrrv3sMtIE8WHKxmlN4KeH+uMGbmc=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "a49bc3583ff223f426cb3526fdaa4bcaa247ec14", + "rev": "b31a6a4da8199ae3489057db7d36069a70749a56", "type": "github" }, "original": { @@ -100,11 +100,11 @@ }, "locked": { "dir": "pkgs/firefox-addons", - "lastModified": 1731297786, - "narHash": "sha256-YC+FPREQqPF2HNSu1PkvVps5mBzexxvCV6NXfTf/kQI=", + "lastModified": 1732161788, + "narHash": "sha256-ilkOtBbv5onnMOYnLWVpBd6bZHP3xwzagccBk1mW/z4=", "owner": "rycee", "repo": "nur-expressions", - "rev": "85c8db7e7e901f656072b01f89c8fffcab26bfa6", + "rev": "3071fc96bc39e58df1c6d48e8008c96f09a00b42", "type": "gitlab" }, "original": { @@ -285,11 +285,11 @@ ] }, "locked": { - "lastModified": 1731235328, - "narHash": "sha256-NjavpgE9/bMe/ABvZpyHIUeYF1mqR5lhaep3wB79ucs=", + "lastModified": 1732025103, + "narHash": "sha256-qjEI64RKvDxRyEarY0jTzrZMa8ebezh2DEZmJJrpVdo=", "owner": "nix-community", "repo": "home-manager", - "rev": "60bb110917844d354f3c18e05450606a435d2d10", + "rev": "a46e702093a5c46e192243edbd977d5749e7f294", "type": "github" }, "original": { @@ -347,11 +347,11 @@ ] }, "locked": { - "lastModified": 1730561387, - "narHash": "sha256-esE2L7+9CsmlSjTIHwU9VAhzvsFSMC3kO7EiutCPQpg=", + "lastModified": 1731958956, + "narHash": "sha256-21R5LD61oUqjdo9Vz0kLn0qSHCDMXyUMXbbod3kX+ho=", "owner": "hyprwm", "repo": "hypridle", - "rev": "26780ac51f6e7273e3934885036b7a7ed1a5af01", + "rev": "9f23e70bb494107df8f959c925d4521a298c65eb", "type": "github" }, "original": { @@ -374,11 +374,11 @@ "xdph": "xdph" }, "locked": { - "lastModified": 1731340175, - "narHash": "sha256-qhkP+XRa1AuKkVrxKDLdK4gby363vH6wEie5tb6rz2E=", + "lastModified": 1732100541, + "narHash": "sha256-ryxqTo2N5EOwHjrDXCoVFKuG1ZKpoMlRmCjqqUhjQPU=", "owner": "hyprwm", "repo": "hyprland", - "rev": "f5fa84554ffe55e29a397014964238be89ffa54d", + "rev": "940f7aa990dbc99815bab8d355999d8277534b17", "type": "github" }, "original": { @@ -425,11 +425,11 @@ ] }, "locked": { - "lastModified": 1731169722, - "narHash": "sha256-hOljwsXpY4Y6guvcr51tWCnXo6c56yaBknnLXk1m3Vk=", + "lastModified": 1732053779, + "narHash": "sha256-v9FS0r2XWMf/+uwevvzaF/2TimMFeLEQTf4T8cgc6c0=", "owner": "hyprwm", "repo": "hyprland-plugins", - "rev": "844eb98250da448e17471f20beed23a5f5d33a3a", + "rev": "0bc619b2c3b4f9c2b65247e81d69f8bbc573d991", "type": "github" }, "original": { @@ -512,11 +512,11 @@ ] }, "locked": { - "lastModified": 1731340729, - "narHash": "sha256-xM+dVOJ5MXjaVfaZeUD2LHVaQXJUZfXhUCfEGEDW7rc=", + "lastModified": 1732023353, + "narHash": "sha256-FbHP2io0nKSC0qEjTdAhrfmlqiv9oB1P/DcV3jFAnWY=", "owner": "hyprwm", "repo": "hyprlock", - "rev": "c3c28feb4c6469269d049185e9427bf4a33c8c40", + "rev": "578246b9967dec77c56993dc55ca192d35ba9bb7", "type": "github" }, "original": { @@ -571,11 +571,11 @@ ] }, "locked": { - "lastModified": 1731163338, - "narHash": "sha256-Qflei0JBeqQ0c8jxA8e982xAxJvfMwfx4Aci2eJi84s=", + "lastModified": 1731702627, + "narHash": "sha256-+JeO9gevnXannQxMfR5xzZtF4sYmSlWkX/BPmPx0mWk=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "60d3dece30f98e8ad85131829c8529950630d6bc", + "rev": "e911361a687753bbbdfe3b6a9eab755ecaf1d9e1", "type": "github" }, "original": { @@ -719,11 +719,11 @@ ] }, "locked": { - "lastModified": 1731209121, - "narHash": "sha256-BF7FBh1hIYPDihdUlImHGsQzaJZVLLfYqfDx41wjuF0=", + "lastModified": 1731814505, + "narHash": "sha256-l9ryrx1Twh08a+gxrMGM9O/aZKEimZfa6sZVyPCImgI=", "owner": "nix-community", "repo": "nix-index-database", - "rev": "896019f04b22ce5db4c0ee4f89978694f44345c3", + "rev": "bdba246946fb079b87b4cada4df9b1cdf1c06132", "type": "github" }, "original": { @@ -802,11 +802,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1730785428, - "narHash": "sha256-Zwl8YgTVJTEum+L+0zVAWvXAGbWAuXHax3KzuejaDyo=", + "lastModified": 1731676054, + "narHash": "sha256-OZiZ3m8SCMfh3B6bfGC/Bm4x3qc1m2SVEAlkV6iY7Yg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4aa36568d413aca0ea84a1684d2d46f55dbabad7", + "rev": "5e4fbfb6b3de1aa2872b76d49fafc942626e2add", "type": "github" }, "original": { @@ -818,11 +818,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1731139594, - "narHash": "sha256-IigrKK3vYRpUu+HEjPL/phrfh7Ox881er1UEsZvw9Q4=", + "lastModified": 1732014248, + "narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "76612b17c0ce71689921ca12d9ffdc9c23ce40b2", + "rev": "23e89b7da85c3640bbc2173fe04f4bd114342367", "type": "github" }, "original": { @@ -2933,11 +2933,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1730814269, - "narHash": "sha256-fWPHyhYE6xvMI1eGY3pwBTq85wcy1YXqdzTZF+06nOg=", + "lastModified": 1731363552, + "narHash": "sha256-vFta1uHnD29VUY4HJOO/D6p6rxyObnf+InnSMT4jlMU=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "d70155fdc00df4628446352fc58adc640cd705c2", + "rev": "cd1af27aa85026ac759d5d3fccf650abe7e1bbf0", "type": "github" }, "original": { @@ -3178,11 +3178,11 @@ ] }, "locked": { - "lastModified": 1730743262, - "narHash": "sha256-iTLqj3lU8kFehPm5tXpctzkD274t/k1nwSSq3qCWXeg=", + "lastModified": 1731703417, + "narHash": "sha256-rheDc/7C+yI+QspYr9J2z9kQ5P9F4ATapI7qyFAe1XA=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "09b23cef06fe248e61cec8862c04b9bcb62f4b6d", + "rev": "8070f36deec723de71e7557441acb17e478204d3", "type": "github" }, "original": { @@ -3199,11 +3199,11 @@ "rust-overlay": "rust-overlay_2" }, "locked": { - "lastModified": 1730748983, - "narHash": "sha256-72uoWm/34SU5aHgvUJgKqYMhvt4Y9X39bFhcDwVS+P0=", + "lastModified": 1731757608, + "narHash": "sha256-yWY2aGfsBVTT9vtwRqVnNqkiB0xcWcB1MoITrvPmEtA=", "owner": "dj95", "repo": "zjstatus", - "rev": "d5794fbec93860ead015b0beee70489f50cd87b1", + "rev": "5d6ff93551882fddc7773f108470001fe87a5187", "type": "github" }, "original": { From 05274f898bb359af8fb8b0da23b19cc122116ae2 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 22 Nov 2024 11:58:26 +1100 Subject: [PATCH 047/213] nixos: enable bluetooth module --- modules/home/base/home-manager.nix | 3 +-- modules/home/workstation/tools/default.nix | 1 + modules/home/workstation/tools/live-buds-cli.nix | 13 +++++++++++++ modules/nixos/hardware/features/bluetooth.nix | 2 -- modules/nixos/hardware/features/default.nix | 2 +- 5 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 modules/home/workstation/tools/live-buds-cli.nix diff --git a/modules/home/base/home-manager.nix b/modules/home/base/home-manager.nix index cfbf6eb..45d90c6 100644 --- a/modules/home/base/home-manager.nix +++ b/modules/home/base/home-manager.nix @@ -4,7 +4,6 @@ osConfig, ... }: let - inherit (lib) mkDefault; inherit (osConfig.ooknet.host) admin; in { programs.home-manager.enable = true; @@ -13,7 +12,7 @@ in { home = { username = admin.name; homeDirectory = "/home/${config.home.username}"; - stateVersion = mkDefault "22.05"; + stateVersion = "22.05"; sessionPath = ["${config.home.homeDirectory}/.local/bin"]; }; diff --git a/modules/home/workstation/tools/default.nix b/modules/home/workstation/tools/default.nix index 7a1545e..91c44b2 100644 --- a/modules/home/workstation/tools/default.nix +++ b/modules/home/workstation/tools/default.nix @@ -1,6 +1,7 @@ { imports = [ ./ookpower.nix + ./live-buds-cli.nix ./virt-manager.nix ./1password.nix ./ookvolume.nix diff --git a/modules/home/workstation/tools/live-buds-cli.nix b/modules/home/workstation/tools/live-buds-cli.nix new file mode 100644 index 0000000..03f5a4c --- /dev/null +++ b/modules/home/workstation/tools/live-buds-cli.nix @@ -0,0 +1,13 @@ +{ + osConfig, + self', + lib, + ... +}: let + inherit (lib) mkIf elem; + inherit (osConfig.ooknet.hardware) features; +in { + config = mkIf (elem "bluetooth" features) { + home.packages = [self'.packages.live-buds-cli]; + }; +} diff --git a/modules/nixos/hardware/features/bluetooth.nix b/modules/nixos/hardware/features/bluetooth.nix index 9ce0c5c..821f60f 100644 --- a/modules/nixos/hardware/features/bluetooth.nix +++ b/modules/nixos/hardware/features/bluetooth.nix @@ -2,7 +2,6 @@ config, lib, pkgs, - self, ... }: let inherit (lib) mkIf; @@ -16,7 +15,6 @@ in { }; environment.systemPackages = attrValues { - #inherit (self.packages.${pkgs.system}) live-buds-cli; inherit (pkgs) bluetuith; }; diff --git a/modules/nixos/hardware/features/default.nix b/modules/nixos/hardware/features/default.nix index 8704874..882edfd 100644 --- a/modules/nixos/hardware/features/default.nix +++ b/modules/nixos/hardware/features/default.nix @@ -6,6 +6,6 @@ ./battery.nix ./backlight.nix ./ssd.nix - # ./bluetooth.nix + ./bluetooth.nix ]; } From 7590d9af07e8d0effdd0b709d450731ca624fda3 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 23 Nov 2024 14:58:05 +1100 Subject: [PATCH 048/213] server: initial media server config --- modules/nixos/server/options.nix | 2 +- modules/nixos/server/services/default.nix | 1 + .../server/services/media-server/default.nix | 30 +++ .../media-server/file-permissions.nix | 42 +++ .../server/services/media-server/jellyfin.nix | 20 ++ .../server/services/media-server/options.nix | 242 ++++++++++++++++++ .../server/services/media-server/plex.nix | 20 ++ .../server/services/media-server/prowlarr.nix | 48 ++++ .../server/services/media-server/radarr.nix | 20 ++ .../server/services/media-server/sonarr.nix | 20 ++ .../services/media-server/transmission.nix | 77 ++++++ .../server/services/media-server/users.nix | 23 ++ outputs/hosts/servers.nix | 3 +- 13 files changed, 546 insertions(+), 2 deletions(-) create mode 100644 modules/nixos/server/services/media-server/default.nix create mode 100644 modules/nixos/server/services/media-server/file-permissions.nix create mode 100644 modules/nixos/server/services/media-server/jellyfin.nix create mode 100644 modules/nixos/server/services/media-server/options.nix create mode 100644 modules/nixos/server/services/media-server/plex.nix create mode 100644 modules/nixos/server/services/media-server/prowlarr.nix create mode 100644 modules/nixos/server/services/media-server/radarr.nix create mode 100644 modules/nixos/server/services/media-server/sonarr.nix create mode 100644 modules/nixos/server/services/media-server/transmission.nix create mode 100644 modules/nixos/server/services/media-server/users.nix diff --git a/modules/nixos/server/options.nix b/modules/nixos/server/options.nix index 2b437fd..4de3252 100644 --- a/modules/nixos/server/options.nix +++ b/modules/nixos/server/options.nix @@ -14,7 +14,7 @@ in { description = "The server profile the host will use as a base"; }; services = mkOption { - type = listOf (enum ["website" "forgejo"]); + type = listOf (enum ["media-server" "website" "forgejo"]); default = []; description = "List of services the server will host"; }; diff --git a/modules/nixos/server/services/default.nix b/modules/nixos/server/services/default.nix index 6d19766..7685461 100644 --- a/modules/nixos/server/services/default.nix +++ b/modules/nixos/server/services/default.nix @@ -2,5 +2,6 @@ imports = [ ./website ./forgejo + ./media-server ]; } diff --git a/modules/nixos/server/services/media-server/default.nix b/modules/nixos/server/services/media-server/default.nix new file mode 100644 index 0000000..a5bbd81 --- /dev/null +++ b/modules/nixos/server/services/media-server/default.nix @@ -0,0 +1,30 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkIf elem; + inherit (config.ooknet.server) services; +in { + imports = [ + ./plex.nix + ./users.nix + ./options.nix + ./jellyfin.nix + ./transmission.nix + ./file-permissions.nix + ]; + + # short cut for enabling all media-server modules + config = mkIf (elem "media-server" services) { + ooknet.server.media-server = { + enable = true; + jellyfin.enable = true; + plex.enable = true; + transmission.enable = true; + radarr.enable = true; + sonarr.enable = true; + prowlarr.enable = true; + }; + }; +} diff --git a/modules/nixos/server/services/media-server/file-permissions.nix b/modules/nixos/server/services/media-server/file-permissions.nix new file mode 100644 index 0000000..b791728 --- /dev/null +++ b/modules/nixos/server/services/media-server/file-permissions.nix @@ -0,0 +1,42 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkIf; + inherit (config.ooknet.server) media-server; + inherit (config.ooknet.server.media-server) storage groups users; + + contentPermissions = { + group = groups.media; + user = "root"; + mode = "0775"; + }; + + downloadPermissions = { + group = groups.media; + user = users.downloader; + mode = "0775"; + }; +in { + config = mkIf media-server.enable { + systemd.tmpfiles.settings = { + content-dirs = { + "${storage.content.root}"."d" = contentPermissions; + "${storage.content.movies}"."d" = contentPermissions; + "${storage.content.tv}"."d" = contentPermissions; + "${storage.content.music}"."d" = contentPermissions; + "${storage.content.books}"."d" = contentPermissions; + }; + download-dirs = { + "${storage.downloads.root}"."d" = downloadPermissions; + "${storage.downloads.incomplete}"."d" = downloadPermissions; + "${storage.downloads.watch}"."d" = downloadPermissions; + "${storage.downloads.manual}"."d" = downloadPermissions; + "${storage.downloads.radarr}"."d" = downloadPermissions; + "${storage.downloads.sonarr}"."d" = downloadPermissions; + "${storage.downloads.readarr}"."d" = downloadPermissions; + }; + }; + }; +} diff --git a/modules/nixos/server/services/media-server/jellyfin.nix b/modules/nixos/server/services/media-server/jellyfin.nix new file mode 100644 index 0000000..8caf355 --- /dev/null +++ b/modules/nixos/server/services/media-server/jellyfin.nix @@ -0,0 +1,20 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkIf; + inherit (config.ooknet.server) media-server; + inherit (config.ooknet.server.media-server) storage groups users domain proxy; +in { + config = mkIf media-server.jellyfin.enable { + services.jellyfin = { + enable = true; + user = users.streamer; + group = groups.media; + dataDir = storage.state.jellyfin; + }; + ooknet.server.webserver.caddy.enable = true; + services.caddy.virtualHosts."${domain.jellyfin}".extraConfig = proxy.jellyfin; + }; +} diff --git a/modules/nixos/server/services/media-server/options.nix b/modules/nixos/server/services/media-server/options.nix new file mode 100644 index 0000000..a9c89b3 --- /dev/null +++ b/modules/nixos/server/services/media-server/options.nix @@ -0,0 +1,242 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkOption mkEnableOption; + inherit (lib.types) path port str lines; + inherit (config.ooknet) server; + cfg = server.media-server; + + mkSubdomain = name: + mkOption { + type = str; + default = "${name}.${server.domain}"; + }; + + mkProxy = port: '' + encode zstd gzip + reverse_proxy localhost:${toString port} { + header_up X-Real-IP {remote_host} + header_up X-Forwarded-For {remote_host} + header_up X-Forwarded-Proto {scheme} + } + ''; +in { + options.ooknet.server.media-server = { + enable = mkEnableOption "Enable media server functionality"; + + jellyfin.enable = mkEnableOption "Enable the Jellyfin module"; + plex.enable = mkEnableOption "Enable Plex module"; + transmission.enable = mkEnableOption "Enable Transmission module"; + radarr.enable = mkEnableOption "Enable Radarr module"; + sonarr.enable = mkEnableOption "Enable Sonarr module"; + prowlarr.enable = mkEnableOption "Enable Sonarr module"; + + storage = { + mediaRoot = mkOption { + type = path; + default = "/media"; + description = "Root directory for all media-related storage"; + }; + + content = { + root = mkOption { + type = path; + default = "${cfg.storage.mediaRoot}/content"; + description = "Root directory for media content"; + }; + movies = mkOption { + type = path; + default = "${cfg.storage.content.root}/movies"; + }; + tv = mkOption { + type = path; + default = "${cfg.storage.content.root}/tv"; + }; + music = mkOption { + type = path; + default = "${cfg.storage.content.root}/music"; + }; + books = mkOption { + type = path; + default = "${cfg.storage.content.root}/books"; + }; + }; + + downloads = { + root = mkOption { + type = path; + default = "${cfg.storage.mediaRoot}/downloads"; + }; + incomplete = mkOption { + type = path; + default = "${cfg.storage.downloads.root}/.incomplete"; + }; + watch = mkOption { + type = path; + default = "${cfg.storage.downloads.root}/.watch"; + }; + manual = mkOption { + type = path; + default = "${cfg.storage.downloads.root}/manual"; + }; + radarr = mkOption { + type = path; + default = "${cfg.storage.downloads.root}/radarr"; + }; + sonarr = mkOption { + type = path; + default = "${cfg.storage.downloads.root}/sonarr"; + }; + readarr = mkOption { + type = path; + default = "${cfg.storage.downloads.root}/readarr"; + }; + }; + + state = { + root = mkOption { + type = path; + default = "/var/lib"; + description = "Root directory for service state"; + }; + jellyfin = mkOption { + type = path; + default = "${cfg.storage.state.root}/jellyfin"; + }; + plex = mkOption { + type = path; + default = "${cfg.storage.state.root}/plex"; + }; + sonarr = mkOption { + type = path; + default = "${cfg.storage.state.root}/sonarr"; + }; + radarr = mkOption { + type = path; + default = "${cfg.storage.state.root}/radarr"; + }; + transmission = mkOption { + type = path; + default = "${cfg.storage.state.root}/transmission"; + }; + }; + }; + + groups = { + media = mkOption { + type = str; + default = "media"; + }; + prowlarr = mkOption { + type = str; + default = "prowlarr"; + }; + radarr = mkOption { + type = str; + default = "radarr"; + }; + }; + + users = { + jellyfin = mkOption { + type = str; + default = "jellyfin"; + }; + plex = mkOption { + type = str; + default = "plex"; + }; + sonarr = mkOption { + type = str; + default = "sonarr"; + }; + transmission = mkOption { + type = str; + default = "transmission"; + }; + prowlarr = mkOption { + type = str; + default = "prowlarr"; + }; + downloader = mkOption { + type = str; + default = "downloader"; + }; + streamer = mkOption { + type = str; + default = "streamer"; + }; + }; + + ports = { + jellyfin = mkOption { + type = port; + default = 8096; + }; + plex = mkOption { + type = port; + default = 32400; + }; + transmission = { + web = mkOption { + type = port; + default = 9091; + }; + peer = mkOption { + type = port; + default = 50000; + }; + }; + sonarr = mkOption { + type = port; + default = 8989; + }; + radarr = mkOption { + type = port; + default = 7878; + }; + prowlarr = mkOption { + type = port; + default = 9696; + }; + }; + + domain = { + jellyfin = mkSubdomain "jellyfin"; + plex = mkSubdomain "plex"; + transmission = mkSubdomain "transmission"; + sonarr = mkSubdomain "sonarr"; + radarr = mkSubdomain "radarr"; + prowlarr = mkSubdomain "prowlarr"; + }; + + proxy = { + jellyfin = mkOption { + type = lines; + default = mkProxy cfg.ports.jellyfin; + }; + plex = mkOption { + type = lines; + default = mkProxy cfg.ports.plex; + }; + sonarr = mkOption { + type = lines; + default = mkProxy cfg.ports.sonarr; + }; + radarr = mkOption { + type = lines; + default = mkProxy cfg.ports.radarr; + }; + prowlarr = mkOption { + type = lines; + default = mkProxy cfg.ports.prowlarr; + }; + transmission = mkOption { + type = lines; + default = mkProxy cfg.ports.transmission.web; + }; + }; + }; +} diff --git a/modules/nixos/server/services/media-server/plex.nix b/modules/nixos/server/services/media-server/plex.nix new file mode 100644 index 0000000..5c4bfb6 --- /dev/null +++ b/modules/nixos/server/services/media-server/plex.nix @@ -0,0 +1,20 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkIf; + inherit (config.ooknet.server) media-server; + inherit (config.ooknet.server.media-server) groups users storage domain proxy; +in { + config = mkIf media-server.plex.enable { + services.plex = { + enable = true; + user = users.streamer; + group = groups.media; + dataDir = storage.state.plex; + }; + ooknet.server.webserver.caddy.enable = true; + services.caddy.virtualHosts."${domain.plex}".extraConfig = proxy.plex; + }; +} diff --git a/modules/nixos/server/services/media-server/prowlarr.nix b/modules/nixos/server/services/media-server/prowlarr.nix new file mode 100644 index 0000000..b4efd5c --- /dev/null +++ b/modules/nixos/server/services/media-server/prowlarr.nix @@ -0,0 +1,48 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib) mkIf getExe; + inherit (config.ooknet.server) media-server; + inherit (config.ooknet.server.media-server) storage users groups domain proxy; +in { + config = mkIf media-server.prowlarr.enable { + # we dont use the nixpkgs prowlarr service module because it lacks the option to + # declare dataDir, user and group. + + # setup user + users.users.prowlarr = { + group = groups.prowlarr; + home = storage.state.prowlarr; + }; + users.groups.prowlarr = {}; + + # basic systemd service + systemd = { + services.prowlarr = { + description = "Prowlarr"; + after = ["network.target"]; + wantedBy = ["multi-user.target"]; + + serviceConfig = { + Type = "simple"; + User = users.prowlarr; + group = groups.prowlarr; + ExecStart = "${getExe pkgs.prowlarr} -nobrowser -data=${storage.state.prowlarr}"; + Restart = "on-failure"; + }; + }; + tmpfiles.settings.prowlarrDirs = { + "${storage.state.prowlarr}"."d" = { + mode = "700"; + user = users.prowlarr; + group = groups.prowlarr; + }; + }; + }; + ooknet.server.webserver.caddy.enable = true; + services.caddy.virtualHosts."${domain.prowlarr}".extraConfig = proxy.prowlarr; + }; +} diff --git a/modules/nixos/server/services/media-server/radarr.nix b/modules/nixos/server/services/media-server/radarr.nix new file mode 100644 index 0000000..beb5784 --- /dev/null +++ b/modules/nixos/server/services/media-server/radarr.nix @@ -0,0 +1,20 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkIf; + inherit (config.ooknet.server) media-server; + inherit (config.ooknet.server.media-server) storage users groups domain proxy; +in { + config = mkIf media-server.radarr.enable { + services.radarr = { + enable = true; + user = users.radarr; + group = groups.radarr; + dataDir = storage.state.radaar; + }; + ooknet.server.webserver.caddy.enable = true; + services.caddy.virtualHosts."${domain.radarr}".extraConfig = proxy.radarr; + }; +} diff --git a/modules/nixos/server/services/media-server/sonarr.nix b/modules/nixos/server/services/media-server/sonarr.nix new file mode 100644 index 0000000..be42fde --- /dev/null +++ b/modules/nixos/server/services/media-server/sonarr.nix @@ -0,0 +1,20 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkIf; + inherit (config.ooknet.server) media-server; + inherit (config.ooknet.server.media-server) storage users groups domain proxy; +in { + config = mkIf media-server.sonarr.enable { + services.sonarr = { + enable = true; + user = users.sonarr; + group = groups.sonarr; + dataDir = storage.state.sonarr; + }; + ooknet.server.webserver.caddy.enable = true; + services.caddy.virtualHosts."${domain.sonarr}".extraConfig = proxy.sonarr; + }; +} diff --git a/modules/nixos/server/services/media-server/transmission.nix b/modules/nixos/server/services/media-server/transmission.nix new file mode 100644 index 0000000..7999a19 --- /dev/null +++ b/modules/nixos/server/services/media-server/transmission.nix @@ -0,0 +1,77 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib) mkIf; + inherit (builtins) concatStringsSep; + inherit (config.ooknet.server) media-server; + inherit (config.ooknet.server.media-server) storage ports users groups domain proxy; +in { + config = mkIf media-server.transmission.enable { + services.transmission = { + enable = true; + package = pkgs.transmission_4; + + # systemd service permissions + user = users.downloader; + group = groups.media; + + # location of transmission config dir + home = storage.state.transmission; + + # web ui + webHome = pkgs.flood-for-transmission; + + # additional configurations + # see + settings = { + # enable in completed directory + # this is where files will be placed while still being downloaded + incomplete-dir-enabled = true; + + # enable the watch directory + # this will look for any new torrent files and start downloading them + watch-dir-enabled = true; + + # location of the main download directories + download-dir = storage.downloads.root; + incomplete-dir = storage.downloads.incomplete; + watch-dir = storage.downloads.watch; + + # rpc settings + # rpc is how we connect to the service remotely + rpc-port = ports.transmission.web; + + # what ip addresses are allowed to connect through rpc + rpc-whitelist-enabled = true; + rpc-whitelist = concatStringsSep "," [ + # localhost + "127.0.0.1" + # generic home networks + "192.168.*" + "10.*" + ]; + + # basic anti bruteforce protection + anti-brute-force-enabled = true; + + # how many authentication attempts can be made before the rpc server will deny any further + # authentication attempts. + anti-brute-force-threshold = 10; + + peer-port = ports.transmission.peer; + port-forwarding-enabled = false; + + # private trackers usually require disabling these + utp-enabled = false; + dht-enabled = false; + pex-enabled = false; + lpd-enabled = false; + }; + }; + ooknet.server.webserver.caddy.enable = true; + services.caddy.virtualHosts."${domain.transmission}".extraConfig = proxy.transmission; + }; +} diff --git a/modules/nixos/server/services/media-server/users.nix b/modules/nixos/server/services/media-server/users.nix new file mode 100644 index 0000000..6d1bcfd --- /dev/null +++ b/modules/nixos/server/services/media-server/users.nix @@ -0,0 +1,23 @@ +{ + config, + lib, + ... +}: let + inherit (lib) elem mkIf; + inherit (config.ooknet.server) services; +in { + config = mkIf (elem "media-server" services) { + users = { + groups = { + downloader = {}; + media = {}; + }; + users = { + downloader = { + isSystemUser = true; + group = "downloader"; + }; + }; + }; + }; +} diff --git a/outputs/hosts/servers.nix b/outputs/hosts/servers.nix index a05b3cf..1902512 100644 --- a/outputs/hosts/servers.nix +++ b/outputs/hosts/servers.nix @@ -19,8 +19,9 @@ in { inherit withSystem; system = "x86_64-linux"; hostname = "ooksmedia"; + domain = "ooknet.org"; type = "desktop"; - services = []; + services = ["media-server"]; }; }; } From a98484b4202d8fdaaaf55970dc33b8583f5d8f2d Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 24 Nov 2024 21:28:04 +1100 Subject: [PATCH 049/213] media-server: add streamer user config --- modules/nixos/server/services/media-server/users.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/nixos/server/services/media-server/users.nix b/modules/nixos/server/services/media-server/users.nix index 6d1bcfd..b7ec424 100644 --- a/modules/nixos/server/services/media-server/users.nix +++ b/modules/nixos/server/services/media-server/users.nix @@ -11,12 +11,17 @@ in { groups = { downloader = {}; media = {}; + streamer = {}; }; users = { downloader = { isSystemUser = true; group = "downloader"; }; + steamer = { + isSystemUser = true; + group = "streamer"; + }; }; }; }; From 3ef446f9b38ce71776d413312a4e2df7e958b95d Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 25 Nov 2024 23:50:06 +1100 Subject: [PATCH 050/213] website: use tmpfiles.settings --- modules/nixos/server/services/website/default.nix | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/nixos/server/services/website/default.nix b/modules/nixos/server/services/website/default.nix index af0bf4f..64a0fa2 100644 --- a/modules/nixos/server/services/website/default.nix +++ b/modules/nixos/server/services/website/default.nix @@ -7,13 +7,19 @@ inherit (lib) mkIf elem; inherit (config.ooknet.server) services; inherit (self'.packages) website; + + websitePermissions = { + group = "www"; + user = "caddy"; + mode = "0775"; + }; in { config = mkIf (elem "website" services) { ooknet.server.webserver.caddy.enable = true; - systemd.tmpfiles.rules = [ - "d /var/www 0775 caddy www" - "d /var/www/ooknet.org 0775 caddy www" - ]; + systemd.tmpfiles.settings.websiteDirs = { + "/var/www"."d" = websitePermissions; + "/var/www/ooknet.org"."d" = websitePermissions; + }; # cursed activation script # need to find a better way From 54469932ca467b9aaafe79bf379c21f31d26ef0f Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 27 Nov 2024 22:26:41 +1100 Subject: [PATCH 051/213] ooksmedia: add media-server mount --- hosts/ooksmedia/file-system.nix | 4 ++++ outputs/hosts/servers.nix | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/hosts/ooksmedia/file-system.nix b/hosts/ooksmedia/file-system.nix index 64bb4a1..4686100 100644 --- a/hosts/ooksmedia/file-system.nix +++ b/hosts/ooksmedia/file-system.nix @@ -24,6 +24,10 @@ device = "/dev/disk/by-uuid/B511-09E2"; fsType = "vfat"; }; + "/media-server" = { + device = "/dev/disk/by-label/jellyfin"; + fsType = "btrfs"; + }; }; swapDevices = []; } diff --git a/outputs/hosts/servers.nix b/outputs/hosts/servers.nix index 1902512..7df15e8 100644 --- a/outputs/hosts/servers.nix +++ b/outputs/hosts/servers.nix @@ -15,7 +15,7 @@ in { profile = "linode"; services = ["website" "forgejo"]; }; - ookmedia = mkServer { + ooksmedia = mkServer { inherit withSystem; system = "x86_64-linux"; hostname = "ooksmedia"; From 33e5d8fbea7760694da0b842d5815297aa940b4e Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 27 Nov 2024 22:26:55 +1100 Subject: [PATCH 052/213] media-server: add vpn module --- modules/nixos/base/secrets.nix | 5 ++- .../server/services/media-server/default.nix | 3 ++ .../server/services/media-server/vpn.nix | 39 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 modules/nixos/server/services/media-server/vpn.nix diff --git a/modules/nixos/base/secrets.nix b/modules/nixos/base/secrets.nix index 63406e2..c6297e8 100644 --- a/modules/nixos/base/secrets.nix +++ b/modules/nixos/base/secrets.nix @@ -8,7 +8,7 @@ inherit (config.ooknet) host; inherit (host) admin; - inherit (config.services) tailscale; + inherit (config.services) tailscale transmission; in { age.identityPaths = [ "/home/${admin.name}/.ssh/id_ed25519" @@ -36,5 +36,8 @@ in { owner = "${admin.name}"; group = "users"; }; + mullvad_wg = mkIf transmission.enable { + file = "${self}/secrets/mullvad_wg.age"; + }; }; } diff --git a/modules/nixos/server/services/media-server/default.nix b/modules/nixos/server/services/media-server/default.nix index a5bbd81..2e17c8d 100644 --- a/modules/nixos/server/services/media-server/default.nix +++ b/modules/nixos/server/services/media-server/default.nix @@ -1,6 +1,7 @@ { lib, config, + inputs, ... }: let inherit (lib) mkIf elem; @@ -13,6 +14,8 @@ in { ./jellyfin.nix ./transmission.nix ./file-permissions.nix + ./vpn.nix + inputs.vpn-confinement.nixosModules.default ]; # short cut for enabling all media-server modules diff --git a/modules/nixos/server/services/media-server/vpn.nix b/modules/nixos/server/services/media-server/vpn.nix new file mode 100644 index 0000000..7724a97 --- /dev/null +++ b/modules/nixos/server/services/media-server/vpn.nix @@ -0,0 +1,39 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkIf; + inherit (config.ooknet.server.media-server) ports transmission; + inherit (config.age) secrets; +in { + config = mkIf transmission.enable { + vpnNamespaces.wg = { + enable = true; + wireguardConfigFile = secrets.mullvad_wg.path; + accessibleFrom = [ + "192.168.0.1/24" + "127.0.0.1" + "10.0.0.0/8" + ]; + openVPNPorts = [ + # Transmission + { + port = ports.transmission.peer; + protocol = "both"; + } + ]; + portMappings = [ + # Transmission + { + from = ports.transmission.web; + to = ports.transmission.web; + } + ]; + }; + systemd.services.transmission.vpnConfinement = { + enable = true; + vpnNamespace = "wg"; + }; + }; +} From 2565005fe0438bb237f0814f220ebd1323bb572a Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 27 Nov 2024 22:38:41 +1100 Subject: [PATCH 053/213] secrets: add mullvad_wg conf file --- secrets/keys.nix | 5 ++++- secrets/mullvad_wg.age | Bin 0 -> 1269 bytes secrets/secrets.nix | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 secrets/mullvad_wg.age diff --git a/secrets/keys.nix b/secrets/keys.nix index a3cf90f..59036c6 100644 --- a/secrets/keys.nix +++ b/secrets/keys.nix @@ -20,6 +20,9 @@ let hosts.ooksmicro hosts.ooksx1 ]; + servers = [ + hosts.ooksmedia + ]; in { - inherit users hosts workstations; + inherit users servers hosts workstations; } diff --git a/secrets/mullvad_wg.age b/secrets/mullvad_wg.age new file mode 100644 index 0000000000000000000000000000000000000000..24eeed77f2ee33f4ce3b5a47c724c5c01f8ca106 GIT binary patch literal 1269 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCTyNcG4IbyP^oN(oL+ z%?$8Qbq*`_h%C+baZfAH%Xii{buTu`Ee`hd&(2A6G%t1u3gpTzEY5XzP7F^fPc!wY zit-4p$V;!t4M;Nz)pkrxipbBea81bxF)mE=NJqEL%%d!^#8JW6J<2jD%-1nJ%_lrB zAkZhJIMX7z+$GYqGPuOc*WAo3*DN>3BG@&cJe#Z7w8Y!J#7#T2!l}|Dt01S?%%`-_ zB-P71D5<<8#UjP9DBZ2Vsmdb6A{5;=W0!JwlX3+g_f((IR4)%p_Xs~@3&Sc?v(!Li z%lzcBAVZ^ES1;$BqR?zh4<|#joKUX3Kt~Jr&~(4z@^ara6MsW}Ul-#{?cA{PV&7B) zpU}vpKr?NF5^rBmi+pt3{PHZqD;yOfQnHFu11c@UgY(T@-AvO=+?}1glR}e94b4MR z)7(-`OME>t(~NzLLdv-;!+g?G3p}#ii!DvGi;Dcy63sHQvI@=1O}q?Cv`gG7yT5M((Zt0X3W)M|~S}p3YSfnwgxMk(!uNo>$?VQ=XdW;%`>&9O#(k77$eu80_MlZJZpL>lWs3>WS{R zRNpLZuXKf?f)vN9@Su#;aBahP*c(j3Pmvy7yGz#{Ez5AQ6Gz~yaD za%cUhbdx9_XJh~TysWY;XE(=;2)Cd}SJy%>cc;9PB0r~)oYHjj9E?=r8>nyYTCNc6 zmg<%m5$I-NX%v}Om6V$wp6HqsRFq{7pHw=IrL? z9+B!^YEn`h;O_3J?U8S4WZ`95=I`NOZsy}s8XD}CUXJcJXex0}E)DW4^D*{K3CmB+ z@-Fa?$n!5U%y$lo^00_7G|cu0%}Mf!^b8Bg^W^dkc8e;Bun6}tO)d>9t_%$@eM_H1+h; zb~Q*UNlbB#Ec5m=$;`~r&*$207+B@gW9($lvTaQP=Mn9kW3O!w|H_^>Nml32r7b0T z)_ocQA7+_o_?~&Q^#A@nFN($AJvFIwpZieyS+uOojPLRv^_FmkrtehkI;>~;XQQFS z{VS`J<)^jnUuT!0qwGKZ`?gHe`>OLUnXy{1P0SB77Y{Ibx{)RK@=h`CbJfop9Ay@A zw(rv0tbJ7e@F!NqE#fAu)#nRXHlNz}C!lajh=|ILx64IKXXF{bU;ll5 Date: Wed, 27 Nov 2024 22:47:20 +1100 Subject: [PATCH 054/213] flake: add vpn-confinement --- flake.lock | 16 ++++++++++++++++ flake.nix | 3 +++ 2 files changed, 19 insertions(+) diff --git a/flake.lock b/flake.lock index fdbcfd3..5880249 100644 --- a/flake.lock +++ b/flake.lock @@ -2984,6 +2984,7 @@ "ooknet-website": "ooknet-website", "ooks-scripts": "ooks-scripts", "systems": "systems_6", + "vpn-confinement": "vpn-confinement", "zjstatus": "zjstatus" } }, @@ -3150,6 +3151,21 @@ "type": "github" } }, + "vpn-confinement": { + "locked": { + "lastModified": 1731209328, + "narHash": "sha256-b3jggBHZh20jUfBxoaIvew23czsw82zBc0aKxtkF3g8=", + "owner": "Maroka-chan", + "repo": "VPN-Confinement", + "rev": "74e6fd47804b5ca69187200efbb14cf1ecb9ea07", + "type": "github" + }, + "original": { + "owner": "Maroka-chan", + "repo": "VPN-Confinement", + "type": "github" + } + }, "xdph": { "inputs": { "hyprland-protocols": [ diff --git a/flake.nix b/flake.nix index 4b9c24c..05fe767 100644 --- a/flake.nix +++ b/flake.nix @@ -37,6 +37,9 @@ nvf.url = "github:notashelf/nvf/v0.7"; + # confine vpns to specific systemd services + vpn-confinement.url = "github:Maroka-chan/VPN-Confinement"; + # hypr* ecosystem hyprland.url = "github:hyprwm/hyprland"; From 4f20813139e2986da916939a0c4708be760e6171 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 28 Nov 2024 10:32:20 +1100 Subject: [PATCH 055/213] ooksmedia: use jellyfin drive --- hosts/ooksmedia/file-system.nix | 2 +- modules/nixos/server/services/media-server/options.nix | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hosts/ooksmedia/file-system.nix b/hosts/ooksmedia/file-system.nix index 4686100..9dfb8ed 100644 --- a/hosts/ooksmedia/file-system.nix +++ b/hosts/ooksmedia/file-system.nix @@ -24,7 +24,7 @@ device = "/dev/disk/by-uuid/B511-09E2"; fsType = "vfat"; }; - "/media-server" = { + "/jellyfin" = { device = "/dev/disk/by-label/jellyfin"; fsType = "btrfs"; }; diff --git a/modules/nixos/server/services/media-server/options.nix b/modules/nixos/server/services/media-server/options.nix index a9c89b3..61dbd1f 100644 --- a/modules/nixos/server/services/media-server/options.nix +++ b/modules/nixos/server/services/media-server/options.nix @@ -36,7 +36,7 @@ in { storage = { mediaRoot = mkOption { type = path; - default = "/media"; + default = "/jellyfin"; description = "Root directory for all media-related storage"; }; From 9459f9e1f68eb1c31f3c009268ad7d7f8f04ca14 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 30 Nov 2024 16:29:42 +1100 Subject: [PATCH 056/213] nixos: add server conditionals to network manager configuration ensure wifi mac address is static if host is a server --- modules/nixos/base/networking.nix | 20 +++++++-- outputs/lib/containers.nix | 67 +++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 outputs/lib/containers.nix diff --git a/modules/nixos/base/networking.nix b/modules/nixos/base/networking.nix index fa9bffe..9a9252c 100644 --- a/modules/nixos/base/networking.nix +++ b/modules/nixos/base/networking.nix @@ -1,5 +1,10 @@ -{lib, ...}: let +{ + lib, + config, + ... +}: let inherit (lib) mkForce mkDefault; + inherit (config.ooknet) host; in { networking = { enableIPv6 = true; @@ -15,8 +20,13 @@ in { dns = "systemd-resolved"; plugins = mkForce []; wifi = { - macAddress = "random"; - scanRandMacAddress = true; + # why does my server have wifi? not sure. + # ensure my mac addr is static so I can reserve an IP + macAddress = + if host.role == "server" + then "permanent" + else "random"; + scanRandMacAddress = host.role != "server"; powersave = true; }; unmanaged = ["interface-name:tailscale*"]; @@ -30,5 +40,7 @@ in { fallbackDns = ["8.8.8.8"]; # google dns }; }; - systemd.services.NetworkManager-wait-online.enable = false; + # sometimes causes issues with network manager service never actually starting + # requiring me to manually start the service. fine on a workstation, not on a server + systemd.services.NetworkManager-wait-online.enable = host.role != "server"; } diff --git a/outputs/lib/containers.nix b/outputs/lib/containers.nix new file mode 100644 index 0000000..829f800 --- /dev/null +++ b/outputs/lib/containers.nix @@ -0,0 +1,67 @@ +{lib, ...}: let + inherit (builtins) isBool; + inherit (lib) toUpper optionalAttrs mapAttrs' nameValuePair; + + # convert homepage attributes to labels + mkHomepageLabels = { + name, + domain, + group, + widget ? {}, + ... + } @ args: let + # common homepage labels + commonLabels = mapAttrs' (n: v: nameValuePair "homepage.${n}" (toString v)) { + inherit name group; + icon = "${name}.svg"; + href = domain; + description = args.description or name; + }; + + # process widget attributes, flattening them into label format + processWidget = attrs: + mapAttrs' (n: v: + nameValuePair "homepage.widget.${n}" ( + if isBool v + then + if v + then "true" + else "false" + else toString v + )) + attrs; + in + commonLabels // (processWidget widget); + + mkContainerLabels = {name, ...} @ args: let + homepage = args.homepage or {}; + baseWidget = homepage.widget or {}; + in + # traefik router labels + (optionalAttrs (args ? domain) { + "traefik.enable" = "true"; + "traefik.http.routers.${name}.rule" = "Host(`${args.domain}`)"; + "traefik.http.routers.${name}.entrypoints" = "websecure"; + "traefik.http.routers.${name}.tls" = "true"; + "traefik.http.routes.${name}.certresolver" = "cloudflare"; + }) + # traefik service labels + // (optionalAttrs ((args ? domain) && (args ? port)) { + "traefik.http.services.${name}.loadbalancer.server.port" = toString args.port; + }) + # homepage labels + // (optionalAttrs (args ? homepage) (mkHomepageLabels { + inherit name; + inherit (args) domain; + group = args.homepage.group or name; + widget = + baseWidget + // { + type = name; + url = args.domain; + key = "{{HOMEPAGE_FILE_${toUpper name}}}"; + }; + })); +in { + inherit mkContainerLabels; +} From 2d437acfbb6498f3e013a833a41da61a873e5e04 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 1 Dec 2024 18:35:22 +1100 Subject: [PATCH 057/213] ookflix: initial ookflix commit --- modules/nixos/server/options.nix | 2 +- modules/nixos/server/services/default.nix | 1 + .../nixos/server/services/ookflix/default.nix | 24 ++++ .../server/services/ookflix/jellyfin.nix | 60 ++++++++++ .../server/services/ookflix/jellyseer.nix | 32 +++++ modules/nixos/server/services/ookflix/lib.nix | 111 ++++++++++++++++++ .../nixos/server/services/ookflix/options.nix | 92 +++++++++++++++ .../nixos/server/services/ookflix/plex.nix | 66 +++++++++++ .../server/services/ookflix/tautulli.nix | 37 ++++++ .../nixos/server/services/ookflix/users.nix | 38 ++++++ outputs/lib/containers.nix | 23 +++- outputs/lib/default.nix | 2 + 12 files changed, 482 insertions(+), 6 deletions(-) create mode 100644 modules/nixos/server/services/ookflix/default.nix create mode 100644 modules/nixos/server/services/ookflix/jellyfin.nix create mode 100644 modules/nixos/server/services/ookflix/jellyseer.nix create mode 100644 modules/nixos/server/services/ookflix/lib.nix create mode 100644 modules/nixos/server/services/ookflix/options.nix create mode 100644 modules/nixos/server/services/ookflix/plex.nix create mode 100644 modules/nixos/server/services/ookflix/tautulli.nix create mode 100644 modules/nixos/server/services/ookflix/users.nix diff --git a/modules/nixos/server/options.nix b/modules/nixos/server/options.nix index 4de3252..06e8808 100644 --- a/modules/nixos/server/options.nix +++ b/modules/nixos/server/options.nix @@ -14,7 +14,7 @@ in { description = "The server profile the host will use as a base"; }; services = mkOption { - type = listOf (enum ["media-server" "website" "forgejo"]); + type = listOf (enum ["media-server" "website" "forgejo" "ookflix"]); default = []; description = "List of services the server will host"; }; diff --git a/modules/nixos/server/services/default.nix b/modules/nixos/server/services/default.nix index 7685461..468b980 100644 --- a/modules/nixos/server/services/default.nix +++ b/modules/nixos/server/services/default.nix @@ -3,5 +3,6 @@ ./website ./forgejo ./media-server + ./ookflix ]; } diff --git a/modules/nixos/server/services/ookflix/default.nix b/modules/nixos/server/services/ookflix/default.nix new file mode 100644 index 0000000..8b99d22 --- /dev/null +++ b/modules/nixos/server/services/ookflix/default.nix @@ -0,0 +1,24 @@ +{ + lib, + config, + ... +}: let + inherit (lib) elem mkIf; + inherit (config.ooknet.server) services; +in { + imports = [ + ./jellyfin.nix + ./plex.nix + ./options.nix + ]; + + config = mkIf (elem "ookflix" services) { + ooknet.server.ookflix = { + gpuAcceleration.enable = true; + services = { + jellyfin.enable = true; + plex.enable = true; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/jellyfin.nix b/modules/nixos/server/services/ookflix/jellyfin.nix new file mode 100644 index 0000000..cf6738f --- /dev/null +++ b/modules/nixos/server/services/ookflix/jellyfin.nix @@ -0,0 +1,60 @@ +{ + config, + lib, + ook, + ... +}: let + ookflixLib = import ./lib.nix {inherit lib config;}; + inherit (ookflixLib) mkServiceStateDir mkServiceUser; + inherit (lib) mkIf optionalAttrs; + inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; + inherit (config.ooknet.server.ookflix) volumes services groups gpuAcceleration; + inherit (config.ooknet.server.ookflix.services) jellyfin; +in { + config = mkIf services.jellyfin.enable { + hardware.nvidia-container-toolkit.enable = gpuAcceleration.enable && gpuAcceleration.type == "nvidia"; + users = mkServiceUser jellyfin.user.name; + systemd.tmpfiles = mkServiceStateDir "jellyfin" jellyfin.stateDir; + virtualisation.oci-containers.containers = { + # media streaming server + # docs: + jellyfin = { + image = "lscr.io/linuxserver/jellyfin:latest"; + autoStart = true; + hostname = "jellyfin"; + ports = [(mkContainerPort jellyfin.port)]; + volumes = [ + "${volumes.media.movies}:/data/movies" + "${volumes.media.tv}:/data/tv" + "${jellyfin.stateDir}:/config" + ]; + labels = mkContainerLabel { + name = "jellyfin"; + inherit (jellyfin) port domain; + homepage = { + group = "media"; + description = "media-server streamer"; + }; + }; + + extraOptions = optionalAttrs gpuAcceleration.enable ( + if gpuAcceleration.type == "nvidia" + then [ + "--runtime=nvidia" + ] + else if gpuAcceleration.type == "intel" || "amd" + then [ + "--device=/dev/dri:/dev/dri" + ] + else [] + ); + environment = + mkContainerEnvironment jellyfin.user.id groups.media.id + // {JELLYFIN_PublishedServerUrl = jellyfin.domain;} + // optionalAttrs (gpuAcceleration.enable && gpuAcceleration.type == "nvidia") { + NVIDIA_VISIBLE_DEVICES = "all"; + }; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/jellyseer.nix b/modules/nixos/server/services/ookflix/jellyseer.nix new file mode 100644 index 0000000..382c63d --- /dev/null +++ b/modules/nixos/server/services/ookflix/jellyseer.nix @@ -0,0 +1,32 @@ +{ + config, + lib, + ook, + ... +}: let + inherit (lib) mkIf; + inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; + inherit (config.ooknet.server.ookflix) storage groups; + inherit (config.ooknet.server.ookflix.services) jellyseer; +in { + config = mkIf jellyseer.enable { + # media requesting for jellyfin + jellyseer = { + image = "fallenbagel/jellyseerr:latest"; + autoStart = true; + hostname = "jellyseer"; + ports = [(mkContainerPort jellyseer.port)]; + volumes = ["${storage.state.jellyseer}:/config"]; + extraOptions = ["--network" "host"]; + labels = mkContainerLabel { + name = "jellyseer"; + inherit (jellyseer) domain port; + homepage = { + group = "media"; + description = "media-server requesting"; + }; + }; + environment = mkContainerEnvironment jellyseer.user.id groups.media.id; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/lib.nix b/modules/nixos/server/services/ookflix/lib.nix new file mode 100644 index 0000000..ba25024 --- /dev/null +++ b/modules/nixos/server/services/ookflix/lib.nix @@ -0,0 +1,111 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkOption mkEnableOption elem assertMsg; + inherit (builtins) attrValues; + inherit (lib.types) int path port str; + inherit (config.ooknet) server; + cfg = server.ookflix; + + mkSubdomainOption = name: description: example: + mkOption { + type = str; + default = "${name}.${server.domain}"; + inherit description example; + }; + + # check config.ids for static uid/gid based on service name, if available use that, if not, use fallback. + # check fallback doesnt conflict with existing static id + getId = idType: name: fallback: let + allNixosIds = attrValues config.ids.${idType}; + fallbackConflict = elem fallback allNixosIds; + in + mkOption { + type = int; + default = + config.ids.${idType}.${name} + or ( + assert assertMsg (!fallbackConflict) + "Fallback ${idType} ${toString fallback} for ${name} conflicts with NixOS static allocation"; fallback + ); + description = "${idType} of ${name} container"; + example = 224; + }; + + mkUserOption = name: fallback: { + name = mkOption { + type = str; + default = name; + description = "Name of ${name} container user"; + example = "${name}"; + }; + id = getId "uids" name fallback; + }; + + mkGroupOption = name: fallback: { + name = mkOption { + type = str; + default = name; + }; + id = getId "gids" name fallback; + }; + + mkPortOption = value: description: example: + mkOption { + type = port; + default = value; + inherit description example; + }; + + mkVolumeOption = type: pathValue: + mkOption { + type = path; + default = + if type == "state" + then "${cfg.volumes.state.root}/${pathValue}" + else if type == "media" + then "${cfg.volumes.media.root}/${pathValue}" + else if type == "downloads" + then "${cfg.volumes.downloads.root}/${pathValue}" + else if type == "root" + then pathValue + else throw "Invalid VolumeOption type: ${type}. Must be one of 'state' 'media' 'downloads' 'root'"; + }; + + mkServiceOptions = name: { + port, + gid, + uid, + ... + } @ args: { + enable = mkEnableOption "Enable ${name} container"; + port = mkPortOption args.port "Port for ${name} container." 80; + domain = mkSubdomainOption name "Domain for ${name} container." "${name}.mydomain.com"; + stateDir = mkVolumeOption "state" name; + user = mkUserOption name args.uid; + group = mkGroupOption name args.gid; + }; + mkServiceUser = service: { + users.${service} = { + isSystemUser = true; + uid = cfg.services.${service}.user.id; + name = service; + group = service; + }; + groups.${service} = { + gid = cfg.services.${service}.group.id; + name = service; + }; + }; + mkServiceStateDir = service: dir: { + settings."${service}StateDir".${dir}."d" = { + mode = "0700"; + user = cfg.services.${service}.user.name; + group = cfg.services.${service}.group.name; + }; + }; +in { + inherit mkServiceOptions mkServiceStateDir mkServiceUser mkUserOption mkPortOption mkGroupOption mkVolumeOption mkSubdomainOption; +} diff --git a/modules/nixos/server/services/ookflix/options.nix b/modules/nixos/server/services/ookflix/options.nix new file mode 100644 index 0000000..7cd5550 --- /dev/null +++ b/modules/nixos/server/services/ookflix/options.nix @@ -0,0 +1,92 @@ +{ + lib, + config, + ... +}: let + ookflixLib = import ./lib.nix {inherit lib config;}; + + inherit (ookflixLib) mkVolumeOption mkGroupOption mkServiceOptions; + inherit (lib) mkOption mkEnableOption; + inherit (lib.types) enum; + inherit (config.ooknet) server; + cfg = server.ookflix; +in { + options.ooknet.server.ookflix = { + enable = mkEnableOption "Enable ookflix a container based media server module"; + gpuAcceleration = { + enable = mkEnableOption "Enable GPU acceleration for video streamers"; + type = mkOption { + type = enum ["nvidia" "intel" "amd"]; + default = config.ooknet.hardware.gpu.type; + description = '' + What GPU type to use for GPU acceleration. + Defaults to system GPU type (ooknet.hardware.gpu.type) + ''; + }; + }; + volumes = { + state.root = mkVolumeOption "root" "/var/lib/ookflix"; + content.root = mkVolumeOption "root" "/jellyfin"; + downloads = { + root = mkVolumeOption "${cfg.content.root}/downloads"; + incomplete = mkVolumeOption "downloads" "incomplete"; + complete = mkVolumeOption "downloads" "complete"; + watch = mkVolumeOption "downloads" "watch"; + }; + + media = { + root = mkVolumeOption "root" "${cfg.volumes.content.root}/media"; + movies = mkVolumeOption "media" "movies"; + tv = mkVolumeOption "media" "tv"; + }; + }; + # Shared groups + groups = { + media = mkGroupOption "media" 992; + downloader = mkGroupOption "downloader" 981; + }; + + services = { + jellyfin = mkServiceOptions "jellyfin" { + port = 8096; + uid = 994; + gid = 994; + }; + plex = mkServiceOptions "plex" { + port = 32400; + uid = 195; + gid = 195; + }; + sonarr = mkServiceOptions "sonarr" { + port = 8989; + uid = 274; + gid = 274; + }; + radarr = mkServiceOptions "radarr" { + port = 7878; + uid = 275; + gid = 275; + }; + prowlarr = mkServiceOptions "prowlarr" { + port = 9696; + uid = 982; + gid = 987; + }; + transmission = mkServiceOptions "transmission" { + port = 9091; + uid = 70; + gid = 70; + }; + jellyseer = mkServiceOptions "jellyseer" { + port = 5055; + uid = 345; + gid = 345; + }; + tautulli = mkServiceOptions "tautulli" { + port = 8181; + uid = 355; + gid = 355; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/plex.nix b/modules/nixos/server/services/ookflix/plex.nix new file mode 100644 index 0000000..1bee37e --- /dev/null +++ b/modules/nixos/server/services/ookflix/plex.nix @@ -0,0 +1,66 @@ +{ + config, + lib, + ook, + ... +}: let + ookflixLib = import ./lib.nix {inherit lib config;}; + inherit (ookflixLib) mkServiceUser mkServiceStateDir; + inherit (lib) mkIf optionalAttrs; + inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; + inherit (config.ooknet.server.ookflix) gpuAcceleration services volumes groups; + inherit (config.ooknet.server.ookflix.services) plex; +in { + config = mkIf plex.enable { + # not sure if this is needed for podman + hardware.nvidia-container-toolkit.enable = gpuAcceleration.enable && gpuAcceleration.type == "nvidia"; + + # users/group/directories configuration, see lib.nix + users = mkServiceUser plex.user.name; + systemd.tmpfiles = mkServiceStateDir "plex" plex.stateDir; + + # container configuration + virtualisation.oci-containers.containers = { + # media streaming server + plex = { + image = "lscr.io/linuxserver/plex:latest"; + autoStart = true; + hostname = "plex"; + ports = [(mkContainerPort plex.port)]; + volumes = [ + "${volumes.media.movies}:/data/movies" + "${volumes.media.tv}:/data/tv" + "${plex.stateDir}:/config" + ]; + labels = mkContainerLabel { + name = "plex"; + inherit (plex) domain port; + homepage = { + group = "media"; + description = "media-server streamer"; + }; + }; + extraOptions = optionalAttrs gpuAcceleration.enable ( + if gpuAcceleration.type == "nvidia" + then [ + "--runtime=nvidia" + ] + else if gpuAcceleration.type == "intel" + then [ + "--device=/dev/dri:/dev/dri" + ] + else if gpuAcceleration.type == "amd" + then [ + "--device=/dev/dri:/dev/dri" + ] + else [] + ); + environment = + mkContainerEnvironment plex.user.id groups.media.id + // optionalAttrs (gpuAcceleration.enable && gpuAcceleration.type == "nvidia") { + NVIDIA_VISIBLE_DEVICES = "all"; + }; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/tautulli.nix b/modules/nixos/server/services/ookflix/tautulli.nix new file mode 100644 index 0000000..f99fad6 --- /dev/null +++ b/modules/nixos/server/services/ookflix/tautulli.nix @@ -0,0 +1,37 @@ +{ + config, + lib, + ook, + ... +}: let + ookflixLib = import ./lib.nix {inherit lib config;}; + inherit (ookflixLib) mkServiceUser mkServiceStateDir; + inherit (lib) mkIf; + inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; + inherit (config.ooknet.server.ookflix) groups; + inherit (config.ooknet.server.services) tautulli; +in { + config = mkIf tautulli.enable { + users = mkServiceUser tautulli.user.name; + systemd.tmpfiles = mkServiceStateDir "tautulli" tautulli.stateDir; + virtualisation.oci-containers.containers = { + # plex monitoring service + tautulli = { + image = "lscr.io/linuxserver/tautulli:latest"; + autoStart = true; + hostname = "tautulli"; + ports = [(mkContainerPort tautulli.port)]; + volumes = ["${tautulli.stateDir}:/config"]; + labels = mkContainerLabel { + name = "tautulli"; + inherit (tautulli) port domain; + homepage = { + group = "monitoring"; + description = "media-server monitoring"; + }; + }; + environment = mkContainerEnvironment tautulli.user.id groups.media.id; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/users.nix b/modules/nixos/server/services/ookflix/users.nix new file mode 100644 index 0000000..63790b0 --- /dev/null +++ b/modules/nixos/server/services/ookflix/users.nix @@ -0,0 +1,38 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkIf mkMerge; + inherit (builtins) mapAttrs; + inherit (config.ooknet.server) ookflix; + inherit (config.ooknet.server.ookflix) services storage users groups; + + mkServiceUser = name: user: { + isSystemUser = true; + group = groups.${name}.name; + uid = users.${name}.id; + home = storage.state.${name}; + }; + + generateUsers = mapAttrs mkServiceUser users; +in { + config = mkIf ookflix.enable { + users = { + users = mkMerge [ + # media service users + (mkIf services.jellyfin.enable { + ${users.jellyfin.name} = mkServiceUser users.jellyfin.name groups.media.name; + }) + (mkIf services.plex.enable { + ${users.plex.name} = mkServiceUser users.plex.name groups.media.name; + }) + (mkIf (services.jellyfin.enable || services.jellyseer.enable) { + ${users.jellyseer.name} = mkServiceUser users.jellyseer.name groups.media.name; + }) + ]; + groups = { + }; + }; + }; +} diff --git a/outputs/lib/containers.nix b/outputs/lib/containers.nix index 829f800..36c002d 100644 --- a/outputs/lib/containers.nix +++ b/outputs/lib/containers.nix @@ -1,4 +1,8 @@ -{lib, ...}: let +{ + lib, + config, + ... +}: let inherit (builtins) isBool; inherit (lib) toUpper optionalAttrs mapAttrs' nameValuePair; @@ -33,7 +37,7 @@ in commonLabels // (processWidget widget); - mkContainerLabels = {name, ...} @ args: let + mkContainerLabel = {name, ...} @ args: let homepage = args.homepage or {}; baseWidget = homepage.widget or {}; in @@ -52,16 +56,25 @@ # homepage labels // (optionalAttrs (args ? homepage) (mkHomepageLabels { inherit name; - inherit (args) domain; + domain = "https://${args.domain}"; group = args.homepage.group or name; widget = baseWidget // { type = name; - url = args.domain; + url = "https://${args.domain}"; key = "{{HOMEPAGE_FILE_${toUpper name}}}"; }; })); + + mkContainerEnvironment = user: group: { + PUID = toString user; + PGID = toString group; + # TODO: I dont want to hard code this + TZ = "Antarctica/Macquarie"; + }; + + mkContainerPort = port: "${toString port}:${toString port}"; in { - inherit mkContainerLabels; + inherit mkContainerLabel mkContainerEnvironment mkContainerPort; } diff --git a/outputs/lib/default.nix b/outputs/lib/default.nix index 42ee09f..4492913 100644 --- a/outputs/lib/default.nix +++ b/outputs/lib/default.nix @@ -2,6 +2,7 @@ lib, self, inputs, + config, ... }: let # my scuffed lib @@ -9,6 +10,7 @@ builders = import ./builders.nix {inherit self lib inputs;}; mkNeovim = import ./mkNeovim.nix {inherit inputs;}; math = import ./math.nix {inherit lib;}; + container = import ./containers.nix {inherit lib config;}; color = let check = import ./color/check.nix {inherit lib;}; types = import ./color/types.nix { From d0ca588ece4ce336deb122577b19829fdb3d1075 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 1 Dec 2024 18:35:29 +1100 Subject: [PATCH 058/213] flake: bump --- flake.lock | 120 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 90 insertions(+), 30 deletions(-) diff --git a/flake.lock b/flake.lock index 5880249..57d703d 100644 --- a/flake.lock +++ b/flake.lock @@ -100,11 +100,11 @@ }, "locked": { "dir": "pkgs/firefox-addons", - "lastModified": 1732161788, - "narHash": "sha256-ilkOtBbv5onnMOYnLWVpBd6bZHP3xwzagccBk1mW/z4=", + "lastModified": 1732790791, + "narHash": "sha256-bx+ljzcUpVOKqu6k/HJGvij8x/sdFYkehGP8oPVqqRY=", "owner": "rycee", "repo": "nur-expressions", - "rev": "3071fc96bc39e58df1c6d48e8008c96f09a00b42", + "rev": "ac70253fea187562c44006f32ad2b480997e0866", "type": "gitlab" }, "original": { @@ -285,11 +285,11 @@ ] }, "locked": { - "lastModified": 1732025103, - "narHash": "sha256-qjEI64RKvDxRyEarY0jTzrZMa8ebezh2DEZmJJrpVdo=", + "lastModified": 1732793095, + "narHash": "sha256-6TrknJ8CpvSSF4gviQSeD+wyj3siRcMvdBKhOXkEMKU=", "owner": "nix-community", "repo": "home-manager", - "rev": "a46e702093a5c46e192243edbd977d5749e7f294", + "rev": "2f7739d01080feb4549524e8f6927669b61c6ee3", "type": "github" }, "original": { @@ -327,6 +327,64 @@ "type": "github" } }, + "hyprgraphics": { + "inputs": { + "hyprutils": [ + "hyprlock", + "hyprutils" + ], + "nixpkgs": [ + "hyprlock", + "nixpkgs" + ], + "systems": [ + "hyprlock", + "systems" + ] + }, + "locked": { + "lastModified": 1732808127, + "narHash": "sha256-jwqYmLVfvoLPu8UScEzZgdbbiNU3ioYcrsthjEEnGqI=", + "owner": "hyprwm", + "repo": "hyprgraphics", + "rev": "4d927a52be7e15e0846456f2aa1b0ad76b5bf059", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprgraphics", + "type": "github" + } + }, + "hyprgraphics_2": { + "inputs": { + "hyprutils": [ + "hyprpaper", + "hyprutils" + ], + "nixpkgs": [ + "hyprpaper", + "nixpkgs" + ], + "systems": [ + "hyprpaper", + "systems" + ] + }, + "locked": { + "lastModified": 1732808127, + "narHash": "sha256-jwqYmLVfvoLPu8UScEzZgdbbiNU3ioYcrsthjEEnGqI=", + "owner": "hyprwm", + "repo": "hyprgraphics", + "rev": "4d927a52be7e15e0846456f2aa1b0ad76b5bf059", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprgraphics", + "type": "github" + } + }, "hypridle": { "inputs": { "hyprlang": [ @@ -374,11 +432,11 @@ "xdph": "xdph" }, "locked": { - "lastModified": 1732100541, - "narHash": "sha256-ryxqTo2N5EOwHjrDXCoVFKuG1ZKpoMlRmCjqqUhjQPU=", + "lastModified": 1732837919, + "narHash": "sha256-/GySPsuD3UpBLOpr0ZRteN2/zYmlAnrkfIZhvM32AvE=", "owner": "hyprwm", "repo": "hyprland", - "rev": "940f7aa990dbc99815bab8d355999d8277534b17", + "rev": "8f83d29f00bfa89d1e8fe94b4dda98fe898b6b0e", "type": "github" }, "original": { @@ -494,6 +552,7 @@ }, "hyprlock": { "inputs": { + "hyprgraphics": "hyprgraphics", "hyprlang": [ "hyprland", "hyprlang" @@ -512,11 +571,11 @@ ] }, "locked": { - "lastModified": 1732023353, - "narHash": "sha256-FbHP2io0nKSC0qEjTdAhrfmlqiv9oB1P/DcV3jFAnWY=", + "lastModified": 1732812191, + "narHash": "sha256-/gYMXqhjvOcjhaYjzb1iqjpoCDqO5lkkqjG93oMMo60=", "owner": "hyprwm", "repo": "hyprlock", - "rev": "578246b9967dec77c56993dc55ca192d35ba9bb7", + "rev": "4667f721be47ff6f5cf2a7ee64513f818fb764a0", "type": "github" }, "original": { @@ -527,6 +586,7 @@ }, "hyprpaper": { "inputs": { + "hyprgraphics": "hyprgraphics_2", "hyprlang": [ "hyprland", "hyprlang" @@ -546,11 +606,11 @@ ] }, "locked": { - "lastModified": 1729890887, - "narHash": "sha256-Vg98Dm6MaglEUNNTRgLF2Lxy02FrU5ntnlwsMkBSTKg=", + "lastModified": 1732809500, + "narHash": "sha256-CW4r78WhaHtFJN6L+heBztj02ucxthBPgUzFeUZ+yVw=", "owner": "hyprwm", "repo": "hyprpaper", - "rev": "3f8cc92109209364e9d39789b3631e9ac109987a", + "rev": "a3ceb20095c1fae9acb10c37713caf2df28f3ec9", "type": "github" }, "original": { @@ -719,11 +779,11 @@ ] }, "locked": { - "lastModified": 1731814505, - "narHash": "sha256-l9ryrx1Twh08a+gxrMGM9O/aZKEimZfa6sZVyPCImgI=", + "lastModified": 1732519917, + "narHash": "sha256-AGXhwHdJV0q/WNgqwrR2zriubLr785b02FphaBtyt1Q=", "owner": "nix-community", "repo": "nix-index-database", - "rev": "bdba246946fb079b87b4cada4df9b1cdf1c06132", + "rev": "f4a5ca5771ba9ca31ad24a62c8d511a405303436", "type": "github" }, "original": { @@ -818,11 +878,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1732014248, - "narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=", + "lastModified": 1732521221, + "narHash": "sha256-2ThgXBUXAE1oFsVATK1ZX9IjPcS4nKFOAjhPNKuiMn0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "23e89b7da85c3640bbc2173fe04f4bd114342367", + "rev": "4633a7c72337ea8fd23a4f2ba3972865e3ec685d", "type": "github" }, "original": { @@ -834,11 +894,11 @@ }, "nixpkgs_4": { "locked": { - "lastModified": 1730958623, - "narHash": "sha256-JwQZIGSYnRNOgDDoIgqKITrPVil+RMWHsZH1eE1VGN0=", + "lastModified": 1732617236, + "narHash": "sha256-PYkz6U0bSEaEB1al7O1XsqVNeSNS+s3NVclJw7YC43w=", "owner": "nixos", "repo": "nixpkgs", - "rev": "85f7e662eda4fa3a995556527c87b2524b691933", + "rev": "af51545ec9a44eadf3fe3547610a5cdd882bc34e", "type": "github" }, "original": { @@ -1023,11 +1083,11 @@ "systems": "systems_4" }, "locked": { - "lastModified": 1731920974, - "narHash": "sha256-7y5tGSntFAq82A8fv7N8R6BBEmyXBigCxRrSbxK+iMU=", + "lastModified": 1732835777, + "narHash": "sha256-srgGCL+4ZwY5Zf7jOIhSC/6S9kf32/Vu9EWMwX818io=", "owner": "notashelf", "repo": "nvf", - "rev": "b6785f8218bf8a9813881de421ef468b512d9cea", + "rev": "fee1b46924d34a5ba569f37dfd92a761ea373cf2", "type": "github" }, "original": { @@ -2637,11 +2697,11 @@ "plugin-rustaceanvim": { "flake": false, "locked": { - "lastModified": 1731172933, - "narHash": "sha256-B2AdSgGPANCBbVN+Sd7gvJ16ODZZwv4WSOxnRs3SWnk=", + "lastModified": 1732565373, + "narHash": "sha256-WRaNW0trZYEUKd05Uc+5nP+G81HI14d6lM7/WWz61E0=", "owner": "mrcjkb", "repo": "rustaceanvim", - "rev": "244443311f1c4e34ec1ea7f219a4b682b6ec066e", + "rev": "fee0aa094b0c9f93fffe5a385b3d5d2386c2b072", "type": "github" }, "original": { From eeb547269249ca776aad9aec32cf75d1fb33865d Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 1 Dec 2024 18:35:54 +1100 Subject: [PATCH 059/213] lib: pass ook arg to hosts via builder --- outputs/lib/builders.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/outputs/lib/builders.nix b/outputs/lib/builders.nix index 4c954a3..ae85425 100644 --- a/outputs/lib/builders.nix +++ b/outputs/lib/builders.nix @@ -7,7 +7,7 @@ inherit (inputs) nixpkgs; inherit (lib) singleton recursiveUpdate mkDefault; inherit (builtins) concatLists; - inherit (self) hozen keys; + inherit (self) hozen keys ook; hm = inputs.home-manager.nixosModules.home-manager; agenix = inputs.agenix.nixosModules.default; nixosModules = "${self}/modules/nixos"; @@ -44,7 +44,7 @@ mkNixos { specialArgs = recursiveUpdate { - inherit hozen keys lib inputs self inputs' self'; + inherit hozen ook keys lib inputs self inputs' self'; } specialArgs; modules = concatLists [ From 094a457045914b023b392dda06ff638ed6c29f82 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 2 Dec 2024 12:27:27 +1100 Subject: [PATCH 060/213] ooksmedia: enable ookflix --- hosts/ooksmedia/default.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hosts/ooksmedia/default.nix b/hosts/ooksmedia/default.nix index e1457bd..0dbc667 100644 --- a/hosts/ooksmedia/default.nix +++ b/hosts/ooksmedia/default.nix @@ -21,6 +21,15 @@ editor = "nvim"; multiplexer = "zellij"; }; + server = { + ookflix = { + gpuAcceleration.enable = true; + services = { + plex.enable = true; + jellyfin.enable = true; + }; + }; + }; }; boot.kernelPackages = pkgs.linuxPackages_xanmod_latest; From cf9a5b90bd6e21d568fce86c8f944dd0028dd375 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 2 Dec 2024 12:28:22 +1100 Subject: [PATCH 061/213] secrets: use full mullvad file path --- modules/nixos/base/secrets.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nixos/base/secrets.nix b/modules/nixos/base/secrets.nix index c6297e8..8de6673 100644 --- a/modules/nixos/base/secrets.nix +++ b/modules/nixos/base/secrets.nix @@ -36,7 +36,7 @@ in { owner = "${admin.name}"; group = "users"; }; - mullvad_wg = mkIf transmission.enable { + "mullvad_wg.conf" = mkIf transmission.enable { file = "${self}/secrets/mullvad_wg.age"; }; }; From eb1d01174dd8032b44929dc02b1bd86f28ab6bd7 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 2 Dec 2024 12:28:46 +1100 Subject: [PATCH 062/213] server: rework service based media server --- .../server/services/media-server/default.nix | 3 +++ .../server/services/media-server/jellyfin.nix | 3 ++- .../server/services/media-server/options.nix | 12 ++++++++++++ .../nixos/server/services/media-server/plex.nix | 3 ++- .../server/services/media-server/prowlarr.nix | 7 +++++-- .../server/services/media-server/radarr.nix | 5 +++-- .../server/services/media-server/sonarr.nix | 3 ++- .../services/media-server/transmission.nix | 3 +++ .../nixos/server/services/media-server/users.nix | 2 +- .../nixos/server/services/media-server/vpn.nix | 16 ++++++++++++++-- 10 files changed, 47 insertions(+), 10 deletions(-) diff --git a/modules/nixos/server/services/media-server/default.nix b/modules/nixos/server/services/media-server/default.nix index 2e17c8d..717e673 100644 --- a/modules/nixos/server/services/media-server/default.nix +++ b/modules/nixos/server/services/media-server/default.nix @@ -13,6 +13,9 @@ in { ./options.nix ./jellyfin.nix ./transmission.nix + ./sonarr.nix + ./radarr.nix + ./prowlarr.nix ./file-permissions.nix ./vpn.nix inputs.vpn-confinement.nixosModules.default diff --git a/modules/nixos/server/services/media-server/jellyfin.nix b/modules/nixos/server/services/media-server/jellyfin.nix index 8caf355..b8c6365 100644 --- a/modules/nixos/server/services/media-server/jellyfin.nix +++ b/modules/nixos/server/services/media-server/jellyfin.nix @@ -10,9 +10,10 @@ in { config = mkIf media-server.jellyfin.enable { services.jellyfin = { enable = true; - user = users.streamer; + user = users.jellyfin; group = groups.media; dataDir = storage.state.jellyfin; + openFirewall = true; }; ooknet.server.webserver.caddy.enable = true; services.caddy.virtualHosts."${domain.jellyfin}".extraConfig = proxy.jellyfin; diff --git a/modules/nixos/server/services/media-server/options.nix b/modules/nixos/server/services/media-server/options.nix index 61dbd1f..85dcc8b 100644 --- a/modules/nixos/server/services/media-server/options.nix +++ b/modules/nixos/server/services/media-server/options.nix @@ -113,6 +113,10 @@ in { type = path; default = "${cfg.storage.state.root}/sonarr"; }; + prowlarr = mkOption { + type = path; + default = "${cfg.storage.state.root}/prowlarr"; + }; radarr = mkOption { type = path; default = "${cfg.storage.state.root}/radarr"; @@ -129,6 +133,10 @@ in { type = str; default = "media"; }; + sonarr = mkOption { + type = str; + default = "sonarr"; + }; prowlarr = mkOption { type = str; default = "prowlarr"; @@ -152,6 +160,10 @@ in { type = str; default = "sonarr"; }; + radarr = mkOption { + type = str; + default = "radarr"; + }; transmission = mkOption { type = str; default = "transmission"; diff --git a/modules/nixos/server/services/media-server/plex.nix b/modules/nixos/server/services/media-server/plex.nix index 5c4bfb6..7770f8d 100644 --- a/modules/nixos/server/services/media-server/plex.nix +++ b/modules/nixos/server/services/media-server/plex.nix @@ -10,9 +10,10 @@ in { config = mkIf media-server.plex.enable { services.plex = { enable = true; - user = users.streamer; + user = users.plex; group = groups.media; dataDir = storage.state.plex; + openFirewall = true; }; ooknet.server.webserver.caddy.enable = true; services.caddy.virtualHosts."${domain.plex}".extraConfig = proxy.plex; diff --git a/modules/nixos/server/services/media-server/prowlarr.nix b/modules/nixos/server/services/media-server/prowlarr.nix index b4efd5c..ed59158 100644 --- a/modules/nixos/server/services/media-server/prowlarr.nix +++ b/modules/nixos/server/services/media-server/prowlarr.nix @@ -6,7 +6,7 @@ }: let inherit (lib) mkIf getExe; inherit (config.ooknet.server) media-server; - inherit (config.ooknet.server.media-server) storage users groups domain proxy; + inherit (config.ooknet.server.media-server) storage users groups domain proxy ports; in { config = mkIf media-server.prowlarr.enable { # we dont use the nixpkgs prowlarr service module because it lacks the option to @@ -16,6 +16,8 @@ in { users.users.prowlarr = { group = groups.prowlarr; home = storage.state.prowlarr; + uid = 293; + isSystemUser = true; }; users.groups.prowlarr = {}; @@ -36,12 +38,13 @@ in { }; tmpfiles.settings.prowlarrDirs = { "${storage.state.prowlarr}"."d" = { - mode = "700"; + mode = "0700"; user = users.prowlarr; group = groups.prowlarr; }; }; }; + networking.firewall.allowedTCPPorts = [ports.prowlarr]; ooknet.server.webserver.caddy.enable = true; services.caddy.virtualHosts."${domain.prowlarr}".extraConfig = proxy.prowlarr; }; diff --git a/modules/nixos/server/services/media-server/radarr.nix b/modules/nixos/server/services/media-server/radarr.nix index beb5784..a523c0a 100644 --- a/modules/nixos/server/services/media-server/radarr.nix +++ b/modules/nixos/server/services/media-server/radarr.nix @@ -11,8 +11,9 @@ in { services.radarr = { enable = true; user = users.radarr; - group = groups.radarr; - dataDir = storage.state.radaar; + group = groups.media; + dataDir = storage.state.radarr; + openFirewall = true; }; ooknet.server.webserver.caddy.enable = true; services.caddy.virtualHosts."${domain.radarr}".extraConfig = proxy.radarr; diff --git a/modules/nixos/server/services/media-server/sonarr.nix b/modules/nixos/server/services/media-server/sonarr.nix index be42fde..cfa06bc 100644 --- a/modules/nixos/server/services/media-server/sonarr.nix +++ b/modules/nixos/server/services/media-server/sonarr.nix @@ -11,8 +11,9 @@ in { services.sonarr = { enable = true; user = users.sonarr; - group = groups.sonarr; + group = groups.media; dataDir = storage.state.sonarr; + openFirewall = true; }; ooknet.server.webserver.caddy.enable = true; services.caddy.virtualHosts."${domain.sonarr}".extraConfig = proxy.sonarr; diff --git a/modules/nixos/server/services/media-server/transmission.nix b/modules/nixos/server/services/media-server/transmission.nix index 7999a19..1035024 100644 --- a/modules/nixos/server/services/media-server/transmission.nix +++ b/modules/nixos/server/services/media-server/transmission.nix @@ -40,6 +40,7 @@ in { incomplete-dir = storage.downloads.incomplete; watch-dir = storage.downloads.watch; + rpc-authentication-required = false; # rpc settings # rpc is how we connect to the service remotely rpc-port = ports.transmission.web; @@ -54,6 +55,8 @@ in { "10.*" ]; + rpc-bind-address = "192.168.15.1"; + # basic anti bruteforce protection anti-brute-force-enabled = true; diff --git a/modules/nixos/server/services/media-server/users.nix b/modules/nixos/server/services/media-server/users.nix index b7ec424..04e1cf4 100644 --- a/modules/nixos/server/services/media-server/users.nix +++ b/modules/nixos/server/services/media-server/users.nix @@ -18,7 +18,7 @@ in { isSystemUser = true; group = "downloader"; }; - steamer = { + streamer = { isSystemUser = true; group = "streamer"; }; diff --git a/modules/nixos/server/services/media-server/vpn.nix b/modules/nixos/server/services/media-server/vpn.nix index 7724a97..512b354 100644 --- a/modules/nixos/server/services/media-server/vpn.nix +++ b/modules/nixos/server/services/media-server/vpn.nix @@ -1,18 +1,23 @@ { config, lib, + pkgs, ... }: let inherit (lib) mkIf; inherit (config.ooknet.server.media-server) ports transmission; inherit (config.age) secrets; + inherit (builtins) attrValues; in { config = mkIf transmission.enable { + environment.systemPackages = attrValues { + inherit (pkgs) wireguard-tools dnsutils; + }; vpnNamespaces.wg = { enable = true; - wireguardConfigFile = secrets.mullvad_wg.path; + wireguardConfigFile = secrets."mullvad_wg.conf".path; accessibleFrom = [ - "192.168.0.1/24" + "192.168.20.0/24" "127.0.0.1" "10.0.0.0/8" ]; @@ -35,5 +40,12 @@ in { enable = true; vpnNamespace = "wg"; }; + systemd.services.wg = { + serviceConfig = { + LogLevelMax = "debug"; + StandardOutput = "journal"; + StandardError = "journal"; + }; + }; }; } From 4a2c8ccb39dbf2a0e9ff138f28044a5d9e16460d Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 2 Dec 2024 12:29:09 +1100 Subject: [PATCH 063/213] hosts: enable ookflix service on ooksmedia --- outputs/hosts/servers.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/outputs/hosts/servers.nix b/outputs/hosts/servers.nix index 7df15e8..842629d 100644 --- a/outputs/hosts/servers.nix +++ b/outputs/hosts/servers.nix @@ -21,7 +21,7 @@ in { hostname = "ooksmedia"; domain = "ooknet.org"; type = "desktop"; - services = ["media-server"]; + services = ["ookflix"]; }; }; } From 8b8725d90746e0991671020670cee443ca8ffce5 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 2 Dec 2024 12:29:40 +1100 Subject: [PATCH 064/213] secrets: add container secret --- secrets/containers/vpn_env.age | 19 +++++++++++++++++++ secrets/mullvad_wg.age | Bin 1269 -> 1232 bytes secrets/secrets.nix | 1 + 3 files changed, 20 insertions(+) create mode 100644 secrets/containers/vpn_env.age diff --git a/secrets/containers/vpn_env.age b/secrets/containers/vpn_env.age new file mode 100644 index 0000000..80210af --- /dev/null +++ b/secrets/containers/vpn_env.age @@ -0,0 +1,19 @@ +age-encryption.org/v1 +-> ssh-ed25519 xeHnUA t/GzdkZAfIM46D8K/MmzZtvB51U3NfjFksCCENhvAX8 +zmCGfHEZ1JHxbPLwyd/VGowcQAbdfKc9ASRvw5Gdfi8 +-> ssh-ed25519 6HvatA sqd0vyRWfz6vV7ereuLTBWMGxUhWTTNJmfjzCXnML1Q +gG4jf3kYNzXhcpRJq6thZ0cBSJrkppWe3KO9APa7Tc0 +-> ssh-ed25519 3DwG4w HcdgYvmRCsmHPngkCK10PsRhCkfX3OGXu/bJfhw8HA8 +P8oLKZ3zV5hyOtoyZq7E2mGLaDicPuyhiPClGm2A7XM +-> ssh-ed25519 Nn8WxA OknLb2rhzMKYJGWZF3qRYFWLJL5jW5mpBQrkSpioHU0 +J89ya3IQtPLKptL/DndLEsSnrMbGUE9Ahi6ZYA5LhXU +-> ssh-ed25519 Gd+9pg JkWdMNgg7IupAZgy0QZuxcJRr1iS5XaIuCngMOGcnXw +42iWjprOaIUf/BIRPsYCDnH1MT+ZqI2MjKNZz5MQA7E +-> ssh-ed25519 eMj+Jg X3CqdmUT6teNce23WM1VVmoy4MZwvMEIM3VWMpUKpnw +EBGc2tCbDDBv3wd3TNx+0Vt1qHejn46hvcAkmnGDU5o +-> ssh-ed25519 MQ/7Ew DhGlz2Nl8DBOdKBYar7zgN1kN8e/3tx5A2TttORKERA +hRea+js9SLhIEHjHoV9uShkg0AOHv8Nn2A4Pov7TptE +-> ssh-ed25519 3DwG4w hlL4Da/b3O6Z7dy1jsBgUdFM6V83nFLHn2qkreVu3jc +rPhGlPDW1BljDCMndoZ0npNaxlMGXE6WZMJy6jNiRZQ +--- LuJ/39ug9nTaBvpTKjGlS3WwLDjaFyF+TYiiSt5nCUg +\Xw p(a#&}YT r#$|2ogSmF%"HfdV#xi 28%l3IJTz)A0:Jމ7+A~wWߐƹ=m#(aXƵ11F"mr5t1V_R 80Q~b6L+ \ No newline at end of file diff --git a/secrets/mullvad_wg.age b/secrets/mullvad_wg.age index 24eeed77f2ee33f4ce3b5a47c724c5c01f8ca106..0c86499e9af1f4167f61364512758322f4c37554 100644 GIT binary patch delta 1125 zcmey$d4Y3+PJME!Sw?!4r=O*FURiKOg@}cxT3B{fg`=ZqzL{T;E0?aFLUD11 zZfc5=si~o*f|*BIVu_=Ic~V-IwwHE}aaE{WT0lyulUr~=v0G5GSzd0WMX_t4uSH5g zNPdyOQKnNUS9XABxkpuUgubs|MtORXbCPAUqgg?4kxNi{d0KgXRiZ(tw^4d>YNUbd z#E%kTrH)Z~m3bu@iAGuF+1aiIp6NNh+6Dpn+JXKV#`>xHL7ut(5ndS{6`ouXm1+4# z`MCz>?nR|#DIw0<`u_PIQ57x*A^wTQ$)%xL8TrX2dC3Ka29A^C870E}OMMGX!ksGe zJp6*H$^(52(+i!=jnmUI1H#PQDm+5Va!p)3EF3f4%elPFTzslrOe!P2LrUB{wf!Q@ zl8nux3cd2f4NJ@_gG>TleBE7Lv?H9&11Fzl6t6c9FY~JK2sO^lGYzRIEUI)fj!Ml> zGYUv^Nh@}$@-R0v^DqrJ&Ck{j&E~4~Gc)w`4loH0i|{NoPuC9fPcBH$b}WfXGj}m@ ztTHWg3UxM5HqS9mOGXd>RNpLZuXF{!VrRF=u&Ro}Dx(6YwE+C&0WhCB0c;I91ShJ5~Gqra`TFc0)w<&i#*L7GrdZ(&7Jg1oGeWp zb1h6lb4qeOxg33sJX1nTTr={`!Xgq)oQi|WvqRk6BeOG;a|1&?3QCGA9aB9cb0VA! zCVmvJuZT4D@V4{{@;1xJO^Gxs$#9D_DG5z4_Hy=1vMdPCD>jWN%FJ+bG>!1(Dsc)3 zE^%}zNvX<EH4Sn_R)3?ch9j13$rZF%JfR-($&>f2y~9}%J<6+ zcPVl5Nh+|c$_Via%_`S7PRR}laxTsC%68SR4|6jzsSI>X=8`wobq?PvRGDqG<(zYe zEl)(dyytqo#4wPl;s<3dxx0jq=e|F{TeAPod1v(( z=IpbY8s;4H+xWNW>y3lwtK>ddsP!BF6T9~Fv;D=I?I%TJerXj>-P*TfgV5=-=S+8R z@9R3fqN+Js`unk)Ju4>{i*q0QD_hkcw^C7K#%W98b)P`IU2mPJL2VN^p8=W`KXHb6BZIWNE&Sds=y3zO%lmd$Cb&aj>UN7c}a>zieXW@TY*!RMTkY{ z#E%kT?x{YZsa_tI?h$^*7KT-(W~qV3miftLL54=Tu3pYLMWNZ29!`d4IiXy6fsPjL zq3M3b<>kI4c1v|jj0kkIur!KHt4hkv4^MPW3M$GnD6A@TPbmw}H8FMf z)ep`HkI2a83aWI`4oGu$b90YKbuTq3DGqRV_tf^tH#M^GvMlrW@Gm#>aVZTA_DV0G z_))yxJ-IZ%z|g=lEx^k=)mz`p#4N+KDBY1uS65fT*D^P!xHKg# zC9=pZ#MiCTEhOKoIMCG7PutZXsU$JQHL|SU+s`C3Gep7h7$L$tWK7n*0z70U51Xb|Mc(MGEMKR&bwsBYQZ)!Kg?V_ zz~t#hmipYwJH@!qRX=NRlv&8xzDsYj_EGu6pI8;Qh?}rhpD$q9d}`mHfWj#uA}TxH zE*CAGk!SpV{rB~i8~uMTnI7UBeEnd@{`a>NZIW_VuiW;%2%tuOGci%m@PG}F$)h~-$y<#&M*!OBaZ^@k-lsn1Z zWzXx1O9wW&PwYO!Gr4-LT+}+oMA3sz?ZUH{_&loHAuU%LwD(G6L1g5iX>|$A8Oam( P3YO^DJG{&G5}yD7F^sGt diff --git a/secrets/secrets.nix b/secrets/secrets.nix index bafebbb..0a0a933 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -7,4 +7,5 @@ in { "spotify_key.age".publicKeys = [users.ooks] ++ workstations; "ooknet_org.age".publicKeys = [users.ooks] ++ workstations; "mullvad_wg.age".publicKeys = [users.ooks] ++ workstations ++ servers; + "containers/vpn_env.age".publicKeys = [users.ooks] ++ workstations ++ servers; } From 7da5a6a4a6052ee710571592f3d78bbed085cbc4 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 2 Dec 2024 12:29:53 +1100 Subject: [PATCH 065/213] winlab: init --- .../virtualization/winlab/default.nix | 5 ++++ .../virtualization/winlab/networking.nix | 30 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 modules/nixos/workstation/virtualization/winlab/default.nix create mode 100644 modules/nixos/workstation/virtualization/winlab/networking.nix diff --git a/modules/nixos/workstation/virtualization/winlab/default.nix b/modules/nixos/workstation/virtualization/winlab/default.nix new file mode 100644 index 0000000..3bc3069 --- /dev/null +++ b/modules/nixos/workstation/virtualization/winlab/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./networking.nix + ]; +} diff --git a/modules/nixos/workstation/virtualization/winlab/networking.nix b/modules/nixos/workstation/virtualization/winlab/networking.nix new file mode 100644 index 0000000..c16ce65 --- /dev/null +++ b/modules/nixos/workstation/virtualization/winlab/networking.nix @@ -0,0 +1,30 @@ +{ + pkgs, + lib, + config, + ... +}: let + inherit (lib) mkIf elem; + inherit (config.ooknet.workstation) profiles; + winlabNetwork = pkgs.writeText "winlab-network.xml" '' + + winlab-network + fed01297-b97b-49b0-beeb-8f30bc472017 + + + + + + + + + + + ''; +in { + config = mkIf (elem "virtualization" profiles) { + systemd.tmpfiles.settings.qemuNetworks."/var/lib/libvirt/qemu/networks/winlab-network.xml"."f" = { + argument = winlabNetwork; + }; + }; +} From 4ee2e2a877e81e552ce650366579ef44c14dc150 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 2 Dec 2024 12:30:13 +1100 Subject: [PATCH 066/213] ookflix: add gluetun --- .../nixos/server/services/ookflix/gluetun.nix | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 modules/nixos/server/services/ookflix/gluetun.nix diff --git a/modules/nixos/server/services/ookflix/gluetun.nix b/modules/nixos/server/services/ookflix/gluetun.nix new file mode 100644 index 0000000..3f5fb84 --- /dev/null +++ b/modules/nixos/server/services/ookflix/gluetun.nix @@ -0,0 +1,39 @@ +{ + config, + lib, + ook, + self, + ... +}: let + ookflixLib = import ./lib.nix {inherit self lib config;}; + inherit (ookflixLib) mkServiceUser; + inherit (lib) mkIf; + inherit (ook.lib.container) mkContainerEnvironment mkContainerPort mkServiceSecret; + inherit (config.ooknet.server.ookflix.services) transmission gluetun; +in { + config = mkIf gluetun.enable { + users = mkServiceUser gluetun.user.name; + age.secrets.vpn_env = mkServiceSecret "vpn_env" "gluetun"; + virtualisation.oci-containers.containers = { + # vpn container + gluetun = mkIf { + image = "qmcgaw/gluetun:latest"; + # should make this an option. + environmentFiles = [config.age.secrets.vpn_env.path]; + ports = [ + (mkContainerPort transmission.port) + ]; + environment = mkContainerEnvironment gluetun.user.id gluetun.group.id { + VPN_SERVICE_PROVIDER = gluetun.provider; + VPN_TYPE = "wireguard"; + }; + extraOptions = [ + # give network admin permissions + "--cap-add=NET_ADMIN" + # pass the network tunnel device + "--device=/dev/net/tun" + ]; + }; + }; + }; +} From 79a37fa8eb29c1097d656b5b5f99f2c162d47af4 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 2 Dec 2024 12:30:30 +1100 Subject: [PATCH 067/213] ookflix: add containers --- .../nixos/server/services/ookflix/default.nix | 10 +++ .../server/services/ookflix/jellyfin.nix | 8 +-- .../server/services/ookflix/jellyseer.nix | 32 ++++----- modules/nixos/server/services/ookflix/lib.nix | 19 +++++- .../nixos/server/services/ookflix/options.nix | 20 ++++-- .../nixos/server/services/ookflix/plex.nix | 3 +- .../server/services/ookflix/prowlarr.nix | 42 ++++++++++++ .../nixos/server/services/ookflix/radarr.nix | 41 ++++++++++++ .../nixos/server/services/ookflix/shared.nix | 66 +++++++++++++++++++ .../nixos/server/services/ookflix/sonarr.nix | 44 +++++++++++++ .../server/services/ookflix/tautulli.nix | 5 +- .../server/services/ookflix/transmission.nix | 43 ++++++++++++ .../nixos/server/services/ookflix/users.nix | 38 ----------- 13 files changed, 303 insertions(+), 68 deletions(-) create mode 100644 modules/nixos/server/services/ookflix/prowlarr.nix create mode 100644 modules/nixos/server/services/ookflix/radarr.nix create mode 100644 modules/nixos/server/services/ookflix/shared.nix create mode 100644 modules/nixos/server/services/ookflix/sonarr.nix create mode 100644 modules/nixos/server/services/ookflix/transmission.nix delete mode 100644 modules/nixos/server/services/ookflix/users.nix diff --git a/modules/nixos/server/services/ookflix/default.nix b/modules/nixos/server/services/ookflix/default.nix index 8b99d22..f14c124 100644 --- a/modules/nixos/server/services/ookflix/default.nix +++ b/modules/nixos/server/services/ookflix/default.nix @@ -9,6 +9,14 @@ in { imports = [ ./jellyfin.nix ./plex.nix + ./jellyseer.nix + ./tautulli.nix + ./sonarr.nix + ./prowlarr.nix + ./gluetun.nix + ./transmission.nix + ./shared.nix + ./options.nix ]; @@ -18,6 +26,8 @@ in { services = { jellyfin.enable = true; plex.enable = true; + jellyseer.enable = true; + tautulli.enable = true; }; }; }; diff --git a/modules/nixos/server/services/ookflix/jellyfin.nix b/modules/nixos/server/services/ookflix/jellyfin.nix index cf6738f..0692b0e 100644 --- a/modules/nixos/server/services/ookflix/jellyfin.nix +++ b/modules/nixos/server/services/ookflix/jellyfin.nix @@ -2,9 +2,10 @@ config, lib, ook, + self, ... }: let - ookflixLib = import ./lib.nix {inherit lib config;}; + ookflixLib = import ./lib.nix {inherit lib config self;}; inherit (ookflixLib) mkServiceStateDir mkServiceUser; inherit (lib) mkIf optionalAttrs; inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; @@ -22,10 +23,9 @@ in { image = "lscr.io/linuxserver/jellyfin:latest"; autoStart = true; hostname = "jellyfin"; - ports = [(mkContainerPort jellyfin.port)]; + ports = ["${jellyfin.port}:${jellyfin.port}"]; volumes = [ - "${volumes.media.movies}:/data/movies" - "${volumes.media.tv}:/data/tv" + "${volumes.media.root}:/data" "${jellyfin.stateDir}:/config" ]; labels = mkContainerLabel { diff --git a/modules/nixos/server/services/ookflix/jellyseer.nix b/modules/nixos/server/services/ookflix/jellyseer.nix index 382c63d..c0cf5f3 100644 --- a/modules/nixos/server/services/ookflix/jellyseer.nix +++ b/modules/nixos/server/services/ookflix/jellyseer.nix @@ -6,27 +6,29 @@ }: let inherit (lib) mkIf; inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; - inherit (config.ooknet.server.ookflix) storage groups; + inherit (config.ooknet.server.ookflix) groups; inherit (config.ooknet.server.ookflix.services) jellyseer; in { config = mkIf jellyseer.enable { # media requesting for jellyfin - jellyseer = { - image = "fallenbagel/jellyseerr:latest"; - autoStart = true; - hostname = "jellyseer"; - ports = [(mkContainerPort jellyseer.port)]; - volumes = ["${storage.state.jellyseer}:/config"]; - extraOptions = ["--network" "host"]; - labels = mkContainerLabel { - name = "jellyseer"; - inherit (jellyseer) domain port; - homepage = { - group = "media"; - description = "media-server requesting"; + virtualisation.oci-containers.containers = { + jellyseer = { + image = "fallenbagel/jellyseerr:latest"; + autoStart = true; + hostname = "jellyseer"; + ports = [(mkContainerPort jellyseer.port)]; + volumes = ["${jellyseer.stateDir}:/config"]; + extraOptions = ["--network" "host"]; + labels = mkContainerLabel { + name = "jellyseer"; + inherit (jellyseer) domain port; + homepage = { + group = "media"; + description = "media-server requesting"; + }; }; + environment = mkContainerEnvironment jellyseer.user.id groups.media.id; }; - environment = mkContainerEnvironment jellyseer.user.id groups.media.id; }; }; } diff --git a/modules/nixos/server/services/ookflix/lib.nix b/modules/nixos/server/services/ookflix/lib.nix index ba25024..6cc065d 100644 --- a/modules/nixos/server/services/ookflix/lib.nix +++ b/modules/nixos/server/services/ookflix/lib.nix @@ -1,6 +1,7 @@ { lib, config, + self, ... }: let inherit (lib) mkOption mkEnableOption elem assertMsg; @@ -87,6 +88,15 @@ user = mkUserOption name args.uid; group = mkGroupOption name args.gid; }; + mkBasicServiceOptions = name: { + gid, + uid, + ... + } @ args: { + enable = mkEnableOption "Enable ${name} container"; + user = mkUserOption name args.uid; + group = mkGroupOption name args.gid; + }; mkServiceUser = service: { users.${service} = { isSystemUser = true; @@ -106,6 +116,13 @@ group = cfg.services.${service}.group.name; }; }; + mkServiceSecret = name: service: { + ${name} = { + file = "${self}/secrets/container/${name}.age"; + owner = cfg.services.${service}.user.name; + group = cfg.services.${service}.group.name; + }; + }; in { - inherit mkServiceOptions mkServiceStateDir mkServiceUser mkUserOption mkPortOption mkGroupOption mkVolumeOption mkSubdomainOption; + inherit mkServiceSecret mkBasicServiceOptions mkServiceOptions mkServiceStateDir mkServiceUser mkUserOption mkPortOption mkGroupOption mkVolumeOption mkSubdomainOption; } diff --git a/modules/nixos/server/services/ookflix/options.nix b/modules/nixos/server/services/ookflix/options.nix index 7cd5550..8d0637b 100644 --- a/modules/nixos/server/services/ookflix/options.nix +++ b/modules/nixos/server/services/ookflix/options.nix @@ -1,11 +1,12 @@ { lib, config, + self, ... }: let - ookflixLib = import ./lib.nix {inherit lib config;}; + ookflixLib = import ./lib.nix {inherit lib config self;}; - inherit (ookflixLib) mkVolumeOption mkGroupOption mkServiceOptions; + inherit (ookflixLib) mkVolumeOption mkGroupOption mkServiceOptions mkBasicServiceOptions; inherit (lib) mkOption mkEnableOption; inherit (lib.types) enum; inherit (config.ooknet) server; @@ -26,24 +27,25 @@ in { }; volumes = { state.root = mkVolumeOption "root" "/var/lib/ookflix"; - content.root = mkVolumeOption "root" "/jellyfin"; + data.root = mkVolumeOption "root" "/jellyfin"; downloads = { root = mkVolumeOption "${cfg.content.root}/downloads"; - incomplete = mkVolumeOption "downloads" "incomplete"; - complete = mkVolumeOption "downloads" "complete"; - watch = mkVolumeOption "downloads" "watch"; + tv = mkVolumeOption "downloads" "tv"; + movies = mkVolumeOption "downloads" "movies"; + books = mkVolumeOption "downloads" "books"; }; media = { root = mkVolumeOption "root" "${cfg.volumes.content.root}/media"; movies = mkVolumeOption "media" "movies"; tv = mkVolumeOption "media" "tv"; + books = mkVolumeOption "media" "books"; }; }; # Shared groups groups = { media = mkGroupOption "media" 992; - downloader = mkGroupOption "downloader" 981; + downloads = mkGroupOption "downloader" 981; }; services = { @@ -87,6 +89,10 @@ in { uid = 355; gid = 355; }; + gluetun = mkBasicServiceOptions "gluetun" { + uid = 356; + gid = 357; + }; }; }; } diff --git a/modules/nixos/server/services/ookflix/plex.nix b/modules/nixos/server/services/ookflix/plex.nix index 1bee37e..7353e97 100644 --- a/modules/nixos/server/services/ookflix/plex.nix +++ b/modules/nixos/server/services/ookflix/plex.nix @@ -2,9 +2,10 @@ config, lib, ook, + self, ... }: let - ookflixLib = import ./lib.nix {inherit lib config;}; + ookflixLib = import ./lib.nix {inherit lib config self;}; inherit (ookflixLib) mkServiceUser mkServiceStateDir; inherit (lib) mkIf optionalAttrs; inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; diff --git a/modules/nixos/server/services/ookflix/prowlarr.nix b/modules/nixos/server/services/ookflix/prowlarr.nix new file mode 100644 index 0000000..ca8e5ed --- /dev/null +++ b/modules/nixos/server/services/ookflix/prowlarr.nix @@ -0,0 +1,42 @@ +{ + config, + lib, + ook, + self, + ... +}: let + ookflixLib = import ./lib.nix {inherit lib config self;}; + inherit (ookflixLib) mkServiceUser mkServiceStateDir; + inherit (lib) mkIf; + inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; + inherit (config.ooknet.server.ookflix) groups; + inherit (config.ooknet.server.ookflix.services) prowlarr; +in { + config = mkIf prowlarr.enable { + users = mkServiceUser prowlarr.user.name; + systemd.tmpfiles = mkServiceStateDir "prowlarr" prowlarr.stateDir; + virtualisation.oci-containers.containers = { + prowlarr = { + image = "lscr.io/linuxserver/prowlarr:latest"; + autoStart = true; + hostname = "prowlarr"; + ports = [(mkContainerPort prowlarr.port)]; + volumes = ["${prowlarr.stateDir}:/config"]; + extraOptions = ["--network" "host"]; + labels = mkContainerLabel { + name = "prowlarr"; + inherit (prowlarr) port domain; + homepage = { + group = "arr"; + description = "media-server indexer"; + }; + }; + environment = + mkContainerEnvironment prowlarr.user.id groups.media.id + // { + UMASK = "002"; + }; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/radarr.nix b/modules/nixos/server/services/ookflix/radarr.nix new file mode 100644 index 0000000..d478631 --- /dev/null +++ b/modules/nixos/server/services/ookflix/radarr.nix @@ -0,0 +1,41 @@ +{ + config, + lib, + ook, + self, + ... +}: let + ookflixLib = import ./lib.nix {inherit lib config self;}; + inherit (ookflixLib) mkServiceUser mkServiceStateDir; + inherit (lib) mkIf; + inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment; + inherit (config.ooknet.server.ookflix) groups volumes; + inherit (config.ooknet.server.ookflix.services) radarr; +in { + config = mkIf radarr.enable { + users = mkServiceUser radarr.user.name; + systemd.tmpfiles = mkServiceStateDir "radarr" radarr.stateDir; + virtualisation.oci-containers.containers = { + radarr = { + image = "ghcr.io/hotio/qbittorrent"; + autoStart = true; + hostname = "radarr"; + ports = ["${radarr.port}:${radarr.port}"]; + volumes = [ + "${radarr.stateDir}:/config" + "${volumes.data.root}:/data" + ]; + extraOptions = ["--network" "host"]; + labels = mkContainerLabel { + name = "radarr"; + inherit (radarr) port domain; + homepage = { + group = "arr"; + description = "media-server movies downloader"; + }; + }; + environment = mkContainerEnvironment radarr.user.id groups.media.id; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/shared.nix b/modules/nixos/server/services/ookflix/shared.nix new file mode 100644 index 0000000..87a5117 --- /dev/null +++ b/modules/nixos/server/services/ookflix/shared.nix @@ -0,0 +1,66 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkIf; + inherit (config.ooknet.host) admin; + inherit (config.ooknet.server) ookflix; + inherit (config.ooknet.server.ookflix) volumes groups; + inherit (config.ooknet.server.ookflix.services) jellyfin plex sonarr radarr prowlarr transmission; + mediaDirPermissions = { + mode = "0775"; + user = admin.name; + group = groups.media.name; + }; + downloadDirPermissions = { + mode = "0770"; + user = admin.name; + group = groups.downloads.name; + }; + ifTheyExist = users: builtins.filter (user: builtins.hasAttr user config.users.users) users; +in { + config = mkIf ookflix.enable { + users.groups = { + ${groups.media.name} = { + inherit (groups.media) name gid; + members = ifTheyExist [ + jellyfin.user.name + plex.user.name + sonarr.user.name + radarr.user.name + prowlarr.user.name + ]; + }; + ${groups.downloads.name} = { + inherit (groups.downloads) name gid; + members = ifTheyExist [ + sonarr.user.name + radarr.user.name + prowlarr.user.name + transmission.user.name + ]; + }; + }; + systemd.tmpfiles.settings = { + contentRoot = { + "${volumes.content.root}"."d" = { + mode = "0775"; + user = "root"; + group = "root"; + }; + }; + mediaDirectories = { + "${volumes.media.root}"."d" = mediaDirPermissions; + "${volumes.media.tv}"."d" = mediaDirPermissions; + "${volumes.media.movies}"."d" = mediaDirPermissions; + }; + downloadDirectories = { + "${volumes.downloads.root}"."d" = downloadDirPermissions; + "${volumes.downloads.complete}"."d" = downloadDirPermissions; + "${volumes.downloads.incomplete}"."d" = downloadDirPermissions; + "${volumes.downloads.watch}"."d" = downloadDirPermissions; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/sonarr.nix b/modules/nixos/server/services/ookflix/sonarr.nix new file mode 100644 index 0000000..c6384c8 --- /dev/null +++ b/modules/nixos/server/services/ookflix/sonarr.nix @@ -0,0 +1,44 @@ +{ + config, + lib, + ook, + self, + ... +}: let + ookflixLib = import ./lib.nix {inherit lib config self;}; + inherit (ookflixLib) mkServiceUser mkServiceStateDir; + inherit (lib) mkIf; + inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; + inherit (config.ooknet.server.ookflix) groups volumes; + inherit (config.ooknet.server.ookflix.services) sonarr; +in { + config = mkIf sonarr.enable { + users = mkServiceUser sonarr.user.name; + systemd.tmpfiles = mkServiceStateDir "sonarr" sonarr.stateDir; + virtualisation.oci-containers.containers = { + sonarr = { + image = "ghcr.io/hotio/sonarr"; + autoStart = true; + hostname = "sonarr"; + ports = [(mkContainerPort sonarr.port)]; + volumes = [ + "${sonarr.stateDir}:/config" + "${volumes.data.root}:/data" + ]; + labels = mkContainerLabel { + name = "sonarr"; + inherit (sonarr) port domain; + homepage = { + group = "arr"; + description = "media-server tv downloader"; + }; + }; + environment = + mkContainerEnvironment sonarr.user.id groups.media.id + // { + UMASK = "002"; + }; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/tautulli.nix b/modules/nixos/server/services/ookflix/tautulli.nix index f99fad6..5d1ec5d 100644 --- a/modules/nixos/server/services/ookflix/tautulli.nix +++ b/modules/nixos/server/services/ookflix/tautulli.nix @@ -2,14 +2,15 @@ config, lib, ook, + self, ... }: let - ookflixLib = import ./lib.nix {inherit lib config;}; + ookflixLib = import ./lib.nix {inherit lib config self;}; inherit (ookflixLib) mkServiceUser mkServiceStateDir; inherit (lib) mkIf; inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; inherit (config.ooknet.server.ookflix) groups; - inherit (config.ooknet.server.services) tautulli; + inherit (config.ooknet.server.ookflix.services) tautulli; in { config = mkIf tautulli.enable { users = mkServiceUser tautulli.user.name; diff --git a/modules/nixos/server/services/ookflix/transmission.nix b/modules/nixos/server/services/ookflix/transmission.nix new file mode 100644 index 0000000..0122cb3 --- /dev/null +++ b/modules/nixos/server/services/ookflix/transmission.nix @@ -0,0 +1,43 @@ +{ + config, + lib, + ook, + self, + ... +}: let + ookflixLib = import ./lib.nix {inherit lib config self;}; + inherit (ookflixLib) mkServiceUser mkServiceStateDir; + inherit (lib) mkIf; + inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; + inherit (config.ooknet.server.ookflix) groups volumes; + inherit (config.ooknet.server.ookflix.services) transmission gluetun; +in { + config = mkIf transmission.enable { + users = mkServiceUser transmission.user.name; + systemd.tmpfiles = mkServiceStateDir "transmission" transmission.stateDir; + virtualisation.oci-containers.containers = { + # Torrent client + transmission = { + image = "lscr.io/linuxserver/transmission:latest"; + environmentFiles = [config.age.secrets.transmission_env.path]; + environment = mkContainerEnvironment transmission.user.id groups.downloads.id; + dependsOn = ["gluetun"]; + networkMode = "service:gluetun"; # Use VPN container's network + volumes = [ + "${transmission.stateDir}:/config" + "${volumes.downloads.root}:/downloads" + "${volumes.downloads.watch}:/watch" + ]; + extraOptions = ["--network=container:gluetun"]; + labels = mkContainerLabel { + name = "transmission"; + inherit (transmission) port domain; + homepage = { + group = "downloads"; + description = "torrent client"; + }; + }; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/users.nix b/modules/nixos/server/services/ookflix/users.nix deleted file mode 100644 index 63790b0..0000000 --- a/modules/nixos/server/services/ookflix/users.nix +++ /dev/null @@ -1,38 +0,0 @@ -{ - lib, - config, - ... -}: let - inherit (lib) mkIf mkMerge; - inherit (builtins) mapAttrs; - inherit (config.ooknet.server) ookflix; - inherit (config.ooknet.server.ookflix) services storage users groups; - - mkServiceUser = name: user: { - isSystemUser = true; - group = groups.${name}.name; - uid = users.${name}.id; - home = storage.state.${name}; - }; - - generateUsers = mapAttrs mkServiceUser users; -in { - config = mkIf ookflix.enable { - users = { - users = mkMerge [ - # media service users - (mkIf services.jellyfin.enable { - ${users.jellyfin.name} = mkServiceUser users.jellyfin.name groups.media.name; - }) - (mkIf services.plex.enable { - ${users.plex.name} = mkServiceUser users.plex.name groups.media.name; - }) - (mkIf (services.jellyfin.enable || services.jellyseer.enable) { - ${users.jellyseer.name} = mkServiceUser users.jellyseer.name groups.media.name; - }) - ]; - groups = { - }; - }; - }; -} From da77c223ff0ec8c30bef91a91b1bca25eaeab66d Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 2 Dec 2024 18:54:26 +1100 Subject: [PATCH 068/213] ooksmedia: remove ookflix from host conf --- hosts/ooksmedia/default.nix | 9 --------- 1 file changed, 9 deletions(-) diff --git a/hosts/ooksmedia/default.nix b/hosts/ooksmedia/default.nix index 0dbc667..e1457bd 100644 --- a/hosts/ooksmedia/default.nix +++ b/hosts/ooksmedia/default.nix @@ -21,15 +21,6 @@ editor = "nvim"; multiplexer = "zellij"; }; - server = { - ookflix = { - gpuAcceleration.enable = true; - services = { - plex.enable = true; - jellyfin.enable = true; - }; - }; - }; }; boot.kernelPackages = pkgs.linuxPackages_xanmod_latest; From c096dc295a278e34995c75d34189e94b9c5b7344 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 2 Dec 2024 18:55:06 +1100 Subject: [PATCH 069/213] ookflix: refactors FIX COMMIT --- .../nixos/server/services/ookflix/default.nix | 21 +---- .../nixos/server/services/ookflix/gluetun.nix | 17 ++-- .../server/services/ookflix/jellyfin.nix | 2 +- modules/nixos/server/services/ookflix/lib.nix | 27 ++++--- .../nixos/server/services/ookflix/options.nix | 50 ++++++++---- .../server/services/ookflix/prowlarr.nix | 1 - .../server/services/ookflix/qbittorrent.nix | 46 +++++++++++ .../nixos/server/services/ookflix/radarr.nix | 7 +- .../nixos/server/services/ookflix/shared.nix | 78 +++++++++++-------- .../server/services/ookflix/transmission.nix | 43 ---------- 10 files changed, 154 insertions(+), 138 deletions(-) create mode 100644 modules/nixos/server/services/ookflix/qbittorrent.nix delete mode 100644 modules/nixos/server/services/ookflix/transmission.nix diff --git a/modules/nixos/server/services/ookflix/default.nix b/modules/nixos/server/services/ookflix/default.nix index f14c124..616bb63 100644 --- a/modules/nixos/server/services/ookflix/default.nix +++ b/modules/nixos/server/services/ookflix/default.nix @@ -1,11 +1,4 @@ { - lib, - config, - ... -}: let - inherit (lib) elem mkIf; - inherit (config.ooknet.server) services; -in { imports = [ ./jellyfin.nix ./plex.nix @@ -14,21 +7,9 @@ in { ./sonarr.nix ./prowlarr.nix ./gluetun.nix - ./transmission.nix + ./qbittorrent.nix ./shared.nix ./options.nix ]; - - config = mkIf (elem "ookflix" services) { - ooknet.server.ookflix = { - gpuAcceleration.enable = true; - services = { - jellyfin.enable = true; - plex.enable = true; - jellyseer.enable = true; - tautulli.enable = true; - }; - }; - }; } diff --git a/modules/nixos/server/services/ookflix/gluetun.nix b/modules/nixos/server/services/ookflix/gluetun.nix index 3f5fb84..cc56f80 100644 --- a/modules/nixos/server/services/ookflix/gluetun.nix +++ b/modules/nixos/server/services/ookflix/gluetun.nix @@ -6,27 +6,24 @@ ... }: let ookflixLib = import ./lib.nix {inherit self lib config;}; - inherit (ookflixLib) mkServiceUser; + inherit (ookflixLib) mkServiceUser mkServiceSecret; inherit (lib) mkIf; - inherit (ook.lib.container) mkContainerEnvironment mkContainerPort mkServiceSecret; - inherit (config.ooknet.server.ookflix.services) transmission gluetun; + inherit (ook.lib.container) mkContainerEnvironment mkContainerPort; + inherit (config.ooknet.server.ookflix.services) qbittorrent gluetun; in { config = mkIf gluetun.enable { users = mkServiceUser gluetun.user.name; - age.secrets.vpn_env = mkServiceSecret "vpn_env" "gluetun"; + age.secrets = mkServiceSecret "vpn_env" "gluetun"; virtualisation.oci-containers.containers = { # vpn container - gluetun = mkIf { + gluetun = mkIf gluetun.enable { image = "qmcgaw/gluetun:latest"; # should make this an option. environmentFiles = [config.age.secrets.vpn_env.path]; ports = [ - (mkContainerPort transmission.port) + (mkContainerPort qbittorrent.port) ]; - environment = mkContainerEnvironment gluetun.user.id gluetun.group.id { - VPN_SERVICE_PROVIDER = gluetun.provider; - VPN_TYPE = "wireguard"; - }; + environment = mkContainerEnvironment gluetun.user.id gluetun.group.id; extraOptions = [ # give network admin permissions "--cap-add=NET_ADMIN" diff --git a/modules/nixos/server/services/ookflix/jellyfin.nix b/modules/nixos/server/services/ookflix/jellyfin.nix index 0692b0e..6f30b4b 100644 --- a/modules/nixos/server/services/ookflix/jellyfin.nix +++ b/modules/nixos/server/services/ookflix/jellyfin.nix @@ -23,7 +23,7 @@ in { image = "lscr.io/linuxserver/jellyfin:latest"; autoStart = true; hostname = "jellyfin"; - ports = ["${jellyfin.port}:${jellyfin.port}"]; + ports = [(mkContainerPort jellyfin.port)]; volumes = [ "${volumes.media.root}:/data" "${jellyfin.stateDir}:/config" diff --git a/modules/nixos/server/services/ookflix/lib.nix b/modules/nixos/server/services/ookflix/lib.nix index 6cc065d..9b91566 100644 --- a/modules/nixos/server/services/ookflix/lib.nix +++ b/modules/nixos/server/services/ookflix/lib.nix @@ -9,6 +9,7 @@ inherit (lib.types) int path port str; inherit (config.ooknet) server; cfg = server.ookflix; + ookflixEnabled = elem "ookflix" server.services; mkSubdomainOption = name: description: example: mkOption { @@ -60,19 +61,25 @@ inherit description example; }; - mkVolumeOption = type: pathValue: + mkVolumeOption = rootPath: pathValue: mkOption { type = path; default = - if type == "state" + if rootPath == "state" then "${cfg.volumes.state.root}/${pathValue}" - else if type == "media" + else if rootPath == "data" + then "${cfg.volumes.data.root}/${pathValue}" + else if rootPath == "media" then "${cfg.volumes.media.root}/${pathValue}" - else if type == "downloads" - then "${cfg.volumes.downloads.root}/${pathValue}" - else if type == "root" + else if rootPath == "torrents" + then "${cfg.volumes.torrents.root}/${pathValue}" + else if rootPath == "usenet" + then "${cfg.volumes.usenet.root}/${pathValue}" + else if rootPath == "usenet/complete" + then "${cfg.volumes.usenet.complete.root}/${pathValue}" + else if rootPath == "root" then pathValue - else throw "Invalid VolumeOption type: ${type}. Must be one of 'state' 'media' 'downloads' 'root'"; + else throw "Invalid VolumeOption rootPath: ${rootPath}. Must be one of 'state' 'data' 'media' 'torrents' 'usenet' 'usenet/complete' 'root'"; }; mkServiceOptions = name: { @@ -81,7 +88,7 @@ uid, ... } @ args: { - enable = mkEnableOption "Enable ${name} container"; + enable = mkEnableOption "Enable ${name} container" // {default = ookflixEnabled;}; port = mkPortOption args.port "Port for ${name} container." 80; domain = mkSubdomainOption name "Domain for ${name} container." "${name}.mydomain.com"; stateDir = mkVolumeOption "state" name; @@ -93,7 +100,7 @@ uid, ... } @ args: { - enable = mkEnableOption "Enable ${name} container"; + enable = mkEnableOption "Enable ${name} container" // {default = ookflixEnabled;}; user = mkUserOption name args.uid; group = mkGroupOption name args.gid; }; @@ -118,7 +125,7 @@ }; mkServiceSecret = name: service: { ${name} = { - file = "${self}/secrets/container/${name}.age"; + file = "${self}/secrets/containers/${name}.age"; owner = cfg.services.${service}.user.name; group = cfg.services.${service}.group.name; }; diff --git a/modules/nixos/server/services/ookflix/options.nix b/modules/nixos/server/services/ookflix/options.nix index 8d0637b..3cddfdd 100644 --- a/modules/nixos/server/services/ookflix/options.nix +++ b/modules/nixos/server/services/ookflix/options.nix @@ -6,16 +6,19 @@ }: let ookflixLib = import ./lib.nix {inherit lib config self;}; - inherit (ookflixLib) mkVolumeOption mkGroupOption mkServiceOptions mkBasicServiceOptions; - inherit (lib) mkOption mkEnableOption; + inherit (ookflixLib) mkVolumeOption mkGroupOption mkServiceOptions mkBasicServiceOptions mkPortOption; + inherit (lib) mkOption mkEnableOption elem; + inherit (config.ooknet.server) services; inherit (lib.types) enum; - inherit (config.ooknet) server; - cfg = server.ookflix; in { options.ooknet.server.ookflix = { - enable = mkEnableOption "Enable ookflix a container based media server module"; + enable = + mkEnableOption "Enable ookflix a container based media server module" + // {default = elem "ookflix" services;}; gpuAcceleration = { - enable = mkEnableOption "Enable GPU acceleration for video streamers"; + enable = + mkEnableOption "Enable GPU acceleration for video streamers" + // {default = elem "ookflix" services;}; type = mkOption { type = enum ["nvidia" "intel" "amd"]; default = config.ooknet.hardware.gpu.type; @@ -28,15 +31,26 @@ in { volumes = { state.root = mkVolumeOption "root" "/var/lib/ookflix"; data.root = mkVolumeOption "root" "/jellyfin"; - downloads = { - root = mkVolumeOption "${cfg.content.root}/downloads"; - tv = mkVolumeOption "downloads" "tv"; - movies = mkVolumeOption "downloads" "movies"; - books = mkVolumeOption "downloads" "books"; + + torrents = { + root = mkVolumeOption "data" "torrents"; + tv = mkVolumeOption "torrents" "tv"; + movies = mkVolumeOption "torrents" "movies"; + books = mkVolumeOption "torrents" "books"; }; + usenet = { + root = mkVolumeOption "data" "usenet"; + incomplete = mkVolumeOption "usenet" "incomplete"; + complete = { + root = mkVolumeOption "usenet" "complete"; + tv = mkVolumeOption "usenet/complete" "tv"; + movies = mkVolumeOption "usenet/complete" "movies"; + books = mkVolumeOption "usenet/complete" "books"; + }; + }; media = { - root = mkVolumeOption "root" "${cfg.volumes.content.root}/media"; + root = mkVolumeOption "data" "media"; movies = mkVolumeOption "media" "movies"; tv = mkVolumeOption "media" "tv"; books = mkVolumeOption "media" "books"; @@ -74,11 +88,13 @@ in { uid = 982; gid = 987; }; - transmission = mkServiceOptions "transmission" { - port = 9091; - uid = 70; - gid = 70; - }; + qbittorrent = + mkServiceOptions "qbittorrent" { + port = 8080; + uid = 377; + gid = 377; + } + // {torrentPort = mkPortOption 58080 "Torrenting Port for qbittorrent" 58080;}; jellyseer = mkServiceOptions "jellyseer" { port = 5055; uid = 345; diff --git a/modules/nixos/server/services/ookflix/prowlarr.nix b/modules/nixos/server/services/ookflix/prowlarr.nix index ca8e5ed..ee5f333 100644 --- a/modules/nixos/server/services/ookflix/prowlarr.nix +++ b/modules/nixos/server/services/ookflix/prowlarr.nix @@ -22,7 +22,6 @@ in { hostname = "prowlarr"; ports = [(mkContainerPort prowlarr.port)]; volumes = ["${prowlarr.stateDir}:/config"]; - extraOptions = ["--network" "host"]; labels = mkContainerLabel { name = "prowlarr"; inherit (prowlarr) port domain; diff --git a/modules/nixos/server/services/ookflix/qbittorrent.nix b/modules/nixos/server/services/ookflix/qbittorrent.nix new file mode 100644 index 0000000..026a4de --- /dev/null +++ b/modules/nixos/server/services/ookflix/qbittorrent.nix @@ -0,0 +1,46 @@ +{ + config, + lib, + ook, + self, + ... +}: let + ookflixLib = import ./lib.nix {inherit lib config self;}; + inherit (ookflixLib) mkServiceUser mkServiceStateDir; + inherit (lib) mkIf; + inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment; + inherit (config.ooknet.server.ookflix) groups volumes; + inherit (config.ooknet.server.ookflix.services) qbittorrent; +in { + config = mkIf qbittorrent.enable { + users = mkServiceUser qbittorrent.user.name; + systemd.tmpfiles = mkServiceStateDir "qbittorrent" qbittorrent.stateDir; + virtualisation.oci-containers.containers = { + # Torrent client + qbittorrent = { + image = "ghcr.io/hotio/qbittorrent"; + dependsOn = ["gluetun"]; + volumes = [ + "${qbittorrent.stateDir}:/config" + "${volumes.torrents.root}:/data/torrents" + ]; + extraOptions = ["--network=container:gluetun"]; + labels = mkContainerLabel { + name = "qbittorrent"; + inherit (qbittorrent) port domain; + homepage = { + group = "downloads"; + description = "torrent client"; + }; + }; + environment = + mkContainerEnvironment qbittorrent.user.id groups.downloads.id + // { + UMASK = "002"; + WEBUI_PORTS = "${toString qbittorrent.port}/tcp,${toString qbittorrent.port}/udp"; + TORRENTING_PORT = "${toString qbittorrent.torrentPort}"; + }; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/radarr.nix b/modules/nixos/server/services/ookflix/radarr.nix index d478631..b970381 100644 --- a/modules/nixos/server/services/ookflix/radarr.nix +++ b/modules/nixos/server/services/ookflix/radarr.nix @@ -25,7 +25,6 @@ in { "${radarr.stateDir}:/config" "${volumes.data.root}:/data" ]; - extraOptions = ["--network" "host"]; labels = mkContainerLabel { name = "radarr"; inherit (radarr) port domain; @@ -34,7 +33,11 @@ in { description = "media-server movies downloader"; }; }; - environment = mkContainerEnvironment radarr.user.id groups.media.id; + environment = + mkContainerEnvironment radarr.user.id groups.media.id + // { + UMASK = "002"; + }; }; }; }; diff --git a/modules/nixos/server/services/ookflix/shared.nix b/modules/nixos/server/services/ookflix/shared.nix index 87a5117..f8d61e1 100644 --- a/modules/nixos/server/services/ookflix/shared.nix +++ b/modules/nixos/server/services/ookflix/shared.nix @@ -7,59 +7,69 @@ inherit (config.ooknet.host) admin; inherit (config.ooknet.server) ookflix; inherit (config.ooknet.server.ookflix) volumes groups; - inherit (config.ooknet.server.ookflix.services) jellyfin plex sonarr radarr prowlarr transmission; - mediaDirPermissions = { + inherit (config.ooknet.server.ookflix.services) jellyfin plex sonarr radarr prowlarr qbittorrent; + dataDirPermissions = { mode = "0775"; user = admin.name; group = groups.media.name; }; - downloadDirPermissions = { - mode = "0770"; - user = admin.name; - group = groups.downloads.name; - }; ifTheyExist = users: builtins.filter (user: builtins.hasAttr user config.users.users) users; in { config = mkIf ookflix.enable { users.groups = { ${groups.media.name} = { - inherit (groups.media) name gid; + inherit (groups.media) name; + gid = groups.media.id; members = ifTheyExist [ + # need access to the media library jellyfin.user.name plex.user.name + + # need access to the media library and the torrent/usenet library sonarr.user.name radarr.user.name prowlarr.user.name - ]; - }; - ${groups.downloads.name} = { - inherit (groups.downloads) name gid; - members = ifTheyExist [ - sonarr.user.name - radarr.user.name - prowlarr.user.name - transmission.user.name + + # need access to the torrent library + qbittorrent.user.name ]; }; }; systemd.tmpfiles.settings = { - contentRoot = { - "${volumes.content.root}"."d" = { - mode = "0775"; - user = "root"; - group = "root"; - }; - }; - mediaDirectories = { - "${volumes.media.root}"."d" = mediaDirPermissions; - "${volumes.media.tv}"."d" = mediaDirPermissions; - "${volumes.media.movies}"."d" = mediaDirPermissions; - }; - downloadDirectories = { - "${volumes.downloads.root}"."d" = downloadDirPermissions; - "${volumes.downloads.complete}"."d" = downloadDirPermissions; - "${volumes.downloads.incomplete}"."d" = downloadDirPermissions; - "${volumes.downloads.watch}"."d" = downloadDirPermissions; + ookflixDataDirs = { + /* + set up the entire directory structure it should look something like this: + data + ├── torrents + │ ├── movies + │ ├── books + │ └── tv + ├── usenet + │ ├── incomplete + │ └── complete + │ ├── books + │ ├── movies + │ └── tv + └── media + ├── movies + ├── books + └── tv + */ + "${volumes.data.root}"."d" = dataDirPermissions; + "${volumes.torrents.root}"."d" = dataDirPermissions; + "${volumes.torrents.movies}"."d" = dataDirPermissions; + "${volumes.torrents.tv}"."d" = dataDirPermissions; + "${volumes.torrents.books}"."d" = dataDirPermissions; + "${volumes.usenet.root}"."d" = dataDirPermissions; + "${volumes.usenet.incomplete}"."d" = dataDirPermissions; + "${volumes.usenet.complete.root}"."d" = dataDirPermissions; + "${volumes.usenet.complete.movies}"."d" = dataDirPermissions; + "${volumes.usenet.complete.tv}"."d" = dataDirPermissions; + "${volumes.usenet.complete.books}"."d" = dataDirPermissions; + "${volumes.media.root}"."d" = dataDirPermissions; + "${volumes.media.movies}"."d" = dataDirPermissions; + "${volumes.media.tv}"."d" = dataDirPermissions; + "${volumes.media.books}"."d" = dataDirPermissions; }; }; }; diff --git a/modules/nixos/server/services/ookflix/transmission.nix b/modules/nixos/server/services/ookflix/transmission.nix deleted file mode 100644 index 0122cb3..0000000 --- a/modules/nixos/server/services/ookflix/transmission.nix +++ /dev/null @@ -1,43 +0,0 @@ -{ - config, - lib, - ook, - self, - ... -}: let - ookflixLib = import ./lib.nix {inherit lib config self;}; - inherit (ookflixLib) mkServiceUser mkServiceStateDir; - inherit (lib) mkIf; - inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; - inherit (config.ooknet.server.ookflix) groups volumes; - inherit (config.ooknet.server.ookflix.services) transmission gluetun; -in { - config = mkIf transmission.enable { - users = mkServiceUser transmission.user.name; - systemd.tmpfiles = mkServiceStateDir "transmission" transmission.stateDir; - virtualisation.oci-containers.containers = { - # Torrent client - transmission = { - image = "lscr.io/linuxserver/transmission:latest"; - environmentFiles = [config.age.secrets.transmission_env.path]; - environment = mkContainerEnvironment transmission.user.id groups.downloads.id; - dependsOn = ["gluetun"]; - networkMode = "service:gluetun"; # Use VPN container's network - volumes = [ - "${transmission.stateDir}:/config" - "${volumes.downloads.root}:/downloads" - "${volumes.downloads.watch}:/watch" - ]; - extraOptions = ["--network=container:gluetun"]; - labels = mkContainerLabel { - name = "transmission"; - inherit (transmission) port domain; - homepage = { - group = "downloads"; - description = "torrent client"; - }; - }; - }; - }; - }; -} From a9ef09a8a4c47d21811a9166d7ebf909796a024b Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 2 Dec 2024 18:55:35 +1100 Subject: [PATCH 070/213] website: caddy cloudflare package --- modules/nixos/server/options.nix | 5 +- .../nixos/server/services/website/default.nix | 43 +++++++++-------- modules/nixos/server/webserver/caddy.nix | 25 ++++++++-- .../pkgs/caddy-with-cloudflare/default.nix | 46 +++++++++++++++++++ outputs/pkgs/default.nix | 1 + 5 files changed, 95 insertions(+), 25 deletions(-) create mode 100644 outputs/pkgs/caddy-with-cloudflare/default.nix diff --git a/modules/nixos/server/options.nix b/modules/nixos/server/options.nix index 06e8808..eea6d9d 100644 --- a/modules/nixos/server/options.nix +++ b/modules/nixos/server/options.nix @@ -24,7 +24,10 @@ in { }; webserver = { - caddy.enable = mkEnableOption ""; + caddy = { + enable = mkEnableOption ""; + cloudflare.enable = mkEnableOption ""; + }; }; database = { postgresql.enable = mkEnableOption ""; diff --git a/modules/nixos/server/services/website/default.nix b/modules/nixos/server/services/website/default.nix index 64a0fa2..f9f64a1 100644 --- a/modules/nixos/server/services/website/default.nix +++ b/modules/nixos/server/services/website/default.nix @@ -15,7 +15,10 @@ }; in { config = mkIf (elem "website" services) { - ooknet.server.webserver.caddy.enable = true; + ooknet.server.webserver.caddy = { + enable = true; + cloudflare.enable = true; + }; systemd.tmpfiles.settings.websiteDirs = { "/var/www"."d" = websitePermissions; "/var/www/ooknet.org"."d" = websitePermissions; @@ -45,29 +48,31 @@ in { }; # using caddy because it makes my life easy - services.caddy.virtualHosts = { - "ooknet.org".extraConfig = - # sh - '' - encode zstd gzip + services.caddy = { + virtualHosts = { + "ooknet.org".extraConfig = + # sh + '' + encode zstd gzip - header { - Strict-Transport-Security "max-age=31536000;" - X-XSS-Protection "1; mode=block" - X-Frame-Options "DENY" - X-Content-Type-Options "nosniff" - -Server + header { + Strict-Transport-Security "max-age=31536000;" + X-XSS-Protection "1; mode=block" + X-Frame-Options "DENY" + X-Content-Type-Options "nosniff" + -Server - Referrer-Policy: no-referrer - } + Referrer-Policy "no-referrer" + } - root * /var/www/ooknet.org/ - file_server + root * /var/www/ooknet.org/ + file_server + ''; + "www.ooknet.org".extraConfig = '' + redir https://ooknet.org{uri} permanent ''; - "www.ooknet.org".extraConfig = '' - redir https://ooknet.org{uri} - ''; + }; }; }; } diff --git a/modules/nixos/server/webserver/caddy.nix b/modules/nixos/server/webserver/caddy.nix index 99dd2b2..2d04d65 100644 --- a/modules/nixos/server/webserver/caddy.nix +++ b/modules/nixos/server/webserver/caddy.nix @@ -1,16 +1,31 @@ { config, lib, + self', ... }: let - inherit (lib) mkIf; + inherit (lib) mkIf mkMerge; inherit (config.ooknet.server.webserver) caddy; in { config = mkIf caddy.enable { users.groups.www = {}; - services.caddy = { - enable = true; - group = "www"; - }; + services.caddy = mkMerge [ + { + enable = true; + group = "www"; + } + + (mkIf caddy.cloudflare.enable { + package = self'.packages.caddy-with-cloudflare; + globalConfig = '' + servers { + trusted_proxies cloudflare { + interval 12h + timeout 15s + } + } + ''; + }) + ]; }; } diff --git a/outputs/pkgs/caddy-with-cloudflare/default.nix b/outputs/pkgs/caddy-with-cloudflare/default.nix new file mode 100644 index 0000000..1807b3b --- /dev/null +++ b/outputs/pkgs/caddy-with-cloudflare/default.nix @@ -0,0 +1,46 @@ +{ + buildGoModule, + cacert, + go, + lib, + stdenv, + xcaddy, + caddy, +}: +caddy.override { + buildGoModule = args: + buildGoModule (args + // { + src = stdenv.mkDerivation rec { + pname = "caddy-using-xcaddy-${xcaddy.version}"; + inherit (caddy) version; + dontUnpack = true; + dontFixup = true; + nativeBuildInputs = [cacert go]; + plugins = [ + "github.com/WeidiDeng/caddy-cloudflare-ip" + ]; + configurePhase = '' + export GOCACHE=$TMPDIR/go-cache + export GOPATH="$TMPDIR/go" + export XCADDY_SKIP_BUILD=1 + ''; + buildPhase = '' + ${xcaddy}/bin/xcaddy build "${caddy.src.rev}" ${ + lib.concatMapStringsSep " " (plugin: "--with ${plugin}") plugins + } + cd buildenv* + go mod vendor + ''; + installPhase = '' + cp -r --reflink=auto . $out + ''; + outputHash = "sha256-O3QWqgQtLOifsibyB0/UKricEGAx/3NhSjGbgu8+qgY="; + outputHashMode = "recursive"; + }; + subPackages = ["."]; + ldflags = ["-s" "-w"]; + vendorHash = null; + }); +} + diff --git a/outputs/pkgs/default.nix b/outputs/pkgs/default.nix index 037b1b3..a89ffa1 100644 --- a/outputs/pkgs/default.nix +++ b/outputs/pkgs/default.nix @@ -8,6 +8,7 @@ repopack = callPackage ./repopack {}; live-buds-cli = callPackage ./live-buds-cli {}; website = callPackage ./website {}; + caddy-with-cloudflare = callPackage ./caddy-with-cloudflare {}; ook-vim = mkNeovim pkgs [ook-vim-config]; }; From c6b06d5ba74ad26fdda6efcb745126e56a3174b3 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 2 Dec 2024 18:56:04 +1100 Subject: [PATCH 071/213] secrets: fix container secret helper function --- outputs/lib/containers.nix | 6 +----- secrets/containers/vpn_env.age | Bin 1154 -> 1158 bytes 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/outputs/lib/containers.nix b/outputs/lib/containers.nix index 36c002d..7a30393 100644 --- a/outputs/lib/containers.nix +++ b/outputs/lib/containers.nix @@ -1,8 +1,4 @@ -{ - lib, - config, - ... -}: let +{lib, ...}: let inherit (builtins) isBool; inherit (lib) toUpper optionalAttrs mapAttrs' nameValuePair; diff --git a/secrets/containers/vpn_env.age b/secrets/containers/vpn_env.age index 80210af805ad2c1235d73feef1066c744373df51..346dda6c48e63b5f02e64cdabf9b9609d1cf9062 100644 GIT binary patch delta 1052 zcmZqTY~!4uQy<{(omG{X8eVFU>=@x3Y?NW>Wf7%q>|b0}>>FyHmTu&0RPLK^Y@TnN z%oUZJ7MkW5;AC1JP-WucmtNwX=@nMyT~y)koF5*VALJTb=<4s4lj7>*$fawiP+Xj$ zo0?)|YHDbyVCGSlSmLNq5S3Gu8{y^};E`mWr*D+1?dFo`oR*^>nwXnal4_El9qN&8 z8I`Ub=pPu$l~G`9?yjw$7#NY^T$oanW$LT#7gk=9nV%eN;gji6npu|OT~Op`9$K0_ z@uPTnrdhb5NpV?Vq<&apk&|zwheuUKM3BCvuVJZQR%Nb!R8dYOo_$PI7*d zk*l$RMTJRHzL}ewPm+F?o4>1}MU_)tWO7DnR!O9vSGZ}VX@2PBct-K?ln~3jkP7FF z0yB?t$M9lL??hiW?;Jy?u*hUzbHh}3v#>~Qv*bue-z-NigRrvPA`@4)JRhT+%9O+) zlVoQjugU<&l4S2p_eyuSVwb#<&T50D=Q)*{7oHGoI))_ zU5i~!i&H|&(%n3KGXsm!V<6QxOWP}5!7VhzEx^ej!au~bI3V9R*`VG`J2)aO+$6%u zDbS_d&CfDdJIX6Or8Frooh!n$*tjIoGQU_m&@eS3$3G<7IUp<9ytKSHu_DaZ%h$u) zqeMF}H?1%#65TrAKz(!9as?-&Q2jK2=VULJLQ~UVQ@`ZQVnhFk++yv3aP#n>K=ZUD zQ%F2TZz1)LBqpG~p^9(8tvy;NYlcUUx4YGXALb-Hxbrp(Tl0#G7 zLQ6A^Qqn_{yrTTg!+bNs0}B&P@>0s&vc0vn)9b^6vqB?-k|Vh|oc)D%8Xnux^1S#n z+c%C9txrd->~`$-I<)J@Z>70MCiWF4-rW7y)voh_mc~B=wf9`-W`?$W)Vg0inSImw zDB%O|1GY!{Deiu{FtVEArq1bC>tkOxuW5hH^C32(i(BVL$@%u%nO{|Y+~J#=eaE?@ z`kz_#OO?%kql%Yx-hVS&;b(Gm(UPBwMD&GS&d<>DR*C!g=V<+U$B*4_GBy_rtlyKD z`8(}pkbNk7(cYAEHw;%SK58(%zD@Y}lCrbHhWFCm&8=`U5VFbYxY5EQY1vtBQI|Xg E0IrCAi2wiq delta 1048 zcmZqUY~q}tQ(vO*UX_v^<(TH_YhvbN;jQnRTNPDO=45IZYV4Pm<(6IS?Ck27QRWz7 z!Bv&(?4IV~8fEC^QIQnjQ(l>(ALgE4o*d|yl#=G1Z0Q&rR90^4o|2Yn!KG`bP+Xj$ zo0?)|YHDbyVCGSlSmLNqT$o}|Rv8qYR%KQeW}aG<>Q?F#;uP-dUJ;rR9unf`m7A7T zth(mmF{kmm1dkB=~oqzkz5euRcKa{5oM6<6zo-$T~H97YV7TA=@^h`9+GS@ z@uPUSM{-JfWLa*Ib8)UmKwf&bv$vr^Kygrpb9P#UvA=snseY1IT1L5rhoc2ofJMHK zca(8em}y3(e@T92RH3=6QLejBqDy9SKxt)0W`J{!d#;hAd4%uect-JX|Li=UB%`8? zDqrtNFZb{$H{-&fNVjkwFCWvaaMRoZr@*4@;DXG2k5B_HFAK}cL}Smuk^mp?f)XEn zm%J1o*W%#3BHtwUP*+RGj7+nrNJmqjjEK<5XBoxoy|TkoeErhX%{@yC9HY`J4FaP| zE0Vo}iVQP@O(POLOP%x5ef`~&^CHT*OpG$avkHp*6Fo!I^qo9|0*WJ@UGh8(eM7XP z3O$W{v%LMHs!V+Y9nD?QV<6QxOWP}5A;Q?XFeNuM#H=LMFFDo7IK1B1Ff1%LztY4v zs=UnC)zjBFEZnys)Vm7+H9a`@ryJk%rt9xj zCoA3axR5sa#oV(gVag9G+88sxfBntLzxA<^g=!1)!<@Y@87CNfdWB4%TP63eUi`oV zO-F;tR*&y`h287i-E6M?!f|Dt_#x5q@T>PH9NYP#{^L5^+^5PKi9LH3Jc&5Ab)n&& zX&W1t8s3z9>-JUYs96 From 061713745ef27f775a9f478b0cef6907f94527da Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 2 Dec 2024 19:34:21 +1100 Subject: [PATCH 072/213] caddy: add cloudflare ipv4 addresses to trusted proxies --- modules/nixos/server/webserver/caddy.nix | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/nixos/server/webserver/caddy.nix b/modules/nixos/server/webserver/caddy.nix index 2d04d65..be8cd6a 100644 --- a/modules/nixos/server/webserver/caddy.nix +++ b/modules/nixos/server/webserver/caddy.nix @@ -19,10 +19,8 @@ in { package = self'.packages.caddy-with-cloudflare; globalConfig = '' servers { - trusted_proxies cloudflare { - interval 12h - timeout 15s - } + metrics + trusted_proxies static private_ranges 173.245.48.0/20 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 141.101.64.0/18 108.162.192.0/18 190.93.240.0/20 188.114.96.0/20 197.234.240.0/22 198.41.128.0/17 162.158.0.0/15 104.16.0.0/13 104.24.0.0/14 172.64.0.0/13 131.0.72.0/22 } ''; }) From 4edb21607c5fb13092f7aa342995a3e576575370 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 4 Dec 2024 13:19:18 +1100 Subject: [PATCH 073/213] nixos: add admin.email option --- modules/nixos/base/options.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/nixos/base/options.nix b/modules/nixos/base/options.nix index 6683e48..13b2148 100644 --- a/modules/nixos/base/options.nix +++ b/modules/nixos/base/options.nix @@ -50,6 +50,10 @@ in { type = str; default = "ooks@protonmail.com"; }; + email = mkOption { + type = str; + default = "ooks@protonmail.com"; + }; homeManager = mkOption { type = bool; default = false; From bee284691ad1addfd06f1613824160ed85e6d2c8 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 4 Dec 2024 13:19:54 +1100 Subject: [PATCH 074/213] ookflix: segment modules --- .../nixos/server/services/ookflix/default.nix | 16 ++-- .../services/ookflix/downloading/default.nix | 9 +++ .../ookflix/downloading/jellyseer.nix | 38 +++++++++ .../ookflix/{ => downloading}/prowlarr.nix | 4 +- .../ookflix/{ => downloading}/qbittorrent.nix | 11 ++- .../ookflix/{ => downloading}/radarr.nix | 10 +-- .../ookflix/{ => downloading}/sonarr.nix | 4 +- .../server/services/ookflix/homepage.nix | 34 ++++++++ .../server/services/ookflix/jellyseer.nix | 34 -------- modules/nixos/server/services/ookflix/lib.nix | 28 ++++++- .../services/ookflix/monitors/default.nix | 5 ++ .../ookflix/{ => monitors}/tautulli.nix | 4 +- .../services/ookflix/networking/default.nix | 7 ++ .../ookflix/{ => networking}/gluetun.nix | 6 +- .../services/ookflix/networking/networks.nix | 28 +++++++ .../services/ookflix/networking/traefik.nix | 80 +++++++++++++++++++ .../nixos/server/services/ookflix/options.nix | 17 +++- .../nixos/server/services/ookflix/podman.nix | 35 ++++++++ .../services/ookflix/streamers/default.nix | 6 ++ .../ookflix/{ => streamers}/jellyfin.nix | 16 +--- .../services/ookflix/{ => streamers}/plex.nix | 22 +---- 21 files changed, 314 insertions(+), 100 deletions(-) create mode 100644 modules/nixos/server/services/ookflix/downloading/default.nix create mode 100644 modules/nixos/server/services/ookflix/downloading/jellyseer.nix rename modules/nixos/server/services/ookflix/{ => downloading}/prowlarr.nix (88%) rename modules/nixos/server/services/ookflix/{ => downloading}/qbittorrent.nix (78%) rename modules/nixos/server/services/ookflix/{ => downloading}/radarr.nix (75%) rename modules/nixos/server/services/ookflix/{ => downloading}/sonarr.nix (89%) create mode 100644 modules/nixos/server/services/ookflix/homepage.nix delete mode 100644 modules/nixos/server/services/ookflix/jellyseer.nix create mode 100644 modules/nixos/server/services/ookflix/monitors/default.nix rename modules/nixos/server/services/ookflix/{ => monitors}/tautulli.nix (88%) create mode 100644 modules/nixos/server/services/ookflix/networking/default.nix rename modules/nixos/server/services/ookflix/{ => networking}/gluetun.nix (82%) create mode 100644 modules/nixos/server/services/ookflix/networking/networks.nix create mode 100644 modules/nixos/server/services/ookflix/networking/traefik.nix create mode 100644 modules/nixos/server/services/ookflix/podman.nix create mode 100644 modules/nixos/server/services/ookflix/streamers/default.nix rename modules/nixos/server/services/ookflix/{ => streamers}/jellyfin.nix (77%) rename modules/nixos/server/services/ookflix/{ => streamers}/plex.nix (69%) diff --git a/modules/nixos/server/services/ookflix/default.nix b/modules/nixos/server/services/ookflix/default.nix index 616bb63..8580bd0 100644 --- a/modules/nixos/server/services/ookflix/default.nix +++ b/modules/nixos/server/services/ookflix/default.nix @@ -1,15 +1,13 @@ { imports = [ - ./jellyfin.nix - ./plex.nix - ./jellyseer.nix - ./tautulli.nix - ./sonarr.nix - ./prowlarr.nix - ./gluetun.nix - ./qbittorrent.nix - ./shared.nix + ./streamers + ./monitors + ./networking + ./downloading + ./shared.nix + ./podman.nix ./options.nix + ./homepage.nix ]; } diff --git a/modules/nixos/server/services/ookflix/downloading/default.nix b/modules/nixos/server/services/ookflix/downloading/default.nix new file mode 100644 index 0000000..af0e115 --- /dev/null +++ b/modules/nixos/server/services/ookflix/downloading/default.nix @@ -0,0 +1,9 @@ +{ + imports = [ + ./sonarr.nix + ./radarr.nix + ./prowlarr.nix + ./jellyseer.nix + ./qbittorrent.nix + ]; +} diff --git a/modules/nixos/server/services/ookflix/downloading/jellyseer.nix b/modules/nixos/server/services/ookflix/downloading/jellyseer.nix new file mode 100644 index 0000000..bf0b049 --- /dev/null +++ b/modules/nixos/server/services/ookflix/downloading/jellyseer.nix @@ -0,0 +1,38 @@ +{ + config, + lib, + ook, + self, + ... +}: let + ookflixLib = import ../lib.nix {inherit lib config self;}; + inherit (ookflixLib) mkServiceUser mkServiceStateDir; + inherit (lib) mkIf; + inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; + inherit (config.ooknet.server.ookflix) groups; + inherit (config.ooknet.server.ookflix.services) jellyseerr; +in { + config = mkIf jellyseerr.enable { + # media requesting for jellyfin + users = mkServiceUser jellyseerr.user.name; + systemd.tmpfiles.settings.jellyseerrStateDir = mkServiceStateDir "jellyseerr"; + virtualisation.oci-containers.containers = { + jellyseerr = { + image = "ghcr.io/hotio/jellyseerr"; + autoStart = true; + hostname = "jellyseerr"; + ports = [(mkContainerPort jellyseerr.port)]; + volumes = ["${jellyseerr.stateDir}:/config"]; + labels = mkContainerLabel { + name = "jellyseerr"; + inherit (jellyseerr) domain port; + homepage = { + group = "media"; + description = "media-server requesting"; + }; + }; + environment = mkContainerEnvironment jellyseerr.user.id groups.media.id; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/prowlarr.nix b/modules/nixos/server/services/ookflix/downloading/prowlarr.nix similarity index 88% rename from modules/nixos/server/services/ookflix/prowlarr.nix rename to modules/nixos/server/services/ookflix/downloading/prowlarr.nix index ee5f333..7004aea 100644 --- a/modules/nixos/server/services/ookflix/prowlarr.nix +++ b/modules/nixos/server/services/ookflix/downloading/prowlarr.nix @@ -5,7 +5,7 @@ self, ... }: let - ookflixLib = import ./lib.nix {inherit lib config self;}; + ookflixLib = import ../lib.nix {inherit lib config self;}; inherit (ookflixLib) mkServiceUser mkServiceStateDir; inherit (lib) mkIf; inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; @@ -14,7 +14,7 @@ in { config = mkIf prowlarr.enable { users = mkServiceUser prowlarr.user.name; - systemd.tmpfiles = mkServiceStateDir "prowlarr" prowlarr.stateDir; + systemd.tmpfiles.settings.prowlarrStateDir = mkServiceStateDir "prowlarr"; virtualisation.oci-containers.containers = { prowlarr = { image = "lscr.io/linuxserver/prowlarr:latest"; diff --git a/modules/nixos/server/services/ookflix/qbittorrent.nix b/modules/nixos/server/services/ookflix/downloading/qbittorrent.nix similarity index 78% rename from modules/nixos/server/services/ookflix/qbittorrent.nix rename to modules/nixos/server/services/ookflix/downloading/qbittorrent.nix index 026a4de..4117539 100644 --- a/modules/nixos/server/services/ookflix/qbittorrent.nix +++ b/modules/nixos/server/services/ookflix/downloading/qbittorrent.nix @@ -5,7 +5,7 @@ self, ... }: let - ookflixLib = import ./lib.nix {inherit lib config self;}; + ookflixLib = import ../lib.nix {inherit lib config self;}; inherit (ookflixLib) mkServiceUser mkServiceStateDir; inherit (lib) mkIf; inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment; @@ -14,17 +14,20 @@ in { config = mkIf qbittorrent.enable { users = mkServiceUser qbittorrent.user.name; - systemd.tmpfiles = mkServiceStateDir "qbittorrent" qbittorrent.stateDir; + systemd.tmpfiles.settings.qbittorrentStateDir = mkServiceStateDir "qbittorrent"; virtualisation.oci-containers.containers = { # Torrent client qbittorrent = { + hostname = "qbittorrent"; image = "ghcr.io/hotio/qbittorrent"; dependsOn = ["gluetun"]; volumes = [ "${qbittorrent.stateDir}:/config" "${volumes.torrents.root}:/data/torrents" ]; - extraOptions = ["--network=container:gluetun"]; + extraOptions = [ + "--network=container:gluetun" + ]; labels = mkContainerLabel { name = "qbittorrent"; inherit (qbittorrent) port domain; @@ -34,7 +37,7 @@ in { }; }; environment = - mkContainerEnvironment qbittorrent.user.id groups.downloads.id + mkContainerEnvironment qbittorrent.user.id groups.media.id // { UMASK = "002"; WEBUI_PORTS = "${toString qbittorrent.port}/tcp,${toString qbittorrent.port}/udp"; diff --git a/modules/nixos/server/services/ookflix/radarr.nix b/modules/nixos/server/services/ookflix/downloading/radarr.nix similarity index 75% rename from modules/nixos/server/services/ookflix/radarr.nix rename to modules/nixos/server/services/ookflix/downloading/radarr.nix index b970381..4c1c432 100644 --- a/modules/nixos/server/services/ookflix/radarr.nix +++ b/modules/nixos/server/services/ookflix/downloading/radarr.nix @@ -5,22 +5,22 @@ self, ... }: let - ookflixLib = import ./lib.nix {inherit lib config self;}; + ookflixLib = import ../lib.nix {inherit lib config self;}; inherit (ookflixLib) mkServiceUser mkServiceStateDir; inherit (lib) mkIf; - inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment; + inherit (ook.lib.container) mkContainerLabel mkContainerPort mkContainerEnvironment; inherit (config.ooknet.server.ookflix) groups volumes; inherit (config.ooknet.server.ookflix.services) radarr; in { config = mkIf radarr.enable { users = mkServiceUser radarr.user.name; - systemd.tmpfiles = mkServiceStateDir "radarr" radarr.stateDir; + systemd.tmpfiles.settings.radarrStateDir = mkServiceStateDir "radarr"; virtualisation.oci-containers.containers = { radarr = { - image = "ghcr.io/hotio/qbittorrent"; + image = "ghcr.io/hotio/radarr"; autoStart = true; hostname = "radarr"; - ports = ["${radarr.port}:${radarr.port}"]; + ports = [(mkContainerPort radarr.port)]; volumes = [ "${radarr.stateDir}:/config" "${volumes.data.root}:/data" diff --git a/modules/nixos/server/services/ookflix/sonarr.nix b/modules/nixos/server/services/ookflix/downloading/sonarr.nix similarity index 89% rename from modules/nixos/server/services/ookflix/sonarr.nix rename to modules/nixos/server/services/ookflix/downloading/sonarr.nix index c6384c8..c9b8014 100644 --- a/modules/nixos/server/services/ookflix/sonarr.nix +++ b/modules/nixos/server/services/ookflix/downloading/sonarr.nix @@ -5,7 +5,7 @@ self, ... }: let - ookflixLib = import ./lib.nix {inherit lib config self;}; + ookflixLib = import ../lib.nix {inherit lib config self;}; inherit (ookflixLib) mkServiceUser mkServiceStateDir; inherit (lib) mkIf; inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; @@ -14,7 +14,7 @@ in { config = mkIf sonarr.enable { users = mkServiceUser sonarr.user.name; - systemd.tmpfiles = mkServiceStateDir "sonarr" sonarr.stateDir; + systemd.tmpfiles.settings.sonarrStateDir = mkServiceStateDir "sonarr"; virtualisation.oci-containers.containers = { sonarr = { image = "ghcr.io/hotio/sonarr"; diff --git a/modules/nixos/server/services/ookflix/homepage.nix b/modules/nixos/server/services/ookflix/homepage.nix new file mode 100644 index 0000000..586923e --- /dev/null +++ b/modules/nixos/server/services/ookflix/homepage.nix @@ -0,0 +1,34 @@ +{ + config, + lib, + ook, + self, + ... +}: let + ookflixLib = import ./lib.nix {inherit lib config self;}; + inherit (ookflixLib) mkServiceUser mkServiceStateDir; + inherit (lib) mkIf; + inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; + inherit (config.ooknet.server.ookflix) groups; + inherit (config.ooknet.server.ookflix.services) homepage; +in { + config = mkIf homepage.enable { + # media requesting for jellyfin + users = mkServiceUser homepage.user.name; + systemd.tmpfiles.settings.homepageStateDir = mkServiceStateDir "homepage"; + virtualisation.oci-containers.containers = { + homepage = { + image = "ghcr.io/benphelps/homepage:latest"; + autoStart = true; + hostname = "homepage"; + ports = [(mkContainerPort homepage.port)]; + volumes = ["${homepage.stateDir}:/config"]; + labels = mkContainerLabel { + name = "homepage"; + inherit (homepage) domain port; + }; + environment = mkContainerEnvironment homepage.user.id groups.media.id; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/jellyseer.nix b/modules/nixos/server/services/ookflix/jellyseer.nix deleted file mode 100644 index c0cf5f3..0000000 --- a/modules/nixos/server/services/ookflix/jellyseer.nix +++ /dev/null @@ -1,34 +0,0 @@ -{ - config, - lib, - ook, - ... -}: let - inherit (lib) mkIf; - inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; - inherit (config.ooknet.server.ookflix) groups; - inherit (config.ooknet.server.ookflix.services) jellyseer; -in { - config = mkIf jellyseer.enable { - # media requesting for jellyfin - virtualisation.oci-containers.containers = { - jellyseer = { - image = "fallenbagel/jellyseerr:latest"; - autoStart = true; - hostname = "jellyseer"; - ports = [(mkContainerPort jellyseer.port)]; - volumes = ["${jellyseer.stateDir}:/config"]; - extraOptions = ["--network" "host"]; - labels = mkContainerLabel { - name = "jellyseer"; - inherit (jellyseer) domain port; - homepage = { - group = "media"; - description = "media-server requesting"; - }; - }; - environment = mkContainerEnvironment jellyseer.user.id groups.media.id; - }; - }; - }; -} diff --git a/modules/nixos/server/services/ookflix/lib.nix b/modules/nixos/server/services/ookflix/lib.nix index 9b91566..785fef7 100644 --- a/modules/nixos/server/services/ookflix/lib.nix +++ b/modules/nixos/server/services/ookflix/lib.nix @@ -4,10 +4,11 @@ self, ... }: let - inherit (lib) mkOption mkEnableOption elem assertMsg; + inherit (lib) getExe nameValuePair mkOption mkEnableOption elem assertMsg; inherit (builtins) attrValues; inherit (lib.types) int path port str; inherit (config.ooknet) server; + inherit (config.virtualisation) podman; cfg = server.ookflix; ookflixEnabled = elem "ookflix" server.services; @@ -116,13 +117,21 @@ name = service; }; }; - mkServiceStateDir = service: dir: { - settings."${service}StateDir".${dir}."d" = { + mkServiceStateDir = service: { + "${cfg.services.${service}.stateDir}"."d" = { mode = "0700"; user = cfg.services.${service}.user.name; group = cfg.services.${service}.group.name; }; }; + mkServiceStateFile = service: file: { + "${cfg.services.${service}.stateDir}/${file}"."f" = { + mode = "0600"; + user = cfg.services.${service}.user.name; + group = cfg.services.${service}.group.name; + }; + }; + mkServiceSecret = name: service: { ${name} = { file = "${self}/secrets/containers/${name}.age"; @@ -130,6 +139,17 @@ group = cfg.services.${service}.group.name; }; }; + + mkNetworkService = name: network: + nameValuePair "podman-network-${name}" { + description = "Podman network ${name} for ookflix"; + serviceConfig = { + Type = "oneshot"; + RemainsAfterExit = true; + ExecStart = "${getExe podman.package} network create -d bridge ${name}"; + ExecStop = "${getExe podman.package} network rm -f ${name}"; + }; + }; in { - inherit mkServiceSecret mkBasicServiceOptions mkServiceOptions mkServiceStateDir mkServiceUser mkUserOption mkPortOption mkGroupOption mkVolumeOption mkSubdomainOption; + inherit mkServiceStateFile mkServiceSecret mkBasicServiceOptions mkServiceOptions mkServiceStateDir mkServiceUser mkUserOption mkPortOption mkGroupOption mkVolumeOption mkSubdomainOption mkNetworkService; } diff --git a/modules/nixos/server/services/ookflix/monitors/default.nix b/modules/nixos/server/services/ookflix/monitors/default.nix new file mode 100644 index 0000000..3a4ec4f --- /dev/null +++ b/modules/nixos/server/services/ookflix/monitors/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./tautulli.nix + ]; +} diff --git a/modules/nixos/server/services/ookflix/tautulli.nix b/modules/nixos/server/services/ookflix/monitors/tautulli.nix similarity index 88% rename from modules/nixos/server/services/ookflix/tautulli.nix rename to modules/nixos/server/services/ookflix/monitors/tautulli.nix index 5d1ec5d..e012dd0 100644 --- a/modules/nixos/server/services/ookflix/tautulli.nix +++ b/modules/nixos/server/services/ookflix/monitors/tautulli.nix @@ -5,7 +5,7 @@ self, ... }: let - ookflixLib = import ./lib.nix {inherit lib config self;}; + ookflixLib = import ../lib.nix {inherit lib config self;}; inherit (ookflixLib) mkServiceUser mkServiceStateDir; inherit (lib) mkIf; inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; @@ -14,7 +14,7 @@ in { config = mkIf tautulli.enable { users = mkServiceUser tautulli.user.name; - systemd.tmpfiles = mkServiceStateDir "tautulli" tautulli.stateDir; + systemd.tmpfiles.settings.tautulliStateDir = mkServiceStateDir "tautulli"; virtualisation.oci-containers.containers = { # plex monitoring service tautulli = { diff --git a/modules/nixos/server/services/ookflix/networking/default.nix b/modules/nixos/server/services/ookflix/networking/default.nix new file mode 100644 index 0000000..9e862e6 --- /dev/null +++ b/modules/nixos/server/services/ookflix/networking/default.nix @@ -0,0 +1,7 @@ +{ + imports = [ + ./gluetun.nix + ./traefik.nix + # ./networks.nix + ]; +} diff --git a/modules/nixos/server/services/ookflix/gluetun.nix b/modules/nixos/server/services/ookflix/networking/gluetun.nix similarity index 82% rename from modules/nixos/server/services/ookflix/gluetun.nix rename to modules/nixos/server/services/ookflix/networking/gluetun.nix index cc56f80..4131a93 100644 --- a/modules/nixos/server/services/ookflix/gluetun.nix +++ b/modules/nixos/server/services/ookflix/networking/gluetun.nix @@ -5,10 +5,10 @@ self, ... }: let - ookflixLib = import ./lib.nix {inherit self lib config;}; + ookflixLib = import ../lib.nix {inherit self lib config;}; inherit (ookflixLib) mkServiceUser mkServiceSecret; inherit (lib) mkIf; - inherit (ook.lib.container) mkContainerEnvironment mkContainerPort; + inherit (ook.lib.container) mkContainerEnvironment; inherit (config.ooknet.server.ookflix.services) qbittorrent gluetun; in { config = mkIf gluetun.enable { @@ -21,7 +21,7 @@ in { # should make this an option. environmentFiles = [config.age.secrets.vpn_env.path]; ports = [ - (mkContainerPort qbittorrent.port) + "${toString qbittorrent.exposedPort}:${toString qbittorrent.port}" ]; environment = mkContainerEnvironment gluetun.user.id gluetun.group.id; extraOptions = [ diff --git a/modules/nixos/server/services/ookflix/networking/networks.nix b/modules/nixos/server/services/ookflix/networking/networks.nix new file mode 100644 index 0000000..3c99bf1 --- /dev/null +++ b/modules/nixos/server/services/ookflix/networking/networks.nix @@ -0,0 +1,28 @@ +{ + lib, + config, + pkgs, + ... +}: let + inherit (lib) mkIf getExe; + inherit (config.ooknet.server) ookflix; + inherit (config.virtualisation) podman; + podmanCommand = getExe podman.package; +in { + config = mkIf ookflix.enable { + systemd.services = { + "podman-ookflix-network" = { + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + SyslogIdentifier = "%N"; + }; + unitConfig = { + "RequiresMountsFor" = "%t/containers"; + }; + wantedBy = ["multi-user.target"]; + script = "${podmanCommand} network create --ignore --driver=bridge ookflix"; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/networking/traefik.nix b/modules/nixos/server/services/ookflix/networking/traefik.nix new file mode 100644 index 0000000..2adae8c --- /dev/null +++ b/modules/nixos/server/services/ookflix/networking/traefik.nix @@ -0,0 +1,80 @@ +{ + config, + lib, + ook, + self, + ... +}: let + ookflixLib = import ../lib.nix {inherit self lib config;}; + inherit (ookflixLib) mkServiceUser mkServiceSecret mkServiceStateDir mkServiceStateFile; + inherit (lib) mkIf; + inherit (ook.lib.container) mkContainerEnvironment mkContainerLabel mkContainerPort; + inherit (config.ooknet) server; + inherit (config.ooknet.server.ookflix.services) traefik; + inherit (config.ooknet.host) admin; +in { + config = mkIf traefik.enable { + users = mkServiceUser traefik.user.name; + systemd.tmpfiles.settings = { + traefikStateDir = mkServiceStateDir "traefik"; + traefikAcmeFile = mkServiceStateFile "traefik" "acme.json"; + }; + age.secrets = mkServiceSecret "cf_creds" "traefik"; + virtualisation.oci-containers.containers = { + # vpn container + traefik = mkIf traefik.enable { + autoStart = true; + image = "traefik:3.0"; + # should make this an option. + volumes = [ + "/run/podman/podman.sock:/var/run/docker.sock:ro" + "${traefik.stateDir}/acme.json:/acme.json" + ]; + ports = [ + "80:80" + "443:443" + (mkContainerPort traefik.port) + ]; + environmentFiles = [config.age.secrets.cf_creds.path]; + extraOptions = ["--security-opt=no-new-privileges:true"]; + cmd = [ + "--log.level=DEBUG" + "--api.insecure=true" + "--api.dashboard=true" + "--providers.docker=true" + "--providers.docker.exposedbydefault=false" + + "--certificatesresolvers.letsencrypt.acme.email=${admin.email}" + "--certificatesresolvers.letsencrypt.acme.storage=/acme.json" + "--certificatesresolvers.letsencrypt.acme.dnschallenge=true" + "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare" + + "--entrypoints.web.address=:80" + "--entrypoints.websecure.address=:443" + "--entrypoints.traefik.address=:${toString traefik.port}" + + "--entrypoints.websecure.forwardedHeaders.trustedIPs=103.21.244.0/22,103.22.200.0/22,103.31.4.0/22" # Cloudflare IPs + + "--entrypoints.web.http.redirections.entrypoint.to=websecure" + "--entrypoints.web.http.redirections.entrypoint.scheme=https" + + "--entrypoints.websecure.http.tls=true" + "--entrypoints.websecure.http.tls.certResolver=letsencrypt" + "--entrypoints.websecure.http.tls.domains[0].main=${server.domain}" + "--entrypoints.websecure.http.tls.domains[0].sans=*.${server.domain}" + ]; + + labels = mkContainerLabel { + name = "traefik"; + inherit (traefik) domain port; + homepage = { + group = "proxy"; + description = "reverse proxy"; + }; + }; + + environment = mkContainerEnvironment traefik.user.id traefik.group.id; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/options.nix b/modules/nixos/server/services/ookflix/options.nix index 3cddfdd..4b67c62 100644 --- a/modules/nixos/server/services/ookflix/options.nix +++ b/modules/nixos/server/services/ookflix/options.nix @@ -94,8 +94,11 @@ in { uid = 377; gid = 377; } - // {torrentPort = mkPortOption 58080 "Torrenting Port for qbittorrent" 58080;}; - jellyseer = mkServiceOptions "jellyseer" { + // { + torrentPort = mkPortOption 58080 "Torrenting Port for qbittorrent" 58080; + exposedPort = mkPortOption 8081 "Port exposed by qbittorrent" 8081; + }; + jellyseerr = mkServiceOptions "jellyseerr" { port = 5055; uid = 345; gid = 345; @@ -105,6 +108,16 @@ in { uid = 355; gid = 355; }; + traefik = mkServiceOptions "traefik" { + port = 8080; + uid = 389; + gid = 389; + }; + homepage = mkServiceOptions "homepage" { + port = 3000; + uid = 400; + gid = 400; + }; gluetun = mkBasicServiceOptions "gluetun" { uid = 356; gid = 357; diff --git a/modules/nixos/server/services/ookflix/podman.nix b/modules/nixos/server/services/ookflix/podman.nix new file mode 100644 index 0000000..963ab05 --- /dev/null +++ b/modules/nixos/server/services/ookflix/podman.nix @@ -0,0 +1,35 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkIf; + inherit (config.ooknet.host) admin; + inherit (config.ooknet.server) ookflix; +in { + config = mkIf ookflix.enable { + # add admin to podman group + users.groups.podman.members = [admin.name]; + virtualisation = { + # explicitly set this even though its the default value + # this enables the module below + oci-containers.backend = "podman"; + podman = { + # periodically prunes podman resources + # defaults to --all, weekly + autoPrune.enable = true; + + # aliases docker command to podman + dockerCompat = true; + + # makes the podman sockaet available in place of docker socket + dockerSocket.enable = true; + # settings for containers/networks/podman.json + defaultNetwork.settings = { + # allows udp port 53 on podmans network interface: podman+ + dns_enabled = true; + }; + }; + }; + }; +} diff --git a/modules/nixos/server/services/ookflix/streamers/default.nix b/modules/nixos/server/services/ookflix/streamers/default.nix new file mode 100644 index 0000000..9431035 --- /dev/null +++ b/modules/nixos/server/services/ookflix/streamers/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + ./plex.nix + ./jellyfin.nix + ]; +} diff --git a/modules/nixos/server/services/ookflix/jellyfin.nix b/modules/nixos/server/services/ookflix/streamers/jellyfin.nix similarity index 77% rename from modules/nixos/server/services/ookflix/jellyfin.nix rename to modules/nixos/server/services/ookflix/streamers/jellyfin.nix index 6f30b4b..46ba406 100644 --- a/modules/nixos/server/services/ookflix/jellyfin.nix +++ b/modules/nixos/server/services/ookflix/streamers/jellyfin.nix @@ -5,7 +5,7 @@ self, ... }: let - ookflixLib = import ./lib.nix {inherit lib config self;}; + ookflixLib = import ../lib.nix {inherit lib config self;}; inherit (ookflixLib) mkServiceStateDir mkServiceUser; inherit (lib) mkIf optionalAttrs; inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; @@ -15,7 +15,7 @@ in { config = mkIf services.jellyfin.enable { hardware.nvidia-container-toolkit.enable = gpuAcceleration.enable && gpuAcceleration.type == "nvidia"; users = mkServiceUser jellyfin.user.name; - systemd.tmpfiles = mkServiceStateDir "jellyfin" jellyfin.stateDir; + systemd.tmpfiles.settings.jellyfinStateDir = mkServiceStateDir "jellyfin"; virtualisation.oci-containers.containers = { # media streaming server # docs: @@ -36,18 +36,6 @@ in { description = "media-server streamer"; }; }; - - extraOptions = optionalAttrs gpuAcceleration.enable ( - if gpuAcceleration.type == "nvidia" - then [ - "--runtime=nvidia" - ] - else if gpuAcceleration.type == "intel" || "amd" - then [ - "--device=/dev/dri:/dev/dri" - ] - else [] - ); environment = mkContainerEnvironment jellyfin.user.id groups.media.id // {JELLYFIN_PublishedServerUrl = jellyfin.domain;} diff --git a/modules/nixos/server/services/ookflix/plex.nix b/modules/nixos/server/services/ookflix/streamers/plex.nix similarity index 69% rename from modules/nixos/server/services/ookflix/plex.nix rename to modules/nixos/server/services/ookflix/streamers/plex.nix index 7353e97..9c1d2d5 100644 --- a/modules/nixos/server/services/ookflix/plex.nix +++ b/modules/nixos/server/services/ookflix/streamers/plex.nix @@ -5,7 +5,7 @@ self, ... }: let - ookflixLib = import ./lib.nix {inherit lib config self;}; + ookflixLib = import ../lib.nix {inherit lib config self;}; inherit (ookflixLib) mkServiceUser mkServiceStateDir; inherit (lib) mkIf optionalAttrs; inherit (ook.lib.container) mkContainerLabel mkContainerEnvironment mkContainerPort; @@ -18,7 +18,7 @@ in { # users/group/directories configuration, see lib.nix users = mkServiceUser plex.user.name; - systemd.tmpfiles = mkServiceStateDir "plex" plex.stateDir; + systemd.tmpfiles.settings.plexStateDir = mkServiceStateDir "plex"; # container configuration virtualisation.oci-containers.containers = { @@ -29,8 +29,7 @@ in { hostname = "plex"; ports = [(mkContainerPort plex.port)]; volumes = [ - "${volumes.media.movies}:/data/movies" - "${volumes.media.tv}:/data/tv" + "${volumes.media.root}:/data" "${plex.stateDir}:/config" ]; labels = mkContainerLabel { @@ -41,21 +40,6 @@ in { description = "media-server streamer"; }; }; - extraOptions = optionalAttrs gpuAcceleration.enable ( - if gpuAcceleration.type == "nvidia" - then [ - "--runtime=nvidia" - ] - else if gpuAcceleration.type == "intel" - then [ - "--device=/dev/dri:/dev/dri" - ] - else if gpuAcceleration.type == "amd" - then [ - "--device=/dev/dri:/dev/dri" - ] - else [] - ); environment = mkContainerEnvironment plex.user.id groups.media.id // optionalAttrs (gpuAcceleration.enable && gpuAcceleration.type == "nvidia") { From 6a3585e7e5941fe8b16e5dba7daddee74d261ad3 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 4 Dec 2024 13:20:48 +1100 Subject: [PATCH 075/213] lib: fix mkLabel function --- outputs/lib/containers.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/outputs/lib/containers.nix b/outputs/lib/containers.nix index 7a30393..69c0906 100644 --- a/outputs/lib/containers.nix +++ b/outputs/lib/containers.nix @@ -43,7 +43,7 @@ "traefik.http.routers.${name}.rule" = "Host(`${args.domain}`)"; "traefik.http.routers.${name}.entrypoints" = "websecure"; "traefik.http.routers.${name}.tls" = "true"; - "traefik.http.routes.${name}.certresolver" = "cloudflare"; + "traefik.http.routers.${name}.tls.certresolver" = "letsencrypt"; }) # traefik service labels // (optionalAttrs ((args ? domain) && (args ? port)) { From 4fbe8fcfbfd504fb599bf01d9426cbd066847b2f Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 4 Dec 2024 13:21:02 +1100 Subject: [PATCH 076/213] secrets: add cloudflare credentials secret --- secrets/containers/cf_creds.age | 19 +++++++++++++++++++ secrets/secrets.nix | 1 + 2 files changed, 20 insertions(+) create mode 100644 secrets/containers/cf_creds.age diff --git a/secrets/containers/cf_creds.age b/secrets/containers/cf_creds.age new file mode 100644 index 0000000..702af9d --- /dev/null +++ b/secrets/containers/cf_creds.age @@ -0,0 +1,19 @@ +age-encryption.org/v1 +-> ssh-ed25519 xeHnUA orzYvtHssnqm5RxM5aa2/9C8WE+b71dDA2I2Xazhc2k +zkiBhnB7MdSIxrT/Sh14pHGU9ipGkBrrhNrHjW6lbJw +-> ssh-ed25519 6HvatA tABXMcWyBkSJWrl3MM76eJGJSU0XKQTG6lmFWIS/qxs +ZZ3PYHKqbbdz0kDCTXhQBGCnWGsXLqZmdNjlWpT8SY4 +-> ssh-ed25519 3DwG4w GUdLU60u2plRSDoFkAoNep5USX5Lj6jLrIQHzxYyPkI +5dnetJBkJeSe12iczuOMnJO8K0gkB5qhPL1UbGAslzI +-> ssh-ed25519 Nn8WxA wnQzj5PqL1EoXisYGabcHzChGBZWvis+CSTE+6eCMEk +fw4XLdF7kIIWBVVDu3DBxtxdYxBSsXozpJQ7p0No8I4 +-> ssh-ed25519 Gd+9pg TIdiOlNUhp4fkQPQi3PItzVBssM1TxoDYZNCB0GYryw +Ch+pJ6BEO/oUTeUn3t8qaiVuLaRgf9GUO4jpAgnJstY +-> ssh-ed25519 eMj+Jg 83Cbf9k7T0DRcE7hFchQWEj/pR+qNGTLIdXDmbWMeT4 +PqOzucTkTSQg92Vd8ZMLX6cDKyESCE4v9VVHJlAfFyg +-> ssh-ed25519 MQ/7Ew f4axkHyjiTOsbiYu90MAirHKoB9S70dK11JDtMKmSkc +Rb2+dIewpW0bL+qJtAxIgVAyWqTDZI9dcwMQR/0pg3s +-> ssh-ed25519 3DwG4w FYRpJ1zJZmOil2/X+URrw03KXZk7qZoMO1/P+BJGCxo +SRBJ/FOUbisy7Dhd5tXd4fN8HWM95L6oDQOjzmM5St8 +--- /7SydLy/XxsnVqTD5ffym1MnyKzVyvvhIbazmf4oB18 +49aCrB"e5n9uF?ykbDB+͙DbHb^͝LӻV*^˖LϙJ8_6S$+K:$ \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 0a0a933..d48d549 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -8,4 +8,5 @@ in { "ooknet_org.age".publicKeys = [users.ooks] ++ workstations; "mullvad_wg.age".publicKeys = [users.ooks] ++ workstations ++ servers; "containers/vpn_env.age".publicKeys = [users.ooks] ++ workstations ++ servers; + "containers/cf_creds.age".publicKeys = [users.ooks] ++ workstations ++ servers; } From df9d1625d7f74240a6e04a75bea194cd0cf88edf Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 5 Dec 2024 21:34:49 +1100 Subject: [PATCH 077/213] nixos: remove service based media server --- .../server/services/media-server/default.nix | 36 --- .../media-server/file-permissions.nix | 42 --- .../server/services/media-server/jellyfin.nix | 21 -- .../server/services/media-server/options.nix | 254 ------------------ .../server/services/media-server/plex.nix | 21 -- .../server/services/media-server/prowlarr.nix | 51 ---- .../server/services/media-server/radarr.nix | 21 -- .../server/services/media-server/sonarr.nix | 21 -- .../services/media-server/transmission.nix | 80 ------ .../server/services/media-server/users.nix | 28 -- .../server/services/media-server/vpn.nix | 51 ---- 11 files changed, 626 deletions(-) delete mode 100644 modules/nixos/server/services/media-server/default.nix delete mode 100644 modules/nixos/server/services/media-server/file-permissions.nix delete mode 100644 modules/nixos/server/services/media-server/jellyfin.nix delete mode 100644 modules/nixos/server/services/media-server/options.nix delete mode 100644 modules/nixos/server/services/media-server/plex.nix delete mode 100644 modules/nixos/server/services/media-server/prowlarr.nix delete mode 100644 modules/nixos/server/services/media-server/radarr.nix delete mode 100644 modules/nixos/server/services/media-server/sonarr.nix delete mode 100644 modules/nixos/server/services/media-server/transmission.nix delete mode 100644 modules/nixos/server/services/media-server/users.nix delete mode 100644 modules/nixos/server/services/media-server/vpn.nix diff --git a/modules/nixos/server/services/media-server/default.nix b/modules/nixos/server/services/media-server/default.nix deleted file mode 100644 index 717e673..0000000 --- a/modules/nixos/server/services/media-server/default.nix +++ /dev/null @@ -1,36 +0,0 @@ -{ - lib, - config, - inputs, - ... -}: let - inherit (lib) mkIf elem; - inherit (config.ooknet.server) services; -in { - imports = [ - ./plex.nix - ./users.nix - ./options.nix - ./jellyfin.nix - ./transmission.nix - ./sonarr.nix - ./radarr.nix - ./prowlarr.nix - ./file-permissions.nix - ./vpn.nix - inputs.vpn-confinement.nixosModules.default - ]; - - # short cut for enabling all media-server modules - config = mkIf (elem "media-server" services) { - ooknet.server.media-server = { - enable = true; - jellyfin.enable = true; - plex.enable = true; - transmission.enable = true; - radarr.enable = true; - sonarr.enable = true; - prowlarr.enable = true; - }; - }; -} diff --git a/modules/nixos/server/services/media-server/file-permissions.nix b/modules/nixos/server/services/media-server/file-permissions.nix deleted file mode 100644 index b791728..0000000 --- a/modules/nixos/server/services/media-server/file-permissions.nix +++ /dev/null @@ -1,42 +0,0 @@ -{ - config, - lib, - ... -}: let - inherit (lib) mkIf; - inherit (config.ooknet.server) media-server; - inherit (config.ooknet.server.media-server) storage groups users; - - contentPermissions = { - group = groups.media; - user = "root"; - mode = "0775"; - }; - - downloadPermissions = { - group = groups.media; - user = users.downloader; - mode = "0775"; - }; -in { - config = mkIf media-server.enable { - systemd.tmpfiles.settings = { - content-dirs = { - "${storage.content.root}"."d" = contentPermissions; - "${storage.content.movies}"."d" = contentPermissions; - "${storage.content.tv}"."d" = contentPermissions; - "${storage.content.music}"."d" = contentPermissions; - "${storage.content.books}"."d" = contentPermissions; - }; - download-dirs = { - "${storage.downloads.root}"."d" = downloadPermissions; - "${storage.downloads.incomplete}"."d" = downloadPermissions; - "${storage.downloads.watch}"."d" = downloadPermissions; - "${storage.downloads.manual}"."d" = downloadPermissions; - "${storage.downloads.radarr}"."d" = downloadPermissions; - "${storage.downloads.sonarr}"."d" = downloadPermissions; - "${storage.downloads.readarr}"."d" = downloadPermissions; - }; - }; - }; -} diff --git a/modules/nixos/server/services/media-server/jellyfin.nix b/modules/nixos/server/services/media-server/jellyfin.nix deleted file mode 100644 index b8c6365..0000000 --- a/modules/nixos/server/services/media-server/jellyfin.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ - config, - lib, - ... -}: let - inherit (lib) mkIf; - inherit (config.ooknet.server) media-server; - inherit (config.ooknet.server.media-server) storage groups users domain proxy; -in { - config = mkIf media-server.jellyfin.enable { - services.jellyfin = { - enable = true; - user = users.jellyfin; - group = groups.media; - dataDir = storage.state.jellyfin; - openFirewall = true; - }; - ooknet.server.webserver.caddy.enable = true; - services.caddy.virtualHosts."${domain.jellyfin}".extraConfig = proxy.jellyfin; - }; -} diff --git a/modules/nixos/server/services/media-server/options.nix b/modules/nixos/server/services/media-server/options.nix deleted file mode 100644 index 85dcc8b..0000000 --- a/modules/nixos/server/services/media-server/options.nix +++ /dev/null @@ -1,254 +0,0 @@ -{ - lib, - config, - ... -}: let - inherit (lib) mkOption mkEnableOption; - inherit (lib.types) path port str lines; - inherit (config.ooknet) server; - cfg = server.media-server; - - mkSubdomain = name: - mkOption { - type = str; - default = "${name}.${server.domain}"; - }; - - mkProxy = port: '' - encode zstd gzip - reverse_proxy localhost:${toString port} { - header_up X-Real-IP {remote_host} - header_up X-Forwarded-For {remote_host} - header_up X-Forwarded-Proto {scheme} - } - ''; -in { - options.ooknet.server.media-server = { - enable = mkEnableOption "Enable media server functionality"; - - jellyfin.enable = mkEnableOption "Enable the Jellyfin module"; - plex.enable = mkEnableOption "Enable Plex module"; - transmission.enable = mkEnableOption "Enable Transmission module"; - radarr.enable = mkEnableOption "Enable Radarr module"; - sonarr.enable = mkEnableOption "Enable Sonarr module"; - prowlarr.enable = mkEnableOption "Enable Sonarr module"; - - storage = { - mediaRoot = mkOption { - type = path; - default = "/jellyfin"; - description = "Root directory for all media-related storage"; - }; - - content = { - root = mkOption { - type = path; - default = "${cfg.storage.mediaRoot}/content"; - description = "Root directory for media content"; - }; - movies = mkOption { - type = path; - default = "${cfg.storage.content.root}/movies"; - }; - tv = mkOption { - type = path; - default = "${cfg.storage.content.root}/tv"; - }; - music = mkOption { - type = path; - default = "${cfg.storage.content.root}/music"; - }; - books = mkOption { - type = path; - default = "${cfg.storage.content.root}/books"; - }; - }; - - downloads = { - root = mkOption { - type = path; - default = "${cfg.storage.mediaRoot}/downloads"; - }; - incomplete = mkOption { - type = path; - default = "${cfg.storage.downloads.root}/.incomplete"; - }; - watch = mkOption { - type = path; - default = "${cfg.storage.downloads.root}/.watch"; - }; - manual = mkOption { - type = path; - default = "${cfg.storage.downloads.root}/manual"; - }; - radarr = mkOption { - type = path; - default = "${cfg.storage.downloads.root}/radarr"; - }; - sonarr = mkOption { - type = path; - default = "${cfg.storage.downloads.root}/sonarr"; - }; - readarr = mkOption { - type = path; - default = "${cfg.storage.downloads.root}/readarr"; - }; - }; - - state = { - root = mkOption { - type = path; - default = "/var/lib"; - description = "Root directory for service state"; - }; - jellyfin = mkOption { - type = path; - default = "${cfg.storage.state.root}/jellyfin"; - }; - plex = mkOption { - type = path; - default = "${cfg.storage.state.root}/plex"; - }; - sonarr = mkOption { - type = path; - default = "${cfg.storage.state.root}/sonarr"; - }; - prowlarr = mkOption { - type = path; - default = "${cfg.storage.state.root}/prowlarr"; - }; - radarr = mkOption { - type = path; - default = "${cfg.storage.state.root}/radarr"; - }; - transmission = mkOption { - type = path; - default = "${cfg.storage.state.root}/transmission"; - }; - }; - }; - - groups = { - media = mkOption { - type = str; - default = "media"; - }; - sonarr = mkOption { - type = str; - default = "sonarr"; - }; - prowlarr = mkOption { - type = str; - default = "prowlarr"; - }; - radarr = mkOption { - type = str; - default = "radarr"; - }; - }; - - users = { - jellyfin = mkOption { - type = str; - default = "jellyfin"; - }; - plex = mkOption { - type = str; - default = "plex"; - }; - sonarr = mkOption { - type = str; - default = "sonarr"; - }; - radarr = mkOption { - type = str; - default = "radarr"; - }; - transmission = mkOption { - type = str; - default = "transmission"; - }; - prowlarr = mkOption { - type = str; - default = "prowlarr"; - }; - downloader = mkOption { - type = str; - default = "downloader"; - }; - streamer = mkOption { - type = str; - default = "streamer"; - }; - }; - - ports = { - jellyfin = mkOption { - type = port; - default = 8096; - }; - plex = mkOption { - type = port; - default = 32400; - }; - transmission = { - web = mkOption { - type = port; - default = 9091; - }; - peer = mkOption { - type = port; - default = 50000; - }; - }; - sonarr = mkOption { - type = port; - default = 8989; - }; - radarr = mkOption { - type = port; - default = 7878; - }; - prowlarr = mkOption { - type = port; - default = 9696; - }; - }; - - domain = { - jellyfin = mkSubdomain "jellyfin"; - plex = mkSubdomain "plex"; - transmission = mkSubdomain "transmission"; - sonarr = mkSubdomain "sonarr"; - radarr = mkSubdomain "radarr"; - prowlarr = mkSubdomain "prowlarr"; - }; - - proxy = { - jellyfin = mkOption { - type = lines; - default = mkProxy cfg.ports.jellyfin; - }; - plex = mkOption { - type = lines; - default = mkProxy cfg.ports.plex; - }; - sonarr = mkOption { - type = lines; - default = mkProxy cfg.ports.sonarr; - }; - radarr = mkOption { - type = lines; - default = mkProxy cfg.ports.radarr; - }; - prowlarr = mkOption { - type = lines; - default = mkProxy cfg.ports.prowlarr; - }; - transmission = mkOption { - type = lines; - default = mkProxy cfg.ports.transmission.web; - }; - }; - }; -} diff --git a/modules/nixos/server/services/media-server/plex.nix b/modules/nixos/server/services/media-server/plex.nix deleted file mode 100644 index 7770f8d..0000000 --- a/modules/nixos/server/services/media-server/plex.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ - config, - lib, - ... -}: let - inherit (lib) mkIf; - inherit (config.ooknet.server) media-server; - inherit (config.ooknet.server.media-server) groups users storage domain proxy; -in { - config = mkIf media-server.plex.enable { - services.plex = { - enable = true; - user = users.plex; - group = groups.media; - dataDir = storage.state.plex; - openFirewall = true; - }; - ooknet.server.webserver.caddy.enable = true; - services.caddy.virtualHosts."${domain.plex}".extraConfig = proxy.plex; - }; -} diff --git a/modules/nixos/server/services/media-server/prowlarr.nix b/modules/nixos/server/services/media-server/prowlarr.nix deleted file mode 100644 index ed59158..0000000 --- a/modules/nixos/server/services/media-server/prowlarr.nix +++ /dev/null @@ -1,51 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: let - inherit (lib) mkIf getExe; - inherit (config.ooknet.server) media-server; - inherit (config.ooknet.server.media-server) storage users groups domain proxy ports; -in { - config = mkIf media-server.prowlarr.enable { - # we dont use the nixpkgs prowlarr service module because it lacks the option to - # declare dataDir, user and group. - - # setup user - users.users.prowlarr = { - group = groups.prowlarr; - home = storage.state.prowlarr; - uid = 293; - isSystemUser = true; - }; - users.groups.prowlarr = {}; - - # basic systemd service - systemd = { - services.prowlarr = { - description = "Prowlarr"; - after = ["network.target"]; - wantedBy = ["multi-user.target"]; - - serviceConfig = { - Type = "simple"; - User = users.prowlarr; - group = groups.prowlarr; - ExecStart = "${getExe pkgs.prowlarr} -nobrowser -data=${storage.state.prowlarr}"; - Restart = "on-failure"; - }; - }; - tmpfiles.settings.prowlarrDirs = { - "${storage.state.prowlarr}"."d" = { - mode = "0700"; - user = users.prowlarr; - group = groups.prowlarr; - }; - }; - }; - networking.firewall.allowedTCPPorts = [ports.prowlarr]; - ooknet.server.webserver.caddy.enable = true; - services.caddy.virtualHosts."${domain.prowlarr}".extraConfig = proxy.prowlarr; - }; -} diff --git a/modules/nixos/server/services/media-server/radarr.nix b/modules/nixos/server/services/media-server/radarr.nix deleted file mode 100644 index a523c0a..0000000 --- a/modules/nixos/server/services/media-server/radarr.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ - config, - lib, - ... -}: let - inherit (lib) mkIf; - inherit (config.ooknet.server) media-server; - inherit (config.ooknet.server.media-server) storage users groups domain proxy; -in { - config = mkIf media-server.radarr.enable { - services.radarr = { - enable = true; - user = users.radarr; - group = groups.media; - dataDir = storage.state.radarr; - openFirewall = true; - }; - ooknet.server.webserver.caddy.enable = true; - services.caddy.virtualHosts."${domain.radarr}".extraConfig = proxy.radarr; - }; -} diff --git a/modules/nixos/server/services/media-server/sonarr.nix b/modules/nixos/server/services/media-server/sonarr.nix deleted file mode 100644 index cfa06bc..0000000 --- a/modules/nixos/server/services/media-server/sonarr.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ - config, - lib, - ... -}: let - inherit (lib) mkIf; - inherit (config.ooknet.server) media-server; - inherit (config.ooknet.server.media-server) storage users groups domain proxy; -in { - config = mkIf media-server.sonarr.enable { - services.sonarr = { - enable = true; - user = users.sonarr; - group = groups.media; - dataDir = storage.state.sonarr; - openFirewall = true; - }; - ooknet.server.webserver.caddy.enable = true; - services.caddy.virtualHosts."${domain.sonarr}".extraConfig = proxy.sonarr; - }; -} diff --git a/modules/nixos/server/services/media-server/transmission.nix b/modules/nixos/server/services/media-server/transmission.nix deleted file mode 100644 index 1035024..0000000 --- a/modules/nixos/server/services/media-server/transmission.nix +++ /dev/null @@ -1,80 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: let - inherit (lib) mkIf; - inherit (builtins) concatStringsSep; - inherit (config.ooknet.server) media-server; - inherit (config.ooknet.server.media-server) storage ports users groups domain proxy; -in { - config = mkIf media-server.transmission.enable { - services.transmission = { - enable = true; - package = pkgs.transmission_4; - - # systemd service permissions - user = users.downloader; - group = groups.media; - - # location of transmission config dir - home = storage.state.transmission; - - # web ui - webHome = pkgs.flood-for-transmission; - - # additional configurations - # see - settings = { - # enable in completed directory - # this is where files will be placed while still being downloaded - incomplete-dir-enabled = true; - - # enable the watch directory - # this will look for any new torrent files and start downloading them - watch-dir-enabled = true; - - # location of the main download directories - download-dir = storage.downloads.root; - incomplete-dir = storage.downloads.incomplete; - watch-dir = storage.downloads.watch; - - rpc-authentication-required = false; - # rpc settings - # rpc is how we connect to the service remotely - rpc-port = ports.transmission.web; - - # what ip addresses are allowed to connect through rpc - rpc-whitelist-enabled = true; - rpc-whitelist = concatStringsSep "," [ - # localhost - "127.0.0.1" - # generic home networks - "192.168.*" - "10.*" - ]; - - rpc-bind-address = "192.168.15.1"; - - # basic anti bruteforce protection - anti-brute-force-enabled = true; - - # how many authentication attempts can be made before the rpc server will deny any further - # authentication attempts. - anti-brute-force-threshold = 10; - - peer-port = ports.transmission.peer; - port-forwarding-enabled = false; - - # private trackers usually require disabling these - utp-enabled = false; - dht-enabled = false; - pex-enabled = false; - lpd-enabled = false; - }; - }; - ooknet.server.webserver.caddy.enable = true; - services.caddy.virtualHosts."${domain.transmission}".extraConfig = proxy.transmission; - }; -} diff --git a/modules/nixos/server/services/media-server/users.nix b/modules/nixos/server/services/media-server/users.nix deleted file mode 100644 index 04e1cf4..0000000 --- a/modules/nixos/server/services/media-server/users.nix +++ /dev/null @@ -1,28 +0,0 @@ -{ - config, - lib, - ... -}: let - inherit (lib) elem mkIf; - inherit (config.ooknet.server) services; -in { - config = mkIf (elem "media-server" services) { - users = { - groups = { - downloader = {}; - media = {}; - streamer = {}; - }; - users = { - downloader = { - isSystemUser = true; - group = "downloader"; - }; - streamer = { - isSystemUser = true; - group = "streamer"; - }; - }; - }; - }; -} diff --git a/modules/nixos/server/services/media-server/vpn.nix b/modules/nixos/server/services/media-server/vpn.nix deleted file mode 100644 index 512b354..0000000 --- a/modules/nixos/server/services/media-server/vpn.nix +++ /dev/null @@ -1,51 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: let - inherit (lib) mkIf; - inherit (config.ooknet.server.media-server) ports transmission; - inherit (config.age) secrets; - inherit (builtins) attrValues; -in { - config = mkIf transmission.enable { - environment.systemPackages = attrValues { - inherit (pkgs) wireguard-tools dnsutils; - }; - vpnNamespaces.wg = { - enable = true; - wireguardConfigFile = secrets."mullvad_wg.conf".path; - accessibleFrom = [ - "192.168.20.0/24" - "127.0.0.1" - "10.0.0.0/8" - ]; - openVPNPorts = [ - # Transmission - { - port = ports.transmission.peer; - protocol = "both"; - } - ]; - portMappings = [ - # Transmission - { - from = ports.transmission.web; - to = ports.transmission.web; - } - ]; - }; - systemd.services.transmission.vpnConfinement = { - enable = true; - vpnNamespace = "wg"; - }; - systemd.services.wg = { - serviceConfig = { - LogLevelMax = "debug"; - StandardOutput = "journal"; - StandardError = "journal"; - }; - }; - }; -} From 0555fe90c40114e338c38db64353941c3cd5ef6b Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 6 Dec 2024 13:51:34 +1100 Subject: [PATCH 078/213] nixos: remove service based media server --- modules/nixos/server/services/default.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/nixos/server/services/default.nix b/modules/nixos/server/services/default.nix index 468b980..5bad467 100644 --- a/modules/nixos/server/services/default.nix +++ b/modules/nixos/server/services/default.nix @@ -2,7 +2,6 @@ imports = [ ./website ./forgejo - ./media-server ./ookflix ]; } From 7c5bd4329570f09871cc4ad1579e5575fa0189dc Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 6 Dec 2024 13:51:50 +1100 Subject: [PATCH 079/213] lib: add service helper function --- outputs/lib/default.nix | 1 + outputs/lib/services.nix | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 outputs/lib/services.nix diff --git a/outputs/lib/default.nix b/outputs/lib/default.nix index 4492913..c695419 100644 --- a/outputs/lib/default.nix +++ b/outputs/lib/default.nix @@ -11,6 +11,7 @@ mkNeovim = import ./mkNeovim.nix {inherit inputs;}; math = import ./math.nix {inherit lib;}; container = import ./containers.nix {inherit lib config;}; + services = import ./services.nix {inherit lib;}; color = let check = import ./color/check.nix {inherit lib;}; types = import ./color/types.nix { diff --git a/outputs/lib/services.nix b/outputs/lib/services.nix new file mode 100644 index 0000000..648f3e7 --- /dev/null +++ b/outputs/lib/services.nix @@ -0,0 +1,12 @@ +{lib, ...}: let + inherit (lib) recursiveUpdate; + mkGraphicalService = recursiveUpdate { + Unit = { + After = ["graphical-session.target"]; + PartOf = ["graphical-session.target"]; + }; + Install.WantedBy = ["graphical-session.target"]; + }; +in { + inherit mkGraphicalService; +} From bf43fc8e64e8e4ea7c6482b2c61a86e7f438ef09 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 6 Dec 2024 13:52:09 +1100 Subject: [PATCH 080/213] nixos: pass ook args to home-manager --- modules/nixos/base/home-manager.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/nixos/base/home-manager.nix b/modules/nixos/base/home-manager.nix index ae6e4ee..29bb102 100644 --- a/modules/nixos/base/home-manager.nix +++ b/modules/nixos/base/home-manager.nix @@ -6,6 +6,7 @@ lib, config, hozen, + ook, ... }: let inherit (lib) mkIf; @@ -17,7 +18,7 @@ in { useUserPackages = true; backupFileExtension = "hm.old"; verbose = true; - extraSpecialArgs = {inherit hozen inputs inputs' self self';}; + extraSpecialArgs = {inherit ook hozen inputs inputs' self self';}; users.${admin.name} = { imports = ["${self}/modules/home/base"]; }; From 664b22c2bba85cf965019577875ef2964e7c8e5a Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 6 Dec 2024 13:52:32 +1100 Subject: [PATCH 081/213] home: add tailscale-systray service --- modules/home/workstation/tools/default.nix | 1 + .../workstation/tools/tailscale-applet.nix | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 modules/home/workstation/tools/tailscale-applet.nix diff --git a/modules/home/workstation/tools/default.nix b/modules/home/workstation/tools/default.nix index 91c44b2..5f911c0 100644 --- a/modules/home/workstation/tools/default.nix +++ b/modules/home/workstation/tools/default.nix @@ -1,6 +1,7 @@ { imports = [ ./ookpower.nix + ./tailscale-applet.nix ./live-buds-cli.nix ./virt-manager.nix ./1password.nix diff --git a/modules/home/workstation/tools/tailscale-applet.nix b/modules/home/workstation/tools/tailscale-applet.nix new file mode 100644 index 0000000..723365d --- /dev/null +++ b/modules/home/workstation/tools/tailscale-applet.nix @@ -0,0 +1,20 @@ +{ + lib, + pkgs, + ook, + ... +}: let + inherit (ook.lib.services) mkGraphicalService; + inherit (lib) getExe; +in { + systemd.user.services.tailscale-applet = mkGraphicalService { + Unit = { + Description = "Tray applet for tailscale"; + Requires = ["tray.target"]; + }; + Service = { + ExecStart = "${getExe pkgs.tailscale-systray}"; + Restart = "on-abort"; + }; + }; +} From 671da8f32273f252df3fbad05a4eb06192aa1aa3 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 7 Dec 2024 22:51:34 +1100 Subject: [PATCH 082/213] home: add aseprite package --- modules/home/workstation/creative/aseprite.nix | 13 +++++++++++++ modules/home/workstation/creative/default.nix | 1 + 2 files changed, 14 insertions(+) create mode 100644 modules/home/workstation/creative/aseprite.nix diff --git a/modules/home/workstation/creative/aseprite.nix b/modules/home/workstation/creative/aseprite.nix new file mode 100644 index 0000000..14920f8 --- /dev/null +++ b/modules/home/workstation/creative/aseprite.nix @@ -0,0 +1,13 @@ +{ + lib, + osConfig, + pkgs, + ... +}: let + inherit (lib) mkIf elem; + inherit (osConfig.ooknet.workstation) profiles; +in { + config = mkIf (elem "creative" profiles) { + home.packages = [pkgs.aseprite]; + }; +} diff --git a/modules/home/workstation/creative/default.nix b/modules/home/workstation/creative/default.nix index def6f08..2c7c3ff 100644 --- a/modules/home/workstation/creative/default.nix +++ b/modules/home/workstation/creative/default.nix @@ -1,5 +1,6 @@ { imports = [ ./inkscape.nix + ./aseprite.nix ]; } From aaa88d49d770fbe8726af78829fb6656d5fd4895 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 7 Dec 2024 22:52:48 +1100 Subject: [PATCH 083/213] nvf: 0.7 changes --- outputs/pkgs/ook-vim/default.nix | 1 + outputs/pkgs/ook-vim/opts.nix | 9 +++++++++ outputs/pkgs/ook-vim/settings.nix | 9 --------- 3 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 outputs/pkgs/ook-vim/opts.nix diff --git a/outputs/pkgs/ook-vim/default.nix b/outputs/pkgs/ook-vim/default.nix index c460a8c..93fee2d 100644 --- a/outputs/pkgs/ook-vim/default.nix +++ b/outputs/pkgs/ook-vim/default.nix @@ -1,6 +1,7 @@ { imports = [ ./settings.nix + ./opts.nix ./theme.nix ./keymaps.nix ./plugins diff --git a/outputs/pkgs/ook-vim/opts.nix b/outputs/pkgs/ook-vim/opts.nix new file mode 100644 index 0000000..6be19b6 --- /dev/null +++ b/outputs/pkgs/ook-vim/opts.nix @@ -0,0 +1,9 @@ +{ + vim = { + options = { + tabstop = 2; + shiftwidth = 2; + autoindent = true; + }; + }; +} diff --git a/outputs/pkgs/ook-vim/settings.nix b/outputs/pkgs/ook-vim/settings.nix index 5c41a32..ba2287a 100644 --- a/outputs/pkgs/ook-vim/settings.nix +++ b/outputs/pkgs/ook-vim/settings.nix @@ -1,9 +1,6 @@ {pkgs, ...}: { vim = { package = pkgs.neovim-unwrapped; - leaderKey = " "; - tabWidth = 2; - autoIndent = true; searchCase = "smart"; enableLuaLoader = true; enableEditorconfig = true; @@ -14,10 +11,4 @@ enable = false; }; }; - # Additional sets can be added here - # vim.luaConfigRC.basic = - # entryAfter ["entryAfter"] #lua - # '' - # - # ''; } From 4dd03e713b91a449b511781dcc101a8d68c6e2f4 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 7 Dec 2024 22:53:04 +1100 Subject: [PATCH 084/213] flake: switch to nvf main branch --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 05fe767..0ad60ea 100644 --- a/flake.nix +++ b/flake.nix @@ -35,7 +35,7 @@ inputs.nixpkgs.follows = "nixpkgs"; }; - nvf.url = "github:notashelf/nvf/v0.7"; + nvf.url = "github:notashelf/nvf"; # confine vpns to specific systemd services vpn-confinement.url = "github:Maroka-chan/VPN-Confinement"; From 3cb560dfe1870713bf6c8f1b5b4e107ed95c6bff Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 7 Dec 2024 22:53:09 +1100 Subject: [PATCH 085/213] flake: bump --- flake.lock | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 57d703d..b5cd5e4 100644 --- a/flake.lock +++ b/flake.lock @@ -1061,6 +1061,7 @@ "plugin-registers": "plugin-registers", "plugin-rose-pine": "plugin-rose-pine", "plugin-rtp-nvim": "plugin-rtp-nvim", + "plugin-run-nvim": "plugin-run-nvim", "plugin-rustaceanvim": "plugin-rustaceanvim", "plugin-smartcolumn": "plugin-smartcolumn", "plugin-sqls-nvim": "plugin-sqls-nvim", @@ -1083,16 +1084,15 @@ "systems": "systems_4" }, "locked": { - "lastModified": 1732835777, - "narHash": "sha256-srgGCL+4ZwY5Zf7jOIhSC/6S9kf32/Vu9EWMwX818io=", + "lastModified": 1733489853, + "narHash": "sha256-Ir2dsp+e3xTVSmpV+et6DjsVyoaVgctARir+D8hn7Xg=", "owner": "notashelf", "repo": "nvf", - "rev": "fee1b46924d34a5ba569f37dfd92a761ea373cf2", + "rev": "f672d3cdee3617ad1321808f51929b2d2dbb5133", "type": "github" }, "original": { "owner": "notashelf", - "ref": "v0.7", "repo": "nvf", "type": "github" } @@ -2694,6 +2694,22 @@ "type": "github" } }, + "plugin-run-nvim": { + "flake": false, + "locked": { + "lastModified": 1732918526, + "narHash": "sha256-kiszNmZZDXG8tAPMQKuGJDCkqCMzsWT7BkCvkVsH2lA=", + "owner": "diniamo", + "repo": "run.nvim", + "rev": "d867466e01b8fa4e54a589b9ef446cf43fb966de", + "type": "github" + }, + "original": { + "owner": "diniamo", + "repo": "run.nvim", + "type": "github" + } + }, "plugin-rustaceanvim": { "flake": false, "locked": { From 3f1184697726d737f86356d78cc9a21794ec1495 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 8 Dec 2024 23:04:16 +1100 Subject: [PATCH 086/213] nixos: initial bitmap font support --- hosts/ooksdesk/default.nix | 2 +- modules/home/console/tools/starship.nix | 4 +- modules/home/workstation/appearance/fonts.nix | 2 + .../hyprland/components/waybar.nix | 20 +++++++-- .../hyprland/settings/appearance.nix | 27 ++++++++---- modules/home/workstation/terminal/foot.nix | 16 ++++--- modules/nixos/appearance/options.nix | 24 ++++++++++- modules/nixos/workstation/options.nix | 2 +- modules/nixos/workstation/themes/default.nix | 1 + modules/nixos/workstation/themes/hozen.nix | 42 +++++++++++++++++++ 10 files changed, 118 insertions(+), 22 deletions(-) create mode 100644 modules/nixos/workstation/themes/hozen.nix diff --git a/hosts/ooksdesk/default.nix b/hosts/ooksdesk/default.nix index ccb862e..b3f3359 100644 --- a/hosts/ooksdesk/default.nix +++ b/hosts/ooksdesk/default.nix @@ -18,7 +18,7 @@ }; workstation = { environment = "hyprland"; - theme = "minimal"; + theme = "hozen"; profiles = ["creative" "virtualization" "gaming" "media" "communication" "productivity"]; default = { browser = "firefox"; diff --git a/modules/home/console/tools/starship.nix b/modules/home/console/tools/starship.nix index deb4449..95cd762 100644 --- a/modules/home/console/tools/starship.nix +++ b/modules/home/console/tools/starship.nix @@ -51,9 +51,9 @@ in { elixir.symbol = " "; elm.symbol = " "; gcloud.symbol = " "; - git_branch.symbol = " "; + git_branch.symbol = ""; golang.symbol = " "; - hg_branch.symbol = " "; + hg_branch.symbol = ""; java.symbol = " "; julia.symbol = " "; memory_usage.symbol = "󰍛 "; diff --git a/modules/home/workstation/appearance/fonts.nix b/modules/home/workstation/appearance/fonts.nix index 2354d11..1a42574 100644 --- a/modules/home/workstation/appearance/fonts.nix +++ b/modules/home/workstation/appearance/fonts.nix @@ -13,5 +13,7 @@ in { pkgs.noto-fonts pkgs.noto-fonts-cjk-sans pkgs.noto-fonts-emoji + (pkgs.nerdfonts.override + {fonts = ["NerdFontsSymbolsOnly"];}) ]; } diff --git a/modules/home/workstation/hyprland/components/waybar.nix b/modules/home/workstation/hyprland/components/waybar.nix index 89ac6b0..16c44b7 100644 --- a/modules/home/workstation/hyprland/components/waybar.nix +++ b/modules/home/workstation/hyprland/components/waybar.nix @@ -23,13 +23,13 @@ in { settings.mainBar = { layer = "top"; position = "top"; - height = 30; + height = 32; width = monitorWidth; exclusive = true; margin-top = 10; margin-bottom = -12; - modules-left = ["clock" "battery" "hyprland/workspaces"]; + modules-left = ["custom/logo" "clock" "battery" "hyprland/workspaces"]; modules-center = []; modules-right = ["custom/hyprrecord" "tray"]; @@ -82,6 +82,11 @@ in { on-click = "exec hyprrecord -a --waybar screen copysave video"; signal = 12; }; + "custom/logo" = { + format = " "; + tooltop = "false"; + on-click = "exec notify-send 'hello!'"; + }; }; style = /* @@ -89,8 +94,8 @@ in { */ '' * { - font-family: "${fonts.monospace.family}"; - font-size: 19px; + font-family: "${fonts.monospace.family}:style=Medium"; + font-size: ${toString fonts.monospace.size}px; border: solid #${color.border.base}; } @@ -153,6 +158,13 @@ in { color: #${color.orange.base}; } + #custom-logo { + background-image: url('/home/ooks/Media/Pictures/my-art/pixel-art/info-icon.svg'); + background-position: center; + background-repeat: no-repeat; + background-size: 24px; + } + #custom-hyprrecord { color: #${color.red.base}; padding-right: 20px; diff --git a/modules/home/workstation/hyprland/settings/appearance.nix b/modules/home/workstation/hyprland/settings/appearance.nix index 2f06c55..2b15154 100644 --- a/modules/home/workstation/hyprland/settings/appearance.nix +++ b/modules/home/workstation/hyprland/settings/appearance.nix @@ -1,22 +1,24 @@ { osConfig, hozen, + inputs', ... }: let inherit (osConfig.ooknet.appearance) cursor; inherit (hozen) color; in { wayland.windowManager.hyprland = { + plugins = [inputs'.hyprland-plugins.packages.borders-plus-plus]; settings = { # cursor = { # inactive_timeout = 4; # }; general = { + border_size = 2; + "col.inactive_border" = "rgb(${color.neutrals."700"})"; + "col.active_border" = "rgb(${color.neutrals."650"})"; gaps_in = 10; gaps_out = 10; - border_size = 2; - "col.active_border" = "0xff${color.border.active}"; - "col.inactive_border" = "0xff${color.border.inactive}"; }; exec-once = [ @@ -35,12 +37,23 @@ in { ignore_opacity = true; }; shadow = { - range = 12; - offset = "3 3"; - color = "0x44000000"; - color_inactive = "0x66000000"; + enabled = true; + range = 2; + sharp = true; + offset = "2 2"; + color = "0xff${color.neutrals."850"}"; + color_inactive = "0xff${color.neutrals."850"}"; }; }; + "plugin:borders-plus-plus" = { + enabled = true; + add_borders = 1; + "col.border_1" = "rgb(${color.neutrals."600"})"; + + border_size_1 = 2; + border_size_2 = 2; + natural_rounding = false; + }; animations = { enabled = false; }; diff --git a/modules/home/workstation/terminal/foot.nix b/modules/home/workstation/terminal/foot.nix index 2c481cf..3a6f95b 100644 --- a/modules/home/workstation/terminal/foot.nix +++ b/modules/home/workstation/terminal/foot.nix @@ -9,6 +9,10 @@ inherit (lib) mkMerge mkIf; inherit (osConfig.ooknet.workstation) default; cfg = osConfig.ooknet.workstation.programs.foot; + fontOptions = let + size = if fonts.monospace.bitmap then "pixelsize" else "size"; + family = if fonts.monospace.bitmap then "${fonts.monospace.family}:style=Medium" else "${fonts.monospace.family}"; + in "${family}:${size}${toString fonts.monospace.size}"; in { config = mkMerge [ (mkIf (cfg.enable || default.terminal == "foot") { @@ -18,12 +22,12 @@ in { settings = { main = { term = "xterm-256color"; - font = "${fonts.monospace.family}:pixelsize=18:antialias=true"; - font-bold = "${fonts.monospace.family}:style=Bold:pixelsize=18:antialias=true"; - font-italic = "${fonts.monospace.family}:style=Italic:pixelsize=18:antialias=true"; - font-bold-italic = "${fonts.monospace.family}:style=Bold Italic:pixelsize=18:antialias=true"; - dpi-aware = "yes"; - letter-spacing = "-1px"; + font = "${fonts.monospace.family}:style=Medium:pixelsize=${toString fonts.monospace.size}",${fonts.monospace.fallback.family}; + font-bold = "${fonts.monospace.family}:style=Medium:pixelsize=${toString fonts.monospace.size}"; + font-italic = "${fonts.monospace.family}:style=Medium:pixelsize=${toString fonts.monospace.size}"; + font-bold-italic = "${fonts.monospace.family}:style=Medium:pixelsize=${toString fonts.monospace.size}"; + dpi-aware = "no"; + letter-spacing = "0"; bold-text-in-bright = "palette-based"; resize-delay-ms = "80"; pad = "9x9 center"; diff --git a/modules/nixos/appearance/options.nix b/modules/nixos/appearance/options.nix index da0de81..aea78c4 100644 --- a/modules/nixos/appearance/options.nix +++ b/modules/nixos/appearance/options.nix @@ -1,6 +1,6 @@ {lib, ...}: let inherit (lib) mkOption; - inherit (lib.types) str package path int; + inherit (lib.types) str package path int bool; mkFontOption = { family = mkOption { @@ -11,6 +11,28 @@ type = package; default = null; }; + size = mkOption { + type = int; + default = 18; + }; + bitmap = mkOption { + type = bool; + default = false; + }; + fallback = { + family = mkOption { + type = str; + default = ""; + }; + package = mkOption { + type = package; + default = null; + }; + size = mkOption { + type = int; + default = null; + }; + }; }; in { # imports = [./palettes]; diff --git a/modules/nixos/workstation/options.nix b/modules/nixos/workstation/options.nix index f4e72a4..7f1ff9b 100644 --- a/modules/nixos/workstation/options.nix +++ b/modules/nixos/workstation/options.nix @@ -4,7 +4,7 @@ in { options.ooknet.workstation = { theme = mkOption { - type = nullOr (enum ["minimal"]); + type = nullOr (enum ["minimal" "hozen"]); default = null; }; profiles = mkOption { diff --git a/modules/nixos/workstation/themes/default.nix b/modules/nixos/workstation/themes/default.nix index a153a13..269af8e 100644 --- a/modules/nixos/workstation/themes/default.nix +++ b/modules/nixos/workstation/themes/default.nix @@ -1,5 +1,6 @@ { imports = [ ./minimal.nix + ./hozen.nix ]; } diff --git a/modules/nixos/workstation/themes/hozen.nix b/modules/nixos/workstation/themes/hozen.nix new file mode 100644 index 0000000..83f8d12 --- /dev/null +++ b/modules/nixos/workstation/themes/hozen.nix @@ -0,0 +1,42 @@ +{ + config, + lib, + pkgs, + hozen, + ... +}: let + inherit (lib) mkIf; + inherit (config.ooknet.workstation) theme; + generatedWallpaper = import ./generated-wallpaper.nix {inherit hozen config pkgs;} {}; +in { + config = mkIf (theme == "hozen") { + ooknet.appearance = { + fonts = { + monospace = { + family = "CozetteHiDpi"; + package = pkgs.cozette; + size = 22; + fallback = { + family = "JetBrainsMono Nerd Font"; + package = pkgs.nerfonts.override {fonts = ["JetBrainsMono"];}; + size = 18; + }; + }; + regular = { + family = "Fira Sans"; + package = pkgs.fira; + }; + }; + + cursor = { + name = "Bibata-Modern-Ice"; + package = pkgs.bibata-cursors; + size = 22; + }; + + wallpaper = { + path = "${generatedWallpaper}"; + }; + }; + }; +} From c9f7e6b53c8f4ea4f9f1603aa55ba595bb10b85a Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 10 Dec 2024 19:11:33 +1100 Subject: [PATCH 087/213] ooksdesk: swap back to minimal theme --- hosts/ooksdesk/default.nix | 2 +- outputs/pkgs/ook-vim/plugins/languages/default.nix | 1 + outputs/pkgs/ook-vim/plugins/languages/lua.nix | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 outputs/pkgs/ook-vim/plugins/languages/lua.nix diff --git a/hosts/ooksdesk/default.nix b/hosts/ooksdesk/default.nix index b3f3359..ccb862e 100644 --- a/hosts/ooksdesk/default.nix +++ b/hosts/ooksdesk/default.nix @@ -18,7 +18,7 @@ }; workstation = { environment = "hyprland"; - theme = "hozen"; + theme = "minimal"; profiles = ["creative" "virtualization" "gaming" "media" "communication" "productivity"]; default = { browser = "firefox"; diff --git a/outputs/pkgs/ook-vim/plugins/languages/default.nix b/outputs/pkgs/ook-vim/plugins/languages/default.nix index 3ef2c00..589b33c 100644 --- a/outputs/pkgs/ook-vim/plugins/languages/default.nix +++ b/outputs/pkgs/ook-vim/plugins/languages/default.nix @@ -7,6 +7,7 @@ ./html.nix ./ts.nix ./go.nix + ./lua.nix ]; vim.languages = { diff --git a/outputs/pkgs/ook-vim/plugins/languages/lua.nix b/outputs/pkgs/ook-vim/plugins/languages/lua.nix new file mode 100644 index 0000000..c294207 --- /dev/null +++ b/outputs/pkgs/ook-vim/plugins/languages/lua.nix @@ -0,0 +1,5 @@ +{ + vim.languages.lua = { + enable = true; + }; +} From 1fa7ae2a66235a37202c7000e37c4cc6681aa477 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 10 Dec 2024 19:11:52 +1100 Subject: [PATCH 088/213] nixos: rework font options --- modules/home/workstation/appearance/fonts.nix | 22 ++++++---- .../hyprland/components/waybar.nix | 2 +- modules/home/workstation/terminal/foot.nix | 36 +++++++++++----- modules/nixos/appearance/options.nix | 42 ++++++++++++------- modules/nixos/workstation/themes/hozen.nix | 29 ++++++++++--- modules/nixos/workstation/themes/minimal.nix | 17 +++++++- 6 files changed, 107 insertions(+), 41 deletions(-) diff --git a/modules/home/workstation/appearance/fonts.nix b/modules/home/workstation/appearance/fonts.nix index 1a42574..b190577 100644 --- a/modules/home/workstation/appearance/fonts.nix +++ b/modules/home/workstation/appearance/fonts.nix @@ -1,19 +1,23 @@ { osConfig, pkgs, + lib, ... }: let inherit (osConfig.ooknet.appearance.fonts) monospace regular; + inherit (lib) optionals; in { fonts.fontconfig.enable = true; - home.packages = [ - monospace.package - regular.package + home.packages = + [ + monospace.package + regular.package - pkgs.noto-fonts - pkgs.noto-fonts-cjk-sans - pkgs.noto-fonts-emoji - (pkgs.nerdfonts.override - {fonts = ["NerdFontsSymbolsOnly"];}) - ]; + pkgs.noto-fonts + pkgs.noto-fonts-cjk-sans + pkgs.noto-fonts-emoji + (pkgs.nerdfonts.override + {fonts = ["NerdFontsSymbolsOnly"];}) + ] + ++ optionals (monospace.fallback != null) [monospace.fallback.package]; } diff --git a/modules/home/workstation/hyprland/components/waybar.nix b/modules/home/workstation/hyprland/components/waybar.nix index 16c44b7..1aaa034 100644 --- a/modules/home/workstation/hyprland/components/waybar.nix +++ b/modules/home/workstation/hyprland/components/waybar.nix @@ -94,7 +94,7 @@ in { */ '' * { - font-family: "${fonts.monospace.family}:style=Medium"; + font-family: "${fonts.monospace.family}"; font-size: ${toString fonts.monospace.size}px; border: solid #${color.border.base}; } diff --git a/modules/home/workstation/terminal/foot.nix b/modules/home/workstation/terminal/foot.nix index 3a6f95b..3c6d15e 100644 --- a/modules/home/workstation/terminal/foot.nix +++ b/modules/home/workstation/terminal/foot.nix @@ -4,15 +4,27 @@ hozen, ... }: let - inherit (osConfig.ooknet.appearance) fonts; + inherit (osConfig.ooknet.appearance.fonts) monospace; inherit (hozen) color; inherit (lib) mkMerge mkIf; inherit (osConfig.ooknet.workstation) default; + + mkFontConfig = font: style: let + mkFont = f: let + sizeAttr = + if f.bitmap + then "pixelsize" + else "size"; + familyStyle = f.variants.${style} or f.variants.regular; + in "${familyStyle}:${sizeAttr}=${toString font.size}"; + primary = mkFont font; + fallback = + if font.fallback != null + then ",${mkFont font.fallback}" + else ""; + in "${primary}${fallback}"; + cfg = osConfig.ooknet.workstation.programs.foot; - fontOptions = let - size = if fonts.monospace.bitmap then "pixelsize" else "size"; - family = if fonts.monospace.bitmap then "${fonts.monospace.family}:style=Medium" else "${fonts.monospace.family}"; - in "${family}:${size}${toString fonts.monospace.size}"; in { config = mkMerge [ (mkIf (cfg.enable || default.terminal == "foot") { @@ -22,16 +34,20 @@ in { settings = { main = { term = "xterm-256color"; - font = "${fonts.monospace.family}:style=Medium:pixelsize=${toString fonts.monospace.size}",${fonts.monospace.fallback.family}; - font-bold = "${fonts.monospace.family}:style=Medium:pixelsize=${toString fonts.monospace.size}"; - font-italic = "${fonts.monospace.family}:style=Medium:pixelsize=${toString fonts.monospace.size}"; - font-bold-italic = "${fonts.monospace.family}:style=Medium:pixelsize=${toString fonts.monospace.size}"; - dpi-aware = "no"; + font = mkFontConfig monospace "regular"; + font-bold = mkFontConfig monospace "bold"; + font-italic = mkFontConfig monospace "italic"; + font-bold-italic = mkFontConfig monospace "boldItalic"; + dpi-aware = + if monospace.bitmap + then "no" + else "yes"; letter-spacing = "0"; bold-text-in-bright = "palette-based"; resize-delay-ms = "80"; pad = "9x9 center"; selection-target = "clipboard"; + font-size-adjustment = "1px"; }; tweak = { diff --git a/modules/nixos/appearance/options.nix b/modules/nixos/appearance/options.nix index aea78c4..ae3e5a4 100644 --- a/modules/nixos/appearance/options.nix +++ b/modules/nixos/appearance/options.nix @@ -1,12 +1,32 @@ {lib, ...}: let inherit (lib) mkOption; - inherit (lib.types) str package path int bool; + inherit (lib.types) str package path int bool submodule nullOr; - mkFontOption = { + mkVariantOption = { + regular = mkOption { + type = str; + default = ""; + }; + bold = mkOption { + type = str; + default = ""; + }; + italic = mkOption { + type = str; + default = ""; + }; + boldItalic = mkOption { + type = str; + default = ""; + }; + }; + + mkBaseFontOption = { family = mkOption { type = str; default = ""; }; + variants = mkVariantOption; package = mkOption { type = package; default = null; @@ -19,21 +39,15 @@ type = bool; default = false; }; - fallback = { - family = mkOption { - type = str; - default = ""; - }; - package = mkOption { - type = package; - default = null; - }; - size = mkOption { - type = int; + }; + mkFontOption = + mkBaseFontOption + // { + fallback = mkOption { + type = nullOr (submodule {options = mkBaseFontOption;}); default = null; }; }; - }; in { # imports = [./palettes]; options.ooknet.appearance = { diff --git a/modules/nixos/workstation/themes/hozen.nix b/modules/nixos/workstation/themes/hozen.nix index 83f8d12..eb8c22c 100644 --- a/modules/nixos/workstation/themes/hozen.nix +++ b/modules/nixos/workstation/themes/hozen.nix @@ -13,17 +13,36 @@ in { ooknet.appearance = { fonts = { monospace = { - family = "CozetteHiDpi"; - package = pkgs.cozette; - size = 22; + bitmap = true; + package = pkgs.monocraft; + size = 18; + family = "Monocraft"; + variants = { + regular = "Monocraft:style=Medium"; + bold = "Monocraft:style=Medium"; + italic = "Monocraft:style=Medium"; + boldItalic = "Monocraft:style=Medium"; + }; fallback = { - family = "JetBrainsMono Nerd Font"; - package = pkgs.nerfonts.override {fonts = ["JetBrainsMono"];}; + family = "JetBrainsMono NFM"; + variants = { + regular = "JetBrainsMono NFM:style=Regular"; + bold = "JetBrainsMono NFM:style=Bold"; + italic = "JetBrainsMono NFM:style=Italic"; + boldItalic = "JetBrainsMono NFM:style=Bold Italic"; + }; + package = pkgs.nerdfonts.override {fonts = ["JetBrainsMono"];}; size = 18; }; }; regular = { family = "Fira Sans"; + variants = { + regular = "Fira Sans:style=Regular"; + bold = "Fira Sans:style=Bold"; + italic = "Fira Sans:style=Italic"; + boldItalic = "Fira Sans:style=Bold Italic"; + }; package = pkgs.fira; }; }; diff --git a/modules/nixos/workstation/themes/minimal.nix b/modules/nixos/workstation/themes/minimal.nix index 1050dce..c3aa8a4 100644 --- a/modules/nixos/workstation/themes/minimal.nix +++ b/modules/nixos/workstation/themes/minimal.nix @@ -13,12 +13,25 @@ in { ooknet.appearance = { fonts = { monospace = { - family = "JetBrainsMono Nerd Font"; package = pkgs.nerdfonts.override {fonts = ["JetBrainsMono"];}; + size = 18; + family = "JetBrainsMono NF"; + variants = { + regular = "JetBrainsMono NF:style=Regular"; + bold = "JetBrainsMono NF:style=Bold"; + italic = "JetBrainsMono NF:style=Italic"; + boldItalic = "JetBrainsMono NF:style=Bold Italic"; + }; }; regular = { - family = "Fira Sans"; package = pkgs.fira; + family = "Fira Sans"; + variants = { + regular = "Fira Sans:style=Regular"; + bold = "Fira Sans:style=Bold"; + italic = "Fira Sans:style=Italic"; + boldItalic = "Fira Sans:style=Bold Italic"; + }; }; }; From e9451f4a4a6732635e6cc3809d5e45bf827dd193 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 29 Dec 2024 22:12:07 +1100 Subject: [PATCH 089/213] home: ghostty init --- flake.lock | 206 +++++++++++++++--- flake.nix | 3 + modules/home/workstation/terminal/default.nix | 1 + modules/home/workstation/terminal/ghostty.nix | 14 ++ 4 files changed, 193 insertions(+), 31 deletions(-) create mode 100644 modules/home/workstation/terminal/ghostty.nix diff --git a/flake.lock b/flake.lock index b5cd5e4..76a8e50 100644 --- a/flake.lock +++ b/flake.lock @@ -130,6 +130,22 @@ "type": "github" } }, + "flake-compat_2": { + "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" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" @@ -201,7 +217,25 @@ }, "flake-utils_2": { "inputs": { - "systems": "systems_3" + "systems": "systems_2" + }, + "locked": { + "lastModified": 1705309234, + "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "inputs": { + "systems": "systems_4" }, "locked": { "lastModified": 1726560853, @@ -217,9 +251,9 @@ "type": "github" } }, - "flake-utils_3": { + "flake-utils_4": { "inputs": { - "systems": "systems_7" + "systems": "systems_8" }, "locked": { "lastModified": 1726560853, @@ -235,6 +269,42 @@ "type": "github" } }, + "ghostty": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs-stable": "nixpkgs-stable", + "nixpkgs-unstable": "nixpkgs-unstable", + "zig": "zig" + }, + "locked": { + "lastModified": 1735443550, + "narHash": "sha256-0bOG0ykRTyXihwLtyFjkaxNJWcDWs0alnNpC6PzbOvo=", + "owner": "ghostty-org", + "repo": "ghostty", + "rev": "c8950d376ab3be13fbd9a19317163075f4feddbc", + "type": "github" + }, + "original": { + "owner": "ghostty-org", + "repo": "ghostty", + "type": "github" + } + }, + "ghostty-hm": { + "locked": { + "lastModified": 1702368251, + "narHash": "sha256-hafrDmzGplzm+vdIo+LkOjRfA4qRcy5JmpGGksnht5c=", + "owner": "clo4", + "repo": "ghostty-hm-module", + "rev": "887e13a6e7acf5ffaab0119d96e476d84db90904", + "type": "github" + }, + "original": { + "owner": "clo4", + "repo": "ghostty-hm-module", + "type": "github" + } + }, "gitignore": { "inputs": { "nixpkgs": [ @@ -428,7 +498,7 @@ "hyprwayland-scanner": "hyprwayland-scanner", "nixpkgs": "nixpkgs_2", "pre-commit-hooks": "pre-commit-hooks", - "systems": "systems_2", + "systems": "systems_3", "xdph": "xdph" }, "locked": { @@ -845,6 +915,22 @@ } }, "nixpkgs-stable": { + "locked": { + "lastModified": 1733423277, + "narHash": "sha256-TxabjxEgkNbCGFRHgM/b9yZWlBj60gUOUnRT/wbVQR8=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "e36963a147267afc055f7cf65225958633e536bf", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "release-24.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_2": { "locked": { "lastModified": 1730741070, "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=", @@ -860,6 +946,22 @@ "type": "github" } }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1733229606, + "narHash": "sha256-FLYY5M0rpa5C2QAE3CKLYAM6TwbKicdRK6qNrSHlNrE=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "566e53c2ad750c84f6d31f9ccb9d00f823165550", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs_2": { "locked": { "lastModified": 1731676054, @@ -959,7 +1061,7 @@ "nvf": { "inputs": { "flake-parts": "flake-parts_2", - "flake-utils": "flake-utils_2", + "flake-utils": "flake-utils_3", "mnw": "mnw", "nil": "nil", "nixpkgs": "nixpkgs_4", @@ -1081,7 +1183,7 @@ "plugin-vim-startify": "plugin-vim-startify", "plugin-which-key": "plugin-which-key", "rnix-lsp": "rnix-lsp", - "systems": "systems_4" + "systems": "systems_5" }, "locked": { "lastModified": 1733489853, @@ -1104,7 +1206,7 @@ "nixpkgs": [ "nixpkgs" ], - "systems": "systems_5" + "systems": "systems_6" }, "locked": { "lastModified": 1728305902, @@ -3000,13 +3102,13 @@ }, "pre-commit-hooks": { "inputs": { - "flake-compat": "flake-compat", + "flake-compat": "flake-compat_2", "gitignore": "gitignore", "nixpkgs": [ "hyprland", "nixpkgs" ], - "nixpkgs-stable": "nixpkgs-stable" + "nixpkgs-stable": "nixpkgs-stable_2" }, "locked": { "lastModified": 1731363552, @@ -3047,6 +3149,8 @@ "agenix": "agenix", "firefox-addons": "firefox-addons", "flake-parts": "flake-parts", + "ghostty": "ghostty", + "ghostty-hm": "ghostty-hm", "home-manager": "home-manager_2", "hypridle": "hypridle", "hyprland": "hyprland", @@ -3059,7 +3163,7 @@ "nvf": "nvf", "ooknet-website": "ooknet-website", "ooks-scripts": "ooks-scripts", - "systems": "systems_6", + "systems": "systems_7", "vpn-confinement": "vpn-confinement", "zjstatus": "zjstatus" } @@ -3123,21 +3227,6 @@ } }, "systems_2": { - "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" - } - }, - "systems_3": { "locked": { "lastModified": 1681028828, "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", @@ -3152,6 +3241,21 @@ "type": "github" } }, + "systems_3": { + "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" + } + }, "systems_4": { "locked": { "lastModified": 1681028828, @@ -3169,16 +3273,16 @@ }, "systems_5": { "locked": { - "lastModified": 1689347949, - "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", "owner": "nix-systems", - "repo": "default-linux", - "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { "owner": "nix-systems", - "repo": "default-linux", + "repo": "default", "type": "github" } }, @@ -3198,6 +3302,21 @@ } }, "systems_7": { + "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" + } + }, + "systems_8": { "locked": { "lastModified": 1681028828, "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", @@ -3283,10 +3402,35 @@ "type": "github" } }, + "zig": { + "inputs": { + "flake-compat": [ + "ghostty" + ], + "flake-utils": "flake-utils_2", + "nixpkgs": [ + "ghostty", + "nixpkgs-stable" + ] + }, + "locked": { + "lastModified": 1717848532, + "narHash": "sha256-d+xIUvSTreHl8pAmU1fnmkfDTGQYCn2Rb/zOwByxS2M=", + "owner": "mitchellh", + "repo": "zig-overlay", + "rev": "02fc5cc555fc14fda40c42d7c3250efa43812b43", + "type": "github" + }, + "original": { + "owner": "mitchellh", + "repo": "zig-overlay", + "type": "github" + } + }, "zjstatus": { "inputs": { "crane": "crane", - "flake-utils": "flake-utils_3", + "flake-utils": "flake-utils_4", "nixpkgs": "nixpkgs_6", "rust-overlay": "rust-overlay_2" }, diff --git a/flake.nix b/flake.nix index 0ad60ea..b2e5a9c 100644 --- a/flake.nix +++ b/flake.nix @@ -40,6 +40,9 @@ # confine vpns to specific systemd services vpn-confinement.url = "github:Maroka-chan/VPN-Confinement"; + ghostty-hm.url = "github:clo4/ghostty-hm-module"; + ghostty.url = "github:ghostty-org/ghostty"; + # hypr* ecosystem hyprland.url = "github:hyprwm/hyprland"; diff --git a/modules/home/workstation/terminal/default.nix b/modules/home/workstation/terminal/default.nix index c21fc86..f13829f 100644 --- a/modules/home/workstation/terminal/default.nix +++ b/modules/home/workstation/terminal/default.nix @@ -1,5 +1,6 @@ { imports = [ ./foot.nix + ./ghostty.nix ]; } diff --git a/modules/home/workstation/terminal/ghostty.nix b/modules/home/workstation/terminal/ghostty.nix new file mode 100644 index 0000000..934e1a8 --- /dev/null +++ b/modules/home/workstation/terminal/ghostty.nix @@ -0,0 +1,14 @@ +{ + inputs, + inputs', + ... +}: { + imports = [ + inputs.ghostty-hm.homeModules.default + ]; + + programs.ghostty = { + enable = true; + package = inputs'.ghostty.packages.default; + }; +} From 625e67339e88d16e8702998d54346d4347c1fc5b Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 5 Jan 2025 22:08:50 +1100 Subject: [PATCH 090/213] home: add emulation module --- modules/home/workstation/gaming/default.nix | 1 + modules/home/workstation/gaming/emulation.nix | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 modules/home/workstation/gaming/emulation.nix diff --git a/modules/home/workstation/gaming/default.nix b/modules/home/workstation/gaming/default.nix index 048500d..20f918e 100644 --- a/modules/home/workstation/gaming/default.nix +++ b/modules/home/workstation/gaming/default.nix @@ -10,6 +10,7 @@ in { ./wow.nix ./wine.nix ./bottles.nix + ./emulation.nix ]; config = mkIf (elem "gaming" profiles) { ooknet.binds = { diff --git a/modules/home/workstation/gaming/emulation.nix b/modules/home/workstation/gaming/emulation.nix new file mode 100644 index 0000000..c569f10 --- /dev/null +++ b/modules/home/workstation/gaming/emulation.nix @@ -0,0 +1,19 @@ +{ + lib, + osConfig, + pkgs, + ... +}: let + inherit (lib) mkIf elem; + inherit (builtins) attrValues; + inherit (osConfig.ooknet.workstation) profiles; +in { + config = mkIf (elem "gaming" profiles) { + home.packages = attrValues { + inherit + (pkgs) + ryujinx + ; + }; + }; +} From 94f793b6ff317ab58879981ea4a05b4d429fbaa3 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 5 Jan 2025 22:09:22 +1100 Subject: [PATCH 091/213] gaming: add ns-usbloader module --- modules/nixos/workstation/gaming/default.nix | 1 + modules/nixos/workstation/gaming/switch.nix | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 modules/nixos/workstation/gaming/switch.nix diff --git a/modules/nixos/workstation/gaming/default.nix b/modules/nixos/workstation/gaming/default.nix index 22d0e4d..c98c43e 100644 --- a/modules/nixos/workstation/gaming/default.nix +++ b/modules/nixos/workstation/gaming/default.nix @@ -2,5 +2,6 @@ imports = [ ./steam.nix ./gamemode.nix + ./switch.nix ]; } diff --git a/modules/nixos/workstation/gaming/switch.nix b/modules/nixos/workstation/gaming/switch.nix new file mode 100644 index 0000000..c627d7b --- /dev/null +++ b/modules/nixos/workstation/gaming/switch.nix @@ -0,0 +1,14 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkIf elem; + inherit (config.ooknet.workstation) profiles; +in { + config = mkIf (elem "gaming" profiles) { + programs.ns-usbloader = { + enable = true; + }; + }; +} From e01e845a434222fd196af1d672dab617d85670a6 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 5 Jan 2025 22:09:47 +1100 Subject: [PATCH 092/213] virt-manager: add remmina package --- modules/nixos/workstation/virtualization/virt-manager.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/nixos/workstation/virtualization/virt-manager.nix b/modules/nixos/workstation/virtualization/virt-manager.nix index aa45f1e..4b43c40 100644 --- a/modules/nixos/workstation/virtualization/virt-manager.nix +++ b/modules/nixos/workstation/virtualization/virt-manager.nix @@ -18,10 +18,10 @@ in { spice spice-protocol # for windows virtualization - win-virtio win-spice adwaita-icon-theme # virt-manager needs this + remmina # for rdp ; }; # sets up dconf settins for qemu and add virt-manager to systemPackages @@ -50,6 +50,8 @@ in { enable = true; packages = [pkgs.OVMFFull.fd]; }; + # ensure virtiofsd is accessible to all domains + vhostUserPackages = [pkgs.virtiofsd]; }; }; }; From f9958ab4f7d281370f9506c427b5b3874ff5cd80 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 5 Jan 2025 23:48:27 +1100 Subject: [PATCH 093/213] ooksdesk: swap to new monitor --- hosts/ooksdesk/hardware.nix | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/hosts/ooksdesk/hardware.nix b/hosts/ooksdesk/hardware.nix index 2b9e7ef..173a4b3 100644 --- a/hosts/ooksdesk/hardware.nix +++ b/hosts/ooksdesk/hardware.nix @@ -6,12 +6,22 @@ features = ["printing" "ssd" "audio" "video"]; monitors = [ { - name = "DP-3"; + name = "DP-1"; primary = true; + width = 2560; + height = 1440; + refreshRate = 144; + workspace = "1"; + x = 1920; + y = 100; + } + { + name = "DP-2"; width = 1920; height = 1080; refreshRate = 180; - workspace = "1"; + x = 840; + transform = 1; } ]; }; From 34dbb54d6c0637800703adc8bb86238d9abb2036 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 5 Jan 2025 23:49:28 +1100 Subject: [PATCH 094/213] tools: add scrcpy --- modules/home/workstation/tools/default.nix | 1 + modules/home/workstation/tools/qtscrcpy.nix | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 modules/home/workstation/tools/qtscrcpy.nix diff --git a/modules/home/workstation/tools/default.nix b/modules/home/workstation/tools/default.nix index 5f911c0..8d3b0bc 100644 --- a/modules/home/workstation/tools/default.nix +++ b/modules/home/workstation/tools/default.nix @@ -10,5 +10,6 @@ ./ookbrightness.nix ./zellijMenu.nix ./nemo.nix + ./qtscrcpy.nix ]; } diff --git a/modules/home/workstation/tools/qtscrcpy.nix b/modules/home/workstation/tools/qtscrcpy.nix new file mode 100644 index 0000000..4008914 --- /dev/null +++ b/modules/home/workstation/tools/qtscrcpy.nix @@ -0,0 +1,5 @@ +{pkgs, ...}: { + home.packages = [ + pkgs.scrcpy + ]; +} From 45b6a907fb20305d4c1334732601296feda4be88 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 13:17:40 +1100 Subject: [PATCH 095/213] waybar: remove test component --- .../workstation/hyprland/components/waybar.nix | 14 +------------- modules/home/workstation/hyprland/default.nix | 2 +- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/modules/home/workstation/hyprland/components/waybar.nix b/modules/home/workstation/hyprland/components/waybar.nix index 1aaa034..70b6c83 100644 --- a/modules/home/workstation/hyprland/components/waybar.nix +++ b/modules/home/workstation/hyprland/components/waybar.nix @@ -29,7 +29,7 @@ in { margin-top = 10; margin-bottom = -12; - modules-left = ["custom/logo" "clock" "battery" "hyprland/workspaces"]; + modules-left = ["clock" "battery" "hyprland/workspaces"]; modules-center = []; modules-right = ["custom/hyprrecord" "tray"]; @@ -82,11 +82,6 @@ in { on-click = "exec hyprrecord -a --waybar screen copysave video"; signal = 12; }; - "custom/logo" = { - format = " "; - tooltop = "false"; - on-click = "exec notify-send 'hello!'"; - }; }; style = /* @@ -158,13 +153,6 @@ in { color: #${color.orange.base}; } - #custom-logo { - background-image: url('/home/ooks/Media/Pictures/my-art/pixel-art/info-icon.svg'); - background-position: center; - background-repeat: no-repeat; - background-size: 24px; - } - #custom-hyprrecord { color: #${color.red.base}; padding-right: 20px; diff --git a/modules/home/workstation/hyprland/default.nix b/modules/home/workstation/hyprland/default.nix index 0bf1580..a314a2b 100644 --- a/modules/home/workstation/hyprland/default.nix +++ b/modules/home/workstation/hyprland/default.nix @@ -18,7 +18,7 @@ in { enable = true; package = inputs'.hyprland.packages.hyprland; xwayland.enable = true; - systemd = { + systemd = mkIf (!osConfig.programs.uwsm.enable) { enable = true; variables = ["--all"]; }; From c2d52a2683cc7628da4f8a05b7826354e6ebd743 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 13:18:19 +1100 Subject: [PATCH 096/213] templates: fix flake application module --- outputs/templates/basic/outputs/pkgs.nix | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/outputs/templates/basic/outputs/pkgs.nix b/outputs/templates/basic/outputs/pkgs.nix index da50d0e..7300efe 100644 --- a/outputs/templates/basic/outputs/pkgs.nix +++ b/outputs/templates/basic/outputs/pkgs.nix @@ -2,8 +2,11 @@ perSystem = { pkgs, self', + lib, ... - }: { + }: let + inherit (lib) getExe; + in { packages.default = pkgs.stdenvNoCC.mkDerivation { pname = "my package"; version = "0.1.0"; @@ -13,6 +16,9 @@ buildPhase = ""; dontInstall = true; }; - apps.default = self'.packages.default; + apps.default = { + type = "app"; + program = "${getExe self'.packages.default}"; + }; }; } From f3a2f912545e1d747c16564e4c5a70eb0612499c Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 13:18:34 +1100 Subject: [PATCH 097/213] colors: change border colors --- outputs/lib/color/utils.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/outputs/lib/color/utils.nix b/outputs/lib/color/utils.nix index dc0e160..894a9d3 100644 --- a/outputs/lib/color/utils.nix +++ b/outputs/lib/color/utils.nix @@ -124,9 +124,9 @@ menu = args.neutrals."800"; }; border = { - base = args.neutrals."150"; - active = args.neutrals."150"; - inactive = args.neutrals."600"; + base = args.neutrals."650"; + active = args.neutrals."600"; + inactive = args.neutrals."700"; }; typography = { text = args.neutrals."150"; From 4d20cc82c40c9d284be380a3b9cd1de6ef72a546 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 13:18:58 +1100 Subject: [PATCH 098/213] themes: change minimal theme font size --- modules/nixos/workstation/themes/minimal.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nixos/workstation/themes/minimal.nix b/modules/nixos/workstation/themes/minimal.nix index c3aa8a4..80b4ade 100644 --- a/modules/nixos/workstation/themes/minimal.nix +++ b/modules/nixos/workstation/themes/minimal.nix @@ -14,7 +14,7 @@ in { fonts = { monospace = { package = pkgs.nerdfonts.override {fonts = ["JetBrainsMono"];}; - size = 18; + size = 16; family = "JetBrainsMono NF"; variants = { regular = "JetBrainsMono NF:style=Regular"; From 7868ac152925fd93f77ddea7df5e0ff30a93a005 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 13:19:09 +1100 Subject: [PATCH 099/213] greetd: fix launch command --- modules/nixos/workstation/environment/hyprland/default.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/nixos/workstation/environment/hyprland/default.nix b/modules/nixos/workstation/environment/hyprland/default.nix index e5b36fc..a303768 100644 --- a/modules/nixos/workstation/environment/hyprland/default.nix +++ b/modules/nixos/workstation/environment/hyprland/default.nix @@ -14,6 +14,7 @@ in { enable = true; package = hyprland; portalPackage = xdg-desktop-portal-hyprland; + withUWSM = false; #TODO }; xdg.portal = { @@ -42,7 +43,7 @@ in { "--time" "--remember" "--cmd" - (getExe hyprland) + "Hyprland" ]; user = "greeter"; }; From 8d9c2a0ed290e95182d05254a141947fc2bfdeb0 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 16:27:13 +1100 Subject: [PATCH 100/213] neovim: changes to how we access nvf.lib --- modules/home/console/tools/editor/neovim.nix | 1 - outputs/lib/default.nix | 1 - outputs/lib/mkNeovim.nix | 12 ----------- outputs/pkgs/default.nix | 11 ++++++---- outputs/pkgs/ook-vim/config/default.nix | 10 +++++++++ outputs/pkgs/ook-vim/{ => config}/keymaps.nix | 0 .../ook-vim/{ => config}/modules/default.nix | 0 .../{ => config}/modules/plugins/default.nix | 0 .../plugins/gruvbox-material/config.nix | 2 +- .../plugins/gruvbox-material/default.nix | 0 .../modules/plugins/telescope/config.nix | 0 .../modules/plugins/telescope/default.nix | 0 outputs/pkgs/ook-vim/{ => config}/opts.nix | 0 .../pkgs/ook-vim/{ => config}/plugins/cmp.nix | 0 .../ook-vim/{ => config}/plugins/comments.nix | 0 .../ook-vim/{ => config}/plugins/default.nix | 0 .../ook-vim/{ => config}/plugins/filetree.nix | 0 .../pkgs/ook-vim/{ => config}/plugins/git.nix | 0 .../{ => config}/plugins/languages/bash.nix | 0 .../{ => config}/plugins/languages/css.nix | 0 .../plugins/languages/default.nix | 0 .../{ => config}/plugins/languages/go.nix | 0 .../{ => config}/plugins/languages/html.nix | 0 .../{ => config}/plugins/languages/lsp.nix | 0 .../{ => config}/plugins/languages/lua.nix | 0 .../plugins/languages/markdown.nix | 0 .../{ => config}/plugins/languages/nix.nix | 0 .../plugins/languages/treesitter.nix | 0 .../{ => config}/plugins/languages/ts.nix | 0 .../ook-vim/{ => config}/plugins/projects.nix | 0 .../ook-vim/{ => config}/plugins/snippets.nix | 0 .../{ => config}/plugins/statusline.nix | 0 .../{ => config}/plugins/telescope.nix | 0 .../ook-vim/{ => config}/plugins/terminal.nix | 0 .../pkgs/ook-vim/{ => config}/plugins/ui.nix | 0 .../ook-vim/{ => config}/plugins/utility.nix | 0 .../pkgs/ook-vim/{ => config}/settings.nix | 0 outputs/pkgs/ook-vim/{ => config}/theme.nix | 0 outputs/pkgs/ook-vim/default.nix | 21 +++++++++++-------- 39 files changed, 30 insertions(+), 28 deletions(-) delete mode 100644 outputs/lib/mkNeovim.nix create mode 100644 outputs/pkgs/ook-vim/config/default.nix rename outputs/pkgs/ook-vim/{ => config}/keymaps.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/modules/default.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/modules/plugins/default.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/modules/plugins/gruvbox-material/config.nix (97%) rename outputs/pkgs/ook-vim/{ => config}/modules/plugins/gruvbox-material/default.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/modules/plugins/telescope/config.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/modules/plugins/telescope/default.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/opts.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/cmp.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/comments.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/default.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/filetree.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/git.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/languages/bash.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/languages/css.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/languages/default.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/languages/go.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/languages/html.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/languages/lsp.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/languages/lua.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/languages/markdown.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/languages/nix.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/languages/treesitter.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/languages/ts.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/projects.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/snippets.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/statusline.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/telescope.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/terminal.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/ui.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/plugins/utility.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/settings.nix (100%) rename outputs/pkgs/ook-vim/{ => config}/theme.nix (100%) diff --git a/modules/home/console/tools/editor/neovim.nix b/modules/home/console/tools/editor/neovim.nix index ef9f32b..5f55570 100644 --- a/modules/home/console/tools/editor/neovim.nix +++ b/modules/home/console/tools/editor/neovim.nix @@ -14,4 +14,3 @@ in { home.sessionVariables.EDITOR = mkIf (console.editor == "nvim") "nvim"; }; } - diff --git a/outputs/lib/default.nix b/outputs/lib/default.nix index c695419..3991faf 100644 --- a/outputs/lib/default.nix +++ b/outputs/lib/default.nix @@ -8,7 +8,6 @@ # my scuffed lib ook-lib = { builders = import ./builders.nix {inherit self lib inputs;}; - mkNeovim = import ./mkNeovim.nix {inherit inputs;}; math = import ./math.nix {inherit lib;}; container = import ./containers.nix {inherit lib config;}; services = import ./services.nix {inherit lib;}; diff --git a/outputs/lib/mkNeovim.nix b/outputs/lib/mkNeovim.nix deleted file mode 100644 index 951d4f0..0000000 --- a/outputs/lib/mkNeovim.nix +++ /dev/null @@ -1,12 +0,0 @@ -{inputs, ...}: let - inherit (inputs.nvf.lib) neovimConfiguration; - - mkNeovim = pkgs: modules: - (neovimConfiguration { - inherit pkgs; - extraSpecialArgs = {inherit inputs;}; - inherit modules; - }) - .neovim; -in - mkNeovim diff --git a/outputs/pkgs/default.nix b/outputs/pkgs/default.nix index a89ffa1..6624778 100644 --- a/outputs/pkgs/default.nix +++ b/outputs/pkgs/default.nix @@ -1,7 +1,9 @@ -{ook, ...}: { +{ + inputs, + lib, + ... +}: { perSystem = {pkgs, ...}: let - inherit (ook.lib) mkNeovim; - ook-vim-config = import ./ook-vim; inherit (pkgs) callPackage; in { packages = { @@ -10,7 +12,8 @@ website = callPackage ./website {}; caddy-with-cloudflare = callPackage ./caddy-with-cloudflare {}; - ook-vim = mkNeovim pkgs [ook-vim-config]; + #ook-vim = mkNeovim pkgs [ook-vim-config]; + ook-vim = callPackage ./ook-vim {inherit inputs pkgs lib;}; }; }; } diff --git a/outputs/pkgs/ook-vim/config/default.nix b/outputs/pkgs/ook-vim/config/default.nix new file mode 100644 index 0000000..93fee2d --- /dev/null +++ b/outputs/pkgs/ook-vim/config/default.nix @@ -0,0 +1,10 @@ +{ + imports = [ + ./settings.nix + ./opts.nix + ./theme.nix + ./keymaps.nix + ./plugins + ./modules + ]; +} diff --git a/outputs/pkgs/ook-vim/keymaps.nix b/outputs/pkgs/ook-vim/config/keymaps.nix similarity index 100% rename from outputs/pkgs/ook-vim/keymaps.nix rename to outputs/pkgs/ook-vim/config/keymaps.nix diff --git a/outputs/pkgs/ook-vim/modules/default.nix b/outputs/pkgs/ook-vim/config/modules/default.nix similarity index 100% rename from outputs/pkgs/ook-vim/modules/default.nix rename to outputs/pkgs/ook-vim/config/modules/default.nix diff --git a/outputs/pkgs/ook-vim/modules/plugins/default.nix b/outputs/pkgs/ook-vim/config/modules/plugins/default.nix similarity index 100% rename from outputs/pkgs/ook-vim/modules/plugins/default.nix rename to outputs/pkgs/ook-vim/config/modules/plugins/default.nix diff --git a/outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/config.nix b/outputs/pkgs/ook-vim/config/modules/plugins/gruvbox-material/config.nix similarity index 97% rename from outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/config.nix rename to outputs/pkgs/ook-vim/config/modules/plugins/gruvbox-material/config.nix index d03cab7..bfe4345 100644 --- a/outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/config.nix +++ b/outputs/pkgs/ook-vim/config/modules/plugins/gruvbox-material/config.nix @@ -7,7 +7,7 @@ }: let inherit (lib) mkOption mkIf boolToString; inherit (lib.types) bool enum lines; - inherit (inputs.nvf.lib.nvim.dag) entryAfter; + inherit (lib.nvim.dag) entryAfter; cfg = config.vim.gruvbox-material; in { diff --git a/outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/default.nix b/outputs/pkgs/ook-vim/config/modules/plugins/gruvbox-material/default.nix similarity index 100% rename from outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/default.nix rename to outputs/pkgs/ook-vim/config/modules/plugins/gruvbox-material/default.nix diff --git a/outputs/pkgs/ook-vim/modules/plugins/telescope/config.nix b/outputs/pkgs/ook-vim/config/modules/plugins/telescope/config.nix similarity index 100% rename from outputs/pkgs/ook-vim/modules/plugins/telescope/config.nix rename to outputs/pkgs/ook-vim/config/modules/plugins/telescope/config.nix diff --git a/outputs/pkgs/ook-vim/modules/plugins/telescope/default.nix b/outputs/pkgs/ook-vim/config/modules/plugins/telescope/default.nix similarity index 100% rename from outputs/pkgs/ook-vim/modules/plugins/telescope/default.nix rename to outputs/pkgs/ook-vim/config/modules/plugins/telescope/default.nix diff --git a/outputs/pkgs/ook-vim/opts.nix b/outputs/pkgs/ook-vim/config/opts.nix similarity index 100% rename from outputs/pkgs/ook-vim/opts.nix rename to outputs/pkgs/ook-vim/config/opts.nix diff --git a/outputs/pkgs/ook-vim/plugins/cmp.nix b/outputs/pkgs/ook-vim/config/plugins/cmp.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/cmp.nix rename to outputs/pkgs/ook-vim/config/plugins/cmp.nix diff --git a/outputs/pkgs/ook-vim/plugins/comments.nix b/outputs/pkgs/ook-vim/config/plugins/comments.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/comments.nix rename to outputs/pkgs/ook-vim/config/plugins/comments.nix diff --git a/outputs/pkgs/ook-vim/plugins/default.nix b/outputs/pkgs/ook-vim/config/plugins/default.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/default.nix rename to outputs/pkgs/ook-vim/config/plugins/default.nix diff --git a/outputs/pkgs/ook-vim/plugins/filetree.nix b/outputs/pkgs/ook-vim/config/plugins/filetree.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/filetree.nix rename to outputs/pkgs/ook-vim/config/plugins/filetree.nix diff --git a/outputs/pkgs/ook-vim/plugins/git.nix b/outputs/pkgs/ook-vim/config/plugins/git.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/git.nix rename to outputs/pkgs/ook-vim/config/plugins/git.nix diff --git a/outputs/pkgs/ook-vim/plugins/languages/bash.nix b/outputs/pkgs/ook-vim/config/plugins/languages/bash.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/languages/bash.nix rename to outputs/pkgs/ook-vim/config/plugins/languages/bash.nix diff --git a/outputs/pkgs/ook-vim/plugins/languages/css.nix b/outputs/pkgs/ook-vim/config/plugins/languages/css.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/languages/css.nix rename to outputs/pkgs/ook-vim/config/plugins/languages/css.nix diff --git a/outputs/pkgs/ook-vim/plugins/languages/default.nix b/outputs/pkgs/ook-vim/config/plugins/languages/default.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/languages/default.nix rename to outputs/pkgs/ook-vim/config/plugins/languages/default.nix diff --git a/outputs/pkgs/ook-vim/plugins/languages/go.nix b/outputs/pkgs/ook-vim/config/plugins/languages/go.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/languages/go.nix rename to outputs/pkgs/ook-vim/config/plugins/languages/go.nix diff --git a/outputs/pkgs/ook-vim/plugins/languages/html.nix b/outputs/pkgs/ook-vim/config/plugins/languages/html.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/languages/html.nix rename to outputs/pkgs/ook-vim/config/plugins/languages/html.nix diff --git a/outputs/pkgs/ook-vim/plugins/languages/lsp.nix b/outputs/pkgs/ook-vim/config/plugins/languages/lsp.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/languages/lsp.nix rename to outputs/pkgs/ook-vim/config/plugins/languages/lsp.nix diff --git a/outputs/pkgs/ook-vim/plugins/languages/lua.nix b/outputs/pkgs/ook-vim/config/plugins/languages/lua.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/languages/lua.nix rename to outputs/pkgs/ook-vim/config/plugins/languages/lua.nix diff --git a/outputs/pkgs/ook-vim/plugins/languages/markdown.nix b/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/languages/markdown.nix rename to outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix diff --git a/outputs/pkgs/ook-vim/plugins/languages/nix.nix b/outputs/pkgs/ook-vim/config/plugins/languages/nix.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/languages/nix.nix rename to outputs/pkgs/ook-vim/config/plugins/languages/nix.nix diff --git a/outputs/pkgs/ook-vim/plugins/languages/treesitter.nix b/outputs/pkgs/ook-vim/config/plugins/languages/treesitter.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/languages/treesitter.nix rename to outputs/pkgs/ook-vim/config/plugins/languages/treesitter.nix diff --git a/outputs/pkgs/ook-vim/plugins/languages/ts.nix b/outputs/pkgs/ook-vim/config/plugins/languages/ts.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/languages/ts.nix rename to outputs/pkgs/ook-vim/config/plugins/languages/ts.nix diff --git a/outputs/pkgs/ook-vim/plugins/projects.nix b/outputs/pkgs/ook-vim/config/plugins/projects.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/projects.nix rename to outputs/pkgs/ook-vim/config/plugins/projects.nix diff --git a/outputs/pkgs/ook-vim/plugins/snippets.nix b/outputs/pkgs/ook-vim/config/plugins/snippets.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/snippets.nix rename to outputs/pkgs/ook-vim/config/plugins/snippets.nix diff --git a/outputs/pkgs/ook-vim/plugins/statusline.nix b/outputs/pkgs/ook-vim/config/plugins/statusline.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/statusline.nix rename to outputs/pkgs/ook-vim/config/plugins/statusline.nix diff --git a/outputs/pkgs/ook-vim/plugins/telescope.nix b/outputs/pkgs/ook-vim/config/plugins/telescope.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/telescope.nix rename to outputs/pkgs/ook-vim/config/plugins/telescope.nix diff --git a/outputs/pkgs/ook-vim/plugins/terminal.nix b/outputs/pkgs/ook-vim/config/plugins/terminal.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/terminal.nix rename to outputs/pkgs/ook-vim/config/plugins/terminal.nix diff --git a/outputs/pkgs/ook-vim/plugins/ui.nix b/outputs/pkgs/ook-vim/config/plugins/ui.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/ui.nix rename to outputs/pkgs/ook-vim/config/plugins/ui.nix diff --git a/outputs/pkgs/ook-vim/plugins/utility.nix b/outputs/pkgs/ook-vim/config/plugins/utility.nix similarity index 100% rename from outputs/pkgs/ook-vim/plugins/utility.nix rename to outputs/pkgs/ook-vim/config/plugins/utility.nix diff --git a/outputs/pkgs/ook-vim/settings.nix b/outputs/pkgs/ook-vim/config/settings.nix similarity index 100% rename from outputs/pkgs/ook-vim/settings.nix rename to outputs/pkgs/ook-vim/config/settings.nix diff --git a/outputs/pkgs/ook-vim/theme.nix b/outputs/pkgs/ook-vim/config/theme.nix similarity index 100% rename from outputs/pkgs/ook-vim/theme.nix rename to outputs/pkgs/ook-vim/config/theme.nix diff --git a/outputs/pkgs/ook-vim/default.nix b/outputs/pkgs/ook-vim/default.nix index 93fee2d..9bcc5ed 100644 --- a/outputs/pkgs/ook-vim/default.nix +++ b/outputs/pkgs/ook-vim/default.nix @@ -1,10 +1,13 @@ { - imports = [ - ./settings.nix - ./opts.nix - ./theme.nix - ./keymaps.nix - ./plugins - ./modules - ]; -} + inputs, + pkgs, + ... +}: let + configuration = import ./config; + ooks-vim = inputs.nvf.lib.neovimConfiguration { + inherit pkgs; + extraSpecialArgs = {inherit inputs;}; + modules = [configuration]; + }; +in + ooks-vim.neovim From 859ba27ce067f7e7486e7bebbdc191285380d845 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 16:28:30 +1100 Subject: [PATCH 101/213] fonts: new nerd-font packages --- modules/home/workstation/appearance/fonts.nix | 3 +-- modules/nixos/workstation/themes/hozen.nix | 2 +- modules/nixos/workstation/themes/minimal.nix | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/home/workstation/appearance/fonts.nix b/modules/home/workstation/appearance/fonts.nix index b190577..b2c21be 100644 --- a/modules/home/workstation/appearance/fonts.nix +++ b/modules/home/workstation/appearance/fonts.nix @@ -16,8 +16,7 @@ in { pkgs.noto-fonts pkgs.noto-fonts-cjk-sans pkgs.noto-fonts-emoji - (pkgs.nerdfonts.override - {fonts = ["NerdFontsSymbolsOnly"];}) + pkgs.nerd-fonts.symbols-only ] ++ optionals (monospace.fallback != null) [monospace.fallback.package]; } diff --git a/modules/nixos/workstation/themes/hozen.nix b/modules/nixos/workstation/themes/hozen.nix index eb8c22c..083e0d8 100644 --- a/modules/nixos/workstation/themes/hozen.nix +++ b/modules/nixos/workstation/themes/hozen.nix @@ -31,7 +31,7 @@ in { italic = "JetBrainsMono NFM:style=Italic"; boldItalic = "JetBrainsMono NFM:style=Bold Italic"; }; - package = pkgs.nerdfonts.override {fonts = ["JetBrainsMono"];}; + package = pkgs.nerd-fonts.jetbrains-mono; size = 18; }; }; diff --git a/modules/nixos/workstation/themes/minimal.nix b/modules/nixos/workstation/themes/minimal.nix index 80b4ade..ee687a8 100644 --- a/modules/nixos/workstation/themes/minimal.nix +++ b/modules/nixos/workstation/themes/minimal.nix @@ -13,7 +13,7 @@ in { ooknet.appearance = { fonts = { monospace = { - package = pkgs.nerdfonts.override {fonts = ["JetBrainsMono"];}; + package = pkgs.nerd-fonts.jetbrains-mono; size = 16; family = "JetBrainsMono NF"; variants = { From bcf90556753243be882f93b1574197f3a35acb9f Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 16:29:04 +1100 Subject: [PATCH 102/213] networking: wait-online service fix --- modules/nixos/base/networking.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/nixos/base/networking.nix b/modules/nixos/base/networking.nix index 9a9252c..4568c77 100644 --- a/modules/nixos/base/networking.nix +++ b/modules/nixos/base/networking.nix @@ -1,6 +1,7 @@ { lib, config, + pkgs, ... }: let inherit (lib) mkForce mkDefault; @@ -42,5 +43,5 @@ in { }; # sometimes causes issues with network manager service never actually starting # requiring me to manually start the service. fine on a workstation, not on a server - systemd.services.NetworkManager-wait-online.enable = host.role != "server"; + systemd.services.NetworkManager-wait-online.serviceConfig.ExecStart = ["" "${pkgs.networkmanager}/bin/nm-online -q"]; } From 0cb5596d2264cd1a2f091307ba9de4af77789740 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 16:29:34 +1100 Subject: [PATCH 103/213] ghostty: disable wont be moving to ghostty for now --- modules/home/workstation/terminal/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/home/workstation/terminal/default.nix b/modules/home/workstation/terminal/default.nix index f13829f..8ba2eb3 100644 --- a/modules/home/workstation/terminal/default.nix +++ b/modules/home/workstation/terminal/default.nix @@ -1,6 +1,6 @@ { imports = [ ./foot.nix - ./ghostty.nix + # ./ghostty.nix ]; } From caa0f0de748f9879dbdc200949f1405a9b800fd2 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 16:29:43 +1100 Subject: [PATCH 104/213] flake: bump --- flake.lock | 831 ++++++++++++++++++++++++++++++----------------------- flake.nix | 5 +- 2 files changed, 481 insertions(+), 355 deletions(-) diff --git a/flake.lock b/flake.lock index 76a8e50..c19d353 100644 --- a/flake.lock +++ b/flake.lock @@ -41,11 +41,11 @@ ] }, "locked": { - "lastModified": 1731774881, - "narHash": "sha256-1Dxryiw8u2ejntxrrv3sMtIE8WHKxmlN4KeH+uMGbmc=", + "lastModified": 1734906446, + "narHash": "sha256-6OWluVE2A8xi+8V3jN9KA72RCgJjYdyyuLBUjxZ2q2U=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "b31a6a4da8199ae3489057db7d36069a70749a56", + "rev": "eecb74dc79bb6752a2a507e6edee3042390a6091", "type": "github" }, "original": { @@ -56,11 +56,11 @@ }, "crane": { "locked": { - "lastModified": 1730652660, - "narHash": "sha256-+XVYfmVXAiYA0FZT7ijHf555dxCe+AoAT5A6RU+6vSo=", + "lastModified": 1734808813, + "narHash": "sha256-3aH/0Y6ajIlfy7j52FGZ+s4icVX0oHhqBzRdlOeztqg=", "owner": "ipetkov", "repo": "crane", - "rev": "a4ca93905455c07cb7e3aca95d4faf7601cba458", + "rev": "72e2d02dbac80c8c86bf6bf3e785536acf8ee926", "type": "github" }, "original": { @@ -100,11 +100,11 @@ }, "locked": { "dir": "pkgs/firefox-addons", - "lastModified": 1732790791, - "narHash": "sha256-bx+ljzcUpVOKqu6k/HJGvij8x/sdFYkehGP8oPVqqRY=", + "lastModified": 1736120139, + "narHash": "sha256-FAqmrhfoAgGnHUet/CtbPD6fUa579eDNSyL2up97go8=", "owner": "rycee", "repo": "nur-expressions", - "rev": "ac70253fea187562c44006f32ad2b480997e0866", + "rev": "6a32f225d4ec375b68dda3b94a841199526cd01d", "type": "gitlab" }, "original": { @@ -151,11 +151,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1730504689, - "narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=", + "lastModified": 1735774679, + "narHash": "sha256-soePLBazJk0qQdDVhdbM98vYdssfs3WFedcq+raipRI=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "506278e768c2a08bec68eb62932193e341f55c90", + "rev": "f2f7418ce0ab4a5309a4596161d154cfc877af66", "type": "github" }, "original": { @@ -169,11 +169,11 @@ "nixpkgs-lib": "nixpkgs-lib_2" }, "locked": { - "lastModified": 1730504689, - "narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=", + "lastModified": 1733312601, + "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "506278e768c2a08bec68eb62932193e341f55c90", + "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", "type": "github" }, "original": { @@ -238,11 +238,11 @@ "systems": "systems_4" }, "locked": { - "lastModified": 1726560853, - "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -256,11 +256,11 @@ "systems": "systems_8" }, "locked": { - "lastModified": 1726560853, - "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -277,11 +277,11 @@ "zig": "zig" }, "locked": { - "lastModified": 1735443550, - "narHash": "sha256-0bOG0ykRTyXihwLtyFjkaxNJWcDWs0alnNpC6PzbOvo=", + "lastModified": 1736115260, + "narHash": "sha256-9VrUz+JNq90Z1QOBojSxKDdUHr0I5XsK/OHjZSyvXwU=", "owner": "ghostty-org", "repo": "ghostty", - "rev": "c8950d376ab3be13fbd9a19317163075f4feddbc", + "rev": "2485482aecc02c6c377a30c36a34c647cc521ddf", "type": "github" }, "original": { @@ -355,11 +355,11 @@ ] }, "locked": { - "lastModified": 1732793095, - "narHash": "sha256-6TrknJ8CpvSSF4gviQSeD+wyj3siRcMvdBKhOXkEMKU=", + "lastModified": 1736089250, + "narHash": "sha256-/LPWMiiJGPHGd7ZYEgmbE2da4zvBW0acmshUjYC3WG4=", "owner": "nix-community", "repo": "home-manager", - "rev": "2f7739d01080feb4549524e8f6927669b61c6ee3", + "rev": "172b91bfb2b7f5c4a8c6ceac29fd53a01ef07196", "type": "github" }, "original": { @@ -384,11 +384,11 @@ ] }, "locked": { - "lastModified": 1728669738, - "narHash": "sha256-EDNAU9AYcx8OupUzbTbWE1d3HYdeG0wO6Msg3iL1muk=", + "lastModified": 1734906540, + "narHash": "sha256-vQ/L9hZFezC0LquLo4TWXkyniWtYBlFHAKIsDc7PYJE=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "0264e698149fcb857a66a53018157b41f8d97bb0", + "rev": "69270ba8f057d55b0e6c2dca0e165d652856e613", "type": "github" }, "original": { @@ -398,6 +398,35 @@ } }, "hyprgraphics": { + "inputs": { + "hyprutils": [ + "hyprland", + "hyprutils" + ], + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1734906236, + "narHash": "sha256-vH/ysV2ONGQgYZPtcJKwc8jJivzyVxru2aaOxC20ZOE=", + "owner": "hyprwm", + "repo": "hyprgraphics", + "rev": "6dea3fba08fd704dd624b6d4b261638fb4003c9c", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprgraphics", + "type": "github" + } + }, + "hyprgraphics_2": { "inputs": { "hyprutils": [ "hyprlock", @@ -413,11 +442,11 @@ ] }, "locked": { - "lastModified": 1732808127, - "narHash": "sha256-jwqYmLVfvoLPu8UScEzZgdbbiNU3ioYcrsthjEEnGqI=", + "lastModified": 1734906236, + "narHash": "sha256-vH/ysV2ONGQgYZPtcJKwc8jJivzyVxru2aaOxC20ZOE=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "4d927a52be7e15e0846456f2aa1b0ad76b5bf059", + "rev": "6dea3fba08fd704dd624b6d4b261638fb4003c9c", "type": "github" }, "original": { @@ -426,7 +455,7 @@ "type": "github" } }, - "hyprgraphics_2": { + "hyprgraphics_3": { "inputs": { "hyprutils": [ "hyprpaper", @@ -442,11 +471,11 @@ ] }, "locked": { - "lastModified": 1732808127, - "narHash": "sha256-jwqYmLVfvoLPu8UScEzZgdbbiNU3ioYcrsthjEEnGqI=", + "lastModified": 1734906236, + "narHash": "sha256-vH/ysV2ONGQgYZPtcJKwc8jJivzyVxru2aaOxC20ZOE=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "4d927a52be7e15e0846456f2aa1b0ad76b5bf059", + "rev": "6dea3fba08fd704dd624b6d4b261638fb4003c9c", "type": "github" }, "original": { @@ -475,11 +504,11 @@ ] }, "locked": { - "lastModified": 1731958956, - "narHash": "sha256-21R5LD61oUqjdo9Vz0kLn0qSHCDMXyUMXbbod3kX+ho=", + "lastModified": 1734384160, + "narHash": "sha256-zy2uzmlIORQV6VjIqSPhaoUKPLqfzpUQ5UTjmRfrkdg=", "owner": "hyprwm", "repo": "hypridle", - "rev": "9f23e70bb494107df8f959c925d4521a298c65eb", + "rev": "413564cb986cfc67aeb7c4e750b42dc93ff9810f", "type": "github" }, "original": { @@ -492,7 +521,9 @@ "inputs": { "aquamarine": "aquamarine", "hyprcursor": "hyprcursor", + "hyprgraphics": "hyprgraphics", "hyprland-protocols": "hyprland-protocols", + "hyprland-qtutils": "hyprland-qtutils", "hyprlang": "hyprlang", "hyprutils": "hyprutils", "hyprwayland-scanner": "hyprwayland-scanner", @@ -502,11 +533,11 @@ "xdph": "xdph" }, "locked": { - "lastModified": 1732837919, - "narHash": "sha256-/GySPsuD3UpBLOpr0ZRteN2/zYmlAnrkfIZhvM32AvE=", + "lastModified": 1736115553, + "narHash": "sha256-nFagWe+VST+UL+Y/sp4P007PoMpsm6iW+PrWw1VH/Xk=", "owner": "hyprwm", "repo": "hyprland", - "rev": "8f83d29f00bfa89d1e8fe94b4dda98fe898b6b0e", + "rev": "f390f48a07d117e24acec59dcf6791bcb3a81110", "type": "github" }, "original": { @@ -523,11 +554,11 @@ ] }, "locked": { - "lastModified": 1730743354, - "narHash": "sha256-gU4NySYyXeAzVaF5bI6BKmj2CdgiwGFnuPjXUId3Dx0=", + "lastModified": 1733056338, + "narHash": "sha256-sp14z0mrqrtmouz1+bU4Jh8/0xi+xwQHF2l7mhGSSVU=", "owner": "hyprwm", "repo": "contrib", - "rev": "792f6b83dc719214e0e2a0b380c34f147b28ece2", + "rev": "d7c55140f1785b8d9fef351f1cd2a4c9e1eaa466", "type": "github" }, "original": { @@ -553,11 +584,11 @@ ] }, "locked": { - "lastModified": 1732053779, - "narHash": "sha256-v9FS0r2XWMf/+uwevvzaF/2TimMFeLEQTf4T8cgc6c0=", + "lastModified": 1736115213, + "narHash": "sha256-x15KPKaSDBe07tQqkBnN1CV3kthMe0RTu9QomIr2YHg=", "owner": "hyprwm", "repo": "hyprland-plugins", - "rev": "0bc619b2c3b4f9c2b65247e81d69f8bbc573d991", + "rev": "b6b31113ce84419c69ed575c22194e4023d2952a", "type": "github" }, "original": { @@ -578,11 +609,11 @@ ] }, "locked": { - "lastModified": 1728345020, - "narHash": "sha256-xGbkc7U/Roe0/Cv3iKlzijIaFBNguasI31ynL2IlEoM=", + "lastModified": 1735734474, + "narHash": "sha256-9OV4lOqrEJVLdOrpNN/9msNwAhI6FQTu4N7fufilG08=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "a7c183800e74f337753de186522b9017a07a8cee", + "rev": "271df559dd30e4bc5ec6af02d017ac0aaabd63a7", "type": "github" }, "original": { @@ -591,6 +622,35 @@ "type": "github" } }, + "hyprland-qtutils": { + "inputs": { + "hyprutils": [ + "hyprland", + "hyprutils" + ], + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1734906472, + "narHash": "sha256-pWPRv/GA/X/iAwoE6gMNUqn/ZeJX1IeLPRpZI0tTPK0=", + "owner": "hyprwm", + "repo": "hyprland-qtutils", + "rev": "c77109d7e1ddbcdb87cafd32ce411f76328ae152", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprland-qtutils", + "type": "github" + } + }, "hyprlang": { "inputs": { "hyprutils": [ @@ -607,11 +667,11 @@ ] }, "locked": { - "lastModified": 1728168612, - "narHash": "sha256-AnB1KfiXINmuiW7BALYrKqcjCnsLZPifhb/7BsfPbns=", + "lastModified": 1734906259, + "narHash": "sha256-P79t/7HbACO4/PuJBroGpTptvCWJtXTv+gWsF+sM6MI=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "f054f2e44d6a0b74607a6bc0f52dba337a3db38e", + "rev": "0404833ea18d543df44df935ebf1b497310eb046", "type": "github" }, "original": { @@ -621,40 +681,6 @@ } }, "hyprlock": { - "inputs": { - "hyprgraphics": "hyprgraphics", - "hyprlang": [ - "hyprland", - "hyprlang" - ], - "hyprutils": [ - "hyprland", - "hyprutils" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1732812191, - "narHash": "sha256-/gYMXqhjvOcjhaYjzb1iqjpoCDqO5lkkqjG93oMMo60=", - "owner": "hyprwm", - "repo": "hyprlock", - "rev": "4667f721be47ff6f5cf2a7ee64513f818fb764a0", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprlock", - "type": "github" - } - }, - "hyprpaper": { "inputs": { "hyprgraphics": "hyprgraphics_2", "hyprlang": [ @@ -676,11 +702,46 @@ ] }, "locked": { - "lastModified": 1732809500, - "narHash": "sha256-CW4r78WhaHtFJN6L+heBztj02ucxthBPgUzFeUZ+yVw=", + "lastModified": 1736008364, + "narHash": "sha256-8gC5tgoJmvPsV2nuCpbt0p9m1+OqZ1aAd16R6y9PlYo=", + "owner": "hyprwm", + "repo": "hyprlock", + "rev": "8f68fad50aa07f1220961d1d23942565e7562d8d", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlock", + "type": "github" + } + }, + "hyprpaper": { + "inputs": { + "hyprgraphics": "hyprgraphics_3", + "hyprlang": [ + "hyprland", + "hyprlang" + ], + "hyprutils": [ + "hyprland", + "hyprutils" + ], + "hyprwayland-scanner": "hyprwayland-scanner_3", + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1735493740, + "narHash": "sha256-QmfXYQxWmT2w5wx8y4CCADaMdMBiCPxK2M+8/iP1110=", "owner": "hyprwm", "repo": "hyprpaper", - "rev": "a3ceb20095c1fae9acb10c37713caf2df28f3ec9", + "rev": "505e447b6c48e6b49f3aecf5da276f3cc5780054", "type": "github" }, "original": { @@ -701,11 +762,11 @@ ] }, "locked": { - "lastModified": 1731702627, - "narHash": "sha256-+JeO9gevnXannQxMfR5xzZtF4sYmSlWkX/BPmPx0mWk=", + "lastModified": 1735316583, + "narHash": "sha256-AiiUwHWHfEdpFzXy7l1x3zInCUa1xcRMrbZ1XRSkzwU=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "e911361a687753bbbdfe3b6a9eab755ecaf1d9e1", + "rev": "8f15d45b120b33712f6db477fe5ffb18034d0ea8", "type": "github" }, "original": { @@ -726,11 +787,11 @@ ] }, "locked": { - "lastModified": 1726874836, - "narHash": "sha256-VKR0sf0PSNCB0wPHVKSAn41mCNVCnegWmgkrneKDhHM=", + "lastModified": 1734793513, + "narHash": "sha256-rrrHcXapXJvGFqX+L/Bb0182L25jofAZ0fm1FInvrTQ=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "500c81a9e1a76760371049a8d99e008ea77aa59e", + "rev": "4d7367b6eee87397e2dbca2e78078dd0a4ef4c61", "type": "github" }, "original": { @@ -740,6 +801,31 @@ } }, "hyprwayland-scanner_2": { + "inputs": { + "nixpkgs": [ + "hyprlock", + "nixpkgs" + ], + "systems": [ + "hyprlock", + "systems" + ] + }, + "locked": { + "lastModified": 1735493474, + "narHash": "sha256-fktzv4NaqKm94VAkAoVqO/nqQlw+X0/tJJNAeCSfzK4=", + "owner": "hyprwm", + "repo": "hyprwayland-scanner", + "rev": "de913476b59ee88685fdc018e77b8f6637a2ae0b", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprwayland-scanner", + "type": "github" + } + }, + "hyprwayland-scanner_3": { "inputs": { "nixpkgs": [ "hyprpaper", @@ -751,11 +837,11 @@ ] }, "locked": { - "lastModified": 1721324119, - "narHash": "sha256-SOOqIT27/X792+vsLSeFdrNTF+OSRp5qXv6Te+fb2Qg=", + "lastModified": 1734793513, + "narHash": "sha256-rrrHcXapXJvGFqX+L/Bb0182L25jofAZ0fm1FInvrTQ=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "a048a6cb015340bd82f97c1f40a4b595ca85cc30", + "rev": "4d7367b6eee87397e2dbca2e78078dd0a4ef4c61", "type": "github" }, "original": { @@ -766,11 +852,11 @@ }, "mnw": { "locked": { - "lastModified": 1731821965, - "narHash": "sha256-QiGi/HBQRnIRGY4gQPuH7T3hr7NznOpEO7qNpF5ldmE=", + "lastModified": 1735150973, + "narHash": "sha256-OJhcCAoaMMXeD6o4qI/hxBCNELJp4dN8D5LJZc8w8XA=", "owner": "Gerg-L", "repo": "mnw", - "rev": "5fe5c41975ed0af55f55dc37cd28ba906a5d015e", + "rev": "40cd0b006cc48dffd0f8698ad7f54cf1d56779a6", "type": "github" }, "original": { @@ -814,11 +900,11 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1726716330, - "narHash": "sha256-mIuOP4I51eFLquRaxMKx67pHmhatZrcVPjfHL98v/M8=", + "lastModified": 1732053863, + "narHash": "sha256-DCIVdlb81Fct2uwzbtnawLBC/U03U2hqx8trqTJB7WA=", "owner": "oxalica", "repo": "nil", - "rev": "c8e8ce72442a164d89d3fdeaae0bcc405f8c015a", + "rev": "2e24c9834e3bb5aa2a3701d3713b43a6fb106362", "type": "github" }, "original": { @@ -849,11 +935,11 @@ ] }, "locked": { - "lastModified": 1732519917, - "narHash": "sha256-AGXhwHdJV0q/WNgqwrR2zriubLr785b02FphaBtyt1Q=", + "lastModified": 1736047960, + "narHash": "sha256-hutd85FA1jUJhhqBRRJ+u7UHO9oFGD/RVm2x5w8WjVQ=", "owner": "nix-community", "repo": "nix-index-database", - "rev": "f4a5ca5771ba9ca31ad24a62c8d511a405303436", + "rev": "816a6ae88774ba7e74314830546c29e134e0dffb", "type": "github" }, "original": { @@ -880,26 +966,26 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1730504152, - "narHash": "sha256-lXvH/vOfb4aGYyvFmZK/HlsNsr/0CVWlwYvo2rxJk3s=", + "lastModified": 1735774519, + "narHash": "sha256-CewEm1o2eVAnoqb6Ml+Qi9Gg/EfNAxbRx1lANGVyoLI=", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/e9b51731911566bbf7e4895475a87fe06961de0b.tar.gz" }, "original": { "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/e9b51731911566bbf7e4895475a87fe06961de0b.tar.gz" } }, "nixpkgs-lib_2": { "locked": { - "lastModified": 1730504152, - "narHash": "sha256-lXvH/vOfb4aGYyvFmZK/HlsNsr/0CVWlwYvo2rxJk3s=", + "lastModified": 1733096140, + "narHash": "sha256-1qRH7uAUsyQI7R1Uwl4T+XvdNv778H0Nb5njNrqvylY=", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz" }, "original": { "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz" } }, "nixpkgs-lib_3": { @@ -964,11 +1050,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1731676054, - "narHash": "sha256-OZiZ3m8SCMfh3B6bfGC/Bm4x3qc1m2SVEAlkV6iY7Yg=", + "lastModified": 1735291276, + "narHash": "sha256-NYVcA06+blsLG6wpAbSPTCyLvxD/92Hy4vlY9WxFI1M=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5e4fbfb6b3de1aa2872b76d49fafc942626e2add", + "rev": "634fd46801442d760e09493a794c4f15db2d0cbb", "type": "github" }, "original": { @@ -980,11 +1066,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1732521221, - "narHash": "sha256-2ThgXBUXAE1oFsVATK1ZX9IjPcS4nKFOAjhPNKuiMn0=", + "lastModified": 1735834308, + "narHash": "sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4633a7c72337ea8fd23a4f2ba3972865e3ec685d", + "rev": "6df24922a1400241dae323af55f30e4318a6ca65", "type": "github" }, "original": { @@ -995,22 +1081,6 @@ } }, "nixpkgs_4": { - "locked": { - "lastModified": 1732617236, - "narHash": "sha256-PYkz6U0bSEaEB1al7O1XsqVNeSNS+s3NVclJw7YC43w=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "af51545ec9a44eadf3fe3547610a5cdd882bc34e", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_5": { "locked": { "lastModified": 1656753965, "narHash": "sha256-BCrB3l0qpJokOnIVc3g2lHiGhnjUi0MoXiw6t1o8H1E=", @@ -1026,13 +1096,13 @@ "type": "github" } }, - "nixpkgs_6": { + "nixpkgs_5": { "locked": { - "lastModified": 1730272153, - "narHash": "sha256-B5WRZYsRlJgwVHIV6DvidFN7VX7Fg9uuwkRW9Ha8z+w=", + "lastModified": 1734435836, + "narHash": "sha256-kMBQ5PRiFLagltK0sH+08aiNt3zGERC2297iB6vrvlU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2d2a9ddbe3f2c00747398f3dc9b05f7f2ebb0f53", + "rev": "4989a246d7a390a859852baddb1013f825435cee", "type": "github" }, "original": { @@ -1064,7 +1134,9 @@ "flake-utils": "flake-utils_3", "mnw": "mnw", "nil": "nil", - "nixpkgs": "nixpkgs_4", + "nixpkgs": [ + "nixpkgs" + ], "nmd": "nmd", "plugin-alpha-nvim": "plugin-alpha-nvim", "plugin-base16": "plugin-base16", @@ -1099,6 +1171,7 @@ "plugin-gitsigns-nvim": "plugin-gitsigns-nvim", "plugin-glow-nvim": "plugin-glow-nvim", "plugin-gruvbox": "plugin-gruvbox", + "plugin-haskell-tools-nvim": "plugin-haskell-tools-nvim", "plugin-highlight-undo": "plugin-highlight-undo", "plugin-hop-nvim": "plugin-hop-nvim", "plugin-icon-picker-nvim": "plugin-icon-picker-nvim", @@ -1161,6 +1234,7 @@ "plugin-precognition-nvim": "plugin-precognition-nvim", "plugin-project-nvim": "plugin-project-nvim", "plugin-registers": "plugin-registers", + "plugin-render-markdown-nvim": "plugin-render-markdown-nvim", "plugin-rose-pine": "plugin-rose-pine", "plugin-rtp-nvim": "plugin-rtp-nvim", "plugin-run-nvim": "plugin-run-nvim", @@ -1175,6 +1249,7 @@ "plugin-tokyonight": "plugin-tokyonight", "plugin-trouble": "plugin-trouble", "plugin-ts-error-translator": "plugin-ts-error-translator", + "plugin-typst-preview-nvim": "plugin-typst-preview-nvim", "plugin-vim-dirtytalk": "plugin-vim-dirtytalk", "plugin-vim-fugitive": "plugin-vim-fugitive", "plugin-vim-illuminate": "plugin-vim-illuminate", @@ -1186,11 +1261,11 @@ "systems": "systems_5" }, "locked": { - "lastModified": 1733489853, - "narHash": "sha256-Ir2dsp+e3xTVSmpV+et6DjsVyoaVgctARir+D8hn7Xg=", + "lastModified": 1736124878, + "narHash": "sha256-eJmPe9wSa+PtxyokkEE1Z6sC0SKENdRHyRl0w2FKNJY=", "owner": "notashelf", "repo": "nvf", - "rev": "f672d3cdee3617ad1321808f51929b2d2dbb5133", + "rev": "9888a277adc8a34aa13e9f6bb75c9c86b4f2919a", "type": "github" }, "original": { @@ -1245,11 +1320,11 @@ "plugin-alpha-nvim": { "flake": false, "locked": { - "lastModified": 1727720738, - "narHash": "sha256-33lhPP1C4TGo0UQJ61bwRHaiOMAB7XNehcZGaFXOPjQ=", + "lastModified": 1731604504, + "narHash": "sha256-sNi5qarejYqM4/J7lBZI3gjVLxer5FBPq8K6qjqcMjA=", "owner": "goolord", "repo": "alpha-nvim", - "rev": "bf3c8bb8c02ed3d9644cc5bbc48e2bdc39349cd7", + "rev": "de72250e054e5e691b9736ee30db72c65d560771", "type": "github" }, "original": { @@ -1293,11 +1368,11 @@ "plugin-catppuccin": { "flake": false, "locked": { - "lastModified": 1731169755, - "narHash": "sha256-lsnePejThsEygTCKV/rfJJ/h+RSrro91am841iznJe4=", + "lastModified": 1735299190, + "narHash": "sha256-lwQLmqm01FihJdad4QRMK23MTrouyOokyuX/3enWjzs=", "owner": "catppuccin", "repo": "nvim", - "rev": "637d99e638bc6f1efedac582f6ccab08badac0c6", + "rev": "f67b886d65a029f12ffa298701fb8f1efd89295d", "type": "github" }, "original": { @@ -1421,11 +1496,11 @@ "plugin-cmp-nvim-lsp": { "flake": false, "locked": { - "lastModified": 1715931395, - "narHash": "sha256-CT1+Z4XJBVsl/RqvJeGmyitD6x7So0ylXvvef5jh7I8=", + "lastModified": 1733823748, + "narHash": "sha256-iaihXNCF5bB5MdeoosD/kc3QtpA/QaIDZVLiLIurBSM=", "owner": "hrsh7th", "repo": "cmp-nvim-lsp", - "rev": "39e2eda76828d88b773cc27a3f61d2ad782c922d", + "rev": "99290b3ec1322070bcfb9e846450a46f6efa50f0", "type": "github" }, "original": { @@ -1501,11 +1576,11 @@ "plugin-copilot-cmp": { "flake": false, "locked": { - "lastModified": 1718601710, - "narHash": "sha256-8w9go2SBkI+BrXNadWM8ZxDDfrAnZZJx6RbVHAK4+Pg=", + "lastModified": 1733947099, + "narHash": "sha256-erRL8bY/zuwuCZfttw+avTrFV7pjv2H6v73NzY2bymM=", "owner": "zbirenbaum", "repo": "copilot-cmp", - "rev": "b6e5286b3d74b04256d0a7e3bd2908eabec34b44", + "rev": "15fc12af3d0109fa76b60b5cffa1373697e261d1", "type": "github" }, "original": { @@ -1517,11 +1592,11 @@ "plugin-copilot-lua": { "flake": false, "locked": { - "lastModified": 1729295476, - "narHash": "sha256-UY6N2Q+egh+Cn4REZXrSGH9ElWQBedl0n8tWJvGe7vs=", + "lastModified": 1734926641, + "narHash": "sha256-c2UE0dLBtoYMvMxg+jXzfsD+wN9sZLvftJq4gGmooZU=", "owner": "zbirenbaum", "repo": "copilot.lua", - "rev": "f8d8d872bb319f640d5177dad5fbf01f7a16d7d0", + "rev": "886ee73b6d464b2b3e3e6a7ff55ce87feac423a9", "type": "github" }, "original": { @@ -1549,11 +1624,11 @@ "plugin-csharpls-extended": { "flake": false, "locked": { - "lastModified": 1730857197, - "narHash": "sha256-eKkFpEB7ZXNttXz62y3GaKptt4n0xRY+iuTI8RU5z0Q=", + "lastModified": 1734491815, + "narHash": "sha256-jO/vuNgP8JAOIturzPFvxMLL5y+6YTYsUxjWwX6Nyso=", "owner": "Decodetalkers", "repo": "csharpls-extended-lsp.nvim", - "rev": "ef02017d80b1cd914d61285b1fb063cb7fe0aa8f", + "rev": "4f56c06215d10c4fcfee8a7f04ba766c114aece0", "type": "github" }, "original": { @@ -1597,11 +1672,11 @@ "plugin-dracula": { "flake": false, "locked": { - "lastModified": 1729038981, - "narHash": "sha256-3jFOaFtH+EIx4mUKV0U/cFkUo8By0JgorTYgFUKEs/s=", + "lastModified": 1734597715, + "narHash": "sha256-9iRI5NW3mcVzduitY4sr679dRWAWVbZuCAEfgM1OIOs=", "owner": "Mofiqul", "repo": "dracula.nvim", - "rev": "94fa7885a06a67f0a8bfa03e064619d05d1ba496", + "rev": "515acae4fd294fcefa5b15237a333c2606e958d1", "type": "github" }, "original": { @@ -1613,11 +1688,11 @@ "plugin-dressing-nvim": { "flake": false, "locked": { - "lastModified": 1730759661, - "narHash": "sha256-F9mdyANs9QTzlB/VAXt+9GXJUiA5th7Fj79WArdUmRE=", + "lastModified": 1734804193, + "narHash": "sha256-N4hB5wDgoqXrXxSfzDCrqmdDtdVvq+PtOS7FBPH7qXE=", "owner": "stevearc", "repo": "dressing.nvim", - "rev": "6ef1ca479d37d4ff66f13eed44d08912caff483a", + "rev": "3a45525bb182730fe462325c99395529308f431e", "type": "github" }, "original": { @@ -1629,11 +1704,11 @@ "plugin-elixir-tools": { "flake": false, "locked": { - "lastModified": 1727872243, - "narHash": "sha256-7gIvoV6myqbkjLnIhHuyNPix1DFkKEeeND2o6VDxDWc=", + "lastModified": 1735076861, + "narHash": "sha256-CoGTVSKifjqshk8hYaQfFYTYgEGsIb1hKdz6fIS81iU=", "owner": "elixir-tools", "repo": "elixir-tools.nvim", - "rev": "b465f6aff50257fa466de3886fc3e7de2dcff0de", + "rev": "803fa69dbb457305cff98e3997bed2c4b51aea7c", "type": "github" }, "original": { @@ -1645,11 +1720,11 @@ "plugin-fastaction-nvim": { "flake": false, "locked": { - "lastModified": 1731000037, - "narHash": "sha256-oNLKwWj2lze/ZCcwT98ucw6oT4765EiW1CB0BAjox8A=", + "lastModified": 1734546047, + "narHash": "sha256-1GSxTyXqufjkRtNK3drWlCn/mGJ9mM9bHMR6ZwWT6X8=", "owner": "Chaitanyabsprip", "repo": "fastaction.nvim", - "rev": "a55feac91f39b83aa21b9ef3df1e465d9122753c", + "rev": "886e22d85e13115808e81ca367d5aaba02d9a25b", "type": "github" }, "original": { @@ -1661,11 +1736,11 @@ "plugin-fidget-nvim": { "flake": false, "locked": { - "lastModified": 1730221432, - "narHash": "sha256-fQBrkHV54TaOeLYQJ1DE+lr7SFDPN1yqSlzhFm26NAY=", + "lastModified": 1734334336, + "narHash": "sha256-o0za2NxFtzHZa7PRIm9U/P1/fwJrxS1G79ukdGLhJ4Q=", "owner": "j-hui", "repo": "fidget.nvim", - "rev": "e2a175c2abe2d4f65357da1c98c59a5cfb2b543f", + "rev": "9238947645ce17d96f30842e61ba81147185b657", "type": "github" }, "original": { @@ -1677,11 +1752,11 @@ "plugin-flutter-tools": { "flake": false, "locked": { - "lastModified": 1730275333, - "narHash": "sha256-fKsC+ouSfW07dLipXP+RPMzQfCQ70oGknSdVo7dMAxw=", + "lastModified": 1735420417, + "narHash": "sha256-xfSdPhrSUwBYdE9ZA8GgwFvR70nOp+snbNrFHeIfwOM=", "owner": "akinsho", "repo": "flutter-tools.nvim", - "rev": "7e6d8611d8606efca64cb8cf1ca07550b7087d1c", + "rev": "a526c30f1941a7472509aaedda13758f943c968e", "type": "github" }, "original": { @@ -1693,11 +1768,11 @@ "plugin-friendly-snippets": { "flake": false, "locked": { - "lastModified": 1728273759, - "narHash": "sha256-H94Ryad0ZsSg/gioUgW+7sowij7GgtEUMNFi1IOZAys=", + "lastModified": 1733106470, + "narHash": "sha256-I8SRZxnoNC6SOWW+scoA77Jwyxcb4eUczppLdyOiZe0=", "owner": "rafamadriz", "repo": "friendly-snippets", - "rev": "de8fce94985873666bd9712ea3e49ee17aadb1ed", + "rev": "efff286dd74c22f731cdec26a70b46e5b203c619", "type": "github" }, "original": { @@ -1709,11 +1784,11 @@ "plugin-gesture-nvim": { "flake": false, "locked": { - "lastModified": 1726696689, - "narHash": "sha256-d1+czQXyJUyNlMhPjRzb6cEiCJVTFrkYnv7XXh2BLNs=", + "lastModified": 1731669851, + "narHash": "sha256-LTkttlDmKO9ngzrJrMWeeG9R0Bz/PoroCAF2URhUEbM=", "owner": "notomo", "repo": "gesture.nvim", - "rev": "a63d81325a1f84ad87a7d9e1a36e4eeb4e786fc1", + "rev": "dbd839bda337cb73911aeef06897eb29cb99f76f", "type": "github" }, "original": { @@ -1725,11 +1800,11 @@ "plugin-gitsigns-nvim": { "flake": false, "locked": { - "lastModified": 1730713501, - "narHash": "sha256-FHzufzeVrPnbU5j3UabVTCYXP+QNcb7gMgef0BmuclA=", + "lastModified": 1732361574, + "narHash": "sha256-H7A+AxioiedSuC+jqRwP4c7DjZR/0j4o/fTUasT2urc=", "owner": "lewis6991", "repo": "gitsigns.nvim", - "rev": "4daf7022f1481edf1e8fb9947df13bb07c18e89a", + "rev": "5f808b5e4fef30bd8aca1b803b4e555da07fc412", "type": "github" }, "original": { @@ -1757,11 +1832,11 @@ "plugin-gruvbox": { "flake": false, "locked": { - "lastModified": 1727809136, - "narHash": "sha256-/kgZuNJ1vHyOpvFHiJKCb1HzjSPgqis9Ng4aT7jHXG4=", + "lastModified": 1732485864, + "narHash": "sha256-qasIg1nvAlUWUUzSZLF36jnoNm8PmQa3owgh0tKGgHk=", "owner": "ellisonleao", "repo": "gruvbox.nvim", - "rev": "49d9c0b150ba70efcd831ec7b3cb8ee740067045", + "rev": "68c3460a5d1d1a362318960035c9f3466d5011f5", "type": "github" }, "original": { @@ -1770,14 +1845,30 @@ "type": "github" } }, + "plugin-haskell-tools-nvim": { + "flake": false, + "locked": { + "lastModified": 1734222260, + "narHash": "sha256-gZVN9ADPO5wFOaf19FydCneb7aKTT9K1vcLoBURPEjk=", + "owner": "mrcjkb", + "repo": "haskell-tools.nvim", + "rev": "943b77b68a79d3991523ba4d373063c9355c6f55", + "type": "github" + }, + "original": { + "owner": "mrcjkb", + "repo": "haskell-tools.nvim", + "type": "github" + } + }, "plugin-highlight-undo": { "flake": false, "locked": { - "lastModified": 1729426343, - "narHash": "sha256-zNzVmt4WJcspuloePhc6HbDvNA7B92NscE+fEYvCumc=", + "lastModified": 1732378966, + "narHash": "sha256-b0JrMu3vbbYgyHPs9hyayMzUypFwugEAxvZOcuRMc/o=", "owner": "tzachar", "repo": "highlight-undo.nvim", - "rev": "c87a6ec1ded241ef223269077cbd5f97a6f0d5bf", + "rev": "5f588b420179a31d7073854bfd07ed9d5f364645", "type": "github" }, "original": { @@ -1821,11 +1912,11 @@ "plugin-image-nvim": { "flake": false, "locked": { - "lastModified": 1730854538, - "narHash": "sha256-G7Nqs8BqLCR46vw6VVazvdGOpan6Wkkv/PfJB+nBbGE=", + "lastModified": 1735173549, + "narHash": "sha256-Sjbmf4BmjkjAorT3tojbC7JivJagFamAVgzwcCipa8k=", "owner": "3rd", "repo": "image.nvim", - "rev": "9c9dbed0cdb4dbd199ebfc678a881f5745a36f50", + "rev": "b991fc7f845bc6ab40c6ec00b39750dcd5190010", "type": "github" }, "original": { @@ -1837,11 +1928,11 @@ "plugin-indent-blankline": { "flake": false, "locked": { - "lastModified": 1730170343, - "narHash": "sha256-odv43EyZ3gMg410eBFAkye/SdAj+LcVVZPaZm8w0biM=", + "lastModified": 1733296464, + "narHash": "sha256-H3lUQZDvgj3a2STYeMUDiOYPe7rfsy08tJ4SlDd+LuE=", "owner": "lukas-reineke", "repo": "indent-blankline.nvim", - "rev": "04e44b09ee3ff189c69ab082edac1ef7ae2e256c", + "rev": "259357fa4097e232730341fa60988087d189193a", "type": "github" }, "original": { @@ -1869,11 +1960,11 @@ "plugin-lsp-lines": { "flake": false, "locked": { - "lastModified": 1716108775, - "narHash": "sha256-QsvmPOer7JgO7Y+N/iaNJD7Kmy69gnlV4CeyaQesNvA=", + "lastModified": 1734793049, + "narHash": "sha256-jHiIZemneQACTDYZXBJqX2/PRTBoxq403ILvt1Ej1ZM=", "owner": "~whynothugo", "repo": "lsp_lines.nvim", - "rev": "7d9e2748b61bff6ebba6e30adbc7173ccf21c055", + "rev": "a92c755f182b89ea91bd8a6a2227208026f27b4d", "type": "sourcehut" }, "original": { @@ -1901,11 +1992,11 @@ "plugin-lspkind": { "flake": false, "locked": { - "lastModified": 1729872608, - "narHash": "sha256-/ifgjqqCQw67l3+gUs00tt860pa92M1WYdjdZ0lhxak=", + "lastModified": 1733408701, + "narHash": "sha256-OCvKUBGuzwy8OWOL1x3Z3fo+0+GyBMI9TX41xSveqvE=", "owner": "onsails", "repo": "lspkind-nvim", - "rev": "a700f1436d4a938b1a1a93c9962dc796afbaef4d", + "rev": "d79a1c3299ad0ef94e255d045bed9fa26025dab6", "type": "github" }, "original": { @@ -1965,11 +2056,11 @@ "plugin-luasnip": { "flake": false, "locked": { - "lastModified": 1730895001, - "narHash": "sha256-Vb4unHnhppcM1HZtd8oohJHPlkUHORoYUjKUWyhRM6g=", + "lastModified": 1733162004, + "narHash": "sha256-efDe3RXncnNVkj37AmIv8oj0DKurB50Dziao5FGTLP4=", "owner": "L3MON4D3", "repo": "LuaSnip", - "rev": "2737edc9e674e537dc0a97e3405658d57d2d31ed", + "rev": "33b06d72d220aa56a7ce80a0dd6f06c70cd82b9d", "type": "github" }, "original": { @@ -1981,11 +2072,11 @@ "plugin-lz-n": { "flake": false, "locked": { - "lastModified": 1730598851, - "narHash": "sha256-L7og7ZTo5Soyn6pvBHkJcgGuON96eV0V5QC3J1uz/ko=", + "lastModified": 1735437369, + "narHash": "sha256-6NIXqwmX7RgwiZVEzmTnkJgmrPqFNx12ayIcRgNIaEs=", "owner": "nvim-neorocks", "repo": "lz.n", - "rev": "c8675c983e0682c49a13f17fc7ff9353bcb32120", + "rev": "32be28a221b9c98e56841458e4b20c150a4169c4", "type": "github" }, "original": { @@ -2046,11 +2137,11 @@ "plugin-modes-nvim": { "flake": false, "locked": { - "lastModified": 1717693302, - "narHash": "sha256-z1XD0O+gG2/+g/skdWGC64Zv4dXvvhWesaK/8DcPF/E=", + "lastModified": 1734414076, + "narHash": "sha256-ShIK8ROowT1yFHgSIVHUFnnQOEMr3YPIqw4ixzR8w8M=", "owner": "mvllow", "repo": "modes.nvim", - "rev": "326cff3282419b3bcc745061978c1e592cae055d", + "rev": "c7a4b1b383606832aab150902719bd5eb5cdb2b0", "type": "github" }, "original": { @@ -2062,11 +2153,11 @@ "plugin-neo-tree-nvim": { "flake": false, "locked": { - "lastModified": 1726542367, - "narHash": "sha256-Lqt0KJNT9HmpJwZoWChYeVBrDWhscRe8COqVCwgcTwk=", + "lastModified": 1735302061, + "narHash": "sha256-tZMneZsEbB5bgZgYq4ZWwK25B3vcnn80Q7diKcRoEv4=", "owner": "nvim-neo-tree", "repo": "neo-tree.nvim", - "rev": "a77af2e764c5ed4038d27d1c463fa49cd4794e07", + "rev": "a9f8943b4c31f8460d25c71e0f463d65e9775f1c", "type": "github" }, "original": { @@ -2078,11 +2169,11 @@ "plugin-neocord": { "flake": false, "locked": { - "lastModified": 1729369963, - "narHash": "sha256-4dVaxigJ8eOXpgiqcxUYIF4SoC1CPFvNHYKT0zxIYo0=", + "lastModified": 1733429637, + "narHash": "sha256-g/pq6hFo7duonIl1wWoxbJUTh/IRTH3hHEoQUdoiqKE=", "owner": "IogaMaster", "repo": "neocord", - "rev": "587e03390a355e9c364d48638e0e0db2a8431d73", + "rev": "4d55d8dab2d5f2f272192add7a2c21982039c699", "type": "github" }, "original": { @@ -2110,11 +2201,11 @@ "plugin-neorg": { "flake": false, "locked": { - "lastModified": 1730333767, - "narHash": "sha256-qTo8rxwvANrgP8UccFhzsNsH+Jbmqv2iOlw0ccLNYm4=", + "lastModified": 1734188232, + "narHash": "sha256-xH87caxEebrWLwY/v3xyyOy6PTG/ZqX2OfCdwg/RqDY=", "owner": "nvim-neorg", "repo": "neorg", - "rev": "488507bb996f75ee29073f50dec32fa220867ca5", + "rev": "6b945909d84b5aeadc875f9b3f529ec44b9bc60f", "type": "github" }, "original": { @@ -2158,11 +2249,11 @@ "plugin-noice-nvim": { "flake": false, "locked": { - "lastModified": 1731163840, - "narHash": "sha256-zT+fJ88V/LfmibXs4QpIyxCu1HHSjbqsrcQK/vadeRA=", + "lastModified": 1734026622, + "narHash": "sha256-OpwgNTGunmy6Y7D/k0T+DFK/WJ8MeVTGWwjiPTQlvEY=", "owner": "folke", "repo": "noice.nvim", - "rev": "2087bbf8cd64482b47fb5f33b5e0eabf329ab14b", + "rev": "eaed6cc9c06aa2013b5255349e4f26a6b17ab70f", "type": "github" }, "original": { @@ -2191,11 +2282,11 @@ "plugin-nui-nvim": { "flake": false, "locked": { - "lastModified": 1726376728, - "narHash": "sha256-90Wq+vT361mTaGU/SvAezqJkX9HHmZ2GI2fKBDxPn04=", + "lastModified": 1733856815, + "narHash": "sha256-6U7E/i5FuNXQy+sF4C5DVxuTPqNKD5wxUgFohpOjm9Q=", "owner": "MunifTanjim", "repo": "nui.nvim", - "rev": "b58e2bfda5cea347c9d58b7f11cf3012c7b3953f", + "rev": "53e907ffe5eedebdca1cd503b00aa8692068ca46", "type": "github" }, "original": { @@ -2207,11 +2298,11 @@ "plugin-nvim-autopairs": { "flake": false, "locked": { - "lastModified": 1727742362, - "narHash": "sha256-pqYOaEjKUd5YLVWX0Bf/kYT+sBlN1D24rOBuIz2BIqk=", + "lastModified": 1731803843, + "narHash": "sha256-LbaxiU3ienVBcMKrug3Coppc4R+MD2rjREw7rHQim1w=", "owner": "windwp", "repo": "nvim-autopairs", - "rev": "ee297f215e95a60b01fde33275cc3c820eddeebe", + "rev": "b464658e9b880f463b9f7e6ccddd93fb0013f559", "type": "github" }, "original": { @@ -2223,11 +2314,11 @@ "plugin-nvim-bufferline-lua": { "flake": false, "locked": { - "lastModified": 1729768480, - "narHash": "sha256-MpSX8a51Avc9O1XxfWIDOVLiqD7omwAFIwSa02oXNs0=", + "lastModified": 1732824069, + "narHash": "sha256-zqz2GMius0gLxtgxt12RmLUVQFVaWe+MQaGCfUGr6bI=", "owner": "akinsho", "repo": "nvim-bufferline.lua", - "rev": "5cc447cb2b463cb499c82eaeabbed4f5fa6a0a44", + "rev": "261a72b90d6db4ed8014f7bda976bcdc9dd7ce76", "type": "github" }, "original": { @@ -2239,11 +2330,11 @@ "plugin-nvim-cmp": { "flake": false, "locked": { - "lastModified": 1730523275, - "narHash": "sha256-iNEoMl/X0nh2sAio1h+dkuobeOXRBXKFJCcElUyyW54=", + "lastModified": 1734672427, + "narHash": "sha256-Z/Qy2ErbCa7dbjZVuJUkMmb4d24amNunNgRcbCGPfOg=", "owner": "hrsh7th", "repo": "nvim-cmp", - "rev": "f17d9b4394027ff4442b298398dfcaab97e40c4f", + "rev": "b555203ce4bd7ff6192e759af3362f9d217e8c89", "type": "github" }, "original": { @@ -2255,11 +2346,11 @@ "plugin-nvim-colorizer-lua": { "flake": false, "locked": { - "lastModified": 1730855006, - "narHash": "sha256-jDnTDUzslVa+4S2vAwqUZeJN+9Fxf5Naunf6uG54HLI=", + "lastModified": 1735384185, + "narHash": "sha256-quqs3666vQc/4ticc/Z5BHzGxV6UUVE9jVGT07MEMQQ=", "owner": "NvChad", "repo": "nvim-colorizer.lua", - "rev": "f134063618a65cad4d7415fddbd96ff7e0c5b4ae", + "rev": "8a65c448122fc8fac9c67b2e857b6e830a4afd0b", "type": "github" }, "original": { @@ -2287,11 +2378,11 @@ "plugin-nvim-dap": { "flake": false, "locked": { - "lastModified": 1730842757, - "narHash": "sha256-WiypPzEQnModkzgI7ikq2C9OKc/DBeGLZ8ZaKmzHt2c=", + "lastModified": 1735568902, + "narHash": "sha256-5iaXim9bDvSAI6jUXgu2OEk/KivfAsMTRry+UTHs2Gk=", "owner": "mfussenegger", "repo": "nvim-dap", - "rev": "8517126e9323e346f6a99b3b594c5a940b914dcd", + "rev": "ffb077e65259f13be096ea6d603e3575a76b214a", "type": "github" }, "original": { @@ -2319,11 +2410,11 @@ "plugin-nvim-dap-ui": { "flake": false, "locked": { - "lastModified": 1727897692, - "narHash": "sha256-kg7lyVBeuBqPCVzvt3pBoonQupgf1nGh3EvCF/astf4=", + "lastModified": 1735324898, + "narHash": "sha256-psIBQpx3tV2UWm5hZTMPBANcXHPAX24dIuDq8Qcscxs=", "owner": "rcarriga", "repo": "nvim-dap-ui", - "rev": "ffa89839f97bad360e78428d5c740fdad9a0ff02", + "rev": "e94d98649dccb6a3884b66aabc2e07beb279e535", "type": "github" }, "original": { @@ -2335,11 +2426,11 @@ "plugin-nvim-docs-view": { "flake": false, "locked": { - "lastModified": 1723781320, - "narHash": "sha256-6kd3IWsD72eYe+q1w78gcFcK9LalCQHCqtSwwqQR3Ew=", + "lastModified": 1733658747, + "narHash": "sha256-b5aH8Tj+tMk0BjNCgdeCEeR26oQ9NCobj98P7IDgIPY=", "owner": "amrbashir", "repo": "nvim-docs-view", - "rev": "365593534e0acd762bfddce6e8313315ffa4fa36", + "rev": "1b97f8f954d74c46061bf289b6cea9232484c12c", "type": "github" }, "original": { @@ -2351,11 +2442,11 @@ "plugin-nvim-lightbulb": { "flake": false, "locked": { - "lastModified": 1729134062, - "narHash": "sha256-JfXSuOBwyxgH/PzzcBQ7OqoXHkLGZSCYutYHLocbTto=", + "lastModified": 1734997673, + "narHash": "sha256-byvgRJvvt5rhiUVWdreY2jELXoPVld5EKQlOXwjNgWE=", "owner": "kosayoda", "repo": "nvim-lightbulb", - "rev": "33d4c95e0e853956bc9468b70b3064c87d5abaca", + "rev": "3ac0791be37ba9cc7939f1ad90ebc5e75abf4eea", "type": "github" }, "original": { @@ -2367,11 +2458,11 @@ "plugin-nvim-lspconfig": { "flake": false, "locked": { - "lastModified": 1730978746, - "narHash": "sha256-N1vqosgHHVUWoszhdGImH//mb7hiSWWsG1Pq9WNnQxk=", + "lastModified": 1735439232, + "narHash": "sha256-6a1HjpLYdZ+ZmWM1B0tv631A3EHHstPrjaV15UnVtoY=", "owner": "neovim", "repo": "nvim-lspconfig", - "rev": "d01864641c6e43c681c3e9f6cf4745c75fdd9dcc", + "rev": "8b15a1a597a59f4f5306fad9adfe99454feab743", "type": "github" }, "original": { @@ -2383,11 +2474,11 @@ "plugin-nvim-metals": { "flake": false, "locked": { - "lastModified": 1728295172, - "narHash": "sha256-ja/+MNxZ3H9io9jDwm5rhE6iKNi86a22eCOY75g19O8=", + "lastModified": 1735386491, + "narHash": "sha256-G9V7fX65uW4z7kiuiP8mLtEjLoTJ1mkltj51OlN5/oM=", "owner": "scalameta", "repo": "nvim-metals", - "rev": "f861db9fda55939797ac1b05238c49b0dcdc3bdb", + "rev": "e6b02c99161b43c67cfe1d6e5f9a9b9a0bb4701c", "type": "github" }, "original": { @@ -2431,11 +2522,11 @@ "plugin-nvim-neoclip": { "flake": false, "locked": { - "lastModified": 1725927226, - "narHash": "sha256-GHkTIGPgX5j1wUS9EW/fGOp3NSRjfVaz+6o1Aehy2Xw=", + "lastModified": 1734898459, + "narHash": "sha256-RCMZi1DM9JFrXWQ5w2wOjFzpANkiukn+RvHB9swMtbk=", "owner": "AckslD", "repo": "nvim-neoclip.lua", - "rev": "32e05f2d23dc5b6a284a688c0535a83d1bfc633f", + "rev": "5e5e010251281f4aea69cfc1d4976ffe6065cf0f", "type": "github" }, "original": { @@ -2463,11 +2554,11 @@ "plugin-nvim-notify": { "flake": false, "locked": { - "lastModified": 1727022370, - "narHash": "sha256-Sd7IR5roXHOKRCxhqtYMhWfEltyRJMDEMDO/ecSKenE=", + "lastModified": 1735562588, + "narHash": "sha256-9jDpoLLto9WgTsV399WeE2XGrTJXWTYbcJ+zOFWldAA=", "owner": "rcarriga", "repo": "nvim-notify", - "rev": "fbef5d32be8466dd76544a257d3f3dce20082a07", + "rev": "c3797193536711b5d8983975791c4b11dc35ab3a", "type": "github" }, "original": { @@ -2511,11 +2602,11 @@ "plugin-nvim-surround": { "flake": false, "locked": { - "lastModified": 1730136751, - "narHash": "sha256-XVwvoM3Id9lCi9EgK/Y944UuCXj9niTnZ5I5+d1yVqQ=", + "lastModified": 1732818349, + "narHash": "sha256-sC+V86FEDfIapY4Qy0Ch2dTUpqe+C/xEUR/iSIEY6LA=", "owner": "kylechui", "repo": "nvim-surround", - "rev": "dca2e998ff26681ee422b92c6ed39b3d2908d8a9", + "rev": "9f0cb495f25bff32c936062d85046fbda0c43517", "type": "github" }, "original": { @@ -2527,11 +2618,11 @@ "plugin-nvim-tree-lua": { "flake": false, "locked": { - "lastModified": 1731123986, - "narHash": "sha256-zt04Q3Mr1k9x6X6l3F9iy3C1edQYha4pQhDsOX5atPM=", + "lastModified": 1734820548, + "narHash": "sha256-4PmP31vYPH9xw4AjV5rDSKvcvZGTnIaPfR4Bwc0lAiA=", "owner": "nvim-tree", "repo": "nvim-tree.lua", - "rev": "c7639482a1598f4756798df1b2d72f79fe5bb34f", + "rev": "68fc4c20f5803444277022c681785c5edd11916d", "type": "github" }, "original": { @@ -2543,11 +2634,11 @@ "plugin-nvim-treesitter-context": { "flake": false, "locked": { - "lastModified": 1731163983, - "narHash": "sha256-oRmhwRIynCNmgKpTtwUIliYf0Qo+zP3ymEWYs+vzx8A=", + "lastModified": 1734710732, + "narHash": "sha256-TIFMPKzD2ero1eK9aVfY1iKEvf/Sw8SL/9mk9omCQ3c=", "owner": "nvim-treesitter", "repo": "nvim-treesitter-context", - "rev": "158377d700596367a91ea41818f76abdbf75a232", + "rev": "2bcf700b59bc92850ca83a1c02e86ba832e0fae0", "type": "github" }, "original": { @@ -2559,11 +2650,11 @@ "plugin-nvim-ts-autotag": { "flake": false, "locked": { - "lastModified": 1724798540, - "narHash": "sha256-QEzUKvT+ChYSa9F4zg3Lw+7Sj0JzJem9nh2mWmS8Y+I=", + "lastModified": 1733164313, + "narHash": "sha256-v2NTFBIzKTYizUPWB3uhpnTGVZWaelhE3MT5+BDA6Do=", "owner": "windwp", "repo": "nvim-ts-autotag", - "rev": "e239a560f338be31337e7abc3ee42515daf23f5e", + "rev": "1cca23c9da708047922d3895a71032bc0449c52d", "type": "github" }, "original": { @@ -2575,11 +2666,11 @@ "plugin-nvim-web-devicons": { "flake": false, "locked": { - "lastModified": 1728608318, - "narHash": "sha256-SUWEOp+QcfHjYaqqr4Zwvh0x91IAJXvrdMkQtuWMlGc=", + "lastModified": 1735569123, + "narHash": "sha256-h9rY6F+2sBlG9PFN34/0ZTkY66oCeCIPe/HEadM03K4=", "owner": "nvim-tree", "repo": "nvim-web-devicons", - "rev": "19d257cf889f79f4022163c3fbb5e08639077bd8", + "rev": "4adeeaa7a32d46cf3b5833341358c797304f950a", "type": "github" }, "original": { @@ -2607,11 +2698,11 @@ "plugin-omnisharp-extended": { "flake": false, "locked": { - "lastModified": 1719701797, - "narHash": "sha256-P1ZCaW8w+e3H3oBhbEjDc7vuR+XuxJmb/7IbPL3KWi4=", + "lastModified": 1732802864, + "narHash": "sha256-lA22ncMWHz2oVcZMPQGpLL3UjjXOXGxhtXR1LX5cX3A=", "owner": "Hoffs", "repo": "omnisharp-extended-lsp.nvim", - "rev": "aad7bf06b4ca0de816b919d475a75b30f5f62b61", + "rev": "4916fa12e5b28d21a1f031f0bdd10aa15a75d85d", "type": "github" }, "original": { @@ -2639,11 +2730,11 @@ "plugin-orgmode-nvim": { "flake": false, "locked": { - "lastModified": 1730794385, - "narHash": "sha256-Rt/qhulJjNolQLz9OdP25U2+3KButPHgHc886yFpLpE=", + "lastModified": 1734770880, + "narHash": "sha256-E1YJeTay1tX2PgiXwV/DRgrlYHIGUe9/uTA+6ORIhBw=", "owner": "nvim-orgmode", "repo": "orgmode", - "rev": "fafb8f14d85a68d8f0fca812444cc0fd594f0168", + "rev": "bf657742f7cb56211f99946ff64f5f87d7d7f0d0", "type": "github" }, "original": { @@ -2655,11 +2746,11 @@ "plugin-otter-nvim": { "flake": false, "locked": { - "lastModified": 1724585935, - "narHash": "sha256-euHwoK2WHLF/hrjLY2P4yGrIbYyBN38FL3q4CKNZmLY=", + "lastModified": 1735130975, + "narHash": "sha256-NPBGcLi1lEmpGGbGs58Xzw1IriOyKTMQdwIdVFsbVDM=", "owner": "jmbuhr", "repo": "otter.nvim", - "rev": "ca9ce67d0399380b659923381b58d174344c9ee7", + "rev": "e8c662e1aefa8b483cfba6e00729a39a363dcecc", "type": "github" }, "original": { @@ -2719,11 +2810,11 @@ "plugin-precognition-nvim": { "flake": false, "locked": { - "lastModified": 1730325090, - "narHash": "sha256-onY1Aa+dwLR1wRua52hpSXj6zZOZXjkUlDjDa0xEEcE=", + "lastModified": 1732647805, + "narHash": "sha256-m3dKoKxCd/QODM+EL89c3RVOoZnuA4nrBG0KhPZ/o9Y=", "owner": "tris203", "repo": "precognition.nvim", - "rev": "0189e8d6f96275a079b2805d68d49414871885cd", + "rev": "531971e6d883e99b1572bf47294e22988d8fbec0", "type": "github" }, "original": { @@ -2764,14 +2855,30 @@ "type": "github" } }, + "plugin-render-markdown-nvim": { + "flake": false, + "locked": { + "lastModified": 1735525479, + "narHash": "sha256-ncFqBv0JITX3pTsLON+HctLUaKXhLRMBUrRWmI8KOSA=", + "owner": "MeanderingProgrammer", + "repo": "render-markdown.nvim", + "rev": "6fbd1491abc104409f119685de5353c35c97c005", + "type": "github" + }, + "original": { + "owner": "MeanderingProgrammer", + "repo": "render-markdown.nvim", + "type": "github" + } + }, "plugin-rose-pine": { "flake": false, "locked": { - "lastModified": 1729724348, - "narHash": "sha256-/a4pwuVJ5odm3Iio2MeoqAm8GlWIPI91mM4cVnSy/gE=", + "lastModified": 1733845819, + "narHash": "sha256-ejh9UXQbLc8Ie6wF7zszzL1gaJzr16gcu0dUWqTo8AM=", "owner": "rose-pine", "repo": "neovim", - "rev": "07a887a7bef4aacea8c7caebaf8cbf808cdc7a8e", + "rev": "91548dca53b36dbb9d36c10f114385f759731be1", "type": "github" }, "original": { @@ -2799,11 +2906,11 @@ "plugin-run-nvim": { "flake": false, "locked": { - "lastModified": 1732918526, - "narHash": "sha256-kiszNmZZDXG8tAPMQKuGJDCkqCMzsWT7BkCvkVsH2lA=", + "lastModified": 1735501787, + "narHash": "sha256-CFOyOARCLQiMOhFPeqz8n2ULyaaRxRZrOk0FCibjuIM=", "owner": "diniamo", "repo": "run.nvim", - "rev": "d867466e01b8fa4e54a589b9ef446cf43fb966de", + "rev": "9015c9cece816ccf10a185b420f6e345fd990802", "type": "github" }, "original": { @@ -2815,11 +2922,11 @@ "plugin-rustaceanvim": { "flake": false, "locked": { - "lastModified": 1732565373, - "narHash": "sha256-WRaNW0trZYEUKd05Uc+5nP+G81HI14d6lM7/WWz61E0=", + "lastModified": 1735431742, + "narHash": "sha256-ucZXGbxHtbSKf5n11lL3vb6rD2BxJacIDOgcx32PLzA=", "owner": "mrcjkb", "repo": "rustaceanvim", - "rev": "fee0aa094b0c9f93fffe5a385b3d5d2386c2b072", + "rev": "51c097ebfb65d83baa71f48000b1e5c0a8dcc4fb", "type": "github" }, "original": { @@ -2831,11 +2938,11 @@ "plugin-smartcolumn": { "flake": false, "locked": { - "lastModified": 1710067624, - "narHash": "sha256-DHIeDNUF9n9s14GVeojIwc5QUPwJMYYl3gRvhvO/rdE=", + "lastModified": 1734696989, + "narHash": "sha256-6RodA5BQnL6tB3RCE5G2RiXqBvM3VP3HYZ+T3AxIF7Q=", "owner": "m4xshen", "repo": "smartcolumn.nvim", - "rev": "cefb17be095ad5526030a21bb2a80553cae09127", + "rev": "f14fbea6f86cd29df5042897ca9e3ba10ba4d27f", "type": "github" }, "original": { @@ -2847,11 +2954,11 @@ "plugin-sqls-nvim": { "flake": false, "locked": { - "lastModified": 1684697500, - "narHash": "sha256-jKFut6NZAf/eIeIkY7/2EsjsIhvZQKCKAJzeQ6XSr0s=", + "lastModified": 1733090837, + "narHash": "sha256-o5uD6shPkweuE+k/goBX42W3I2oojXVijfJC7L50sGU=", "owner": "nanotee", "repo": "sqls.nvim", - "rev": "4b1274b5b44c48ce784aac23747192f5d9d26207", + "rev": "a514379f5f89bf72955ed3bf5c1c31a40b8a1472", "type": "github" }, "original": { @@ -2879,11 +2986,11 @@ "plugin-telescope": { "flake": false, "locked": { - "lastModified": 1730164948, - "narHash": "sha256-Qa/f+0asQvA8mhIUajC4BGZCI92OqA6ySVoQSC3ZY3s=", + "lastModified": 1732884846, + "narHash": "sha256-npb61MZYAotz71Co5G1dUeIqWt7GVeqZNz0A2Yz2dy4=", "owner": "nvim-telescope", "repo": "telescope.nvim", - "rev": "85922dde3767e01d42a08e750a773effbffaea3e", + "rev": "2eca9ba22002184ac05eddbe47a7fe2d5a384dfc", "type": "github" }, "original": { @@ -2895,11 +3002,11 @@ "plugin-tiny-devicons-auto-colors": { "flake": false, "locked": { - "lastModified": 1724403745, - "narHash": "sha256-Ndkbvxn/x7+fxEYD7JIygqUiItuhoY+4+DaL/pJGKdc=", + "lastModified": 1733445616, + "narHash": "sha256-klUZKvdYhwO3sq4Su4sBFDcNSAYXh53O72vg4+ZOrhI=", "owner": "rachartier", "repo": "tiny-devicons-auto-colors.nvim", - "rev": "a39fa4c92268832f6034306793b8acbfec2a7549", + "rev": "c8f63933ee013c1e0a26091d58131e060546f01f", "type": "github" }, "original": { @@ -2927,11 +3034,11 @@ "plugin-toggleterm-nvim": { "flake": false, "locked": { - "lastModified": 1731162901, - "narHash": "sha256-g1FwgCc3a8Fak0Nb0gQQ+SI44uyAGaH1tIk1qpaAPEY=", + "lastModified": 1735340326, + "narHash": "sha256-oeNIb+QHa/9yGZz/2u9LYIdKluel0bcQkaIqOuQUkis=", "owner": "akinsho", "repo": "toggleterm.nvim", - "rev": "87b2d6a3cab8e2bd9a0255427074285f0365398d", + "rev": "344fc1810292785b3d962ddac2de57669e1a7ff9", "type": "github" }, "original": { @@ -2943,11 +3050,11 @@ "plugin-tokyonight": { "flake": false, "locked": { - "lastModified": 1730826006, - "narHash": "sha256-BkSkC9UKcDExpIx91air280soPa8QIa3eK/e/E5QYLc=", + "lastModified": 1734211493, + "narHash": "sha256-TJ/a6N6Cc1T0wdMxMopma1NtwL7rMYbZ6F0zFI1zaIA=", "owner": "folke", "repo": "tokyonight.nvim", - "rev": "ce91ba480070c95f40753e4663e32b4632ac6db3", + "rev": "45d22cf0e1b93476d3b6d362d720412b3d34465c", "type": "github" }, "original": { @@ -2959,11 +3066,11 @@ "plugin-trouble": { "flake": false, "locked": { - "lastModified": 1730928038, - "narHash": "sha256-zUh0o+piRVDMSXLjBj+IygZj3VX7i5nXsaNn2pPu1fg=", + "lastModified": 1732701472, + "narHash": "sha256-JhnERZfma2JHFEn/DElVmrSU5KxM2asx3SJ+86lCfoo=", "owner": "folke", "repo": "trouble.nvim", - "rev": "3dc00c0447c016cd43e03054c3d49436a1f2076d", + "rev": "46cf952fc115f4c2b98d4e208ed1e2dce08c9bf6", "type": "github" }, "original": { @@ -2975,11 +3082,11 @@ "plugin-ts-error-translator": { "flake": false, "locked": { - "lastModified": 1727112009, - "narHash": "sha256-8eUDQJYfhEsqv9G1QU96k5tTIcVa8oR8/SAoFN1XZ5I=", + "lastModified": 1731721659, + "narHash": "sha256-fi68jJVNTL2WlTehcl5Q8tijAeu2usjIsWXjcuixkCM=", "owner": "dmmulroy", "repo": "ts-error-translator.nvim", - "rev": "3bd23c4cfe4c2edc99278e01b75cdb2a26f03152", + "rev": "47e5ba89f71b9e6c72eaaaaa519dd59bd6897df4", "type": "github" }, "original": { @@ -2988,6 +3095,22 @@ "type": "github" } }, + "plugin-typst-preview-nvim": { + "flake": false, + "locked": { + "lastModified": 1734839452, + "narHash": "sha256-d6Tv7xZRghYYDfABk/p2e9qTm4qnWHM+ejKDCcR0TfY=", + "owner": "chomosuke", + "repo": "typst-preview.nvim", + "rev": "c1100e8788baabe8ca8f8cd7fd63d3d479e49e36", + "type": "github" + }, + "original": { + "owner": "chomosuke", + "repo": "typst-preview.nvim", + "type": "github" + } + }, "plugin-vim-dirtytalk": { "flake": false, "locked": { @@ -3007,11 +3130,11 @@ "plugin-vim-fugitive": { "flake": false, "locked": { - "lastModified": 1725670815, - "narHash": "sha256-ArYerBws+MBY4BpKh16J5TfVTrA0OFKPoZq7c2YQjp0=", + "lastModified": 1735457366, + "narHash": "sha256-45zsqKavWoclA67MC54bAel1nE8CLHtSdullHByiRS8=", "owner": "tpope", "repo": "vim-fugitive", - "rev": "d4877e54cef67f5af4f950935b1ade19ed6b7370", + "rev": "174230d6a7f2df94705a7ffd8d5413e27ec10a80", "type": "github" }, "original": { @@ -3087,11 +3210,11 @@ "plugin-which-key": { "flake": false, "locked": { - "lastModified": 1730919714, - "narHash": "sha256-5t6UnOP2+CXB55/C4YWbp2pE+xKDLMvCJK8m085Fk4w=", + "lastModified": 1734253151, + "narHash": "sha256-f/+sYMDEguB5ZDiYiQAsDvdF/2cVcWnLBU+9qwigk4s=", "owner": "folke", "repo": "which-key.nvim", - "rev": "68e37e12913a66b60073906f5d3f14dee0de19f2", + "rev": "8ab96b38a2530eacba5be717f52e04601eb59326", "type": "github" }, "original": { @@ -3111,11 +3234,11 @@ "nixpkgs-stable": "nixpkgs-stable_2" }, "locked": { - "lastModified": 1731363552, - "narHash": "sha256-vFta1uHnD29VUY4HJOO/D6p6rxyObnf+InnSMT4jlMU=", + "lastModified": 1734797603, + "narHash": "sha256-ulZN7ps8nBV31SE+dwkDvKIzvN6hroRY8sYOT0w+E28=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "cd1af27aa85026ac759d5d3fccf650abe7e1bbf0", + "rev": "f0f0dc4920a903c3e08f5bdb9246bb572fcae498", "type": "github" }, "original": { @@ -3127,7 +3250,7 @@ "rnix-lsp": { "inputs": { "naersk": "naersk", - "nixpkgs": "nixpkgs_5", + "nixpkgs": "nixpkgs_4", "utils": "utils" }, "locked": { @@ -3177,11 +3300,11 @@ ] }, "locked": { - "lastModified": 1726453838, - "narHash": "sha256-pupsow4L79SBfNwT6vh/5RAbVZuhngIA0RTCZksXmZY=", + "lastModified": 1731983527, + "narHash": "sha256-JECaBgC0pQ91Hq3W4unH6K9to8s2Zl2sPNu7bLOv4ek=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "ca2e79cd22625d214b8437c2c4080ce79bd9f7d2", + "rev": "71287228d96e9568e1e70c6bbfa3f992d145947b", "type": "github" }, "original": { @@ -3198,11 +3321,11 @@ ] }, "locked": { - "lastModified": 1730687492, - "narHash": "sha256-xQVadjquBA/tFxDt5A55LJ1D1AvkVWsnrKC2o+pr8F4=", + "lastModified": 1734834660, + "narHash": "sha256-bm8V+Cu8rWJA+vKQnc94mXTpSDgvedyoDKxTVi/uJfw=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "41814763a2c597755b0755dbe3e721367a5e420f", + "rev": "b070e6030118680977bc2388868c4b3963872134", "type": "github" }, "original": { @@ -3389,11 +3512,11 @@ ] }, "locked": { - "lastModified": 1731703417, - "narHash": "sha256-rheDc/7C+yI+QspYr9J2z9kQ5P9F4ATapI7qyFAe1XA=", + "lastModified": 1734907020, + "narHash": "sha256-p6HxwpRKVl1KIiY5xrJdjcEeK3pbmc///UOyV6QER+w=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "8070f36deec723de71e7557441acb17e478204d3", + "rev": "d7f18dda5e511749fa1511185db3536208fb1a63", "type": "github" }, "original": { @@ -3431,15 +3554,15 @@ "inputs": { "crane": "crane", "flake-utils": "flake-utils_4", - "nixpkgs": "nixpkgs_6", + "nixpkgs": "nixpkgs_5", "rust-overlay": "rust-overlay_2" }, "locked": { - "lastModified": 1731757608, - "narHash": "sha256-yWY2aGfsBVTT9vtwRqVnNqkiB0xcWcB1MoITrvPmEtA=", + "lastModified": 1735846901, + "narHash": "sha256-rcyuAGKYYSLHueXGSktzCSHOO4gHyg6KDi6R9aIFpug=", "owner": "dj95", "repo": "zjstatus", - "rev": "5d6ff93551882fddc7773f108470001fe87a5187", + "rev": "bc15143d662f2c22fced866b0376d360ebc5f36c", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index b2e5a9c..582e514 100644 --- a/flake.nix +++ b/flake.nix @@ -35,7 +35,10 @@ inputs.nixpkgs.follows = "nixpkgs"; }; - nvf.url = "github:notashelf/nvf"; + nvf = { + url = "github:notashelf/nvf"; + inputs.nixpkgs.follows = "nixpkgs"; + }; # confine vpns to specific systemd services vpn-confinement.url = "github:Maroka-chan/VPN-Confinement"; From 09715c85706c5860c4a9c1813ac6be25ddc5c9e7 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 16:30:21 +1100 Subject: [PATCH 105/213] vesktop: remove patch --- .../communication/vesktop/default.nix | 4 +- .../communication/vesktop/vesktop-patch.patch | 76 ------------------- 2 files changed, 1 insertion(+), 79 deletions(-) delete mode 100644 modules/home/workstation/communication/vesktop/vesktop-patch.patch diff --git a/modules/home/workstation/communication/vesktop/default.nix b/modules/home/workstation/communication/vesktop/default.nix index 4ca0ce3..ecdeec5 100644 --- a/modules/home/workstation/communication/vesktop/default.nix +++ b/modules/home/workstation/communication/vesktop/default.nix @@ -15,9 +15,7 @@ in { config = mkIf (elem "communication" profiles) { # home.packages = [ - (pkgs.vesktop.overrideAttrs (old: { - patches = (old.patches or []) ++ [./vesktop-patch.patch]; - })) + pkgs.vesktop pkgs.equibop ]; diff --git a/modules/home/workstation/communication/vesktop/vesktop-patch.patch b/modules/home/workstation/communication/vesktop/vesktop-patch.patch deleted file mode 100644 index 9e057be..0000000 --- a/modules/home/workstation/communication/vesktop/vesktop-patch.patch +++ /dev/null @@ -1,76 +0,0 @@ -diff --git a/src/main/index.ts b/src/main/index.ts -index 2e0d6f7..70dabba 100644 ---- a/src/main/index.ts -+++ b/src/main/index.ts -@@ -35,7 +35,7 @@ function init() { - if (hardwareAcceleration === false) { - app.disableHardwareAcceleration(); - } else { -- enabledFeatures.push("VaapiVideoDecodeLinuxGL", "VaapiVideoEncoder", "VaapiVideoDecoder"); -+ enabledFeatures.push("VaapiVideoDecodeLinuxGL", "VaapiVideoEncoder", "VaapiVideoDecoder", "VulkanFromANGLE", "DefaultANGLEVulkan", "VaapiIgnoreDriverChecks", "PlatformHEVCDecoderSupport", "VaapiVP8Encoder", "VaapiVP9Encoder", "VaapiAV1Encoder", "WaylandWindowDecorations", "UseOzonePlatform", "WebRTCPipeWireCapturer"); - } - - if (disableSmoothScroll) { -@@ -48,6 +48,26 @@ function init() { - app.commandLine.appendSwitch("disable-renderer-backgrounding"); - app.commandLine.appendSwitch("disable-background-timer-throttling"); - app.commandLine.appendSwitch("disable-backgrounding-occluded-windows"); -+ app.commandLine.appendSwitch("disable-renderer-backgrounding"); -+ app.commandLine.appendSwitch("disable-background-timer-throttling"); -+ app.commandLine.appendSwitch("disable-backgrounding-occluded-windows"); -+ app.commandLine.appendSwitch("enable-zero-copy"); -+ app.commandLine.appendSwitch("use-gl=angle"); -+ app.commandLine.appendSwitch("use-angle=gl"); -+ app.commandLine.appendSwitch("use-vulkan"); -+ app.commandLine.appendSwitch("enable-oop-rasterization"); -+ app.commandLine.appendSwitch("enable-raw-draw"); -+ app.commandLine.appendSwitch("enable-gpu-rasterization"); -+ app.commandLine.appendSwitch("enable-gpu-compositing"); -+ app.commandLine.appendSwitch("enable-native-gpu-memory-buffers"); -+ app.commandLine.appendSwitch("enable-accelerated-2d-canvas"); -+ app.commandLine.appendSwitch("enable-accelerated-video-decode"); -+ app.commandLine.appendSwitch("enable-accelerated-mjpeg-decode"); -+ app.commandLine.appendSwitch("disable-gpu-vsync"); -+ app.commandLine.appendSwitch("disable-frame-rate-limit"); -+ app.commandLine.appendSwitch("ozone-platform-hint=auto"); -+ app.commandLine.appendSwitch("enable-webrtc-pipewire-capturer"); -+ app.commandLine.appendSwitch("ozone-platform=wayland"); - if (process.platform === "win32") { - disabledFeatures.push("CalculateNativeWinOcclusion"); - } - -diff --git a/src/renderer/components/ScreenSharePicker.tsx b/src/renderer/components/ScreenSharePicker.tsx -index c7403b9..9b454e6 100644 ---- a/src/renderer/components/ScreenSharePicker.tsx -+++ b/src/renderer/components/ScreenSharePicker.tsx -@@ -84,9 +84,9 @@ addPatch({ - const width = Math.round(height * (16 / 9)); - - Object.assign(opts, { -- bitrateMin: 500000, -- bitrateMax: 8000000, -- bitrateTarget: 600000 -+ bitrateMin: 10000000, -+ bitrateMax: 60000000, -+ bitrateTarget: 32000000 - }); - if (opts?.encode) { - Object.assign(opts.encode, { - -diff --git a/src/main/settings.ts b/src/main/settings.ts -index 6fad97f..dfc64e3 100644 ---- a/src/main/settings.ts -+++ b/src/main/settings.ts -@@ -26,8 +26,10 @@ function loadSettings(file: string, name: string) { - - const store = new SettingsStore(settings); - store.addGlobalChangeListener(o => { -- mkdirSync(dirname(file), { recursive: true }); -- writeFileSync(file, JSON.stringify(o, null, 4)); -+ try { -+ mkdirSync(dirname(file), { recursive: true }); -+ writeFileSync(file, JSON.stringify(o, null, 4)); -+ } catch {} - }); - - return store; From 78c70e0560f643e7f744aa2b0ac55d3116d1ce96 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 16:30:40 +1100 Subject: [PATCH 106/213] hyprlock: small text change couldnt get the glyph to work correctly --- modules/home/workstation/hyprland/components/hyprlock.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/home/workstation/hyprland/components/hyprlock.nix b/modules/home/workstation/hyprland/components/hyprlock.nix index 337a097..4a30552 100644 --- a/modules/home/workstation/hyprland/components/hyprlock.nix +++ b/modules/home/workstation/hyprland/components/hyprlock.nix @@ -51,7 +51,7 @@ in { label = { monitor = ""; - text = " \ "; + text = "LOCKED"; position = "0, 150"; valign = "center"; halign = "center"; From 770144613051079e31329a26a93f5a49268d0d09 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 17:07:55 +1100 Subject: [PATCH 107/213] neovim: markdown plugins --- outputs/pkgs/ook-vim/config/plugins/default.nix | 1 + .../pkgs/ook-vim/config/plugins/languages/markdown.nix | 7 ++++++- outputs/pkgs/ook-vim/config/plugins/notes.nix | 8 ++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 outputs/pkgs/ook-vim/config/plugins/notes.nix diff --git a/outputs/pkgs/ook-vim/config/plugins/default.nix b/outputs/pkgs/ook-vim/config/plugins/default.nix index a1a72f6..6c6970f 100644 --- a/outputs/pkgs/ook-vim/config/plugins/default.nix +++ b/outputs/pkgs/ook-vim/config/plugins/default.nix @@ -11,5 +11,6 @@ ./languages ./statusline.nix ./snippets.nix + ./notes.nix ]; } diff --git a/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix b/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix index 79e953e..bc85539 100644 --- a/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix +++ b/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix @@ -3,9 +3,14 @@ languages.markdown = { enable = true; format = true; + extensions = { + render-markdown-nvim = { + enable = true; + }; + }; }; utility = { - preview.markdownPreview = {enable = true;}; + preview.markdownPreview = {enable = false;}; }; }; } diff --git a/outputs/pkgs/ook-vim/config/plugins/notes.nix b/outputs/pkgs/ook-vim/config/plugins/notes.nix new file mode 100644 index 0000000..5315bca --- /dev/null +++ b/outputs/pkgs/ook-vim/config/plugins/notes.nix @@ -0,0 +1,8 @@ +{ + vim.notes = { + obsidian = { + enable = true; + dir = "~/Documents/notes"; + }; + }; +} From 7ed3b8f63cfae7dcbd312e20eefbda46b3cd59fd Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 21:51:34 +1100 Subject: [PATCH 108/213] firefox: update navbar css issue with navbar auto-hide, hopefully resolved --- modules/home/workstation/browser/firefox/theme/ooksfox.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/home/workstation/browser/firefox/theme/ooksfox.nix b/modules/home/workstation/browser/firefox/theme/ooksfox.nix index 1526974..ef6d118 100644 --- a/modules/home/workstation/browser/firefox/theme/ooksfox.nix +++ b/modules/home/workstation/browser/firefox/theme/ooksfox.nix @@ -136,6 +136,8 @@ in padding: 0; } + /* https://github.com/MrOtherGuy/firefox-csshacks/blob/8957a709e3abb7242fa89339c684f8027e66774c/chrome/autohide_main_toolbar.css#L46 */ + root{ --uc-navbar-transform: -40px; } @@ -201,4 +203,6 @@ in } /* Move up the content view */ :root[sessionrestored]:not([inFullscreen],[chromehidden~="toolbar"]) > body > #browser{ margin-top: var(--uc-navbar-transform); } + + '' From e95ae8039fc365c324e3865126052504bc84453d Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 21:53:08 +1100 Subject: [PATCH 109/213] hyprland: disable borders plus plus not working as of hyprland v0.46.2 --- .../hyprland/settings/appearance.nix | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/modules/home/workstation/hyprland/settings/appearance.nix b/modules/home/workstation/hyprland/settings/appearance.nix index 2b15154..b2ef821 100644 --- a/modules/home/workstation/hyprland/settings/appearance.nix +++ b/modules/home/workstation/hyprland/settings/appearance.nix @@ -8,7 +8,7 @@ inherit (hozen) color; in { wayland.windowManager.hyprland = { - plugins = [inputs'.hyprland-plugins.packages.borders-plus-plus]; + #plugins = [inputs'.hyprland-plugins.packages.borders-plus-plus]; settings = { # cursor = { # inactive_timeout = 4; @@ -45,15 +45,16 @@ in { color_inactive = "0xff${color.neutrals."850"}"; }; }; - "plugin:borders-plus-plus" = { - enabled = true; - add_borders = 1; - "col.border_1" = "rgb(${color.neutrals."600"})"; - - border_size_1 = 2; - border_size_2 = 2; - natural_rounding = false; - }; + # FIXME + #"plugin:borders-plus-plus" = { + # enabled = true; + # add_borders = 1; + # "col.border_1" = "rgb(${color.neutrals."600"})"; + # + # border_size_1 = 2; + # border_size_2 = 2; + # natural_rounding = false; + #}; animations = { enabled = false; }; From 728ef6ca9a500e7b7d3922983330609dc039375b Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 21:53:32 +1100 Subject: [PATCH 110/213] audio: hardware.pulseaudio > services.pulseaudio --- modules/nixos/hardware/features/audio.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nixos/hardware/features/audio.nix b/modules/nixos/hardware/features/audio.nix index 9fb0b20..6b93a05 100644 --- a/modules/nixos/hardware/features/audio.nix +++ b/modules/nixos/hardware/features/audio.nix @@ -9,7 +9,6 @@ in { # generic audio configuration config = mkIf (elem "audio" features) { - hardware.pulseaudio.enable = false; services = { pipewire = { enable = true; @@ -22,6 +21,7 @@ in { jack.enable = true; wireplumber.enable = true; }; + pulseaudio.enable = false; # realtime audio udev.extraRules = '' From c4053ad9c1bb698efda88c4bf002188a28409c4a Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 21:54:05 +1100 Subject: [PATCH 111/213] printing: remove canon printer packager, fails to build --- modules/nixos/hardware/features/printing.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/nixos/hardware/features/printing.nix b/modules/nixos/hardware/features/printing.nix index 334f8a1..ae79a21 100644 --- a/modules/nixos/hardware/features/printing.nix +++ b/modules/nixos/hardware/features/printing.nix @@ -12,7 +12,10 @@ in { services = { printing = { enable = true; - drivers = [pkgs.hplip pkgs.cnijfilter2]; + drivers = [ + pkgs.hplip + # FIXME: pkgs.cnijfilter2 + ]; }; avahi = { enable = true; From 779b437a1347bb77afc5f19d2c0b6f9e90a37064 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 21:54:31 +1100 Subject: [PATCH 112/213] neovim: mapping obsidian option init --- .../config/modules/plugins/default.nix | 1 + .../modules/plugins/obsidian/config.nix | 21 +++++++++++++++++++ .../modules/plugins/obsidian/default.nix | 6 ++++++ .../modules/plugins/obsidian/obsidian.nix | 9 ++++++++ 4 files changed, 37 insertions(+) create mode 100644 outputs/pkgs/ook-vim/config/modules/plugins/obsidian/config.nix create mode 100644 outputs/pkgs/ook-vim/config/modules/plugins/obsidian/default.nix create mode 100644 outputs/pkgs/ook-vim/config/modules/plugins/obsidian/obsidian.nix diff --git a/outputs/pkgs/ook-vim/config/modules/plugins/default.nix b/outputs/pkgs/ook-vim/config/modules/plugins/default.nix index d4ef450..ccd4904 100644 --- a/outputs/pkgs/ook-vim/config/modules/plugins/default.nix +++ b/outputs/pkgs/ook-vim/config/modules/plugins/default.nix @@ -2,5 +2,6 @@ imports = [ ./gruvbox-material ./telescope + ./obsidian ]; } diff --git a/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/config.nix b/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/config.nix new file mode 100644 index 0000000..4a47bea --- /dev/null +++ b/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/config.nix @@ -0,0 +1,21 @@ +{ + config, + lib, + options, + ... +}: let + inherit (lib) mkIf; + inherit (lib.nvim.binds) mkKeymap; + inherit (options.vim.notes.obsidian) mappings; + + cfg = config.vim.notes.obsidian; + keys = cfg.mappings; +in { + config = mkIf cfg.enable { + vim = { + keymaps = [ + (mkKeymap "n" keys.openNote "ObsidianOpen" {desc = mappings.openNote.description;}) + ]; + }; + }; +} diff --git a/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/default.nix b/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/default.nix new file mode 100644 index 0000000..011b9b6 --- /dev/null +++ b/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + ./config.nix + ./obsidian.nix + ]; +} diff --git a/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/obsidian.nix b/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/obsidian.nix new file mode 100644 index 0000000..089f5e1 --- /dev/null +++ b/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/obsidian.nix @@ -0,0 +1,9 @@ +{lib, ...}: let + inherit (lib.nvim.binds) mkMappingOption; +in { + options.vim.notes.obsidian = { + mappings = { + openNote = mkMappingOption "Open obsidian note" "oo"; + }; + }; +} From 7174cbcd3db97389895bc561897fabf04be4f07c Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 21:55:05 +1100 Subject: [PATCH 113/213] neovim: enable obsidian plugin module --- outputs/pkgs/ook-vim/config/plugins/notes.nix | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/outputs/pkgs/ook-vim/config/plugins/notes.nix b/outputs/pkgs/ook-vim/config/plugins/notes.nix index 5315bca..4fde8ec 100644 --- a/outputs/pkgs/ook-vim/config/plugins/notes.nix +++ b/outputs/pkgs/ook-vim/config/plugins/notes.nix @@ -1,8 +1,12 @@ { - vim.notes = { - obsidian = { - enable = true; - dir = "~/Documents/notes"; + vim = { + notes = { + obsidian = { + enable = true; + setupOpts = { + dir = "~/Documents/notes"; + }; + }; }; }; } From 928db722b4f4ba171c3b9ef6c4cc3da694f1ecc5 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 6 Jan 2025 21:55:23 +1100 Subject: [PATCH 114/213] neovim: enable markdown module --- outputs/pkgs/ook-vim/config/plugins/languages/default.nix | 1 + outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/outputs/pkgs/ook-vim/config/plugins/languages/default.nix b/outputs/pkgs/ook-vim/config/plugins/languages/default.nix index 589b33c..78552be 100644 --- a/outputs/pkgs/ook-vim/config/plugins/languages/default.nix +++ b/outputs/pkgs/ook-vim/config/plugins/languages/default.nix @@ -8,6 +8,7 @@ ./ts.nix ./go.nix ./lua.nix + ./markdown.nix ]; vim.languages = { diff --git a/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix b/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix index bc85539..17280fb 100644 --- a/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix +++ b/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix @@ -2,15 +2,11 @@ vim = { languages.markdown = { enable = true; - format = true; extensions = { render-markdown-nvim = { enable = true; }; }; }; - utility = { - preview.markdownPreview = {enable = false;}; - }; }; } From acb87b6bb1a4ecaf942ecf2379f0ecf0b1e67ece Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 7 Jan 2025 14:34:47 +1100 Subject: [PATCH 115/213] neovim: add extended obsidian plugin module --- outputs/pkgs/ook-vim/config/default.nix | 1 - .../modules/plugins/obsidian/config.nix | 21 ----- .../modules/plugins/obsidian/obsidian.nix | 9 -- outputs/pkgs/ook-vim/config/plugins/notes.nix | 9 +- outputs/pkgs/ook-vim/default.nix | 6 +- .../ook-vim/{config => }/modules/default.nix | 0 .../{config => }/modules/plugins/default.nix | 0 .../plugins/gruvbox-material/config.nix | 0 .../plugins/gruvbox-material/default.nix | 0 .../modules/plugins/obsidian/config.nix | 37 ++++++++ .../modules/plugins/obsidian/default.nix | 0 .../modules/plugins/obsidian/obsidian.nix | 90 +++++++++++++++++++ .../modules/plugins/telescope/config.nix | 0 .../modules/plugins/telescope/default.nix | 0 14 files changed, 139 insertions(+), 34 deletions(-) delete mode 100644 outputs/pkgs/ook-vim/config/modules/plugins/obsidian/config.nix delete mode 100644 outputs/pkgs/ook-vim/config/modules/plugins/obsidian/obsidian.nix rename outputs/pkgs/ook-vim/{config => }/modules/default.nix (100%) rename outputs/pkgs/ook-vim/{config => }/modules/plugins/default.nix (100%) rename outputs/pkgs/ook-vim/{config => }/modules/plugins/gruvbox-material/config.nix (100%) rename outputs/pkgs/ook-vim/{config => }/modules/plugins/gruvbox-material/default.nix (100%) create mode 100644 outputs/pkgs/ook-vim/modules/plugins/obsidian/config.nix rename outputs/pkgs/ook-vim/{config => }/modules/plugins/obsidian/default.nix (100%) create mode 100644 outputs/pkgs/ook-vim/modules/plugins/obsidian/obsidian.nix rename outputs/pkgs/ook-vim/{config => }/modules/plugins/telescope/config.nix (100%) rename outputs/pkgs/ook-vim/{config => }/modules/plugins/telescope/default.nix (100%) diff --git a/outputs/pkgs/ook-vim/config/default.nix b/outputs/pkgs/ook-vim/config/default.nix index 93fee2d..7fb6b10 100644 --- a/outputs/pkgs/ook-vim/config/default.nix +++ b/outputs/pkgs/ook-vim/config/default.nix @@ -5,6 +5,5 @@ ./theme.nix ./keymaps.nix ./plugins - ./modules ]; } diff --git a/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/config.nix b/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/config.nix deleted file mode 100644 index 4a47bea..0000000 --- a/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/config.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ - config, - lib, - options, - ... -}: let - inherit (lib) mkIf; - inherit (lib.nvim.binds) mkKeymap; - inherit (options.vim.notes.obsidian) mappings; - - cfg = config.vim.notes.obsidian; - keys = cfg.mappings; -in { - config = mkIf cfg.enable { - vim = { - keymaps = [ - (mkKeymap "n" keys.openNote "ObsidianOpen" {desc = mappings.openNote.description;}) - ]; - }; - }; -} diff --git a/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/obsidian.nix b/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/obsidian.nix deleted file mode 100644 index 089f5e1..0000000 --- a/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/obsidian.nix +++ /dev/null @@ -1,9 +0,0 @@ -{lib, ...}: let - inherit (lib.nvim.binds) mkMappingOption; -in { - options.vim.notes.obsidian = { - mappings = { - openNote = mkMappingOption "Open obsidian note" "oo"; - }; - }; -} diff --git a/outputs/pkgs/ook-vim/config/plugins/notes.nix b/outputs/pkgs/ook-vim/config/plugins/notes.nix index 4fde8ec..ef417de 100644 --- a/outputs/pkgs/ook-vim/config/plugins/notes.nix +++ b/outputs/pkgs/ook-vim/config/plugins/notes.nix @@ -1,10 +1,17 @@ { vim = { notes = { - obsidian = { + obsidianExtended = { enable = true; setupOpts = { dir = "~/Documents/notes"; + daily_notes = { + folder = "~/Documents/notes/dailies"; + }; + templates = { + folder = "~/Documents/notes/templates"; + }; + ui.enable = false; }; }; }; diff --git a/outputs/pkgs/ook-vim/default.nix b/outputs/pkgs/ook-vim/default.nix index 9bcc5ed..40ad2fa 100644 --- a/outputs/pkgs/ook-vim/default.nix +++ b/outputs/pkgs/ook-vim/default.nix @@ -3,11 +3,13 @@ pkgs, ... }: let - configuration = import ./config; ooks-vim = inputs.nvf.lib.neovimConfiguration { inherit pkgs; extraSpecialArgs = {inherit inputs;}; - modules = [configuration]; + modules = [ + ./config + ./modules + ]; }; in ooks-vim.neovim diff --git a/outputs/pkgs/ook-vim/config/modules/default.nix b/outputs/pkgs/ook-vim/modules/default.nix similarity index 100% rename from outputs/pkgs/ook-vim/config/modules/default.nix rename to outputs/pkgs/ook-vim/modules/default.nix diff --git a/outputs/pkgs/ook-vim/config/modules/plugins/default.nix b/outputs/pkgs/ook-vim/modules/plugins/default.nix similarity index 100% rename from outputs/pkgs/ook-vim/config/modules/plugins/default.nix rename to outputs/pkgs/ook-vim/modules/plugins/default.nix diff --git a/outputs/pkgs/ook-vim/config/modules/plugins/gruvbox-material/config.nix b/outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/config.nix similarity index 100% rename from outputs/pkgs/ook-vim/config/modules/plugins/gruvbox-material/config.nix rename to outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/config.nix diff --git a/outputs/pkgs/ook-vim/config/modules/plugins/gruvbox-material/default.nix b/outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/default.nix similarity index 100% rename from outputs/pkgs/ook-vim/config/modules/plugins/gruvbox-material/default.nix rename to outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/default.nix diff --git a/outputs/pkgs/ook-vim/modules/plugins/obsidian/config.nix b/outputs/pkgs/ook-vim/modules/plugins/obsidian/config.nix new file mode 100644 index 0000000..da7ee0f --- /dev/null +++ b/outputs/pkgs/ook-vim/modules/plugins/obsidian/config.nix @@ -0,0 +1,37 @@ +{ + config, + lib, + options, + ... +}: let + inherit (lib.modules) mkIf; + inherit (lib.nvim.dag) entryAnywhere; + inherit (lib.nvim.lua) toLuaObject; + inherit (lib.nvim.binds) mkKeymap pushDownDefault; + inherit (options.vim.notes.obsidianExtended) mappings; + + cfg = config.vim.notes.obsidianExtended; + keys = cfg.mappings; +in { + config = mkIf cfg.enable { + vim = { + startPlugins = [ + "obsidian-nvim" + "vim-markdown" + "tabular" + ]; + + binds.whichKey.register = pushDownDefault { + "o" = "+Notes"; + }; + + pluginRC.obsidian = entryAnywhere '' + require("obsidian").setup(${toLuaObject cfg.setupOpts}) + ''; + keymaps = [ + (mkKeymap "n" keys.openNote "ObsidianOpen" {desc = mappings.openNote.description;}) + (mkKeymap "n" keys.findNote "ObsidianQuickSwitch" {desc = mappings.findNote.description;}) + ]; + }; + }; +} diff --git a/outputs/pkgs/ook-vim/config/modules/plugins/obsidian/default.nix b/outputs/pkgs/ook-vim/modules/plugins/obsidian/default.nix similarity index 100% rename from outputs/pkgs/ook-vim/config/modules/plugins/obsidian/default.nix rename to outputs/pkgs/ook-vim/modules/plugins/obsidian/default.nix diff --git a/outputs/pkgs/ook-vim/modules/plugins/obsidian/obsidian.nix b/outputs/pkgs/ook-vim/modules/plugins/obsidian/obsidian.nix new file mode 100644 index 0000000..f406bac --- /dev/null +++ b/outputs/pkgs/ook-vim/modules/plugins/obsidian/obsidian.nix @@ -0,0 +1,90 @@ +{ + lib, + config, + ... +}: let + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.types) str nullOr bool enum; + inherit (lib.nvim.binds) mkMappingOption; + inherit (lib.nvim.types) mkPluginSetupOption; +in { + options.vim.notes.obsidianExtended = { + enable = mkEnableOption "Complementary neovim plugin for Obsidian editor"; + setupOpts = mkPluginSetupOption "Obsidian.nvim" { + dir = mkOption { + type = str; + default = "~/my-vault"; + description = "Location of Obsidian vault directory"; + }; + daily_notes = { + folder = mkOption { + type = nullOr str; + default = null; + description = "Directory in which daily notes should be created"; + }; + date_format = mkOption { + type = nullOr str; + default = null; + description = "Date format used for creating daily notes"; + }; + }; + completion = { + nvim_cmp = mkOption { + # If using nvim-cmp, otherwise set to false + type = bool; + description = "If using nvim-cmp, otherwise set to false"; + default = config.vim.autocomplete.nvim-cmp.enable; + }; + }; + new_notes_location = mkOption { + type = nullOr (enum ["current_dir" "notes_subdir"]); + default = null; + description = '' + Where to put new notes. Valid options are: + * "current_dir" - put notes in same directory as current buffer + * "notes_subdir" - put notes in the default notes subdirectory + + default option: "current_dir" + ''; + }; + templates = { + folder = mkOption { + type = nullOr str; + default = null; + description = "Obsidian templates directory"; + }; + date_format = mkOption { + type = nullOr str; + default = null; + description = "Date format used for templates"; + }; + time_format = mkOption { + type = nullOr str; + default = null; + description = "Time format used for templates"; + }; + }; + preferred_link_style = mkOption { + type = nullOr (enum ["wiki" "markdown"]); + default = null; + description = '' + Either "wiki" or "markdown" + ''; + }; + ui = { + enable = mkOption { + type = nullOr bool; + default = null; + description = '' + Set to false to disable all additional syntax features + ''; + }; + # TODO: add rest of ui options + }; + }; + mappings = { + openNote = mkMappingOption "Open note in obsidian" "oo"; + findNote = mkMappingOption "Open finder in obsidian vault" "of"; + }; + }; +} diff --git a/outputs/pkgs/ook-vim/config/modules/plugins/telescope/config.nix b/outputs/pkgs/ook-vim/modules/plugins/telescope/config.nix similarity index 100% rename from outputs/pkgs/ook-vim/config/modules/plugins/telescope/config.nix rename to outputs/pkgs/ook-vim/modules/plugins/telescope/config.nix diff --git a/outputs/pkgs/ook-vim/config/modules/plugins/telescope/default.nix b/outputs/pkgs/ook-vim/modules/plugins/telescope/default.nix similarity index 100% rename from outputs/pkgs/ook-vim/config/modules/plugins/telescope/default.nix rename to outputs/pkgs/ook-vim/modules/plugins/telescope/default.nix From b0cfbf184fbb87a4b0da33981b3312ef899defae Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 7 Jan 2025 16:25:55 +1100 Subject: [PATCH 116/213] fish: neovim telescope alias init --- modules/home/console/shell/fish/aliases.nix | 3 ++- modules/home/console/shell/fish/binds.nix | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/home/console/shell/fish/aliases.nix b/modules/home/console/shell/fish/aliases.nix index bf6494c..e8bfedf 100644 --- a/modules/home/console/shell/fish/aliases.nix +++ b/modules/home/console/shell/fish/aliases.nix @@ -13,10 +13,11 @@ in { lst = "${getExe eza} -T -L 5 --icons --group-directories-first"; du = "${getExe dust}"; gitroot = "cd (git rev-parse --show-toplevel)"; + gitedit = "cd (git rev-parse --show-toplevel); nvim -c 'Telescope find_files'; cd -"; }; shellAbbrs = { f = "cd $FLAKE"; - fe = "$EDITOR $FLAKE"; + fe = "$EDITOR (git rev-parse --show-toplevel) -c 'Telescope find_files'"; nswitch = "${getExe nh} os switch"; }; diff --git a/modules/home/console/shell/fish/binds.nix b/modules/home/console/shell/fish/binds.nix index 3d35402..8fb9f74 100644 --- a/modules/home/console/shell/fish/binds.nix +++ b/modules/home/console/shell/fish/binds.nix @@ -2,7 +2,7 @@ programs.fish = { functions = { fish_user_key_bindings = '' - bind --preset -M insert \cf nvim '+Telescope find_files' $FLAKE + bind --preset -M insert \cf gitedit bind --preset -M insert \ec fzf_cd_widget ''; }; From 4c08871afec959271b1e1d04eecf635dfc317824 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 7 Jan 2025 16:26:14 +1100 Subject: [PATCH 117/213] neovim: center filename with lualine --- .../ook-vim/config/plugins/statusline.nix | 68 ++++++++++++++++++- .../plugins/gruvbox-material/config.nix | 1 - 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/outputs/pkgs/ook-vim/config/plugins/statusline.nix b/outputs/pkgs/ook-vim/config/plugins/statusline.nix index f376a24..c9c4216 100644 --- a/outputs/pkgs/ook-vim/config/plugins/statusline.nix +++ b/outputs/pkgs/ook-vim/config/plugins/statusline.nix @@ -28,7 +28,18 @@ } '' ]; - c = ["filename"]; + c = [ + #lua + '' + "%=", + { + "filename", + symbols = {modified = ' ', readonly = ' '}, + separator = {right = ' '}, + path = 1, + } + '' + ]; x = [ # lua '' @@ -47,6 +58,61 @@ } '' ]; + y = [ + #lua + '' + { + "", + draw_empty = true, + separator = { left = ' ', right = ' ' } + } + '' + '' + { + 'searchcount', + maxcount = 999, + timeout = 120, + separator = {left = ' '} + } + '' + '' + { + "branch", + icon = ' •', + separator = {left = ' '} + } + '' + ]; + z = [ + #lua + '' + { + "", + draw_empty = true, + separator = { left = ' ', right = ' ' } + } + '' + '' + { + "progress", + separator = {left = ' '} + } + '' + '' + {"location"} + '' + '' + { + "fileformat", + color = {fg='black'}, + symbols = { + unix = '', -- e712 + dos = '', -- e70f + mac = '', -- e711 + } + } + '' + ]; }; }; } diff --git a/outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/config.nix b/outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/config.nix index bfe4345..4af5235 100644 --- a/outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/config.nix +++ b/outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/config.nix @@ -1,7 +1,6 @@ { config, lib, - inputs, pkgs, ... }: let From 5fee6a8970cebc98cc3bbbb9452f55e38a77c5f2 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 9 Jan 2025 21:56:19 +1100 Subject: [PATCH 118/213] packages: wii-u-gc-adapter init --- outputs/pkgs/wii-u-gc-adapter/default.nix | 53 +++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 outputs/pkgs/wii-u-gc-adapter/default.nix diff --git a/outputs/pkgs/wii-u-gc-adapter/default.nix b/outputs/pkgs/wii-u-gc-adapter/default.nix new file mode 100644 index 0000000..e4a0af5 --- /dev/null +++ b/outputs/pkgs/wii-u-gc-adapter/default.nix @@ -0,0 +1,53 @@ +{ + lib, + stdenv, + fetchFromGitHub, + pkg-config, + libusb1, + udev, +}: +stdenv.mkDerivation { + pname = "wii-u-gc-adapter"; + version = "unstable-2020-01-20"; + + src = fetchFromGitHub { + owner = "ToadKing"; + repo = "wii-u-gc-adapter"; + rev = "fa098efa7f6b34f8cd82e2c249c81c629901976c"; + hash = "sha256-wm0vDU7QckFvpgI50PG4/elgPEkfr8xTmroz8kE6QMo"; + }; + + nativeBuildInputs = [ + pkg-config + ]; + + buildInputs = [ + libusb1 + udev + ]; + + # Add -Wformat to CFLAGS to enable format checks + NIX_CFLAGS_COMPILE = "-Wformat"; + + # Disable hardening to prevent format security errors + hardeningDisable = ["format"]; + + makeFlags = ["PREFIX=${placeholder "out"}"]; + + # Add install phase since Makefile doesn't have one + installPhase = '' + runHook preInstall + + mkdir -p $out/bin + cp wii-u-gc-adapter $out/bin/ + + runHook postInstall + ''; + + meta = with lib; { + description = "Tool for using the Wii U GameCube Adapter on Linux"; + homepage = "https://github.com/ToadKing/wii-u-gc-adapter"; + license = licenses.mit; + platforms = platforms.linux; + }; +} From 308f18cdcda38f46e1fb8b4bfefc48e58bb21793 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 9 Jan 2025 21:56:36 +1100 Subject: [PATCH 119/213] packages: project plus init --- outputs/pkgs/default.nix | 15 +- outputs/pkgs/project-plus/default.nix | 187 +++++++++++++++++++++ outputs/pkgs/project-plus/fpp-launcher.nix | 20 +++ 3 files changed, 220 insertions(+), 2 deletions(-) create mode 100644 outputs/pkgs/project-plus/default.nix create mode 100644 outputs/pkgs/project-plus/fpp-launcher.nix diff --git a/outputs/pkgs/default.nix b/outputs/pkgs/default.nix index 6624778..4710db9 100644 --- a/outputs/pkgs/default.nix +++ b/outputs/pkgs/default.nix @@ -1,6 +1,7 @@ { inputs, lib, + hozen, ... }: { perSystem = {pkgs, ...}: let @@ -12,8 +13,18 @@ website = callPackage ./website {}; caddy-with-cloudflare = callPackage ./caddy-with-cloudflare {}; - #ook-vim = mkNeovim pkgs [ook-vim-config]; - ook-vim = callPackage ./ook-vim {inherit inputs pkgs lib;}; + wii-u-gc-adapter = callPackage ./wii-u-gc-adapter {}; + + ook-vim = callPackage ./ook-vim {inherit inputs pkgs lib hozen;}; + + project-plus = let + fpp-config = callPackage ./project-plus/fpp-config.nix {}; + fpp-launcher = callPackage ./project-plus/fpp-launcher.nix {}; + fpp-sd = callPackage ./project-plus/fpp-sd.nix {}; + in + callPackage ./project-plus { + inherit fpp-config fpp-launcher fpp-sd; + }; }; }; } diff --git a/outputs/pkgs/project-plus/default.nix b/outputs/pkgs/project-plus/default.nix new file mode 100644 index 0000000..098eb9f --- /dev/null +++ b/outputs/pkgs/project-plus/default.nix @@ -0,0 +1,187 @@ +{ + fpp-config, + fpp-sd, + fpp-launcher, + lib, + stdenv, + fetchFromGitHub, + cmake, + pkg-config, + wrapQtAppsHook, + fetchpatch, + makeDesktopItem, + copyDesktopItems, + alsa-lib, + bluez, + bzip2, + cubeb, + curl, + ffmpeg, + fmt_10, + glib, + gtk2, + gtk3, + gtest, + hidapi, + enet, + libevdev, + libGL, + libiconv, + libpulseaudio, + libspng, + libusb1, + libXdmcp, + libXext, + libXi, + libXrandr, + lz4, + lzo, + mbedtls_2, + miniupnpc, + minizip-ng, + openal, + pugixml, + qtbase, + qtsvg, + SDL2, + sfml, + udev, + vulkan-loader, + xorg, + xxHash, + xz, +}: let + rev = "f245e1ee105eeb5c18653657cd8b29415dc37243"; + version = "3.0.5"; +in + stdenv.mkDerivation { + pname = "project-plus"; + inherit version; + + src = fetchFromGitHub { + owner = "jlambert360"; + repo = "Ishiiruka"; + hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + inherit rev; + }; + + patches = [ + fetchpatch + { + url = "https://github.com/dolphin-emu/dolphin/commit/3da2e15e6b95f02f66df461e87c8b896e450fdab.patch"; + hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + } + ]; + + strictDeps = true; + + nativeBuildInputs = [ + cmake + pkg-config + wrapQtAppsHook + copyDesktopItems + ]; + buildInputs = [ + bzip2 + cubeb + curl + enet + ffmpeg + fmt_10 + gtest + hidapi + libiconv + libpulseaudio + libspng + libXdmcp + libXi + lz4 + lzo + libusb1 + mbedtls_2 + miniupnpc + minizip-ng + openal + pugixml + qtbase + qtsvg + SDL2 + sfml + xxHash + xz + alsa-lib + bluez + libevdev + libGL + libXrandr + udev + vulkan-loader + libXext + glib + gtk2 + gtk3 + xorg.libXinerama + ]; + + cmakeFlags = [ + "-DLINUX_LOCAL_DEV=true" + "-DGTK3_GLIBCONFIG_INCLUDE_DIR=${glib.out}/lib/glib-3.0/include" + "-DGTK3_GDKCONFIG_INCLUDE_DIR=${gtk3.out}/lib/gtk-3.0/include" + "-DGTK3_INCLUDE_DIRS=${gtk3.out}/lib/gtk-3.0" + "-DENABLE_LTO=True" + "-DGTK2_GLIBCONFIG_INCLUDE_DIR=${glib.out}/lib/glib-2.0/include" + "-DGTK2_GDKCONFIG_INCLUDE_DIR=${gtk2.out}/lib/gtk-2.0/include" + "-DGTK2_INCLUDE_DIRS=${gtk2}/lib/gtk-2.0" + ]; + + qtWrapperArgs = [ + "--prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [vulkan-loader]}" + "--set QT_QPA_PLATFORM xcb" + ]; + + patchPhase = '' + sed -i 's|\$\\{GIT_EXECUTABLE} rev-parse HEAD|echo ${rev}|g' CMakeLists.txt # --set scm_rev_str everywhere to actual commit hash when downloaded + sed -i 's|\$\\{GIT_EXECUTABLE} describe --always --long --dirty|echo FM v${version}|g' CMakeLists.txt # ensures compatibility w/ netplay + sed -i 's|\$\\{GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD|echo HEAD|g' CMakeLists.txt + sed -i 's|#include |#include \n#include |g' Source/Core/DiscIO/DiscExtractor.h + cp Externals/wxWidgets3/include/wx Source/Core/ -r + cp Externals/wxWidgets3/wx/* Source/Core/wx/ + ''; + + installPhase = '' + runHook preInstall + + cp -rf ${fpp-config}/Binaries/* Binaries/ + chmod -R 755 Binaries/ + rm Binaries/portable.txt + + cp -rf ${fpp-launcher}/Launcher/* Binaries/Launcher + mkdir -p Binaries/User/Wii + install -D -m 755 ${fpp-sd}/sd.raw Binaries/User/Wii + mkdir -p $out + cp Binaries/ $out/ -r + + sed -i 's|ISOPaths = 2|ISOPaths = 1|g' $out/Binaries/User/Config/Dolphin.ini + sed -i 's|WiiSDCardPath = ./User/Wii/sd.raw|WiiSDCardPath = '$out'/User/Wii/sd.raw|g' $out/Binaries/User/Config/Dolphin.ini + sed -i 's|ISOPath0 = ./Launcher|ISOPath0 = '$out'/Launcher|g' $out/Binaries/User/Config/Dolphin.ini + sed -i '\|ISOPath1 = ./Games|d' $out/Binaries/User/Config/Dolphin.ini + + mkdir -p $out/bin + ln -s $out/Binaries/ishiiruka $out/bin/faster-project-plus + + runHook postInstall + ''; + + desktopItems = [ + (makeDesktopItem { + name = "project-plus"; + exec = "project-plus"; + icon = "ishiiruka"; + desktopName = "Project+"; + comment = "Ishiiruka fork for SSBPM"; + type = "Application"; + categories = ["Emulator" "Game"]; + keywords = ["ProjectM" "Project M" "ProjectPlus" "Project Plus" "Project+"]; + }) + ]; + } diff --git a/outputs/pkgs/project-plus/fpp-launcher.nix b/outputs/pkgs/project-plus/fpp-launcher.nix new file mode 100644 index 0000000..f291658 --- /dev/null +++ b/outputs/pkgs/project-plus/fpp-launcher.nix @@ -0,0 +1,20 @@ +{ + stdenv, + fetchzip, +}: let + version = "3.0.5"; +in + stdenv.mkDerivation { + inherit version; + name = "fpp-launcher"; + + src = fetchzip { + url = "https://github.com/jlambert360/FPM-AppImage/releases/download/v${version}/Launcher.tar.gz"; + sha256 = "sha256-Q3F4V/ggePaZRsGFM54hkGBkLb52PaIn2lQ31gYANW0="; + }; + + installPhase = '' + mkdir -p $out/Launcher + cp -rf . $out/Launcher + ''; + } From e2a4f1c4bb0e47a8ccd6dadd8be888e4410509ec Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 9 Jan 2025 21:56:58 +1100 Subject: [PATCH 120/213] nvf: add obsidian newNote mapping --- .../modules/plugins/obsidian/config.nix | 1 + .../modules/plugins/obsidian/obsidian.nix | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/outputs/pkgs/ook-vim/modules/plugins/obsidian/config.nix b/outputs/pkgs/ook-vim/modules/plugins/obsidian/config.nix index da7ee0f..ca64f97 100644 --- a/outputs/pkgs/ook-vim/modules/plugins/obsidian/config.nix +++ b/outputs/pkgs/ook-vim/modules/plugins/obsidian/config.nix @@ -31,6 +31,7 @@ in { keymaps = [ (mkKeymap "n" keys.openNote "ObsidianOpen" {desc = mappings.openNote.description;}) (mkKeymap "n" keys.findNote "ObsidianQuickSwitch" {desc = mappings.findNote.description;}) + (mkKeymap "n" keys.newNote "ObsidianNewFromTemplate" {desc = mappings.newNote.description;}) ]; }; }; diff --git a/outputs/pkgs/ook-vim/modules/plugins/obsidian/obsidian.nix b/outputs/pkgs/ook-vim/modules/plugins/obsidian/obsidian.nix index f406bac..a6f8b7e 100644 --- a/outputs/pkgs/ook-vim/modules/plugins/obsidian/obsidian.nix +++ b/outputs/pkgs/ook-vim/modules/plugins/obsidian/obsidian.nix @@ -5,8 +5,9 @@ }: let inherit (lib.options) mkOption mkEnableOption; inherit (lib.types) str nullOr bool enum; + inherit (lib.generators) mkLuaInline; inherit (lib.nvim.binds) mkMappingOption; - inherit (lib.nvim.types) mkPluginSetupOption; + inherit (lib.nvim.types) mkPluginSetupOption luaInline; in { options.vim.notes.obsidianExtended = { enable = mkEnableOption "Complementary neovim plugin for Obsidian editor"; @@ -71,6 +72,20 @@ in { Either "wiki" or "markdown" ''; }; + note_id_func = mkOption { + type = nullOr luaInline; + default = + mkLuaInline + # lua + '' + function(title) + return title + end + ''; + description = '' + Customize how a note ID is generated given an optional title + ''; + }; ui = { enable = mkOption { type = nullOr bool; @@ -85,6 +100,7 @@ in { mappings = { openNote = mkMappingOption "Open note in obsidian" "oo"; findNote = mkMappingOption "Open finder in obsidian vault" "of"; + newNote = mkMappingOption "Create new note" "on"; }; }; } From 1c29de52d3269d8f3f102fbde3cc3e22722eae4c Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 9 Jan 2025 21:57:30 +1100 Subject: [PATCH 121/213] nvf: add custom theme module \ --- outputs/lib/color/utils.nix | 4 + .../ook-vim/config/plugins/statusline.nix | 1 + outputs/pkgs/ook-vim/default.nix | 3 +- .../pkgs/ook-vim/modules/plugins/default.nix | 1 + .../ook-vim/modules/plugins/theme/config.nix | 49 +++++++++ .../modules/plugins/theme/custom-theme.nix | 103 ++++++++++++++++++ .../ook-vim/modules/plugins/theme/default.nix | 6 + 7 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 outputs/pkgs/ook-vim/modules/plugins/theme/config.nix create mode 100644 outputs/pkgs/ook-vim/modules/plugins/theme/custom-theme.nix create mode 100644 outputs/pkgs/ook-vim/modules/plugins/theme/default.nix diff --git a/outputs/lib/color/utils.nix b/outputs/lib/color/utils.nix index 894a9d3..47cff82 100644 --- a/outputs/lib/color/utils.nix +++ b/outputs/lib/color/utils.nix @@ -122,6 +122,8 @@ header = args.neutrals."800"; footer = args.neutrals."800"; menu = args.neutrals."800"; + selection = args.neutrals."650"; + dimmed = args.neutrals."850"; }; border = { base = args.neutrals."650"; @@ -164,6 +166,8 @@ header = args.neutrals."150"; footer = args.neutrals."150"; menu = args.neutrals."150"; + selection = args.neutrals."300"; + dimmed = args.neutrals."200"; }; border = { base = args.neutrals."800"; diff --git a/outputs/pkgs/ook-vim/config/plugins/statusline.nix b/outputs/pkgs/ook-vim/config/plugins/statusline.nix index c9c4216..b60c12c 100644 --- a/outputs/pkgs/ook-vim/config/plugins/statusline.nix +++ b/outputs/pkgs/ook-vim/config/plugins/statusline.nix @@ -2,6 +2,7 @@ vim.statusline.lualine = { enable = true; activeSection = { + # most of this are the default values provided by nvf a = [ #lua '' diff --git a/outputs/pkgs/ook-vim/default.nix b/outputs/pkgs/ook-vim/default.nix index 40ad2fa..0196c62 100644 --- a/outputs/pkgs/ook-vim/default.nix +++ b/outputs/pkgs/ook-vim/default.nix @@ -1,11 +1,12 @@ { inputs, pkgs, + hozen, ... }: let ooks-vim = inputs.nvf.lib.neovimConfiguration { inherit pkgs; - extraSpecialArgs = {inherit inputs;}; + extraSpecialArgs = {inherit inputs hozen;}; modules = [ ./config ./modules diff --git a/outputs/pkgs/ook-vim/modules/plugins/default.nix b/outputs/pkgs/ook-vim/modules/plugins/default.nix index ccd4904..18f7c03 100644 --- a/outputs/pkgs/ook-vim/modules/plugins/default.nix +++ b/outputs/pkgs/ook-vim/modules/plugins/default.nix @@ -3,5 +3,6 @@ ./gruvbox-material ./telescope ./obsidian + ./theme ]; } diff --git a/outputs/pkgs/ook-vim/modules/plugins/theme/config.nix b/outputs/pkgs/ook-vim/modules/plugins/theme/config.nix new file mode 100644 index 0000000..ef7872a --- /dev/null +++ b/outputs/pkgs/ook-vim/modules/plugins/theme/config.nix @@ -0,0 +1,49 @@ +{ + config, + lib, + pkgs, + ... +}: let + inherit (lib) mkIf; + inherit (lib.nvim.dag) entryBefore; + inherit (lib.nvim.lua) toLuaObject; + + cfg = config.vim.theme.custom; + + themePlugin = pkgs.vimUtils.buildVimPlugin { + inherit (cfg) name; + src = pkgs.writeTextDir "colors/${cfg.name}.lua" '' + local M = {} + M.highlights = ${toLuaObject cfg.highlights} + + local function set_groups() + for group, settings in pairs(M.highlights) do + vim.api.nvim_set_hl(0, group, settings) + end + end + + function M.colorscheme() + vim.api.nvim_command("hi clear") + if vim.fn.exists("syntax_on") then + vim.api.nvim_command("syntax reset") + end + + vim.o.termguicolors = true + vim.g.colors_name = "${cfg.name}" + + set_groups() + end + + return M.colorscheme() + ''; + }; +in { + config = mkIf cfg.enable { + vim = { + startPlugins = [themePlugin]; + luaConfigRC.customTheme = '' + vim.cmd.colorscheme("${cfg.name}") + ''; + }; + }; +} diff --git a/outputs/pkgs/ook-vim/modules/plugins/theme/custom-theme.nix b/outputs/pkgs/ook-vim/modules/plugins/theme/custom-theme.nix new file mode 100644 index 0000000..c666826 --- /dev/null +++ b/outputs/pkgs/ook-vim/modules/plugins/theme/custom-theme.nix @@ -0,0 +1,103 @@ +{lib, ...}: let + inherit (lib) mkOption mkEnableOption; + inherit (lib.types) nullOr str bool attrsOf submodule; + + highlightOpts = submodule { + options = { + # https://neovim.io/doc/user/api.html#nvim_set_hl() + fg = mkOption { + type = nullOr str; + default = null; + description = "Foreground color"; + }; + bg = mkOption { + type = nullOr str; + default = null; + description = "Background color"; + }; + sp = mkOption { + type = nullOr str; + default = null; + description = "SP color"; + }; + blend = mkOption { + type = nullOr bool; + default = null; + description = "Blend attribute"; + }; + bold = mkOption { + type = nullOr bool; + default = null; + description = "Italic attribute"; + }; + standout = mkOption { + type = nullOr bool; + default = null; + description = "Standout attribute"; + }; + underline = mkOption { + type = nullOr bool; + default = null; + description = "underline attribute"; + }; + undercurl = mkOption { + type = nullOr bool; + default = null; + description = "Undercurl attribute"; + }; + underdouble = mkOption { + type = nullOr bool; + default = null; + description = "Underdouble attribute"; + }; + underdotted = mkOption { + type = nullOr bool; + default = null; + description = "Underdotted attribute"; + }; + underdashed = mkOption { + type = nullOr bool; + default = null; + description = "Underdashed attribute"; + }; + strikethrough = mkOption { + type = nullOr bool; + default = null; + description = "Strikethrough attribute"; + }; + italic = mkOption { + type = nullOr bool; + default = null; + description = "Bold attribute"; + }; + reverse = mkOption { + type = nullOr bool; + default = null; + description = "Reverse attribute"; + }; + nocombine = mkOption { + type = nullOr bool; + default = null; + description = "Nocombine attribute"; + }; + link = mkOption { + type = nullOr str; + default = null; + description = "Link attribute"; + }; + }; + }; +in { + options.vim.theme.custom = { + enable = mkEnableOption "Enable custom theme"; + name = mkOption { + type = str; + default = "my-custom-theme"; + description = "Name of custom theme"; + }; + highlights = mkOption { + type = attrsOf highlightOpts; + default = {}; + }; + }; +} diff --git a/outputs/pkgs/ook-vim/modules/plugins/theme/default.nix b/outputs/pkgs/ook-vim/modules/plugins/theme/default.nix new file mode 100644 index 0000000..bf217ec --- /dev/null +++ b/outputs/pkgs/ook-vim/modules/plugins/theme/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + ./config.nix + ./custom-theme.nix + ]; +} From 35af38915849d0fc96649ecd4f63e05cf3af1293 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 9 Jan 2025 21:57:59 +1100 Subject: [PATCH 122/213] firefox: fix navbar css add delay to when navbar collapses --- .../browser/firefox/theme/ooksfox.nix | 244 ++++++++++-------- 1 file changed, 131 insertions(+), 113 deletions(-) diff --git a/modules/home/workstation/browser/firefox/theme/ooksfox.nix b/modules/home/workstation/browser/firefox/theme/ooksfox.nix index ef6d118..ca5276f 100644 --- a/modules/home/workstation/browser/firefox/theme/ooksfox.nix +++ b/modules/home/workstation/browser/firefox/theme/ooksfox.nix @@ -7,139 +7,140 @@ in #css '' - :root { + :root { - --clr-menu: #${color.layout.menu}; - --clr-fg: #${color.typography.text}; - --clr-secondary: #${color.secondary.base}; + --clr-menu: #${color.layout.menu}; + --clr-fg: #${color.typography.text}; + --clr-secondary: #${color.secondary.base}; - --border: 1px solid var(--clr-fg); - --border-active: 1px solid var(--clr-fg); - --border-inactive: 1px solid var(--clr-secondary); + --border: 1px solid var(--clr-fg); + --border-active: 1px solid var(--clr-fg); + --border-inactive: 1px solid var(--clr-secondary); - --font-base: ${fonts.monospace.family}; + --font-base: ${fonts.monospace.family}; - } + } - * { - border-radius: 0 !important; - font-family: ${fonts.monospace.family}; - } - #nav-bar { - border: var(--border) !important; - background-color: var(--clr-menu) !important; - margin-top: 0px !important; - } - #urlbar { - text-align: center; - } + * { + border-radius: 0 !important; + font-family: ${fonts.monospace.family}; + } + #nav-bar { + border: var(--border) !important; + background-color: var(--clr-menu) !important; + margin-top: 0px !important; + } + #urlbar { + text-align: center; + } - .browser-toolbar { - padding-bottom: 1px !important; - } + .browser-toolbar { + padding-bottom: 1px !important; + } - #urlbar-background { - background-color: transparent !important; - border: unset !important; - box-shadow: unset !important; - } + #urlbar-background { + background-color: transparent !important; + border: unset !important; + box-shadow: unset !important; + } - #urlbar-container { - padding: 0 !important; - } + #urlbar-container { + padding: 0 !important; + } - .urlbarView { - text-align: start; - border: var(--border) !important; - margin: 0; - padding: 0 !important; - background-color: var(--clr-menu); - } + .urlbarView { + text-align: start; + border: var(--border) !important; + margin: 0; + padding: 0 !important; + background-color: var(--clr-menu); + } - .urlbar-input-container { - margin: 0px !important; - } + .urlbar-input-container { + margin: 0px !important; + } - #identity-icon { - color: red !important; - } + #identity-icon { + color: red !important; + } - #forward-button, - #stop-button, - #star-button-box, - #translations-button, - #reload-button, - #identity-box, - #tracking-protection-icon-container, - #save-to-pocket-button, - .urlbar-page-action, - .urlbar-go-button, - /* firefox account button */ - #fxa-toolbar-menu-button, - /* hamburger menu icon */ - #PanelUI-button, - #PersonalToolbar - { - display: none; - } + #forward-button, + #stop-button, + #star-button-box, + #translations-button, + #reload-button, + #identity-box, + #tracking-protection-icon-container, + #save-to-pocket-button, + .urlbar-page-action, + .urlbar-go-button, + /* firefox account button */ + #fxa-toolbar-menu-button, + /* hamburger menu icon */ + #PanelUI-button, + #PersonalToolbar + { + display: none; + } - .titlebar-buttonbox-container, - .tab-close-button, - .titlebar-spacer, - #tabs-newtab-button, - #alltabs-button, - #firefox-view-button, - #new-tab-button { - display: none; - } + .titlebar-buttonbox-container, + .tab-close-button, + .titlebar-spacer, + #tabs-newtab-button, + #alltabs-button, + #firefox-view-button, + #new-tab-button { + display: none; + } - #tabbrowser-tabs { - margin: 0 !important; - padding: 0 !important; + #tabbrowser-tabs { + margin: 0 !important; + padding: 0 !important; - margin-inline: 0px !important; - border: unset !important; - border-bottom: var(--border-inactive) !important; - } + margin-inline: 0px !important; + border: unset !important; + border-bottom: var(--border-inactive) !important; + } - .tabbrowser-tab { - padding: 3px !important; - padding-left: 3px !important; - --tab-label-mask-size: unset !important; - } + .tabbrowser-tab { + padding: 3px !important; + padding-left: 3px !important; + --tab-label-mask-size: unset !important; + } - .tabbrowser-tab[pinned] { - padding: 3px !important; - } + .tabbrowser-tab[pinned] { + padding: 3px !important; + } - #tabbrowser-tabs[haspinnedtabs]:not([positionpinnedtabs])[orient="horizontal"] > #tabbrowser-arrowscrollbox > .tabbrowser-tab:nth-child(1 of :not([pinned], [hidden])) { - margin-inline-start: 0px !important; - } + #tabbrowser-tabs[haspinnedtabs]:not([positionpinnedtabs])[orient="horizontal"] > #tabbrowser-arrowscrollbox > .tabbrowser-tab:nth-child(1 of :not([pinned], [hidden])) { + margin-inline-start: 0px !important; + } - .tab-stack { - margin-inline: 0 !important; - } - .tab-background { - border-radius: 0px; - border: var(--border-inactive); - } - .tab-background[selected] { - border: var(--border-active); - } + .tab-stack { + margin-inline: 0 !important; + } + .tab-background { + border-radius: 0px; + border: var(--border-inactive); + } + .tab-background[selected] { + border: var(--border-active); + } - #TabsToolbar { - padding-left: 0px !important; - margin: 0; - padding: 0; - } + #TabsToolbar { + padding-left: 0px !important; + margin: 0; + padding: 0; + } - /* https://github.com/MrOtherGuy/firefox-csshacks/blob/8957a709e3abb7242fa89339c684f8027e66774c/chrome/autohide_main_toolbar.css#L46 */ - - root{ + /* https://github.com/MrOtherGuy/firefox-csshacks/blob/8957a709e3abb7242fa89339c684f8027e66774c/chrome/autohide_main_toolbar.css#L46 */ + :root{ --uc-navbar-transform: -40px; + --uc-autohide-toolbar-delay: 1s; + --uc-autohide-toolbar-duration: 100ms; } :root[uidensity="compact"]{ --uc-navbar-transform: -34px } @@ -154,8 +155,9 @@ in #nav-bar:not([customizing]){ opacity: 0; + transition: transform var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay), opacity var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay) !important; position: relative; - z-index: 2; + z-index: 1; } #titlebar{ position: relative; z-index: 3 } @@ -166,34 +168,48 @@ in #tabbrowser-tabbox{ z-index: auto !important; } + /* Show when toolbox is focused, like when urlbar has received focus */ #navigator-toolbox:focus-within > .browser-toolbar{ transform: translateY(0); opacity: 1; + transition-duration: var(--uc-autohide-toolbar-duration), var(--uc-autohide-toolbar-duration) !important; + transition-delay: 0s !important; } + /* Show when toolbox is hovered */ #titlebar:hover ~ .browser-toolbar, .browser-titlebar:hover ~ :is(#nav-bar,#PersonalToolbar), #nav-bar:hover, #nav-bar:hover + #PersonalToolbar{ transform: translateY(0); opacity: 1; + transition-duration: var(--uc-autohide-toolbar-duration), var(--uc-autohide-toolbar-duration) !important; + transition-delay: 0s !important; } :root[sessionrestored] #urlbar[popover]{ opacity: 0; pointer-events: none; + transition: transform var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay), opacity var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay); transform: translateY(var(--uc-navbar-transform)); } - #mainPopupSet:has(> [role="group"][panelopen]) ~ toolbox #urlbar[popover], + #mainPopupSet:has(> [panelopen]:not(#ask-chat-shortcuts,#tab-preview-panel)) ~ toolbox #urlbar[popover], .browser-titlebar:is(:hover,:focus-within) ~ #nav-bar #urlbar[popover], #nav-bar:is(:hover,:focus-within) #urlbar[popover], #urlbar-container > #urlbar[popover]:is([focused],[open]){ opacity: 1; pointer-events: auto; + transition-delay: 0ms; transform: translateY(0); } - #mainPopupSet:has(> [role="group"][panelopen]) ~ #navigator-toolbox > .browser-toolbar{ + #urlbar-container > #urlbar[popover]:is([focused],[open]){ + transition-duration: 100ms; /* Faster when focused */ + } + /* This ruleset is separate, because not having :has support breaks other selectors as well */ + #mainPopupSet:has(> [panelopen]:not(#ask-chat-shortcuts,#tab-preview-panel)) ~ #navigator-toolbox > .browser-toolbar{ + transition-delay: 33ms !important; transform: translateY(0); opacity: 1; } + /* If tabs are in sidebar then nav-bar doesn't normally have its own background - so we nee to add it back */ #nav-bar.browser-titlebar{ background: inherit; } @@ -201,8 +217,10 @@ in background-position-y: -28px; /* best guess, could vary */ border-top: none !important; } + + /* Bookmarks toolbar needs so extra rules */ + #PersonalToolbar{ transition: transform var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay) !important; position: relative; z-index: 1 } + /* Move up the content view */ :root[sessionrestored]:not([inFullscreen],[chromehidden~="toolbar"]) > body > #browser{ margin-top: var(--uc-navbar-transform); } - - '' From 1898815955fde04e3c153042f473dfab63b4d818 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 10 Jan 2025 21:50:38 +1100 Subject: [PATCH 123/213] packages: project-plus; remove User config --- outputs/pkgs/default.nix | 6 ++-- outputs/pkgs/project-plus/default.nix | 43 +++++++----------------- outputs/pkgs/project-plus/fpp-config.nix | 19 +++++++++++ outputs/pkgs/project-plus/fpp-sd.nix | 20 +++++++++++ 4 files changed, 54 insertions(+), 34 deletions(-) create mode 100644 outputs/pkgs/project-plus/fpp-config.nix create mode 100644 outputs/pkgs/project-plus/fpp-sd.nix diff --git a/outputs/pkgs/default.nix b/outputs/pkgs/default.nix index 4710db9..58ba4e5 100644 --- a/outputs/pkgs/default.nix +++ b/outputs/pkgs/default.nix @@ -5,7 +5,7 @@ ... }: { perSystem = {pkgs, ...}: let - inherit (pkgs) callPackage; + inherit (pkgs) callPackage qt6Packages; in { packages = { repopack = callPackage ./repopack {}; @@ -22,8 +22,8 @@ fpp-launcher = callPackage ./project-plus/fpp-launcher.nix {}; fpp-sd = callPackage ./project-plus/fpp-sd.nix {}; in - callPackage ./project-plus { - inherit fpp-config fpp-launcher fpp-sd; + qt6Packages.callPackage ./project-plus { + inherit fpp-launcher fpp-sd fpp-config; }; }; }; diff --git a/outputs/pkgs/project-plus/default.nix b/outputs/pkgs/project-plus/default.nix index 098eb9f..629a689 100644 --- a/outputs/pkgs/project-plus/default.nix +++ b/outputs/pkgs/project-plus/default.nix @@ -1,5 +1,6 @@ { fpp-config, + userDir ? "/home/ooks/.config/project-plus", fpp-sd, fpp-launcher, lib, @@ -9,7 +10,6 @@ pkg-config, wrapQtAppsHook, fetchpatch, - makeDesktopItem, copyDesktopItems, alsa-lib, bluez, @@ -61,16 +61,16 @@ in src = fetchFromGitHub { owner = "jlambert360"; repo = "Ishiiruka"; - hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + hash = "sha256-UmIaOBHMRsl9FnfowAQGBjB83wpVRhoO0gzLed09lmk"; inherit rev; }; patches = [ - fetchpatch - { - url = "https://github.com/dolphin-emu/dolphin/commit/3da2e15e6b95f02f66df461e87c8b896e450fdab.patch"; - hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - } + (fetchpatch + { + url = "https://github.com/dolphin-emu/dolphin/commit/3da2e15e6b95f02f66df461e87c8b896e450fdab.patch"; + hash = "sha256-+8yGF412wQUYbyEuYWd41pgOgEbhCaezexxcI5CNehc="; + }) ]; strictDeps = true; @@ -121,6 +121,7 @@ in gtk2 gtk3 xorg.libXinerama + xorg.libXxf86vm ]; cmakeFlags = [ @@ -137,6 +138,8 @@ in qtWrapperArgs = [ "--prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [vulkan-loader]}" "--set QT_QPA_PLATFORM xcb" + "--add-flags -u" + "--add-flags ${toString userDir}" ]; patchPhase = '' @@ -151,37 +154,15 @@ in installPhase = '' runHook preInstall - cp -rf ${fpp-config}/Binaries/* Binaries/ + cp -rf ${fpp-config}/Binaries/Sys Binaries/ chmod -R 755 Binaries/ - rm Binaries/portable.txt - cp -rf ${fpp-launcher}/Launcher/* Binaries/Launcher - mkdir -p Binaries/User/Wii - install -D -m 755 ${fpp-sd}/sd.raw Binaries/User/Wii mkdir -p $out cp Binaries/ $out/ -r - sed -i 's|ISOPaths = 2|ISOPaths = 1|g' $out/Binaries/User/Config/Dolphin.ini - sed -i 's|WiiSDCardPath = ./User/Wii/sd.raw|WiiSDCardPath = '$out'/User/Wii/sd.raw|g' $out/Binaries/User/Config/Dolphin.ini - sed -i 's|ISOPath0 = ./Launcher|ISOPath0 = '$out'/Launcher|g' $out/Binaries/User/Config/Dolphin.ini - sed -i '\|ISOPath1 = ./Games|d' $out/Binaries/User/Config/Dolphin.ini - mkdir -p $out/bin - ln -s $out/Binaries/ishiiruka $out/bin/faster-project-plus + ln -s $out/Binaries/ishiiruka $out/bin/project-plus runHook postInstall ''; - - desktopItems = [ - (makeDesktopItem { - name = "project-plus"; - exec = "project-plus"; - icon = "ishiiruka"; - desktopName = "Project+"; - comment = "Ishiiruka fork for SSBPM"; - type = "Application"; - categories = ["Emulator" "Game"]; - keywords = ["ProjectM" "Project M" "ProjectPlus" "Project Plus" "Project+"]; - }) - ]; } diff --git a/outputs/pkgs/project-plus/fpp-config.nix b/outputs/pkgs/project-plus/fpp-config.nix new file mode 100644 index 0000000..bf773a3 --- /dev/null +++ b/outputs/pkgs/project-plus/fpp-config.nix @@ -0,0 +1,19 @@ +{ + stdenv, + fetchzip, +}: +stdenv.mkDerivation { + name = "fpp-config"; + version = "2.28"; + + archiveName = "fppconfig.tar.gz"; + src = fetchzip { + url = "https://github.com/jlambert360/FPM-AppImage/raw/refs/heads/master/config/fppconfig.tar.gz"; + sha256 = "sha256-1+dQkNuZi2LXqmUuYJHI6RYuFUmI2wzVb4D2SYdZt1Y="; + }; + + installPhase = '' + mkdir -p $out/Binaries + cp -rf . $out/Binaries + ''; +} diff --git a/outputs/pkgs/project-plus/fpp-sd.nix b/outputs/pkgs/project-plus/fpp-sd.nix new file mode 100644 index 0000000..dcea0b6 --- /dev/null +++ b/outputs/pkgs/project-plus/fpp-sd.nix @@ -0,0 +1,20 @@ +{ + stdenv, + fetchzip, +}: let + version = "3.0.5"; +in + stdenv.mkDerivation { + name = "fpp-sdcard"; + inherit version; + + src = fetchzip { + url = "https://github.com/jlambert360/FPM-AppImage/releases/download/v${version}/sd.tar.gz"; + sha256 = "sha256-9QrfAxY62x5RlELOUey+zfVzP3xuDB/sRe/0rVevV6A"; + }; + + installPhase = '' + mkdir -p $out + cp sd.raw $out + ''; + } From f59c08deb52fa3ec36c4eb57ccd1b4b8d78d10ec Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 11 Jan 2025 20:18:38 +1100 Subject: [PATCH 124/213] project-plus: home-manager module init --- modules/home/workstation/gaming/default.nix | 1 + modules/home/workstation/gaming/emulation.nix | 9 ++ .../gaming/project-plus/default.nix | 5 + .../gaming/project-plus/options.nix | 129 ++++++++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 modules/home/workstation/gaming/project-plus/default.nix create mode 100644 modules/home/workstation/gaming/project-plus/options.nix diff --git a/modules/home/workstation/gaming/default.nix b/modules/home/workstation/gaming/default.nix index 20f918e..4412448 100644 --- a/modules/home/workstation/gaming/default.nix +++ b/modules/home/workstation/gaming/default.nix @@ -11,6 +11,7 @@ in { ./wine.nix ./bottles.nix ./emulation.nix + ./project-plus ]; config = mkIf (elem "gaming" profiles) { ooknet.binds = { diff --git a/modules/home/workstation/gaming/emulation.nix b/modules/home/workstation/gaming/emulation.nix index c569f10..a9cb88e 100644 --- a/modules/home/workstation/gaming/emulation.nix +++ b/modules/home/workstation/gaming/emulation.nix @@ -2,6 +2,7 @@ lib, osConfig, pkgs, + self', ... }: let inherit (lib) mkIf elem; @@ -14,6 +15,14 @@ in { (pkgs) ryujinx ; + inherit + (self'.packages) + wii-u-gc-adapter + ; + }; + ooknet.gaming.project-plus = { + enable = true; + netplay.nickname = "ooks"; }; }; } diff --git a/modules/home/workstation/gaming/project-plus/default.nix b/modules/home/workstation/gaming/project-plus/default.nix new file mode 100644 index 0000000..86e0060 --- /dev/null +++ b/modules/home/workstation/gaming/project-plus/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./options.nix + ]; +} diff --git a/modules/home/workstation/gaming/project-plus/options.nix b/modules/home/workstation/gaming/project-plus/options.nix new file mode 100644 index 0000000..7a27230 --- /dev/null +++ b/modules/home/workstation/gaming/project-plus/options.nix @@ -0,0 +1,129 @@ +{ + lib, + self', + config, + ... +}: let + inherit (lib) mkOption mkEnableOption mkIf; + inherit (lib.types) package str path attrsOf anything bool int; + cfg = config.ooknet.gaming.project-plus; +in { + options.ooknet.gaming.project-plus = { + enable = mkEnableOption "Enable Project Plus"; + package = mkOption { + type = package; + default = self'.packages.project-plus.override { + inherit (cfg) userDir; + }; + }; + userDir = mkOption { + type = str; + default = "${config.xdg.configHome}/project-plus"; + description = '' + Location of the Dolphin User directory, this is the path that the wrapped package + will use for User configuration. defaults to "\$\{config.xdg.configHome}/project-plus" + ''; + }; + + launcherSource = mkOption { + type = path; + default = "${self'.packages.fpp-launcher}/Launcher"; + description = '' + Location of the faster-project-plus launcher files. + ''; + }; + sdCardSource = mkOption { + type = path; + default = "${self'.packages.fpp-sd}/sd.raw"; + description = '' + Location of the faster-project-plus sd card + ''; + }; + userSource = mkOption { + type = path; + default = "${self'.packages.fpp-config}/Binaries/User"; + }; + + netplay = { + nickname = mkOption { + type = str; + default = "Player"; + description = "Netplay nickname displayed to other players"; + }; + disableMusic = mkOption { + type = bool; + default = true; + description = "Whether to disable music during netplay"; + }; + buffer = mkOption { + type = int; + default = 4; + description = "Default netplay buffer"; + }; + }; + + gamesDir = mkOption { + type = str; + default = "./Games"; + description = '' + Location of the directory that stores all game isos, this is where you should store + your brawl iso. Defaults to "./Brawl" (The . is relative to the User dolphin directory) + ''; + }; + + extraSettings = mkOption { + type = attrsOf anything; + default = {}; + description = '' + Additional settings for Dolphin.ini + ''; + }; + }; + config = mkIf cfg.enable { + home.packages = [cfg.package]; + xdg.configFile = { + "project-plus/Config/Dolphin.ini" = { + text = lib.generators.toINI {} { + # default settings to ensure project-plus works OOTB. + General = { + IsoPaths = 2; + IsoPath0 = "${cfg.userDir}/Games"; + IsoPath1 = "${cfg.userDir}/Launcher"; + WiiSDCardPath = "${cfg.userDir}/Wii/sd.raw"; + }; + Core = { + DefaultISO = "${cfg.userDir}/Games/brawl.iso"; + }; + Netplay = + { + SelectedHostGame = "Project+ Netplay Launcher.dol"; + BufferSize = cfg.netplay.buffer; + Nickname = cfg.netplay.nickname; + MusicOff = cfg.netplay.disableMusic; + ListenPort = "0x0a42"; + HostPort = "0x0a42"; + ConnectPort = "0x0a42"; + HostCode = 00000000; + TraversalChoice = "traversal"; + } + // cfg.extraSettings; + }; + }; + # Copy dolphin GameSettings configuration from faster-project-plus config + # This includes various Gecko Code files to make for a better Netplay experience + "project-plus/GameSettings" = { + source = "${cfg.userSource}/GameSettings"; + recursive = true; + }; + "project-plus/Launcher" = { + source = "${cfg.launcherSource}"; + recursive = true; + }; + # Cant get this to work, does the sd card need to be writable for dolphin to use it? + # for now sd card will need to be manually placed in the SD directory + # "project-plus/Wii/sd.raw" = { + # source = cfg.sdCardSource; + # }; + }; + }; +} From 5aae9cdf5d3d39f1b8c112e7c79ea840a59973a1 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 11 Jan 2025 20:18:53 +1100 Subject: [PATCH 125/213] gaming: nixos emulation module --- modules/nixos/workstation/gaming/default.nix | 1 + .../nixos/workstation/gaming/emulation.nix | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 modules/nixos/workstation/gaming/emulation.nix diff --git a/modules/nixos/workstation/gaming/default.nix b/modules/nixos/workstation/gaming/default.nix index c98c43e..b415fc7 100644 --- a/modules/nixos/workstation/gaming/default.nix +++ b/modules/nixos/workstation/gaming/default.nix @@ -3,5 +3,6 @@ ./steam.nix ./gamemode.nix ./switch.nix + ./emulation.nix ]; } diff --git a/modules/nixos/workstation/gaming/emulation.nix b/modules/nixos/workstation/gaming/emulation.nix new file mode 100644 index 0000000..f4c3f30 --- /dev/null +++ b/modules/nixos/workstation/gaming/emulation.nix @@ -0,0 +1,32 @@ +{ + lib, + config, + pkgs, + ... +}: let + inherit (lib) mkIf elem; + inherit (config.ooknet.workstation) profiles; +in { + config = mkIf (elem "gaming" profiles) { + services.udev.packages = [ + pkgs.dolphin-emu + (pkgs.writeTextFile { + name = "99-nintendo-controller.rules"; + text = '' + SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", \ + ATTRS{idVendor}=="057e", ATTRS{idProduct}=="0337", \ + MODE="0666"; + ''; + destination = "/etc/udev/rules.d/40-nintendo-controller.rules"; + }) + ]; + boot.extraModulePackages = [ + config.boot.kernelPackages.gcadapter-oc-kmod + ]; + + # to autoload at boot: + boot.kernelModules = [ + "gcadapter_oc" + ]; + }; +} From 4191eb50bf06472b29d3add3c9cd6d58f89274d7 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 11 Jan 2025 20:19:23 +1100 Subject: [PATCH 126/213] project-plus: remove sd and launcher from derivation --- outputs/pkgs/default.nix | 21 +++++++++++---------- outputs/pkgs/project-plus/default.nix | 4 +--- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/outputs/pkgs/default.nix b/outputs/pkgs/default.nix index 58ba4e5..b49dd40 100644 --- a/outputs/pkgs/default.nix +++ b/outputs/pkgs/default.nix @@ -6,25 +6,26 @@ }: { perSystem = {pkgs, ...}: let inherit (pkgs) callPackage qt6Packages; + + projectPlus = { + fpp-config = callPackage ./project-plus/fpp-config.nix {}; + fpp-launcher = callPackage ./project-plus/fpp-launcher.nix {}; + fpp-sd = callPackage ./project-plus/fpp-sd.nix {}; + package = qt6Packages.callPackage ./project-plus { + inherit (projectPlus) fpp-config; + }; + }; in { packages = { repopack = callPackage ./repopack {}; live-buds-cli = callPackage ./live-buds-cli {}; website = callPackage ./website {}; caddy-with-cloudflare = callPackage ./caddy-with-cloudflare {}; - wii-u-gc-adapter = callPackage ./wii-u-gc-adapter {}; - ook-vim = callPackage ./ook-vim {inherit inputs pkgs lib hozen;}; - project-plus = let - fpp-config = callPackage ./project-plus/fpp-config.nix {}; - fpp-launcher = callPackage ./project-plus/fpp-launcher.nix {}; - fpp-sd = callPackage ./project-plus/fpp-sd.nix {}; - in - qt6Packages.callPackage ./project-plus { - inherit fpp-launcher fpp-sd fpp-config; - }; + inherit (projectPlus) fpp-config fpp-launcher fpp-sd; + project-plus = projectPlus.package; }; }; } diff --git a/outputs/pkgs/project-plus/default.nix b/outputs/pkgs/project-plus/default.nix index 629a689..eb756e3 100644 --- a/outputs/pkgs/project-plus/default.nix +++ b/outputs/pkgs/project-plus/default.nix @@ -1,8 +1,6 @@ { fpp-config, userDir ? "/home/ooks/.config/project-plus", - fpp-sd, - fpp-launcher, lib, stdenv, fetchFromGitHub, @@ -161,7 +159,7 @@ in cp Binaries/ $out/ -r mkdir -p $out/bin - ln -s $out/Binaries/ishiiruka $out/bin/project-plus + ln -s $out/Binaries/ishiiruka $out/bin/faster-project-plus runHook postInstall ''; From f020ae8902725f98d818ebfb9e353050a2f96e83 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 13 Jan 2025 13:25:06 +1100 Subject: [PATCH 127/213] hardware: add cpu cores option --- hosts/ooksdesk/hardware.nix | 7 +++++-- modules/nixos/hardware/options.nix | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/hosts/ooksdesk/hardware.nix b/hosts/ooksdesk/hardware.nix index 173a4b3..703abeb 100644 --- a/hosts/ooksdesk/hardware.nix +++ b/hosts/ooksdesk/hardware.nix @@ -1,7 +1,10 @@ { ooknet.hardware = { - cpu.type = "amd"; - cpu.amd.pstate.enable = true; + cpu = { + type = "amd"; + amd.pstate.enable = true; + cores = 16; + }; gpu.type = "amd"; features = ["printing" "ssd" "audio" "video"]; monitors = [ diff --git a/modules/nixos/hardware/options.nix b/modules/nixos/hardware/options.nix index 57aaece..44a4a36 100644 --- a/modules/nixos/hardware/options.nix +++ b/modules/nixos/hardware/options.nix @@ -21,6 +21,10 @@ in { default = null; }; amd.pstate.enable = mkEnableOption ""; + cores = { + type = int; + description = "Number of Physical CPU cores the system has"; + }; }; features = mkOption { From aa2d8c578e75755888a34d4e5deab9434806c59b Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 13 Jan 2025 13:25:23 +1100 Subject: [PATCH 128/213] nixos: distributed builds config init --- modules/nixos/base/builder.nix | 12 ----- modules/nixos/base/default.nix | 1 + modules/nixos/base/distributed-builds.nix | 59 +++++++++++++++++++++++ modules/nixos/base/nix.nix | 4 +- 4 files changed, 62 insertions(+), 14 deletions(-) delete mode 100644 modules/nixos/base/builder.nix create mode 100644 modules/nixos/base/distributed-builds.nix diff --git a/modules/nixos/base/builder.nix b/modules/nixos/base/builder.nix deleted file mode 100644 index d37d94c..0000000 --- a/modules/nixos/base/builder.nix +++ /dev/null @@ -1,12 +0,0 @@ -{ - keys, - config, - ... -}: let - inherit (config.ooknet.host) admin; -in { - users = { - groups.builder = {}; - users.builder = (key: ''command="nix-daemon --stdio",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ${key}'') keys.users.${admin.name}; - }; -} diff --git a/modules/nixos/base/default.nix b/modules/nixos/base/default.nix index b039af3..018ada6 100644 --- a/modules/nixos/base/default.nix +++ b/modules/nixos/base/default.nix @@ -1,6 +1,7 @@ { imports = [ ./nix.nix + ./distributed-builds.nix ./home-manager.nix ./boot.nix ./admin.nix diff --git a/modules/nixos/base/distributed-builds.nix b/modules/nixos/base/distributed-builds.nix new file mode 100644 index 0000000..aa9daac --- /dev/null +++ b/modules/nixos/base/distributed-builds.nix @@ -0,0 +1,59 @@ +{ + keys, + config, + lib, + self, + ... +}: let + inherit (lib) mkIf; + inherit (config.ooknet.host) admin; + inherit (config.networking) hostName; + + mkBuilderMachine = { + host, + speedFactor, + systems ? ["x86_64-linux"], + supportedFeatures ? ["big-parallel" "kvm" "nixos-test"], + }: { + inherit speedFactor systems supportedFeatures; + hostName = host; + maxJobs = self.nixosConfigurations.${host}.config.nix.settings.max-jobs or "auto"; + protocol = "ssh"; + sshKey = "/home/${admin.name}/.ssh/builder"; + }; + + builders = { + ooksdesk = mkBuilderMachine { + host = "ooksdesk"; + speedFactor = 16; + }; + ooksmedia = mkBuilderMachine { + host = "ooksmedia"; + speedFactor = 8; + }; + }; +in { + users = mkIf (hostName == "ooksdesk" || hostName == "ooksmedia") { + groups.builder = {}; + users.builder = { + createHome = false; + isSystemUser = true; + useDefaultShell = true; + group = "builder"; + openssh.authorizedKeys.keys = [ + '' + command="nix-daemon --stdio",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ${keys.users.${admin.name}} + '' + ]; + }; + }; + nix = { + distributedBuilds = true; + buildMachines = + if hostName == "ooksdesk" + then [] + else if hostName == "ooksmedia" + then [builders.ooksdesk] + else [builders.ooksdesk builders.ooksmedia]; + }; +} diff --git a/modules/nixos/base/nix.nix b/modules/nixos/base/nix.nix index 1ea9590..d79ed4e 100644 --- a/modules/nixos/base/nix.nix +++ b/modules/nixos/base/nix.nix @@ -44,8 +44,9 @@ in { settings = { trusted-users = ["@wheel" "root" "builder"]; experimental-features = ["nix-command" "flakes"]; - accept-flake-config = true; + accept-flake-config = false; auto-optimise-store = true; + warn-dirty = false; # cache substituters = [ "https://cache.nixos.org?priority=10" @@ -57,7 +58,6 @@ in { "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" "neovim-flake.cachix.org-1:iyQ6lHFhnB5UkVpxhQqLJbneWBTzM8LBYOFPLNH4qZw=" ]; - # TODO: setup builders -- builders-use-substitutes = true; }; }; nixpkgs = { From 615cea9f508c0b379acfb1c12f1aa115c8a93455 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 12 Jan 2025 16:42:07 +1100 Subject: [PATCH 129/213] caddy: use nixpkgs caddy.withPlugins helper --- modules/nixos/server/webserver/caddy.nix | 10 ++++++++-- outputs/pkgs/caddy-with-cloudflare/default.nix | 3 +-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/modules/nixos/server/webserver/caddy.nix b/modules/nixos/server/webserver/caddy.nix index be8cd6a..b17b89a 100644 --- a/modules/nixos/server/webserver/caddy.nix +++ b/modules/nixos/server/webserver/caddy.nix @@ -1,7 +1,7 @@ { config, lib, - self', + pkgs, ... }: let inherit (lib) mkIf mkMerge; @@ -16,7 +16,13 @@ in { } (mkIf caddy.cloudflare.enable { - package = self'.packages.caddy-with-cloudflare; + package = pkgs.caddy.withPlugins { + plugins = [ + "github.com/caddy-dns/cloudflare@v0.0.0-20240703190432-89f16b99c18e" + "github.com/WeidiDeng/caddy-cloudflare-ip@v0.0.0-20231130002422-f53b62aa13cb" + ]; + hash = "sha256-X3SNPfianAWLXnE0hpQpgaaCqIqHm0jgyp1clnQKmUg="; + }; globalConfig = '' servers { metrics diff --git a/outputs/pkgs/caddy-with-cloudflare/default.nix b/outputs/pkgs/caddy-with-cloudflare/default.nix index 1807b3b..2957fb5 100644 --- a/outputs/pkgs/caddy-with-cloudflare/default.nix +++ b/outputs/pkgs/caddy-with-cloudflare/default.nix @@ -35,7 +35,7 @@ caddy.override { installPhase = '' cp -r --reflink=auto . $out ''; - outputHash = "sha256-O3QWqgQtLOifsibyB0/UKricEGAx/3NhSjGbgu8+qgY="; + outputHash = "sha256-7FlCaHLuyESq+0YAkud7y83hY4oow7omJPTVVweEnJI="; outputHashMode = "recursive"; }; subPackages = ["."]; @@ -43,4 +43,3 @@ caddy.override { vendorHash = null; }); } - From 338e3a25a1daf0051bc603726ba177856a3898f2 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 12 Jan 2025 22:05:06 +1100 Subject: [PATCH 130/213] forgejo: add forgejo cli script --- .../nixos/server/services/forgejo/default.nix | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/modules/nixos/server/services/forgejo/default.nix b/modules/nixos/server/services/forgejo/default.nix index c31731a..7cfd06e 100644 --- a/modules/nixos/server/services/forgejo/default.nix +++ b/modules/nixos/server/services/forgejo/default.nix @@ -1,10 +1,11 @@ { config, lib, + pkgs, ... }: let inherit (config.ooknet.server) services domain; - inherit (lib) mkIf elem; + inherit (lib) mkIf elem getExe; in { config = mkIf (elem "forgejo" services) { networking.firewall.allowedTCPPorts = [2222]; @@ -62,5 +63,24 @@ in { ''; }; }; + # credit to TLATER + # https://discourse.nixos.org/t/how-to-access-forgejo-cli/45370 + environment.systemPackages = let + cfg = config.services.forgejo; + forgejo-cli = pkgs.writeScriptBin "forgejo-cli" '' + #!${pkgs.runtimeShell} + cd ${cfg.stateDir} + sudo=exec + if [[ "$USER" != forgejo ]]; then + sudo='exec /run/wrappers/bin/sudo -u ${cfg.user} -g ${cfg.group} --preserve-env=GITEA_WORK_DIR --preserve-env=GITEA_CUSTOM' + fi + # Note that these variable names will change + export GITEA_WORK_DIR=${cfg.stateDir} + export GITEA_CUSTOM=${cfg.customDir} + $sudo ${getExe cfg.package} "$@" + ''; + in [ + forgejo-cli + ]; }; } From ce67d0de9b43c1ed81874103dd35e521bd138759 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 13 Jan 2025 20:56:22 +1100 Subject: [PATCH 131/213] hardware: remove monitor.workspace option, add primaryMonitor option --- hosts/ooksdesk/hardware.nix | 1 - hosts/ooksmedia/hardware.nix | 1 - hosts/ookst480s/hardware.nix | 1 - modules/nixos/hardware/options.nix | 32 ++++++++++++++++++++---------- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/hosts/ooksdesk/hardware.nix b/hosts/ooksdesk/hardware.nix index 703abeb..94e6c27 100644 --- a/hosts/ooksdesk/hardware.nix +++ b/hosts/ooksdesk/hardware.nix @@ -14,7 +14,6 @@ width = 2560; height = 1440; refreshRate = 144; - workspace = "1"; x = 1920; y = 100; } diff --git a/hosts/ooksmedia/hardware.nix b/hosts/ooksmedia/hardware.nix index bc4629e..6ed6778 100644 --- a/hosts/ooksmedia/hardware.nix +++ b/hosts/ooksmedia/hardware.nix @@ -10,7 +10,6 @@ width = 1920; height = 1080; refreshRate = 180; - workspace = "1"; } ]; }; diff --git a/hosts/ookst480s/hardware.nix b/hosts/ookst480s/hardware.nix index d67061d..73dff74 100644 --- a/hosts/ookst480s/hardware.nix +++ b/hosts/ookst480s/hardware.nix @@ -16,7 +16,6 @@ name = "eDP-1"; width = 1920; height = 1080; - workspace = "1"; } ]; }; diff --git a/modules/nixos/hardware/options.nix b/modules/nixos/hardware/options.nix index 44a4a36..864eba3 100644 --- a/modules/nixos/hardware/options.nix +++ b/modules/nixos/hardware/options.nix @@ -3,9 +3,14 @@ config, ... }: let + inherit (builtins) filter length head; inherit (lib) mkOption mkEnableOption; inherit (lib.types) nullOr enum bool submodule listOf int str; - inherit (config.ooknet) hardware; + + cfg = config.ooknet.hardware; + hasMonitors = length cfg.monitors != 0; + primaryAttr = filter (m: m.primary or false) cfg.monitors; + primaryCount = length primaryAttr; in { options.ooknet.hardware = { gpu = { @@ -21,10 +26,14 @@ in { default = null; }; amd.pstate.enable = mkEnableOption ""; - cores = { + cores = mkOption { type = int; description = "Number of Physical CPU cores the system has"; }; + threads = mkOption { + type = int; + description = "Number of cpu threads the cpu has"; + }; }; features = mkOption { @@ -43,6 +52,15 @@ in { # monitor module inspired by misterio77 # includes the addition of transform option + primaryMonitor = mkOption { + type = nullOr str; + default = + if !hasMonitors + then null + else (head primaryAttr).name; + description = "Name of the primary monitor, derived from the monitors list"; + readOnly = true; + }; monitors = mkOption { type = listOf (submodule { options = { @@ -82,10 +100,6 @@ in { type = bool; default = true; }; - workspace = mkOption { - type = nullOr str; - default = null; - }; }; }); default = []; @@ -95,10 +109,8 @@ in { config = { assertions = [ { - assertion = - ((lib.length hardware.monitors) != 0) - -> ((lib.length (lib.filter (m: m.primary) hardware.monitors)) == 1); - message = "At least 1 primary monitor is required"; + assertion = hasMonitors -> primaryCount == 1; + message = "Error: config.ooknet.hardware.monitors. When monitors are configured, exactly one monitor must be designated as primary (found ${toString primaryCount} primary monitors)"; } ]; }; From 7f784a59faf556f4baed00bbba890260b60ee061 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 13 Jan 2025 20:57:13 +1100 Subject: [PATCH 132/213] nixos: use ssh-ng as default distributed builds protocol --- modules/nixos/base/distributed-builds.nix | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/nixos/base/distributed-builds.nix b/modules/nixos/base/distributed-builds.nix index aa9daac..88311fc 100644 --- a/modules/nixos/base/distributed-builds.nix +++ b/modules/nixos/base/distributed-builds.nix @@ -14,11 +14,11 @@ speedFactor, systems ? ["x86_64-linux"], supportedFeatures ? ["big-parallel" "kvm" "nixos-test"], + maxJobs, }: { - inherit speedFactor systems supportedFeatures; + inherit speedFactor systems supportedFeatures maxJobs; hostName = host; - maxJobs = self.nixosConfigurations.${host}.config.nix.settings.max-jobs or "auto"; - protocol = "ssh"; + protocol = "ssh-ng"; sshKey = "/home/${admin.name}/.ssh/builder"; }; @@ -26,10 +26,12 @@ ooksdesk = mkBuilderMachine { host = "ooksdesk"; speedFactor = 16; + maxJobs = 4; }; ooksmedia = mkBuilderMachine { host = "ooksmedia"; speedFactor = 8; + maxJobs = 1; }; }; in { From 249b68cb161870a3ff81ee097d0cc7a7d148228e Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 13 Jan 2025 21:13:18 +1100 Subject: [PATCH 133/213] nix: add builders-use-substitutes setting --- modules/nixos/base/nix.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/nixos/base/nix.nix b/modules/nixos/base/nix.nix index d79ed4e..fcf15c7 100644 --- a/modules/nixos/base/nix.nix +++ b/modules/nixos/base/nix.nix @@ -48,6 +48,7 @@ in { auto-optimise-store = true; warn-dirty = false; # cache + builders-use-substitutes = true; substituters = [ "https://cache.nixos.org?priority=10" "https://nix-community.cachix.org" From 3207e27f1d15bad4cc0b1ec4613b7b74498bd481 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 14 Jan 2025 12:28:10 +1100 Subject: [PATCH 134/213] ookst480s: disable gaming profile --- hosts/ookst480s/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/ookst480s/default.nix b/hosts/ookst480s/default.nix index 1d1b5af..2493c59 100644 --- a/hosts/ookst480s/default.nix +++ b/hosts/ookst480s/default.nix @@ -17,7 +17,7 @@ }; }; workstation = { - profiles = ["media" "gaming" "communication"]; + profiles = ["media" "communication"]; environment = "hyprland"; theme = "minimal"; }; From 3d1a0dc56fba25fea1d360c7cede36c921443c06 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 14 Jan 2025 12:28:51 +1100 Subject: [PATCH 135/213] neovim: disable markdown preview auto-start --- outputs/pkgs/ook-vim/config/plugins/utility.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/outputs/pkgs/ook-vim/config/plugins/utility.nix b/outputs/pkgs/ook-vim/config/plugins/utility.nix index eea1e91..174174b 100644 --- a/outputs/pkgs/ook-vim/config/plugins/utility.nix +++ b/outputs/pkgs/ook-vim/config/plugins/utility.nix @@ -7,7 +7,7 @@ preview = { markdownPreview = { enable = true; - autoStart = true; + autoStart = false; }; }; }; From 25452b9540c05a17a2a536957bd127243101e8a5 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 14 Jan 2025 12:29:00 +1100 Subject: [PATCH 136/213] neovim: enable spellchecker --- outputs/pkgs/ook-vim/config/settings.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/outputs/pkgs/ook-vim/config/settings.nix b/outputs/pkgs/ook-vim/config/settings.nix index ba2287a..46b572a 100644 --- a/outputs/pkgs/ook-vim/config/settings.nix +++ b/outputs/pkgs/ook-vim/config/settings.nix @@ -7,6 +7,7 @@ useSystemClipboard = true; autopairs.nvim-autopairs.enable = true; hideSearchHighlight = true; + spellcheck.enable = true; theme = { enable = false; }; From 0b8a73051902502f4269f1ed4a01790ad5aa5835 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 14 Jan 2025 12:29:28 +1100 Subject: [PATCH 137/213] neovim: add follow_url_func option --- .../ook-vim/modules/plugins/obsidian/obsidian.nix | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/outputs/pkgs/ook-vim/modules/plugins/obsidian/obsidian.nix b/outputs/pkgs/ook-vim/modules/plugins/obsidian/obsidian.nix index a6f8b7e..5410f72 100644 --- a/outputs/pkgs/ook-vim/modules/plugins/obsidian/obsidian.nix +++ b/outputs/pkgs/ook-vim/modules/plugins/obsidian/obsidian.nix @@ -86,6 +86,17 @@ in { Customize how a note ID is generated given an optional title ''; }; + follow_url_func = mkOption { + type = nullOr luaInline; + default = + mkLuaInline + # lua + '' + function(url) + vim.fn.jobstart({"xdg-open", url}) + end + ''; + }; ui = { enable = mkOption { type = nullOr bool; From 0873f56c288766deaa5483c69e7683f9679fcd36 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 15 Jan 2025 23:03:36 +1100 Subject: [PATCH 138/213] hyprland: workspace/rules module init still some work too be done, the regex types are cursed. --- .../workstation/hyprland/settings/default.nix | 2 + .../hyprland/settings/options/default.nix | 140 +++++++++++ .../hyprland/settings/options/rules.nix | 237 ++++++++++++++++++ .../workstation/hyprland/settings/rules.nix | 53 ++-- .../hyprland/settings/workspaces.nix | 37 +++ 5 files changed, 447 insertions(+), 22 deletions(-) create mode 100644 modules/home/workstation/hyprland/settings/options/default.nix create mode 100644 modules/home/workstation/hyprland/settings/options/rules.nix create mode 100644 modules/home/workstation/hyprland/settings/workspaces.nix diff --git a/modules/home/workstation/hyprland/settings/default.nix b/modules/home/workstation/hyprland/settings/default.nix index 7645edd..02c8304 100644 --- a/modules/home/workstation/hyprland/settings/default.nix +++ b/modules/home/workstation/hyprland/settings/default.nix @@ -8,5 +8,7 @@ ./monitor.nix ./gestures.nix ./appearance.nix + ./workspaces.nix + ./options ]; } diff --git a/modules/home/workstation/hyprland/settings/options/default.nix b/modules/home/workstation/hyprland/settings/options/default.nix new file mode 100644 index 0000000..a7d5605 --- /dev/null +++ b/modules/home/workstation/hyprland/settings/options/default.nix @@ -0,0 +1,140 @@ +{ + lib, + config, + ... +}: let + inherit + (lib) + flatten + attrValues + concatStringsSep + filterAttrs + mapAttrsToList + boolToString + mkOption + isBool + ; + inherit + (lib.types) + listOf + attrsOf + submodule + nullOr + str + int + bool + oneOf + ; + + # our cursed regex types + hyprland = import ./rules.nix {inherit lib;}; + + _toString = type: val: + if isBool val + then + if type == "windowrule" + then + if val + then "1" + else "0" + else boolToString val # for workspace rules + else toString val; + + # format rules for hyprland + formatRules = type: rule: + concatStringsSep "," ( + mapAttrsToList (name: value: "${name}:${_toString type value}") + (filterAttrs (_: v: v != null) rule) + ); + + # workspace handling + mkWorkspaces = mapAttrsToList ( + selector: rules: "${selector},${formatRules "workspacerule" rules}" + ); + + # rule options + mkRuleOption = type: description: + mkOption { + type = nullOr type; + default = null; + inherit description; + }; + + # window rule matchers + windowRuleMatchers = submodule { + options = { + class = mkRuleOption str "Window class matcher"; + title = mkRuleOption str "Window title matcher"; + initialClass = mkRuleOption str "Initial window class matcher"; + initialTitle = mkRuleOption str "Initial window title matcher"; + xwayland = mkRuleOption bool "Match XWayland windows"; + floating = mkRuleOption bool "Match floating windows"; + fullscreen = mkRuleOption bool "Match fullscreen windows"; + workspace = mkRuleOption str "Match windows on specific workspace"; + }; + }; + + # Workspace rules submodule + workspaceRules = submodule { + options = { + name = mkRuleOption str "Default name of workspace"; + monitor = mkRuleOption str "Binds workspace to monitor"; + default = mkRuleOption bool "Set as default workspace for monitor"; + gapsin = mkRuleOption int "Gaps between windows"; + gapsout = mkRuleOption int "Gaps between windows and monitor edges"; + bordersize = mkRuleOption int "Border size around windows"; + border = mkRuleOption bool "Draw borders"; + shadow = mkRuleOption bool "Draw shadows"; + rounding = mkRuleOption bool "Draw rounded corners"; + decorate = mkRuleOption bool "Draw window decorations"; + persistent = mkRuleOption bool "Keep workspace alive when empty"; + on-created-empty = mkRuleOption str "Command to run when workspace created empty"; + }; + }; + + # Window rules type using our validated types from rules.nix + windowRuleType = listOf (oneOf (attrValues hyprland.types)); + + cfg = config.wayland.windowManager.hyprland; +in { + options.wayland.windowManager.hyprland = { + # Workspace configuration + workspaces = mkOption { + type = attrsOf workspaceRules; + default = {}; + description = "Workspace-specific configurations"; + }; + + # Window rules configuration + windowRules = mkOption { + type = listOf (submodule { + options = { + matches = mkOption { + type = windowRuleMatchers; + description = "Window matching criteria"; + }; + rules = mkOption { + type = windowRuleType; + description = "Rules to apply to matching windows"; + }; + }; + }); + default = []; + description = "Window-specific rules"; + }; + }; + + config.wayland.windowManager.hyprland.settings = { + workspace = mkWorkspaces cfg.workspaces; + windowrulev2 = let + # Convert rules to Hyprland format + formatWindowRule = rule: let + matches = formatRules "windowrule" rule.matches; + rules = map (r: "${r},${matches}") rule.rules; + in + rules; + in + flatten (map formatWindowRule cfg.windowRules); + }; +} + diff --git a/modules/home/workstation/hyprland/settings/options/rules.nix b/modules/home/workstation/hyprland/settings/options/rules.nix new file mode 100644 index 0000000..24040a1 --- /dev/null +++ b/modules/home/workstation/hyprland/settings/options/rules.nix @@ -0,0 +1,237 @@ +{lib, ...}: let + inherit (lib) concatStringsSep attrValues; + inherit (lib.types) enum strMatching; + + # helper function for constructing regex patterns for hyprland rules + mkRegexTarget = { + name, + regex ? [], + extraRegex ? "", + optional ? false, + }: let + regexPart = concatStringsSep "|" regex; + parameterPart = + if optional + then "( (${regexPart}))?" + else " (${regexPart})"; + in + strMatching "${name}${parameterPart}${extraRegex}"; + + # basic windowrules that can be validated with simple enum + + basicWindowRules = enum [ + "float" + "tile" + "fullscreen" + "maximize" + "pseudo" + "noinitialfocus" + "pin" + "unset" + "nomaxsize" + "stayfocused" + ]; + + # toggleable options + toggleableRules = [ + # window decoration + "decorate" # window decorations + "noborder" # borders + "noshadow" # shadows + "norounding" # corner rounding + + # Visual effects + "noblur" # blur + "noanim" # animations + "nodim" # dimming + "opaque" # opacity enforcement + "forcergbx" # RGB handling + "xray" # blur xray mode + "immediate" # tearing mode + + # Behavior + "dimaround" # dim around window + "focusonactivate" # focus on activation request + "nofocus" # disable focus + "stayfocused" # keep focus + "keepaspectratio" # maintain aspect ratio + "nearestneighbor" # nearest neighbor filtering + "nomaxsize" # disable max size + "noshortcutsinhibit" # shortcut inhibiting + "allowsinput" # XWayland input forcing + "renderunfocused" # unfocused rendering + "syncfullscreen" # fullscreen sync + ]; + + # reusable regex pattens to be used in constructing our types + patterns = { + # toggles + onOpt = "1|true|on|yes|0|salse|off|no|toggle|unset"; + + # numbers + float = "[+-]?([0-9]*[.])?[0-9]+"; + int = "[0-9]+"; + alpha = ''(0|0?\.[[:digit:]]+|1|1\.0)''; + percentage = "[0-9]+(%)?"; + + # position + anchor = "100%-w?-[0-9]+"; + coordinate = "${patterns.percentage}|${patterns.anchor}"; + deg = "(0-360)"; + + # identification + numericId = "[1-9][0-9]*"; + sign = "[+-]"; + relative = "${patterns.sign}${patterns.numericId}"; + monitorPrefix = "(m|r)"; + monitorRelative = "${patterns.monitorPrefix}(${patterns.sign}${patterns.numericId}|~${patterns.numericId})"; + emptyModifiers = "[mn]*"; + empty = "empty${patterns.emptyModifiers}"; + mode = "(always|focus|fullscreen|none)"; + ident = "[A-Za-z0-9_][A-Za-z0-9_ -]*"; + name = "name:${patterns.ident}"; + special = "special(:[a-zA-Z0-9_-]+)?"; + previous = "previous(_per_monitor)?"; + openWorkspace = "e(${patterns.sign}${patterns.numericId}|~${patterns.numericId})"; + + # colors + rgbValue = ''([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])''; + rgbaHex = ''rgba\([[:xdigit:]]{8}\)''; + rgbaDecimal = ''rgba\(${patterns.rgbValue}, *${patterns.rgbValue}, *${patterns.rgbValue}, *${patterns.alpha}\)''; + rgbHex = ''rgb\([[:xdigit:]]{3}([[:xdigit:]]{3})?\)''; + rgbDecimal = ''rgb\(${patterns.rgbValue}, *${patterns.rgbValue}, *${patterns.rgbValue}\)''; + legacy = ''0x[[:xdigit:]]{8}''; + color = concatStringsSep "|" [ + patterns.rgbaHex + patterns.rgbaDecimal + patterns.rgbHex + patterns.rgbDecimal + patterns.legacy + ]; + }; + + mkToggleableRules = name: + mkRegexTarget { + inherit name; + regex = [patterns.onOpt]; + optional = true; + }; + + toggleTargets = builtins.listToAttrs (map (name: { + inherit name; + value = mkToggleableRules name; + }) + toggleableRules); + + # regex patterns to pass to the workspace rule + + types = + { + inherit basicWindowRules; + workspace = mkRegexTarget { + name = "workspace"; + regex = attrValues { + inherit (patterns) numericId relative monitorRelative empty name special previous openWorkspace; + }; + extraRegex = "( +silent)?"; + }; + + monitor = mkRegexTarget { + name = "monitor"; + regex = attrValues { + inherit (patterns) numericId ident; + }; + }; + + group = mkRegexTarget { + name = "group"; + regex = ["set|new|lock|barred|deny|invade|override|unset"]; + }; + + size = mkRegexTarget { + name = "size"; + regex = [ + "([0-9]+|[<>][0-9]+)(%|px)?( ([0-9]+|[<>][0-9]+)(%|px)?)?" + ]; + }; + + move = mkRegexTarget { + name = "move"; + regex = [ + "(${patterns.coordinate}) (${patterns.coordinate})" + "cursor (${patterns.percentage}) (${patterns.percentage})" + "onscreen cursor (${patterns.percentage}) (${patterns.percentage})" + ]; + }; + + bordercolor = mkRegexTarget { + name = "bordercolor"; + regex = [patterns.color]; + }; + + idleinhibit = mkRegexTarget { + name = "idleinhibit"; + regex = [patterns.mode]; + }; + + opacity = mkRegexTarget { + name = "opacity"; + regex = let + opacityValue = "${patterns.alpha}( override)?"; + in [ + opacityValue + "${opacityValue} ${opacityValue}" + "${opacityValue} ${opacityValue} ${opacityValue}" + ]; + }; + + center = mkRegexTarget { + name = "center"; + regex = ["[0-1]"]; + optional = true; + }; + + roundingpower = mkRegexTarget { + name = "roundingpower"; + regex = [patterns.float]; + }; + + bordersize = mkRegexTarget { + name = "bordersize"; + regex = [patterns.int]; + }; + + rounding = mkRegexTarget { + name = "rounding"; + regex = [patterns.int]; + }; + + scrollmouse = mkRegexTarget { + name = "scrollmouse"; + regex = [patterns.float]; + }; + + scrolltouchpad = mkRegexTarget { + name = "scrolltouchpad"; + regex = [patterns.float]; + }; + + tag = mkRegexTarget { + name = "tag"; + regex = [''[+-]?[[:alnum:]_]+\*?'']; + }; + + maxsize = mkRegexTarget { + name = "maxsize"; + regex = ["${patterns.int} ${patterns.int}"]; + }; + + minsize = mkRegexTarget { + name = "minsize"; + regex = ["${patterns.int} ${patterns.int}"]; + }; + } + // toggleTargets; +in { + inherit types; +} diff --git a/modules/home/workstation/hyprland/settings/rules.nix b/modules/home/workstation/hyprland/settings/rules.nix index cc79331..0edfa89 100644 --- a/modules/home/workstation/hyprland/settings/rules.nix +++ b/modules/home/workstation/hyprland/settings/rules.nix @@ -1,24 +1,33 @@ { - wayland.windowManager.hyprland.settings = { - windowrulev2 = [ - "float,move 191 15,size 924 396,class:^(1Password)$" - - "float, title:^(Picture-in-Picture)$" - "pin, title:^(Picture-in-Picture)$" - - "float,move 237 175, size 1200 720,title:^(File Upload)$" - - "workspace 4, title:^(Vesktop)$" - - # Floating BTOP - "float,title:^(BTOP)$" - "size 85%,title:^(BTOP)$" - "pin,title:^(BTOP)$" - "center,title:^(BTOP)$" - "stayfocused,title:^(BTOP)$" - - # Tearing - "immediate, title:^(TEKKEN™8)$" - ]; - }; + wayland.windowManager.hyprland.windowRules = [ + # TODO tag games for immediate + { + matches = {title = "TEKKEN™8";}; + rules = ["immediate"]; + } + { + matches = {class = "firefox";}; + rules = ["idleinhibit fullscreen"]; + } + { + matches = {class = "1Password";}; + rules = ["center 1" "float" "size 50%"]; + } + { + matches = {title = "BTOP";}; + rules = ["float" "size 85%" "pin" "center 1" "stayfocused" "dimaround"]; + } + { + matches = {class = "vesktop";}; + rules = ["workspace 4 silent"]; + } + { + matches = {title = "^(Picture-in-Picture)$";}; + rules = ["float" "pin"]; + } + { + matches = {title = "^(Open Files)$";}; + rules = ["center 1" "float" "size 50%"]; + } + ]; } diff --git a/modules/home/workstation/hyprland/settings/workspaces.nix b/modules/home/workstation/hyprland/settings/workspaces.nix new file mode 100644 index 0000000..952091b --- /dev/null +++ b/modules/home/workstation/hyprland/settings/workspaces.nix @@ -0,0 +1,37 @@ +{osConfig, ...}: let + inherit (osConfig.ooknet) hardware; + multiMonitor = builtins.length hardware.monitors > 1; + primary = hardware.primaryMonitor; + secondary = + if multiMonitor + then (builtins.elemAt hardware.monitors 1).name + else primary; +in { + wayland.windowManager.hyprland.workspaces = { + "1" = { + name = "terminal"; + monitor = primary; + default = true; + }; + "2" = { + name = "browser"; + monitor = primary; + }; + "3" = { + name = "media"; + monitor = secondary; + default = true; + }; + "4" = { + name = "discord"; + monitor = secondary; + }; + "5" = { + name = "gaming"; + monitor = primary; + }; + "r[6-9]" = { + monitor = primary; + }; + }; +} From d91bb7c006181e9163d997e8988adcdde7b8b381 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 16 Jan 2025 11:07:07 +1100 Subject: [PATCH 139/213] project-plus: add fullscreen/analytics option --- modules/home/workstation/gaming/emulation.nix | 1 + .../gaming/project-plus/options.nix | 37 ++++++++++++------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/modules/home/workstation/gaming/emulation.nix b/modules/home/workstation/gaming/emulation.nix index a9cb88e..7b18cae 100644 --- a/modules/home/workstation/gaming/emulation.nix +++ b/modules/home/workstation/gaming/emulation.nix @@ -22,6 +22,7 @@ in { }; ooknet.gaming.project-plus = { enable = true; + startFullscreen = true; netplay.nickname = "ooks"; }; }; diff --git a/modules/home/workstation/gaming/project-plus/options.nix b/modules/home/workstation/gaming/project-plus/options.nix index 7a27230..2055b67 100644 --- a/modules/home/workstation/gaming/project-plus/options.nix +++ b/modules/home/workstation/gaming/project-plus/options.nix @@ -62,6 +62,12 @@ in { }; }; + analytics = { + enable = mkEnableOption "Enable anaylytics"; + }; + + startFullscreen = mkEnableOption "Start emulated game fullscreen"; + gamesDir = mkOption { type = str; default = "./Games"; @@ -94,19 +100,24 @@ in { Core = { DefaultISO = "${cfg.userDir}/Games/brawl.iso"; }; - Netplay = - { - SelectedHostGame = "Project+ Netplay Launcher.dol"; - BufferSize = cfg.netplay.buffer; - Nickname = cfg.netplay.nickname; - MusicOff = cfg.netplay.disableMusic; - ListenPort = "0x0a42"; - HostPort = "0x0a42"; - ConnectPort = "0x0a42"; - HostCode = 00000000; - TraversalChoice = "traversal"; - } - // cfg.extraSettings; + Netplay = { + SelectedHostGame = "Project+ Netplay Launcher.dol"; + BufferSize = cfg.netplay.buffer; + Nickname = cfg.netplay.nickname; + MusicOff = cfg.netplay.disableMusic; + ListenPort = "0x0a42"; + HostPort = "0x0a42"; + ConnectPort = "0x0a42"; + HostCode = 00000000; + TraversalChoice = "traversal"; + }; + Analytics = { + Enabled = cfg.analytics.enable; + PermissionAsked = true; + }; + Display = { + Fullscreen = cfg.startFullscreen; + }; }; }; # Copy dolphin GameSettings configuration from faster-project-plus config From 5596951ab98cca9363a054d756bbb0f6a1d306ae Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 16 Jan 2025 23:14:32 +1100 Subject: [PATCH 140/213] qt: implement kvantum --- .../home/workstation/appearance/default.nix | 2 +- modules/home/workstation/appearance/qt.nix | 16 - .../workstation/appearance/qt/default.nix | 426 ++++ .../home/workstation/appearance/qt/gruv.nix | 1960 ++++++++++++++++ .../workstation/appearance/qt/kdeglobals.nix | 154 ++ .../workstation/appearance/qt/kvantumSVG.nix | 1962 +++++++++++++++++ .../workstation/appearance/qt/testSVG.nix | 753 +++++++ modules/home/workstation/hyprland/default.nix | 2 +- 8 files changed, 5257 insertions(+), 18 deletions(-) delete mode 100644 modules/home/workstation/appearance/qt.nix create mode 100644 modules/home/workstation/appearance/qt/default.nix create mode 100644 modules/home/workstation/appearance/qt/gruv.nix create mode 100644 modules/home/workstation/appearance/qt/kdeglobals.nix create mode 100644 modules/home/workstation/appearance/qt/kvantumSVG.nix create mode 100644 modules/home/workstation/appearance/qt/testSVG.nix diff --git a/modules/home/workstation/appearance/default.nix b/modules/home/workstation/appearance/default.nix index 662d776..7a7f605 100644 --- a/modules/home/workstation/appearance/default.nix +++ b/modules/home/workstation/appearance/default.nix @@ -1,6 +1,6 @@ { imports = [ - ./qt.nix + ./qt ./gtk.nix ./fonts.nix ./cursor.nix diff --git a/modules/home/workstation/appearance/qt.nix b/modules/home/workstation/appearance/qt.nix deleted file mode 100644 index 3ad74c8..0000000 --- a/modules/home/workstation/appearance/qt.nix +++ /dev/null @@ -1,16 +0,0 @@ -{pkgs, ...}: { - qt = { - enable = true; - style.name = "gtk2"; - platformTheme.name = "gtk2"; - }; - - home.packages = with pkgs; [ - libsForQt5.qt5.qtwayland - kdePackages.qtwayland - qt6.qtwayland - kdePackages.qqc2-desktop-style - libsForQt5.qtstyleplugins - qt6Packages.qt6gtk2 - ]; -} diff --git a/modules/home/workstation/appearance/qt/default.nix b/modules/home/workstation/appearance/qt/default.nix new file mode 100644 index 0000000..42010af --- /dev/null +++ b/modules/home/workstation/appearance/qt/default.nix @@ -0,0 +1,426 @@ +{ + pkgs, + hozen, + lib, + ... +}: let + inherit (hozen) color; + mkKvconig = text: lib.generators.toINI {} text; + kvantumSVG = import ./gruv.nix {inherit color;}; + + theme = "KvHozen"; +in { + imports = [ + ./kdeglobals.nix + ]; + + qt = { + enable = true; + platformTheme.name = "gtk3"; + style = { + name = "kvantum"; + }; + }; + + xdg.configFile = { + "Kvantum/kvantum.kvconfig".text = mkKvconig { + General = {inherit theme;}; + #Applications."${theme}" = "org.kde.dolphin, dolphin-emu, faster-project-plus"; + }; + "Kvantum/KvHozen/KvHozen.svg".text = kvantumSVG; + "Kvantum/KvHozen/KvHozen.kvconfig".text = mkKvconig { + # docs: + "%General" = { + author = "ooks"; + comment = "Hozen theme using Hozen color scheme"; + + # Window/Widget Behavior + respect_DE = true; + x11drag = "menubar_and_primary_toolbar"; + alt_mnemonic = true; + click_behavior = 0; + double_click = false; + inline_spin_indicators = true; + vertical_spin_indicators = false; + spin_button_width = 16; + combo_as_lineedit = true; + combo_menu = true; + hide_combo_checkboxes = true; + combo_focus_rect = true; + groupbox_top_label = true; + button_contents_shift = false; + fill_rubberband = false; + merge_menubar_with_toolbar = true; + toolbutton_style = 1; + + # compositing & effects + composite = true; + translucent_windows = true; + reduce_window_opacity = 10; + reduce_menu_opacity = 0; + blurring = false; + popup_blurring = true; + menu_blur_radius = 5; + tooltip_blur_radius = 5; + contrast = 1.00; + intensity = 1.00; + saturation = 1.00; + + # animations & visual feedback + animate_states = false; + no_inactiveness = false; + no_window_pattern = false; + + # menu configuration + menubar_mouse_tracking = true; + menu_shadow_depth = 7; + tooltip_shadow_depth = 6; + spread_menuitems = true; + submenu_overlap = 0; + spread_progressbar = true; + + # scrollbars & sliders + scroll_width = 8; + scroll_min_extent = 36; + scrollbar_in_view = false; + transient_scrollbar = true; + transient_groove = false; + slider_width = 4; + slider_handle_width = 18; + slider_handle_length = 18; + + # layout & sizing + layout_spacing = 2; + layout_margin = 4; + small_icon_size = 16; + large_icon_size = 32; + button_icon_size = 16; + toolbar_icon_size = 16; + + # widget specific + check_size = 16; + tooltip_delay = -1; + tree_branch_line = true; + progressbar_thickness = 8; + }; + + # color configuration + GeneralColors = { + # Base Colors + "window.color" = "#${color.layout.menu}"; + "inactive.window.color" = "#${color.layout.menu}"; + "base.color" = "#${color.layout.body}"; + "inactive.base.color" = "#${color.layout.body}"; + "alt.base.color" = "#${color.layout.body}"; + "button.color" = "#${color.layout.menu}"; + "light.color" = "#${color.secondary.base}"; + "mid.light.color" = "#${color.secondary.soft1}"; + "dark.color" = "#${color.secondary.hard1}"; + "mid.color" = "#${color.secondary.base}"; + + # Highlight Colors + "highlight.color" = "#${color.primary.base}"; + "inactive.highlight.color" = "#${color.primary.soft1}"; + + # Text Colors + "text.color" = "#${color.typography.text}"; + "inactive.text.color" = "#${color.typography.subtext}"; + "window.text.color" = "#${color.typography.text}"; + "inactive.window.text.color" = "#${color.typography.subtext}"; + "button.text.color" = "#${color.typography.text}"; + "disabled.text.color" = "#${color.typography.subtext}"; + "tooltip.text.color" = "#${color.typography.text}"; + "highlight.text.color" = "#${color.typography.contrast-text}"; + "link.color" = "#${color.blue.base}"; + "link.visited.color" = "#${color.purple.base}"; + "progress.indicator.text.color" = "#${color.typography.text}"; + "progress.inactive.indicator.text.color" = "#${color.typography.subtext}"; + }; + + # Widget-Specific Configurations + Hacks = { + transparent_dolphin_view = false; + blur_konsole = true; + transparent_ktitle_label = true; + transparent_menutitle = true; + respect_darkness = true; + force_size_grip = false; + iconless_pushbutton = true; + iconless_menu = false; + disabled_icon_opacity = 100; + normal_default_pushbutton = true; + tint_on_mouseover = 0; + blur_translucent = true; + kinetic_scrolling = false; + middle_click_scroll = false; + no_selection_tint = false; + }; + + # Button Configuration + PanelButtonCommand = { + frame = true; + "frame.element" = "button"; + "frame.expanded" = true; + interior = true; + "interior.element" = "button"; + "indicator.size" = 8; + "text.normal.color" = "#${color.typography.text}"; + "text.focus.color" = "#${color.typography.text}"; + "text.press.color" = "#${color.typography.text}"; + "text.toggle.color" = "#${color.typography.text}"; + "text.shadow" = false; + "text.margin" = 1; + "text.iconspacing" = 4; + "frame.expansion" = 6; + }; + + PanelButtonTool = { + inherits = "PanelButtonCommand"; + }; + + # Window Frames + GenericFrame = { + inherits = "PanelButtonCommand"; + frame = true; + "frame.element" = "common"; + interior = false; + "frame.top" = 3; + "frame.bottom" = 3; + "frame.left" = 3; + "frame.right" = 3; + }; + + # menu configuration + Menu = { + inherits = "PanelButtonCommand"; + "frame.element" = "menu"; + "interior.element" = "menu"; + "frame.top" = 3; + "frame.bottom" = 3; + "frame.left" = 3; + "frame.right" = 3; + }; + + MenuItem = { + inherits = "PanelButtonCommand"; + frame = true; + interior = true; + "interior.element" = "menuitem"; + "indicator.size" = 8; + "text.focus.color" = "#${color.typography.text}"; + "text.press.color" = "#${color.typography.text}"; + }; + + MenuBarItem = { + inherits = "PanelButtonCommand"; + "interior.element" = "menubaritem"; + frame = false; + "text.margin.top" = 3; + "text.margin.bottom" = 3; + "text.margin.left" = 5; + "text.margin.right" = 5; + }; + + MenuBar = { + inherits = "PanelButtonCommand"; + "frame.element" = "menubar"; + "interior.element" = "menubar"; + "frame.bottom" = 0; + "text.normal.color" = "#${color.typography.text}"; + }; + + # Scrollbars + ScrollbarSlider = { + inherits = "PanelButtonCommand"; + frame = true; + interior = false; + "frame.element" = "scrollbarslider"; + "indicator.element" = "grip"; + "indicator.size" = 13; + "frame.left" = 6; + "frame.right" = 6; + "frame.top" = 6; + "frame.bottom" = 6; + }; + + ScrollbarGroove = { + inherits = "PanelButtonCommand"; + interior = false; + frame = false; + }; + + # Sliders + Slider = { + inherits = "PanelButtonCommand"; + frame = false; + "interior.element" = "slider"; + "frame.top" = 3; + "frame.bottom" = 3; + "frame.left" = 3; + "frame.right" = 3; + }; + + SliderCursor = { + inherits = "PanelButtonCommand"; + frame = false; + "interior.element" = "slidercursor"; + }; + + # Progress Bars + Progressbar = { + inherits = "PanelButtonCommand"; + "frame.element" = "progress"; + "interior.element" = "progress"; + "text.margin" = 0; + "text.normal.color" = "#${color.typography.text}"; + "text.focus.color" = "#${color.typography.text}"; + "text.press.color" = "#${color.typography.contrast-text}"; + "text.toggle.color" = "#${color.typography.contrast-text}"; + }; + + ProgressbarContents = { + inherits = "PanelButtonCommand"; + frame = true; + "frame.element" = "progress-pattern"; + "interior.element" = "progress-pattern"; + }; + + # Tabs + TabBarFrame = { + inherits = "GenericFrame"; + frame = true; + "frame.element" = "tabBarFrame"; + interior = false; + "frame.top" = 4; + "frame.bottom" = 4; + "frame.left" = 4; + "frame.right" = 4; + }; + + TabFrame = { + inherits = "PanelButtonCommand"; + "frame.element" = "tabframe"; + "interior.element" = "tabframe"; + }; + + Tab = { + inherits = "PanelButtonCommand"; + "interior.element" = "tab"; + "frame.element" = "tab"; + "frame.top" = 2; + "frame.bottom" = 2; + "frame.left" = 2; + "frame.right" = 2; + "text.margin.left" = 8; + "text.margin.right" = 8; + "text.margin.top" = 2; + "text.margin.bottom" = 2; + }; + + # Line Edits + LineEdit = { + inherits = "PanelButtonCommand"; + "frame.element" = "lineedit"; + "interior.element" = "lineedit"; + "frame.top" = 3; + "frame.bottom" = 3; + "frame.left" = 3; + "frame.right" = 3; + "text.margin.top" = 2; + "text.margin.bottom" = 2; + "text.margin.left" = 2; + "text.margin.right" = 2; + }; + + # Combo Boxes + ComboBox = { + inherits = "PanelButtonCommand"; + "frame.element" = "combo"; + "interior.element" = "combo"; + "frame.top" = 3; + "frame.bottom" = 3; + "frame.left" = 3; + "frame.right" = 3; + "text.margin.top" = 2; + "text.margin.bottom" = 2; + "text.margin.left" = 2; + "text.margin.right" = 2; + "indicator.element" = "carrow"; + }; + + # Spinboxes + SpinBox = { + inherits = "ComboBox"; + "frame.element" = "spinbox"; + "interior.element" = "spinbox"; + "frame.top" = 3; + "frame.bottom" = 3; + "frame.left" = 3; + "frame.right" = 3; + "indicator.element" = "arrow"; + "indicator.size" = 8; + }; + + # Group Boxes + GroupBox = { + inherits = "GenericFrame"; + frame = true; + "frame.element" = "group"; + interior = false; + "frame.top" = 4; + "frame.bottom" = 4; + "frame.left" = 4; + "frame.right" = 4; + }; + + # tooltips + ToolTip = { + inherits = "PanelButtonCommand"; + "frame.top" = 3; + "frame.bottom" = 3; + "frame.left" = 3; + "frame.right" = 3; + interior = true; + "text.shadow" = false; + "text.margin" = 0; + "frame.element" = "tooltip"; + "interior.element" = "tooltip"; + "frame.expansion" = 0; + }; + + # window decorations + Window = { + interior = true; + "interior.element" = "window"; + "frame.element" = "window"; + "frame.top" = 0; + "frame.bottom" = 0; + "frame.left" = 0; + "frame.right" = 0; + }; + + Dialog = { + inherits = "Window"; + }; + }; + }; + home.packages = with pkgs; [ + libsForQt5.qt5.qtwayland + kdePackages.qtwayland + kdePackages.qqc2-desktop-style + kdePackages.qttools + qt6Packages.qt6gtk2 + qt6.qtwayland + + libsForQt5.qtstyleplugins + qt6Packages.qt6gtk2 + libsForQt5.qt5ct + kdePackages.qt6ct + + #libsForQt5.breeze-qt5 + #kdePackages.breeze-icons + # kvantum libraries + libsForQt5.qtstyleplugin-kvantum + qt6Packages.qtstyleplugin-kvantum + ]; +} diff --git a/modules/home/workstation/appearance/qt/gruv.nix b/modules/home/workstation/appearance/qt/gruv.nix new file mode 100644 index 0000000..66602ba --- /dev/null +++ b/modules/home/workstation/appearance/qt/gruv.nix @@ -0,0 +1,1960 @@ +{color}: '' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +'' diff --git a/modules/home/workstation/appearance/qt/kdeglobals.nix b/modules/home/workstation/appearance/qt/kdeglobals.nix new file mode 100644 index 0000000..486a6ff --- /dev/null +++ b/modules/home/workstation/appearance/qt/kdeglobals.nix @@ -0,0 +1,154 @@ +{ + lib, + hozen, + ... +}: let + inherit (hozen) color; +in { + xdg.configFile."kdeglobals".text = lib.generators.toINI {} { + "ColorEffects:Disabled" = { + Color = "#${color.layout.menu}"; + ColorAmount = 0.30000000000000004; + ColorEffect = 2; + ContrastAmount = 0.1; + ContrastEffect = 0; + IntensityAmount = -1; + IntensityEffect = 0; + }; + "ColorEffects:Inactive" = { + ChangeSelectionColor = true; + Color = "#${color.layout.menu}"; + ColorAmount = 0.5; + ColorEffect = 3; + ContrastAmount = 0; + ContrastEffect = 0; + Enable = true; + IntensityAmount = 0; + IntensityEffect = 0; + }; + "Colors:Button" = { + BackgroundAlternate = "#${color.primary.base}"; + BackgroundNormal = "#${color.layout.body}"; + DecorationFocus = "#${color.primary.base}"; + DecorationHover = "#${color.layout.body}"; + ForegroundActive = "#${color.orange.base}"; + ForegroundInactive = "#${color.typography.subtext}"; + ForegroundLink = "#${color.primary.base}"; + ForegroundNegative = "#${color.error.base}"; + ForegroundNeutral = "#${color.yellow.base}"; + ForegroundNormal = "#${color.typography.text}"; + ForegroundPositive = "#${color.success.base}"; + ForegroundVisited = "#${color.purple.base}"; + }; + + "Colors:Complementary" = { + BackgroundAlternate = "#${color.neutrals."900"}"; + BackgroundNormal = "#${color.layout.dimmed}"; + DecorationFocus = "#${color.primary.base}"; + DecorationHover = "#${color.layout.body}"; + ForegroundActive = "#${color.orange.base}"; + ForegroundInactive = "#${color.typography.subtext}"; + ForegroundLink = "#${color.primary.base}"; + ForegroundNegative = "#${color.error.base}"; + ForegroundNeutral = "#${color.yellow.base}"; + ForegroundNormal = "#${color.typography.text}"; + ForegroundPositive = "#${color.success.base}"; + ForegroundVisited = "#${color.purple.base}"; + }; + + "Colors:Header" = { + BackgroundAlternate = "#${color.neutrals."900"}"; + BackgroundNormal = "#${color.layout.dimmed}"; + DecorationFocus = "#${color.primary.base}"; + DecorationHover = "#${color.layout.body}"; + ForegroundActive = "#${color.orange.base}"; + ForegroundInactive = "#${color.typography.subtext}"; + ForegroundLink = "#${color.primary.base}"; + ForegroundNegative = "#${color.error.base}"; + ForegroundNeutral = "#${color.yellow.base}"; + ForegroundNormal = "#${color.typography.text}"; + ForegroundPositive = "#${color.success.base}"; + ForegroundVisited = "#${color.purple.base}"; + }; + + "Colors:Selection" = { + BackgroundAlternate = "#${color.primary.base}"; + BackgroundNormal = "#${color.primary.base}"; + DecorationFocus = "#${color.primary.base}"; + DecorationHover = "#${color.layout.body}"; + ForegroundLink = "#${color.primary.base}"; + ForegroundInactive = "#${color.layout.dimmed}"; + ForegroundActive = "#${color.orange.base}"; + ForegroundNegative = "#${color.error.base}"; + ForegroundNeutral = "#${color.yellow.base}"; + ForegroundNormal = "#${color.neutrals."900"}"; + ForegroundPositive = "#${color.success.base}"; + ForegroundVisited = "#${color.purple.base}"; + }; + + "Colors:Tooltip" = { + BackgroundAlternate = "#${color.layout.dimmed}"; + BackgroundNormal = "#${color.layout.menu}"; + DecorationFocus = "#${color.primary.base}"; + DecorationHover = "#${color.layout.body}"; + ForegroundActive = "#${color.orange.base}"; + ForegroundInactive = "#${color.typography.subtext}"; + ForegroundLink = "#${color.primary.base}"; + ForegroundNegative = "#${color.error.base}"; + ForegroundNeutral = "#${color.yellow.base}"; + ForegroundNormal = "#${color.typography.text}"; + ForegroundPositive = "#${color.success.base}"; + ForegroundVisited = "#${color.purple.base}"; + }; + + "Colors:View" = { + BackgroundAlternate = "#${color.layout.dimmed}"; + BackgroundNormal = "#${color.layout.menu}"; + DecorationFocus = "#${color.primary.base}"; + DecorationHover = "#${color.layout.body}"; + ForegroundActive = "#${color.orange.base}"; + ForegroundInactive = "#${color.typography.subtext}"; + ForegroundLink = "#${color.primary.base}"; + ForegroundNegative = "#${color.error.base}"; + ForegroundNeutral = "#${color.yellow.base}"; + ForegroundNormal = "#${color.typography.text}"; + ForegroundPositive = "#${color.success.base}"; + ForegroundVisited = "#${color.purple.base}"; + }; + + "Colors:Window" = { + BackgroundAlternate = "#${color.neutrals."900"}"; + BackgroundNormal = "#${color.layout.dimmed}"; + DecorationFocus = "#${color.primary.base}"; + DecorationHover = "#${color.layout.body}"; + ForegroundActive = "#${color.orange.base}"; + ForegroundInactive = "#${color.typography.subtext}"; + ForegroundLink = "#${color.primary.base}"; + ForegroundNegative = "#${color.error.base}"; + ForegroundNeutral = "#${color.yellow.base}"; + ForegroundNormal = "#${color.typography.text}"; + ForegroundPositive = "#${color.success.base}"; + ForegroundVisited = "#${color.purple.base}"; + }; + + General = { + ColorScheme = "GruvboxMaterial"; + Name = "GruvboxMaterial"; + accentActiveTitlebar = false; + shadeSortColumn = true; + }; + + KDE = { + contrast = 4; + }; + + WM = { + activeBackground = "#${color.layout.menu}"; + activeBlend = "#${color.typography.text}"; + activeForeground = "#${color.typography.text}"; + inactiveBackground = "#${color.neutrals."900"}"; + inactiveBlend = "#${color.typography.subtext}"; + inactiveForeground = "#${color.typography.subtext}"; + }; + }; +} diff --git a/modules/home/workstation/appearance/qt/kvantumSVG.nix b/modules/home/workstation/appearance/qt/kvantumSVG.nix new file mode 100644 index 0000000..587458d --- /dev/null +++ b/modules/home/workstation/appearance/qt/kvantumSVG.nix @@ -0,0 +1,1962 @@ +{color}: +#svg +'' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +'' diff --git a/modules/home/workstation/appearance/qt/testSVG.nix b/modules/home/workstation/appearance/qt/testSVG.nix new file mode 100644 index 0000000..b3cd821 --- /dev/null +++ b/modules/home/workstation/appearance/qt/testSVG.nix @@ -0,0 +1,753 @@ +{color}: '' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Date: Thu, 16 Jan 2025 23:14:57 +1100 Subject: [PATCH 141/213] hyprland: add dropdown bar --- modules/home/workstation/hyprland/settings/binds.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/home/workstation/hyprland/settings/binds.nix b/modules/home/workstation/hyprland/settings/binds.nix index 4040286..07c9f22 100644 --- a/modules/home/workstation/hyprland/settings/binds.nix +++ b/modules/home/workstation/hyprland/settings/binds.nix @@ -2,10 +2,12 @@ inherit (config.ooknet) binds; in { wayland.windowManager.hyprland.settings = { + # TODO: build better binds interface bind = [ # Program Launch "SUPER, b, exec, ${binds.browser}" "SUPER, return, exec, ${binds.terminal}" + "SUPERSHIFT, return, exec, ${binds.terminal} --title foot-dropdown" "SUPER, e, exec, ${binds.terminalLaunch} $EDITOR" "SUPERSHIFT, P, exec, ${binds.password}" "SUPERCTRL, P, exec, ${binds.quickpass}" From a0eed0bcc1a62d53f03627736089df05687eb0ee Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 16 Jan 2025 23:15:08 +1100 Subject: [PATCH 142/213] foot: disable dpi aware --- modules/home/workstation/terminal/foot.nix | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/modules/home/workstation/terminal/foot.nix b/modules/home/workstation/terminal/foot.nix index 3c6d15e..1612364 100644 --- a/modules/home/workstation/terminal/foot.nix +++ b/modules/home/workstation/terminal/foot.nix @@ -38,10 +38,7 @@ in { font-bold = mkFontConfig monospace "bold"; font-italic = mkFontConfig monospace "italic"; font-bold-italic = mkFontConfig monospace "boldItalic"; - dpi-aware = - if monospace.bitmap - then "no" - else "yes"; + dpi-aware = false; letter-spacing = "0"; bold-text-in-bright = "palette-based"; resize-delay-ms = "80"; From 11f014919af0881422a94073915038a8c87888bb Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 16 Jan 2025 23:15:35 +1100 Subject: [PATCH 143/213] hyprland: add animation option to windowrules module --- .../hyprland/settings/options/default.nix | 2 +- .../hyprland/settings/options/rules.nix | 4 ++ .../workstation/hyprland/settings/rules.nix | 42 ++++++++++++++++++- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/modules/home/workstation/hyprland/settings/options/default.nix b/modules/home/workstation/hyprland/settings/options/default.nix index a7d5605..d59c620 100644 --- a/modules/home/workstation/hyprland/settings/options/default.nix +++ b/modules/home/workstation/hyprland/settings/options/default.nix @@ -67,6 +67,7 @@ title = mkRuleOption str "Window title matcher"; initialClass = mkRuleOption str "Initial window class matcher"; initialTitle = mkRuleOption str "Initial window title matcher"; + tag = mkRuleOption str "Window tag matcher"; xwayland = mkRuleOption bool "Match XWayland windows"; floating = mkRuleOption bool "Match floating windows"; fullscreen = mkRuleOption bool "Match fullscreen windows"; @@ -137,4 +138,3 @@ in { flatten (map formatWindowRule cfg.windowRules); }; } - diff --git a/modules/home/workstation/hyprland/settings/options/rules.nix b/modules/home/workstation/hyprland/settings/options/rules.nix index 24040a1..99b5356 100644 --- a/modules/home/workstation/hyprland/settings/options/rules.nix +++ b/modules/home/workstation/hyprland/settings/options/rules.nix @@ -230,6 +230,10 @@ name = "minsize"; regex = ["${patterns.int} ${patterns.int}"]; }; + animation = mkRegexTarget { + name = "animation"; + regex = ["(slide)( (left|right|up|down|top|bottom))?|(popin)( ([0-9]+%))?"]; + }; } // toggleTargets; in { diff --git a/modules/home/workstation/hyprland/settings/rules.nix b/modules/home/workstation/hyprland/settings/rules.nix index 0edfa89..5296acd 100644 --- a/modules/home/workstation/hyprland/settings/rules.nix +++ b/modules/home/workstation/hyprland/settings/rules.nix @@ -1,9 +1,37 @@ -{ +{osConfig, ...}: let + monitor = builtins.elemAt osConfig.ooknet.hardware.monitors 0; + + widthMinusGaps = toString (monitor.width - 23); +in { wayland.windowManager.hyprland.windowRules = [ # TODO tag games for immediate + { + matches = {class = "factorio";}; + rules = ["tag +games"]; + } + { + matches = {initialTitle = "World of Warcraft";}; + rules = ["tag +games"]; + } { matches = {title = "TEKKEN™8";}; - rules = ["immediate"]; + rules = ["tag +games"]; + } + { + matches = {initialTitle = "Dolphin";}; + rules = ["tag +games" "idleinhibit focus"]; + } + { + matches = {tag = "games";}; + rules = ["workspace 6" "immediate"]; + } + { + matches = {title = "Steam";}; + rules = ["workspace 5"]; + } + { + matches = {title = "Steam Settings";}; + rules = ["float" "size 50%" "center 1"]; } { matches = {class = "firefox";}; @@ -29,5 +57,15 @@ matches = {title = "^(Open Files)$";}; rules = ["center 1" "float" "size 50%"]; } + { + matches = {initialTitle = "foot-dropdown";}; + rules = [ + "monitor 0" + "animation slide down" + "float" + "move 12 46" + "size ${widthMinusGaps} 30%" + ]; + } ]; } From 887507a022def42f5ef968a578bd592cda41993f Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 17 Jan 2025 19:47:56 +1100 Subject: [PATCH 144/213] appearance: add berkeley font --- flake.lock | 27 +++++++++++++++++++ flake.nix | 8 ++++++ .../workstation/appearance/qt/default.nix | 2 +- modules/nixos/workstation/themes/minimal.nix | 13 ++++----- 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/flake.lock b/flake.lock index c19d353..a5bf59a 100644 --- a/flake.lock +++ b/flake.lock @@ -3286,6 +3286,7 @@ "nvf": "nvf", "ooknet-website": "ooknet-website", "ooks-scripts": "ooks-scripts", + "secrets": "secrets", "systems": "systems_7", "vpn-confinement": "vpn-confinement", "zjstatus": "zjstatus" @@ -3334,6 +3335,32 @@ "type": "github" } }, + "secrets": { + "inputs": { + "flake-parts": [ + "flake-parts" + ], + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1737094724, + "narHash": "sha256-PeNJWuk+zNrqCsrSbElfFmMP+R5E0uFaAgW9tWG03ag=", + "ref": "refs/heads/master", + "rev": "dbbf390c798a14bb316681e62fe56355d9ea88f6", + "revCount": 4, + "type": "git", + "url": "ssh://git@github.com/ooks-io/kunzen" + }, + "original": { + "type": "git", + "url": "ssh://git@github.com/ooks-io/kunzen" + } + }, "systems": { "locked": { "lastModified": 1681028828, diff --git a/flake.nix b/flake.nix index 582e514..63152d2 100644 --- a/flake.nix +++ b/flake.nix @@ -34,6 +34,14 @@ url = "git+ssh://git@github.com/ooks-io/website"; inputs.nixpkgs.follows = "nixpkgs"; }; + secrets = { + url = "git+ssh://git@github.com/ooks-io/kunzen"; + inputs = { + nixpkgs.follows = "nixpkgs"; + flake-parts.follows = "flake-parts"; + systems.follows = "systems"; + }; + }; nvf = { url = "github:notashelf/nvf"; diff --git a/modules/home/workstation/appearance/qt/default.nix b/modules/home/workstation/appearance/qt/default.nix index 42010af..0a1e3d6 100644 --- a/modules/home/workstation/appearance/qt/default.nix +++ b/modules/home/workstation/appearance/qt/default.nix @@ -16,7 +16,7 @@ in { qt = { enable = true; - platformTheme.name = "gtk3"; + platformTheme.name = "qtct"; style = { name = "kvantum"; }; diff --git a/modules/nixos/workstation/themes/minimal.nix b/modules/nixos/workstation/themes/minimal.nix index ee687a8..73f3484 100644 --- a/modules/nixos/workstation/themes/minimal.nix +++ b/modules/nixos/workstation/themes/minimal.nix @@ -3,6 +3,7 @@ lib, pkgs, hozen, + inputs', ... }: let inherit (lib) mkIf; @@ -13,14 +14,14 @@ in { ooknet.appearance = { fonts = { monospace = { - package = pkgs.nerd-fonts.jetbrains-mono; + package = inputs'.secrets.packages.berkeley-nerd-mono; size = 16; - family = "JetBrainsMono NF"; + family = "BerkeleyMono Nerd Font"; variants = { - regular = "JetBrainsMono NF:style=Regular"; - bold = "JetBrainsMono NF:style=Bold"; - italic = "JetBrainsMono NF:style=Italic"; - boldItalic = "JetBrainsMono NF:style=Bold Italic"; + regular = "BerkeleyMono Nerd Font:style=Regular"; + bold = "BerkeleyMono Nerd Font:style=Bold"; + italic = "BerkeleyMono Nerd Font:style=Italic"; + boldItalic = "BerkeleyMono Nerd Font:style=Bold Italic"; }; }; regular = { From f10661f33fdcfb33393b2acd7ccdc7b3abac7cb9 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 17 Jan 2025 23:05:05 +1100 Subject: [PATCH 145/213] packages: repopack -> repomix --- modules/home/console/tools/utils.nix | 14 +++----------- outputs/pkgs/default.nix | 2 +- outputs/pkgs/{repopack => repomix}/default.nix | 14 +++++++------- 3 files changed, 11 insertions(+), 19 deletions(-) rename outputs/pkgs/{repopack => repomix}/default.nix (50%) diff --git a/modules/home/console/tools/utils.nix b/modules/home/console/tools/utils.nix index 5354ff6..cbe00aa 100644 --- a/modules/home/console/tools/utils.nix +++ b/modules/home/console/tools/utils.nix @@ -15,32 +15,26 @@ in { inherit (pkgs) bc # Calculator - + # file utility - duf du-dust fd ripgrep # archive - zip unzip unrar # file transfer - rsync wget httpie # Better curl - + # resource manager - powertop #shell scripting - gum # audio ctrl - pamixer diffsitter # Better diff jq # JSON pretty printer and manipulator @@ -49,15 +43,13 @@ in { killall acpi # Notifications - libnotify # Nix tooling - alejandra ; #AI - inherit (self'.packages) repopack; + inherit (self'.packages) repomix; }; }; } diff --git a/outputs/pkgs/default.nix b/outputs/pkgs/default.nix index b49dd40..abdead4 100644 --- a/outputs/pkgs/default.nix +++ b/outputs/pkgs/default.nix @@ -17,7 +17,7 @@ }; in { packages = { - repopack = callPackage ./repopack {}; + repomix = callPackage ./repomix {}; live-buds-cli = callPackage ./live-buds-cli {}; website = callPackage ./website {}; caddy-with-cloudflare = callPackage ./caddy-with-cloudflare {}; diff --git a/outputs/pkgs/repopack/default.nix b/outputs/pkgs/repomix/default.nix similarity index 50% rename from outputs/pkgs/repopack/default.nix rename to outputs/pkgs/repomix/default.nix index b9a67fd..7ff9f30 100644 --- a/outputs/pkgs/repopack/default.nix +++ b/outputs/pkgs/repomix/default.nix @@ -4,24 +4,24 @@ fetchFromGitHub, }: buildNpmPackage rec { - pname = "repopack"; - version = "0.1.24"; + pname = "repomix"; + version = "0.2.20"; src = fetchFromGitHub { owner = "yamadashy"; - repo = "repopack"; + repo = "repomix"; rev = "v${version}"; - hash = "sha256-+UcpfxMcG47j4fSOAXBvNgwKy0nSC6UKJvNc5G8c6U0="; + hash = "sha256-ZfkaopnftD6wJ0KAScE1q2u3/jM36QVwx6CgPiS1nWY"; }; - npmDepsHash = "sha256-Jyp48JNRuqxGSNi6eLrnOkF4Z+OResbtfbTYHg1S1mU="; + npmDepsHash = "sha256-/ocQ5vp67w5U6Gx+1LgJzcObsvKeTVN9BOEKXSb6oU0"; meta = { description = '' A powerful tool that packs your entire repository into a single, AI-friendly file. ''; - homepage = "https://github.com/yamadashy/repopack"; - mainProgram = "repopack"; + homepage = "https://github.com/yamadashy/repomix"; + mainProgram = "repomix"; }; } From 910d6f99c6990c3ae3662ccebe1e6052500a9520 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 17 Jan 2025 23:05:37 +1100 Subject: [PATCH 146/213] qt: update kdeglobals --- .../workstation/appearance/qt/kdeglobals.nix | 2 +- .../workstation/appearance/qt/kvantumSVG.nix | 1962 ----------------- .../workstation/appearance/qt/testSVG.nix | 753 ------- 3 files changed, 1 insertion(+), 2716 deletions(-) delete mode 100644 modules/home/workstation/appearance/qt/kvantumSVG.nix delete mode 100644 modules/home/workstation/appearance/qt/testSVG.nix diff --git a/modules/home/workstation/appearance/qt/kdeglobals.nix b/modules/home/workstation/appearance/qt/kdeglobals.nix index 486a6ff..2a5ca19 100644 --- a/modules/home/workstation/appearance/qt/kdeglobals.nix +++ b/modules/home/workstation/appearance/qt/kdeglobals.nix @@ -8,7 +8,7 @@ in { xdg.configFile."kdeglobals".text = lib.generators.toINI {} { "ColorEffects:Disabled" = { Color = "#${color.layout.menu}"; - ColorAmount = 0.30000000000000004; + ColorAmount = "0.30000000000000004"; ColorEffect = 2; ContrastAmount = 0.1; ContrastEffect = 0; diff --git a/modules/home/workstation/appearance/qt/kvantumSVG.nix b/modules/home/workstation/appearance/qt/kvantumSVG.nix deleted file mode 100644 index 587458d..0000000 --- a/modules/home/workstation/appearance/qt/kvantumSVG.nix +++ /dev/null @@ -1,1962 +0,0 @@ -{color}: -#svg -'' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -'' diff --git a/modules/home/workstation/appearance/qt/testSVG.nix b/modules/home/workstation/appearance/qt/testSVG.nix deleted file mode 100644 index b3cd821..0000000 --- a/modules/home/workstation/appearance/qt/testSVG.nix +++ /dev/null @@ -1,753 +0,0 @@ -{color}: '' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Date: Fri, 17 Jan 2025 23:06:00 +1100 Subject: [PATCH 148/213] ci: garnix --- .github/workflows/garnix.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/workflows/garnix.yml diff --git a/.github/workflows/garnix.yml b/.github/workflows/garnix.yml new file mode 100644 index 0000000..68d75c1 --- /dev/null +++ b/.github/workflows/garnix.yml @@ -0,0 +1,15 @@ +name: Garnix +on: + push: + branches: + - main + +permissions: + contents: read + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: garnix-io/check-flake@v2 From d0040b8a0fd8c2d802c56629c643ed0d839b37bb Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 18 Jan 2025 15:48:49 +1100 Subject: [PATCH 149/213] cachix: initial config --- .github/workflows/cachix.yaml | 27 +++++++++++++++++++++++++++ .github/workflows/garnix.yml | 15 --------------- modules/home/console/tools/utils.nix | 1 + 3 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/cachix.yaml delete mode 100644 .github/workflows/garnix.yml diff --git a/.github/workflows/cachix.yaml b/.github/workflows/cachix.yaml new file mode 100644 index 0000000..b2a6897 --- /dev/null +++ b/.github/workflows/cachix.yaml @@ -0,0 +1,27 @@ +name: "cache" +on: + push: + branches: + - main +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: cachix/install-nix-action@v24 + - uses: cachix/cachix-action@v12 + with: + name: ooknet + authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' + - name: Build packages + run: | + nix build .#ook-vim \ + .#live-buds-cli \ + .#caddy-with-cloudflare \ + .#fpp-config \ + .#fpp-launcher \ + .#fpp-sd \ + .#project-plus \ + .#repomix \ + .#website \ + .#wii-u-gc-adapter diff --git a/.github/workflows/garnix.yml b/.github/workflows/garnix.yml deleted file mode 100644 index 68d75c1..0000000 --- a/.github/workflows/garnix.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Garnix -on: - push: - branches: - - main - -permissions: - contents: read - -jobs: - check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: garnix-io/check-flake@v2 diff --git a/modules/home/console/tools/utils.nix b/modules/home/console/tools/utils.nix index cbe00aa..641ab9c 100644 --- a/modules/home/console/tools/utils.nix +++ b/modules/home/console/tools/utils.nix @@ -46,6 +46,7 @@ in { libnotify # Nix tooling alejandra + cachix ; #AI From 60730c1cd2ce703aa1823bedec120824bab3b6bc Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 18 Jan 2025 17:21:27 +1100 Subject: [PATCH 150/213] nix: add ooknet cachix cache --- modules/nixos/base/nix.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/nixos/base/nix.nix b/modules/nixos/base/nix.nix index fcf15c7..e144164 100644 --- a/modules/nixos/base/nix.nix +++ b/modules/nixos/base/nix.nix @@ -53,11 +53,13 @@ in { "https://cache.nixos.org?priority=10" "https://nix-community.cachix.org" "https://neovim-flake.cachix.org" + "https://ooknet.cachix.org" ]; trusted-public-keys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" "neovim-flake.cachix.org-1:iyQ6lHFhnB5UkVpxhQqLJbneWBTzM8LBYOFPLNH4qZw=" + "ooknet.cachix.org-1:mtr4ue+8ux58b8mgTGRAG/txxHBnZvgX7Gi3amno+zs=" ]; }; }; From b8149a8beb1da08f60c2d5e637f03d7660d9c867 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 18 Jan 2025 17:21:59 +1100 Subject: [PATCH 151/213] ci: add packages path to cachix workflow --- .github/workflows/cachix.yaml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cachix.yaml b/.github/workflows/cachix.yaml index b2a6897..e330187 100644 --- a/.github/workflows/cachix.yaml +++ b/.github/workflows/cachix.yaml @@ -1,6 +1,7 @@ -name: "cache" +name: Build Packages on: push: + paths: - outputs/pkgs/* branches: - main jobs: @@ -8,13 +9,13 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v24 - - uses: cachix/cachix-action@v12 + - uses: cachix/install-nix-action@v25 + - uses: cachix/cachix-action@v14 with: name: ooknet authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - name: Build packages - run: | + run: nix build .#ook-vim \ .#live-buds-cli \ .#caddy-with-cloudflare \ From 7109d9dcf229aafdd1bd4f49ae625132245e61da Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 18 Jan 2025 17:23:58 +1100 Subject: [PATCH 152/213] ci: fix err --- .github/workflows/cachix.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cachix.yaml b/.github/workflows/cachix.yaml index e330187..4cb5e61 100644 --- a/.github/workflows/cachix.yaml +++ b/.github/workflows/cachix.yaml @@ -1,7 +1,7 @@ name: Build Packages on: push: - paths: - outputs/pkgs/* + paths: - "outputs/pkgs/*" branches: - main jobs: From c919b0461498b75c67809d1a7852d4c27219915e Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 18 Jan 2025 17:29:31 +1100 Subject: [PATCH 153/213] ci: test --- .github/workflows/cachix.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cachix.yaml b/.github/workflows/cachix.yaml index 4cb5e61..19c4afe 100644 --- a/.github/workflows/cachix.yaml +++ b/.github/workflows/cachix.yaml @@ -1,7 +1,8 @@ name: Build Packages on: push: - paths: - "outputs/pkgs/*" + paths: + - "outputs/pkgs/**" branches: - main jobs: From 4ae8e335086588ce91e2fff3807d2d26f121564b Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 18 Jan 2025 17:31:54 +1100 Subject: [PATCH 154/213] project-plus: remove useless flags --- outputs/pkgs/project-plus/default.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/outputs/pkgs/project-plus/default.nix b/outputs/pkgs/project-plus/default.nix index 5c71e32..eb756e3 100644 --- a/outputs/pkgs/project-plus/default.nix +++ b/outputs/pkgs/project-plus/default.nix @@ -136,8 +136,6 @@ in qtWrapperArgs = [ "--prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [vulkan-loader]}" "--set QT_QPA_PLATFORM xcb" - "--set QT_QPA_PLATFROMTHEME qt5ct" - "--set QT_STYLE_OVERRIDE kvantum" "--add-flags -u" "--add-flags ${toString userDir}" ]; From aaf89fc568c5da1c03e118ef517affb9d829453e Mon Sep 17 00:00:00 2001 From: ooks-io <68526158+ooks-io@users.noreply.github.com> Date: Sat, 18 Jan 2025 17:40:52 +1100 Subject: [PATCH 155/213] ci: fix ci --- .github/workflows/cachix.yaml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/cachix.yaml b/.github/workflows/cachix.yaml index 19c4afe..1c13c4f 100644 --- a/.github/workflows/cachix.yaml +++ b/.github/workflows/cachix.yaml @@ -17,13 +17,14 @@ jobs: authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - name: Build packages run: - nix build .#ook-vim \ - .#live-buds-cli \ - .#caddy-with-cloudflare \ - .#fpp-config \ - .#fpp-launcher \ - .#fpp-sd \ - .#project-plus \ - .#repomix \ - .#website \ - .#wii-u-gc-adapter + nix build \ + .#ook-vim \ + .#live-buds-cli \ + .#caddy-with-cloudflare \ + .#fpp-config \ + .#fpp-launcher \ + .#fpp-sd \ + .#project-plus \ + .#repomix \ + .#website \ + .#wii-u-gc-adapter From ccec50895900cba613130163b9214d211376683f Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 18 Jan 2025 17:43:57 +1100 Subject: [PATCH 156/213] ci: multi-line string --- .github/workflows/cachix.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cachix.yaml b/.github/workflows/cachix.yaml index 1c13c4f..b985f20 100644 --- a/.github/workflows/cachix.yaml +++ b/.github/workflows/cachix.yaml @@ -16,7 +16,7 @@ jobs: name: ooknet authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - name: Build packages - run: + run: | nix build \ .#ook-vim \ .#live-buds-cli \ From 6f3ab0b8d3306075b8276742a24b20eabb25cf24 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 18 Jan 2025 21:09:51 +1100 Subject: [PATCH 157/213] spotify-player: lower default volume and disable image --- modules/home/workstation/media/music.nix | 2 +- outputs/pkgs/default.nix | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/home/workstation/media/music.nix b/modules/home/workstation/media/music.nix index fa181b4..4b52721 100644 --- a/modules/home/workstation/media/music.nix +++ b/modules/home/workstation/media/music.nix @@ -64,7 +64,7 @@ in { device = { name = "${hostName}"; device_type = "speaker"; - volume = 100; + volume = 60; bitrate = 320; audio_cache = false; normalization = false; diff --git a/outputs/pkgs/default.nix b/outputs/pkgs/default.nix index abdead4..3a5d2cc 100644 --- a/outputs/pkgs/default.nix +++ b/outputs/pkgs/default.nix @@ -26,6 +26,7 @@ inherit (projectPlus) fpp-config fpp-launcher fpp-sd; project-plus = projectPlus.package; + spotify-player = pkgs.spotify-player.override {withImage = false;}; }; }; } From 082722b2a8a2dcc48dbc2387a76008d0b4044852 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 00:16:13 +1100 Subject: [PATCH 158/213] ci: add check and format workflows --- .github/workflows/cachix.yaml | 57 ++++++++++++++++++++++------------- .github/workflows/check.yaml | 24 +++++++++++++++ .github/workflows/format.yaml | 34 +++++++++++++++++++++ 3 files changed, 94 insertions(+), 21 deletions(-) create mode 100644 .github/workflows/check.yaml create mode 100644 .github/workflows/format.yaml diff --git a/.github/workflows/cachix.yaml b/.github/workflows/cachix.yaml index b985f20..584929e 100644 --- a/.github/workflows/cachix.yaml +++ b/.github/workflows/cachix.yaml @@ -1,30 +1,45 @@ -name: Build Packages +name: "Build packages and push to cache" on: push: paths: - - "outputs/pkgs/**" + - outputs/pkgs/** branches: - main +concurrency: + group: ooknet-cache-${{ github.ref }} + cancel-in-progress: true jobs: build: runs-on: ubuntu-latest + strategy: + matrix: + package: + - ook-vim + - live-buds-cli + - caddy-with-cloudflare + - fpp-config + - fpp-launcher + - fpp-sd + - project-plus + - repomix + - website + - wii-u-gc-adapter + - spotify-player steps: - - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v25 - - uses: cachix/cachix-action@v14 - with: - name: ooknet - authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - - name: Build packages - run: | - nix build \ - .#ook-vim \ - .#live-buds-cli \ - .#caddy-with-cloudflare \ - .#fpp-config \ - .#fpp-launcher \ - .#fpp-sd \ - .#project-plus \ - .#repomix \ - .#website \ - .#wii-u-gc-adapter + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Nix + uses: DeterminateSystems/nix-installer-action@main + - name: Magic Nix Cache + uses: DeterminateSystems/magic-nix-cache-action@main + - name: Setup Cachix + uses: cachix/cachix-action@v15 + with: + name: ooknet + authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' + extraPullNames: nix-community + - name: Check Flake + run: nix flake check + - name: Build packages + run: nix build .#${{ matrix.package }} --print-build-logs + continue-on-error: true diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml new file mode 100644 index 0000000..875d473 --- /dev/null +++ b/.github/workflows/check.yaml @@ -0,0 +1,24 @@ +name: "Nix Flake Check" +on: + push: + branches: + - main + paths-ignore: + - outputs/pkgs/** + - .github/** +concurrency: + group: ooknet-check-${{ github.ref }} + cancel-in-progress: true +jobs: + nix-flake-check: + name: Evaluate Flake + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Nix + uses: DeterminateSystems/nix-installer-action@main + - name: Magic Nix Cache + uses: DeterminateSystems/magic-nix-cache-action@main + - name: Nix Flake + run: nix flake check diff --git a/.github/workflows/format.yaml b/.github/workflows/format.yaml new file mode 100644 index 0000000..24f2b44 --- /dev/null +++ b/.github/workflows/format.yaml @@ -0,0 +1,34 @@ +name: "Format Flake" +on: + push: + branches: + - main + paths-ignore: + - .github/** + - .gitignore +jobs: + alejandra: + name: Format with Alejandra + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Nix + uses: DeterminateSystems/nix-installer-action@main + - name: Nix Magic Cache + uses: DeterminateSystems/magic-nix-cache-action@main + - name: Format Flake + run: nix run nixpkgs#alejandra -- -c . + deadnix: + name: Dead Code Analysis with Deadnix + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Nix + uses: DeterminateSystems/nix-installer-action@main + - name: Setup Deadnix + uses: cachix/cachix-action@v15 + with: + name: deadnix + - uses: astro/deadnix-action@main From 3a3e949e64d942ac7237cd52781a8cb6dc57d3c9 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 00:29:26 +1100 Subject: [PATCH 159/213] music: disable sixel for spotify --- modules/home/workstation/media/music.nix | 2 ++ outputs/pkgs/default.nix | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/home/workstation/media/music.nix b/modules/home/workstation/media/music.nix index 4b52721..b5a967f 100644 --- a/modules/home/workstation/media/music.nix +++ b/modules/home/workstation/media/music.nix @@ -4,6 +4,7 @@ config, lib, hozen, + self', ... }: let inherit (lib) mkIf getExe elem; @@ -36,6 +37,7 @@ in { programs = { spotify-player = { enable = true; + package = self'.packages.spotify-player; settings = { theme = "default"; client_id_command = "cat ${spotify_key.path}"; diff --git a/outputs/pkgs/default.nix b/outputs/pkgs/default.nix index 3a5d2cc..f33f137 100644 --- a/outputs/pkgs/default.nix +++ b/outputs/pkgs/default.nix @@ -26,7 +26,10 @@ inherit (projectPlus) fpp-config fpp-launcher fpp-sd; project-plus = projectPlus.package; - spotify-player = pkgs.spotify-player.override {withImage = false;}; + spotify-player = pkgs.spotify-player.override { + withImage = false; + withSixel = false; + }; }; }; } From 07caf5671dd1957d08b36174e0b91f1766af2dc6 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 00:29:47 +1100 Subject: [PATCH 160/213] neovim: add yaml ts grammar --- outputs/pkgs/ook-vim/config/plugins/languages/treesitter.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/outputs/pkgs/ook-vim/config/plugins/languages/treesitter.nix b/outputs/pkgs/ook-vim/config/plugins/languages/treesitter.nix index 33c3410..89c601c 100644 --- a/outputs/pkgs/ook-vim/config/plugins/languages/treesitter.nix +++ b/outputs/pkgs/ook-vim/config/plugins/languages/treesitter.nix @@ -6,6 +6,7 @@ kdl regex fish + yaml ]; }; } From b48c99ab6f3697d6659a08df6106932956309e93 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 12:29:20 +1100 Subject: [PATCH 161/213] ci: add workflow dispatch trigger --- .github/workflows/cachix.yaml | 1 + .github/workflows/check.yaml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/cachix.yaml b/.github/workflows/cachix.yaml index 584929e..ea2bdf9 100644 --- a/.github/workflows/cachix.yaml +++ b/.github/workflows/cachix.yaml @@ -1,5 +1,6 @@ name: "Build packages and push to cache" on: + workflow_dispatch: push: paths: - outputs/pkgs/** diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 875d473..9e01263 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -1,5 +1,6 @@ name: "Nix Flake Check" on: + workflow_dispatch: push: branches: - main @@ -16,6 +17,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + - name: Configure git + uses: git config --global url."https://github.com/".insteadOf "git@github.com:" - name: Setup Nix uses: DeterminateSystems/nix-installer-action@main - name: Magic Nix Cache From af10032dcb796dfbdcc6709830e89ecfbc6cd451 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 12:29:30 +1100 Subject: [PATCH 162/213] flake: remove unused input --- flake.lock | 88 ++---------------------------------------------------- flake.nix | 4 --- 2 files changed, 2 insertions(+), 90 deletions(-) diff --git a/flake.lock b/flake.lock index a5bf59a..fee1f90 100644 --- a/flake.lock +++ b/flake.lock @@ -182,24 +182,6 @@ "type": "github" } }, - "flake-parts_3": { - "inputs": { - "nixpkgs-lib": "nixpkgs-lib_3" - }, - "locked": { - "lastModified": 1726153070, - "narHash": "sha256-HO4zgY0ekfwO5bX0QH/3kJ/h4KvUDFZg8YpkNwIbg1U=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "bcef6817a8b2aa20a5a6dbb19b43e63c5bf8619a", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, "flake-utils": { "locked": { "lastModified": 1629284811, @@ -253,7 +235,7 @@ }, "flake-utils_4": { "inputs": { - "systems": "systems_8" + "systems": "systems_7" }, "locked": { "lastModified": 1731533236, @@ -913,21 +895,6 @@ "type": "github" } }, - "nix-filter": { - "locked": { - "lastModified": 1710156097, - "narHash": "sha256-1Wvk8UP7PXdf8bCCaEoMnOT1qe5/Duqgj+rL8sRQsSM=", - "owner": "numtide", - "repo": "nix-filter", - "rev": "3342559a24e85fc164b295c3444e8a139924675b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "nix-filter", - "type": "github" - } - }, "nix-index-db": { "inputs": { "nixpkgs": [ @@ -988,18 +955,6 @@ "url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz" } }, - "nixpkgs-lib_3": { - "locked": { - "lastModified": 1725233747, - "narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=", - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz" - } - }, "nixpkgs-stable": { "locked": { "lastModified": 1733423277, @@ -1274,29 +1229,6 @@ "type": "github" } }, - "ooknet-website": { - "inputs": { - "flake-parts": "flake-parts_3", - "nix-filter": "nix-filter", - "nixpkgs": [ - "nixpkgs" - ], - "systems": "systems_6" - }, - "locked": { - "lastModified": 1728305902, - "narHash": "sha256-761elKy4m30bx9+3QTlc2MGlRbESek/klbufIP75UqI=", - "ref": "refs/heads/master", - "rev": "b0ed4617e28b40e43cc286c9cd50d75d0e204668", - "revCount": 4, - "type": "git", - "url": "ssh://git@github.com/ooks-io/website" - }, - "original": { - "type": "git", - "url": "ssh://git@github.com/ooks-io/website" - } - }, "ooks-scripts": { "inputs": { "nixpkgs": [ @@ -3284,10 +3216,9 @@ "nix-index-db": "nix-index-db", "nixpkgs": "nixpkgs_3", "nvf": "nvf", - "ooknet-website": "ooknet-website", "ooks-scripts": "ooks-scripts", "secrets": "secrets", - "systems": "systems_7", + "systems": "systems_6", "vpn-confinement": "vpn-confinement", "zjstatus": "zjstatus" } @@ -3452,21 +3383,6 @@ } }, "systems_7": { - "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" - } - }, - "systems_8": { "locked": { "lastModified": 1681028828, "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", diff --git a/flake.nix b/flake.nix index 63152d2..47c66b1 100644 --- a/flake.nix +++ b/flake.nix @@ -30,10 +30,6 @@ url = "git+ssh://git@github.com/ooks-io/scripts"; inputs.nixpkgs.follows = "nixpkgs"; }; - ooknet-website = { - url = "git+ssh://git@github.com/ooks-io/website"; - inputs.nixpkgs.follows = "nixpkgs"; - }; secrets = { url = "git+ssh://git@github.com/ooks-io/kunzen"; inputs = { From 8964a0c3a3e5366e134dd9c1598c969dfc2129de Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 12:33:08 +1100 Subject: [PATCH 163/213] ci: run instead of use --- .github/workflows/cachix.yaml | 2 ++ .github/workflows/check.yaml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cachix.yaml b/.github/workflows/cachix.yaml index ea2bdf9..cd1e487 100644 --- a/.github/workflows/cachix.yaml +++ b/.github/workflows/cachix.yaml @@ -29,6 +29,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + - name: Configure git + run: git config --global url."https://github.com/".insteadOf "git@github.com:" - name: Setup Nix uses: DeterminateSystems/nix-installer-action@main - name: Magic Nix Cache diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 9e01263..d635366 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -18,7 +18,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Configure git - uses: git config --global url."https://github.com/".insteadOf "git@github.com:" + run: git config --global url."https://github.com/".insteadOf "git@github.com:" - name: Setup Nix uses: DeterminateSystems/nix-installer-action@main - name: Magic Nix Cache From c5fe176f3889dc9c435505b1fcdb345fd657f5ec Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 12:36:27 +1100 Subject: [PATCH 164/213] ci: debug private flake input --- .github/workflows/check.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index d635366..fc30185 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -18,7 +18,9 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Configure git - run: git config --global url."https://github.com/".insteadOf "git@github.com:" + run: | + git config --global url."https://github.com/".insteadOf "git@github.com:" + git config --global url."https://github.com/".insteadOf ssh://git@github.com/ - name: Setup Nix uses: DeterminateSystems/nix-installer-action@main - name: Magic Nix Cache From 2abc93421c79cd1c2c067224d86640617c023740 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 13:59:51 +1100 Subject: [PATCH 165/213] ci: test token for check --- .github/workflows/cachix.yaml | 2 -- .github/workflows/check.yaml | 8 +++----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cachix.yaml b/.github/workflows/cachix.yaml index cd1e487..ad29975 100644 --- a/.github/workflows/cachix.yaml +++ b/.github/workflows/cachix.yaml @@ -41,8 +41,6 @@ jobs: name: ooknet authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' extraPullNames: nix-community - - name: Check Flake - run: nix flake check - name: Build packages run: nix build .#${{ matrix.package }} --print-build-logs continue-on-error: true diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index fc30185..954580d 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -5,7 +5,6 @@ on: branches: - main paths-ignore: - - outputs/pkgs/** - .github/** concurrency: group: ooknet-check-${{ github.ref }} @@ -17,10 +16,9 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - name: Configure git - run: | - git config --global url."https://github.com/".insteadOf "git@github.com:" - git config --global url."https://github.com/".insteadOf ssh://git@github.com/ + with: + token: ${{ secrets.KUNZEN_TOKEN }} + submodules: true - name: Setup Nix uses: DeterminateSystems/nix-installer-action@main - name: Magic Nix Cache From 214622f76f821bdfe2563bfb1e1314597512e19b Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 14:04:54 +1100 Subject: [PATCH 166/213] flake: reduce closure --- flake.lock | 403 +++----------------- flake.nix | 56 ++- modules/home/workstation/tools/ookpower.nix | 167 +++++++- 3 files changed, 254 insertions(+), 372 deletions(-) diff --git a/flake.lock b/flake.lock index fee1f90..ae36e2d 100644 --- a/flake.lock +++ b/flake.lock @@ -3,9 +3,15 @@ "agenix": { "inputs": { "darwin": "darwin", - "home-manager": "home-manager", - "nixpkgs": "nixpkgs", - "systems": "systems" + "home-manager": [ + "home-manager" + ], + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "systems" + ] }, "locked": { "lastModified": 1723293904, @@ -130,22 +136,6 @@ "type": "github" } }, - "flake-compat_2": { - "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" - } - }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" @@ -164,24 +154,6 @@ "type": "github" } }, - "flake-parts_2": { - "inputs": { - "nixpkgs-lib": "nixpkgs-lib_2" - }, - "locked": { - "lastModified": 1733312601, - "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, "flake-utils": { "locked": { "lastModified": 1629284811, @@ -199,14 +171,16 @@ }, "flake-utils_2": { "inputs": { - "systems": "systems_2" + "systems": [ + "systems" + ] }, "locked": { - "lastModified": 1705309234, - "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -217,7 +191,7 @@ }, "flake-utils_3": { "inputs": { - "systems": "systems_4" + "systems": "systems_2" }, "locked": { "lastModified": 1731533236, @@ -233,60 +207,6 @@ "type": "github" } }, - "flake-utils_4": { - "inputs": { - "systems": "systems_7" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "ghostty": { - "inputs": { - "flake-compat": "flake-compat", - "nixpkgs-stable": "nixpkgs-stable", - "nixpkgs-unstable": "nixpkgs-unstable", - "zig": "zig" - }, - "locked": { - "lastModified": 1736115260, - "narHash": "sha256-9VrUz+JNq90Z1QOBojSxKDdUHr0I5XsK/OHjZSyvXwU=", - "owner": "ghostty-org", - "repo": "ghostty", - "rev": "2485482aecc02c6c377a30c36a34c647cc521ddf", - "type": "github" - }, - "original": { - "owner": "ghostty-org", - "repo": "ghostty", - "type": "github" - } - }, - "ghostty-hm": { - "locked": { - "lastModified": 1702368251, - "narHash": "sha256-hafrDmzGplzm+vdIo+LkOjRfA4qRcy5JmpGGksnht5c=", - "owner": "clo4", - "repo": "ghostty-hm-module", - "rev": "887e13a6e7acf5ffaab0119d96e476d84db90904", - "type": "github" - }, - "original": { - "owner": "clo4", - "repo": "ghostty-hm-module", - "type": "github" - } - }, "gitignore": { "inputs": { "nixpkgs": [ @@ -310,27 +230,6 @@ } }, "home-manager": { - "inputs": { - "nixpkgs": [ - "agenix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1703113217, - "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=", - "owner": "nix-community", - "repo": "home-manager", - "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "home-manager", - "type": "github" - } - }, - "home-manager_2": { "inputs": { "nixpkgs": [ "nixpkgs" @@ -509,9 +408,11 @@ "hyprlang": "hyprlang", "hyprutils": "hyprutils", "hyprwayland-scanner": "hyprwayland-scanner", - "nixpkgs": "nixpkgs_2", + "nixpkgs": "nixpkgs", "pre-commit-hooks": "pre-commit-hooks", - "systems": "systems_3", + "systems": [ + "systems" + ], "xdph": "xdph" }, "locked": { @@ -917,11 +818,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1703013332, - "narHash": "sha256-+tFNwMvlXLbJZXiMHqYq77z/RfmpfpiI3yjL6o/Zo9M=", + "lastModified": 1735291276, + "narHash": "sha256-NYVcA06+blsLG6wpAbSPTCyLvxD/92Hy4vlY9WxFI1M=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "54aac082a4d9bb5bbc5c4e899603abfb76a3f6d6", + "rev": "634fd46801442d760e09493a794c4f15db2d0cbb", "type": "github" }, "original": { @@ -943,35 +844,7 @@ "url": "https://github.com/NixOS/nixpkgs/archive/e9b51731911566bbf7e4895475a87fe06961de0b.tar.gz" } }, - "nixpkgs-lib_2": { - "locked": { - "lastModified": 1733096140, - "narHash": "sha256-1qRH7uAUsyQI7R1Uwl4T+XvdNv778H0Nb5njNrqvylY=", - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz" - } - }, "nixpkgs-stable": { - "locked": { - "lastModified": 1733423277, - "narHash": "sha256-TxabjxEgkNbCGFRHgM/b9yZWlBj60gUOUnRT/wbVQR8=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "e36963a147267afc055f7cf65225958633e536bf", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "release-24.11", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-stable_2": { "locked": { "lastModified": 1730741070, "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=", @@ -987,39 +860,7 @@ "type": "github" } }, - "nixpkgs-unstable": { - "locked": { - "lastModified": 1733229606, - "narHash": "sha256-FLYY5M0rpa5C2QAE3CKLYAM6TwbKicdRK6qNrSHlNrE=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "566e53c2ad750c84f6d31f9ccb9d00f823165550", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, "nixpkgs_2": { - "locked": { - "lastModified": 1735291276, - "narHash": "sha256-NYVcA06+blsLG6wpAbSPTCyLvxD/92Hy4vlY9WxFI1M=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "634fd46801442d760e09493a794c4f15db2d0cbb", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_3": { "locked": { "lastModified": 1735834308, "narHash": "sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk=", @@ -1035,7 +876,7 @@ "type": "github" } }, - "nixpkgs_4": { + "nixpkgs_3": { "locked": { "lastModified": 1656753965, "narHash": "sha256-BCrB3l0qpJokOnIVc3g2lHiGhnjUi0MoXiw6t1o8H1E=", @@ -1051,22 +892,6 @@ "type": "github" } }, - "nixpkgs_5": { - "locked": { - "lastModified": 1734435836, - "narHash": "sha256-kMBQ5PRiFLagltK0sH+08aiNt3zGERC2297iB6vrvlU=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "4989a246d7a390a859852baddb1013f825435cee", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, "nmd": { "flake": false, "locked": { @@ -1085,8 +910,12 @@ }, "nvf": { "inputs": { - "flake-parts": "flake-parts_2", - "flake-utils": "flake-utils_3", + "flake-parts": [ + "flake-parts" + ], + "flake-utils": [ + "flake-utils" + ], "mnw": "mnw", "nil": "nil", "nixpkgs": [ @@ -1213,7 +1042,9 @@ "plugin-vim-startify": "plugin-vim-startify", "plugin-which-key": "plugin-which-key", "rnix-lsp": "rnix-lsp", - "systems": "systems_5" + "systems": [ + "systems" + ] }, "locked": { "lastModified": 1736124878, @@ -1229,26 +1060,6 @@ "type": "github" } }, - "ooks-scripts": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1718496814, - "narHash": "sha256-q9OaUOdA0+bmlJ8nK11aiEjHxlJ6a9sqAdvG8CwsH8M=", - "ref": "refs/heads/main", - "rev": "53ef8a8bc986f6a3a80aa0336eb6ea8ccd6e3ae7", - "revCount": 39, - "type": "git", - "url": "ssh://git@github.com/ooks-io/scripts" - }, - "original": { - "type": "git", - "url": "ssh://git@github.com/ooks-io/scripts" - } - }, "plugin-alpha-nvim": { "flake": false, "locked": { @@ -3157,13 +2968,13 @@ }, "pre-commit-hooks": { "inputs": { - "flake-compat": "flake-compat_2", + "flake-compat": "flake-compat", "gitignore": "gitignore", "nixpkgs": [ "hyprland", "nixpkgs" ], - "nixpkgs-stable": "nixpkgs-stable_2" + "nixpkgs-stable": "nixpkgs-stable" }, "locked": { "lastModified": 1734797603, @@ -3182,7 +2993,7 @@ "rnix-lsp": { "inputs": { "naersk": "naersk", - "nixpkgs": "nixpkgs_4", + "nixpkgs": "nixpkgs_3", "utils": "utils" }, "locked": { @@ -3204,9 +3015,8 @@ "agenix": "agenix", "firefox-addons": "firefox-addons", "flake-parts": "flake-parts", - "ghostty": "ghostty", - "ghostty-hm": "ghostty-hm", - "home-manager": "home-manager_2", + "flake-utils": "flake-utils_2", + "home-manager": "home-manager", "hypridle": "hypridle", "hyprland": "hyprland", "hyprland-contrib": "hyprland-contrib", @@ -3214,12 +3024,10 @@ "hyprlock": "hyprlock", "hyprpaper": "hyprpaper", "nix-index-db": "nix-index-db", - "nixpkgs": "nixpkgs_3", + "nixpkgs": "nixpkgs_2", "nvf": "nvf", - "ooks-scripts": "ooks-scripts", "secrets": "secrets", - "systems": "systems_6", - "vpn-confinement": "vpn-confinement", + "systems": "systems", "zjstatus": "zjstatus" } }, @@ -3294,16 +3102,16 @@ }, "systems": { "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", "type": "github" }, "original": { "owner": "nix-systems", - "repo": "default", + "repo": "default-linux", "type": "github" } }, @@ -3322,81 +3130,6 @@ "type": "github" } }, - "systems_3": { - "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" - } - }, - "systems_4": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_5": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "systems_6": { - "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" - } - }, - "systems_7": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, "utils": { "locked": { "lastModified": 1656928814, @@ -3412,21 +3145,6 @@ "type": "github" } }, - "vpn-confinement": { - "locked": { - "lastModified": 1731209328, - "narHash": "sha256-b3jggBHZh20jUfBxoaIvew23czsw82zBc0aKxtkF3g8=", - "owner": "Maroka-chan", - "repo": "VPN-Confinement", - "rev": "74e6fd47804b5ca69187200efbb14cf1ecb9ea07", - "type": "github" - }, - "original": { - "owner": "Maroka-chan", - "repo": "VPN-Confinement", - "type": "github" - } - }, "xdph": { "inputs": { "hyprland-protocols": [ @@ -3468,36 +3186,13 @@ "type": "github" } }, - "zig": { - "inputs": { - "flake-compat": [ - "ghostty" - ], - "flake-utils": "flake-utils_2", - "nixpkgs": [ - "ghostty", - "nixpkgs-stable" - ] - }, - "locked": { - "lastModified": 1717848532, - "narHash": "sha256-d+xIUvSTreHl8pAmU1fnmkfDTGQYCn2Rb/zOwByxS2M=", - "owner": "mitchellh", - "repo": "zig-overlay", - "rev": "02fc5cc555fc14fda40c42d7c3250efa43812b43", - "type": "github" - }, - "original": { - "owner": "mitchellh", - "repo": "zig-overlay", - "type": "github" - } - }, "zjstatus": { "inputs": { "crane": "crane", - "flake-utils": "flake-utils_4", - "nixpkgs": "nixpkgs_5", + "flake-utils": "flake-utils_3", + "nixpkgs": [ + "nixpkgs" + ], "rust-overlay": "rust-overlay_2" }, "locked": { diff --git a/flake.nix b/flake.nix index 47c66b1..313e272 100644 --- a/flake.nix +++ b/flake.nix @@ -9,27 +9,48 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - flake-parts.url = "github:hercules-ci/flake-parts"; + + systems.url = "github:nix-systems/default-linux"; + + flake-parts = { + url = "github:hercules-ci/flake-parts"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + flake-utils = { + url = "github:numtide/flake-utils"; + inputs.systems.follows = "systems"; + }; + home-manager = { url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; - agenix.url = "github:ryantm/agenix"; + + agenix = { + url = "github:ryantm/agenix"; + inputs = { + nixpkgs.follows = "nixpkgs"; + systems.follows = "systems"; + home-manager.follows = "home-manager"; + }; + }; + nix-index-db = { url = "github:nix-community/nix-index-database"; inputs.nixpkgs.follows = "nixpkgs"; }; - zjstatus.url = "github:dj95/zjstatus"; - systems.url = "github:nix-systems/default-linux"; + + zjstatus = { + url = "github:dj95/zjstatus"; + inputs.nixpkgs.follows = "nixpkgs"; + }; firefox-addons = { url = "gitlab:rycee/nur-expressions?dir=pkgs/firefox-addons"; inputs.nixpkgs.follows = "nixpkgs"; }; - ooks-scripts = { - url = "git+ssh://git@github.com/ooks-io/scripts"; - inputs.nixpkgs.follows = "nixpkgs"; - }; + secrets = { url = "git+ssh://git@github.com/ooks-io/kunzen"; inputs = { @@ -41,17 +62,20 @@ nvf = { url = "github:notashelf/nvf"; - inputs.nixpkgs.follows = "nixpkgs"; + inputs = { + systems.follows = "systems"; + + nixpkgs.follows = "nixpkgs"; + flake-parts.follows = "flake-parts"; + flake-utils.follows = "flake-utils"; + }; }; - # confine vpns to specific systemd services - vpn-confinement.url = "github:Maroka-chan/VPN-Confinement"; - - ghostty-hm.url = "github:clo4/ghostty-hm-module"; - ghostty.url = "github:ghostty-org/ghostty"; - # hypr* ecosystem - hyprland.url = "github:hyprwm/hyprland"; + hyprland = { + url = "github:hyprwm/hyprland"; + inputs.systems.follows = "systems"; + }; hypridle = { url = "github:hyprwm/hypridle"; diff --git a/modules/home/workstation/tools/ookpower.nix b/modules/home/workstation/tools/ookpower.nix index 23903ab..b8d4850 100644 --- a/modules/home/workstation/tools/ookpower.nix +++ b/modules/home/workstation/tools/ookpower.nix @@ -1,14 +1,177 @@ { lib, config, - inputs', + pkgs, ... }: let inherit (lib) mkIf; inherit (config.programs) rofi; + + powermenu = pkgs.writeShellApplication { + name = "powermenu"; + runtimeInputs = [pkgs.rofi-wayland]; + text = + # bash + '' + + pid_file="/tmp/my_countdown.pid" + + DRY= + COUNTDOWN= + + while [ $# -gt 0 ]; do + key="$1" + case $key in + -c | --countdown) + COUNTDOWN=true + shift + ;; + -d | --dry) + DRY=true + shift + ;; + *) + break + ;; + esac + done + + notify() { + notify-send -u critical -a system-notify -t 1000 -h string:x-canonical-private-synchronous:anything "$@" + } + + # Used for development, instead of running command, notifies if command was successful and exits. + dry_success() { + if [ "$DRY" == "true" ]; then + TITLE="Action Successful:" + notify "$TITLE" "$1" + exit 0 + fi + } + + cancel() { + if [ -f "$pid_file" ]; then + # Read the process ID from the file and kill the process + kill "$(cat "$pid_file")" &>/dev/null + notify-send "Action canceled" + rm -f "$pid_file" + else + echo "No countdown to cancel." + fi + } + + countdown() { + if [ "$COUNTDOWN" == "true" ]; then + msg="''${1:-doing something}" + echo $$ >"$pid_file" + for i in {5..1}; do + notify-send "$msg in $i" -h string:x-canonical-private-synchronous:anything + sleep 1 + done + echo "Countdown done" + rm -f "$pid_file" + fi + } + + action_logout() { + countdown "Logging out" + dry_success "Logged out" + PROCESS="Hyprland|\.Hyprland-wrapp" + if pgrep -x $PROCESS >/dev/null; then + hyprctl dispatch exit 0 + sleep 2 + if pgrep -x $PROCESS; then + pkill -9 $PROCESS + fi + fi + + } + + action_poweroff() { + countdown "Shutting down" + dry_success "Shutdown" + poweroff + } + + action_lock() { + dry_success "Screen Locked" + hyprlock + } + + action_reboot() { + countdown "Rebooting" + dry_success "Reboot" + reboot + } + + action_suspend() { + countdown "Suspending" + dry_success "Suspend" + suspend + } + + action_dmenu() { + selection=$(echo -e " Reboot\n Lock\n󰍃 Logout\n󰐥 Shutdown\n󰒲 Suspend" | rofi -dmenu -i) + + case "$selection" in + "󰐥 Shutdown") action_poweroff ;; + " Reboot") action_reboot ;; + " Lock") action_lock ;; + "󰍃 Logout") action_logout ;; + "󰒲 Suspend") action_suspend ;; + *) + echo "ERROR" "Invalid option" + exit 1 + ;; + esac + } + # Check if the script is already running and decide to cancel or start countdown + if [ -f "$pid_file" ]; then + cancel + else + ACTION=''${1:-usage} + case "$ACTION" in + logout) + action_logout + ;; + poweroff) + action_poweroff + ;; + reboot) + action_reboot + ;; + lock) + action_lock + ;; + usage) + echo " Usage: powermenu [OPTION]... [ACTION usage|dmenu|logout|poweroff|reboot|lock]" + echo "" + echo "Options:" + echo " -c, --countdown Enable 5 seconds countdown before action is performed" + echo " -d, --dry Print instead of perform action debug/development" + echo "" + echo "Actions:" + echo " usage Print help information" + echo " dmenu Open menu with rofi for selecting action" + echo " logout Kills current active Hyprland session" + echo " poweroff Shut down current host" + echo " reboot Restart current host" + echo " lock Locks current session with hyprlock" + echo "" + ;; + dmenu) + action_dmenu + ;; + *) + echo "Invalid action: $ACTION (expecting: usage|logout|poweroff|reboot|lock)" + ;; + esac + fi + ''; + }; in { config = mkIf rofi.enable { - home.packages = [inputs'.ooks-scripts.packages.powermenu]; + home.packages = [powermenu]; ooknet.binds.powerMenu = "powermenu -c dmenu"; }; } From 0055bb8146971546a655b78dd49bbdaa3f277eef Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 15:59:38 +1100 Subject: [PATCH 167/213] flake: use https instead of ssh --- flake.lock | 4 ++-- flake.nix | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index ae36e2d..154622e 100644 --- a/flake.lock +++ b/flake.lock @@ -3093,11 +3093,11 @@ "rev": "dbbf390c798a14bb316681e62fe56355d9ea88f6", "revCount": 4, "type": "git", - "url": "ssh://git@github.com/ooks-io/kunzen" + "url": "https://git@github.com/ooks-io/kunzen" }, "original": { "type": "git", - "url": "ssh://git@github.com/ooks-io/kunzen" + "url": "https://git@github.com/ooks-io/kunzen" } }, "systems": { diff --git a/flake.nix b/flake.nix index 313e272..adbcbd4 100644 --- a/flake.nix +++ b/flake.nix @@ -14,7 +14,6 @@ flake-parts = { url = "github:hercules-ci/flake-parts"; - inputs.nixpkgs.follows = "nixpkgs"; }; flake-utils = { @@ -52,7 +51,7 @@ }; secrets = { - url = "git+ssh://git@github.com/ooks-io/kunzen"; + url = "git+https://git@github.com/ooks-io/kunzen"; inputs = { nixpkgs.follows = "nixpkgs"; flake-parts.follows = "flake-parts"; From 73315712409a1366c559f05a42c1b37f4332289c Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 16:06:13 +1100 Subject: [PATCH 168/213] ci: try https --- .github/workflows/check.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 954580d..b1103d6 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -19,6 +19,10 @@ jobs: with: token: ${{ secrets.KUNZEN_TOKEN }} submodules: true + - name: Configure Git + run: | + git config --global url."https://${{ secrets.GH_TOKEN }}@github.com/".insteadOf git@github.com: + git config --global url."https://${{ secrets.GH_TOKEN }}@github.com/".insteadOf ssh://git@github.com/ - name: Setup Nix uses: DeterminateSystems/nix-installer-action@main - name: Magic Nix Cache From bdf2b6d5eaa386db95685ea91ade0424785691eb Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 16:55:54 +1100 Subject: [PATCH 169/213] ci: use kunzen token --- .github/workflows/check.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index b1103d6..f73a624 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -11,7 +11,7 @@ concurrency: cancel-in-progress: true jobs: nix-flake-check: - name: Evaluate Flake + name: Check Flake runs-on: ubuntu-latest steps: - name: Checkout @@ -21,8 +21,8 @@ jobs: submodules: true - name: Configure Git run: | - git config --global url."https://${{ secrets.GH_TOKEN }}@github.com/".insteadOf git@github.com: - git config --global url."https://${{ secrets.GH_TOKEN }}@github.com/".insteadOf ssh://git@github.com/ + git config --global url."https://${{ secrets.KUNZEN_TOKEN }}@github.com/".insteadOf git@github.com: + git config --global url."https://${{ secrets.KUNZEN_TOKEN }}@github.com/".insteadOf ssh://git@github.com/ - name: Setup Nix uses: DeterminateSystems/nix-installer-action@main - name: Magic Nix Cache From 4e1310c367efcd15587bf4975528a0c8667c4b59 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 17:02:30 +1100 Subject: [PATCH 170/213] ci: try with determinate systems github-token --- .github/workflows/check.yaml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index f73a624..1144aa3 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -16,15 +16,10 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - token: ${{ secrets.KUNZEN_TOKEN }} - submodules: true - - name: Configure Git - run: | - git config --global url."https://${{ secrets.KUNZEN_TOKEN }}@github.com/".insteadOf git@github.com: - git config --global url."https://${{ secrets.KUNZEN_TOKEN }}@github.com/".insteadOf ssh://git@github.com/ - name: Setup Nix uses: DeterminateSystems/nix-installer-action@main + with: + github-token: ${{ secrets.KUNZEN_TOKEN }} - name: Magic Nix Cache uses: DeterminateSystems/magic-nix-cache-action@main - name: Nix Flake From bc64202040b85e180cd399ab84080f4dd1c7577d Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 17:06:16 +1100 Subject: [PATCH 171/213] flake: kunzen allRefs --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index adbcbd4..e41b9f8 100644 --- a/flake.nix +++ b/flake.nix @@ -52,6 +52,7 @@ secrets = { url = "git+https://git@github.com/ooks-io/kunzen"; + allRefs = true; inputs = { nixpkgs.follows = "nixpkgs"; flake-parts.follows = "flake-parts"; From b940df6af713233c1ec22ea5bd20fc1150eb29a2 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 21:58:06 +1100 Subject: [PATCH 172/213] ci: use github app --- .github/workflows/check.yaml | 17 +++++++++++++++-- flake.lock | 4 ++-- flake.nix | 3 +-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 1144aa3..c7d50b3 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -16,11 +16,24 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + + - name: Generate GitHub App Token + id: generate-token + uses: actions/create-github-app-token@v1 + with: + app_id: ${{ vars.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + repositories: + + - name: Setup Git Config + run: | + git config --global url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/".insteadOf "git+ssh://git@github.com/" + - name: Setup Nix uses: DeterminateSystems/nix-installer-action@main - with: - github-token: ${{ secrets.KUNZEN_TOKEN }} + - name: Magic Nix Cache uses: DeterminateSystems/magic-nix-cache-action@main + - name: Nix Flake run: nix flake check diff --git a/flake.lock b/flake.lock index 154622e..ae36e2d 100644 --- a/flake.lock +++ b/flake.lock @@ -3093,11 +3093,11 @@ "rev": "dbbf390c798a14bb316681e62fe56355d9ea88f6", "revCount": 4, "type": "git", - "url": "https://git@github.com/ooks-io/kunzen" + "url": "ssh://git@github.com/ooks-io/kunzen" }, "original": { "type": "git", - "url": "https://git@github.com/ooks-io/kunzen" + "url": "ssh://git@github.com/ooks-io/kunzen" } }, "systems": { diff --git a/flake.nix b/flake.nix index e41b9f8..0034cd4 100644 --- a/flake.nix +++ b/flake.nix @@ -51,8 +51,7 @@ }; secrets = { - url = "git+https://git@github.com/ooks-io/kunzen"; - allRefs = true; + url = "git+ssh://git@github.com/ooks-io/kunzen"; inputs = { nixpkgs.follows = "nixpkgs"; flake-parts.follows = "flake-parts"; From e0fc5903cd55ae713f784a3d514cef9f45f3897e Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 22:00:37 +1100 Subject: [PATCH 173/213] ci: app_id -> app-id --- .github/workflows/check.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index c7d50b3..3418066 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -21,13 +21,13 @@ jobs: id: generate-token uses: actions/create-github-app-token@v1 with: - app_id: ${{ vars.APP_ID }} - private_key: ${{ secrets.APP_PRIVATE_KEY }} + app-id: ${{ vars.APP_ID }} # Updated input name + private-key: ${{ secrets.APP_PRIVATE_KEY }} # Updated input name repositories: - name: Setup Git Config run: | - git config --global url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/".insteadOf "git+ssh://git@github.com/" + git config --global url."https://x-access-token:${{ steps.generate-token.outputs.token }}@github.com/".insteadOf "git+ssh://git@github.com/" - name: Setup Nix uses: DeterminateSystems/nix-installer-action@main From 7f3ee1d335e88a1fa2bcc9a7cb2ee426d8d2c35d Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 22:09:23 +1100 Subject: [PATCH 174/213] ci: debug private key --- .github/workflows/check.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 3418066..baa49fd 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -18,16 +18,16 @@ jobs: uses: actions/checkout@v4 - name: Generate GitHub App Token - id: generate-token - uses: actions/create-github-app-token@v1 + id: app-token + uses: actions/create-github-app-token@v1 with: - app-id: ${{ vars.APP_ID }} # Updated input name - private-key: ${{ secrets.APP_PRIVATE_KEY }} # Updated input name - repositories: + app-id: ${{ vars.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + owner: ooks-io - name: Setup Git Config run: | - git config --global url."https://x-access-token:${{ steps.generate-token.outputs.token }}@github.com/".insteadOf "git+ssh://git@github.com/" + git config --global url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/".insteadOf "git+ssh://git@github.com/" - name: Setup Nix uses: DeterminateSystems/nix-installer-action@main From 475fe7769cb321b3357a88a95957955ed6a0c0a4 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 22:14:20 +1100 Subject: [PATCH 175/213] ci: add some git debug output --- .github/workflows/check.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index baa49fd..a0cb19d 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -27,8 +27,13 @@ jobs: - name: Setup Git Config run: | + git config --global url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/".insteadOf "git@github.com:" + git config --global url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/".insteadOf "ssh://git@github.com/" git config --global url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/".insteadOf "git+ssh://git@github.com/" + git config --global --list + + git ls-remote https://github.com/ooks-io/kunzen.git - name: Setup Nix uses: DeterminateSystems/nix-installer-action@main From dee0d03fadbbc29cffca0e36b4ac6fbb567e9fe9 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 22:19:40 +1100 Subject: [PATCH 176/213] ci: add kunzen repo --- .github/workflows/check.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index a0cb19d..ed7a970 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -24,6 +24,7 @@ jobs: app-id: ${{ vars.APP_ID }} private-key: ${{ secrets.APP_PRIVATE_KEY }} owner: ooks-io + repositories: kunzen - name: Setup Git Config run: | From 9f296a42cd6c1397efea9588773294dff14a03e8 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 23:02:14 +1100 Subject: [PATCH 177/213] ci: use ssh for check --- .github/workflows/check.yaml | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index ed7a970..1c5f22e 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -17,24 +17,13 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Generate GitHub App Token - id: app-token - uses: actions/create-github-app-token@v1 + - name: Setup SSH + uses: webfactory/ssh-agent@v0.9.0 with: - app-id: ${{ vars.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - owner: ooks-io - repositories: kunzen + ssh-private-key: | + ${{ secrets.OOKNET_DEPLOY_KEY }} + ${{ secrets.KUNZEN_DEPLOY_KEY }} - - name: Setup Git Config - run: | - git config --global url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/".insteadOf "git@github.com:" - git config --global url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/".insteadOf "ssh://git@github.com/" - git config --global url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/".insteadOf "git+ssh://git@github.com/" - - git config --global --list - - git ls-remote https://github.com/ooks-io/kunzen.git - name: Setup Nix uses: DeterminateSystems/nix-installer-action@main From fcc280a41a6e69f48edbc54668811bfe4b3e9078 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 19 Jan 2025 23:38:26 +1100 Subject: [PATCH 178/213] ci: just use kunzen key --- .github/workflows/check.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 1c5f22e..b35a02f 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -17,12 +17,11 @@ jobs: - name: Checkout uses: actions/checkout@v4 + # Get access to kunzen - name: Setup SSH uses: webfactory/ssh-agent@v0.9.0 with: - ssh-private-key: | - ${{ secrets.OOKNET_DEPLOY_KEY }} - ${{ secrets.KUNZEN_DEPLOY_KEY }} + ssh-private-key: ${{ secrets.KUNZEN_DEPLOY_KEY }} - name: Setup Nix uses: DeterminateSystems/nix-installer-action@main From 6c644b8a809f9ca0ce90d48d09ba466f583503bb Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 20 Jan 2025 11:17:12 +1100 Subject: [PATCH 179/213] deadnix --- modules/home/base/home-manager.nix | 1 - modules/home/workstation/hyprland/components/hyprlock.nix | 3 +-- modules/home/workstation/hyprland/settings/appearance.nix | 1 - modules/nixos/base/admin.nix | 1 - modules/nixos/base/distributed-builds.nix | 1 - modules/nixos/hardware/features/video.nix | 1 - modules/nixos/server/services/ookflix/lib.nix | 2 +- modules/nixos/server/services/ookflix/networking/networks.nix | 1 - outputs/images.nix | 4 +--- outputs/pkgs/ook-vim/modules/plugins/theme/config.nix | 1 - outputs/pkgs/repomix/default.nix | 1 - outputs/pkgs/wallpapers/generated-wallpaper.nix | 4 ---- 12 files changed, 3 insertions(+), 18 deletions(-) diff --git a/modules/home/base/home-manager.nix b/modules/home/base/home-manager.nix index 45d90c6..5431cc6 100644 --- a/modules/home/base/home-manager.nix +++ b/modules/home/base/home-manager.nix @@ -1,5 +1,4 @@ { - lib, config, osConfig, ... diff --git a/modules/home/workstation/hyprland/components/hyprlock.nix b/modules/home/workstation/hyprland/components/hyprlock.nix index 4a30552..d829761 100644 --- a/modules/home/workstation/hyprland/components/hyprlock.nix +++ b/modules/home/workstation/hyprland/components/hyprlock.nix @@ -5,8 +5,7 @@ hozen, ... }: let - inherit (osConfig.ooknet.appearance) colorscheme fonts; - inherit (colorscheme) palette; + inherit (osConfig.ooknet.appearance) fonts; inherit (osConfig.ooknet.workstation) environment; inherit (hozen) color; inherit (lib) mkIf; diff --git a/modules/home/workstation/hyprland/settings/appearance.nix b/modules/home/workstation/hyprland/settings/appearance.nix index b2ef821..9d46ed5 100644 --- a/modules/home/workstation/hyprland/settings/appearance.nix +++ b/modules/home/workstation/hyprland/settings/appearance.nix @@ -1,7 +1,6 @@ { osConfig, hozen, - inputs', ... }: let inherit (osConfig.ooknet.appearance) cursor; diff --git a/modules/nixos/base/admin.nix b/modules/nixos/base/admin.nix index 64bf329..4a4e122 100644 --- a/modules/nixos/base/admin.nix +++ b/modules/nixos/base/admin.nix @@ -1,5 +1,4 @@ { - lib, config, pkgs, keys, diff --git a/modules/nixos/base/distributed-builds.nix b/modules/nixos/base/distributed-builds.nix index 88311fc..7b469d4 100644 --- a/modules/nixos/base/distributed-builds.nix +++ b/modules/nixos/base/distributed-builds.nix @@ -2,7 +2,6 @@ keys, config, lib, - self, ... }: let inherit (lib) mkIf; diff --git a/modules/nixos/hardware/features/video.nix b/modules/nixos/hardware/features/video.nix index 5740b99..05a1ed2 100644 --- a/modules/nixos/hardware/features/video.nix +++ b/modules/nixos/hardware/features/video.nix @@ -1,7 +1,6 @@ { lib, config, - pkgs, ... }: let inherit (lib) mkIf; diff --git a/modules/nixos/server/services/ookflix/lib.nix b/modules/nixos/server/services/ookflix/lib.nix index 785fef7..77d0c2e 100644 --- a/modules/nixos/server/services/ookflix/lib.nix +++ b/modules/nixos/server/services/ookflix/lib.nix @@ -140,7 +140,7 @@ }; }; - mkNetworkService = name: network: + mkNetworkService = name: _network: nameValuePair "podman-network-${name}" { description = "Podman network ${name} for ookflix"; serviceConfig = { diff --git a/modules/nixos/server/services/ookflix/networking/networks.nix b/modules/nixos/server/services/ookflix/networking/networks.nix index 3c99bf1..582c0be 100644 --- a/modules/nixos/server/services/ookflix/networking/networks.nix +++ b/modules/nixos/server/services/ookflix/networking/networks.nix @@ -1,7 +1,6 @@ { lib, config, - pkgs, ... }: let inherit (lib) mkIf getExe; diff --git a/outputs/images.nix b/outputs/images.nix index 40293f8..3b20e5e 100644 --- a/outputs/images.nix +++ b/outputs/images.nix @@ -2,9 +2,7 @@ ook, self, ... -}: let - inherit (ook.lib.builders) mkImage; -in { +}: { flake.images = { ooknode = self.nixosConfigurations.ooknode.config.system.build.image; }; diff --git a/outputs/pkgs/ook-vim/modules/plugins/theme/config.nix b/outputs/pkgs/ook-vim/modules/plugins/theme/config.nix index ef7872a..07196cf 100644 --- a/outputs/pkgs/ook-vim/modules/plugins/theme/config.nix +++ b/outputs/pkgs/ook-vim/modules/plugins/theme/config.nix @@ -5,7 +5,6 @@ ... }: let inherit (lib) mkIf; - inherit (lib.nvim.dag) entryBefore; inherit (lib.nvim.lua) toLuaObject; cfg = config.vim.theme.custom; diff --git a/outputs/pkgs/repomix/default.nix b/outputs/pkgs/repomix/default.nix index 7ff9f30..459bd53 100644 --- a/outputs/pkgs/repomix/default.nix +++ b/outputs/pkgs/repomix/default.nix @@ -1,5 +1,4 @@ { - lib, buildNpmPackage, fetchFromGitHub, }: diff --git a/outputs/pkgs/wallpapers/generated-wallpaper.nix b/outputs/pkgs/wallpapers/generated-wallpaper.nix index b8c994b..1d23a3c 100644 --- a/outputs/pkgs/wallpapers/generated-wallpaper.nix +++ b/outputs/pkgs/wallpapers/generated-wallpaper.nix @@ -11,10 +11,6 @@ in { width ? largestWidth, height ? largestHeight, - logoScale ? 4, - backgroundColor ? colorscheme.palette.mantle, - logoColor1 ? colorscheme.palette.yellow, - logoColor2 ? colorscheme.palette.green, }: pkgs.stdenv.mkDerivation { name = "generated-nix-wallpaper-${colorscheme.slug}.png"; From 0ecc1cbf402c08df37c48d30571771e33b212548 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 20 Jan 2025 11:29:49 +1100 Subject: [PATCH 180/213] alejandra --- outputs/lib/icon/mkLogo.nix | 122 ------------------------------------ outputs/lib/icon/utils.nix | 16 ----- 2 files changed, 138 deletions(-) delete mode 100644 outputs/lib/icon/mkLogo.nix delete mode 100644 outputs/lib/icon/utils.nix diff --git a/outputs/lib/icon/mkLogo.nix b/outputs/lib/icon/mkLogo.nix deleted file mode 100644 index 2fb7303..0000000 --- a/outputs/lib/icon/mkLogo.nix +++ /dev/null @@ -1,122 +0,0 @@ -{ - lib, - pkgs, - hozen, - ... -}: let - inherit (lib) makeExtensible; - inherit (hozen) color; -in - makeExtensible (self: { - # Base logo derivation - mkLogo = { - name ? "ooknet-logo", - width ? 512, - height ? 512, - dark ? color.neutrals."800", - mid ? color.neutrals."650", - light ? color.neutrals."550", - shadow ? color.neutrals."700", - highlight ? color.neutrals."300", - }: - pkgs.stdenv.mkDerivation { - inherit name width height; - - # Use your SVG content here - src = pkgs.writeTextFile { - name = "logo.svg"; - text = - /* - html - */ - '' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ''; - }; - - nativeBuildInputs = [pkgs.inkscape]; - - # Proper build phases - buildPhase = '' - # Ensure output directory exists - mkdir -p $out/share/icons - - # Convert SVG to PNG - inkscape --export-type="png" \ - --export-filename="$out/share/icons/${name}.png" \ - --export-width=${toString width} \ - --export-height=${toString height} \ - $src - - # Also keep the SVG - cp $src "$out/share/icons/${name}.svg" - ''; - - # Meta information is always good practice - meta = { - description = "OokNet Logo"; - mainProgram = name; - }; - }; - - # Wallpaper derivation that uses the logo - mkWallpaper = { - width, - height, - logo ? self.mkLogo {}, - backgroundColor ? "282828", - }: - pkgs.stdenv.mkDerivation { - name = "ooknet-wallpaper"; - - buildInputs = [pkgs.imagemagick]; - - buildPhase = '' - # Create background - convert -size ${toString width}x${toString height} \ - xc:#${backgroundColor} \ - background.png - - # Composite logo onto center of background - composite -gravity center \ - ${logo}/share/icons/*.png \ - background.png \ - $out - ''; - }; - }) diff --git a/outputs/lib/icon/utils.nix b/outputs/lib/icon/utils.nix deleted file mode 100644 index 57ac62c..0000000 --- a/outputs/lib/icon/utils.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ - lib, - pkgs, - ... -}: let - inherit (lib) concatStrings; - - mkIcon = { - svg, - colors, {}, - height ? 24, - width ? 24 - }: let - - in - in From d3d0ae8fcbb4911dae768b41b4fb10bced4dac6e Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 20 Jan 2025 20:57:53 +1100 Subject: [PATCH 181/213] refactor: move secrets off-shore --- flake.lock | 237 ++++++++++++++++-- flake.nix | 9 - modules/nixos/base/admin.nix | 2 +- modules/nixos/base/default.nix | 1 - modules/nixos/base/distributed-builds.nix | 2 +- modules/nixos/base/nix.nix | 1 - modules/nixos/base/secrets.nix | 43 ---- modules/nixos/server/services/ookflix/lib.nix | 10 +- .../services/ookflix/networking/gluetun.nix | 3 +- .../services/ookflix/networking/traefik.nix | 3 +- outputs/default.nix | 1 - outputs/images.nix | 6 +- outputs/keys.nix | 6 - outputs/lib/builders.nix | 10 +- secrets/containers/cf_creds.age | 19 -- secrets/containers/vpn_env.age | Bin 1158 -> 0 bytes secrets/github_key.age | Bin 1260 -> 0 bytes secrets/keys.nix | 28 --- secrets/mullvad_wg.age | Bin 1232 -> 0 bytes secrets/ooknet_org.age | Bin 1259 -> 0 bytes secrets/secrets.nix | 12 - secrets/spotify_key.age | 17 -- secrets/tailscale-auth.age | Bin 934 -> 0 bytes 23 files changed, 231 insertions(+), 179 deletions(-) delete mode 100644 modules/nixos/base/secrets.nix delete mode 100644 outputs/keys.nix delete mode 100644 secrets/containers/cf_creds.age delete mode 100644 secrets/containers/vpn_env.age delete mode 100644 secrets/github_key.age delete mode 100644 secrets/keys.nix delete mode 100644 secrets/mullvad_wg.age delete mode 100644 secrets/ooknet_org.age delete mode 100644 secrets/secrets.nix delete mode 100644 secrets/spotify_key.age delete mode 100644 secrets/tailscale-auth.age diff --git a/flake.lock b/flake.lock index ae36e2d..b282215 100644 --- a/flake.lock +++ b/flake.lock @@ -3,22 +3,19 @@ "agenix": { "inputs": { "darwin": "darwin", - "home-manager": [ - "home-manager" - ], + "home-manager": "home-manager_2", "nixpkgs": [ + "secrets", "nixpkgs" ], - "systems": [ - "systems" - ] + "systems": "systems" }, "locked": { - "lastModified": 1723293904, - "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=", + "lastModified": 1736955230, + "narHash": "sha256-uenf8fv2eG5bKM8C/UvFaiJMZ4IpUFaQxk9OH5t/1gA=", "owner": "ryantm", "repo": "agenix", - "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41", + "rev": "e600439ec4c273cf11e06fe4d9d906fb98fa097c", "type": "github" }, "original": { @@ -27,6 +24,28 @@ "type": "github" } }, + "agenix-rekey": { + "inputs": { + "devshell": "devshell", + "flake-parts": "flake-parts_2", + "nixpkgs": "nixpkgs_4", + "pre-commit-hooks": "pre-commit-hooks_2", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1737124467, + "narHash": "sha256-askwM5GDYo4xy/UARNXUvn7lKERyNp31BcES/t4Ki2Y=", + "owner": "oddlama", + "repo": "agenix-rekey", + "rev": "27c5fc5b763321054832d0c96a9259d849b2f58a", + "type": "github" + }, + "original": { + "owner": "oddlama", + "repo": "agenix-rekey", + "type": "github" + } + }, "aquamarine": { "inputs": { "hyprutils": [ @@ -78,6 +97,7 @@ "darwin": { "inputs": { "nixpkgs": [ + "secrets", "agenix", "nixpkgs" ] @@ -97,6 +117,28 @@ "type": "github" } }, + "devshell": { + "inputs": { + "nixpkgs": [ + "secrets", + "agenix-rekey", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1728330715, + "narHash": "sha256-xRJ2nPOXb//u1jaBnDP56M7v5ldavjbtR6lfGqSvcKg=", + "owner": "numtide", + "repo": "devshell", + "rev": "dd6b80932022cea34a019e2bb32f6fa9e494dfef", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, "firefox-addons": { "inputs": { "flake-utils": "flake-utils", @@ -136,6 +178,22 @@ "type": "github" } }, + "flake-compat_2": { + "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" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" @@ -154,6 +212,28 @@ "type": "github" } }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "secrets", + "agenix-rekey", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733312601, + "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, "flake-utils": { "locked": { "lastModified": 1629284811, @@ -191,7 +271,7 @@ }, "flake-utils_3": { "inputs": { - "systems": "systems_2" + "systems": "systems_3" }, "locked": { "lastModified": 1731533236, @@ -229,6 +309,29 @@ "type": "github" } }, + "gitignore_2": { + "inputs": { + "nixpkgs": [ + "secrets", + "agenix-rekey", + "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": [ @@ -249,6 +352,28 @@ "type": "github" } }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "secrets", + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1703113217, + "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, "hyprcursor": { "inputs": { "hyprlang": [ @@ -892,6 +1017,22 @@ "type": "github" } }, + "nixpkgs_4": { + "locked": { + "lastModified": 1735471104, + "narHash": "sha256-0q9NGQySwDQc7RhAV2ukfnu7Gxa5/ybJ2ANT8DQrQrs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "88195a94f390381c6afcdaa933c2f6ff93959cb4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "nmd": { "flake": false, "locked": { @@ -2990,6 +3131,30 @@ "type": "github" } }, + "pre-commit-hooks_2": { + "inputs": { + "flake-compat": "flake-compat_2", + "gitignore": "gitignore_2", + "nixpkgs": [ + "secrets", + "agenix-rekey", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1735882644, + "narHash": "sha256-3FZAG+pGt3OElQjesCAWeMkQ7C/nB1oTHLRQ8ceP110=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "a5a961387e75ae44cc20f0a57ae463da5e959656", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, "rnix-lsp": { "inputs": { "naersk": "naersk", @@ -3012,7 +3177,6 @@ }, "root": { "inputs": { - "agenix": "agenix", "firefox-addons": "firefox-addons", "flake-parts": "flake-parts", "flake-utils": "flake-utils_2", @@ -3027,7 +3191,7 @@ "nixpkgs": "nixpkgs_2", "nvf": "nvf", "secrets": "secrets", - "systems": "systems", + "systems": "systems_2", "zjstatus": "zjstatus" } }, @@ -3076,6 +3240,8 @@ }, "secrets": { "inputs": { + "agenix": "agenix", + "agenix-rekey": "agenix-rekey", "flake-parts": [ "flake-parts" ], @@ -3087,11 +3253,11 @@ ] }, "locked": { - "lastModified": 1737094724, - "narHash": "sha256-PeNJWuk+zNrqCsrSbElfFmMP+R5E0uFaAgW9tWG03ag=", + "lastModified": 1737363899, + "narHash": "sha256-9W7+5Mx2J60I/s6mgq6iRcxIV06nrBr6KWzN55GWnYE=", "ref": "refs/heads/master", - "rev": "dbbf390c798a14bb316681e62fe56355d9ea88f6", - "revCount": 4, + "rev": "ec8227f9dacaef659249df279d6fd98776ebaeb6", + "revCount": 25, "type": "git", "url": "ssh://git@github.com/ooks-io/kunzen" }, @@ -3101,6 +3267,21 @@ } }, "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { "locked": { "lastModified": 1689347949, "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", @@ -3115,7 +3296,7 @@ "type": "github" } }, - "systems_2": { + "systems_3": { "locked": { "lastModified": 1681028828, "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", @@ -3130,6 +3311,28 @@ "type": "github" } }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "secrets", + "agenix-rekey", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1735135567, + "narHash": "sha256-8T3K5amndEavxnludPyfj3Z1IkcFdRpR23q+T0BVeZE=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "9e09d30a644c57257715902efbb3adc56c79cf28", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, "utils": { "locked": { "lastModified": 1656928814, diff --git a/flake.nix b/flake.nix index 0034cd4..176273c 100644 --- a/flake.nix +++ b/flake.nix @@ -26,15 +26,6 @@ inputs.nixpkgs.follows = "nixpkgs"; }; - agenix = { - url = "github:ryantm/agenix"; - inputs = { - nixpkgs.follows = "nixpkgs"; - systems.follows = "systems"; - home-manager.follows = "home-manager"; - }; - }; - nix-index-db = { url = "github:nix-community/nix-index-database"; inputs.nixpkgs.follows = "nixpkgs"; diff --git a/modules/nixos/base/admin.nix b/modules/nixos/base/admin.nix index 4a4e122..f3c5a61 100644 --- a/modules/nixos/base/admin.nix +++ b/modules/nixos/base/admin.nix @@ -1,10 +1,10 @@ { config, pkgs, - keys, ... }: let inherit (config.ooknet.host) admin; + inherit (config.ooknet.secrets) keys; ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups; in { diff --git a/modules/nixos/base/default.nix b/modules/nixos/base/default.nix index 018ada6..ca1e4eb 100644 --- a/modules/nixos/base/default.nix +++ b/modules/nixos/base/default.nix @@ -7,7 +7,6 @@ ./admin.nix ./locale.nix ./options.nix - ./secrets.nix ./openssh.nix ./tailscale.nix ./networking.nix diff --git a/modules/nixos/base/distributed-builds.nix b/modules/nixos/base/distributed-builds.nix index 7b469d4..b125c8f 100644 --- a/modules/nixos/base/distributed-builds.nix +++ b/modules/nixos/base/distributed-builds.nix @@ -1,5 +1,4 @@ { - keys, config, lib, ... @@ -7,6 +6,7 @@ inherit (lib) mkIf; inherit (config.ooknet.host) admin; inherit (config.networking) hostName; + inherit (config.ooknet.secrets) keys; mkBuilderMachine = { host, diff --git a/modules/nixos/base/nix.nix b/modules/nixos/base/nix.nix index e144164..e83f449 100644 --- a/modules/nixos/base/nix.nix +++ b/modules/nixos/base/nix.nix @@ -23,7 +23,6 @@ in { defaultPackages = []; systemPackages = attrValues { inherit (pkgs) git deadnix statix; - inherit (inputs'.agenix.packages) default; }; # location of the configuration flake diff --git a/modules/nixos/base/secrets.nix b/modules/nixos/base/secrets.nix deleted file mode 100644 index 8de6673..0000000 --- a/modules/nixos/base/secrets.nix +++ /dev/null @@ -1,43 +0,0 @@ -{ - config, - lib, - self, - ... -}: let - inherit (lib) mkIf; - - inherit (config.ooknet) host; - inherit (host) admin; - inherit (config.services) tailscale transmission; -in { - age.identityPaths = [ - "/home/${admin.name}/.ssh/id_ed25519" - ]; - - age.secrets = { - tailscale-auth = mkIf tailscale.enable { - file = "${self}/secrets/tailscale-auth.age"; - mode = "444"; - }; - github_key = mkIf admin.homeManager { - file = "${self}/secrets/github_key.age"; - path = "/home/${admin.name}/.ssh/github_key"; - owner = "${admin.name}"; - group = "users"; - }; - ooknet_org = mkIf admin.homeManager { - file = "${self}/secrets/ooknet_org.age"; - path = "/home/${admin.name}/.ssh/ooknet_org"; - owner = "${admin.name}"; - group = "users"; - }; - spotify_key = mkIf admin.homeManager { - file = "${self}/secrets/spotify_key.age"; - owner = "${admin.name}"; - group = "users"; - }; - "mullvad_wg.conf" = mkIf transmission.enable { - file = "${self}/secrets/mullvad_wg.age"; - }; - }; -} diff --git a/modules/nixos/server/services/ookflix/lib.nix b/modules/nixos/server/services/ookflix/lib.nix index 77d0c2e..3cd0adb 100644 --- a/modules/nixos/server/services/ookflix/lib.nix +++ b/modules/nixos/server/services/ookflix/lib.nix @@ -132,14 +132,6 @@ }; }; - mkServiceSecret = name: service: { - ${name} = { - file = "${self}/secrets/containers/${name}.age"; - owner = cfg.services.${service}.user.name; - group = cfg.services.${service}.group.name; - }; - }; - mkNetworkService = name: _network: nameValuePair "podman-network-${name}" { description = "Podman network ${name} for ookflix"; @@ -151,5 +143,5 @@ }; }; in { - inherit mkServiceStateFile mkServiceSecret mkBasicServiceOptions mkServiceOptions mkServiceStateDir mkServiceUser mkUserOption mkPortOption mkGroupOption mkVolumeOption mkSubdomainOption mkNetworkService; + inherit mkServiceStateFile mkBasicServiceOptions mkServiceOptions mkServiceStateDir mkServiceUser mkUserOption mkPortOption mkGroupOption mkVolumeOption mkSubdomainOption mkNetworkService; } diff --git a/modules/nixos/server/services/ookflix/networking/gluetun.nix b/modules/nixos/server/services/ookflix/networking/gluetun.nix index 4131a93..91f500e 100644 --- a/modules/nixos/server/services/ookflix/networking/gluetun.nix +++ b/modules/nixos/server/services/ookflix/networking/gluetun.nix @@ -6,14 +6,13 @@ ... }: let ookflixLib = import ../lib.nix {inherit self lib config;}; - inherit (ookflixLib) mkServiceUser mkServiceSecret; + inherit (ookflixLib) mkServiceUser; inherit (lib) mkIf; inherit (ook.lib.container) mkContainerEnvironment; inherit (config.ooknet.server.ookflix.services) qbittorrent gluetun; in { config = mkIf gluetun.enable { users = mkServiceUser gluetun.user.name; - age.secrets = mkServiceSecret "vpn_env" "gluetun"; virtualisation.oci-containers.containers = { # vpn container gluetun = mkIf gluetun.enable { diff --git a/modules/nixos/server/services/ookflix/networking/traefik.nix b/modules/nixos/server/services/ookflix/networking/traefik.nix index 2adae8c..c976e7e 100644 --- a/modules/nixos/server/services/ookflix/networking/traefik.nix +++ b/modules/nixos/server/services/ookflix/networking/traefik.nix @@ -6,7 +6,7 @@ ... }: let ookflixLib = import ../lib.nix {inherit self lib config;}; - inherit (ookflixLib) mkServiceUser mkServiceSecret mkServiceStateDir mkServiceStateFile; + inherit (ookflixLib) mkServiceUser mkServiceStateDir mkServiceStateFile; inherit (lib) mkIf; inherit (ook.lib.container) mkContainerEnvironment mkContainerLabel mkContainerPort; inherit (config.ooknet) server; @@ -19,7 +19,6 @@ in { traefikStateDir = mkServiceStateDir "traefik"; traefikAcmeFile = mkServiceStateFile "traefik" "acme.json"; }; - age.secrets = mkServiceSecret "cf_creds" "traefik"; virtualisation.oci-containers.containers = { # vpn container traefik = mkIf traefik.enable { diff --git a/outputs/default.nix b/outputs/default.nix index 2a45066..8104347 100644 --- a/outputs/default.nix +++ b/outputs/default.nix @@ -4,7 +4,6 @@ ./lib ./hozen ./hosts - ./keys.nix ./pkgs ./images.nix ./devshells diff --git a/outputs/images.nix b/outputs/images.nix index 3b20e5e..8e15f51 100644 --- a/outputs/images.nix +++ b/outputs/images.nix @@ -1,8 +1,4 @@ -{ - ook, - self, - ... -}: { +{self, ...}: { flake.images = { ooknode = self.nixosConfigurations.ooknode.config.system.build.image; }; diff --git a/outputs/keys.nix b/outputs/keys.nix deleted file mode 100644 index 7c84285..0000000 --- a/outputs/keys.nix +++ /dev/null @@ -1,6 +0,0 @@ -let - keys = import ../secrets/keys.nix; -in { - perSystem._module.args.keys = keys; - flake.keys = keys; -} diff --git a/outputs/lib/builders.nix b/outputs/lib/builders.nix index ae85425..0c9677a 100644 --- a/outputs/lib/builders.nix +++ b/outputs/lib/builders.nix @@ -7,9 +7,9 @@ inherit (inputs) nixpkgs; inherit (lib) singleton recursiveUpdate mkDefault; inherit (builtins) concatLists; - inherit (self) hozen keys ook; + inherit (self) hozen ook; + inherit (inputs.secrets.nixosModules) secrets; hm = inputs.home-manager.nixosModules.home-manager; - agenix = inputs.agenix.nixosModules.default; nixosModules = "${self}/modules/nixos"; baseModules = nixosModules + "/base"; hardwareModules = nixosModules + "/hardware"; @@ -22,7 +22,7 @@ (baseModules + "/admin.nix") (baseModules + "/ssh.nix") ]; - core = [baseModules hardwareModules consoleModules appearanceModules hm agenix]; + core = [baseModules hardwareModules consoleModules appearanceModules hm secrets]; hostModules = "${self}/hosts"; mkNixos = nixpkgs.lib.nixosSystem; @@ -44,7 +44,7 @@ mkNixos { specialArgs = recursiveUpdate { - inherit hozen ook keys lib inputs self inputs' self'; + inherit hozen ook lib inputs self inputs' self'; } specialArgs; modules = concatLists [ @@ -123,7 +123,7 @@ ... }: mkNixos { - specialArgs = {inherit keys inputs lib self;}; + specialArgs = {inherit inputs lib self;}; modules = concatLists [ (singleton { networking.hostName = hostname; diff --git a/secrets/containers/cf_creds.age b/secrets/containers/cf_creds.age deleted file mode 100644 index 702af9d..0000000 --- a/secrets/containers/cf_creds.age +++ /dev/null @@ -1,19 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 xeHnUA orzYvtHssnqm5RxM5aa2/9C8WE+b71dDA2I2Xazhc2k -zkiBhnB7MdSIxrT/Sh14pHGU9ipGkBrrhNrHjW6lbJw --> ssh-ed25519 6HvatA tABXMcWyBkSJWrl3MM76eJGJSU0XKQTG6lmFWIS/qxs -ZZ3PYHKqbbdz0kDCTXhQBGCnWGsXLqZmdNjlWpT8SY4 --> ssh-ed25519 3DwG4w GUdLU60u2plRSDoFkAoNep5USX5Lj6jLrIQHzxYyPkI -5dnetJBkJeSe12iczuOMnJO8K0gkB5qhPL1UbGAslzI --> ssh-ed25519 Nn8WxA wnQzj5PqL1EoXisYGabcHzChGBZWvis+CSTE+6eCMEk -fw4XLdF7kIIWBVVDu3DBxtxdYxBSsXozpJQ7p0No8I4 --> ssh-ed25519 Gd+9pg TIdiOlNUhp4fkQPQi3PItzVBssM1TxoDYZNCB0GYryw -Ch+pJ6BEO/oUTeUn3t8qaiVuLaRgf9GUO4jpAgnJstY --> ssh-ed25519 eMj+Jg 83Cbf9k7T0DRcE7hFchQWEj/pR+qNGTLIdXDmbWMeT4 -PqOzucTkTSQg92Vd8ZMLX6cDKyESCE4v9VVHJlAfFyg --> ssh-ed25519 MQ/7Ew f4axkHyjiTOsbiYu90MAirHKoB9S70dK11JDtMKmSkc -Rb2+dIewpW0bL+qJtAxIgVAyWqTDZI9dcwMQR/0pg3s --> ssh-ed25519 3DwG4w FYRpJ1zJZmOil2/X+URrw03KXZk7qZoMO1/P+BJGCxo -SRBJ/FOUbisy7Dhd5tXd4fN8HWM95L6oDQOjzmM5St8 ---- /7SydLy/XxsnVqTD5ffym1MnyKzVyvvhIbazmf4oB18 -49aCrB"e5n9uF?ykbDB+͙DbHb^͝LӻV*^˖LϙJ8_6S$+K:$ \ No newline at end of file diff --git a/secrets/containers/vpn_env.age b/secrets/containers/vpn_env.age deleted file mode 100644 index 346dda6c48e63b5f02e64cdabf9b9609d1cf9062..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1158 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCTyNcG4IbyNuO_s*(H zObstJNOp{H4mQd#^s)JoBtJXUBi%A8T|3Y}FqA8!z}VbfTR$-{BEz{br6|kPSKBYF zyd*O}IoQG{)1x%AEXBK^$k9BsG#TACW0!JwlX8Vjvv5O`;9$gNme^*0`DyO{2 zEJ#-{i1Kzd3MdP!%yx6kx2#Cs zE!8(m+bdncEi}X}z{w!OKg6>*Am2FIz)U+hA}!n`!pSMnrQFTWGFLmwD?Ft%DKDKX z!nD}9B+)XzSUb=#H6q79B-=S4E7`oXyg0EU%-74;!`!1pJ1{q`FbczOzJdDYuH_0& zMxpv?{?5r>E`_G1!KQx6nZ<_w5xK?M0paH1L4oFJNiNwX`q~90#>rf+IR*Jq9^rl- zJ|(G0!ZHp^-t!kz5?k{z5wqkL_rAUi_Ku8%K%Or=wPOJ9c{=+V$hN(%d5x z`-&59?*8j)*ZDw8`=BPKQ7b#)c=1C5Q#Dhy1t4T~!> zBBH!YOT7b1^DRPBirg#{y&|HLiXB5sO)I>N{XMyCJq^#PTb`X4&3I|cekPL;79Ydp zW9xrke{f*pzprhbEGD0|v^NE?i0l=<^!D9jor!FRX16bmKESoL=roT>%ESpD&4U-)F6s;MTIir1c_GF& zC(d_OSSRP{CXJ3X@ZjyV4IetYn}$D(O1 zv$?B9jA#Gh?Q+d{ef{P6**Ah#uy(IEFW$P;`O;U;N#XT!oz}t4t&M6$lD&mt%q_b= z*PT~P@v!TW{%+ZG%)2i13P*5C)*ho1Vo&)c>X^8mH6?!DDt_kA`r|x~5|)>(ZSM;i z7fw2?u)S}aoLXOwrfBR_u19vSSQ?(~61!9X;E3@(qdhstmCx-df8euh=$e`1^_zS)FuD` diff --git a/secrets/keys.nix b/secrets/keys.nix deleted file mode 100644 index 59036c6..0000000 --- a/secrets/keys.nix +++ /dev/null @@ -1,28 +0,0 @@ -let - users = { - ooks = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEx2kNirkcFrNji+qz7KX+zdRxpgJyOwK0vyBrx9Ae3c"; - }; - - hosts = { - ooksdesk = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBn3ff3HaZHIyH4K13k8Mwqu/o7jIABJ8rANK+r2PfJk"; - ooksmedia = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL7ttz1jTy+byfzi874vogy3ZPLW9+8W2o512tdsqUUV"; - ookst480s = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEWFZwTuHIITHa7s4Zp6KPF2suZIMXZbe085OiG0GRh5"; - ooksphone = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINredx07UAk2l1wUPujYnmJci1+XEmcUuSX0DIYg6Vzz"; - ooksmicro = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMUSu2iy3GvMXT5eEDAymIwSQe8UuVG5GH5FJ408JiG4"; - ooksx1 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBR6Cyx64Qjth/4aS2x95scEkfiOnsCzufMZW5e41bfE"; - }; - - workstations = [ - hosts.ooksdesk - hosts.ooksmedia - hosts.ookst480s - hosts.ooksphone - hosts.ooksmicro - hosts.ooksx1 - ]; - servers = [ - hosts.ooksmedia - ]; -in { - inherit users servers hosts workstations; -} diff --git a/secrets/mullvad_wg.age b/secrets/mullvad_wg.age deleted file mode 100644 index 0c86499e9af1f4167f61364512758322f4c37554..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1232 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCTyNcG4IbyP@BHOokk z^7OOx&MOP9sPOO&FfR5mNb`5{PcL-wFmMiVuQJPVb+2;Ca^x!VhzvHfFf@ruDNGJ? zbk}!EN(}ZY_6hd#^YnEOO$*Des&I7l%s2B3az(ez%%d!^#8JUKDJ@IeOFPH7D%344 zASKi(IH1@qDA_D8H`1cmwb0ihB_Jff$loZ_DU>Taz_Z+=Dmg;m*Ds?yy~sJqGTG6r zAh^gSsJuL_JijW@Ak^C^JvlYf0K+z8mvVQLas{7K$Edu@ypoJWqpb4mY}W$M^c-Jp zgMfVPK>rM5{Z#!R&s_fquMCe0Pp*i{w0xudTmy6WqSCUI5NBgpb285Zp zRd|G!<(jy7SU6_7mvecUx%gDMm{dl3hm^Q^YWqc)B^jGX6?)}|8}%W)zU-l2+_g9bgh17U5ZFo~|9{pInfh?N}0(X6|C*SY=w~6zXiAY@TDBmW*y& zs&AIISGs~2bP6p_BL3m!VX+%+GhLfXdgfCZ#Q$TQuqf1FjRbHe~TBM(OX<=@8 zS#n}|Nno~*wrjY1jzw6QWpP%fS2~xjuC79$bCg%UUv9WdiIY!Kfn`-jh*xM1kx6BsV=|Y#v95FYUZKitqb=v0J8XF(>h?``3cYgokK7N#$1XxV z2N#!zI-R`4|3bybkwL70bK^bN>ovCBZLfEkgl=o?+*>8HV2hdmhdj#(s&C?AV;XO? zH^t~r;R|4LO6+V%l0MtGVe@%4d4?MvWlXEtwjH-@n6hFPOCzh6<4U6x-HMHy8(v;H z`Ic>)#tGB3OE*NW7e6R#$=xMejv;8-z}uJ!iUmdtcY-6;;jA(%+BW>{&UvSe*OV zU)ieuxRr_;GfrCyulw|&WHzHT=U4UrM`s=N*6VDTFv0it52HPSn|YLlRJ0~ZYlu02`&bLI3~& diff --git a/secrets/ooknet_org.age b/secrets/ooknet_org.age deleted file mode 100644 index e957cac827c9731cfceeb3c380ab8b9ed2ad5ad8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1259 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCTyNcG4IbyTQu&+yFf z(GT%Wa>+<9(+=^r3@-EVO)@D>w=hqM$Z?BGGs-A-DGV?T59RVSNl#5rG4^ox$n?(+ zFVA%`&(1SWvdjo7DNMV zBtO+4u{_z$u`<}u%d8~d(BG?~G{D`z$Sv47J)bKoG|{EfNk2^6-NMm8JJ&hK(Y4Ij zG9ol5-O?yDSvxet*frJFFx0%TG!)%7W0!JwlX8WO%uqu!Z~bHwW50mPz>q|jV8f6w z*ZfkSRPXd+%fuwNl7fOnN1w7n_du>l*CLmKken3%z{>Q@ET1gz3~#UEe3wGM$RbC- z^z!1wjB?+^GIKY5i*$6`{PHZqD;yQFQamlaf-`f|0+Pytj7w9B-P3ZT3_Jn@y+fm_ zObtCF9n&fb3cQPba(ubc%FJ_&JoJ52L(9yJ%ah78Q^LygBD9UFd_tVHJqo;Ca!iZN z^S!gRvoUOQPtmq4NLL8;Fmwt^FO4cN%kWApF->wz^K{R3HFq+rs`PdAPD&3CO>r!X z^fR?c59Eq4&MF9V&Wj2(35!fDEK2p!&koB9E=lny4b3x(@`}ocNXsjT%5yCAEl2lT zs&AIISGq!KwrhS)RknXrse77>N3LFz}(N!jk9iMi$#+Ky=+ZdnxtNja5)g+WCw`XR3FNv>SFy1EK}h3Tewe#NF~UQUVW zuEmw9IaLN(p^;u8M&`an{%+>QhLIJah9;gB-ho^Tq{~%1w6^+7vH$-6Q|?);NC{UH zv!{vVv(x3=$^mz_SUa4%^ZClBne&>$oHuR@5S&zf=)w${XP0j;DbraRwRz!zg=>sA zduPSF?oHgymCVxVa!Bx?Q*VQg8E2d46RiVsNjm!fUiNL=ov~gwW%t|AklU@Za;7J( zWawVjzyDp)b(TPh+jc#3bzFDOOSoxsFZ|_vPn%6Fob3@;I(EMMvaEvTiqPs88&+nX zc=W0`TgO>_?(=}wJ9QowA!&>GQ#HPw)QwYL$!Vml!O@!ZY}Kr0hBB55i5Jq=_Hr{d;iul~ySh`VwBKXCl~BaTn{X0t3D z8YKkUb&HQiW-=Yy^SgP|nK0>PlLA_pE6XE3rpsFKuFY;z*b^7FqHTTl!AUD8E;;o3 z*}||!J;TJNF77`SDQhIo)?Ig!o%H9);tjnkBrHz<<1ckKHHu1W^_jfm_3B#_3XArA zQM+xm?`xHJUX#Ffk3*JUowgTtWqRm!-mT&4KIl*|aTU|n66H%>A6ch)?3*R<`kH=v I{;T&o00NKPF8}}l diff --git a/secrets/secrets.nix b/secrets/secrets.nix deleted file mode 100644 index d48d549..0000000 --- a/secrets/secrets.nix +++ /dev/null @@ -1,12 +0,0 @@ -let - keys = import ./keys.nix; - inherit (keys) users workstations servers; -in { - "tailscale-auth.age".publicKeys = [users.ooks] ++ workstations; - "github_key.age".publicKeys = [users.ooks] ++ workstations; - "spotify_key.age".publicKeys = [users.ooks] ++ workstations; - "ooknet_org.age".publicKeys = [users.ooks] ++ workstations; - "mullvad_wg.age".publicKeys = [users.ooks] ++ workstations ++ servers; - "containers/vpn_env.age".publicKeys = [users.ooks] ++ workstations ++ servers; - "containers/cf_creds.age".publicKeys = [users.ooks] ++ workstations ++ servers; -} diff --git a/secrets/spotify_key.age b/secrets/spotify_key.age deleted file mode 100644 index 06f0b6b..0000000 --- a/secrets/spotify_key.age +++ /dev/null @@ -1,17 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 xeHnUA +isoneTG5GTQVZ2mkNWJMApJL0EbtlRg2lE7CFPVs0o -b0katAQ3DeRRTZZKzexJMM5JtcqY6pPpz1Z017ZmVBw --> ssh-ed25519 6HvatA Knq4A7wvjmXnWAikVSbv9BALW7f0lph2bQsiyUcilSo -SFHeWqjVO5jxnNW0cgE9qJrg0xG8SkEfZ87GpE77EZ8 --> ssh-ed25519 3DwG4w j7k+whyqKrKrkQCIMkOHl+EpCsIlJqtfqBShCc1ZGkk -vLwteoZ9DvjAecJJhPzcXvnMVsKWEDwHiL76fm2PTC0 --> ssh-ed25519 Nn8WxA ENSIpye6C7RaxwmUQP4fGD3NZ/mXh7Q0gyNsdvEGyxU -zhKepo7NqWe4NVTRcTcqKJavgZdHAXi5TK8nsHqRJNA --> ssh-ed25519 Gd+9pg wlz2TZrZVdNz9yBugvydWeUgc/430iOPpDP3+aJ0nDo -ST+uLYDvOg95qXN86vsvKmlr56sttg7Z7l4OAJfgytI --> ssh-ed25519 eMj+Jg XP+CWaVkKTzptg2lpmPcT0d+K3JoDTfmFjpyKouqwXk -WGrv56kthwxT88xXSyaPecLklfumxva9RxCoFNZwVTU --> ssh-ed25519 MQ/7Ew XgTs4XL6bGspzSFdT2IW4BW3MPjdP0YiLQqo0SDR+EI -18MBJWrgjk3J58EPZjwW/OwAo3bKG+jHztowqQeYG5M ---- nxPnfZNn24Q70LqqEO2Mo76xPcaBuZ7OEYXTO0Ac/wk -4V+_1Fs;an z2y(9sbuKB-G0n(wHBK=w4l;Dita2-Jt#H*3bIne74%YTa59M+X%kqxYcMlITFwb&H zb~i{0cehA2(00-H2upJDPbn!%at+OoNUq8)cSN_%%%d!^#8DwASwE`0z|z~#vBbrx zq%7FmGAy7tF~riyA}KW6H_Fq;E5ax#qdY$(B$O*MGcP>dAX(ef+rZmD(9grkBrnaP zqAIv7%F)T+!pt{4&CDaPtR%`M0K+z8mvVQLa)t67NAD2FVDq937w^DGgR0~-Z4b+g zL~}zA*GeyoL>HI5aQBP=gOE~pUoNw7(@+cjqH@>pl(Imxa+kzH^C|;J%ZSv}48LSw ze~sw}2IJxEerke(Yxh3UVdZedh=LDx&7G#_G zMEX=1`=Z0Ra?5*e80S`}QBn-Wx6U~Fh&8s?iBTIN#d z9#!b>me1vurCs2eCd3aH2lC!5}iBZ0Ocvz)pgqx|CYh+|dSXjEYvnN-Y zenC!go^M`JVMUTxl}E9EQdq8gg_om2k&9WltG;_$PM~K>Sypj|zX`f+zJdDYuH_2O zS>AqYBX@0KhWl=t1 zDVf^A9)%VGPRUi4?g7aLCZ?6C{$_zW#bw!s#^HITnI>Giy1EMC`C+;KS%HN{=0yfR z9+s9NNm1#J#^nW7IfjKfmX7Wg-mW=SZowrkmcCpJ?+?oxibR!W&r7}}dBSMx`a@sO zi>0&eQI}TGH~$l4d_I1C$l2za@2AUk4~W<2t(#Vt+gAHsC2!{Me+5rh-fT^sm&>`- e+as6R-#>GLkjDPT_{%28_VTd@P2u%nTm%3caWo|W From 1ba4fd2d8d1205170fc0938aace5da2588390e71 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Mon, 20 Jan 2025 21:05:27 +1100 Subject: [PATCH 182/213] deadnix --- modules/nixos/base/nix.nix | 1 - modules/nixos/server/services/ookflix/lib.nix | 1 - 2 files changed, 2 deletions(-) diff --git a/modules/nixos/base/nix.nix b/modules/nixos/base/nix.nix index e83f449..1fd5c6e 100644 --- a/modules/nixos/base/nix.nix +++ b/modules/nixos/base/nix.nix @@ -1,5 +1,4 @@ { - inputs', inputs, pkgs, lib, diff --git a/modules/nixos/server/services/ookflix/lib.nix b/modules/nixos/server/services/ookflix/lib.nix index 3cd0adb..df29800 100644 --- a/modules/nixos/server/services/ookflix/lib.nix +++ b/modules/nixos/server/services/ookflix/lib.nix @@ -1,7 +1,6 @@ { lib, config, - self, ... }: let inherit (lib) getExe nameValuePair mkOption mkEnableOption elem assertMsg; From 602b82fb045596619ee339720083b2ca190dd731 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 21 Jan 2025 13:31:41 +1100 Subject: [PATCH 183/213] nix: add shortcut to kunzen repo --- modules/home/console/shell/fish/aliases.nix | 1 + modules/nixos/base/nix.nix | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/home/console/shell/fish/aliases.nix b/modules/home/console/shell/fish/aliases.nix index e8bfedf..16254ea 100644 --- a/modules/home/console/shell/fish/aliases.nix +++ b/modules/home/console/shell/fish/aliases.nix @@ -17,6 +17,7 @@ in { }; shellAbbrs = { f = "cd $FLAKE"; + s = "cd $KUNZEN"; fe = "$EDITOR (git rev-parse --show-toplevel) -c 'Telescope find_files'"; nswitch = "${getExe nh} os switch"; diff --git a/modules/nixos/base/nix.nix b/modules/nixos/base/nix.nix index 1fd5c6e..8af9f9d 100644 --- a/modules/nixos/base/nix.nix +++ b/modules/nixos/base/nix.nix @@ -14,6 +14,7 @@ paths = { FLAKE = "/home/${admin.name}/.config/ooknet"; WEBSITE = "${paths.FLAKE}/outputs/pkgs/website"; + KUNZEN = "/home/${admin.name}/.config/kunzen"; }; in { environment = { From b07798e0e87743e8b7eb49fd58d41703da5c2e64 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 21 Jan 2025 13:33:40 +1100 Subject: [PATCH 184/213] zellij: rework layout configuration extend the base zellij home-manager module to include the option to define layouts with zjstatus, opinionated module; will never be upstreamed in current state also re-enable cava as build failure has been fixed in nixpkgs --- .../tools/multiplexer/zellij/default.nix | 46 ++++--- .../zellij/layouts/flakeLayout.nix | 19 ++- .../tools/multiplexer/zellij/options.nix | 115 ++++++++++++++++++ modules/home/workstation/media/music.nix | 69 +++-------- 4 files changed, 184 insertions(+), 65 deletions(-) create mode 100644 modules/home/console/tools/multiplexer/zellij/options.nix diff --git a/modules/home/console/tools/multiplexer/zellij/default.nix b/modules/home/console/tools/multiplexer/zellij/default.nix index de5de56..6e13853 100644 --- a/modules/home/console/tools/multiplexer/zellij/default.nix +++ b/modules/home/console/tools/multiplexer/zellij/default.nix @@ -1,8 +1,6 @@ { osConfig, - config, lib, - pkgs, hozen, ... }: let @@ -13,6 +11,7 @@ cfg = osConfig.ooknet.console.tools.zellij; in { + imports = [./options.nix]; config = mkIf (cfg.enable || console.multiplexer == "zellij") { programs.zellij = { enable = true; @@ -38,18 +37,37 @@ in { }; }; }; - }; - # Layouts - xdg.configFile = { - # Default layout - "zellij/layouts/default.kdl" = import ./layouts/defaultLayout.nix {inherit pkgs config osConfig hozen;}; - # Layout for bash scripts - "zellij/layouts/script.kdl" = import ./layouts/scriptLayout.nix {inherit pkgs config osConfig hozen;}; - # Layout for configuring my flake - "zellij/layouts/flake.kdl" = import ./layouts/flakeLayout.nix {inherit pkgs config osConfig hozen;}; - # Additional keybinds - "zellij/config.kdl".text = + # layout configurations + layouts = { + default = { + tabs = + #kdl + '' + tab name="terminal" focus=true { + pane name="term" focus=true + } + ''; + }; + flake = { + tabs = + # kdl + '' + tab name="terminal" focus=true { + pane name="term" cwd="$FLAKE" focus=true + } + tab name="editor" { + pane name="edit" edit="$FLAKE" + } + tab name="git" { + pane name="git" cwd="$FLAKE" command="lazygit" + } + ''; + }; + }; + + # keybind configuration + extraSettings = # kdl '' keybinds clear-defaults=true { @@ -57,7 +75,7 @@ in { bind "Alt 1" { GoToTab 1; } bind "Alt 2" { GoToTab 2; } bind "Alt 3" { GoToTab 3; } - bind "Alt 4" { GoToTab 4; } + bind "Alt 4" { GoToTab 4; } bind "Alt 5" { GoToTab 5; } bind "Alt 6" { GoToTab 6; } bind "Alt 7" { GoToTab 7; } diff --git a/modules/home/console/tools/multiplexer/zellij/layouts/flakeLayout.nix b/modules/home/console/tools/multiplexer/zellij/layouts/flakeLayout.nix index 4a50b5b..d563a58 100644 --- a/modules/home/console/tools/multiplexer/zellij/layouts/flakeLayout.nix +++ b/modules/home/console/tools/multiplexer/zellij/layouts/flakeLayout.nix @@ -2,11 +2,28 @@ pkgs, hozen, osConfig, + ook, ... }: let inherit (hozen) color; + inherit (ook.lib.generators) mkZellijLayout; in { - text = + text = mkZellijLayout { + zjstatusFile = "${inputs'.zjstatus.packages.default}/bin/zjstatus.wasm"; + icon = ""; + timeZone = "${osConfig.time.timeZone}"; + tabs = '' + tab name="terminal" focus=true { + pane name="term" cwd="$FLAKE" focus=true + } + tab name="editor" { + pane name="edit" edit="$FLAKE" + } + tab name="git" { + pane name="git" cwd="$FLAKE" command="lazygit" + } + ''; + }; /* kdl */ diff --git a/modules/home/console/tools/multiplexer/zellij/options.nix b/modules/home/console/tools/multiplexer/zellij/options.nix new file mode 100644 index 0000000..289bc6d --- /dev/null +++ b/modules/home/console/tools/multiplexer/zellij/options.nix @@ -0,0 +1,115 @@ +{ + lib, + config, + inputs', + osConfig, + hozen, + ... +}: let + inherit (hozen) color; + inherit (lib) optionalAttrs mapAttrs' nameValuePair mkIf mkOption; + inherit (lib.types) nullOr lines submodule str attrsOf; + + cfg = config.programs.zellij; + + mkZellijLayout = { + zjstatus, + icon ? "", + timeZone, + tabs ? '''', + }: + # kdl + '' + layout { + default_tab_template { + pane size=2 borderless=true { + plugin location="file:${zjstatus}" { + format_left "{mode}" + format_right "{session} {datetime}" + format_center "#[fg=#${color.base0D},bold] {tabs}" + format_space "" + + border_enabled "true" + border_char "─" + border_format "#[fg=#${color.base05}]{char}" + border_position "bottom" + + hide_frame_for_single_pane "true" + + mode_normal "#[fg=#${color.base0D}]${icon} " + mode_tmux "#[fg=#${color.base0E}]${icon} " + mode_pane "#[fg=#${color.base08}]${icon} " + mode_tab "#[fg=#${color.base08}]${icon} " + mode_rename_tab "#[fg=#${color.base08}]${icon} " + mode_rename_pane "#[fg=#${color.base08}]${icon} " + mode_session "#[fg=#${color.base08}]${icon} " + mode_locked "#[fg=#${color.base05}]${icon} " + mode_move "#[fg=#${color.base0B}]${icon} " + mode_resize "#[fg=#${color.base0B}]${icon} " + mode_prompt "#[fg=#${color.base0A}]${icon} " + mode_search "#[fg=#${color.base0A}]${icon} " + mode_enter_search "#[fg=#${color.base0A}]${icon} " + + tab_normal "#[bg=#${color.base01}] {name} " + tab_active "#[bg=#${color.base02}] {name} " + tab_separator " " + + datetime "#[fg=#${color.base05},bold] {format} " + datetime_format "%I:%M %p" + datetime_timezone "${timeZone}" + } + } + children + } + ${tabs} + } + ''; + + layoutModule = submodule { + options = { + icon = mkOption { + type = str; + description = "Icon to display on the status bar"; + default = ""; + }; + timeZone = mkOption { + type = str; + description = "Timezone for the datetime display"; + default = osConfig.time.timeZone; + }; + zjstatus = mkOption { + type = str; + default = "${inputs'.zjstatus.packages.default}/bin/zjstatus.wasm"; + }; + tabs = mkOption { + type = lines; + default = ''''; + description = "KDL configuration for layouts tabs"; + }; + }; + }; +in { + options.programs.zellij = { + # TODO: turn this into a binds options + extraSettings = mkOption { + type = nullOr lines; + default = null; + description = "Additional settings in KDL format"; + }; + layouts = mkOption { + type = attrsOf layoutModule; + description = "Zellij layouts with zjstatus"; + }; + }; + config = mkIf cfg.enable { + xdg.configFile = + mapAttrs' (name: layout: + nameValuePair "zellij/layouts/${name}.kdl" { + text = mkZellijLayout layout; + }) + cfg.layouts + // optionalAttrs (cfg.extraSettings != null) { + "zellij/config.kdl".text = cfg.extraSettings; + }; + }; +} diff --git a/modules/home/workstation/media/music.nix b/modules/home/workstation/media/music.nix index b5a967f..1855058 100644 --- a/modules/home/workstation/media/music.nix +++ b/modules/home/workstation/media/music.nix @@ -75,7 +75,7 @@ in { }; cava = { - enable = false; # FIX ME!!! + enable = true; settings = { general.framerate = 60; color = { @@ -91,57 +91,26 @@ in { }; }; - xdg.configFile."zellij/layouts/music.kdl".text = - mkIf (zellij.enable || multiplexer == "zellij") - /* - kdl - */ - '' - layout { - default_tab_template { - pane size=2 borderless=true { - plugin location="file:${pkgs.zjstatus}/bin/zjstatus.wasm" { - format_left "{mode}" - format_right "{session} {datetime}" - format_center "#[fg=#89B4FA,bold] {tabs}" - format_space "" - - border_enabled "true" - border_char "─" - border_format "#[fg=#${color.base0D}]{char}" - border_position "bottom" - - hide_frame_for_single_pane "true" - - mode_normal "#[fg=${color.base0D}]󰝚" - - tab_normal "#[bg=#${color.base01}] {name} " - tab_active "#[bg=#${color.base02}] {name} " - tab_separator " " - - datetime "#[fg=#${color.base05},bold] {format} " - datetime_format "%I:%M %p" - datetime_timezone "${osConfig.time.timeZone}" - } + programs.zellij.layouts.music = { + icon = "󰝚"; + tabs = + # kdl + '' + tab name="spotify" focus=true { + pane name="spotify" { + borderless true + command "${getExe self'.packages.spotify-player}" + focus true } - children - } - - tab name="spotify" focus=true { - pane name="spotify" { - borderless true - command "${getExe pkgs.spotify-player}" - focus true - } - //pane name="Visualizer" { - // borderless false - // split_direction "horizontal" - // size "20%" - // command "cava" - //} + pane name="Visualizer" { + borderless false + split_direction "horizontal" + size "20%" + command "${getExe pkgs.cava}" } - } - ''; + } + ''; + }; home.shellAliases = mkIf (zellij.enable || multiplexer == "zellij") { zjm = "zellij --layout music"; From 7de6837bb6d13b46da72d6dff894e44284e789a8 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 21 Jan 2025 13:34:08 +1100 Subject: [PATCH 185/213] docs: add comment on spotify-player package --- outputs/pkgs/default.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/outputs/pkgs/default.nix b/outputs/pkgs/default.nix index f33f137..887e4b8 100644 --- a/outputs/pkgs/default.nix +++ b/outputs/pkgs/default.nix @@ -26,6 +26,9 @@ inherit (projectPlus) fpp-config fpp-launcher fpp-sd; project-plus = projectPlus.package; + + # disable spotify-player images due to jank with zellij + # put it here so it gets cached spotify-player = pkgs.spotify-player.override { withImage = false; withSixel = false; From 512774da029da29f807412c8fea09675e2d7d2f8 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 21 Jan 2025 13:38:57 +1100 Subject: [PATCH 186/213] zellij: remove old layout configuration --- .../zellij/layouts/defaultLayout.nix | 63 ------------- .../zellij/layouts/flakeLayout.nix | 88 ------------------- .../zellij/layouts/scriptLayout.nix | 69 --------------- modules/home/workstation/media/music.nix | 6 -- 4 files changed, 226 deletions(-) delete mode 100644 modules/home/console/tools/multiplexer/zellij/layouts/defaultLayout.nix delete mode 100644 modules/home/console/tools/multiplexer/zellij/layouts/flakeLayout.nix delete mode 100644 modules/home/console/tools/multiplexer/zellij/layouts/scriptLayout.nix diff --git a/modules/home/console/tools/multiplexer/zellij/layouts/defaultLayout.nix b/modules/home/console/tools/multiplexer/zellij/layouts/defaultLayout.nix deleted file mode 100644 index 10d842a..0000000 --- a/modules/home/console/tools/multiplexer/zellij/layouts/defaultLayout.nix +++ /dev/null @@ -1,63 +0,0 @@ -{ - pkgs, - osConfig, - hozen, - ... -}: let - inherit (hozen) color; -in { - text = - # kdl - '' - layout { - default_tab_template { - pane size=2 borderless=true { - plugin location="file:${pkgs.zjstatus}/bin/zjstatus.wasm" { - format_left "{mode}" - format_right "{session} {command_git_branch} {datetime}" - format_center "#[fg=#${color.base0D},bold] {tabs}" - format_space "" - - border_enabled "true" - border_char "─" - border_format "#[fg=#${color.base05}]{char}" - border_position "bottom" - - hide_frame_for_single_pane "true" - - mode_normal "#[fg=#${color.base0D}] " - mode_tmux "#[fg=#${color.base0E}] " - mode_pane "#[fg=#${color.base08}] " - mode_tab "#[fg=#${color.base08}] " - mode_rename_tab "#[fg=#${color.base08}] " - mode_rename_pane "#[fg=#${color.base08}] " - mode_session "#[fg=#${color.base08}] " - mode_locked "#[fg=#${color.base05}] " - mode_move "#[fg=#${color.base0B}] " - mode_resize "#[fg=#${color.base0B}] " - mode_prompt "#[fg=#${color.base0A}] " - mode_search "#[fg=#${color.base0A}] " - mode_enter_search "#[fg=#${color.base0A}] " - - tab_normal "#[bg=#${color.base01}] {name} " - tab_active "#[bg=#${color.base02}] {name} " - tab_separator " " - - command_git_branch_command "git rev-parse --abbrev-ref HEAD" - command_git_branch_format "#[fg=#${color.base0C}] {stdout} " - command_git_branch_interval "10" - command_git_branch_rendermode "static" - - datetime "#[fg=#${color.base05},bold] {format} " - datetime_format "%I:%M %p" - datetime_timezone "${osConfig.time.timeZone}" - } - } - children - } - tab name="terminal" focus=true { - pane name="term" focus=true - } - } - ''; -} diff --git a/modules/home/console/tools/multiplexer/zellij/layouts/flakeLayout.nix b/modules/home/console/tools/multiplexer/zellij/layouts/flakeLayout.nix deleted file mode 100644 index d563a58..0000000 --- a/modules/home/console/tools/multiplexer/zellij/layouts/flakeLayout.nix +++ /dev/null @@ -1,88 +0,0 @@ -{ - pkgs, - hozen, - osConfig, - ook, - ... -}: let - inherit (hozen) color; - inherit (ook.lib.generators) mkZellijLayout; -in { - text = mkZellijLayout { - zjstatusFile = "${inputs'.zjstatus.packages.default}/bin/zjstatus.wasm"; - icon = ""; - timeZone = "${osConfig.time.timeZone}"; - tabs = '' - tab name="terminal" focus=true { - pane name="term" cwd="$FLAKE" focus=true - } - tab name="editor" { - pane name="edit" edit="$FLAKE" - } - tab name="git" { - pane name="git" cwd="$FLAKE" command="lazygit" - } - ''; - }; - /* - kdl - */ - '' - layout { - default_tab_template { - pane size=2 borderless=true { - plugin location="file:${pkgs.zjstatus}/bin/zjstatus.wasm" { - format_left "{mode}" - format_right "{session} {command_git_branch} {datetime}" - format_center "#[fg=#${color.base0D},bold] {tabs}" - format_space "" - - border_enabled "true" - border_char "─" - border_format "#[fg=#${color.base05}]{char}" - border_position "bottom" - - hide_frame_for_single_pane "true" - - mode_normal "#[fg=#${color.base0D}] " - mode_tmux "#[fg=#${color.base0E}] " - mode_pane "#[fg=#${color.base08}] " - mode_tab "#[fg=#${color.base08}] " - mode_rename_tab "#[fg=#${color.base08}] " - mode_rename_pane "#[fg=#${color.base08}] " - mode_session "#[fg=#${color.base08}] " - mode_locked "#[fg=#${color.base05}] " - mode_move "#[fg=#${color.base0B}] " - mode_resize "#[fg=#${color.base0B}] " - mode_prompt "#[fg=#${color.base0A}] " - mode_search "#[fg=#${color.base0A}] " - mode_enter_search "#[fg=#${color.base0A}] " - - tab_normal "#[bg=#${color.base01}] {name} " - tab_active "#[bg=#${color.base02}] {name} " - tab_separator " " - - command_git_branch_command "git rev-parse --abbrev-ref HEAD" - command_git_branch_format "#[fg=#${color.base0C}] {stdout} " - command_git_branch_interval "10" - command_git_branch_rendermode "static" - - datetime "#[fg=#${color.base05},bold] {format} " - datetime_format "%I:%M %p" - datetime_timezone "${osConfig.time.timeZone}" - } - } - children - } - tab name="terminal" focus=true { - pane name="term" cwd="$FLAKE" focus=true - } - tab name="editor" { - pane name="edit" edit="$FLAKE" - } - tab name="git" { - pane name="git" cwd="$FLAKE" command="lazygit" - } - } - ''; -} diff --git a/modules/home/console/tools/multiplexer/zellij/layouts/scriptLayout.nix b/modules/home/console/tools/multiplexer/zellij/layouts/scriptLayout.nix deleted file mode 100644 index 835b8ee..0000000 --- a/modules/home/console/tools/multiplexer/zellij/layouts/scriptLayout.nix +++ /dev/null @@ -1,69 +0,0 @@ -{ - pkgs, - hozen, - osConfig, - ... -}: let - inherit (hozen) color; -in { - text = - /* - kdl - */ - '' - layout { - default_tab_template { - pane size=2 borderless=true { - plugin location="file:${pkgs.zjstatus}/bin/zjstatus.wasm" { - format_left "{mode}" - format_right "{session} {command_git_branch} {datetime}" - format_center "#[fg=#${color.base0D},bold] {tabs}" - format_space "" - - border_enabled "true" - border_char "─" - border_format "#[fg=#${color.base05}]{char}" - border_position "bottom" - - hide_frame_for_single_pane "true" - - mode_normal "#[fg=#${color.base0D}] " - mode_tmux "#[fg=#${color.base0E}] " - mode_pane "#[fg=#${color.base08}] " - mode_tab "#[fg=#${color.base08}] " - mode_rename_tab "#[fg=#${color.base08}] " - mode_rename_pane "#[fg=#${color.base08}] " - mode_session "#[fg=#${color.base08}] " - mode_locked "#[fg=#${color.base05}] " - mode_move "#[fg=#${color.base0B}] " - mode_resize "#[fg=#${color.base0B}] " - mode_prompt "#[fg=#${color.base0A}] " - mode_search "#[fg=#${color.base0A}] " - mode_enter_search "#[fg=#${color.base0A}] " - - tab_normal "#[bg=#${color.base01}] {name} " - tab_active "#[bg=#${color.base02}] {name} " - tab_separator " " - - command_git_branch_command "git rev-parse --abbrev-ref HEAD" - command_git_branch_format "#[fg=#${color.base0C}] {stdout} " - command_git_branch_interval "10" - command_git_branch_rendermode "static" - - datetime "#[fg=#${color.base05},bold] {format} " - datetime_format "%I:%M %p" - datetime_timezone "${osConfig.time.timeZone}" - } - } - children - } - tab name="edit" focus=true { - pane edit="./" name="edit" focus=true size="85%" borderless=true - pane name="term" focus=false size="15%" borderless=false - } - tab name="git" focus=false { - pane name="git" focus=false command="lazygit" - } - } - ''; -} diff --git a/modules/home/workstation/media/music.nix b/modules/home/workstation/media/music.nix index 1855058..85ec603 100644 --- a/modules/home/workstation/media/music.nix +++ b/modules/home/workstation/media/music.nix @@ -10,8 +10,6 @@ inherit (lib) mkIf getExe elem; inherit (builtins) attrValues; inherit (osConfig.networking) hostName; - inherit (osConfig.ooknet.console.tools) zellij; - inherit (osConfig.ooknet.console) multiplexer; inherit (osConfig.ooknet.workstation) profiles; inherit (osConfig.age.secrets) spotify_key; inherit (config.ooknet) binds; @@ -111,9 +109,5 @@ in { } ''; }; - - home.shellAliases = mkIf (zellij.enable || multiplexer == "zellij") { - zjm = "zellij --layout music"; - }; }; } From 4ffecbac0ccc8ce463ab0f2c18336915fa3f23df Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 21 Jan 2025 15:35:02 +1100 Subject: [PATCH 187/213] terminal: foot --> ghostty --- hosts/ooksdesk/default.nix | 2 +- modules/home/workstation/binds.nix | 2 + .../workstation/hyprland/settings/binds.nix | 4 +- .../workstation/hyprland/settings/rules.nix | 2 +- modules/home/workstation/terminal/default.nix | 2 +- modules/home/workstation/terminal/ghostty.nix | 89 ++++++++++++++++--- modules/nixos/workstation/options.nix | 5 +- 7 files changed, 89 insertions(+), 17 deletions(-) diff --git a/hosts/ooksdesk/default.nix b/hosts/ooksdesk/default.nix index ccb862e..8516049 100644 --- a/hosts/ooksdesk/default.nix +++ b/hosts/ooksdesk/default.nix @@ -22,7 +22,7 @@ profiles = ["creative" "virtualization" "gaming" "media" "communication" "productivity"]; default = { browser = "firefox"; - terminal = "foot"; + terminal = "ghostty"; }; }; console = { diff --git a/modules/home/workstation/binds.nix b/modules/home/workstation/binds.nix index 5e906a7..3c2e9ee 100644 --- a/modules/home/workstation/binds.nix +++ b/modules/home/workstation/binds.nix @@ -13,6 +13,8 @@ in { browser = mkBind "No browser is enabled"; terminal = mkBind "No terminal is enabled"; terminalLaunch = mkBind "Failed to launch tui"; + terminalDropdown = mkBind "Terminal Dropdown not enabled"; + btop = mkBind "Btop binding not set"; fileManager = mkBind "No file manager is enabled."; notes = mkBind "No Notes app is enabled"; discord = mkBind "No Discord app is enabled"; diff --git a/modules/home/workstation/hyprland/settings/binds.nix b/modules/home/workstation/hyprland/settings/binds.nix index 07c9f22..971147b 100644 --- a/modules/home/workstation/hyprland/settings/binds.nix +++ b/modules/home/workstation/hyprland/settings/binds.nix @@ -7,7 +7,7 @@ in { # Program Launch "SUPER, b, exec, ${binds.browser}" "SUPER, return, exec, ${binds.terminal}" - "SUPERSHIFT, return, exec, ${binds.terminal} --title foot-dropdown" + "SUPERSHIFT, return, exec, ${binds.terminal} --title=dropdown" "SUPER, e, exec, ${binds.terminalLaunch} $EDITOR" "SUPERSHIFT, P, exec, ${binds.password}" "SUPERCTRL, P, exec, ${binds.quickpass}" @@ -15,7 +15,7 @@ in { "SUPERSHIFT, e, exec, ${binds.fileManager}" "SUPERSHIFT, S, exec, ${binds.steam}" "SUPERSHIFT, n, exec, ${binds.notes}" - "SUPER, escape, exec, ${binds.terminalLaunch} --title=BTOP btop" + "SUPER, escape, exec, ${binds.btop}" "SUPER CTRL, return, exec, ${binds.zellijMenu}" "SUPER, delete, exec, ${binds.powerMenu}" "SUPERSHIFT, F, exec, ${binds.factorio}" diff --git a/modules/home/workstation/hyprland/settings/rules.nix b/modules/home/workstation/hyprland/settings/rules.nix index 5296acd..c1141f5 100644 --- a/modules/home/workstation/hyprland/settings/rules.nix +++ b/modules/home/workstation/hyprland/settings/rules.nix @@ -58,7 +58,7 @@ in { rules = ["center 1" "float" "size 50%"]; } { - matches = {initialTitle = "foot-dropdown";}; + matches = {initialTitle = "dropdown";}; rules = [ "monitor 0" "animation slide down" diff --git a/modules/home/workstation/terminal/default.nix b/modules/home/workstation/terminal/default.nix index 8ba2eb3..f13829f 100644 --- a/modules/home/workstation/terminal/default.nix +++ b/modules/home/workstation/terminal/default.nix @@ -1,6 +1,6 @@ { imports = [ ./foot.nix - # ./ghostty.nix + ./ghostty.nix ]; } diff --git a/modules/home/workstation/terminal/ghostty.nix b/modules/home/workstation/terminal/ghostty.nix index 934e1a8..9c965fc 100644 --- a/modules/home/workstation/terminal/ghostty.nix +++ b/modules/home/workstation/terminal/ghostty.nix @@ -1,14 +1,83 @@ { - inputs, - inputs', + lib, + hozen, + osConfig, + config, ... -}: { - imports = [ - inputs.ghostty-hm.homeModules.default - ]; +}: let + inherit (lib) mkIf mkMerge; + inherit (hozen) color; + inherit (osConfig.ooknet.host) admin; + inherit (osConfig.ooknet.appearance.fonts) monospace; + inherit (osConfig.ooknet.workstation) default; - programs.ghostty = { - enable = true; - package = inputs'.ghostty.packages.default; - }; + cfg = osConfig.ooknet.workstation.programs.ghostty; +in { + config = mkMerge [ + (mkIf (cfg.enable || default.terminal == "ghostty") { + programs.ghostty = { + enable = true; + enableFishIntegration = admin.shell == "fish"; + settings = { + # defined below + theme = "hozen"; + + # font config + font-size = monospace.size; + font-family = monospace.family; + font-family-bold = "${monospace.family} Bold"; + font-family-italic = "${monospace.family} Italic"; + font-family-bold-italic = "${monospace.family} Bold Italic"; + + # padding + window-padding-x = 9; + window-padding-y = 9; + + # box drawing glyph thickness + adjust-box-thickness = -10; # why where they so thick? + + # disable the window decorations + gtk-titlebar = false; + window-decoration = false; + + # disable close terminal prompt + confirm-close-surface = false; + }; + themes.hozen = { + background = "${color.base00}"; + foreground = "${color.base05}"; + palette = [ + "0=#${color.base00}" # black + "1=#${color.base08}" # red + "2=#${color.base0B}" # green + "3=#${color.base0A}" # yellow + "4=#${color.base0D}" # blue + "5=#${color.base0E}" # magenta + "6=#${color.base0C}" # cyan + "7=#${color.base05}" # white + "8=#${color.base03}" # bright black + "9=#${color.base08}" # bright red + "10=#${color.base0B}" # bright green + "11=#${color.base0A}" # bright yellow + "12=#${color.base0D}" # bright blue + "13=#${color.base0E}" # bright magenta + "14=#${color.base0C}" # bright cyan + "15=#${color.base07}" # bright white + ]; + }; + }; + }) + (mkIf (default.terminal == "ghostty") { + home.sessionVariables = { + TERMINAL = "ghostty"; + TERM = "ghostty"; + }; + ooknet.binds = { + terminal = "ghostty"; + terminalLaunch = "ghostty -e"; + terminalDropdown = "ghostty --title=dropdown"; + btop = mkIf config.programs.btop.enable "ghostty --title=BTOP -e btop"; + }; + }) + ]; } diff --git a/modules/nixos/workstation/options.nix b/modules/nixos/workstation/options.nix index 7f1ff9b..6c385a4 100644 --- a/modules/nixos/workstation/options.nix +++ b/modules/nixos/workstation/options.nix @@ -21,13 +21,14 @@ in { default = "firefox"; }; terminal = mkOption { - type = enum ["foot"]; - default = "foot"; + type = enum ["foot" "ghostty"]; + default = "ghostty"; }; }; programs = { firefox.enable = mkEnableOption ""; foot.enable = mkEnableOption ""; + ghostty.enable = mkEnableOption ""; }; }; } From 8a0a7d444cdbb623b5cd402a3f770439e8a15aa6 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 21 Jan 2025 17:02:04 +1100 Subject: [PATCH 188/213] ghostty: add shaders derivation --- modules/home/workstation/terminal/ghostty.nix | 6 +++++- outputs/pkgs/default.nix | 1 + outputs/pkgs/ghostty-shaders/default.nix | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 outputs/pkgs/ghostty-shaders/default.nix diff --git a/modules/home/workstation/terminal/ghostty.nix b/modules/home/workstation/terminal/ghostty.nix index 9c965fc..ffc0f2c 100644 --- a/modules/home/workstation/terminal/ghostty.nix +++ b/modules/home/workstation/terminal/ghostty.nix @@ -11,6 +11,8 @@ inherit (osConfig.ooknet.appearance.fonts) monospace; inherit (osConfig.ooknet.workstation) default; + # getShader = shader: "${self'.packages.ghostty-shaders}/${shader}.glsl"; + cfg = osConfig.ooknet.workstation.programs.ghostty; in { config = mkMerge [ @@ -18,6 +20,7 @@ in { programs.ghostty = { enable = true; enableFishIntegration = admin.shell == "fish"; + clearDefaultKeybinds = true; settings = { # defined below theme = "hozen"; @@ -36,9 +39,10 @@ in { # box drawing glyph thickness adjust-box-thickness = -10; # why where they so thick? - # disable the window decorations + # disable the decorations gtk-titlebar = false; window-decoration = false; + resize-overlay = "never"; # disable close terminal prompt confirm-close-surface = false; diff --git a/outputs/pkgs/default.nix b/outputs/pkgs/default.nix index 887e4b8..bbf6c24 100644 --- a/outputs/pkgs/default.nix +++ b/outputs/pkgs/default.nix @@ -22,6 +22,7 @@ website = callPackage ./website {}; caddy-with-cloudflare = callPackage ./caddy-with-cloudflare {}; wii-u-gc-adapter = callPackage ./wii-u-gc-adapter {}; + ghostty-shaders = callPackage ./ghostty-shaders {}; ook-vim = callPackage ./ook-vim {inherit inputs pkgs lib hozen;}; inherit (projectPlus) fpp-config fpp-launcher fpp-sd; diff --git a/outputs/pkgs/ghostty-shaders/default.nix b/outputs/pkgs/ghostty-shaders/default.nix new file mode 100644 index 0000000..8bd111f --- /dev/null +++ b/outputs/pkgs/ghostty-shaders/default.nix @@ -0,0 +1,18 @@ +{ + fetchFromGitHub, + stdenvNoCC, + ... +}: +stdenvNoCC.mkDerivation { + name = "ghostty-shaders"; + src = fetchFromGitHub { + owner = "m-ahdal"; + repo = "ghostty-shaders"; + rev = "ec29c83d81ebe7e9ca9250b3c799a2d700c1cca8"; + sha256 = "sha256-8D0H13JzCTzgzjzjERQG8ruayeHn1CPcRsd+KtC6nj4="; + }; + installPhase = '' + mkdir -p $out + mv *.glsl $out + ''; +} From e91fc01543053db3ff19f2560715e27478afa48f Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 21 Jan 2025 18:25:05 +1100 Subject: [PATCH 189/213] ci: consolidate check and format --- .github/workflows/check.yaml | 39 +++++++++++++++++++++-------------- .github/workflows/format.yaml | 34 ------------------------------ 2 files changed, 24 insertions(+), 49 deletions(-) delete mode 100644 .github/workflows/format.yaml diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index b35a02f..6ca7491 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -10,24 +10,33 @@ concurrency: group: ooknet-check-${{ github.ref }} cancel-in-progress: true jobs: - nix-flake-check: + check-format: + name: Check Formatting + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: DeterminateSystems/nix-installer-action@main + - run: nix run nixpkgs#alejandra -- --check . + + check-dead-code: + name: Check Dead Code + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: cachix/cachix-action@v15 + with: + name: deadnix + - uses: astro/deadnix-action@main + + check-flake: name: Check Flake runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 - - # Get access to kunzen - - name: Setup SSH - uses: webfactory/ssh-agent@v0.9.0 + - uses: actions/checkout@v4 + - uses: webfactory/ssh-agent@v0.9.0 with: ssh-private-key: ${{ secrets.KUNZEN_DEPLOY_KEY }} + - uses: DeterminateSystems/nix-installer-action@main + - uses: DeterminateSystems/magic-nix-cache-action@main + - run: nix flake check - - name: Setup Nix - uses: DeterminateSystems/nix-installer-action@main - - - name: Magic Nix Cache - uses: DeterminateSystems/magic-nix-cache-action@main - - - name: Nix Flake - run: nix flake check diff --git a/.github/workflows/format.yaml b/.github/workflows/format.yaml deleted file mode 100644 index 24f2b44..0000000 --- a/.github/workflows/format.yaml +++ /dev/null @@ -1,34 +0,0 @@ -name: "Format Flake" -on: - push: - branches: - - main - paths-ignore: - - .github/** - - .gitignore -jobs: - alejandra: - name: Format with Alejandra - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup Nix - uses: DeterminateSystems/nix-installer-action@main - - name: Nix Magic Cache - uses: DeterminateSystems/magic-nix-cache-action@main - - name: Format Flake - run: nix run nixpkgs#alejandra -- -c . - deadnix: - name: Dead Code Analysis with Deadnix - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup Nix - uses: DeterminateSystems/nix-installer-action@main - - name: Setup Deadnix - uses: cachix/cachix-action@v15 - with: - name: deadnix - - uses: astro/deadnix-action@main From 0749f112b06904b001ad7b70232c5c781e6cb6e2 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 21 Jan 2025 18:27:40 +1100 Subject: [PATCH 190/213] ci: missing nix-install --- .github/workflows/check.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 6ca7491..b73fb8e 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -23,6 +23,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - uses: DeterminateSystems/nix-installer-action@main - uses: cachix/cachix-action@v15 with: name: deadnix From aa3af5f0e5e6c5b296d4776c95c0bf32f83097dd Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 22 Jan 2025 20:16:07 +1100 Subject: [PATCH 191/213] ghostty: add basic keybinds & add to swallow regex --- modules/home/workstation/hyprland/settings/misc.nix | 2 +- modules/home/workstation/terminal/ghostty.nix | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/modules/home/workstation/hyprland/settings/misc.nix b/modules/home/workstation/hyprland/settings/misc.nix index 064daf4..eb4cde6 100644 --- a/modules/home/workstation/hyprland/settings/misc.nix +++ b/modules/home/workstation/hyprland/settings/misc.nix @@ -8,7 +8,7 @@ enable_swallow = true; # TODO: use terminal/file-explorer module - swallow_regex = "foot|nemo"; + swallow_regex = "foot|nemo|com.mitchellh.ghostty"; focus_on_activate = true; }; diff --git a/modules/home/workstation/terminal/ghostty.nix b/modules/home/workstation/terminal/ghostty.nix index ffc0f2c..c685210 100644 --- a/modules/home/workstation/terminal/ghostty.nix +++ b/modules/home/workstation/terminal/ghostty.nix @@ -28,9 +28,6 @@ in { # font config font-size = monospace.size; font-family = monospace.family; - font-family-bold = "${monospace.family} Bold"; - font-family-italic = "${monospace.family} Italic"; - font-family-bold-italic = "${monospace.family} Bold Italic"; # padding window-padding-x = 9; @@ -46,6 +43,14 @@ in { # disable close terminal prompt confirm-close-surface = false; + + keybind = [ + "ctrl+equal=increase_font_size:1" + "ctrl+minus=decrease_font_size:1" + "ctrl+zero=reset_font_size" + "ctrl+shift+v=paste_from_clipboard" + "ctrl+shift+c=copy_to_clipboard" + ]; }; themes.hozen = { background = "${color.base00}"; From 5604745c7814969ffe8ffdd5fc832395424c2152 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Fri, 24 Jan 2025 22:30:45 +1100 Subject: [PATCH 192/213] neovim: add vale & ltex-lsp --- .../workstation/communication/default.nix | 1 + .../communication/equicord/default.nix | 4 + .../communication/equicord/options.nix | 716 ++++++++++++++++++ .../ook-vim/config/plugins/languages/lsp.nix | 3 + .../config/plugins/languages/markdown.nix | 10 + outputs/pkgs/ook-vim/config/settings.nix | 4 +- outputs/pkgs/ook-vim/config/theme.nix | 35 +- .../pkgs/ook-vim/modules/plugins/default.nix | 3 +- .../plugins/gruvbox-material/config.nix | 117 ++- .../modules/plugins/languages/default.nix | 1 + .../modules/plugins/languages/markdown.nix | 135 ++++ .../ook-vim/modules/plugins/notes/default.nix | 3 + .../plugins/{ => notes}/obsidian/config.nix | 0 .../plugins/{ => notes}/obsidian/default.nix | 0 .../plugins/{ => notes}/obsidian/obsidian.nix | 0 .../notes/render-markdown/render-markdown.nix | 428 +++++++++++ 16 files changed, 1442 insertions(+), 18 deletions(-) create mode 100644 modules/home/workstation/communication/equicord/default.nix create mode 100644 modules/home/workstation/communication/equicord/options.nix create mode 100644 outputs/pkgs/ook-vim/modules/plugins/languages/default.nix create mode 100644 outputs/pkgs/ook-vim/modules/plugins/languages/markdown.nix create mode 100644 outputs/pkgs/ook-vim/modules/plugins/notes/default.nix rename outputs/pkgs/ook-vim/modules/plugins/{ => notes}/obsidian/config.nix (100%) rename outputs/pkgs/ook-vim/modules/plugins/{ => notes}/obsidian/default.nix (100%) rename outputs/pkgs/ook-vim/modules/plugins/{ => notes}/obsidian/obsidian.nix (100%) create mode 100644 outputs/pkgs/ook-vim/modules/plugins/notes/render-markdown/render-markdown.nix diff --git a/modules/home/workstation/communication/default.nix b/modules/home/workstation/communication/default.nix index 1141ceb..e155b1b 100644 --- a/modules/home/workstation/communication/default.nix +++ b/modules/home/workstation/communication/default.nix @@ -1,5 +1,6 @@ { imports = [ ./vesktop + ./equicord ]; } diff --git a/modules/home/workstation/communication/equicord/default.nix b/modules/home/workstation/communication/equicord/default.nix new file mode 100644 index 0000000..9be6fb9 --- /dev/null +++ b/modules/home/workstation/communication/equicord/default.nix @@ -0,0 +1,4 @@ +{ + imports = [./options.nix]; + programs.equicord.enable = true; +} diff --git a/modules/home/workstation/communication/equicord/options.nix b/modules/home/workstation/communication/equicord/options.nix new file mode 100644 index 0000000..b06f850 --- /dev/null +++ b/modules/home/workstation/communication/equicord/options.nix @@ -0,0 +1,716 @@ +{ + lib, + pkgs, + config, + ... +}: let + inherit (lib) mkIf mkOption mkEnableOption mkPackageOption; + inherit (lib.types) listOf str int enum numbers oneOf nullOr attrsOf submodule bool strMatching; + mkBoolOption = default: description: + mkOption { + type = bool; + inherit default description; + }; + + mkLabelOption = default: + mkOption { + type = str; + inherit default; + description = "${default} label"; + }; + + mkEquibopSelect = attr: v: attr.${v}; + listToString = sep: list: builtins.concatStringsSep sep list; + + rgbValue = ''([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])''; + rgbDecimal = strMatching ''${rgbValue}, *${rgbValue}, *${rgbValue}''; + hexColor = strMatching "#[[:xdigit:]]{6}"; + + mkHexColorOption = name: + mkOption { + type = oneOf [hexColor (enum [""])]; + default = ""; + description = "${name} color in hex format"; + example = "#ea6962"; + }; + + cfg = config.programs.equicord; +in { + options.programs.equicord = { + enable = mkEnableOption "Enable Equicord, for of Vencord"; + package = mkPackageOption pkgs "equibop" { + default = "equibop"; + example = pkgs.equicord; + }; + settings = { + autoUpdate = mkEnableOption "Enable auto updating for Equicord" // {default = true;}; + autoUpdateNotification = mkEnableOption "Notify when Equicord automatically updates"; + useQuickCss = mkEnableOption "Enable custom CSS"; + themeLinks = mkOption { + type = listOf str; + default = []; + description = "List of Discord CSS themes to install via link"; + example = ["https://refact0r.github.io/midnight-discord/midnight.css"]; + }; + enabledThemes = mkOption { + type = listOf str; + default = []; + description = "List of themes to enable from XDG_CONFIG_HOME/equibop/themes"; + }; + enableReactDevtools = mkEnableOption "Enable react dev tools extension"; + frameless = mkEnableOption "Enable frameless mode"; + transparent = mkEnableOption "Enable transparent mode. Requires a theme that supports transparency"; + disableMinSize = mkEnableOption "Disable minimum window size"; + notifications = { + timeout = mkOption { + type = int; + default = 5000; + description = "Notification timeout in ms, set to 0 to never automatically time out"; + example = 0; + }; + position = mkOption { + type = enum ["bottom-right" "top-right"]; + default = "bottom-right"; + description = "Position of notifications"; + example = "top-right"; + }; + useNative = mkOption { + type = enum ["always" "never" "not-focused"]; + default = "not-focused"; + description = "When should notifications be used"; + example = "always"; + }; + logLimit = mkOption { + type = int; + default = 50; + description = '' + The amount of notifications to save in the log until old ones are removed. + Set to 0 to disable log. Set to 0 to to disable notification log and 200 to + never automatically remove old notifcations + ''; + }; + }; + plugins = { + # API plugins + ChatInputButtonsAPI.enabled = mkBoolOption true "Chat Input API"; + CommandsAPI.enabled = mkBoolOption true ""; + DynamicImageModalAPI.enabled = mkBoolOption false ""; + MemberListDecoratorsAPI.enabled = mkBoolOption false ""; + MessageAccessoriesAPI.enabled = mkBoolOption true ""; + MessageDecorationsAPI.enabled = mkBoolOption false ""; + MessageEventsAPI.enabled = mkBoolOption false ""; + MessageUpdaterAPI.enabled = mkBoolOption false ""; + ServerListAPI.enabled = mkBoolOption false ""; + UserSettingsAPI.enabled = mkBoolOption true ""; + + AccountPanelServerProfile = { + enabled = mkEnableOption '' + Right click your account panel in the bottom left to + view your profile in the current server. + ''; + prioritizeServerProfile = mkEnableOption '' + Prioritize Server Profile when left clicking your account panel. + ''; + }; + AllCallTimers = { + enabled = mkEnableOption '' + Add call timer to all users in a server voice channel. + ''; + showWithoutHover = mkEnableOption '' + Always show the timer without needing to hover. + ''; + showRoleColor = mkEnableOption '' + Show the users role color. + ''; + trackSelf = mkEnableOption '' + Also track yourself. + ''; + showSeconds = mkEnableOption '' + Show seconds in the timer. + ''; + format = mkOption { + type = enum ["stopwatch" "human"]; + default = "human"; + description = '' + Compact or human readable format: + - stopwatch: 30:23:00:42 + - human: 30d 23h 00m 42s + ''; + }; + watchLargeGuilds = mkEnableOption '' + Track users in large guild. Warning this may cause lag if your in a lot + of guilds with active voice users. + ''; + }; + AltKrispSwitch.enabled = mkEnableOption '' + Makes the Noise Suppression Popout switch between None and Krisp instead + of Krisp and Strandard. + ''; + AlwaysAnimate = { + enable = mkEnableOption '' + Animates anything that can be animated. + ''; + }; + AlwaysExpandRoles = { + enabled = mkEnableOption "Always expand the role list in profile popouts."; + hideArrow = mkEnableOption "Hide Arrows."; + }; + AlwaysTrust = { + enabled = mkEnableOption '' + Remove the untrusted domain and suspicious file popup. + ''; + domain = mkEnableOption '' + Remove the untrusted domain popup when opening links. + ''; + file = mkEnableOption '' + Remove the "Potentially Dangerous Download" popup when opening links. + ''; + }; + AmITyping.enabled = mkEnableOption "Shows you if other people can see you typing."; + Anammox = { + enabled = mkEnableOption '' + A microbial process that plays an important part in the nitrogen cycle. + Hide various discord nitro excusive features. + ''; + dms = mkEnableOption "Remove shops above DMs list"; + billing = mkEnableOption "Remove billings settings"; + gift = mkEnableOption "Remove gift button"; + emojiList = mkEnableOption "Remove unavailable catagories from the emoji picker"; + }; + AnonymiseFileNames = { + enabled = mkEnableOption "Anonymise uploaded file names"; + anonymiseByDefault = mkEnableOption "Whether to anonymise file names by default"; + method = mkOption { + type = enum ["random characters" "consistant" "timestamp"]; + default = "random characters"; + apply = mkEquibopSelect { + "random characters" = 0; + "consistent" = 1; + "timestamp" = 2; + }; + }; + randomizedLength = mkOption { + type = int; + default = 7; + description = "Random character length."; + }; + consistent = mkOption { + type = str; + default = "image"; + description = "Consistant filename."; + # doesn't appear to be an option you can change + readOnly = true; + }; + }; + AtSomeone.enabled = mkEnableOption "Mention someone randomly."; + BANger = { + enabled = mkEnableOption "Replaces the GIF i nthe ban dialogue with a custom one."; + source = mkOption { + type = str; + default = ""; + description = "Source to replace ban GIF with (video or GIF)."; + example = "https://i.imgur.com/wp5q52C.mp4"; + }; + }; + BannersEverywhere = { + enabled = mkEnableOption "Display banners in the member list."; + animate = mkEnableOption "Animate banners."; + }; + BetterActivities = { + enabled = mkEnableOption '' + Shows activity icons in the member list and allows showing all activities. + ''; + memberList = mkEnableOption "Show activity icons in the member list"; + iconSize = mkOption { + type = int; + default = 15; + description = "Size of the activity icons."; + }; + specialFirst = mkEnableOption "Show special activities first (Currently Spotify and Twitch)."; + renderGifs = mkEnableOption "Allow rendering GIFs."; + showAppDescription = mkEnableOption "Show application descriptions in the activity tooltip."; + userPopout = mkEnableOption "Show all activities in the profile popout/sidebar."; + allActivitiesStyle = mkOption { + type = enum ["corousel" "list"]; + default = "corousel"; + description = "Style for showing all activities"; + }; + }; + BetterAudioPlayer = { + enabled = mkEnableOption '' + Adds a spectograph and oscilloscope visualizer to audio attachment players. + ''; + oscilloscope = mkEnableOption "Enable oscilloscope visualizer."; + spectograph = mkEnableOption "Enable spectograph visualizer."; + oscilloscopeSolidColor = mkEnableOption "Use colid color for oscilloscope."; + oscilloscopeColor = mkOption { + # not 100% sure if a hex color value can be set via json here + type = rgbDecimal; + default = "255, 255, 255"; + description = "RGB Color for the oscilloscope."; + example = "10, 200, 130"; + }; + spectographSolidColor = mkEnableOption "Use solid color for spectograph."; + spectographColor = mkOption { + type = rgbDecimal; + default = "33, 150, 243"; + example = "10, 200, 130"; + }; + }; + BetterBanReasons = { + enabled = mkEnableOption '' + Create custom reasons to use in the Discord Ban modal, and/or + show a test input by default instead of the options. + ''; + reasons = mkOption { + type = listOf str; + default = []; + description = "List of ban reasons"; + example = [ + "uses nix" + "arch user" + ]; + }; + textInputDefault = mkEnableOption '' + Shows a text input instead of a select menu by default. (Equivalent to clicking the "Other" option). + ''; + }; + BetterFolders = { + enabled = mkEnableOption '' + Shows server folders on dedicated sidebar and adds folder related improvements. + ''; + sidebar = mkEnableOption "Display servers from folder on dedicated sidebar."; + sidebarAnim = mkEnableOption "Animate opening the folder sidebar."; + closeAllFolders = mkEnableOption "Close all folders when selecting a server not in a folder."; + closeOthers = mkEnableOption "Close other folders when opening a folder."; + forceOpen = mkEnableOption "Force a folder to open when switching to a server of that folder."; + keepIcons = mkEnableOption '' + Keep showing guild icons in the primary guild bar folder when it's open + in the BetterFolders sidebar. + ''; + showFoldersIcon = mkOption { + type = enum ["never" "always" "when more than one folder is expanded"]; + default = "always"; + description = '' + Show the folder icon above the folder guilds in the BetterFolders sidebar. + Available options: + - "never" + - "always" + - "when more than one folder is expanded" + ''; + apply = mkEquibopSelect { + "never" = 0; + "always" = 1; + "when more than one folder is expanded" = 2; + }; + }; + }; + BetterGifAltText = mkEnableOption '' + Change GIF alt text from simply being 'GIF' to containing the gif tags/filename. + ''; + BetterGifPicker = mkEnableOption "Makes the GIF picker open the favourite category by default"; + BetterInvites = mkEnableOption '' + See invites expiration date, view inviter profile and preview discoverable servers before joining + by clicking their name. + ''; + BetterNotesBox = { + enabled = mkEnableOption "Hide notes or disable spellcheck."; + hide = mkEnableOption "Hide notes."; + noSpellCheck = mkEnableOption "Disable spellcheck in notes"; + }; + BetterQuickReact = { + enabled = mkEnableOption "Improves the quick react buttons in the message context menu"; + frequentEmojis = mkEnableOption "Use frequently used emojis instead of favorite emojis"; + rows = mkOption { + type = numbers.between 1 16; + default = 2; + description = "Rows of quick reactions to display. Number between 1-16"; + example = 4; + }; + columns = mkOption { + type = numbers.between 1 12; + default = 4; + description = "Columns of quick reactions to display. Number betwen 1-12"; + example = 6; + }; + compactMode = mkEnableOption '' + Scales the buttons to 75% of their original scale, whilst increasing the inner emoji to 125% scale. + Emojis will be 93.75% of the original size. Reccomended to have a minimum of 5 columns. + ''; + scroll = mkEnableOption "Enable scrolling the list of emojis"; + }; + BetterRoleContext = { + enabled = mkEnableOption '' + Adds options to copy role color / edit role / view role icon when right clicking roles in + in the user profile + ''; + roleIconFileFormat = mkOption { + type = enum ["webp" "png" "jpg"]; + default = "png"; + description = "File formate to use when viewing role icons"; + }; + }; + BetterRoleDot = { + enabled = mkEnableOption '' + Copy role colour on RoleDot (accessibility setting) click. Also allows using both + RoleDot and coloured names simultaneously. + ''; + bothStyles = mkEnableOption "Show both role dot and coloured names"; + copyRoleColorInProfilePopout = mkEnableOption "Allow click on role dot in profile popout to copy role color"; + }; + BetterSession = { + enabled = mkEnableOption '' + Enhances the sessions (devices) menu. Allows you to view exact timestamps, give each session a + custom name, and receive notifications about new sessions. + ''; + backgroundCheck = mkEnableOption '' + Check for new sessions in the background, and display notifications when they are detected. + ''; + checkInterval = mkOption { + type = int; + default = 20; + description = "How often to check for new sessions in the background (if enabled), in minutes."; + }; + }; + BetterSettings = { + enabled = mkEnableOption "Enhances your settings-menu-opening experience."; + disableFade = mkEnableOption "Disable the crossfade animation."; + organizeMenu = mkEnableOption "Organizes the settings cog context menu into categories."; + eagerLoad = mkEnableOption "Removes the loading delay when opening the menu for the first time."; + }; + BetterUploadButton.enabled = mkEnableOption "Upload with a single click, open menu with right click"; + BetterUserArea.enabled = mkEnableOption '' + Reworks the user area styling to fit more buttons and overall look nicer + ''; + BetterStreamPreview.enabled = mkEnableOption "Allows you to enlarge stream previews"; + BlockKeywords = { + enabled = mkEnableOption '' + Blocks messages containing specific user-defined keywords, as if the user sending them was blocked. + ''; + blockedWords = mkOption { + type = str; + default = ""; + description = "Comma-seperated list of words to block."; + example = "arch,home-manager"; + }; + useRegex = mkEnableOption "Use each value as a regular expression when checking message content (advanced)"; + caseSensitive = mkEnableOption "Whether to use a case sensitive search or not."; + ignoreBlockedMessages = mkEnableOption "Completely ignores (recent) new messages bar"; + }; + BlockKrisp.enabled = mkEnableOption "Prevent Krist from loading"; + BlurNSFW = { + enabled = mkEnableOption "Blur attachments in NSFW channels until hovered."; + blurAmount = mkOption { + type = int; + default = 10; + description = "Blur amount"; + }; + }; + BypassStatus = { + enabled = mkEnableOption '' + Still get notifications from specific sources when in do not disturb mode. + Right-click on users/channels/guilds to set them to bypass do not disturb mode. + ''; + guilds = mkOption { + type = listOf str; + default = []; + description = '' + Guilds to let bypass (notified when pinged anywhere in guild). + List of comma seperated guild IDs. + ''; + example = [ + "123451234512345123" + "456456456456456456" + ]; + apply = listToString ","; + }; + channels = mkOption { + type = listOf str; + default = []; + description = '' + channels to let bypass (notified when pinged anywhere in channel). + List of . + ''; + example = [ + "123451234512345123" + "456456456456456456" + ]; + apply = listToString ","; + }; + users = mkOption { + type = listOf str; + default = []; + description = '' + users to let bypass (notified when pinged anywhere in guild). + List of comma seperated user IDs. + ''; + example = [ + "123451234512345123" + "456456456456456456" + ]; + apply = listToString ","; + }; + notificationSound = mkEnableOption "Whether the notification sound should be played"; + statusToUse = mkOption { + type = enum ["dnd" "invisible" "idle"]; + default = "dnd"; + description = "Status to use for whitelist."; + }; + allowOutsideOfDm = mkEnableOption '' + Allow selected users to bypass status outside of DMs too + (acts like a channel/guild bypass, but it's for all messages sent by the selected users). + ''; + }; + CallTimer = { + enabled = mkEnableOption "Adds a timer to vcs."; + format = mkOption { + type = enum ["human" "stopwatch"]; + default = "human"; + description = "The timer format."; + }; + }; + ChannelBadges = { + enabled = mkEnableOption "Adds badges to channels based on their type."; + oneBadgePerChannel = mkEnableOption "Show only one badge per channel."; + showTextBadge = mkEnableOption "Show Text badge"; + showVoiceBadge = mkEnableOption "Show Voice badge"; + showCategoryBadge = mkEnableOption "Show Category badge"; + showDirectoryBadge = mkEnableOption "Show Directory badge"; + showAnnouncementThreadBadge = mkEnableOption "Show Announcement Thread badge"; + showPublicThreadBadge = mkEnableOption "Show Public Thread badge"; + showPrivateThreadBadge = mkEnableOption "Show Private Thread badge"; + showStageBadge = mkEnableOption "Show Stage badge"; + showAnnouncementBadge = mkEnableOption "Show Announcement badge"; + showForumBadge = mkEnableOption "Show Forum badge"; + showMediaBadge = mkEnableOption "Show Media badge"; + showNSFWBadge = mkEnableOption "Show NSFW badge"; + showLockedBadge = mkEnableOption "Show Locked badge"; + showRulesBadge = mkEnableOption "Show Rules badge"; + showUnknownBadge = mkEnableOption "Show Unknown badge"; + textBadgeLabel = mkLabelOption "Text"; + voiceBadgeLabel = mkLabelOption "Voice"; + categoryBadgeLabel = mkLabelOption "Category"; + announcementBadgeLabel = mkLabelOption "News"; + announcementThreadBadgeLabel = mkLabelOption "News Thread"; + publicThreadBadgeLabel = mkLabelOption "Thread"; + privateThreadBadgeLabel = mkLabelOption "Private Thread"; + stageBadgeLabel = mkLabelOption "Stage"; + directoryBadgeLabel = mkLabelOption "Directory"; + forumBadgeLabel = mkLabelOption "Forum"; + mediaBadgeLabel = mkLabelOption "Media"; + nsfwBadgeLabel = mkLabelOption "NSFW"; + lockedBadgeLabel = mkLabelOption "Locked"; + rulesBadgeLabel = mkLabelOption "Rules"; + unknownBadgeLabel = mkLabelOption "Unknown"; + lockedBadgeColor = mkHexColorOption "Locked badge"; + rulesBadgeColor = mkHexColorOption "Rules badge"; + unknownBadgeColor = mkHexColorOption "Unknown badge"; + nsfwBadgeColor = mkHexColorOption "NSFW badge"; + mediaBadgeColor = mkHexColorOption "Media badge"; + forumBadgeColor = mkHexColorOption "Forum badge"; + directoryBadgeColor = mkHexColorOption "Directory badge"; + stageBadgeColor = mkHexColorOption "Stage badge"; + privateThreadBadgeColor = mkHexColorOption "Private Thread badge"; + publicThreadBadgeColor = mkHexColorOption "Public Thread badge"; + announcementThreadBadgeColor = mkHexColorOption "Announcement Thread badge"; + announcementBadgeColor = mkHexColorOption "Announcement badge"; + categoryBadgeColor = mkHexColorOption "Category badge"; + voiceBadgeColor = mkHexColorOption "Voice badge"; + textBadgeColor = mkHexColorOption "Text Badge"; + }; + # doesn't seem to work for me. May require window decorations? + ChannelTabs.enabled = mkEnableOption '' + Group our commonly visited channels in tabs. Warning: this doesnt appear to be working. + ''; + CharacterCounter = { + enabled = mkEnableOption "Adds a character counter to the chat input."; + colorEffects = mkEnableOption "Turn on or off color effects for getting close to the character limit"; + position = mkEnableOption "Move the character counter to the left side of the chat input"; + }; + CleanChannelName.enabled = mkEnableOption "Remove all emoji and decor from channel names"; + ClearURLs.enabled = mkEnableOption "Remove tracking garbage from URLs"; + ClientSideBlock = { + enabled = mkEnableOption "Allows you to locally hide almost all content from any user"; + usersToBlock = mkOption { + type = listOf str; + default = []; + description = "List of User IDs to block"; + example = [ + "123456789" + "987654321" + ]; + apply = listToString ", "; + }; + hideBlockedUser = mkEnableOption "Should blocked users also be hidden everywhere."; + hideBlockedMessages = mkEnableOption "Should messages from blocked users be hidden fully."; + hideEmptyRoles = mkEnableOption "Should role headers be hidden if all of their member are blocked."; + blockedReplyDisplay = mkOption { + type = enum ["displayText" "hideReply"]; + default = "displayText"; + description = '' + What should display instead of the message when someone replies to someone you have hidden. + - "displayText": Display text saying a hidden message was replied to. + - "hideReply": Literally nothing + ''; + }; + guildBlackList = mkOption { + type = listOf str; + default = []; + description = "List of guild IDs to disable functionality in"; + apply = listToString ", "; + }; + guildWhiteList = mkOption { + type = listOf str; + default = []; + description = "List of guild IDs to enable functionality in"; + apply = listToString ", "; + }; + }; + ClientTheme = { + enabled = mkEnableOption "Recreation of the old client theme experiment. Add color to your Discord client theme"; + color = mkOption { + type = strMatching "[[:xdigit:]]{6}"; + description = "Themes Color"; + default = "282828"; + }; + }; + ColorSighted.enabled = mkEnableOption "Removes the colorblind-friendly icons from statuses, just like 2015-2017 Discord"; + CommandPalette = { + enabled = mkEnableOption "Allows you to navigate the UI with a keyboard."; + hotkey = mkOption { + # TODO: Regex this + type = listOf str; + default = [ + "control" + "shift" + "p" + ]; + description = "HotKey to toggle the command palette."; + example = [ + "control" + "h" + ]; + }; + }; + ConsoleJanitor = { + enabled = mkEnableOption "Disables annoying console messages/errors"; + disableLoggers = mkEnableOption "Disables Discord loggers"; + disableSpotifyLoggers = mkEnableOption "Disable the Spotify logger, which leaks account information and access token"; + whitlistedLoggers = mkOption { + type = listOf str; + default = [ + "GatewaySocket" + "Routing/Utils" + ]; + description = "List of loggers to allow even if others are hidden."; + apply = listToString "; "; + }; + }; + ConsoleShortcuts.enabled = mkEnableOption '' + Adds shorter Aliases for many things on the window. Run 'shortcutList' for a list. + ''; + CopyEmojiMarkdown = { + enabled = mkEnableOption "Allows you to copy emojis as formatted string (<:blobcatcozy:1026533070955872337>)."; + copyUnicode = mkEnableOption "Copy the raw unicode character instead of :name: for default emojis."; + }; + CopyFileContents.enabled = mkEnableOption "Adds a button to text file attachments to copy their contents."; + CopyUserMention.enabled = mkEnableOption '' + Adds a button to copy user's mention on the user context menu, works best with ValidUser. + ''; + CopyUserURLs.enabled = mkEnableOption "Adds a 'Copy User URL' option to the user context menu."; + CrashHandler = { + enabled = mkBoolOption true "Utility for handling and possibly recovering from chrashes without restart."; + attemptToPreventCrashes = mkBoolOption true "Whether to attempt to prevent Discord crashes."; + attemptToNavigateToHome = mkEnableOption "Whether to attempt to navigate to the home when preventing Discord crashes."; + }; + CtrlEnterSend = { + enabled = mkEnableOption "Use Ctrl+Enter to send messages (customizable)."; + submitRule = mkOption { + type = enum ["ctrl+enter" "shift+enter" "enter"]; + default = "ctrl+enter"; + description = '' + The way to send a messages. + Available options: + - "ctrl+enter" (Enter of Shift+Enter for new line) (cmd+enter on macOS) + - "shift+enter" (Enter for a new Line) + - "enter" (Shift+Enter for new line; Discord default) + ''; + }; + sendMessageInTheMiddleOfACodeBlock = mkEnableOption "Whether to send a message in the middle of a code block."; + }; + CustomIdle = { + enabled = mkEnableOption "Allows you to set the time before Discord goes idle (or disable auto-idle)"; + idleTimeout = { + type = numbers.between 0 60; + default = 20; + description = "Minutes before Discord goes idle (0 to disable auto-idle). 0.0 - 60.0"; + }; + remainInIdle = mkEnableOption "When you come back to Discord, remain idle until you confirm you want to go online"; + }; + CustomSounds.enabled = mkEnableOption "Replace Discord's sounds with your own, custom sounds must be defined via client"; + CustomTimestamps = let + mkTimestampOption = default: description: + mkOption { + type = str; + inherit default description; + }; + in { + enabled = mkEnableOption '' + Custom timestamps on mesages and tooltips. + See for documentation on formatting. + ''; + cozyFormat = mkTimestampOption "[calander]" "Time format to use in messages on cozy mode."; + compactFormat = mkTimestampOption "LT" "Time format on compact mode and hovering messages."; + tooltipFormat = mkTimestampOption "LLLL • [relative]" "Time format to use on tooltips."; + sameDayFormat = mkTimestampOption "HH:mm:ss" "[calander] format for today."; + lastDayFormat = mkTimestampOption "[yesterday] HH:mm:ss" "[calander] format for yesterday."; + lastWeekFormat = mkTimestampOption "ddd DD.MM.YYYY HH:mm:ss" "[calander] format for last week."; + sameElseFormat = mkTimestampOption "ddd DD.MM.YYYY HH:mm:ss" "[calander] format for older dates."; + }; + # why weebs, why + CuteAnimeBoys.enabled = mkEnableOption "Add a command to send cute anime boys in the chat"; + CuteNekos.enabled = mkEnableOption "Send Nekos to others"; + CutePats.enabled = mkEnableOption "Sending head pats."; + DeadMembers.enabled = mkEnableOption "Shows when the sender of a message has left the guild."; + Dearrow = { + enabled = mkEnableOption "Makes YouTube embed titles and thumbnails less sensationalist, powered by Dearrow."; + hideButton = mkEnableOption "Hides the Dearrow button from Youtube embeds."; + replaceElements = mkOption { + type = enum ["everything" "titles" "thumbnails"]; + default = "everything"; + description = '' + Choose which elements of the embed will be replaced. + Available options: + - "everything" + - "titles" + - "thumbnails" + ''; + apply = mkEquibopSelect { + "everything" = 0; + "titles" = 1; + "thumbnails" = 2; + }; + }; + dearrowByDefault = mkEnableOption "Dearrow videos automatically"; + }; + DecodeBase64 = { + enabled = mkEnableOption "Decode base64 content of any message and copy the decoded content."; + clickMethod = mkOption { + type = enum ["Left" "Right"]; + default = "Left"; + }; + }; + }; + }; + }; + config = mkIf cfg.enable { + # test file until module is complete + xdg.configFile."equibop/test.json".text = builtins.toJSON cfg.settings; + + ooknet.equicord = { + plugins = { + CommandPallete.enabled = true; + }; + }; + }; +} diff --git a/outputs/pkgs/ook-vim/config/plugins/languages/lsp.nix b/outputs/pkgs/ook-vim/config/plugins/languages/lsp.nix index a5cbb77..9afab91 100644 --- a/outputs/pkgs/ook-vim/config/plugins/languages/lsp.nix +++ b/outputs/pkgs/ook-vim/config/plugins/languages/lsp.nix @@ -4,5 +4,8 @@ lspkind.enable = true; lspSignature.enable = true; trouble = {enable = true;}; + null-ls = { + enable = true; + }; }; } diff --git a/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix b/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix index 17280fb..3bf7b83 100644 --- a/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix +++ b/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix @@ -2,9 +2,19 @@ vim = { languages.markdown = { enable = true; + vale.enable = true; + ltex.enable = true; extensions = { render-markdown-nvim = { enable = true; + setupOpts = { + heading = { + border = true; + width = "block"; + left_pad = 3; + right_pad = 4; + }; + }; }; }; }; diff --git a/outputs/pkgs/ook-vim/config/settings.nix b/outputs/pkgs/ook-vim/config/settings.nix index 46b572a..9524e21 100644 --- a/outputs/pkgs/ook-vim/config/settings.nix +++ b/outputs/pkgs/ook-vim/config/settings.nix @@ -7,9 +7,11 @@ useSystemClipboard = true; autopairs.nvim-autopairs.enable = true; hideSearchHighlight = true; - spellcheck.enable = true; theme = { enable = false; }; + spellcheck = { + enable = true; + }; }; } diff --git a/outputs/pkgs/ook-vim/config/theme.nix b/outputs/pkgs/ook-vim/config/theme.nix index 3e0335d..b269789 100644 --- a/outputs/pkgs/ook-vim/config/theme.nix +++ b/outputs/pkgs/ook-vim/config/theme.nix @@ -1,20 +1,31 @@ -{ +{hozen, ...}: let + inherit (hozen) color; +in { vim.gruvbox-material = { enable = true; contrast = "medium"; italics = false; transparent = false; - extraConfig = - # lua - '' - local g_colors = require("gruvbox-material.colors") - local colors = g_colors.get(vim.o.background, "soft") + additionalHighlights = { + RenderMarkdownH1Bg = {bg = "#${color.layout.body}";}; + RenderMarkdownH2Bg = {bg = "#${color.layout.body}";}; + RenderMarkdownH3Bg = {bg = "#${color.layout.body}";}; + RenderMarkdownH4Bg = {bg = "#${color.layout.body}";}; + RenderMarkdownH5Bg = {bg = "#${color.layout.body}";}; + RenderMarkdownH6Bg = {bg = "#${color.layout.body}";}; + "@markup.heading.1" = { + fg = "#${color.green.base}"; + bold = true; + }; + "@markup.heading.2" = { + fg = "#${color.blue.base}"; + bold = true; + }; - -- Noice - vim.api.nvim_set_hl(0, "NoiceCmdlinePopupBorderHelp", { fg = colors.yellow }) - vim.api.nvim_set_hl(0, "NoiceCmdlinePopupBorder", { fg = colors.grey1 }) - vim.api.nvim_set_hl(0, "NoiceCmdlineIcon", { fg = colors.green }) - vim.api.nvim_set_hl(0, "NoiceCmdLinePopupTitle", { fg = colors.grey1 }) - ''; + NoiceCmdlinePopupBorder = {fg = "#${color.border.active}";}; + NoiceCmdlinePopupBorderHelp = {fg = "#${color.yellow.base}";}; + NoiceCmdlineIcon = {fg = "#${color.green.base}";}; + NoiceCmdLinePopupTitle = {fg = "#${color.typography.text}";}; + }; }; } diff --git a/outputs/pkgs/ook-vim/modules/plugins/default.nix b/outputs/pkgs/ook-vim/modules/plugins/default.nix index 18f7c03..0fe0dd9 100644 --- a/outputs/pkgs/ook-vim/modules/plugins/default.nix +++ b/outputs/pkgs/ook-vim/modules/plugins/default.nix @@ -2,7 +2,8 @@ imports = [ ./gruvbox-material ./telescope - ./obsidian ./theme + ./notes + ./languages ]; } diff --git a/outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/config.nix b/outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/config.nix index 4af5235..a169102 100644 --- a/outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/config.nix +++ b/outputs/pkgs/ook-vim/modules/plugins/gruvbox-material/config.nix @@ -5,8 +5,105 @@ ... }: let inherit (lib) mkOption mkIf boolToString; - inherit (lib.types) bool enum lines; - inherit (lib.nvim.dag) entryAfter; + inherit (lib.types) bool enum lines nullOr str submodule attrsOf; + inherit (lib.nvim.dag) entryBefore; + inherit (lib.nvim.lua) toLuaObject; + + # hack to get around nvf's handling of prefixed @ in toLuaObject + wrapHighlights = highlights: + lib.mapAttrs' ( + name: value: + if lib.hasPrefix "@" name + then lib.nameValuePair "hl_${name}" value + else lib.nameValuePair name value + ) + highlights; + + highlightOpts = submodule { + options = { + # https://neovim.io/doc/user/api.html#nvim_set_hl() + fg = mkOption { + type = nullOr str; + default = null; + description = "Foreground color"; + }; + bg = mkOption { + type = nullOr str; + default = null; + description = "Background color"; + }; + sp = mkOption { + type = nullOr str; + default = null; + description = "SP color"; + }; + blend = mkOption { + type = nullOr bool; + default = null; + description = "Blend attribute"; + }; + bold = mkOption { + type = nullOr bool; + default = null; + description = "Italic attribute"; + }; + standout = mkOption { + type = nullOr bool; + default = null; + description = "Standout attribute"; + }; + underline = mkOption { + type = nullOr bool; + default = null; + description = "underline attribute"; + }; + undercurl = mkOption { + type = nullOr bool; + default = null; + description = "Undercurl attribute"; + }; + underdouble = mkOption { + type = nullOr bool; + default = null; + description = "Underdouble attribute"; + }; + underdotted = mkOption { + type = nullOr bool; + default = null; + description = "Underdotted attribute"; + }; + underdashed = mkOption { + type = nullOr bool; + default = null; + description = "Underdashed attribute"; + }; + strikethrough = mkOption { + type = nullOr bool; + default = null; + description = "Strikethrough attribute"; + }; + italic = mkOption { + type = nullOr bool; + default = null; + description = "Bold attribute"; + }; + reverse = mkOption { + type = nullOr bool; + default = null; + description = "Reverse attribute"; + }; + nocombine = mkOption { + type = nullOr bool; + default = null; + description = "Nocombine attribute"; + }; + link = mkOption { + type = nullOr str; + default = null; + description = "Link attribute"; + }; + }; + }; cfg = config.vim.gruvbox-material; in { @@ -45,13 +142,18 @@ in { type = lines; description = "Additional lua configuration after"; }; + additionalHighlights = mkOption { + type = attrsOf highlightOpts; + default = {}; + description = "Additional highlight groups to be applied after theme setup."; + }; }; config = mkIf cfg.enable { vim = { startPlugins = [pkgs.vimPlugins.gruvbox-material-nvim]; luaConfigRC.theme = - entryAfter ["basic"] + entryBefore ["pluginConfigs" "lazyConfigs"] /* lua */ @@ -72,7 +174,14 @@ in { highlight = ${boolToString cfg.signsHighlight}, }, } - ${cfg.extraConfig} + + local extra_highlights = ${toLuaObject (wrapHighlights cfg.additionalHighlights)} + for group_name, settings in pairs(extra_highlights) do + -- Unwrap our prefixed names back to @ form + local actual_name = group_name:gsub("^hl_@", "@") + vim.api.nvim_set_hl(0, actual_name, settings) + end + ''; }; }; diff --git a/outputs/pkgs/ook-vim/modules/plugins/languages/default.nix b/outputs/pkgs/ook-vim/modules/plugins/languages/default.nix new file mode 100644 index 0000000..a50dfb6 --- /dev/null +++ b/outputs/pkgs/ook-vim/modules/plugins/languages/default.nix @@ -0,0 +1 @@ +{imports = [./markdown.nix];} diff --git a/outputs/pkgs/ook-vim/modules/plugins/languages/markdown.nix b/outputs/pkgs/ook-vim/modules/plugins/languages/markdown.nix new file mode 100644 index 0000000..4b6ff4b --- /dev/null +++ b/outputs/pkgs/ook-vim/modules/plugins/languages/markdown.nix @@ -0,0 +1,135 @@ +# modules/plugins/vale/default.nix +{ + config, + pkgs, + lib, + ... +}: let + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.modules) mkIf mkMerge; + inherit (lib.types) package enum str; + + languages = [ + "auto" + "ar" + "ast-ES" + "be-BY" + "br-FR" + "ca-ES" + "ca-ES-valencia" + "da-DK" + "de" + "de-AT" + "de-CH" + "de-DE" + "de-DE-x-simple-language" + "el-GR" + "en" + "en-AU" + "en-CA" + "en-GB" + "en-NZ" + "en-US" + "en-ZA" + "eo" + "es" + "es-AR" + "fa" + "fr" + "ga-IE" + "gl-ES" + "it" + "ja-JP" + "km-KH" + "nl" + "nl-BE" + "pl-PL" + "pt" + "pt-AO" + "pt-BR" + "pt-MZ" + "pt-PT" + "ro-RO" + "ru-RU" + "sk-SK" + "sl-SI" + "sv" + "ta-IN" + "tl-PH" + "uk-UA" + "zh-CN" + ]; + + cfg = config.vim.languages.markdown; +in { + options.vim.languages.markdown = { + vale = { + enable = mkEnableOption "Vale linting support"; + package = mkOption { + type = package; + default = pkgs.vale.withStyles (styles: [ + styles.proselint + styles.microsoft + styles.write-good + styles.readability + styles.alex + ]); + description = "Vale package to use"; + }; + }; + ltex = { + enable = mkEnableOption "Enable ltex-ls"; + package = mkOption { + type = package; + default = pkgs.ltex-ls; + }; + language = mkOption { + type = enum languages; + default = "en"; + }; + modelPath = mkOption { + type = str; + default = "~/.config/nvf/models/ngrams/"; + }; + }; + }; + + config = mkMerge [ + (mkIf cfg.vale.enable { + vim.lsp.null-ls = { + enable = true; + sources.vale-lint = + # lua + '' + table.insert( + ls_sources, + null_ls.builtins.diagnostics.vale.with({ + command = "${cfg.vale.package}/bin/vale", + diagnostics_format = "#{m} [#{c}]" + }) + ) + ''; + }; + }) + (mkIf cfg.ltex.enable { + vim.lsp.lspconfig.enable = true; + vim.lsp.lspconfig.sources.ltex-lsp = + # lua + '' + lspconfig.ltex.setup{ + cmd = {"${cfg.ltex.package}/bin/ltex-ls"}, + capabilities = capabilities; + on_attach = default_on_attach; + settings = { + ltex = { + language = "${cfg.ltex.language}", + additionalRules = { + languageModel = "${cfg.ltex.modelPath}", + }, + }, + }, + } + ''; + }) + ]; +} diff --git a/outputs/pkgs/ook-vim/modules/plugins/notes/default.nix b/outputs/pkgs/ook-vim/modules/plugins/notes/default.nix new file mode 100644 index 0000000..f8803b7 --- /dev/null +++ b/outputs/pkgs/ook-vim/modules/plugins/notes/default.nix @@ -0,0 +1,3 @@ +{ + imports = [./obsidian]; +} diff --git a/outputs/pkgs/ook-vim/modules/plugins/obsidian/config.nix b/outputs/pkgs/ook-vim/modules/plugins/notes/obsidian/config.nix similarity index 100% rename from outputs/pkgs/ook-vim/modules/plugins/obsidian/config.nix rename to outputs/pkgs/ook-vim/modules/plugins/notes/obsidian/config.nix diff --git a/outputs/pkgs/ook-vim/modules/plugins/obsidian/default.nix b/outputs/pkgs/ook-vim/modules/plugins/notes/obsidian/default.nix similarity index 100% rename from outputs/pkgs/ook-vim/modules/plugins/obsidian/default.nix rename to outputs/pkgs/ook-vim/modules/plugins/notes/obsidian/default.nix diff --git a/outputs/pkgs/ook-vim/modules/plugins/obsidian/obsidian.nix b/outputs/pkgs/ook-vim/modules/plugins/notes/obsidian/obsidian.nix similarity index 100% rename from outputs/pkgs/ook-vim/modules/plugins/obsidian/obsidian.nix rename to outputs/pkgs/ook-vim/modules/plugins/notes/obsidian/obsidian.nix diff --git a/outputs/pkgs/ook-vim/modules/plugins/notes/render-markdown/render-markdown.nix b/outputs/pkgs/ook-vim/modules/plugins/notes/render-markdown/render-markdown.nix new file mode 100644 index 0000000..ddd35ae --- /dev/null +++ b/outputs/pkgs/ook-vim/modules/plugins/notes/render-markdown/render-markdown.nix @@ -0,0 +1,428 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkOption mkEnableOption; + inherit (lib.types) str nullOr bool enum listOf int float attrsOf submodule; + inherit (lib.nvim.types) mkPluginSetupOption luaInline; + + # All possible Neovim modes + neovimModes = [ + "n" + "no" + "nov" + "noV" + "noCTRL-v" + "niI" + "niR" + "niV" + "nt" + "ntT" + "v" + "vs" + "V" + "Vs" + "CTRL-V" + "CTRL-Vs" + "s" + "S" + "CTRL-S" + "i" + "ic" + "ix" + "R" + "Rc" + "Rx" + "Rv" + "Rvc" + "Rvx" + "c" + "cr" + "cv" + "cvr" + "r" + "rm" + "r?" + "!" + "t" + ]; + + # Preset options + presetOptions = enum ["obsidian" "lazy" "none"]; + + # Log level options + logLevelOptions = enum ["error" "warn" "info" "debug" "trace"]; + + # Anti-conceal ignore options submodule + antiConcealIgnoreOptions = submodule { + options = { + head_icon = mkOption { + type = nullOr (listOf (enum neovimModes)); + default = null; + description = "Modes where head icon anti-conceal behavior will be ignored"; + }; + head_background = mkOption { + type = nullOr (listOf (enum neovimModes)); + default = null; + description = "Modes where head background anti-conceal behavior will be ignored"; + }; + head_border = mkOption { + type = nullOr (listOf (enum neovimModes)); + default = null; + description = "Modes where head border anti-conceal behavior will be ignored"; + }; + code_language = mkOption { + type = nullOr (listOf (enum neovimModes)); + default = null; + description = "Modes where code language anti-conceal behavior will be ignored"; + }; + code_background = mkOption { + type = nullOr bool; + default = true; + description = "Whether to ignore code background anti-conceal behavior"; + }; + code_border = mkOption { + type = nullOr (listOf (enum neovimModes)); + default = null; + description = "Modes where code border anti-conceal behavior will be ignored"; + }; + dash = mkOption { + type = nullOr (listOf (enum neovimModes)); + default = null; + description = "Modes where dash anti-conceal behavior will be ignored"; + }; + bullet = mkOption { + type = nullOr (listOf (enum neovimModes)); + default = null; + description = "Modes where bullet anti-conceal behavior will be ignored"; + }; + check_icon = mkOption { + type = nullOr (listOf (enum neovimModes)); + default = null; + description = "Modes where check icon anti-conceal behavior will be ignored"; + }; + check_scope = mkOption { + type = nullOr (listOf (enum neovimModes)); + default = null; + description = "Modes where check scope anti-conceal behavior will be ignored"; + }; + quote = mkOption { + type = nullOr (listOf (enum neovimModes)); + default = null; + description = "Modes where quote anti-conceal behavior will be ignored"; + }; + table_border = mkOption { + type = nullOr (listOf (enum neovimModes)); + default = null; + description = "Modes where table border anti-conceal behavior will be ignored"; + }; + callout = mkOption { + type = nullOr (listOf (enum neovimModes)); + default = null; + description = "Modes where callout anti-conceal behavior will be ignored"; + }; + link = mkOption { + type = nullOr (listOf (enum neovimModes)); + default = null; + description = "Modes where link anti-conceal behavior will be ignored"; + }; + sign = mkOption { + type = nullOr bool; + default = true; + description = "Whether to ignore sign anti-conceal behavior"; + }; + }; + }; + + # Injection options submodule + injectionOptions = submodule { + options = { + enabled = mkOption { + type = nullOr bool; + default = null; + description = "Whether this injection is enabled"; + }; + query = mkOption { + type = luaInline; + description = "Treesitter query for the injection"; + }; + }; + }; + + headingWidthType = enum ["block" "full"]; + + headingPositionType = enum ["right" "inline" "overlay"]; +in { + options.vim.notes.render-markdown-nvim = { + enable = mkEnableOption "Inline markdown rendering"; + setupOpts = mkPluginSetupOption "render-markdown" { + enabled = mkOption { + type = bool; + default = true; + description = "Whether Markdown should be rendered by default"; + }; + + render_modes = mkOption { + type = listOf (enum neovimModes); + default = ["n" "c" "t"]; + description = '' + Vim modes that will show a rendered view of the markdown file. + Individual components can be enabled for other modes. + ''; + }; + + max_file_size = mkOption { + type = float; + default = 10.0; + description = "Maximum file size (in MB) that this plugin will attempt to render"; + }; + + debounce = mkOption { + type = int; + default = 100; + description = "Milliseconds that must pass before updating marks"; + }; + + preset = mkOption { + type = presetOptions; + default = "none"; + description = "Pre-configured settings to mimic various target user experiences"; + }; + + log_level = mkOption { + type = logLevelOptions; + default = "error"; + description = "The level of logs to write to file"; + }; + + log_runtime = mkOption { + type = bool; + default = false; + description = "Print runtime of main update method"; + }; + + file_types = mkOption { + type = listOf str; + default = ["markdown"]; + description = "Filetypes this plugin will run on"; + }; + + injections = mkOption { + type = attrsOf injectionOptions; + default = { + gitcommit = { + enabled = true; + query = '' + ((message) @injection.content + (#set! injection.combined) + (#set! injection.include-children) + (#set! injection.language "markdown")) + ''; + }; + }; + description = "Language injections for known filetypes"; + }; + + anti_conceal = { + enabled = mkOption { + type = bool; + default = true; + description = "Enable hiding added text on the cursor line"; + }; + + ignore = mkOption { + type = antiConcealIgnoreOptions; + default = { + code_background = true; + sign = true; + }; + description = "Elements to always show, ignoring anti-conceal behavior"; + }; + + above = mkOption { + type = int; + default = 0; + description = "Number of lines above cursor to show"; + }; + + below = mkOption { + type = int; + default = 0; + description = "Number of lines below cursor to show"; + }; + }; + + padding = { + highlight = mkOption { + type = str; + default = "Normal"; + description = "Highlight to use when adding whitespace"; + }; + }; + + on = { + attach = mkOption { + type = nullOr luaInline; + default = null; + description = "Called when plugin initially attaches to a buffer"; + }; + + render = mkOption { + type = nullOr luaInline; + default = null; + description = "Called after plugin renders a buffer"; + }; + }; + + latex = { + enabled = mkOption { + type = nullOr bool; + default = null; + description = "Whether LaTeX should be rendered"; + }; + + render_modes = mkOption { + type = nullOr bool; + default = null; + description = "Additional modes to render LaTeX"; + }; + + converter = mkOption { + type = nullOr str; + default = null; + description = "Executable used to convert latex formula to rendered unicode"; + }; + + highlight = mkOption { + type = nullOr str; + default = null; + description = "Highlight for LaTeX blocks"; + }; + + top_pad = mkOption { + type = nullOr int; + default = null; + description = "Amount of empty lines above LaTeX blocks"; + }; + + bottom_pad = mkOption { + type = nullOr int; + default = null; + description = "Amount of empty lines below LaTeX blocks"; + }; + }; + + heading = { + enabled = mkOption { + type = nullOr bool; + default = null; + description = "Enable heading icon & background rendering"; + }; + + render_modes = mkOption { + type = nullOr bool; + default = null; + description = "Additional modes to render headings"; + }; + + sign = mkOption { + type = nullOr bool; + default = null; + description = "Turn on/off sign column related rendering"; + }; + + icons = mkOption { + type = nullOr (listOf str); + default = null; + description = "Icons for different heading levels"; + }; + + position = mkOption { + type = nullOr headingPositionType; + default = null; + description = "How icons fill available space"; + }; + + signs = mkOption { + type = nullOr (listOf str); + default = null; + description = "Signs added to the sign column if enabled"; + }; + + width = mkOption { + type = nullOr (either headingWidthType (listOf headingWidthType)); + default = null; + description = "Width of the heading background"; + }; + + left_margin = mkOption { + type = nullOr (either float (listOf float)); + default = null; + description = "Margin to add to left of headings"; + }; + + left_pad = mkOption { + type = nullOr (either float (listOf float)); + default = null; + description = "Padding to add to left of headings"; + }; + + right_pad = mkOption { + type = nullOr (either float (listOf float)); + default = null; + description = "Padding to add to right of headings when width is 'block'"; + }; + + min_width = mkOption { + type = nullOr (either int (listOf int)); + default = null; + description = "Minimum width for headings when width is 'block'"; + }; + + border = mkOption { + type = nullOr (either bool (listOf bool)); + default = null; + description = "Add border above and below headings"; + }; + + border_virtual = mkOption { + type = nullOr bool; + default = null; + description = "Always use virtual lines for heading borders"; + }; + + border_prefix = mkOption { + type = nullOr bool; + default = null; + description = "Highlight border start using foreground highlight"; + }; + + above = mkOption { + type = nullOr str; + default = null; + description = "Character used above heading for border"; + }; + + below = mkOption { + type = nullOr str; + default = null; + description = "Character used below heading for border"; + }; + + backgrounds = mkOption { + type = nullOr (listOf str); + default = null; + description = "Highlights for heading backgrounds per level"; + }; + + foregrounds = mkOption { + type = nullOr (listOf str); + default = null; + description = "Highlights for heading and sign icons per level"; + }; + }; + }; + }; +} + From b98b3a1472ea5d8de5c3958510f131c7964267fd Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 25 Jan 2025 20:53:01 +1100 Subject: [PATCH 193/213] equicord: more options --- modules/home/workstation/communication/equicord/default.nix | 4 ++-- modules/home/workstation/communication/equicord/options.nix | 6 ------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/modules/home/workstation/communication/equicord/default.nix b/modules/home/workstation/communication/equicord/default.nix index 9be6fb9..226ae6e 100644 --- a/modules/home/workstation/communication/equicord/default.nix +++ b/modules/home/workstation/communication/equicord/default.nix @@ -1,4 +1,4 @@ { - imports = [./options.nix]; - programs.equicord.enable = true; + #imports = [./options.nix]; + #programs.equicord.enable = true; } diff --git a/modules/home/workstation/communication/equicord/options.nix b/modules/home/workstation/communication/equicord/options.nix index b06f850..33996d0 100644 --- a/modules/home/workstation/communication/equicord/options.nix +++ b/modules/home/workstation/communication/equicord/options.nix @@ -706,11 +706,5 @@ in { config = mkIf cfg.enable { # test file until module is complete xdg.configFile."equibop/test.json".text = builtins.toJSON cfg.settings; - - ooknet.equicord = { - plugins = { - CommandPallete.enabled = true; - }; - }; }; } From 1438b4f9f1a65069abdce9e0840800bb36304814 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sat, 25 Jan 2025 20:53:22 +1100 Subject: [PATCH 194/213] neovim: add debounce flag to ltex-ls --- outputs/pkgs/ook-vim/modules/plugins/languages/markdown.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/outputs/pkgs/ook-vim/modules/plugins/languages/markdown.nix b/outputs/pkgs/ook-vim/modules/plugins/languages/markdown.nix index 4b6ff4b..73833c6 100644 --- a/outputs/pkgs/ook-vim/modules/plugins/languages/markdown.nix +++ b/outputs/pkgs/ook-vim/modules/plugins/languages/markdown.nix @@ -120,6 +120,7 @@ in { cmd = {"${cfg.ltex.package}/bin/ltex-ls"}, capabilities = capabilities; on_attach = default_on_attach; + flags = { debounce_text_changes = 300 }, settings = { ltex = { language = "${cfg.ltex.language}", From 9dee07646df7c56fcfa73fb24259b57a603aff3f Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 26 Jan 2025 14:57:46 +1100 Subject: [PATCH 195/213] deadnix --- .../home/workstation/communication/equicord/options.nix | 2 +- .../plugins/notes/render-markdown/render-markdown.nix | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/modules/home/workstation/communication/equicord/options.nix b/modules/home/workstation/communication/equicord/options.nix index 33996d0..839f513 100644 --- a/modules/home/workstation/communication/equicord/options.nix +++ b/modules/home/workstation/communication/equicord/options.nix @@ -5,7 +5,7 @@ ... }: let inherit (lib) mkIf mkOption mkEnableOption mkPackageOption; - inherit (lib.types) listOf str int enum numbers oneOf nullOr attrsOf submodule bool strMatching; + inherit (lib.types) listOf str int enum numbers oneOf bool strMatching; mkBoolOption = default: description: mkOption { type = bool; diff --git a/outputs/pkgs/ook-vim/modules/plugins/notes/render-markdown/render-markdown.nix b/outputs/pkgs/ook-vim/modules/plugins/notes/render-markdown/render-markdown.nix index ddd35ae..775447d 100644 --- a/outputs/pkgs/ook-vim/modules/plugins/notes/render-markdown/render-markdown.nix +++ b/outputs/pkgs/ook-vim/modules/plugins/notes/render-markdown/render-markdown.nix @@ -1,10 +1,6 @@ -{ - lib, - config, - ... -}: let +{lib, ...}: let inherit (lib) mkOption mkEnableOption; - inherit (lib.types) str nullOr bool enum listOf int float attrsOf submodule; + inherit (lib.types) str nullOr bool enum listOf int float attrsOf submodule either; inherit (lib.nvim.types) mkPluginSetupOption luaInline; # All possible Neovim modes @@ -425,4 +421,3 @@ in { }; }; } - From 38c00f771ba579c2b13f7697d98087d25e853dde Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 26 Jan 2025 15:38:10 +1100 Subject: [PATCH 196/213] flake: bump all inputs --- .github/workflows/cachix.yaml | 1 + flake.lock | 1172 +++++++++++++++++++++++++++------ 2 files changed, 971 insertions(+), 202 deletions(-) diff --git a/.github/workflows/cachix.yaml b/.github/workflows/cachix.yaml index ad29975..ad7d8ad 100644 --- a/.github/workflows/cachix.yaml +++ b/.github/workflows/cachix.yaml @@ -4,6 +4,7 @@ on: push: paths: - outputs/pkgs/** + - flake.lock branches: - main concurrency: diff --git a/flake.lock b/flake.lock index b282215..cd14408 100644 --- a/flake.lock +++ b/flake.lock @@ -28,7 +28,10 @@ "inputs": { "devshell": "devshell", "flake-parts": "flake-parts_2", - "nixpkgs": "nixpkgs_4", + "nixpkgs": [ + "secrets", + "nixpkgs" + ], "pre-commit-hooks": "pre-commit-hooks_2", "treefmt-nix": "treefmt-nix" }, @@ -66,11 +69,11 @@ ] }, "locked": { - "lastModified": 1734906446, - "narHash": "sha256-6OWluVE2A8xi+8V3jN9KA72RCgJjYdyyuLBUjxZ2q2U=", + "lastModified": 1737636397, + "narHash": "sha256-F5MbBj3QVorycVSFE9qjuOTLtIQBqt2VWbXa0uwzm98=", "owner": "hyprwm", "repo": "aquamarine", - "rev": "eecb74dc79bb6752a2a507e6edee3042390a6091", + "rev": "7fe006981fae53e931f513026fc754e322f13145", "type": "github" }, "original": { @@ -81,11 +84,11 @@ }, "crane": { "locked": { - "lastModified": 1734808813, - "narHash": "sha256-3aH/0Y6ajIlfy7j52FGZ+s4icVX0oHhqBzRdlOeztqg=", + "lastModified": 1736898272, + "narHash": "sha256-D10wlrU/HCpSRcb3a7yk+bU3ggpMD1kGbseKtO+7teo=", "owner": "ipetkov", "repo": "crane", - "rev": "72e2d02dbac80c8c86bf6bf3e785536acf8ee926", + "rev": "6a589f034202a7c6e10bce6c5d1d392d7bc0f340", "type": "github" }, "original": { @@ -148,11 +151,11 @@ }, "locked": { "dir": "pkgs/firefox-addons", - "lastModified": 1736120139, - "narHash": "sha256-FAqmrhfoAgGnHUet/CtbPD6fUa579eDNSyL2up97go8=", + "lastModified": 1737864207, + "narHash": "sha256-pmww5SaFlgqYxgzAZ5He/LWMLFWyh37kebwLHBDNvQk=", "owner": "rycee", "repo": "nur-expressions", - "rev": "6a32f225d4ec375b68dda3b94a841199526cd01d", + "rev": "6770d28ffd09fee64fcded7b9f1cbeaf2883a9f6", "type": "gitlab" }, "original": { @@ -199,11 +202,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1735774679, - "narHash": "sha256-soePLBazJk0qQdDVhdbM98vYdssfs3WFedcq+raipRI=", + "lastModified": 1736143030, + "narHash": "sha256-+hu54pAoLDEZT9pjHlqL9DNzWz0NbUn8NEAHP7PQPzU=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "f2f7418ce0ab4a5309a4596161d154cfc877af66", + "rev": "b905f6fc23a9051a6e1b741e1438dbfc0634c6de", "type": "github" }, "original": { @@ -339,11 +342,11 @@ ] }, "locked": { - "lastModified": 1736089250, - "narHash": "sha256-/LPWMiiJGPHGd7ZYEgmbE2da4zvBW0acmshUjYC3WG4=", + "lastModified": 1737762889, + "narHash": "sha256-5HGG09bh/Yx0JA8wtBMAzt0HMCL1bYZ93x4IqzVExio=", "owner": "nix-community", "repo": "home-manager", - "rev": "172b91bfb2b7f5c4a8c6ceac29fd53a01ef07196", + "rev": "daf04c5950b676f47a794300657f1d3d14c1a120", "type": "github" }, "original": { @@ -390,11 +393,11 @@ ] }, "locked": { - "lastModified": 1734906540, - "narHash": "sha256-vQ/L9hZFezC0LquLo4TWXkyniWtYBlFHAKIsDc7PYJE=", + "lastModified": 1737634937, + "narHash": "sha256-Ffw4ujFpi++6pPHe+gCBOfDgAoNlzVPZN6MReC1beu8=", "owner": "hyprwm", "repo": "hyprcursor", - "rev": "69270ba8f057d55b0e6c2dca0e165d652856e613", + "rev": "9c5dd1f7c825ee47f72727ad0a4e16ca46a2688e", "type": "github" }, "original": { @@ -419,11 +422,11 @@ ] }, "locked": { - "lastModified": 1734906236, - "narHash": "sha256-vH/ysV2ONGQgYZPtcJKwc8jJivzyVxru2aaOxC20ZOE=", + "lastModified": 1737634889, + "narHash": "sha256-9JZE3KxcXOqZH9zs3UeadngDiK/yIACTiAR8HSA/TNI=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "6dea3fba08fd704dd624b6d4b261638fb4003c9c", + "rev": "0d77b4895ad5f1bb3b0ee43103a5246c58b65591", "type": "github" }, "original": { @@ -448,11 +451,11 @@ ] }, "locked": { - "lastModified": 1734906236, - "narHash": "sha256-vH/ysV2ONGQgYZPtcJKwc8jJivzyVxru2aaOxC20ZOE=", + "lastModified": 1737634889, + "narHash": "sha256-9JZE3KxcXOqZH9zs3UeadngDiK/yIACTiAR8HSA/TNI=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "6dea3fba08fd704dd624b6d4b261638fb4003c9c", + "rev": "0d77b4895ad5f1bb3b0ee43103a5246c58b65591", "type": "github" }, "original": { @@ -477,11 +480,11 @@ ] }, "locked": { - "lastModified": 1734906236, - "narHash": "sha256-vH/ysV2ONGQgYZPtcJKwc8jJivzyVxru2aaOxC20ZOE=", + "lastModified": 1737634889, + "narHash": "sha256-9JZE3KxcXOqZH9zs3UeadngDiK/yIACTiAR8HSA/TNI=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "6dea3fba08fd704dd624b6d4b261638fb4003c9c", + "rev": "0d77b4895ad5f1bb3b0ee43103a5246c58b65591", "type": "github" }, "original": { @@ -510,11 +513,11 @@ ] }, "locked": { - "lastModified": 1734384160, - "narHash": "sha256-zy2uzmlIORQV6VjIqSPhaoUKPLqfzpUQ5UTjmRfrkdg=", + "lastModified": 1737635556, + "narHash": "sha256-Ahb+xhd80dlzgRSICthPktiDcvi+DqDtHP+YX0TrSdE=", "owner": "hyprwm", "repo": "hypridle", - "rev": "413564cb986cfc67aeb7c4e750b42dc93ff9810f", + "rev": "33ac8cae64226d3a0b63ebf77a22455807895455", "type": "github" }, "original": { @@ -530,8 +533,8 @@ "hyprgraphics": "hyprgraphics", "hyprland-protocols": "hyprland-protocols", "hyprland-qtutils": "hyprland-qtutils", - "hyprlang": "hyprlang", - "hyprutils": "hyprutils", + "hyprlang": "hyprlang_2", + "hyprutils": "hyprutils_2", "hyprwayland-scanner": "hyprwayland-scanner", "nixpkgs": "nixpkgs", "pre-commit-hooks": "pre-commit-hooks", @@ -541,11 +544,11 @@ "xdph": "xdph" }, "locked": { - "lastModified": 1736115553, - "narHash": "sha256-nFagWe+VST+UL+Y/sp4P007PoMpsm6iW+PrWw1VH/Xk=", + "lastModified": 1737842278, + "narHash": "sha256-5N0ExKra/jw3HI/0EEIzmeJKHN9RIBV7ceR/sxQR11s=", "owner": "hyprwm", "repo": "hyprland", - "rev": "f390f48a07d117e24acec59dcf6791bcb3a81110", + "rev": "8b1d6e3009c540457068e23e6c2bc201d20ce4d1", "type": "github" }, "original": { @@ -562,11 +565,11 @@ ] }, "locked": { - "lastModified": 1733056338, - "narHash": "sha256-sp14z0mrqrtmouz1+bU4Jh8/0xi+xwQHF2l7mhGSSVU=", + "lastModified": 1737834765, + "narHash": "sha256-xiThQfn7aCcV8+aQ8qdIornefqRATY6/H+3qqyiiUbQ=", "owner": "hyprwm", "repo": "contrib", - "rev": "d7c55140f1785b8d9fef351f1cd2a4c9e1eaa466", + "rev": "296740785d25b5fe19cce4978050dc5dc704876a", "type": "github" }, "original": { @@ -592,11 +595,11 @@ ] }, "locked": { - "lastModified": 1736115213, - "narHash": "sha256-x15KPKaSDBe07tQqkBnN1CV3kthMe0RTu9QomIr2YHg=", + "lastModified": 1737682243, + "narHash": "sha256-sQh5Wjt+BWzcLmL1/Aaup9slDJfHd952BfxFvJnDsnc=", "owner": "hyprwm", "repo": "hyprland-plugins", - "rev": "b6b31113ce84419c69ed575c22194e4023d2952a", + "rev": "7634792d199d32ed9396d5864e6431cde1cca6bd", "type": "github" }, "original": { @@ -617,11 +620,11 @@ ] }, "locked": { - "lastModified": 1735734474, - "narHash": "sha256-9OV4lOqrEJVLdOrpNN/9msNwAhI6FQTu4N7fufilG08=", + "lastModified": 1737556638, + "narHash": "sha256-laKgI3mr2qz6tas/q3tuGPxMdsGhBi/w+HO+hO2f1AY=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "271df559dd30e4bc5ec6af02d017ac0aaabd63a7", + "rev": "4c75dd5c015c8a0e5a34c6d02a018a650f57feb5", "type": "github" }, "original": { @@ -630,8 +633,37 @@ "type": "github" } }, + "hyprland-qt-support": { + "inputs": { + "hyprlang": "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", "hyprutils": [ "hyprland", "hyprutils" @@ -646,11 +678,11 @@ ] }, "locked": { - "lastModified": 1734906472, - "narHash": "sha256-pWPRv/GA/X/iAwoE6gMNUqn/ZeJX1IeLPRpZI0tTPK0=", + "lastModified": 1737811848, + "narHash": "sha256-WZ7LeiKHk5Y94MU5gHIWn0r8asWxYOvie4LqfCjVIZU=", "owner": "hyprwm", "repo": "hyprland-qtutils", - "rev": "c77109d7e1ddbcdb87cafd32ce411f76328ae152", + "rev": "9c0831ff98856c0f312fcb8b57553fbe3dd34d5b", "type": "github" }, "original": { @@ -660,6 +692,36 @@ } }, "hyprlang": { + "inputs": { + "hyprutils": "hyprutils", + "nixpkgs": [ + "hyprland", + "hyprland-qtutils", + "hyprland-qt-support", + "nixpkgs" + ], + "systems": [ + "hyprland", + "hyprland-qtutils", + "hyprland-qt-support", + "systems" + ] + }, + "locked": { + "lastModified": 1737634606, + "narHash": "sha256-W7W87Cv6wqZ9PHegI6rH1+ve3zJPiyevMFf0/HwdbCQ=", + "owner": "hyprwm", + "repo": "hyprlang", + "rev": "f41271d35cc0f370d300413d756c2677f386af9d", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlang", + "type": "github" + } + }, + "hyprlang_2": { "inputs": { "hyprutils": [ "hyprland", @@ -675,11 +737,11 @@ ] }, "locked": { - "lastModified": 1734906259, - "narHash": "sha256-P79t/7HbACO4/PuJBroGpTptvCWJtXTv+gWsF+sM6MI=", + "lastModified": 1737634606, + "narHash": "sha256-W7W87Cv6wqZ9PHegI6rH1+ve3zJPiyevMFf0/HwdbCQ=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "0404833ea18d543df44df935ebf1b497310eb046", + "rev": "f41271d35cc0f370d300413d756c2677f386af9d", "type": "github" }, "original": { @@ -710,11 +772,11 @@ ] }, "locked": { - "lastModified": 1736008364, - "narHash": "sha256-8gC5tgoJmvPsV2nuCpbt0p9m1+OqZ1aAd16R6y9PlYo=", + "lastModified": 1737837801, + "narHash": "sha256-i7nKSo/FGU5Sjq2xM+UFahZHqqrjZn5WUekOZFsjO2w=", "owner": "hyprwm", "repo": "hyprlock", - "rev": "8f68fad50aa07f1220961d1d23942565e7562d8d", + "rev": "e77bc92b99e06ee66ccd684afbfe3a743af1f01d", "type": "github" }, "original": { @@ -745,11 +807,11 @@ ] }, "locked": { - "lastModified": 1735493740, - "narHash": "sha256-QmfXYQxWmT2w5wx8y4CCADaMdMBiCPxK2M+8/iP1110=", + "lastModified": 1737645174, + "narHash": "sha256-pmkJCzjflvsOytiu2mgn2wfSeyL6mTfoi214T4A2OZQ=", "owner": "hyprwm", "repo": "hyprpaper", - "rev": "505e447b6c48e6b49f3aecf5da276f3cc5780054", + "rev": "7efb4a03464c45bf9fee7b0f428c09462da70a14", "type": "github" }, "original": { @@ -759,6 +821,37 @@ } }, "hyprutils": { + "inputs": { + "nixpkgs": [ + "hyprland", + "hyprland-qtutils", + "hyprland-qt-support", + "hyprlang", + "nixpkgs" + ], + "systems": [ + "hyprland", + "hyprland-qtutils", + "hyprland-qt-support", + "hyprlang", + "systems" + ] + }, + "locked": { + "lastModified": 1737632363, + "narHash": "sha256-X9I8POSlHxBVjD0fiX1O2j7U9Zi1+4rIkrsyHP0uHXY=", + "owner": "hyprwm", + "repo": "hyprutils", + "rev": "006620eb29d54ea9086538891404c78563d1bae1", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprutils", + "type": "github" + } + }, + "hyprutils_2": { "inputs": { "nixpkgs": [ "hyprland", @@ -770,11 +863,11 @@ ] }, "locked": { - "lastModified": 1735316583, - "narHash": "sha256-AiiUwHWHfEdpFzXy7l1x3zInCUa1xcRMrbZ1XRSkzwU=", + "lastModified": 1737725508, + "narHash": "sha256-jGmcPc6y/prg/4A8KGYqJ27nSPaProCMiFadaxNAKvA=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "8f15d45b120b33712f6db477fe5ffb18034d0ea8", + "rev": "fb0c2d1de3d1ef7396d19c18ac09e12bd956929e", "type": "github" }, "original": { @@ -795,11 +888,11 @@ ] }, "locked": { - "lastModified": 1734793513, - "narHash": "sha256-rrrHcXapXJvGFqX+L/Bb0182L25jofAZ0fm1FInvrTQ=", + "lastModified": 1735493474, + "narHash": "sha256-fktzv4NaqKm94VAkAoVqO/nqQlw+X0/tJJNAeCSfzK4=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "4d7367b6eee87397e2dbca2e78078dd0a4ef4c61", + "rev": "de913476b59ee88685fdc018e77b8f6637a2ae0b", "type": "github" }, "original": { @@ -845,11 +938,11 @@ ] }, "locked": { - "lastModified": 1734793513, - "narHash": "sha256-rrrHcXapXJvGFqX+L/Bb0182L25jofAZ0fm1FInvrTQ=", + "lastModified": 1735493474, + "narHash": "sha256-fktzv4NaqKm94VAkAoVqO/nqQlw+X0/tJJNAeCSfzK4=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "4d7367b6eee87397e2dbca2e78078dd0a4ef4c61", + "rev": "de913476b59ee88685fdc018e77b8f6637a2ae0b", "type": "github" }, "original": { @@ -873,28 +966,6 @@ "type": "github" } }, - "naersk": { - "inputs": { - "nixpkgs": [ - "nvf", - "rnix-lsp", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1655042882, - "narHash": "sha256-9BX8Fuez5YJlN7cdPO63InoyBy7dm3VlJkkmTt6fS1A=", - "owner": "nix-community", - "repo": "naersk", - "rev": "cddffb5aa211f50c4b8750adbec0bbbdfb26bb9f", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "naersk", - "type": "github" - } - }, "nil": { "inputs": { "flake-utils": [ @@ -928,11 +999,11 @@ ] }, "locked": { - "lastModified": 1736047960, - "narHash": "sha256-hutd85FA1jUJhhqBRRJ+u7UHO9oFGD/RVm2x5w8WjVQ=", + "lastModified": 1737861961, + "narHash": "sha256-LIRtMvAwLGb8pBoamzgEF67oKlNPz4LuXiRPVZf+TpE=", "owner": "nix-community", "repo": "nix-index-database", - "rev": "816a6ae88774ba7e74314830546c29e134e0dffb", + "rev": "79b7b8eae3243fc5aa9aad34ba6b9bbb2266f523", "type": "github" }, "original": { @@ -943,11 +1014,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1735291276, - "narHash": "sha256-NYVcA06+blsLG6wpAbSPTCyLvxD/92Hy4vlY9WxFI1M=", + "lastModified": 1737632463, + "narHash": "sha256-38J9QfeGSej341ouwzqf77WIHAScihAKCt8PQJ+NH28=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "634fd46801442d760e09493a794c4f15db2d0cbb", + "rev": "0aa475546ed21629c4f5bbf90e38c846a99ec9e9", "type": "github" }, "original": { @@ -969,61 +1040,13 @@ "url": "https://github.com/NixOS/nixpkgs/archive/e9b51731911566bbf7e4895475a87fe06961de0b.tar.gz" } }, - "nixpkgs-stable": { - "locked": { - "lastModified": 1730741070, - "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "d063c1dd113c91ab27959ba540c0d9753409edf3", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-24.05", - "repo": "nixpkgs", - "type": "github" - } - }, "nixpkgs_2": { "locked": { - "lastModified": 1735834308, - "narHash": "sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk=", + "lastModified": 1737746512, + "narHash": "sha256-nU6AezEX4EuahTO1YopzueAXfjFfmCHylYEFCagduHU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6df24922a1400241dae323af55f30e4318a6ca65", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_3": { - "locked": { - "lastModified": 1656753965, - "narHash": "sha256-BCrB3l0qpJokOnIVc3g2lHiGhnjUi0MoXiw6t1o8H1E=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "0ea7a8f1b939d74e5df8af9a8f7342097cdf69eb", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_4": { - "locked": { - "lastModified": 1735471104, - "narHash": "sha256-0q9NGQySwDQc7RhAV2ukfnu7Gxa5/ybJ2ANT8DQrQrs=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "88195a94f390381c6afcdaa933c2f6ff93959cb4", + "rev": "825479c345a7f806485b7f00dbe3abb50641b083", "type": "github" }, "original": { @@ -1063,6 +1086,7 @@ "nixpkgs" ], "nmd": "nmd", + "plugin-aerial-nvim": "plugin-aerial-nvim", "plugin-alpha-nvim": "plugin-alpha-nvim", "plugin-base16": "plugin-base16", "plugin-bufdelete-nvim": "plugin-bufdelete-nvim", @@ -1092,6 +1116,7 @@ "plugin-fidget-nvim": "plugin-fidget-nvim", "plugin-flutter-tools": "plugin-flutter-tools", "plugin-friendly-snippets": "plugin-friendly-snippets", + "plugin-fzf-lua": "plugin-fzf-lua", "plugin-gesture-nvim": "plugin-gesture-nvim", "plugin-gitsigns-nvim": "plugin-gitsigns-nvim", "plugin-glow-nvim": "plugin-glow-nvim", @@ -1113,6 +1138,46 @@ "plugin-lz-n": "plugin-lz-n", "plugin-lzn-auto-require": "plugin-lzn-auto-require", "plugin-mind-nvim": "plugin-mind-nvim", + "plugin-mini-ai": "plugin-mini-ai", + "plugin-mini-align": "plugin-mini-align", + "plugin-mini-animate": "plugin-mini-animate", + "plugin-mini-base16": "plugin-mini-base16", + "plugin-mini-basics": "plugin-mini-basics", + "plugin-mini-bracketed": "plugin-mini-bracketed", + "plugin-mini-bufremove": "plugin-mini-bufremove", + "plugin-mini-clue": "plugin-mini-clue", + "plugin-mini-colors": "plugin-mini-colors", + "plugin-mini-comment": "plugin-mini-comment", + "plugin-mini-completion": "plugin-mini-completion", + "plugin-mini-diff": "plugin-mini-diff", + "plugin-mini-doc": "plugin-mini-doc", + "plugin-mini-extra": "plugin-mini-extra", + "plugin-mini-files": "plugin-mini-files", + "plugin-mini-fuzzy": "plugin-mini-fuzzy", + "plugin-mini-git": "plugin-mini-git", + "plugin-mini-hipatterns": "plugin-mini-hipatterns", + "plugin-mini-hues": "plugin-mini-hues", + "plugin-mini-icons": "plugin-mini-icons", + "plugin-mini-indentscope": "plugin-mini-indentscope", + "plugin-mini-jump": "plugin-mini-jump", + "plugin-mini-jump2d": "plugin-mini-jump2d", + "plugin-mini-map": "plugin-mini-map", + "plugin-mini-misc": "plugin-mini-misc", + "plugin-mini-move": "plugin-mini-move", + "plugin-mini-notify": "plugin-mini-notify", + "plugin-mini-operators": "plugin-mini-operators", + "plugin-mini-pairs": "plugin-mini-pairs", + "plugin-mini-pick": "plugin-mini-pick", + "plugin-mini-sessions": "plugin-mini-sessions", + "plugin-mini-snippets": "plugin-mini-snippets", + "plugin-mini-splitjoin": "plugin-mini-splitjoin", + "plugin-mini-starter": "plugin-mini-starter", + "plugin-mini-statusline": "plugin-mini-statusline", + "plugin-mini-surround": "plugin-mini-surround", + "plugin-mini-tabline": "plugin-mini-tabline", + "plugin-mini-test": "plugin-mini-test", + "plugin-mini-trailspace": "plugin-mini-trailspace", + "plugin-mini-visits": "plugin-mini-visits", "plugin-minimap-vim": "plugin-minimap-vim", "plugin-modes-nvim": "plugin-modes-nvim", "plugin-neo-tree-nvim": "plugin-neo-tree-nvim", @@ -1123,6 +1188,7 @@ "plugin-new-file-template-nvim": "plugin-new-file-template-nvim", "plugin-noice-nvim": "plugin-noice-nvim", "plugin-none-ls": "plugin-none-ls", + "plugin-nord": "plugin-nord", "plugin-nui-nvim": "plugin-nui-nvim", "plugin-nvim-autopairs": "plugin-nvim-autopairs", "plugin-nvim-bufferline-lua": "plugin-nvim-bufferline-lua", @@ -1147,6 +1213,7 @@ "plugin-nvim-tree-lua": "plugin-nvim-tree-lua", "plugin-nvim-treesitter-context": "plugin-nvim-treesitter-context", "plugin-nvim-ts-autotag": "plugin-nvim-ts-autotag", + "plugin-nvim-ufo": "plugin-nvim-ufo", "plugin-nvim-web-devicons": "plugin-nvim-web-devicons", "plugin-obsidian-nvim": "plugin-obsidian-nvim", "plugin-omnisharp-extended": "plugin-omnisharp-extended", @@ -1158,6 +1225,8 @@ "plugin-plenary-nvim": "plugin-plenary-nvim", "plugin-precognition-nvim": "plugin-precognition-nvim", "plugin-project-nvim": "plugin-project-nvim", + "plugin-promise-async": "plugin-promise-async", + "plugin-rainbow-delimiters": "plugin-rainbow-delimiters", "plugin-registers": "plugin-registers", "plugin-render-markdown-nvim": "plugin-render-markdown-nvim", "plugin-rose-pine": "plugin-rose-pine", @@ -1182,17 +1251,16 @@ "plugin-vim-repeat": "plugin-vim-repeat", "plugin-vim-startify": "plugin-vim-startify", "plugin-which-key": "plugin-which-key", - "rnix-lsp": "rnix-lsp", "systems": [ "systems" ] }, "locked": { - "lastModified": 1736124878, - "narHash": "sha256-eJmPe9wSa+PtxyokkEE1Z6sC0SKENdRHyRl0w2FKNJY=", + "lastModified": 1737815146, + "narHash": "sha256-UptKVzFBLGhN25BHsyT9V78FpmWjfXM982YHz8O16T4=", "owner": "notashelf", "repo": "nvf", - "rev": "9888a277adc8a34aa13e9f6bb75c9c86b4f2919a", + "rev": "4242640c9801d6bcd9e72ae942eb92928093b0a5", "type": "github" }, "original": { @@ -1201,6 +1269,22 @@ "type": "github" } }, + "plugin-aerial-nvim": { + "flake": false, + "locked": { + "lastModified": 1736064692, + "narHash": "sha256-7YQtkUTACTMfAGoqoFDPmRrqtw+ypxDbeLCTB3sy4Us=", + "owner": "stevearc", + "repo": "aerial.nvim", + "rev": "b3ec25ca8c347fafa976484a6cace162239112e1", + "type": "github" + }, + "original": { + "owner": "stevearc", + "repo": "aerial.nvim", + "type": "github" + } + }, "plugin-alpha-nvim": { "flake": false, "locked": { @@ -1665,6 +1749,22 @@ "type": "github" } }, + "plugin-fzf-lua": { + "flake": false, + "locked": { + "lastModified": 1737131132, + "narHash": "sha256-0IdADUsIr+SZ0ort92jPPfGIH1EdcwELYz+TCmDCPPI=", + "owner": "ibhagwan", + "repo": "fzf-lua", + "rev": "fbe21aeb147b3dc8b188b5753a8e288ecedcee5e", + "type": "github" + }, + "original": { + "owner": "ibhagwan", + "repo": "fzf-lua", + "type": "github" + } + }, "plugin-gesture-nvim": { "flake": false, "locked": { @@ -2002,6 +2102,646 @@ "type": "github" } }, + "plugin-mini-ai": { + "flake": false, + "locked": { + "lastModified": 1733662803, + "narHash": "sha256-b/776l9nYM9e2atzXrvOk9dCxjzIuW/+iINC/yPv88Y=", + "owner": "echasnovski", + "repo": "mini.ai", + "rev": "ebb04799794a7f94628153991e6334c3304961b8", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.ai", + "type": "github" + } + }, + "plugin-mini-align": { + "flake": false, + "locked": { + "lastModified": 1735582248, + "narHash": "sha256-oHub8dEihIx4kcP3CD9GXG1SUObJUVpH4bg2Z6PmadQ=", + "owner": "echasnovski", + "repo": "mini.align", + "rev": "e715137aece7d05734403d793b8b6b64486bc812", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.align", + "type": "github" + } + }, + "plugin-mini-animate": { + "flake": false, + "locked": { + "lastModified": 1733078395, + "narHash": "sha256-ZePmJuHCCymTgaK46nSg5tRloxs+UKrVgVmT++rGKpc=", + "owner": "echasnovski", + "repo": "mini.animate", + "rev": "d14190ac3040116540889e2ebc25f488b195799e", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.animate", + "type": "github" + } + }, + "plugin-mini-base16": { + "flake": false, + "locked": { + "lastModified": 1734960100, + "narHash": "sha256-VGs4k/xDujPcA0Nv5T18ybSv1iqnzg0AFmaweRdhvDM=", + "owner": "echasnovski", + "repo": "mini.base16", + "rev": "23453dacc1606e5d42238d82f0b42a2985386b62", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.base16", + "type": "github" + } + }, + "plugin-mini-basics": { + "flake": false, + "locked": { + "lastModified": 1730194519, + "narHash": "sha256-R8POaMcgb6SBOxIpanZsswieywapnU7zDNjQMRTkR8U=", + "owner": "echasnovski", + "repo": "mini.basics", + "rev": "67c10b3436d5d3b892715137f4773e71c6753b13", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.basics", + "type": "github" + } + }, + "plugin-mini-bracketed": { + "flake": false, + "locked": { + "lastModified": 1737036218, + "narHash": "sha256-y+tGFF1H37ES/hnEtr3GJK3GeB6D5s8ZdSpvzl+lh3s=", + "owner": "echasnovski", + "repo": "mini.bracketed", + "rev": "0091e11fabe34973fc038a8d0d0485202742e403", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.bracketed", + "type": "github" + } + }, + "plugin-mini-bufremove": { + "flake": false, + "locked": { + "lastModified": 1730726192, + "narHash": "sha256-CB6ZIlrCQlh2W44Knnb10REDcvj4jcYkW/9CiOaoH2E=", + "owner": "echasnovski", + "repo": "mini.bufremove", + "rev": "285bdac9596ee7375db50c0f76ed04336dcd2685", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.bufremove", + "type": "github" + } + }, + "plugin-mini-clue": { + "flake": false, + "locked": { + "lastModified": 1737130586, + "narHash": "sha256-/0DpZV/jXuhaqBz5j4JN3xmofATlwPMHNSm/uTXALg0=", + "owner": "echasnovski", + "repo": "mini.clue", + "rev": "63e42dad781b9ed4845d90ef1da8c52dfb6dce3f", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.clue", + "type": "github" + } + }, + "plugin-mini-colors": { + "flake": false, + "locked": { + "lastModified": 1730726192, + "narHash": "sha256-B2JahCUhKpYwOJrl+BhSp3UQFiyyMGJAYKGK+uMv3fk=", + "owner": "echasnovski", + "repo": "mini.colors", + "rev": "d64b1c0f520579d905f97208eca85329e664ab88", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.colors", + "type": "github" + } + }, + "plugin-mini-comment": { + "flake": false, + "locked": { + "lastModified": 1736611383, + "narHash": "sha256-vAgBDSVtXCP+rlu+cmXdoZQBGShyH7KfL8E/gvDMfnM=", + "owner": "echasnovski", + "repo": "mini.comment", + "rev": "6e1f9a8ebbf6f693fa3787ceda8ca3bf3cb6aec7", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.comment", + "type": "github" + } + }, + "plugin-mini-completion": { + "flake": false, + "locked": { + "lastModified": 1732271068, + "narHash": "sha256-dlQCfHUQX9rPiSYZSRipezHX0CG/redbV2g7cpwwExY=", + "owner": "echasnovski", + "repo": "mini.completion", + "rev": "6eb9546685c4e1c4af2365b87166d4afa39d8a1b", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.completion", + "type": "github" + } + }, + "plugin-mini-diff": { + "flake": false, + "locked": { + "lastModified": 1735324663, + "narHash": "sha256-dRvW/1lfVShiHmRU0mQA5g5xDyQ0EVtVLLZ0y6WSedg=", + "owner": "echasnovski", + "repo": "mini.diff", + "rev": "00f072250061ef498f91ed226918c9ec31a416a4", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.diff", + "type": "github" + } + }, + "plugin-mini-doc": { + "flake": false, + "locked": { + "lastModified": 1723308950, + "narHash": "sha256-Q3DAEV1ZHS+lFhZKFCNoIjn41ksk7WRrVP2b2d6uSss=", + "owner": "echasnovski", + "repo": "mini.doc", + "rev": "bb73a3d1ff390f7e2740027ea2567017099a237c", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.doc", + "type": "github" + } + }, + "plugin-mini-extra": { + "flake": false, + "locked": { + "lastModified": 1736279066, + "narHash": "sha256-lUJrviUjAmJ70g2y93aNw3e1mHGHoB9lbh44HGP7zQs=", + "owner": "echasnovski", + "repo": "mini.extra", + "rev": "477e3dda7b597b49bc1373951ea7da4da834c352", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.extra", + "type": "github" + } + }, + "plugin-mini-files": { + "flake": false, + "locked": { + "lastModified": 1736535707, + "narHash": "sha256-UHW78m4BiYMMrABwdkyyzQUENgQrVFbWJnmNdRMtr0w=", + "owner": "echasnovski", + "repo": "mini.files", + "rev": "d0f03a5c38836fd2cce3dc80734124959002078c", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.files", + "type": "github" + } + }, + "plugin-mini-fuzzy": { + "flake": false, + "locked": { + "lastModified": 1730726192, + "narHash": "sha256-XvDkDfwPcBxySuz58f2mpWTeo8EsOnMvZUcNI8HNZg8=", + "owner": "echasnovski", + "repo": "mini.fuzzy", + "rev": "faa5a6c0d29c28012c90bd011162963a58715428", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.fuzzy", + "type": "github" + } + }, + "plugin-mini-git": { + "flake": false, + "locked": { + "lastModified": 1736535710, + "narHash": "sha256-rXuKopyZBCBbpKuytCdm8keruSNK1ohk2NdeZv1wifI=", + "owner": "echasnovski", + "repo": "mini-git", + "rev": "fc13dde6cfe87cf25a4fd1ee177c0d157468436b", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini-git", + "type": "github" + } + }, + "plugin-mini-hipatterns": { + "flake": false, + "locked": { + "lastModified": 1733141274, + "narHash": "sha256-zJ8OMzfcBh9NtSg2FHDjB5DFX9C2qZRo8t8lc097sCI=", + "owner": "echasnovski", + "repo": "mini.hipatterns", + "rev": "f34975103a38b3f608219a1324cdfc58ea660b8b", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.hipatterns", + "type": "github" + } + }, + "plugin-mini-hues": { + "flake": false, + "locked": { + "lastModified": 1734960100, + "narHash": "sha256-4y79ejOkRL/fajZ4jC8t4K6EgNbnTsH++mIjmo6G3q0=", + "owner": "echasnovski", + "repo": "mini.hues", + "rev": "ae6ad4c666ff42c1102344fe1eba18bb486f2e46", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.hues", + "type": "github" + } + }, + "plugin-mini-icons": { + "flake": false, + "locked": { + "lastModified": 1737036219, + "narHash": "sha256-w0PxiTj9uiUffZXkMM18IO/b/zPpdRKW9ydyhvXRoqE=", + "owner": "echasnovski", + "repo": "mini.icons", + "rev": "910db5df9724d65371182948f921fce23c2c881e", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.icons", + "type": "github" + } + }, + "plugin-mini-indentscope": { + "flake": false, + "locked": { + "lastModified": 1737036220, + "narHash": "sha256-Mrzc7oHXxyEGqdE003qiC9unScyb7i5A6+l8Do7yxws=", + "owner": "echasnovski", + "repo": "mini.indentscope", + "rev": "613df2830d7faeae7483ba2e736683154b95921e", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.indentscope", + "type": "github" + } + }, + "plugin-mini-jump": { + "flake": false, + "locked": { + "lastModified": 1733662809, + "narHash": "sha256-qMP9ezk4xZov5S4vrUFM62lnc4YkEaZL1EVzdXwDq1Q=", + "owner": "echasnovski", + "repo": "mini.jump", + "rev": "bb93d998c9db6936697746330411f5fb9957145e", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.jump", + "type": "github" + } + }, + "plugin-mini-jump2d": { + "flake": false, + "locked": { + "lastModified": 1733662811, + "narHash": "sha256-+DihKCh6GYwin3H9YD+q30MLMRNXvvb1GtKnfBinGjc=", + "owner": "echasnovski", + "repo": "mini.jump2d", + "rev": "88077058297e80f1c76a18ed801ae9d7064187c6", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.jump2d", + "type": "github" + } + }, + "plugin-mini-map": { + "flake": false, + "locked": { + "lastModified": 1725613927, + "narHash": "sha256-dL+d92+GLAILQ/A1JVCwoe3B5WtwVK01tPuC+fOTB5A=", + "owner": "echasnovski", + "repo": "mini.map", + "rev": "4c58e755d75f9999abcd3b3c6e934734b6a8b098", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.map", + "type": "github" + } + }, + "plugin-mini-misc": { + "flake": false, + "locked": { + "lastModified": 1734103112, + "narHash": "sha256-qnYa4IZk14MGZArmVpn15l+P9cwtFWomBVxRuYHVyXc=", + "owner": "echasnovski", + "repo": "mini.misc", + "rev": "645fb9367c19bb485902e54e5451425981498601", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.misc", + "type": "github" + } + }, + "plugin-mini-move": { + "flake": false, + "locked": { + "lastModified": 1723711319, + "narHash": "sha256-nX0eAlhMnKhAftgM6qeHUuawagumLQMPKDkqZNPLljg=", + "owner": "echasnovski", + "repo": "mini.move", + "rev": "4caa1c212f5ca3d1633d21cfb184808090ed74b1", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.move", + "type": "github" + } + }, + "plugin-mini-notify": { + "flake": false, + "locked": { + "lastModified": 1736790793, + "narHash": "sha256-q27j14OV6LAfoxeqBG75GSiqtqmW37GOPHpmA2fD4gs=", + "owner": "echasnovski", + "repo": "mini.notify", + "rev": "05e598d5b349bd66404d576e6a4d4340aea5f194", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.notify", + "type": "github" + } + }, + "plugin-mini-operators": { + "flake": false, + "locked": { + "lastModified": 1731776514, + "narHash": "sha256-+Zhy0AhuMPSHnM6dqbV45Aa7dS7XJ4mpfcHApSbuy8A=", + "owner": "echasnovski", + "repo": "mini.operators", + "rev": "7cb4dc66c51a3d736d347bbc517dc73dc7d28888", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.operators", + "type": "github" + } + }, + "plugin-mini-pairs": { + "flake": false, + "locked": { + "lastModified": 1728656795, + "narHash": "sha256-PtHxLKU1smVTx655r5SINxuz5CJmZWnBW70T8zJ/oxM=", + "owner": "echasnovski", + "repo": "mini.pairs", + "rev": "7e834c5937d95364cc1740e20d673afe2d034cdb", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.pairs", + "type": "github" + } + }, + "plugin-mini-pick": { + "flake": false, + "locked": { + "lastModified": 1736696004, + "narHash": "sha256-Q4GD0WzUYNtoBMx8pIl6fX5glKn1oflS4HZVC+w/eAM=", + "owner": "echasnovski", + "repo": "mini.pick", + "rev": "09ade94d2c9c5133db9ae00f3693d82eae78e9be", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.pick", + "type": "github" + } + }, + "plugin-mini-sessions": { + "flake": false, + "locked": { + "lastModified": 1735582250, + "narHash": "sha256-vyn8MGyOWFgJ5QVvjYb7K1cKDtg9qWnWYMNf80+kpHk=", + "owner": "echasnovski", + "repo": "mini.sessions", + "rev": "71c9ae596664ac110560d27eb928fc24e22bc53d", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.sessions", + "type": "github" + } + }, + "plugin-mini-snippets": { + "flake": false, + "locked": { + "lastModified": 1736611383, + "narHash": "sha256-How9m7KTo66FrwjZQlgZRmJ5toFKn/+GnUbx/0va3lM=", + "owner": "echasnovski", + "repo": "mini.snippets", + "rev": "72920f62e3dd1330720e94e8f5d42592f3a1ecf8", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.snippets", + "type": "github" + } + }, + "plugin-mini-splitjoin": { + "flake": false, + "locked": { + "lastModified": 1719822504, + "narHash": "sha256-LDIbh5KfupTI4zkYOlLmVCd3DuZRhx5lTASN53VG34g=", + "owner": "echasnovski", + "repo": "mini.splitjoin", + "rev": "3e92f6764e770ba392325cad3a4497adcada695f", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.splitjoin", + "type": "github" + } + }, + "plugin-mini-starter": { + "flake": false, + "locked": { + "lastModified": 1736858747, + "narHash": "sha256-pJYkZUo+L3IeGCRdTipqTzMv+HatpNnyRxshaygKtIw=", + "owner": "echasnovski", + "repo": "mini.starter", + "rev": "4b257cfc93241e8c8cde3f9302d1616ad4e0d036", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.starter", + "type": "github" + } + }, + "plugin-mini-statusline": { + "flake": false, + "locked": { + "lastModified": 1735582251, + "narHash": "sha256-AQ2N93JDjtFpgerWTzRspmxrl9oQuALbeCUxBO4ZPqo=", + "owner": "echasnovski", + "repo": "mini.statusline", + "rev": "1b0edf76fe2af015f8c989385ff949f1db7aade2", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.statusline", + "type": "github" + } + }, + "plugin-mini-surround": { + "flake": false, + "locked": { + "lastModified": 1733662812, + "narHash": "sha256-okWJlG0KOdg1ShvkIIMnPSoOzGd7K84eDcp5kx6eVP8=", + "owner": "echasnovski", + "repo": "mini.surround", + "rev": "aa5e245829dd12d8ff0c96ef11da28681d6049aa", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.surround", + "type": "github" + } + }, + "plugin-mini-tabline": { + "flake": false, + "locked": { + "lastModified": 1729176541, + "narHash": "sha256-nucUqSN8w2xBnDp1dFBgRVVvfVoqZMdx7Zj78wdFAP0=", + "owner": "echasnovski", + "repo": "mini.tabline", + "rev": "06ef4ecaeca2e362c7d31113435d86d144b3cbbe", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.tabline", + "type": "github" + } + }, + "plugin-mini-test": { + "flake": false, + "locked": { + "lastModified": 1729520957, + "narHash": "sha256-NtsX441k84owAAJywq4G2rMvV6d7UR2K75G8oKam+gs=", + "owner": "echasnovski", + "repo": "mini.test", + "rev": "86a64d5a4bf9d73ebf5875edaae0d878f64f5e48", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.test", + "type": "github" + } + }, + "plugin-mini-trailspace": { + "flake": false, + "locked": { + "lastModified": 1725613928, + "narHash": "sha256-JKYvFz8g8kVZvxE44RhwoHXQykghXx7ebW/Mj1ZdJIw=", + "owner": "echasnovski", + "repo": "mini.trailspace", + "rev": "3a328e62559c33014e422fb9ae97afc4208208b1", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.trailspace", + "type": "github" + } + }, + "plugin-mini-visits": { + "flake": false, + "locked": { + "lastModified": 1737036221, + "narHash": "sha256-Q+m1gZ5Obu6Zzo87Djt6VCX76ZjdOiLb0j771jP8uQE=", + "owner": "echasnovski", + "repo": "mini.visits", + "rev": "90f20ba6ab7d3d7cb984fffddd82f5f6c7a6bea7", + "type": "github" + }, + "original": { + "owner": "echasnovski", + "repo": "mini.visits", + "type": "github" + } + }, "plugin-minimap-vim": { "flake": false, "locked": { @@ -2163,6 +2903,22 @@ "type": "github" } }, + "plugin-nord": { + "flake": false, + "locked": { + "lastModified": 1737019140, + "narHash": "sha256-ZhDS7Y90DKp+jkUqcoQRf/zHy4DVgSDQXrnl3sBYJXs=", + "owner": "gbprod", + "repo": "nord.nvim", + "rev": "b0f3ed242fd8e5bafa7231367821d46c6c835dd8", + "type": "github" + }, + "original": { + "owner": "gbprod", + "repo": "nord.nvim", + "type": "github" + } + }, "plugin-nui-nvim": { "flake": false, "locked": { @@ -2547,6 +3303,22 @@ "type": "github" } }, + "plugin-nvim-ufo": { + "flake": false, + "locked": { + "lastModified": 1735147722, + "narHash": "sha256-etyfm4KpwjYN+kkotOMl0LgbQniILmqMqab4acMtTlw=", + "owner": "kevinhwang91", + "repo": "nvim-ufo", + "rev": "32cb247b893a384f1888b9cd737264159ecf183c", + "type": "github" + }, + "original": { + "owner": "kevinhwang91", + "repo": "nvim-ufo", + "type": "github" + } + }, "plugin-nvim-web-devicons": { "flake": false, "locked": { @@ -2723,6 +3495,38 @@ "type": "github" } }, + "plugin-promise-async": { + "flake": false, + "locked": { + "lastModified": 1722813441, + "narHash": "sha256-9eM66brPjiFlY64vmBetRYrKnpDyN7+/URMm4GsGimA=", + "owner": "kevinhwang91", + "repo": "promise-async", + "rev": "119e8961014c9bfaf1487bf3c2a393d254f337e2", + "type": "github" + }, + "original": { + "owner": "kevinhwang91", + "repo": "promise-async", + "type": "github" + } + }, + "plugin-rainbow-delimiters": { + "flake": false, + "locked": { + "lastModified": 1736686348, + "narHash": "sha256-zWHXYs3XdnoszqOFY3hA2L5mNn1a44OAeKv3lL3EMEw=", + "owner": "HiPhish", + "repo": "rainbow-delimiters.nvim", + "rev": "85b80abaa09cbbc039e3095b2f515b3cf8cadd11", + "type": "github" + }, + "original": { + "owner": "HiPhish", + "repo": "rainbow-delimiters.nvim", + "type": "github" + } + }, "plugin-registers": { "flake": false, "locked": { @@ -3114,15 +3918,14 @@ "nixpkgs": [ "hyprland", "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" + ] }, "locked": { - "lastModified": 1734797603, - "narHash": "sha256-ulZN7ps8nBV31SE+dwkDvKIzvN6hroRY8sYOT0w+E28=", + "lastModified": 1737465171, + "narHash": "sha256-R10v2hoJRLq8jcL4syVFag7nIGE7m13qO48wRIukWNg=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "f0f0dc4920a903c3e08f5bdb9246bb572fcae498", + "rev": "9364dc02281ce2d37a1f55b6e51f7c0f65a75f17", "type": "github" }, "original": { @@ -3155,26 +3958,6 @@ "type": "github" } }, - "rnix-lsp": { - "inputs": { - "naersk": "naersk", - "nixpkgs": "nixpkgs_3", - "utils": "utils" - }, - "locked": { - "lastModified": 1669555118, - "narHash": "sha256-F0s0m62S5bHNVWNHLZD6SeHiLrsDx98VQbRjDyIu+qQ=", - "owner": "nix-community", - "repo": "rnix-lsp", - "rev": "95d40673fe43642e2e1144341e86d0036abd95d9", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "rnix-lsp", - "type": "github" - } - }, "root": { "inputs": { "firefox-addons": "firefox-addons", @@ -3225,11 +4008,11 @@ ] }, "locked": { - "lastModified": 1734834660, - "narHash": "sha256-bm8V+Cu8rWJA+vKQnc94mXTpSDgvedyoDKxTVi/uJfw=", + "lastModified": 1737166965, + "narHash": "sha256-vlDROBAgq+7PEVM0vaS2zboY6DXs3oKK0qW/1dVuFs4=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "b070e6030118680977bc2388868c4b3963872134", + "rev": "fc839c9d5d1ebc789b4657c43c4d54838c7c01de", "type": "github" }, "original": { @@ -3253,11 +4036,11 @@ ] }, "locked": { - "lastModified": 1737363899, - "narHash": "sha256-9W7+5Mx2J60I/s6mgq6iRcxIV06nrBr6KWzN55GWnYE=", + "lastModified": 1737365729, + "narHash": "sha256-k3XwPxuGMBSe0rz7C00br7qO2K4R3Eh0ZjYRo2wthZM=", "ref": "refs/heads/master", - "rev": "ec8227f9dacaef659249df279d6fd98776ebaeb6", - "revCount": 25, + "rev": "caf59a774002ea041b11322850e3fa5d225f080e", + "revCount": 26, "type": "git", "url": "ssh://git@github.com/ooks-io/kunzen" }, @@ -3333,21 +4116,6 @@ "type": "github" } }, - "utils": { - "locked": { - "lastModified": 1656928814, - "narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "xdph": { "inputs": { "hyprland-protocols": [ @@ -3376,11 +4144,11 @@ ] }, "locked": { - "lastModified": 1734907020, - "narHash": "sha256-p6HxwpRKVl1KIiY5xrJdjcEeK3pbmc///UOyV6QER+w=", + "lastModified": 1737634991, + "narHash": "sha256-dBAnb7Kbnier30cA7AgxVSxxARmxKZ1vHZT33THSIr8=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "d7f18dda5e511749fa1511185db3536208fb1a63", + "rev": "e09dfe2726c8008f983e45a0aa1a3b7416aaeb8a", "type": "github" }, "original": { @@ -3399,11 +4167,11 @@ "rust-overlay": "rust-overlay_2" }, "locked": { - "lastModified": 1735846901, - "narHash": "sha256-rcyuAGKYYSLHueXGSktzCSHOO4gHyg6KDi6R9aIFpug=", + "lastModified": 1737741991, + "narHash": "sha256-FCIlCT8HNEVEWwtiL5zwWH01XW1vHir83HWodfKeWU4=", "owner": "dj95", "repo": "zjstatus", - "rev": "bc15143d662f2c22fced866b0376d360ebc5f36c", + "rev": "8e9aa9d977ec70991c4e4cde8bcda9942dee3f5d", "type": "github" }, "original": { From b631904365a76792fe1d8a1e4bee4ca49e55355a Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 26 Jan 2025 21:57:49 +1100 Subject: [PATCH 197/213] docs: readme --- .../2025-01-26T21:52:48,481278761+11:00.png | Bin 0 -> 374240 bytes .gitignore | 1 + .repomixignore | 5 + README.md | 125 ++++++++++++++++++ repomix.config.json | 25 ++++ 5 files changed, 156 insertions(+) create mode 100644 .github/assets/2025-01-26T21:52:48,481278761+11:00.png create mode 100644 .gitignore create mode 100644 .repomixignore create mode 100644 README.md create mode 100644 repomix.config.json diff --git a/.github/assets/2025-01-26T21:52:48,481278761+11:00.png b/.github/assets/2025-01-26T21:52:48,481278761+11:00.png new file mode 100644 index 0000000000000000000000000000000000000000..4b64ffa1cdf141c7e857f5d21c18a36fd9fc9560 GIT binary patch literal 374240 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 )+p!X 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

IQ7rayn4rT?6hE>&|{^Vdb$<<4Ag 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⁣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'nFm!vL>p%7G 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 literal 0 HcmV?d00001 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a40c183 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +repodump.xml diff --git a/.repomixignore b/.repomixignore new file mode 100644 index 0000000..221341a --- /dev/null +++ b/.repomixignore @@ -0,0 +1,5 @@ +*.lock +**/equicord/options.nix +**/gruv.nix +.repomixignore +repomix* diff --git a/README.md b/README.md new file mode 100644 index 0000000..16616c7 --- /dev/null +++ b/README.md @@ -0,0 +1,125 @@ +

ooknet

+

A monorepo for all my nix expressions powered by flake-parts.

+ +## Overview + +This repository serves two main purposes: + +1. Centralized location for all my personal computing infrastructure. +2. A place to experiment and learn about networking, administration, security, + unix, design and programming. + +> [!WARNING] +> This repository is not intended to be used by anyone but myself. It is highly +> personalized and likely doesn't fit anyone else's needs. I leave this +> repository public to serve as a reference for anyone else building a something +> similar. + +## Features + +- NixOS configurations for all my hosts +- Home-manager configuration for my workstations +- Custom packages +- Development environments +- Declarative secrets with agenix +- Personal website +- Templates for bootstrapping projects + +## Fleet + +Below are all the hosts I currently maintain within this flake: + +| host | spec | role | description | architecture | status | +| --------- | ------------------------------------- | ----------- | --------------------------------- | ------------ | ------ | +| ooksdesk | 7500F / RX5700XT / 32 GB DDR5 | Workstation | Primary desktop workstation | x86_64-linux | UP | +| ookst480s | T480s / i5-8350U / 24 GB DDR4 | Workstation | Primary mobile workstation | x86_64-linux | UP | +| ooksmicro | GPD Micro PC / N8100 / 8 GB LPDR3 | Workstation | Pocket workstation | x86_64-linux | UP | +| ooksmedia | i3-10100 / 1650 Super / 8 GB DDR4 | Server | Homelab/Media server | x86_64-linux | UP | +| ooksx1 | X1 Carbon G4 / i5 6200U / 8 GB LPDDR3 | Workstation | Alternative mobile workstation | x86_64-linux | DOWN | +| ooknode | Linode Nanode | Server | VPS for website | x86_64-linux | UP | +| ooksphone | Termux | Workstation | Nix environment for android phone | x86_64-linux | DOWN | + +## Architecture + +I like to experiment with different ideas a lot. Due to that, much of this is +subject to change. I will try to keep this readme as up to date as possible. + +I won't go too indepth here, as everything is subject to change. But here is the +high-level. + +One of the main goals of this project was to allow for easy bootstrapping of new +hosts while maintaining fine-grained configuration on a per-host basis. This is +accomplished using a roles and profiles pattern (similar to +[Puppet's roles and profiles method](https://www.puppet.com/docs/puppet/7/the_roles_and_profiles_method.html)). + +#### Roles + +- **Workstation**: Desktop/laptop systems with GUI environment +- **Server**: Headless systems running specific services + +Roles are declared via their own respective helper functions `mkWorkstation` and +`mkServer`. Both being simple wrappers of +[`lib.nixosSystem`](https://github.com/NixOS/nixpkgs/blob/e5db80ae487b59b4e9f950d68983ffb0575e26c6/flake.nix#L21) +(also see [`lib.evalModules`](https://noogle.dev/f/lib/evalModules)). These +functions serve to abstract the boilerplate, leaving a simple interface for +declaring hosts. + +Example: + +```nix +flake.nixosConfigurations = { + ookst480s = mkWorkstation { + inherit withSystem; + system = "x86_64-linux"; + hostname = "ookst480s"; + type = "laptop"; + }; + ooknode = mkServer { + inherit withSystem; + system = "x86_64-linux"; + hostname = "ooknode"; + domain = "ooknet.org"; + type = "vm"; + profile = "linode"; + services = ["website" "forgejo"]; + }; +}; +``` + +#### Profiles + +Profiles are collections of related software and configurations that can be +enabled on a per-host basis. Here are some example profiles for workstations: + +- `gaming`: Steam & emulators +- `communication`: Discord, Teams, Matrix +- `productivity`: Document editing, note-taking +- `creative`: Art and design tools +- `media`: Audio/video playback and management +- `virtualization`: Virtual machine support + +Example configuration: + +```nix +ooknet.workstation.profiles = ["gaming" "creative" "media"]; +``` + +For servers, profiles are defined as services. For example: + +- `ookflix`: Media server services +- `forgjo`: Git server +- `website`: My static website + +```nix +ooknet.server.services = ["ookflix"]; +``` + +## Desktop environment + +All workstations run a minimal hyprland configuration made from a few +components: + +- Hyprland +- Hypr* ware (hypridle, hyprlock, hyprpaper) +- Waybar (status bar) +- Mako (notifications) diff --git a/repomix.config.json b/repomix.config.json new file mode 100644 index 0000000..c0f1d48 --- /dev/null +++ b/repomix.config.json @@ -0,0 +1,25 @@ +{ + "output": { + "filePath": "repodump.xml", + "style": "xml", + "fileSummary": true, + "directoryStructure": true, + "removeComments": false, + "removeEmptyLines": false, + "topFilesLength": 5, + "showLineNumbers": false, + "copyToClipboard": false + }, + "include": [], + "ignore": { + "useGitignore": true, + "useDefaultPatterns": true, + "customPatterns": [] + }, + "security": { + "enableSecurityCheck": true + }, + "tokenCount": { + "encoding": "o200k_base" + } +} From 28cbe5f554a14baea13003347de1dcb09f73d8e8 Mon Sep 17 00:00:00 2001 From: ooks-io <68526158+ooks-io@users.noreply.github.com> Date: Sun, 26 Jan 2025 22:15:26 +1100 Subject: [PATCH 198/213] docs: add screenshot to readme --- README.md | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 16616c7..30631d4 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,8 @@ Below are all the hosts I currently maintain within this flake: I like to experiment with different ideas a lot. Due to that, much of this is subject to change. I will try to keep this readme as up to date as possible. -I won't go too indepth here, as everything is subject to change. But here is the -high-level. +I won't go too in-depth here, as everything is subject to change. But here is +the high-level. One of the main goals of this project was to allow for easy bootstrapping of new hosts while maintaining fine-grained configuration on a per-host basis. This is @@ -116,10 +116,38 @@ ooknet.server.services = ["ookflix"]; ## Desktop environment -All workstations run a minimal hyprland configuration made from a few + +All workstations currently run a minimal wayland configuration made from a few components: -- Hyprland -- Hypr* ware (hypridle, hyprlock, hyprpaper) -- Waybar (status bar) -- Mako (notifications) +- [Hyprland](https://github.com/hyprwm/Hyprland) +- Hypr* ware ([hypridle](https://github.com/hyprwm/hypridle), + [hyprlock](https://github.com/hyprwm/hyprlock), + [hyprpaper](https://github.com/hyprwm/hyprpaper)) +- [Waybar](https://github.com/Alexays/Waybar) +- [Mako](https://github.com/emersion/mako) +- [Gruvbox extended](https://github.com/ooks-io/ooknet/blob/main/outputs/hozen/default.nix) + +## Appreciation + +I want to give some appreciation to the many people/resources who have helped in +some way to build this project. + +#### People + +- [ghuntley](https://github.com/ghuntley) +- [NobbZ](https://github.com/NobbZ) +- [notashelf](https://github.com/NotAShelf) +- [mic92](https://github.com/Mic92) +- [fabaff](https://github.com/fabaff) +- [gerg-l](https://github.com/Gerg-L) +- [viperML](https://github.com/viperML) +- [colemickens](https://github.com/colemickens) +- [fufexan](https://github.com/fufexan) +- [max-privatevoid](https://github.com/max-privatevoid) + +### Resources + +- [nix.dev](https://nix.dev/) +- [noogle](https://noogle.dev/) +- [nix-pills](https://nixos.org/guides/nix-pills/) From 68af92924f33f373562bed38ae47204e7f6ba2a7 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 26 Jan 2025 22:40:28 +1100 Subject: [PATCH 199/213] ci: ignore readme --- .github/workflows/check.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index b73fb8e..8c1c92e 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -6,6 +6,10 @@ on: - main paths-ignore: - .github/** + - README.md + - .repomixignore + - repomix.config.json + - .gitignore concurrency: group: ooknet-check-${{ github.ref }} cancel-in-progress: true From 9bd427e3654c831ff7ca0f0307d67dadf9f61ed5 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Sun, 26 Jan 2025 22:47:55 +1100 Subject: [PATCH 200/213] docs: minor tweaks --- README.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 30631d4..f26b6b0 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,15 @@ This repository serves two main purposes: -1. Centralized location for all my personal computing infrastructure. -2. A place to experiment and learn about networking, administration, security, - unix, design and programming. +1. To serve as a centralized location for all my personal computing + infrastructure +2. To provide a place to experiment and learn about networking, administration, + security, unix, design, and programming > [!WARNING] > This repository is not intended to be used by anyone but myself. It is highly > personalized and likely doesn't fit anyone else's needs. I leave this -> repository public to serve as a reference for anyone else building a something +> repository public to serve as a reference for anyone else building something > similar. ## Features @@ -41,11 +42,9 @@ Below are all the hosts I currently maintain within this flake: ## Architecture -I like to experiment with different ideas a lot. Due to that, much of this is -subject to change. I will try to keep this readme as up to date as possible. - -I won't go too in-depth here, as everything is subject to change. But here is -the high-level. +As this project serves as a learning environment, its architecture changes +frequently. While I'll try to keep this documentation current, what follows is a +high-level overview of the current design. One of the main goals of this project was to allow for easy bootstrapping of new hosts while maintaining fine-grained configuration on a per-host basis. This is @@ -133,7 +132,7 @@ components: I want to give some appreciation to the many people/resources who have helped in some way to build this project. -#### People +### People - [ghuntley](https://github.com/ghuntley) - [NobbZ](https://github.com/NobbZ) From 84849d5b2db0f8bb2662c5e432fc98cc19005fd7 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 28 Jan 2025 19:55:21 +1100 Subject: [PATCH 201/213] userDirs: Summit init --- modules/home/base/userDirs.nix | 15 +++++++++------ .../home/workstation/productivity/obsidian.nix | 2 +- outputs/pkgs/ook-vim/config/plugins/notes.nix | 6 +++--- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/modules/home/base/userDirs.nix b/modules/home/base/userDirs.nix index 000a2f2..87bb54a 100644 --- a/modules/home/base/userDirs.nix +++ b/modules/home/base/userDirs.nix @@ -6,18 +6,21 @@ dataHome = "${config.home.homeDirectory}/.local/share"; stateHome = "${config.home.homeDirectory}/.local/state"; - userDirs = { + userDirs = let + summit = "${config.home.homeDirectory}/Summit"; + in { enable = true; createDirectories = true; desktop = "${config.home.homeDirectory}/Desktop"; - documents = "${config.home.homeDirectory}/Documents"; - music = "${config.home.homeDirectory}/Media/Music"; - videos = "${config.home.homeDirectory}/Media/Videos"; - pictures = "${config.home.homeDirectory}/Media/Pictures"; + documents = "${summit}/Documents"; + music = "${summit}/Media/Music"; + videos = "${summit}/Media/Videos"; + pictures = "${summit}/Media/Pictures"; extraConfig = { XDG_SCREENSHOTS_DIR = "${config.xdg.userDirs.pictures}/Screenshots"; - XDG_CODE_DIR = "${config.home.homeDirectory}/Code"; + XDG_CODE_DIR = "${summit}/code"; XDG_RECORDINGS_DIR = "${config.xdg.userDirs.videos}/Recordings"; + XDG_NOTES_DIR = "${summit}/notes"; }; }; }; diff --git a/modules/home/workstation/productivity/obsidian.nix b/modules/home/workstation/productivity/obsidian.nix index 8a6bc4f..b9a68b2 100644 --- a/modules/home/workstation/productivity/obsidian.nix +++ b/modules/home/workstation/productivity/obsidian.nix @@ -10,7 +10,7 @@ # admin = osConfig.ooknet.host.admin; # TODO: use admin.githubUsername notesRepo = "git@github.com:ooks-io/notes.git"; - notesPath = "${config.xdg.userDirs.documents}/notes"; + notesPath = "${config.xdg.userDirs.extraConfig.XDG_NOTES_DIR}"; in { config = mkIf (elem "productivity" profiles) { home.packages = [pkgs.obsidian]; diff --git a/outputs/pkgs/ook-vim/config/plugins/notes.nix b/outputs/pkgs/ook-vim/config/plugins/notes.nix index ef417de..1f0767a 100644 --- a/outputs/pkgs/ook-vim/config/plugins/notes.nix +++ b/outputs/pkgs/ook-vim/config/plugins/notes.nix @@ -4,12 +4,12 @@ obsidianExtended = { enable = true; setupOpts = { - dir = "~/Documents/notes"; + dir = "~/Summit/notes"; daily_notes = { - folder = "~/Documents/notes/dailies"; + folder = "~/Summit/notes/dailies"; }; templates = { - folder = "~/Documents/notes/templates"; + folder = "~/Summit/notes/templates"; }; ui.enable = false; }; From 8e84af98ac5a7f3b5be9ffd856193fed98704d2a Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 28 Jan 2025 19:58:23 +1100 Subject: [PATCH 202/213] syncthing: init --- hosts/ooksdesk/default.nix | 1 + hosts/ooksmedia/default.nix | 1 + modules/home/workstation/tools/default.nix | 1 + .../workstation/tools/syncthing-applet.nix | 15 ++++++ modules/nixos/base/default.nix | 1 + modules/nixos/base/nix.nix | 6 +-- modules/nixos/base/options.nix | 6 ++- modules/nixos/base/syncthing.nix | 52 +++++++++++++++++++ outputs/lib/services.nix | 14 ++++- 9 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 modules/home/workstation/tools/syncthing-applet.nix create mode 100644 modules/nixos/base/syncthing.nix diff --git a/hosts/ooksdesk/default.nix b/hosts/ooksdesk/default.nix index 8516049..e05050a 100644 --- a/hosts/ooksdesk/default.nix +++ b/hosts/ooksdesk/default.nix @@ -10,6 +10,7 @@ ooknet = { host = { + syncthing.enable = true; admin = { name = "ooks"; shell = "fish"; diff --git a/hosts/ooksmedia/default.nix b/hosts/ooksmedia/default.nix index e1457bd..9acfcf5 100644 --- a/hosts/ooksmedia/default.nix +++ b/hosts/ooksmedia/default.nix @@ -10,6 +10,7 @@ ooknet = { host = { + syncthing.enable = true; admin = { name = "ooks"; shell = "fish"; diff --git a/modules/home/workstation/tools/default.nix b/modules/home/workstation/tools/default.nix index 8d3b0bc..55cb2b2 100644 --- a/modules/home/workstation/tools/default.nix +++ b/modules/home/workstation/tools/default.nix @@ -9,6 +9,7 @@ ./kdeconnect.nix ./ookbrightness.nix ./zellijMenu.nix + ./syncthing-applet.nix ./nemo.nix ./qtscrcpy.nix ]; diff --git a/modules/home/workstation/tools/syncthing-applet.nix b/modules/home/workstation/tools/syncthing-applet.nix new file mode 100644 index 0000000..0fa36f3 --- /dev/null +++ b/modules/home/workstation/tools/syncthing-applet.nix @@ -0,0 +1,15 @@ +{ + osConfig, + pkgs, + lib, + ook, + ... +}: let + inherit (lib) mkIf; + inherit (ook.lib.services) mkTrayService; + inherit (osConfig.ooknet.host) syncthing; +in { + config = mkIf syncthing.enable { + systemd.user.services."syncthing-applet" = mkTrayService "${pkgs.syncthingtray-minimal}/bin/syncthingtray --wait"; + }; +} diff --git a/modules/nixos/base/default.nix b/modules/nixos/base/default.nix index ca1e4eb..efd876c 100644 --- a/modules/nixos/base/default.nix +++ b/modules/nixos/base/default.nix @@ -11,5 +11,6 @@ ./tailscale.nix ./networking.nix ./security + ./syncthing.nix ]; } diff --git a/modules/nixos/base/nix.nix b/modules/nixos/base/nix.nix index 8af9f9d..2e06c36 100644 --- a/modules/nixos/base/nix.nix +++ b/modules/nixos/base/nix.nix @@ -12,9 +12,9 @@ flakeInputs = filterAttrs (_: v: isType "flake" v) inputs; paths = { - FLAKE = "/home/${admin.name}/.config/ooknet"; + FLAKE = "/home/${admin.name}/Summit/ooknet"; WEBSITE = "${paths.FLAKE}/outputs/pkgs/website"; - KUNZEN = "/home/${admin.name}/.config/kunzen"; + KUNZEN = "/home/${admin.name}/Summit/kunzen"; }; in { environment = { @@ -76,7 +76,5 @@ in { # nix rebuild utililty programs.nh = mkIf (role == "workstation") { enable = true; - # sets an environment variable FLAKE that nh will refer to by default - flake = mkIf admin.homeManager "/home/${admin.name}/.config/ooknet"; }; } diff --git a/modules/nixos/base/options.nix b/modules/nixos/base/options.nix index 13b2148..ff3fcc6 100644 --- a/modules/nixos/base/options.nix +++ b/modules/nixos/base/options.nix @@ -3,7 +3,7 @@ pkgs, ... }: let - inherit (lib) mkOption; + inherit (lib) mkEnableOption mkOption; inherit (lib.types) str enum bool package; in { options.ooknet.host = { @@ -18,6 +18,10 @@ in { type = enum ["workstation" "server"]; }; + syncthing = { + enable = mkEnableOption "Enable syncthing"; + }; + boot = { loader = mkOption { type = enum ["systemd" "grub"]; diff --git a/modules/nixos/base/syncthing.nix b/modules/nixos/base/syncthing.nix new file mode 100644 index 0000000..1967b32 --- /dev/null +++ b/modules/nixos/base/syncthing.nix @@ -0,0 +1,52 @@ +{ + config, + lib, + ... +}: let + inherit (lib) mkIf; + inherit (config.networking) hostName; + inherit (config.ooknet.host) admin syncthing; + inherit (config.ooknet.secrets) devices; + + key = config.age.secrets."${hostName}-syncthing-key"; + cert = config.age.secrets."${hostName}-syncthing-cert"; +in { + config = mkIf syncthing.enable { + services.syncthing = { + enable = true; + user = admin.name; + group = "users"; + openDefaultPorts = true; + configDir = "/home/${admin.name}/.config/syncthing"; + + # host credentials + key = key.path; + cert = cert.path; + + settings = { + # obfuscating device ids is not necessary, but i do it anyway + devices = { + "ooksdesk" = { + inherit (devices.ooksdesk) id addresses; + }; + "ooksmedia" = { + inherit (devices.ooksmedia) id addresses; + }; + }; + folders = { + "Summit" = { + path = "/home/${admin.name}/Summit"; + devices = [ + "ooksdesk" + "ooksmedia" + ]; + ignorePerms = false; + }; + }; + }; + }; + # Dont create default ~/Sync folder + # https://wiki.nixos.org/wiki/Syncthing + systemd.services.syncthing.environment.STNODEFAULTFOLDER = "true"; + }; +} diff --git a/outputs/lib/services.nix b/outputs/lib/services.nix index 648f3e7..a0dedf6 100644 --- a/outputs/lib/services.nix +++ b/outputs/lib/services.nix @@ -7,6 +7,18 @@ }; Install.WantedBy = ["graphical-session.target"]; }; + + mkTrayService = exec: { + Unit = { + Requires = ["tray.target"]; + After = ["graphical-session-pre.target" "tray.target"]; + PartOf = ["graphical-session.target"]; + }; + Service = { + ExecStart = exec; + }; + Install = {WantedBy = ["graphical-session.target"];}; + }; in { - inherit mkGraphicalService; + inherit mkGraphicalService mkTrayService; } From 9dd3ff1f8fcd6bdcfee306fb7f599d4a6e818866 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 28 Jan 2025 19:58:55 +1100 Subject: [PATCH 203/213] starship: enable transience --- modules/home/console/tools/starship.nix | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/modules/home/console/tools/starship.nix b/modules/home/console/tools/starship.nix index 95cd762..fbefb51 100644 --- a/modules/home/console/tools/starship.nix +++ b/modules/home/console/tools/starship.nix @@ -5,10 +5,13 @@ }: let cfg = osConfig.ooknet.console.tools.starship; inherit (lib) concatStrings mkIf; + inherit (osConfig.ooknet.host) admin; in { config = mkIf cfg.enable { programs.starship = { enable = true; + enableTransience = admin.shell == "fish"; + enableInteractive = false; settings = { format = concatStrings [ "$username" @@ -27,6 +30,14 @@ in { directory = { truncation_length = 0; truncate_to_repo = true; + substitutions = { + "Documents" = " Documents"; + "Downloads" = " Downloads"; + "Music" = " Music"; + "Pictures" = " Picures"; + "Screenshots" = "󰹑 Screenshots"; + "Summit" = " "; + }; }; fill = { From 48368d3be20f1cd8842ba17679c580382c4653aa Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 28 Jan 2025 19:59:20 +1100 Subject: [PATCH 204/213] home: remove term env --- modules/home/workstation/terminal/foot.nix | 1 - modules/home/workstation/terminal/ghostty.nix | 1 - 2 files changed, 2 deletions(-) diff --git a/modules/home/workstation/terminal/foot.nix b/modules/home/workstation/terminal/foot.nix index 1612364..bfababf 100644 --- a/modules/home/workstation/terminal/foot.nix +++ b/modules/home/workstation/terminal/foot.nix @@ -91,7 +91,6 @@ in { (mkIf (default.terminal == "foot") { home.sessionVariables = { TERMINAL = "foot"; - TERM = "foot"; }; ooknet.binds.terminal = "foot"; ooknet.binds.terminalLaunch = "foot"; diff --git a/modules/home/workstation/terminal/ghostty.nix b/modules/home/workstation/terminal/ghostty.nix index c685210..e381e82 100644 --- a/modules/home/workstation/terminal/ghostty.nix +++ b/modules/home/workstation/terminal/ghostty.nix @@ -79,7 +79,6 @@ in { (mkIf (default.terminal == "ghostty") { home.sessionVariables = { TERMINAL = "ghostty"; - TERM = "ghostty"; }; ooknet.binds = { terminal = "ghostty"; From a31bebbf7419153454acd7d90c66c30b468cb6fb Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 28 Jan 2025 19:59:48 +1100 Subject: [PATCH 205/213] neovim: nvf options change enableconfig --> globals --- outputs/pkgs/ook-vim/config/default.nix | 2 +- outputs/pkgs/ook-vim/config/globals.nix | 6 ++++++ outputs/pkgs/ook-vim/config/keymaps.nix | 5 ----- outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix | 1 - outputs/pkgs/ook-vim/config/plugins/utility.nix | 6 ++++++ outputs/pkgs/ook-vim/config/settings.nix | 1 - 6 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 outputs/pkgs/ook-vim/config/globals.nix delete mode 100644 outputs/pkgs/ook-vim/config/keymaps.nix diff --git a/outputs/pkgs/ook-vim/config/default.nix b/outputs/pkgs/ook-vim/config/default.nix index 7fb6b10..3fe173b 100644 --- a/outputs/pkgs/ook-vim/config/default.nix +++ b/outputs/pkgs/ook-vim/config/default.nix @@ -3,7 +3,7 @@ ./settings.nix ./opts.nix ./theme.nix - ./keymaps.nix + ./globals.nix ./plugins ]; } diff --git a/outputs/pkgs/ook-vim/config/globals.nix b/outputs/pkgs/ook-vim/config/globals.nix new file mode 100644 index 0000000..74fcdc5 --- /dev/null +++ b/outputs/pkgs/ook-vim/config/globals.nix @@ -0,0 +1,6 @@ +{ + vim.globals = { + editorconfig = true; + mapleader = " "; + }; +} diff --git a/outputs/pkgs/ook-vim/config/keymaps.nix b/outputs/pkgs/ook-vim/config/keymaps.nix deleted file mode 100644 index 2fbb68d..0000000 --- a/outputs/pkgs/ook-vim/config/keymaps.nix +++ /dev/null @@ -1,5 +0,0 @@ -{ - config.vim = { - globals.mapleader = " "; - }; -} diff --git a/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix b/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix index 3bf7b83..e7a5855 100644 --- a/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix +++ b/outputs/pkgs/ook-vim/config/plugins/languages/markdown.nix @@ -9,7 +9,6 @@ enable = true; setupOpts = { heading = { - border = true; width = "block"; left_pad = 3; right_pad = 4; diff --git a/outputs/pkgs/ook-vim/config/plugins/utility.nix b/outputs/pkgs/ook-vim/config/plugins/utility.nix index 174174b..e913804 100644 --- a/outputs/pkgs/ook-vim/config/plugins/utility.nix +++ b/outputs/pkgs/ook-vim/config/plugins/utility.nix @@ -10,6 +10,12 @@ autoStart = false; }; }; + images.image-nvim = { + enable = true; + setupOpts = { + backend = "kitty"; + }; + }; }; }; } diff --git a/outputs/pkgs/ook-vim/config/settings.nix b/outputs/pkgs/ook-vim/config/settings.nix index 9524e21..fef1b43 100644 --- a/outputs/pkgs/ook-vim/config/settings.nix +++ b/outputs/pkgs/ook-vim/config/settings.nix @@ -3,7 +3,6 @@ package = pkgs.neovim-unwrapped; searchCase = "smart"; enableLuaLoader = true; - enableEditorconfig = true; useSystemClipboard = true; autopairs.nvim-autopairs.enable = true; hideSearchHighlight = true; From bf496658718fab6fc78b0832923e144c16fcbab2 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Tue, 28 Jan 2025 19:59:57 +1100 Subject: [PATCH 206/213] flake: update secrets --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index cd14408..3b5c623 100644 --- a/flake.lock +++ b/flake.lock @@ -4036,11 +4036,11 @@ ] }, "locked": { - "lastModified": 1737365729, - "narHash": "sha256-k3XwPxuGMBSe0rz7C00br7qO2K4R3Eh0ZjYRo2wthZM=", + "lastModified": 1738040410, + "narHash": "sha256-0qjZ451IaL7douYhOvUJ2vWDw/0Bom0RsovJ76ml3Jk=", "ref": "refs/heads/master", - "rev": "caf59a774002ea041b11322850e3fa5d225f080e", - "revCount": 26, + "rev": "182b972f57e906c6cf2c4f38ac8587f6af702feb", + "revCount": 32, "type": "git", "url": "ssh://git@github.com/ooks-io/kunzen" }, From 377bd48ee59cc23db360d7c39c761d4a09b601e6 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 29 Jan 2025 17:26:11 +1100 Subject: [PATCH 207/213] ollama: init --- hosts/ooksdesk/default.nix | 2 ++ modules/nixos/workstation/options.nix | 1 + .../nixos/workstation/services/default.nix | 1 + modules/nixos/workstation/services/ollama.nix | 21 +++++++++++++++++++ 4 files changed, 25 insertions(+) create mode 100644 modules/nixos/workstation/services/ollama.nix diff --git a/hosts/ooksdesk/default.nix b/hosts/ooksdesk/default.nix index e05050a..c7a3fdd 100644 --- a/hosts/ooksdesk/default.nix +++ b/hosts/ooksdesk/default.nix @@ -25,6 +25,8 @@ browser = "firefox"; terminal = "ghostty"; }; + # FIXME + programs.ollama.enable = false; }; console = { profile = "standard"; diff --git a/modules/nixos/workstation/options.nix b/modules/nixos/workstation/options.nix index 6c385a4..da3d19a 100644 --- a/modules/nixos/workstation/options.nix +++ b/modules/nixos/workstation/options.nix @@ -29,6 +29,7 @@ in { firefox.enable = mkEnableOption ""; foot.enable = mkEnableOption ""; ghostty.enable = mkEnableOption ""; + ollama.enable = mkEnableOption ""; }; }; } diff --git a/modules/nixos/workstation/services/default.nix b/modules/nixos/workstation/services/default.nix index 0dce40b..a50d475 100644 --- a/modules/nixos/workstation/services/default.nix +++ b/modules/nixos/workstation/services/default.nix @@ -3,5 +3,6 @@ ./dbus.nix ./gnome-services.nix ./geoclue.nix + ./ollama.nix ]; } diff --git a/modules/nixos/workstation/services/ollama.nix b/modules/nixos/workstation/services/ollama.nix new file mode 100644 index 0000000..549c6f1 --- /dev/null +++ b/modules/nixos/workstation/services/ollama.nix @@ -0,0 +1,21 @@ +{ + lib, + config, + ... +}: let + inherit (lib) mkIf; + cfg = config.ooknet.workstation.programs.ollama; +in { + config = mkIf cfg.enable { + # FIXME: + # https://github.com/NixOS/nixpkgs/issues/376930 + services.ollama = { + enable = true; + acceleration = "rocm"; + rocmOverrideGfx = "10.1.0"; + environmentVariables = { + HCC_AMDGPU_TARGET = "gfx1010"; + }; + }; + }; +} From c1a264e98eb5c5ba1f2ab6d3fcffac87ce22a293 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 29 Jan 2025 17:26:31 +1100 Subject: [PATCH 208/213] amd-gpu: use amdvlk and opencl modules --- modules/nixos/hardware/gpu/amd.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/nixos/hardware/gpu/amd.nix b/modules/nixos/hardware/gpu/amd.nix index 4c39252..64eb1fc 100644 --- a/modules/nixos/hardware/gpu/amd.nix +++ b/modules/nixos/hardware/gpu/amd.nix @@ -9,6 +9,13 @@ inherit (builtins) attrValues; in { config = mkIf (gpu.type == "amd") { + hardware.amdgpu = { + amdvlk = { + enable = true; + support32Bit.enable = true; + }; + opencl.enable = true; + }; hardware.graphics = { extraPackages = attrValues { inherit From e2bb0b4a00171899771e123ec9cb177985b2a236 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 29 Jan 2025 19:04:01 +1100 Subject: [PATCH 209/213] hyprland: hyprlock tweaks/syncthing tray window rules --- modules/home/workstation/hyprland/components/hyprlock.nix | 4 +++- modules/home/workstation/hyprland/settings/rules.nix | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/home/workstation/hyprland/components/hyprlock.nix b/modules/home/workstation/hyprland/components/hyprlock.nix index d829761..bee1c9a 100644 --- a/modules/home/workstation/hyprland/components/hyprlock.nix +++ b/modules/home/workstation/hyprland/components/hyprlock.nix @@ -7,6 +7,7 @@ }: let inherit (osConfig.ooknet.appearance) fonts; inherit (osConfig.ooknet.workstation) environment; + inherit (osConfig.ooknet.hardware) primaryMonitor; inherit (hozen) color; inherit (lib) mkIf; in { @@ -34,6 +35,7 @@ in { }; input-field = { + monitor = primaryMonitor; size = "200, 30"; position = "0, 0"; @@ -49,7 +51,7 @@ in { }; label = { - monitor = ""; + monitor = primaryMonitor; text = "LOCKED"; position = "0, 150"; valign = "center"; diff --git a/modules/home/workstation/hyprland/settings/rules.nix b/modules/home/workstation/hyprland/settings/rules.nix index c1141f5..33ae20e 100644 --- a/modules/home/workstation/hyprland/settings/rules.nix +++ b/modules/home/workstation/hyprland/settings/rules.nix @@ -5,6 +5,10 @@ in { wayland.windowManager.hyprland.windowRules = [ # TODO tag games for immediate + { + matches = {initialTitle = "Syncthing Tray";}; + rules = ["float" "center 1" "size 50%"]; + } { matches = {class = "factorio";}; rules = ["tag +games"]; From 85eb695499bb73681bbe5cc49e012a5704fc2d74 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 29 Jan 2025 19:04:33 +1100 Subject: [PATCH 210/213] wallpaper: credit --- outputs/pkgs/wallpapers/generated-wallpaper.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/outputs/pkgs/wallpapers/generated-wallpaper.nix b/outputs/pkgs/wallpapers/generated-wallpaper.nix index 1d23a3c..698ecd8 100644 --- a/outputs/pkgs/wallpapers/generated-wallpaper.nix +++ b/outputs/pkgs/wallpapers/generated-wallpaper.nix @@ -12,6 +12,7 @@ in width ? largestWidth, height ? largestHeight, }: + # Credit to misterio77 pkgs.stdenv.mkDerivation { name = "generated-nix-wallpaper-${colorscheme.slug}.png"; src = pkgs.writeTextFile { From 46cf664bb59588e917d20ee700a301295d569125 Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 29 Jan 2025 19:04:40 +1100 Subject: [PATCH 211/213] flake: bump secrets --- flake.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/flake.lock b/flake.lock index 3b5c623..ae6f9b1 100644 --- a/flake.lock +++ b/flake.lock @@ -1042,11 +1042,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1737746512, - "narHash": "sha256-nU6AezEX4EuahTO1YopzueAXfjFfmCHylYEFCagduHU=", + "lastModified": 1737885589, + "narHash": "sha256-Zf0hSrtzaM1DEz8//+Xs51k/wdSajticVrATqDrfQjg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "825479c345a7f806485b7f00dbe3abb50641b083", + "rev": "852ff1d9e153d8875a83602e03fdef8a63f0ecf8", "type": "github" }, "original": { @@ -4036,11 +4036,11 @@ ] }, "locked": { - "lastModified": 1738040410, - "narHash": "sha256-0qjZ451IaL7douYhOvUJ2vWDw/0Bom0RsovJ76ml3Jk=", + "lastModified": 1738128696, + "narHash": "sha256-SY+UKbuhfHrAbAqVpCi3+Z4zSZ7cLJ5z6WXO8JcDmd0=", "ref": "refs/heads/master", - "rev": "182b972f57e906c6cf2c4f38ac8587f6af702feb", - "revCount": 32, + "rev": "f88c11c910405e489716ca02c9d993aa50572e64", + "revCount": 34, "type": "git", "url": "ssh://git@github.com/ooks-io/kunzen" }, From f55e861fddb472e9729f97462b134751ccb143fa Mon Sep 17 00:00:00 2001 From: ooks-io Date: Wed, 29 Jan 2025 23:16:46 +1100 Subject: [PATCH 212/213] modules: vale init --- modules/home/console/tools/default.nix | 1 + modules/home/console/tools/vale.nix | 29 +++++ outputs/default.nix | 1 + outputs/modules/default.nix | 5 + outputs/modules/home-manager/default.nix | 5 + outputs/modules/home-manager/vale/default.nix | 119 ++++++++++++++++++ 6 files changed, 160 insertions(+) create mode 100644 modules/home/console/tools/vale.nix create mode 100644 outputs/modules/default.nix create mode 100644 outputs/modules/home-manager/default.nix create mode 100644 outputs/modules/home-manager/vale/default.nix diff --git a/modules/home/console/tools/default.nix b/modules/home/console/tools/default.nix index 45a4b5a..d79fdcf 100644 --- a/modules/home/console/tools/default.nix +++ b/modules/home/console/tools/default.nix @@ -1,6 +1,7 @@ { imports = [ ./bat.nix + ./vale.nix ./networking.nix ./btop.nix ./git.nix diff --git a/modules/home/console/tools/vale.nix b/modules/home/console/tools/vale.nix new file mode 100644 index 0000000..206ed99 --- /dev/null +++ b/modules/home/console/tools/vale.nix @@ -0,0 +1,29 @@ +{self, ...}: { + imports = [ + self.homeManagerModules.vale + ]; + programs.vale = { + enable = true; + styles = [ + "microsoft" + "write-good" + "alex" + "readability" + "proselint" + ]; + globalSettings = { + MinAlertLevel = "suggestion"; + }; + formatSettings = { + "*.{md,txt,tex}" = { + BasedOnStyles = [ + "proselint" + "alex" + "Readability" + "Microsoft" + ]; + "Microsoft.Acronyms" = "NO"; + }; + }; + }; +} diff --git a/outputs/default.nix b/outputs/default.nix index 8104347..560febe 100644 --- a/outputs/default.nix +++ b/outputs/default.nix @@ -8,5 +8,6 @@ ./images.nix ./devshells ./templates + ./modules ]; } diff --git a/outputs/modules/default.nix b/outputs/modules/default.nix new file mode 100644 index 0000000..73b1132 --- /dev/null +++ b/outputs/modules/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./home-manager + ]; +} diff --git a/outputs/modules/home-manager/default.nix b/outputs/modules/home-manager/default.nix new file mode 100644 index 0000000..4304d29 --- /dev/null +++ b/outputs/modules/home-manager/default.nix @@ -0,0 +1,5 @@ +{ + flake.homeManagerModules = { + vale = import ./vale; + }; +} diff --git a/outputs/modules/home-manager/vale/default.nix b/outputs/modules/home-manager/vale/default.nix new file mode 100644 index 0000000..8b26b1e --- /dev/null +++ b/outputs/modules/home-manager/vale/default.nix @@ -0,0 +1,119 @@ +{ + lib, + pkgs, + config, + ... +}: let + inherit (lib) filterAttrs mapAttrs mkEnableOption mkOption mkIf; + inherit (lib.generators) toINIWithGlobalSection; + inherit (lib.types) attrsOf submodule listOf str enum package nullOr; + + filterNullRec = let + # helper to check if a value should be kept + isNonNull = value: + if builtins.isAttrs value + then filterNullRec value != {} + else value != null; + in + attrs: + filterAttrs + (_: isNonNull) + (mapAttrs ( + name: value: + if builtins.isAttrs value + then filterNullRec value + else value + ) + attrs); + + listToStr = list: builtins.concatStringsSep "," list; + availableStyles = [ + "alex" + "google" + "joblint" + "proselint" + "write-good" + "readability" + "microsoft" + ]; + formatOptions = submodule { + freeformType = attrsOf str; + options = { + BasedOnStyles = mkOption { + type = nullOr (listOf str); + default = null; + apply = listToStr; + }; + BlockIgnores = mkOption { + type = nullOr str; + default = null; + }; + TokenIgnores = mkOption { + type = nullOr str; + default = null; + }; + CommentDelimiters = mkOption { + type = nullOr str; + default = null; + }; + Transform = mkOption { + type = nullOr str; + default = null; + }; + }; + }; + + cfg = config.programs.vale; +in { + options.programs.vale = { + enable = mkEnableOption "Enable vale linter"; + package = mkOption { + type = package; + default = pkgs.vale; + }; + styles = mkOption { + type = listOf (enum availableStyles); + default = []; + description = "Style packages to include."; + }; + globalSettings = { + MinAlertLevel = mkOption { + type = enum [ + "suggestion" + "warning" + "error" + ]; + default = "suggestion"; + description = "Set the minimum alert level that Vale will report."; + }; + IgnoredScopes = mkOption { + type = nullOr (listOf str); + default = null; + description = "Specifies inline-level HTML tags to ignore."; + apply = v: + if v != null + then listToStr + else null; + }; + }; + formatSettings = mkOption { + type = nullOr (attrsOf formatOptions); + default = null; + }; + }; + config = mkIf cfg.enable { + home.packages = [ + (cfg.package.withStyles ( + styles: + map (name: styles.${name}) config.programs.vale.styles + )) + ]; + xdg.configFile."vale/.vale.ini".text = toINIWithGlobalSection {} { + globalSection = filterNullRec cfg.globalSettings; + sections = + if cfg.formatSettings != null + then filterNullRec cfg.formatSettings + else {}; + }; + }; +} From 81377aef7d8940ca6ce8a47ab4eaa19231bd316f Mon Sep 17 00:00:00 2001 From: ooks-io Date: Thu, 30 Jan 2025 23:26:33 +1100 Subject: [PATCH 213/213] ollama: disable until fixed --- hosts/ooksdesk/default.nix | 2 +- modules/nixos/workstation/services/ollama.nix | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hosts/ooksdesk/default.nix b/hosts/ooksdesk/default.nix index c7a3fdd..c237d08 100644 --- a/hosts/ooksdesk/default.nix +++ b/hosts/ooksdesk/default.nix @@ -26,7 +26,7 @@ terminal = "ghostty"; }; # FIXME - programs.ollama.enable = false; + programs.ollama.enable = true; }; console = { profile = "standard"; diff --git a/modules/nixos/workstation/services/ollama.nix b/modules/nixos/workstation/services/ollama.nix index 549c6f1..cff6844 100644 --- a/modules/nixos/workstation/services/ollama.nix +++ b/modules/nixos/workstation/services/ollama.nix @@ -10,7 +10,7 @@ in { # FIXME: # https://github.com/NixOS/nixpkgs/issues/376930 services.ollama = { - enable = true; + enable = false; acceleration = "rocm"; rocmOverrideGfx = "10.1.0"; environmentVariables = {