desktop is building I guess, idk, need to start commiting stuff eventually lmao

This commit is contained in:
mjallen18
2025-07-17 20:57:18 -05:00
parent 6c7c76887b
commit 442c24997d
219 changed files with 3166 additions and 3583 deletions

View File

@@ -0,0 +1,26 @@
{ config, inputs, pkgs, ... }:
{
imports = [
./nix.nix
./homebrew.nix
./programs.nix
./system.nix
];
# List packages installed in system profile. To search by name, run:
# $ nix-env -qaP | grep wget
environment = {
systemPackages = with pkgs; [
asitop
mas
nh
];
};
security.pam.services.sudo_local.touchIdAuth = true;
users.users.mattjallen = {
name = "mattjallen";
home = "/Users/mattjallen";
};
}

View File

@@ -0,0 +1,59 @@
{ lib, pkgs, home, ... }:
let
shellAliases = {
update-switch = "darwin-rebuild switch --flake ~/nix-config";
update-flake = "nix flake update ~/nix-config";
ducks = "du -cksh * | sort -hr | head -n 15";
};
packages = with pkgs; [
age
cpufetch
deadnix
direnv
nixfmt-rfc-style
sops
tree
wget
];
in
{
imports = [
../../modules/home/defaults.nix
../../modules/home/git.nix
../../modules/home/shell.nix
../../modules/home/vscode.nix
];
# Home Manager needs a bit of information about you and the
# paths it should manage.
home = {
username = "mattjallen";
homeDirectory = "/Users/mattjallen";
packages = lib.mkForce packages;
sessionVariables = {
NH_DARWIN_FLAKE = "${home.homeDirectory}/nix-config";
};
};
programs = {
zsh = {
shellAliases = shellAliases;
};
};
# Manage bug in compilations - who uses manpages in 2024 anyways? :P
manual.manpages.enable = false;
# Override defaults that arent supported
programs = {
mangohud.enable = lib.mkForce false;
nh = {
flake = "${home.homeDirectory}/nix-config";
};
};
services = {
pass-secret-service.enable = lib.mkForce false;
nextcloud-client.enable = lib.mkForce false;
};
}

View File

@@ -0,0 +1,66 @@
{ config, inputs, ... }:
{
nix-homebrew = {
user = config.system.primaryUser;
enable = true;
autoMigrate = true;
enableRosetta = true;
mutableTaps = false;
taps = {
"homebrew/homebrew-core" = inputs.homebrew-core;
"homebrew/homebrew-cask" = inputs.homebrew-cask;
};
};
# Homebrew
homebrew = {
enable = true;
taps = builtins.attrNames config.nix-homebrew.taps;
global = {
autoUpdate = false;
brewfile = true;
};
onActivation = {
autoUpdate = false;
cleanup = "zap";
};
casks = [
"aldente"
"bartender"
"betterdisplay"
"chromium"
"discord"
"epic-games"
"gstreamer-runtime"
"iterm2"
"kitty"
"minecraft"
"omnissa-horizon-client"
"onlyoffice"
"orcaslicer"
"proton-drive"
"proton-pass"
"protonvpn"
"scroll-reverser"
"steam"
"tabby"
"tg-pro"
"utm"
"vesktop"
"vlc"
"vscodium"
"wine-stable"
"xpipe"
"xquartz"
];
masApps = {
Amphetamine = 937984704;
Infuse = 1136220934;
"Proton Pass for Safari" = 6502835663;
Tailscale = 1475387142;
Termius = 1176074088;
};
};
# homebrew.global.autoUpdate = true;
}

View File

@@ -0,0 +1,17 @@
{ ... }:
{
# Auto upgrade nix package and the daemon service.
# services.nix-daemon.enable = true;
# nix.package = pkgs.nix;
# Necessary for using flakes on this system.
nix = {
settings.experimental-features = "nix-command flakes";
};
# The platform the configuration will be used on.
nixpkgs = {
config.allowUnfree = true;
hostPlatform = "aarch64-darwin";
};
}

View File

@@ -0,0 +1,24 @@
{ ... }:
{
programs = {
direnv = {
enable = true;
nix-direnv.enable = true;
};
nix-index = {
enable = true;
};
ssh.knownHosts = {
desktop = {
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPTBMydhOc6SnOdB5WrEd7X07DrboAtagCUgXiOJjLov matt@matt-nixos";
};
nas = {
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIwoHWOLSTGVif9hAhaMLl0qDA4roIzCNuyR6kyIXDOj admin@jallen-nas";
};
};
zsh.enable = true; # default shell on catalina
};
}

View File

@@ -0,0 +1,50 @@
{ config, ... }:
{
system = {
primaryUser = config.users.users.mattjallen.name;
defaults = {
controlcenter = {
AirDrop = true;
BatteryShowPercentage = true;
Bluetooth = true;
Display = true;
FocusModes = true;
NowPlaying = true;
};
dock = {
minimize-to-application = true;
mouse-over-hilite-stack = true;
show-recents = false;
};
finder = {
AppleShowAllExtensions = true;
AppleShowAllFiles = true;
_FXSortFoldersFirst = true;
_FXSortFoldersFirstOnDesktop = true;
FXEnableExtensionChangeWarning = false;
ShowPathbar = true; # breadcrumb nav at bottom
ShowStatusBar = true; # file count & disk space
};
loginwindow = {
GuestEnabled = false;
};
NSGlobalDomain = {
"com.apple.keyboard.fnState" = false;
AppleInterfaceStyle = "Dark";
"com.apple.mouse.tapBehavior" = 1;
AppleShowAllExtensions = true;
AppleShowAllFiles = true;
};
trackpad = {
Clicking = true;
};
WindowManager = {
EnableTiledWindowMargins = false;
};
};
startup.chime = false;
# Used for backwards compatibility, please read the changelog before changing.
# $ darwin-rebuild changelog
stateVersion = 5;
};
}

View File

@@ -0,0 +1,25 @@
# Hook home-manager to make a trampoline for each app we install
# from: https://github.com/nix-community/home-manager/issues/1341#issuecomment-1870352014
{
config,
lib,
pkgs,
...
}:
with lib;
{
config = mkIf pkgs.stdenv.hostPlatform.isDarwin {
# Install MacOS applications to the user Applications folder. Also update Docked applications
home.extraActivationPath = with pkgs; [
rsync
dockutil
gawk
];
home.activation.trampolineApps = hm.dag.entryAfter [ "writeBoundary" ] ''
${builtins.readFile ./lib-bash/trampoline-apps.sh}
fromDir="$HOME/Applications/Home Manager Apps"
toDir="$HOME/Applications/Home Manager Trampolines"
sync_trampolines "$fromDir" "$toDir"
'';
};
}

View File

