Compare commits

..

5 Commits

Author SHA1 Message Date
4a456c5a06 bootstrapping 2024-10-25 16:54:01 -04:00
8d78862326 sorted haproxy.cfg 2024-10-25 16:50:34 -04:00
090c14ed47 enabled firewall on jeeves 2024-10-25 16:50:34 -04:00
cc7c44203c enabled firewall on rhapsody-in-green 2024-10-25 16:50:34 -04:00
e5239304e7 enabled firewall on bob 2024-10-25 16:50:34 -04:00
106 changed files with 1572 additions and 2660 deletions

View File

@@ -1,26 +0,0 @@
name: build_systems
on:
workflow_dispatch:
pull_request:
push:
branches: [main]
schedule:
- cron: "0 22 * * *"
jobs:
build:
name: build-${{ matrix.system }}
runs-on: self-hosted
strategy:
matrix:
system:
- "bob"
- "jeeves"
- "rhapsody-in-green"
steps:
- uses: actions/checkout@v4
- name: Build default package
run: "nixos-rebuild build --flake ./#${{ matrix.system }}"
- name: copy to nix-cache
run: nix copy --to ssh://jeeves .#nixosConfigurations.${{ matrix.system }}.config.system.build.toplevel

View File

@@ -0,0 +1,24 @@
#!/bin/bash
# Update ZFS package to match the latest supported Linux kernel version
echo "geting latest ZFS version"
raw_zfs_max_kernel_version=$(curl -s https://raw.githubusercontent.com/openzfs/zfs/master/META | grep Linux-Maximum | cut -d" " -f2)
zfs_max_kernel_version="${raw_zfs_max_kernel_version//./_}"
echo "geting latest ZFS version"
if grep "linuxPackages_$zfs_max_kernel_version" systems/common/global/default.nix; then
echo "No changes needed"
exit 0
fi
sed -i "s/linuxPackages_6_[0-9]\+/linuxPackages_$zfs_max_kernel_version/" systems/common/global/default.nix
# Commit the changes
git config user.name "GitHub Actions Bot"
git config user.email "<>"
git add systems/common/global/default.nix
git commit -m "Update Linux kernel and ZFS packages"

View File

@@ -0,0 +1,27 @@
name: Kernel Packages Update
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
jobs:
create-pull-request:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Make changes
run: bash ${GITHUB_WORKSPACE}/.github/workflows/kernel_packages_update.sh
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Base linuxPackages update
title: Base linuxPackages update
body: |
Update linuxPackages
branch: daily-update
delete-branch: true

View File

@@ -1,15 +0,0 @@
name: treefmt
on:
workflow_dispatch:
pull_request:
push:
branches: [main]
jobs:
treefmt:
name: nix fmt
runs-on: self-hosted
steps:
- uses: actions/checkout@v4
- name: runs treefmt
run: "treefmt --ci"

View File

@@ -1,22 +0,0 @@
name: update-flake-lock
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
jobs:
lockfile:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@main
with:
token: ${{ secrets.GH_TOKEN_FOR_UPDATES }}
pr-title: "Update flake.lock"
pr-labels: |
dependencies
automated

4
.gitignore vendored
View File

@@ -162,6 +162,4 @@ cython_debug/
#.idea/ #.idea/
test.* test.*
secrets.*
# syncthing
.stfolder

View File

@@ -1,17 +0,0 @@
keys:
- &admin_richie age1u8zj599elqqvcmhxn8zuwrufsz8w8w366d3ayrljjejljt2q45kq8mxw9c # cspell:disable-line
- &system_bob age1q47vup0tjhulkg7d6xwmdsgrw64h4ax3la3evzqpxyy4adsmk9fs56qz3y # cspell:disable-line
- &system_jeeves age13lmqgc3jvkyah5e3vcwmj4s5wsc2akctcga0lpc0x8v8du3fxprqp4ldkv # cspell:disable-line
- &system_router age1xzxryqq63x65yuza9lmmkud7crjjxpnkdew070yhx6xn7xe4tdws5twxsv # cspell:disable-line
- &system_rhapsody age1ufnewppysaq2wwcl4ugngjz8pfzc5a35yg7luq0qmuqvctajcycs5lf6k4 # cspell:disable-line
creation_rules:
- path_regex: users/secrets\.yaml$
key_groups:
- age:
- *admin_richie
- *system_bob
- *system_jeeves
- *system_router
- *system_rhapsody

61
.vscode/settings.json vendored
View File

@@ -6,9 +6,7 @@
"advplyr", "advplyr",
"ahci", "ahci",
"aioesphomeapi", "aioesphomeapi",
"aiounifi",
"alsa", "alsa",
"apiclient",
"archlinux", "archlinux",
"ashift", "ashift",
"asrouter", "asrouter",
@@ -18,15 +16,11 @@
"audiobookshelf", "audiobookshelf",
"auditd", "auditd",
"autofetch", "autofetch",
"autologin",
"automations",
"autopull", "autopull",
"autotrim", "autotrim",
"autoupdate",
"azuretools", "azuretools",
"bantime", "bantime",
"bazarr", "bazarr",
"bgwriter",
"binhex", "binhex",
"bitwarden", "bitwarden",
"blkdiscard", "blkdiscard",
@@ -37,27 +31,20 @@
"captivedetect", "captivedetect",
"cgroupdriver", "cgroupdriver",
"charliermarsh", "charliermarsh",
"Checkpointing",
"cloudflared", "cloudflared",
"codellama",
"codezombiech", "codezombiech",
"compactmode", "compactmode",
"Compat", "Compat",
"contentblocking", "contentblocking",
"cookiebanners", "cookiebanners",
"createdb",
"createrole",
"crlite", "crlite",
"cryptsetup", "cryptsetup",
"cuda",
"darkreader", "darkreader",
"datagrip",
"datareporting", "datareporting",
"davidanson", "davidanson",
"dconf", "dconf",
"dearrow", "dearrow",
"debugpy", "debugpy",
"deepseek",
"dialout", "dialout",
"diffie", "diffie",
"direnv", "direnv",
@@ -65,19 +52,14 @@
"dnodesize", "dnodesize",
"dotfiles", "dotfiles",
"drawio", "drawio",
"duckdns",
"eamodio", "eamodio",
"ehci",
"emerg",
"endlessh", "endlessh",
"errorlens", "errorlens",
"esbenp", "esbenp",
"esphome", "esphome",
"extest", "extest",
"fadvise",
"fastforwardteam", "fastforwardteam",
"FASTFOX", "FASTFOX",
"ffmpegthumbnailer",
"filebot", "filebot",
"filebrowser", "filebrowser",
"fileroller", "fileroller",
@@ -86,10 +68,8 @@
"fmask", "fmask",
"fontconfig", "fontconfig",
"formfill", "formfill",
"forwardfor",
"foxundermoon", "foxundermoon",
"FULLSCREEN", "FULLSCREEN",
"fwupd",
"fxaccounts", "fxaccounts",
"gamemode", "gamemode",
"gamescope", "gamescope",
@@ -99,8 +79,6 @@
"globalprivacycontrol", "globalprivacycontrol",
"gparted", "gparted",
"gtts", "gtts",
"gutenprint",
"hass",
"healthreport", "healthreport",
"Heatsink", "Heatsink",
"hediet", "hediet",
@@ -109,9 +87,7 @@
"hmac", "hmac",
"homeassistant", "homeassistant",
"HPKP", "HPKP",
"hplip",
"htmlaboutaddons", "htmlaboutaddons",
"httpchk",
"hurlenko", "hurlenko",
"hwloc", "hwloc",
"INITDB", "INITDB",
@@ -119,19 +95,15 @@
"ioit", "ioit",
"iperf", "iperf",
"isal", "isal",
"jellyfin",
"jnoortheen", "jnoortheen",
"jsbc", "jsbc",
"kagi",
"kuma", "kuma",
"lazer",
"levelname", "levelname",
"libglvnd", "libglvnd",
"libmysqlclient", "libmysqlclient",
"libsodium", "libsodium",
"libssh", "libssh",
"libvirtd", "libvirtd",
"llms",
"localtime", "localtime",
"louislam", "louislam",
"lsnew", "lsnew",
@@ -139,13 +111,10 @@
"lynis", "lynis",
"mangohud", "mangohud",
"markdownlint", "markdownlint",
"maxconn",
"maxpages",
"maxretry", "maxretry",
"maxtime", "maxtime",
"mechatroner", "mechatroner",
"mediainfo", "mediainfo",
"mixtral",
"mklabel", "mklabel",
"mkpart", "mkpart",
"modesetting", "modesetting",
@@ -162,29 +131,22 @@
"Networkd", "Networkd",
"networkmanager", "networkmanager",
"newtabpage", "newtabpage",
"nixfmt",
"nixos", "nixos",
"nixpkgs", "nixpkgs",
"nmap", "nmap",
"noauto", "noauto",
"nodev",
"noecho", "noecho",
"nonsponsored", "nonsponsored",
"Noto", "Noto",
"nprt",
"nvme", "nvme",
"OCSP", "OCSP",
"oderwat", "oderwat",
"ollama",
"ondemand",
"oneshot", "oneshot",
"openwakeword",
"optimise", "optimise",
"optoutstudies", "optoutstudies",
"overalljails", "overalljails",
"overscroll", "overscroll",
"overseerr", "overseerr",
"partitionwise",
"pbmode", "pbmode",
"pciutils", "pciutils",
"pcscd", "pcscd",
@@ -192,17 +154,14 @@
"peerconnection", "peerconnection",
"PESKYFOX", "PESKYFOX",
"PGID", "PGID",
"photoprism",
"pipewire", "pipewire",
"pkgs", "pkgs",
"plugdev", "plugdev",
"poppler",
"posixacl", "posixacl",
"powertop",
"primarycache", "primarycache",
"prismlauncher",
"privatebrowsing", "privatebrowsing",
"PRIVOXY", "PRIVOXY",
"protontricks",
"prowlarr", "prowlarr",
"proxychains", "proxychains",
"prusa", "prusa",
@@ -210,10 +169,8 @@
"PUID", "PUID",
"pulseaudio", "pulseaudio",
"punycode", "punycode",
"pychromecast",
"pylance", "pylance",
"pymetno", "pymetno",
"pyownet",
"qbit", "qbit",
"qbittorrent", "qbittorrent",
"qbittorrentvpn", "qbittorrentvpn",
@@ -221,16 +178,12 @@
"quicksuggest", "quicksuggest",
"radarr", "radarr",
"readahead", "readahead",
"receiveencrypted",
"recordsize",
"Redistributable", "Redistributable",
"referer", "referer",
"REFERERS", "REFERERS",
"relatime", "relatime",
"Rhosts", "Rhosts",
"ripgrep", "ripgrep",
"roboto",
"rokuecp",
"routable", "routable",
"rspace", "rspace",
"rtkit", "rtkit",
@@ -252,7 +205,6 @@
"sponsorblock", "sponsorblock",
"sqltools", "sqltools",
"ssdp", "ssdp",
"SSHOPTS",
"stdenv", "stdenv",
"subresource", "subresource",
"substituters", "substituters",
@@ -260,44 +212,35 @@
"sysstat", "sysstat",
"tabmanager", "tabmanager",
"tamasfe", "tamasfe",
"TCPIP",
"tiktok", "tiktok",
"timonwong", "timonwong",
"titlebar",
"tmmworkshop", "tmmworkshop",
"Tmpfs", "Tmpfs",
"topsites", "topsites",
"topstories", "topstories",
"treefmt", "torrenting",
"twimg", "twimg",
"uaccess", "uaccess",
"ublock", "ublock",
"uiprotect",
"uitour", "uitour",
"unrar",
"unsubmitted", "unsubmitted",
"uptimekuma",
"urlbar", "urlbar",
"urlclassifier", "urlclassifier",
"usbhid", "usbhid",
"usbutils", "usbutils",
"useragent",
"usernamehw", "usernamehw",
"userprefs", "userprefs",
"vfat", "vfat",
"virt", "virt",
"virtualisation", "virtualisation",
"vpnpromourl", "vpnpromourl",
"wakeonlan",
"webchannel", "webchannel",
"WEBRTC", "WEBRTC",
"WEBUI", "WEBUI",
"wireplumber",
"wireshark", "wireshark",
"Workqueues", "Workqueues",
"xattr", "xattr",
"xhci", "xhci",
"yazi",
"yubikey", "yubikey",
"yubioath", "yubioath",
"yzhang", "yzhang",

View File

@@ -8,9 +8,8 @@
{ {
imports = [ imports = [
inputs.home-manager.nixosModules.home-manager inputs.home-manager.nixosModules.home-manager
inputs.sops-nix.nixosModules.sops ./docker.nix
./fail2ban.nix ./fail2ban.nix
./fonts.nix
./libs.nix ./libs.nix
./locale.nix ./locale.nix
./nh.nix ./nh.nix
@@ -21,9 +20,8 @@
]; ];
boot = { boot = {
kernelPackages = lib.mkDefault pkgs.linuxPackages_6_10;
tmp.useTmpfs = true; tmp.useTmpfs = true;
kernelPackages = lib.mkDefault pkgs.linuxPackages_6_12;
zfs.package = lib.mkDefault pkgs.zfs_2_3;
}; };
hardware.enableRedistributableFirmware = true; hardware.enableRedistributableFirmware = true;
@@ -31,41 +29,19 @@
home-manager = { home-manager = {
useGlobalPkgs = true; useGlobalPkgs = true;
useUserPackages = true; useUserPackages = true;
extraSpecialArgs = { inherit inputs outputs; }; extraSpecialArgs = {inherit inputs outputs;};
backupFileExtension = "backup";
}; };
nixpkgs = { nixpkgs.config.allowUnfree = true;
overlays = builtins.attrValues outputs.overlays;
config.allowUnfree = true; programs = {
zsh.enable = true;
fish.enable = true;
}; };
services = { security.auditd.enable = lib.mkDefault true;
# firmware update
fwupd.enable = true;
snapshot_manager.enable = lib.mkDefault true; users.mutableUsers = lib.mkDefault true;
zfs = {
trim.enable = lib.mkDefault true;
autoScrub.enable = lib.mkDefault true;
};
};
powerManagement.powertop.enable = lib.mkDefault true;
programs.zsh.enable = true;
security = {
auditd.enable = lib.mkDefault true;
sudo-rs = {
enable = true;
execWheelOnly = true;
};
sudo.enable = false;
};
users.mutableUsers = lib.mkDefault false;
zramSwap = { zramSwap = {
enable = lib.mkDefault true; enable = lib.mkDefault true;

View File

@@ -1,12 +0,0 @@
{ pkgs, ... }:
{
fonts = {
fontconfig.enable = true;
enableDefaultPackages = true;
packages = with pkgs; [
nerd-fonts.roboto-mono
nerd-fonts.intone-mono
nerd-fonts.symbols-only
];
};
}

View File

@@ -4,7 +4,8 @@
console.keyMap = lib.mkDefault "us"; console.keyMap = lib.mkDefault "us";
i18n = { i18n = {
defaultLocale = lib.mkDefault "en_US.UTF-8"; defaultLocale = lib.mkDefault "en_US.utf8";
supportedLocales = lib.mkDefault [ "en_US.UTF-8/UTF-8" ];
extraLocaleSettings = lib.mkDefault { extraLocaleSettings = lib.mkDefault {
LC_ADDRESS = "en_US.UTF-8"; LC_ADDRESS = "en_US.UTF-8";
LC_IDENTIFICATION = "en_US.UTF-8"; LC_IDENTIFICATION = "en_US.UTF-8";

View File

@@ -2,29 +2,15 @@
inputs, inputs,
lib, lib,
... ...
}: }: let
let
flakeInputs = lib.filterAttrs (_: lib.isType "flake") inputs; flakeInputs = lib.filterAttrs (_: lib.isType "flake") inputs;
in in {
{
nix = { nix = {
settings = { settings = {
trusted-users = [ trusted-users = [
"root" "root"
"@wheel" "@wheel"
]; ];
trusted-substituters = [
"https://cache.nixos.org"
"https://nix-community.cachix.org"
];
substituters = [
"https://cache.nixos.org/?priority=2&want-mass-query=true"
"https://nix-community.cachix.org/?priority=10&want-mass-query=true"
];
trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
];
auto-optimise-store = lib.mkDefault true; auto-optimise-store = lib.mkDefault true;
experimental-features = [ experimental-features = [
"nix-command" "nix-command"
@@ -36,7 +22,7 @@ in
}; };
# Add each flake input as a registry and nix_path # Add each flake input as a registry and nix_path
registry = lib.mapAttrs (_: flake: { inherit flake; }) flakeInputs; registry = lib.mapAttrs (_: flake: {inherit flake;}) flakeInputs;
nixPath = lib.mapAttrsToList (n: _: "${n}=flake:${n}") flakeInputs; nixPath = lib.mapAttrsToList (n: _: "${n}=flake:${n}") flakeInputs;
}; };
} }

View File

@@ -2,6 +2,6 @@
{ {
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
git git
python313 python312
]; ];
} }

View File

@@ -6,8 +6,8 @@ monthly = 0
["root_pool/home"] ["root_pool/home"]
15_min = 8 15_min = 8
hourly = 12 hourly = 24
daily = 1 daily = 14
monthly = 0 monthly = 0
["root_pool/root"] ["root_pool/root"]

View File

@@ -1,10 +1,4 @@
{ { inputs, pkgs, lib, config, ... }:
inputs,
pkgs,
lib,
config,
...
}:
let let
cfg = config.services.snapshot_manager; cfg = config.services.snapshot_manager;
in in

View File

@@ -67,5 +67,5 @@
}; };
}; };
networking.firewall.allowedTCPPorts = [ 22 ]; networking.firewall.allowedTCPPorts = [ 22 ];
} }

View File

@@ -1,26 +1,6 @@
{ pkgs, ... }:
{ {
boot = {
kernelPackages = pkgs.linuxPackages_6_15;
zfs.package = pkgs.zfs_2_3;
};
hardware.bluetooth = {
enable = true;
powerOnBoot = true;
};
# rtkit is optional but recommended for pipewire
security.rtkit.enable = true;
services = { services = {
displayManager.sddm = {
enable = true;
wayland.enable = true;
};
desktopManager.plasma6.enable = true; desktopManager.plasma6.enable = true;
xserver = { xserver = {
enable = true; enable = true;
xkb = { xkb = {
@@ -28,15 +8,5 @@
variant = ""; variant = "";
}; };
}; };
pulseaudio.enable = false;
pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
wireplumber.enable = true;
};
}; };
} }

