Compare commits

..

24 Commits

Author SHA1 Message Date
433cfe3985 Update plan to use WinBtrfs 2025-07-29 11:18:24 -07:00
ffd7ce45a7 Initial plan using symlinks 2025-07-29 10:34:50 -07:00
cc3d398963 [printing] Ensure Brother printer is found 2025-07-23 19:47:43 -07:00
f757ea7271 [kodi] Add kdeconnect 2025-07-19 14:55:35 -07:00
64149713d2 [home] Add k8s management apps 2025-07-16 22:38:19 -07:00
88b413e0af [nixbook] disable gaming 2025-07-16 18:52:51 -07:00
c5070eb4bf [home] Re-enable openscad-unstable 2025-07-13 12:07:01 -07:00
6b4dc1e6b7 Add CLAUDE.md 2025-07-13 12:06:55 -07:00
aadd8c7b6c [home] Add claude-code 2025-07-13 12:06:46 -07:00
f8d145b495 [secrets] Remove altogether
I'm standardizing on bitwarden and rbw for secrets. No need to build out
a separate secret management system. The complexity of this was just not
worth it for my effectively single-user workflows
2025-07-13 11:08:42 -07:00
9232d46f6a [wixos] Add users role 2025-07-13 11:06:49 -07:00
b2b34fc05f [flake] update 2025-07-13 10:44:00 -07:00
aa4dacb3af Add bootstrap script
Adds a very simple bootstrap script for setting up a new host. I'm not
exactly sure the best way to use this yet. Though I suppose it could be
run with some sort of "curl https://blahblah | bash" shenanigans. That
just seems like it would be about as much effort as just running the
nixos-rebuild command itself from a new host.

In any case though, this worked well for bootstrapping a new wixos
instance. So that was nice.
2025-07-13 10:28:52 -07:00
6dc4d6956a [doom] defer loading gptel
This prevents the rbw auth prompt from appearing until it is actually needed
2025-07-13 10:27:52 -07:00
be83fc566f [wixos] remove deprecated reference 2025-07-13 10:16:31 -07:00
485df44aea [home] Add snapcast 2025-06-07 09:41:39 -07:00
4861128de6 [doom] Add gptel 2025-05-28 18:45:20 -07:00
9fe7cfbbfc [home] Add codex 2025-05-27 19:35:26 -07:00
741e3a67d6 [doom] unset DOOMPROFILE 2025-05-27 19:35:16 -07:00
22254eb1f3 [doom] bump version 2025-05-27 19:02:34 -07:00
79dde1a0fe [flake] update 2025-05-26 11:28:26 -07:00
f4b3c36a4e [openscad] Disable for now 2025-05-26 11:27:27 -07:00
1fa7a2689c [home] Add openscad-unstable 2025-05-26 11:23:56 -07:00
c08c5e2486 [emacs] Remove doom-emacs-unstraightened 2025-05-26 11:23:50 -07:00
19 changed files with 543 additions and 217 deletions

View File

@@ -7,7 +7,6 @@ This repository hosts modular and reproducible NixOS configurations managed via
Directory Structure:
----------------------
• secrets/ - Confidential data (passwords, keys, etc.) required for system configuration.
• packages/ - Custom Nix packages leveraged across various configurations.
• roles/ - Role-based configurations (e.g., kodi, bluetooth) each with its own module (default.nix) for inclusion in machine setups.
• machines/ - Machine-specific configurations (e.g., nix-book, z790prors, boxy, wixos) including configuration.nix and hardware-configuration.nix tailored for each hardware.

View File

@@ -1,11 +0,0 @@
keys:
- &admin_johno age1ls6a033d4p4u8h4rwazjwt8w4c4xg73wq0mdnm64jajxzcz4k9asvjnks3
- &host_z790prors age12l5u7sw59u5pkwp83qm8t3ff7uv0ld2c9k3zh5j4ame9k2szcynqu7ftqe
- &host_nixbook age1fa3zqavfmqk4ssa22yne9td90gyqv9q5a8y0s8jp3xak8q7p3yjqyn7rkg
creation_rules:
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
key_groups:
- age:
- *admin_johno
- *host_z790prors
- *host_nixbook

110
CLAUDE.md Normal file
View File