@@ -0,0 +1,131 @@
# Utilities not in nixpkgs.
plutil="/usr/bin/plutil"
killall="/usr/bin/killall"
osacompile="/usr/bin/osacompile"
copyable_app_props=(
"CFBundleDevelopmentRegion"
"CFBundleDocumentTypes"
"CFBundleGetInfoString"
"CFBundleIconFile"
"CFBundleIdentifier"
"CFBundleInfoDictionaryVersion"
"CFBundleName"
"CFBundleShortVersionString"
"CFBundleURLTypes"
"NSAppleEventsUsageDescription"
"NSAppleScriptEnabled"
"NSDesktopFolderUsageDescription"
"NSDocumentsFolderUsageDescription"
"NSDownloadsFolderUsageDescription"
"NSPrincipalClass"
"NSRemovableVolumesUsageDescription"
"NSServices"
"UTExportedTypeDeclarations"
)
function sync_icons() {
local from="$1"
local to="$2"
from_resources="$from/Contents/Resources/"
to_resources="$to/Contents/Resources/"
find "$to_resources" -name "*.icns" -delete
rsync --include "*.icns" --exclude "*" --recursive "$from_resources" "$to_resources"
}
function copy_paths() {
local from="$1"
local to="$2"
local paths=("${@:3}")
keys=$(jq -n '$ARGS.positional' --args "${paths[@]}")
jqfilter="to_entries |[.[]| select(.key as \$item| \$keys | index(\$item) >= 0) ] | from_entries"
temp_dir=$(mktemp -d)
trap 'rm -rf "$temp_dir"' EXIT
pushd $temp_dir >/dev/null
cp "$from" "orig"
chmod u+w "orig"
cp "$to" "bare-wrapper"
chmod u+w "bare-wrapper"
$plutil -convert json -- "orig"
$plutil -convert json -- "bare-wrapper"
jq --argjson keys "$keys" "$jqfilter" <"orig" >"filtered"
cat "bare-wrapper" "filtered" | jq -s add >"final"
$plutil -convert xml1 -- "final"
cp "final" "$to"
popd >/dev/null
}
function sync_dock() {
# Make sure all environment variables are cleared that might affect dockutil
unset SUDO_USER
# Array of applications to sync
declare -a apps=("$@")
# Iterate through each provided app
for app_path in "${apps[@]}"; do
if [ -d "$app_path" ]; then
# Extract the name of the app from the path
app_name=$(basename "$app_path")
app_name=${app_name%.*} # Remove the '.app' extension
resolved_path=$(realpath "$app_path")
# Find the current Dock item for the app, if it exists
current_dock_item=$(dockutil --list --no-restart | grep "$app_name.app" | awk -F "\t" '{print $1}' || echo "")
if [ -n "$current_dock_item" ]; then
# The app is currently in the Dock, attempt to replace it
echo "Updating $app_name in Dock..."
dockutil --add "$resolved_path" --replacing "$current_dock_item" --no-restart
else
# The app is not in the Dock; you might choose to add it or do nothing
echo "$app_name is not currently in the Dock."
fi
else
echo "Warning: Provided path $app_path is not valid."
fi
done
# Restart the Dock to apply changes
$killall Dock
}
function mktrampoline() {
local app="$1"
local trampoline="$2"
if [[ ! -d $app ]]; then
echo "app path is not directory."
return 1
fi
cmd="do shell script \"open '$app'\""
$osacompile -o "$trampoline" -e "$cmd"
sync_icons "$app" "$trampoline"
copy_paths "$(realpath "$app/Contents/Info.plist")" "$(realpath "$trampoline/Contents/Info.plist")" "${copyable_app_props[@]}"
}
function sync_trampolines() {
[[ ! -d "$1" ]] && echo "Source directory does not exist" && return 1
if [[ -d "$2" ]]; then
rm -rf "$2"
fi
mkdir -p "$2"
apps=("$1"/*.app)
for app in "${apps[@]}"; do
trampoline="$2/$(basename "$app")"
mktrampoline "$app" "$trampoline"
done
sync_dock "${apps[@]}"
}

View File

@@ -0,0 +1,7 @@
{ ... }:
{
imports = [
./modules/default.nix
];
}

View File

@@ -0,0 +1,55 @@
{ config, pkgs, lib, ... }:
let
pkgs' = config.hardware.asahi.pkgs;
bootM1n1 = pkgs'.m1n1.override {
isRelease = true;
withTools = false;
customLogo = config.boot.m1n1CustomLogo;
};
bootUBoot = pkgs'.uboot-asahi.override {
m1n1 = bootM1n1;
};
bootFiles = {
"m1n1/boot.bin" = pkgs.runCommand "boot.bin" {} ''
cat ${bootM1n1}/build/m1n1.bin > $out
cat ${config.boot.kernelPackages.kernel}/dtbs/apple/*.dtb >> $out
cat ${bootUBoot}/u-boot-nodtb.bin.gz >> $out
if [ -n "${config.boot.m1n1ExtraOptions}" ]; then
echo '${config.boot.m1n1ExtraOptions}' >> $out
fi
'';
};
in {
config = lib.mkIf config.hardware.asahi.enable {
# install m1n1 with the boot loader
boot.loader.grub.extraFiles = bootFiles;
boot.loader.systemd-boot.extraFiles = bootFiles;
# ensure the installer has m1n1 in the image
system.extraDependencies = lib.mkForce [ bootM1n1 bootUBoot ];
system.build.m1n1 = bootFiles."m1n1/boot.bin";
};
options.boot = {
m1n1ExtraOptions = lib.mkOption {
type = lib.types.str;
default = "";
description = ''
Append extra options to the m1n1 boot binary. Might be useful for fixing
display problems on Mac minis.
https://github.com/AsahiLinux/m1n1/issues/159
'';
};
m1n1CustomLogo = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
Custom logo to build into m1n1. The path must point to a 256x256 PNG.
'';
};
};
}

View File

@@ -0,0 +1,92 @@
{ config, pkgs, lib, ... }:
{
imports = [
./kernel
./mesa
./peripheral-firmware
./boot-m1n1
./sound
];
config = let
cfg = config.hardware.asahi;
in lib.mkIf cfg.enable {
nixpkgs.overlays = lib.mkBefore [ cfg.overlay ];
# patch systemd-boot to boot in Apple Silicon UEFI environment.
# This regression only appeared in systemd 256.7.
# see https://github.com/NixOS/nixpkgs/pull/355290
# and https://github.com/systemd/systemd/issues/35026
systemd.package = let
systemdBroken = (pkgs.systemd.version == "256.7");
systemdPatched = pkgs.systemd.overrideAttrs (old: {
patches = let
oldPatches = (old.patches or []);
# not sure why there are non-paths in there but oh well
patchNames = (builtins.map (p: if ((builtins.typeOf p) == "path") then builtins.baseNameOf p else "") oldPatches);
fixName = "0019-Revert-boot-Make-initrd_prepare-semantically-equival.patch";
alreadyPatched = builtins.elem fixName patchNames;
in oldPatches ++ lib.optionals (!alreadyPatched) [
(pkgs.fetchpatch {
url = "https://raw.githubusercontent.com/NixOS/nixpkgs/125e99477b0ac0a54b7cddc6c5a704821a3074c7/pkgs/os-specific/linux/systemd/${fixName}";
hash = "sha256-UW3DZiaykQUUNcGA5UFxN+/wgNSW3ufxDDCZ7emD16o=";
})
];
});
in if systemdBroken then systemdPatched else pkgs.systemd;
hardware.asahi.pkgs =
if cfg.pkgsSystem != "aarch64-linux"
then
import (pkgs.path) {
crossSystem.system = "aarch64-linux";
localSystem.system = cfg.pkgsSystem;
overlays = [ cfg.overlay ];
}
else pkgs;
};
options.hardware.asahi = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Enable the basic Asahi Linux components, such as kernel and boot setup.
'';
};
pkgsSystem = lib.mkOption {
type = lib.types.str;
default = "aarch64-linux";
description = ''
System architecture that should be used to build the major Asahi
packages, if not the default aarch64-linux. This allows installing from
a cross-built ISO without rebuilding them during installation.
'';
};
pkgs = lib.mkOption {
type = lib.types.raw;
description = ''
Package set used to build the major Asahi packages. Defaults to the
ambient set if not cross-built, otherwise re-imports the ambient set
with the system defined by `hardware.asahi.pkgsSystem`.
'';
};
overlay = lib.mkOption {
type = lib.mkOptionType {
name = "nixpkgs-overlay";
description = "nixpkgs overlay";
check = lib.isFunction;
merge = lib.mergeOneOption;
};
default = import ../packages/overlay.nix;
defaultText = "overlay provided with the module";
description = ''
The nixpkgs overlay for asahi packages.
'';
};
};
}

View File

@@ -0,0 +1,106 @@
# the Asahi Linux kernel and options that must go along with it
{ config, pkgs, lib, ... }:
{
config = lib.mkIf config.hardware.asahi.enable {
boot.kernelPackages = let
pkgs' = config.hardware.asahi.pkgs;
in
pkgs'.linux-asahi.override {
_kernelPatches = config.boot.kernelPatches;
withRust = config.hardware.asahi.withRust;
};
# we definitely want to use CONFIG_ENERGY_MODEL, and
# schedutil is a prerequisite for using it
# source: https://www.kernel.org/doc/html/latest/scheduler/sched-energy.html
powerManagement.cpuFreqGovernor = lib.mkOverride 800 "schedutil";
boot.initrd.includeDefaultModules = false;
boot.initrd.availableKernelModules = [
# list of initrd modules stolen from
# https://github.com/AsahiLinux/asahi-scripts/blob/f461f080a1d2575ae4b82879b5624360db3cff8c/initcpio/install/asahi
"apple-mailbox"
"nvme_apple"
"pinctrl-apple-gpio"
"macsmc"
"macsmc-rtkit"
"i2c-pasemi-platform"
"tps6598x"
"apple-dart"
"dwc3"
"dwc3-of-simple"
"xhci-pci"
"pcie-apple"
"gpio_macsmc"
"phy-apple-atc"
"nvmem_apple_efuses"
"spi-apple"
"spi-hid-apple"
"spi-hid-apple-of"
"rtc-macsmc"
"simple-mfd-spmi"
"spmi-apple-controller"
"nvmem_spmi_mfd"
"apple-dockchannel"
"dockchannel-hid"
"apple-rtkit-helper"
# additional stuff necessary to boot off USB for the installer
# and if the initrd (i.e. stage 1) goes wrong
"usb-storage"
"xhci-plat-hcd"
"usbhid"
"hid_generic"
];
boot.kernelParams = [
"earlycon"
"console=tty0"
"boot.shell_on_fail"
# Apple's SSDs are slow (~dozens of ms) at processing flush requests which
# slows down programs that make a lot of fsync calls. This parameter sets
# a delay in ms before actually flushing so that such requests can be
# coalesced. Be warned that increasing this parameter above zero (default
# is 1000) has the potential, though admittedly unlikely, risk of
# UNBOUNDED data corruption in case of power loss!!!! Don't even think
# about it on desktops!!
"nvme_apple.flush_interval=0"
];
# U-Boot does not support EFI variables
boot.loader.efi.canTouchEfiVariables = lib.mkForce false;
# U-Boot does not support switching console mode
boot.loader.systemd-boot.consoleMode = "0";
# GRUB has to be installed as removable if the user chooses to use it
boot.loader.grub = lib.mkDefault {
efiSupport = true;
efiInstallAsRemovable = true;
device = "nodev";
};
# autosuspend was enabled as safe for the PCI SD card reader
# "Genesys Logic, Inc GL9755 SD Host Controller [17a0:9755] (rev 01)"
# by recent systemd versions, but this has a "negative interaction"
# with our kernel/SoC and causes random boot hangs. disable it!
services.udev.extraHwdb = ''
pci:v000017A0d00009755*
ID_AUTOSUSPEND=0
'';
};
imports = [
(lib.mkRemovedOptionModule [ "hardware" "asahi" "addEdgeKernelConfig" ]
"All edge kernel config options are now the default.")
];
options.hardware.asahi.withRust = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Build the Asahi Linux kernel with Rust support.
'';
};
}

View File

@@ -0,0 +1,53 @@
{ options, config, pkgs, lib, ... }:
{
config = let
isMode = mode: (config.hardware.asahi.useExperimentalGPUDriver
&& config.hardware.asahi.experimentalGPUInstallMode == mode);
in lib.mkIf config.hardware.asahi.enable (lib.mkMerge [
{
# required for proper DRM setup even without GPU driver
services.xserver.config = ''
Section "OutputClass"
Identifier "appledrm"
MatchDriver "apple"
Driver "modesetting"
Option "PrimaryGPU" "true"
EndSection
'';
}
(lib.mkIf config.hardware.asahi.useExperimentalGPUDriver {
# install the Asahi Mesa version
hardware.graphics.package = config.hardware.asahi.pkgs.mesa-asahi-edge;
# required for in-kernel GPU driver
hardware.asahi.withRust = true;
})
]);
options.hardware.asahi.useExperimentalGPUDriver = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Use the experimental Asahi Mesa GPU driver.
Do not report issues using this driver under NixOS to the Asahi project.
'';
};
# hopefully no longer used, should be deprecated eventually
options.hardware.asahi.experimentalGPUInstallMode = lib.mkOption {
type = lib.types.enum [ "driver" "replace" "overlay" ];
default = "replace";
description = ''
Mode to use to install the experimental GPU driver into the system.
driver: install only as a driver, do not replace system Mesa.
Causes issues with certain programs like Plasma Wayland.
replace (default): use replaceRuntimeDependencies to replace system Mesa with Asahi Mesa.
Does not work in pure evaluation context (i.e. in flakes by default).
overlay: overlay system Mesa with Asahi Mesa
Requires rebuilding the world.
'';
};
}

View File

@@ -0,0 +1,69 @@
{ config, pkgs, lib, ... }:
{
config = lib.mkIf config.hardware.asahi.enable {
assertions = lib.mkIf config.hardware.asahi.extractPeripheralFirmware [
{ assertion = config.hardware.asahi.peripheralFirmwareDirectory != null;
message = ''
Asahi peripheral firmware extraction is enabled but the firmware
location appears incorrect.
'';
}
];
hardware.firmware = let
pkgs' = config.hardware.asahi.pkgs;
in
lib.mkIf ((config.hardware.asahi.peripheralFirmwareDirectory != null)
&& config.hardware.asahi.extractPeripheralFirmware) [
(pkgs.stdenv.mkDerivation {
name = "asahi-peripheral-firmware";
nativeBuildInputs = [ pkgs'.asahi-fwextract pkgs.cpio ];
buildCommand = ''
mkdir extracted
asahi-fwextract ${config.hardware.asahi.peripheralFirmwareDirectory} extracted
mkdir -p $out/lib/firmware
cat extracted/firmware.cpio | cpio -id --quiet --no-absolute-filenames
mv vendorfw/* $out/lib/firmware
'';
})
];
};
options.hardware.asahi = {
extractPeripheralFirmware = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Automatically extract the non-free non-redistributable peripheral
firmware necessary for features like Wi-Fi.
'';
};
peripheralFirmwareDirectory = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = lib.findFirst (path: builtins.pathExists (path + "/all_firmware.tar.gz")) null
[
# path when the system is operating normally
/boot/asahi
# path when the system is mounted in the installer
/mnt/boot/asahi
];
description = ''
Path to the directory containing the non-free non-redistributable
peripheral firmware necessary for features like Wi-Fi. Ordinarily, this
will automatically point to the appropriate location on the ESP. Flake
users and those interested in maximum purity will want to copy those
files elsewhere and specify this manually.
Currently, this consists of the files `all-firmware.tar.gz` and
`kernelcache*`. The official Asahi Linux installer places these files
in the `asahi` directory of the EFI system partition when creating it.
'';
};
};
}

View File

@@ -0,0 +1,49 @@
{ config, options, pkgs, lib, ... }:
{
options.hardware.asahi = {
setupAsahiSound = lib.mkOption {
type = lib.types.bool;
default = config.hardware.asahi.enable;
description = ''
Set up the Asahi DSP components so that the speakers and headphone jack
work properly and safely.
'';
};
};
config = let
cfg = config.hardware.asahi;
in lib.mkIf (cfg.setupAsahiSound && cfg.enable) (lib.mkMerge [
{
# can't be used by Asahi sound infrastructure
services.pulseaudio.enable = false;
# enable pipewire to run real-time and avoid audible glitches
security.rtkit.enable = true;
# set up pipewire with the supported capabilities (instead of pulseaudio)
# and asahi-audio configs and plugins
services.pipewire = {
enable = true;
alsa.enable = true;
pulse.enable = true;
configPackages = [ pkgs.asahi-audio ];
wireplumber = {
enable = true;
configPackages = [ pkgs.asahi-audio ];
};
};
# set up enivronment so that UCM configs are used as well
environment.variables.ALSA_CONFIG_UCM2 = "${pkgs.alsa-ucm-conf-asahi}/share/alsa/ucm2";
systemd.user.services.pipewire.environment.ALSA_CONFIG_UCM2 = config.environment.variables.ALSA_CONFIG_UCM2;
systemd.user.services.wireplumber.environment.ALSA_CONFIG_UCM2 = config.environment.variables.ALSA_CONFIG_UCM2;
# enable speakersafetyd to protect speakers
systemd.packages = [ pkgs.speakersafetyd ];
services.udev.packages = [ pkgs.speakersafetyd ];
}
]);
}

View File

@@ -0,0 +1,22 @@
{ lib
, fetchFromGitHub
, alsa-ucm-conf
}:
(alsa-ucm-conf.overrideAttrs (oldAttrs: let
versionAsahi = "8";
srcAsahi = fetchFromGitHub {
# tracking: https://src.fedoraproject.org/rpms/alsa-ucm-asahi
owner = "AsahiLinux";
repo = "alsa-ucm-conf-asahi";
rev = "v${versionAsahi}";
hash = "sha256-FPrAzscc1ICSCQSqULaGLqG4UCq8GZU9XLV7TUSBBRM=";
};
in {
name = "${oldAttrs.pname}-${oldAttrs.version}-asahi-${versionAsahi}";
postInstall = oldAttrs.postInstall or "" + ''
cp -r ${srcAsahi}/ucm2 $out/share/alsa
'';
}))

View File

@@ -0,0 +1,46 @@
{ stdenv
, lib
, fetchFromGitHub
, lsp-plugins
, bankstown-lv2
, triforce-lv2
}:
stdenv.mkDerivation rec {
pname = "asahi-audio";
# tracking: https://src.fedoraproject.org/rpms/asahi-audio
version = "3.3";
src = fetchFromGitHub {
owner = "AsahiLinux";
repo = "asahi-audio";
rev = "v${version}";
hash = "sha256-p0M1pPxov+wSLT2F4G6y5NZpCXzbjZkzle+75zQ4xxU=";
};
preBuild = ''
export PREFIX=$out
readarray -t configs < <(\
find . \
-name '*.conf' -or \
-name '*.json' -or \
-name '*.lua'
)
substituteInPlace "''${configs[@]}" --replace \
"/usr/share/asahi-audio" \
"$out/asahi-audio"
'';
postInstall = ''
# no need to link the asahi-audio dir globally
mv $out/share/asahi-audio $out
'';
passthru.requiredLv2Packages = [
lsp-plugins
bankstown-lv2
triforce-lv2
];
}

View File

@@ -0,0 +1,32 @@
{ lib
, python3
, fetchFromGitHub
, gzip
, gnutar
, lzfse
}:
python3.pkgs.buildPythonApplication rec {
pname = "asahi-fwextract";
version = "0.7.8";
# tracking version: https://packages.fedoraproject.org/pkgs/asahi-installer/python3-asahi_firmware/
src = fetchFromGitHub {
owner = "AsahiLinux";
repo = "asahi-installer";
rev = "v${version}";
hash = "sha256-UmgHWKIRbcg9PK44YPPM4tyuEDC0+ANKO3Mzc4N9RHo=";
};
postPatch = ''
substituteInPlace asahi_firmware/img4.py \
--replace 'liblzfse.so' '${lzfse}/lib/liblzfse.so'
substituteInPlace asahi_firmware/update.py \
--replace '"tar"' '"${gnutar}/bin/tar"' \
--replace '"xf"' '"-x", "-I", "${gzip}/bin/gzip", "-f"'
'';
nativeBuildInputs = [ python3.pkgs.setuptools ];
doCheck = false;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,104 @@
{ lib
, callPackage
, writeText
, linuxPackagesFor
, withRust ? true
, _kernelPatches ? [ ]
}:
let
i = builtins.elemAt;
# parse <OPT> [ymn]|foo style configuration as found in a patch's extraConfig
# into a list of k, v tuples
parseExtraConfig = config:
let
lines =
builtins.filter (s: s != "") (lib.strings.splitString "\n" config);
parseLine = line: let
t = lib.strings.splitString " " line;
join = l: builtins.foldl' (a: b: "${a} ${b}")
(builtins.head l) (builtins.tail l);
v = if (builtins.length t) > 2 then join (builtins.tail t) else (i t 1);
in [ "CONFIG_${i t 0}" v ];
in map parseLine lines;
# parse <OPT>=lib.kernel.(yes|module|no)|lib.kernel.freeform "foo"
# style configuration as found in a patch's extraStructuredConfig into
# a list of k, v tuples
parseExtraStructuredConfig = config: lib.attrsets.mapAttrsToList
(k: v: [ "CONFIG_${k}" (v.tristate or v.freeform) ] ) config;
parsePatchConfig = { extraConfig ? "", extraStructuredConfig ? {}, ... }:
(parseExtraConfig extraConfig) ++
(parseExtraStructuredConfig extraStructuredConfig);
# parse CONFIG_<OPT>=[ymn]|"foo" style configuration as found in a config file
# into a list of k, v tuples
parseConfig = config:
let
parseLine = builtins.match ''(CONFIG_[[:upper:][:digit:]_]+)=(([ymn])|"([^"]*)")'';
# get either the [ymn] option or the "foo" option; whichever matched
t = l: let v = (i l 2); in [ (i l 0) (if v != null then v else (i l 3)) ];
lines = lib.strings.splitString "\n" config;
in map t (builtins.filter (l: l != null) (map parseLine lines));
origConfigfile = ./config;
linux-asahi-pkg = { stdenv, lib, fetchFromGitHub, fetchpatch, linuxKernel,
rustc, rust-bindgen, ... } @ args:
let
origConfigText = builtins.readFile origConfigfile;
# extraConfig from all patches in order
extraConfig =
lib.fold (patch: ex: ex ++ (parsePatchConfig patch)) [] _kernelPatches
++ (lib.optional withRust [ "CONFIG_RUST" "y" ]);
# config file text for above
extraConfigText = let
text = k: v: if (v == "y") || (v == "m") || (v == "n")
then "${k}=${v}" else ''${k}="${v}"'';
in (map (t: text (i t 0) (i t 1)) extraConfig);
# final config as a text file path
configfile = if extraConfig == [] then origConfigfile else
writeText "config" ''
${origConfigText}
# Patches
${lib.strings.concatStringsSep "\n" extraConfigText}
'';
# final config as an attrset
configAttrs = let
makePair = t: lib.nameValuePair (i t 0) (i t 1);
configList = (parseConfig origConfigText) ++ extraConfig;
in builtins.listToAttrs (map makePair (lib.lists.reverseList configList));
# used to fix issues when nixpkgs gets ahead of the kernel
rustAtLeast = version: withRust && (lib.versionAtLeast rustc.version version);
bindgenAtLeast = version: withRust && (lib.versionAtLeast rust-bindgen.unwrapped.version version);
in
linuxKernel.manualConfig rec {
inherit stdenv lib;
version = "6.14.8-asahi";
modDirVersion = version;
extraMeta.branch = "6.14";
src = fetchFromGitHub {
# tracking: https://github.com/AsahiLinux/linux/tree/asahi-wip (w/ fedora verification)
owner = "AsahiLinux";
repo = "linux";
rev = "asahi-6.14.8-1";
hash = "sha256-JrWVw1FiF9LYMiOPm0QI0bg/CrZAMSSVcs4AWNDIH3Q=";
};
kernelPatches = [
] ++ _kernelPatches;
inherit configfile;
config = configAttrs;
};
linux-asahi = (callPackage linux-asahi-pkg { });
in lib.recurseIntoAttrs (linuxPackagesFor linux-asahi)

View File

@@ -0,0 +1,110 @@
{ stdenv
, buildPackages
, lib
, fetchFromGitHub
, python3
, dtc
, imagemagick
, isRelease ? false
, withTools ? true
, withChainloading ? false
, customLogo ? null
}:
let
pyenv = python3.withPackages (p: with p; [
construct
pyserial
]);
stdenvOpts = {
targetPlatform.system = "aarch64-none-elf";
targetPlatform.rust.rustcTarget = "${stdenv.hostPlatform.parsed.cpu.name}-unknown-none-softfloat";
targetPlatform.rust.rustcTargetSpec = "${stdenv.hostPlatform.parsed.cpu.name}-unknown-none-softfloat";
};
rust = buildPackages.rust.override {
stdenv = lib.recursiveUpdate buildPackages.stdenv stdenvOpts;
};
rustPackages = rust.packages.stable.overrideScope (f: p: {
rustc-unwrapped = p.rustc-unwrapped.override {
stdenv = lib.recursiveUpdate p.rustc-unwrapped.stdenv stdenvOpts;
};
});
rustPlatform = buildPackages.makeRustPlatform rustPackages;
in stdenv.mkDerivation rec {
pname = "m1n1";
version = "1.4.21";
src = fetchFromGitHub {
# tracking: https://src.fedoraproject.org/rpms/m1n1
owner = "AsahiLinux";
repo = "m1n1";
rev = "v${version}";
hash = "sha256-PEjTaSwcsV8PzM9a3rDWMYXGX9FlrM0oeElrP5HYRPg=";
fetchSubmodules = true;
};
cargoVendorDir = ".";
makeFlags = [ "ARCH=${stdenv.cc.targetPrefix}" ]
++ lib.optional isRelease "RELEASE=1"
++ lib.optional withChainloading "CHAINLOADING=1";
nativeBuildInputs = [
dtc
] ++ lib.optionals withChainloading [rustPackages.rustc rustPackages.cargo rustPlatform.cargoSetupHook]
++ lib.optional (customLogo != null) imagemagick;
postPatch = ''
substituteInPlace proxyclient/m1n1/asm.py \
--replace 'aarch64-linux-gnu-' 'aarch64-unknown-linux-gnu-' \
--replace 'TOOLCHAIN = ""' 'TOOLCHAIN = "'$out'/toolchain-bin/"'
'';
preConfigure = lib.optionalString (customLogo != null) ''
pushd data &>/dev/null
ln -fs ${customLogo} bootlogo_256.png
if [[ "$(magick identify bootlogo_256.png)" != 'bootlogo_256.png PNG 256x256'* ]]; then
echo "Custom logo is not a 256x256 PNG"
exit 1
fi
rm bootlogo_128.png
convert bootlogo_256.png -resize 128x128 bootlogo_128.png
patchShebangs --build ./makelogo.sh
./makelogo.sh
popd &>/dev/null
'';
installPhase = ''
runHook preInstall
mkdir -p $out/build
cp build/m1n1.bin $out/build
'' + (lib.optionalString withTools ''
mkdir -p $out/{bin,script,toolchain-bin}
cp -r proxyclient $out/script
cp -r tools $out/script
for toolpath in $out/script/proxyclient/tools/*.py; do
tool=$(basename $toolpath .py)
script=$out/bin/m1n1-$tool
cat > $script <<EOF
#!/bin/sh
${pyenv}/bin/python $toolpath "\$@"
EOF
chmod +x $script
done
GCC=${buildPackages.gcc}
BINUTILS=${buildPackages.binutils-unwrapped}
ln -s $GCC/bin/${stdenv.cc.targetPrefix}gcc $out/toolchain-bin/
ln -s $GCC/bin/${stdenv.cc.targetPrefix}ld $out/toolchain-bin/
ln -s $BINUTILS/bin/${stdenv.cc.targetPrefix}objcopy $out/toolchain-bin/
ln -s $BINUTILS/bin/${stdenv.cc.targetPrefix}objdump $out/toolchain-bin/
ln -s $GCC/bin/${stdenv.cc.targetPrefix}nm $out/toolchain-bin/
'') + ''
runHook postInstall
'';
}

View File

@@ -0,0 +1,48 @@
{ lib
, fetchFromGitLab
, mesa
}:
(mesa.override {
galliumDrivers = [ "softpipe" "llvmpipe" "asahi" ];
vulkanDrivers = [ "swrast" "asahi" ];
}).overrideAttrs (oldAttrs: {
version = "25.1.0-asahi";
src = fetchFromGitLab {
# tracking: https://pagure.io/fedora-asahi/mesa/commits/asahi
domain = "gitlab.freedesktop.org";
owner = "asahi";
repo = "mesa";
tag = "asahi-20250425";
hash = "sha256-3c3uewzKv5wL9BRwaVL4E3FnyA04veQwAPxfHiL7wII=";
};
mesonFlags =
let
badFlags = [
"-Dinstall-mesa-clc"
"-Dgallium-nine"
"-Dtools"
];
isBadFlagList = f: builtins.map (b: lib.hasPrefix b f) badFlags;
isGoodFlag = f: !(builtins.foldl' (x: y: x || y) false (isBadFlagList f));
in
(builtins.filter isGoodFlag oldAttrs.mesonFlags) ++ [
# we do not build any graphics drivers these features can be enabled for
"-Dgallium-va=disabled"
"-Dgallium-vdpau=disabled"
"-Dgallium-xa=disabled"
"-Dtools=asahi"
];
# replace patches with ones tweaked slightly to apply to this version
patches = [
./opencl.patch
];
postInstall = (oldAttrs.postInstall or "") + ''
# we don't build anything to go in this output but it needs to exist
touch $spirv2dxil
touch $cross_tools
'';
})

View File

@@ -0,0 +1,54 @@
diff --git a/meson.build b/meson.build
index 07991a6..4c875b9 100644
--- a/meson.build
+++ b/meson.build
@@ -1900,7 +1900,7 @@ endif
dep_clang = null_dep
if with_clc or with_gallium_clover
- llvm_libdir = dep_llvm.get_variable(cmake : 'LLVM_LIBRARY_DIR', configtool: 'libdir')
+ llvm_libdir = get_option('clang-libdir')
dep_clang = cpp.find_library('clang-cpp', dirs : llvm_libdir, required : false)
diff --git a/meson.options b/meson.options
index 84e0f20..38ea92c 100644
--- a/meson.options
+++ b/meson.options
@@ -795,3 +795,10 @@ option(
value : false,
description : 'Install the drivers internal shader compilers (if needed for cross builds).'
)
+
+option(
+ 'clang-libdir',
+ type : 'string',
+ value : '',
+ description : 'Locations to search for clang libraries.'
+)
diff --git a/src/gallium/targets/opencl/meson.build b/src/gallium/targets/opencl/meson.build
index ab2c835..a59e88e 100644
--- a/src/gallium/targets/opencl/meson.build
+++ b/src/gallium/targets/opencl/meson.build
@@ -56,7 +56,7 @@ if with_opencl_icd
configuration : _config,
input : 'mesa.icd.in',
output : 'mesa.icd',
- install : true,
+ install : false,
install_tag : 'runtime',
install_dir : join_paths(get_option('sysconfdir'), 'OpenCL', 'vendors'),
)
diff --git a/src/gallium/targets/rusticl/meson.build b/src/gallium/targets/rusticl/meson.build
index 2b214ad..7f91939 100644
--- a/src/gallium/targets/rusticl/meson.build
+++ b/src/gallium/targets/rusticl/meson.build
@@ -64,7 +64,7 @@ configure_file(
configuration : _config,
input : 'rusticl.icd.in',
output : 'rusticl.icd',
- install : true,
+ install : false,
install_tag : 'runtime',
install_dir : join_paths(get_option('sysconfdir'), 'OpenCL', 'vendors'),
)

View File

@@ -0,0 +1,9 @@
final: prev: {
linux-asahi = final.callPackage ./linux-asahi { };
m1n1 = final.callPackage ./m1n1 { };
uboot-asahi = final.callPackage ./uboot-asahi { };
asahi-fwextract = final.callPackage ./asahi-fwextract { };
mesa-asahi-edge = final.callPackage ./mesa-asahi-edge { };
alsa-ucm-conf-asahi = final.callPackage ./alsa-ucm-conf-asahi { inherit (prev) alsa-ucm-conf; };
asahi-audio = final.callPackage ./asahi-audio { };
}

View File

@@ -0,0 +1,44 @@
{ lib
, fetchFromGitHub
, buildUBoot
, m1n1
}:
(buildUBoot rec {
src = fetchFromGitHub {
# tracking: https://pagure.io/fedora-asahi/uboot-tools/commits/main
owner = "AsahiLinux";
repo = "u-boot";
rev = "asahi-v2025.04-1";
hash = "sha256-/z37qj26AqsyEBsFT6UEN3GjG6KVsoJOoUB4s9BRDbE=";
};
version = "2025.04-1-asahi";
defconfig = "apple_m1_defconfig";
extraMeta.platforms = [ "aarch64-linux" ];
filesToInstall = [
"u-boot-nodtb.bin.gz"
"m1n1-u-boot.bin"
];
extraConfig = ''
CONFIG_IDENT_STRING=" ${version}"
CONFIG_VIDEO_FONT_4X6=n
CONFIG_VIDEO_FONT_8X16=n
CONFIG_VIDEO_FONT_SUN12X22=n
CONFIG_VIDEO_FONT_16X32=y
CONFIG_CMD_BOOTMENU=y
'';
}).overrideAttrs (o: {
# nixos's downstream patches are not applicable
patches = [
];
# DTC= flag somehow breaks DTC compilation so we remove it
makeFlags = builtins.filter (s: (!(lib.strings.hasPrefix "DTC=" s))) o.makeFlags;
preInstall = ''
# compress so that m1n1 knows U-Boot's size and can find things after it
gzip -n u-boot-nodtb.bin
cat ${m1n1}/build/m1n1.bin arch/arm/dts/t[68]*.dtb u-boot-nodtb.bin.gz > m1n1-u-boot.bin
'';
})

View File

@@ -0,0 +1,34 @@
{ pkgs, lib, ... }:
{
# Use the systemd-boot EFI boot loader.
boot = {
loader = {
systemd-boot = {
enable = true;
configurationLimit = 15;
consoleMode = lib.mkDefault "max";
};
efi.canTouchEfiVariables = lib.mkForce false;
};
kernelParams = [
"apple_dcp.show_notch=1"
];
extraModprobeConfig = ''
options hid_apple iso_layout=0
'';
binfmt.registrations. "x86_64-linux" = {
magicOrExtension = ''\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00'';
mask = ''\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'';
openBinary = true;
interpreter = "${pkgs.box64}/bin/box64";
preserveArgvZero = true;
matchCredentials = true;
fixBinary = false;
};
};
zramSwap.enable = true;
}

View File

@@ -0,0 +1,70 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{ pkgs, lib, ... }:
let
plasma = false;
in
{
imports = [
./boot.nix
./hardware-configuration.nix
./networking.nix
./services.nix
];
hardware.asahi = {
enable = true;
useExperimentalGPUDriver = true;
peripheralFirmwareDirectory = ./firmware;
setupAsahiSound = true;
};
hardware.graphics.enable32Bit = lib.mkForce false;
nixpkgs.config.allowUnfree = true;
nixpkgs.config.allowUnsupportedSystem = true;
# Define a user account. Don't forget to set a password with passwd.
users.users.matt = {
isNormalUser = true;
extraGroups = [
"wheel"
"keys"
"networkmanager"
"ratbagd"
"input"
"scanner"
"lp"
"video"
"i2c"
]; # Enable sudo for the user.
shell = pkgs.zsh;
packages = with pkgs; [
firefox
tree
git
box64
prismlauncher
distrobox
];
};
virtualisation = {
containers.enable = true;
podman.enable = true;
};
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
micro
vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
wget
];
environment.sessionVariables = {
DBX_CONTAINER_MANAGER = "podman";
};
}

Binary file not shown.

View File

@@ -0,0 +1,78 @@
# 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, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "uas" "sdhci_pci" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "none";
fsType = "tmpfs";
};
fileSystems."/root" =
{ device = "/dev/disk/by-uuid/adcc14fa-8bf7-4b4b-a9e4-b038993b96cc";
fsType = "btrfs";
options = [ "compress=zstd" "noatime" "subvol=root" ];
};
fileSystems."/etc" =
{ device = "/dev/disk/by-uuid/adcc14fa-8bf7-4b4b-a9e4-b038993b96cc";
fsType = "btrfs";
options = [ "compress=zstd" "noatime" "subvol=etc" ];
};
fileSystems."/tmp" =
{ device = "/dev/disk/by-uuid/adcc14fa-8bf7-4b4b-a9e4-b038993b96cc";
fsType = "btrfs";
options = [ "compress=zstd" "noatime" "subvol=tmp" ];
};
fileSystems."/nix" =
{ device = "/dev/disk/by-uuid/adcc14fa-8bf7-4b4b-a9e4-b038993b96cc";
fsType = "btrfs";
options = [ "compress=zstd" "noatime" "subvol=nix" ];
};
fileSystems."/var/log" =
{ device = "/dev/disk/by-uuid/adcc14fa-8bf7-4b4b-a9e4-b038993b96cc";
fsType = "btrfs";
options = [ "compress=zstd" "noatime" "subvol=log" ];
};
fileSystems."/home" =
{ device = "/dev/disk/by-uuid/adcc14fa-8bf7-4b4b-a9e4-b038993b96cc";
fsType = "btrfs";
options = [ "compress=zstd" "subvol=home" ];
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/23FA-AD3E";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
};
swapDevices = [
{
device = "/tmp/swapfile";
randomEncryption.enable = true;
}
];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.wlan0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
}

View File

@@ -0,0 +1,28 @@
{ pkgs, ... }:
let
shellAliases = {
update-boot = "sudo nixos-rebuild boot --max-jobs 10 --build-host admin@10.0.1.3";
update-switch = "sudo nixos-rebuild switch --max-jobs 10 --build-host admin@10.0.1.3";
update-flake = "nix flake update mac-nixpkgs mac-nixos-apple-silicon mac-home-manager mac-impermanence mac-sops-nix --flake /etc/nixos";
update-nas = "nixos-rebuild switch --use-remote-sudo --target-host admin@10.0.1.3 --build-host admin@10.0.1.3 --flake ~/nix-config#jallen-nas";
};
in
{
home.username = "matt";
home.homeDirectory = "/home/matt";
home.stateVersion = "23.11";
home.packages = with pkgs; [
iw
iwd
orca-slicer
vscodium
];
programs = {
password-store.enable = true;
zsh.shellAliases = shellAliases;
};
}

View File

@@ -0,0 +1,82 @@
let
theme = import ../../modules/desktop-environments/hyprland/theme.nix;
# Displays
display = {
input = "eDP-1";
resolution = "3456x2234";
refreshRate = "60.00000";
};
in
{
primaryDisplay = display;
networkInterface = "wlan0";
wallpaper = [
"${display.input}, /run/wallpaper.jpg"
];
monitor = [
"${display.input},${display.resolution}@${display.refreshRate},0x0,1.25,bitdepth,10,cm,hdr,sdrbrightness,1.2,sdrsaturation,0.98"
];
# monitorv2 = {
# output = "eDP-1";
# mode = "3456x2234@60.00000";
# position = "0x0";
# scale = "1.25";
# #bitdepth,10,cm,hdr,sdrbrightness,1.2,sdrsaturation,0.98"
# };
workspace = [
"name:firefox, monitor:${display.input}, default:false, special, class:(.*firefox.*)"
"name:discord, monitor:${display.input}, default:true, special, title:(.*vesktop.*), title:(.*Apple Music.*)"
"name:steam, monitor:${display.input}, default:false, special, class:(.*[Ss]team.*)"
];
windowRule = [
# "tag +fakefull, fullscreen: 0"
# "float, tag:fakefull"
# "size 3356 2160, tag:fakefull"
# "move 100 74, tag:fakefull"
# "noanim, tag:fakefull"
# "noblur, tag:fakefull"
# "norounding, tag:fakefull"
# "noshadow, tag:fakefull"
# "immediate, tag:fakefull"
# "noborder, tag:fakefull"
# "nodim, tag:fakefull"
# "idleinhibit, tag:fakefull"
"size 2160 3356, tag:horizonrdp"
];
waybar = {
layer = "top";
modules-right = [
"tray"
"temperature"
"temperature#gpu"
"keyboard-state#capslock"
"keyboard-state#numlock"
"wireplumber#sink"
# "wireplumber#source"
"bluetooth"
"network"
"idle_inhibitor"
"clock"
"battery"
"custom/weather"
];
moduleStyle = {
window = {
margin-right = "75rem";
};
temperature = {
location = "${theme.waybar.borderLeft}";
border-radius = "1";
};
};
};
}

View File

@@ -0,0 +1,44 @@
{ pkgs, lib, ... }:
{
# Networking configs
networking = {
hostName = "macbook-pro-nixos";
wireless.iwd = {
enable = true;
settings = {
General = {
EnableNetworkConfiguration = true;
};
Rank = {
BandModifier2_4GHz = 1.0;
BandModifier5GHz = 5.0;
BandModifier6GHz = 10.0;
};
# DriverQuirks = {
# PowerSaveDisable = "hci_bcm4377,brcmfmac";
# };
Network = {
AutoConnect = true;
};
};
};
# Enable Network Manager
networkmanager = {
enable = lib.mkForce false;
wifi = {
backend = lib.mkForce "iwd";
powersave = lib.mkDefault false;
};
settings.connectivity.uri = lib.mkDefault "http://nmcheck.gnome.org/check_network_status.txt";
};
# orca
firewall.extraCommands = ''
iptables -I INPUT -m pkttype --pkt-type multicast -j ACCEPT
iptables -A INPUT -m pkttype --pkt-type multicast -j ACCEPT
iptables -I INPUT -p udp -m udp --match multiport --dports 1990,2021 -j ACCEPT
'';
};
}

View File

@@ -0,0 +1,123 @@
{ stdenv
, lib
, buildFHSEnv
, fetchurl
, makeWrapper
, gsettings-desktop-schemas
, opensc
, writeTextDir
, configText ? ""
}:
let
version = "2503-8.15.0";
sysArch = "armhf";
mainProgram = "horizon-client";
wrapBinCommands = path: name: ''
makeWrapper "$out/${path}/${name}" "$out/bin/${name}_wrapper" \
--set GTK_THEME Adwaita \
--suffix XDG_DATA_DIRS : "${gsettings-desktop-schemas}/share/gsettings-schemas/${gsettings-desktop-schemas.name}" \
--suffix LD_LIBRARY_PATH : "$out/lib/omnissa/horizon:$out/lib/omnissa/horizon/vdpService:$out/lib/omnissa"
'';
omnissaHorizonClientFiles = stdenv.mkDerivation {
pname = "omnissa-horizon-armhf-files";
inherit version;
src = fetchurl {
url = "https://download3.omnissa.com/software/CART26FQ1_LIN_2503_TARBALL/Omnissa-Horizon-Client-Linux-2503-8.15.0-14256322247.tar.gz";
sha256 = "sha256-x98ITXF9xwzlPq375anQ2qBpMbZAcCqDVXBfvZPha7Q=";
};
nativeBuildInputs = [ makeWrapper ];
installPhase = ''
mkdir ext
tar -xzf $src
cd Omnissa-Horizon-Client-Linux-*/${sysArch}
mkdir -p ext
for archive in *.tar.gz; do
tar -C ext --strip-components=1 -xf "$archive"
done
chmod -R u+w ext/usr/lib
mkdir -p $out
mv ext/usr $out
mv ext/${sysArch}/lib $out/
mv ext/${sysArch}/include $out/
mkdir -p $out/lib/omnissa/horizon/pkcs11
ln -s ${opensc}/lib/pkcs11/opensc-pkcs11.so $out/lib/omnissa/horizon/pkcs11/libopenscpkcs11.so
chmod +x "$out/usr/bin/horizon-client"
${wrapBinCommands "usr/bin" "horizon-client"}
'';
};
omnissaFHSUserEnv =
pname:
buildFHSEnv {
inherit pname version;
runScript = "${omnissaHorizonClientFiles}/bin/${pname}_wrapper";
targetPkgs = pkgs: with pkgs; [
atk
cairo
dbus
file
fontconfig
freetype
gdk-pixbuf
glib
gtk3
libjpeg
libpng
libpulseaudio
libtiff
libuuid
libv4l
libxml2
pango
pcsclite
pixman
udev
omnissaHorizonClientFiles
xorg.libX11
xorg.libXau
xorg.libXcursor
xorg.libXext
xorg.libXi
xorg.libXrandr
xorg.libXrender
xorg.libXtst
zlib
(writeTextDir "etc/omnissa/config" configText)
];
};
in
stdenv.mkDerivation {
pname = "omnissa-horizon-client";
inherit version;
dontUnpack = true;
installPhase = ''
mkdir -p $out/bin
ln -s ${omnissaFHSUserEnv "horizon-client"}/bin/horizon-client $out/bin/
ln -s ${omnissaFHSUserEnv "horizon-eucusbarbitrator"}/bin/horizon-eucusbarbitrator $out/bin/
'';
passthru.unwrapped = omnissaHorizonClientFiles;
meta = {
description = "Omnissa Horizon Client for ARM";
homepage = "https://www.omnissa.com/products/horizon-8/";
license = lib.licenses.unfree;
platforms = [ "aarch64-linux" "armv7l-linux" ];
};
}

View File

@@ -0,0 +1,130 @@
{ lib, ... }:
{
services = {
auto-cpufreq = {
enable = true;
settings = {
# settings for when connected to a power source
charger = {
# see available governors by running: cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
# preferred governor
governor = "performance";
# minimum cpu frequency (in kHz)
# example: for 800 MHz = 800000 kHz --> scaling_min_freq = 800000
# see conversion info: https://www.rapidtables.com/convert/frequency/mhz-to-hz.html
# to use this feature, uncomment the following line and set the value accordingly
# scaling_min_freq = 800000
# maximum cpu frequency (in kHz)
# example: for 1GHz = 1000 MHz = 1000000 kHz -> scaling_max_freq = 1000000
# see conversion info: https://www.rapidtables.com/convert/frequency/mhz-to-hz.html
# to use this feature, uncomment the following line and set the value accordingly
# scaling_max_freq = 1000000
# turbo boost setting. possible values: always, auto, never
turbo = "auto";
};
# settings for when using battery power
battery = {
# see available governors by running: cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
# preferred governor
governor = "schedutil";
# minimum cpu frequency (in kHz)
# example: for 800 MHz = 800000 kHz --> scaling_min_freq = 800000
# see conversion info: https://www.rapidtables.com/convert/frequency/mhz-to-hz.html
# to use this feature, uncomment the following line and set the value accordingly
# scaling_min_freq = 800000
# maximum cpu frequency (in kHz)
# see conversion info: https://www.rapidtables.com/convert/frequency/mhz-to-hz.html
# example: for 1GHz = 1000 MHz = 1000000 kHz -> scaling_max_freq = 1000000
# to use this feature, uncomment the following line and set the value accordingly
# scaling_max_freq = 1000000
# turbo boost setting (always, auto, or never)
turbo = "auto";
# battery charging threshold
# reference: https://github.com/AdnanHodzic/auto-cpufreq/#battery-charging-thresholds
#enable_thresholds = true
#start_threshold = 20
#stop_threshold = 80
};
};
};
displayManager = {
sddm = {
enable = lib.mkForce true;
wayland.enable = lib.mkForce true;
};
gdm.enable = lib.mkForce false;
};
desktopManager = {
plasma6.enable = lib.mkForce false;
gnome.enable = lib.mkForce false;
};
logind = {
lidSwitch = "suspend";
lidSwitchExternalPower = "ignore";
powerKey = "suspend";
powerKeyLongPress = "poweroff";
};
# Enable Flatpak
flatpak.enable = lib.mkDefault false;
gvfs.enable = true;
keyd = {
enable = true;
keyboards = {
default = {
ids = [ "*" ];
settings = {
main = {
# Use ⌘ key (leftmeta) to activate macOS-like layer
leftmeta = "layer(meta_mac)";
};
meta_mac = {
# Tab switching
tab = "swapm(app_switch_state, M-tab)";
"`" = "A-f6";
# App shortcuts
c = "C-insert"; # Copy
v = "S-insert"; # Paste
x = "S-delete"; # Cut
"1" = "A-1";
"2" = "A-2";
"3" = "A-3";
"4" = "A-4";
"5" = "A-5";
"6" = "A-6";
"7" = "A-7";
"8" = "A-8";
"9" = "A-9";
# Move to line start/end
left = "home";
right = "end";
};
app_switch_state = {
tab = "M-tab";
right = "M-tab";
"`" = "M-S-tab";
left = "M-S-tab";
};
};
};
};
};
};
}

View File

@@ -0,0 +1,70 @@
{ config, ... }:
let
user = "matt";
in
{
# Permission modes are in octal representation (same as chmod),
# the digits represent: user|group|others
# 7 - full (rwx)
# 6 - read and write (rw-)
# 5 - read and execute (r-x)
# 4 - read only (r--)
# 3 - write and execute (-wx)
# 2 - write only (-w-)
# 1 - execute only (--x)
# 0 - none (---)
# Either a user id or group name representation of the secret owner
# It is recommended to get the user name from `config.users.users.<?name>.name` to avoid misconfiguration
# Either the group id or group name representation of the secret group
# It is recommended to get the group name from `config.users.users.<?name>.group` to avoid misconfiguration
sops = {
defaultSopsFile = ../../secrets/secrets.yaml;
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
# ------------------------------
# Secrets
# ------------------------------
secrets = {
"wifi" = {
sopsFile = ../../secrets/secrets.yaml;
};
# ------------------------------
# SSH keys
# ------------------------------
# "ssh-keys-public/desktop-nixos" = {
# sopsFile = ../../secrets/secrets.yaml;
# mode = "0644";
# owner = config.users.users."${user}".name;
# group = config.users.users."${user}".group;
# restartUnits = [ "sshd.service" ];
# };
# "ssh-keys-private/desktop-nixos" = {
# sopsFile = ../../secrets/secrets.yaml;
# mode = "0600";
# owner = config.users.users."${user}".name;
# group = config.users.users."${user}".group;
# restartUnits = [ "sshd.service" ];
# };
# "ssh-keys-public/desktop-nixos-root" = {
# sopsFile = ../../secrets/secrets.yaml;
# path = "/root/.ssh/id_ed25519.pub";
# mode = "0600";
# restartUnits = [ "sshd.service" ];
# };
# "ssh-keys-private/desktop-nixos-root" = {
# sopsFile = ../../secrets/secrets.yaml;
# path = "/root/.ssh/id_ed25519";
# mode = "0600";
# restartUnits = [ "sshd.service" ];
# };
};
# ------------------------------
# Templates
# ------------------------------
templates = {
# ...
};
};
}

View File

@@ -0,0 +1,57 @@
{ ... }:
{
services.adguardhome = {
enable = true;
openFirewall = true;
allowDHCP = true;
mutableSettings = true;
settings = {
http.address = "0.0.0.0:0";
users = [
{
name = "mjallen";
password = "$2a$10$G07P7V1EnBQxWtMNGyfgTOTpAgr4d.uqYoG.cGSFCv9jQdiYWCsfq";
}
];
dns = {
upstream_dns = [
"https://dns10.quad9.net/dns-query"
"1.1.1.1"
"8.8.8.8"
];
bootstrap_dns = [
"9.9.9.10"
"149.112.112.10"
"2620:fe::10"
"2620:fe::fe:10"
];
upstream_mode = "load_balance";
trusted_proxies = [
"127.0.0.0/8"
"::1/128"
"10.0.1.3"
];
cache_optimistic = true;
};
dhcp = {
enabled = false;
interface_name = "end0";
local_domain_name = "lan";
dhcpv4 = {
gateway_ip = "10.0.1.1";
subnet_mask = "255.255.255.0";
range_start = "10.0.1.100";
range_end = "10.0.1.254";
lease_duration = 86400;
icmp_timeout_msec = 1000;
};
dhcpv6 = {
range_start = "2001::1";
lease_duration = 86400;
ra_slaac_only = false;
ra_allow_slaac = false;
};
};
};
};
}

View File

@@ -0,0 +1,69 @@
# { ... }:
# {
# programs.argon.one = {
# enable = true;
# settings = {
# # Is 'celsius' by default, can also be set to 'fahrenheit'
# displayUnits = "celsius";
# # This is the same config as the original Argon40 config.
# # This is also the default config for this flake.
# fanspeed = [
# {
# # This the temperature threshold at which this fan speed will activate.
# # The temperature is in the above specified unit.
# temperature = 55;
# # This is speed percentage at which the fan will spin.
# speed = 30;
# }
# {
# temperature = 60;
# speed = 55;
# }
# {
# temperature = 65;
# speed = 100;
# }
# ];
# ir = {
# enable = true;
# gpio.enable = true;
# keymap = {
# "POWER" = "00ff39c6";
# "UP" = "00ff53ac";
# "DOWN" = "00ff4bb4";
# "LEFT" = "00ff9966";
# "RIGHT" = "00ff837c";
# "VOLUMEUP" = "00ff01fe";
# "VOLUMEDOWN" = "00ff817e";
# "OK" = "00ff738c";
# "HOME" = "00ffd32c";
# "MENU" = "00ffb946";
# "BACK" = "00ff09f6";
# };
# };
# };
# };
# }
# { lib, stdenv, pkgs, config, ...}:
# {
# imports = let
# argononed = fetchGit {
# url = "https://github.com/mjallen18/argononed.git";
# ref = "dev"; # Or any other branches deemed suitable
# };
# in
# [ "${argononed}/OS/nixos" ];
# services.argonone = {
# enable = true;
# logLevel = 4;
# settings = {
# fanTemp0 = 36; fanSpeed0 = 10;
# fanTemp1 = 41; fanSpeed1 = 50;
# fanTemp2 = 46; fanSpeed2 = 80;
# hysteresis = 4;
# };
# };
# }

View File

@@ -0,0 +1,78 @@
# { pkgs, lib, ... }:
# let
# uefi_pi4 = pkgs.callPackage ./pi4-uefi.nix { };
# in
# {
# boot = {
# loader = {
# systemd-boot.enable = lib.mkForce false;
# efi.canTouchEfiVariables = false;
# generic-extlinux-compatible.enable = lib.mkForce true;
# };
# plymouth.enable = false;
# kernelPackages = pkgs.linuxPackages_rpi4;
# kernelModules = [ "i2c-dev" "i2c-bcm2835" ];
# initrd.kernelModules = [ "i2c-dev" "i2c-bcm2835" ];
# };
# # environment.systemPackages = [ uefi_pi4 ];
# # Copy UEFI firmware files to the boot partition
# # system.activationScripts.installUEFIFirmware.text = ''
# # cp -r ${uefi_pi4}/share/uefi_rpi4/* /boot/firmware/
# # '';
# }
{ pkgs, lib, ... }:
let
kernelBundle = pkgs.linuxAndFirmware.latest;
in
{
boot = {
loader.raspberryPi.firmwarePackage = kernelBundle.raspberrypifw;
kernelPackages = kernelBundle.linuxPackages_rpi4;
};
hardware.raspberry-pi.config = {
all = { # [all] conditional filter, https://www.raspberrypi.com/documentation/computers/config_txt.html#conditional-filters
base-dt-params = {
i2c_arm = {
enable = true;
value = "on";
};
i2c = {
enable = true;
value = "on";
};
spi = {
enable = true;
value = "on";
};
};
options = {
# https://www.raspberrypi.com/documentation/computers/config_txt.html#enable_uart
# in conjunction with `console=serial0,115200` in kernel command line (`cmdline.txt`)
# creates a serial console, accessible using GPIOs 14 and 15 (pins
# 8 and 10 on the 40-pin header)
enable_uart = {
enable = true;
value = true;
};
# https://www.raspberrypi.com/documentation/computers/config_txt.html#uart_2ndstage
# enable debug logging to the UART, also automatically enables
# UART logging in `start.elf`
uart_2ndstage = {
enable = true;
value = true;
};
};
# Base DTB parameters
# https://github.com/raspberrypi/linux/blob/a1d3defcca200077e1e382fe049ca613d16efd2b/arch/arm/boot/dts/overlays/README#L132
base-dt-params = {
};
};
};
}

View File

@@ -0,0 +1,113 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{ config, lib, pkgs, ... }:
let
user = "matt";
# password = config.sops.secrets."pi4/matt-password".path;
kernelBundle = pkgs.linuxAndFirmware.latest;
in
{
imports = [
./adguard.nix
./boot.nix
./impermanence.nix
./networking.nix
./sops.nix
];
nix = {
settings = {
substituters = [
"https://nixos-raspberrypi.cachix.org"
"https://cache.mjallen.dev"
];
trusted-public-keys = [
"nixos-raspberrypi.cachix.org-1:4iMO9LXa8BqhU+Rpg6LQKiGa2lsNh/j2oiYLNOQ5sPI="
"cache.mjallen.dev-1:IzFmKCd8/gggI6lcCXsW65qQwiCLGFFN9t9s2iw7Lvc="
];
};
};
# Configure nixpkgs
nixpkgs = {
overlays = lib.mkAfter [
(self: super: {
# This is used in (modulesPath + "/hardware/all-firmware.nix") when at least
# enableRedistributableFirmware is enabled
# I know no easier way to override this package
inherit (kernelBundle) raspberrypiWirelessFirmware;
# Some derivations want to use it as an input,
# e.g. raspberrypi-dtbs, omxplayer, sd-image-* modules
inherit (kernelBundle) raspberrypifw;
})
];
};
system.nixos.tags = let
cfg = config.boot.loader.raspberryPi;
in [
"raspberry-pi-${cfg.variant}"
cfg.bootloader
config.boot.kernelPackages.kernel.version
];
programs.zsh.enable = true;
hardware.i2c.enable = true;
services = {
openssh = {
enable = true;
authorizedKeysFiles = [
config.sops.secrets."ssh-keys-public/pi5".path
];
hostKeys = [ ];
};
};
systemd.services.btattach = {
before = [ "bluetooth.service" ];
after = [ "dev-ttyAMA0.device" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.bluez}/bin/btattach -B /dev/ttyAMA0 -P bcm -S 3000000";
};
};
environment = {
systemPackages = with pkgs; [
i2c-tools
libraspberrypi
raspberrypi-eeprom
raspberrypifw
raspberrypiWirelessFirmware
raspberrypi-armstubs
];
};
users = {
mutableUsers = false;
users."${user}" = {
isNormalUser = true;
# hashedPasswordFile = password;
password = "BogieDudie1";
extraGroups = [
"wheel"
"docker"
"video"
];
shell = pkgs.zsh;
openssh.authorizedKeys.keys = [
# macBook
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCw9zq8DLGByI5v2gAn95hKNyOsm3g61a2buxu2BBMFysQJgmZPCCLUqRJKhSM5Vm/JOgsAmdpRBRZQoHD+6S844CJHb4v4VIbjkyQgYCuM7Rst2IOZ5QybvsA2/D0nwytZ+HXQqDj2AagUYDbz0gyyIHkDQ5YGBMkvkWz/h1Vci6aoBM7VihEDM4KlWoTVuPeASGM8r5IZ2FS83Djbqo4ov6AYvLMrKB9Z7hmFgH6R3LE0gxOkzbGVXtSuvJyrjvgytoT22UhATjjxSQ9D+YJXXkQoB3lUdg8OoIquUPjMZpl4mR8ffvseWPfcvD1XlD5t+TOHFqKpESO547tlOBYhdpew+NSgAXpamCU6oyV8tDCywLQu2ucxHRn78u6WXzWHkDtffdhzmk6TZaPhWqVHuTGjR4higBgGqUfSaKOMszt+FDRZAr3HtuQ2+zJ8bowK9fW5OqilTtK2HtQqroD9ApegDNbqOz6kGy5IycSXvqPURy/M4lxZxbtBPuemcJs= mattjallen@MacBook-Pro.local"
# desktop windows
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDZ2PYPjZddOzR8OJj16G88KcUhCDLkvrEmpUQP0wKHDUuA27HQQ2ORo66asadwGHY3k1VDZ1ei9l9H++SIIeKOaaUr5yZdktvj4POUNtbd9ZhcS7sZU7BSF+NMDM+h3tImh6z0S7mWvRQOUv3ZM+ZER+5xTWJVG1OOJEpb1drxJk6Qz0wbZKSR7TPNFBLLXlVy7hkNYf07RtDyhCCxNB3hJfa8c+oztnWumwDhDQWLqiUXWIU2QH6iRLGl/WYnujtNvVVaV/Hn3JJkS6MM9dnV3cpoIO0+J7+WfsN9rZ0wXt5yY3GhiGXwmcO5eYVli8lHlLWtK7aYSETyry6CBsLbojzOQO5rSqhpwfF2njAAFAQU0UjLc8PahisIuFKCwHH4iyXXOagiv5K1Mc/0Ak+WhhMPee6vV2p7NTyNpXRvouDbWy5cSRH31WgQ9fK5mIGe5v8nGGqtEhUubUkiOgP+H3UbT2V/nTv/TFKdJcKw+WmizvTrxBmaMjWALlkYl+s= mattl@Jallen-PC"
# desktop nixos
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPTBMydhOc6SnOdB5WrEd7X07DrboAtagCUgXiOJjLov matt@matt-nixos"
];
};
users.root.shell = pkgs.zsh;
};
}