View File

@@ -1,10 +0,0 @@
{ pkgs, ... }:
{
services.printing = {
enable = true;
drivers = with pkgs; [
gutenprint
hplip
];
};
}

View File

@@ -1,9 +1,6 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [mangohud steam-run];
mangohud
steam-run
];
hardware.steam-hardware.enable = true; hardware.steam-hardware.enable = true;
programs = { programs = {
@@ -13,13 +10,8 @@
gamescopeSession.enable = true; gamescopeSession.enable = true;
remotePlay.openFirewall = true; remotePlay.openFirewall = true;
localNetworkGameTransfers.openFirewall = true; localNetworkGameTransfers.openFirewall = true;
protontricks.enable = true; extraCompatPackages = with pkgs; [proton-ge-bin];
extraCompatPackages = with pkgs; [ proton-ge-bin ];
extest.enable = true; extest.enable = true;
}; };
gamescope = {
enable = true;
capSysNice = true;
};
}; };
} }

View File

@@ -1,18 +1,19 @@
{ lib, ... }:
{ {
services.syncthing = { services.syncthing = {
enable = true; enable = true;
user = "richie"; user = "richie";
overrideDevices = true; overrideDevices = true;
overrideFolders = lib.mkDefault true; overrideFolders = true;
dataDir = "/home/richie/Syncthing"; dataDir = "/home/richie/Syncthing";
configDir = "/home/richie/.config/syncthing"; configDir = "/home/richie/.config/syncthing";
settings.devices = { settings = {
phone.id = "TBRULKD-7DZPGGZ-F6LLB7J-MSO54AY-7KLPBIN-QOFK6PX-W2HBEWI-PHM2CQI"; # cspell:disable-line devices = {
jeeves.id = "ICRHXZW-ECYJCUZ-I4CZ64R-3XRK7CG-LL2HAAK-FGOHD22-BQA4AI6-5OAL6AG"; # cspell:disable-line phone.id = "LTGPLAE-M4ZDJTM-TZ3DJGY-SLLAVWF-CQDVEVS-RGCS75T-GAPZYK3-KUM6LA5"; # cspell:disable-line
ipad.id = "KI76T3X-SFUGV2L-VSNYTKR-TSIUV5L-SHWD3HE-GQRGRCN-GY4UFMD-CW6Z6AX"; # cspell:disable-line jeeves.id = "ICRHXZW-ECYJCUZ-I4CZ64R-3XRK7CG-LL2HAAK-FGOHD22-BQA4AI6-5OAL6AG"; # cspell:disable-line
bob.id = "CJIAPEJ-VO74RR4-F75VU6M-QNZAMYG-FYUJG7Y-6AT62HJ-355PRPL-PJFETAZ"; # cspell:disable-line ipad.id = "KI76T3X-SFUGV2L-VSNYTKR-TSIUV5L-SHWD3HE-GQRGRCN-GY4UFMD-CW6Z6AX"; # cspell:disable-line
rhapsody-in-green.id = "ASL3KC4-3XEN6PA-7BQBRKE-A7JXLI6-DJT43BY-Q4WPOER-7UALUAZ-VTPQ6Q4"; # cspell:disable-line bob.id = "CJIAPEJ-VO74RR4-F75VU6M-QNZAMYG-FYUJG7Y-6AT62HJ-355PRPL-PJFETAZ"; # cspell:disable-line
rhapsody-in-green.id = "ASL3KC4-3XEN6PA-7BQBRKE-A7JXLI6-DJT43BY-Q4WPOER-7UALUAZ-VTPQ6Q4"; # cspell:disable-line
};
}; };
}; };
} }

View File

@@ -1,7 +0,0 @@
{
nix.settings = {
trusted-substituters = [ "http://cache.tmmworkshop.com" ];
substituters = [ "http://cache.tmmworkshop.com/?priority=1&want-mass-query=true" ];
trusted-public-keys = [ "cache.tmmworkshop.com:jHffkpgbmEdstQPoihJPYW9TQe6jnQbWR2LqkNGV3iA=" ];
};
}

View File

@@ -1,9 +1,19 @@
{ lib, ... }:
{ {
services.autopull = {
enable = lib.mkDefault true;
repo.dotfiles = {
enable = lib.mkDefault true;
ssh-key = lib.mkDefault "/root/.ssh/id_ed25519_ghdeploy";
path = lib.mkDefault /root/dotfiles;
};
};
system.autoUpgrade = { system.autoUpgrade = {
enable = true; enable = lib.mkDefault true;
flags = [ "--accept-flake-config" ]; flags = [ "--accept-flake-config" ];
randomizedDelaySec = "1h"; randomizedDelaySec = "1h";
persistent = true; persistent = true;
flake = "github:RichieCahill/dotfiles"; flake = "github:RAD-Development/nix-dotfiles";
}; };
} }

View File

@@ -3,9 +3,4 @@
enable = true; enable = true;
joinNetworks = [ "e4da7455b2ae64ca" ]; joinNetworks = [ "e4da7455b2ae64ca" ];
}; };
nix.settings = {
trusted-substituters = [ "http://192.168.90.40:5000" ];
substituters = [ "http://192.168.90.40:5000/?priority=1&want-mass-query=true" ];
trusted-public-keys = [ "cache.tmmworkshop.com:jHffkpgbmEdstQPoihJPYW9TQe6jnQbWR2LqkNGV3iA=" ];
};
} }

278
flake.lock generated
View File

@@ -2,17 +2,18 @@
"nodes": { "nodes": {
"firefox-addons": { "firefox-addons": {
"inputs": { "inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"dir": "pkgs/firefox-addons", "dir": "pkgs/firefox-addons",
"lastModified": 1750219402, "lastModified": 1729414746,
"narHash": "sha256-b3y7V7db0VwLGtpcLRmT1Aa9dpAKoHQdem55UhgB/fw=", "narHash": "sha256-B7wGWFjIL6/BllPaTXyp31srxG7+4I0hlsBkL6S8pIM=",
"owner": "rycee", "owner": "rycee",
"repo": "nur-expressions", "repo": "nur-expressions",
"rev": "a00ce73b626ed274fbfe9f51627861e140b08f6d", "rev": "7bd3068e495e1f430e1a640b5f9ee683e4e5e616",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
@@ -22,6 +23,55 @@
"type": "gitlab" "type": "gitlab"
} }
}, },
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1717312683,
"narHash": "sha256-FrlieJH50AuvagamEvWMIE6D2OAnERuDboFDYAED/dE=",
"owner": "nix-community",
"repo": "flake-compat",
"rev": "38fd3954cf65ce6faf3d0d45cd26059e059f07ea",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1629284811,
"narHash": "sha256-JHgasjPR0/J1J3DRm4KxM4zTyAj4IOJY8vIl75v/kPI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c5d161cc0af116a2e17f54316f0bf43f0819785c",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"home-manager": { "home-manager": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -29,11 +79,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1750275572, "lastModified": 1729414726,
"narHash": "sha256-upC/GIlsIgtdtWRGd1obzdXWYQptNkfzZeyAFWgsgf0=", "narHash": "sha256-Dtmm1OU8Ymiy9hVWn/a2B8DhRYo9Eoyx9veERdOBR4o=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "0f355844e54e4c70906b1ef5cc35a0047d666c04", "rev": "fe56302339bb28e3471632379d733547caec8103",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -42,13 +92,58 @@
"type": "github" "type": "github"
} }
}, },
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"system_tools",
"poetry2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1703863825,
"narHash": "sha256-rXwqjtwiGKJheXB43ybM8NwWB8rO2dSRrEqes0S7F5Y=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "5163432afc817cf8bd1f031418d1869e4c9d5547",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nixos-cosmic": {
"inputs": {
"flake-compat": "flake-compat",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable",
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1729388162,
"narHash": "sha256-ARCVRKnANfAb1iwGVpNOujXTXsTdyHz80ocFxjpswv8=",
"owner": "lilyinstarlight",
"repo": "nixos-cosmic",
"rev": "1bfff37ff0178721ff4c0a7ed2fb39689b8db796",
"type": "github"
},
"original": {
"owner": "lilyinstarlight",
"repo": "nixos-cosmic",
"type": "github"
}
},
"nixos-hardware": { "nixos-hardware": {
"locked": { "locked": {
"lastModified": 1750083401, "lastModified": 1729417461,
"narHash": "sha256-ynqbgIYrg7P1fAKYqe8I/PMiLABBcNDYG9YaAP/d/C4=", "narHash": "sha256-p0j/sUs7noqZw0W+SEuZXskzOfgOH7yY80ksIM0fCi4=",
"owner": "nixos", "owner": "nixos",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "61837d2a33ccc1582c5fabb7bf9130d39fee59ad", "rev": "8f38d8a4754cf673c2609c4ed399630db87e678b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -60,11 +155,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1750134718, "lastModified": 1729256560,
"narHash": "sha256-v263g4GbxXv87hMXMCpjkIxd/viIF7p3JpJrwgKdNiI=", "narHash": "sha256-/uilDXvCIEs3C9l73JTACm4quuHUsIHcns1c+cHUJwA=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "9e83b64f727c88a7711a2c463a7b16eedb69a84c", "rev": "4c2fcb090b1f3e5b47eaa7bd33913b574a11e0a0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -74,29 +169,29 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-master": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1750291913, "lastModified": 1729181673,
"narHash": "sha256-JW40+zIiDS+rZavb9IYdIN40/GmErO2+0+A66rM6/b8=", "narHash": "sha256-LDiPhQ3l+fBjRATNtnuDZsBS7hqoBtPkKBkhpoBHv3I=",
"owner": "nixos", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "ba92ab5dc0759a8740003ca34b5c1b888f4766d4", "rev": "4eb33fe664af7b41a4c446f87d20c9a0a6321fa3",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "NixOS",
"ref": "master", "ref": "nixos-24.05",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
}, },
"nixpkgs-stable": { "nixpkgs-stable_2": {
"locked": { "locked": {
"lastModified": 1735563628, "lastModified": 1729181673,
"narHash": "sha256-OnSAY7XDSx7CtDoqNh8jwVwh4xNL/2HaJxGjryLWzX8=", "narHash": "sha256-LDiPhQ3l+fBjRATNtnuDZsBS7hqoBtPkKBkhpoBHv3I=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "b134951a4c9f3c995fd7be05f3243f8ecd65d798", "rev": "4eb33fe664af7b41a4c446f87d20c9a0a6321fa3",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -106,53 +201,31 @@
"type": "github" "type": "github"
} }
}, },
"pyproject-build-systems": { "poetry2nix": {
"inputs": { "inputs": {
"flake-utils": [
"system_tools",
"flake-utils"
],
"nix-github-actions": "nix-github-actions",
"nixpkgs": [ "nixpkgs": [
"system_tools", "system_tools",
"nixpkgs" "nixpkgs"
], ],
"pyproject-nix": [ "systems": "systems_2",
"system_tools", "treefmt-nix": "treefmt-nix"
"pyproject-nix"
],
"uv2nix": [
"system_tools",
"uv2nix"
]
}, },
"locked": { "locked": {
"lastModified": 1744599653, "lastModified": 1723343306,
"narHash": "sha256-nysSwVVjG4hKoOjhjvE6U5lIKA8sEr1d1QzEfZsannU=", "narHash": "sha256-/6sRkPq7/5weX2y0V8sQ29Sz35nt8kyj+BsFtkhgbJE=",
"owner": "pyproject-nix", "owner": "nix-community",
"repo": "build-system-pkgs", "repo": "poetry2nix",
"rev": "7dba6dbc73120e15b558754c26024f6c93015dd7", "rev": "4a1c112ff0c67f496573dc345bd0b2247818fc29",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "pyproject-nix", "owner": "nix-community",
"repo": "build-system-pkgs", "repo": "poetry2nix",
"type": "github"
}
},
"pyproject-nix": {
"inputs": {
"nixpkgs": [
"system_tools",
"nixpkgs"
]
},
"locked": {
"lastModified": 1746540146,
"narHash": "sha256-QxdHGNpbicIrw5t6U3x+ZxeY/7IEJ6lYbvsjXmcxFIM=",
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"rev": "e09c10c24ebb955125fda449939bfba664c467fd",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"type": "github" "type": "github"
} }
}, },
@@ -160,50 +233,49 @@
"inputs": { "inputs": {
"firefox-addons": "firefox-addons", "firefox-addons": "firefox-addons",
"home-manager": "home-manager", "home-manager": "home-manager",
"nixos-cosmic": "nixos-cosmic",
"nixos-hardware": "nixos-hardware", "nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"nixpkgs-master": "nixpkgs-master", "nixpkgs-stable": "nixpkgs-stable_2",
"nixpkgs-stable": "nixpkgs-stable",
"sops-nix": "sops-nix",
"system_tools": "system_tools", "system_tools": "system_tools",
"systems": "systems" "systems": "systems_3"
} }
}, },
"sops-nix": { "rust-overlay": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"nixos-cosmic",
"nixpkgs" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1750119275, "lastModified": 1729304879,
"narHash": "sha256-Rr7Pooz9zQbhdVxux16h7URa6mA80Pb/G07T4lHvh0M=", "narHash": "sha256-H7KGGJUU9BcDNnfXiATBGgs6FJKWQdfftNJS+/v2aMU=",
"owner": "Mic92", "owner": "oxalica",
"repo": "sops-nix", "repo": "rust-overlay",
"rev": "77c423a03b9b2b79709ea2cb63336312e78b72e2", "rev": "b259ef799b5ac014604da71ecd92d4a52603ed2d",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "Mic92", "owner": "oxalica",
"repo": "sops-nix", "repo": "rust-overlay",
"type": "github" "type": "github"
} }
}, },
"system_tools": { "system_tools": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
"pyproject-build-systems": "pyproject-build-systems", "poetry2nix": "poetry2nix"
"pyproject-nix": "pyproject-nix",
"uv2nix": "uv2nix"
}, },
"locked": { "locked": {
"lastModified": 1747501237, "lastModified": 1729435836,
"narHash": "sha256-woyaUwmZurfNTXBEFM6M7ueSd/Udixs+4DUInhL835c=", "narHash": "sha256-wDhbznFihvVh8sm93HUAeFDw0t8hoe9RGEyWBMkB4yw=",
"owner": "RichieCahill", "owner": "RichieCahill",
"repo": "system_tools", "repo": "system_tools",
"rev": "68ab5d1c17ac3fe2487f73dbbb4848bd2291139e", "rev": "84f9ef479e6561fe1daac304cddf195303d855dc",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -213,6 +285,35 @@
} }
}, },
"systems": { "systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"id": "systems",
"type": "indirect"
}
},
"systems_3": {
"locked": { "locked": {
"lastModified": 1689347949, "lastModified": 1689347949,
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
@@ -227,28 +328,25 @@
"type": "github" "type": "github"
} }
}, },
"uv2nix": { "treefmt-nix": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"system_tools", "system_tools",
"poetry2nix",
"nixpkgs" "nixpkgs"
],
"pyproject-nix": [
"system_tools",
"pyproject-nix"
] ]
}, },
"locked": { "locked": {
"lastModified": 1747441483, "lastModified": 1719749022,
"narHash": "sha256-W8BFXk5R0TuJcjIhcGoMpSOaIufGXpizK0pm+uTqynA=", "narHash": "sha256-ddPKHcqaKCIFSFc/cvxS14goUhCOAwsM1PbMr0ZtHMg=",
"owner": "pyproject-nix", "owner": "numtide",
"repo": "uv2nix", "repo": "treefmt-nix",
"rev": "582024dc64663e9f88d467c2f7f7b20d278349de", "rev": "8df5ff62195d4e67e2264df0b7f5e8c9995fd0bd",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "pyproject-nix", "owner": "numtide",
"repo": "uv2nix", "repo": "treefmt-nix",
"type": "github" "type": "github"
} }
} }

View File

@@ -3,20 +3,21 @@
nixConfig = { nixConfig = {
extra-substituters = [ extra-substituters = [
"https://cache.nixos.org/?priority=2&want-mass-query=true" "https://cache.nixos.org/?priority=1&want-mass-query=true"
"https://cache.tmmworkshop.com/?priority=1&want-mass-query=true"
"https://nix-community.cachix.org/?priority=10&want-mass-query=true" "https://nix-community.cachix.org/?priority=10&want-mass-query=true"
]; ];
extra-trusted-public-keys = [ extra-trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" # cspell:disable-line "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" # cspell:disable-line "cache.tmmworkshop.com:jHffkpgbmEdstQPoihJPYW9TQe6jnQbWR2LqkNGV3iA="
"cache-nix-dot:Od9KN34LXc6Lu7y1ozzV1kIXZa8coClozgth/SYE7dU=" # cspell:disable-line "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"cache-nix-dot:Od9KN34LXc6Lu7y1ozzV1kIXZa8coClozgth/SYE7dU="
]; ];
}; };
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-24.05"; nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-24.05";
nixpkgs-master.url = "github:nixos/nixpkgs/master";
systems.url = "github:nix-systems/default-linux"; systems.url = "github:nix-systems/default-linux";
nixos-hardware.url = "github:nixos/nixos-hardware/master"; nixos-hardware.url = "github:nixos/nixos-hardware/master";
@@ -36,59 +37,50 @@
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
sops-nix = { nixos-cosmic = {
url = "github:Mic92/sops-nix"; url = "github:lilyinstarlight/nixos-cosmic";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
}; };
outputs = outputs = {
{ self,
self, nixpkgs,
nixpkgs, home-manager,
home-manager, systems,
systems, nixos-cosmic,
sops-nix, ...
... } @ inputs: let
}@inputs: inherit (self) outputs;
let lib = nixpkgs.lib // home-manager.lib;
inherit (self) outputs; forEachSystem = f: lib.genAttrs (import systems) (system: f pkgsFor.${system});
lib = nixpkgs.lib // home-manager.lib; pkgsFor = lib.genAttrs (import systems) (
forEachSystem = f: lib.genAttrs (import systems) (system: f pkgsFor.${system}); system:
pkgsFor = lib.genAttrs (import systems) (
system:
import nixpkgs { import nixpkgs {
inherit system; inherit system;
config.allowUnfree = true; config.allowUnfree = true;
} }
); );
in in {
{ inherit lib;
inherit lib; overlays = import ./overlays {inherit inputs outputs;};
overlays = import ./overlays { inherit inputs outputs; };
devShells = forEachSystem (pkgs: import ./shell.nix { inherit pkgs; }); devShells = forEachSystem (pkgs: import ./shell.nix {inherit pkgs;});
formatter = forEachSystem (pkgs: pkgs.treefmt); formatter = forEachSystem (pkgs: pkgs.alejandra);
nixosConfigurations = { nixosConfigurations = {
bob = lib.nixosSystem { bob = lib.nixosSystem {
modules = [ modules = [./systems/bob];
./systems/bob specialArgs = {inherit inputs outputs;};
]; };
specialArgs = { inherit inputs outputs; }; jeeves = lib.nixosSystem {
}; modules = [./systems/jeeves];
jeeves = lib.nixosSystem { specialArgs = {inherit inputs outputs;};
modules = [ };
./systems/jeeves rhapsody-in-green = lib.nixosSystem {
]; modules = [./systems/rhapsody-in-green];
specialArgs = { inherit inputs outputs; }; specialArgs = {inherit inputs outputs;};
};
rhapsody-in-green = lib.nixosSystem {
modules = [
./systems/rhapsody-in-green
];
specialArgs = { inherit inputs outputs; };
};
}; };
}; };
};
} }