@@ -0,0 +1,110 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Repository Overview
This is a NixOS configuration repository using flakes, managing multiple machines and home-manager configurations. The repository follows a modular architecture with reusable "roles" that can be composed for different machines.
## Architecture
### Flake Structure
- **flake.nix**: Main entry point defining inputs (nixpkgs, home-manager, plasma-manager, etc.) and outputs for multiple NixOS configurations
- **Machines**: `nix-book`, `boxy`, `wixos` (WSL configuration)
- **Home configurations**: Standalone home-manager configuration for user `johno`
### Directory Structure
- `machines/`: Machine-specific configurations with hardware-configuration.nix
- `roles/`: Modular system configurations (audio, bluetooth, desktop, users, etc.)
- `home/`: Home Manager configurations and user-specific modules
- `home/modules/`: User environment modules (emacs, i3+sway, plasma-manager, tmux)
- `packages/`: Custom package definitions
### Role-Based Configuration System
The repository uses a custom "roles" system where each role is a NixOS module with enable options:
- `roles.desktop`: Desktop environment with sub-options for X11, Wayland, KDE, gaming, SDDM
- `roles.audio`: Audio configuration
- `roles.bluetooth`: Bluetooth support
- `roles.users`: User account management
- `roles.virtualisation`: Virtualization setup
- `roles.kodi`: Kodi media center
Example role usage in machine configuration:
```nix
roles = {
audio.enable = true;
desktop = {
enable = true;
gaming = true;
kde = true;
wayland = true;
};
users.enable = true;
};
```
## Common Commands
### Building and Switching Configurations
```bash
# Build and switch to a specific machine configuration
sudo nixos-rebuild switch --flake .#<hostname>
# Build without switching
nixos-rebuild build --flake .#<hostname>
# Build home-manager configuration only
home-manager switch --flake .#johno
```
### Available Machine Configurations
- `nix-book`: Uses `home/home-nix-book.nix`
- `boxy`: Gaming desktop with AMD GPU, uses `home/home.nix`
- `wixos`: WSL configuration, uses `home/home.nix`
### Flake Operations
```bash
# Update flake inputs
nix flake update
# Check flake
nix flake check
# Show flake info
nix flake show
```
### Bootstrap New Machine
Use the provided bootstrap script:
```bash
sudo ./bootstrap.sh <hostname>
```
This script pulls from the remote git repository and applies the configuration.
## Development Workflow
### Adding New Machines
1. Create new directory in `machines/<hostname>/`
2. Add `configuration.nix` with role assignments
3. Include hardware-configuration.nix (generated by nixos-generate-config)
4. Add nixosConfiguration to flake.nix outputs
### Adding New Roles
1. Create directory in `roles/<role-name>/`
2. Create `default.nix` with module definition using mkEnableOption
3. Add role import to `roles/default.nix`
4. Configure role options in machine configurations
### Home Manager Modules
- Located in `home/modules/`
- Each module has its own `default.nix`
- Imported in main home configuration files
## Key Configuration Details
- **Experimental features**: nix-command and flakes are enabled
- **User**: Primary user is `johno` with trusted-user privileges
- **Locale**: en_US.UTF-8, America/Los_Angeles timezone
- **SSH**: OpenSSH enabled on all configurations
- **Garbage collection**: Automatic, deletes older than 10 days
- **Unfree packages**: Allowed globally

11
bootstrap.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
# bootstrap.sh
# Usage: sudo ./bootstrap.sh <hostname>
set -euo pipefail
NEW_HOSTNAME="${1:?missing hostname}"
FLAKE_URI="git+https://git.johnogle.info/johno/nixos-configs.git#${NEW_HOSTNAME}"
export NIX_CONFIG="experimental-features = nix-command flakes"
nixos-rebuild switch --flake "$FLAKE_URI"

147
flake.lock generated
View File