View File

@@ -0,0 +1,66 @@
{ lib, ... }:
let
shellAliases = {
ll = "ls -alh";
update-boot = "sudo nixos-rebuild boot --max-jobs 10 --build-host admin@10.0.1.3";
update-switch = "sudo nixos-rebuild switch --max-jobs 10 --build-host admin@10.0.1.3";
update-flake = "nix flake update pi4-nixpkgs pi4-home-manager pi4-impermanence pi4-sops-nix pi4-nixos-hardware pi4-nixos-raspberrypi pi4-disko --flake /etc/nixos";
update-nas = "nixos-rebuild switch --use-remote-sudo --target-host admin@10.0.1.3 --build-host admin@10.0.1.3 --flake ~/nix-config#jallen-nas";
nas-ssh = "kitten ssh admin@10.0.1.3";
ducks = "du -cksh * | sort -hr | head -n 15";
};
in
{
imports = [
../../share/home/defaults.nix
../../share/home/git.nix
../../share/home/shell.nix
];
home.username = "matt";
sops = {
age.keyFile = "/home/matt/.config/sops/age/keys.txt";
defaultSopsFile = "/etc/nixos/secrets/secrets.yaml";
validateSopsFiles = false;
secrets = {
"ssh-keys-public/pi4" = {
path = "/home/matt/.ssh/id_ed25519.pub";
mode = "0644";
};
"ssh-keys-private/pi4" = {
path = "/home/matt/.ssh/id_ed25519";
mode = "0600";
};
# "ssh-keys-public/desktop-nixos" = {
# path = "/home/matt/.ssh/authorized_keys";
# mode = "0600";
# };
# "ssh-keys-public/desktop-nixos-root" = {
# path = "/home/matt/.ssh/authorized_keys2";
# mode = "0600";
# };
# "ssh-keys-public/desktop-windows" = {
# path = "/home/matt/.ssh/authorized_keys3";
# mode = "0600";
# };
# "ssh-keys-public/macbook-macos" = {
# path = "/home/matt/.ssh/authorized_keys4";
# mode = "0600";
# };
};
};
programs = {
java.enable = lib.mkForce true;
mangohud.enable = lib.mkForce true;
zsh.shellAliases = shellAliases;
};
services = {
nextcloud-client.enable = lib.mkForce true;
};
}