View File

@@ -1,5 +1,4 @@
{ inputs, ... }: {inputs, ...}: {
{
# When applied, the stable nixpkgs set (declared in the flake inputs) will be accessible through 'pkgs.stable' # When applied, the stable nixpkgs set (declared in the flake inputs) will be accessible through 'pkgs.stable'
stable = final: _prev: { stable = final: _prev: {
stable = import inputs.nixpkgs-stable { stable = import inputs.nixpkgs-stable {
@@ -7,11 +6,4 @@
config.allowUnfree = true; config.allowUnfree = true;
}; };
}; };
# When applied, the master nixpkgs set (declared in the flake inputs) will be accessible through 'pkgs.master'
master = final: _prev: {
master = import inputs.nixpkgs-master {
system = final.system;
config.allowUnfree = true;
};
};
} }

View File

@@ -1,8 +1,4 @@
{ {pkgs ? import <nixpkgs> {}, ...}: {
pkgs ? import <nixpkgs> { },
...
}:
{
default = pkgs.mkShell { default = pkgs.mkShell {
NIX_CONFIG = "extra-experimental-features = nix-command flakes ca-derivations"; NIX_CONFIG = "extra-experimental-features = nix-command flakes ca-derivations";
nativeBuildInputs = with pkgs; [ nativeBuildInputs = with pkgs; [

View File

@@ -1,22 +1,17 @@
{ {
imports = [ imports = [
../../users/richie ../../users/richie
../../users/gaming
../../common/global ../../common/global
../../common/optional/desktop.nix ../../common/optional/desktop.nix
../../common/optional/docker.nix
../../common/optional/scanner.nix ../../common/optional/scanner.nix
../../common/optional/steam.nix ../../common/optional/steam.nix
../../common/optional/syncthing_base.nix ../../common/optional/syncthing_base.nix
../../common/optional/systemd-boot.nix ../../common/optional/systemd-boot.nix
../../common/optional/update.nix
../../common/optional/yubikey.nix
../../common/optional/zerotier.nix ../../common/optional/zerotier.nix
../../common/optional/nvidia.nix ../../common/optional/yubikey.nix
./hardware.nix ./hardware.nix
./nvidia.nix
./syncthing.nix ./syncthing.nix
./games.nix
./llms.nix
]; ];
networking = { networking = {
@@ -26,19 +21,37 @@
networkmanager.enable = true; networkmanager.enable = true;
}; };
services = { hardware = {
displayManager = { pulseaudio.enable = false;
bluetooth = {
enable = true; enable = true;
autoLogin = { powerOnBoot = true;
user = "gaming";
enable = true;
};
defaultSession = "plasma";
}; };
};
security.rtkit.enable = true;
services = {
displayManager.sddm.enable = true;
openssh.ports = [ 262 ]; openssh.ports = [ 262 ];
snapshot_manager.path = ./snapshot_config.toml; printing.enable = true;
pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
};
snapshot_manager.enable = true;
zfs = {
trim.enable = true;
autoScrub.enable = true;
};
}; };
system.stateVersion = "24.05"; system.stateVersion = "24.05";

View File

@@ -1,7 +0,0 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
osu-lazer-bin
jellyfin-media-player
];
}

View File

@@ -26,9 +26,6 @@
device = "/dev/disk/by-id/nvme-Samsung_SSD_990_PRO_with_Heatsink_1TB_S73JNJ0X114418B-part2"; device = "/dev/disk/by-id/nvme-Samsung_SSD_990_PRO_with_Heatsink_1TB_S73JNJ0X114418B-part2";
bypassWorkqueues = true; bypassWorkqueues = true;
allowDiscards = true; allowDiscards = true;
keyFileSize = 4096;
keyFile = "/dev/disk/by-id/usb-Samsung_Flash_Drive_FIT_0374620080067131-0:0";
fallbackToPassword = true;
}; };
}; };
kernelModules = [ "kvm-amd" ]; kernelModules = [ "kvm-amd" ];
@@ -51,11 +48,6 @@
fsType = "zfs"; fsType = "zfs";
}; };
"/zfs/models" = {
device = "root_pool/models";
fsType = "zfs";
};
"/boot" = { "/boot" = {
device = "/dev/disk/by-uuid/609D-FF29"; device = "/dev/disk/by-uuid/609D-FF29";
fsType = "vfat"; fsType = "vfat";

View File

@@ -1,28 +0,0 @@
{
services = {
ollama = {
user = "ollama";
enable = true;
loadModels = [
"codellama:7b"
"deepseek-r1:8b"
"deepseek-r1:14b"
"deepseek-r1:32b"
"llama3.2:3b"
"llama2-uncensored:7b"
"mistral-nemo:12b"
"dolphin-mixtral:8x7b"
"qwq:32b"
"Qihoo360-Light-R1-32B"
];
models = "/zfs/models";
acceleration = "cuda";
openFirewall = true;
};
# open-webui = {
# enable = true;
# openFirewall = true;
# host = "0.0.0.0";
# };
};
}

View File

@@ -1,15 +1,12 @@
{ config, ... }: { config, ... }:
{ {
nixpkgs.config.cudaSupport = true;
services.xserver.videoDrivers = [ "nvidia" ]; services.xserver.videoDrivers = [ "nvidia" ];
hardware = { hardware = {
nvidia = { nvidia = {
modesetting.enable = true; modesetting.enable = true;
powerManagement.enable = true; powerManagement.enable = true;
package = config.boot.kernelPackages.nvidiaPackages.beta; package = config.boot.kernelPackages.nvidiaPackages.production;
nvidiaSettings = true; nvidiaSettings = true;
open = true;
}; };
nvidia-container-toolkit.enable = true; nvidia-container-toolkit.enable = true;
}; };

View File

@@ -1,29 +0,0 @@
["default"]
15_min = 8
hourly = 24
daily = 0
monthly = 0
["root_pool/home"]
15_min = 8
hourly = 12
daily = 1
monthly = 0
["root_pool/root"]
15_min = 8
hourly = 24
daily = 0
monthly = 0
["root_pool/nix"]
15_min = 4
hourly = 0
daily = 0
monthly = 0
["root_pool/models"]
15_min = 4
hourly = 24
daily = 0
monthly = 0

View File

@@ -1,7 +1,8 @@
{ {
services.syncthing.settings.folders = { services.syncthing.settings.folders = {
"dotfiles" = { "notes" = {
path = "/home/richie/dotfiles"; id = "l62ul-lpweo"; # cspell:disable-line
path = "/home/richie/notes";
devices = [ devices = [
"jeeves" "jeeves"
"rhapsody-in-green" "rhapsody-in-green"
@@ -29,5 +30,29 @@
]; ];
fsWatcherEnabled = true; fsWatcherEnabled = true;
}; };
"projects" = {
id = "vyma6-lqqrz"; # cspell:disable-line
path = "/home/richie/projects";
devices = [
"jeeves"
"rhapsody-in-green"
];
fsWatcherEnabled = true;
};
"temp" = {
id = "bob_temp";
path = "/home/richie/temp";
devices = [
"jeeves"
];
fsWatcherEnabled = true;
};
"vault" = {
path = "/home/richie/vault";
devices = [
"rhapsody-in-green"
];
fsWatcherEnabled = true;
};
}; };
} }

View File

@@ -0,0 +1,39 @@
{ inputs, pkgs, ... }:
let
vars = import ./vars.nix;
in
{
users = {
users.arch-mirror = {
isSystemUser = true;
group = "arch-mirror";
};
groups.arch-mirror = {};
};
virtualisation.oci-containers.containers.arch_mirror = {
image = "ubuntu/apache2:latest";
volumes = [
"${../../common/docker_templates}/file_server/sites/:/etc/apache2/sites-enabled/"
"${vars.media_mirror}:/data"
];
ports = [ "800:80" ];
extraOptions = [ "--network=web" ];
autoStart = true;
};
systemd.services.sync_mirror = {
requires = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
description = "validates startup";
path = [ pkgs.rsync ];
serviceConfig = {
Environment = "MIRROR_DIR=${vars.media_mirror}/archlinux/";
Type = "simple";
User = "arch-mirror";
Group = "arch-mirror";
ExecStart = "${inputs.system_tools.packages.x86_64-linux.default}/bin/sync_mirror";
};
};
}

View File

@@ -1,27 +1,56 @@
let
vars = import ./vars.nix;
in
{ {
imports = [ imports = [
../../users/richie ../../users/richie
../../common/global ../../common/global
../../common/optional/docker.nix
../../common/optional/ssh_decrypt.nix ../../common/optional/ssh_decrypt.nix
../../common/optional/syncthing_base.nix ../../common/optional/syncthing_base.nix
../../common/optional/zerotier.nix ../../common/optional/zerotier.nix
./arch_mirror.nix
./docker ./docker
./services
./hardware.nix ./hardware.nix
./home_assistant.nix
./networking.nix ./networking.nix
./nvidia.nix
./programs.nix ./programs.nix
./runners ./services.nix
./syncthing.nix ./syncthing.nix
]; ];
boot.zfs.extraPools = [
"media"
"storage"
"torrenting"
];
services = { services = {
openssh.ports = [ 629 ]; openssh.ports = [ 629 ];
nix-serve = {
enable = true;
secretKeyFile = "${vars.storage_secrets}/services/nix-cache/cache-priv-key.pem";
};
plex = {
enable = true;
dataDir = vars.media_plex;
openFirewall = true;
};
smartd.enable = true; smartd.enable = true;
snapshot_manager.path = ./snapshot_config.toml; snapshot_manager = {
enable = true;
path = ./snapshot_config.toml;
};
sysstat.enable = true;
zfs = {
trim.enable = true;
autoScrub.enable = true;
};
}; };
system.stateVersion = "24.05"; system.stateVersion = "24.05";

View File

@@ -0,0 +1,15 @@
let
vars = import ../vars.nix;
in
{
virtualisation.oci-containers.containers.filebrowser = {
image = "hurlenko/filebrowser:latest";
extraOptions = [ "--network=web" ];
volumes = [
"/zfs:/data"
"${vars.media_docker_configs}/filebrowser:/config"
];
autoStart = true;
user = "1000:users";
};
}

View File

@@ -1,61 +0,0 @@
{
config,
pkgs,
lib,
...
}:
let
vars = import ../vars.nix;
in
{
# environment.systemPackages = with pkgs; [ php.withExtensions ({ all, ... }: [ all.pdo_pgsql ]) ];
services.httpd = {
enable = true;
adminAddr = "webmaster@localhost";
enablePHP = true;
phpPackage = pkgs.php.withExtensions (
{ enabled, all }:
enabled
++ [
all.pdo
all.pdo_pgsql
]
);
extraModules = [ "rewrite" ];
virtualHosts.great_cloud_of_witnesses = {
hostName = "localhost";
listen = [
{
ip = "*";
port = 8092;
}
];
documentRoot = "${vars.services}/great_cloud_of_witnesses";
extraConfig = ''
<Directory "${vars.services}/great_cloud_of_witnesses">
AllowOverride All
Require all granted
</Directory>
'';
};
};
sops.secrets.gcw_password = {
sopsFile = ../../../users/secrets.yaml;
neededForUsers = true;
};
users = {
users.gcw = {
isSystemUser = true;
hashedPasswordFile = config.sops.secrets.gcw_password.path;
group = "gcw";
};
groups.gcw = { };
};
}

View File

@@ -21,53 +21,51 @@ defaults
#Application Setup #Application Setup
frontend ContentSwitching frontend ContentSwitching
bind *:80 v4v6 bind *:80
bind *:443 v4v6 ssl crt /zfs/storage/secrets/docker/cloudflare.pem bind *:443 ssl crt /etc/ssl/certs/cloudflare.pem
mode http mode http
# tmmworkshop.com # tmmworkshop.com
acl host_audiobookshelf hdr(host) -i audiobookshelf.tmmworkshop.com acl host_audiobookshelf hdr(host) -i audiobookshelf.tmmworkshop.com
acl host_cache hdr(host) -i cache.tmmworkshop.com acl host_cache hdr(host) -i cache.tmmworkshop.com
acl host_filebrowser hdr(host) -i filebrowser.tmmworkshop.com acl host_filebrowser hdr(host) -i filebrowser.tmmworkshop.com
acl host_homeassistant hdr(host) -i homeassistant.tmmworkshop.com acl host_grafana hdr(host) -i grafana.tmmworkshop.com
acl host_jellyfin hdr(host) -i jellyfin.tmmworkshop.com acl host_mirror hdr(host) -i mirror.tmmworkshop.com
acl host_share hdr(host) -i share.tmmworkshop.com acl host_photoprism hdr(host) -i photoprism.tmmworkshop.com
acl host_gcw hdr(host) -i gcw.tmmworkshop.com acl host_uptime_kuma hdr(host) -i uptimekuma-jeeves.tmmworkshop.com
use_backend audiobookshelf_nodes if host_audiobookshelf use_backend audiobookshelf_nodes if host_audiobookshelf
use_backend cache_nodes if host_cache use_backend cache_nodes if host_cache
use_backend filebrowser_nodes if host_filebrowser use_backend filebrowser_nodes if host_filebrowser
use_backend homeassistant_nodes if host_homeassistant use_backend grafana_nodes if host_grafana
use_backend jellyfin if host_jellyfin use_backend mirror_nodes if host_mirror
use_backend share_nodes if host_share use_backend photoprism_nodes if host_photoprism
use_backend gcw_nodes if host_gcw use_backend uptime_kuma_nodes if host_uptime_kuma
backend audiobookshelf_nodes backend audiobookshelf_nodes
mode http mode http
server server 127.0.0.1:8000 server server audiobookshelf:80
backend cache_nodes backend cache_nodes
mode http mode http
server server 127.0.0.1:5000 server server 192.168.90.40:5000
backend grafana_nodes
mode http
server server grafana:3000
backend filebrowser_nodes backend filebrowser_nodes
mode http mode http
server server 127.0.0.1:8080 server server filebrowser:8080
backend homeassistant_nodes backend mirror_nodes
mode http mode http
server server 127.0.0.1:8123 server server arch_mirror:80
backend jellyfin backend photoprism_nodes
option httpchk
option forwardfor
http-check send meth GET uri /health
http-check expect string Healthy
server jellyfin 127.0.0.1:8096
backend share_nodes
mode http mode http
server server 127.0.0.1:8091 server server photoprism:2342
backend gcw_nodes backend uptime_kuma_nodes
mode http mode http
server server 127.0.0.1:8092 server server uptime_kuma:3001

View File

@@ -0,0 +1,54 @@
let
vars = import ../vars.nix;
in
{
virtualisation.oci-containers.containers.photoprism = {
image = "photoprism/photoprism:latest";
volumes = [
"${vars.media_docker_configs}/photoprism:/photoprism/storage"
"${vars.storage_photos}/originals:/photoprism/originals"
"${vars.storage_photos}/import:/photoprism/import"
];
environment = {
PHOTOPRISM_ADMIN_USER="admin";
PHOTOPRISM_AUTH_MODE="password";
PHOTOPRISM_DISABLE_TLS="false";
PHOTOPRISM_DEFAULT_TLS="true";
PHOTOPRISM_ORIGINALS_LIMIT="30000";
PHOTOPRISM_HTTP_COMPRESSION="gzip";
PHOTOPRISM_LOG_LEVEL="info";
PHOTOPRISM_READONLY="false";
PHOTOPRISM_EXPERIMENTAL="false";
PHOTOPRISM_DISABLE_CHOWN="false";
PHOTOPRISM_DISABLE_WEBDAV="false";
PHOTOPRISM_DISABLE_SETTINGS="false";
PHOTOPRISM_DISABLE_TENSORFLOW="false";
PHOTOPRISM_DISABLE_FACES="false";
PHOTOPRISM_DISABLE_CLASSIFICATION="false";
PHOTOPRISM_DISABLE_VECTORS="false";
PHOTOPRISM_DISABLE_RAW="false";
PHOTOPRISM_RAW_PRESETS="false";
PHOTOPRISM_SIDECAR_YAML="true";
PHOTOPRISM_BACKUP_ALBUMS="true";
PHOTOPRISM_BACKUP_DATABASE="true";
PHOTOPRISM_BACKUP_SCHEDULE="daily";
PHOTOPRISM_INDEX_SCHEDULE="";
PHOTOPRISM_AUTO_INDEX="300";
PHOTOPRISM_AUTO_IMPORT= "-1";
PHOTOPRISM_DETECT_NSFW="false";
PHOTOPRISM_UPLOAD_NSFW="true";
PHOTOPRISM_DATABASE_DRIVER="sqlite";
PHOTOPRISM_SITE_CAPTION="AI-Powered Photos App";
PHOTOPRISM_SITE_DESCRIPTION="";
PHOTOPRISM_SITE_AUTHOR="";
PHOTOPRISM_UID="600";
PHOTOPRISM_GID="600";
# PHOTOPRISM_UMASK: 0000
};
environmentFiles = ["${vars.storage_secrets}/docker/photoprism"];
autoStart = true;
dependsOn = [ "photoprism_mariadb" ];
extraOptions = [ "--network=web" ];
};
}

View File

@@ -0,0 +1,32 @@
let
vars = import ../vars.nix;
in
{
users = {
users.postgres = {
isSystemUser = true;
group = "postgres";
uid = 999;
};
groups.postgres = {
gid = 999;
};
};
# virtualisation.oci-containers.containers = {
# postgres = {
# image = "postgres:16";
# ports = [ "5432:5432" ];
# volumes = [ "${vars.media_database}/postgres:/var/lib/postgresql/data" ];
# environment = {
# POSTGRES_USER = "admin";
# POSTGRES_DB = "archive";
# POSTGRES_INITDB_ARGS = "--auth-host=scram-sha-256";
# };
# environmentFiles = [/root/secrets/docker/postgres];
# autoStart = true;
# user = "postgres:postgres";
# };
# };
}

View File

@@ -0,0 +1,19 @@
let
vars = import ../vars.nix;
in
{
networking.firewall = {
allowedTCPPorts = [ 9696 ];
};
virtualisation.oci-containers.containers.prowlarr = {
image = "ghcr.io/linuxserver/prowlarr:latest";
ports = [ "9696:9696" ];
environment = {
PUID = "600";
PGID = "100";
TZ = "America/New_York";
};
volumes = [ "${vars.media_docker_configs}/prowlarr:/config" ];
autoStart = true;
};
}

View File

@@ -0,0 +1,29 @@
let
vars = import ../vars.nix;
in
{
networking.firewall = {
allowedTCPPorts = [ 6881 8082 29432 ];
allowedUDPPorts = [ 6881 ];
};
virtualisation.oci-containers.containers.qbit = {
image = "ghcr.io/linuxserver/qbittorrent:latest";
ports = [
"6881:6881"
"6881:6881/udp"
"8082:8082"
"29432:29432"
];
volumes = [
"${vars.media_docker_configs}/qbit:/config"
"${vars.torrenting_qbit}:/data"
];
environment = {
PUID = "600";
PGID = "100";
TZ = "America/New_York";
WEBUI_PORT = "8082";
};
autoStart = true;
};
}

View File

@@ -3,16 +3,11 @@ let
in in
{ {
networking.firewall = { networking.firewall = {
allowedTCPPorts = [ allowedTCPPorts = [ 6882 8081 8118 ];
6882
8081
8118
];
allowedUDPPorts = [ 6882 ]; allowedUDPPorts = [ 6882 ];
}; };
virtualisation.oci-containers.containers.qbitvpn = { virtualisation.oci-containers.containers.qbitvpn = {
image = "binhex/arch-qbittorrentvpn:5.0.3-1-01"; image = "binhex/arch-qbittorrentvpn:latest";
devices = [ "/dev/net/tun:/dev/net/tun" ];
extraOptions = [ "--cap-add=NET_ADMIN" ]; extraOptions = [ "--cap-add=NET_ADMIN" ];
ports = [ ports = [
"6882:6881" "6882:6881"
@@ -21,9 +16,8 @@ in
"8118:8118" "8118:8118"
]; ];
volumes = [ volumes = [
"${vars.docker_configs}/qbitvpn:/config" "${vars.media_docker_configs}/qbitvpn:/config"
"${vars.qbitvpn}:/data" "${vars.torrenting_qbitvpn}:/data"
"${vars.qbitvpn_scratch}:/data/incomplete"
"/etc/localtime:/etc/localtime:ro" "/etc/localtime:/etc/localtime:ro"
]; ];
environment = { environment = {
@@ -41,7 +35,7 @@ in
DELUGE_DAEMON_LOG_LEVEL = "debug"; DELUGE_DAEMON_LOG_LEVEL = "debug";
DELUGE_WEB_LOG_LEVEL = "debug"; DELUGE_WEB_LOG_LEVEL = "debug";
}; };
environmentFiles = [ "${vars.secrets}/docker/qbitvpn" ]; environmentFiles = ["${vars.storage_secrets}/docker/qbitvpn"];
autoStart = true; autoStart = true;
}; };
} }

View File

@@ -1,15 +0,0 @@
let
vars = import ../vars.nix;
in
{
virtualisation.oci-containers.containers.share = {
image = "ubuntu/apache2:2.4-22.04_beta";
ports = [ "8091:80" ];
volumes = [
"${../../../common/docker_templates}/file_server/sites/:/etc/apache2/sites-enabled/"
"${vars.share}:/data"
];
extraOptions = [ "--network=web" ];
autoStart = true;
};
}

View File

@@ -0,0 +1,21 @@
let
vars = import ../vars.nix;
in
{
networking.firewall.allowedTCPPorts = [ 9696 8989 ];
virtualisation.oci-containers.containers.sonarr = {
image = "ghcr.io/linuxserver/sonarr:latest";
ports = [ "8989:8989" ];
environment = {
PUID = "600";
PGID = "100";
TZ = "America/New_York";
};
volumes = [
"${vars.media_docker_configs}/sonarr:/config"
"${vars.storage_plex}/tv:/tv"
"${vars.torrenting_qbitvpn}:/data"
];
autoStart = true;
};
}

View File

@@ -0,0 +1,16 @@
let
vars = import ../vars.nix;
in
{
virtualisation.oci-containers.containers = {
uptime_kuma = {
image = "louislam/uptime-kuma:latest";
volumes = [
"${vars.media_docker_configs}/uptime_kuma:/app/data"
"/var/run/docker.sock:/var/run/docker.sock"
];
extraOptions = [ "--network=web" ];
autoStart = true;
};
};
}

View File

@@ -0,0 +1,60 @@
let
vars = import ../vars.nix;
in
{
virtualisation.oci-containers.containers = {
audiobookshelf = {
image = "ghcr.io/advplyr/audiobookshelf:latest";
volumes = [
"${vars.media_docker_configs}/audiobookshelf:/config"
"${vars.media_docker_configs}/audiobookshelf:/metadata"
"${vars.storage_library}/audiobooks:/audiobooks"
"${vars.storage_library}/books:/books"
];
environment = {
TZ = "America/New_York";
};
extraOptions = [ "--network=web" ];
autoStart = true;
};
grafana = {
image = "grafana/grafana-enterprise:latest";
volumes = [ "${vars.media_docker_configs}/grafana:/var/lib/grafana" ];
user = "600:600";
extraOptions = [ "--network=web" ];
autoStart = true;
};
haproxy = {
image = "haproxy:latest";
user = "600:600";
environment = {
TZ = "Etc/EST";
};
volumes = [
"${vars.storage_secrets}/docker/cloudflare.pem:/etc/ssl/certs/cloudflare.pem"
"${./haproxy.cfg}:/usr/local/etc/haproxy/haproxy.cfg"
];
dependsOn = [
"arch_mirror"
"audiobookshelf"
"filebrowser"
"grafana"
"uptime_kuma"
];
extraOptions = [ "--network=web" ];
autoStart = true;
};
cloud_flare_tunnel = {
image = "cloudflare/cloudflared:latest";
user = "600:600";
cmd = [
"tunnel"
"run"
];
environmentFiles = ["${vars.storage_secrets}/docker/cloud_flare_tunnel"];
dependsOn = [ "haproxy" ];
extraOptions = [ "--network=web" ];
autoStart = true;
};
};
}

View File

@@ -1,26 +1,6 @@
{ config, lib, modulesPath, ... }:
{ {
config, imports =[ (modulesPath + "/installer/scan/not-detected.nix") ];
lib,
modulesPath,
...
}:
let
makeLuksDevice = device: {
inherit device;
keyFileSize = 4096;
keyFile = "/dev/disk/by-id/usb-XIAO_USB_Drive_24587CE29074-0:0";
fallbackToPassword = true;
};
makeLuksSSD =
device:
(makeLuksDevice device)
// {
bypassWorkqueues = true;
allowDiscards = true;
};
in
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
boot = { boot = {
loader = { loader = {
@@ -56,51 +36,77 @@ in
luks.devices = { luks.devices = {
# cspell:disable # cspell:disable
# Root pool # Root pool
"luks-root-pool-wwn-0x55cd2e4150f01519-part2" = "luks-root-pool-wwn-0x55cd2e4150f01519-part2" = {
makeLuksSSD "/dev/disk/by-id/wwn-0x55cd2e4150f01519-part2"; device = "/dev/disk/by-id/wwn-0x55cd2e4150f01519-part2";
"luks-root-pool-wwn-0x55cd2e4150f01556-part2" = bypassWorkqueues = true;
makeLuksSSD "/dev/disk/by-id/wwn-0x55cd2e4150f01556-part2"; allowDiscards = true;
};
"luks-root-pool-wwn-0x55cd2e4150f01556-part2" = {
device = "/dev/disk/by-id/wwn-0x55cd2e4150f01556-part2";
bypassWorkqueues = true;
allowDiscards = true;
};
# Media pool # Media pool
"luks-media_pool-nvme-INTEL_SSDPEK1A118GA_BTOC14120V2J118B-part1" = "luks-media_pool-nvme-INTEL_SSDPEK1A118GA_BTOC14120V2J118B-part1" = {
makeLuksSSD "/dev/disk/by-id/nvme-INTEL_SSDPEK1A118GA_BTOC14120V2J118B-part1"; device = "/dev/disk/by-id/nvme-INTEL_SSDPEK1A118GA_BTOC14120V2J118B-part1";
"luks-media_pool-nvme-INTEL_SSDPEK1A118GA_BTOC14120WAG118B-part1" = bypassWorkqueues = true;
makeLuksSSD "/dev/disk/by-id/nvme-INTEL_SSDPEK1A118GA_BTOC14120WAG118B-part1"; allowDiscards = true;
"luks-media_pool-nvme-INTEL_SSDPE2ME012T4_CVMD5130000G1P2HGN-part1" = };
makeLuksSSD "/dev/disk/by-id/nvme-INTEL_SSDPE2ME012T4_CVMD5130000G1P2HGN-part1"; "luks-media_pool-nvme-INTEL_SSDPEK1A118GA_BTOC14120WAG118B-part1" = {
"luks-media_pool-nvme-INTEL_SSDPE2ME012T4_CVMD5130000U1P2HGN-part1" = device = "/dev/disk/by-id/nvme-INTEL_SSDPEK1A118GA_BTOC14120WAG118B-part1";
makeLuksSSD "/dev/disk/by-id/nvme-INTEL_SSDPE2ME012T4_CVMD5130000U1P2HGN-part1"; bypassWorkqueues = true;
allowDiscards = true;
# Scratch pool };
"luks-scratch-pool-ata-CT480BX500SSD1_2314E6C3C01C-part1" = "luks-media_pool-nvme-INTEL_SSDPE2ME012T4_CVMD5130000G1P2HGN-part1" = {
makeLuksSSD "/dev/disk/by-id/ata-CT480BX500SSD1_2314E6C3C01C-part1"; device = "/dev/disk/by-id/nvme-INTEL_SSDPE2ME012T4_CVMD5130000G1P2HGN-part1";
"luks-scratch-pool-ata-CT480BX500SSD1_2314E6C3C01E-part1" = bypassWorkqueues = true;
makeLuksSSD "/dev/disk/by-id/ata-CT480BX500SSD1_2314E6C3C01E-part1"; allowDiscards = true;
};
"luks-media_pool-nvme-INTEL_SSDPE2ME012T4_CVMD5130000U1P2HGN-part1" = {
device = "/dev/disk/by-id/nvme-INTEL_SSDPE2ME012T4_CVMD5130000U1P2HGN-part1";
bypassWorkqueues = true;
allowDiscards = true;
};
# Storage pool # Storage pool
"luks-storage_pool-nvme-Samsung_SSD_970_EVO_Plus_2TB_S6S2NS0T834822N-part1" = "luks-storage_pool-nvme-Samsung_SSD_970_EVO_Plus_2TB_S6S2NS0T834822N-part1" = {
makeLuksSSD "/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_2TB_S6S2NS0T834822N-part1"; device = "/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_2TB_S6S2NS0T834822N-part1";
"luks-storage_pool-nvme-Samsung_SSD_970_EVO_Plus_2TB_S6S2NS0T834817F-part1" = bypassWorkqueues = true;
makeLuksSSD "/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_2TB_S6S2NS0T834817F-part1"; allowDiscards = true;
"luks-storage_pool-nvme-INTEL_MEMPEK1W016GA_PHBT828104DF016D-part1" = };
makeLuksSSD "/dev/disk/by-id/nvme-INTEL_MEMPEK1W016GA_PHBT828104DF016D-part1"; "luks-storage_pool-nvme-Samsung_SSD_970_EVO_Plus_2TB_S6S2NS0T834817F-part1" = {
"luks-storage_pool-nvme-INTEL_MEMPEK1W016GA_PHBT828105A8016D-part1" = device = "/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_2TB_S6S2NS0T834817F-part1";
makeLuksSSD "/dev/disk/by-id/nvme-INTEL_MEMPEK1W016GA_PHBT828105A8016D-part1"; bypassWorkqueues = true;
"luks-storage_pool-wwn-0x5000cca23bc438dd-part1" = allowDiscards = true;
makeLuksDevice "/dev/disk/by-id/wwn-0x5000cca23bc438dd-part1"; };
"luks-storage_pool-wwn-0x5000cca23bd035f5-part1" = "luks-storage_pool-nvme-INTEL_MEMPEK1W016GA_PHBT828104DF016D-part1" = {
makeLuksDevice "/dev/disk/by-id/wwn-0x5000cca23bd035f5-part1"; device = "/dev/disk/by-id/nvme-INTEL_MEMPEK1W016GA_PHBT828104DF016D-part1";
"luks-storage_pool-wwn-0x5000cca23bd00ad6-part1" = bypassWorkqueues = true;
makeLuksDevice "/dev/disk/by-id/wwn-0x5000cca23bd00ad6-part1"; allowDiscards = true;
};
"luks-storage_pool-nvme-INTEL_MEMPEK1W016GA_PHBT828105A8016D-part1" = {
device = "/dev/disk/by-id/nvme-INTEL_MEMPEK1W016GA_PHBT828105A8016D-part1";
bypassWorkqueues = true;
allowDiscards = true;
};
"luks-storage_pool-wwn-0x5000cca23bc438dd-part1".device = "/dev/disk/by-id/wwn-0x5000cca23bc438dd-part1";
"luks-storage_pool-wwn-0x5000cca23bd035f5-part1".device = "/dev/disk/by-id/wwn-0x5000cca23bd035f5-part1";
"luks-storage_pool-wwn-0x5000cca23bd00ad6-part1".device = "/dev/disk/by-id/wwn-0x5000cca23bd00ad6-part1";
"luks-storage_pool-wwn-0x5000cca23bcf313e-part1".device = "/dev/disk/by-id/wwn-0x5000cca23bcf313e-part1";
"luks-storage_pool-wwn-0x5000cca23bcdf3b8-part1".device = "/dev/disk/by-id/wwn-0x5000cca23bcdf3b8-part1";
"luks-storage_pool-wwn-0x5000cca23bd02746-part1".device = "/dev/disk/by-id/wwn-0x5000cca23bd02746-part1";
"luks-storage_pool-wwn-0x5000cca23bcf9f89-part1".device = "/dev/disk/by-id/wwn-0x5000cca23bcf9f89-part1";
"luks-storage_pool-wwn-0x5000cca23bd00ae9-part1".device = "/dev/disk/by-id/wwn-0x5000cca23bd00ae9-part1";
# Torrenting pool
"luks-torrenting_pool-wwn-0x500a0751e6c3c01e-part1" = {
device = "/dev/disk/by-id/wwn-0x500a0751e6c3c01e-part1";
bypassWorkqueues = true;
allowDiscards = true;
};
"luks-torrenting_pool-wwn-0x5000cca264f080a3-part1".device = "/dev/disk/by-id/wwn-0x5000cca264f080a3-part1";
"luks-torrenting_pool-wwn-0x5000cca298c33ae5-part1".device = "/dev/disk/by-id/wwn-0x5000cca298c33ae5-part1";
# cspell:enable
}; };
}; };
zfs.extraPools = [
"media"
"scratch"
"storage"
];
kernelModules = [ "kvm-amd" ]; kernelModules = [ "kvm-amd" ];
extraModulePackages = [ ]; extraModulePackages = [ ];
}; };
@@ -116,8 +122,8 @@ in
fsType = "zfs"; fsType = "zfs";
}; };
"/nix" = { "/nix" =
device = "root_pool/nix"; { device = "root_pool/nix";
fsType = "zfs"; fsType = "zfs";
}; };

View File

@@ -0,0 +1,49 @@
{
services.home-assistant = {
enable = true;
openFirewall = true;
config = {
http = {
server_port = 8123;
server_host = [
"192.168.95.14"
"192.168.90.40"
"192.168.98.4"
];
use_x_forwarded_for = true;
trusted_proxies = "172.100.0.4";
};
homeassistant = {
time_zone = "America/New_York";
unit_system = "imperial";
temperature_unit = "F";
};
assist_pipeline = { };
backup = { };
bluetooth = { };
config = { };
dhcp = { };
energy = { };
history = { };
homeassistant_alerts = { };
image_upload = { };
logbook = { };
media_source = { };
mobile_app = { };
ssdp = { };
sun = { };
webhook = { };
zeroconf = { };
};
extraPackages =
python3Packages: with python3Packages; [
psycopg2
gtts
aioesphomeapi
esphome-dashboard-api
bleak-esphome
pymetno
];
extraComponents = [ "isal" ];
};
}

View File

@@ -7,12 +7,24 @@
}; };
systemd.network = { systemd.network = {
enable = true; enable = true;
netdevs = {
"20-ioit-vlan" = {
netdevConfig = {
Kind = "vlan";
Name = "ioit-vlan";
};
vlanConfig.Id = 20;
};
};
networks = { networks = {
"10-1GB_Primary" = { "10-1GB_Primary" = {
matchConfig.Name = "enp98s0f0"; matchConfig.Name = "enp98s0f0";
address = [ "192.168.99.14/24" ]; DHCP = "yes";
routes = [ { Gateway = "192.168.99.1"; } ]; vlan = [ "ioit-vlan" ];
linkConfig.RequiredForOnline = "routable"; linkConfig.RequiredForOnline = "routable";
}; };
"10-1GB_Secondary" = { "10-1GB_Secondary" = {
@@ -28,6 +40,15 @@
matchConfig.Name = "enp97s0f1np1"; matchConfig.Name = "enp97s0f1np1";
DHCP = "yes"; DHCP = "yes";
}; };
"40-ioit-vlan" = {
matchConfig.Name = "ioit-vlan";
DHCP = "yes";
};
}; };
}; };
services.zerotierone = {
enable = true;
joinNetworks = [ "e4da7455b2ae64ca" ];
};
} }

View File

@@ -1,16 +0,0 @@
{ config, ... }:
{
nixpkgs.config.cudaSupport = true;
services.xserver.videoDrivers = [ "nvidia" ];
hardware = {
nvidia = {
modesetting.enable = true;
powerManagement.enable = true;
package = config.boot.kernelPackages.nvidiaPackages.beta;
nvidiaSettings = true;
open = false;
};
nvidia-container-toolkit.enable = true;
};
}

View File

@@ -1,26 +0,0 @@
{ pkgs, ... }:
{
imports = [ ./nix_builder.nix ];
users = {
users.github-runners = {
shell = pkgs.bash;
isSystemUser = true;
group = "github-runners";
uid = 601;
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA/S8i+BNX/12JNKg+5EKGX7Aqimt5KM+ve3wt/SyWuO github-runners" # cspell:disable-line
];
};
groups.github-runners.gid = 601;
};
services.nix_builder.containers = {
nix-builder-0.enable = true;
nix-builder-1.enable = true;
nix-builder-2.enable = true;
nix-builder-3.enable = true;
nix-builder-4.enable = true;
nix-builder-5.enable = true;
};
}