@@ -1,52 +1,13 @@
{
"nodes": {
"doomemacs": {
"flake": false,
"locked": {
"lastModified": 1742013576,
"narHash": "sha256-wgzv3IFBxJkAYfLG0vCp1jbajHKrrpFzKZ2BssWVSlo=",
"owner": "doomemacs",
"repo": "doomemacs",
"rev": "466490c252d06f42a9c165f361de74a6e6abad8d",
"type": "github"
},
"original": {
"owner": "doomemacs",
"repo": "doomemacs",
"type": "github"
}
},
"emacs-overlay": {
"inputs": {
"nixpkgs": [
"nix-doom-emacs-unstraightened"
],
"nixpkgs-stable": [
"nix-doom-emacs-unstraightened"
]
},
"locked": {
"lastModified": 1742113225,
"narHash": "sha256-tUor57FbLwwy+duUbjq8Ff0TyayK1i50rUbXBfdgfuM=",
"owner": "nix-community",
"repo": "emacs-overlay",
"rev": "7e13aa507d714371e6ff70a91d76dcb339311773",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "emacs-overlay",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1733328505,
"narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
"lastModified": 1747046372,
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
"type": "github"
},
"original": {
@@ -62,11 +23,11 @@
]
},
"locked": {
"lastModified": 1739823862,
"narHash": "sha256-h08hlS0ImlONZfeemVMzo29PUC3/abdSb9muYO9E048=",
"lastModified": 1752428473,
"narHash": "sha256-IsE7fdAYbRlZuc0H5FtPfhhuHvlxnDGoAxdlnjpVNCU=",
"ref": "refs/heads/main",
"rev": "675f98b0145f908897c4d899836bcb3dad9da79a",
"revCount": 9,
"rev": "1fad66b55144ab6beaecd900172a21ac3c34dc52",
"revCount": 10,
"type": "git",
"url": "https://git.johnogle.info/johno/google-cookie-retrieval.git"
},
@@ -82,11 +43,11 @@
]
},
"locked": {
"lastModified": 1741955947,
"narHash": "sha256-2lbURKclgKqBNm7hVRtWh0A7NrdsibD0EaWhahUVhhY=",
"lastModified": 1752402455,
"narHash": "sha256-mCHfZhQKdTj2JhCFcqfOfa3uKZbwUkPQbd0/zPnhOE8=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "4e12151c9e014e2449e0beca2c0e9534b96a26b4",
"rev": "bf893ad4cbf46610dd1b620c974f824e266cd1df",
"type": "github"
},
"original": {
@@ -95,40 +56,17 @@
"type": "github"
}
},
"nix-doom-emacs-unstraightened": {
"inputs": {
"doomemacs": "doomemacs",
"emacs-overlay": "emacs-overlay",
"nixpkgs": [
"nixpkgs"
],
"systems": "systems"
},
"locked": {
"lastModified": 1742122199,
"narHash": "sha256-vEdsZd9MmjRYXutcSVnOoR15ikI9yU8Oc9f1UCNvUwI=",
"owner": "marienz",
"repo": "nix-doom-emacs-unstraightened",
"rev": "366d3b516d4878e1f93158708015be3dac09a72f",
"type": "github"
},
"original": {
"owner": "marienz",
"repo": "nix-doom-emacs-unstraightened",
"type": "github"
}
},
"nixos-wsl": {
"inputs": {
"flake-compat": "flake-compat",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1741870048,
"narHash": "sha256-odXRdNZGdXg1LmwlAeWL85kgy/FVHsgKlDwrvbR2BsU=",
"lastModified": 1752199438,
"narHash": "sha256-xSBMmGtq8K4Qv80TMqREmESCAsRLJRHAbFH2T/2Bf1Y=",
"owner": "nix-community",
"repo": "NixOS-WSL",
"rev": "5d76001e33ee19644a598ad80e7318ab0957b122",
"rev": "d34d9412556d3a896e294534ccd25f53b6822e80",
"type": "github"
},
"original": {
@@ -140,27 +78,27 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1740865531,
"narHash": "sha256-h00vGIh/jxcGl8aWdfnVRD74KuLpyY3mZgMFMy7iKIc=",
"lastModified": 1751792365,
"narHash": "sha256-J1kI6oAj25IG4EdVlg2hQz8NZTBNYvIS0l4wpr9KcUo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5ef6c425980847c78a80d759abc476e941a9bf42",
"rev": "1fd8bada0b6117e6c7eb54aad5813023eed37ccb",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.11",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1742069588,
"narHash": "sha256-C7jVfohcGzdZRF6DO+ybyG/sqpo1h6bZi9T56sxLy+k=",
"lastModified": 1751984180,
"narHash": "sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X+xgOL0=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "c80f6a7e10b39afcc1894e02ef785b1ad0b0d7e5",
"rev": "9807714d6944a957c2e036f84b0ff8caf9930bc0",
"type": "github"
},
"original": {
@@ -180,11 +118,11 @@
]
},
"locked": {
"lastModified": 1740569341,
"narHash": "sha256-WV8nY2IOfWdzBF5syVgCcgOchg/qQtpYh6LECYS9XkY=",
"lastModified": 1748196248,
"narHash": "sha256-1iHjsH6/5UOerJEoZKE+Gx1BgAoge/YcnUsOA4wQ/BU=",
"owner": "nix-community",
"repo": "plasma-manager",
"rev": "5eeb0172fb74392053b66a8149e61b5e191b2845",
"rev": "b7697abe89967839b273a863a3805345ea54ab56",
"type": "github"
},
"original": {
@@ -197,46 +135,9 @@
"inputs": {
"google-cookie-retrieval": "google-cookie-retrieval",
"home-manager": "home-manager",
"nix-doom-emacs-unstraightened": "nix-doom-emacs-unstraightened",
"nixos-wsl": "nixos-wsl",
"nixpkgs": "nixpkgs_2",
"plasma-manager": "plasma-manager",
"sops-nix": "sops-nix"
}
},
"sops-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1741861888,
"narHash": "sha256-ynOgXAyToeE1UdLNfrUn/hL7MN0OpIS2BtNdLjpjPf0=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "d016ce0365b87d848a57c12ffcfdc71da7a2b55f",
"type": "github"
},
"original": {
"owner": "Mic92",
"repo": "sops-nix",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
"plasma-manager": "plasma-manager"
}
}
},

