Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 65093a1f87 | |||
| f0fb1ba5f3 | |||
| ce79bcd03f | |||
| 202555c5f1 | |||
| 3dfaeb111a | |||
| 691b71a5cd | |||
| cea0050597 | |||
| 73401750a0 |
+29
-7
@@ -47,7 +47,7 @@ Leave upstream `services.*`, `networking.*`, `home.*`, etc. alone.
|
|||||||
|
|
||||||
Aggregates: `nixosModules.system` and `nixosModules.desktop` import their leaves. Host configs import those stacks and set options — they shouldn't reimplement whole subsystems.
|
Aggregates: `nixosModules.system` and `nixosModules.desktop` import their leaves. Host configs import those stacks and set options — they shouldn't reimplement whole subsystems.
|
||||||
|
|
||||||
**Home** — files under `modules/wisdom/`. Baseline is `homeManagerModules.wisdom` (`chiasson.home.enable`). Everything else is separate exports (`wisdomBrowsersZen`, …); enable on a host via `chiasson.users.extraModules.<user>` and the matching `chiasson.home.*.enable`.
|
**Home** — files under `modules/wisdom/`. Baseline is `homeManagerModules.wisdom` (`chiasson.home.enable`, wired via `chiasson.desktop.homeManager.bundleWisdom`). Other `wisdom*` slices auto-wire once per user via `lib.wisdomCatalogExtraModules self` (`modules/lib/wisdom-catalog.nix`); hosts only set matching `chiasson.home.*.enable` toggles — no re-import in `home.nix`.
|
||||||
|
|
||||||
User apps / dotfiles → wisdom. Daemons, firewall, kernel → NixOS. Sometimes both (LocalSend: HM installs, `systemLocalsend` opens the firewall).
|
User apps / dotfiles → wisdom. Daemons, firewall, kernel → NixOS. Sometimes both (LocalSend: HM installs, `systemLocalsend` opens the firewall).
|
||||||
|
|
||||||
@@ -72,14 +72,36 @@ Passwords aren't in the repo. They're in `secrets/secrets.yaml` (encrypted with
|
|||||||
On a host:
|
On a host:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
|
# configuration.nix — machine policy
|
||||||
chiasson.users.enabled = [ "olivier" ];
|
chiasson.users.enabled = [ "olivier" ];
|
||||||
chiasson.users.hostOverrides.<name> = { /* optional */ };
|
chiasson.users.hostOverrides.<name> = { /* optional */ };
|
||||||
chiasson.users.extraModules.olivier = [
|
|
||||||
self.homeManagerModules.wisdomTerminalsKitty
|
|
||||||
# …
|
|
||||||
];
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Desktop hosts also have `home.nix` exporting `flake.nixosModules.<host>Home`, wired from `default.nix` alongside `*Configuration`:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
# default.nix
|
||||||
|
modules = [
|
||||||
|
self.nixosModules."14900kConfiguration"
|
||||||
|
self.nixosModules."14900kHome"
|
||||||
|
];
|
||||||
|
|
||||||
|
# home.nix — flake fragment, per-host `chiasson.home.*` toggles
|
||||||
|
{ self, inputs, ... }: {
|
||||||
|
flake.nixosModules."14900kHome" = { self, pkgs, ... }: {
|
||||||
|
imports = [ self.nixosModules.desktopHomeBase ];
|
||||||
|
chiasson.users.extraModules.olivier = [
|
||||||
|
{
|
||||||
|
chiasson.home.browsers.edge.enable = true;
|
||||||
|
# …
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`flake.nixosModules.desktopHomeBase` expands `lib.wisdomCatalogExtraModules` plus shared desktop toggles. Host `*Home` modules append per-host `chiasson.home` overrides (and rare inline `home.packages` blocks). `chiasson.users.extraModules` concatenates lists from multiple modules (base + host), so both can set the same user key.
|
||||||
|
|
||||||
`usersHomeIntegration` turns that into `users.users` + HM. Don't hand-roll catalog users unless you're changing the users module itself.
|
`usersHomeIntegration` turns that into `users.users` + HM. Don't hand-roll catalog users unless you're changing the users module itself.
|
||||||
|
|
||||||
SSH: `sshInbound` on NixOS, outbound/rbw under `modules/ssh/home-manager/`.
|
SSH: `sshInbound` on NixOS, outbound/rbw under `modules/ssh/home-manager/`.
|
||||||
@@ -88,11 +110,11 @@ SSH: `sshInbound` on NixOS, outbound/rbw under `modules/ssh/home-manager/`.
|
|||||||
|
|
||||||
**New NixOS leaf:** export `flake.nixosModules.whatever`, wire from `system/default.nix` or `desktop/default.nix` if it's global, or only from a host `configuration.nix` if it's not. `nix flake check`. Git-add new paths if eval uses the git tree.
|
**New NixOS leaf:** export `flake.nixosModules.whatever`, wire from `system/default.nix` or `desktop/default.nix` if it's global, or only from a host `configuration.nix` if it's not. `nix flake check`. Git-add new paths if eval uses the git tree.
|
||||||
|
|
||||||
**New HM slice:** export `flake.homeManagerModules.wisdomFoo`, add the file to `imports` in `modules/wisdom/default.nix`, then wire `extraModules` + options on hosts that need it.
|
**New HM slice:** add `modules/wisdom/.../foo.nix` exporting `flake.homeManagerModules.wisdomFoo` (import-tree picks it up; `wisdomCatalogExtraModules` includes every `wisdom*` export except `wisdom` / `wisdomShellBash`). Gate packages on `chiasson.home.*.enable`, set `mkDefault true` in `desktop-home-base.nix` if shared, or `enable = true` in a host `home.nix`. Upstream HM deps stay imported unconditionally — use `mkIf` on `cfg.enable` for config (never `config`-dependent `imports`; that recurses).
|
||||||
|
|
||||||
**Derivations:** `let` inside a fragment, or `flake.packages` / `flake.lib` — not a bare `mkDerivation` file import-tree will try to load.
|
**Derivations:** `let` inside a fragment, or `flake.packages` / `flake.lib` — not a bare `mkDerivation` file import-tree will try to load.
|
||||||
|
|
||||||
**New host:** `hosts/<name>/default.nix` with `nixosSystem`, `configuration.nix` exporting `*Configuration`, hardware + `_private/` as needed, register in `modules/deploy/navi.nix` if it should be in the fleet.
|
**New host:** `hosts/<name>/default.nix` with `nixosSystem` listing `*Configuration` (+ `*Home` for desktops), `configuration.nix` exporting `*Configuration`, hardware + `_private/` as needed. Desktop/laptop hosts also get `home.nix` exporting `*Home` (import `self.nixosModules.desktopHomeBase` unless it's a special case). Register in `modules/deploy/navi.nix` if it should be in the fleet.
|
||||||
|
|
||||||
## When editing
|
## When editing
|
||||||
|
|
||||||
|
|||||||
Generated
+20
@@ -706,6 +706,25 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nixvirt": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1748140003,
|
||||||
|
"narHash": "sha256-DNBZmuk1YRM2PmwbHzVdXumRjCUzQkMarg4iI/37rOQ=",
|
||||||
|
"rev": "5dfe108fd859b122f9a96981cb6bc12297653d6c",
|
||||||
|
"revCount": 407,
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://api.flakehub.com/f/pinned/AshleyYakeley/NixVirt/0.6.0/0197059a-e45f-7446-86b5-411ccc894ab0/source.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://flakehub.com/f/AshleyYakeley/NixVirt/%2A.tar.gz"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nur": {
|
"nur": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-parts": "flake-parts_5",
|
"flake-parts": "flake-parts_5",
|
||||||
@@ -809,6 +828,7 @@
|
|||||||
"nixcord": "nixcord",
|
"nixcord": "nixcord",
|
||||||
"nixos-raspberrypi": "nixos-raspberrypi",
|
"nixos-raspberrypi": "nixos-raspberrypi",
|
||||||
"nixpkgs": "nixpkgs_2",
|
"nixpkgs": "nixpkgs_2",
|
||||||
|
"nixvirt": "nixvirt",
|
||||||
"nur": "nur",
|
"nur": "nur",
|
||||||
"oom-hardware": "oom-hardware",
|
"oom-hardware": "oom-hardware",
|
||||||
"personal-website": "personal-website",
|
"personal-website": "personal-website",
|
||||||
|
|||||||
@@ -105,6 +105,11 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
navi.url = "github:cafkafk/navi";
|
navi.url = "github:cafkafk/navi";
|
||||||
|
|
||||||
|
nixvirt = {
|
||||||
|
url = "https://flakehub.com/f/AshleyYakeley/NixVirt/*.tar.gz";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs:
|
outputs = inputs:
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
# Default keybinds
|
# Default keybinds
|
||||||
bind =
|
bind =
|
||||||
[
|
[
|
||||||
"SUPER,T,exec,kitty -e fish"
|
"SUPER,T,exec,kitty"
|
||||||
"ControlSuper,T,exec,konsole"
|
"ControlSuper,T,exec,konsole"
|
||||||
"SUPER,D,exec,rofi -show drun"
|
"SUPER,D,exec,rofi -show drun"
|
||||||
"ControlSuper,D,exec,rofi -show window"
|
"ControlSuper,D,exec,rofi -show window"
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ let
|
|||||||
];
|
];
|
||||||
#TODO[epic=Binds] Go over binds again
|
#TODO[epic=Binds] Go over binds again
|
||||||
binds = {
|
binds = {
|
||||||
"Mod+T"."spawn-sh" = "${pkgs.lib.getExe pkgs.kitty} -e fish"; #TODO[epic=Binds] This should only be set if having kitty
|
"Mod+T"."spawn-sh" = pkgs.lib.getExe pkgs.kitty; # shell from kitty HM config
|
||||||
"Mod+Control+T"."spawn-sh" = "konsole"; #TODO[epic=Binds] This should only be set if having konsole
|
"Mod+Control+T"."spawn-sh" = "konsole"; #TODO[epic=Binds] This should only be set if having konsole
|
||||||
"Mod+D"."spawn-sh" = "rofi -show drun"; #TODO[epic=Binds] This should only be set if having rofi
|
"Mod+D"."spawn-sh" = "rofi -show drun"; #TODO[epic=Binds] This should only be set if having rofi
|
||||||
"Mod+Space"."spawn-sh" = "dms ipc call spotlight toggle"; #TODO[epic=Binds] This should only be set if having dms
|
"Mod+Space"."spawn-sh" = "dms ipc call spotlight toggle"; #TODO[epic=Binds] This should only be set if having dms
|
||||||
@@ -139,9 +139,17 @@ let
|
|||||||
keyringExtra = lib.optionalString keyringEnable keyringNiriStartupKdl;
|
keyringExtra = lib.optionalString keyringEnable keyringNiriStartupKdl;
|
||||||
extraConfigMerged = keyringExtra + rpi5Extra + (userExtra.extraConfig or "");
|
extraConfigMerged = keyringExtra + rpi5Extra + (userExtra.extraConfig or "");
|
||||||
windowRules = (base.window-rules or [ ]) ++ (userExtra.window-rules or [ ]);
|
windowRules = (base.window-rules or [ ]) ++ (userExtra.window-rules or [ ]);
|
||||||
|
userExtraNoSpecial = lib.removeAttrs userExtra [ "window-rules" "extraConfig" "binds" ];
|
||||||
|
mergedBinds =
|
||||||
|
(base.binds or { })
|
||||||
|
// (userExtra.binds or { })
|
||||||
|
// (niriCfg.extraBinds or { });
|
||||||
in
|
in
|
||||||
lib.recursiveUpdate base (
|
lib.recursiveUpdate base (
|
||||||
lib.removeAttrs userExtra [ "window-rules" "extraConfig" ]
|
userExtraNoSpecial
|
||||||
|
// {
|
||||||
|
binds = mergedBinds;
|
||||||
|
}
|
||||||
// lib.optionalAttrs (windowRules != [ ]) {
|
// lib.optionalAttrs (windowRules != [ ]) {
|
||||||
window-rules = windowRules;
|
window-rules = windowRules;
|
||||||
}
|
}
|
||||||
@@ -195,6 +203,15 @@ in
|
|||||||
Merged into shared defaults → `config.kdl` via wrapper-modules. Put raw KDL in `extraConfig`.
|
Merged into shared defaults → `config.kdl` via wrapper-modules. Put raw KDL in `extraConfig`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extraBinds = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf lib.types.anything;
|
||||||
|
default = { };
|
||||||
|
description = ''
|
||||||
|
Keybind overrides merged with shared defaults and `extraSettings.binds`.
|
||||||
|
Use this when multiple modules need to add binds without overwriting each other.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkMerge [
|
config = lib.mkMerge [
|
||||||
|
|||||||
@@ -153,7 +153,7 @@
|
|||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
default = true;
|
default = true;
|
||||||
description = ''
|
description = ''
|
||||||
Add `wisdom` (baseline + bash) to HM `sharedModules`. Other slices still go in per-user `extraModules`.
|
Add `wisdom` (baseline + bash) to HM `sharedModules`. Per-user `extraModules` should use `lib.wisdomCatalogExtraModules self` once and set `chiasson.home.*.enable`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ in {
|
|||||||
{
|
{
|
||||||
|
|
||||||
# Nix rebuild widget used by DankMaterialShell (via nix-monitor).
|
# Nix rebuild widget used by DankMaterialShell (via nix-monitor).
|
||||||
# Per-host `rebuildCommand` is set in `hosts/clients/<host>/home.nix`.
|
# Per-host `rebuildCommand` is set in `modules/hosts/<host>/configuration.nix` (`chiasson.desktop.shells.dms`).
|
||||||
programs.nix-monitor = {
|
programs.nix-monitor = {
|
||||||
enable = true;
|
enable = true;
|
||||||
generationsCommand = [
|
generationsCommand = [
|
||||||
@@ -1108,6 +1108,12 @@ in {
|
|||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
(lib.mkIf (lib.attrByPath [ "chiasson" "home" "shell" "ohMyPosh" "enable" ] false config) {
|
(lib.mkIf (lib.attrByPath [ "chiasson" "home" "shell" "ohMyPosh" "enable" ] false config) {
|
||||||
|
# Matugen overwrites this at runtime; seed a stock theme so `oh-my-posh init fish` works before DMS runs matugen.
|
||||||
|
xdg.configFile."oh-my-posh/theme.omp.json".source =
|
||||||
|
let
|
||||||
|
ompTheme = config.chiasson.home.shell.ohMyPosh.builtinTheme or "jandedobbeleer";
|
||||||
|
in
|
||||||
|
"${config.programs.oh-my-posh.package}/themes/${ompTheme}.omp.json";
|
||||||
# Same path as matugen `[templates.ohmyposh]` output in `programs.dank-material-shell` config.
|
# Same path as matugen `[templates.ohmyposh]` output in `programs.dank-material-shell` config.
|
||||||
programs.oh-my-posh = {
|
programs.oh-my-posh = {
|
||||||
useTheme = lib.mkForce null;
|
useTheme = lib.mkForce null;
|
||||||
|
|||||||
@@ -1,61 +1,99 @@
|
|||||||
# Monitor layout for 14900k (ported from NixOS-New `hosts/clients/14900k/home.nix`).
|
# Monitor layout for 14900k.
|
||||||
# Niri: `chiasson.desktop.niri.extraSettings` (`extraConfig` KDL + `binds` merged with defaults).
|
# NVIDIA (default): DP-2 ultrawide, HDMI-A-3 + DP-4 side/top stack.
|
||||||
|
# Intel iGPU (gpu passthru): DP-1 ultrawide, HDMI-A-2 Samsung to the left.
|
||||||
|
# Niri: `extraSettings` (KDL via `extraConfig`, other wrapper-modules keys) + `extraBinds` (merged keybinds).
|
||||||
# Hyprland: `chiasson.desktop.hyprland.settings` (merged in HM when `chiasson.desktop.hyprland.enable`).
|
# Hyprland: `chiasson.desktop.hyprland.settings` (merged in HM when `chiasson.desktop.hyprland.enable`).
|
||||||
|
|
||||||
#TODO[epic=Moderate] Clean this up, move to host's configuration.nix.
|
#TODO[epic=Moderate] Clean this up, move to host's configuration.nix.
|
||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
{
|
let
|
||||||
chiasson.desktop.niri.extraSettings = {
|
gpuPassthru = config.chiasson.system.gpuPassthru.enable;
|
||||||
extraConfig = ''
|
|
||||||
output "DP-2" {
|
|
||||||
mode "2560x1080@144"
|
|
||||||
scale 1.0
|
|
||||||
position x=0 y=0
|
|
||||||
focus-at-startup
|
|
||||||
}
|
|
||||||
output "HDMI-A-3" {
|
|
||||||
mode "1920x1080@60"
|
|
||||||
scale 1.0
|
|
||||||
position x=-1920 y=0
|
|
||||||
}
|
|
||||||
output "DP-4" {
|
|
||||||
mode "1920x1080@144"
|
|
||||||
scale 1.0
|
|
||||||
position x=0 y=-1080
|
|
||||||
}
|
|
||||||
|
|
||||||
'';
|
niriOutputs =
|
||||||
|
if gpuPassthru then
|
||||||
|
''
|
||||||
|
output "DP-1" {
|
||||||
|
mode "2560x1080@144"
|
||||||
|
scale 1.0
|
||||||
|
position x=0 y=0
|
||||||
|
focus-at-startup
|
||||||
|
}
|
||||||
|
output "HDMI-A-2" {
|
||||||
|
mode "1920x1080@60"
|
||||||
|
scale 1.0
|
||||||
|
position x=-1920 y=0
|
||||||
|
}
|
||||||
|
''
|
||||||
|
else
|
||||||
|
''
|
||||||
|
output "DP-3" {
|
||||||
|
mode "2560x1080@144"
|
||||||
|
scale 1.0
|
||||||
|
position x=0 y=0
|
||||||
|
focus-at-startup
|
||||||
|
}
|
||||||
|
output "HDMI-A-3" {
|
||||||
|
mode "1920x1080@60"
|
||||||
|
scale 1.0
|
||||||
|
position x=-1920 y=0
|
||||||
|
}
|
||||||
|
output "DP-4" {
|
||||||
|
mode "1920x1080@144"
|
||||||
|
scale 1.0
|
||||||
|
position x=0 y=-1080
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
binds."XF86Tools".spawn = [
|
hyprlandMonitors =
|
||||||
"wpctl"
|
if gpuPassthru then
|
||||||
"set-mute"
|
[
|
||||||
"@DEFAULT_AUDIO_SOURCE@"
|
"DP-1, 2560x1080@144, 0x0, 1"
|
||||||
"toggle"
|
"HDMI-A-2, 1920x1080@60, -1920x0, 1"
|
||||||
];
|
]
|
||||||
};
|
else
|
||||||
|
[
|
||||||
chiasson.desktop.hyprland.settings = lib.mkIf config.chiasson.desktop.hyprland.enable (
|
"DP-3, 2560x1080@144, 0x0, 1"
|
||||||
let
|
|
||||||
monitorList = [
|
|
||||||
"DP-2, 2560x1080@144, 0x0, 1"
|
|
||||||
"DP-4, 1920x1080@144, 0x-1080, 1"
|
"DP-4, 1920x1080@144, 0x-1080, 1"
|
||||||
"HDMI-A-3, 1920x1080@60, -1920x0, 1"
|
"HDMI-A-3, 1920x1080@60, -1920x0, 1"
|
||||||
];
|
];
|
||||||
workspaceList = [
|
|
||||||
|
hyprlandWorkspaces =
|
||||||
|
if gpuPassthru then
|
||||||
|
[
|
||||||
|
"1, monitor:DP-1, default:true"
|
||||||
|
"2, monitor:DP-1"
|
||||||
|
"3, monitor:DP-1"
|
||||||
|
"4, monitor:HDMI-A-2, default:true"
|
||||||
|
"5, monitor:HDMI-A-2"
|
||||||
|
"6, monitor:HDMI-A-2"
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[
|
||||||
"1, monitor:DP-3, default:true"
|
"1, monitor:DP-3, default:true"
|
||||||
"2, monitor:DP-3"
|
"2, monitor:DP-3"
|
||||||
"3, monitor:DP-3"
|
"3, monitor:DP-3"
|
||||||
"4, monitor:Unknown-2, default:true"
|
"4, monitor:HDMI-A-3, default:true"
|
||||||
"5, monitor:Unknown-2"
|
"5, monitor:HDMI-A-3"
|
||||||
"6, monitor:Unknown-2"
|
"6, monitor:HDMI-A-3"
|
||||||
"7, monitor:DP-4"
|
"7, monitor:DP-4"
|
||||||
"8, monitor:DP-4"
|
"8, monitor:DP-4"
|
||||||
"9, monitor:DP-4"
|
"9, monitor:DP-4"
|
||||||
];
|
];
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
monitor = lib.mkBefore monitorList;
|
chiasson.desktop.niri.extraSettings = {
|
||||||
workspace = workspaceList;
|
extraConfig = niriOutputs;
|
||||||
}
|
};
|
||||||
);
|
|
||||||
|
chiasson.desktop.niri.extraBinds."XF86Tools".spawn = [
|
||||||
|
"wpctl"
|
||||||
|
"set-mute"
|
||||||
|
"@DEFAULT_AUDIO_SOURCE@"
|
||||||
|
"toggle"
|
||||||
|
];
|
||||||
|
|
||||||
|
chiasson.desktop.hyprland.settings = lib.mkIf config.chiasson.desktop.hyprland.enable {
|
||||||
|
monitor = lib.mkBefore hyprlandMonitors;
|
||||||
|
workspace = hyprlandWorkspaces;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
# 14900k: RTX 2070 VFIO passthrough + Windows 11 gaming VM on Crucial MX500.
|
||||||
|
{ config, lib, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.chiasson.system.gpuPassthru;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
chiasson.system.gpuPassthru = {
|
||||||
|
enable = false;
|
||||||
|
pciIds = [
|
||||||
|
"10de:1f07" # RTX 2070 VGA
|
||||||
|
"10de:10f9" # HDMI audio
|
||||||
|
"10de:1ada" # USB 3.1
|
||||||
|
"10de:1adb" # USB-C UCSI
|
||||||
|
"14c3:7927" # MediaTek MT7927 WiFi (M.2, no Linux driver — Windows only)
|
||||||
|
];
|
||||||
|
windowsDisk = "/dev/disk/by-id/ata-CT1000MX500SSD1_1830E14B054A";
|
||||||
|
lookingGlass = {
|
||||||
|
enable = true;
|
||||||
|
shmSizeMiB = 32;
|
||||||
|
captureOnFocus = false;
|
||||||
|
};
|
||||||
|
vm = {
|
||||||
|
enable = true;
|
||||||
|
name = "win11";
|
||||||
|
memoryGiB = 16;
|
||||||
|
vcpus = 8;
|
||||||
|
installMode = false;
|
||||||
|
};
|
||||||
|
libvirtUsers = [ "olivier" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
chiasson.desktop.niri.extraBinds = lib.mkIf (cfg.enable && cfg.lookingGlass.enable) {
|
||||||
|
"Mod+J"."spawn-sh" = "looking-glass-toggle";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Applied last in configuration.nix imports — wins over system module defaults.
|
||||||
|
virtualisation.libvirtd.qemu.verbatimConfig = lib.mkIf (cfg.lookingGlass.enable) (
|
||||||
|
lib.mkForce ''
|
||||||
|
namespaces = []
|
||||||
|
seccomp_sandbox = 0
|
||||||
|
security_driver = "none"
|
||||||
|
security_default_confined = 0
|
||||||
|
security_require_confined = 0
|
||||||
|
cgroup_device_acl = [
|
||||||
|
"/dev/null", "/dev/full", "/dev/zero",
|
||||||
|
"/dev/random", "/dev/urandom",
|
||||||
|
"/dev/ptmx", "/dev/kvm", "/dev/kqemu",
|
||||||
|
"/dev/rtc", "/dev/hpet",
|
||||||
|
"/dev/vfio/", "/dev/vfio/vfio",
|
||||||
|
"/dev/kvmfr0", "c 234:* rwm",
|
||||||
|
"/dev/disk/", "/dev/disk/by-id/",
|
||||||
|
"/dev/bus/usb/",
|
||||||
|
]
|
||||||
|
''
|
||||||
|
);
|
||||||
|
|
||||||
|
virtualisation.libvirt = lib.mkIf (cfg.enable && cfg.vm.enable) {
|
||||||
|
enable = true;
|
||||||
|
swtpm.enable = true;
|
||||||
|
connections."qemu:///system".domains = [
|
||||||
|
{
|
||||||
|
definition =
|
||||||
|
if cfg.vm.installMode then
|
||||||
|
./win11-domain-install.xml
|
||||||
|
else
|
||||||
|
./win11-domain.xml;
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
# Moonfin 2.0.0 Jellyfin client — upstream Flatpak bundle (not on Flathub yet).
|
# Moonfin 2.1.0 Jellyfin client — upstream Flatpak bundle (not on Flathub yet).
|
||||||
# https://github.com/Moonfin-Client/Moonfin-Core/releases/tag/2.0.0
|
# https://github.com/Moonfin-Client/Moonfin-Core/releases/tag/2.1.0
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
chiasson.system.flatpak.bundles = [
|
chiasson.system.flatpak.bundles = [
|
||||||
{
|
{
|
||||||
appId = "org.moonfin.linux";
|
appId = "org.moonfin.linux";
|
||||||
bundle = pkgs.fetchurl {
|
bundle = pkgs.fetchurl {
|
||||||
url = "https://github.com/Moonfin-Client/Moonfin-Core/releases/download/2.0.0/Moonfin_Linux_v2.0.0.flatpak";
|
url = "https://github.com/Moonfin-Client/Moonfin-Core/releases/download/2.1.0/Moonfin_Linux_v2.1.0.flatpak";
|
||||||
hash = "sha256-sLtrsqBaJ1wriTkIdLylqMc9ygNkHrNm4YS/816nIFQ=";
|
hash = "sha256-dJcI/bzKS/+SCkHarSBesei5CKCm93SjRJBp09Jn810=";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# NVIDIA for host desktop.
|
# NVIDIA for host desktop (disabled when GPU passthrough binds the card to VFIO).
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
{
|
lib.mkIf (!config.chiasson.system.gpuPassthru.enable) {
|
||||||
boot.kernelParams = [ "snd_hda_core.gpu_bind=0" ];
|
boot.kernelParams = [ "snd_hda_core.gpu_bind=0" ];
|
||||||
boot.kernelPackages = lib.mkDefault pkgs.linuxPackages_latest;
|
boot.kernelPackages = lib.mkDefault pkgs.linuxPackages_latest;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<!-- Windows 11 install profile: emulated display (virt-manager console), no GPU passthrough.
|
||||||
|
After install + NVIDIA driver: set vm.installMode = false and rebuild for gaming profile. -->
|
||||||
|
<domain type='kvm'>
|
||||||
|
<name>win11</name>
|
||||||
|
<uuid>a7b3c8d1-4e2f-5a6b-9c0d-1e2f3a4b5c6d</uuid>
|
||||||
|
<memory unit='GiB'>16</memory>
|
||||||
|
<currentMemory unit='GiB'>16</currentMemory>
|
||||||
|
<vcpu placement='static'>8</vcpu>
|
||||||
|
<os>
|
||||||
|
<type arch='x86_64' machine='pc-q35-9.0'>hvm</type>
|
||||||
|
<loader readonly='yes' secure='yes' type='pflash'>/run/libvirt/nix-ovmf/edk2-x86_64-secure-code.fd</loader>
|
||||||
|
<nvram template='/run/libvirt/nix-ovmf/edk2-i386-vars.fd'>/var/lib/libvirt/qemu/nvram/win11_VARS.fd</nvram>
|
||||||
|
<bootmenu enable='yes'/>
|
||||||
|
<boot dev='cdrom'/>
|
||||||
|
<boot dev='hd'/>
|
||||||
|
</os>
|
||||||
|
<features>
|
||||||
|
<acpi/>
|
||||||
|
<apic/>
|
||||||
|
</features>
|
||||||
|
<cpu mode='host-passthrough' check='none' migratable='on'/>
|
||||||
|
<clock offset='localtime'>
|
||||||
|
<timer name='rtc' tickpolicy='catchup'/>
|
||||||
|
<timer name='pit' tickpolicy='delay'/>
|
||||||
|
<timer name='hpet' present='no'/>
|
||||||
|
</clock>
|
||||||
|
<on_poweroff>destroy</on_poweroff>
|
||||||
|
<on_reboot>restart</on_reboot>
|
||||||
|
<on_crash>preserve</on_crash>
|
||||||
|
<devices>
|
||||||
|
<emulator>/run/libvirt/nix-emulators/qemu-system-x86_64</emulator>
|
||||||
|
|
||||||
|
<disk type='block' device='disk'>
|
||||||
|
<driver name='qemu' type='raw' cache='none' io='native' discard='unmap'/>
|
||||||
|
<source dev='/dev/disk/by-id/ata-CT1000MX500SSD1_1830E14B054A'/>
|
||||||
|
<target dev='sda' bus='sata'/>
|
||||||
|
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
|
||||||
|
</disk>
|
||||||
|
|
||||||
|
<disk type='file' device='cdrom'>
|
||||||
|
<driver name='qemu' type='raw'/>
|
||||||
|
<source file='/var/lib/libvirt/boot/win11.iso'/>
|
||||||
|
<target dev='sdb' bus='sata'/>
|
||||||
|
<readonly/>
|
||||||
|
<address type='drive' controller='0' bus='0' target='0' unit='1'/>
|
||||||
|
</disk>
|
||||||
|
|
||||||
|
<controller type='sata' index='0'>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
|
||||||
|
</controller>
|
||||||
|
<controller type='pci' index='0' model='pcie-root'/>
|
||||||
|
<controller type='pci' index='1' model='pcie-root-port'>
|
||||||
|
<model name='pcie-root-port'/>
|
||||||
|
<target chassis='1' port='0x10'/>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
|
||||||
|
</controller>
|
||||||
|
<controller type='usb' index='0' model='qemu-xhci' ports='15'>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
|
||||||
|
</controller>
|
||||||
|
|
||||||
|
<interface type='network'>
|
||||||
|
<source network='default'/>
|
||||||
|
<model type='e1000e'/>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<rng model='virtio'>
|
||||||
|
<backend model='random'>/dev/urandom</backend>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>
|
||||||
|
</rng>
|
||||||
|
|
||||||
|
<memballoon model='none'/>
|
||||||
|
|
||||||
|
<graphics type='spice' port='5900' autoport='no' listen='127.0.0.1'>
|
||||||
|
<listen type='address' address='127.0.0.1'/>
|
||||||
|
</graphics>
|
||||||
|
<video>
|
||||||
|
<model type='vga'/>
|
||||||
|
</video>
|
||||||
|
<input type='mouse' bus='virtio'/>
|
||||||
|
<input type='keyboard' bus='virtio'/>
|
||||||
|
<sound model='ich9'>
|
||||||
|
<audio id='1'/>
|
||||||
|
</sound>
|
||||||
|
<audio id='1' type='spice'/>
|
||||||
|
|
||||||
|
<tpm model='tpm-crb'>
|
||||||
|
<backend type='emulator' version='2.0'/>
|
||||||
|
</tpm>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
<!-- Gaming: GPU + Looking Glass (kvmfr) -->
|
||||||
|
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0' xmlns:libosinfo='http://libosinfo.org/xmlns/libvirt/domain/1.0'>
|
||||||
|
<name>win11</name>
|
||||||
|
<uuid>a7b3c8d1-4e2f-5a6b-9c0d-1e2f3a4b5c6d</uuid>
|
||||||
|
<memory unit='GiB'>16</memory>
|
||||||
|
<currentMemory unit='GiB'>16</currentMemory>
|
||||||
|
<vcpu placement='static'>8</vcpu>
|
||||||
|
<metadata>
|
||||||
|
<libosinfo:libosinfo>
|
||||||
|
<libosinfo:os id='http://microsoft.com/win/11'/>
|
||||||
|
</libosinfo:libosinfo>
|
||||||
|
</metadata>
|
||||||
|
<os>
|
||||||
|
<type arch='x86_64' machine='pc-q35-9.0'>hvm</type>
|
||||||
|
<loader readonly='yes' secure='yes' type='pflash'>/run/libvirt/nix-ovmf/edk2-x86_64-secure-code.fd</loader>
|
||||||
|
<nvram template='/run/libvirt/nix-ovmf/edk2-i386-vars.fd'>/var/lib/libvirt/qemu/nvram/win11_VARS.fd</nvram>
|
||||||
|
<smbios mode='host'/>
|
||||||
|
<boot dev='hd'/>
|
||||||
|
</os>
|
||||||
|
<features>
|
||||||
|
<acpi/>
|
||||||
|
<apic/>
|
||||||
|
<hyperv mode='custom'>
|
||||||
|
<relaxed state='on'/>
|
||||||
|
<vapic state='on'/>
|
||||||
|
<spinlocks state='on' retries='8191'/>
|
||||||
|
<vendor_id state='on' value='GenuineIntel'/>
|
||||||
|
</hyperv>
|
||||||
|
<kvm>
|
||||||
|
<hidden state='on'/>
|
||||||
|
</kvm>
|
||||||
|
<vmport state='off'/>
|
||||||
|
<smm state='on'/>
|
||||||
|
<ioapic driver='kvm'/>
|
||||||
|
</features>
|
||||||
|
<cpu mode='host-passthrough' check='none' migratable='off'>
|
||||||
|
<topology sockets='1' dies='1' cores='4' threads='2'/>
|
||||||
|
<maxphysaddr mode='passthrough' limit='40'/>
|
||||||
|
<feature policy='disable' name='hypervisor'/>
|
||||||
|
</cpu>
|
||||||
|
<clock offset='localtime'>
|
||||||
|
<timer name='rtc' tickpolicy='catchup'/>
|
||||||
|
<timer name='pit' tickpolicy='delay'/>
|
||||||
|
<timer name='hpet' present='no'/>
|
||||||
|
<timer name='hypervclock' present='yes'/>
|
||||||
|
</clock>
|
||||||
|
<on_poweroff>destroy</on_poweroff>
|
||||||
|
<on_reboot>restart</on_reboot>
|
||||||
|
<on_crash>preserve</on_crash>
|
||||||
|
<pm>
|
||||||
|
<suspend-to-mem enabled='no'/>
|
||||||
|
<suspend-to-disk enabled='no'/>
|
||||||
|
</pm>
|
||||||
|
<devices>
|
||||||
|
<emulator>/run/libvirt/nix-emulators/qemu-system-x86_64</emulator>
|
||||||
|
|
||||||
|
<disk type='block' device='disk'>
|
||||||
|
<driver name='qemu' type='raw' cache='none' io='native' discard='unmap'/>
|
||||||
|
<source dev='/dev/disk/by-id/ata-CT1000MX500SSD1_1830E14B054A'/>
|
||||||
|
<target dev='sda' bus='sata'/>
|
||||||
|
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
|
||||||
|
</disk>
|
||||||
|
|
||||||
|
<controller type='sata' index='0'>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
|
||||||
|
</controller>
|
||||||
|
<controller type='pci' index='0' model='pcie-root'/>
|
||||||
|
<controller type='pci' index='1' model='pcie-root-port'>
|
||||||
|
<model name='pcie-root-port'/>
|
||||||
|
<target chassis='1' port='0x10'/>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
|
||||||
|
</controller>
|
||||||
|
<controller type='pci' index='2' model='pcie-root-port'>
|
||||||
|
<model name='pcie-root-port'/>
|
||||||
|
<target chassis='2' port='0x11'/>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x1'/>
|
||||||
|
</controller>
|
||||||
|
<controller type='pci' index='3' model='pcie-root-port'>
|
||||||
|
<model name='pcie-root-port'/>
|
||||||
|
<target chassis='3' port='0x12'/>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x2'/>
|
||||||
|
</controller>
|
||||||
|
<controller type='pci' index='4' model='pcie-root-port'>
|
||||||
|
<model name='pcie-root-port'/>
|
||||||
|
<target chassis='4' port='0x13'/>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x3'/>
|
||||||
|
</controller>
|
||||||
|
<controller type='pci' index='5' model='pcie-root-port'>
|
||||||
|
<model name='pcie-root-port'/>
|
||||||
|
<target chassis='5' port='0x14'/>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x4'/>
|
||||||
|
</controller>
|
||||||
|
<controller type='usb' index='0' model='qemu-xhci' ports='15'>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
|
||||||
|
</controller>
|
||||||
|
|
||||||
|
<interface type='network'>
|
||||||
|
<mac address='04:7c:16:c9:48:a7'/>
|
||||||
|
<source network='default'/>
|
||||||
|
<model type='e1000e'/>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<input type='keyboard' bus='ps2'/>
|
||||||
|
<input type='mouse' bus='ps2'/>
|
||||||
|
|
||||||
|
<memballoon model='none'/>
|
||||||
|
|
||||||
|
<graphics type='spice' port='5900' autoport='no' listen='127.0.0.1'>
|
||||||
|
<listen type='address' address='127.0.0.1'/>
|
||||||
|
<image compression='off'/>
|
||||||
|
</graphics>
|
||||||
|
<video>
|
||||||
|
<model type='none'/>
|
||||||
|
</video>
|
||||||
|
<sound model='ich9'>
|
||||||
|
<audio id='1'/>
|
||||||
|
</sound>
|
||||||
|
<audio id='1' type='spice'/>
|
||||||
|
|
||||||
|
<hostdev mode='subsystem' type='pci' managed='yes'>
|
||||||
|
<source>
|
||||||
|
<address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
|
||||||
|
</source>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x0' multifunction='on'/>
|
||||||
|
</hostdev>
|
||||||
|
<hostdev mode='subsystem' type='pci' managed='yes'>
|
||||||
|
<source>
|
||||||
|
<address domain='0x0000' bus='0x01' slot='0x00' function='0x1'/>
|
||||||
|
</source>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x1'/>
|
||||||
|
</hostdev>
|
||||||
|
<hostdev mode='subsystem' type='pci' managed='yes'>
|
||||||
|
<source>
|
||||||
|
<address domain='0x0000' bus='0x01' slot='0x00' function='0x2'/>
|
||||||
|
</source>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x2'/>
|
||||||
|
</hostdev>
|
||||||
|
<hostdev mode='subsystem' type='pci' managed='yes'>
|
||||||
|
<source>
|
||||||
|
<address domain='0x0000' bus='0x01' slot='0x00' function='0x3'/>
|
||||||
|
</source>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x06' slot='0x00' function='0x3'/>
|
||||||
|
</hostdev>
|
||||||
|
|
||||||
|
<hostdev mode='subsystem' type='pci' managed='yes'>
|
||||||
|
<source>
|
||||||
|
<address domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
|
||||||
|
</source>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
|
||||||
|
</hostdev>
|
||||||
|
|
||||||
|
<hostdev mode='subsystem' type='usb' managed='yes'>
|
||||||
|
<source startupPolicy='optional'>
|
||||||
|
<vendor id='0x046d'/>
|
||||||
|
<product id='0xc08b'/>
|
||||||
|
</source>
|
||||||
|
</hostdev>
|
||||||
|
|
||||||
|
<hostdev mode='subsystem' type='usb' managed='yes'>
|
||||||
|
<source startupPolicy='optional'>
|
||||||
|
<vendor id='0x0489'/>
|
||||||
|
<product id='0xe10f'/>
|
||||||
|
</source>
|
||||||
|
</hostdev>
|
||||||
|
|
||||||
|
<tpm model='tpm-crb'>
|
||||||
|
<backend type='emulator' version='2.0'/>
|
||||||
|
</tpm>
|
||||||
|
</devices>
|
||||||
|
<qemu:commandline>
|
||||||
|
<qemu:arg value='-device'/>
|
||||||
|
<qemu:arg value='{"driver":"ivshmem-plain","id":"shmem0","memdev":"looking-glass"}'/>
|
||||||
|
<qemu:arg value='-object'/>
|
||||||
|
<qemu:arg value='{"qom-type":"memory-backend-file","id":"looking-glass","mem-path":"/dev/kvmfr0","size":33554432,"share":true}'/>
|
||||||
|
</qemu:commandline>
|
||||||
|
</domain>
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
self.nixosModules."14900kHardware"
|
self.nixosModules."14900kHardware"
|
||||||
inputs.home-manager.nixosModules.home-manager
|
inputs.home-manager.nixosModules.home-manager
|
||||||
inputs.sops-nix.nixosModules.sops
|
inputs.sops-nix.nixosModules.sops
|
||||||
|
inputs.nixvirt.nixosModules.default
|
||||||
|
|
||||||
self.nixosModules.system
|
self.nixosModules.system
|
||||||
self.nixosModules.desktop
|
self.nixosModules.desktop
|
||||||
@@ -14,6 +15,7 @@
|
|||||||
self.nixosModules."client-services"
|
self.nixosModules."client-services"
|
||||||
./_private/platform.nix
|
./_private/platform.nix
|
||||||
./_private/nvidia.nix
|
./_private/nvidia.nix
|
||||||
|
./_private/gpu-passthru.nix
|
||||||
./_private/peripherals.nix
|
./_private/peripherals.nix
|
||||||
# ./_private/printing-epson.nix
|
# ./_private/printing-epson.nix
|
||||||
./_private/displays.nix
|
./_private/displays.nix
|
||||||
@@ -86,8 +88,6 @@ services.cloudflare-warp.enable = true;
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
chiasson.system.chromiumHevc.enable = true;
|
|
||||||
|
|
||||||
chiasson.system = {
|
chiasson.system = {
|
||||||
ytDlpTelequebecPatch.enable = true;
|
ytDlpTelequebecPatch.enable = true;
|
||||||
|
|
||||||
@@ -141,78 +141,5 @@ services.cloudflare-warp.enable = true;
|
|||||||
};
|
};
|
||||||
|
|
||||||
chiasson.users.enabled = [ "olivier" ];
|
chiasson.users.enabled = [ "olivier" ];
|
||||||
|
|
||||||
chiasson.users.extraModules.olivier = [
|
|
||||||
self.homeManagerModules.wisdomFilebrowsersDolphin
|
|
||||||
self.homeManagerModules.wisdomTerminalsKitty
|
|
||||||
self.homeManagerModules.wisdomBrowsersEdge
|
|
||||||
self.homeManagerModules.wisdomBrowsersFlow
|
|
||||||
self.homeManagerModules.wisdomBrowsersOrion
|
|
||||||
self.homeManagerModules.wisdomBrowsersZen
|
|
||||||
self.homeManagerModules.wisdomBrowsersChromiumHevc
|
|
||||||
self.homeManagerModules.wisdomEditorsCursor
|
|
||||||
self.homeManagerModules.wisdomEditorsObsidian
|
|
||||||
self.homeManagerModules.wisdomShellYazi
|
|
||||||
self.homeManagerModules.wisdomShellFish
|
|
||||||
self.homeManagerModules.wisdomShellOhMyPosh
|
|
||||||
self.homeManagerModules.wisdomAppsDiscord
|
|
||||||
self.homeManagerModules.wisdomAppsSpotify
|
|
||||||
self.homeManagerModules.wisdomAppsLocalsend
|
|
||||||
self.homeManagerModules.wisdomAppsPokeclicker
|
|
||||||
self.homeManagerModules.wisdomDesktopScreenshot
|
|
||||||
self.homeManagerModules.wisdomDesktopGtkQtTheming
|
|
||||||
{
|
|
||||||
programs.git = {
|
|
||||||
enable = true;
|
|
||||||
settings.user = {
|
|
||||||
name = "OlivierChiasson";
|
|
||||||
email = "olivierchiasson@hotmail.fr";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
chiasson.home = {
|
|
||||||
extraPackages = [ pkgs.parsec-bin ];
|
|
||||||
|
|
||||||
shell = {
|
|
||||||
fish.enable = true;
|
|
||||||
yazi.enable = true;
|
|
||||||
ohMyPosh.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
terminals.kitty.enable = true;
|
|
||||||
|
|
||||||
filebrowsers.dolphin.enable = true;
|
|
||||||
|
|
||||||
browsers.edge.enable = true;
|
|
||||||
browsers.flow.enable = false;
|
|
||||||
browsers.orion.enable = true;
|
|
||||||
browsers.zen.enable = true;
|
|
||||||
browsers.chromiumHevc = {
|
|
||||||
enable = true;
|
|
||||||
packages = [ "google-chrome" ];
|
|
||||||
vaapi.gpu = "intel"; # Chromium + NVIDIA VA-API → frame pool errors in Jellyfin cuz chrome is proprietary rats nests, gecko engine might support NVIDIA VA-API
|
|
||||||
};
|
|
||||||
|
|
||||||
editors.cursor.enable = true;
|
|
||||||
editors.obsidian.enable = true;
|
|
||||||
|
|
||||||
apps = {
|
|
||||||
discord.enable = true;
|
|
||||||
spotify.enable = true;
|
|
||||||
spotify.openDiscoveryFirewall = true;
|
|
||||||
localsend.enable = true;
|
|
||||||
pokeclicker.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
desktop = {
|
|
||||||
screenshot = {
|
|
||||||
enable = true;
|
|
||||||
swiftshareApiKeyFile = "/run/secrets/swiftshare/API_KEY"; #TODO[epic=sops] redo this by passing sops file output directly
|
|
||||||
};
|
|
||||||
theming.enable = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
};
|
};
|
||||||
modules = [
|
modules = [
|
||||||
self.nixosModules."14900kConfiguration"
|
self.nixosModules."14900kConfiguration"
|
||||||
|
self.nixosModules."14900kHome"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
{ self, inputs, ... }:
|
||||||
|
{
|
||||||
|
flake.nixosModules."14900kHome" =
|
||||||
|
{ self, pkgs, ... }:
|
||||||
|
{
|
||||||
|
imports = [ self.nixosModules.desktopHomeBase ];
|
||||||
|
|
||||||
|
chiasson.users.extraModules.olivier = [
|
||||||
|
{
|
||||||
|
chiasson.home = {
|
||||||
|
extraPackages = [ pkgs.parsec-bin ];
|
||||||
|
|
||||||
|
browsers = {
|
||||||
|
edge.enable = true;
|
||||||
|
orion.enable = true;
|
||||||
|
zen.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
apps = {
|
||||||
|
discord.enable = true;
|
||||||
|
spotify.enable = true;
|
||||||
|
spotify.openDiscoveryFirewall = true;
|
||||||
|
pokeclicker.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
# Shared Home Manager selection for all desktop hosts (14900k, t2mbp, ideapad, uConsole).
|
||||||
|
# Wisdom slices resolved here (NixOS has `self`); toggles select what actually installs.
|
||||||
|
{ self, inputs, ... }:
|
||||||
|
{
|
||||||
|
flake.nixosModules.desktopHomeBase =
|
||||||
|
{ self, lib, pkgs, ... }:
|
||||||
|
{
|
||||||
|
chiasson.system.chromiumHevc.enable = lib.mkDefault true;
|
||||||
|
|
||||||
|
chiasson.users.extraModules.olivier =
|
||||||
|
self.lib.wisdomCatalogExtraModules self
|
||||||
|
++ [
|
||||||
|
(
|
||||||
|
{ lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
aarch64 = pkgs.stdenv.hostPlatform.isAarch64;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
programs.git = {
|
||||||
|
enable = lib.mkDefault true;
|
||||||
|
settings.user = {
|
||||||
|
name = "OlivierChiasson";
|
||||||
|
email = "olivierchiasson@hotmail.fr";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
chiasson.home = {
|
||||||
|
# Catalog of `chiasson.home.*` toggles — host `home.nix` sets `enable = true` to override `mkDefault false`.
|
||||||
|
shell = {
|
||||||
|
fish.enable = lib.mkDefault true;
|
||||||
|
ohMyPosh.enable = lib.mkDefault true;
|
||||||
|
yazi.enable = lib.mkDefault true;
|
||||||
|
};
|
||||||
|
|
||||||
|
terminals.kitty.enable = lib.mkDefault true;
|
||||||
|
|
||||||
|
filebrowsers.dolphin.enable = lib.mkDefault true;
|
||||||
|
|
||||||
|
browsers = {
|
||||||
|
chrome.enable = lib.mkDefault false;
|
||||||
|
chromiumHevc = {
|
||||||
|
enable = lib.mkDefault true;
|
||||||
|
packages = lib.mkDefault (
|
||||||
|
if aarch64 then
|
||||||
|
[ "chromium" ]
|
||||||
|
else
|
||||||
|
[ "google-chrome" ]
|
||||||
|
);
|
||||||
|
} // lib.optionalAttrs (!aarch64) {
|
||||||
|
# Chromium + NVIDIA VA-API → frame pool errors in Jellyfin; gecko may fare better on NVIDIA.
|
||||||
|
vaapi.gpu = lib.mkDefault "intel";
|
||||||
|
};
|
||||||
|
edge.enable = lib.mkDefault false;
|
||||||
|
flow.enable = lib.mkDefault false;
|
||||||
|
orion.enable = lib.mkDefault false;
|
||||||
|
zen.enable = lib.mkDefault false;
|
||||||
|
};
|
||||||
|
|
||||||
|
editors = {
|
||||||
|
cursor.enable = lib.mkDefault true;
|
||||||
|
kate.enable = lib.mkDefault false;
|
||||||
|
obsidian.enable = lib.mkDefault true;
|
||||||
|
};
|
||||||
|
|
||||||
|
apps = {
|
||||||
|
discord.enable = lib.mkDefault false;
|
||||||
|
localsend.enable = lib.mkDefault true;
|
||||||
|
pokeclicker.enable = lib.mkDefault false;
|
||||||
|
spotify = {
|
||||||
|
enable = lib.mkDefault false;
|
||||||
|
openDiscoveryFirewall = lib.mkDefault false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
desktop = {
|
||||||
|
screenshot = {
|
||||||
|
enable = lib.mkDefault true;
|
||||||
|
swiftshareApiKeyFile = "/run/secrets/swiftshare/API_KEY"; #TODO[epic=sops] redo this by passing sops file output directly
|
||||||
|
};
|
||||||
|
# WhiteSur GTK/icons, Phinger cursor, Qt via KDE platform theme; imports DMS matugen `dank-colors.css`.
|
||||||
|
theming.enable = lib.mkDefault true;
|
||||||
|
};
|
||||||
|
|
||||||
|
hardware.uconsoleGamepad.enable = lib.mkDefault false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -127,67 +127,8 @@
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# ─────────────────────── Users / HM ───────────────────────
|
|
||||||
chiasson.users.enabled = [ "olivier" ];
|
chiasson.users.enabled = [ "olivier" ];
|
||||||
|
|
||||||
# Touch-friendly application set, mirroring uConsole's selection (no heavy IDEs / gaming).
|
|
||||||
chiasson.users.extraModules.olivier = [
|
|
||||||
self.homeManagerModules.wisdomFilebrowsersDolphin
|
|
||||||
self.homeManagerModules.wisdomTerminalsKitty
|
|
||||||
self.homeManagerModules.wisdomBrowsersZen
|
|
||||||
self.homeManagerModules.wisdomEditorsKate
|
|
||||||
self.homeManagerModules.wisdomEditorsCursor
|
|
||||||
self.homeManagerModules.wisdomShellFish
|
|
||||||
self.homeManagerModules.wisdomShellOhMyPosh
|
|
||||||
self.homeManagerModules.wisdomAppsSpotify
|
|
||||||
self.homeManagerModules.wisdomAppsLocalsend
|
|
||||||
self.homeManagerModules.wisdomDesktopScreenshot
|
|
||||||
{
|
|
||||||
chiasson.home = {
|
|
||||||
shell = {
|
|
||||||
fish.enable = true;
|
|
||||||
ohMyPosh.enable = true;
|
|
||||||
};
|
|
||||||
terminals.kitty.enable = true;
|
|
||||||
filebrowsers.dolphin.enable = true;
|
|
||||||
browsers.zen.enable = true;
|
|
||||||
editors.kate.enable = true;
|
|
||||||
editors.cursor.enable = true;
|
|
||||||
apps.spotify.enable = true;
|
|
||||||
apps.localsend.enable = true;
|
|
||||||
desktop = {
|
|
||||||
screenshot = {
|
|
||||||
enable = true;
|
|
||||||
swiftshareApiKeyFile = "/run/secrets/swiftshare/API_KEY"; #TODO[epic=sops] redo this by passing sops file output directly
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
# Tablet-class apps: kept inline rather than promoting to wisdom modules — these aren't
|
|
||||||
# part of the broader catalog (no use on uConsole / 14900k / servers) and adding a wisdom
|
|
||||||
# module per single-host package would just be ceremony. If a second tablet host ever
|
|
||||||
# appears, factor them out then.
|
|
||||||
#
|
|
||||||
# NOTE on cameras: no v4l2/libcamera GUI is installed. The Mobile NixOS kernel for
|
|
||||||
# `lenovo-wormdingler` ships with `CONFIG_VIDEO_QCOM_CAMSS` disabled and no
|
|
||||||
# `VIDEO_OV*`/`VIDEO_HI*` sensor drivers, so `/dev/video0`-`/dev/video1` only expose
|
|
||||||
# the Qualcomm Venus codecs (h.264/h.265 enc/dec) and there is no camera source for
|
|
||||||
# PipeWire / libcamera to pick up. See `_private/CAMERA-TODO.md` for the steps that
|
|
||||||
# would (potentially) bring the front/rear cameras online — it's a kernel-rebuild +
|
|
||||||
# device-tree + libcamera project, not a config tweak.
|
|
||||||
(
|
|
||||||
{ pkgs, ... }:
|
|
||||||
{
|
|
||||||
home.packages = with pkgs; [
|
|
||||||
# PDF viewer — fits the existing KDE app set (Dolphin + Kate).
|
|
||||||
kdePackages.okular
|
|
||||||
# ePub reader, GTK4, large touch targets.
|
|
||||||
foliate
|
|
||||||
];
|
|
||||||
}
|
|
||||||
)
|
|
||||||
];
|
|
||||||
|
|
||||||
system.stateVersion = "26.05";
|
system.stateVersion = "26.05";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
};
|
};
|
||||||
modules = [
|
modules = [
|
||||||
self.nixosModules.ideapadConfiguration
|
self.nixosModules.ideapadConfiguration
|
||||||
|
self.nixosModules.ideapadHome
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
{ self, inputs, ... }:
|
||||||
|
{
|
||||||
|
flake.nixosModules.ideapadHome =
|
||||||
|
{ self, ... }:
|
||||||
|
{
|
||||||
|
imports = [ self.nixosModules.desktopHomeBase ];
|
||||||
|
|
||||||
|
# Host-only HM overrides (tablet apps, toggles off from desktop-home-base, …).
|
||||||
|
chiasson.users.extraModules.olivier = [
|
||||||
|
# {
|
||||||
|
# chiasson.home = {
|
||||||
|
# # editors.kate.enable = true;
|
||||||
|
# };
|
||||||
|
# }
|
||||||
|
# (
|
||||||
|
# { pkgs, ... }:
|
||||||
|
# { home.packages = with pkgs; [ ]; }
|
||||||
|
# )
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -50,6 +50,9 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets."users/server/hashedPassword".neededForUsers = true;
|
sops.secrets."users/server/hashedPassword".neededForUsers = true;
|
||||||
|
sops.secrets."tailscale/auth-key" = {
|
||||||
|
mode = "0400";
|
||||||
|
};
|
||||||
|
|
||||||
security.sudo.wheelNeedsPassword = true;
|
security.sudo.wheelNeedsPassword = true;
|
||||||
|
|
||||||
@@ -63,6 +66,11 @@
|
|||||||
networking = {
|
networking = {
|
||||||
hostName = "nix-server";
|
hostName = "nix-server";
|
||||||
networkManager.enable = true;
|
networkManager.enable = true;
|
||||||
|
tailscale = {
|
||||||
|
enable = true;
|
||||||
|
authKeyFile = config.sops.secrets."tailscale/auth-key".path;
|
||||||
|
subnetRouter.enable = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
caching.attic = {
|
caching.attic = {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
swiftshare:
|
swiftshare:
|
||||||
ghcr-token: ENC[AES256_GCM,data:V/5dLVLv4BbAxdMiBxXgmNbK17HAQkqzHJA2NWzOFfFlcy3dq8SnZQ==,iv:YTB3Bef+kZXunXVUCkFj/YZo1POdx2K+bNvzarSJ1Iw=,tag:HEBT4ZKMXTIy+ZEkNx3rHw==,type:str]
|
ghcr-token: ENC[AES256_GCM,data:MFNjMrh3mlH2gGZlzp9lty3n/+6/SQSFbBowqrR3QFO4/t/afBtv2Q==,iv:3wZzjUU4uzctX5woHiAY4Y9QJIiBLeGdmrJzhmpVy9E=,tag:sK/Jy53jBsbdd1YWoOVT5A==,type:str]
|
||||||
database-password: ENC[AES256_GCM,data:r9GSaoQ7bS644ipb3kU=,iv:KYDTzYtjfz5meDb0nemY1lhSFEorKHL0hSRIcQaHg5c=,tag:RVjAfb8XGsybAgIc2/hH+g==,type:str]
|
database-password: ENC[AES256_GCM,data:r9GSaoQ7bS644ipb3kU=,iv:KYDTzYtjfz5meDb0nemY1lhSFEorKHL0hSRIcQaHg5c=,tag:RVjAfb8XGsybAgIc2/hH+g==,type:str]
|
||||||
auth-secret: ENC[AES256_GCM,data:tTXLMWASBfF49gBFrf+CZ3R4oTt7hEGUhAqEdvoQtm0zbb2VUhTq7y4tH/c=,iv:Halfu9hBex4SEUMHLAicqApTxZP0NV9pJZTr+bBSek4=,tag:1WqN75zT+zoka9sIXOJGfQ==,type:str]
|
auth-secret: ENC[AES256_GCM,data:tTXLMWASBfF49gBFrf+CZ3R4oTt7hEGUhAqEdvoQtm0zbb2VUhTq7y4tH/c=,iv:Halfu9hBex4SEUMHLAicqApTxZP0NV9pJZTr+bBSek4=,tag:1WqN75zT+zoka9sIXOJGfQ==,type:str]
|
||||||
oauth-discord-client-secret: ENC[AES256_GCM,data:a9Iarcpl1HOFXdsDMh3H662T8yqVvGtfguVICwWVrAg=,iv:LsUserWQcEDV0TiRWj1sHh5/ZiFQzyc1gRWg+Ewwjik=,tag:33Ml08oHVXl0ZMmiwQ2mig==,type:str]
|
oauth-discord-client-secret: ENC[AES256_GCM,data:a9Iarcpl1HOFXdsDMh3H662T8yqVvGtfguVICwWVrAg=,iv:LsUserWQcEDV0TiRWj1sHh5/ZiFQzyc1gRWg+Ewwjik=,tag:33Ml08oHVXl0ZMmiwQ2mig==,type:str]
|
||||||
@@ -46,7 +46,7 @@ sops:
|
|||||||
Nf0uOoSWPTJ/2SRNkSu7FMumATH4ldQ6TFSwKda3mBfBwhnFzLq10Q==
|
Nf0uOoSWPTJ/2SRNkSu7FMumATH4ldQ6TFSwKda3mBfBwhnFzLq10Q==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
recipient: age1p05z980kdtngk9mw67hfev72h7xhslplpxfk9yskgmf0hl4lu3ls04zht9
|
recipient: age1p05z980kdtngk9mw67hfev72h7xhslplpxfk9yskgmf0hl4lu3ls04zht9
|
||||||
lastmodified: "2026-05-28T21:04:07Z"
|
lastmodified: "2026-06-12T00:44:20Z"
|
||||||
mac: ENC[AES256_GCM,data:L53UYFh5xtuMx19GKAg3jW7U0/DlwJ2usy/pup+4t1HQN3KHxMwbc4BzLYkLnRBTwKMJdfKXiYmmYiYvfbbWzsPtfXLxPnF/5ROiCJ2NlxAe86SmRy2nI++eTHAXRgexIhYyL7SchsroGRvW2B3aL1jV+Eu11fD9trA9Ex1EfuI=,iv:XrRJCFSgwW2+N+4FnWrFFZz8UEVzhuhpRtHGtf8dyqc=,tag:LcO4+ilwKdU+JPyjyKaGNw==,type:str]
|
mac: ENC[AES256_GCM,data:cyI5NH6+OR/Q4T3atFN+gXsJbRaR/Q5I+MyJHy5qXsShh8LnQvEKBnnIPKz2xpuDwFvKd4DabMOxcu5xe6IRH9TN7G411vp+vruM+TicoCJ4U2xAP/J9Tlh3YKT6kZJqj/zAhvP5qPCzvz7xkFTvluLrWgPlaHWn/rlCskh0t5M=,iv:WBeS1rqjJblNGMVa7hEn5MXbZJU8WKd6541BCxu2rGI=,tag:OfOzQI6ESUdUYCbBEq9GFw==,type:str]
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.13.1
|
version: 3.13.1
|
||||||
|
|||||||
@@ -38,6 +38,9 @@
|
|||||||
group = "users";
|
group = "users";
|
||||||
mode = "0400";
|
mode = "0400";
|
||||||
};
|
};
|
||||||
|
sops.secrets."tailscale/auth-key" = {
|
||||||
|
mode = "0400";
|
||||||
|
};
|
||||||
|
|
||||||
chiasson.system.librepods.enable = true;
|
chiasson.system.librepods.enable = true;
|
||||||
chiasson.system.palera1n.enable = true;
|
chiasson.system.palera1n.enable = true;
|
||||||
@@ -106,63 +109,15 @@
|
|||||||
networking = {
|
networking = {
|
||||||
hostName = "t2mbp";
|
hostName = "t2mbp";
|
||||||
networkManager.enable = true;
|
networkManager.enable = true;
|
||||||
|
tailscale = {
|
||||||
|
enable = true;
|
||||||
|
authKeyFile = config.sops.secrets."tailscale/auth-key".path;
|
||||||
|
acceptRoutes = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
chiasson.users.enabled = [ "olivier" ];
|
chiasson.users.enabled = [ "olivier" ];
|
||||||
|
|
||||||
chiasson.users.extraModules.olivier = [
|
|
||||||
self.homeManagerModules.wisdomFilebrowsersDolphin
|
|
||||||
self.homeManagerModules.wisdomTerminalsKitty
|
|
||||||
self.homeManagerModules.wisdomBrowsersZen
|
|
||||||
self.homeManagerModules.wisdomBrowsersChrome
|
|
||||||
self.homeManagerModules.wisdomBrowsersEdge
|
|
||||||
self.homeManagerModules.wisdomEditorsCursor
|
|
||||||
self.homeManagerModules.wisdomEditorsKate
|
|
||||||
self.homeManagerModules.wisdomEditorsObsidian
|
|
||||||
self.homeManagerModules.wisdomShellYazi
|
|
||||||
self.homeManagerModules.wisdomShellFish
|
|
||||||
self.homeManagerModules.wisdomShellOhMyPosh
|
|
||||||
self.homeManagerModules.wisdomAppsDiscord
|
|
||||||
self.homeManagerModules.wisdomAppsSpotify
|
|
||||||
self.homeManagerModules.wisdomAppsLocalsend
|
|
||||||
self.homeManagerModules.wisdomAppsPokeclicker
|
|
||||||
self.homeManagerModules.wisdomDesktopScreenshot
|
|
||||||
{
|
|
||||||
chiasson.home = {
|
|
||||||
shell = {
|
|
||||||
fish.enable = true;
|
|
||||||
yazi.enable = true;
|
|
||||||
ohMyPosh.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
terminals.kitty.enable = true;
|
|
||||||
filebrowsers.dolphin.enable = true;
|
|
||||||
browsers = {
|
|
||||||
zen.enable = false;
|
|
||||||
chrome.enable = false;
|
|
||||||
edge.enable = true;
|
|
||||||
};
|
|
||||||
editors = {
|
|
||||||
cursor.enable = true;
|
|
||||||
kate.enable = false;
|
|
||||||
obsidian.enable = true;
|
|
||||||
};
|
|
||||||
apps = {
|
|
||||||
discord.enable = true;
|
|
||||||
spotify.enable = false;
|
|
||||||
localsend.enable = true;
|
|
||||||
pokeclicker.enable = true;
|
|
||||||
};
|
|
||||||
desktop = {
|
|
||||||
screenshot = {
|
|
||||||
enable = true;
|
|
||||||
swiftshareApiKeyFile = "/run/secrets/swiftshare/API_KEY"; #TODO[epic=sops] redo this by passing sops file output directly
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
};
|
};
|
||||||
modules = [
|
modules = [
|
||||||
self.nixosModules.t2mbpConfiguration
|
self.nixosModules.t2mbpConfiguration
|
||||||
];
|
self.nixosModules.t2mbpHome
|
||||||
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{ self, inputs, ... }:
|
||||||
|
{
|
||||||
|
flake.nixosModules.t2mbpHome =
|
||||||
|
{ self, ... }:
|
||||||
|
{
|
||||||
|
imports = [ self.nixosModules.desktopHomeBase ];
|
||||||
|
|
||||||
|
chiasson.users.extraModules.olivier = [
|
||||||
|
{
|
||||||
|
chiasson.home = {
|
||||||
|
browsers = {
|
||||||
|
edge.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
apps = {
|
||||||
|
discord.enable = true;
|
||||||
|
pokeclicker.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -103,40 +103,6 @@
|
|||||||
|
|
||||||
chiasson.users.enabled = [ "olivier" ];
|
chiasson.users.enabled = [ "olivier" ];
|
||||||
|
|
||||||
chiasson.users.extraModules.olivier = [
|
|
||||||
self.homeManagerModules.wisdomFilebrowsersDolphin
|
|
||||||
self.homeManagerModules.wisdomTerminalsKitty
|
|
||||||
self.homeManagerModules.wisdomBrowsersZen
|
|
||||||
self.homeManagerModules.wisdomEditorsKate
|
|
||||||
self.homeManagerModules.wisdomShellFish
|
|
||||||
self.homeManagerModules.wisdomShellOhMyPosh
|
|
||||||
self.homeManagerModules.wisdomAppsSpotify
|
|
||||||
self.homeManagerModules.wisdomAppsLocalsend
|
|
||||||
self.homeManagerModules.wisdomDesktopScreenshot
|
|
||||||
self.homeManagerModules.wisdomHardwareUconsoleGamepad
|
|
||||||
{
|
|
||||||
chiasson.home = {
|
|
||||||
shell = {
|
|
||||||
fish.enable = true;
|
|
||||||
ohMyPosh.enable = true;
|
|
||||||
};
|
|
||||||
terminals.kitty.enable = true;
|
|
||||||
filebrowsers.dolphin.enable = true;
|
|
||||||
browsers.zen.enable = true;
|
|
||||||
editors.kate.enable = true;
|
|
||||||
apps.spotify.enable = true;
|
|
||||||
apps.localsend.enable = true;
|
|
||||||
desktop = {
|
|
||||||
screenshot = {
|
|
||||||
enable = true;
|
|
||||||
swiftshareApiKeyFile = "/run/secrets/swiftshare/API_KEY"; #TODO[epic=sops] redo this by passing sops file output directly
|
|
||||||
};
|
|
||||||
};
|
|
||||||
hardware.uconsoleGamepad.enable = true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
console.packages = with pkgs; [ terminus_font ];
|
console.packages = with pkgs; [ terminus_font ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
inputs.oom-hardware.nixosModules.uc.configtxt
|
inputs.oom-hardware.nixosModules.uc.configtxt
|
||||||
inputs.oom-hardware.nixosModules.uc.base-cm5
|
inputs.oom-hardware.nixosModules.uc.base-cm5
|
||||||
self.nixosModules.uConsoleConfiguration
|
self.nixosModules.uConsoleConfiguration
|
||||||
|
self.nixosModules.uConsoleHome
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{ self, inputs, ... }:
|
||||||
|
{
|
||||||
|
flake.nixosModules.uConsoleHome =
|
||||||
|
{ self, ... }:
|
||||||
|
{
|
||||||
|
imports = [ self.nixosModules.desktopHomeBase ];
|
||||||
|
|
||||||
|
chiasson.users.extraModules.olivier = [
|
||||||
|
{
|
||||||
|
chiasson.home = {
|
||||||
|
hardware.uconsoleGamepad.enable = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Resolve `wisdom*` HM slices for NixOS `extraModules` (`self` is not an HM specialArg).
|
||||||
|
# Slices are gated by `chiasson.home.*.enable`; hosts only flip toggles in `home.nix`.
|
||||||
|
{ lib, ... }: {
|
||||||
|
flake.lib.wisdomCatalogExtraModules =
|
||||||
|
self:
|
||||||
|
let
|
||||||
|
names = lib.sort builtins.lessThan (
|
||||||
|
lib.filter (
|
||||||
|
n:
|
||||||
|
lib.hasPrefix "wisdom" n
|
||||||
|
&& n != "wisdom"
|
||||||
|
&& n != "wisdomShellBash"
|
||||||
|
) (builtins.attrNames self.homeManagerModules)
|
||||||
|
);
|
||||||
|
in
|
||||||
|
map (name: self.homeManagerModules.${name}) names;
|
||||||
|
}
|
||||||
@@ -5,17 +5,20 @@
|
|||||||
self.nixosModules.systemLocalization
|
self.nixosModules.systemLocalization
|
||||||
self.nixosModules.systemFonts
|
self.nixosModules.systemFonts
|
||||||
self.nixosModules.systemNetworking
|
self.nixosModules.systemNetworking
|
||||||
|
self.nixosModules.systemTailscale
|
||||||
self.nixosModules.systemLocalsend
|
self.nixosModules.systemLocalsend
|
||||||
self.nixosModules.systemChromiumHevcVaapi
|
self.nixosModules.systemChromiumHevcVaapi
|
||||||
self.nixosModules.systemMonitorInput
|
self.nixosModules.systemMonitorInput
|
||||||
self.nixosModules.systemSpotify
|
self.nixosModules.systemSpotify
|
||||||
self.nixosModules.systemPackagesDefaults
|
self.nixosModules.systemPackagesDefaults
|
||||||
self.nixosModules.systemDocker
|
self.nixosModules.systemDocker
|
||||||
|
self.nixosModules.systemDockerRegistryAuth
|
||||||
self.nixosModules.systemFlatpak
|
self.nixosModules.systemFlatpak
|
||||||
self.nixosModules.systemAudio
|
self.nixosModules.systemAudio
|
||||||
self.nixosModules.systemIdeapadMrubyOverlay
|
self.nixosModules.systemIdeapadMrubyOverlay
|
||||||
self.nixosModules.systemYtDlpTelequebecPatch
|
self.nixosModules.systemYtDlpTelequebecPatch
|
||||||
self.nixosModules.systemGaming
|
self.nixosModules.systemGaming
|
||||||
|
self.nixosModules.systemGpuPassthru
|
||||||
self.nixosModules.systemUconsoleKernelBuilder
|
self.nixosModules.systemUconsoleKernelBuilder
|
||||||
self.nixosModules.systemLibrepods
|
self.nixosModules.systemLibrepods
|
||||||
self.nixosModules.systemPalera1n
|
self.nixosModules.systemPalera1n
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# oci-containers runs `docker login` in ExecStartPre, which stores plaintext credentials
|
||||||
|
# in /root/.docker/config.json. For any container with `login` set, use in-memory
|
||||||
|
# DOCKER_AUTH_CONFIG instead (no per-service list to maintain).
|
||||||
|
{ ... }: {
|
||||||
|
flake.nixosModules.systemDockerRegistryAuth =
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.chiasson.system.docker.ephemeralRegistryAuth;
|
||||||
|
ociCfg = lib.attrByPath [ "virtualisation" "oci-containers" ] null config;
|
||||||
|
backend = if ociCfg == null then "docker" else ociCfg.backend or "docker";
|
||||||
|
|
||||||
|
containerBackend =
|
||||||
|
if backend == "podman" then
|
||||||
|
lib.attrByPath [ "virtualisation" "podman" "package" ] pkgs.podman config
|
||||||
|
else
|
||||||
|
lib.attrByPath [ "virtualisation" "docker" "package" ] pkgs.docker config;
|
||||||
|
|
||||||
|
isValidLogin =
|
||||||
|
login: login.registry != null && login.username != null && login.passwordFile != null;
|
||||||
|
|
||||||
|
mkRegistryAuthPreStart =
|
||||||
|
login: lib.mkBefore ''
|
||||||
|
export DOCKER_AUTH_CONFIG="$(${pkgs.jq}/bin/jq -cn \
|
||||||
|
--arg registry ${lib.escapeShellArg login.registry} \
|
||||||
|
--arg user ${lib.escapeShellArg login.username} \
|
||||||
|
--arg pass "$(${pkgs.coreutils}/bin/tr -d '\n\r' < ${login.passwordFile})" \
|
||||||
|
'{auths: {($registry): {username: $user, password: $pass, auth: (($user + ":" + $pass) | @base64)}}}')"
|
||||||
|
'';
|
||||||
|
|
||||||
|
mkPreStartWithoutLogin =
|
||||||
|
name: container:
|
||||||
|
pkgs.writeShellScript "oci-pre-start-${name}" ''
|
||||||
|
${containerBackend}/bin/${backend} rm -f ${lib.escapeShellArg name} || true
|
||||||
|
${
|
||||||
|
lib.optionalString (container.imageFile != null) ''
|
||||||
|
${containerBackend}/bin/${backend} load -i ${container.imageFile}
|
||||||
|
''
|
||||||
|
}
|
||||||
|
${
|
||||||
|
lib.optionalString (container.imageStream != null) ''
|
||||||
|
${container.imageStream} | ${containerBackend}/bin/${backend} load
|
||||||
|
''
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.chiasson.system.docker.ephemeralRegistryAuth = {
|
||||||
|
enable = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Authenticate oci-containers registry pulls via in-memory `DOCKER_AUTH_CONFIG`
|
||||||
|
instead of `docker login`. Applies automatically to every container that sets
|
||||||
|
`virtualisation.oci-containers.containers.<name>.login`.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Read merged container config only when defining systemd overrides — never write back
|
||||||
|
# to `virtualisation.oci-containers.containers` (that causes infinite recursion).
|
||||||
|
config =
|
||||||
|
let
|
||||||
|
containers =
|
||||||
|
lib.attrByPath [ "virtualisation" "oci-containers" "containers" ] { } config;
|
||||||
|
containersWithLogin = lib.filterAttrs (_: c: isValidLogin (c.login or { })) containers;
|
||||||
|
in
|
||||||
|
lib.mkIf (cfg.enable && containersWithLogin != { }) {
|
||||||
|
systemd.services = lib.mapAttrs' (
|
||||||
|
name: container:
|
||||||
|
lib.nameValuePair (container.serviceName or "${backend}-${name}") {
|
||||||
|
preStart = mkRegistryAuthPreStart container.login;
|
||||||
|
serviceConfig.ExecStartPre = lib.mkForce [
|
||||||
|
"${mkPreStartWithoutLogin name container}"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
) containersWithLogin;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,383 @@
|
|||||||
|
{ ... }: {
|
||||||
|
flake.nixosModules.systemGpuPassthru =
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.chiasson.system.gpuPassthru;
|
||||||
|
vfioIds = lib.concatStringsSep "," cfg.pciIds;
|
||||||
|
# Must match the Windows host installer build (B7-244-4bb2c58f).
|
||||||
|
lgRev = "4bb2c58fb6d0df9e863ad45924dd4decc7e9cf4e";
|
||||||
|
lgVersion = "B7-244-4bb2c58f";
|
||||||
|
# Tarball hashes omit submodules; fetchSubmodules needs the git tree hash.
|
||||||
|
lgHash = "sha256-Dc0sFnJVM0xJ0FfIQqGQKxFUj6mhp3qgB772h3Dgowc=";
|
||||||
|
# https://wiki.nixos.org/wiki/Looking_Glass — systemd 258+ needs namespaces=[]
|
||||||
|
# and an explicit ACL; seccomp can block mmap on /dev/kvmfr0.
|
||||||
|
lgQemuVerbatimConfig = ''
|
||||||
|
namespaces = []
|
||||||
|
seccomp_sandbox = 0
|
||||||
|
security_driver = "none"
|
||||||
|
security_default_confined = 0
|
||||||
|
security_require_confined = 0
|
||||||
|
cgroup_device_acl = [
|
||||||
|
"/dev/null", "/dev/full", "/dev/zero",
|
||||||
|
"/dev/random", "/dev/urandom",
|
||||||
|
"/dev/ptmx", "/dev/kvm", "/dev/kqemu",
|
||||||
|
"/dev/rtc", "/dev/hpet",
|
||||||
|
"/dev/vfio/", "/dev/vfio/vfio",
|
||||||
|
"/dev/kvmfr0", "c 234:* rwm",
|
||||||
|
"/dev/disk/", "/dev/disk/by-id/",
|
||||||
|
"/dev/bus/usb/",
|
||||||
|
]
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.chiasson.system.gpuPassthru = {
|
||||||
|
enable = lib.mkEnableOption ''
|
||||||
|
Bind passthrough GPU(s) to VFIO, run the host on Intel iGPU, and enable libvirt +
|
||||||
|
Looking Glass for a Windows gaming VM.
|
||||||
|
|
||||||
|
Prerequisites (manual, one-time):
|
||||||
|
- BIOS: VT-d/IOMMU on, Above 4G Decoding / Resizable BAR on
|
||||||
|
- Move host monitors to motherboard (Intel) ports; dummy HDMI/DP plug on passthrough GPU
|
||||||
|
- Wipe the VM disk before first boot: `wipefs -a <windowsDisk>`
|
||||||
|
- Verify IOMMU groups after switch: GPU functions should be isolated
|
||||||
|
|
||||||
|
Rollout: leave `enable = false` until cabling and disk backup are done, then rebuild and switch.
|
||||||
|
'';
|
||||||
|
|
||||||
|
pciIds = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [ ];
|
||||||
|
example = [ "10de:1f07" "10de:10f9" "10de:1ada" "10de:1adb" ];
|
||||||
|
description = ''
|
||||||
|
PCI vendor:device IDs to bind to vfio-pci (all GPU functions: VGA, audio, USB, etc.).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
windowsDisk = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "";
|
||||||
|
example = "/dev/disk/by-id/ata-CT1000MX500SSD1_1830E14B054A";
|
||||||
|
description = ''
|
||||||
|
Whole-disk by-id path for the Windows VM (raw block passthrough). Must not be mounted by the host.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
lookingGlass = {
|
||||||
|
enable = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Load the kvmfr kernel module and grant QEMU access to /dev/kvmfr0 for Looking Glass
|
||||||
|
(required for NVIDIA VFIO; plain /dev/shm IVSHMEM causes DMA mapping failures).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
shmSizeMiB = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
default = 32;
|
||||||
|
description = ''
|
||||||
|
kvmfr shared memory size (MiB). Must match `kvmfr.static_size_mb` and the VM
|
||||||
|
`memory-backend-file` size in the domain XML.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
captureOnFocus = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Grab keyboard/mouse when the Looking Glass window is focused. Set `false` to
|
||||||
|
keep input on the Linux host while viewing the guest.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
vm = {
|
||||||
|
enable = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Declaratively define the Windows VM via NixVirt (host module must import NixVirt and set
|
||||||
|
`virtualisation.libvirt.connections`).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
name = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "win11";
|
||||||
|
description = "libvirt domain name.";
|
||||||
|
};
|
||||||
|
|
||||||
|
memoryGiB = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
default = 16;
|
||||||
|
description = "VM RAM in GiB (informational; domain XML is authoritative).";
|
||||||
|
};
|
||||||
|
|
||||||
|
vcpus = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
default = 8;
|
||||||
|
description = "vCPU count (informational; domain XML is authoritative).";
|
||||||
|
};
|
||||||
|
|
||||||
|
installMode = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Use install domain (ISO, no GPU). Set `false` after Windows is installed.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
hugepages.enable = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Reserve 2 MiB hugepages for Looking Glass IVSHMEM (enable if frame drops).";
|
||||||
|
};
|
||||||
|
|
||||||
|
libvirtUsers = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [ ];
|
||||||
|
description = "Users added to libvirtd, kvm, and disk groups.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable (lib.mkMerge [
|
||||||
|
{
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = cfg.pciIds != [ ];
|
||||||
|
message = "chiasson.system.gpuPassthru: pciIds must list every passthrough GPU function.";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = cfg.windowsDisk != "";
|
||||||
|
message = "chiasson.system.gpuPassthru: windowsDisk must be set to a /dev/disk/by-id/ path.";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = cfg.libvirtUsers != [ ];
|
||||||
|
message = "chiasson.system.gpuPassthru: libvirtUsers must name at least one user.";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
boot.kernelParams = [
|
||||||
|
"intel_iommu=on"
|
||||||
|
"iommu=pt"
|
||||||
|
"kvm.ignore_msrs=1"
|
||||||
|
"vfio-pci.ids=${vfioIds}"
|
||||||
|
];
|
||||||
|
|
||||||
|
boot.initrd.kernelModules = [
|
||||||
|
"vfio_pci"
|
||||||
|
"vfio"
|
||||||
|
"vfio_iommu_type1"
|
||||||
|
];
|
||||||
|
|
||||||
|
boot.blacklistedKernelModules = [
|
||||||
|
"nouveau"
|
||||||
|
"nvidia"
|
||||||
|
"nvidia_drm"
|
||||||
|
"nvidia_modeset"
|
||||||
|
"i2c_nvidia_gpu"
|
||||||
|
"mt7921e"
|
||||||
|
"mt7925e"
|
||||||
|
];
|
||||||
|
|
||||||
|
boot.extraModprobeConfig = ''
|
||||||
|
softdep nvidia pre: vfio-pci
|
||||||
|
softdep nvidia_drm pre: vfio-pci
|
||||||
|
softdep nouveau pre: vfio-pci
|
||||||
|
options vfio_iommu_type1 allow_unsafe_interrupts=1
|
||||||
|
'';
|
||||||
|
|
||||||
|
services.xserver.videoDrivers = lib.mkForce [ "modesetting" ];
|
||||||
|
|
||||||
|
hardware.nvidia-container-toolkit.enable = lib.mkForce false;
|
||||||
|
chiasson.system.gaming.sunshine.cudaSupport = lib.mkForce false;
|
||||||
|
|
||||||
|
# libvirt enables ZFS storage pools on Linux by default, which pulls in
|
||||||
|
# zfs-user (currently broken to build on nixos-unstable). Raw block disk
|
||||||
|
# passthrough does not need libvirt ZFS support.
|
||||||
|
nixpkgs.overlays =
|
||||||
|
[
|
||||||
|
(final: prev: {
|
||||||
|
libvirt = prev.libvirt.override { enableZfs = false; };
|
||||||
|
})
|
||||||
|
]
|
||||||
|
++ lib.optionals cfg.lookingGlass.enable [
|
||||||
|
(final: prev: {
|
||||||
|
looking-glass-client = prev.looking-glass-client.overrideAttrs (old: {
|
||||||
|
version = lgVersion;
|
||||||
|
src = prev.fetchFromGitHub {
|
||||||
|
owner = "gnif";
|
||||||
|
repo = "LookingGlass";
|
||||||
|
rev = lgRev;
|
||||||
|
hash = lgHash;
|
||||||
|
fetchSubmodules = true;
|
||||||
|
};
|
||||||
|
patches = old.patches;
|
||||||
|
postUnpack = ''
|
||||||
|
echo ${lgRev} > $sourceRoot/VERSION
|
||||||
|
export sourceRoot="$sourceRoot/client"
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
programs.virt-manager.enable = true;
|
||||||
|
virtualisation.spiceUSBRedirection.enable = true;
|
||||||
|
|
||||||
|
virtualisation.libvirtd = {
|
||||||
|
enable = true;
|
||||||
|
onBoot = "ignore";
|
||||||
|
onShutdown = "shutdown";
|
||||||
|
qemu = {
|
||||||
|
package = pkgs.qemu_kvm;
|
||||||
|
# GPU + raw block passthrough needs root (or fragile per-device ACLs).
|
||||||
|
runAsRoot = true;
|
||||||
|
swtpm.enable = true;
|
||||||
|
verbatimConfig = lib.mkIf cfg.lookingGlass.enable (lib.mkForce lgQemuVerbatimConfig);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.libvirtd.restartTriggers = [
|
||||||
|
"${pkgs.qemu_kvm}/bin/qemu-system-x86_64"
|
||||||
|
];
|
||||||
|
|
||||||
|
environment.systemPackages =
|
||||||
|
with pkgs;
|
||||||
|
[
|
||||||
|
virt-manager
|
||||||
|
qemu_kvm
|
||||||
|
OVMF
|
||||||
|
edk2
|
||||||
|
looking-glass-client
|
||||||
|
swtpm
|
||||||
|
]
|
||||||
|
++ lib.optionals cfg.lookingGlass.enable [
|
||||||
|
(writeShellScriptBin "looking-glass-toggle" ''
|
||||||
|
set -euo pipefail
|
||||||
|
pkill -f 'looking-glass-client' || true
|
||||||
|
exec looking-glass-client -F -m 97
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
|
||||||
|
# B7 defaults to /dev/kvmfr0; pin SPICE to the fixed port in the domain XMLs.
|
||||||
|
environment.etc."looking-glass-client.ini" = lib.mkIf cfg.lookingGlass.enable (lib.mkForce {
|
||||||
|
text = ''
|
||||||
|
[app]
|
||||||
|
shmFile=/dev/kvmfr0
|
||||||
|
allowDMA=yes
|
||||||
|
|
||||||
|
[win]
|
||||||
|
fullScreen=yes
|
||||||
|
|
||||||
|
[spice]
|
||||||
|
enable=yes
|
||||||
|
host=127.0.0.1
|
||||||
|
port=5900
|
||||||
|
input=yes
|
||||||
|
audio=yes
|
||||||
|
clipboard=yes
|
||||||
|
|
||||||
|
[input]
|
||||||
|
captureOnFocus=${lib.boolToString cfg.lookingGlass.captureOnFocus}
|
||||||
|
escapeKey=97
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
|
||||||
|
users.groups.libvirtd.members = cfg.libvirtUsers;
|
||||||
|
users.users =
|
||||||
|
lib.genAttrs cfg.libvirtUsers (_: {
|
||||||
|
extraGroups = [
|
||||||
|
"libvirtd"
|
||||||
|
"kvm"
|
||||||
|
"disk"
|
||||||
|
];
|
||||||
|
})
|
||||||
|
// {
|
||||||
|
qemu-libvirtd.extraGroups = [
|
||||||
|
"kvm"
|
||||||
|
"disk"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d /var/lib/libvirt/boot 0755 root root -"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
(lib.mkIf cfg.lookingGlass.enable {
|
||||||
|
boot.extraModulePackages = lib.mkAfter [ config.boot.kernelPackages.kvmfr ];
|
||||||
|
boot.initrd.kernelModules = lib.mkAfter [ "kvmfr" ];
|
||||||
|
boot.kernelModules = lib.mkAfter [ "kvmfr" ];
|
||||||
|
boot.kernelParams = lib.mkAfter [
|
||||||
|
"kvmfr.static_size_mb=${toString cfg.lookingGlass.shmSizeMiB}"
|
||||||
|
];
|
||||||
|
|
||||||
|
boot.extraModprobeConfig = lib.mkAfter ''
|
||||||
|
options kvmfr static_size_mb=${toString cfg.lookingGlass.shmSizeMiB}
|
||||||
|
'';
|
||||||
|
|
||||||
|
services.udev.packages = [
|
||||||
|
(pkgs.writeTextFile {
|
||||||
|
name = "kvmfr-udev";
|
||||||
|
text = ''
|
||||||
|
SUBSYSTEM=="kvmfr", GROUP="kvm", MODE="0660", TAG+="uaccess"
|
||||||
|
'';
|
||||||
|
destination = "/etc/udev/rules.d/70-kvmfr.rules";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
# insmod from the nix store: extraModulePackages only lands in
|
||||||
|
# /run/booted-system/kernel-modules after a reboot.
|
||||||
|
systemd.services.kvmfr = {
|
||||||
|
description = "Looking Glass kvmfr module";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
before = [
|
||||||
|
"libvirtd.service"
|
||||||
|
"libvirtd-config.service"
|
||||||
|
"libvirt-guests.service"
|
||||||
|
];
|
||||||
|
after = [ "systemd-modules-load.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
ExecStart = pkgs.writeShellScript "kvmfr-start" (
|
||||||
|
let
|
||||||
|
kvmfrKo = "${config.boot.kernelPackages.kvmfr}/lib/modules/${config.boot.kernelPackages.kernel.modDirVersion}/kernel/drivers/misc/kvmfr.ko";
|
||||||
|
shmMiB = toString cfg.lookingGlass.shmSizeMiB;
|
||||||
|
in
|
||||||
|
''
|
||||||
|
set -euo pipefail
|
||||||
|
if [ -e /dev/kvmfr0 ] && [ ! -c /dev/kvmfr0 ]; then
|
||||||
|
rm -f /dev/kvmfr0
|
||||||
|
fi
|
||||||
|
if [ -c /dev/kvmfr0 ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if ${pkgs.kmod}/bin/lsmod | ${pkgs.gnugrep}/bin/grep -q '^kvmfr '; then
|
||||||
|
${pkgs.kmod}/bin/rmmod kvmfr
|
||||||
|
fi
|
||||||
|
if [ ! -f ${kvmfrKo} ]; then
|
||||||
|
echo "kvmfr: module missing at ${kvmfrKo}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
${pkgs.kmod}/bin/insmod ${kvmfrKo} static_size_mb=${shmMiB}
|
||||||
|
if [ ! -c /dev/kvmfr0 ]; then
|
||||||
|
echo "kvmfr: /dev/kvmfr0 not created (static_size_mb=${shmMiB})" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
''
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
systemd.services.libvirtd = lib.mkIf cfg.lookingGlass.enable {
|
||||||
|
after = [ "kvmfr.service" ];
|
||||||
|
requires = [ "kvmfr.service" ];
|
||||||
|
};
|
||||||
|
})
|
||||||
|
(lib.mkIf cfg.hugepages.enable {
|
||||||
|
boot.kernelParams = [ "hugepagesz=2M" "hugepages=64" ];
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
wget
|
wget
|
||||||
unzip
|
unzip
|
||||||
jq
|
jq
|
||||||
|
ripgrep
|
||||||
pfetch
|
pfetch
|
||||||
];
|
];
|
||||||
description = "Default packages to install on all hosts.";
|
description = "Default packages to install on all hosts.";
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
{ ... }: {
|
||||||
|
flake.nixosModules.systemTailscale =
|
||||||
|
{ config, lib, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.chiasson.system.networking.tailscale;
|
||||||
|
tsCfg = config.services.tailscale;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.chiasson.system.networking.tailscale = {
|
||||||
|
enable = lib.mkEnableOption ''
|
||||||
|
Tailscale mesh VPN. Joins this host to your tailnet for encrypted access
|
||||||
|
from anywhere without opening inbound ports on your router.
|
||||||
|
'';
|
||||||
|
|
||||||
|
authKeyFile = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.path;
|
||||||
|
default = null;
|
||||||
|
example = "/run/secrets/tailscale/auth-key";
|
||||||
|
description = ''
|
||||||
|
Reusable Tailscale auth key (sops path). Create one at
|
||||||
|
https://login.tailscale.com/admin/settings/keys — enable Reusable and
|
||||||
|
Pre-approved. Store under `tailscale/auth-key` in secrets/secrets.yaml.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
openFirewall = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Allow Tailscale UDP 41641 through the host firewall.";
|
||||||
|
};
|
||||||
|
|
||||||
|
acceptRoutes = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Accept subnet routes advertised by other tailnet nodes (e.g. home LAN
|
||||||
|
via nix-server). Enable on portable clients like t2mbp.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
subnetRouter = {
|
||||||
|
enable = lib.mkEnableOption ''
|
||||||
|
Advertise the home LAN through this node so other tailnet devices can
|
||||||
|
reach local IPs (SSH, Attic, Gitea, Jellyfin, etc.). Enable on an
|
||||||
|
always-on home host (nix-server). Approve the route in the Tailscale
|
||||||
|
admin console after first connect.
|
||||||
|
'';
|
||||||
|
|
||||||
|
routes = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [ "192.168.2.0/24" ];
|
||||||
|
example = [ "192.168.2.0/24" ];
|
||||||
|
description = "Subnets to advertise to the tailnet.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable (lib.mkMerge [
|
||||||
|
{
|
||||||
|
services.tailscale = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = cfg.openFirewall;
|
||||||
|
authKeyFile = cfg.authKeyFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.trustedInterfaces = lib.mkAfter [ "tailscale0" ];
|
||||||
|
}
|
||||||
|
(lib.mkIf cfg.acceptRoutes {
|
||||||
|
services.tailscale.useRoutingFeatures = "client";
|
||||||
|
services.tailscale.extraUpFlags = [ "--accept-routes" ];
|
||||||
|
})
|
||||||
|
(lib.mkIf cfg.subnetRouter.enable {
|
||||||
|
services.tailscale.useRoutingFeatures = "both";
|
||||||
|
services.tailscale.extraUpFlags =
|
||||||
|
map (route: "--advertise-routes=${route}") cfg.subnetRouter.routes;
|
||||||
|
})
|
||||||
|
(lib.mkIf (cfg.authKeyFile != null) {
|
||||||
|
# Upstream uses `$(cat $authKeyFile)` which breaks when sops leaves a trailing newline.
|
||||||
|
systemd.services.tailscaled-autoconnect.script = lib.mkOverride 50 ''
|
||||||
|
getState() {
|
||||||
|
tailscale status --json --peers=false | jq -r '.BackendState'
|
||||||
|
}
|
||||||
|
|
||||||
|
lastState=""
|
||||||
|
while state="$(getState)"; do
|
||||||
|
if [[ "$state" != "$lastState" ]]; then
|
||||||
|
case "$state" in
|
||||||
|
NeedsLogin|NeedsMachineAuth|Stopped)
|
||||||
|
echo "Server needs authentication, sending auth key"
|
||||||
|
tailscale up --auth-key "$(tr -d '\n\r' < ${cfg.authKeyFile})" ${lib.escapeShellArgs tsCfg.extraUpFlags}
|
||||||
|
;;
|
||||||
|
Running)
|
||||||
|
echo "Tailscale is running"
|
||||||
|
systemd-notify --ready
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Waiting for Tailscale State = Running or systemd timeout"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo "State = $state"
|
||||||
|
fi
|
||||||
|
lastState="$state"
|
||||||
|
sleep .5
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -23,11 +23,24 @@
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
extraModules = lib.mkOption {
|
extraModules = lib.mkOption {
|
||||||
type = lib.types.attrsOf (lib.types.listOf lib.types.unspecified);
|
type =
|
||||||
|
(lib.types.attrsOf (lib.types.listOf lib.types.unspecified))
|
||||||
|
// {
|
||||||
|
merge =
|
||||||
|
loc: defs:
|
||||||
|
let
|
||||||
|
values = map (d: d.value) defs;
|
||||||
|
names = lib.unique (lib.concatLists (map builtins.attrNames values));
|
||||||
|
in
|
||||||
|
lib.genAttrs names (
|
||||||
|
name: lib.concatLists (map (v: v.${name} or [ ]) values)
|
||||||
|
);
|
||||||
|
};
|
||||||
default = { };
|
default = { };
|
||||||
description = ''
|
description = ''
|
||||||
Per-user Home Manager `extraModules` keyed by catalog user name.
|
Per-user Home Manager `extraModules` keyed by catalog user name.
|
||||||
Keys must match `chiasson.users.enabled`.
|
Keys must match `chiasson.users.enabled`. Lists from multiple modules
|
||||||
|
are concatenated (e.g. `desktop-home-base.nix` + host `home.nix`).
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
homeManager = {
|
homeManager = {
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
./hardware/uconsole-gamepad.nix
|
./hardware/uconsole-gamepad.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# Root module: chiasson.home.enable + bash. Everything else is separate `wisdom*` exports —
|
# Root module: chiasson.home.enable + bash. Other `wisdom*` slices auto-wire via
|
||||||
# pull those into `home.users.<name>.extraModules` on each host as needed.
|
# `lib.wisdomCatalogExtraModules`; hosts flip `chiasson.home.*.enable` rather than re-importing.
|
||||||
flake.homeManagerModules.wisdom =
|
flake.homeManagerModules.wisdom =
|
||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
let
|
let
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
|
|
||||||
options.chiasson.home = {
|
options.chiasson.home = {
|
||||||
enable = lib.mkEnableOption ''
|
enable = lib.mkEnableOption ''
|
||||||
HM profile root for this flake (bash on by default). Wire other `wisdom*` modules in
|
HM profile root for this flake (bash on by default). Desktop hosts use
|
||||||
`home.users.<name>.extraModules` and flip their `chiasson.home.*.enable` options on the host.
|
`lib.wisdomCatalogExtraModules` once per user and flip `chiasson.home.*.enable` on the host.
|
||||||
'' // {
|
'' // {
|
||||||
default = true;
|
default = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
{ ... }: {
|
{ ... }: {
|
||||||
# Optional fragment: import from `home.users.<name>.extraModules` only on hosts that need Yazi so this
|
# Gated by `chiasson.home.shell.yazi.enable` (desktop hosts wire slices via `desktopHomeBase`).
|
||||||
# module (and its `pkgs.yazi` wiring) is not evaluated when omitted.
|
|
||||||
flake.homeManagerModules.wisdomShellYazi =
|
flake.homeManagerModules.wisdomShellYazi =
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
let
|
let
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
{ ... }: {
|
{ ... }: {
|
||||||
flake.homeManagerModules.wisdomTerminalsKitty =
|
flake.homeManagerModules.wisdomTerminalsKitty =
|
||||||
{ config, lib, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
let
|
let
|
||||||
root = config.chiasson.home;
|
root = config.chiasson.home;
|
||||||
cfg = config.chiasson.home.terminals.kitty;
|
cfg = config.chiasson.home.terminals.kitty;
|
||||||
|
kittyShellExe =
|
||||||
|
if config.programs.fish.enable or false then
|
||||||
|
lib.getExe config.programs.fish.package
|
||||||
|
else if config.programs.bash.enable or false then
|
||||||
|
lib.getExe config.programs.bash.package
|
||||||
|
else
|
||||||
|
"${pkgs.bash}/bin/bash";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.chiasson.home.terminals.kitty.enable = lib.mkEnableOption ''
|
options.chiasson.home.terminals.kitty.enable = lib.mkEnableOption ''
|
||||||
@@ -14,6 +21,7 @@
|
|||||||
programs.kitty = {
|
programs.kitty = {
|
||||||
enable = true;
|
enable = true;
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
|
shell ${kittyShellExe}
|
||||||
include dank-tabs.conf
|
include dank-tabs.conf
|
||||||
include dank-theme.conf
|
include dank-theme.conf
|
||||||
allow_remote_control yes
|
allow_remote_control yes
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ cachix:
|
|||||||
caching:
|
caching:
|
||||||
attic:
|
attic:
|
||||||
token: ENC[AES256_GCM,data:8omssG3GwCFIegfz+8IAGGhFGj01RB3dqqHeFpmZOzMJUshIDvSRuTTpGFhUBC7Xue8h09hAhpirIHmqzyG3I+e2Se/VZZoByXmpyIKesl3+NqOXDkJvgImqhvFVkTiSe5p/vSN3slWDylfkThQ0hZYw5mB9J13M5965iUnWcRbg+1fYFdTuSgrHY8Rxt4da0287A0YGnsN63k7j32XOJndxsRoOLoo+IQ+X+hiPOJkfGYxY0MglnxaxhPwH8SP1V+p78N75Z2npOtMdEikdHmj/NmKbqUXN2P0+IXthxV17WePCulZVsKC1Jw+clgbyAvHcQeVG/yyrcb1CRRQpszHtq1Pz7DHvfAG+gxyPNyP7D6oQNT8foX4C6CwuHgYQtM1x0D6oAL+lppQWJ0kEV/GDlJSXQnp/aBbVAqDmqS0TCx40nVmQ0PvMcjtsiZJigkRJRNLCg6n+qmhc5Rh9RhslPN5JXU0orWs9QYAoLXzdDDGP/R9tlEhwQBxwGrFAp016iilqPavMdI8txrWWdvezQuAh//eeW5LQSa6t363VCjX8phnXeJltOgXYlyuKnCCmv0a6XwhmT0PA+32/F0BxTf9lcZConpurlvOHdznaVeUXcFOEwKouDC7smPIZZqcRU8OIbWs7YXqMgatgb/bJVtB0P0Avsj9t9Uz8Dv8xBV+90U5qwM7HV16FIERorDquzgKFcvtb8/QfjTINoswpHZKNCbmQPxfJYPheJFwMQGFn+b+ecv+Z7qng9JEujJSNtEPv2CIuVmSxZJaU5g2CMu3rFGIA3qF81Bf1Ri8n+KYWgOKpQt11nClouv2XePO8JKI6fslF411zJ8zD4E/6Qg95UWhLh0RG2cXzYSXXvrpXDlIe9spc4OLuj4tFtXkiZZvfM5MgRTtoh93soypUpEbswTji2UprC3OPikjIIW49YysGVsH2100/67HbtinRoazM1M+DjaD2pMryx7kW/oVpyaW61wiqtHk9nq8vqROLWBhQxzGSh9157z/46AT+8PN89gFh5uNdFuhFz8e8/HIV3HtIrzrtR+flJfHJ1ZT5dhTDicSMiC/DhG/hupX4GHGX6zlaMgBqB8bKxxvs+v0iHfSkDIkuenZ+nTD72DP5yuIQVIwGV16CZA6rusjb1zLn6QYpvQtCuqlih+epsGNEYP6B3rvNMc/N7JcwY4YMTK+C46EC9mXhpfPn0a5OdD4kQ6s=,iv:+g9W5MzgtLppD1K3dZ/tCuaMxaa194W3Lf23/jUmDvk=,tag:5uVwIOkB2+MRHPGlKGQtGg==,type:str]
|
token: ENC[AES256_GCM,data:8omssG3GwCFIegfz+8IAGGhFGj01RB3dqqHeFpmZOzMJUshIDvSRuTTpGFhUBC7Xue8h09hAhpirIHmqzyG3I+e2Se/VZZoByXmpyIKesl3+NqOXDkJvgImqhvFVkTiSe5p/vSN3slWDylfkThQ0hZYw5mB9J13M5965iUnWcRbg+1fYFdTuSgrHY8Rxt4da0287A0YGnsN63k7j32XOJndxsRoOLoo+IQ+X+hiPOJkfGYxY0MglnxaxhPwH8SP1V+p78N75Z2npOtMdEikdHmj/NmKbqUXN2P0+IXthxV17WePCulZVsKC1Jw+clgbyAvHcQeVG/yyrcb1CRRQpszHtq1Pz7DHvfAG+gxyPNyP7D6oQNT8foX4C6CwuHgYQtM1x0D6oAL+lppQWJ0kEV/GDlJSXQnp/aBbVAqDmqS0TCx40nVmQ0PvMcjtsiZJigkRJRNLCg6n+qmhc5Rh9RhslPN5JXU0orWs9QYAoLXzdDDGP/R9tlEhwQBxwGrFAp016iilqPavMdI8txrWWdvezQuAh//eeW5LQSa6t363VCjX8phnXeJltOgXYlyuKnCCmv0a6XwhmT0PA+32/F0BxTf9lcZConpurlvOHdznaVeUXcFOEwKouDC7smPIZZqcRU8OIbWs7YXqMgatgb/bJVtB0P0Avsj9t9Uz8Dv8xBV+90U5qwM7HV16FIERorDquzgKFcvtb8/QfjTINoswpHZKNCbmQPxfJYPheJFwMQGFn+b+ecv+Z7qng9JEujJSNtEPv2CIuVmSxZJaU5g2CMu3rFGIA3qF81Bf1Ri8n+KYWgOKpQt11nClouv2XePO8JKI6fslF411zJ8zD4E/6Qg95UWhLh0RG2cXzYSXXvrpXDlIe9spc4OLuj4tFtXkiZZvfM5MgRTtoh93soypUpEbswTji2UprC3OPikjIIW49YysGVsH2100/67HbtinRoazM1M+DjaD2pMryx7kW/oVpyaW61wiqtHk9nq8vqROLWBhQxzGSh9157z/46AT+8PN89gFh5uNdFuhFz8e8/HIV3HtIrzrtR+flJfHJ1ZT5dhTDicSMiC/DhG/hupX4GHGX6zlaMgBqB8bKxxvs+v0iHfSkDIkuenZ+nTD72DP5yuIQVIwGV16CZA6rusjb1zLn6QYpvQtCuqlih+epsGNEYP6B3rvNMc/N7JcwY4YMTK+C46EC9mXhpfPn0a5OdD4kQ6s=,iv:+g9W5MzgtLppD1K3dZ/tCuaMxaa194W3Lf23/jUmDvk=,tag:5uVwIOkB2+MRHPGlKGQtGg==,type:str]
|
||||||
|
tailscale:
|
||||||
|
auth-key: ENC[AES256_GCM,data:ffBLc/LIm67P/DUSvDUek/qWHLfQbmSE3jQL1/TLHrZEEGk+HqEO4Prlj5bGGAU37tiHaD7Ksj1wqX3U+Q==,iv:Uw1tnuxMPZVwqvrRkZZusJM/a7QeoggR047+CKx9fnY=,tag:kS1IixpXYm1QVBIAmmgQ6Q==,type:str]
|
||||||
sops:
|
sops:
|
||||||
age:
|
age:
|
||||||
- enc: |
|
- enc: |
|
||||||
@@ -75,7 +77,7 @@ sops:
|
|||||||
6POXxpxjGhlWJaV47jqeN+7mQY2oTHE/x4raoX/KA2ouXL29K8QpmA==
|
6POXxpxjGhlWJaV47jqeN+7mQY2oTHE/x4raoX/KA2ouXL29K8QpmA==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
recipient: age1pewusvlcgzcnk0kpskgc9qr6jlq8s2yzwnqrnh84p7v5z0kj3qhsya8h2x
|
recipient: age1pewusvlcgzcnk0kpskgc9qr6jlq8s2yzwnqrnh84p7v5z0kj3qhsya8h2x
|
||||||
lastmodified: "2026-03-24T00:15:02Z"
|
lastmodified: "2026-06-10T03:00:15Z"
|
||||||
mac: ENC[AES256_GCM,data:dYTwO5DtkKinTKfBXGuvXRFxl8yavxXMKTw27M5/GcK/kkstHBG119IRk9B9KC6s6IHTY81U3MeUxE9XwdBiE7q4m15+ZO2vmdBVhN8wAh+82P9BP0HSaxLkjWLeKWBfULyLX/YXmQVsr09/NUEVSZcugJ6m40Ta+X9AQgO+cyA=,iv:FmsznsKTuIr61s3Zn0QZKSKvb/e2AljEB1ijKE52RKk=,tag:rHF2Xi4iP9VF33rxpBr5pg==,type:str]
|
mac: ENC[AES256_GCM,data:F1DU7Sj9lsTOHWlyuY4L4N+urrBXv2GLKhlzohMA9iF6/bphRABa9we3WZX9MFNIc2Te+2SCh3f6Rv5eHwWSsZVdD4iwN/6HTabdNPTEOZyk/OVsap/F374MLu8ys3OVZ5vzg2PYCGmhlf4PQMrjvaz+CV3t8UezB6E4U0N3RuU=,iv:wT2ieUON5VInJhDtZFLENzyaty5TqcisLmYePnCHGM4=,tag:z9CYpCWa/XdSqPKMG3M41A==,type:str]
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.12.1
|
version: 3.13.1
|
||||||
|
|||||||
Reference in New Issue
Block a user