View File

@@ -1,101 +0,0 @@
{ config, lib, ... }:
with lib;
let
vars = import ../vars.nix;
in
{
options.services.nix_builder.containers = mkOption {
type = types.attrsOf (
types.submodule (
{ name, ... }:
{
options.enable = mkEnableOption "GitHub runner container";
}
)
);
default = { };
description = "GitHub runner container configurations";
};
config.containers = mapAttrs (
name: cfg:
mkIf cfg.enable {
autoStart = true;
bindMounts = {
"/storage" = {
mountPoint = "/zfs/media/github-runners/${name}";
isReadOnly = false;
};
"/secrets".mountPoint = "${vars.secrets}/services/github-runners/${name}";
"ssh-keys".mountPoint = "${vars.secrets}/services/github-runners/id_ed25519_github-runners";
};
config =
{
config,
pkgs,
lib,
...
}:
{
nix.settings = {
trusted-substituters = [
"https://cache.nixos.org"
"https://cache.tmmworkshop.com"
"https://nix-community.cachix.org"
];
substituters = [
"https://cache.nixos.org/?priority=2&want-mass-query=true"
"https://cache.tmmworkshop.com/?priority=2&want-mass-query=true"
"https://nix-community.cachix.org/?priority=10&want-mass-query=true"
];
trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"cache.tmmworkshop.com:jHffkpgbmEdstQPoihJPYW9TQe6jnQbWR2LqkNGV3iA="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
];
experimental-features = [
"flakes"
"nix-command"
];
};
programs.ssh.extraConfig = ''
Host jeeves
Port 629
User github-runners
HostName 192.168.99.14
IdentityFile ${vars.secrets}/services/github-runners/id_ed25519_github-runners
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
'';
services.github-runners.${name} = {
enable = true;
replace = true;
workDir = "/zfs/media/github-runners/${name}";
url = "https://github.com/RichieCahill/dotfiles";
extraLabels = [ "nixos" ];
tokenFile = "${vars.secrets}/services/github-runners/${name}";
user = "github-runners";
group = "github-runners";
extraPackages = with pkgs; [
nixfmt-rfc-style
nixos-rebuild
openssh
treefmt
];
};
users = {
users.github-runners = {
shell = pkgs.bash;
isSystemUser = true;
group = "github-runners";
uid = 601;
};
groups.github-runners.gid = 601;
};
system.stateVersion = "24.11";
};
}
) config.services.nix_builder.containers;
}