View File

@@ -0,0 +1,35 @@
{ ... }:
{
# Set up impernance configuration for things like bluetooth
# In this configuration with /etc and /var/log being persistent, only directories outside of that need to be done here. See hardware configuration for all mountpoints.
environment.persistence."/nix/persist/system" = {
hideMounts = true;
directories = [
"/var/lib/bluetooth"
"/var/lib/nixos"
"/var/lib/libvirt"
"/var/lib/systemd/coredump"
{
directory = "/var/lib/private";
mode = "u=rwx,g=,o=";
}
"/etc/NetworkManager/system-connections"
{
directory = "/etc/nix";
user = "root";
group = "root";
mode = "u=rwx,g=rx,o=rx";
}
];
files = [
"/etc/machine-id"
];
};
security.sudo.extraConfig = ''
# rollback results in sudo lectures after each reboot
Defaults lecture = never
'';
}

View File

@@ -0,0 +1,75 @@
{ lib, config, ... }:
let
hostname = "pi4";
in
{
# Networking configs
networking = {
hostName = hostname;
defaultGateway.address = "10.0.1.1";
nameservers = [ "10.0.1.1" ];
firewall = {
enable = true;
allowPing = true;
allowedTCPPorts = [ 53 ];
allowedUDPPorts = [ 53 ];
};
# Enable Network Manager
networkmanager = {
enable = lib.mkDefault true;
wifi.powersave = lib.mkDefault false;
settings.connectivity.uri = lib.mkDefault "http://nmcheck.gnome.org/check_network_status.txt";
ensureProfiles = {
environmentFiles = [
config.sops.secrets.wifi.path
];
profiles = {
# "Joey's Jungle 5G" = {
# connection = {
# id = "Joey's Jungle 5G";
# type = "wifi";
# };
# ipv4 = {
# method = "auto";
# };
# ipv6 = {
# addr-gen-mode = "stable-privacy";
# method = "auto";
# };
# wifi = {
# mode = "infrastructure";
# ssid = "Joey's Jungle 5G";
# };
# wifi-security = {
# key-mgmt = "sae";
# psk = "$PSK";
# };
# };
"static-enabcm6e4ei0" = {
connection = {
id = "static-enabcm6e4ei0";
type = "ethernet";
interface-name = "enabcm6e4ei0";
};
ipv4 = {
method = "manual";
address = "10.0.1.2/24";
gateway = "10.0.1.1";
dns = "1.1.1.1";
};
ipv6 = {
addr-gen-mode = "stable-privacy";
method = "auto";
};
};
};
};
};
};
}

View File

@@ -0,0 +1,22 @@
{ ... }:
{
hardware = {
raspberry-pi."4" = {
apply-overlays-dtmerge.enable = true;
audio.enable = true;
backlight.enable = false;
bluetooth.enable = true;
dwc2.enable = true;
i2c0.enable = true;
i2c1.enable = true;
leds = {
eth.disable = false;
act.disable = false;
pwr.disable = false;
};
fkms-3d.enable = true;
xhci.enable = true;
};
deviceTree.filter = "bcm2711-rpi-4*.dtb";
};
}

View File

@@ -0,0 +1,23 @@
{ stdenv, fetchzip }:
stdenv.mkDerivation rec {
pname = "uefi_rpi4";
version = "1.38";
src = fetchzip {
url = "https://github.com/pftf/RPi4/releases/download/v1.38/RPi4_UEFI_Firmware_v1.38.zip";
hash = "sha256-9tOr80jcmguFy2bSz+H3TfmG8BkKyBTFoUZkMy8x+0g=";
stripRoot = false;
};
installPhase = ''
mkdir -p $out/share/uefi_rpi4
cp -r * $out/share/uefi_rpi4
'';
meta = {
description = "UEFI Firmware for Raspberry Pi 4";
homepage = "https://github.com/pftf/RPi4";
platforms = [ "aarch64-linux" ];
};
}

View File

