1
0
Fork 0

Initial public commit!

This commit is contained in:
Aires 2024-02-29 09:53:34 -05:00
commit d8c9631d3b
57 changed files with 4864 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.qcow2
result

95
README.md Normal file
View file

@ -0,0 +1,95 @@
# NixOS Configuration
A full set of configuration files managed via NixOS. This project follows the general structure of https://github.com/tiredofit/nixos-config
## Running
### Note on secrets management
Secrets are stored in a separate repo called `nix-secrets`, which gets pulled automagically for all configs. See `hosts/common/default.nix`. This is a poor man's secret management solution, but y'know what, it works. These "secrets" will be readable to users on the system with access to the `/nix/store/`, but for single-user systems, it's fine.
### Building the system
When using nix-secrets, we need to separate the build process into two steps (because of secrets being stored in a private repo; the alternative is to give root access to the private repo on all hosts). First step is to create the build by running this as `aires`:
```zsh
nixos-rebuild build --flake .#Shura
```
When the build is done, run this command as root:
```zsh
sudo ./result/bin/switch-to-configuration switch
```
`switch` replaces the running system immediately, or you can use `boot` to only apply the switch during the next reboot. After applying the build at least once (or setting the hostname manually), you can omit the hostname from the command and just run `nixos-rebuild build --flake .`
#### Normal build process
Normally (without a secret GitHub repo) you'd just use `sudo nixos-rebuild` like so:
```zsh
sudo nixos-rebuild switch --flake .#Shura
```
### Testing
To quickly validate the configuration, create a dry build. This builds the config without actually adding it to the system:
```zsh
nixos-rebuild dry-build --flake .
```
To preview changes in a virtual machine, use this command to create a virtual machine image (remove the .qcow2 image after a while, otherwise data persistence might mess things up):
```zsh
nixos-rebuild build-vm --flake .
```
### Updating
`flake.lock` locks the version of any packages/modules used. To update them, run `nix flake update` first:
```zsh
nix flake update && nixos-rebuild build --flake . && sudo ./result/bin/switch-to-configuration switch
```
Home-manager also installs a ZSH alias, so you can just run `update` or `upgrade` for the same effect.
## Layout
This config uses two systems: Flakes, and Home-manager.
- Flakes are the entrypoint, via `flake.nix`. This is where you include Flake modules and define Flake-specific options.
- Home-manager configs live in the `users/` folders. Each user gets its own `home-manager.nix` file too.
- Modules are stored in `modules`. All of these files are imported, and you enable the ones you want to use. For example, to install Flatpak, set `host.ui.flatpak.enable = true;`.
- After adding a new module, make sure to `git add` it _and_ `import` it in `default.nix`.
### Adding a host
When adding a host:
1. Create its config in `hosts/hostname/<hostname>.nix`. Add its `hardware-configuration.nix` here too.
2. Reference a profile from `profiles/`. This sets up its base configuration.
3. Include user accounts from `users`.
4. Add any host-specific options,
5. Import it in `/hosts/default.nix`.
6. Run `nixos-rebuild`.
## Features
This Nix config features:
- Flakes
- Home Manager
- AMD and Intel hardware configurations
- Workstation and server base system configurations
- GNOME Desktop environment and KDE integrations
- Boot splash screens via Plymouth
- Secure Boot
- Disk encryption via LUKS
- Custom packages and systemd services (Duplicacy)
- Flatpaks
- Per-user configurations
- Default ZSH shell using Oh My ZSH
- Secrets (in a janky hacky kinda way)

322
flake.lock Normal file
View file