View File

@@ -3,31 +3,28 @@
# zpools # zpools
# media # media
sudo zpool create -o ashift=12 -O acltype=posixacl -O atime=off -O dnodesize=auto -O xattr=sa -O compression=zstd -m /zfs/media media mirror sudo zpool create -o ashift=12 -O acltype=posixacl -O atime=off -O dnodesize=auto -O xattr=sa -O zstd -m /zfs/media media mirror
sudo zpool add media -o ashift=12 special mirror sudo zpool add media -o ashift=12 special mirror
# storage # storage
sudo zpool create -o ashift=12 -O acltype=posixacl -O atime=off -O dnodesize=auto -O xattr=sa -O compression=zstd -m /zfs/storage storage sudo zpool create -o ashift=12 -O acltype=posixacl -O atime=off -O dnodesize=auto -O xattr=sa -O zstd -m /zfs/storage storage
sudo zpool add storage -o ashift=12 special mirror sudo zpool add storage -o ashift=12 special mirror
sudo zpool add storage -o ashift=12 logs mirror sudo zpool add storage -o ashift=12 logs mirror
# scratch # torrenting
sudo zpool create -o ashift=12 -O acltype=posixacl -O atime=off -O dnodesize=auto -O xattr=sa -O compression=zstd -m /zfs/scratch scratch sudo zpool create -o ashift=12 -O acltype=posixacl -O atime=off -O dnodesize=auto -O xattr=sa -O zstd -m /zfs/torrenting torrenting
sudo zpool add torrenting -o ashift=12 special
# media datasets # media datasets
sudo zfs create -o compression=zstd-9 media/docker sudo zfs create -o compression=zstd-9 media/docker
sudo zfs create -o compression=zstd-9 -o sync=disabled media/github-runners sudo zfs create -o recordsize=1M -o compression=zstd-19 media/library
sudo zfs create -o exec=off media/minio
sudo zfs create -o exec=off media/mirror
sudo zfs create -o copies=3 media/notes sudo zfs create -o copies=3 media/notes
sudo zfs create -o recordsize=16k -o primarycache=metadata -o mountpoint=/zfs/media/database/photoprism_mariadb media/photoprism_mariadb
sudo zfs create -o compression=zstd-9 media/plex sudo zfs create -o compression=zstd-9 media/plex
sudo zfs create -o compression=zstd-9 media/services
sudo zfs create -o compression=zstd-19 media/home_assistant
sudo zfs create -o exec=off media/share
sudo zfs create -o recordsize=16k -o primarycache=metadata -o mountpoint=/zfs/media/database/postgres media/postgres sudo zfs create -o recordsize=16k -o primarycache=metadata -o mountpoint=/zfs/media/database/postgres media/postgres
# scratch datasets
sudo zfs create -o recordsize=16k -o sync=disabled scratch/qbitvpn
sudo zfs create -o recordsize=16k -o sync=disabled scratch/transmission
# storage datasets # storage datasets
sudo zfs create -o recordsize=1M -o compression=zstd-19 storage/archive sudo zfs create -o recordsize=1M -o compression=zstd-19 storage/archive
sudo zfs create -o compression=zstd-19 storage/main sudo zfs create -o compression=zstd-19 storage/main
@@ -35,6 +32,7 @@ sudo zfs create -o recordsize=16K -o compression=zstd-19 -o copies=2 storage/pho
sudo zfs create -o recordsize=1M -o compression=zstd-19 storage/plex sudo zfs create -o recordsize=1M -o compression=zstd-19 storage/plex
sudo zfs create -o compression=zstd-19 -o copies=3 storage/secrets sudo zfs create -o compression=zstd-19 -o copies=3 storage/secrets
sudo zfs create -o compression=zstd-19 storage/syncthing sudo zfs create -o compression=zstd-19 storage/syncthing
sudo zfs create -o recordsize=1M -o compression=zstd-9 -o exec=off -o sync=disabled storage/qbitvpn
sudo zfs create -o recordsize=1M -o compression=zstd-9 -o exec=off -o sync=disabled storage/transmission # torrenting datasets
sudo zfs create -o recordsize=1M -o compression=zstd-19 storage/library sudo zfs create -o recordsize=16K -o exec=off -o sync=disabled torrenting/qbit
sudo zfs create -o recordsize=16K -o exec=off -o sync=disabled torrenting/qbitvpn

View File

@@ -4,7 +4,7 @@
... ...
}: }:
let let
vars = import ../vars.nix; vars = import ./vars.nix;
in in
{ {
systemd = { systemd = {
@@ -13,7 +13,7 @@ in
description = "maintains /zfs/storage/plex permissions"; description = "maintains /zfs/storage/plex permissions";
serviceConfig = { serviceConfig = {
Type = "oneshot"; Type = "oneshot";
ExecStart = "${pkgs.bash}/bin/bash ${../scripts/plex_permission.sh}"; ExecStart = "${pkgs.bash}/bin/bash ${./scripts/plex_permission.sh}";
}; };
}; };
startup_validation = { startup_validation = {
@@ -23,9 +23,9 @@ in
description = "validates startup"; description = "validates startup";
path = [ pkgs.zfs ]; path = [ pkgs.zfs ];
serviceConfig = { serviceConfig = {
EnvironmentFile = "${vars.secrets}/services/server-validation"; EnvironmentFile = "${vars.storage_secrets}/services/server-validation";
Type = "oneshot"; Type = "oneshot";
ExecStart = "${inputs.system_tools.packages.x86_64-linux.default}/bin/validate_system --config-file='${./validate_system.toml}'"; ExecStart = "${inputs.system_tools.packages.x86_64-linux.default}/bin/validate_jeeves";
}; };
}; };
}; };

View File

@@ -1,10 +0,0 @@
{ lib, ... }:
let
vars = import ../vars.nix;
in
{
services.audiobookshelf.enable = true;
systemd.services.audiobookshelf.serviceConfig.WorkingDirectory =
lib.mkForce "${vars.docker_configs}/audiobookshelf";
users.users.audiobookshelf.home = lib.mkForce "${vars.docker_configs}/audiobookshelf";
}

View File

@@ -1,17 +0,0 @@
{ pkgs, ... }:
let
vars = import ../vars.nix;
in
{
systemd.services.cloud_flare_tunnel = {
description = "cloud_flare_tunnel proxy's traffic through cloudflare";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
EnvironmentFile = "${vars.secrets}/docker/cloud_flare_tunnel";
ExecStart = "${pkgs.cloudflared}/bin/cloudflared --no-autoupdate tunnel run";
Restart = "on-failure";
};
};
}

View File

@@ -1,9 +0,0 @@
{ lib, ... }:
{
imports =
let
files = builtins.attrNames (builtins.readDir ./.);
nixFiles = builtins.filter (name: lib.hasSuffix ".nix" name && name != "default.nix") files;
in
map (file: ./. + "/${file}") nixFiles;
}

View File

@@ -1,21 +0,0 @@
{
pkgs,
...
}:
let
vars = import ../vars.nix;
in
{
systemd.services.filebrowser = {
description = "filebrowser";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
User = "richie";
Group = "users";
ExecStart = "${pkgs.filebrowser}/bin/filebrowser --root=/zfs --address=0.0.0.0 --database=${vars.docker_configs}/filebrowser/filebrowser.db";
Restart = "on-failure";
};
};
}

View File

@@ -1,11 +0,0 @@
{
networking.firewall.allowedTCPPorts = [
80
443
];
services.haproxy = {
enable = true;
config = builtins.readFile ./haproxy.cfg;
};
}

View File

@@ -1,103 +0,0 @@
let
vars = import ../vars.nix;
in
{
users = {
users.hass = {
isSystemUser = true;
group = "hass";
};
groups.hass = { };
};
services = {
home-assistant = {
enable = true;
openFirewall = true;
configDir = vars.home_assistant;
config = {
http = {
server_port = 8123;
server_host = [
"192.168.99.14"
"192.168.90.40"
"127.0.0.1"
];
use_x_forwarded_for = true;
trusted_proxies = "127.0.0.1";
};
homeassistant = {
time_zone = "America/New_York";
unit_system = "us_customary";
temperature_unit = "F";
};
recorder = {
db_url = "postgresql://@/hass";
auto_purge = true;
purge_keep_days = 3650;
db_retry_wait = 15;
};
assist_pipeline = { };
backup = { };
bluetooth = { };
config = { };
dhcp = { };
energy = { };
history = { };
homeassistant_alerts = { };
image_upload = { };
logbook = { };
media_source = { };
mobile_app = { };
ssdp = { };
sun = { };
webhook = { };
zeroconf = { };
automation = "!include automations.yaml";
script = "!include scripts.yaml";
scene = "!include scenes.yaml";
group = "!include groups.yaml";
};
extraPackages =
python3Packages: with python3Packages; [
aioesphomeapi
aiounifi
bleak-esphome
esphome-dashboard-api
gtts
jellyfin-apiclient-python
psycopg2
pymetno
pyownet
rokuecp
uiprotect
wakeonlan
wyoming
];
extraComponents = [ "isal" ];
};
esphome = {
enable = true;
openFirewall = true;
address = "192.168.90.40";
};
wyoming = {
faster-whisper.servers.main = {
enable = true;
uri = "tcp://0.0.0.0:10300";
model = "medium.en";
language = "en";
device = "cuda";
};
piper.servers.main = {
enable = true;
uri = "tcp://0.0.0.0:10200";
voice = "en_GB-alba-medium";
};
openwakeword = {
enable = true;
uri = "tcp://0.0.0.0:10400";
};
};
};
}

View File

@@ -1,10 +0,0 @@
let
vars = import ../vars.nix;
in
{
services.jellyfin = {
enable = true;
openFirewall = true;
dataDir = "${vars.services}/jellyfin";
};
}

View File

@@ -1,10 +0,0 @@
let
vars = import ../vars.nix;
in
{
services.nix-serve = {
enable = true;
secretKeyFile = "${vars.secrets}/services/nix-cache/cache-priv-key.pem";
openFirewall = true;
};
}

View File

@@ -1,192 +0,0 @@
{ pkgs, ... }:
let
vars = import ../vars.nix;
in
{
networking.firewall.allowedTCPPorts = [ 5432 ];
services.postgresql = {
enable = true;
package = pkgs.postgresql_17_jit;
enableTCPIP = true;
enableJIT = true;
dataDir = "${vars.database}/postgres";
authentication = pkgs.lib.mkOverride 10 ''
# admins
local all postgres trust
host all postgres 127.0.0.1/32 trust
host all postgres ::1/128 trust
local all richie trust
host all richie 127.0.0.1/32 trust
host all richie ::1/128 trust
host all richie 192.168.90.1/24 trust
host all richie 192.168.99.1/24 trust
#type database DBuser origin-address auth-method
local hass hass trust
# ipv4
host hass hass 192.168.90.1/24 trust
host hass hass 127.0.0.1/32 trust
# ipv6
host hass hass ::1/128 trust
# megan
host megan megan 192.168.90.1/24 trust
host megan megan 127.0.0.1/32 trust
host gcw megan 192.168.90.1/24 trust
host gcw megan 127.0.0.1/32 trust
# gcw
local gcw gcw trust
host gcw gcw 192.168.90.1/24 trust
host gcw gcw 127.0.0.1/32 trust
'';
identMap = ''
# ArbitraryMapName systemUser DBUser
superuser_map root postgres
superuser_map postgres postgres
# Let other names login as themselves
superuser_map richie postgres
superuser_map hass hass
'';
ensureUsers = [
{
name = "postgres";
ensureClauses = {
superuser = true;
login = true;
createrole = true;
createdb = true;
replication = true;
};
}
{
name = "richie";
ensureDBOwnership = true;
ensureClauses = {
superuser = true;
login = true;
createrole = true;
createdb = true;
replication = true;
};
}
{
name = "hass";
ensureDBOwnership = true;
ensureClauses = {
login = true;
createrole = true;
createdb = true;
replication = true;
};
}
{
name = "megan";
ensureDBOwnership = true;
ensureClauses = {
login = true;
createrole = true;
createdb = true;
replication = true;
};
}
{
name = "gcw";
ensureDBOwnership = true;
ensureClauses = {
login = true;
createrole = true;
createdb = true;
replication = true;
};
}
];
ensureDatabases = [
"gcw"
"hass"
"megan"
"mxr_dev"
"mxr_prod"
"richie"
];
# Thank you NotAShelf
# https://github.com/NotAShelf/nyx/blob/d407b4d6e5ab7f60350af61a3d73a62a5e9ac660/modules/core/roles/server/system/services/databases/postgresql.nix#L74
settings = {
# Connectivity;
max_connections = 100;
superuser_reserved_connections = 3;
# Memory Settings;
shared_buffers = "1024 MB";
work_mem = "32 MB";
maintenance_work_mem = "320 MB";
huge_pages = "off";
effective_cache_size = "2 GB";
effective_io_concurrency = 100; # concurrent IO only really activated if OS supports posix_fadvise function;
random_page_cost = 1.25; # speed of random disk access relative to sequential access (1.0);
# Monitoring;
shared_preload_libraries = "pg_stat_statements,auto_explain"; # per statement resource usage stats & log explain statements for slow queries
track_io_timing = "on"; # measure exact block IO times;
track_functions = "pl"; # track execution times of pl-language procedures if any;
# Replication;
wal_level = "replica"; # consider using at least "replica";
max_wal_senders = 0;
synchronous_commit = "on";
# Checkpointing: ;
checkpoint_timeout = "15 min";
checkpoint_completion_target = 0.9;
max_wal_size = "1024 MB";
min_wal_size = "512 MB";
# WAL writing;
wal_compression = "on";
wal_buffers = -1; # auto-tuned by Postgres till maximum of segment size (16MB by default);
wal_writer_delay = "200ms";
wal_writer_flush_after = "1MB";
# Background writer;
bgwriter_delay = "200ms";
bgwriter_lru_maxpages = 100;
bgwriter_lru_multiplier = 2.0;
bgwriter_flush_after = 0;
# Parallel queries: ;
max_worker_processes = 6;
max_parallel_workers_per_gather = 3;
max_parallel_maintenance_workers = 3;
max_parallel_workers = 6;
parallel_leader_participation = "on";
# Advanced features ;
enable_partitionwise_join = "on";
enable_partitionwise_aggregate = "on";
jit = "on";
jit_above_cost = 100000;
jit_inline_above_cost = 150000;
jit_optimize_above_cost = 500000;
# log slow queries
log_min_duration_statement = 100;
"auto_explain.log_min_duration" = 100;
# logging configuration
log_connections = true;
log_statement = "all";
logging_collector = true;
log_disconnections = true;
};
};
}

View File

@@ -1,32 +0,0 @@
{ pkgs, ... }:
let
vars = import ../vars.nix;
in
{
services.transmission = {
enable = true;
package = pkgs.transmission_4;
webHome = pkgs.flood-for-transmission;
home = "${vars.services}/transmission";
openPeerPorts = true;
openRPCPort = true;
downloadDirPermissions = "770";
settings = {
bind-address-ipv4 = "192.168.99.14";
cache-size-mb = 0;
download-dir = "${vars.transmission}/complete";
download-queue-enabled = false;
incomplete-dir = "${vars.transmission_scratch}/incomplete";
incomplete-dir-enabled = true;
message-level = 3;
peer-port = 51413;
rpc-bind-address = "0.0.0.0";
rpc-host-whitelist = "127.0.0.1,192.168.90.40";
rpc-host-whitelist-enabled = true;
rpc-port = 9091;
rpc-whitelist-enabled = true;
rpc-whitelist = "127.0.0.1,192.168.90.49";
seed-queue-enabled = false;
};
};
}