View File

@@ -5,11 +5,6 @@
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
nixos-wsl.url = "github:nix-community/NixOS-WSL/main";
sops-nix = {
url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
@@ -21,11 +16,6 @@
inputs.home-manager.follows = "home-manager";
};
nix-doom-emacs-unstraightened = {
url = "github:marienz/nix-doom-emacs-unstraightened";
inputs.nixpkgs.follows = "nixpkgs";
};
google-cookie-retrieval = {
url = "git+https://git.johnogle.info/johno/google-cookie-retrieval.git";
inputs.nixpkgs.follows = "nixpkgs";
@@ -35,14 +25,12 @@
outputs = { self, nixpkgs, nixos-wsl, ... } @ inputs: let
baseModules = [
./roles
inputs.sops-nix.nixosModules.sops
inputs.home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.sharedModules = [
inputs.plasma-manager.homeManagerModules.plasma-manager
inputs.nix-doom-emacs-unstraightened.hmModule
];
home-manager.extraSpecialArgs = {
globalInputs = inputs;
@@ -90,7 +78,6 @@
pkgs = inputs.nixpkgs.legacyPackages."x86_64-linux";
modules = [
inputs.plasma-manager.homeManagerModules.plasma-manager
inputs.nix-doom-emacs-unstraightened.hmModule
./home/home.nix
];
extraSpecialArgs = {

View File

@@ -39,6 +39,8 @@ in
# '')
pkgs.bitwarden
pkgs.claude-code
pkgs.codex
pkgs.dunst
pkgs.element-desktop
pkgs.fd
@@ -54,16 +56,22 @@ in
pkgs.moonlight-qt
pkgs.ncdu
pkgs.nextcloud-talk-desktop
pkgs.openscad-unstable
pkgs.pandoc
#pkgs.pinentry-qt
#pkgs.pytest
pkgs.shellcheck
pkgs.solaar # Logitech management software
(pkgs.snapcast.override { pulseaudioSupport = true; })
pkgs.tmux
pkgs.waybar
pkgs.wofi
pkgs.vlc
## Kubernetes cluster management
pkgs.kubectl
pkgs.kubernetes-helm
globalInputs.google-cookie-retrieval.packages.${system}.default
];
@@ -113,7 +121,16 @@ in
./modules/tmux
];
programs.bash.enable = true;
programs.bash = {
enable = true;
initExtra = ''
codex() {
local key
key="$(rbw get openai-api-key-codex)"
OPENAI_API_KEY="$key" command codex "$@"
}
'';
};
# Let Home Manager install and manage itself.
programs.home-manager.enable = true;

View File

@@ -2,10 +2,21 @@
with lib;
let
doomEmacs = pkgs.fetchFromGitHub {
owner = "doomemacs";
repo = "doomemacs";
rev = "8406c1ff22b95bd0f816de4a0223fa3ce3c82568";
sha256 = "sha256-rOkgOdmLESVAbOeEM9nJTzxyI+akdk48Ed2VlktOy3Q=";
};
in
{
config = {
home.packages = [
pkgs.emacs
pkgs.emacs-all-the-icons-fonts
pkgs.fira-code
pkgs.fontconfig
pkgs.graphviz
pkgs.isort
@@ -19,15 +30,18 @@ with lib;
pkgs.python3
];
programs.doom-emacs = {
enable = true;
doomDir = ./doom;
};
fonts.fontconfig.enable = true;
home.file."${config.xdg.configHome}/emacs".source = doomEmacs;
home.sessionPath = [
"${config.xdg.configHome}/emacs/bin"
];
home.sessionVariables = {
EDITOR = "emacs -nw";
DOOMDIR = "${config.xdg.configHome}/doom";
DOOMLOCALDIR = "${config.xdg.dataHome}/doom";
};
home.file."${config.xdg.configHome}/doom".source = ./doom;
};
}

View File

@@ -72,6 +72,16 @@
;; org-caldav-files nil
;; org-caldav-sync-direction 'cal->org))
(defun my/get-rbw-password (alias)
"Return the password for ALIAS via rbw, unlocking the vault only if needed."
(let* ((cmd (format "rbw get %s 2>&1" alias))
(output (shell-command-to-string cmd)))
(string-trim output)))
(use-package! gptel
:defer t
:config
(setq! gptel-api-key (my/get-rbw-password "openai-api-key-chatgpt-el")))
;; Whenever you reconfigure a package, make sure to wrap your config in an
;; `after!' block, otherwise Doom's defaults may override your settings. E.g.

View File

@@ -108,7 +108,7 @@
:os
(:if (featurep :system 'macos) macos) ; improve compatibility with macOS
;;tty ; improve the terminal Emacs experience
tty ; improve the terminal Emacs experience
:lang
;;agda ; types of types of types of types...

View File

@@ -50,3 +50,5 @@
;; (unpin! t)
;; (package! org-caldav)
(package! gptel :recipe (:nonrecursive t))

View File

@@ -15,7 +15,7 @@
desktop = {
enable = true;
wayland = true;
gaming = true;
gaming = false;
kde = true;
sddm = true;
};

View File

@@ -17,6 +17,7 @@
enable = true;
wayland = true;
};
users.enable = true;
};
networking.hostName = "wixos";
@@ -33,7 +34,7 @@
enable = true;
extraPackages = with pkgs; [
mesa.drivers
mesa
libvdpau-va-gl
vaapiVdpau
];

View File

@@ -0,0 +1,333 @@
# NixOS Steam Dual Boot Implementation Plan (Btrfs + Beesd Edition)
## Goals & Motivations
### Primary Goals
1. **Eliminate storage waste**: Avoid duplicating terabytes of Steam games across Windows and NixOS
2. **Minimize maintenance overhead**: Create a solution that works reliably without constant tweaking
3. **Preserve Windows stability**: Ensure Windows Steam functionality remains unaffected by the dual-boot setup
4. **Maintain gaming performance**: No significant performance degradation on either OS
### Secondary Goals
- **Seamless game access**: Games should be available on both OSes without manual intervention
- **Update compatibility**: Game updates from either OS should be usable by both
- **Future-proof architecture**: Solution should be extensible and maintainable
- **Multi-user support**: Handle 3 Windows users sharing libraries, with 1 user also using Linux
## Architectural Overview
### The Problem with Previous Approaches
**Shared NTFS Library (Traditional)**:
- ❌ Proton creates files with colons, corrupting NTFS
- ❌ Requires fragile symlinks that Windows can break
- ❌ Permission issues plague the setup
- ❌ Valve officially discourages this approach
**Complex Symlink Management**:
- ❌ Requires custom scripts and maintenance
- ❌ Fragile edge cases with Steam updates
- ❌ Potential compatibility issues with Proton and anti-cheat
**Separate Libraries**:
- ❌ Wastes terabytes of storage
- ❌ Games must be installed twice
- ❌ No benefit from either OS's installations
### Our Solution: Btrfs + Beesd Automatic Deduplication
```
Windows Steam → /steam/windows/ (btrfs via WinBtrfs driver)
Linux Steam → /steam/linux/ (native btrfs)
[beesd automatically deduplicates identical files]
```
**Key Insight**: Let each Steam installation work independently, rely on proven btrfs deduplication technology to eliminate duplicate storage automatically.
## Architecture Deep Dive
### Component 1: Shared Btrfs Filesystem
**Purpose**: Single high-performance filesystem for all game storage
- **Location**: `/steam` (dedicated btrfs partition)
- **Contents**:
- `/steam/windows/` - Windows Steam library
- `/steam/linux/` - Linux Steam library
- **Access**: Native on Linux, WinBtrfs driver on Windows
**Why this satisfies our goals**:
-**Automatic deduplication**: Beesd handles duplicate elimination transparently
-**No maintenance**: Zero custom scripts or symlink management
-**Independent operation**: Each Steam installation works normally
-**Performance**: Optimized mount options for gaming workloads
### Component 2: Beesd Deduplication Service
**Purpose**: Automatic background deduplication of game files
**Core Functionality**:
- Continuously scans `/steam` for duplicate blocks
- Automatically deduplicates identical files between `/steam/windows/` and `/steam/linux/`
- Operates transparently - games never know deduplication is happening
- Handles common duplicates: DirectX runtimes, Visual C++ redistributables, game engines, shared assets
**Expected Efficiency**:
- **40-70% storage savings** for typical game libraries
- **Common targets**: Unity/Unreal engine files, shared libraries, identical texture assets
- **Real-time operation**: New duplicates eliminated automatically
### Component 3: WinBtrfs Driver Integration
**Purpose**: Provide Windows with native btrfs read/write access
```nix
# No special configuration needed - standard btrfs mount
fileSystems."/steam" = {
device = "/dev/disk/by-uuid/YOUR-BTRFS-UUID";
fsType = "btrfs";
options = [
"noatime" # Don't update access times - major gaming performance boost
"ssd" # SSD optimizations
];
};
```
**Windows Requirements**:
- Install WinBtrfs driver (https://github.com/maharmstone/btrfs)
- Configure Steam library path to point to `/steam/windows/`
- No special configuration needed - works like any other drive
### Component 4: Beesd Configuration
**Purpose**: Optimized deduplication for gaming workloads
```nix
services.beesd.filesystems = {
steam = {
spec = "/steam";
hashTableSizeMB = 512; # Sized for ~4TB of game data (128MB per TB)
verbosity = "err"; # Only show actual problems
};
};
```
**Hash Table Storage**:
- Stored as file: `/steam/.beeshash`
- 512MB handles up to 4TB of game data efficiently (beesd recommends 128MB per TB)
- Loaded into RAM on-demand, not all resident simultaneously
- Smaller hash table = better performance and less disk usage
## Partition Strategy
### 4-Partition Architecture
1. **Windows Boot Partition** (NTFS) - *Existing*
- Standard Windows system drive
- Unchanged from current setup
2. **Linux Boot Partition** (btrfs/ext4) - *New*
- NixOS system installation
- Standard Linux root filesystem
3. **Shared Steam Library** (btrfs) - *New*
- `/steam/windows/` - Windows Steam library
- `/steam/linux/` - Linux Steam library
- Automatic beesd deduplication
4. **Legacy Windows Steam** (NTFS) - *Existing, Optional*
- Keep for anti-cheat games that may not work on btrfs
- Can be eliminated if all games work on btrfs
- Provides fallback option during testing
### Multi-User Considerations
**Current Setup**: 3 Windows users sharing Steam libraries
**Migration Strategy**:
- Other Windows users continue using existing NTFS library
- Primary user (johno) experiments with btrfs library
- Easy rollback: point Steam back to NTFS if issues arise
- Gradual migration as confidence builds
## Implementation Strategy
### Phase 1: Base Setup
1. **Partition Creation**:
- Create new btrfs partition for `/steam` (recommend 2TB+ for modern libraries)
- Install NixOS on separate Linux boot partition
- Keep existing Windows partitions untouched
2. **NixOS Configuration**:
```nix
fileSystems."/steam" = {
device = "/dev/disk/by-uuid/YOUR-BTRFS-UUID";
fsType = "btrfs";
options = [ "noatime" "ssd" ];
};
services.beesd.filesystems = {
steam = {
spec = "/steam";
hashTableSizeMB = 512; # 128MB per TB recommended
verbosity = "err";
};
};
```
3. **Windows Setup**:
- Install WinBtrfs driver
- Add Steam library pointing to `/steam/windows/`
- Test with a few small games initially
### Phase 2: Gradual Migration
1. **Safe Game Testing**:
- Start with single-player games
- Test save game compatibility
- Verify performance matches NTFS installation
2. **Anti-Cheat Evaluation**:
- Test multiplayer games progressively
- Document which games work on btrfs vs require NTFS
- Keep problematic games on legacy NTFS partition
3. **Deduplication Verification**:
- Monitor beesd logs for successful deduplication
- Use `btrfs filesystem du /steam` to verify space savings
- Benchmark game loading times vs separate installations
### Phase 3: Optimization
1. **Performance Tuning**:
- Monitor btrfs performance under gaming workloads
- Adjust mount options if needed
- Optimize beesd parameters based on actual usage
2. **Monitoring Setup**:
- SystemD service monitoring for beesd
- Disk space alerts for `/steam` partition
- Basic health checks for WinBtrfs stability
## Trade-offs and Considerations
### Advantages
**Storage Efficiency**:
- ✅ 40-70% storage savings through automatic deduplication
- ✅ No manual intervention required
- ✅ Works with any game installation method
**Simplicity**:
- ✅ No custom scripts to maintain
- ✅ No symlink complexity
- ✅ Standard Steam library management on both OSes
**Reliability**:
- ✅ Each Steam installation completely independent
- ✅ Btrfs and beesd are mature, proven technologies
- ✅ Graceful degradation if deduplication fails
**Performance**:
- ✅ Optimized mount options for gaming
- ✅ No compression overhead
- ✅ Native filesystem performance on both OSes
### Limitations
**Windows Dependencies**:
- ⚠️ Requires WinBtrfs third-party driver
- ⚠️ Driver updates needed with major Windows releases
- ⚠️ Potential compatibility issues with some anti-cheat systems
**Complexity Trade-offs**:
- ⚠️ More partitions to manage than single-filesystem approach
- ⚠️ Beesd adds background CPU/disk usage (minimal but present)
- ⚠️ Hash table requires disk space (512MB for large libraries)
**Platform Compatibility**:
- ⚠️ Some games may prefer NTFS for maximum compatibility
- ⚠️ Anti-cheat systems may flag non-NTFS installations
- ⚠️ WinBtrfs stability depends on third-party development
### Risk Mitigation
**Backup Strategy**:
- Regular btrfs snapshots of `/steam` partition
- Keep legacy NTFS Steam library as fallback
- Steam's built-in backup/restore for critical games
**Fallback Options**:
- Easy to revert games to NTFS library if needed
- Linux can install games locally if `/steam` partition fails
- Independent operation means failure in one OS doesn't affect the other
**Monitoring**:
- SystemD service status for beesd
- Disk space monitoring for early warning
- Game launch testing after major updates
## Expected Outcomes
### Immediate Benefits
- **40-70% storage savings** for typical game libraries
- **Zero maintenance** after initial setup
- **Identical performance** to native installations
- **Future-proof** architecture using standard technologies
### Long-term Benefits
- **Automatic optimization**: New games deduplicated without intervention
- **Simplified management**: One shared library instead of separate installations
- **Technology leverage**: Benefits from ongoing btrfs and beesd improvements
### Success Metrics
- ✅ Games launch successfully from both OSes
- ✅ Save games work correctly on both platforms
- ✅ Updates from either OS don't break the other
- ✅ Storage usage 40-70% less than separate libraries
- ✅ No performance degradation vs native installations
- ✅ Anti-cheat compatibility acceptable for target games
### Monitoring and Maintenance
**Automated Monitoring**:
```nix
# Add to NixOS configuration for basic monitoring
systemd.services.steam-health-check = {
description = "Check Steam partition and beesd health";
serviceConfig = {
Type = "oneshot";
ExecStart = pkgs.writeScript "steam-health" ''
#!/bin/bash
# Check beesd service status
systemctl is-active beesd-steam >/dev/null || echo "WARN: beesd not running"
# Check disk space
USAGE=$(df /steam | tail -1 | awk '{print $5}' | sed 's/%//')
[ "$USAGE" -gt 90 ] && echo "WARN: Steam partition >90% full"
# Verify both directories exist
[ ! -d "/steam/windows" ] && echo "ERROR: Windows Steam directory missing"
[ ! -d "/steam/linux" ] && echo "ERROR: Linux Steam directory missing"
'';
};
};
systemd.timers.steam-health-check = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
};
};
```
## Implementation Files Needed
1. **NixOS Configuration Addition** - Add to existing machine config
2. **WinBtrfs Installation Guide** - Windows setup instructions
3. **Migration Checklist** - Step-by-step game migration process
4. **Troubleshooting Guide** - Common issues and solutions
This architecture provides maximum storage efficiency with minimal complexity, leveraging proven technologies instead of custom solutions. The automatic nature of btrfs deduplication eliminates the maintenance overhead of complex symlink management while providing excellent storage savings.

View File

@@ -10,7 +10,6 @@ with lib;
./kodi
./nfs-mounts
./printing
./secrets
./spotifyd
./users
./virtualisation

View File

@@ -29,7 +29,7 @@ in
{
users.extraUsers.kodi = {
isNormalUser = true;
extraGroups = [ "wheel" "networkmanager" "audio" "video" ];
extraGroups = [ "wheel" "networkmanager" "audio" "video" ];
};
networking.firewall = {
@@ -38,10 +38,12 @@ in
};
environment.systemPackages = with pkgs; [
kodiPkg
kodiPkg
wget
];
programs.kdeconnect.enable = true;
services = if cfg.autologin then {
displayManager = {
autoLogin.enable = true;

View File

@@ -19,5 +19,12 @@ in
nssmdns4 = true;
openFirewall = true;
};
hardware.printers.ensurePrinters = [{
name = "MFC-L8900CDW_series";
deviceUri = "dnssd://Brother%20MFC-L8900CDW%20series._ipp._tcp.local/?uuid=e3248000-80ce-11db-8000-b422006699d8";
model = "everywhere";
}];
hardware.printers.ensureDefaultPrinter = "MFC-L8900CDW_series";
};
}

View File

@@ -1,8 +0,0 @@
{ config, lib, pkgs, inputs, ... }:
{
sops.defaultSopsFile = ../../secrets/secrets.yaml;
sops.defaultSopsFormat = "yaml";
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" "/home/johno/.ssh/id_ed25519" ];
sops.secrets.example_key = {};
}

View File

@@ -1,48 +0,0 @@
hello: ENC[AES256_GCM,data:5ZpbPx3D8gQc1fOhViUqiCr0zLWYotB+vIBixqTbqP9XLS52y6tr5DXus0aV9mTgka5deqc=,iv:yPJaCqDD9WD56swfBjSm7A62ZTTIQDqyAKOgP1ese+U=,tag:bo8+7Ne2f9aEZSvpkt1fzA==,type:str]
example_key: ENC[AES256_GCM,data:v15bEcb0H3vaj13blg==,iv:9P3IA7ChBamo41VE8G8tj46sZqeijsO1LcvwLtEPVPA=,tag:o/lAyAYYGNLP9EjQNa/K8Q==,type:str]
example_array:
- ENC[AES256_GCM,data:3Vwa7dfNfKzRc/xpk6I=,iv:IevBgxwWdaBvZY1ywteWcfWwDIA8lK3FTWs67lLBKxw=,tag:Mx5lzUeNZ/3wJBWAl5XSBw==,type:str]
- ENC[AES256_GCM,data:epkT6WPGW5Oe/S+4HtU=,iv:N0yoDuieAaEi+NuCoCL4zrkhaDDdkttboI89m+UccjQ=,tag:OoERRByb0OM4un9oGLJQgA==,type:str]
#ENC[AES256_GCM,data:YzMFXxn3sbbHpGB4jPRtRw==,iv:TN6ogQuH7c6xtDoWt0Ew9B2f7wuaipJynvscZmaJYoU=,tag:No0UwEktEyMNBg/46P+Zmg==,type:comment]
example_number: ENC[AES256_GCM,data:jmLoVC+8YIlB2A==,iv:u9GztD/aE9UN5zWq3Am2nhYwmYt3sf8sy65MHbhVoD0=,tag:wKuf1mMr5XBJveJrz0uHPA==,type:float]
example_booleans:
- ENC[AES256_GCM,data:ZacILA==,iv:xo+7aFFQXzbJzKDY0mYTeFLf10AlnHkywDRAMHeprEM=,tag:F/OnJdqjrZP02sTLWLmnbg==,type:bool]
- ENC[AES256_GCM,data:NaFrvrs=,iv:kKDmGs9u/w5qrZ/379Jlx8AotUVADvH+eHwHCqykmkE=,tag:nD9TsmkXUm4ABaT1ABWmcg==,type:bool]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1ls6a033d4p4u8h4rwazjwt8w4c4xg73wq0mdnm64jajxzcz4k9asvjnks3
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjak9vRVJtVmJoanhEZ0hQ
MFJwMEE4UDcrRkdPRmZ6R09FSDY1aTk3Y1dNClZJYXRLNU5senR3Qzh6VmZGMlhu
bnl6VjlaUEFISnBtSTVrcEd0ZjI5Q2MKLS0tIFl1b3A5ZWVqc1gvWVZnZis0ZHFk
bWhnNVB2TUJ4YzY4NHdSVXhPc3dReTgKWRYBbBE3+oGsRNw1CROhFY+btENbShfv
gw3IdW7OoZV6JpJBOcI82eOuOkIxrmgSGDGeyy10/a5MA/cB1umm+w==
-----END AGE ENCRYPTED FILE-----
- recipient: age12l5u7sw59u5pkwp83qm8t3ff7uv0ld2c9k3zh5j4ame9k2szcynqu7ftqe
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGcmV3TDlNL2Zxb0h5QTYx
QkVmczA0MDc2ZnpNNU1YeFVzSXJwc3RWUmk4CjF4bHIrVU9VM3htTUxGZ2FUR256
UEovdVV2cmNIbkloS1VobTNFSDVyRG8KLS0tIEFhUk5kL3hCNGs4MGJBTmNJaVFm
b2ZBUGJ1K0lKTitKYTRUMWszQzhBU0UKBaM6t6JmWfiG+wPorGea1gqvV5RSIPyw
6yb2PcH2oZ0HrjJM5sjfu7XOWY3KneiZZikR1BpD5KvevfagWTSR/w==
-----END AGE ENCRYPTED FILE-----
- recipient: age1fa3zqavfmqk4ssa22yne9td90gyqv9q5a8y0s8jp3xak8q7p3yjqyn7rkg
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaMFJiNjVOb0lTcmJ3VnhH
WlRKZERRZFM3TFZBZGNSZC9GdHlHakMza21zClJ3SDdFUkVRc3oyVVU3WEtDQzBu
OEFqS3NwbHZFUlpCYlN6RW84N0F1amcKLS0tIHFZK21aTHdwZ2dWbVRrWEZDWFZj
aU1IQzdTMVhnbHhsNENwMG05dXhOU2MK8fEJea9sL5JLgltVlTI6mRDb+Tl83Iz7
4wPYvo68cn8vimXqSk45ldHRrNa3zhYai3CalQaGtDT3fkWGvSq0zQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-09-28T15:44:39Z"
mac: ENC[AES256_GCM,data:YUi+AbS6DQTmrSyOXsbkZWfWaMyKGR8fYm/MHcxmqChi8hng+UWHBZjsLBe6ef/FLH3rnP6bhfwK8KYnVS6fHvHahoqIq/BHydTsqrclnSgRAGl8Lh0yuhwISNRvP1AuW5pd50sdQaS0uGOtzOCharI/pZ9H+cmt2SB5WOCdeLs=,iv:2nBG6it3tNSLSia8hGzCcesuK9QwzB9EzfjWegjQ2kw=,tag:RGGPAPw/rQKhWA2OqLjTJw==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.0