@ -0,0 +1,322 @@
{
"nodes": {
"crane": {
"inputs": {
"flake-compat": [
"lanzaboote",
"flake-compat"
],
"flake-utils": [
"lanzaboote",
"flake-utils"
],
"nixpkgs": [
"lanzaboote",
"nixpkgs"
],
"rust-overlay": [
"lanzaboote",
"rust-overlay"
]
},
"locked": {
"lastModified": 1681177078,
"narHash": "sha256-ZNIjBDou2GOabcpctiQykEQVkI8BDwk7TyvlWlI4myE=",
"owner": "ipetkov",
"repo": "crane",
"rev": "0c9f468ff00576577d83f5019a66c557ede5acf6",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"lanzaboote",
"nixpkgs"
]
},
"locked": {
"lastModified": 1680392223,
"narHash": "sha256-n3g7QFr85lDODKt250rkZj2IFS3i4/8HBU2yKHO3tqw=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "dcc36e45d054d7bb554c9cdab69093debd91a0b5",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1681202837,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"lanzaboote",
"pre-commit-hooks-nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1660459072,
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1709204054,
"narHash": "sha256-U1idK0JHs1XOfSI1APYuXi4AEADf+B+ZU4Wifc0pBHk=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "2f3367769a93b226c467551315e9e270c3f78b15",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "master",
"repo": "home-manager",
"type": "github"
}
},
"lanzaboote": {
"inputs": {
"crane": "crane",
"flake-compat": "flake-compat",
"flake-parts": "flake-parts",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"pre-commit-hooks-nix": "pre-commit-hooks-nix",
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1682802423,
"narHash": "sha256-Fb5TeRTdvUlo/5Yi2d+FC8a6KoRLk2h1VE0/peMhWPs=",
"owner": "nix-community",
"repo": "lanzaboote",
"rev": "64b903ca87d18cef2752c19c098af275c6e51d63",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "v0.3.0",
"repo": "lanzaboote",
"type": "github"
}
},
"nix-flatpak": {
"locked": {
"lastModified": 1708268179,
"narHash": "sha256-NNVuhf84AeDTxadfSGnFqPHR0ED+QyM2gmu+Wyz6PrY=",
"owner": "gmodena",
"repo": "nix-flatpak",
"rev": "a243cb0522f6240c194b873dde68e25370b06034",
"type": "github"
},
"original": {
"owner": "gmodena",
"ref": "v0.3.0",
"repo": "nix-flatpak",
"type": "github"
}
},
"nixos-hardware": {
"locked": {
"lastModified": 1709147990,
"narHash": "sha256-vpXMWoaCtMYJ7lisJedCRhQG9BSsInEyZnnG5GfY9tQ=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "33a97b5814d36ddd65ad678ad07ce43b1a67f159",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "master",
"repo": "nixos-hardware",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1682741954,
"narHash": "sha256-RPZxzRu8XU0YD2WeYUFYzJy5yAvWUsxkuK+zWw+6WVk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "373e9eb4c42b2fc0611d794de5ea715a35d72393",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable-small",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1678872516,
"narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-22.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1709150264,
"narHash": "sha256-HofykKuisObPUfj0E9CJVfaMhawXkYx3G8UIFR/XQ38=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9099616b93301d5cf84274b184a3a5ec69e94e08",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"pre-commit-hooks-nix": {
"inputs": {
"flake-compat": [
"lanzaboote",
"flake-compat"
],
"flake-utils": [
"lanzaboote",
"flake-utils"
],
"gitignore": "gitignore",
"nixpkgs": [
"lanzaboote",
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1681413034,
"narHash": "sha256-/t7OjNQcNkeWeSq/CFLYVBfm+IEnkjoSm9iKvArnUUI=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "d3de8f69ca88fb6f8b09e5b598be5ac98d28ede5",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"home-manager": "home-manager",
"lanzaboote": "lanzaboote",
"nix-flatpak": "nix-flatpak",
"nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs_2"
}
},
"rust-overlay": {
"inputs": {
"flake-utils": [
"lanzaboote",
"flake-utils"
],
"nixpkgs": [
"lanzaboote",
"nixpkgs"
]
},
"locked": {
"lastModified": 1682129965,
"narHash": "sha256-1KRPIorEL6pLpJR04FwAqqnt4Tzcm4MqD84yhlD+XSk=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "2c417c0460b788328220120c698630947547ee83",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

89
flake.nix Normal file
View file

@ -0,0 +1,89 @@
# For info on Flakes, see: https://nixos-and-flakes.thiscute.world/nixos-with-flakes/nixos-with-flakes-enabled
{
description = "Aires' system Flake";
inputs = {
# Configure nixpkgs
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# For SecureBoot support
lanzaboote.url = "github:nix-community/lanzaboote/v0.3.0";
# For Flatpak support
nix-flatpak.url = "github:gmodena/nix-flatpak/v0.3.0"; # Use github:gmodena/nix-flatpak/?ref=<tag> to change release version, nix-flatpak/<commit> to reference a specific commit, or remove to track main (unstable).
# Hardware configurations
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
# Home-manager
home-manager = {
url = "github:nix-community/home-manager/master";
inputs.nixpkgs.follows = "nixpkgs"; # Use system packages list where available
};
};
outputs = inputs@{ self, nixpkgs, lanzaboote, nix-flatpak, home-manager, nixos-hardware, ... }:
let
inherit (self) outputs;
lib = nixpkgs.lib;
systems = [ "x86_64-linux" "aarch64-linux" ];
forEachSystem = f: lib.genAttrs systems (sys: f pkgsFor.${sys});
pkgsFor = lib.genAttrs systems (system: import nixpkgs {
inherit system;
config.allowUnfree = true;
});
# Define shared modules and imports
defaultModules = {
base = [
{ _module.args = { inherit inputs; }; }
lanzaboote.nixosModules.lanzaboote
nix-flatpak.nixosModules.nix-flatpak
home-manager.nixosModules.home-manager {
home-manager = {
/*
When running, Home Manager will use the global package cache.
It will also back up any files that it would otherwise overwrite.
The originals will have the extension shown below.
*/
useGlobalPkgs = true;
useUserPackages = true;
backupFileExtension = "home-manager-backup";
};
}
];
};
in {
nixosConfigurations = {
Dimaga = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = defaultModules.base ++ [
./hosts/Dimaga
];
};
Haven = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = defaultModules.base ++ [
./hosts/Haven
];
};
Pihole = nixpkgs.lib.nixosSystem {
system = "aarch64-linux";
modules = defaultModules.base ++ [
nixos-hardware.nixosModules.raspberry-pi-4
./hosts/Pihole
];
};
Shura = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = defaultModules.base ++ [
./hosts/Shura
];
};
};
};
}

45
hosts/Dimaga/default.nix Normal file
View file

@ -0,0 +1,45 @@
{ pkgs, ... }:
# Settings specific to Dimaga
{
imports = [
./hardware-configuration.nix
../common
];
system.stateVersion = "24.05";
host = {
role = "workstation";
apps = {
development.enable = true;
hugo.enable = true;
media.enable = true;
office.enable = true;
pandoc.enable = true;
};
ui = {
flatpak.enable = true;
gnome.enable = true;
};
users = {
aires = {
enable = true;
autologin = true;
services = {
syncthing = {
enable = true;
autostart = true;
};
};
};
};
};
# Configure the virtual machine created by nixos-rebuild build-vm
virtualisation.vmVariant.virtualisation = {
memorySize = 2048;
cores = 2;
};
}

View file

@ -0,0 +1,48 @@
# Surface Laptop Go
{ config, lib, pkgs, modulesPath, ... }:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot = {
initrd = {
availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "usbhid" "sd_mod" ];
kernelModules = [ ];
luks.devices."luks-5a91100b-8ed9-4090-b1d8-d8291000fe38".device = "/dev/disk/by-uuid/5a91100b-8ed9-4090-b1d8-d8291000fe38";
};
kernelModules = [ "kvm-intel" ];
extraModulePackages = [ ];
};
fileSystems = {
"/" = {
device = "/dev/disk/by-uuid/76d67291-5aed-4f2a-b71f-1c2871cefe24";
fsType = "btrfs";
options = [ "subvol=@" ];
};
"/boot" = {
device = "/dev/disk/by-uuid/0C53-A645";
fsType = "vfat";
};
};
swapDevices = [ ];
networking = {
# 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`.
useDHCP = lib.mkDefault true;
# networking.interfaces.wlp0s20f3.useDHCP = lib.mkDefault true;
# Set the hostname.
hostName = "Dimaga";
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

66
hosts/Haven/default.nix Normal file
View file

@ -0,0 +1,66 @@
{ pkgs, home-manager, lib, config, ... }:
# Settings specific to Haven
let
start-haven = pkgs.writeText "info" (builtins.readFile ./start-haven.sh);
in
{
imports = [
./hardware-configuration.nix
../common
];
system.stateVersion = "24.05";
host = {
role = "server";
services = {
apcupsd.enable = true;
duplicacy-web = {
enable = true;
autostart = false;
environment = "${config.users.users.aires.home}";
};
k3s = {
enable = true;
role = "server";
};
msmtp.enable = true;
};
users = {
aires = {
enable = true;
services = {
syncthing = {
enable = true;
autostart = false;
};
};
};
media.enable = true;
};
};
# Enable SSH
services.openssh = {
enable = true;
ports = [ 33105 ];
settings = {
# require public key authentication for better security
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
PubkeyAuthentication = true;
PermitRootLogin = "without-password";
};
};
# Add script for booting Haven
systemd.tmpfiles.rules = [
"d ${config.users.users.aires.home}/bin/ 0700 aires users" # First, make sure the directory exists
"L+ ${config.users.users.aires.home}/bin/start-haven 0700 - - - ${start-haven}"
];
}

View file

@ -0,0 +1,52 @@
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix") ];
boot = {
supportedFilesystems = [ "btrfs" ];
kernelModules = [ "kvm-amd" ];
extraModulePackages = [ ];
initrd = {
supportedFilesystems = [ "btrfs" ];
availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" "btrfs" ];
kernelModules = [ ];
};
};
fileSystems = {
"/" = {
device = "/dev/disk/by-uuid/2c76c660-3573-4622-8771-f23fa7ee302a";
fsType = "btrfs";
options = [ "subvol=@,compress=zstd" ];
};
"/home" = {
device = "/dev/disk/by-uuid/2c76c660-3573-4622-8771-f23fa7ee302a";
fsType = "btrfs";
options = [ "subvol=@home,compress=zstd" ];
};
"/swap" = {
device = "/dev/disk/by-uuid/2c76c660-3573-4622-8771-f23fa7ee302a";
fsType = "btrfs";
options = [ "subvol=@swap" ];
};
"/boot" = {
device = "/dev/disk/by-uuid/0120-A755";
fsType = "vfat";
};
};
swapDevices = [{
device = "/swap/swapfile";
}];
networking = {
useDHCP = lib.mkDefault true;
hostName = "Haven";
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -0,0 +1,46 @@
#!/bin/sh
# Script to unlock the /storage partition and start up services that depend on it.
# check if the current user is root
if [ "$(id -u)" != "0" ]; then
echo "This script must be run as root" 1>&2
exit 1
fi
# Immediately exit on any errors
set -e
# local storage partition
echo "Unlocking storage partition:"
cryptsetup luksOpen /dev/disk/by-uuid/223582c7-fbad-467d-8f85-4d4cebd3230c storage
# mount local storage
if [ ! -f /dev/mapper/storage ]; then
mount /dev/mapper/storage /storage
if [ $? -eq "0" ]; then
echo "Storage and backup partitions mounted."
echo "Starting Duplicacy:"
systemctl start duplicacy-web.service
if [ $? -eq "0" ]; then
echo "Duplicacy started."
else
echo "Failed to start Duplicacy."
fi
echo "Starting SyncThing:"
systemctl --user -M aires@ start syncthing.service
if [ $? -eq "0" ]; then
echo "SyncThing started."
else
echo "Failed to start SyncThing."
fi
else
echo "Failed to mount storage partition."
fi
else
echo "Failed to unlock storage and/or backup partition(s)."
fi
exit 0

43
hosts/Pihole/default.nix Normal file
View file

@ -0,0 +1,43 @@
{ pkgs, lib, ... }:
# Settings specific to Raspberry Pi 4b
{
imports = [
./hardware-configuration.nix
../common
];
system.stateVersion = "24.05";
host = {
role = "server";
users.aires.enable = true;
boot.enable = false;
};
networking.hostName = "Pihole";
time.timeZone = "America/New_York";
environment.systemPackages = with pkgs; [
libraspberrypi
raspberrypifw
raspberrypi-eeprom
linuxKernel.kernels.linux_rpi4
];
# Connect to the network automagically
networking.networkmanager.enable = lib.mkForce false;
# Enable SSH
services.openssh = {
enable = true;
ports = [ 33105 ];
settings = {
PasswordAuthentication = true;
AllowUsers = ["aires"];
PermitRootLogin = "no";
};
};
}

View file

@ -0,0 +1,42 @@
# Raspberry Pi 4
# See https://nixos.wiki/wiki/NixOS_on_ARM/Raspberry_Pi_4
{ config, lib, pkgs, modulesPath, nixos-hardware, ... }:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.loader = lib.mkForce {
grub.enable = false;
generic-extlinux-compatible.enable = true;
};
#boot.kernelParams = [
# "console=serial0,115200n8"
#];
fileSystems ."/" = {
device = "/dev/disk/by-uuid/44444444-4444-4444-8888-888888888888";
fsType = "ext4";
};
swapDevices = [{
device = "/swapfile";
size = 2048;
}];
hardware.enableRedistributableFirmware = true;
networking.wireless.enable = true;
hardware = {
raspberry-pi."4" = {
apply-overlays-dtmerge.enable = true;
};
deviceTree = {
enable = true;
filter = "*rpi-4-*.dtb";
};
};
}

View file

@ -0,0 +1,31 @@
[General]
Name=MANO-703UB V2_BLE
Appearance=0x03c1
AddressType=static
SupportedTechnologies=LE;
Trusted=true
Blocked=false
WakeAllowed=true
Services=00001800-0000-1000-8000-00805f9b34fb;0000180a-0000-1000-8000-00805f9b34fb;0000180f-0000-1000-8000-00805f9b34fb;00001812-0000-1000-8000-00805f9b34fb;0000ff00-0000-1000-8000-00805f9b34fb;
[ConnectionParameters]
MinInterval=6
MaxInterval=6
Latency=9
Timeout=200
[IdentityResolvingKey]
Key=10943ED4C3FD489941E66426DB4C2479
[LongTermKey]
Key=9EEF52460DD57A878A1629B814361EDC
Authenticated=0
EncSize=16
EDiv=35588
Rand=8974202121033153697
[DeviceID]
Source=2
Vendor=8654
Product=24577
Version=17

View file

@ -0,0 +1,19 @@
[General]
Name=Shure AONIC TW2
Class=0x2c0404
SupportedTechnologies=BR/EDR;LE;
Trusted=true
Blocked=false
Services=00001101-0000-1000-8000-00805f9b34fb;00001108-0000-1000-8000-00805f9b34fb;0000110a-0000-1000-8000-00805f9b34fb;0000110b-0000-1000-8000-00805f9b34fb;0000110c-0000-1000-8000-00805f9b34fb;0000110d-0000-1000-8000-00805f9b34fb;0000110e-0000-1000-8000-00805f9b34fb;0000111e-0000-1000-8000-00805f9b34fb;0000eb03-d102-11e1-9b23-00025b00a5a5;0000eb04-d102-11e1-9b23-00025b00a5a5;0000eb05-d102-11e1-9b23-00025b00a5a5;
AddressType=public
[LinkKey]
Key=DFC42899B038D6C6B1296CF98DB0508A
Type=4
PINLength=0
[ConnectionParameters]
MinInterval=24
MaxInterval=40
Latency=0
Timeout=400

View file

@ -0,0 +1,38 @@
[General]
Name=Xbox Wireless Controller
Appearance=0x03c4
AddressType=public
SupportedTechnologies=LE;
Trusted=true
Blocked=false
WakeAllowed=true
Services=00000001-5f60-4c4f-9c83-a7953298d40d;00001800-0000-1000-8000-00805f9b34fb;00001801-0000-1000-8000-00805f9b34fb;0000180a-0000-1000-8000-00805f9b34fb;0000180f-0000-1000-8000-00805f9b34fb;00001812-0000-1000-8000-00805f9b34fb;
[IdentityResolvingKey]
Key=763775163AD76AF443DAEAEBCCED3776
[PeripheralLongTermKey]
Key=BE68B197C7F98340A5A40DEF3EBE4545
Authenticated=2
EncSize=16
EDiv=0
Rand=0
[SlaveLongTermKey]
Key=BE68B197C7F98340A5A40DEF3EBE4545
Authenticated=2
EncSize=16
EDiv=0
Rand=0
[ConnectionParameters]
MinInterval=6
MaxInterval=6
Latency=0
Timeout=300
[DeviceID]
Source=2
Vendor=1118
Product=2850
Version=1301

104
hosts/Shura/default.nix Normal file
View file

@ -0,0 +1,104 @@
{ config, pkgs, lib, ... }:
# Configuration options unique to Shura
let
# Copy bluetooth device configs
shure-aonic-bluetooth = pkgs.writeText "info" (builtins.readFile ./bluetooth/shure-aonic-bluetooth-params);
xbox-elite-bluetooth = pkgs.writeText "info" (builtins.readFile ./bluetooth/xbox-elite-controller-bluetooth-params);
mano-touchpad-bluetooth = pkgs.writeText "info" (builtins.readFile ./bluetooth/mano-touchpad-bluetooth-params);
# Use gremlin user's monitor configuration for GDM (desktop monitor primary). See https://discourse.nixos.org/t/gdm-monitor-configuration/6356/4
monitorsXmlContent = builtins.readFile ./monitors.xml;
monitorsConfig = pkgs.writeText "gdm_monitors.xml" monitorsXmlContent;
in
{
imports = [
./hardware-configuration.nix
../common
];
system.stateVersion = "24.05";
host = {
role = "workstation";
apps = {
development.enable = true;
dj.enable = true;
gaming.enable = true;
hugo.enable = true;
media.enable = true;
office.enable = true;
pandoc.enable = true;
recording.enable = true;
};
ui = {
flatpak.enable = true;
gnome.enable = true;
};
users = {
aires = {
enable = true;
services.syncthing = {
enable = true;
enableTray = true;
};
};
gremlin = {
enable = true;
services.syncthing = {
enable = true;
enableTray = true;
};
};
};
};
# Configure users
users.users = {
aires = {
extraGroups = [ "libvirt" "gremlin" ];
};
gremlin = {
extraGroups = [ "libvirt" ];
};
};
# Add packages specific to Shura
environment.systemPackages = with pkgs; [
kubectl
kubevirt # Virtctl command-line tool
linuxKernel.packages.linux_zen.xpadneo # Xbox controller driver
];
# Move files into target system
systemd.tmpfiles.rules = [
# Use gremlin user's monitor config for GDM (defined above)
"L+ /run/gdm/.config/monitors.xml - - - - ${monitorsConfig}"
# Install Bluetooth device profiles
"d /var/lib/bluetooth/AC:50:DE:9F:AB:88/ 0700 root root" # First, make sure the directory exists
"L+ /var/lib/bluetooth/AC:50:DE:9F:AB:88/00:0E:DD:72:2F:0C/info - - - - ${shure-aonic-bluetooth}"
"L+ /var/lib/bluetooth/AC:50:DE:9F:AB:88/F4:6A:D7:3A:16:75/info - - - - ${xbox-elite-bluetooth}"
"L+ /var/lib/bluetooth/AC:50:DE:9F:AB:88/F8:5D:3C:7D:9A:00/info - - - - ${mano-touchpad-bluetooth}"
];
# Configure the virtual machine created by nixos-rebuild build-vm
virtualisation.vmVariant.virtualisation = {
memorySize = 4096;
cores = 4;
};
# FIXME: Add extra boot entry for the recovery image. This doesn't work with lanzaboote though :(
# NixOS config: https://nixos.org/manual/nixos/stable/options.html#opt-boot.loader.systemd-boot.extraEntries
# Systemd-boot config: https://wiki.archlinux.org/title/Systemd-boot#Adding_loaders
# Booting an ISO from disk: https://www.reddit.com/r/archlinux/comments/qy281v/boot_an_archlinux_iso_directly_from_my_boot_using/
boot.loader.systemd-boot.extraEntries = {
"nixos-live.conf" = ''
title NixOS
linux /live/vmlinuz-linux
initrd /live/initramfs-linux.img
options img_dev=/dev/nvme0n1p3 img_loop=nixos-gnome-23.11.3019.8bf65f17d807-x86_64-linux.isosudo copytoram
'';
};
}

View file

@ -0,0 +1,95 @@
# Lenovo Legion S7 16ARHA7 configuration
{ config, lib, pkgs, modulesPath, ... }:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
# Configure the kernel.
boot = {
# First, install the latest Zen kernel
kernelPackages = pkgs.linuxPackages_zen;
# Hardware defaults detected by nixos-generate-configuration
initrd = {
# SystemD in the initrd is required for TPM auto-unlocking.
# See https://discourse.nixos.org/t/full-disk-encryption-tpm2/29454/2
# If the LUKS volume is recently created, run this command to bind it to the TPM:
# sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/<device>
systemd.enable = true;
availableKernelModules = [ "nvme" "xhci_pci" "usbhid" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" "tpm_crb" ];
kernelModules = [ "amdgpu" "tpm_crb" ];
luks.devices."luks-bcf67e34-339e-40b9-8ffd-bec8f7f55248" = {
device = "/dev/disk/by-uuid/bcf67e34-339e-40b9-8ffd-bec8f7f55248";
crypttabExtraOpts = [ "tpm2-device=auto" ]; # Enable TPM auto-unlocking
};
};
kernelModules = [
"kvm-amd"
"hid_xpadneo"
];
# Add XPadNeo
extraModulePackages = with config.boot.kernelPackages; [ xpadneo ];
# Add kernel patch to enable sound over the speakers.
# This might not be necessary for long - see https://forums.lenovo.com/topic/findpost/27/5258964/6212600
#kernelPatches = [{
# name = "legion-speaker-fix";
# patch = ./patches/legion_7i-gen7-16IAX7-sound-6.7.3.patch;
#}];
};
fileSystems = {
"/" = { device = "/dev/disk/by-uuid/b801fbea-4cb5-4255-bea9-a2ce77d1a1b7";
fsType = "btrfs";
options = [ "subvol=@,compress=zstd" ];
};
"/home" = { device = "/dev/disk/by-uuid/b801fbea-4cb5-4255-bea9-a2ce77d1a1b7";
fsType = "btrfs";
options = [ "subvol=@home,compress=zstd" ];
};
"/swap" = { device = "/dev/disk/by-uuid/b801fbea-4cb5-4255-bea9-a2ce77d1a1b7";
fsType = "btrfs";
options = [ "subvol=@swap" ];
};
"/boot" = {
device = "/dev/disk/by-uuid/AFCB-D880";
fsType = "vfat";
};
};
swapDevices = [{
device = "/swap/swapfile";
}];
# Enable AMDGPU
hardware = {
opengl = {
driSupport = true; # This is already enabled by default, but just in case.
driSupport32Bit = true; # For 32 bit applications.
extraPackages = with pkgs; [
rocmPackages.clr.icd # OpenCL
];
};
};
networking = {
# 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`.
useDHCP = lib.mkDefault true;
# networking.interfaces.wlp4s0.useDHCP = lib.mkDefault true;
# Set the hostname.
hostName = "Shura";
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

60
hosts/Shura/monitors.xml Normal file
View file

@ -0,0 +1,60 @@
<monitors version="2">
<configuration>
<logicalmonitor>
<x>0</x>
<y>0</y>
<scale>1</scale>
<primary>yes</primary>
<monitor>
<monitorspec>
<connector>DP-2</connector>
<vendor>MSI</vendor>
<product>MSI MAG401QR</product>
<serial>EA5H013900434</serial>
</monitorspec>
<mode>
<width>3440</width>
<height>1440</height>
<rate>144.000</rate>
</mode>
</monitor>
</logicalmonitor>
<disabled>
<monitorspec>
<connector>eDP-2</connector>
<vendor>BOE</vendor>
<product>0x0a9b</product>
<serial>0x00000000</serial>
</monitorspec>
</disabled>
</configuration>
<configuration>
<logicalmonitor>
<x>0</x>
<y>0</y>
<scale>1</scale>
<primary>yes</primary>
<monitor>
<monitorspec>
<connector>DP-1</connector>
<vendor>MSI</vendor>
<product>MSI MAG401QR</product>
<serial>EA5H013900434</serial>
</monitorspec>
<mode>
<width>3440</width>
<height>1440</height>
<rate>144.000</rate>
</mode>
</monitor>
</logicalmonitor>
<disabled>
<monitorspec>
<connector>eDP-2</connector>
<vendor>BOE</vendor>
<product>0x0a9b</product>
<serial>0x00000000</serial>
</monitorspec>
</disabled>
</configuration>
</monitors>

View file

@ -0,0 +1,32 @@
diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c
index d74cf11eef1e..8a6b484b2184 100644
--- a/sound/pci/hda/cs35l41_hda_property.c
+++ b/sound/pci/hda/cs35l41_hda_property.c
@@ -95,6 +95,7 @@ static const struct cs35l41_config cs35l41_config_table[] = {
{ "10431F12", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
{ "10431F1F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 },
{ "10431F62", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
+ { "17AA386F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
{ "17AA38B4", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
{ "17AA38B5", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
{ "17AA38B6", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
@@ -431,6 +432,7 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = {
{ "CSC3551", "10431F12", generic_dsd_config },
{ "CSC3551", "10431F1F", generic_dsd_config },
{ "CSC3551", "10431F62", generic_dsd_config },
+ { "CSC3551", "17AA386F", generic_dsd_config },
{ "CSC3551", "17AA38B4", generic_dsd_config },
{ "CSC3551", "17AA38B5", generic_dsd_config },
{ "CSC3551", "17AA38B6", generic_dsd_config },
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 6994c4c5073c..9ebe42f33d27 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -10269,6 +10269,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3886, "Y780 VECO DUAL", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38a7, "Y780P AMD YG dual", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38a8, "Y780P AMD VECO dual", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x3877, "Legion 7 slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x38b4, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x38b5, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x38b6, "Legion Slim 7 16APH8", ALC287_FIXUP_CS35L41_I2C_2),

View file

@ -0,0 +1,134 @@
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index f7815ee24f83..93d86c5a9d53 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -1270,6 +1270,8 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
size_t nval;
int i, ret;
+ printk("CSC3551: probing %s\n", hid);
+
adev = acpi_dev_get_first_match_dev(hid, NULL, -1);
if (!adev) {
dev_err(cs35l41->dev, "Failed to find an ACPI device for %s\n", hid);
@@ -1287,8 +1289,9 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
property = "cirrus,dev-index";
ret = device_property_count_u32(physdev, property);
if (ret <= 0) {
- ret = cs35l41_no_acpi_dsd(cs35l41, physdev, id, hid);
- goto err_put_physdev;
+ //ret = cs35l41_no_acpi_dsd(cs35l41, physdev, id, hid);
+ //goto err_put_physdev;
+ goto no_acpi_dsd;
}
if (ret > ARRAY_SIZE(values)) {
ret = -EINVAL;
@@ -1383,6 +1386,92 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
put_device(physdev);
return ret;
+
+no_acpi_dsd:
+ /*
+ * Device CLSA0100 doesn't have _DSD so a gpiod_get by the label reset won't work.
+ * And devices created by i2c-multi-instantiate don't have their device struct pointing to
+ * the correct fwnode, so acpi_dev must be used here.
+ * And devm functions expect that the device requesting the resource has the correct
+ * fwnode.
+ */
+
+ printk("CSC3551: no_acpi_dsd: %s\n", hid);
+
+ /* TODO: This is a hack. */
+ if (strncmp(hid, "CSC3551", 7) == 0) {
+ goto csc3551;
+ }
+
+ if (strncmp(hid, "CLSA0100", 8) != 0)
+ return -EINVAL;
+
+ /* check I2C address to assign the index */
+ cs35l41->index = id == 0x40 ? 0 : 1;
+ cs35l41->hw_cfg.spk_pos = cs35l41->index;
+ cs35l41->channel_index = 0;
+ cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH);
+ cs35l41->hw_cfg.bst_type = CS35L41_EXT_BOOST_NO_VSPK_SWITCH;
+ hw_cfg->gpio2.func = CS35L41_GPIO2_INT_OPEN_DRAIN;
+ hw_cfg->gpio2.valid = true;
+ cs35l41->hw_cfg.valid = true;
+ put_device(physdev);
+
+ return 0;
+
+ csc3551:
+
+ printk("CSC3551: id == 0x%x\n", id);
+
+ // cirrus,dev-index
+ if(id == 0x40)
+ cs35l41->index = 0;
+ else
+ cs35l41->index = 1;
+
+ cs35l41->channel_index = 0;
+
+ cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, cs35l41->index, GPIOD_OUT_LOW);
+
+ printk("CS3551: reset_gpio == 0x%x\n", cs35l41->reset_gpio);
+
+ // cirrus,speaker-position
+ if(cs35l41->index == 0)
+ hw_cfg->spk_pos = 0;
+ else
+ hw_cfg->spk_pos = 1;
+
+ // cirrus,gpio1-func
+ hw_cfg->gpio1.func = 1;
+ hw_cfg->gpio1.valid = true;
+
+ // cirrus,gpio2-func
+ hw_cfg->gpio2.func = 0x02;
+ hw_cfg->gpio2.valid = true;
+
+ // cirrus,boost-peak-milliamp
+ hw_cfg->bst_ipk = -1;
+
+ // cirrus,boost-ind-nanohenry
+ hw_cfg->bst_ind = -1;
+
+ // cirrus,boost-cap-microfarad
+ hw_cfg->bst_cap = -1;
+
+ cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, cs35l41->index, nval, -1);
+
+ if (hw_cfg->bst_ind > 0 || hw_cfg->bst_cap > 0 || hw_cfg->bst_ipk > 0)
+ hw_cfg->bst_type = CS35L41_INT_BOOST;
+ else
+ hw_cfg->bst_type = CS35L41_EXT_BOOST;
+
+ hw_cfg->valid = true;
+
+ put_device(physdev);
+
+ printk("CSC3551: Done.\n");
+
+ return 0;
}
int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e103bb3693c0..8ec2b0f99d8c 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -9682,6 +9682,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6),
SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
+ SND_PCI_QUIRK(0x17aa, 0x3874, "Legion 7 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x17aa, 0x386f, "Legion 7 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x17aa, 0x3803, "Legion 7i slim 16IAH7", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x17aa, 0x3856, "Yoga Slim 7 Carbon 14ACN6", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x17aa, 0x3877, "Legion 7 slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),

15
hosts/common/default.nix Normal file
View file

@ -0,0 +1,15 @@
{ lib, ... }:
let
# Fetch secrets.
# NOTE: This requires access to a private repo. Make sure you generate the build as `aires`, then switch to it as root.
nix-secrets = builtins.fetchGit {
url = "ssh://git@code.8bitbuddhism.com:22222/andre/nix-secrets.git";
ref = "main";
rev = "a5b902f720e1e51df0f688b29d449c910468fb28";
};
in{
imports = [
../../modules
"${nix-secrets}/default.nix"
];
}

8
hosts/default.nix Normal file
View file

@ -0,0 +1,8 @@
{ ... }: {
imports = [
./Dimaga
./Haven
./Pihole
./Shura
];
}

12
modules/apps/default.nix Normal file
View file

@ -0,0 +1,12 @@
{ ... }: {
imports = [
./development.nix
./dj.nix
./gaming.nix
./hugo.nix
./media.nix
./office.nix
./pandoc.nix
./recording.nix
];
}

View file

@ -0,0 +1,20 @@
{ config, lib, ... }:
let
cfg = config.host.apps.development;
in
with lib;
{
options = {
host.apps.development.enable = mkEnableOption (mdDoc "Enables development tools");
};
config = mkIf cfg.enable {
host.ui.flatpak.enable = true;
services.flatpak.packages = [
"com.vscodium.codium"
"dev.k8slens.OpenLens"
];
};
}

19
modules/apps/dj.nix Normal file
View file

@ -0,0 +1,19 @@
{ config, lib, ... }:
let
cfg = config.host.apps.dj;
in
with lib;
{
options = {
host.apps.dj.enable = mkEnableOption (mdDoc "Enables DJing tools (i.e. Mixxx)");
};
config = mkIf cfg.enable {
host.ui.flatpak.enable = true;
services.flatpak.packages = [
"org.mixxx.Mixxx"
];
};
}

20
modules/apps/gaming.nix Normal file
View file

@ -0,0 +1,20 @@
{ config, lib, pkgs, ... }:
# Gaming-related settings
let
cfg = config.host.apps.gaming;
in
with lib;
{
options = {
host.apps.gaming.enable = mkEnableOption (mdDoc "Enables gaming features");
};
config = mkIf cfg.enable {
services.flatpak.packages = lib.mkIf (config.services.flatpak.enable == true) [
"gg.minion.Minion"
"com.valvesoftware.Steam"
"org.firestormviewer.FirestormViewer"
];
};
}

19
modules/apps/hugo.nix Normal file
View file

@ -0,0 +1,19 @@
{ pkgs, config, lib, ... }:
let
cfg = config.host.apps.hugo;
in
with lib;
{
options = {
host.apps.hugo.enable = mkEnableOption (mdDoc "Enables Hugo and webdev tools");
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [
hugo
rsync
yarn
];
};
}

28
modules/apps/media.nix Normal file
View file

@ -0,0 +1,28 @@
{ config, lib, ... }:
let
cfg = config.host.apps.media;
in
with lib;
{
options = {
host.apps.media.enable = mkEnableOption (mdDoc "Enables media playback and editing apps");
};
config = mkIf cfg.enable {
host.ui.flatpak.enable = true;
services.flatpak = {
packages = [
"com.calibre_ebook.calibre"
"com.github.unrud.VideoDownloader"
"io.github.celluloid_player.Celluloid"
"org.kde.krita"
"org.kde.KStyle.Adwaita//5.15-23.08" # Retrieved from https://docs.flatpak.org/en/latest/desktop-integration.html
"org.kde.KStyle.Adwaita//6.5"
"org.kde.WaylandDecoration.QAdwaitaDecorations//5.15-23.08" # Replaced deprecated QGnomePlatform https://wiki.archlinux.org/title/Uniform_look_for_Qt_and_GTK_applications
"org.kde.WaylandDecoration.QAdwaitaDecorations//6.5"
];
};
};
}

20
modules/apps/office.nix Normal file
View file

@ -0,0 +1,20 @@
{ config, lib, ... }:
let
cfg = config.host.apps.office;
in
with lib;
{
options = {
host.apps.office.enable = mkEnableOption (mdDoc "Enables office and workstation apps");
};
config = mkIf cfg.enable {
host.ui.flatpak.enable = true;
services.flatpak.packages = [
"org.libreoffice.LibreOffice"
"us.zoom.Zoom"
];
};
}

20
modules/apps/pandoc.nix Normal file
View file

@ -0,0 +1,20 @@
{ pkgs, config, lib, ... }:
let
cfg = config.host.apps.pandoc;
in
with lib;
{
options = {
host.apps.pandoc.enable = mkEnableOption (mdDoc "Enables pandoc");
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [
haskellPackages.pandoc
haskellPackages.pandoc-cli
haskellPackages.pandoc-crossref
texliveSmall
];
};
}

View file

@ -0,0 +1,36 @@
{ config, lib, ... }:
let
cfg = config.host.apps.recording;
in
with lib;
{
options = {
host.apps.recording.enable = mkEnableOption (mdDoc "Enables video editing tools");
};
config = mkIf cfg.enable {
host.ui.flatpak.enable = true;
services.flatpak = {
packages = [
"com.obsproject.Studio"
"com.obsproject.Studio.Plugin.DroidCam"
"org.kde.kdenlive"
];
};
# Add a virtual camera to use with Droidcam
boot = {
extraModulePackages = with config.boot.kernelPackages; [ v4l2loopback.out ];
kernelModules = [ "v4l2loopback" ];
# Note on v4l2loopback kernel module parameters:
# exclusive_caps: Skype, Zoom, Teams etc. will only show device when actually streaming. This MUST be set to 1 for Chrome to detect virtual cameras.
# card_label: Name of virtual camera, how it'll show up in Skype, Zoom, Teams
# https://github.com/umlaeute/v4l2loopback
extraModprobeConfig = ''
options v4l2loopback exclusive_caps=1 card_label="Virtual Camera"
'';
};
};
}

View file

@ -0,0 +1,60 @@
{ lib, config, pkgs, ... }:
let
cfg = config.host.ui.bluetooth;
in
with lib;
{
options = {
host.ui.bluetooth = {
enable = mkEnableOption (mdDoc "Enables bluetooth");
};
};
config = mkIf cfg.enable {
# Set up Bluetooth
hardware.bluetooth = {
enable = true;
powerOnBoot = true;
settings = {
General = {
Enable = "Source,Sink,Media,Socket";
Experimental = true;
KernelExperimental = true;
};
};
};
# Add Bluetooth LE audio support
environment.systemPackages = with pkgs; [
liblc3
];
# Enable Pipewire codec support - see https://pipewire.pages.freedesktop.org/wireplumber/daemon/configuration/bluetooth.html
# FIXME: Editing etc packages causes a "permission denied" build error. Not sure of the cause.
/*
environment.etc = lib.mkIf (config.sound.enable == true) {
"wireplumber/bluetooth.lua.d/51-bluez-config.lua".text = ''
bluez_monitor.properties = {
["bluez5.enable-sbc-xq"] = true,
["bluez5.enable-msbc"] = true,
["bluez5.enable-hw-volume"] = true,
["bluez5.headset-roles"] = "[ hsp_hs hsp_ag hfp_hf hfp_ag ]",
["bluez5.auto-connect"] = "[ hfp_hf hsp_hs a2dp_sink ]"
}
'';
# Reduce audio latency per https://nixos.wiki/wiki/PipeWire#Low-latency_setup
"pipewire/pipewire.conf.d/92-low-latency.conf".text = ''
context.properties = {
default.clock.rate = 48000
default.clock.quantum = 32
default.clock.min-quantum = 32
default.clock.max-quantum = 32
}
'';
};
*/
};
}

View file

@ -0,0 +1,58 @@
{ config, lib, ... }:
# Bootloader
let
cfg = config.host.boot;
in
with lib;
{
options = {
host.boot = {
enable = mkOption {
description = "Automatically configures the bootloader. Set to false to configure manually.";
type = types.bool;
default = true;
};
secureboot.enable = mkOption {
description = "Enables Secureboot";
type = types.bool;
default = true;
};
};
};
config = mkIf cfg.enable (mkMerge[
(mkIf (cfg.secureboot.enable == true) {
boot = {
# Enable Secure Boot
bootspec.enable = true;
# Disable systemd-boot. We lanzaboote now.
loader.systemd-boot.enable = false;
loader.efi.canTouchEfiVariables = true;
lanzaboote = {
enable = true;
pkiBundle = "/etc/secureboot";
};
};
# Set up TPM. See https://nixos.wiki/wiki/TPM
# After installing and rebooting, set it up via https://wiki.archlinux.org/title/Systemd-cryptenroll#Trusted_Platform_Module
security.tpm2 = {
enable = true;
pkcs11.enable = true;
tctiEnvironment.enable = true;
};
})
# Plain boot
(mkIf (cfg.secureboot.enable == false) {
boot = {
loader.systemd-boot.enable = true;
loader.efi.canTouchEfiVariables = true;
};
})
]);
}

9
modules/base/default.nix Normal file
View file

@ -0,0 +1,9 @@
{ ... }: {
imports = [
./bluetooth.nix
./bootloader.nix
./network.nix
./shell.nix
./system.nix
];
}

12
modules/base/network.nix Normal file
View file

@ -0,0 +1,12 @@
{ ... }: {
networking = {
# Enable networking via NetworkManager
networkmanager.enable = true;
# Enable firewall
nftables.enable = true;
firewall = {
enable = true;
};
};
}

7
modules/base/shell.nix Normal file
View file

@ -0,0 +1,7 @@
{ pkgs, ... }:
{
# Install ZSH for all users
programs.zsh.enable = true;
users.defaultUserShell = pkgs.zsh;
}

163
modules/base/system.nix Normal file
View file

@ -0,0 +1,163 @@
{ pkgs, config, lib, inputs, ... }:
# System options
let
cfg = config.host.system;
in
with lib;
{
config = {
# Set up the environment
environment = {
# Install base packages
systemPackages = with pkgs; [
bash
dconf # Needed to fix an issue with Home-manager. See https://github.com/nix-community/home-manager/issues/3113
git
home-manager
nano
p7zip
tpm2-tss
];
# Set default editor to nano
variables.EDITOR = "nano";
# System configuration file overrides
etc = {
# Reduce systemd logout time to 30s
"systemd/system.conf.d/10-reduce-logout-wait-time.conf" = {
text = ''
[Manager]
DefaultTimeoutStopSec=30s
'';
};
};
};
# Enable automatic updates. I'm using a weird setup here to account for pulling secrets from a private repo, which requires aires' SSH keys.
systemd.services = {
"nixos-rebuild" = {
script = ''
nixos-rebuild build . --flake
'';
serviceConfig = {
Type = "oneshot";
User = "${config.users.users.aires.name}";
WorkingDirectory = "${config.users.users.aires.home}/Development/nix-configuration";
};
};
"nixos-activate" = {
script = ''
./result/switch-to-configuration switch
'';
requires = [ "nixos-rebuild.service" ];
serviceConfig = {
Type = "oneshot";
User = "${config.users.users.root.name}";
WorkingDirectory = "${config.users.users.aires.home}/Development/nix-configuration";
};
};
};
systemd.timers = {
"nixos-update" = {
wantedBy = [ "timers.target" ];
wants = [ "network-online.target" ];
timerConfig = {
Unit = "nixos-activate.service";
OnCalendar = "daily";
Persistent = true;
};
};
};
# Configure automatic updates (deprecated in favor of systemd timers)
/*
system = {
# Enable automatic updates
autoUpgrade = {
enable = true;
flake = "${config.users.users.aires.home}/Development/nix-configuration";
flags = [
"--commit-lock-file" # Create a new commit when flake.lock updates
"--update-input"
"nixpkgs"
"-L" # print build logs
];
dates = "02:00";
randomizedDelaySec = "45min";
allowReboot = false;
};
};
*/
# Set your time zone.
time.timeZone = "America/New_York";
# Select internationalisation properties.
i18n = {
defaultLocale = "en_US.UTF-8";
extraLocaleSettings = {
LC_ADDRESS = "en_US.UTF-8";
LC_IDENTIFICATION = "en_US.UTF-8";
LC_MEASUREMENT = "en_US.UTF-8";
LC_MONETARY = "en_US.UTF-8";
LC_NAME = "en_US.UTF-8";
LC_NUMERIC = "en_US.UTF-8";
LC_PAPER = "en_US.UTF-8";
LC_TELEPHONE = "en_US.UTF-8";
LC_TIME = "en_US.UTF-8";
};
};
# Configure nix
nix = {
# Enables Flakes
settings.experimental-features = [ "nix-command" "flakes" ];
# Enable periodic nix store optimization
optimise.automatic = true;
# Enable garbage collection
gc = {
automatic = true;
dates = "daily";
options = "--delete-older-than 7d";
};
# Configure NixOS to use the same software channel as Flakes
registry = lib.mapAttrs (_: value: { flake = value; }) inputs;
nixPath = lib.mapAttrsToList (key: value: "${key}=${value.to.path}") config.nix.registry;
};
# Set up base apps
programs = {
direnv.enable = true;
nano = {
enable = true;
syntaxHighlight = true;
nanorc = ''
set linenumbers
set tabsize 4
set softwrap
'';
};
};
# Scrub BTRFS partitions if the root partition is btrfs
services.btrfs.autoScrub = lib.mkIf (config.fileSystems."/".fsType == "btrfs") {
enable = true;
interval = "weekly";
fileSystems = [ "/" ];
};
# Enable fwupd (firmware updater)
services.fwupd.enable = true;
# Allow systemd user services to keep running after the user has logged out
services.logind.killUserProcesses = false;
};
}

10
modules/default.nix Normal file
View file

@ -0,0 +1,10 @@
{ ... }: {
imports = [
./apps
./base
./roles
./services
./ui
./users
];
}

View file

@ -0,0 +1,27 @@
{ pkgs, lib }:
pkgs.stdenv.mkDerivation rec {
pname = "duplicacy-web";
version = "1.7.2";
src = builtins.fetchurl {
url = "https://acrosync.com/duplicacy-web/duplicacy_web_linux_x64_${version}";
sha256 = "88383f7fea8462539cab7757dfa167bf42e37cbc19531b9de97373bc20efd317";
};
doCheck = false;
dontUnpack = true;
installPhase = ''
install -D $src $out/duplicacy-web
chmod a+x $out/duplicacy-web
'';
meta = with lib; {
homepage = "https://duplicacy.com";
description = "A new generation cloud backup tool";
platforms = platforms.linux;
license = licenses.unfreeRedistributable;
};
}

18
modules/roles/default.nix Normal file
View file

@ -0,0 +1,18 @@
{lib, ...}:
with lib;
{
imports = [
./server.nix
./workstation.nix
];
options = {
host.role = mkOption {
type = types.enum [
"server"
"workstation"
];
};
};
}

15
modules/roles/server.nix Normal file
View file

@ -0,0 +1,15 @@
{ config, lib, modulesPath, pkgs, ... }:
let
role = config.host.role;
in
with lib;
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
config = mkIf (role == "server") {
environment.systemPackages = with pkgs; [
direnv
htop
];
};
}

View file

@ -0,0 +1,35 @@
{ config, lib, modulesPath, pkgs, ... }:
let
role = config.host.role;
in
with lib;
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
config = mkIf (role == "workstation") {
host.ui = {
audio.enable = true;
bluetooth.enable = true;
gnome.enable = true;
flatpak.enable = true;
};
environment.systemPackages = with pkgs; [
direnv
];
boot = {
# Enable Plymouth
plymouth.enable = true;
plymouth.theme = "bgrt";
# Increase minimum log level. This removes ACPI errors from the boot screen.
consoleLogLevel = 1;
# Add kernel parameters
kernelParams = [
"quiet"
];
};
};
}

View file

@ -0,0 +1,17 @@
{ pkgs, config, lib, ... }:
let
cfg = config.host.services.apcupsd;
in
with lib;
{
options = {
host.services.apcupsd.enable = mkEnableOption (mdDoc "Enables apcupsd");
};
config = mkIf cfg.enable {
services.apcupsd = {
enable = true;
configText = (builtins.readFile ./etc/apcupsd.conf);
};
};
}

View file

@ -0,0 +1,8 @@
{ ... }: {
imports = [
./apcupsd.nix
./duplicacy-web.nix
./k3s.nix
./msmtp.nix
];
}

View file

@ -0,0 +1,52 @@
{ pkgs, config, lib, ... }:
let
cfg = config.host.services.duplicacy-web;
duplicacy-web = pkgs.callPackage ../packages/duplicacy-web.nix { inherit pkgs lib; };
in
with lib;
rec {
options = {
host.services.duplicacy-web = {
enable = mkEnableOption (mdDoc "Enables duplicacy-web");
autostart = mkOption {
default = true;
type = types.bool;
description = "Whether to auto-start duplicacy-web on boot";
};
environment = mkOption {
default = "";
type = types.str;
description = "Environment where duplicacy-web stores its config files";
};
};
};
config = mkIf cfg.enable {
nixpkgs.config.allowUnfree = true;
environment.systemPackages = [
duplicacy-web
];
networking.firewall.allowedTCPPorts = [ 3875 ];
# Install systemd service.
systemd.services."duplicacy-web" = {
enable = true;
wants = [ "network-online.target" ];
after = [ "syslog.target" "network-online.target" ];
description = "Start the Duplicacy backup service and web UI";
serviceConfig = {
Type = "simple";
ExecStart = ''${duplicacy-web}/duplicacy-web'';
Restart = "on-failure";
RestartSrc = 10;
KillMode = "process";
};
environment = {
HOME = cfg.environment;
};
} // optionalAttrs (cfg.autostart == true) { wantedBy = ["multi-user.target"]; }; # Start at boot if autostart is enabled.
};
}

View file

@ -0,0 +1,333 @@
## apcupsd.conf v1.1 ##
#
# for apcupsd release 3.14.12 (29 March 2014) - debian
#
# "apcupsd" POSIX config file
#
# ========= General configuration parameters ============
#
# UPSNAME xxx
# Use this to give your UPS a name in log files and such. This
# is particulary useful if you have multiple UPSes. This does not
# set the EEPROM. It should be 8 characters or less.
#UPSNAME
# UPSCABLE <cable>
# Defines the type of cable connecting the UPS to your computer.
#
# Possible generic choices for <cable> are:
# simple, smart, ether, usb
#
# Or a specific cable model number may be used:
# 940-0119A, 940-0127A, 940-0128A, 940-0020B,
# 940-0020C, 940-0023A, 940-0024B, 940-0024C,
# 940-1524C, 940-0024G, 940-0095A, 940-0095B,
# 940-0095C, 940-0625A, M-04-02-2000
#
UPSCABLE usb
# To get apcupsd to work, in addition to defining the cable
# above, you must also define a UPSTYPE, which corresponds to
# the type of UPS you have (see the Description for more details).
# You must also specify a DEVICE, sometimes referred to as a port.
# For USB UPSes, please leave the DEVICE directive blank. For
# other UPS types, you must specify an appropriate port or address.
#
# UPSTYPE DEVICE Description
# apcsmart /dev/tty** Newer serial character device, appropriate for
# SmartUPS models using a serial cable (not USB).
#
# usb <BLANK> Most new UPSes are USB. A blank DEVICE
# setting enables autodetection, which is
# the best choice for most installations.
#
# net hostname:port Network link to a master apcupsd through apcupsd's
# Network Information Server. This is used if the
# UPS powering your computer is connected to a
# different computer for monitoring.
#
# snmp hostname:port:vendor:community
# SNMP network link to an SNMP-enabled UPS device.
# Hostname is the ip address or hostname of the UPS
# on the network. Vendor can be can be "APC" or
# "APC_NOTRAP". "APC_NOTRAP" will disable SNMP trap
# catching; you usually want "APC". Port is usually
# 161. Community is usually "private".
#
# netsnmp hostname:port:vendor:community
# OBSOLETE
# Same as SNMP above but requires use of the
# net-snmp library. Unless you have a specific need
# for this old driver, you should use 'snmp' instead.
#
# dumb /dev/tty** Old serial character device for use with
# simple-signaling UPSes.
#
# pcnet ipaddr:username:passphrase:port
# PowerChute Network Shutdown protocol which can be
# used as an alternative to SNMP with the AP9617
# family of smart slot cards. ipaddr is the IP
# address of the UPS management card. username and
# passphrase are the credentials for which the card
# has been configured. port is the port number on
# which to listen for messages from the UPS, normally
# 3052. If this parameter is empty or missing, the
# default of 3052 will be used.
#
# modbus /dev/tty** Serial device for use with newest SmartUPS models
# supporting the MODBUS protocol.
#
UPSTYPE usb
DEVICE
# POLLTIME <int>
# Interval (in seconds) at which apcupsd polls the UPS for status. This
# setting applies both to directly-attached UPSes (UPSTYPE apcsmart, usb,
# dumb) and networked UPSes (UPSTYPE net, snmp). Lowering this setting
# will improve apcupsd's responsiveness to certain events at the cost of
# higher CPU utilization. The default of 60 is appropriate for most
# situations.
#POLLTIME 60
# LOCKFILE <path to lockfile>
# Path for device lock file. Not used on Win32.
LOCKFILE /var/lock
# SCRIPTDIR <path to script directory>
# Directory in which apccontrol and event scripts are located.
SCRIPTDIR /etc/apcupsd
# PWRFAILDIR <path to powerfail directory>
# Directory in which to write the powerfail flag file. This file
# is created when apcupsd initiates a system shutdown and is
# checked in the OS halt scripts to determine if a killpower
# (turning off UPS output power) is required.
PWRFAILDIR /etc/apcupsd
# NOLOGINDIR <path to nologin directory>
# Directory in which to write the nologin file. The existence
# of this flag file tells the OS to disallow new logins.
NOLOGINDIR /etc
#
# ======== Configuration parameters used during power failures ==========
#
# The ONBATTERYDELAY is the time in seconds from when a power failure
# is detected until we react to it with an onbattery event.
#
# This means that, apccontrol will be called with the powerout argument
# immediately when a power failure is detected. However, the
# onbattery argument is passed to apccontrol only after the
# ONBATTERYDELAY time. If you don't want to be annoyed by short
# powerfailures, make sure that apccontrol powerout does nothing
# i.e. comment out the wall.
ONBATTERYDELAY 6
#
# Note: BATTERYLEVEL, MINUTES, and TIMEOUT work in conjunction, so
# the first that occurs will cause the initation of a shutdown.
#
# If during a power failure, the remaining battery percentage
# (as reported by the UPS) is below or equal to BATTERYLEVEL,
# apcupsd will initiate a system shutdown.
BATTERYLEVEL 5
# If during a power failure, the remaining runtime in minutes
# (as calculated internally by the UPS) is below or equal to MINUTES,
# apcupsd, will initiate a system shutdown.
MINUTES 5
# If during a power failure, the UPS has run on batteries for TIMEOUT
# many seconds or longer, apcupsd will initiate a system shutdown.
# A value of 0 disables this timer.
#
# Note, if you have a Smart UPS, you will most likely want to disable
# this timer by setting it to zero. That way, you UPS will continue
# on batteries until either the % charge remaing drops to or below BATTERYLEVEL,
# or the remaining battery runtime drops to or below MINUTES. Of course,
# if you are testing, setting this to 60 causes a quick system shutdown
# if you pull the power plug.
# If you have an older dumb UPS, you will want to set this to less than
# the time you know you can run on batteries.
TIMEOUT 0
# Time in seconds between annoying users to signoff prior to
# system shutdown. 0 disables.
ANNOY 300
# Initial delay after power failure before warning users to get
# off the system.
ANNOYDELAY 60
# The condition which determines when users are prevented from
# logging in during a power failure.
# NOLOGON <string> [ disable | timeout | percent | minutes | always ]
NOLOGON disable
# If KILLDELAY is non-zero, apcupsd will continue running after a
# shutdown has been requested, and after the specified time in
# seconds attempt to kill the power. This is for use on systems
# where apcupsd cannot regain control after a shutdown.
# KILLDELAY <seconds> 0 disables
KILLDELAY 0
#
# ==== Configuration statements for Network Information Server ====
#
# NETSERVER [ on | off ] on enables, off disables the network
# information server. If netstatus is on, a network information
# server process will be started for serving the STATUS and
# EVENT data over the network (used by CGI programs).
NETSERVER on
# NISIP <dotted notation ip address>
# IP address on which NIS server will listen for incoming connections.
# This is useful if your server is multi-homed (has more than one
# network interface and IP address). Default value is 0.0.0.0 which
# means any incoming request will be serviced. Alternatively, you can
# configure this setting to any specific IP address of your server and
# NIS will listen for connections only on that interface. Use the
# loopback address (127.0.0.1) to accept connections only from the
# local machine.
NISIP 127.0.0.1
# NISPORT <port> default is 3551 as registered with the IANA
# port to use for sending STATUS and EVENTS data over the network.
# It is not used unless NETSERVER is on. If you change this port,
# you will need to change the corresponding value in the cgi directory
# and rebuild the cgi programs.
NISPORT 3551
# If you want the last few EVENTS to be available over the network
# by the network information server, you must define an EVENTSFILE.
EVENTSFILE /var/log/apcupsd.events
# EVENTSFILEMAX <kilobytes>
# By default, the size of the EVENTSFILE will be not be allowed to exceed
# 10 kilobytes. When the file grows beyond this limit, older EVENTS will
# be removed from the beginning of the file (first in first out). The
# parameter EVENTSFILEMAX can be set to a different kilobyte value, or set
# to zero to allow the EVENTSFILE to grow without limit.
EVENTSFILEMAX 10
#
# ========== Configuration statements used if sharing =============
# a UPS with more than one machine
#
# Remaining items are for ShareUPS (APC expansion card) ONLY
#
# UPSCLASS [ standalone | shareslave | sharemaster ]
# Normally standalone unless you share an UPS using an APC ShareUPS
# card.
UPSCLASS standalone
# UPSMODE [ disable | share ]
# Normally disable unless you share an UPS using an APC ShareUPS card.
UPSMODE disable
#
# ===== Configuration statements to control apcupsd system logging ========
#
# Time interval in seconds between writing the STATUS file; 0 disables
STATTIME 0
# Location of STATUS file (written to only if STATTIME is non-zero)
STATFILE /var/log/apcupsd.status
# LOGSTATS [ on | off ] on enables, off disables
# Note! This generates a lot of output, so if
# you turn this on, be sure that the
# file defined in syslog.conf for LOG_NOTICE is a named pipe.
# You probably do not want this on.
LOGSTATS off
# Time interval in seconds between writing the DATA records to
# the log file. 0 disables.
DATATIME 0
# FACILITY defines the logging facility (class) for logging to syslog.
# If not specified, it defaults to "daemon". This is useful
# if you want to separate the data logged by apcupsd from other
# programs.
#FACILITY DAEMON
#
# ========== Configuration statements used in updating the UPS EPROM =========
#
#
# These statements are used only by apctest when choosing "Set EEPROM with conf
# file values" from the EEPROM menu. THESE STATEMENTS HAVE NO EFFECT ON APCUPSD.
#
# UPS name, max 8 characters
#UPSNAME UPS_IDEN
# Battery date - 8 characters
#BATTDATE mm/dd/yy
BATTDATE 07/08/19
# Sensitivity to line voltage quality (H cause faster transfer to batteries)
# SENSITIVITY H M L (default = H)
#SENSITIVITY H
# UPS delay after power return (seconds)
# WAKEUP 000 060 180 300 (default = 0)
#WAKEUP 60
# UPS Grace period after request to power off (seconds)
# SLEEP 020 180 300 600 (default = 20)
#SLEEP 180
# Low line voltage causing transfer to batteries
# The permitted values depend on your model as defined by last letter
# of FIRMWARE or APCMODEL. Some representative values are:
# D 106 103 100 097
# M 177 172 168 182
# A 092 090 088 086
# I 208 204 200 196 (default = 0 => not valid)
#LOTRANSFER 208
# High line voltage causing transfer to batteries
# The permitted values depend on your model as defined by last letter
# of FIRMWARE or APCMODEL. Some representative values are:
# D 127 130 133 136
# M 229 234 239 224
# A 108 110 112 114
# I 253 257 261 265 (default = 0 => not valid)
#HITRANSFER 253
# Battery charge needed to restore power
# RETURNCHARGE 00 15 50 90 (default = 15)
#RETURNCHARGE 15
# Alarm delay
# 0 = zero delay after pwr fail, T = power fail + 30 sec, L = low battery, N = never
# BEEPSTATE 0 T L N (default = 0)
BEEPSTATE N
# Low battery warning delay in minutes
# LOWBATT 02 05 07 10 (default = 02)
#LOWBATT 2
# UPS Output voltage when running on batteries
# The permitted values depend on your model as defined by last letter
# of FIRMWARE or APCMODEL. Some representative values are:
# D 115
# M 208
# A 100
# I 230 240 220 225 (default = 0 => not valid)
#OUTPUTVOLTS 230
# Self test interval in hours 336=2 weeks, 168=1 week, ON=at power on
# SELFTEST 336 168 ON OFF (default = 336)
#SELFTEST 336

57
modules/services/k3s.nix Normal file
View file

@ -0,0 +1,57 @@
{ config, lib, pkgs, ... }:
let
cfg = config.host.services.k3s;
in
with lib;
{
options = {
host.services.k3s = {
enable = mkEnableOption (mdDoc "Enables K3s");
role = mkOption {
default = "server";
type = types.enum [
"agent"
"server"
];
description = "Which K3s role to use";
};
serverAddr = mkOption {
default = "";
type = types.str;
description = "If an agent, this is the address of the server.";
};
};
};
config = mkIf cfg.enable {
# Add packages for developing with K3s.
# For details, see https://nixos.wiki/wiki/K3s
environment.systemPackages = with pkgs; [
k3s
];
networking.firewall = {
allowedTCPPorts = [
6443 # k3s: required so that pods can reach the API server (running on port 6443 by default)
# 2379 # k3s, etcd clients: required if using a "High Availability Embedded etcd" configuration
# 2380 # k3s, etcd peers: required if using a "High Availability Embedded etcd" configuration
];
allowedUDPPorts = [
# 8472 # k3s, flannel: required if using multi-node for inter-node networking
];
};
services.k3s = {
enable = true;
role = cfg.role;
extraFlags = toString [
# "--kubelet-arg=v=4" # Optionally add additional args to k3s
];
} // optionalAttrs (cfg.role == "agent") { serverAddr = cfg.serverAddr; };
# Increase number of open file handlers so K3s doesn't exhaust them...again.
systemd.extraConfig = ''
DefaultLimitNOFILE=8192:1048576
'';
};
}

View file

@ -0,0 +1,25 @@
# See https://nixos.wiki/wiki/Msmtp
{ config, lib, ... }:
let
cfg = config.host.services.msmtp;
in
with lib;
{
options = {
host.services.msmtp.enable = mkEnableOption (mdDoc "Enables mail server");
};
config = mkIf cfg.enable {
programs.msmtp = {
enable = true;
accounts.default = {
auth = true;
tls = true;
from = "root@${config.networking.hostName}";
user = "root";
# SMTP host and password set in nix-secrets
};
};
};
}

33
modules/ui/audio.nix Normal file
View file

@ -0,0 +1,33 @@
{ pkgs, lib, config, ... }:
let
cfg = config.host.ui.audio;
in
with lib;
{
options = {
host.ui.audio.enable = mkEnableOption (mdDoc "Enables audio");
};
config = mkIf cfg.enable {
# Enable sound with pipewire.
sound.enable = true;
security.rtkit.enable = true;
hardware.pulseaudio = {
enable = false;
package = pkgs.pulseaudioFull; # Enable extra audio codecs
};
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
jack.enable = true;
};
services.flatpak.packages = lib.mkIf (config.host.ui.flatpak.enable == true) [
"com.github.wwmm.easyeffects"
];
};
}

9
modules/ui/default.nix Normal file
View file

@ -0,0 +1,9 @@
{ ... }:
{
imports = [
./audio.nix
./flatpak.nix
./gnome.nix
];
}

65
modules/ui/flatpak.nix Normal file
View file

@ -0,0 +1,65 @@
{ nix-flatpak, pkgs, config, lib, ... }:
# Flatpak support and options
let
cfg = config.host.ui.flatpak;
in
with lib;
{
options = {
host.ui.flatpak.enable = mkEnableOption (mdDoc "Enables Flatpak");
};
config = mkIf cfg.enable {
# Enable Flatpak
services.flatpak = {
enable = true;
# Enable daily automatic updates
update.auto = {
enable = true;
onCalendar = "daily";
};
# Add remote(s)
remotes = [
{ name = "flathub"; location = "https://dl.flathub.org/repo/flathub.flatpakrepo"; }
];
# Install Flatpaks. For details, see https://github.com/gmodena/nix-flatpak
packages = [
"com.github.tchx84.Flatseal"
"md.obsidian.Obsidian"
"org.keepassxc.KeePassXC"
"org.mozilla.firefox"
];
};
# Workaround for getting Flatpak apps to use system fonts, icons, and cursors
# For details (and source), see https://github.com/NixOS/nixpkgs/issues/119433#issuecomment-1767513263
system.fsPackages = [ pkgs.bindfs ];
fileSystems = let
mkRoSymBind = path: {
device = path;
fsType = "fuse.bindfs";
options = [ "ro" "resolve-symlinks" "x-gvfs-hide" ];
};
aggregatedIcons = pkgs.buildEnv {
name = "system-icons";
paths = with pkgs; [
#libsForQt5.breeze-qt5 # for plasma
gnome.gnome-themes-extra
];
pathsToLink = [ "/share/icons" ];
};
aggregatedFonts = pkgs.buildEnv {
name = "system-fonts";
paths = config.fonts.packages;
pathsToLink = [ "/share/fonts" ];
};
in {
"/usr/share/icons" = mkRoSymBind "${aggregatedIcons}/share/icons";
"/usr/local/share/fonts" = mkRoSymBind "${aggregatedFonts}/share/fonts";
};
};
}

122
modules/ui/gnome.nix Normal file
View file

@ -0,0 +1,122 @@
{ pkgs, config, lib, ... }:
# UI and desktop-related options
let
cfg = config.host.ui.gnome;
in
with lib;
{
options = {
host.ui.gnome.enable = mkEnableOption (mdDoc "Enables Gnome");
};
config = mkIf cfg.enable {
host.ui.audio.enable = true;
host.ui.flatpak.enable = true;
# Configure the xserver
services.xserver = {
# Enable the X11 windowing system.
enable = true;
# Configure keymap in X11
xkb = {
layout = "us";
variant = "";
};
# Enable Gnome
desktopManager.gnome.enable = true;
displayManager = {
gdm.enable = true;
};
};
# Remove default packages that came with the install
services.xserver.excludePackages = (with pkgs; [
xterm
]);
environment.gnome.excludePackages = (with pkgs; [
gnome-photos
gnome-tour
gnomeExtensions.extension-list
gedit # text editor
]) ++ (with pkgs.gnome; [
cheese # webcam tool
gnome-music
gnome-calendar
epiphany # web browser
geary # email reader
evince # document viewer
gnome-characters
totem # video player
tali # poker game
iagno # go game
hitori # sudoku game
atomix # puzzle game
]);
# Install additional Gnome packages
environment.systemPackages = with pkgs; [
# Gnome tweak tools
gnome.gnome-tweaks
# Gnome extensions
gnomeExtensions.appindicator
gnomeExtensions.dash-to-panel
gnomeExtensions.gsconnect
gnomeExtensions.forge
# Themeing
gnome.gnome-themes-extra
qogir-icon-theme
];
# Install Flatpaks
services.flatpak.packages = [
"com.mattjakeman.ExtensionManager"
"org.bluesabre.MenuLibre"
"org.gnome.baobab"
"org.gnome.Calculator"
"org.gnome.Characters"
"org.gnome.Calendar"
"org.gnome.Evince"
"org.gnome.Evolution"
"org.gnome.FileRoller"
"org.gnome.Firmware"
"org.gnome.gitg"
"org.gnome.Loupe" # Gnome's fancy new image viewer
"org.gnome.Music"
"org.gnome.seahorse.Application"
"org.gnome.TextEditor"
"org.gtk.Gtk3theme.Adwaita-dark"
];
# Disable CUPS - not needed
services.printing.enable = false;
# Manage fonts
fonts = {
# Install extra fonts
packages = with pkgs; [
noto-fonts
noto-fonts-cjk
noto-fonts-emoji
liberation_ttf
fira-code
fira-code-symbols
fira
roboto-slab
];
# Enable font dir for use with Flatpak. See https://nixos.wiki/wiki/Fonts#Flatpak_applications_can.27t_find_system_fonts
fontDir.enable = true;
};
# Gnome UI integration for KDE apps
qt = {
enable = true;
platformTheme = "gnome";
style = "adwaita-dark";
};
};
}

View file

@ -0,0 +1,156 @@
{ pkgs, lib, config, ... }:
# Define 'aires'
let
cfg = config.host.users.aires;
in
with lib;
{
options = {
host.users.aires = {
enable = mkEnableOption (mdDoc "Enables aires user account");
autologin = mkEnableOption (mdDoc "Automatically logs aires in on boot");
services.syncthing = {
enable = mkEnableOption (mdDoc "Enables Syncthing");
enableTray = mkEnableOption (mdDoc "Enables the Syncthing Tray application");
autostart = mkOption {
default = true;
type = types.bool;
description = "Whether to auto-start Syncthing on boot";
};
};
};
};
config = mkIf cfg.enable (mkMerge [
({
users.users.aires = {
isNormalUser = true;
description = "Aires";
uid = 1000;
extraGroups = [ "input" "networkmanager" "plugdev" "tss" "wheel" ]; # tss group has access to TPM devices
# Allow systemd services to run even while aires is logged out
linger = true;
};
# Install aires-specific Flatpaks
services.flatpak.packages = mkIf (config.services.flatpak.enable == true) [
"com.discordapp.Discord"
"org.telegram.desktop"
];
# Configure home-manager
home-manager.users.aires = {
imports = [
../common/gnome.nix
];
# The state version is required and should stay at the version you originally installed.
home.stateVersion = "24.05";
# Let home Manager install and manage itself.
programs.home-manager.enable = true;
# Basic setup
home.username = "aires";
home.homeDirectory = "/home/aires";
# Install extra packages, specifically gnome extensions
home.packages = lib.mkIf (config.host.ui.gnome.enable) [
pkgs.gnomeExtensions.wallpaper-slideshow
];
# Set up git
programs.git = {
enable = true;
# Username and email set in nix-secrets
extraConfig = {
push.autoSetupRemote = "true";
};
};
# SSH set up in nix-secrets
# Set up Zsh
programs.zsh = {
enable = true;
oh-my-zsh = {
enable = true;
plugins = [
"git"
];
theme = "gentoo";
};
enableAutosuggestions = true;
syntaxHighlighting.enable = true;
history.ignoreDups = true; # Do not enter command lines into the history list if they are duplicates of the previous event.
prezto = {
git.submoduleIgnore = "untracked"; # Ignore submodules when they are untracked.
};
shellAliases = {
dry-build = "cd ~/Development/nix-configuration && nix flake update && nixos-rebuild dry-build --flake .";
update = "cd ~/Development/nix-configuration && nix flake update && sudo nixos-rebuild switch --flake .";
upgrade = "update";
protontricks = "flatpak run com.github.Matoking.protontricks";
please = "sudo";
};
};
# Gnome settings specific to aires on Shura
dconf.settings = lib.mkIf (config.networking.hostName == "Shura") {
"org/gnome/desktop/interface" = {
# Increase font scaling(if config.networking.hostName == "Haven" then false else true);
text-scaling-factor = 1.2;
# Dark mode
color-scheme = "prefer-dark";
};
};
};
})
# Autologin aires
(mkIf (cfg.autologin == true) {
services.xserver.displayManager.autoLogin = {
enable = true;
user = "aires";
};
systemd.services = {
"getty@tty1".enable = false;
"autovt@tty1".enable = false;
};
})
# Enable Syncthing
(mkIf (cfg.services.syncthing.enable == true) {
users.users.aires.packages = [
pkgs.syncthing
(mkIf (cfg.services.syncthing.enableTray == true) pkgs.syncthingtray)
];
# Open port 8080
networking.firewall.allowedTCPPorts = [
8080
];
home-manager.users.aires = {
# Syncthing options
services.syncthing = {
enable = true;
extraOptions = [
"--gui-address=0.0.0.0:8080"
"--home=${config.users.users.aires.home}/.config/syncthing"
"--no-default-folder"
];
};
# Override the default Syncthing settings so it doesn't start on boot
systemd.user.services."syncthing" = mkIf (cfg.services.syncthing.autostart == false) {
Install = lib.mkForce {};
};
};
})
]);
}

View file

@ -0,0 +1,51 @@
{ lib, pkgs, osConfig, ... }: {
# Additional Gnome configurations via home-manager. Imported by default by aires and gremlin.
dconf.settings = lib.mkIf (osConfig.host.ui.gnome.enable) {
"org/gnome/mutter" = {
edge-tiling = true;
workspaces-only-on-primary = false;
};
"org/gnome/desktop/interface" = {
# Configure fonts
font-name = "Fira Sans Semi-Light 11";
document-font-name = "Roboto Slab 11";
monospace-font-name = "Liberation Mono 11";
titlebar-font = "Fira Sans Semi-Bold 11";
# Configure hinting
font-hinting = "slight";
font-antialiasing = "rgba";
# Configure workspace
enable-hot-corners = true;
};
# Configure touchpad scroll & tap behavior
"org/gnome/desktop/peripherals/touchpad" = {
disable-while-typing = true;
click-method = "fingers";
tap-to-click = true;
natural-scroll = true;
two-finger-scrolling-enabled = true;
};
# Tweak window management
"org/gnome/desktop/wm/preferences" = {
button-layout = "appmenu:minimize,maximize,close";
resize-with-right-button = true;
focus-mode = "click";
};
# Make alt-tab switch windows, not applications
"org/gnome/desktop/wm/keybindings" = {
switch-tab = [];
switch-windows = [ "<Alt>Tab" ];
switch-windows-backward = [ "<Shift><Alt>Tab" ];
};
"org/gnome/shell" = {
disable-user-extensions = false;
};
};
}

View file

@ -0,0 +1,7 @@
{ ... }: {
imports = [
./aires
./gremlin
./media
];
}

View file

@ -0,0 +1,125 @@
{ pkgs, lib, config, ... }:
# Define 'gremlin' user
let
cfg = config.host.users.gremlin;
in
with lib;
{
options = {
host.users.gremlin = {
enable = mkEnableOption (mdDoc "Enables gremlin user account");
services.syncthing = {
enable = mkEnableOption (mdDoc "Enables Syncthing");
enableTray = mkEnableOption (mdDoc "Enables the Syncthing Tray application");
autostart = mkOption {
default = true;
type = types.bool;
description = "Whether to auto-start Syncthing on boot";
};
};
};
};
config = mkMerge [
(mkIf cfg.enable {
# Add Gremlin account
users.users.gremlin = {
isNormalUser = true;
description = "Gremlin";
uid = 1001;
extraGroups = [ "networkmanager" "input" ];
# Allow systemd services to keep running even while gremlin is logged out
linger = true;
};
# Install gremlin-specific flatpaks
services.flatpak.packages = lib.mkIf (config.services.flatpak.enable == true) [
"com.google.Chrome"
"com.slack.Slack"
];
home-manager.users.gremlin = {
imports = [
../common/gnome.nix
];
# The state version is required and should stay at the version you originally installed.
home.stateVersion = "24.05";
# Let home Manager install and manage itself.
programs.home-manager.enable = true;
# Basic setup
home.username = "gremlin";
home.homeDirectory = "/home/gremlin";
# Set up git
programs.git = {
# Name and email set in nix-secrets
enable = true;
extraConfig = {
push.autoSetupRemote = "true";
};
};
# SSH entries set in nix-secrets
# Set up Zsh
programs.zsh = {
enable = true;
# Install and source the p10k theme
plugins = [
{ name = "powerlevel10k"; src = pkgs.zsh-powerlevel10k; file = "share/zsh-powerlevel10k/powerlevel10k.zsh-theme"; }
{ name = "powerlevel10k-config"; src = ./p10k-config; file = "p10k.zsh"; }
];
enableAutosuggestions = true;
syntaxHighlighting.enable = true;
history.ignoreDups = true; # Do not enter command lines into the history list if they are duplicates of the previous event.
prezto = {
git.submoduleIgnore = "untracked"; # Ignore submodules when they are untracked.
};
shellAliases = {
please = "sudo";
};
oh-my-zsh = {
enable = true;
plugins = [
"git"
];
};
};
};
})
# Enable Syncthing
(mkIf (cfg.services.syncthing.enable == true) {
users.users.gremlin = {
packages = [
pkgs.syncthing
(mkIf (cfg.services.syncthing.enableTray == true) pkgs.syncthingtray)
];
};
home-manager.users.gremlin = {
# Syncthing options
services.syncthing = {
enable = true;
extraOptions = [
"--gui-address=0.0.0.0:8081"
"--home=${config.users.users.gremlin.home}.config/syncthing"
"--no-default-folder"
];
};
# Override the default Syncthing settings so it doesn't start on boot
systemd.user.services."syncthing" = mkIf (cfg.services.syncthing.autostart == false) {
Install = lib.mkForce {};
};
};
})
];
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,29 @@
{ pkgs, lib, config, ... }:
# Define user for managing media on Haven
let
cfg = config.host.users.media;
in
with lib;
{
options = {
host.users.media = {
enable = mkEnableOption (mdDoc "Enables media user account");
};
};
config = mkIf cfg.enable {
users.groups."media" = {
gid = 1001;
};
users.users.media = {
isNormalUser = false;
isSystemUser = true;
description = "Media manager";
uid = 1001;
group = "media";
};
};
}