View File

@@ -1,11 +0,0 @@
zpool = ["root_pool", "storage", "media"]
services = [
"audiobookshelf",
"cloud_flare_tunnel",
"haproxy",
"docker-qbitvpn",
"docker",
"filebrowser",
"home-assistant",
"jellyfin",
]

View File

@@ -2,128 +2,61 @@ let
vars = import ./vars.nix; vars = import ./vars.nix;
in in
{ {
networking.firewall.allowedTCPPorts = [ 8384 ];
services.syncthing = { services.syncthing = {
overrideFolders = false;
guiAddress = "192.168.90.40:8384"; guiAddress = "192.168.90.40:8384";
settings = { settings.folders = {
devices.davids-server.id = "7GXTDGR-AOXFW2O-K6J7NM3-XYZNRRW-AKHAFWM-GBOWUPQ-OA6JIWD-ER7RDQL"; # cspell:disable-line "bob_temp" = {
folders = { path = "${vars.storage_syncthing}/bob_temp";
"dotfiles" = { devices = [
path = "/home/richie/dotfiles"; "jeeves"
devices = [ ];
"bob" fsWatcherEnabled = true;
"rhapsody-in-green" };
]; "notes" = {
fsWatcherEnabled = true; id = "l62ul-lpweo"; # cspell:disable-line
}; path = vars.media_notes;
"notes" = { devices = [
id = "l62ul-lpweo"; # cspell:disable-line "bob"
path = vars.notes; "rhapsody-in-green"
devices = [ ];
"rhapsody-in-green" fsWatcherEnabled = true;
"davids-server" };
]; "important" = {
fsWatcherEnabled = true; id = "4ckma-gtshs"; # cspell:disable-line
}; path = "${vars.storage_syncthing}/important";
"important" = { devices = [
id = "4ckma-gtshs"; # cspell:disable-line "bob"
path = "${vars.syncthing}/important"; "rhapsody-in-green"
devices = [ "phone"
"bob" ];
"rhapsody-in-green" fsWatcherEnabled = true;
"phone" };
]; "music" = {
fsWatcherEnabled = true; id = "vprc5-3azqc"; # cspell:disable-line
}; path = "${vars.storage_syncthing}/music";
"music" = { devices = [
id = "vprc5-3azqc"; # cspell:disable-line "bob"
path = "${vars.syncthing}/music"; "rhapsody-in-green"
devices = [ "ipad"
"bob" "phone"
"rhapsody-in-green" ];
"ipad" fsWatcherEnabled = true;
"phone" };
]; "projects" = {
fsWatcherEnabled = true; id = "vyma6-lqqrz"; # cspell:disable-line
}; path = "${vars.storage_syncthing}/projects";
"projects" = { devices = [
id = "vyma6-lqqrz"; # cspell:disable-line "bob"
path = "${vars.syncthing}/projects"; "rhapsody-in-green"
devices = [ ];
"rhapsody-in-green" fsWatcherEnabled = true;
]; };
fsWatcherEnabled = true; "rhapsody-in-green_temp" = {
}; path = "${vars.storage_syncthing}/rhapsody-in-green_temp";
"rhapsody-in-green_temp" = { devices = [
path = "${vars.syncthing}/rhapsody-in-green_temp"; "rhapsody-in-green"
devices = [ ];
"rhapsody-in-green" fsWatcherEnabled = true;
];
fsWatcherEnabled = true;
};
"vault" = {
path = "/home/richie/vault";
devices = [
"rhapsody-in-green"
"davids-server"
];
fsWatcherEnabled = true;
};
"backup" = {
path = "${vars.syncthing}/backup";
devices = [
"davids-server"
];
fsWatcherEnabled = true;
};
#
"davids-backup1" = {
id = "8229p-8z3tm"; # cspell:disable-line
path = "${vars.syncthing}/davids_backups/1";
devices = [
"davids-server"
];
fsWatcherEnabled = true;
type = "receiveencrypted";
};
"davids-backup2" = {
id = "iciw3-dp6ao"; # cspell:disable-line
path = "${vars.syncthing}/davids_backups/2";
devices = [
"davids-server"
];
fsWatcherEnabled = true;
type = "receiveencrypted";
};
"davids-backup3" = {
id = "9si6m-bnkjb"; # cspell:disable-line
path = "${vars.syncthing}/davids_backups/3";
devices = [
"davids-server"
];
fsWatcherEnabled = true;
type = "receiveencrypted";
};
"davids-backup4" = {
id = "qjyfy-uupj4"; # cspell:disable-line
path = "${vars.syncthing}/davids_backups/4";
devices = [
"davids-server"
];
fsWatcherEnabled = true;
type = "receiveencrypted";
};
"davids-backup5" = {
id = "fm4h5-emsu2"; # cspell:disable-line
path = "${vars.syncthing}/davids_backups/5";
devices = [
"davids-server"
];
fsWatcherEnabled = true;
type = "receiveencrypted";
};
}; };
}; };
}; };

View File

@@ -1,21 +1,25 @@
let let
zfs_media = "/zfs/media"; zfs_media = "/zfs/media";
zfs_storage = "/zfs/storage"; zfs_storage = "/zfs/storage";
zfs_scratch = "/zfs/scratch"; zfs_torrenting = "/zfs/torrenting";
in in
{ {
inherit zfs_media zfs_storage zfs_scratch; inherit zfs_media zfs_storage zfs_torrenting;
database = "${zfs_media}/database"; # media
docker = "${zfs_media}/docker"; media_database = "${zfs_media}/database";
docker_configs = "${zfs_media}/docker/configs"; media_docker = "${zfs_media}/docker";
home_assistant = "${zfs_media}/home_assistant"; media_docker_configs = "${zfs_media}/docker/configs";
notes = "${zfs_media}/notes"; media_mirror = "${zfs_media}/mirror";
qbitvpn = "${zfs_storage}/qbitvpn"; media_notes = "${zfs_media}/notes";
qbitvpn_scratch = "${zfs_scratch}/qbitvpn"; media_plex = "${zfs_media}/plex";
secrets = "${zfs_storage}/secrets"; # storage
services = "${zfs_media}/services"; storage_main = "${zfs_storage}/main";
share = "${zfs_media}/share"; storage_photos = "${zfs_storage}/photos";
syncthing = "${zfs_storage}/syncthing"; storage_plex = "${zfs_storage}/plex";
transmission = "${zfs_storage}/transmission"; storage_secrets = "${zfs_storage}/secrets";
transmission_scratch = "${zfs_scratch}/transmission"; storage_syncthing = "${zfs_storage}/syncthing";
storage_library = "${zfs_storage}/library";
# torrenting
torrenting_qbit = "${zfs_torrenting}/qbit";
torrenting_qbitvpn = "${zfs_torrenting}/qbitvpn";
} }

View File

@@ -4,8 +4,6 @@
../../users/richie ../../users/richie
../../common/global ../../common/global
../../common/optional/desktop.nix ../../common/optional/desktop.nix
../../common/optional/docker.nix
../../common/optional/steam.nix
../../common/optional/syncthing_base.nix ../../common/optional/syncthing_base.nix
../../common/optional/systemd-boot.nix ../../common/optional/systemd-boot.nix
../../common/optional/yubikey.nix ../../common/optional/yubikey.nix
@@ -22,8 +20,37 @@
networkmanager.enable = true; networkmanager.enable = true;
}; };
hardware = {
pulseaudio.enable = false;
bluetooth = {
enable = true;
powerOnBoot = true;
};
};
security.rtkit.enable = true;
services = { services = {
displayManager.sddm.enable = true;
openssh.ports = [ 922 ]; openssh.ports = [ 922 ];
printing.enable = true;
pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
};
snapshot_manager.enable = true;
zfs = {
trim.enable = true;
autoScrub.enable = true;
};
}; };
system.stateVersion = "24.05"; system.stateVersion = "24.05";

View File