@@ -0,0 +1,58 @@
{ lib, stdenv, fetchFromGitHub, nix-gitignore, dtc, installShellFiles, logLevel ? 5, ... }:
let
rawSrc = fetchFromGitHub {
owner = "mjallen18";
repo = "argononed";
rev = "master"; # replace with actual commit or tag
sha256 = "sha256-PpFR+6Aa4Pz9EmxOayMSsSTKFzUR6sYIAkGZ8+SUK18="; # fill this in with actual hash
};
ignores = ''
/*
!/version
!/makefile
!/configure
!/src
!/OS
/OS/*
!/OS/_common/
!/OS/nixos/
'';
cleanSrc = nix-gitignore.gitignoreSourcePure ignores rawSrc;
in
stdenv.mkDerivation {
pname = "argononed";
version = lib.strings.fileContents "${cleanSrc}/version";
src = cleanSrc;
nativeBuildInputs = [ dtc installShellFiles ];
preConfigure = ''
patchShebangs --build ./configure
export TARGET_DISTRO=nixos
'';
patches = [
"${cleanSrc}/OS/nixos/patches/nixos.patch"
"${cleanSrc}/OS/nixos/patches/shutdown.patch"
];
buildFlags = [ "LOGLEVEL=${toString logLevel}" ];
installFlags = [ "NIX_DRVOUT=$(out)" ];
postInstall = ''
installShellCompletion --bash --name argonone-cli OS/_common/argonone-cli-complete.bash
'';
meta = {
description = "A replacement daemon for the Argon One Raspberry Pi case";
homepage = "https://gitlab.com/DarkElvenAngel/argononed";
license = lib.licenses.mit;
platforms = [ "aarch64-linux" ];
};
}

View File

@@ -0,0 +1,70 @@
{ config, ... }:
let
user = "matt";
in
{
sops = {
defaultSopsFile = ../../secrets/pi4-secrets.yaml;
# age = {
# generateKey = true;
# sshKeyPaths = [ "/etc/ssd/ssh_host_ed25519_key" ];
# };
age.keyFile = "/home/matt/.config/sops/age/keys.txt";
validateSopsFiles = false;
# ------------------------------
# Secrets
# ------------------------------
secrets = {
"wifi" = {
sopsFile = ../../secrets/secrets.yaml;
};
"pi4/matt-password" = {
neededForUsers = true;
mode = "0600";
owner = config.users.users."${user}".name;
group = config.users.users."${user}".group;
};
# ------------------------------
# SSH keys
# ------------------------------
"ssh-keys-public/pi4" = {
sopsFile = ../../secrets/secrets.yaml;
mode = "0644";
owner = config.users.users."${user}".name;
group = config.users.users."${user}".group;
restartUnits = [ "sshd.service" ];
};
"ssh-keys-private/pi4" = {
sopsFile = ../../secrets/secrets.yaml;
mode = "0600";
owner = config.users.users."${user}".name;
group = config.users.users."${user}".group;
restartUnits = [ "sshd.service" ];
};
"ssh-keys-public/pi5" = {
sopsFile = ../../secrets/secrets.yaml;
neededForUsers = true;
mode = "0600";
owner = config.users.users.root.name;
group = config.users.users.root.group;
restartUnits = [ "sshd.service" ];
};
"pi4/sys-public-key" = {
neededForUsers = true;
mode = "0600";
owner = config.users.users.root.name;
group = config.users.users.root.group;
restartUnits = [ "sshd.service" ];
};
"pi4/sys-priv-key" = {
neededForUsers = true;
mode = "0600";
owner = config.users.users.root.name;
group = config.users.users.root.group;
restartUnits = [ "sshd.service" ];
};
};
};
}

View File

@@ -0,0 +1,52 @@
{ pkgs, lib, ... }:
let
kernelBundle = pkgs.linuxAndFirmware.latest;
in
{
boot = {
loader.raspberryPi.firmwarePackage = kernelBundle.raspberrypifw;
kernelPackages = kernelBundle.linuxPackages_rpi5;
};
hardware.raspberry-pi.config = {
all = { # [all] conditional filter, https://www.raspberrypi.com/documentation/computers/config_txt.html#conditional-filters
options = {
# https://www.raspberrypi.com/documentation/computers/config_txt.html#enable_uart
# in conjunction with `console=serial0,115200` in kernel command line (`cmdline.txt`)
# creates a serial console, accessible using GPIOs 14 and 15 (pins
# 8 and 10 on the 40-pin header)
enable_uart = {
enable = true;
value = true;
};
# https://www.raspberrypi.com/documentation/computers/config_txt.html#uart_2ndstage
# enable debug logging to the UART, also automatically enables
# UART logging in `start.elf`
uart_2ndstage = {
enable = true;
value = true;
};
};
# Base DTB parameters
# https://github.com/raspberrypi/linux/blob/a1d3defcca200077e1e382fe049ca613d16efd2b/arch/arm/boot/dts/overlays/README#L132
base-dt-params = {
# https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#enable-pcie
pciex1 = {
enable = true;
value = "on";
};
# PCIe Gen 3.0
# https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#pcie-gen-3-0
pciex1_gen = {
enable = true;
value = "3";
};
};
};
};
}

View File

@@ -0,0 +1,110 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{ config, lib, pkgs, ... }:
let
user = "matt";
password = config.sops.secrets."pi5/matt-password".path;
kernelBundle = pkgs.linuxAndFirmware.latest;
in
{
imports = [
./boot.nix
./impermanence.nix
./networking.nix
./services.nix
./sops.nix
../../modules/desktop-environments/hyprland
./hass.nix
];
# Enable nix flakes and nix-command tools
nix = {
settings = {
substituters = [
"https://nixos-raspberrypi.cachix.org"
# "https://cache.mjallen.dev"
];
trusted-public-keys = [
"nixos-raspberrypi.cachix.org-1:4iMO9LXa8BqhU+Rpg6LQKiGa2lsNh/j2oiYLNOQ5sPI="
# "cache.mjallen.dev-1:IzFmKCd8/gggI6lcCXsW65qQwiCLGFFN9t9s2iw7Lvc="
];
};
};
# Configure nixpkgs
nixpkgs = {
overlays = lib.mkAfter [
(self: super: {
# This is used in (modulesPath + "/hardware/all-firmware.nix") when at least
# enableRedistributableFirmware is enabled
# I know no easier way to override this package
inherit (kernelBundle) raspberrypiWirelessFirmware;
# Some derivations want to use it as an input,
# e.g. raspberrypi-dtbs, omxplayer, sd-image-* modules
inherit (kernelBundle) raspberrypifw;
})
];
};
system.nixos.tags = let
cfg = config.boot.loader.raspberryPi;
in [
"raspberry-pi-${cfg.variant}"
cfg.bootloader
config.boot.kernelPackages.kernel.version
];
systemd.services.btattach = {
before = [ "bluetooth.service" ];
after = [ "dev-ttyAMA0.device" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.bluez}/bin/btattach -B /dev/ttyAMA0 -P bcm -S 3000000";
};
};
environment = {
systemPackages = with pkgs; [
erofs-utils
fex
libraspberrypi
raspberrypi-eeprom
raspberrypifw
raspberrypiWirelessFirmware
raspberrypi-armstubs
squashfuse
squashfsTools
];
};
hardware.graphics.enable32Bit = lib.mkForce false;
users = {
mutableUsers = false;
users."${user}" = {
isNormalUser = true;
# hashedPasswordFile = password;
password = "BogieDudie1";
extraGroups = [
"wheel"
"docker"
];
openssh.authorizedKeys.keys = [
# macBook
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCw9zq8DLGByI5v2gAn95hKNyOsm3g61a2buxu2BBMFysQJgmZPCCLUqRJKhSM5Vm/JOgsAmdpRBRZQoHD+6S844CJHb4v4VIbjkyQgYCuM7Rst2IOZ5QybvsA2/D0nwytZ+HXQqDj2AagUYDbz0gyyIHkDQ5YGBMkvkWz/h1Vci6aoBM7VihEDM4KlWoTVuPeASGM8r5IZ2FS83Djbqo4ov6AYvLMrKB9Z7hmFgH6R3LE0gxOkzbGVXtSuvJyrjvgytoT22UhATjjxSQ9D+YJXXkQoB3lUdg8OoIquUPjMZpl4mR8ffvseWPfcvD1XlD5t+TOHFqKpESO547tlOBYhdpew+NSgAXpamCU6oyV8tDCywLQu2ucxHRn78u6WXzWHkDtffdhzmk6TZaPhWqVHuTGjR4higBgGqUfSaKOMszt+FDRZAr3HtuQ2+zJ8bowK9fW5OqilTtK2HtQqroD9ApegDNbqOz6kGy5IycSXvqPURy/M4lxZxbtBPuemcJs= mattjallen@MacBook-Pro.local"
# desktop windows
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDZ2PYPjZddOzR8OJj16G88KcUhCDLkvrEmpUQP0wKHDUuA27HQQ2ORo66asadwGHY3k1VDZ1ei9l9H++SIIeKOaaUr5yZdktvj4POUNtbd9ZhcS7sZU7BSF+NMDM+h3tImh6z0S7mWvRQOUv3ZM+ZER+5xTWJVG1OOJEpb1drxJk6Qz0wbZKSR7TPNFBLLXlVy7hkNYf07RtDyhCCxNB3hJfa8c+oztnWumwDhDQWLqiUXWIU2QH6iRLGl/WYnujtNvVVaV/Hn3JJkS6MM9dnV3cpoIO0+J7+WfsN9rZ0wXt5yY3GhiGXwmcO5eYVli8lHlLWtK7aYSETyry6CBsLbojzOQO5rSqhpwfF2njAAFAQU0UjLc8PahisIuFKCwHH4iyXXOagiv5K1Mc/0Ak+WhhMPee6vV2p7NTyNpXRvouDbWy5cSRH31WgQ9fK5mIGe5v8nGGqtEhUubUkiOgP+H3UbT2V/nTv/TFKdJcKw+WmizvTrxBmaMjWALlkYl+s= mattl@Jallen-PC"
# desktop nixos
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPTBMydhOc6SnOdB5WrEd7X07DrboAtagCUgXiOJjLov matt@matt-nixos"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOTha0FbV1tkpnJr7xVH78S5MetJH+0o2YrEcuvhL692 root@jallen-nas"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIwoHWOLSTGVif9hAhaMLl0qDA4roIzCNuyR6kyIXDOj admin@jallen-nas"
];
shell = pkgs.zsh;
};
users.root.shell = pkgs.zsh;
};
zramSwap.enable = true;
}

View File

@@ -0,0 +1,109 @@
{ ... }:
let
rootDisk = "/dev/nvme0n1";
in
{
disko.devices.disk.main.imageSize = "15G";
disko.devices = {
nodev."/" = {
fsType = "tmpfs";
mountOptions = [
"mode=755"
"defaults"
"size=2G"
];
};
# root disk setup
disk.main = {
type = "disk";
device = rootDisk;
content = {
type = "gpt";
# specify partitions
partitions = {
# /boot/firmware
FIRMWARE = {
priority = 1;
name = "FIRMWARE";
start = "1M";
end = "1G";
type = "0700";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot/firmware";
mountOptions = [ "umask=0077" ];
};
};
# /boot
ESP = {
priority = 2;
name = "ESP";
# start = "1G";
# end = "2G";
size = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
root = {
name = "btrfs-root";
size = "100%";
content = {
type = "btrfs";
extraArgs = [ "-f" ]; # Override existing partition
# Subvolumes must set a mountpoint in order to be mounted,
# unless their parent is mounted
subvolumes = {
"home" = {
mountOptions = [ "compress=zstd" ];
mountpoint = "/home";
};
"root" = {
mountOptions = [
"compress=zstd"
"noatime"
];
mountpoint = "/root";
};
"nix" = {
mountOptions = [
"compress=zstd"
"noatime"
];
mountpoint = "/nix";
};
"etc" = {
mountOptions = [
"compress=zstd"
"noatime"
];
mountpoint = "/etc";
};
"tmp" = {
mountOptions = [
"compress=zstd"
"noatime"
];
mountpoint = "/tmp";
};
"log" = {
mountOptions = [
"compress=zstd"
"noatime"
];
mountpoint = "/var/log";
};
};
};
};
};
};
};
};
}

View File

@@ -0,0 +1,74 @@
# 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, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "none";
fsType = "tmpfs";
};
fileSystems."/nix" =
{ device = "/dev/disk/by-uuid/6f7adf66-5662-48cd-9c50-690469e2b615";
fsType = "btrfs";
options = [ "subvol=nix" "compress=zstd" "noatime" ];
};
fileSystems."/etc" =
{ device = "/dev/disk/by-uuid/6f7adf66-5662-48cd-9c50-690469e2b615";
fsType = "btrfs";
options = [ "subvol=etc" "compress=zstd" "noatime" ];
};
fileSystems."/root" =
{ device = "/dev/disk/by-uuid/6f7adf66-5662-48cd-9c50-690469e2b615";
fsType = "btrfs";
options = [ "subvol=root" "compress=zstd" "noatime" ];
};
fileSystems."/var/log" =
{ device = "/dev/disk/by-uuid/6f7adf66-5662-48cd-9c50-690469e2b615";
fsType = "btrfs";
options = [ "subvol=log" "compress=zstd" "noatime" ];
};
fileSystems."/home" =
{ device = "/dev/disk/by-uuid/6f7adf66-5662-48cd-9c50-690469e2b615";
fsType = "btrfs";
options = [ "subvol=home" "compress=zstd" ];
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/7793-909B";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
};
fileSystems."/boot/firmware" =
{ device = "/dev/disk/by-uuid/15B0-5CAA";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
};
swapDevices = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.end0.useDHCP = lib.mkDefault true;
# networking.interfaces.wlan0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
}

View File

@@ -0,0 +1,65 @@
{ pkgs, lib, config, ... }:
let
shellAliases = {
update-boot = "sudo nixos-rebuild boot --max-jobs 10 --build-host admin@10.0.1.3";
update-switch = "sudo nixos-rebuild switch --max-jobs 10 --build-host admin@10.0.1.3";
update-flake = "nix flake update pi5-nixpkgs pi5-home-manager pi5-impermanence pi5-nixos-hardware pi5-sops-nix nixos-raspberrypi --flake /etc/nixos";
update-nas = "nixos-rebuild switch --use-remote-sudo --target-host admin@10.0.1.3 --build-host admin@10.0.1.3 --flake ~/nix-config#jallen-nas";
nas-ssh = "kitten ssh admin@10.0.1.3";
};
in
{
imports = [
../../share/home/defaults.nix
../../share/home/git.nix
../../share/home/gnome.nix
../../share/home/librewolf.nix
../../share/home/shell.nix
../../share/home/vscode.nix
];
home.username = "matt";
sops = {
age.keyFile = "/home/matt/.config/sops/age/keys.txt";
defaultSopsFile = "/etc/nixos/secrets/secrets.yaml";
validateSopsFiles = false;
secrets = {
"ssh-keys-public/pi5" = {
path = "/home/matt/.ssh/id_ed25519.pub";
mode = "0644";
};
"ssh-keys-private/pi5" = {
path = "/home/matt/.ssh/id_ed25519";
mode = "0600";
};
"ssh-keys-public/jallen-nas" = { };
"ssh-keys-public/jallen-nas-root" = { };
"ssh-keys-public/desktop-nixos" = { };
"ssh-keys-public/desktop-nixos-root" = { };
"ssh-keys-public/desktop-windows" = { };
"ssh-keys-public/macbook-macos" = { };
};
templates = {
"authorized_keys" = {
content = ''
${config.sops.placeholder."ssh-keys-public/jallen-nas"}
${config.sops.placeholder."ssh-keys-public/jallen-nas-root"}
${config.sops.placeholder."ssh-keys-public/desktop-nixos"}
${config.sops.placeholder."ssh-keys-public/desktop-nixos-root"}
${config.sops.placeholder."ssh-keys-public/macbook-macos"}
'';
};
};
};
programs = {
zsh.shellAliases = shellAliases;
};
}

View File

@@ -0,0 +1,36 @@
{ ... }:
{
# Set up impernance configuration for things like bluetooth
# In this configuration with /etc and /var/log being persistent, only directories outside of that need to be done here. See hardware configuration for all mountpoints.
environment.persistence."/nix/persist/system" = {
hideMounts = true;
directories = [
"/var/lib/bluetooth"
"/var/lib/nixos"
"/var/lib/libvirt"
"/var/lib/systemd/coredump"
{
directory = "/var/lib/private";
mode = "u=rwx,g=,o=";
}
"/etc/NetworkManager/system-connections"
{
directory = "/etc/nix";
user = "root";
group = "root";
mode = "u=rwx,g=rx,o=rx";
}
];
# files = [
# "/etc/machine-id"
# { file = "/etc/nix/id_rsa"; parentDirectory = { mode = "u=rwx,g=,o="; }; }
# ];
};
security.sudo.extraConfig = ''
# rollback results in sudo lectures after each reboot
Defaults lecture = never
'';
}

View File

@@ -0,0 +1,54 @@
{ lib, config, ... }:
let
hostname = "pi5";
in
{
# Networking configs
networking = {
hostName = hostname;
defaultGateway.address = "10.0.1.1";
nameservers = [ "10.0.1.1" ];
firewall = {
enable = true;
allowPing = true;
};
# Enable Network Manager
networkmanager = {
enable = lib.mkDefault true;
wifi.powersave = lib.mkDefault false;
settings.connectivity.uri = lib.mkDefault "http://nmcheck.gnome.org/check_network_status.txt";
ensureProfiles = {
environmentFiles = [
config.sops.secrets.wifi.path
];
profiles = {
"Joey's Jungle 5G" = {
connection = {
id = "Joey's Jungle 5G";
type = "wifi";
};
ipv4 = {
method = "auto";
};
ipv6 = {
addr-gen-mode = "stable-privacy";
method = "auto";
};
wifi = {
mode = "infrastructure";
ssid = "Joey's Jungle 5G";
};
wifi-security = {
key-mgmt = "sae";
psk = "$PSK";
};
};
};
};
};
};
}

View File

@@ -0,0 +1,16 @@
{ ... }:
{
services = {
xserver.desktopManager.gnome.enable = true;
shairport-sync = {
enable = false;
openFirewall = true;
settings = {
general = {
name = "Living Room Speakers";
};
};
};
};
}

View File

@@ -0,0 +1,60 @@
{ config, ... }:
let
user = "matt";
in
{
sops = {
defaultSopsFile = ../../secrets/pi5-secrets.yaml;
# age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
age.keyFile = "/home/matt/.config/sops/age/keys.txt";
# ------------------------------
# Secrets
# ------------------------------
secrets = {
"wifi" = {
sopsFile = ../../secrets/secrets.yaml;
};
"pi5/matt-password" = {
neededForUsers = true;
mode = "0600";
owner = config.users.users."${user}".name;
group = config.users.users."${user}".group;
};
# ------------------------------
# SSH keys
# ------------------------------
"ssh-keys-public/pi5" = {
sopsFile = ../../secrets/secrets.yaml;
mode = "0644";
owner = config.users.users."${user}".name;
group = config.users.users."${user}".group;
restartUnits = [ "sshd.service" ];
};
"ssh-keys-private/pi5" = {
sopsFile = ../../secrets/secrets.yaml;
mode = "0600";
owner = config.users.users."${user}".name;
group = config.users.users."${user}".group;
restartUnits = [ "sshd.service" ];
};
"pi5/sys-public-key" = {
neededForUsers = true;
mode = "0600";
owner = config.users.users.root.name;
group = config.users.users.root.group;
restartUnits = [ "sshd.service" ];
};
"pi5/sys-priv-key" = {
neededForUsers = true;
mode = "0600";
owner = config.users.users.root.name;
group = config.users.users.root.group;
restartUnits = [ "sshd.service" ];
};
};
};
}

View File

@@ -0,0 +1,76 @@
{ pkgs, ... }:
let
kernel = pkgs.linuxPackages_cachyos;
in
{
# Configure bootloader with lanzaboot and secureboot
boot = {
consoleLogLevel = 0;
initrd.verbose = false;
kernelModules = [ "nct6775" ];
loader = {
systemd-boot = {
enable = false;
configurationLimit = 5;
extraInstallCommands = ''
${pkgs.uutils-coreutils}/bin/uutils-echo "timeout 0
console-mode 1
default nixos-*" > /boot/loader/loader.conf
'';
};
efi = {
canTouchEfiVariables = true;
efiSysMountPoint = "/boot";
};
};
lanzaboote = {
enable = true;
pkiBundle = "/etc/secureboot";
settings = {
console-mode = "max";
timeout = "0";
};
configurationLimit = 5;
# extraInstallCommands = ''
# ${pkgs.uutils-coreutils}/bin/uutils-echo "timeout 0
# console-mode 1
# default nixos-*" > /boot/loader/loader.conf
# '';
};
plymouth = {
enable = true;
};
kernelPackages = kernel;
kernelParams = [
"quiet"
"amdgpu.ppfeaturemask=0xffffffff"
"splash"
"rd.systemd.show_status=false"
"rd.udev.log_level=3"
"udev.log_priority=3"
"loglevel=0"
"vt.global_cursor_default=0"
"rd.shell=0"
# Disable audit messages
"audit=0"
# Disable CPU mitigations messages
"mitigations=off"
];
bootspec.enable = true;
};
# Further reduce systemd output
systemd = {
services.systemd-udev-settle.enable = false;
extraConfig = ''
ShowStatus=no
DefaultTimeoutStartSec=15s
'';
};
}

View File

@@ -0,0 +1,100 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{ config, lib, pkgs, ... }:
{
imports =
[
./boot.nix
./jovian.nix
./networking.nix
./sops.nix
];
nix = {
settings = {
substituters = [
"https://cache.mjallen.dev"
];
trusted-public-keys = [
"cache.mjallen.dev-1:IzFmKCd8/gggI6lcCXsW65qQwiCLGFFN9t9s2iw7Lvc="
];
builders-use-substitutes = true;
};
distributedBuilds = true;
buildMachines = [
{
hostName = "jalle-nas.local";
system = "x86_64-linux";
maxJobs = 10;
sshUser = "admin";
supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ];
}
];
};
# Define a user account. Don't forget to set a password with passwd.
users.users = {
deck = {
hashedPasswordFile = config.sops.secrets."steamdeck/deck-password".path;
isNormalUser = true;
extraGroups = [ "wheel" ]; # Enable sudo for the user.
openssh.authorizedKeys.keys = [
# macBook
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCw9zq8DLGByI5v2gAn95hKNyOsm3g61a2buxu2BBMFysQJgmZPCCLUqRJKhSM5Vm/JOgsAmdpRBRZQoHD+6S844CJHb4v4VIbjkyQgYCuM7Rst2IOZ5QybvsA2/D0nwytZ+HXQqDj2AagUYDbz0gyyIHkDQ5YGBMkvkWz/h1Vci6aoBM7VihEDM4KlWoTVuPeASGM8r5IZ2FS83Djbqo4ov6AYvLMrKB9Z7hmFgH6R3LE0gxOkzbGVXtSuvJyrjvgytoT22UhATjjxSQ9D+YJXXkQoB3lUdg8OoIquUPjMZpl4mR8ffvseWPfcvD1XlD5t+TOHFqKpESO547tlOBYhdpew+NSgAXpamCU6oyV8tDCywLQu2ucxHRn78u6WXzWHkDtffdhzmk6TZaPhWqVHuTGjR4higBgGqUfSaKOMszt+FDRZAr3HtuQ2+zJ8bowK9fW5OqilTtK2HtQqroD9ApegDNbqOz6kGy5IycSXvqPURy/M4lxZxbtBPuemcJs= mattjallen@MacBook-Pro.local"
# desktop windows
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDZ2PYPjZddOzR8OJj16G88KcUhCDLkvrEmpUQP0wKHDUuA27HQQ2ORo66asadwGHY3k1VDZ1ei9l9H++SIIeKOaaUr5yZdktvj4POUNtbd9ZhcS7sZU7BSF+NMDM+h3tImh6z0S7mWvRQOUv3ZM+ZER+5xTWJVG1OOJEpb1drxJk6Qz0wbZKSR7TPNFBLLXlVy7hkNYf07RtDyhCCxNB3hJfa8c+oztnWumwDhDQWLqiUXWIU2QH6iRLGl/WYnujtNvVVaV/Hn3JJkS6MM9dnV3cpoIO0+J7+WfsN9rZ0wXt5yY3GhiGXwmcO5eYVli8lHlLWtK7aYSETyry6CBsLbojzOQO5rSqhpwfF2njAAFAQU0UjLc8PahisIuFKCwHH4iyXXOagiv5K1Mc/0Ak+WhhMPee6vV2p7NTyNpXRvouDbWy5cSRH31WgQ9fK5mIGe5v8nGGqtEhUubUkiOgP+H3UbT2V/nTv/TFKdJcKw+WmizvTrxBmaMjWALlkYl+s= mattl@Jallen-PC"
# desktop nixos
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPTBMydhOc6SnOdB5WrEd7X07DrboAtagCUgXiOJjLov matt@matt-nixos"
];
packages = with pkgs; [
firefox
tree
];
shell = pkgs.zsh;
};
root.shell = pkgs.zsh;
};
programs.coolercontrol.enable = true;
services = {
btrfs = {
autoScrub.enable = lib.mkDefault true;
autoScrub.fileSystems = lib.mkDefault [
"/nix"
"/root"
"/etc"
"/var/log"
"/home"
];
};
};
chaotic.mesa-git.enable = false;
services.displayManager.gdm.enable = lib.mkForce false;
# List packages installed in system profile. To search, run:
# $ nix search wget
environment = {
systemPackages = with pkgs; [
fuse
jq
newt
sbctl
steam-run
udisks2
zenity
];
variables = {
STEAM_FORCE_DESKTOPUI_SCALING = "1.0";
GDK_SCALE = "1";
};
};
}

View File

@@ -0,0 +1,73 @@
{ pkgs, ... }:
let
shellAliases = {
update-boot = "sudo nixos-rebuild boot --max-jobs 10 --build-host admin@10.0.1.3";
update-switch = "sudo nixos-rebuild switch --max-jobs 10";
update-flake = "nix flake update steamdeck-nixpkgs steamdeck-chaotic steamdeck-home-manager steamdeck-impermanence steamdeck-jovian steamdeck-lanzaboote steamdeck-nixos-hardware steamdeck-sops-nix steamdeck-steam-rom-manager --flake /etc/nixos";
nas-ssh = "ssh admin@10.0.1.3";
};
in
{
home.username = "deck";
sops = {
age.keyFile = "/home/deck/.config/sops/age/keys.txt";
defaultSopsFile = "/etc/nixos/secrets/secrets.yaml";
validateSopsFiles = false;
secrets = {
"ssh-keys-public/deck" = {
path = "/home/deck/.ssh/id_ed25519.pub";
mode = "0644";
};
"ssh-keys-private/deck" = {
path = "/home/deck/.ssh/id_ed25519";
mode = "0600";
};
};
};
programs = {
steam-rom-manager = {
enable = true;
steamUsername = "mjallen18";
# Optional: override default paths if needed
environmentVariables = {
romsDirectory = "/home/deck/Emulation/roms";
steamDirectory = "/home/deck/.local/share/Steam";
};
emulators = {
ryujinx.enable = true;
dolphin-gamecube = {
enable = true;
package = pkgs.dolphin-emu;
romFolder = "gc";
fileTypes = [ ".iso" ".ISO" ".gcm" ".GCM" ".ciso" ".CISO" "rvz" ];
extraArgs = "-b -e \"\${filePath}\"";
};
pcsx2.enable = true;
mgba.enable = true;
"Non-SRM Shortcuts" = {
enable = true;
parserType = "Non-SRM Shortcuts";
extraArgs = "";
};
};
};
zsh.shellAliases = shellAliases;
};
home.packages = with pkgs; [
dolphin-emu
heroic
mgba
prismlauncher
ryujinx-greemdev
vmware-horizon-client
];
}

View File

@@ -0,0 +1,24 @@
{ ... }:
{
jovian = {
steam = {
enable = true;
autoStart = true;
user = "deck";
desktopSession = "gnome";
};
steamos = {
useSteamOSConfig = true;
};
devices = {
steamdeck = {
enable = true;
enableGyroDsuService = true; # If enabled, motion data from the gyroscope can be used in Cemu with Cemuhoo
};
};
hardware.has.amd.gpu = true;
};
}

View File

@@ -0,0 +1,44 @@
{ config, lib, ... }:
let
hostname = "steamdeck";
wifiSsid = "Joey's Jungle 5G";
in
{
networking = {
hostName = hostname;
networkmanager = {
enable = true;
wifi.powersave = lib.mkDefault false;
settings.connectivity.uri = lib.mkDefault "http://nmcheck.gnome.org/check_network_status.txt";
ensureProfiles = {
environmentFiles = [
config.sops.secrets.wifi.path
];
profiles = {
wifiSsid = {
connection = {
id = wifiSsid;
type = "wifi";
};
ipv4 = {
method = "auto";
};
ipv6 = {
addr-gen-mode = "stable-privacy";
method = "auto";
};
wifi = {
mode = "infrastructure";
ssid = wifiSsid;
};
wifi-security = {
key-mgmt = "sae";
psk = "$PSK";
};
};
};
};
};
};
}

View File

@@ -0,0 +1,111 @@
{ config, ... }:
let
user = "deck";
in
{
# Permission modes are in octal representation (same as chmod),
# the digits represent: user|group|others
# 7 - full (rwx)
# 6 - read and write (rw-)
# 5 - read and execute (r-x)
# 4 - read only (r--)
# 3 - write and execute (-wx)
# 2 - write only (-w-)
# 1 - execute only (--x)
# 0 - none (---)
# Either a user id or group name representation of the secret owner
# It is recommended to get the user name from `config.users.users.<?name>.name` to avoid misconfiguration
# Either the group id or group name representation of the secret group
# It is recommended to get the group name from `config.users.users.<?name>.group` to avoid misconfiguration
sops = {
defaultSopsFile = ../../secrets/steamdeck-secrets.yaml;
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
# ------------------------------
# Secrets
# ------------------------------
secrets = {
"steamdeck/deck-password" = {
neededForUsers = true;
mode = "0600";
owner = config.users.users."${user}".name;
group = config.users.users."${user}".group;
};
"wifi" = {
sopsFile = ../../secrets/secrets.yaml;
};
# ------------------------------
# SSH keys
# ------------------------------
# "ssh-keys-public/desktop-nixos" = {
# mode = "0644";
# owner = config.users.users."${user}".name;
# group = config.users.users."${user}".group;
# restartUnits = [ "sshd.service" ];
# };
# "ssh-keys-private/desktop-nixos" = {
# mode = "0600";
# owner = config.users.users."${user}".name;
# group = config.users.users."${user}".group;
# restartUnits = [ "sshd.service" ];
# };
# "ssh-keys-public/desktop-nixos-root" = {
# path = "/root/.ssh/id_ed25519.pub";
# mode = "0600";
# restartUnits = [ "sshd.service" ];
# };
# "ssh-keys-private/desktop-nixos-root" = {
# path = "/root/.ssh/id_ed25519";
# mode = "0600";
# restartUnits = [ "sshd.service" ];
# };
# ------------------------------
# Secureboot keys
# ------------------------------
"secureboot/GUID" = {
sopsFile = ../../secrets/secrets.yaml;
# path = "/etc/secureboot/GUID";
mode = "0600";
};
"secureboot/keys/db-key" = {
sopsFile = ../../secrets/secrets.yaml;
# path = "/etc/secureboot/keys/db/db.key";
mode = "0600";
};
"secureboot/keys/db-pem" = {
sopsFile = ../../secrets/secrets.yaml;
# path = "/etc/secureboot/keys/db/db.pem";
mode = "0600";
};
"secureboot/keys/KEK-key" = {
sopsFile = ../../secrets/secrets.yaml;
# path = "/etc/secureboot/keys/KEK/KEK.key";
mode = "0600";
};
"secureboot/keys/KEK-pem" = {
sopsFile = ../../secrets/secrets.yaml;
# path = "/etc/secureboot/keys/KEK/KEK.pem";
mode = "0600";
};
"secureboot/keys/PK-key" = {
sopsFile = ../../secrets/secrets.yaml;
# path = "/etc/secureboot/keys/PK/PK.key";
mode = "0600";
};
"secureboot/keys/PK-pem" = {
sopsFile = ../../secrets/secrets.yaml;
# path = "/etc/secureboot/keys/PK/PK.pem";
mode = "0600";
};
};
# ------------------------------
# Templates
# ------------------------------
templates = {
};
};
}

View File

@@ -1,4 +1,4 @@
{ config, pkgs, ... }:
{ config, pkgs, namespace, ... }:
let
configLimit = 5;
# default = "@saved";
@@ -40,16 +40,6 @@ in
enable = true;
};
lanzaboote = {
enable = true;
pkiBundle = "/etc/secureboot";
settings = {
# default = default;
console-mode = "max";
};
configurationLimit = configLimit;
};
kernelPackages = kernel;
kernelParams = [

View File

@@ -28,15 +28,15 @@ let
# brscan5
ddcui
ddcutil
ddccontrol
ddccontrol-db
# ddccontrol
# ddccontrol-db
efibootmgr
kdePackages.ksvg
memtest86-efi
memtest86plus
os-prober
nil
qemu_full
qemu
rclone
rclone-browser
restic
@@ -49,8 +49,6 @@ let
udisks2
unzip
winetricks
inputs.desktop-lsfg.packages."x86_64-linux".default
];
in
{

View File

@@ -21,16 +21,17 @@
{
imports = [
./boot.nix
./configuration.nix
./filesystems.nix
./hardware-configuration.nix
./networking.nix
./nix.nix
./services.nix
./sops.nix
./users.nix
({ ... }: {
_module.args.hyprlandSettings = import ./hyprland-settings.nix;
})
];
${namespace} = {
bootloader.lanzaboote.enable = true;
desktop.gnome.enable = true;
};
}

View File

@@ -1,155 +0,0 @@
{ config, lib, pkgs, ... }:
let
pkgsVersion = pkgs; #.unstable;
in
{
services = {
# Enable Flatpak
flatpak.enable = lib.mkDefault false;
# enable auto discovery of printers
avahi = {
enable = lib.mkDefault true;
nssmdns4 = lib.mkDefault true;
openFirewall = lib.mkDefault true;
};
restic.backups = {
jallen-nas = {
initialize = true;
createWrapper = true;
inhibitsSleep = true;
environmentFile = config.sops.templates."restic.env".path;
passwordFile = config.sops.secrets."desktop/restic/password".path;
repositoryFile = config.sops.secrets."desktop/restic/repo".path;
paths = [
"/home/matt"
];
exclude = [
"/home/matt/Steam"
"/home/matt/Heroic"
"/home/matt/1TB"
"/home/matt/Downloads"
"/home/matt/Nextcloud"
"/home/matt/.cache"
"/home/matt/.local/share/Steam"
"/home/matt/.var/app/com.valvesoftware.Steam"
"/home/matt/.tmp"
"/home/matt/.thumbnails"
"/home/matt/.compose-cache"
];
};
proton-drive = {
initialize = true;
createWrapper = true;
inhibitsSleep = true;
passwordFile = config.sops.secrets."desktop/restic/password".path;
rcloneConfigFile = "/home/matt/.config/rclone/rclone.conf";
repository = "rclone:proton-drive:backup-nix";
paths = [
"/home/matt"
];
exclude = [
"/home/matt/Steam"
"/home/matt/Heroic"
"/home/matt/1TB"
"/home/matt/Downloads"
"/home/matt/Nextcloud"
"/home/matt/.cache"
"/home/matt/.local/share/Steam"
"/home/matt/.var/app/com.valvesoftware.Steam"
"/home/matt/.tmp"
"/home/matt/.thumbnails"
"/home/matt/.compose-cache"
];
};
};
btrfs = {
autoScrub.enable = lib.mkDefault true;
autoScrub.fileSystems = lib.mkDefault [
"/nix"
"/root"
"/etc"
"/var/log"
"/home"
];
};
ratbagd.enable = lib.mkDefault true;
keyd = {
enable = false;
keyboards = {
default = {
ids = [ "*" ];
settings = {
main = {
# Use ⌘ key (leftmeta) to activate macOS-like layer
leftmeta = "layer(meta_mac)";
};
meta_mac = {
# Tab switching
tab = "swapm(app_switch_state, M-tab)";
"`" = "A-f6";
# App shortcuts
c = "C-insert"; # Copy
v = "S-insert"; # Paste
x = "S-delete"; # Cut
"1" = "A-1";
"2" = "A-2";
"3" = "A-3";
"4" = "A-4";
"5" = "A-5";
"6" = "A-6";
"7" = "A-7";
"8" = "A-8";
"9" = "A-9";
# Move to line start/end
left = "home";
right = "end";
};
app_switch_state = {
tab = "M-tab";
right = "M-tab";
"`" = "M-S-tab";
left = "M-S-tab";
};
};
};
};
};
};
systemd = {
user.services = {
rclone-home-proton = {
enable = lib.mkDefault false;
path = with pkgsVersion; [
bash
pkgs.rclone
];
script = ''
rclone sync /home/matt proton-drive:backup-nix --exclude '/home/matt/Games/**' --exclude '/home/matt/1TB/**' --exclude '/home/matt/Downloads/**'
'';
};
rsync-home = {
enable = lib.mkDefault false;
path = with pkgsVersion; [
bash
rsync
openssh
];
script = ''
rsync -rtpogvPlHzs --ignore-existing --exclude={'/home/matt/Games', '/home/matt/1TB', '/home/matt/Downloads/*', '/home/matt/.cache'} -e ssh /home/matt admin@10.0.1.3:/media/nas/main/backup/desktop-nix/home
'';
};
};
};
}

View File

@@ -0,0 +1,13 @@
{ lib, ... }:
{
services.btrfs = {
autoScrub.enable = lib.mkDefault true;
autoScrub.fileSystems = lib.mkDefault [
"/nix"
"/root"
"/etc"
"/var/log"
"/home"
];
};
}

View File

@@ -0,0 +1,49 @@
{ ... }:
{
services.keyd = {
enable = false;
keyboards = {
default = {
ids = [ "*" ];
settings = {
main = {
# Use ⌘ key (leftmeta) to activate macOS-like layer
leftmeta = "layer(meta_mac)";
};
meta_mac = {
# Tab switching
tab = "swapm(app_switch_state, M-tab)";
"`" = "A-f6";
# App shortcuts
c = "C-insert"; # Copy
v = "S-insert"; # Paste
x = "S-delete"; # Cut
"1" = "A-1";
"2" = "A-2";
"3" = "A-3";
"4" = "A-4";
"5" = "A-5";
"6" = "A-6";
"7" = "A-7";
"8" = "A-8";
"9" = "A-9";
# Move to line start/end
left = "home";
right = "end";
};
app_switch_state = {
tab = "M-tab";
right = "M-tab";
"`" = "M-S-tab";
left = "M-S-tab";
};
};
};
};
};
}

View File

@@ -0,0 +1,4 @@
{ lib, ... }:
{
services.ratbagd.enable = lib.mkDefault true;
}

View File

@@ -0,0 +1,53 @@
{ config, ... }:
{
services.restic.backups = {
jallen-nas = {
initialize = true;
createWrapper = true;
inhibitsSleep = true;
environmentFile = config.sops.templates."restic.env".path;
passwordFile = config.sops.secrets."desktop/restic/password".path;
repositoryFile = config.sops.secrets."desktop/restic/repo".path;
paths = [
"/home/matt"
];
exclude = [
"/home/matt/Steam"
"/home/matt/Heroic"
"/home/matt/1TB"
"/home/matt/Downloads"
"/home/matt/Nextcloud"
"/home/matt/.cache"
"/home/matt/.local/share/Steam"
"/home/matt/.var/app/com.valvesoftware.Steam"
"/home/matt/.tmp"
"/home/matt/.thumbnails"
"/home/matt/.compose-cache"
];
};
proton-drive = {
initialize = true;
createWrapper = true;
inhibitsSleep = true;
passwordFile = config.sops.secrets."desktop/restic/password".path;
rcloneConfigFile = "/home/matt/.config/rclone/rclone.conf";
repository = "rclone:proton-drive:backup-nix";
paths = [
"/home/matt"
];
exclude = [
"/home/matt/Steam"
"/home/matt/Heroic"
"/home/matt/1TB"
"/home/matt/Downloads"
"/home/matt/Nextcloud"
"/home/matt/.cache"
"/home/matt/.local/share/Steam"
"/home/matt/.var/app/com.valvesoftware.Steam"
"/home/matt/.tmp"
"/home/matt/.thumbnails"
"/home/matt/.compose-cache"
];
};
};
}

View File

@@ -18,7 +18,7 @@ in
# Either the group id or group name representation of the secret group
# It is recommended to get the group name from `config.users.users.<?name>.group` to avoid misconfiguration
sops = {
defaultSopsFile = ../../secrets/desktop-secrets.yaml;
defaultSopsFile = ../../../secrets/desktop-secrets.yaml;
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
# ------------------------------
@@ -44,34 +44,34 @@ in
mode = "0600";
};
"wifi" = {
sopsFile = ../../secrets/secrets.yaml;
sopsFile = ../../../secrets/secrets.yaml;
};
# ------------------------------
# SSH keys
# ------------------------------
"ssh-keys-public/desktop-nixos" = {
sopsFile = ../../secrets/secrets.yaml;
sopsFile = ../../../secrets/secrets.yaml;
mode = "0644";
owner = config.users.users."${user}".name;
group = config.users.users."${user}".group;
restartUnits = [ "sshd.service" ];
};
"ssh-keys-private/desktop-nixos" = {
sopsFile = ../../secrets/secrets.yaml;
sopsFile = ../../../secrets/secrets.yaml;
mode = "0600";
owner = config.users.users."${user}".name;
group = config.users.users."${user}".group;
restartUnits = [ "sshd.service" ];
};
"ssh-keys-public/desktop-nixos-root" = {
sopsFile = ../../secrets/secrets.yaml;
sopsFile = ../../../secrets/secrets.yaml;
path = "/root/.ssh/id_ed25519.pub";
mode = "0600";
restartUnits = [ "sshd.service" ];
};
"ssh-keys-private/desktop-nixos-root" = {
sopsFile = ../../secrets/secrets.yaml;
sopsFile = ../../../secrets/secrets.yaml;
path = "/root/.ssh/id_ed25519";
mode = "0600";
restartUnits = [ "sshd.service" ];
@@ -81,37 +81,37 @@ in
# Secureboot keys
# ------------------------------
"secureboot/GUID" = {
sopsFile = ../../secrets/secrets.yaml;
sopsFile = ../../../secrets/secrets.yaml;
path = "/etc/secureboot/GUID";
mode = "0600";
};
"secureboot/keys/db-key" = {
sopsFile = ../../secrets/secrets.yaml;
sopsFile = ../../../secrets/secrets.yaml;
path = "/etc/secureboot/keys/db/db.key";
mode = "0600";
};
"secureboot/keys/db-pem" = {
sopsFile = ../../secrets/secrets.yaml;
sopsFile = ../../../secrets/secrets.yaml;
path = "/etc/secureboot/keys/db/db.pem";
mode = "0600";
};
"secureboot/keys/KEK-key" = {
sopsFile = ../../secrets/secrets.yaml;
sopsFile = ../../../secrets/secrets.yaml;
path = "/etc/secureboot/keys/KEK/KEK.key";
mode = "0600";
};
"secureboot/keys/KEK-pem" = {
sopsFile = ../../secrets/secrets.yaml;
sopsFile = ../../../secrets/secrets.yaml;
path = "/etc/secureboot/keys/KEK/KEK.pem";
mode = "0600";
};
"secureboot/keys/PK-key" = {
sopsFile = ../../secrets/secrets.yaml;
sopsFile = ../../../secrets/secrets.yaml;
path = "/etc/secureboot/keys/PK/PK.key";
mode = "0600";
};
"secureboot/keys/PK-pem" = {
sopsFile = ../../secrets/secrets.yaml;
sopsFile = ../../../secrets/secrets.yaml;
path = "/etc/secureboot/keys/PK/PK.pem";
mode = "0600";
};

View File

@@ -0,0 +1,12 @@
{ namespace, ... }:
{
specialisation.cosmic.configuration = {
${namespace} = {
desktop = {
cosmic.enable = true;
gnome.enable = true;
};
};
environment.etc."specialisation".text = "cosmic";
};
}

View File

@@ -0,0 +1,12 @@
{ namespace, ... }:
{
specialisation.hyprland.configuration = {
${namespace} = {
desktop = {
hyprland.enable = true;
gnome.enable = false;
};
};
environment.etc."specialisation".text = "hyprland";
};
}

105
systems/x86_64-linux/nas/apps.nix Executable file
View File

@@ -0,0 +1,105 @@
{ pkgs, lib, ... }:
let
settings = import ./settings.nix;
in
{
imports = [
./apps/actual
./apps/arrs
./apps/crowdsec
./apps/excalidraw
./apps/gitea
./apps/immich
./apps/jellyfin
./apps/jellyseerr
./apps/lubelogger
./apps/nextcloud
./apps/ollama
./apps/orca
./apps/paperless
./apps/traefik
./apps/wyoming
../../modules
];
nas-apps = {
actual = {
enable = true;
port = 3333;
localAddress = "10.0.3.18";
dataDir = "/media/nas/ssd/nix-app-data/actual";
reverseProxy = {
enable = true;
host = "actual.mjallen.dev";
middlewares = [ "crowdsec" "whitelist-geoblock" ];
};
};
arrs = {
enable = true;
localAddress = "10.0.1.51";
downloadsDir = "/media/nas/ssd/ssd_app_data/downloads";
incompleteDownloadsDir = "/media/nas/ssd/ssd_app_data/downloads-incomplete";
moviesDir = "/media/nas/main/movies";
tvDir = "/media/nas/main/tv";
isosDir = "/media/nas/main/isos";
radarr = {
enable = true;
port = 7878;
dataDir = "/media/nas/ssd/nix-app-data/radarr";
};
sonarr = {
enable = true;
port = 8989;
dataDir = "/media/nas/ssd/nix-app-data/sonarr";
};
sabnzbd = {
enable = true;
port = 8280;
dataDir = "/media/nas/ssd/nix-app-data/sabnzbd";
};
deluge = {
enable = true;
port = 8112;
};
jackett = {
enable = true;
port = 9117;
dataDir = "/media/nas/ssd/nix-app-data/jackett";
};
};
crowdsec = {
enable = true;
port = 9898;
apiAddress = settings.hostAddress;
apiKey = "1daH89qmJ41r2Lpd9hvDw4sxtOAtBzaj3aKFOFqE";
dataDir = "/media/nas/ssd/nix-app-data/crowdsec";
};
gitea = {
enable = true;
httpPort = 3000;
sshPort = 2222;
localAddress = "10.0.4.18";
dataDir = "/media/nas/ssd/nix-app-data/gitea";
reverseProxy = {
enable = true;
host = "gitea.mjallen.dev";
middlewares = [ "crowdsec" "whitelist-geoblock" ];
};
};
free-games-claimer.enable = true;
manyfold.enable = true;
orca-slicer = {
enable = true;
httpPort = "3100";
httpsPort = "3101";
};
tdarr.enable = true;
};
}

View File

@@ -0,0 +1,125 @@
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.nas-apps.actual;
settings = import ../../settings.nix;
dataDir = "/data";
hostAddress = settings.hostAddress;
actualUserId = config.users.users.nix-apps.uid;
actualGroupId = config.users.groups.jallen-nas.gid;
in
{
imports = [ ./options.nix ];
config = mkIf cfg.enable {
containers.actual = {
autoStart = true;
privateNetwork = true;
hostAddress = hostAddress;
localAddress = cfg.localAddress;
bindMounts = {
${dataDir} = {
hostPath = cfg.dataDir;
isReadOnly = false;
};
};
config = { lib, ... }:
{
services.actual = {
enable = true;
openFirewall = true;
settings = {
trustedProxies = [ hostAddress ];
port = cfg.port;
dataDir = dataDir;
serverFiles = "${dataDir}/server-files";
userFiles = "${dataDir}/user-files";
};
};
users.users.actual = {
isSystemUser = true;
uid = lib.mkForce actualUserId;
group = "actual";
};
users.groups = {
actual = {
gid = lib.mkForce actualGroupId;
};
};
# System packages
environment.systemPackages = with pkgs; [
sqlite
];
# Create and set permissions for required directories
system.activationScripts.actual-dirs = ''
mkdir -p ${dataDir}
chown -R actual:actual ${dataDir}
chmod -R 0700 ${dataDir}
'';
systemd.services = {
actual = {
environment.ACTUAL_CONFIG_PATH = lib.mkForce "${dataDir}/config.json";
serviceConfig = {
ExecStart = lib.mkForce "${pkgs.actual-server}/bin/actual-server --config ${dataDir}/config.json";
WorkingDirectory = lib.mkForce dataDir;
StateDirectory = lib.mkForce dataDir;
StateDirectoryMode = lib.mkForce 0700;
DynamicUser = lib.mkForce false;
ProtectSystem = lib.mkForce null;
};
};
};
networking = {
firewall = {
enable = true;
allowedTCPPorts = [ cfg.port ];
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
useHostResolvConf = lib.mkForce false;
};
services.resolved.enable = true;
system.stateVersion = "23.11";
};
};
services.traefik.dynamicConfigOptions = lib.mkIf cfg.reverseProxy.enable {
services.actual.loadBalancer.servers = [
{
url = "http://${cfg.localAddress}:${toString cfg.port}";
}
];
routers.actual = {
entryPoints = [ "websecure" ];
rule = "Host(`${cfg.reverseProxy.host}`)";
service = "actual";
middlewares = cfg.reverseProxy.middlewares;
tls.certResolver = "letsencrypt";
};
};
networking = {
nat = {
forwardPorts = [
{
destination = "${cfg.localAddress}:${toString cfg.port}";
sourcePort = cfg.port;
}
];
};
firewall = {
allowedTCPPorts = [ cfg.port ];
allowedUDPPorts = [ cfg.port ];
};
};
};
}

View File

@@ -0,0 +1,37 @@
{ lib, ... }:
with lib;
{
options.nas-apps.actual = {
enable = mkEnableOption "actual service";
port = mkOption {
type = types.int;
default = 80;
};
localAddress = mkOption {
type = types.str;
default = "127.0.0.1";
};
dataDir = mkOption {
type = types.str;
default = "";
};
reverseProxy = {
enable = mkOption {
type = types.bool;
default = false;
};
host = mkOption {
type = types.str;
default = "";
};
middlewares = mkOption {
type = with types; listOf str;
default = [ ];
};
};
};
}

View File

@@ -0,0 +1,237 @@
{
config,
pkgs,
lib,
...
}:
with lib;
let
cfg = config.nas-apps.arrs;
settings = import ../../settings.nix;
radarrDataDir = "/var/lib/radarr";
downloadDir = "/downloads";
incompleteDir = "/downloads-incomplete";
sonarrDataDir = "/var/lib/sonarr";
sabnzbdConfig = "/var/lib/sabnzbd";
jackettDir = "/var/lib/jackett/.config/Jackett";
mediaDir = "/media";
arrUserId = config.users.users.nix-apps.uid;
arrGroupId = config.users.groups.jallen-nas.gid;
radarrPkg = pkgs.radarr;
sonarrPkg = pkgs.sonarr;
delugePkg = pkgs.deluge;
jackettPkg = pkgs.jackett;
sabnzbdPkg = pkgs.sabnzbd;
in
{
imports = [ ./options.nix ];
config = mkIf cfg.enable {
containers.arrs = {
autoStart = true;
privateNetwork = true;
hostAddress = settings.hostAddress;
localAddress = cfg.localAddress;
config =
{
pkgs,
lib,
...
}:
{
nixpkgs.config.allowUnfree = true;
# Enable radarr service
services.radarr = {
enable = cfg.radarr.enable;
openFirewall = true;
user = "arrs";
group = "media";
dataDir = radarrDataDir;
package = radarrPkg;
};
# Enable Sonarr service
services.sonarr = {
enable = cfg.sonarr.enable;
openFirewall = true;
user = "arrs";
group = "media";
dataDir = sonarrDataDir;
package = sonarrPkg;
};
# Enable Sabnzbd service
services.sabnzbd = {
enable = cfg.sabnzbd.enable;
openFirewall = true;
user = "arrs";
group = "media";
configFile = "${sabnzbdConfig}/sabnzbd.ini";
package = sabnzbdPkg;
};
services.deluge = {
enable = cfg.deluge.enable;
user = "arrs";
group = "media";
openFirewall = true;
dataDir = "/media";
package = delugePkg;
web = {
enable = true;
port = cfg.deluge.port;
openFirewall = true;
};
};
services.jackett = {
enable = cfg.jackett.enable;
user = "arrs";
group = "media";
openFirewall = true;
package = jackettPkg;
};
# Create required users and groups
users.users.arrs = {
isSystemUser = true;
uid = lib.mkForce arrUserId;
group = "media";
extraGroups = [ "downloads" ];
};
users.groups = {
media = {
gid = lib.mkForce arrGroupId;
};
downloads = { };
};
# System packages
environment.systemPackages = with pkgs; [
glib
sqlite
mono
mediainfo
protonvpn-cli_2
];
# Create and set permissions for required directories
system.activationScripts.arr-dirs = ''
mkdir -p ${radarrDataDir}
mkdir -p ${sonarrDataDir}
mkdir -p ${sabnzbdConfig}
mkdir -p ${downloadDir}
mkdir -p ${incompleteDir}
mkdir -p ${mediaDir}
chown -R arrs:media ${radarrDataDir}
chown -R arrs:media ${sonarrDataDir}
chown -R arrs:media ${sabnzbdConfig}
chown -R arrs:media ${downloadDir}
chown -R arrs:media ${incompleteDir}
chown -R arrs:media ${mediaDir}
chmod -R 775 ${radarrDataDir}
chmod -R 775 ${sonarrDataDir}
chmod -R 775 ${sabnzbdConfig}
chmod -R 775 ${downloadDir}
chmod -R 775 ${incompleteDir}
chmod -R 775 ${mediaDir}
'';
networking = {
firewall = {
enable = true;
allowedTCPPorts = [
cfg.radarr.port
cfg.sonarr.port
cfg.sabnzbd.port
8080
];
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
useHostResolvConf = lib.mkForce false;
};
services.resolved.enable = true;
system.stateVersion = "23.11";
};
# Bind mount directories from host
bindMounts = {
"${radarrDataDir}" = {
hostPath = cfg.radarr.dataDir;
isReadOnly = false;
};
"${sonarrDataDir}" = {
hostPath = cfg.sonarr.dataDir;
isReadOnly = false;
};
"${sabnzbdConfig}" = {
hostPath = cfg.sabnzbd.dataDir;
isReadOnly = false;
};
"${downloadDir}" = {
hostPath = cfg.downloadsDir;
isReadOnly = false;
};
"${incompleteDir}" = {
hostPath = cfg.incompleteDownloadsDir;
isReadOnly = false;
};
"${jackettDir}" = {
hostPath = cfg.jackett.dataDir;
isReadOnly = false;
};
"/media/movies" = {
hostPath = cfg.moviesDir;
isReadOnly = false;
};
"/media/tv" = {
hostPath = cfg.tvDir;
isReadOnly = false;
};
"/media/isos" = {
hostPath = cfg.isosDir;
isReadOnly = false;
};
};
};
networking = {
nat = {
forwardPorts = [
{
destination = "${cfg.localAddress}:${toString cfg.radarr.port}";
sourcePort = cfg.radarr.port;
}
{
destination = "${cfg.localAddress}:${toString cfg.sonarr.port}";
sourcePort = cfg.sonarr.port;
}
{
destination = "${cfg.localAddress}:8080";
sourcePort = cfg.sabnzbd.port;
}
{
destination = "${cfg.localAddress}:${toString cfg.deluge.port}";
sourcePort = cfg.deluge.port;
}
{
destination = "${cfg.localAddress}:${toString cfg.jackett.port}";
sourcePort = cfg.jackett.port;
}
];
};
firewall = {
allowedTCPPorts = [ cfg.radarr.port cfg.sonarr.port cfg.sabnzbd.port 8080 cfg.deluge.port cfg.jackett.port ];
allowedUDPPorts = [ cfg.radarr.port cfg.sonarr.port cfg.sabnzbd.port 8080 cfg.deluge.port cfg.jackett.port ];
};
};
};
}

View File

@@ -0,0 +1,112 @@
{ lib, ... }:
with lib;
{
options.nas-apps.arrs = {
enable = mkEnableOption "arrs services";
radarr = {
enable = mkOption {
type = types.bool;
default = false;
};
port = mkOption {
type = types.int;
default = 7878;
};
dataDir = mkOption {
type = types.str;
default = "";
};
};
sonarr = {
enable = mkOption {
type = types.bool;
default = false;
};
port = mkOption {
type = types.int;
default = 8989;
};
dataDir = mkOption {
type = types.str;
default = "";
};
};
sabnzbd = {
enable = mkOption {
type = types.bool;
default = false;
};
port = mkOption {
type = types.int;
default = 8280;
};
dataDir = mkOption {
type = types.str;
default = "";
};
};
deluge = {
enable = mkOption {
type = types.bool;
default = false;
};
port = mkOption {
type = types.int;
default = 8112;
};
dataDir = mkOption {
type = types.str;
default = "";
};
};
jackett = {
enable = mkOption {
type = types.bool;
default = false;
};
port = mkOption {
type = types.int;
default = 9117;
};
dataDir = mkOption {
type = types.str;
default = "";
};
};
localAddress = mkOption {
type = types.str;
default = "127.0.0.1";
};
downloadsDir = mkOption {
type = types.str;
default = "";
};
incompleteDownloadsDir = mkOption {
type = types.str;
default = "";
};
moviesDir = mkOption {
type = types.str;
default = "";
};
tvDir = mkOption {
type = types.str;
default = "";
};
isosDir = mkOption {
type = types.str;
default = "";
};
};
}

View File

@@ -0,0 +1,58 @@
{ outputs, config, lib, pkgs, ... }:
with lib;
let
cfg = config.nas-apps.crowdsec;
in
{
imports = [ ./options.nix ];
config = lib.mkIf cfg.enable {
services = {
crowdsec = let
yaml = (pkgs.formats.yaml {}).generate;
acquisitions_file = yaml "acquisitions.yaml" {
source = "journalctl";
journalctl_filter = ["_SYSTEMD_UNIT=sshd.service"];
labels.type = "syslog";
};
in {
enable = true;
enrollKeyFile = "${cfg.dataDir}/enroll.key";
settings = {
crowdsec_service.acquisition_path = acquisitions_file;
api.server = {
listen_uri = "0.0.0.0:${toString cfg.port}";
};
};
};
crowdsec-firewall-bouncer = {
enable = true;
settings = {
api_key = cfg.apiKey;
api_url = "http://${cfg.apiAddress}:${toString cfg.port}";
};
};
};
systemd.services.crowdsec.serviceConfig = {
ExecStartPre = let
script = pkgs.writeScriptBin "register-bouncer" ''
#!${pkgs.runtimeShell}
set -eu
set -o pipefail
if ! cscli bouncers list | grep -q "nas-bouncer"; then
cscli bouncers add "nas-bouncer" --key "${cfg.apiKey}"
fi
'';
in ["${script}/bin/register-bouncer"];
};
networking = {
firewall = {
allowedTCPPorts = [ cfg.port ];
allowedUDPPorts = [ cfg.port ];
};
};
};
}

View File

@@ -0,0 +1,27 @@
{ lib, ... }:
with lib;
{
options.nas-apps.crowdsec = {
enable = mkEnableOption "crowdsec service";
port = mkOption {
type = types.int;
default = 9898;
};
apiAddress = mkOption {
type = types.str;
default = "127.0.0.1";
};
apiKey = mkOption {
type = types.str;
default = "";
};
dataDir = mkOption {
type = types.str;
default = "";
};
};
}

View File

@@ -0,0 +1,13 @@
{ config, ... }:
{
virtualisation.oci-containers.containers.excalidraw = {
autoStart = true;
image = "excalidraw/excalidraw";
ports = [ "8765:80" ];
environment = {
PUID = toString config.users.users.nix-apps.uid;
PGID = toString config.users.groups.jallen-nas.gid;
TZ = "America/Chicago";
};
};
}

View File

@@ -0,0 +1,131 @@
{ config, lib, ... }:
with lib;
let
cfg = config.nas-apps.gitea;
settings = import ../../settings.nix;
hostAddress = settings.hostAddress;
# localAddress = "10.0.4.18";
# httpPort = 3000;
# sshPort = 2222;
rootUrl = "https://gitea.mjallen.dev/";
# stateDir = "/media/nas/ssd/nix-app-data/gitea";
dataDir = "/var/lib/gitea";
secretsDir = "/run/secrets/jallen-nas/gitea";
mailerPasswordFile = config.sops.secrets."jallen-nas/gitea/mail-key".path;
metricsTokenFile = config.sops.secrets."jallen-nas/gitea/metrics-key".path;
in
{
imports = [ ./options.nix ];
config = mkIf cfg.enable {
containers.gitea = {
autoStart = true;
privateNetwork = true;
hostAddress = hostAddress;
localAddress = cfg.localAddress;
bindMounts = {
${dataDir} = {
hostPath = cfg.dataDir;
isReadOnly = false;
};
secrets = {
hostPath = secretsDir;
isReadOnly = true;
mountPoint = secretsDir;
};
};
config = { lib, ... }:
{
services.gitea = {
enable = true;
stateDir = dataDir;
mailerPasswordFile = mailerPasswordFile;
metricsTokenFile = metricsTokenFile;
settings = {
server = {
DOMAIN = "jallen-nas";
HTTP_ADDR = "0.0.0.0";
HTTP_PORT = cfg.httpPort;
PROTOCOL = "http";
ROOT_URL = rootUrl;
START_SSH_SERVER = true;
SSH_PORT = cfg.sshPort;
};
service = {
REGISTER_EMAIL_CONFIRM = false;
ENABLE_CAPTCHA = false;
DISABLE_REGISTRATION = true;
ENABLE_OPENID_SIGNIN = false;
ENABLE_LDAP_SIGNIN = false;
ENABLE_SSH_SIGNIN = true;
ENABLE_BUILTIN_SSH_SERVER = true;
ENABLE_REVERSE_PROXY_AUTHENTICATION = true;
};
};
};
users.users.gitea = {
extraGroups = [ "keys" ];
};
networking = {
firewall = {
enable = true;
allowedTCPPorts = [ cfg.httpPort cfg.sshPort ];
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
useHostResolvConf = lib.mkForce false;
};
# Create and set permissions for required directories
system.activationScripts.gitea-dirs = ''
mkdir -p /var/lib/gitea
chown -R gitea:gitea /var/lib/gitea
chmod -R 775 /var/lib/gitea
mkdir -p /run/secrets/jallen-nas
chown -R gitea:gitea /run/secrets/jallen-nas
chmod -R 775 /run/secrets/jallen-nas
'';
services.resolved.enable = true;
system.stateVersion = "23.11";
};
};
services.traefik.dynamicConfigOptions = lib.mkIf cfg.reverseProxy.enable {
services.gitea.loadBalancer.servers = [
{
url = "http://${cfg.localAddress}:${toString cfg.httpPort}";
}
];
routers.gitea = {
entryPoints = [ "websecure" ];
rule = "Host(`${cfg.reverseProxy.host}`)";
service = "gitea";
middlewares = cfg.reverseProxy.middlewares;
tls.certResolver = "letsencrypt";
};
};
networking = {
nat = {
forwardPorts = [
{
destination = "${cfg.localAddress}:${toString cfg.httpPort}";
sourcePort = cfg.httpPort;
}
{
destination = "${cfg.localAddress}:${toString cfg.sshPort}";
sourcePort = cfg.sshPort;
}
];
};
firewall = {
allowedTCPPorts = [ cfg.httpPort cfg.sshPort ];
allowedUDPPorts = [ cfg.httpPort cfg.sshPort ];
};
};
};
}

View File

@@ -0,0 +1,42 @@
{ lib, ... }:
with lib;
{
options.nas-apps.gitea = {
enable = mkEnableOption "gitea service";
httpPort = mkOption {
type = types.int;
default = 80;
};
sshPort = mkOption {
type = types.int;
default = 22;
};
localAddress = mkOption {
type = types.str;
default = "127.0.0.1";
};
dataDir = mkOption {
type = types.str;
default = "";
};
reverseProxy = {
enable = mkOption {
type = types.bool;
default = false;
};
host = mkOption {
type = types.str;
default = "";
};
middlewares = mkOption {
type = with types; listOf str;
default = [ ];
};
};
};
}

View File

@@ -0,0 +1,27 @@
{ config, lib, ... }:
let
settings = import ../../settings.nix;
immichPort = 2283;
dataDir = "/media/nas/main/photos";
dbPassword = config.sops.secrets."jallen-nas/immich/db-password".path;
in
{
# Enable immich service
services.immich = {
enable = true;
port = immichPort;
openFirewall = true;
secretsFile = dbPassword;
mediaLocation = dataDir;
environment = {
IMMICH_HOST = lib.mkForce "0.0.0.0";
IMMICH_TRUSTED_PROXIES = settings.hostAddress;
TZ = "America/Chicago";
};
machine-learning = {
enable = true;
};
};
}

View File

@@ -0,0 +1,11 @@
{ ... }:
{
services.jellyfin = {
enable = true;
openFirewall = true;
user = "nix-apps";
group = "jallen-nas";
dataDir = "/media/nas/ssd/nix-app-data/jellyfin";
# cacheDir = "/cache";
};
}

View File

@@ -0,0 +1,73 @@
{ ... }:
let
jellyseerrPort = 5055;
dataDir = "/var/lib/private/jellyseerr";
settings = import ../../settings.nix;
in
{
containers.jellyseerr = {
autoStart = true;
privateNetwork = true;
hostAddress = settings.hostAddress;
localAddress = "10.0.1.52";
hostAddress6 = "fc00::1";
localAddress6 = "fc00::4";
bindMounts = {
${dataDir} = {
hostPath = "/media/nas/ssd/nix-app-data/jellyseerr";
isReadOnly = false;
};
};
config =
{
lib,
...
}:
{
# Enable jellyseerr service
services.jellyseerr = {
enable = true;
port = jellyseerrPort;
# package = package;
openFirewall = true;
};
networking = {
firewall = {
enable = true;
allowedTCPPorts = [ jellyseerrPort ];
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
useHostResolvConf = lib.mkForce false;
};
# Create and set permissions for required directories
system.activationScripts.jellyseerr-dirs = ''
mkdir -p /var/lib/private/jellyseerr
chown -R jellyseerr:jellyseerr /var/lib/private/jellyseerr
chmod -R 775 /var/lib/private/jellyseerr
ln -sf /var/lib/private/jellyseerr /var/lib/jellyfin
'';
services.resolved.enable = true;
system.stateVersion = "23.11";
};
};
networking.nat = {
forwardPorts = [
{
destination = "10.0.1.52:5055";
sourcePort = jellyseerrPort;
}
];
};
}

View File

@@ -0,0 +1,20 @@
{ config, ... }:
{
virtualisation.oci-containers.containers.lubelogger = {
autoStart = true;
image = "ghcr.io/hargata/lubelogger";
ports = [ "6754:8080" ];
volumes = [
"/media/nas/ssd/nix-app-data/lubelogger:/App/data"
"/media/nas/ssd/nix-app-data/lubelogger/keys:/root/.aspnet/DataProtection-Keys"
];
environmentFiles = [
"/media/nas/ssd/nix-app-data/lubelogger/lubelogger.env"
];
environment = {
PUID = toString config.users.users.nix-apps.uid;
PGID = toString config.users.groups.jallen-nas.gid;
TZ = "America/Chicago";
};
};
}

View File

@@ -0,0 +1,241 @@
{ config, pkgs, ... }:
let
settings = import ../../settings.nix;
adminpass = config.sops.secrets."jallen-nas/nextcloud/adminpassword".path;
secretsFile = config.sops.secrets."jallen-nas/nextcloud/smtp_settings".path;
jwtSecretFile = config.sops.secrets."jallen-nas/onlyoffice-key".path;
nextcloudUserId = config.users.users.nix-apps.uid;
nextcloudGroupId = config.users.groups.jallen-nas.gid;
nextcloudPackage = pkgs.unstable.nextcloud31;
hostAddress = settings.hostAddress;
localAddress = "10.0.2.18";
nextcloudPortExtHttp = 9988;
nextcloudPortExtHttps = 9943;
onlyofficePortExt = 9943;
in
{
containers.nextcloud = {
autoStart = true;
privateNetwork = true;
hostAddress = hostAddress;
localAddress = localAddress;
bindMounts = {
secrets = {
hostPath = "/run/secrets/jallen-nas/nextcloud";
isReadOnly = true;
mountPoint = "/run/secrets/jallen-nas/nextcloud";
};
secrets2 = {
hostPath = "/run/secrets/jallen-nas/onlyoffice-key";
isReadOnly = true;
mountPoint = "/run/secrets/jallen-nas/onlyoffice-key";
};
data = {
hostPath = "/media/nas/main/nextcloud";
isReadOnly = false;
mountPoint = "/data";
};
"/var/lib/nextcloud" = {
hostPath = "/media/nas/ssd/nix-app-data/nextcloud";
isReadOnly = false;
mountPoint = "/var/lib/nextcloud";
};
"/var/lib/onlyoffice" = {
hostPath = "/media/nas/ssd/nix-app-data/onlyoffice";
isReadOnly = false;
mountPoint = "/var/lib/onlyoffice";
};
};
config =
{ pkgs, lib, ... }:
{
imports = [ ../../../../modules/nvidia ];
nixpkgs.config.allowUnfree = true;
networking.extraHosts = ''
${hostAddress} host.containers protonmail-bridge
'';
services = {
nextcloud = {
enable = true;
package = nextcloudPackage;
# datadir = "/data";
database.createLocally = true;
hostName = "cloud.mjallen.dev";
appstoreEnable = true;
caching.redis = true;
configureRedis = true;
enableImagemagick = true;
https = true;
secretFile = secretsFile;
config = {
adminuser = "mjallen";
adminpassFile = adminpass;
dbhost = "localhost";
dbtype = "sqlite";
dbname = "nextcloud";
dbuser = "nextcloud";
};
settings = {
loglevel = 3;
allow_local_remote_servers = true;
upgrade.disable-web = false;
datadirectory = "/data";
trusted_domains = [
"${hostAddress}:${toString nextcloudPortExtHttp}"
"${hostAddress}:${toString nextcloudPortExtHttps}"
"${localAddress}:80"
"${localAddress}:443"
"cloud.mjallen.dev"
];
opcache.interned_strings_buffer = 16;
trusted_proxies = [ hostAddress ];
maintenance_window_start = 6;
default_phone_region = "US";
enable_previews = true;
enabledPreviewProviders = [
"OC\\Preview\\PNG"
"OC\\Preview\\JPEG"
"OC\\Preview\\GIF"
"OC\\Preview\\BMP"
"OC\\Preview\\XBitmap"
"OC\\Preview\\MP3"
"OC\\Preview\\TXT"
"OC\\Preview\\MarkDown"
"OC\\Preview\\OpenDocument"
"OC\\Preview\\Krita"
"OC\\Preview\\HEIC"
"OC\\Preview\\Movie"
"OC\\Preview\\MSOffice2003"
"OC\\Preview\\MSOffice2007"
"OC\\Preview\\MSOfficeDoc"
];
installed = true;
user_oidc = {
auto_provision = false;
soft_auto_provision = false;
allow_multiple_user_backends = false; # auto redirect to authentik for login
};
};
};
};
services.onlyoffice = {
enable = true;
port = onlyofficePortExt;
hostname = "office.mjallen.dev";
jwtSecretFile = jwtSecretFile;
};
# System packages
environment.systemPackages = with pkgs; [
cudaPackages.cudnn
cudatoolkit
ffmpeg
# libtensorflow-bin
nextcloud31
nodejs
onlyoffice-documentserver
sqlite
];
# Create required users and groups
users.users.nextcloud = {
isSystemUser = true;
uid = lib.mkForce nextcloudUserId;
group = "nextcloud";
};
users.users.onlyoffice = {
group = lib.mkForce "nextcloud";
};
users.groups = {
nextcloud = {
gid = lib.mkForce nextcloudGroupId;
};
downloads = { };
};
# Create and set permissions for required directories
system.activationScripts.nextcloud-dirs = ''
mkdir -p /data
chown -R nextcloud:nextcloud /data
chown -R nextcloud:nextcloud /run/secrets/jallen-nas/nextcloud
chmod -R 775 /data
chmod -R 750 /run/secrets/jallen-nas/nextcloud
'';
hardware = {
graphics = {
enable = true;
# setLdLibraryPath = true;
};
};
programs = {
nix-ld.enable = true;
};
share.hardware.nvidia = {
enable = true;
enableBeta = true;
enableOpen = true;
nvidiaSettings = true;
enableNvidiaDocker = true;
};
system.stateVersion = "23.11";
networking = {
firewall = {
enable = true;
allowedTCPPorts = [
80
443
onlyofficePortExt
];
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
useHostResolvConf = lib.mkForce false;
};
services.resolved.enable = true;
};
};
networking = {
nat = {
forwardPorts = [
{
destination = "${localAddress}:443";
sourcePort = nextcloudPortExtHttps;
}
{
destination = "${localAddress}:80";
sourcePort = nextcloudPortExtHttp;
}
{
destination = "${localAddress}:8000";
sourcePort = 8000;
}
{
destination = "${localAddress}:${toString onlyofficePortExt}";
sourcePort = onlyofficePortExt;
}
];
};
};
}

View File

@@ -0,0 +1,70 @@
{ config, pkgs, ... }:
let
llamaPackage = pkgs.llama-cpp.overrideAttrs (old: {
src = pkgs.fetchFromGitHub {
owner = "ggml-org";
repo = "llama.cpp";
rev = "b4920";
sha256 = "sha256-SnQIeY74JpAPRMxWcpklDH5D4CQvAgi0GYx5+ECk2J4=";
};
# Optionally override other attributes if you need to
# version = "my-fork-version";
# pname = "llama-cpp-custom";
});
in
{
services.ollama = {
enable = true;
port = 11434;
host = "0.0.0.0";
user = "nix-apps";
group = "jallen-nas";
openFirewall = true;
acceleration = "cuda";
home = "/media/nas/ssd/nix-app-data/ollama";
};
environment.systemPackages = [ llamaPackage ];
services.llama-cpp = {
enable = true;
port = 8127;
host = "0.0.0.0";
openFirewall = true;
model = "/media/nas/ssd/nix-app-data/llama-cpp/models/functionary-small-v3.2-GGUF/functionary-small-v3.2.Q4_0.gguf";
package = llamaPackage; # pkgs.unstable.llama-cpp;
extraFlags = [
"--n_gpu-layers"
"500"
"-c"
"0"
"--numa"
"numactl"
"--jinja"
];
};
services.open-webui = {
enable = false;
host = "0.0.0.0";
port = 8888;
openFirewall = true;
# stateDir = "/media/nas/ssd/nix-app-data/open-webui";
environmentFile = config.sops.secrets."jallen-nas/open-webui".path;
environment = {
OPENID_PROVIDER_URL = "https://authentik.mjallen.dev/application/o/chat/.well-known/openid-configuration";
OAUTH_PROVIDER_NAME = "authentik";
OPENID_REDIRECT_URI = "https://chat.mjallen.dev/oauth/oidc/callback";
ENABLE_OAUTH_SIGNUP = "False";
OAUTH_MERGE_ACCOUNTS_BY_EMAIL = "True";
ENABLE_SIGNUP = "False";
ENABLE_LOGIN_FORM = "False";
ANONYMIZED_TELEMETRY = "False";
DO_NOT_TRACK = "True";
SCARF_NO_ANALYTICS = "True";
OLLAMA_API_BASE_URL = "http://127.0.0.1:11434";
LOCAL_FILES_ONLY = "False";
WEBUI_AUTH = "False";
};
};
}

View File

@@ -0,0 +1,46 @@
{ lib, ... }:
let
inherit (lib) types mkOption;
in
{
options.nas-apps = mkOption {
type = types.attrsOf (types.submodule ({ config, name, ... }: {
options = {
enable = mkOption {
type = types.bool;
default = false;
};
port = mkOption {
type = types.int;
default = 80;
};
localAddress = mkOption {
type = types.str;
default = "127.0.0.1";
};
dataDir = mkOption {
type = types.str;
default = "";
};
reverseProxy = {
enable = mkOption {
type = types.bool;
default = false;
};
host = mkOption {
type = types.str;
default = "";
};
middlewares = mkOption {
type = with types; listOf str;
default = [ ];
};
};
};
}));
};
}

View File

@@ -0,0 +1,30 @@
{
lib,
pkgs,
config,
...
}:
with lib;
let
cfg = config.nas-apps.orca-slicer;
in
{
imports = [ ./options.nix ];
config = mkIf cfg.enable {
virtualisation.oci-containers.containers."${cfg.name}" = {
autoStart = cfg.autoStart;
image = cfg.image;
ports = [
"${cfg.httpPort}:3000"
"${cfg.httpsPort}:3001"
];
volumes = [ "${cfg.configPath}:/config" ];
environment = {
PUID = cfg.puid;
PGID = cfg.pgid;
TZ = cfg.timeZone;
};
};
};
}

View File

@@ -0,0 +1,57 @@
{ lib, ... }:
with lib;
{
options.nas-apps.orca-slicer = {
enable = mkEnableOption "orca slicer docker service";
autoStart = mkOption {
type = types.bool;
default = true;
};
httpPort = mkOption {
type = types.str;
default = "3000";
};
httpsPort = mkOption {
type = types.str;
default = "3001";
};
name = mkOption {
type = types.str;
default = "orca-slicer";
};
image = mkOption {
type = types.str;
default = "linuxserver/orcaslicer";
};
configPath = mkOption {
type = types.str;
default = "/media/nas/ssd/ssd_app_data/orca-slicer";
};
dataPath = mkOption {
type = types.str;
default = "/media/nas/main/3d_printer";
};
puid = mkOption {
type = types.str;
default = "911";
};
pgid = mkOption {
type = types.str;
default = "1000";
};
timeZone = mkOption {
type = types.str;
default = "America/Chicago";
};
};
}

View File

@@ -0,0 +1,104 @@
{
config,
pkgs,
...
}:
let
settings = import ../../settings.nix;
paperlessPort = 28981;
paperlessUserId = config.users.users.nix-apps.uid;
paperlessGroupId = config.users.groups.jallen-nas.gid;
paperlessEnv = config.sops.templates."paperless.env".path;
paperlessPkg = pkgs.paperless-ngx;
in
{
containers.paperless = {
autoStart = true;
privateNetwork = true;
hostAddress = settings.hostAddress;
localAddress = "10.0.1.20";
hostAddress6 = "fc00::1";
localAddress6 = "fc00::20";
config =
{
lib,
...
}:
{
# Enable paperless service
services.paperless = {
enable = false;
package = paperlessPkg;
port = paperlessPort;
user = "paperless";
address = "0.0.0.0";
passwordFile = "/var/lib/paperless/paperless-password";
# environmentFile = paperlessEnv; # unstable is too unstable, but this doesnt exist in stable.... disabling altogether....
};
# Create required users and groups
users.groups = {
documents = {
gid = lib.mkForce paperlessGroupId;
};
};
users.users.paperless = {
isSystemUser = true;
uid = lib.mkForce paperlessUserId;
group = lib.mkForce "documents";
};
# Create and set permissions for required directories
system.activationScripts.paperless-dirs = ''
mkdir -p /var/lib/paperless
chown -R paperless:documents /var/lib/paperless
chmod -R 775 /var/lib/paperless
'';
networking = {
firewall = {
enable = true;
allowedTCPPorts = [ paperlessPort ];
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
useHostResolvConf = lib.mkForce false;
};
services.resolved.enable = true;
system.stateVersion = "23.11";
};
# Bind mount directories from host
bindMounts = {
"/var/lib/paperless" = {
hostPath = "/media/nas/ssd/nix-app-data/paperless";
isReadOnly = false;
};
secrets = {
hostPath = "/run/secrets/jallen-nas/paperless";
isReadOnly = true;
mountPoint = "/run/secrets/jallen-nas/paperless";
};
secret-env = {
hostPath = "/run/secrets/rendered/paperless.env";
isReadOnly = true;
mountPoint = "/run/secrets/rendered/paperless.env";
};
};
};
networking.nat = {
forwardPorts = [
{
destination = "10.0.1.20:28981";
sourcePort = paperlessPort;
}
];
};
}

View File

@@ -0,0 +1,391 @@
{ config, ... }:
let
settings = import ../../settings.nix;
domain = "mjallen.dev";
serverIp = settings.hostAddress;
# Forward services
authUrl = "http://${serverIp}:9000/outpost.goauthentik.io";
actualUrl = "http://${config.containers.actual.localAddress}:${toString config.containers.actual.config.services.actual.settings.port}";
authentikUrl = "http://${serverIp}:9000";
cacheUrl = "http://${serverIp}:9012";
cloudUrl = "http://${config.containers.nextcloud.localAddress}:80";
giteaUrl = "http://${config.containers.gitea.localAddress}:${toString config.containers.gitea.config.services.gitea.settings.server.HTTP_PORT}";
hassUrl = "http://homeassistant.local:8123";
immichUrl = "http://${serverIp}:${toString config.services.immich.port}";
jellyfinUrl = "http://${serverIp}:8096";
jellyseerrUrl = "http://${config.containers.jellyseerr.localAddress}:${toString config.containers.jellyseerr.config.services.jellyseerr.port}";
lubeloggerUrl = "http://${serverIp}:6754";
onlyofficeUrl = "http://${config.containers.nextcloud.localAddress}:${toString config.containers.nextcloud.config.services.onlyoffice.port}";
openWebUIUrl = "http://${serverIp}:8888";
paperlessUrl = "http://${config.containers.paperless.localAddress}:${toString config.containers.paperless.config.services.paperless.port}";
# Plugins
traefikPlugins = {
bouncer = {
moduleName = "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin";
version = "v1.4.2";
};
geoblock = {
moduleName = "github.com/PascalMinder/geoblock";
version = "v0.2.5";
};
};
crowdsecAppsecHost = "${serverIp}:7422";
crowdsecLapiKeyFile = config.sops.secrets."jallen-nas/traefik/crowdsec-lapi-key".path;
# Ports
httpPort = 80;
httpsPort = 443;
traefikPort = 8080;
metricsPort = 8082;
forwardPorts = [
httpPort
httpsPort
traefikPort
metricsPort
];
# misc
letsEncryptEmail = "jalle008@proton.me";
dataDir = "/media/nas/ssd/nix-app-data/traefik";
authentikAddress = "http://${serverIp}:9000/outpost.goauthentik.io/auth/traefik";
in
{
sops = {
secrets = {
"jallen-nas/traefik/crowdsec-lapi-key" = {
owner = config.users.users.traefik.name;
group = config.users.users.traefik.group;
restartUnits = [ "traefik.service" ];
};
"jallen-nas/traefik/cloudflare-dns-api-token" = { };
"jallen-nas/traefik/cloudflare-zone-api-token" = { };
"jallen-nas/traefik/cloudflare-api-key" = { };
"jallen-nas/traefik/cloudflare-email" = { };
};
templates = {
"traefik.env" = {
content = ''
CLOUDFLARE_DNS_API_TOKEN = ${config.sops.placeholder."jallen-nas/traefik/cloudflare-dns-api-token"}
CLOUDFLARE_ZONE_API_TOKEN = ${config.sops.placeholder."jallen-nas/traefik/cloudflare-zone-api-token"}
CLOUDFLARE_API_KEY = ${config.sops.placeholder."jallen-nas/traefik/cloudflare-api-key"}
CLOUDFLARE_EMAIL = ${config.sops.placeholder."jallen-nas/traefik/cloudflare-email"}
'';
owner = config.users.users.traefik.name;
group = config.users.users.traefik.group;
restartUnits = [ "traefik.service" ];
};
};
};
networking.firewall = {
allowedTCPPorts = forwardPorts;
allowedUDPPorts = forwardPorts;
};
services.traefik = {
enable = true;
dataDir = dataDir;
group = "jallen-nas";#group;
environmentFiles = [ "${config.services.traefik.dataDir}/traefik.env" ]; # todo: sops
staticConfigOptions = {
entryPoints = {
web = {
address = ":${toString httpPort}";
asDefault = true;
http.redirections.entrypoint = {
to = "websecure";
scheme = "https";
};
};
websecure = {
address = ":${toString httpsPort}";
asDefault = true;
http.tls.certResolver = "letsencrypt";
};
metrics = {
address = ":${toString metricsPort}"; # Port for metrics
};
};
log = {
level = "INFO";
};
metrics = {
prometheus = {
entryPoint = "metrics";
addEntryPointsLabels = true;
addServicesLabels = true;
buckets = [0.1 0.3 1.2 5.0]; # Response time buckets
};
};
certificatesResolvers.letsencrypt.acme = {
email = letsEncryptEmail;
storage = "${config.services.traefik.dataDir}/acme.json";
dnsChallenge = {
provider = "cloudflare";
resolvers = [
"1.1.1.1:53"
"8.8.8.8:53"
];
};
};
api.dashboard = true;
# Access the Traefik dashboard on <Traefik IP>:8080 of your server
api.insecure = true;
experimental = {
plugins = traefikPlugins;
};
};
dynamicConfigOptions = {
http = {
middlewares = {
authentik = {
forwardAuth = {
tls.insecureSkipVerify = true;
address = authentikAddress;
trustForwardHeader = true;
authResponseHeaders = [
"X-authentik-username"
"X-authentik-groups"
"X-authentik-email"
"X-authentik-name"
"X-authentik-uid"
"X-authentik-jwt"
"X-authentik-meta-jwks"
"X-authentik-meta-outpost"
"X-authentik-meta-provider"
"X-authentik-meta-app"
"X-authentik-meta-version"
];
};
};
onlyoffice-websocket = {
headers.customrequestheaders = {
X-Forwarded-Proto = "https";
};
};
crowdsec = {
plugin = {
bouncer = {
crowdsecAppsecEnabled = true;
crowdsecAppsecHost = crowdsecAppsecHost;
crowdsecAppsecFailureBlock = true;
crowdsecAppsecUnreachableBlock = true;
crowdsecLapiKeyFile = crowdsecLapiKeyFile;
};
};
};
whitelist-geoblock = {
plugin = {
geoblock = {
silentStartUp = false;
allowLocalRequests = true;
logLocalRequests = false;
logAllowedRequests = false;
logApiRequests = false;
api = "https://get.geojs.io/v1/ip/country/{ip}";
apiTimeoutMs = 500;
cacheSize = 25;
forceMonthlyUpdate = true;
allowUnknownCountries = false;
unknownCountryApiResponse = "nil";
blackListMode = false;
countries = [
"CA"
"US"
];
};
};
};
internal-ipallowlist =
{
ipAllowList = {
sourceRange = [
"127.0.0.1/32"
"10.0.1.0/24"
];
};
};
};
services = {
auth.loadBalancer.servers = [
{
url = authUrl;
}
];
actual.loadBalancer.servers = [
{
url = actualUrl;
}
];
authentik.loadBalancer.servers = [
{
url = authentikUrl;
}
];
cache.loadBalancer.servers = [
{
url = cacheUrl;
}
];
chat.loadBalancer.servers = [
{
url = openWebUIUrl;
}
];
cloud.loadBalancer.servers = [
{
url = cloudUrl;
}
];
gitea.loadBalancer.servers = [
{
url = giteaUrl;
}
];
hass.loadBalancer.servers = [
{
url = hassUrl;
}
];
immich.loadBalancer.servers = [
{
url = immichUrl;
}
];
jellyfin.loadBalancer.servers = [
{
url = jellyfinUrl;
}
];
jellyseerr.loadBalancer.servers = [
{
url = jellyseerrUrl;
}
];
lubelogger.loadBalancer.servers = [
{
url = lubeloggerUrl;
}
];
onlyoffice.loadBalancer.servers = [
{
url = onlyofficeUrl;
}
];
paperless.loadBalancer.servers = [
{
url = paperlessUrl;
}
];
};
routers = {
auth = {
entryPoints = [ "websecure" ];
rule = "HostRegexp(`{subdomain:[a-z]+}.mjallen.dev`) && PathPrefix(`/outpost.goauthentik.io/`)";
service = "auth";
middlewares = [ "crowdsec" "whitelist-geoblock" ];
priority = 15;
tls.certResolver = "letsencrypt";
};
actual = {
entryPoints = [ "websecure" ];
rule = "Host(`actual.${domain}`)";
service = "actual";
middlewares = [ "crowdsec" "whitelist-geoblock" ];
tls.certResolver = "letsencrypt";
};
authentik = {
entryPoints = [ "websecure" ];
rule = "Host(`authentik.${domain}`)";
service = "authentik";
middlewares = [ "crowdsec" "whitelist-geoblock" ];
tls.certResolver = "letsencrypt";
};
cache = {
entryPoints = [ "websecure" ];
rule = "Host(`cache.${domain}`)";
service = "cache";
middlewares = [ "crowdsec" "whitelist-geoblock" ];
priority = 10;
tls.certResolver = "letsencrypt";
};
cloud = {
entryPoints = [ "websecure" ];
rule = "Host(`cloud.${domain}`)";
service = "cloud";
middlewares = [ "crowdsec" "whitelist-geoblock" ];
tls.certResolver = "letsencrypt";
};
gitea = {
entryPoints = [ "websecure" ];
rule = "Host(`gitea.${domain}`)";
service = "gitea";
middlewares = [ "crowdsec" "whitelist-geoblock" ];
tls.certResolver = "letsencrypt";
};
hass = {
entryPoints = [ "websecure" ];
rule = "Host(`hass.${domain}`)";
service = "hass";
middlewares = [ "crowdsec" "whitelist-geoblock" "authentik" ];
priority = 10;
tls.certResolver = "letsencrypt";
};
immich = {
entryPoints = [ "websecure" ];
rule = "Host(`immich.${domain}`)";
service = "immich";
middlewares = [ "crowdsec" "whitelist-geoblock" ];
tls.certResolver = "letsencrypt";
};
jellyfin = {
entryPoints = [ "websecure" ];
rule = "Host(`jellyfin.${domain}`)";
service = "jellyfin";
middlewares = [ "crowdsec" "whitelist-geoblock" ];
tls.certResolver = "letsencrypt";
};
jellyseerr = {
entryPoints = [ "websecure" ];
rule = "Host(`jellyseerr.${domain}`)";
service = "jellyseerr";
middlewares = [ "crowdsec" "whitelist-geoblock" ];
tls.certResolver = "letsencrypt";
};
lubelogger = {
entryPoints = [ "websecure" ];
rule = "Host(`lubelogger.${domain}`)";
service = "lubelogger";
middlewares = [ "crowdsec" "whitelist-geoblock" ];
tls.certResolver = "letsencrypt";
};
onlyoffice = {
entryPoints = [ "websecure" ];
rule = "Host(`office.${domain}`)";
service = "onlyoffice";
middlewares = [ "crowdsec" "whitelist-geoblock" "onlyoffice-websocket" ];
tls.certResolver = "letsencrypt";
};
};
};
};
};
}

View File

@@ -0,0 +1,19 @@
{ pkgs, ... }:
{
services.wyoming = {
faster-whisper.servers.hass-whisper = {
enable = true;
useTransformers = false;
device = "cuda";
language = "en";
model = "distil-large-v3";
uri = "tcp://0.0.0.0:10300";
};
piper.servers.hass-piper = {
enable = true;
voice = "en-us-ryan-high";
uri = "tcp://0.0.0.0:10200";
};
};
}

View File

@@ -0,0 +1,68 @@
{ pkgs, ... }:
let
configLimit = 50;
kernel = pkgs.linuxPackages; # linuxPackages_latest;
in
{
# Configure bootloader with lanzaboot and secureboot
boot = {
kernelModules = [ "nct6775" ];
loader = {
systemd-boot = {
enable = false;
configurationLimit = configLimit;
};
efi = {
canTouchEfiVariables = true;
efiSysMountPoint = "/boot";
};
};
lanzaboote = {
enable = true;
pkiBundle = "/etc/secureboot";
settings = {
console-mode = "max";
};
configurationLimit = configLimit;
};
kernel.sysctl = {
"net.ipv4.ip_forward" = 1;
"net.ipv6.conf.all.forwarding" = 1;
"vm.swappiness" = 60;
};
# Override kernel to latest
kernelPackages = kernel;
kernelParams = [
"nohibernate"
];
consoleLogLevel = 3;
bootspec.enable = true;
initrd = {
kernelModules = [
"tpm"
"tpm_tis"
"tpm_crb"
"tpm_infineon"
];
systemd = {
enable = true;
# tpm2.enable = true;
tpm2.enable = true;
};
};
# Enable binfmt emulation for ARM
binfmt.emulatedSystems = [ "aarch64-linux" ]; # --argstr system aarch64-linux
};
zramSwap = {
enable = true;
};
}

View File

@@ -0,0 +1,199 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{
config,
pkgs,
lib,
inputs,
...
}:
{
imports = [
# Include the results of the hardware scan.
./hardware-configuration.nix
./filesystems.nix
./boot.nix
./apps.nix
./grafana.nix
./networking.nix
./nixpkgs.nix
./ups.nix
./users.nix
./samba.nix
./services.nix
./sops.nix
];
powerManagement.cpuFreqGovernor = "powersave";
share.hardware.nvidia = {
enable = true;
enableBeta = true;
enableOpen = true;
nvidiaSettings = true;
enableNvidiaDocker = true;
};
security.tpm2 = {
enable = true;
};
# Configure environment
environment = {
etc.crypttab.text = ''
ssd1 UUID=eff4b19c-aba7-41ab-b452-a8c6654d8754 none tpm2-device=auto
ssd2 UUID=c8640e19-6cd9-49d0-a355-bac09d17ea0d none tpm2-device=auto
hdd1 UUID=8d7dd657-d9b0-47ed-97e1-a9d1eba12b56 none tpm2-device=auto
hdd2 UUID=11ee92b0-6334-4be7-bb2d-d85f5a3f51a6 none tpm2-device=auto
hdd3 UUID=4463ea6f-3fcf-4e49-80c8-ba7f424471f0 none tpm2-device=auto
hdd4 UUID=13fe7737-b72b-4d5f-a79d-1ca0d438f8f0 none tpm2-device=auto
hdd5 UUID=2b4be219-613d-4512-8277-0260989d5377 none tpm2-device=auto
'';
etc.machine-id.text = ''
57cdf5fc27f3469f80d0a339f1238aeb
'';
systemPackages = with pkgs; [
attic-client
binutils
cryptsetup
cmake
deconz
duperemove
efibootmgr
ffmpeg
gcc
glances
ipset
jq
llama-cpp
ninja
inputs.nas-nixai.packages.x86_64-linux.nixai
networkmanagerapplet
nmon
nut
packagekit
pass
protonmail-bridge
protonvpn-cli
python3
unstable.python3Packages.llama-cpp-python
qrencode
rcon
sbctl
speedtest-cli
tigervnc
tpm2-tools
tpm2-tss
];
};
# Configure programs
programs = {
virt-manager.enable = true;
nix-ld.enable = true;
screen.enable = true;
coolercontrol = {
enable = true;
nvidiaSupport = true;
};
msmtp = {
enable = true;
accounts = {
default = {
auth = true;
tls_starttls = false;
host = "smtp.gmail.com";
user = "matt.l.jallen";
from = "matt.l.jallen@gmail.com";
passwordeval = "cat ${config.sops.secrets."jallen-nas/gitea/mail-key".path}";
};
};
defaults = {
port = 465;
tls = true;
};
};
};
hardware.fancontrol = {
enable = false;
config = ''
# Configuration file generated by pwmconfig, changes will be lost
# hwmon6/temp9_input -- chipset temp?
# hwmon2/temp1_input -- cpu temp?
# hwmon6/pwm5 -- chipset fan?
# hwmon6/pwm2, hwmon6/pwm3 -- cpu fans?
# hwmon6/pwm4 -- case fans?
INTERVAL=10
DEVPATH=hwmon2=devices/pci0000:00/0000:00:18.3 hwmon6=devices/platform/nct6775.656
DEVNAME=hwmon2=k10temp hwmon6=nct6798
FCTEMPS=hwmon6/pwm5=hwmon6/temp9_input hwmon6/pwm2=hwmon2/temp1_input hwmon6/pwm3=hwmon2/temp1_input hwmon6/pwm4=hwmon2/temp1_input
FCFANS=hwmon6/pwm5=hwmon6/fan5_input hwmon6/pwm2=hwmon6/fan2_input hwmon6/pwm3=hwmon6/fan3_input hwmon6/pwm4=hwmon6/fan4_input
MINTEMP=hwmon6/pwm5=20 hwmon6/pwm2=20 hwmon6/pwm3=20 hwmon6/pwm4=20
MAXTEMP=hwmon6/pwm5=60 hwmon6/pwm2=90 hwmon6/pwm3=90 hwmon6/pwm4=90
MINSTART=hwmon6/pwm5=16 hwmon6/pwm2=90 hwmon6/pwm3=45 hwmon6/pwm4=60
MINSTOP=hwmon6/pwm5=14 hwmon6/pwm2=0 hwmon6/pwm3=30 hwmon6/pwm4=45
MINPWM=hwmon6/pwm5=14 hwmon6/pwm2=0 hwmon6/pwm3=0 hwmon6/pwm4=0
MAXPWM=hwmon6/pwm5=255 hwmon6/pwm2=255 hwmon6/pwm3=255 hwmon6/pwm4=255
'';
};
# Virtualisation
virtualisation = {
podman = {
enable = true;
dockerCompat = true;
autoPrune.enable = true;
defaultNetwork.settings = {
dns_enabled = true;
};
};
libvirtd.enable = true;
};
# Enable nix flakes and nix-command tools
nix = {
settings = {
substituters = [
"https://nix-community.cachix.org"
"https://cache.nixos.org/"
];
trusted-public-keys = [
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
];
warn-dirty = lib.mkForce false;
experimental-features = lib.mkForce [
"nix-command"
"flakes"
];
trusted-users = [ "@wheel" ];
};
# Garbage collect automatically every week
gc.automatic = lib.mkDefault true;
gc.options = lib.mkDefault "--delete-older-than 30d";
optimise.automatic = lib.mkDefault true;
};
# Nixpkgs configuration
nixpkgs = {
config = {
allowUnfree = lib.mkForce true;
allowUnsupportedSystem = true;
permittedInsecurePackages = [
# ...
];
};
};
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
"vscode-extension-github-copilot"
];
}

View File

@@ -0,0 +1,135 @@
{ ... }:
let
defaultOptions = [ "compress=zstd" ];
in
{
fileSystems."/media/nas/ssd/nix-app-data" = {
device = "/dev/disk/by-uuid/09ac8b6b-e553-4cd8-ae62-8d8c17fe8b0c";
fsType = "btrfs";
options = [ "subvol=nix-app-data" ] ++ defaultOptions;
};
fileSystems."/media/nas/ssd/ssd_app_data" = {
device = "/dev/disk/by-uuid/09ac8b6b-e553-4cd8-ae62-8d8c17fe8b0c";
fsType = "btrfs";
options = [ "subvol=ssd_app_data" ] ++ defaultOptions;
};
fileSystems."/media/nas/ssd/mariadb" = {
device = "/dev/disk/by-uuid/09ac8b6b-e553-4cd8-ae62-8d8c17fe8b0c";
fsType = "btrfs";
options = [ "subvol=mariadb" ] ++ defaultOptions;
};
fileSystems."/media/nas/ssd/mongodb" = {
device = "/dev/disk/by-uuid/09ac8b6b-e553-4cd8-ae62-8d8c17fe8b0c";
fsType = "btrfs";
options = [ "subvol=mongodb" ] ++ defaultOptions;
};
fileSystems."/media/nas/ssd/VMs" = {
device = "/dev/disk/by-uuid/09ac8b6b-e553-4cd8-ae62-8d8c17fe8b0c";
fsType = "btrfs";
options = [ "subvol=VMs" ] ++ defaultOptions;
};
fileSystems."/media/nas/main/3d_printer" = {
device = "/dev/disk/by-uuid/76e7cd98-3145-4cff-b78d-bab0206aae28";
fsType = "btrfs";
options = [ "subvol=3d_printer" ] ++ defaultOptions;
};
fileSystems."/media/nas/main/backup" = {
device = "/dev/disk/by-uuid/76e7cd98-3145-4cff-b78d-bab0206aae28";
fsType = "btrfs";
options = [ "subvol=backup" ] ++ defaultOptions;
};
fileSystems."/media/nas/main/books" = {
device = "/dev/disk/by-uuid/76e7cd98-3145-4cff-b78d-bab0206aae28";
fsType = "btrfs";
options = [ "subvol=books" ] ++ defaultOptions;
};
fileSystems."/media/nas/main/documents" = {
device = "/dev/disk/by-uuid/76e7cd98-3145-4cff-b78d-bab0206aae28";
fsType = "btrfs";
options = [ "subvol=documents" ] ++ defaultOptions;
};
fileSystems."/media/nas/main/homeassistant" = {
device = "/dev/disk/by-uuid/76e7cd98-3145-4cff-b78d-bab0206aae28";
fsType = "btrfs";
options = [ "subvol=homeassistant" ] ++ defaultOptions;
};
fileSystems."/media/nas/main/isos" = {
device = "/dev/disk/by-uuid/76e7cd98-3145-4cff-b78d-bab0206aae28";
fsType = "btrfs";
options = [ "subvol=isos" ] ++ defaultOptions;
};
fileSystems."/media/nas/main/movies" = {
device = "/dev/disk/by-uuid/76e7cd98-3145-4cff-b78d-bab0206aae28";
fsType = "btrfs";
options = [ "subvol=movies" ] ++ defaultOptions;
};
fileSystems."/media/nas/main/nextcloud" = {
device = "/dev/disk/by-uuid/76e7cd98-3145-4cff-b78d-bab0206aae28";
fsType = "btrfs";
options = [ "subvol=nextcloud" ] ++ defaultOptions;
};
fileSystems."/media/nas/main/photos" = {
device = "/dev/disk/by-uuid/76e7cd98-3145-4cff-b78d-bab0206aae28";
fsType = "btrfs";
options = [ "subvol=photos" ] ++ defaultOptions;
};
fileSystems."/media/nas/main/switch" = {
device = "/dev/disk/by-uuid/76e7cd98-3145-4cff-b78d-bab0206aae28";
fsType = "btrfs";
options = [ "subvol=switch" ] ++ defaultOptions;
};
fileSystems."/media/nas/main/tv" = {
device = "/dev/disk/by-uuid/76e7cd98-3145-4cff-b78d-bab0206aae28";
fsType = "btrfs";
options = [ "subvol=tv" ] ++ defaultOptions;
};
fileSystems."/media/nas/main/timemachine" = {
device = "/dev/disk/by-uuid/76e7cd98-3145-4cff-b78d-bab0206aae28";
fsType = "btrfs";
options = [ "subvol=timemachine" ] ++ defaultOptions;
};
fileSystems."/run/mount/ssd" = {
device = "/dev/mapper/ssd1";
fsType = "btrfs";
};
fileSystems."/run/mount/main" = {
device = "/dev/mapper/hdd1";
fsType = "btrfs";
};
# fileSystems."/media/nas/junk/nextcloud-backup" = {
# device = "/dev/disk/by-uuid/11948951106919390044";
# fsType = "btrfs";
# options = [
# "subvol=nextcloud-backup"
# ]
# ++ defaultOptions;
# };
# fileSystems."/media/nas/main/vms" = {
# device = "/dev/disk/by-uuid/76e7cd98-3145-4cff-b78d-bab0206aae28";
# fsType = "btrfs";
# options = [
# "subvol=vms"
# ]
# ++ defaultOptions;
# };
}

View File

@@ -0,0 +1,80 @@
{ config, ... }:
let
upsUser = "nas-admin";
in
{
services = {
prometheus = {
enable = true;
exporters = {
node = {
enable = true;
enabledCollectors = [
"filesystem"
"diskstats"
"meminfo"
"cpu"
"systemd" # Ensures systemd collector is enabled
"processes"
];
extraFlags = [
"--collector.filesystem.mount-points-exclude=^/(dev|proc|sys|run)($|/)"
];
};
libvirt = {
enable = false;
openFirewall = true;
};
nut = {
enable = true;
openFirewall = true;
passwordPath = config.sops.secrets."jallen-nas/ups_password".path;
nutUser = upsUser;
};
# restic = {
# enable = true;
# openFirewall = true;
# resticPort = 8008;
# };
};
scrapeConfigs = [
{
job_name = "node";
static_configs = [{
targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ];
}];
}
{
job_name = "traefik";
static_configs = [{
targets = [ "localhost:8082" ];
}];
}
];
};
grafana = {
enable = true;
settings = {
server = {
http_port = 9999;
http_addr = "0.0.0.0";
};
};
dataDir = "/media/nas/ssd/nix-app-data/grafana";
provision = {
enable = true;
datasources.settings.datasources = [{
name = "Prometheus";
type = "prometheus";
access = "proxy";
url = "http://localhost:${toString config.services.prometheus.port}";
}];
};
};
};
# Open firewall ports for Grafana
networking.firewall.allowedTCPPorts = [ 9999 ];
}

View File

@@ -0,0 +1,128 @@
# 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"
"mpt3sas"
"xhci_pci"
"ahci"
"uas"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "none";
fsType = "tmpfs";
options = [
"defaults"
"size=25%"
"mode=755"
];
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/C6E9-7371";
fsType = "vfat";
};
fileSystems."/nix" = {
device = "/dev/disk/by-uuid/85e2fa30-816f-4457-80a1-9f88b9ab77b3";
fsType = "btrfs";
options = [
"subvol=nix"
"compress-force=zstd"
"noatime"
];
};
fileSystems."/etc" = {
device = "/dev/disk/by-uuid/85e2fa30-816f-4457-80a1-9f88b9ab77b3";
fsType = "btrfs";
options = [
"subvol=etc"
"compress-force=zstd"
"noatime"
];
};
fileSystems."/root" = {
device = "/dev/disk/by-uuid/85e2fa30-816f-4457-80a1-9f88b9ab77b3";
fsType = "btrfs";
options = [
"subvol=root"
"compress-force=zstd"
"noatime"
];
};
fileSystems."/var/log" = {
device = "/dev/disk/by-uuid/85e2fa30-816f-4457-80a1-9f88b9ab77b3";
fsType = "btrfs";
options = [
"subvol=log"
"compress-force=zstd"
"noatime"
];
};
fileSystems."/home" = {
device = "/dev/disk/by-uuid/85e2fa30-816f-4457-80a1-9f88b9ab77b3";
fsType = "btrfs";
options = [
"subvol=home"
"compress-force=zstd"
];
};
fileSystems."/tmp" = {
device = "/dev/disk/by-uuid/8e3841fc-9222-443c-af72-075dd8ac07f2";
fsType = "btrfs";
options = [
"compress-force=zstd"
"noatime"
];
};
swapDevices = [
{
device = "/dev/disk/by-id/ata-Samsung_SSD_860_EVO_500GB_S3Z1NW0KA10457X-part2";
randomEncryption.enable = true;
}
];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.docker0.useDHCP = lib.mkDefault true;
# networking.interfaces.enp7s0.useDHCP = lib.mkDefault true;
# networking.interfaces.podman0.useDHCP = lib.mkDefault true;
# networking.interfaces.veth0.useDHCP = lib.mkDefault true;
# networking.interfaces.veth1.useDHCP = lib.mkDefault true;
# networking.interfaces.veth2.useDHCP = lib.mkDefault true;
# networking.interfaces.veth3.useDHCP = lib.mkDefault true;
# networking.interfaces.veth4.useDHCP = lib.mkDefault true;
# networking.interfaces.veth5.useDHCP = lib.mkDefault true;
# networking.interfaces.veth6.useDHCP = lib.mkDefault true;
# networking.interfaces.veth7.useDHCP = lib.mkDefault true;
# networking.interfaces.vethd3ca67e.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp6s0.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp7s0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

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