@@ -1,9 +1,4 @@
{ { config, lib, modulesPath, ... }:
config,
lib,
modulesPath,
...
}:
{ {
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];

View File

@@ -1,17 +1,10 @@
{ {
services.syncthing.settings.folders = { services.syncthing.settings.folders = {
"dotfiles" = {
path = "/home/richie/dotfiles";
devices = [
"jeeves"
"bob"
];
fsWatcherEnabled = true;
};
"notes" = { "notes" = {
id = "l62ul-lpweo"; # cspell:disable-line id = "l62ul-lpweo"; # cspell:disable-line
path = "/home/richie/notes"; path = "/home/richie/notes";
devices = [ devices = [
"bob"
"jeeves" "jeeves"
]; ];
fsWatcherEnabled = true; fsWatcherEnabled = true;
@@ -41,6 +34,7 @@
id = "vyma6-lqqrz"; # cspell:disable-line id = "vyma6-lqqrz"; # cspell:disable-line
path = "/home/richie/projects"; path = "/home/richie/projects";
devices = [ devices = [
"bob"
"jeeves" "jeeves"
]; ];
fsWatcherEnabled = true; fsWatcherEnabled = true;
@@ -56,7 +50,7 @@
"vault" = { "vault" = {
path = "/home/richie/vault"; path = "/home/richie/vault";
devices = [ devices = [
"jeeves" "bob"
]; ];
fsWatcherEnabled = true; fsWatcherEnabled = true;
}; };

147
systems/router/default.nix Normal file
View File

@@ -0,0 +1,147 @@
# https://github.com/ghostbuster91/blogposts/blob/a2374f0039f8cdf4faddeaaa0347661ffc2ec7cf/router2023-part2/main.md
# https://francis.begyn.be/blog/nixos-home-router
{
imports = [
../../users/richie
../../common/global
../../common/optional/zerotier.nix
./docker
./hardware.nix
];
boot.kernel = {
sysctl = {
"net.ipv4.conf.all.forwarding" = true;
"net.ipv6.conf.all.forwarding" = false;
};
};
systemd.network = {
wait-online.anyInterface = true;
networks = {
"30-lan0" = {
matchConfig.Name = "lan0";
linkConfig.RequiredForOnline = "enslaved";
networkConfig = {
ConfigureWithoutCarrier = true;
};
};
# lan1 and lan2 look analogical
"30-lan3" = {
matchConfig.Name = "lan3";
linkConfig.RequiredForOnline = "enslaved";
networkConfig = {
ConfigureWithoutCarrier = true;
};
};
"10-wan" = {
matchConfig.Name = "wan";
networkConfig = {
# start a DHCP Client for IPv4 Addressing/Routing
DHCP = "ipv4";
DNSOverTLS = true;
DNSSEC = true;
IPv6PrivacyExtensions = false;
IPForward = true;
};
# make routing on this interface a dependency for network-online.target
linkConfig.RequiredForOnline = "routable";
};
};
};
networking = {
hostName = "surfer";
useNetworkd = true;
useDHCP = false;
# No local firewall.
nat.enable = false;
firewall.enable = false;
nftables = {
enable = true;
ruleset = ''
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
iifname { "br-lan" } accept comment "Allow local network to access the router"
iifname "wan" ct state { established, related } accept comment "Allow established traffic"
iifname "wan" icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP"
iifname "wan" counter drop comment "Drop all other unsolicited traffic from wan"
iifname "lo" accept comment "Accept everything from loopback interface"
}
chain forward {
type filter hook forward priority filter; policy drop;
iifname { "br-lan" } oifname { "wan" } accept comment "Allow trusted LAN to WAN"
iifname { "wan" } oifname { "br-lan" } ct state { established, related } accept comment "Allow established back to LANs"
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority 100; policy accept;
oifname "wan" masquerade
}
}
'';
};
};
services.dnsmasq = {
enable = true;
settings = {
# upstream DNS servers
server = [ "9.9.9.9" "8.8.8.8" "1.1.1.1" ];
# sensible behaviours
domain-needed = true;
bogus-priv = true;
no-resolv = true;
# Cache dns queries.
cache-size = 1000;
dhcp-range = [ "br-lan,192.168.10.50,192.168.10.254,24h" ];
interface = "br-lan";
dhcp-host = "192.168.10.1";
# local domains
local = "/lan/";
domain = "lan";
expand-hosts = true;
# don't use /etc/hosts as this would advertise surfer as localhost
no-hosts = true;
address = "/surfer.lan/192.168.10.1";
};
};
boot.kernel = {
sysctl = {
"net.ipv4.conf.default.rp_filter" = 1;
"net.ipv4.conf.wan.rp_filter" = 1;
"net.ipv4.conf.br-lan.rp_filter" = 0;
};
};
services = {
openssh.ports = [ 629 ];
smartd.enable = true;
snapshot_manager = {
enable = true;
path = ./snapshot_config.toml;
};
sysstat.enable = true;
zfs = {
trim.enable = true;
autoScrub.enable = true;
};
};
system.stateVersion = "24.05";
}

View File

@@ -0,0 +1,67 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
modulesPath,
...
}:
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
boot = {
initrd = {
availableKernelModules = [
"nvme"
"xhci_pci"
"ahci"
"usbhid"
"usb_storage"
"sd_mod"
];
kernelModules = [ ];
luks.devices."luks-root-pool-nvme-Samsung_SSD_990_PRO_with_Heatsink_1TB_S73JNJ0X114418B-part2" = {
device = "/dev/disk/by-id/nvme-Samsung_SSD_990_PRO_with_Heatsink_1TB_S73JNJ0X114418B-part2";
bypassWorkqueues = true;
allowDiscards = true;
};
};
kernelModules = [ "kvm-amd" ];
extraModulePackages = [ ];
};
fileSystems = {
"/" = lib.mkDefault {
device = "root_pool/root";
fsType = "zfs";
};
"/home" = {
device = "root_pool/home";
fsType = "zfs";
};
"/var" = {
device = "root_pool/var";
fsType = "zfs";
};
"/boot" = {
device = "/dev/disk/by-uuid/609D-FF29";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
};
swapDevices = [ ];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View File

@@ -1,682 +0,0 @@
"""Install NixOS on a ZFS pool."""
from __future__ import annotations
import curses
import logging
import sys
from collections import defaultdict
from os import getenv
from pathlib import Path
from random import getrandbits
from subprocess import PIPE, Popen, run
from time import sleep
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Sequence
def configure_logger(level: str = "INFO") -> None:
"""Configure the logger.
Args:
level (str, optional): The logging level. Defaults to "INFO".
"""
logging.basicConfig(
level=level,
datefmt="%Y-%m-%dT%H:%M:%S%z",
format="%(asctime)s %(levelname)s %(filename)s:%(lineno)d - %(message)s",
handlers=[logging.StreamHandler(sys.stdout)],
)
def bash_wrapper(command: str) -> str:
"""Execute a bash command and capture the output.
Args:
command (str): The bash command to be executed.
Returns:
Tuple[str, int]: A tuple containing the output of the command (stdout) as a string,
the error output (stderr) as a string (optional), and the return code as an integer.
"""
logging.debug(f"running {command=}")
# This is a acceptable risk
process = Popen(command.split(), stdout=PIPE, stderr=PIPE) # noqa: S603
output, _ = process.communicate()
if process.returncode != 0:
error = f"Failed to run command {command=} return code {process.returncode=}"
raise RuntimeError(error)
return output.decode()
def partition_disk(disk: str, swap_size: int, reserve: int = 0) -> None:
"""Partition a disk.
Args:
disk (str): The disk to partition.
swap_size (int): The size of the swap partition in GB.
minimum value is 1.
reserve (int, optional): The size of the reserve partition in GB. Defaults to 0.
minimum value is 0.
"""
logging.info(f"partitioning {disk=}")
swap_size = max(swap_size, 1)
reserve = max(reserve, 0)
bash_wrapper(f"blkdiscard -f {disk}")
if reserve > 0:
msg = f"Creating swap partition on {disk=} with size {swap_size=}GiB and reserve {reserve=}GiB"
logging.info(msg)
swap_start = swap_size + reserve
swap_partition = f"mkpart swap -{swap_start}GiB -{reserve}GiB "
else:
logging.info(f"Creating swap partition on {disk=} with size {swap_size=}GiB")
swap_start = swap_size
swap_partition = f"mkpart swap -{swap_start}GiB 100% "
logging.debug(f"{swap_partition=}")
create_partitions = (
f"parted --script --align=optimal {disk} -- "
"mklabel gpt "
"mkpart EFI 1MiB 4GiB "
f"mkpart root_pool 4GiB -{swap_start}GiB "
f"{swap_partition}"
"set 1 esp on"
)
bash_wrapper(create_partitions)
logging.info(f"{disk=} successfully partitioned")
def create_zfs_pool(pool_disks: Sequence[str], mnt_dir: str) -> None:
"""Create a ZFS pool.
Args:
disks (Sequence[str]): A tuple of disks to use for the pool.
mnt_dir (str): The mount directory.
"""
if len(pool_disks) <= 0:
error = "disks must be a tuple of at least length 1"
raise ValueError(error)
zpool_create = (
"zpool create "
"-o ashift=12 "
"-o autotrim=on "
f"-R {mnt_dir} "
"-O acltype=posixacl "
"-O canmount=off "
"-O dnodesize=auto "
"-O normalization=formD "
"-O relatime=on "
"-O xattr=sa "
"-O mountpoint=legacy "
"-O compression=zstd "
"-O atime=off "
"root_pool "
)
if len(pool_disks) == 1:
zpool_create += pool_disks[0]
else:
zpool_create += "mirror "
zpool_create += " ".join(pool_disks)
bash_wrapper(zpool_create)
zpools = bash_wrapper("zpool list -o name")
if "root_pool" not in zpools.splitlines():
logging.critical("Failed to create root_pool")
sys.exit(1)
def create_zfs_datasets() -> None:
"""Create ZFS datasets."""
bash_wrapper("zfs create -o canmount=noauto -o reservation=10G root_pool/root")
bash_wrapper("zfs create root_pool/home")
bash_wrapper("zfs create root_pool/var -o reservation=1G")
bash_wrapper("zfs create -o compression=zstd-9 -o reservation=10G root_pool/nix")
datasets = bash_wrapper("zfs list -o name")
expected_datasets = {
"root_pool/root",
"root_pool/home",
"root_pool/var",
"root_pool/nix",
}
missing_datasets = expected_datasets.difference(datasets.splitlines())
if missing_datasets:
logging.critical(f"Failed to create pools {missing_datasets}")
sys.exit(1)
def get_cpu_manufacturer() -> str:
"""Get the CPU manufacturer."""
output = bash_wrapper("cat /proc/cpuinfo")
id_vendor = {"AuthenticAMD": "amd", "GenuineIntel": "intel"}
for line in output.splitlines():
if "vendor_id" in line:
return id_vendor[line.split(": ")[1].strip()]
def get_boot_drive_id(disk: str) -> str:
"""Get the boot drive ID."""
output = bash_wrapper(f"lsblk -o UUID {disk}-part1")
return output.splitlines()[1]
def create_nix_hardware_file(mnt_dir: str, disks: Sequence[str], encrypt: bool) -> None:
"""Create a NixOS hardware file."""
cpu_manufacturer = get_cpu_manufacturer()
devices = ""
if encrypt:
disk = disks[0]
devices = (
f' luks.devices."luks-root-pool-{disk.split("/")[-1]}-part2"'
"= {\n"
f' device = "{disk}-part2";\n'
" bypassWorkqueues = true;\n"
" allowDiscards = true;\n"
" };\n"
)
host_id = format(getrandbits(32), "08x")
nix_hardware = (
"{ config, lib, modulesPath, ... }:\n"
"{\n"
' imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];\n\n'
" boot = {\n"
" initrd = {\n"
' availableKernelModules = [ \n "ahci"\n "ehci_pci"\n "nvme"\n "sd_mod"\n "usb_storage"\n "usbhid"\n "xhci_pci"\n ];\n'
" kernelModules = [ ];\n"
f" {devices}"
" };\n"
f' kernelModules = [ "kvm-{cpu_manufacturer}" ];\n'
" extraModulePackages = [ ];\n"
" };\n\n"
" fileSystems = {\n"
' "/" = lib.mkDefault {\n device = "root_pool/root";\n fsType = "zfs";\n };\n\n'
' "/home" = {\n device = "root_pool/home";\n fsType = "zfs";\n };\n\n'
' "/var" = {\n device = "root_pool/var";\n fsType = "zfs";\n };\n\n'
' "/nix" = {\n device = "root_pool/nix";\n fsType = "zfs";\n };\n\n'
' "/boot" = {\n'
f' device = "/dev/disk/by-uuid/{get_boot_drive_id(disks[0])}";\n'
' fsType = "vfat";\n options = [\n "fmask=0077"\n "dmask=0077"\n ];\n };\n };\n\n'
" swapDevices = [ ];\n\n"
" networking.useDHCP = lib.mkDefault true;\n\n"
' nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";\n'
f" hardware.cpu.{cpu_manufacturer}.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;\n"
f' networking.hostId = "{host_id}";\n'
"}\n"
)
Path(f"{mnt_dir}/etc/nixos/hardware-configuration.nix").write_text(nix_hardware)
def install_nixos(mnt_dir: str, disks: Sequence[str], encrypt: bool) -> None:
"""Install NixOS."""
bash_wrapper(f"mount -o X-mount.mkdir -t zfs root_pool/root {mnt_dir}")
bash_wrapper(f"mount -o X-mount.mkdir -t zfs root_pool/home {mnt_dir}/home")
bash_wrapper(f"mount -o X-mount.mkdir -t zfs root_pool/var {mnt_dir}/var")
bash_wrapper(f"mount -o X-mount.mkdir -t zfs root_pool/nix {mnt_dir}/nix")
for disk in disks:
bash_wrapper(f"mkfs.vfat -n EFI {disk}-part1")
# set up mirroring afterwards if more than one disk
boot_partition = f"mount -t vfat -o fmask=0077,dmask=0077,iocharset=iso8859-1,X-mount.mkdir {disks[0]}-part1 {mnt_dir}/boot"
bash_wrapper(boot_partition)
bash_wrapper(f"nixos-generate-config --root {mnt_dir}")
create_nix_hardware_file(mnt_dir, disks, encrypt)
run(("nixos-install", "--root", mnt_dir), check=True) # noqa: S603
def installer(
disks: set[str],
swap_size: int,
reserve: int,
encrypt_key: str | None,
) -> None:
"""Main."""
logging.info("Starting installation")
for disk in disks:
partition_disk(disk, swap_size, reserve)
if encrypt_key:
sleep(1)
for command in (
f'printf "{encrypt_key}" | cryptsetup luksFormat --type luks2 {disk}-part2 -',
f'printf "{encrypt_key}" | cryptsetup luksOpen {disk}-part2 luks-root-pool-{disk.split("/")[-1]}-part2 -',
):
run(command, shell=True, check=True)
mnt_dir = "/tmp/nix_install" # noqa: S108
Path(mnt_dir).mkdir(parents=True, exist_ok=True)
if encrypt_key:
pool_disks = [
f"/dev/mapper/luks-root-pool-{disk.split('/')[-1]}-part2" for disk in disks
]
else:
pool_disks = [f"{disk}-part2" for disk in disks]
create_zfs_pool(pool_disks, mnt_dir)
create_zfs_datasets()
install_nixos(mnt_dir, disks, encrypt_key)
logging.info("Installation complete")
class Cursor:
def __init__(self):
self.x_position = 0
self.y_position = 0
self.height = 0
self.width = 0
def set_height(self, height: int):
self.height = height
def set_width(self, width: int):
self.width = width
def x_bounce_check(self, cursor: int) -> int:
cursor = max(0, cursor)
return min(self.width - 1, cursor)
def y_bounce_check(self, cursor: int) -> int:
cursor = max(0, cursor)
return min(self.height - 1, cursor)
def set_x(self, x: int):
self.x_position = self.x_bounce_check(x)
def set_y(self, y: int):
self.y_position = self.y_bounce_check(y)
def get_x(self) -> int:
return self.x_position
def get_y(self) -> int:
return self.y_position
def move_up(self):
self.set_y(self.y_position - 1)
def move_down(self):
self.set_y(self.y_position + 1)
def move_left(self):
self.set_x(self.x_position - 1)
def move_right(self):
self.set_x(self.x_position + 1)
def navigation(self, key: int) -> None:
action = {
curses.KEY_DOWN: self.move_down,
curses.KEY_UP: self.move_up,
curses.KEY_RIGHT: self.move_right,
curses.KEY_LEFT: self.move_left,
}
action.get(key, lambda: None)()
class State:
"""State class to store the state of the program."""
def __init__(self):
self.key = 0
self.cursor = Cursor()
self.swap_size = 0
self.show_swap_input = False
self.reserve_size = 0
self.show_reserve_input = False
self.selected_device_ids = set()
def get_selected_devices(self) -> tuple[str]:
"""Get selected devices."""
return tuple(self.selected_device_ids)
def get_device(raw_device: str) -> dict[str, str]:
raw_device_components = raw_device.split(" ")
return {
thing.split("=")[0].lower(): thing.split("=")[1].strip('"')
for thing in raw_device_components
}
def get_devices() -> list[dict[str, str]]:
"""Get a list of devices."""
# --bytes
raw_devices = bash_wrapper("lsblk --paths --pairs").splitlines()
return [get_device(raw_device) for raw_device in raw_devices]
def get_device_id_mapping() -> dict[str, set[str]]:
"""Get a list of device ids.
Returns:
list[str]: the list of device ids
"""
device_ids = bash_wrapper("find /dev/disk/by-id -type l").splitlines()
device_id_mapping: dict[str, set[str]] = defaultdict(set)
for device_id in device_ids:
device = bash_wrapper(f"readlink -f {device_id}").strip()
device_id_mapping[device].add(device_id)
return device_id_mapping
def calculate_device_menu_padding(
devices: list[dict[str, str]], column: str, padding: int = 0
) -> int:
return max(len(device[column]) for device in devices) + padding
def draw_device_ids(
state: State,
row_number: int,
menu_start_x: int,
std_screen: curses.window,
menu_width: list[int],
device_ids: set[str],
) -> tuple[State, int]:
for device_id in sorted(device_ids):
row_number = row_number + 1
if row_number == state.cursor.get_y() and state.cursor.get_x() in menu_width:
std_screen.attron(curses.A_BOLD)
if state.key == ord(" "):
if device_id not in state.selected_device_ids:
state.selected_device_ids.add(device_id)
else:
state.selected_device_ids.remove(device_id)
if device_id in state.selected_device_ids:
std_screen.attron(curses.color_pair(7))
std_screen.addstr(row_number, menu_start_x, f" {device_id}")
std_screen.attroff(curses.color_pair(7))
std_screen.attroff(curses.A_BOLD)
return state, row_number
def draw_device_menu(
std_screen: curses.window,
devices: list[dict[str, str]],
device_id_mapping: dict[str, set[str]],
state: State,
menu_start_y: int = 0,
menu_start_x: int = 0,
) -> State:
"""draw the device menu and handle user input
Args:
std_screen (curses.window): the curses window to draw on
devices (list[dict[str, str]]): the list of devices to draw
device_id_mapping (dict[str, set[str]]): the list of device ids to draw
state (State): the state object to update
menu_start_y (int, optional): the y position to start drawing the menu. Defaults to 0.
menu_start_x (int, optional): the x position to start drawing the menu. Defaults to 0.
Returns:
State: the updated state object
"""
padding = 2
name_padding = calculate_device_menu_padding(devices, "name", padding)
size_padding = calculate_device_menu_padding(devices, "size", padding)
type_padding = calculate_device_menu_padding(devices, "type", padding)
mountpoints_padding = calculate_device_menu_padding(devices, "mountpoints", padding)
device_header = f"{'Name':{name_padding}}{'Size':{size_padding}}{'Type':{type_padding}}{'Mountpoints':{mountpoints_padding}}"
menu_width = range(menu_start_x, len(device_header) + menu_start_x)
std_screen.addstr(menu_start_y, menu_start_x, device_header, curses.color_pair(5))
devises_list_start = menu_start_y + 1
row_number = devises_list_start
for device in devices:
row_number = row_number + 1
device_name = device["name"]
device_row = (
f"{device_name:{name_padding}}"
f"{device['size']:{size_padding}}"
f"{device['type']:{type_padding}}"
f"{device['mountpoints']:{mountpoints_padding}}"
)
std_screen.addstr(row_number, menu_start_x, device_row)
state, row_number = draw_device_ids(
state=state,
row_number=row_number,
menu_start_x=menu_start_x,
std_screen=std_screen,
menu_width=menu_width,
device_ids=device_id_mapping[device_name],
)
return state, row_number
def debug_menu(std_screen: curses.window, key: int) -> None:
height, width = std_screen.getmaxyx()
width_height = "Width: {}, Height: {}".format(width, height)
std_screen.addstr(height - 4, 0, width_height, curses.color_pair(5))
key_pressed = f"Last key pressed: {key}"[: width - 1]
if key == 0:
key_pressed = "No key press detected..."[: width - 1]
std_screen.addstr(height - 3, 0, key_pressed)
for i in range(0, 8):
std_screen.addstr(height - 2, i * 3, f"{i}██", curses.color_pair(i))
def status_bar(
std_screen: curses.window,
cursor: Cursor,
width: int,
height: int,
) -> None:
std_screen.attron(curses.A_REVERSE)
std_screen.attron(curses.color_pair(3))
status_bar = (
f"Press 'q' to exit | STATUS BAR | Pos: {cursor.get_x()}, {cursor.get_y()}"
)
std_screen.addstr(height - 1, 0, status_bar)
std_screen.addstr(height - 1, len(status_bar), " " * (width - len(status_bar) - 1))
std_screen.attroff(curses.color_pair(3))
std_screen.attroff(curses.A_REVERSE)
def set_color() -> None:
curses.start_color()
curses.use_default_colors()
for i in range(0, curses.COLORS):
curses.init_pair(i + 1, i, -1)
def get_text_input(std_screen: curses.window, prompt: str, y: int, x: int) -> str:
curses.echo()
std_screen.addstr(y, x, prompt)
input_str = ""
while True:
key = std_screen.getch()
if key == ord("\n"):
break
elif key == 27: # ESC key
input_str = ""
break
elif key in (curses.KEY_BACKSPACE, ord("\b"), 127):
input_str = input_str[:-1]
std_screen.addstr(y, x + len(prompt), input_str + " ")
else:
input_str += chr(key)
std_screen.refresh()
curses.noecho()
return input_str
def swap_size_input(
std_screen: curses.window,
state: State,
swap_offset: int,
) -> State:
swap_size_text = "Swap size (GB): "
std_screen.addstr(swap_offset, 0, f"{swap_size_text}{state.swap_size}")
if state.key == ord("\n") and state.cursor.get_y() == swap_offset:
state.show_swap_input = True
if state.show_swap_input:
swap_size_str = get_text_input(std_screen, swap_size_text, swap_offset, 0)
try:
state.swap_size = int(swap_size_str)
state.show_swap_input = False
except ValueError:
std_screen.addstr(
swap_offset, 0, "Invalid input. Press any key to continue."
)
std_screen.getch()
state.show_swap_input = False
return state
def reserve_size_input(
std_screen: curses.window,
state: State,
reserve_offset: int,
) -> State:
reserve_size_text = "reserve size (GB): "
std_screen.addstr(reserve_offset, 0, f"{reserve_size_text}{state.reserve_size}")
if state.key == ord("\n") and state.cursor.get_y() == reserve_offset:
state.show_reserve_input = True
if state.show_reserve_input:
reserve_size_str = get_text_input(
std_screen, reserve_size_text, reserve_offset, 0
)
try:
state.reserve_size = int(reserve_size_str)
state.show_reserve_input = False
except ValueError:
std_screen.addstr(
reserve_offset, 0, "Invalid input. Press any key to continue."
)
std_screen.getch()
state.show_reserve_input = False
return state
def draw_menu(std_screen: curses.window) -> State:
"""draw the menu and handle user input
Args:
std_screen (curses.window): the curses window to draw on
Returns:
State: the state object
"""
# Clear and refresh the screen for a blank canvas
std_screen.clear()
std_screen.refresh()
set_color()
state = State()
devices = get_devices()
device_id_mapping = get_device_id_mapping()
# Loop where k is the last character pressed
while state.key != ord("q"):
std_screen.clear()
height, width = std_screen.getmaxyx()
state.cursor.set_height(height)
state.cursor.set_width(width)
state.cursor.navigation(state.key)
state, device_menu_size = draw_device_menu(
std_screen=std_screen,
state=state,
devices=devices,
device_id_mapping=device_id_mapping,
)
swap_offset = device_menu_size + 2
swap_size_input(
std_screen=std_screen,
state=state,
swap_offset=swap_offset,
)
reserve_size_input(
std_screen=std_screen,
state=state,
reserve_offset=swap_offset + 1,
)
status_bar(std_screen, state.cursor, width, height)
debug_menu(std_screen, state.key)
std_screen.move(state.cursor.get_y(), state.cursor.get_x())
std_screen.refresh()
state.key = std_screen.getch()
return state
def main() -> None:
configure_logger("DEBUG")
state = curses.wrapper(draw_menu)
encrypt_key = getenv("ENCRYPT_KEY")
logging.info("installing_nixos")
logging.info(f"disks: {state.selected_device_ids}")
logging.info(f"swap_size: {state.swap_size}")
logging.info(f"reserve: {state.reserve_size}")
logging.info(f"encrypted: {bool(encrypt_key)}")
sleep(3)
installer(
disks=state.get_selected_devices(),
swap_size=state.swap_size,
reserve=state.reserve_size,
encrypt_key=encrypt_key,
)
if __name__ == "__main__":
main()

230
tools/intaller.py Normal file
View File

@@ -0,0 +1,230 @@
"""Install NixOS on a ZFS pool."""
from __future__ import annotations
import logging
import sys
from os import getenv
from pathlib import Path
from random import getrandbits
from subprocess import PIPE, Popen, run
from time import sleep
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Sequence
def configure_logger(level: str = "INFO") -> None:
"""Configure the logger.
Args:
level (str, optional): The logging level. Defaults to "INFO".
"""
logging.basicConfig(
level=level,
datefmt="%Y-%m-%dT%H:%M:%S%z",
format="%(asctime)s %(levelname)s %(filename)s:%(lineno)d - %(message)s",
handlers=[logging.StreamHandler(sys.stdout)],
)
def bash_wrapper(command: str) -> str:
"""Execute a bash command and capture the output.
Args:
command (str): The bash command to be executed.
Returns:
Tuple[str, int]: A tuple containing the output of the command (stdout) as a string,
the error output (stderr) as a string (optional), and the return code as an integer.
"""
logging.debug(f"running {command=}")
# This is a acceptable risk
process = Popen(command.split(), stdout=PIPE, stderr=PIPE) # noqa: S603
output, _ = process.communicate()
if process.returncode != 0:
error = f"Failed to run command {command=} return code {process.returncode=}"
raise RuntimeError(error)
return output.decode()
def partition_disk(disk: str, swap_size: int, reserve: int = 0) -> None:
"""Partition a disk.
Args:
disk (str): The disk to partition.
swap_size (int): The size of the swap partition in GB.
minimum value is 1.
reserve (int, optional): The size of the reserve partition in GB. Defaults to 0.
minimum value is 0.
"""
logging.info(f"partitioning {disk=}")
swap_size = max(swap_size, 1)
reserve = max(reserve, 0)
bash_wrapper(f"blkdiscard -f {disk}")
if reserve > 0:
msg = f"Creating swap partition on {disk=} with size {swap_size=}GiB and reserve {reserve=}GiB"
logging.info(msg)
swap_start = swap_size + reserve
swap_partition = f"mkpart swap -{swap_start}GiB -{reserve}GiB "
else:
logging.info(f"Creating swap partition on {disk=} with size {swap_size=}GiB")
swap_start = swap_size
swap_partition = f"mkpart swap -{swap_start}GiB 100% "
logging.debug(f"{swap_partition=}")
create_partitions = (
f"parted --script --align=optimal {disk} -- "
"mklabel gpt "
"mkpart EFI 1MiB 4GiB "
f"mkpart root_pool 4GiB -{swap_start}GiB "
f"{swap_partition}"
"set 1 esp on"
)
bash_wrapper(create_partitions)
logging.info(f"{disk=} successfully partitioned")
def create_zfs_pool(pool_disks: Sequence[str], mnt_dir: str) -> None:
"""Create a ZFS pool.
Args:
disks (Sequence[str]): A tuple of disks to use for the pool.
mnt_dir (str): The mount directory.
"""
if len(pool_disks) <= 0:
error = "disks must be a tuple of at least length 1"
raise ValueError(error)
zpool_create = (
"zpool create "
"-o ashift=12 "
"-o autotrim=on "
f"-R {mnt_dir} "
"-O acltype=posixacl "
"-O canmount=off "
"-O dnodesize=auto "
"-O normalization=formD "
"-O relatime=on "
"-O xattr=sa "
"-O mountpoint=none "
"-O primarycache=metadata "
"root_pool "
)
if len(pool_disks) == 1:
zpool_create += pool_disks[0]
else:
zpool_create += "mirror "
zpool_create += " ".join(pool_disks)
bash_wrapper(zpool_create)
zpools = bash_wrapper("zpool list -o name")
if "root_pool" not in zpools.splitlines():
logging.critical("Failed to create root_pool")
sys.exit(1)
def create_zfs_datasets() -> None:
"""Create ZFS datasets."""
default_options = "-o compression=zstd -o atime=off -o mountpoint=legacy"
bash_wrapper(f"zfs create {default_options} -o canmount=noauto root_pool/root")
for dataset in ("home", "var"):
bash_wrapper(f"zfs create {default_options} root_pool/{dataset}")
datasets = bash_wrapper("zfs list -o name")
expected_datasets = {"root_pool/root", "root_pool/home", "root_pool/var"}
missing_datasets = expected_datasets.difference(datasets.splitlines())
if missing_datasets:
logging.critical(f"Failed to create pools {missing_datasets}")
sys.exit(1)
def install_nixos(mnt_dir: str, disks: Sequence[str], encrypt: bool) -> None:
"""Install NixOS."""
bash_wrapper(f"mount -o X-mount.mkdir -t zfs root_pool/root {mnt_dir}")
bash_wrapper(f"mount -o X-mount.mkdir -t zfs root_pool/home {mnt_dir}/home")
bash_wrapper(f"mount -o X-mount.mkdir -t zfs root_pool/var {mnt_dir}/var")
for disk in disks:
bash_wrapper(f"mkfs.vfat -n EFI {disk}-part1")
# set up mirroring afterwards if more than one disk
boot_partition = f"mount -t vfat -o fmask=0077,dmask=0077,iocharset=iso8859-1,X-mount.mkdir {disks[0]}-part1 {mnt_dir}/boot"
bash_wrapper(boot_partition)
bash_wrapper(f"nixos-generate-config --root {mnt_dir}")
host_id = format(getrandbits(32), "08x")
nix_hardware = Path(f"{mnt_dir}/etc/nixos/hardware-configuration.nix").read_text()
nix_hardware = nix_hardware.replace(
";\n}", f';\n networking.hostId = "{host_id}";' "\n}"
)
if encrypt:
test = [
f' "luks-root-pool-{disk.split("/")[-1]}-part2".device = "{disk}-part2";\n'
for disk in disks
]
encrypted_disks = (
";\n boot.initrd.luks.devices = {\n" f"{''.join(test)}" " };\n" "}"
)
nix_hardware = nix_hardware.replace(";\n}", encrypted_disks)
Path(f"{mnt_dir}/etc/nixos/hardware-configuration.nix").write_text(nix_hardware)
run(("nixos-install", "--root", mnt_dir), check=True) # noqa: S603
def main() -> None:
"""Main."""
configure_logger("DEBUG")
logging.info("Starting installation")
disks = ("/dev/disk/by-id/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",)
# Set swap size in GB, set to 1 if you don't want swap to take up too much space
swap_size = 1
reserve = 0
encrypt_key = getenv("ENCRYPT_KEY")
for disk in disks:
partition_disk(disk, swap_size, reserve)
if encrypt_key:
sleep(1)
for command in (
f'printf "{encrypt_key}" | cryptsetup luksFormat --type luks2 {disk}-part2 -',
f'printf "{encrypt_key}" | cryptsetup luksOpen {disk}-part2 luks-root-pool-{disk.split("/")[-1]}-part2 -',
):
run(command, shell=True, check=True)
mnt_dir = "/tmp/nix_install" # noqa: S108
Path(mnt_dir).mkdir(parents=True, exist_ok=True)
if encrypt_key:
pool_disks = [
f'/dev/mapper/luks-root-pool-{disk.split("/")[-1]}-part2' for disk in disks
]
else:
pool_disks = [f"{disk}-part2" for disk in disks]
create_zfs_pool(pool_disks, mnt_dir)
create_zfs_datasets()
install_nixos(mnt_dir, disks, encrypt_key)
logging.info("Installation complete")
if __name__ == "__main__":
main()

View File

@@ -1,14 +0,0 @@
# One CLI to format the code tree - https://github.com/numtide/treefmt
[global]
# Glob patterns of files to exclude
excludes = [".git/"]
[formatter.nixfmt]
# Formatter to run
command = "nixfmt"
# Command-line arguments for the command
#options = []
# Glob pattern of files to include
includes = ["*.nix"]

View File

@@ -1,30 +0,0 @@
{
pkgs,
config,
...
}:
{
sops.secrets.gaming_password = {
sopsFile = ../secrets.yaml;
neededForUsers = true;
};
users = {
users.gaming = {
isNormalUser = true;
hashedPasswordFile = "${config.sops.secrets.gaming_password.path}";
shell = pkgs.zsh;
group = "gaming";
extraGroups = [
"audio"
"video"
"users"
];
uid = 1100;
};
groups.gaming.gid = 1100;
};
home-manager.users.gaming = import ./systems/${config.networking.hostName}.nix;
}

View File

@@ -1,17 +0,0 @@
{ config, ... }:
{
imports = [
./programs.nix
];
programs = {
home-manager.enable = true;
git.enable = true;
};
home = {
username = "gaming";
homeDirectory = "/home/${config.home.username}";
stateVersion = "24.05";
};
}

View File

@@ -1,8 +0,0 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
chromium
vscode
firefox
];
}

View File

@@ -1,5 +0,0 @@
{
imports = [
../home/global.nix
];
}

View File

@@ -1,30 +0,0 @@
{
pkgs,
config,
...
}:
{
sops.secrets.megan_password = {
sopsFile = ../secrets.yaml;
neededForUsers = true;
};
users = {
users.megan = {
isNormalUser = true;
hashedPasswordFile = "${config.sops.secrets.megan_password.path}";
shell = pkgs.zsh;
group = "megan";
extraGroups = [
"audio"
"video"
"users"
];
uid = 1101;
};
groups.megan.gid = 1101;
};
home-manager.users.megan = import ./systems/${config.networking.hostName}.nix;
}

View File

@@ -1,9 +0,0 @@
{
imports = [
./direnv.nix
./git.nix
./zsh.nix
];
programs.starship.enable = true;
}

View File

@@ -1,8 +0,0 @@
{
programs.direnv = {
enable = true;
enableZshIntegration = true;
nix-direnv.enable = true;
};
}

View File

@@ -1,12 +0,0 @@
{
programs.git = {
enable = true;
userEmail = "mousikos112@gmail.com";
userName = "megan";
extraConfig = {
pull.rebase = true;
color.ui = true;
};
lfs.enable = true;
};
}

View File

@@ -1,31 +0,0 @@
{
programs.zsh = {
enable = true;
syntaxHighlighting.enable = true;
history.size = 10000;
oh-my-zsh = {
enable = true;
plugins = [
"git"
"docker"
"docker-compose"
"colored-man-pages"
"rust"
"systemd"
"tmux"
"ufw"
"z"
];
};
shellAliases = {
"lrt" = "eza --icons -lsnew";
"ls" = "eza";
"ll" = "eza --long --group";
"la" = "eza --all";
"rspace" = "'for f in *\ *; do mv \"$f\" \"\${f// /_}\"; done'";
"rebuild" = "sudo nixos-rebuild switch --flake /home/richie/dotfiles#$HOST";
"nix-test" = "nixos-rebuild test --flake /home/richie/dotfiles";
};
};
}

View File

@@ -1,18 +0,0 @@
{ config, ... }:
{
imports = [
./cli
./programs.nix
];
programs = {
home-manager.enable = true;
git.enable = true;
};
home = {
username = "megan";
homeDirectory = "/home/${config.home.username}";
stateVersion = "24.05";
};
}

View File

@@ -1,42 +0,0 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
# cli
bat
btop
eza
fd
ffmpegthumbnailer
fzf
git
gnupg
imagemagick
jq
ncdu
neofetch
ouch
p7zip
poppler
rar
ripgrep
starship
tmux
unzip
yazi
zoxide
# system info
hwloc
lynis
pciutils
smartmontools
usbutils
# networking
iperf3
nmap
wget
# python
poetry
python313
ruff
];
}

View File

@@ -1,5 +0,0 @@
{
imports = [
../home/global.nix
];
}

View File

@@ -2,51 +2,39 @@
pkgs, pkgs,
config, config,
... ...
}: }: let
let
ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups; ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups;
in in {
{ users.users.richie = {
isNormalUser = true;
sops.secrets.richie_password = { shell = pkgs.zsh;
sopsFile = ../secrets.yaml; group = "richie";
neededForUsers = true; openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIPtuYhiJHRTYhNaDmTcJOqJASk7D8mIn6u3F1IN5AFJ bob" # cspell:disable-line
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJYZFsc9CSH03ZUP7y81AHwSyjLwFmcshVFCyxDcYhBT rhapsody-in-green" # cspell:disable-line
];
extraGroups =
[
"audio"
"video"
"wheel"
"users"
]
++ ifTheyExist [
"dialout"
"docker"
"libvirtd"
"networkmanager"
"plugdev"
"scanner"
"uaccess"
"wireshark"
];
uid = 1000;
}; };
users = { users.groups.richie = {
users.richie = { gid = 1000;
isNormalUser = true;
hashedPasswordFile = "${config.sops.secrets.richie_password.path}";
shell = pkgs.zsh;
group = "richie";
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJYZFsc9CSH03ZUP7y81AHwSyjLwFmcshVFCyxDcYhBT rhapsody-in-green" # cspell:disable-line
];
extraGroups =
[
"audio"
"video"
"wheel"
"users"
]
++ ifTheyExist [
"dialout"
"docker"
"hass"
"libvirtd"
"networkmanager"
"plugdev"
"scanner"
"transmission"
"uaccess"
"wireshark"
];
uid = 1000;
};
groups.richie.gid = 1000;
}; };
home-manager.users.richie = import ./systems/${config.networking.hostName}.nix; home-manager.users.richie = import ./systems/${config.networking.hostName}.nix;

View File

@@ -1,8 +1,8 @@
{ {
imports = [ imports = [
./direnv.nix
./git.nix ./git.nix
./zsh.nix ./zsh.nix
./direnv.nix
]; ];
programs.starship.enable = true; programs.starship.enable = true;

View File

@@ -3,10 +3,5 @@
enable = true; enable = true;
userEmail = "Richie@tmmworkshop.com"; userEmail = "Richie@tmmworkshop.com";
userName = "Richie Cahill"; userName = "Richie Cahill";
extraConfig = {
pull.rebase = true;
color.ui = true;
};
lfs.enable = true;
}; };
} }

View File

@@ -18,14 +18,17 @@
]; ];
}; };
shellAliases = { shellAliases = {
"sgc" = "sudo git -C /root/dotfiles";
## Utilities
"lrt" = "eza --icons -lsnew"; "lrt" = "eza --icons -lsnew";
"ls" = "eza"; "ls" = "eza";
"ll" = "eza --long --group"; "ll" = "eza --long --group";
"la" = "eza --all"; "la" = "eza --all";
"rebuild" = "sudo nixos-rebuild switch --flake $HOME/dotfiles#$HOST"; "rspace" = "'for f in *\ *; do mv \"$f\" \"\${f// /_}\"; done'";
"rebuild_backup" = "rebuild" = "sudo nixos-rebuild switch --flake /home/richie/projects/dotfiles#$HOST";
"sudo nixos-rebuild switch --flake $HOME/dotfiles#$HOST --option substituters 'https://nix-community.cachix.org' --option trusted-public-keys 'cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY='"; "nix-test" = "nixos-rebuild test --flake /home/richie/projects/dotfiles";
}; };
}; };
} }

View File

@@ -1,22 +1,37 @@
{ config, ... }:
{ {
lib,
pkgs,
config,
...
}: {
imports = [ imports = [
./cli ./cli
./programs.nix ./programs.nix
./ssh_config.nix ./ssh_config.nix
]; ];
nix = {
package = lib.mkDefault pkgs.nix;
settings = {
experimental-features = [
"nix-command"
"flakes"
"ca-derivations"
];
};
};
programs = { programs = {
home-manager.enable = true; home-manager.enable = true;
git.enable = true; git.enable = true;
}; };
home = { home = {
username = "richie"; username = lib.mkDefault "richie";
homeDirectory = "/home/${config.home.username}"; homeDirectory = lib.mkDefault "/home/${config.home.username}";
stateVersion = "24.05"; stateVersion = lib.mkDefault "24.05";
sessionVariables = { sessionVariables = {
FLAKE = "$HOME/dotfiles"; FLAKE = "$HOME/Projects/dotfiles";
}; };
}; };
} }

View File

@@ -1,25 +1,20 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
imports = [ imports = [
./firefox ./firefox.nix
./vscode ./vscode
./kitty.nix
]; ];
home.packages = with pkgs; [ home.packages = with pkgs; [
candy-icons candy-icons
chromium
discord-canary discord-canary
gimp gimp
gparted gparted
jetbrains.datagrip
ladybird
mediainfo mediainfo
nemo nemo
nemo-fileroller nemo-fileroller
obs-studio obs-studio
obsidian obsidian
prismlauncher
proxychains proxychains
prusa-slicer prusa-slicer
signal-desktop signal-desktop

View File

@@ -1,11 +1,13 @@
{ inputs, ... }:
{ {
imports = [ ./search_engines.nix ]; pkgs,
inputs,
...
}:
{
programs.firefox = { programs.firefox = {
enable = true; enable = true;
profiles.richie = { profiles.richie = {
extensions.packages = with inputs.firefox-addons.packages.x86_64-linux; [ extensions = with inputs.firefox-addons.packages.x86_64-linux; [
bitwarden bitwarden
darkreader darkreader
dearrow dearrow
@@ -14,15 +16,55 @@
sponsorblock sponsorblock
ublock-origin ublock-origin
]; ];
search = { search.engines = {
force = true; "Nix Options" = {
default = "kagi"; urls = [
order = [ {
"kagi" template = "https://search.nixos.org/options";
"ddg" params = [
"google" {
]; name = "type";
value = "packages";
}
{
name = "channel";
value = "unstable";
}
{
name = "query";
value = "{searchTerms}";
}
];
}
];
icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@o" ];
};
"Nix Packages" = {
urls = [
{
template = "https://search.nixos.org/packages";
params = [
{
name = "type";
value = "packages";
}
{
name = "channel";
value = "unstable";
}
{
name = "query";
value = "{searchTerms}";
}
];
}
];
icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@n" ];
};
}; };
search.force = true;
settings = { settings = {
# SECTION: FASTFOX # SECTION: FASTFOX
# GENERAL # GENERAL
@@ -142,8 +184,7 @@
"permissions.default.desktop-notification" = 0; # allow websites to ask "permissions.default.desktop-notification" = 0; # allow websites to ask
# PREF: allow websites to ask you for your location # PREF: allow websites to ask you for your location
"permissions.default.geo" = 0; "permissions.default.geo" = 0;
"geo.provider.network.url" = "geo.provider.network.url" = "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%";
"https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%";
"permissions.manager.defaultsUrl" = ""; "permissions.manager.defaultsUrl" = "";
"webchannel.allowObject.urlWhitelist" = ""; "webchannel.allowObject.urlWhitelist" = "";

View File

@@ -1,3 +0,0 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16 0C7.16 0 0 7.16 0 16C0 23.08 4.58 29.06 10.94 31.18C11.74 31.32 12.04 30.84 12.04 30.42C12.04 30.04 12.02 28.78 12.02 27.44C8 28.18 6.96 26.46 6.64 25.56C6.46 25.1 5.68 23.68 5 23.3C4.44 23 3.64 22.26 4.98 22.24C6.24 22.22 7.14 23.4 7.44 23.88C8.88 26.3 11.18 25.62 12.1 25.2C12.24 24.16 12.66 23.46 13.12 23.06C9.56 22.66 5.84 21.28 5.84 15.16C5.84 13.42 6.46 11.98 7.48 10.86C7.32 10.46 6.76 8.82 7.64 6.62C7.64 6.62 8.98 6.2 12.04 8.26C13.32 7.9 14.68 7.72 16.04 7.72C17.4 7.72 18.76 7.9 20.04 8.26C23.1 6.18 24.44 6.62 24.44 6.62C25.32 8.82 24.76 10.46 24.6 10.86C25.62 11.98 26.24 13.4 26.24 15.16C26.24 21.3 22.5 22.66 18.94 23.06C19.52 23.56 20.02 24.52 20.02 26.02C20.02 28.16 20 29.88 20 30.42C20 30.84 20.3 31.34 21.1 31.18C27.42 29.06 32 23.06 32 16C32 7.16 24.84 0 16 0V0Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 957 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 924 B

View File

@@ -1,99 +0,0 @@
{ pkgs, ... }:
{
programs.firefox.profiles.richie.search.engines = {
"Nix Options" = {
urls = [
{
template = "https://search.nixos.org/options";
params = [
{
name = "type";
value = "packages";
}
{
name = "channel";
value = "unstable";
}
{
name = "query";
value = "{searchTerms}";
}
];
}
];
icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@o" ];
};
"Nix Packages" = {
urls = [
{
template = "https://search.nixos.org/packages";
params = [
{
name = "type";
value = "packages";
}
{
name = "channel";
value = "unstable";
}
{
name = "query";
value = "{searchTerms}";
}
];
}
];
icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@n" ];
};
"Nix Packages pr-tracker" = {
urls = [
{
template = "https://nixpk.gs/pr-tracker.html?";
params = [
{
name = "pr";
value = "{searchTerms}";
}
];
}
];
icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg";
definedAliases = [ "@nprt" ];
};
"kagi" = {
urls = [
{
template = "https://kagi.com/search?";
params = [
{
name = "q";
value = "{searchTerms}";
}
];
}
];
icon = ./kagi.png;
};
github = {
urls = [
{
template = "https://github.com/search?";
params = [
{
name = "q";
value = "{searchTerms}";
}
{
name = "type";
value = "code";
}
];
}
];
icon = ./github.svg;
definedAliases = [ "@g" ];
};
};
}

Some files were not shown because too many files have changed in this diff Show More