├── .gitattributes ├── .gitignore ├── .vscode └── settings.json ├── README.md ├── bin ├── compile-manuscript.sh ├── format-drives.sh └── nixos-operations-script.sh ├── flake.lock ├── flake.nix ├── homes ├── common │ ├── git.nix │ ├── gnome.nix │ └── zsh.nix └── x86_64-linux │ ├── aires │ ├── default.nix │ ├── face.png │ └── fastfetch │ │ ├── fastfetch-config.jsonc │ │ ├── lion_ascii.txt │ │ └── lion_ascii_smol.txt │ └── gremlin@Shura │ ├── default.nix │ └── face.png ├── lib └── default.nix ├── modules └── nixos │ ├── apps │ ├── development │ │ └── default.nix │ ├── gaming │ │ └── default.nix │ ├── media │ │ └── default.nix │ ├── office │ │ └── default.nix │ ├── recording │ │ └── default.nix │ ├── social │ │ └── default.nix │ └── writing │ │ └── default.nix │ ├── default.nix │ ├── secrets │ ├── Freight-20240828T164047Z-001.zip │ └── default.nix │ ├── services │ ├── acme │ │ └── default.nix │ ├── apcupsd │ │ └── default.nix │ ├── archiveteam-warrior │ │ └── default.nix │ ├── autoupgrade │ │ └── default.nix │ ├── binary-cache │ │ └── default.nix │ ├── boinc │ │ └── default.nix │ ├── duplicacy-web │ │ └── default.nix │ ├── forgejo │ │ └── default.nix │ ├── jellyfin │ │ ├── default.nix │ │ └── jellyfin-audio-save-position.patch │ ├── languagetool │ │ └── default.nix │ ├── msmtp │ │ └── default.nix │ ├── nginx │ │ └── default.nix │ ├── observability │ │ └── default.nix │ ├── ollama │ │ └── default.nix │ ├── qbittorrent │ │ └── default.nix │ ├── ssh │ │ └── default.nix │ ├── syncthing │ │ └── default.nix │ ├── tor │ │ └── default.nix │ ├── virtualization │ │ └── default.nix │ └── vpn │ │ └── default.nix │ ├── system │ ├── bluetooth │ │ └── default.nix │ ├── bootloader │ │ └── default.nix │ ├── default.nix │ ├── filesystem │ │ └── default.nix │ ├── gpu │ │ └── default.nix │ ├── networking │ │ └── default.nix │ ├── nix │ │ └── default.nix │ ├── power │ │ ├── default.nix │ │ └── power-profiles-daemon.patch │ └── raid │ │ └── default.nix │ ├── ui │ ├── audio │ │ └── default.nix │ ├── desktops │ │ ├── default.nix │ │ └── gnome │ │ │ └── default.nix │ └── flatpak │ │ └── default.nix │ └── users │ ├── aires │ └── default.nix │ ├── gremlin │ └── default.nix │ ├── media │ └── default.nix │ └── root │ └── default.nix ├── nix-on-droid ├── Readme.md └── Skadi │ ├── default.nix │ ├── homes │ └── default.nix │ └── modules │ ├── nix │ └── default.nix │ └── ssh │ ├── default.nix │ └── sshd_config ├── overlays └── pkgs │ └── unstable │ └── default.nix ├── packages ├── duplicacy-web │ └── default.nix ├── freight-pro │ └── default.nix └── languagetool-ngrams │ └── default.nix ├── systems ├── aarch64-linux │ └── Pihole │ │ ├── default.nix │ │ └── hardware-configuration.nix └── x86_64-linux │ ├── Hevana │ ├── default.nix │ ├── etc │ │ └── apcupsd.conf │ └── hardware-configuration.nix │ ├── Khanda │ ├── default.nix │ └── hardware-configuration.nix │ ├── Shura │ ├── default.nix │ ├── hardware-configuration.nix │ └── monitors.xml │ └── gremlin-lab │ ├── default.nix │ └── hardware-configuration.nix ├── templates ├── module │ └── default.nix └── systems │ ├── default.nix │ └── hardware-configuration.nix └── treefmt.nix /.gitattributes: -------------------------------------------------------------------------------- 1 | modules/nixos/secrets/** filter=crypt diff=crypt merge=crypt 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.qcow2 2 | result -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "direnv.path.executable": "/run/current-system/sw/bin/direnv", 3 | "direnv.restart.automatic": true, 4 | "nix.enableLanguageServer": true, 5 | "nix.serverPath": "/run/current-system/sw/bin/nil", 6 | "nix.formatterPath": "treefmt" 7 | } 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NixOS Configuration 2 | 3 | A full set of configuration files managed via NixOS. This project uses the [Snowfall library](https://snowfall.org/guides/lib/quickstart). 4 | 5 | > [!NOTE] 6 | > Are you new to NixOS? Hi, hello, and welcome! This repository probably won't make much sense to you 😅 If you're looking for a good beginner configuration or template, check out https://github.com/Misterio77/nix-starter-configs 7 | > 8 | > Warning: DO NOT DOWNLOAD AND RUN `nixos-rebuild` ON THIS REPOSITORY! These are my personal configuration files. I invite you to look through them, modify them, and take inspiration from them, but if you run `nixos-rebuild`, it _will completely overwrite your current system_! 9 | 10 | ## Using this repo 11 | 12 | ### Note on secrets management 13 | 14 | Secrets are managed using [transcrypt](https://github.com/elasticdog/transcrypt). To unlock the repo, use `transcrypt -c [cipher] -p '[password]'`. Transcrypt will transparently encrypt/decrypt files stored in `modules/nixos/secrets` going forward. You can get the cipher and password from a host with transcrypt already configured by running `transcrypt --display`. 15 | 16 | > [!NOTE] 17 | > This is a poor man's secret management solution. If you use this, your secrets will be world-readable in the `/nix/store/`. 18 | 19 | ### First-time installation 20 | 21 | When installing on a brand new system, partition the main drive into two partitions: a `/boot` partition, and a LUKS partition. Then, run `bin/format-drives.sh --root [root partition] --luks [luks partition]` (the script will request sudo privileges): 22 | 23 | ```sh 24 | ./bin/format-drives.sh --boot /dev/nvme0n1p1 --luks /dev/nvme0n1p2 25 | ``` 26 | 27 | Next, set up the host's config in the `systems/[architecture]` folder by copying `default.nix.template` and `hardware-configuration.nix.template` into a new folder named after the hostname. Running `format-drives.sh` also generates a `hardware-configuration.nix` file you can use. 28 | 29 | If necessary, import modules by adding the host to `flake.nix` under the `outputs.systems.hosts` section. 30 | 31 | Finally, run the NixOS installer, replacing `host` with your actual hostname: 32 | 33 | ```sh 34 | sudo nixos-install --verbose --root /mnt --flake .#host --no-root-password 35 | ``` 36 | 37 | > [!TIP] 38 | > This config installs a nixos-rebuild wrapper called `nos` (NixOS Operations Script) that handles pulling and pushing changes to your configuration repository via git. For more info, run `nixos-operations-script --help`. 39 | 40 | ### Running updates 41 | 42 | To update a system, run `nixos-operations-script` (or just `nos`). To commit updates back to the repo, use `nos --update`. Do not run this script as root - it will automatically request sudo permissions as needed. 43 | 44 | #### Automatic updates 45 | 46 | To enable automatic updates for a host, set `config.${namespace}.services.autoUpgrade = true;`. You can configure the autoUpgrade module with additional settings, e.g.: 47 | 48 | ```nix 49 | services.autoUpgrade = { 50 | enable = true; 51 | configDir = config.${namespace}.secrets.nixConfigFolder; 52 | onCalendar = "daily"; 53 | user = config.users.users.aires.name; 54 | }; 55 | ``` 56 | 57 | Automatic updates work by running `nos`. There's an additional `pushUpdates` option that, when enabled, updates the `flake.lock` file and pushes it back up to the Git repository. Only one host needs to do this (in this case, it's [Hevana](./systems/x86_64-linux/Hevana)), but you can safely enable it on multiple hosts as long as they use the same repository and update at different times. 58 | 59 | #### Manually updating 60 | 61 | Run `nos` to update the system. Use the `--update` flag to update `flake.lock` as part of the process. For the first build, you'll need to specify the path to your `flake.nix` file and the hostname using `nos --hostname my_hostname --flake /path/to/flake.nix`. 62 | 63 | After the first build, you can omit the hostname and path: 64 | 65 | ```sh 66 | nos 67 | ``` 68 | 69 | This is the equivalent of running: 70 | 71 | ```sh 72 | cd [flake dir] 73 | git pull 74 | nix flake update --commit-lock-file 75 | git push 76 | sudo nixos-rebuild switch --flake . 77 | ``` 78 | 79 | There are a few different actions for handling the update: 80 | 81 | - `switch` replaces the running system immediately. 82 | - `boot` switches to the new generation during the next reboot. 83 | - `build` creates and caches the update without applying it. 84 | - `test` creates the generation and switches to it, but doesn't add it to the bootloader. 85 | 86 | #### Using Remote builds 87 | 88 | Nix can create builds for or on remote systems, and transfer them via SSH. 89 | 90 | ##### Generating a build on a remote system 91 | 92 | You can run a build on a remote server by using `--build-host`: 93 | 94 | ```sh 95 | nixos-rebuild build --flake . --build-host [remote hostname] 96 | ``` 97 | 98 | ##### Pushing a build to a remote system 99 | 100 | Conversely, you can run a build on the local host, then push it to a remote system. 101 | 102 | ```sh 103 | NIX_SSHOPTS="-o RequestTTY=force" nixos-rebuild --target-host user@example.com --use-remote-sudo switch 104 | ``` 105 | 106 | ### Testing without modifying the system 107 | 108 | If you want to test without doing a whole build, or without modifying the current system, there are a couple additional tools to try. 109 | 110 | #### Dry builds 111 | 112 | To quickly validate your configuration, create a dry build. This analyzes your configuration to determine whether it'll actually build: 113 | 114 | ```zsh 115 | nixos-rebuild dry-build --flake . 116 | ``` 117 | 118 | #### Virtual machines 119 | 120 | You can also build a virtual machine image to preview changes. The first command builds the VM, and the second runs it: 121 | 122 | ```zsh 123 | nixos-rebuild build-vm --flake . 124 | ./result/bin/run-nixos-vm 125 | ``` 126 | 127 | > [!NOTE] 128 | > Running the VM also creates a `.qcow2` file for data persistence. Remove this file after a while, otherwise data might persist between builds and muck things up. 129 | 130 | ## About this repository 131 | 132 | This config uses the [Snowfall lib](https://snowfall.org/), along with some default options and settings for common software. It features: 133 | 134 | - Flakes 135 | - Home Manager 136 | - Automatic daily updates 137 | - AMD, Intel, and Raspberry Pi (ARM64) hardware configurations 138 | - Support for various GUIs and desktop environments including Gnome, KDE, XFCE, and Hyprland 139 | - Boot splash screens via Plymouth 140 | - Secure Boot support via Lanzaboote 141 | - Disk encryption via LUKS with TPM auto-unlocking 142 | - Custom packages and systemd services 143 | - Flatpaks 144 | - Default ZSH shell using Oh My ZSH 145 | - Secrets (sorta - using Transcrypt) 146 | -------------------------------------------------------------------------------- /bin/compile-manuscript.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Script to compile Markdown files within a directory into various output formats. 3 | # Based on https://github.com/8bitbuddhist/markdown-novel-template 4 | 5 | draftName="draft" 6 | inDir="." 7 | outDir="./out" 8 | metadataFile="$inDir/metadata.yml" 9 | 10 | function usage() { 11 | echo "Compile a directory of Markdown (.md) files into DOCX, ePub, and PDF files." 12 | echo "" 13 | echo "Options:" 14 | echo " --help Show this help screen." 15 | echo " -n, --name [name] The name of this draft." 16 | echo " -i, --input [path] Directory containing the files to convert. Defaults to this directory." 17 | echo " -o, --output [path] Directory to store the converted files in. Defaults to ./out." 18 | echo " -m, --metadata [path] Path to the YAML file containing metadata for pandoc." 19 | echo "" 20 | exit 0 21 | } 22 | 23 | # Argument processing logic shamelessly stolen from https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash 24 | POSITIONAL_ARGS=() 25 | while [[ $# -gt 0 ]]; do 26 | case "$1" in 27 | --draft-name|--name|-n) 28 | draftName="$2" 29 | shift 30 | shift 31 | ;; 32 | --input|--indir|-i) 33 | inDir="$2" 34 | shift 35 | shift 36 | ;; 37 | --output|--outdir|-o) 38 | outDir="$2" 39 | shift 40 | shift 41 | ;; 42 | --metadata|--metadataFile|-m) 43 | metadataFile="$2" 44 | shift 45 | shift 46 | ;; 47 | --help) 48 | usage 49 | ;; 50 | *) 51 | POSITIONAL_ARGS+=("$1") # save positional arg 52 | shift 53 | ;; 54 | esac 55 | done 56 | set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters 57 | 58 | # If this is a git repo and no name has been provided, name the draft after the current branch 59 | if [ -d ".git" ] && [ "$draftName" = "draft" ]; then 60 | draftName=$(git rev-parse --abbrev-ref HEAD) 61 | fi 62 | 63 | # Check if this directory already exists 64 | outDir="$outDir/${draftName}" 65 | if [ -d "$outDir" ]; then 66 | echo "The folder $outDir already exists." 67 | read -rp "Enter YES to overwrite, or Ctrl-C to cancel: " confirm && [ "$confirm" = "YES" ] || exit 1 68 | fi 69 | 70 | draftFile="$outDir/${draftName}" 71 | 72 | echo "Compiling draft \"${draftName}\"..." 73 | 74 | # Create the draft directory if it doesn't already exist 75 | mkdir -p "$outDir" 76 | 77 | # Initialize merged file 78 | echo > "$draftFile".md 79 | 80 | # Grab content files and add a page break to the end of each one. 81 | # Obsidian specifically creates "folder notes," which are named for the directory, so we make sure to exclude it. 82 | find "$inDir" -type f -wholename "**.md" ! -name content.md -print0 | sort -z | while read -rd $'\0' file 83 | do 84 | # Add newline to Markdown doc 85 | echo >> "$draftFile".md 86 | # Clean up incoming Markdown and append it to final doc 87 | sed "s|(../|($inDir/../|g" "$file" >> "$draftFile".md 88 | echo "\\newpage" >> "$draftFile".md 89 | done 90 | 91 | # Generate the output files: 92 | # Markdown -> DOCX 93 | # Markdown -> EPUB 94 | # Markdown -> PDF (A4 size) 95 | # Markdown -> PDF (B6/Standard book size) 96 | pandoc -t docx "$draftFile".md -o "$draftFile".docx --metadata-file "$metadataFile" 97 | pandoc -t epub "$draftFile".md -o "$draftFile".epub --metadata-file "$metadataFile" 98 | pandoc "$draftFile".md -o "$draftFile"-a4.pdf --metadata-file "$metadataFile" -V geometry:"a4paper" -V fontsize:"12pt" 99 | pandoc "$draftFile".md -o "$draftFile"-b6.pdf --metadata-file "$metadataFile" -V geometry:"b6paper" -V fontsize:"10pt" 100 | 101 | echo "Done! Your new draft is in $outDir" 102 | -------------------------------------------------------------------------------- /bin/format-drives.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Script to setup a drive for a brand new NixOS installation. 3 | # IMPORTANT: Before running this script, you'll need to create a LUKS partition using: 4 | # cryptsetup --label=nixos-crypt --type=luks2 luksFormat [partition] 5 | 6 | set -e 7 | 8 | if [ "$(id -u)" != "0" ]; then 9 | echo "This script must be run as root" 1>&2 10 | exit 1 11 | fi 12 | 13 | # Configuration parameters 14 | ask_root_password=false # Whether to prompt for a root user password 15 | boot_partition="" # The drive to install the bootloader to 16 | luks_partition="" # The drive partition to create the LUKS container on 17 | root_partition="/dev/mapper/nixos-crypt" # The partition to install NixOS to 18 | 19 | function usage() { 20 | echo "Usage: format-drives.sh [--boot boot-partition-path] [--luks luks-partition-path] [--ask-root-password]" 21 | echo "Options:" 22 | echo " -h | --help Show this help screen." 23 | echo " -b | --boot The path to the boot drive (e.g. /dev/nvme0n1p1)." 24 | echo " -l | --luks The path to the partition to create the LUKS container on (e.g. /dev/nvme0n1p2)." 25 | echo " -a | --ask-root-password Sets a password for the root user account." 26 | exit 2 27 | } 28 | 29 | # Argument processing logic shamelessly stolen from https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash 30 | POSITIONAL_ARGS=() 31 | while [[ $# -gt 0 ]]; do 32 | case "$1" in 33 | --ask-root-password|-a) 34 | ask_root_password=true 35 | shift 36 | ;; 37 | --boot|-b) 38 | boot_partition="$2" 39 | shift 40 | shift 41 | ;; 42 | --luks|-l) 43 | luks_partition="$2" 44 | shift 45 | shift 46 | ;; 47 | --help|-h) 48 | usage 49 | ;; 50 | *) 51 | POSITIONAL_ARGS+=("$1") # save positional arg 52 | shift # past argument 53 | ;; 54 | esac 55 | done 56 | 57 | set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters 58 | 59 | cryptsetup luksOpen "$luks_partition" nixos-crypt 60 | mkfs.btrfs -L nixos "$root_partition" 61 | mount /dev/mapper/nixos-crypt /mnt 62 | btrfs subvolume create /mnt/@ 63 | btrfs subvolume create /mnt/@home 64 | btrfs subvolume create /mnt/@log 65 | btrfs subvolume create /mnt/@nix 66 | btrfs subvolume create /mnt/@swap 67 | umount /mnt 68 | 69 | mount -o subvol=@ "$root_partition" /mnt 70 | mkdir -p /mnt/{boot,home,var/log,nix,swap} 71 | mount "$boot_partition" /mnt/boot 72 | mount -o subvol=@home "$root_partition" /mnt/home 73 | mount -o subvol=@log "$root_partition" /mnt/var/log 74 | mount -o subvol=@nix "$root_partition" /mnt/nix 75 | mount -o subvol=@swap "$root_partition" /mnt/swap 76 | echo "Disks partitioned and mounted to /mnt." 77 | 78 | # Generate hardware-configuration.nix 79 | nixos-generate-config --no-filesystems --dir /home/nixos 80 | echo "Configuration files generated and saved to /home/nixos." 81 | 82 | echo "Setup complete!" 83 | echo "To install, set up your system's configuration files under ./hosts/yourHost and add it to flake.nix." 84 | echo "Then, run the following command:" 85 | echo "nixos-install --verbose --root /mnt --flake [path-to-flake.nix] $( (( ask_root_password == false )) && echo "--no-root-password" )" 86 | 87 | exit 0 88 | 89 | -------------------------------------------------------------------------------- /bin/nixos-operations-script.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # The NixOS Operations Script (NOS) is a wrapper script for nixos-rebuild and Flake-based configurations. 3 | # It handles pulling the latest version of your repository using Git, running system updates, and pushing changes back up. 4 | 5 | # Exit on error 6 | set -e 7 | 8 | # Configuration parameters 9 | operation="switch" # The nixos-rebuild operation to use 10 | hostname=$(/run/current-system/sw/bin/hostname) # The name of the host to build 11 | flakeDir="${FLAKE_DIR}" # Path to the flake file (and optionally the hostname) 12 | update=false # Whether to update and commmit flake.lock 13 | user=$(/run/current-system/sw/bin/whoami) # Which user account to use for git commands 14 | buildHost="" # Which host to use to generate the build (defaults to the local host) 15 | remainingArgs="" # All remaining arguments that haven't yet been processed (will be passed to nixos-rebuild) 16 | 17 | function usage() { 18 | echo "The NixOS Operations Script (NOS) is a nixos-rebuild wrapper for system maintenance." 19 | echo "" 20 | echo "Running the script with no parameters performs the following operations:" 21 | echo " 1. Pull the latest version of your Nix config repository" 22 | echo " 2. Run 'nixos-rebuild switch'." 23 | echo "" 24 | echo "Advanced usage: nixos-operations-script.sh [-h | --hostname hostname-to-build] [-o | --operation operation] [-f | --flake path-to-flake] [extra nixos-rebuild parameters]" 25 | echo "" 26 | echo "Options:" 27 | echo " --help Show this help screen." 28 | echo " -f, --flake [path] The path to your flake.nix file (defualts to the FLAKE_DIR environment variable)." 29 | echo " -h, --hostname [hostname] The name of the host to build (defaults to the current system's hostname)." 30 | echo " -o, --operation [operation] The nixos-rebuild operation to perform (defaults to 'switch')." 31 | echo " -U, --update Update and commit the flake.lock file." 32 | echo " -u, --user [username] Which user account to run git commands under (defaults to the user running this script)." 33 | echo "" 34 | exit 0 35 | } 36 | 37 | # Argument processing logic shamelessly stolen from https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash 38 | POSITIONAL_ARGS=() 39 | while [[ $# -gt 0 ]]; do 40 | case "$1" in 41 | --build-host) 42 | buildHost="$2" 43 | shift 44 | shift 45 | ;; 46 | --flake|-f) 47 | flakeDir="$2" 48 | shift 49 | shift 50 | ;; 51 | --hostname|-h) 52 | hostname="$2" 53 | shift 54 | shift 55 | ;; 56 | --update|--upgrade|-U) 57 | update=true 58 | shift 59 | ;; 60 | --operation|-o) 61 | operation="$2" 62 | shift 63 | shift 64 | ;; 65 | --user|-u) 66 | user="$2" 67 | shift 68 | shift 69 | ;; 70 | --help) 71 | usage 72 | ;; 73 | *) 74 | POSITIONAL_ARGS+=("$1") # save positional arg 75 | shift 76 | ;; 77 | esac 78 | done 79 | remainingArgs=${POSITIONAL_ARGS[*]} 80 | set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters 81 | 82 | if [ -z "${flakeDir}" ]; then 83 | echo "Flake directory not specified. Use '--flake ' or set \$FLAKE_DIR." 84 | exit 1 85 | fi 86 | 87 | cd "$flakeDir" || exit 1 88 | 89 | echo "Pulling the latest version of the repository..." 90 | /run/wrappers/bin/sudo -u "$user" /run/current-system/sw/bin/git pull 91 | 92 | if [ $update = true ]; then 93 | echo "Updating flake.lock..." 94 | /run/wrappers/bin/sudo -u "$user" /run/current-system/sw/bin/nix flake update --commit-lock-file 95 | /run/wrappers/bin/sudo -u "$user" git push 96 | else 97 | echo "Skipping 'nix flake update'..." 98 | fi 99 | 100 | options="--flake ${flakeDir}#${hostname} ${remainingArgs} --use-remote-sudo --log-format multiline-with-logs" 101 | 102 | if [[ -n "${buildHost}" && "$operation" != "build" && "$operation" != *"dry"* ]]; then 103 | echo "Remote build detected, running this operation first: nixos-rebuild build ${options} --build-host $buildHost" 104 | /run/current-system/sw/bin/nixos-rebuild build $options --build-host $buildHost 105 | echo "Remote build complete!" 106 | fi 107 | 108 | echo "Running this operation: nixos-rebuild ${operation} ${options}" 109 | /run/current-system/sw/bin/nixos-rebuild $operation $options 110 | 111 | case "$operation" in 112 | boot|switch) 113 | echo "" 114 | echo "New generation created: " 115 | /run/current-system/sw/bin/nixos-rebuild list-generations 116 | ;; 117 | esac 118 | 119 | exit 0 120 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | # Uses Snowfall: https://snowfall.org/ 2 | # For info on Flakes, see: https://nixos-and-flakes.thiscute.world/nixos-with-flakes/nixos-with-flakes-enabled 3 | { 4 | description = "Aires' system Flake"; 5 | 6 | inputs = { 7 | # Import the desired Nix channel. Defaults to unstable, which uses a fully tested rolling release model. 8 | # You can find a list of channels at https://wiki.nixos.org/wiki/Channel_branches 9 | # To follow a different channel, replace `nixos-unstable` with the channel name, e.g. `nixos-24.05`. 10 | nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; 11 | nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; 12 | 13 | # Blocklist for AI bots 14 | ai-blocklist = { 15 | url = "github:ai-robots-txt/ai.robots.txt"; 16 | flake = false; 17 | }; 18 | 19 | # Flatpak support 20 | flatpak.url = "github:gmodena/nix-flatpak/latest"; 21 | 22 | # Home-manager support 23 | home-manager = { 24 | url = "github:nix-community/home-manager/release-24.11"; 25 | inputs.nixpkgs.follows = "nixpkgs"; 26 | }; 27 | 28 | # SecureBoot support 29 | lanzaboote.url = "github:nix-community/lanzaboote/master"; 30 | 31 | # Use Lix in place of Nix. 32 | # If you'd rather use regular Nix, remove `lix-module.nixosModules.default` from the `modules` section below. 33 | # To learn more about Lix, see https://lix.systems/ 34 | lix = { 35 | url = "git+https://git.lix.systems/lix-project/nixos-module?ref=stable"; 36 | inputs.nixpkgs.follows = "nixpkgs"; 37 | }; 38 | 39 | # NixOS hardware quirks 40 | nixos-hardware.url = "github:NixOS/nixos-hardware/master"; 41 | 42 | # Snowfall lib: https://snowfall.org/guides/lib/quickstart/ 43 | # Jake's reference config: https://github.com/jakehamilton/config 44 | snowfall-lib = { 45 | url = "github:snowfallorg/lib"; 46 | inputs.nixpkgs.follows = "nixpkgs"; 47 | }; 48 | 49 | # Code formatter 50 | treefmt = { 51 | url = "github:numtide/treefmt-nix"; 52 | inputs.nixpkgs.follows = "nixpkgs"; 53 | }; 54 | 55 | # Support for nix-on-droid 56 | nixpkgs-2405.url = "github:nixos/nixpkgs/nixos-24.05"; 57 | nix-on-droid = { 58 | url = "github:nix-community/nix-on-droid/release-24.05"; 59 | inputs.nixpkgs.follows = "nixpkgs-2405"; 60 | }; 61 | 62 | # Extra packages for nix-on-droid 63 | nixdroidpkgs = { 64 | url = "github:horriblename/nixdroidpkgs"; 65 | inputs.nixpkgs.follows = "nixpkgs-2405"; 66 | }; 67 | 68 | }; 69 | 70 | outputs = 71 | inputs: 72 | let 73 | lib = inputs.snowfall-lib.mkLib { 74 | inherit inputs; 75 | 76 | # Root dir for flake.nix 77 | src = ./.; 78 | 79 | # Configure Snowfall 80 | snowfall = { 81 | # Choose a namespace to use for your flake's packages, library, and overlays. 82 | namespace = "Sapana"; 83 | 84 | # Add flake metadata that can be processed by tools like Snowfall Frost. 85 | meta = { 86 | # A slug to use in documentation when displaying things like file paths. 87 | name = "aires-flake"; 88 | 89 | # A title to show for your flake, typically the name. 90 | title = "Aires' Flake"; 91 | }; 92 | }; 93 | }; 94 | in 95 | lib.mkFlake { 96 | # Allow unfree packages in Nix config 97 | channels-config.allowUnfree = true; 98 | 99 | # Define nix-on-droid 100 | nixOnDroidConfigurations.default = inputs.nix-on-droid.lib.nixOnDroidConfiguration { 101 | # Pass Snowfall args into nix-on-droid 102 | extraSpecialArgs = { 103 | namespace = lib.snowfall.namespace; 104 | }; 105 | pkgs = import inputs.nixpkgs-2405 { 106 | system = "aarch64-linux"; 107 | }; 108 | modules = [ 109 | ./modules/nixos/secrets 110 | ./nix-on-droid/Skadi 111 | { 112 | environment.packages = with inputs.nixdroidpkgs.packages.aarch64-linux; [ 113 | termux-auth 114 | #openssh # Unable to build due to outdated patches 115 | ]; 116 | } 117 | ]; 118 | }; 119 | 120 | # Define NixOS systems 121 | systems = { 122 | # Modules to import for all systems 123 | modules.nixos = with inputs; [ 124 | lix.nixosModules.default 125 | lanzaboote.nixosModules.lanzaboote 126 | flatpak.nixosModules.nix-flatpak 127 | home-manager.nixosModules.home-manager 128 | { 129 | _module.args = { 130 | inherit inputs; 131 | }; 132 | home-manager = { 133 | /* 134 | When running, Home Manager will use the global package cache. 135 | It will also back up any files that it would otherwise overwrite. 136 | The originals will have the extension shown below. 137 | */ 138 | useGlobalPkgs = true; 139 | useUserPackages = true; 140 | backupFileExtension = "home-manager-backup"; 141 | }; 142 | } 143 | ]; 144 | 145 | # Individual host configurations 146 | hosts = { 147 | gremlin-lab.modules = with inputs; [ 148 | nixos-hardware.nixosModules.common-cpu-intel 149 | ]; 150 | 151 | Hevana.modules = with inputs; [ 152 | nixos-hardware.nixosModules.common-cpu-amd-pstate 153 | nixos-hardware.nixosModules.common-gpu-amd 154 | ]; 155 | 156 | Khanda.modules = with inputs; [ 157 | nixos-hardware.nixosModules.microsoft-surface-pro-9 158 | ]; 159 | 160 | Pihole.modules = with inputs; [ 161 | nixos-hardware.nixosModules.raspberry-pi-4 162 | ]; 163 | 164 | Shura.modules = with inputs; [ 165 | nixos-hardware.nixosModules.lenovo-legion-16arha7 166 | ]; 167 | }; 168 | }; 169 | 170 | # Define .nix file templates 171 | templates = { 172 | module.description = "Template for creating a new module."; 173 | systems.description = "Template for defining a new system."; 174 | }; 175 | 176 | # Use treefmt to format project repo 177 | outputs-builder = channels: { 178 | formatter = (inputs.treefmt.lib.evalModule channels.nixpkgs ./treefmt.nix).config.build.wrapper; 179 | }; 180 | }; 181 | } 182 | -------------------------------------------------------------------------------- /homes/common/git.nix: -------------------------------------------------------------------------------- 1 | { namespace, osConfig, ... }: 2 | { 3 | programs.git = { 4 | enable = true; 5 | userName = osConfig.${namespace}.secrets.users.aires.firstName; 6 | userEmail = osConfig.${namespace}.secrets.users.aires.email; 7 | extraConfig = { 8 | merge.conflictStyle = "zdiff3"; 9 | pull.ff = "only"; 10 | push.autoSetupRemote = "true"; 11 | safe.directory = "${osConfig.${namespace}.secrets.nixConfigFolder}/.git"; 12 | submodule.recurse = true; 13 | credential.helper = "/run/current-system/sw/bin/git-credential-libsecret"; 14 | }; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /homes/common/gnome.nix: -------------------------------------------------------------------------------- 1 | _: { 2 | # Additional Gnome configurations via home-manager. 3 | dconf.settings = { 4 | "org/gnome/mutter" = { 5 | edge-tiling = true; 6 | workspaces-only-on-primary = false; 7 | }; 8 | 9 | "org/gnome/desktop/interface" = { 10 | # Configure fonts 11 | font-name = "Fira Sans Semi-Light 11"; 12 | document-font-name = "Roboto Slab 11"; 13 | monospace-font-name = "Liberation Mono 11"; 14 | titlebar-font = "Fira Sans Semi-Bold 11"; 15 | 16 | # Configure hinting 17 | font-hinting = "slight"; 18 | font-antialiasing = "rgba"; 19 | 20 | # Configure workspace 21 | enable-hot-corners = true; 22 | 23 | # Set icon theme 24 | icon-theme = "Papirus-Dark"; 25 | 26 | # Set legacy application theme 27 | gtk-theme = "Adwaita-dark"; 28 | }; 29 | 30 | # Configure touchpad scroll & tap behavior 31 | "org/gnome/desktop/peripherals/touchpad" = { 32 | disable-while-typing = true; 33 | click-method = "fingers"; 34 | tap-to-click = true; 35 | natural-scroll = true; 36 | two-finger-scrolling-enabled = true; 37 | }; 38 | 39 | # Tweak window management 40 | "org/gnome/desktop/wm/preferences" = { 41 | button-layout = "appmenu:minimize,maximize,close"; 42 | resize-with-right-button = true; 43 | focus-mode = "click"; 44 | }; 45 | 46 | # Make alt-tab switch windows, not applications 47 | "org/gnome/desktop/wm/keybindings" = { 48 | switch-tab = [ ]; 49 | switch-windows = [ "Tab" ]; 50 | switch-windows-backward = [ "Tab" ]; 51 | }; 52 | 53 | "org/gnome/shell" = { 54 | disable-user-extensions = false; 55 | }; 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /homes/common/zsh.nix: -------------------------------------------------------------------------------- 1 | # Additional ZSH settings via Home Manager 2 | { pkgs, ... }: 3 | { 4 | programs = { 5 | command-not-found.enable = true; 6 | 7 | zsh = { 8 | enable = true; 9 | autosuggestion.enable = true; 10 | syntaxHighlighting.enable = true; 11 | history.ignoreDups = true; # Do not enter command lines into the history list if they are duplicates of the previous event. 12 | prezto = { 13 | git.submoduleIgnore = "untracked"; # Ignore submodules when they are untracked. 14 | }; 15 | plugins = [ 16 | { 17 | name = "zsh-nix-shell"; 18 | file = "nix-shell.plugin.zsh"; 19 | src = pkgs.fetchFromGitHub { 20 | owner = "chisui"; 21 | repo = "zsh-nix-shell"; 22 | rev = "v0.8.0"; 23 | sha256 = "1lzrn0n4fxfcgg65v0qhnj7wnybybqzs4adz7xsrkgmcsr0ii8b7"; 24 | }; 25 | } 26 | ]; 27 | sessionVariables = { 28 | NIX_AUTO_RUN = true; 29 | }; 30 | oh-my-zsh = { 31 | enable = true; 32 | plugins = [ 33 | "command-not-found" 34 | "cp" 35 | "direnv" 36 | "dotenv" 37 | "extract" 38 | "git" 39 | "systemd" 40 | ]; 41 | }; 42 | }; 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /homes/x86_64-linux/aires/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | namespace, 3 | osConfig, 4 | ... 5 | }: 6 | 7 | { 8 | imports = [ 9 | ../../common/git.nix 10 | ../../common/gnome.nix 11 | ../../common/zsh.nix 12 | ]; 13 | 14 | home = { 15 | # The state version is required and should stay at the version you originally installed. 16 | stateVersion = "24.05"; 17 | 18 | # Copy files ~/ 19 | file = { 20 | # fastfetch config 21 | ".config/fastfetch/config.jsonc".source = ./fastfetch/fastfetch-config.jsonc; 22 | ".config/fastfetch/logo.txt".source = ./fastfetch/lion_ascii_smol.txt; 23 | 24 | # User account image 25 | ".face".source = ./face.png; 26 | }; 27 | }; 28 | 29 | programs = { 30 | # Let home Manager install and manage itself. 31 | home-manager.enable = true; 32 | 33 | # Set up SSH 34 | ssh = { 35 | enable = true; 36 | compression = true; 37 | matchBlocks = osConfig.${namespace}.secrets.users.aires.sshConfig; 38 | }; 39 | 40 | # Set up Zsh 41 | zsh = { 42 | oh-my-zsh = { 43 | theme = "gentoo"; 44 | }; 45 | sessionVariables = { 46 | # Quit bugging me about unfree packages! 47 | NIXPKGS_ALLOW_UNFREE = "1"; 48 | }; 49 | shellAliases = { 50 | com = "compile-manuscript"; 51 | nos = "nixos-operations-script"; 52 | z = "zellij"; 53 | update = "upgrade"; 54 | upgrade = "nos --update"; 55 | }; 56 | loginExtra = "fastfetch"; 57 | }; 58 | }; 59 | } 60 | -------------------------------------------------------------------------------- /homes/x86_64-linux/aires/face.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbuddhist/nix-configuration/17ad82dbf64214aadd45b19dd10f59cd53b5c5d1/homes/x86_64-linux/aires/face.png -------------------------------------------------------------------------------- /homes/x86_64-linux/aires/fastfetch/fastfetch-config.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", 3 | "logo": { 4 | "type": "file", 5 | "source": "~/.config/fastfetch/logo.txt", 6 | "position": "right" 7 | }, 8 | "modules": [ 9 | "title", 10 | "separator", 11 | "os", 12 | "host", 13 | "kernel", 14 | "uptime", 15 | "shell", 16 | "display", 17 | "cpu", 18 | "gpu", 19 | { 20 | "type": "memory", 21 | "percent": { 22 | "green": 75, 23 | "yellow": 90 24 | } 25 | }, 26 | "swap", 27 | "disk", 28 | "battery", 29 | "poweradapter", 30 | { 31 | "type": "localip", 32 | "showIpv4": true, 33 | "showIpv6": true, 34 | "showPrefixLen": false, 35 | "defaultRouteOnly": true 36 | }, 37 | { 38 | "type": "publicip", 39 | "url": "ident.me", 40 | "ipv6": false 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /homes/x86_64-linux/aires/fastfetch/lion_ascii.txt: -------------------------------------------------------------------------------- 1 | _^``''"''v.``:. 2 | ,,/`' ;-_ \ 3 | ,._v' : 1 `| 4 | `.` '. `: 5 | ,| o o`| 6 | ,. . '. 7 | .. | `"'`| 8 | ..__---.. ...__._.__._../'" `. _ ; 9 | .:/:`' `` `-_ `-. '```;` 10 | ..--``.:/` -._ ' 11 | .-`` .// \. I 12 | .` .// ` :' 13 | .` _+.// \ |' 14 | .` .` ( . `: 15 | .` .` | !.. 16 | .` .` .` : `-. 17 | .` | | ..^^``^^--__ :. __ `-. 18 | .` .` .` .``. "''---''---...___... :. .-``` `:*-. ``:-, 19 | _-` .` | .` `. `: ```--_ \. ^:. ^.. 20 | "` __..' /^ .`` `. | \. $:% `. \. 21 | _"`` .: .'' :.. |: \ . .|. `. / 22 | : _.` #_ $ : :. ``--:`' 23 | \ ./ :. : .-` :. 24 | .` /` ./ / .: :` 25 | 1, /` < `\ :. .--`` 26 | `: /` `._ ``::.. ``` 27 | '. '`.. `-. ``''`> 28 | `. // `@:\\'\\ 29 | ```''' 30 | -------------------------------------------------------------------------------- /homes/x86_64-linux/aires/fastfetch/lion_ascii_smol.txt: -------------------------------------------------------------------------------- 1 | __...,_ 2 | _.-'' .-. __\ 3 | | `. 1 `\ 4 | ../' .` o `-._ 5 | _.--**^^^**hu*****i;-/ \. | `%: 6 | .$'` \. | ' 7 | '' .-, | `-__ .'*_*' 8 | `'' | `\ ```| 9 | $' |' ``._ \*` 10 | '' |, ``--.' 11 | .'$ | \ 12 | _ '' |' .'*-____ ____.-. `| 13 | *@*' / .' ```` `. . `| 14 | |' ,/\ ,' | | \ `| 15 | \ `-,\ `-, | `. \ `-. 16 | \.__.* \.__.* `.__.` *.__* 17 | -------------------------------------------------------------------------------- /homes/x86_64-linux/gremlin@Shura/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | namespace, 3 | osConfig, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | { 9 | imports = [ 10 | ../../common/git.nix 11 | ../../common/gnome.nix 12 | ../../common/zsh.nix 13 | ]; 14 | 15 | home = { 16 | 17 | # The state version is required and should stay at the version you originally installed. 18 | stateVersion = "24.05"; 19 | 20 | # Install packages specific to Gremlin 21 | packages = with pkgs; [ 22 | awscli2 23 | unstable.figma-linux 24 | ]; 25 | 26 | # User account image 27 | file.".face".source = ./face.png; 28 | }; 29 | 30 | programs = { 31 | # Let home Manager install and manage itself. 32 | home-manager.enable = true; 33 | 34 | # Set up SSH 35 | ssh = { 36 | enable = true; 37 | compression = true; 38 | matchBlocks = osConfig.${namespace}.secrets.users.gremlin.sshConfig; 39 | }; 40 | 41 | # Tweak Zsh for Gremlin 42 | zsh.oh-my-zsh = { 43 | plugins = [ 44 | "aws" 45 | ]; 46 | theme = "gnzh"; 47 | }; 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /homes/x86_64-linux/gremlin@Shura/face.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbuddhist/nix-configuration/17ad82dbf64214aadd45b19dd10f59cd53b5c5d1/homes/x86_64-linux/gremlin@Shura/face.png -------------------------------------------------------------------------------- /lib/default.nix: -------------------------------------------------------------------------------- 1 | # Extra utility functions 2 | { 3 | lib, 4 | }: 5 | { 6 | # Parses the domain from a URI 7 | getDomainFromURI = 8 | url: 9 | let 10 | parsedURL = (lib.strings.splitString "." url); 11 | in 12 | builtins.concatStringsSep "." [ 13 | (builtins.elemAt parsedURL 1) 14 | (builtins.elemAt parsedURL 2) 15 | ]; 16 | } 17 | -------------------------------------------------------------------------------- /modules/nixos/apps/development/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | namespace, 6 | ... 7 | }: 8 | 9 | let 10 | cfg = config.${namespace}.apps.development; 11 | in 12 | { 13 | options = { 14 | ${namespace}.apps.development = { 15 | enable = lib.mkEnableOption "Enables development tools"; 16 | kubernetes.enable = lib.mkEnableOption "Enables kubectl, virtctl, and similar tools."; 17 | }; 18 | }; 19 | 20 | config = lib.mkMerge [ 21 | (lib.mkIf cfg.enable { 22 | ${namespace} = { 23 | packages = with pkgs; [ 24 | nil # Nix Language server: https://github.com/oxalica/nil 25 | nix-prefetch-scripts 26 | ]; 27 | ui.flatpak = { 28 | enable = true; 29 | packages = [ 30 | "com.vscodium.codium" 31 | "org.gnome.gitg" 32 | ]; 33 | }; 34 | }; 35 | }) 36 | (lib.mkIf cfg.kubernetes.enable { 37 | environment.systemPackages = with pkgs; [ 38 | kubectl 39 | kubernetes-helm 40 | kubevirt # Virtctl command-line tool 41 | ]; 42 | 43 | services.flatpak.packages = [ "dev.k8slens.OpenLens" ]; 44 | }) 45 | ]; 46 | } 47 | -------------------------------------------------------------------------------- /modules/nixos/apps/gaming/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | namespace, 6 | ... 7 | }: 8 | 9 | # Gaming-related settings 10 | let 11 | cfg = config.${namespace}.apps.gaming; 12 | reset-controllers-script = pkgs.writeShellScriptBin "reset-controllers" '' 13 | #!/usr/bin/env bash 14 | sudo rmmod hid_xpadneo && sudo modprobe hid_xpadneo 15 | sudo systemctl restart bluetooth.service 16 | ''; 17 | in 18 | { 19 | options = { 20 | ${namespace}.apps.gaming.enable = lib.mkEnableOption "Enables gaming features"; 21 | }; 22 | 23 | config = lib.mkIf cfg.enable { 24 | ${namespace} = { 25 | # Add script to restart xpadneo in case of issues 26 | packages = [ reset-controllers-script ]; 27 | 28 | ui.flatpak = { 29 | enable = true; 30 | packages = [ 31 | "gg.minion.Minion" 32 | "com.valvesoftware.Steam" 33 | "com.valvesoftware.Steam.CompatibilityTool.Proton-GE" 34 | "io.github.lime3ds.Lime3DS" 35 | "org.firestormviewer.FirestormViewer" 36 | ]; 37 | }; 38 | }; 39 | 40 | # Enable Xbox controller driver (XPadNeo) 41 | hardware.xpadneo.enable = true; 42 | 43 | # Enable GameMode 44 | programs.gamemode.enable = true; 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /modules/nixos/apps/media/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | namespace, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.${namespace}.apps.media; 10 | in 11 | { 12 | options = { 13 | ${namespace}.apps.media = { 14 | enable = lib.mkEnableOption "Enables media playback and editing apps."; 15 | mixxx.enable = lib.mkEnableOption "Installs the Mixxx DJing software."; 16 | }; 17 | }; 18 | 19 | config = lib.mkIf cfg.enable { 20 | ${namespace}.ui.flatpak = { 21 | enable = true; 22 | packages = [ 23 | "app.drey.EarTag" 24 | "com.calibre_ebook.calibre" 25 | "com.github.unrud.VideoDownloader" 26 | "io.freetubeapp.FreeTube" 27 | "org.kde.digikam" 28 | "org.kde.krita" 29 | "org.kde.KStyle.Adwaita//5.15-23.08" # Retrieved from https://docs.flatpak.org/en/latest/desktop-integration.html 30 | "org.kde.KStyle.Adwaita//6.6" 31 | "org.kde.WaylandDecoration.QAdwaitaDecorations//5.15-23.08" # Replaced deprecated QGnomePlatform https://wiki.archlinux.org/title/Uniform_look_for_Qt_and_GTK_applications 32 | "org.kde.WaylandDecoration.QAdwaitaDecorations//6.6" 33 | (lib.mkIf cfg.mixxx.enable "org.mixxx.Mixxx") 34 | "org.videolan.VLC" 35 | ]; 36 | }; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /modules/nixos/apps/office/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | namespace, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.${namespace}.apps.office; 10 | in 11 | { 12 | options = { 13 | ${namespace}.apps.office.enable = lib.mkEnableOption "Enables office and workstation apps"; 14 | }; 15 | 16 | config = lib.mkIf cfg.enable { 17 | ${namespace}.ui.flatpak = { 18 | enable = true; 19 | packages = [ 20 | "md.obsidian.Obsidian" 21 | "org.onlyoffice.desktopeditors" 22 | "us.zoom.Zoom" 23 | ]; 24 | }; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /modules/nixos/apps/recording/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | namespace, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.${namespace}.apps.recording; 10 | in 11 | { 12 | options = { 13 | ${namespace}.apps.recording.enable = lib.mkEnableOption "Enables video editing tools"; 14 | }; 15 | 16 | config = lib.mkIf cfg.enable { 17 | ${namespace}.ui.flatpak.enable = true; 18 | 19 | services.flatpak.packages = [ 20 | "com.obsproject.Studio" 21 | "org.kde.kdenlive" 22 | "org.tenacityaudio.Tenacity" 23 | "io.github.seadve.Kooha" 24 | ]; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /modules/nixos/apps/social/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | namespace, 6 | ... 7 | }: 8 | 9 | let 10 | cfg = config.${namespace}.apps.social; 11 | in 12 | { 13 | options = { 14 | ${namespace}.apps.social.enable = lib.mkEnableOption "Enables chat apps"; 15 | }; 16 | 17 | config = lib.mkIf cfg.enable { 18 | ${namespace} = { 19 | packages = [ pkgs.beeper ]; 20 | ui.flatpak = { 21 | enable = true; 22 | packages = [ 23 | "com.discordapp.Discord" 24 | "org.gnome.Polari" # IRC client 25 | ]; 26 | }; 27 | }; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /modules/nixos/apps/writing/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | config, 4 | lib, 5 | namespace, 6 | ... 7 | }: 8 | 9 | let 10 | cfg = config.${namespace}.apps.writing; 11 | 12 | compile-manuscript = pkgs.writeShellScriptBin "compile-manuscript" ( 13 | builtins.readFile (lib.snowfall.fs.get-file "bin/compile-manuscript.sh") 14 | ); 15 | in 16 | { 17 | options = { 18 | ${namespace}.apps.writing.enable = lib.mkEnableOption "Enables writing and editing tools"; 19 | }; 20 | 21 | config = lib.mkIf cfg.enable { 22 | # Install packages for building ebooks 23 | environment.systemPackages = with pkgs; [ 24 | haskellPackages.pandoc 25 | haskellPackages.pandoc-cli 26 | haskellPackages.pandoc-crossref 27 | (texlive.combine { inherit (texlive) scheme-small draftwatermark; }) 28 | compile-manuscript 29 | ]; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /modules/nixos/default.nix: -------------------------------------------------------------------------------- 1 | # Modules common to all systems 2 | { 3 | pkgs, 4 | namespace, 5 | ... 6 | }: 7 | 8 | { 9 | ${namespace} = { 10 | # Install base packages 11 | packages = with pkgs; [ 12 | fastfetch # Show a neat system statistics screen when opening a terminal 13 | htop # System monitor 14 | lm_sensors # System temperature monitoring 15 | zellij # Terminal multiplexer 16 | ]; 17 | 18 | # Install the nos helper script 19 | nix.nixos-operations-script.enable = true; 20 | }; 21 | 22 | programs = { 23 | # Install ZSH for all users 24 | zsh.enable = true; 25 | 26 | # Configure nano 27 | nano = { 28 | enable = true; 29 | syntaxHighlight = true; 30 | nanorc = '' 31 | set tabsize 4 32 | set softwrap 33 | set autoindent 34 | set indicator 35 | ''; 36 | }; 37 | }; 38 | 39 | # Set nano as the default editor 40 | environment.variables."EDITOR" = "nano"; 41 | 42 | # Set ZSH as the default shell 43 | users.defaultUserShell = pkgs.zsh; 44 | } 45 | -------------------------------------------------------------------------------- /modules/nixos/secrets/default.nix: -------------------------------------------------------------------------------- 1 | U2FsdGVkX18zKisAIK5vYdYA/GllYyw5W1kULHq6zqYx/c0/S1rC+UFO9zU0Z0Ty 2 | koTofa4fvD5EXsuzjFxZW7Xj9bmmzV2yZYF8hmdd0l2h067YL5bY4Q1RkXuOEE3Z 3 | ihC+Uq6aekRQGlpZ2MTKtq6ddIfa7aJJNZg0+t40MLwV4bCAXz3F3fsIcL4f6Bgy 4 | D2g3WudX0xKqe3bGb4Ke5A3cuQBL7udfg33CMI/108wW+KIX8rx8peoCnKqYUQbT 5 | WwCAhdDlJ6QoEmFAv1iWnCkROjxyBumhvmmV3zTO0VTY2TIkx7eQKs1nrRhynyRw 6 | IESBZbkZe5jQDWXwQli2n3wLJfmRrVSzTwP1/paYNQ6IekovV/Fncu96aSsX4jIu 7 | AHj31tqzgkAGEX/OKH+n6IplhyOl2rXunIRZ7CqjRoKY3WqR2va1uce+WWrw9f/2 8 | lXqc7ejQEB5ZfyCO6jDWSU3REiMMwWg9HwfDkao4imQl59bCkKmOkJkCWSLEWCXb 9 | UKyfpc6K4MWSMr0E6DqxqPPUSSLvyAbPdsXAs2Ycj0VshfOnDlDws2YZ3pSIyDz7 10 | CngigBNyaFUXdDOZyySNTtgaTvSR2s04iW8cpBhgJv1rnXGCdaWP8rKvVbsTgwSp 11 | bc78rW/Cf0T0n1OllomTCj1RTCesowi+lhxN2RAuXT/7ZX4rr5vaEqTMHHBp1tUD 12 | nHy/AdDchz3QUAwA+5mIRgxl56A3Pz9P2kMuDmrz1iO0PqhcfqGBYT1+g9sfOH69 13 | HjRC1yL2NYJWAR213zlKTOmOVBvjFFO6O/oDgEqzW5qfAUiB1yz6s0TGO+9mG1/z 14 | SAHNMCGna3n+LdYmghjssJrd+EmWJPAaaWKP1S8JDz3+uGofCw0R77m7RMnvwPTg 15 | 93DmAdN3wkyK/mAF//GbOpU9XV89IHpYOvIZf8P/PahELMpuLoncx1cG9eObxpad 16 | aDWGdKpYRCCjTl7KV5tV+0+xBLOF2Yfc2ghBL+QI6hX1gZZ18A0ITcTOBHJdfrIH 17 | EiGx9pWfc9KAjqOpEFXDmpMFmSwKs11OftP301jokUWIe/9V0MfkJOKWWM8IuPTW 18 | j9etkppN0a62hgcCOqNKja512Y/ppJlCpAEeruG/l0sRpUh2E/RrrB8wquiNkr1+ 19 | 76grzCn4zwwoVy5XSPTIyevNyyD8TcSKBRL/9004aIyqMpt9GcNXeIpEcVFk/A1i 20 | xhZXtyu8NXx+AZ4K+igXAvhpRFS4qrPYzLzVtwHepZ+5C/Me31O1UdGrrQFehEsA 21 | nklZpBl3QrQAMtDFMNFqFTPM1K4gEUAmRd2Qpa1zcM2+8oLKH3eWkNRjiS6fldT/ 22 | Er1pLXWlxL4xxbzgSfH/sDmTBgPA4MHmlx+3R7m3KpOaIJAvZJqXphbXk+OMG/oB 23 | 1Gj2ldTLnA5lmkB+/4GrwT3FnNRw+XJGq+kCnneMH87rXVZKufn8sZf744q9Nwvc 24 | GFO37gTuuTgJNSLQd48rlnqmNsQMY5orfVJ/RzdxtkKf61cwSpMSGM34HWjv0V7k 25 | HeLuy4HnlwhSBAWDazy11HZD2hlpBduNnyhWqjniY5P9+hxwFzEG2Nza0xHpFEr/ 26 | uVhwjVfZSr7QxjmwcQdFzmLvwhmJDVfL6IvCABu6bHePUgnM2wDg71CAkoo7Ogy1 27 | VXYO6yJIPcSTjQlcGYuNAgxyWk7t6IVgFcvtta0e2W0tLWAwUnsX/JrSllrciBRo 28 | ayb39BLn2HuvgK7k1+HalGv4oEziOLtrKyKG3u6OdqLxTeowKNUGpHe2IBAvmTEt 29 | QL1g53hSdl4k+gYCsGdPuYAKEjiP0iHvfUJWhPf77pg7betkjMFNA3j1M70kHUv7 30 | GE/PUqIuZLhX8vEs4EWctSSWGhvR/fOD/WiFkLS1NixDh3Wady4UNOB5TTzEqou/ 31 | Q3ykjDNUMQj7H/XHiR5Jr2xsRtVMp02AOQhqOlyRNLC6ikfanIrt6fzYsL5kFbzG 32 | /PCkpDxHGe7QwLsGZhsjUQAe8dnvOm24BKPURVBRAnRrLcQ2oLvuihU7SCPIUU7B 33 | iXDJQj3LCP74gBHda+iOweMeX8cLlNdXnrQnz5wtq0QBj+gSbHlreL2t+2NZaJ4J 34 | PBFgetMJIU9uumTnJwiv5kmjD6giQOg1aLk+cE3iqC0ioxbPYCO6KLPAc/0DbHgr 35 | Ucq8BFKMgRAIDy7/QdRIj/dThSYEdz2IaeRecA2DbC7mDvbHl3I7EFn3I8IWKJHZ 36 | CzL4BRt+nuVAWX6Xrnwjn2G88pOsBuA7C7rSm5hDE6gfOCchlG4M+h2sGqDMf3LK 37 | UifF7/wfKyigXmsVyOBmaCZfJLcE/PKpSfbUTgW4ZgufHi7CmOQYPjeYqxKWWQ5t 38 | lrqnynnCuZwA39N5HW4wiO1Kh3pDbQlX4T6lxWAsB4m0Ue75pj02RGFSv5FkrxoX 39 | dlqj9slpa+8PPy7r7RHi9nNJjmvCgucrPrkiBHgvizlEkUtf++W7mOm0fdu+TscC 40 | Au4tfQLWWPE1jPKMt3CBcLwDrbix4/J0hHl/WKsyvWR52nNmo4XIesJm0JvDvSc7 41 | VJcgJ+ezW0be/2WOdEegvlTpV3mJ4CkaK9TCrWuoUJI3TcfOsqHdErWDQ9HA3f0/ 42 | lsNzI9XgT2XvgOu21SqQ1AO/jphsNNe3RWz95cadCL3/mnl0yEzuMUAivzzG32sV 43 | XiC6UE/LP8MolFo+GCkiYq0/ayN/S3O2vMKcV7x/KfXwUkMvS44KbwWAG/4dlciY 44 | M3xWmhxOp89J1/wUJ9W+/hahBLTjzNKr2Cl8oMxgUwB4MFD2ds2Jvodckw3j8w1D 45 | lNszkexNBigiKnlUIB2gaaTZ8RvrHp8l6Od2Mre/UySj4Y73xqoSABcDes2ut5Nl 46 | CZIv2Zwv4ItviUozkz6r/NuP2Qcgk3Da6I4y8JcaPmLoxiGerb8lqYD1SQg6EmuS 47 | cKH2QYbDsnqyZBHrQDcrc7+dDMCojsK5LVaeXxxDDZjh6Q+2MdYUQGtNAgQoRWTU 48 | MMKNbBxgkeP/pV/AtSb91FBN+TLIPKvsFlHKhppG/TXQ0bwSfyfdezl1PFbC0tN/ 49 | G3ONS39hpQ2dZntvvjtDanKYT3eY6wcyTe0Z9PUbz4z3D5B1V4aX1hzKj+zWjz/K 50 | LyHY8Rf8HFxegAL3AR9zJ+en2QRU0DZtq+a3GXd310l3K4OzKixioFM2awxH1GRg 51 | zI/b6FoKptArpq5geKXlZXiE09/YspwbGo9FrITmKvJEsr1ht83rpvD8d8Z8p7An 52 | K//m68zTwBsvQodXlJ59nzAJuCDSMovjtKN2/Ubxs03H5EfnDYrSFw1sAi4IaGpz 53 | SakqmHAD3S9ClEWkvQ+laS6qC9e9gzwyEhCZDeh9X3Q4tmYESpKvYQwGycO3c6EH 54 | ZQbKfL7zVsuxENOUNbAfRVj/2EJI8A0/C0EPPsuZDcwnPyQPJ7HSzBa6+FxJZOHf 55 | bGH9T02MbNKbx88GcHL8QmEfEXXWvxjkx43a1eEYfUuNIxBCZS6SEV34pANEcoVX 56 | yweTivARajF378X9Tr77aH5fDOWk50zp0EO4KZsN3w+BN07TTmhTipwb13X5nLmC 57 | B8aa03Zk+C2UXSyI2UjsvYFdH6XN4sb7zL+95HCV1L55e4Db/13qPx8cw0lUvP+9 58 | IOY6sFiVTRkZiAXt0XG4wWSEvB+zKKC5n/TtJJzRzrkcUgdar4+5bCUYaexJ6qRQ 59 | r5WoQutz4p89dGhNgATK4j5iScdvttJLGEHNoLQtObnAaEuihwX+Yc5kKsMW3tWb 60 | cQoA9A07fUdIpqRfTnikX89k6zNpzIVFG7bjnkXrND3t0pBwGCAqhQSTDfirbuKC 61 | Qlr9sLlMOkBTA/ly3Pa/2rfvMiSDO2GJ07k0jlN/Y22e188Wp21346hNCAVA+s/h 62 | aqLMwNYuV45mBsLHlF7Sg/L6u9UEebryCvyv/u8PidXH7g6i8VkVR7C+B0QkghpI 63 | FJ9fI72DwekKWwBbWHcFfnA8mOJH5TgC9w7Yky517eox/e3GqJeFrlCcCTgaFw/Q 64 | gtog48XrApgOsdUNEd7WWx69R3rl4Oe6S/Hph14f2pjbGhxShuV+DEqNYWepKJZn 65 | 7zwkwGetknoSzAwZEu7z0UpbLvLpEbokVfTgU3gqvhs+gwj++jq+2iltKkL6MvBu 66 | ktQNfm1uKshX9VVSwF5/ZLyAZ6JQYRUpIJ7UzeM4Nj8OpLAod+zZJfKGbEdmyFrv 67 | bALhQyrDcnVJIz2FBIJH11YXy6mBhD6/CBG7SALTOwVbdzPSHRYMESlwGAbo6pJ/ 68 | MU+Y++h1Y1PDsJUjMlUEI4MvnyjnAm2YjoaLaEC7IRBlHkwJKnRv789eXEnHnwwq 69 | C4NSMGiZW1NwLcIc9pBa010/TZsQNOOsYQORYS/yw+UTQd7yo1xPOdZvhLRwd82j 70 | Wvi6obQJKpamvoSHXCWq+6WHW0yXIJ+uHzlkIdPI7ClJZha+OIsImS9rYp0xRn2e 71 | sCTAlWFx2KDWySM7bMG8zqofp6A2qcVSFY43oAQb2N04m3aOqrUk9+j4PUZOwHna 72 | qw0Vnnk9hsXm7Dg6lqlNmd9loGnyZCG4zKWd+n0GAaJEPD3kE4yZE6Q/o6AyOjcw 73 | mVz14vQss7FjC/np3EMZNAmecDEs09fgSNxh70Sm3BQb/8Bef+bAxdusZzqbobfy 74 | nyhsJFx17R8Q6pRrbnQeh7P1PIaH+OedSfflQjtg/bNq4XbP6Zqj8IO4CkWtLCxV 75 | Ad3KuyGo34F2CQqeERcIbX45TeloNufNWwWYdSbDB0x7ncnUJB9/mtepd0L4bWZT 76 | 9aN9HTMyxhwPkucSwFbwAPb/5X7GgTQX8K2LM7qvjqb5aLAzFD7NAm6gWh4QyLIS 77 | DthXpykES1OncxKTH99BPTWdxEJtpgsr+2Lkhy0BZwxmapHasPhSIy/pYWJJLUkS 78 | HCxE5gaP6kgxdWcXG9ljUi24WWgrl1m02D0hceM41h3VZywmHy0gfTrcg9vFNHMM 79 | BEe09qtDMz1nBmYgKSt38rSjpURBx+NeWQUBIEXXHCdWWdu9DOc1XusxU6l+TeI4 80 | 1Esrna3JY/6n1LusnZHNuXYzx5n+OV46DjNgXZHX0L5ydXJBVxlghlaLxTNa5oK8 81 | QQX5r5q+vTKj6LsoWPnsjnig3lMUIiFdtQoclVdCMHfdpQwhRhvTMSoQBvbcKRAa 82 | m8CdwID3vPtn4FovsOFMJCpiYfmhWooy4SPc9WJZupfhY3xwoiGt/4a4Au8dyCNa 83 | uv+dmT8dqfaR4o+4GqNyXGmg5dvwZJnPXnR1VQyGf4AAaVVnfejui6d2ShSim95r 84 | Z5t9H7ZBbMBt96eG0F6D155Uq2l+d1uApMrXusioQAoNTR6JpCV+lEOa3p8DivB4 85 | iwLDltjOonr/f/yq3tH5LVdoiLsd1t2JZcPYPWyw+DFuEryLK01KZ8NfC01vkFev 86 | prU3OTWilm/SJutgWnPGzy4fFExQqBOiNlrS3LqMgEl8EVNjmBfK2ACdn48PpLn0 87 | HWiag0KqxEPafRnt89eputnMeIElNunlFSfkH/my8i490LEZQtp0wGuT9g2ms0Pv 88 | GpM2pRc/CYQcs/P0GN7DNsbMdWjBrtjc8ouu0Y/uJ9cgDvc2XQaLQjjkZoMePTDH 89 | kVbelYsP6JGasDL1IkjheTQZoZKI2BxTGgfibKhD1l94ixth/ywPE7eEd6bKpsXJ 90 | GDd62dUNRFETPj5aMZoGWgyOEesBJFqd6dagb8nbtr2iD32cyVmsljAwqWjzfXDQ 91 | r70kzAY05GoFVGBvHQlfSi9tMH5CflCJKN/1YwisTHkzTejPX5lLRe36avLFEbMV 92 | 1kgvZCqulaWhx19CLTRvuKQQETVd46KDllMgthSA/4I2mm4H0iQSad7tKGlVQNRW 93 | 0LkAMEhAefCIT9W/t+COpL7cDS2+wTCr6cDGiCcjN6FW7K6FDg7rbl+ey8lEuMrg 94 | VULM3/v0m9pbWC3bOPzvppJ3lfXFfKFmzD1vbTPNO44QEIOrAJY0DrYWABCCOzOL 95 | gqrhC9S6eK7LPkcdV2CP7zFv5S/I4ItKOd+1rrZYz1x26ibXhbYw2iGB1I2v4VjC 96 | +Dz+4x00Fk7T1psSFiV/Qhzijb8JeRfvlApqaOE4Ez2Cos99PDeZ5vGjT50jKOPA 97 | t997igy7+Jz8rVtGh4eLC61tqXAWrFUU/ih2/A2Te6dJhDjKU+KGvJh08T7Z6nep 98 | yZTht/jX6wEWL+8AE1W9zZT8mIV/5SM1m9kbUs5Uteu4RAX34dvqkts3YCbQIRbH 99 | oynIdxCTvyBTTMJ6Cpqkb8JkqOXIdUrVnHpt+WAsUWVoo7MyEKmPux1Svzg+z9Kx 100 | G+8NDNwVBf9E0AS6gMyBMV/CwIXtXd4nKz1lrH2l7RDPNsXGEyb8bHmbOaz3Uj5s 101 | a+aB6M6uAYRd8o5kyGP/406Jjb/Owyb106sCmAE1n+eUN29oSkfBMw7ix63u3+Hg 102 | UvdW1CRIgBu3tVgq8LJzhNxk4FwdFv8EVgvbojK5BAqzQ2tiO10XTaBvysylD7ae 103 | vf/OVqgl4CbFwCCGQjpoDpaaLqjeOzpBygOvkiJQIf+PpaeB4WBKS0Yeisq7M1Wv 104 | 2vkNTYpbBP8ofiLlKDNllpL5BKjXzl6tddo47TnTe5BFzlOP3ikaDJtDG2T4i+Ob 105 | pk/JZL3Xke6XAp2suTfWNh0Vy8JlStPpYSgrhZuOTPSmBZJT/A1efMZFng2wiNnK 106 | JwdDt4WbyIa/Hlo6P9+uajKgtbhoYVuQr2+6nJ6KX2aG7bT9bXeBKKww+7YDhNCH 107 | 0LT/Qj4fmsRcU14MtGPVWk3UGGhr7CfA5vFNB1ie4aWGgKuO2U2An6JVPBKqMZ/H 108 | L2P0ouktojrYhSV5m8OC9Dd/VWYcRo6pFCi6bsXFjHOx5RyIcqPwzAl/CbdLBAiN 109 | JgNFrKvL3ynS1AsGDScbTbVOuhRSWjPX5PSrjEVXhoGfwH0Z7FOWSP6WpkOeOBOA 110 | 9l3JqC8TGWGZDz6xMEd2rcV7DtdN6xogITgrYHG+fDfUJfIzpvMT/HCwjeIuB4Wa 111 | 8LcPcgJDRlXEE7tlxcOf3nAisQQp3u4E456n0/iF1Lm13DcmLRyE8FnMAvZC3P3g 112 | 1lGyrLbvwCV0Z3VP5+S8ta5oZbhtMQJBcUXbzPepVvhnND8BmamFb8QX7PHnLPbf 113 | 35d6W6VDsVZ0S1Ry4WWhf7CT7Y6GX8gqdeevdlJLFOjhnd85tz23gS6VGizhv9JS 114 | M8woAWQOBEUctCiDnZR7DmgNNG0ICQ/SO5w9rgKQkm/czJ/W8Nry9HUeWg0iGdHe 115 | GGO0EYYRcK/iltMYFgTCTFb9WYxKJOPCl2A2U62p7rwgFMYwDrADf5b7G7EmMY5s 116 | cfpOBetkbxoz3n3a6bV9e8Cm2onT79ATl2TSXelWZ2mDcBEYkqo2Flqlxr6f9Ohu 117 | FrOV4YV/eSWu5S9BQNIrQv3a8ZUueScXQWMQ5pmSjZsAvkyq6zwZC32DCe3to2Uh 118 | nCF0Mg2y923yxC54QE8oTTbwuP1W/vU/CG+cPCqEYUTx8kQGESrCT15jJsa/LTMB 119 | EiJlz1d7TBL7BW8JFStXG/8IF9rnw3jqEvsj8PsBQ7avxG1ERdxOZQAzkKz9vvnw 120 | ZW5HiC5ZceiovS/P49WCPYuAWxdm5Ny1hmCE7cuwjcKeEyw/xkiiPZ923uEs6FZM 121 | xXSkdquWsXFFo3PNVhxKANE3wJe6BGyT04eIan2spEI+DU+EYVLAT7IsPwTFg6Bg 122 | qWIqSKmKJBo9aPv/XGls0c4fsb85KYlgLQSeCatxXkK409mDsH1pDrnLBYPqDLy8 123 | oVvXmotld/obHt7mwV0Z+VPhtaOeXtFhD1927ppSh5QTuPZPVtxAjk9xQ1aW4JEv 124 | W3dXkkCttTjwEJkFwW/dmRohkoAG6Vd6QgLhIViP1pVaQqlcbB/24yFEyRk8KoJi 125 | SWqQZICa0baCw499OdNSLBYMeEyuCBlWx0gMVfn6LgQ/WQrP2fi/xh/weos1e3XQ 126 | BPHhWixHuenQBOTiD8Hp/o67UIa/QtUSMauRZcbxANHRegYs0PYGD8uHjjmCQli1 127 | 4ZffAgn82/sFXmGlpQxkVXTR1N2HilUekHN+XetY2vUwXOC/wUXJnrs34iun1JAB 128 | QY9VpH9eM+SzT7ADGifIxsGs8jeWlbIo5VzzEv2HWJ/xGARy7+V6P70OOYGwqkYp 129 | O9QlJJ12OCxxmkvYCt4ssP2H12+FJX2ANA9byGkeVgc8vdEbZumpAKKOP+ZgU9qZ 130 | tnewaRNR46c2SlLUnr35JTHY7jTH0AeHlUqlaVKBiLLRh4XgIREsiqx5ZMV6kiGX 131 | hdYLz01EHpROh2B6JzzTVc5mXlpoBcIogShbNR+wAYgCW+wJP8CcHd+P6aG6r4Cr 132 | JKcqLQPg68yaAFFi1smUJ4WmXqTUljUzdYkPsz352Ag= 133 | -------------------------------------------------------------------------------- /modules/nixos/services/acme/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | namespace, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.${namespace}.services.acme; 10 | in 11 | { 12 | options = { 13 | ${namespace}.services.acme = { 14 | enable = lib.mkEnableOption "Enable the ACME client (for Let's Encrypt TLS certificates)."; 15 | certs = lib.mkOption { 16 | default = { }; 17 | type = lib.types.attrs; 18 | description = "Cert configurations for ACME."; 19 | }; 20 | defaultEmail = lib.mkOption { 21 | default = ""; 22 | type = lib.types.str; 23 | description = "Default admin email to use for problems."; 24 | }; 25 | }; 26 | }; 27 | 28 | config = lib.mkIf cfg.enable { 29 | security.acme = { 30 | acceptTerms = true; 31 | defaults.email = cfg.defaultEmail; 32 | certs = cfg.certs; 33 | }; 34 | 35 | # /var/lib/acme/.challenges must be writable by the ACME user 36 | # and readable by the Nginx user. The easiest way to achieve 37 | # this is to add the Nginx user to the ACME group. 38 | users.users.nginx.extraGroups = lib.mkIf config.${namespace}.services.nginx.enable [ "acme" ]; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /modules/nixos/services/apcupsd/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | namespace, 5 | ... 6 | }: 7 | let 8 | cfg = config.${namespace}.services.apcupsd; 9 | in 10 | { 11 | options = { 12 | ${namespace}.services.apcupsd = { 13 | enable = lib.mkEnableOption "Enables apcupsd"; 14 | configText = lib.mkOption { 15 | type = lib.types.str; 16 | description = "The configuration to pass to apcupsd."; 17 | }; 18 | }; 19 | }; 20 | 21 | config = lib.mkIf cfg.enable { 22 | services.apcupsd = { 23 | enable = true; 24 | configText = cfg.configText; 25 | }; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /modules/nixos/services/archiveteam-warrior/default.nix: -------------------------------------------------------------------------------- 1 | # Module for running Warrior from ArchiveTeam 2 | { 3 | config, 4 | lib, 5 | namespace, 6 | ... 7 | }: 8 | 9 | let 10 | cfg = config.${namespace}.services.archiveteam-warrior; 11 | 12 | UID = 8001; 13 | GID = 8001; 14 | in 15 | { 16 | options = { 17 | ${namespace}.services.archiveteam-warrior = { 18 | enable = lib.mkEnableOption "Enables Warrior."; 19 | useVPN = lib.mkEnableOption "Sends traffic from Warrior through Gluetun."; 20 | home = lib.mkOption { 21 | default = "/var/lib/archiveteam/warrior"; 22 | type = lib.types.str; 23 | description = "Where to store Warrior's files."; 24 | }; 25 | user = lib.mkOption { 26 | type = lib.types.str; 27 | default = "archiveteam"; 28 | description = "User account under which Warrior runs."; 29 | }; 30 | group = lib.mkOption { 31 | type = lib.types.str; 32 | default = "archiveteam"; 33 | description = "Group under which Warrior runs."; 34 | }; 35 | port = lib.mkOption { 36 | type = lib.types.int; 37 | default = 8001; 38 | description = "Which port to run Warrior on. Set to 0 to disable host port binding."; 39 | }; 40 | }; 41 | }; 42 | 43 | config = lib.mkIf cfg.enable { 44 | ${namespace}.services.virtualization.containers.enable = true; 45 | 46 | users = { 47 | users.${cfg.user} = { 48 | uid = UID; 49 | description = "ArchiveTeam Warrior user"; 50 | isSystemUser = true; 51 | group = cfg.group; 52 | }; 53 | groups.${cfg.group}.gid = GID; 54 | }; 55 | 56 | virtualisation.oci-containers.containers = { 57 | archiveteam-warrior = { 58 | image = "atdr.meo.ws/archiveteam/warrior-dockerfile:latest"; 59 | user = "${builtins.toString UID}:${builtins.toString GID}"; 60 | volumes = [ 61 | "${cfg.home}/data:/home/warrior/data" 62 | "${cfg.home}/projects:/home/warrior/projects" 63 | ]; 64 | extraOptions = 65 | [ 66 | "--label=io.containers.autoupdate=registry" 67 | ] 68 | ++ lib.optionals config.${namespace}.services.vpn.enable [ 69 | "--network=container:gluetun" 70 | "--no-healthcheck" 71 | ]; 72 | dependsOn = lib.mkIf config.${namespace}.services.vpn.enable [ "gluetun" ]; 73 | ports = lib.mkIf (cfg.port > 0 && !config.${namespace}.services.vpn.enable) [ 74 | "127.0.0.1:8001:${builtins.toString cfg.port}" 75 | ]; 76 | }; 77 | 78 | # Open port in Gluetun if we're using it 79 | gluetun.ports = lib.mkIf config.${namespace}.services.vpn.enable [ 80 | "127.0.0.1:8001:${builtins.toString cfg.port}" 81 | ]; 82 | }; 83 | 84 | systemd = { 85 | # Set permissions for home folder 86 | tmpfiles.rules = [ "Z ${cfg.home} ${builtins.toString UID} ${builtins.toString GID} - -" ]; 87 | 88 | # Tell systemd to wait for the module's configuration directory to be available before starting the service. 89 | services.archiveteam-warrior.unitConfig.RequiresMountsFor = cfg.home; 90 | }; 91 | }; 92 | } 93 | -------------------------------------------------------------------------------- /modules/nixos/services/autoupgrade/default.nix: -------------------------------------------------------------------------------- 1 | # Run automatic updates. Replaces system.autoUpgrade. 2 | { 3 | config, 4 | lib, 5 | namespace, 6 | ... 7 | }: 8 | 9 | let 10 | cfg = config.${namespace}.services.autoUpgrade; 11 | in 12 | { 13 | options = { 14 | ${namespace}.services.autoUpgrade = { 15 | enable = lib.mkEnableOption "Enables automatic system updates."; 16 | configDir = lib.mkOption { 17 | type = lib.types.str; 18 | description = "Path where your NixOS configuration files are stored."; 19 | }; 20 | extraFlags = lib.mkOption { 21 | type = lib.types.str; 22 | description = "Extra flags to pass to nixos-rebuild."; 23 | default = ""; 24 | }; 25 | onCalendar = lib.mkOption { 26 | default = "daily"; 27 | type = lib.types.str; 28 | description = "How frequently to run updates. See systemd.timer(5) and systemd.time(7) for configuration details."; 29 | }; 30 | operation = lib.mkOption { 31 | type = lib.types.enum [ 32 | "boot" 33 | "switch" 34 | "test" 35 | ]; 36 | default = "switch"; 37 | description = "Which `nixos-rebuild` operation to perform. Defaults to `switch`."; 38 | }; 39 | persistent = lib.mkOption { 40 | default = true; 41 | type = lib.types.bool; 42 | description = "If true, the time when the service unit was last triggered is stored on disk. When the timer is activated, the service unit is triggered immediately if it would have been triggered at least once during the time when the timer was inactive. This is useful to catch up on missed runs of the service when the system was powered down."; 43 | }; 44 | pushUpdates = lib.mkEnableOption "Updates the flake.lock file and pushes it back to the repo."; 45 | user = lib.mkOption { 46 | type = lib.types.str; 47 | description = "The user who owns the configDir."; 48 | }; 49 | }; 50 | }; 51 | 52 | config = lib.mkIf cfg.enable { 53 | # Assert that system.autoUpgrade is not also enabled 54 | assertions = [ 55 | { 56 | assertion = !config.system.autoUpgrade.enable; 57 | message = "The system.autoUpgrade option conflicts with this module."; 58 | } 59 | ]; 60 | 61 | # Deploy update script 62 | ${namespace}.nix.nixos-operations-script.enable = true; 63 | 64 | # Pull and apply updates. 65 | systemd = { 66 | services."nixos-upgrade" = { 67 | serviceConfig = { 68 | Type = "oneshot"; 69 | User = "root"; 70 | }; 71 | path = config.${namespace}.corePackages; 72 | unitConfig.RequiresMountsFor = cfg.configDir; 73 | script = 74 | "/run/current-system/sw/bin/nixos-operations-script --operation ${cfg.operation} " 75 | + (if (cfg.configDir != "") then "--flake ${cfg.configDir} " else "") 76 | + (if (cfg.user != "") then "--user ${cfg.user} " else "") 77 | + (if (cfg.pushUpdates) then "--update " else "") 78 | + (if (cfg.extraFlags != "") then cfg.extraFlags else ""); 79 | }; 80 | timers."nixos-upgrade" = { 81 | wants = [ "network-online.target" ]; 82 | after = [ "network-online.target" ]; 83 | wantedBy = [ "timers.target" ]; 84 | timerConfig = { 85 | OnCalendar = cfg.onCalendar; 86 | Persistent = cfg.persistent; 87 | Unit = "nixos-upgrade.service"; 88 | RandomizedDelaySec = "30m"; 89 | }; 90 | }; 91 | }; 92 | }; 93 | } 94 | -------------------------------------------------------------------------------- /modules/nixos/services/binary-cache/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | namespace, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.${namespace}.services.binary-cache; 10 | in 11 | { 12 | options = { 13 | ${namespace}.services.binary-cache = { 14 | enable = lib.mkEnableOption "Enable a binary cache hosting service."; 15 | secretKeyFile = lib.mkOption { 16 | default = "/var/lib/nix-binary-cache/privkey.pem"; 17 | type = lib.types.str; 18 | description = "Where to find the binary cache's private key."; 19 | }; 20 | url = lib.mkOption { 21 | default = ""; 22 | type = lib.types.str; 23 | description = "The complete URL where the cache is hosted."; 24 | example = "https://cache.example.com"; 25 | }; 26 | auth = { 27 | password = lib.mkOption { 28 | default = ""; 29 | type = lib.types.str; 30 | description = "The password to use for basic authentication for the cache."; 31 | example = "MySuperSecurePassword123"; 32 | }; 33 | user = lib.mkOption { 34 | default = "cache-user"; 35 | type = lib.types.str; 36 | description = "The username to use for basic auth."; 37 | }; 38 | }; 39 | }; 40 | }; 41 | 42 | config = lib.mkIf cfg.enable { 43 | services = { 44 | nix-serve = { 45 | enable = true; 46 | secretKeyFile = cfg.secretKeyFile; 47 | bindAddress = "127.0.0.1"; 48 | }; 49 | 50 | nginx.virtualHosts."${cfg.url}" = { 51 | useACMEHost = lib.${namespace}.getDomainFromURI cfg.url; 52 | forceSSL = true; 53 | basicAuth = { 54 | "${cfg.auth.user}" = cfg.auth.password; 55 | }; 56 | locations."/" = { 57 | proxyPass = "http://${config.services.nix-serve.bindAddress}:${toString config.services.nix-serve.port}"; 58 | }; 59 | }; 60 | }; 61 | 62 | systemd.services = { 63 | nix-serve.unitConfig.RequiresMountsFor = cfg.secretKeyFile; 64 | nginx.wants = [ config.systemd.services.nix-serve.name ]; 65 | }; 66 | }; 67 | } 68 | -------------------------------------------------------------------------------- /modules/nixos/services/boinc/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | namespace, 6 | ... 7 | }: 8 | 9 | let 10 | cfg = config.${namespace}.services.boinc; 11 | in 12 | { 13 | options = { 14 | ${namespace}.services.boinc = { 15 | enable = lib.mkEnableOption "Enables BOINC distributed computing service."; 16 | home = lib.mkOption { 17 | default = "/var/lib/boinc"; 18 | type = lib.types.str; 19 | description = "Where to store BOINC's files"; 20 | }; 21 | }; 22 | }; 23 | 24 | config = lib.mkIf cfg.enable { 25 | services.boinc = { 26 | enable = true; 27 | package = pkgs.boinc-headless; 28 | dataDir = cfg.home; 29 | extraEnvPackages = [ 30 | pkgs.ocl-icd 31 | ] ++ lib.optionals config.${namespace}.gpu.nvidia.enable [ pkgs.linuxPackages.nvidia_x11 ]; 32 | allowRemoteGuiRpc = true; 33 | }; 34 | 35 | systemd.services.boinc.unitConfig.RequiresMountsFor = cfg.home; 36 | 37 | # Allow connections via BOINC Manager 38 | networking.firewall.allowedTCPPorts = [ 31416 ]; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /modules/nixos/services/duplicacy-web/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | config, 4 | lib, 5 | namespace, 6 | ... 7 | }: 8 | 9 | let 10 | cfg = config.${namespace}.services.duplicacy-web; 11 | in 12 | { 13 | options = { 14 | ${namespace}.services.duplicacy-web = { 15 | enable = lib.mkEnableOption "Enables duplicacy-web"; 16 | home = lib.mkOption { 17 | default = "/var/lib/duplicacy-web"; 18 | type = lib.types.str; 19 | description = "Environment where duplicacy-web stores its config files"; 20 | }; 21 | homeBackupDir = lib.mkOption { 22 | default = null; 23 | type = lib.types.str; 24 | description = "Where to back up Duplicacy's settings in case of an emergency."; 25 | }; 26 | port = lib.mkOption { 27 | default = 3875; 28 | type = lib.types.int; 29 | description = "The port to host duplicacy-web on."; 30 | }; 31 | }; 32 | }; 33 | 34 | config = lib.mkIf cfg.enable { 35 | environment.systemPackages = [ pkgs.${namespace}.duplicacy-web ]; 36 | 37 | systemd.services = { 38 | # Install systemd service for the web UI. 39 | duplicacy-web = { 40 | enable = true; 41 | wants = [ "network-online.target" ]; 42 | wantedBy = [ "multi-user.target" ]; 43 | after = [ 44 | "syslog.target" 45 | "network-online.target" 46 | ]; 47 | description = "Start the Duplicacy backup service and web UI"; 48 | serviceConfig = { 49 | Type = "simple"; 50 | ExecStart = ''${pkgs.${namespace}.duplicacy-web}/duplicacy-web''; 51 | Restart = "on-failure"; 52 | RestartSec = 10; 53 | KillMode = "process"; 54 | }; 55 | environment = { 56 | HOME = cfg.home; 57 | }; 58 | unitConfig.RequiresMountsFor = cfg.home; 59 | }; 60 | 61 | # Periodically back up Duplicacy's settings to a separate location/drive 62 | duplicacy-backup = lib.mkIf (cfg.homeBackupDir != null) { 63 | serviceConfig = { 64 | Type = "oneshot"; 65 | User = "root"; 66 | }; 67 | path = [ pkgs.rsync ]; 68 | script = "${lib.getExe pkgs.rsync} -a ${cfg.home}/ ${cfg.homeBackupDir}/"; 69 | }; 70 | }; 71 | 72 | systemd.timers."duplicacy-backup" = lib.mkIf (cfg.homeBackupDir != null) { 73 | wants = [ "duplicacy-web.target" ]; 74 | after = [ "duplicacy-web.target" ]; 75 | wantedBy = [ "timers.target" ]; 76 | timerConfig = { 77 | OnCalendar = "daily"; 78 | Persistent = true; 79 | Unit = "duplicacy-backup.service"; 80 | }; 81 | }; 82 | }; 83 | } 84 | -------------------------------------------------------------------------------- /modules/nixos/services/forgejo/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | namespace, 5 | ... 6 | }: 7 | let 8 | cfg = config.${namespace}.services.forgejo; 9 | in 10 | { 11 | options = { 12 | ${namespace}.services.forgejo = { 13 | enable = lib.mkEnableOption "Enables Forgejo Git hosting service."; 14 | home = lib.mkOption { 15 | default = ""; 16 | type = lib.types.str; 17 | description = "Where to store Forgejo's files"; 18 | example = "/home/forgejo"; 19 | }; 20 | url = lib.mkOption { 21 | default = ""; 22 | type = lib.types.str; 23 | description = "The complete URL where Forgejo is hosted."; 24 | example = "https://forgejo.example.com"; 25 | }; 26 | }; 27 | }; 28 | 29 | config = lib.mkIf cfg.enable { 30 | services = { 31 | forgejo = { 32 | enable = true; 33 | settings = { 34 | server = { 35 | DOMAIN = lib.${namespace}.getDomainFromURI cfg.url; 36 | ROOT_URL = cfg.url; 37 | HTTP_PORT = 3000; 38 | }; 39 | indexer.REPO_INDEXER_ENABLED = true; # Enable code indexing 40 | }; 41 | useWizard = true; 42 | } // lib.optionalAttrs (cfg.home != null) { stateDir = cfg.home; }; 43 | 44 | nginx.virtualHosts."${cfg.url}" = { 45 | useACMEHost = lib.${namespace}.getDomainFromURI cfg.url; 46 | forceSSL = true; 47 | locations."/" = { 48 | proxyPass = "http://127.0.0.1:3000"; 49 | proxyWebsockets = true; 50 | extraConfig = "proxy_ssl_server_name on;"; # required when the target is also TLS server with multiple hosts 51 | }; 52 | }; 53 | }; 54 | 55 | systemd.services = { 56 | forgejo.unitConfig.RequiresMountsFor = cfg.home; 57 | nginx.wants = [ config.systemd.services.forgejo.name ]; 58 | }; 59 | }; 60 | } 61 | -------------------------------------------------------------------------------- /modules/nixos/services/jellyfin/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | config, 4 | lib, 5 | namespace, 6 | ... 7 | }: 8 | let 9 | cfg = config.${namespace}.services.jellyfin; 10 | 11 | jellyfin-audio-save = pkgs.unstable.jellyfin.overrideAttrs ( 12 | _finalAttrs: _prevAttrs: { patches = [ ./jellyfin-audio-save-position.patch ]; } 13 | ); 14 | in 15 | { 16 | options = { 17 | ${namespace}.services.jellyfin = { 18 | enable = lib.mkEnableOption "Enables the Jellyfin media streaming service."; 19 | home = lib.mkOption { 20 | default = "/var/lib/jellyfin"; 21 | type = lib.types.str; 22 | description = "Where to store Jellyfin's files"; 23 | }; 24 | url = lib.mkOption { 25 | default = ""; 26 | type = lib.types.str; 27 | description = "The complete URL where Jellyfin is hosted."; 28 | example = "https://jellyfin.example.com"; 29 | }; 30 | }; 31 | }; 32 | 33 | config = lib.mkIf cfg.enable { 34 | ${namespace}.users.media.enable = true; 35 | 36 | services = { 37 | nginx.virtualHosts."${cfg.url}" = { 38 | useACMEHost = lib.${namespace}.getDomainFromURI cfg.url; 39 | forceSSL = true; 40 | locations."/" = { 41 | proxyPass = "http://127.0.0.1:8096"; 42 | proxyWebsockets = true; 43 | extraConfig = '' 44 | # Taken from https://jellyfin.org/docs/general/networking/nginx/ 45 | client_max_body_size 20M; 46 | 47 | # Security / XSS Mitigation Headers 48 | # NOTE: X-Frame-Options may cause issues with the webOS app 49 | add_header X-Frame-Options "SAMEORIGIN"; 50 | add_header X-Content-Type-Options "nosniff"; 51 | 52 | proxy_set_header Host $host; 53 | proxy_set_header X-Real-IP $remote_addr; 54 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 55 | proxy_set_header X-Forwarded-Proto $scheme; 56 | proxy_set_header X-Forwarded-Protocol $scheme; 57 | proxy_set_header X-Forwarded-Host $host; 58 | 59 | # Disable buffering when the nginx proxy gets very resource heavy upon streaming 60 | proxy_buffering off; 61 | ''; 62 | }; 63 | locations."/socket" = { 64 | proxyPass = "http://127.0.0.1:8096"; 65 | proxyWebsockets = true; 66 | extraConfig = '' 67 | # Proxy Jellyfin Websockets traffic 68 | proxy_set_header Upgrade $http_upgrade; 69 | proxy_set_header Connection "upgrade"; 70 | proxy_set_header Host $host; 71 | proxy_set_header X-Real-IP $remote_addr; 72 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 73 | proxy_set_header X-Forwarded-Proto $scheme; 74 | proxy_set_header X-Forwarded-Protocol $scheme; 75 | proxy_set_header X-Forwarded-Host $host; 76 | ''; 77 | }; 78 | }; 79 | 80 | jellyfin = { 81 | enable = true; 82 | dataDir = cfg.home; 83 | group = "media"; 84 | package = jellyfin-audio-save; 85 | }; 86 | }; 87 | 88 | systemd.services = { 89 | jellyfin = { 90 | # Install packages for plugins 91 | path = with pkgs; [ 92 | id3v2 93 | yt-dlp 94 | ]; 95 | unitConfig.RequiresMountsFor = cfg.home; 96 | }; 97 | nginx.wants = [ config.systemd.services.jellyfin.name ]; 98 | }; 99 | 100 | # Set permissions for media folders 101 | systemd.tmpfiles.rules = [ "Z /storage/Media 6775 aires media - -" ]; 102 | }; 103 | } 104 | -------------------------------------------------------------------------------- /modules/nixos/services/jellyfin/jellyfin-audio-save-position.patch: -------------------------------------------------------------------------------- 1 | From 6d4ddc706c414a9c4370cc9b3a823afc5c4ff2dc Mon Sep 17 00:00:00 2001 2 | From: Blake Smith 3 | Date: Mon, 8 Jan 2024 20:41:32 -0600 4 | Subject: [PATCH] Support resume on audio 5 | 6 | --- 7 | MediaBrowser.Controller/Entities/Audio/Audio.cs | 3 +++ 8 | 1 file changed, 3 insertions(+) 9 | 10 | diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs 11 | index 243d2f04f2f..2b363ae2083 100644 12 | --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs 13 | +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs 14 | @@ -37,6 +37,9 @@ public Audio() 15 | [JsonIgnore] 16 | public IReadOnlyList AlbumArtists { get; set; } 17 | 18 | + [JsonIgnore] 19 | + public override bool SupportsPositionTicksResume => true; 20 | + 21 | [JsonIgnore] 22 | public override bool SupportsPlayedStatus => true; 23 | -------------------------------------------------------------------------------- /modules/nixos/services/languagetool/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | config, 4 | lib, 5 | namespace, 6 | ... 7 | }: 8 | let 9 | cfg = config.${namespace}.services.languagetool; 10 | in 11 | { 12 | options = { 13 | ${namespace}.services.languagetool = { 14 | enable = lib.mkEnableOption (lib.mdDoc "Enables LanguageTool server."); 15 | auth = { 16 | password = lib.mkOption { 17 | default = ""; 18 | type = lib.types.str; 19 | description = "The password to use for basic authentication for LanguageTool."; 20 | example = "MySuperSecurePassword123"; 21 | }; 22 | user = lib.mkOption { 23 | default = "ltuser"; 24 | type = lib.types.str; 25 | description = "The username to use for basic auth."; 26 | }; 27 | }; 28 | ngrams.enable = lib.mkEnableOption ( 29 | lib.mdDoc "Enables n-gram data set. See https://dev.languagetool.org/finding-errors-using-n-gram-data.html" 30 | ); 31 | port = lib.mkOption { 32 | default = 8080; 33 | type = lib.types.int; 34 | description = "The port to run LanguageTool on."; 35 | example = 8080; 36 | }; 37 | url = lib.mkOption { 38 | default = ""; 39 | type = lib.types.str; 40 | description = "The complete URL where LanguageTool is hosted."; 41 | example = "https://languagetool.example.com"; 42 | }; 43 | }; 44 | }; 45 | 46 | config = lib.mkIf cfg.enable { 47 | services = { 48 | languagetool = lib.mkIf cfg.enable { 49 | enable = true; 50 | port = cfg.port; 51 | public = true; 52 | allowOrigin = "*"; 53 | # Enable Ngrams 54 | settings.languageModel = lib.mkIf cfg.ngrams.enable "${ 55 | pkgs.${namespace}.languagetool-ngrams 56 | }/share/languagetool/ngrams"; 57 | }; 58 | # Create Nginx virtualhost 59 | nginx.virtualHosts."${cfg.url}" = { 60 | useACMEHost = lib.${namespace}.getDomainFromURI cfg.url; 61 | forceSSL = true; 62 | basicAuth = { 63 | "${cfg.auth.user}" = cfg.auth.password; 64 | }; 65 | locations."/" = { 66 | proxyPass = "http://127.0.0.1:${builtins.toString cfg.port}"; 67 | extraConfig = "proxy_ssl_server_name on;"; 68 | }; 69 | }; 70 | }; 71 | 72 | systemd.services.nginx.wants = [ config.systemd.services.languagetool.name ]; 73 | }; 74 | } 75 | -------------------------------------------------------------------------------- /modules/nixos/services/msmtp/default.nix: -------------------------------------------------------------------------------- 1 | # See https://wiki.nixos.org/wiki/Msmtp 2 | { 3 | config, 4 | lib, 5 | namespace, 6 | ... 7 | }: 8 | 9 | let 10 | cfg = config.${namespace}.services.msmtp; 11 | in 12 | { 13 | options = { 14 | ${namespace}.services.msmtp = { 15 | enable = lib.mkEnableOption "Enables mail server"; 16 | accounts = lib.mkOption { 17 | type = lib.types.attrs; 18 | description = "A list of accounts to use for msmtp."; 19 | }; 20 | aliases = lib.mkOption { 21 | default = { }; 22 | type = lib.types.attrs; 23 | description = "Optional email aliases to add."; 24 | }; 25 | }; 26 | }; 27 | 28 | config = lib.mkIf cfg.enable { 29 | programs.msmtp = { 30 | enable = true; 31 | defaults.aliases = "/etc/aliases"; 32 | accounts = cfg.accounts; 33 | }; 34 | 35 | # Send all mail to my email address by default 36 | environment.etc."aliases" = cfg.aliases; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /modules/nixos/services/nginx/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | namespace, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.${namespace}.services.nginx; 10 | in 11 | { 12 | options = { 13 | ${namespace}.services.nginx = { 14 | enable = lib.mkEnableOption "Enable the Nginx web server."; 15 | 16 | virtualHosts = lib.mkOption { 17 | default = { }; 18 | type = lib.types.attrs; 19 | description = "Virtualhost configurations for Nginx."; 20 | }; 21 | }; 22 | }; 23 | 24 | config = lib.mkIf cfg.enable { 25 | services.nginx = { 26 | enable = true; 27 | 28 | # Use recommended settings per https://wiki.nixos.org/wiki/Nginx#Hardened_setup_with_TLS_and_HSTS_preloading 29 | recommendedGzipSettings = true; 30 | recommendedOptimisation = true; 31 | recommendedTlsSettings = true; 32 | 33 | virtualHosts = cfg.virtualHosts; 34 | }; 35 | 36 | # Open ports 37 | networking.firewall = { 38 | enable = true; 39 | allowedTCPPorts = [ 40 | 80 41 | 443 42 | ]; 43 | }; 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /modules/nixos/services/observability/default.nix: -------------------------------------------------------------------------------- 1 | # Sets up an observability stack with Prometheus, Grafana, and Loki 2 | # Follows https://xeiaso.net/blog/prometheus-grafana-loki-nixos-2020-11-20/ 3 | { 4 | config, 5 | lib, 6 | namespace, 7 | ... 8 | }: 9 | 10 | let 11 | cfg = config.${namespace}.services.observability; 12 | in 13 | { 14 | options = { 15 | ${namespace}.services.observability = { 16 | enable = lib.mkEnableOption "Enables monitoring via Prometheus, Grafana, and Loki."; 17 | grafana = { 18 | home = lib.mkOption { 19 | default = "/var/lib/grafana"; 20 | type = lib.types.str; 21 | description = "Where to store Grafana's files."; 22 | }; 23 | port = lib.mkOption { 24 | default = 2342; 25 | type = lib.types.int; 26 | description = "The port to host Grafana on."; 27 | }; 28 | smtp = lib.mkOption { 29 | default = { }; 30 | type = lib.types.attrs; 31 | description = "SMTP configuration for Grafana alerts."; 32 | }; 33 | }; 34 | loki.port = lib.mkOption { 35 | default = 3030; 36 | type = lib.types.int; 37 | description = "The port to host Loki on."; 38 | }; 39 | promtail.port = lib.mkOption { 40 | default = 3031; 41 | type = lib.types.int; 42 | description = "The port to host Grafana on."; 43 | }; 44 | prometheus.port = lib.mkOption { 45 | default = 3020; 46 | type = lib.types.int; 47 | description = "The port to host Grafana on."; 48 | }; 49 | url = lib.mkOption { 50 | default = ""; 51 | type = lib.types.str; 52 | description = "The complete URL where Grafana is hosted."; 53 | example = "https://ops.example.com"; 54 | }; 55 | }; 56 | }; 57 | 58 | config = lib.mkIf cfg.enable { 59 | services = { 60 | grafana = { 61 | enable = true; 62 | settings = { 63 | analytics.reporting_enabled = false; 64 | server = { 65 | domain = lib.${namespace}.getDomainFromURI cfg.url; 66 | http_addr = "127.0.0.1"; 67 | http_port = cfg.grafana.port; 68 | }; 69 | smtp = lib.mkIf (cfg.grafana.smtp != { }) cfg.grafana.smtp; 70 | }; 71 | dataDir = cfg.grafana.home; 72 | provision = { 73 | enable = true; 74 | datasources.settings.datasources = [ 75 | { 76 | name = "Prometheus"; 77 | type = "prometheus"; 78 | access = "proxy"; 79 | url = "http://127.0.0.1:${toString cfg.prometheus.port}"; 80 | } 81 | { 82 | name = "Loki"; 83 | type = "loki"; 84 | access = "proxy"; 85 | url = "http://127.0.0.1:${toString cfg.loki.port}"; 86 | } 87 | ]; 88 | }; 89 | }; 90 | 91 | loki = { 92 | enable = true; 93 | configuration = { 94 | server.http_listen_port = cfg.loki.port; 95 | auth_enabled = false; 96 | 97 | ingester = { 98 | lifecycler = { 99 | address = "127.0.0.1"; 100 | ring = { 101 | kvstore = { 102 | store = "inmemory"; 103 | }; 104 | replication_factor = 1; 105 | }; 106 | }; 107 | chunk_idle_period = "1h"; 108 | max_chunk_age = "1h"; 109 | chunk_target_size = 999999; 110 | chunk_retain_period = "30s"; 111 | }; 112 | 113 | schema_config = { 114 | configs = [ 115 | { 116 | from = "2025-02-01"; 117 | store = "boltdb"; 118 | object_store = "filesystem"; 119 | schema = "v13"; 120 | index = { 121 | prefix = "index_"; 122 | period = "24h"; 123 | }; 124 | } 125 | ]; 126 | }; 127 | 128 | storage_config = { 129 | boltdb = { 130 | directory = "/var/lib/loki/index"; 131 | }; 132 | filesystem = { 133 | directory = "/var/lib/loki/chunks"; 134 | }; 135 | }; 136 | 137 | limits_config = { 138 | allow_structured_metadata = false; 139 | reject_old_samples = true; 140 | reject_old_samples_max_age = "168h"; 141 | }; 142 | 143 | table_manager = { 144 | retention_deletes_enabled = false; 145 | retention_period = "0s"; 146 | }; 147 | 148 | compactor = { 149 | working_directory = "/var/lib/loki"; 150 | compactor_ring = { 151 | kvstore = { 152 | store = "inmemory"; 153 | }; 154 | }; 155 | }; 156 | }; 157 | }; 158 | 159 | # Promtail sends logs into Loki 160 | promtail = { 161 | enable = true; 162 | configuration = { 163 | server = { 164 | http_listen_port = cfg.promtail.port; 165 | grpc_listen_port = 0; 166 | }; 167 | positions = { 168 | filename = "/tmp/positions.yaml"; 169 | }; 170 | clients = [ 171 | { 172 | url = "http://127.0.0.1:${toString cfg.loki.port}/loki/api/v1/push"; 173 | } 174 | ]; 175 | scrape_configs = [ 176 | { 177 | job_name = "journal"; 178 | journal = { 179 | max_age = "12h"; 180 | labels = { 181 | job = "systemd-journal"; 182 | host = config.networking.hostName; 183 | }; 184 | }; 185 | relabel_configs = [ 186 | { 187 | source_labels = [ "__journal__systemd_unit" ]; 188 | target_label = "unit"; 189 | } 190 | ]; 191 | } 192 | ]; 193 | }; 194 | }; 195 | 196 | prometheus = { 197 | enable = true; 198 | port = cfg.prometheus.port; 199 | globalConfig.scrape_interval = "15s"; # Fix data not showing on Grafana graphs for short (<3 hour) time frames. See https://github.com/grafana/grafana/issues/29858#issuecomment-2120235388 200 | retentionTime = "7d"; # Retain samples for one week 201 | exporters = { 202 | # Export this node's statistics 203 | node = { 204 | enable = true; 205 | enabledCollectors = [ "systemd" ]; 206 | }; 207 | # Export additional statistics 208 | apcupsd.enable = config.${namespace}.services.apcupsd.enable; 209 | nginx = { 210 | enable = config.${namespace}.services.nginx.enable; 211 | scrapeUri = "http://127.0.0.1/nginx_status"; 212 | }; 213 | smartctl.enable = config.services.smartd.enable; 214 | }; 215 | # Ingest statistics from nodes 216 | scrapeConfigs = [ 217 | { 218 | job_name = "prometheus-ingest"; 219 | static_configs = [ 220 | { 221 | targets = with config.services.prometheus.exporters; [ 222 | "127.0.0.1:${toString node.port}" 223 | "127.0.0.1:${toString apcupsd.port}" 224 | "127.0.0.1:${toString nginx.port}" 225 | "127.0.0.1:${toString smartctl.port}" 226 | ]; 227 | } 228 | ]; 229 | relabel_configs = [ 230 | { 231 | source_labels = [ "__address__" ]; 232 | separator = ":"; 233 | regex = "(.*):(.*)"; 234 | replacement = config.networking.hostName; 235 | target_label = "instance"; 236 | } 237 | ]; 238 | } 239 | ]; 240 | }; 241 | 242 | # Taken from https://grafana.com/tutorials/run-grafana-behind-a-proxy/ 243 | nginx = { 244 | /* 245 | FIXME: Nginx fails to start if this upstream is defined 246 | upstreams."grafana" = { 247 | servers = { 248 | "http://127.0.0.1:${builtins.toString cfg.grafana.port}" = { 249 | weight = 1; 250 | }; 251 | }; 252 | }; 253 | */ 254 | virtualHosts."${cfg.url}" = { 255 | useACMEHost = lib.${namespace}.getDomainFromURI cfg.url; 256 | forceSSL = true; 257 | locations."/" = { 258 | proxyPass = "http://127.0.0.1:${builtins.toString cfg.grafana.port}"; 259 | proxyWebsockets = true; 260 | extraConfig = '' 261 | proxy_set_header Host $host; 262 | proxy_set_header X-Forwarded-Host $host; 263 | proxy_set_header X-Forwarded-Server $host; 264 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 265 | proxy_pass_request_headers on; 266 | proxy_set_header Connection "keep-alive"; 267 | proxy_store off; 268 | ''; 269 | }; 270 | }; 271 | }; 272 | }; 273 | 274 | systemd.services = { 275 | grafana.unitConfig.RequiresMountsFor = cfg.grafana.home; 276 | nginx.wants = [ config.systemd.services.grafana.name ]; 277 | }; 278 | }; 279 | } 280 | -------------------------------------------------------------------------------- /modules/nixos/services/ollama/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | namespace, 5 | ... 6 | }: 7 | let 8 | cfg = config.${namespace}.services.open-webui; 9 | 10 | api.port = 11434; 11 | webui.port = 8130; 12 | 13 | ollamaUser = "ollama"; 14 | ollamaGroup = ollamaUser; 15 | in 16 | { 17 | options = { 18 | ${namespace}.services.open-webui = { 19 | enable = lib.mkEnableOption "Enables Ollama."; 20 | url = lib.mkOption { 21 | default = ""; 22 | type = lib.types.str; 23 | description = "The complete URL where Open-WebUI is hosted."; 24 | example = "https://open-webui.example.com"; 25 | }; 26 | home = lib.mkOption { 27 | default = "/var/lib/open-webui"; 28 | type = lib.types.str; 29 | description = "Where to store Open-webUI's files"; 30 | }; 31 | ollama = { 32 | enable = lib.mkEnableOption "Enables Ollama."; 33 | home = lib.mkOption { 34 | default = "/var/lib/ollama"; 35 | type = lib.types.str; 36 | description = "Where to store Ollama's files"; 37 | }; 38 | }; 39 | }; 40 | }; 41 | 42 | config = lib.mkIf cfg.enable { 43 | services = { 44 | ollama = { 45 | enable = true; 46 | acceleration = 47 | with config.${namespace}.gpu; 48 | if amd.enable then 49 | "rocm" 50 | else if nvidia.enable then 51 | "cuda" 52 | else 53 | false; 54 | home = cfg.ollama.home; 55 | port = api.port; 56 | user = ollamaUser; 57 | }; 58 | 59 | open-webui = { 60 | enable = true; 61 | port = webui.port; 62 | environment = { 63 | ANONYMIZED_TELEMETRY = "False"; 64 | DO_NOT_TRACK = "True"; 65 | SCARF_NO_ANALYTICS = "True"; 66 | OLLAMA_BASE_URL = "http://127.0.0.1:${builtins.toString api.port}"; 67 | }; 68 | stateDir = cfg.home; 69 | }; 70 | 71 | nginx.virtualHosts."${cfg.url}" = { 72 | useACMEHost = lib.${namespace}.getDomainFromURI cfg.url; 73 | forceSSL = true; 74 | locations."/" = { 75 | proxyPass = "http://127.0.0.1:${builtins.toString webui.port}"; 76 | extraConfig = "proxy_ssl_server_name on;"; 77 | }; 78 | }; 79 | }; 80 | 81 | systemd.services = { 82 | ollama.unitConfig.RequiresMountsFor = cfg.ollama.home; 83 | open-webui = { 84 | serviceConfig = { 85 | User = ollamaUser; 86 | Group = ollamaGroup; 87 | }; 88 | 89 | unitConfig.RequiresMountsFor = cfg.home; 90 | wants = [ config.systemd.services.ollama.name ]; 91 | }; 92 | nginx.wants = [ config.systemd.services.open-webui.name ]; 93 | }; 94 | }; 95 | } 96 | -------------------------------------------------------------------------------- /modules/nixos/services/qbittorrent/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | namespace, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.${namespace}.services.qbittorrent; 10 | UID = 850; 11 | GID = 850; 12 | in 13 | { 14 | options = { 15 | ${namespace}.services.qbittorrent = { 16 | enable = lib.mkEnableOption "Enables qBittorrent."; 17 | home = lib.mkOption { 18 | default = "/var/lib/qbittorrent"; 19 | type = lib.types.str; 20 | description = "Where to store qBittorrent's files"; 21 | }; 22 | url = lib.mkOption { 23 | default = ""; 24 | type = lib.types.str; 25 | description = "The complete URL where qBittorrent is hosted."; 26 | example = "https://qbittorrent.example.com"; 27 | }; 28 | port = lib.mkOption { 29 | type = lib.types.int; 30 | default = 8080; 31 | description = "The port to host qBittorrent on."; 32 | }; 33 | user = lib.mkOption { 34 | type = lib.types.str; 35 | default = "qbittorrent"; 36 | description = "User account under which qBittorrent runs."; 37 | }; 38 | group = lib.mkOption { 39 | type = lib.types.str; 40 | default = "qbittorrent"; 41 | description = "Group under which qBittorrent runs."; 42 | }; 43 | }; 44 | }; 45 | 46 | config = lib.mkIf cfg.enable { 47 | services = { 48 | nginx.virtualHosts."${cfg.url}" = { 49 | useACMEHost = lib.${namespace}.getDomainFromURI cfg.url; 50 | forceSSL = true; 51 | locations."/" = { 52 | proxyPass = "http://127.0.0.1:${builtins.toString cfg.port}"; 53 | extraConfig = '' 54 | proxy_set_header X-Real-IP $remote_addr; 55 | proxy_set_header X-Forwarded-Host $host; 56 | proxy_set_header X-Forwarded-Server $host; 57 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 58 | ''; 59 | }; 60 | }; 61 | }; 62 | 63 | ${namespace}.services.virtualization.containers.enable = true; 64 | 65 | virtualisation.oci-containers.containers = { 66 | qbittorrent = { 67 | image = "lscr.io/linuxserver/qbittorrent:latest"; 68 | environment = { 69 | PUID = (builtins.toString UID); 70 | PGID = (builtins.toString GID); 71 | WEBUI_PORT = "${builtins.toString cfg.port}"; 72 | }; 73 | volumes = [ 74 | "${cfg.home}:/config" 75 | "${cfg.home}/qBittorrent/downloads:/downloads" 76 | ]; 77 | # Forward ports to gluetun if VPN is enabled. Otherwise, open ports directly 78 | extraOptions = lib.mkIf config.${namespace}.services.vpn.enable [ "--network=container:gluetun" ]; 79 | dependsOn = lib.mkIf config.${namespace}.services.vpn.enable [ "gluetun" ]; 80 | ports = lib.mkIf (!config.${namespace}.services.vpn.enable) [ 81 | "127.0.0.1:${builtins.toString cfg.port}:${builtins.toString cfg.port}" 82 | ]; 83 | }; 84 | 85 | # Allow Gluetun to update qBittorrent when the VPN port changes. 86 | # See https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/vpn-port-forwarding.md#qbittorrent-example 87 | gluetun.environment = lib.mkIf config.${namespace}.services.vpn.enable { 88 | VPN_PORT_FORWARDING_UP_COMMAND = "/bin/sh -c 'wget -O- --retry-connrefused --post-data \"json={\"listen_port\":{{PORTS}}}\" http://127.0.0.1:${builtins.toString cfg.port}/api/v2/app/setPreferences 2>&1'"; 89 | }; 90 | }; 91 | 92 | users = { 93 | users.${cfg.user} = { 94 | description = "qBittorrent user"; 95 | isNormalUser = false; 96 | group = cfg.group; 97 | uid = UID; 98 | }; 99 | groups.${cfg.group}.gid = GID; 100 | }; 101 | 102 | systemd.services = { 103 | qbittorrent.unitConfig.RequiresMountsFor = cfg.home; 104 | nginx.wants = [ config.systemd.services.podman-qbittorrent.name ]; 105 | }; 106 | }; 107 | } 108 | -------------------------------------------------------------------------------- /modules/nixos/services/ssh/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | namespace, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.${namespace}.services.ssh; 10 | in 11 | { 12 | options = { 13 | ${namespace}.services.ssh = { 14 | enable = lib.mkEnableOption "Enables SSH server."; 15 | ports = lib.mkOption { 16 | default = [ 22 ]; 17 | type = lib.types.listOf lib.types.int; 18 | description = "Ports for SSH to listen on."; 19 | }; 20 | }; 21 | }; 22 | 23 | config = lib.mkIf cfg.enable { 24 | services.openssh = { 25 | enable = true; 26 | ports = cfg.ports; 27 | 28 | settings = { 29 | # require public key authentication and disable root logins 30 | PasswordAuthentication = false; 31 | KbdInteractiveAuthentication = false; 32 | PubkeyAuthentication = true; 33 | PermitRootLogin = "no"; 34 | }; 35 | }; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /modules/nixos/services/syncthing/default.nix: -------------------------------------------------------------------------------- 1 | # See https://wiki.nixos.org/wiki/Syncthing 2 | { 3 | config, 4 | lib, 5 | namespace, 6 | ... 7 | }: 8 | 9 | let 10 | cfg = config.${namespace}.services.syncthing; 11 | in 12 | { 13 | options = { 14 | ${namespace}.services.syncthing = { 15 | enable = lib.mkEnableOption "Enables Syncthing."; 16 | home = lib.mkOption { 17 | default = "/var/lib/syncthing"; 18 | type = lib.types.str; 19 | description = "Where to store Syncthing's configuration files"; 20 | }; 21 | tray.enable = lib.mkEnableOption "Enables the Syncthing Tray applet."; 22 | user = lib.mkOption { 23 | type = lib.types.str; 24 | default = "syncthing"; 25 | description = "User account under which Syncthing runs."; 26 | }; 27 | web = { 28 | enable = lib.mkEnableOption "Enables the Syncthing web UI."; 29 | port = lib.mkOption { 30 | type = lib.types.int; 31 | default = 8384; 32 | description = "The port to host Syncthing web on."; 33 | }; 34 | public = lib.mkEnableOption "Whether to expose the Syncthing web UI to the network."; 35 | }; 36 | }; 37 | }; 38 | 39 | config = lib.mkIf cfg.enable { 40 | # If the web UI is public, open the port in the firewall 41 | networking.firewall.allowedTCPPorts = with cfg.web; lib.mkIf (enable && public) [ port ]; 42 | 43 | services = { 44 | flatpak.packages = lib.mkIf (config.${namespace}.ui.flatpak.enable && cfg.tray.enable) [ 45 | "io.github.martchus.syncthingtray" 46 | ]; 47 | 48 | syncthing = { 49 | enable = true; 50 | user = cfg.user; 51 | group = config.users.users.${cfg.user}.group; 52 | configDir = cfg.home; 53 | guiAddress = 54 | let 55 | listenAddress = with cfg.web; (if (enable && public) then "0.0.0.0" else "127.0.0.1"); 56 | in 57 | "${listenAddress}:${builtins.toString cfg.web.port}"; 58 | }; 59 | }; 60 | 61 | systemd.services.syncthing = { 62 | environment.STNODEFAULTFOLDER = "true"; # Don't create default ~/Sync folder 63 | unitConfig.RequiresMountsFor = cfg.home; 64 | }; 65 | }; 66 | } 67 | -------------------------------------------------------------------------------- /modules/nixos/services/tor/default.nix: -------------------------------------------------------------------------------- 1 | # https://wiki.nixos.org/wiki/Tor 2 | { 3 | config, 4 | lib, 5 | namespace, 6 | ... 7 | }: 8 | 9 | let 10 | cfg = config.${namespace}.services.tor; 11 | in 12 | { 13 | options = { 14 | ${namespace}.services.tor = { 15 | enable = lib.mkEnableOption "Enables the TOR router."; 16 | browser.enable = lib.mkEnableOption "Installs the TOR browser."; 17 | relay = { 18 | enable = lib.mkEnableOption "Configures the system as a TOR relay."; 19 | role = lib.mkOption { 20 | description = "Whether to treat this as a regular relay or a bridge."; 21 | default = "relay"; 22 | type = lib.types.enum [ 23 | "relay" 24 | "bridge" 25 | ]; 26 | }; 27 | ORPort = lib.mkOption { 28 | type = lib.types.str; 29 | description = "The port (or IP:port) to bind the Tor relay to."; 30 | }; 31 | }; 32 | # For details, see https://wiki.nixos.org/wiki/Tor#Advanced 33 | settings = lib.mkOption { 34 | description = "Settings to apply to the relay."; 35 | type = lib.types.attrs; 36 | default = { 37 | # Reject all exit traffic 38 | ExitPolicy = [ "reject *:*" ]; 39 | 40 | # Performance and security settings 41 | CookieAuthentication = true; 42 | AvoidDiskWrites = 1; 43 | HardwareAccel = 1; 44 | SafeLogging = 1; 45 | }; 46 | }; 47 | snowflake-proxy = { 48 | enable = lib.mkEnableOption "Enables Snowflake Proxy. See https://snowflake.torproject.org."; 49 | capacity = lib.mkOption { 50 | type = lib.types.int; 51 | default = 10; 52 | description = "How many concurrent clients to support."; 53 | }; 54 | }; 55 | }; 56 | }; 57 | 58 | config = lib.mkMerge [ 59 | (lib.mkIf cfg.enable { 60 | services.tor = { 61 | enable = true; 62 | settings = cfg.settings; 63 | }; 64 | 65 | services.snowflake-proxy = lib.mkIf cfg.snowflake-proxy.enable { 66 | enable = true; 67 | capacity = cfg.snowflake-proxy.capacity; 68 | }; 69 | }) 70 | (lib.mkIf cfg.browser.enable { 71 | services.tor = { 72 | client.enable = true; 73 | 74 | # Enable Torsocks for transparent proxying of applications through Tor 75 | torsocks.enable = true; 76 | }; 77 | 78 | ${namespace}.ui.flatpak.packages = [ 79 | "org.torproject.torbrowser-launcher" 80 | ]; 81 | }) 82 | (lib.mkIf cfg.relay.enable { 83 | services.tor.relay = { 84 | enable = true; 85 | role = cfg.relay.role; 86 | }; 87 | }) 88 | ]; 89 | } 90 | -------------------------------------------------------------------------------- /modules/nixos/services/virtualization/default.nix: -------------------------------------------------------------------------------- 1 | # Enables virtualization via QEMU/KVM 2 | { 3 | config, 4 | lib, 5 | pkgs, 6 | namespace, 7 | ... 8 | }: 9 | 10 | let 11 | cfg = config.${namespace}.services.virtualization; 12 | in 13 | { 14 | options = { 15 | ${namespace}.services.virtualization = { 16 | enable = lib.mkEnableOption "Enables virtualization tools on this host."; 17 | containers.enable = lib.mkEnableOption "Enables containers via Podman on this host."; 18 | host = { 19 | enable = lib.mkEnableOption "Enables virtual machine hosting."; 20 | vmBuilds = { 21 | enable = lib.mkEnableOption "Enables builds via `nixos-rebuild build-vm` on this host."; 22 | cores = lib.mkOption { 23 | type = lib.types.int; 24 | description = "How many cores to assign to `nixos-rebuild build-vm` builds. Defaults to 2."; 25 | default = 2; 26 | }; 27 | ram = lib.mkOption { 28 | type = lib.types.int; 29 | description = "How much RAM (in MB) to assign to `nixos-rebuild build-vm` builds. Defaults to 2GB."; 30 | default = 2048; 31 | }; 32 | }; 33 | }; 34 | 35 | }; 36 | }; 37 | 38 | config = lib.mkMerge [ 39 | { programs.virt-manager.enable = cfg.enable; } 40 | (lib.mkIf cfg.containers.enable { 41 | virtualisation.podman = { 42 | enable = true; 43 | autoPrune.enable = true; 44 | }; 45 | }) 46 | (lib.mkIf (cfg.host.enable || cfg.host.vmBuilds.enable) { 47 | virtualisation = { 48 | libvirtd = { 49 | enable = true; 50 | qemu = { 51 | package = pkgs.qemu_kvm; 52 | swtpm.enable = true; 53 | ovmf = { 54 | enable = true; 55 | packages = [ pkgs.OVMFFull.fd ]; 56 | }; 57 | }; 58 | }; 59 | spiceUSBRedirection.enable = true; 60 | }; 61 | 62 | environment.systemPackages = with pkgs; [ 63 | spice 64 | spice-gtk 65 | spice-protocol 66 | ]; 67 | 68 | # Allow the default bridge interface to access the network 69 | networking.firewall.trustedInterfaces = [ "virbr0" ]; 70 | }) 71 | (lib.mkIf cfg.host.vmBuilds.enable { 72 | virtualisation.vmVariant.virtualisation = { 73 | memorySize = cfg.host.vmBuilds.ram; 74 | cores = cfg.host.vmBuilds.cores; 75 | }; 76 | }) 77 | ]; 78 | } 79 | -------------------------------------------------------------------------------- /modules/nixos/services/vpn/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | namespace, 5 | ... 6 | }: 7 | 8 | let 9 | cfg = config.${namespace}.services.vpn; 10 | in 11 | { 12 | options = { 13 | ${namespace}.services.vpn = { 14 | enable = lib.mkEnableOption "Creates a VPN connection on /dev/net/tun (via PIA)."; 15 | auth = { 16 | password = lib.mkOption { 17 | default = ""; 18 | type = lib.types.str; 19 | description = "Your PIA username."; 20 | example = "MySuperSecurePassword123"; 21 | }; 22 | user = lib.mkOption { 23 | default = ""; 24 | type = lib.types.str; 25 | description = "The username for PIA."; 26 | }; 27 | }; 28 | countries = lib.mkOption { 29 | type = lib.types.listOf lib.types.str; 30 | description = "List of countries to base the VPN out of."; 31 | default = [ "Netherlands" ]; 32 | }; 33 | port = lib.mkOption { 34 | type = lib.types.int; 35 | default = 0; 36 | description = "Any port to expose on the container."; 37 | }; 38 | portForwarding.enable = lib.mkEnableOption "Enables port forwarding."; 39 | }; 40 | }; 41 | 42 | config = lib.mkIf cfg.enable { 43 | ${namespace}.services.virtualization.containers.enable = true; 44 | virtualisation.oci-containers.containers.gluetun = { 45 | image = "qmcgaw/gluetun:v3"; 46 | extraOptions = [ 47 | "--cap-add=NET_ADMIN" 48 | "--device=/dev/net/tun" 49 | ]; 50 | environment = { 51 | VPN_SERVICE_PROVIDER = "private internet access"; 52 | OPENVPN_USER = cfg.auth.user; 53 | OPENVPN_PASSWORD = cfg.auth.password; 54 | SERVER_REGIONS = (lib.strings.concatStringsSep "," cfg.countries); 55 | TZ = "America/New_York"; 56 | VPN_PORT_FORWARDING = lib.mkIf cfg.portForwarding.enable "on"; 57 | }; 58 | ports = lib.mkIf (cfg.port > 0) [ 59 | "127.0.0.1:${builtins.toString cfg.port}:${builtins.toString cfg.port}" 60 | ]; 61 | }; 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /modules/nixos/system/bluetooth/default.nix: -------------------------------------------------------------------------------- 1 | # Configures bluetooth. 2 | { 3 | lib, 4 | config, 5 | pkgs, 6 | namespace, 7 | ... 8 | }: 9 | 10 | let 11 | cfg = config.${namespace}.bluetooth; 12 | in 13 | { 14 | 15 | options = { 16 | ${namespace}.bluetooth = { 17 | enable = lib.mkEnableOption "Enables bluetooth."; 18 | experimental.enable = lib.mkEnableOption "Enables experimental features, like device power reporting."; 19 | }; 20 | }; 21 | 22 | config = lib.mkIf cfg.enable { 23 | # Set up Bluetooth 24 | hardware.bluetooth = { 25 | enable = true; 26 | powerOnBoot = true; 27 | settings = lib.mkIf cfg.experimental.enable { 28 | General = { 29 | Enable = "Source,Sink,Media,Socket"; 30 | Experimental = true; 31 | KernelExperimental = true; 32 | 33 | # Additional options based on: 34 | # https://www.reddit.com/r/NixOS/comments/1hdsfz0/what_do_i_have_to_do_to_make_my_xbox_controller/ 35 | JustWorksRepairing = "always"; 36 | FastConnectable = true; 37 | }; 38 | }; 39 | }; 40 | 41 | # Add Bluetooth LE audio support 42 | environment.systemPackages = with pkgs; [ liblc3 ]; 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /modules/nixos/system/bootloader/default.nix: -------------------------------------------------------------------------------- 1 | # Configuration options specific to bootloader management. 2 | # SecureBoot is handled via Lanzaboote. See https://github.com/nix-community/lanzaboote 3 | { 4 | config, 5 | lib, 6 | pkgs, 7 | namespace, 8 | ... 9 | }: 10 | 11 | # Bootloader 12 | let 13 | cfg = config.${namespace}.bootloader; 14 | in 15 | { 16 | 17 | options = { 18 | ${namespace}.bootloader = { 19 | enable = lib.mkOption { 20 | description = "Automatically configures the bootloader. Set to false to configure manually."; 21 | type = lib.types.bool; 22 | default = true; 23 | }; 24 | 25 | secureboot.enable = lib.mkEnableOption "Enables Secureboot support (please read the README before enabling!)."; 26 | tpm2.enable = lib.mkEnableOption "Enables TPM2 support."; 27 | }; 28 | }; 29 | 30 | config = lib.mkIf cfg.enable ( 31 | lib.mkMerge [ 32 | (lib.mkIf cfg.secureboot.enable { 33 | boot = { 34 | # Enable Secure Boot 35 | bootspec.enable = true; 36 | 37 | # Use Lanzaboote in place of systemd-boot. 38 | loader = { 39 | systemd-boot.enable = false; 40 | efi.canTouchEfiVariables = true; 41 | }; 42 | lanzaboote = { 43 | enable = true; 44 | pkiBundle = "/etc/secureboot"; 45 | }; 46 | }; 47 | }) 48 | 49 | # Set up TPM if enabled. See https://wiki.nixos.org/wiki/TPM 50 | (lib.mkIf (cfg.tpm2.enable) { 51 | boot.initrd = { 52 | # Enable modules and support for TPM auto-unlocking 53 | systemd.enable = true; 54 | kernelModules = [ "tpm_crb" ]; 55 | }; 56 | # After installing and rebooting, set it up via https://wiki.archlinux.org/title/Systemd-cryptenroll#Trusted_Platform_Module 57 | environment.systemPackages = with pkgs; [ tpm2-tss ]; 58 | security.tpm2 = { 59 | enable = true; 60 | pkcs11.enable = true; 61 | tctiEnvironment.enable = true; 62 | }; 63 | }) 64 | 65 | # Use the default systemd-boot bootloader. 66 | (lib.mkIf (!cfg.secureboot.enable) { 67 | boot.loader = { 68 | systemd-boot.enable = true; 69 | efi.canTouchEfiVariables = true; 70 | }; 71 | }) 72 | ] 73 | ); 74 | } 75 | -------------------------------------------------------------------------------- /modules/nixos/system/default.nix: -------------------------------------------------------------------------------- 1 | # System options 2 | { 3 | pkgs, 4 | config, 5 | lib, 6 | namespace, 7 | ... 8 | }: 9 | let 10 | cfg = config.${namespace}; 11 | 12 | gitWithLibsecret = pkgs.git.override { withLibsecret = true; }; 13 | in 14 | { 15 | options = { 16 | ${namespace} = { 17 | packages = lib.mkOption { 18 | description = "Additional system packages to install. This is just a wrapper for environment.systemPackages."; 19 | type = lib.types.listOf lib.types.package; 20 | default = [ ]; 21 | example = lib.literalExpression "[ pkgs.firefox pkgs.thunderbird ]"; 22 | }; 23 | 24 | corePackages = lib.mkOption { 25 | description = "Minimum set of packages to install."; 26 | type = lib.types.listOf lib.types.package; 27 | default = with pkgs; [ 28 | # Courtesy of https://discourse.nixos.org/t/how-to-use-other-packages-binary-in-systemd-service-configuration/14363 29 | bash 30 | coreutils 31 | dconf 32 | direnv 33 | gitWithLibsecret 34 | gnutar 35 | gzip 36 | home-manager 37 | openssh 38 | sudo 39 | treefmt2 40 | xz.bin 41 | # Packages required for decrypting config files 42 | transcrypt 43 | openssl 44 | xxd 45 | ]; 46 | }; 47 | }; 48 | }; 49 | config = { 50 | # Install base packages 51 | environment.systemPackages = cfg.corePackages ++ cfg.packages; 52 | 53 | services = { 54 | # Automatically set the timezone based on location 55 | automatic-timezoned.enable = true; 56 | geoclue2.enableDemoAgent = lib.mkForce true; 57 | 58 | # Enable fwupd (firmware updater) 59 | fwupd.enable = true; 60 | 61 | # Allow systemd user services to keep running after the user has logged out 62 | logind.killUserProcesses = false; 63 | 64 | # Enable disk monitoring 65 | smartd = { 66 | enable = true; 67 | autodetect = true; 68 | notifications = { 69 | wall.enable = true; 70 | mail = lib.mkIf config.${namespace}.services.msmtp.enable { 71 | enable = true; 72 | mailer = "/run/wrappers/bin/sendmail"; 73 | sender = "${config.networking.hostName}@${config.${namespace}.secrets.networking.domains.primary}"; 74 | recipient = config.${namespace}.secrets.users.aires.email; 75 | }; 76 | }; 77 | }; 78 | }; 79 | 80 | # Enable visual updates 81 | system.activationScripts.diff = { 82 | supportsDryActivation = true; 83 | text = '' 84 | ${pkgs.nvd}/bin/nvd --nix-bin-dir=${pkgs.nix}/bin diff /run/current-system "$systemConfig" 85 | ''; 86 | }; 87 | 88 | # Limit logout stop timer duration to 30 seconds 89 | systemd.user.extraConfig = '' 90 | DefaultTimeoutStopSec=30s 91 | ''; 92 | 93 | # Select internationalisation properties. 94 | i18n = { 95 | defaultLocale = "en_US.UTF-8"; 96 | 97 | extraLocaleSettings = { 98 | LC_ADDRESS = "en_US.UTF-8"; 99 | LC_IDENTIFICATION = "en_US.UTF-8"; 100 | LC_MEASUREMENT = "en_US.UTF-8"; 101 | LC_MONETARY = "en_US.UTF-8"; 102 | LC_NAME = "en_US.UTF-8"; 103 | LC_NUMERIC = "en_US.UTF-8"; 104 | LC_PAPER = "en_US.UTF-8"; 105 | LC_TELEPHONE = "en_US.UTF-8"; 106 | LC_TIME = "en_US.UTF-8"; 107 | }; 108 | }; 109 | }; 110 | } 111 | -------------------------------------------------------------------------------- /modules/nixos/system/filesystem/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | config, 4 | namespace, 5 | ... 6 | }: 7 | let 8 | cfg = config.${namespace}.filesystem; 9 | 10 | # LUKS partition will decrypt to /dev/mapper/nixos-root 11 | decryptPart = "nixos-root"; 12 | decryptPath = "/dev/mapper/${decryptPart}"; 13 | 14 | # Default mount options for your main partitions 15 | primaryPartOpts = [ 16 | "compress=zstd" 17 | (lib.mkIf cfg.discard "discard=async").content 18 | ]; 19 | in 20 | { 21 | options = { 22 | ${namespace}.filesystem = { 23 | enable = lib.mkEnableOption "Enables standard BTRFS subvolumes and parameters."; 24 | partitions = { 25 | boot = lib.mkOption { 26 | type = lib.types.str; 27 | description = "The ID of your boot partition. Use /dev/disk/by-uuid for best results."; 28 | default = ""; 29 | }; 30 | luks = lib.mkOption { 31 | type = lib.types.str; 32 | description = "The ID of your LUKS partition. Use /dev/disk/by-uuid for best results."; 33 | default = ""; 34 | }; 35 | }; 36 | discard = lib.mkOption { 37 | type = lib.types.bool; 38 | description = "Whether to enable TRIM for SSD and NVMe drives. Defaults to true."; 39 | default = true; 40 | }; 41 | swapFile = { 42 | enable = lib.mkEnableOption "Enables the creation of a swap file."; 43 | size = lib.mkOption { 44 | type = lib.types.int; 45 | description = "The size of the swap file to create in MB (defaults to 8192, or ~8 gigabytes)."; 46 | default = 8192; 47 | }; 48 | }; 49 | }; 50 | }; 51 | 52 | config = lib.mkIf cfg.enable { 53 | 54 | # Check for blank parameters 55 | assertions = [ 56 | { 57 | assertion = cfg.partitions.luks != ""; 58 | message = "Please specify a LUKS partition to use as the root filesystem."; 59 | } 60 | { 61 | assertion = cfg.partitions.boot != ""; 62 | message = "Please specify your boot partition."; 63 | } 64 | ]; 65 | boot = { 66 | supportedFilesystems = [ "btrfs" ]; 67 | initrd = { 68 | availableKernelModules = [ "btrfs" ]; 69 | luks.devices.${decryptPart} = { 70 | device = cfg.partitions.luks; 71 | # Enable TPM auto-unlocking if configured 72 | crypttabExtraOpts = lib.mkIf config.${namespace}.bootloader.tpm2.enable [ "tpm2-device=auto" ]; 73 | }; 74 | }; 75 | }; 76 | fileSystems = { 77 | "/" = { 78 | device = decryptPath; 79 | fsType = "btrfs"; 80 | options = [ "subvol=@" ] ++ primaryPartOpts; 81 | }; 82 | "/boot" = { 83 | device = cfg.partitions.boot; 84 | fsType = "vfat"; 85 | }; 86 | "/home" = { 87 | device = decryptPath; 88 | fsType = "btrfs"; 89 | options = [ "subvol=@home" ] ++ primaryPartOpts; 90 | }; 91 | "/var/log" = { 92 | device = decryptPath; 93 | fsType = "btrfs"; 94 | options = [ "subvol=@log" ] ++ primaryPartOpts; 95 | }; 96 | "/nix" = { 97 | device = decryptPath; 98 | fsType = "btrfs"; 99 | options = [ 100 | "subvol=@nix" 101 | "noatime" 102 | ] ++ primaryPartOpts; 103 | }; 104 | "/swap" = lib.mkIf cfg.swapFile.enable { 105 | device = decryptPath; 106 | fsType = "btrfs"; 107 | options = [ 108 | "subvol=@swap" 109 | "noatime" 110 | (lib.mkIf cfg.discard "discard=async").content 111 | ]; 112 | }; 113 | }; 114 | 115 | swapDevices = lib.mkIf cfg.swapFile.enable [ 116 | { 117 | device = "/swap/swapfile"; 118 | size = cfg.swapFile.size; 119 | } 120 | ]; 121 | }; 122 | } 123 | -------------------------------------------------------------------------------- /modules/nixos/system/gpu/default.nix: -------------------------------------------------------------------------------- 1 | # Enables AMD GPU support. 2 | { 3 | pkgs, 4 | config, 5 | lib, 6 | namespace, 7 | ... 8 | }: 9 | let 10 | cfg = config.${namespace}.gpu; 11 | in 12 | { 13 | options = { 14 | ${namespace}.gpu = { 15 | amd.enable = lib.mkEnableOption "Enables AMD GPU support."; 16 | intel.enable = lib.mkEnableOption "Enables Intel GPU support."; 17 | nvidia = { 18 | enable = lib.mkEnableOption "Enables Nvidia GPU support."; 19 | hybrid = { 20 | enable = lib.mkEnableOption "Enables hybrid GPU support."; 21 | sync = lib.mkEnableOption "Enables sync mode for faster performance at the cost of higher battery usage."; 22 | busIDs = { 23 | nvidia = lib.mkOption { 24 | description = "The bus ID for your Nvidia GPU."; 25 | type = lib.types.str; 26 | example = "PCI:0:2:0"; 27 | default = ""; 28 | }; 29 | intel = lib.mkOption { 30 | description = "The bus ID for your integrated Intel GPU. If you don't have an Intel GPU, you can leave this blank."; 31 | type = lib.types.str; 32 | example = "PCI:14:0:0"; 33 | default = ""; 34 | }; 35 | amd = lib.mkOption { 36 | description = "The bus ID for your integrated AMD GPU. If you don't have an AMD GPU, you can leave this blank."; 37 | type = lib.types.str; 38 | example = "PCI:54:0:0"; 39 | default = ""; 40 | }; 41 | }; 42 | }; 43 | }; 44 | }; 45 | }; 46 | 47 | config = lib.mkMerge [ 48 | (lib.mkIf cfg.amd.enable { 49 | boot.initrd.kernelModules = [ "amdgpu" ]; 50 | services.xserver.videoDrivers = [ "amdgpu" ]; 51 | 52 | hardware.graphics = { 53 | enable = true; 54 | # 32-bit application compatibility 55 | enable32Bit = true; 56 | }; 57 | }) 58 | 59 | (lib.mkIf cfg.intel.enable { 60 | services.xserver.videoDrivers = [ "modesetting" ]; 61 | 62 | hardware.graphics = { 63 | enable = true; 64 | extraPackages = with pkgs; [ 65 | intel-media-driver 66 | vpl-gpu-rt 67 | ]; 68 | extraPackages32 = with pkgs.driversi686Linux; [ 69 | intel-media-driver 70 | vpl-gpu-rt 71 | ]; 72 | }; 73 | }) 74 | (lib.mkIf cfg.nvidia.enable { 75 | assertions = [ 76 | { 77 | assertion = (cfg.nvidia.hybrid.busIDs.nvidia != ""); 78 | message = "You need to define a bus ID for your Nvidia GPU. To learn how to find the bus ID, see https://wiki.nixos.org/wiki/Nvidia#Configuring_Optimus_PRIME:_Bus_ID_Values_.28Mandatory.29."; 79 | } 80 | { 81 | assertion = (cfg.nvidia.hybrid.busIDs.intel != "" || cfg.nvidia.hybrid.busIDs.amd != ""); 82 | message = "You need to define a bus ID for your non-Nvidia GPU. To learn how to find your bus ID, see https://wiki.nixos.org/wiki/Nvidia#Configuring_Optimus_PRIME:_Bus_ID_Values_.28Mandatory.29."; 83 | } 84 | ]; 85 | 86 | services.xserver.videoDrivers = lib.mkDefault [ "nvidia" ]; 87 | hardware = { 88 | graphics.extraPackages = with pkgs; [ vaapiVdpau ]; 89 | nvidia = { 90 | modesetting.enable = true; 91 | nvidiaSettings = config.${namespace}.ui.desktops.enable; 92 | package = config.boot.kernelPackages.nvidiaPackages.stable; 93 | prime = lib.mkIf cfg.nvidia.hybrid.enable { 94 | 95 | offload = lib.mkIf (!cfg.nvidia.hybrid.sync) { 96 | enable = true; 97 | enableOffloadCmd = true; # Provides `nvidia-offload` command. 98 | }; 99 | 100 | sync.enable = cfg.nvidia.hybrid.sync; 101 | 102 | nvidiaBusId = cfg.nvidia.hybrid.busIDs.nvidia; 103 | intelBusId = cfg.nvidia.hybrid.busIDs.intel; 104 | amdgpuBusId = cfg.nvidia.hybrid.busIDs.amd; 105 | }; 106 | }; 107 | }; 108 | }) 109 | ]; 110 | } 111 | -------------------------------------------------------------------------------- /modules/nixos/system/networking/default.nix: -------------------------------------------------------------------------------- 1 | # Configure basic networking options. 2 | { lib, ... }: 3 | { 4 | networking = { 5 | # Default to DHCP. Set to false to use static IPs. 6 | useDHCP = lib.mkDefault true; 7 | 8 | # Enable networking via NetworkManager 9 | networkmanager.enable = true; 10 | 11 | # Enable firewall 12 | nftables.enable = true; 13 | firewall.enable = true; 14 | }; 15 | 16 | # Enable fail2ban by default 17 | # https://github.com/fail2ban/fail2ban 18 | services.fail2ban.enable = true; 19 | } 20 | -------------------------------------------------------------------------------- /modules/nixos/system/nix/default.nix: -------------------------------------------------------------------------------- 1 | # Core Nix configuration 2 | { 3 | config, 4 | inputs, 5 | lib, 6 | pkgs, 7 | namespace, 8 | system, 9 | ... 10 | }: 11 | 12 | let 13 | cfg = config.${namespace}.nix; 14 | 15 | nixos-operations-script = pkgs.writeShellScriptBin "nixos-operations-script" ( 16 | builtins.readFile (lib.snowfall.fs.get-file "bin/nixos-operations-script.sh") 17 | ); 18 | in 19 | { 20 | options.${namespace}.nix = { 21 | retention = lib.mkOption { 22 | description = "How long to retain NixOS generations. Defaults to two weeks."; 23 | type = lib.types.str; 24 | default = "14d"; 25 | }; 26 | nixos-operations-script.enable = lib.mkEnableOption "Installs the nos (nixos-operations-script) helper script."; 27 | }; 28 | config = lib.mkMerge [ 29 | { 30 | nix = { 31 | # Use Lix in place of Nix 32 | package = inputs.lix.packages.${system}.default; 33 | 34 | # Ensure we can still build when secondary caches are unavailable 35 | extraOptions = '' 36 | fallback = true 37 | ''; 38 | 39 | settings = { 40 | # Enable Flakes 41 | experimental-features = [ 42 | "nix-command" 43 | "flakes" 44 | ]; 45 | 46 | # Set up Hevana and Lix as secondary binary caches 47 | substituters = [ 48 | "https://cache.nixos.org/" 49 | "https://${config.${namespace}.secrets.services.binary-cache.url}" 50 | "https://cache.lix.systems" 51 | ]; 52 | trusted-public-keys = [ 53 | config.${namespace}.secrets.services.binary-cache.pubcert 54 | "cache.lix.systems:aBnZUw8zA7H35Cz2RyKFVs3H4PlGTLawyY5KRbvJR8o=" 55 | ]; 56 | 57 | # Authentication for Hevana's binary cache 58 | netrc-file = 59 | with config.${namespace}.secrets.services.binary-cache; 60 | pkgs.writeText "netrc" '' 61 | machine ${url} login ${auth.username} password ${auth.password} 62 | ''; 63 | 64 | # Only allow these users to use Nix 65 | allowed-users = with config.users.users; [ 66 | root.name 67 | (lib.mkIf config.${namespace}.users.aires.enable aires.name) 68 | (lib.mkIf config.${namespace}.users.gremlin.enable gremlin.name) 69 | ]; 70 | 71 | # Avoid signature verification messages when doing remote builds 72 | trusted-users = with config.users.users; [ 73 | root.name 74 | (lib.mkIf config.${namespace}.users.aires.enable aires.name) 75 | ]; 76 | }; 77 | 78 | # Optimize the Nix store on each build 79 | settings.auto-optimise-store = true; 80 | # Enable garbage collection 81 | gc = { 82 | automatic = true; 83 | dates = "weekly"; 84 | options = "--delete-older-than ${cfg.retention}"; 85 | persistent = true; 86 | randomizedDelaySec = "1hour"; 87 | }; 88 | 89 | # Configure NixOS to use the same software channel as Flakes 90 | registry.nixpkgs.flake = inputs.nixpkgs; 91 | nixPath = [ "nixpkgs=${inputs.nixpkgs}" ]; 92 | }; 93 | 94 | # Support for standard, dynamically-linked executables 95 | programs.nix-ld.enable = true; 96 | } 97 | (lib.mkIf cfg.nixos-operations-script.enable { 98 | # Enable and configure NOS 99 | ${namespace}.packages = [ nixos-operations-script ]; 100 | environment.variables."FLAKE_DIR" = config.${namespace}.secrets.nixConfigFolder; 101 | }) 102 | ]; 103 | } 104 | -------------------------------------------------------------------------------- /modules/nixos/system/power/default.nix: -------------------------------------------------------------------------------- 1 | # Power management options 2 | { 3 | pkgs, 4 | config, 5 | lib, 6 | namespace, 7 | ... 8 | }: 9 | let 10 | cfg = config.${namespace}; 11 | 12 | ppd-patched = pkgs.power-profiles-daemon.overrideAttrs ( 13 | _finalAttrs: _prevAttrs: { 14 | patches = [ ./power-profiles-daemon.patch ]; 15 | mesonFlags = [ 16 | "-Dsystemdsystemunitdir=${placeholder "out"}/lib/systemd/system" 17 | "-Dgtk_doc=true" 18 | "-Dpylint=disabled" 19 | "-Dzshcomp=${placeholder "out"}/share/zsh/site-functions" 20 | "-Dtests=false" # Disable built-in tests, since they'll fail due to the patch 21 | ]; 22 | } 23 | ); 24 | in 25 | { 26 | options.${namespace}.powerManagement.enable = 27 | lib.mkEnableOption "Enables power management, e.g. for laptops."; 28 | 29 | # Configure power management via power-profiles-daemon 30 | # https://gitlab.freedesktop.org/upower/power-profiles-daemon 31 | config.services.power-profiles-daemon = lib.mkIf cfg.powerManagement.enable { 32 | enable = true; 33 | package = ppd-patched; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /modules/nixos/system/power/power-profiles-daemon.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/ppd-driver-amd-pstate.c b/src/ppd-driver-amd-pstate.c 2 | index 55635b0..0ed87ab 100644 3 | --- a/src/ppd-driver-amd-pstate.c 4 | +++ b/src/ppd-driver-amd-pstate.c 5 | @@ -175,7 +175,7 @@ profile_to_epp_pref (PpdProfile profile, gboolean battery) 6 | case PPD_PROFILE_POWER_SAVER: 7 | return "power"; 8 | case PPD_PROFILE_BALANCED: 9 | - return battery ? "balance_power" : "balance_performance"; 10 | + return "balance_performance"; 11 | case PPD_PROFILE_PERFORMANCE: 12 | return "performance"; 13 | } 14 | diff --git a/src/ppd-driver-intel-pstate.c b/src/ppd-driver-intel-pstate.c 15 | index 90a5d17..4eaca2e 100644 16 | --- a/src/ppd-driver-intel-pstate.c 17 | +++ b/src/ppd-driver-intel-pstate.c 18 | @@ -300,7 +300,7 @@ profile_to_epp_pref (PpdProfile profile, gboolean battery) 19 | case PPD_PROFILE_POWER_SAVER: 20 | return "power"; 21 | case PPD_PROFILE_BALANCED: 22 | - return battery ? "balance_power" : "balance_performance"; 23 | + return "balance_performance"; 24 | case PPD_PROFILE_PERFORMANCE: 25 | return "performance"; 26 | } -------------------------------------------------------------------------------- /modules/nixos/system/raid/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | config, 4 | namespace, 5 | ... 6 | }: 7 | let 8 | cfg = config.${namespace}.raid; 9 | in 10 | { 11 | 12 | options = { 13 | ${namespace}.raid = { 14 | enable = lib.mkEnableOption "Enables RAID support."; 15 | mailAddr = lib.mkOption { 16 | default = ""; 17 | type = lib.types.str; 18 | description = "Address to email in case of issues."; 19 | example = "admin@example.com"; 20 | }; 21 | 22 | storage = { 23 | enable = lib.mkEnableOption "Enables support for the storage array."; 24 | keyFile = lib.mkOption { 25 | default = ""; 26 | type = lib.types.str; 27 | description = "Path to the key file to use to auto-unlock the array."; 28 | example = "/home/user/storage.key"; 29 | }; 30 | }; 31 | }; 32 | }; 33 | 34 | config = lib.mkMerge [ 35 | (lib.mkIf cfg.enable { boot.swraid.enable = true; }) 36 | (lib.mkIf cfg.storage.enable { 37 | ${namespace}.raid.enable = true; 38 | boot.swraid.mdadmConf = '' 39 | ARRAY /dev/md/Sapana metadata=1.2 UUID=51076daf:efdb34dd:bce48342:3b549fcb 40 | MAILADDR ${cfg.mailAddr} 41 | ''; 42 | 43 | # Auto-unlock RAID array with a key file 44 | environment.etc."crypttab" = lib.mkIf (cfg.storage.keyFile != "") { 45 | text = "storage /dev/md/Sapana ${cfg.storage.keyFile} nofail,keyfile-timeout=5s"; 46 | }; 47 | fileSystems."/storage" = { 48 | device = "/dev/mapper/storage"; 49 | options = [ 50 | "nofail" # Keep booting even if the array fails to unlock 51 | "lazytime" # Reduce atime writes: https://wiki.archlinux.org/title/Fstab#atime_options 52 | "commit=60" # Increase commit interval to 60 seconds to reduce writes: https://wiki.archlinux.org/title/Ext4#Increasing_commit_interval 53 | "data=journal" # Commit to the journal before writing to the filesystem. 54 | "journal_async_commit" 55 | ]; 56 | }; 57 | 58 | # Optimize RAID performance via udev rules 59 | # See https://serverfault.com/questions/579489/linux-what-is-stripe-cache-size-and-what-does-it-do 60 | services.udev.extraRules = '' 61 | SUBSYSTEM=="block", KERNEL=="md*", ACTION=="change", TEST=="md/stripe_cache_size", ATTR{md/stripe_cache_size}="8192" 62 | SUBSYSTEM=="block", KERNEL=="md*", ACTION=="change", TEST=="queue/read_ahead_kb", ATTR{md/read_ahead_kb}="8192" 63 | ''; 64 | 65 | # Automatically scrub the array monthly 66 | systemd = { 67 | services."raid-scrub" = { 68 | description = "Periodically scrub RAID volumes for errors."; 69 | serviceConfig = { 70 | Type = "oneshot"; 71 | User = "root"; 72 | }; 73 | script = "echo check > /sys/block/md127/md/sync_action"; 74 | }; 75 | timers."raid-scrub" = { 76 | description = "Periodically scrub RAID volumes for errors."; 77 | wantedBy = [ "timers.target" ]; 78 | timerConfig = { 79 | OnCalendar = "monthly"; 80 | Persistent = true; 81 | Unit = "raid-scrub.service"; 82 | }; 83 | }; 84 | }; 85 | }) 86 | ]; 87 | } 88 | -------------------------------------------------------------------------------- /modules/nixos/ui/audio/default.nix: -------------------------------------------------------------------------------- 1 | # Enables audio support. 2 | { 3 | pkgs, 4 | lib, 5 | config, 6 | namespace, 7 | ... 8 | }: 9 | 10 | let 11 | cfg = config.${namespace}.ui.audio; 12 | in 13 | { 14 | options = { 15 | ${namespace}.ui.audio = { 16 | enable = lib.mkEnableOption "Enables audio."; 17 | enableLowLatency = lib.mkEnableOption "Enables low-latency audio (may cause crackling) per https://wiki.nixos.org/wiki/PipeWire#Low-latency_setup."; 18 | }; 19 | }; 20 | 21 | config = lib.mkIf cfg.enable { 22 | # Enable sound with pipewire. 23 | security.rtkit.enable = true; 24 | hardware.pulseaudio = { 25 | enable = false; 26 | package = pkgs.pulseaudioFull; # Enable extra audio codecs 27 | }; 28 | 29 | services.pipewire = { 30 | enable = true; 31 | pulse.enable = true; 32 | jack.enable = true; 33 | alsa = { 34 | enable = true; 35 | support32Bit = true; 36 | }; 37 | 38 | # Reduce audio latency per https://wiki.nixos.org/wiki/PipeWire#Low-latency_setup 39 | extraConfig.pipewire = lib.mkIf cfg.enableLowLatency { 40 | "92-low-latency.conf" = { 41 | "context.properties" = { 42 | "default.clock.rate" = 48000; 43 | "default.clock.quantum" = 32; 44 | "default.clock.min-quantum" = 32; 45 | "default.clock.max-quantum" = 32; 46 | }; 47 | }; 48 | }; 49 | }; 50 | 51 | ${namespace}.ui.flatpak.packages = lib.mkIf config.${namespace}.ui.flatpak.enable [ 52 | "com.github.wwmm.easyeffects" 53 | ]; 54 | }; 55 | } 56 | -------------------------------------------------------------------------------- /modules/nixos/ui/desktops/default.nix: -------------------------------------------------------------------------------- 1 | # Common desktop environment modules 2 | { 3 | pkgs, 4 | config, 5 | lib, 6 | namespace, 7 | ... 8 | }: 9 | 10 | let 11 | cfg = config.${namespace}.ui.desktops; 12 | in 13 | { 14 | options = { 15 | ${namespace}.ui.desktops = { 16 | enable = lib.mkEnableOption "Enables base desktop environment support."; 17 | themePackages = lib.mkOption { 18 | description = "List of extra packages to install as themes."; 19 | type = lib.types.listOf lib.types.package; 20 | default = with pkgs; [ 21 | gnome-themes-extra 22 | papirus-icon-theme 23 | qogir-icon-theme 24 | ]; 25 | }; 26 | xkb = lib.mkOption { 27 | description = "The keyboard layout to use by default. Defaults to us."; 28 | type = lib.types.attrs; 29 | default = { 30 | layout = "us"; 31 | variant = ""; 32 | }; 33 | }; 34 | }; 35 | }; 36 | 37 | config = lib.mkIf cfg.enable { 38 | ${namespace} = { 39 | bluetooth = { 40 | enable = true; 41 | experimental.enable = true; 42 | }; 43 | packages = cfg.themePackages; 44 | ui.audio.enable = true; 45 | }; 46 | 47 | boot = { 48 | # Enable Plymouth for graphical bootsplash. 49 | plymouth = { 50 | enable = true; 51 | theme = "bgrt"; 52 | }; 53 | 54 | # Add kernel parameters 55 | kernelParams = [ 56 | "quiet" 57 | "splash" 58 | ]; 59 | 60 | # Increase minimum log level. This removes ACPI errors from the boot screen. 61 | consoleLogLevel = 1; 62 | }; 63 | 64 | # Manage fonts 65 | fonts = { 66 | # Install extra fonts 67 | packages = with pkgs; [ 68 | noto-fonts 69 | noto-fonts-cjk-sans 70 | noto-fonts-emoji 71 | liberation_ttf 72 | fira-code 73 | fira-code-nerdfont 74 | fira-code-symbols 75 | fira 76 | roboto-slab 77 | ]; 78 | 79 | # Enable font dir for use with Flatpak. See https://wiki.nixos.org/wiki/Fonts#Flatpak_applications_can.27t_find_system_fonts 80 | fontDir.enable = true; 81 | }; 82 | 83 | services = { 84 | # Configure the xserver 85 | xserver = { 86 | # Enable the X11 windowing system. 87 | enable = true; 88 | 89 | # Configure keymap in X11 90 | xkb = config.${namespace}.ui.desktops.xkb; 91 | }; 92 | 93 | # Enable touchpad support (enabled by default in most desktop managers, buuuut just in case). 94 | libinput.enable = true; 95 | 96 | # Enable printing support, but disable browsed per https://discourse.nixos.org/t/cups-cups-filters-and-libppd-security-issues/52780. 97 | printing = { 98 | enable = true; 99 | browsed.enable = false; 100 | }; 101 | }; 102 | 103 | # Support for AppImage files 104 | programs.appimage = { 105 | enable = true; 106 | binfmt = true; 107 | }; 108 | 109 | environment.sessionVariables = { 110 | # Tell Electron apps that they can use Wayland 111 | NIXOS_OZONE_WL = "1"; 112 | # Install full GStreamer capabilities. 113 | # References: 114 | # https://wiki.nixos.org/wiki/GStreamer 115 | # https://github.com/NixOS/nixpkgs/issues/195936 116 | GST_PLUGIN_SYSTEM_PATH_1_0 = lib.makeSearchPathOutput "lib" "lib/gstreamer-1.0" ( 117 | with pkgs.gst_all_1; 118 | [ 119 | gstreamer 120 | gst-plugins-base 121 | gst-plugins-good 122 | gst-plugins-bad 123 | gst-plugins-ugly 124 | gst-libav 125 | gst-vaapi 126 | ] 127 | ); 128 | }; 129 | }; 130 | } 131 | -------------------------------------------------------------------------------- /modules/nixos/ui/desktops/gnome/default.nix: -------------------------------------------------------------------------------- 1 | # Enables the Gnome desktop environment. 2 | { 3 | pkgs, 4 | config, 5 | lib, 6 | namespace, 7 | ... 8 | }: 9 | 10 | let 11 | cfg = config.${namespace}.ui.desktops.gnome; 12 | in 13 | { 14 | 15 | options = { 16 | ${namespace}.ui.desktops.gnome = { 17 | enable = lib.mkEnableOption "Enables the Gnome Desktop Environment."; 18 | autologin = lib.mkOption { 19 | type = lib.types.str; 20 | default = ""; 21 | description = "Which user to automatically log in (leave empty to disable)."; 22 | }; 23 | }; 24 | }; 25 | 26 | config = lib.mkIf cfg.enable { 27 | ${namespace}.ui.desktops.enable = true; 28 | 29 | # This is a workaround for shells crashing on autologin. 30 | # See https://github.com/NixOS/nixpkgs/issues/103746#issuecomment-945091229 31 | systemd.services = lib.mkIf (cfg.autologin != "") { 32 | "getty@tty1".enable = false; 33 | "autovt@tty1".enable = false; 34 | }; 35 | 36 | # Enable Gnome 37 | services = { 38 | displayManager.autoLogin = lib.mkIf (cfg.autologin != "") { 39 | enable = true; 40 | user = cfg.autologin; 41 | }; 42 | 43 | xserver = { 44 | # Remove default packages that came with the install 45 | excludePackages = [ pkgs.xterm ]; 46 | 47 | # Enable Gnome 48 | desktopManager.gnome = { 49 | enable = true; 50 | # Enable native app scaling and VRR, and disable version checks for gnome extensions 51 | extraGSettingsOverrides = '' 52 | [org.gnome.mutter] 53 | experimental-features = [ 'scale-monitor-framebuffer', 'variable-refresh-rate' ] 54 | [org.gnome.shell] 55 | disable-extension-version-validation = true 56 | ''; 57 | extraGSettingsOverridePackages = with pkgs; [ 58 | mutter 59 | gnome-shell 60 | ]; 61 | }; 62 | displayManager.gdm.enable = true; 63 | }; 64 | 65 | # Install Flatpaks 66 | flatpak.packages = [ 67 | "com.github.finefindus.eyedropper" 68 | "com.mattjakeman.ExtensionManager" 69 | "org.bluesabre.MenuLibre" 70 | "org.gnome.baobab" 71 | "org.gnome.Calculator" 72 | "org.gnome.Characters" 73 | "org.gnome.Calendar" 74 | "org.gnome.Evince" 75 | "org.gnome.Evolution" 76 | "org.gnome.FileRoller" 77 | "org.gnome.Firmware" 78 | "org.gnome.Loupe" 79 | "org.gnome.Music" 80 | "org.gnome.seahorse.Application" 81 | "org.gnome.TextEditor" 82 | "org.gtk.Gtk3theme.Adwaita-dark" 83 | ]; 84 | }; 85 | 86 | environment = { 87 | # Remove default Gnome packages that came with the install, then install the ones I actually use 88 | gnome.excludePackages = ( 89 | with pkgs; 90 | [ 91 | gnome-photos 92 | gnome-tour 93 | gnomeExtensions.extension-list 94 | gedit # text editor 95 | gnome-music 96 | gnome-calendar 97 | epiphany # web browser 98 | geary # email reader 99 | evince # document viewer 100 | gnome-characters 101 | gnome-software 102 | totem # video player 103 | tali # poker game 104 | iagno # go game 105 | hitori # sudoku game 106 | atomix # puzzle game 107 | ] 108 | ); 109 | 110 | # Install additional packages 111 | systemPackages = with pkgs; [ 112 | # Gnome tweak tools 113 | gnome-tweaks 114 | # Gnome extensions 115 | gnomeExtensions.another-window-session-manager 116 | gnomeExtensions.appindicator 117 | gnomeExtensions.dash-to-panel 118 | gnomeExtensions.random-wallpaper 119 | ]; 120 | }; 121 | 122 | # Gnome UI integration for KDE apps 123 | qt = { 124 | enable = true; 125 | platformTheme = "gnome"; 126 | style = "adwaita-dark"; 127 | }; 128 | }; 129 | } 130 | -------------------------------------------------------------------------------- /modules/nixos/ui/flatpak/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | config, 4 | lib, 5 | namespace, 6 | ... 7 | }: 8 | 9 | # Flatpak support and options 10 | let 11 | cfg = config.${namespace}.ui.flatpak; 12 | in 13 | { 14 | options = { 15 | ${namespace}.ui.flatpak = { 16 | enable = lib.mkEnableOption { description = "Enables Flatpak support."; }; 17 | packages = lib.mkOption { 18 | description = "Flatpak packages to install."; 19 | type = lib.types.listOf lib.types.str; 20 | default = [ 21 | "com.github.tchx84.Flatseal" 22 | "io.github.ungoogled_software.ungoogled_chromium" 23 | "org.mozilla.firefox" 24 | ]; 25 | example = lib.literalExpression "[ \"com.valvesoftware.Steam\" ]"; 26 | }; 27 | remotes = lib.mkOption { 28 | description = "The list of remote Flatpak repos to pull from. Includes Flathub by default."; 29 | type = lib.types.listOf lib.types.attrs; 30 | default = [ 31 | { 32 | name = "flathub"; 33 | location = "https://dl.flathub.org/repo/flathub.flatpakrepo"; 34 | } 35 | ]; 36 | }; 37 | useBindFS = lib.mkEnableOption "Whether to use a BindFS mount to support custom themes and cursors. May cause performance issues."; 38 | }; 39 | }; 40 | 41 | config = lib.mkMerge [ 42 | (lib.mkIf cfg.enable { 43 | # Enable Flatpak 44 | services.flatpak = { 45 | enable = true; 46 | 47 | # Manage all Flatpak packages and remotes 48 | uninstallUnmanaged = true; 49 | 50 | # Delete stale/unused packages 51 | uninstallUnused = true; 52 | 53 | # Enable automatic updates alongside nixos-rebuild 54 | update.onActivation = true; 55 | 56 | # Add remote(s) 57 | remotes = cfg.remotes; 58 | 59 | # Install base Flatpaks. For details, see https://github.com/gmodena/nix-flatpak 60 | packages = cfg.packages; 61 | }; 62 | }) 63 | (lib.mkIf cfg.useBindFS { 64 | # Workaround for getting Flatpak apps to use system fonts, icons, and cursors 65 | # For details (and source), see https://github.com/NixOS/nixpkgs/issues/119433#issuecomment-1767513263 66 | # NOTE: If fonts in Flatpaks appear incorrect (like squares), run this command to regenerate the font cache: 67 | # flatpak list --columns=application | xargs -I %s -- flatpak run --command=fc-cache %s -f -v 68 | system.fsPackages = [ pkgs.bindfs ]; 69 | fileSystems = 70 | let 71 | mkRoSymBind = path: { 72 | device = path; 73 | fsType = "fuse.bindfs"; 74 | options = [ 75 | "ro" 76 | "resolve-symlinks" 77 | "x-gvfs-hide" 78 | ]; 79 | }; 80 | aggregatedIcons = pkgs.buildEnv { 81 | name = "system-icons"; 82 | paths = config.${namespace}.ui.desktops.themePackages; 83 | pathsToLink = [ "/share/icons" ]; 84 | }; 85 | aggregatedFonts = pkgs.buildEnv { 86 | name = "system-fonts"; 87 | paths = config.fonts.packages; 88 | pathsToLink = [ "/share/fonts" ]; 89 | }; 90 | in 91 | { 92 | "/usr/share/icons" = mkRoSymBind "${aggregatedIcons}/share/icons"; 93 | "/usr/share/fonts" = mkRoSymBind "${aggregatedFonts}/share/fonts"; 94 | }; 95 | }) 96 | ]; 97 | } 98 | -------------------------------------------------------------------------------- /modules/nixos/users/aires/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | config, 4 | namespace, 5 | ... 6 | }: 7 | 8 | # Define 'aires' 9 | 10 | # FIXME: Can't set osConfig in the /homes/ folder, so we unfortunately need to keep the system-level user configuration here. 11 | let 12 | cfg = config.${namespace}.users.aires; 13 | in 14 | { 15 | options = { 16 | ${namespace}.users.aires = { 17 | enable = lib.mkEnableOption "Enables aires user account"; 18 | }; 19 | }; 20 | 21 | config = lib.mkIf cfg.enable { 22 | users = { 23 | users.aires = { 24 | isNormalUser = true; 25 | description = "Aires"; 26 | uid = 1000; 27 | hashedPassword = config.${namespace}.secrets.users.aires.hashedPassword; 28 | extraGroups = [ 29 | "input" 30 | "networkmanager" 31 | "plugdev" 32 | "tss" # For access to TPM devices 33 | "wheel" 34 | "users" 35 | (lib.mkIf config.${namespace}.services.virtualization.host.enable "libvirtd") 36 | ]; 37 | 38 | # Allow systemd services to run even while aires is logged out 39 | linger = true; 40 | 41 | # Allow these systems to log into aires' account via SSH (if enabled on the host) 42 | openssh.authorizedKeys.keys = with config.${namespace}.secrets.hosts; [ 43 | hevana.ssh.publicKey 44 | khanda.ssh.publicKey 45 | pihole.ssh.publicKey 46 | shura.ssh.publicKey 47 | ]; 48 | }; 49 | 50 | groups."aires" = { 51 | gid = 1000; 52 | }; 53 | }; 54 | }; 55 | } 56 | -------------------------------------------------------------------------------- /modules/nixos/users/gremlin/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | config, 4 | namespace, 5 | ... 6 | }: 7 | 8 | # Define 'gremlin' user 9 | let 10 | cfg = config.${namespace}.users.gremlin; 11 | in 12 | { 13 | options = { 14 | ${namespace}.users.gremlin = { 15 | enable = lib.mkEnableOption "Enables gremlin user account"; 16 | }; 17 | }; 18 | 19 | config = lib.mkIf cfg.enable { 20 | # Add Gremlin account 21 | users = { 22 | users.gremlin = { 23 | isNormalUser = true; 24 | description = "Gremlin"; 25 | uid = 1001; 26 | hashedPassword = config.${namespace}.secrets.users.gremlin.hashedPassword; 27 | group = "gremlin"; 28 | extraGroups = [ 29 | "networkmanager" 30 | "input" 31 | "users" 32 | ]; 33 | 34 | # Allow systemd services to keep running even while gremlin is logged out 35 | linger = true; 36 | }; 37 | 38 | groups."gremlin" = { 39 | gid = 1001; 40 | }; 41 | }; 42 | 43 | # Install gremlin-specific flatpaks 44 | ${namespace}.ui.flatpak.packages = [ 45 | "com.google.Chrome" 46 | "com.slack.Slack" 47 | ]; 48 | 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /modules/nixos/users/media/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | config, 4 | namespace, 5 | ... 6 | }: 7 | 8 | # Define user for managing media files 9 | let 10 | cfg = config.${namespace}.users.media; 11 | in 12 | { 13 | 14 | options = { 15 | ${namespace}.users.media = { 16 | enable = lib.mkEnableOption "Enables media user account"; 17 | }; 18 | }; 19 | 20 | config = lib.mkIf cfg.enable { 21 | users = { 22 | users.media = { 23 | isNormalUser = false; 24 | isSystemUser = true; 25 | description = "Media manager"; 26 | uid = 1001; 27 | group = "media"; 28 | }; 29 | 30 | groups."media" = { 31 | gid = 1001; 32 | }; 33 | }; 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /modules/nixos/users/root/default.nix: -------------------------------------------------------------------------------- 1 | { ... }: 2 | { 3 | # FIXME: Dropping this into /homes/ causes a weird error that I don't know how to fix: 4 | # "error: The option `users.users.root.shell' is defined multiple times while it's expected to be unique." 5 | # Keeping here for now. 6 | home-manager.users.root = { 7 | imports = [ ../../../../homes/common/zsh.nix ]; 8 | 9 | home.stateVersion = "24.05"; 10 | programs.zsh = { 11 | oh-my-zsh.theme = "kardan"; 12 | shellAliases.nos = "nixos-operations-script"; 13 | }; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /nix-on-droid/Readme.md: -------------------------------------------------------------------------------- 1 | # nix-on-droid 2 | 3 | Run Nix on an Android device! Includes Home Manager and Flakes. 4 | 5 | Main project: https://github.com/nix-community/nix-on-droid/ 6 | Project wiki: https://github.com/nix-community/nix-on-droid/wiki 7 | Documentation: https://nix-community.github.io/nix-on-droid/ 8 | 9 | ## How to use this repo 10 | 11 | 1. Install the nix-on-droid app from F-Droid: https://f-droid.org/packages/com.termux.nix 12 | 2. Copy this repo to your phone. On the phone, move the folder from regular storage to the `Nix` storage device created by nix-on-droid. This will place it into the home directory. 13 | 3. In the app, run `cd nix-configuration`, then `nix-on-droid switch --flake .`. 14 | 15 | To start an SSH session after installing, run `sshd-start`. 16 | -------------------------------------------------------------------------------- /nix-on-droid/Skadi/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | namespace, 5 | pkgs, 6 | ... 7 | }: 8 | { 9 | imports = [ 10 | modules/nix 11 | modules/ssh 12 | ]; 13 | 14 | environment = { 15 | packages = with pkgs; [ 16 | # User-facing stuff that you really really want to have 17 | gawk 18 | vim # or some other editor, e.g. nano or neovim 19 | nano 20 | 21 | # Some common stuff that people expect to have 22 | procps 23 | killall 24 | diffutils 25 | findutils 26 | utillinux 27 | tzdata 28 | hostname 29 | man 30 | gnugrep 31 | gnupg 32 | gnused 33 | gnutar 34 | bzip2 35 | gzip 36 | xz 37 | zip 38 | 39 | git 40 | zellij 41 | zsh 42 | openssh 43 | nixfmt-rfc-style 44 | 45 | # Required for Transcrypt 46 | transcrypt 47 | openssl 48 | xxd 49 | ]; 50 | # Backup etc files instead of failing to activate generation if a file already exists in /etc 51 | etcBackupExtension = ".bak"; 52 | sessionVariables."EDITOR" = "nano"; 53 | }; 54 | 55 | # Read the changelog before changing this value 56 | system.stateVersion = "24.05"; 57 | 58 | # Set your time zone 59 | #time.timeZone = "Europe/Berlin"; 60 | 61 | home-manager = { 62 | backupFileExtension = "home-manager.bak"; 63 | useGlobalPkgs = true; 64 | extraSpecialArgs = { 65 | secrets = config.${namespace}.secrets; 66 | }; 67 | config = ./homes; 68 | }; 69 | 70 | user.shell = "${lib.getExe pkgs.zsh}"; 71 | } 72 | -------------------------------------------------------------------------------- /nix-on-droid/Skadi/homes/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | secrets, 3 | pkgs, 4 | ... 5 | }: 6 | { 7 | # Read home-manager changelog before changing this value 8 | home.stateVersion = "24.05"; 9 | 10 | home = { 11 | file.".nanorc" = { 12 | enable = true; 13 | text = '' 14 | include ${pkgs.nano}/share/nano/*.nanorc 15 | set tabsize 4 16 | set softwrap 17 | set autoindent 18 | set indicator 19 | ''; 20 | }; 21 | }; 22 | 23 | # insert home-manager config 24 | programs = { 25 | command-not-found.enable = true; 26 | 27 | git = { 28 | enable = true; 29 | userName = secrets.users.aires.firstName; 30 | userEmail = secrets.users.aires.email; 31 | merge.conflictStyle = "zdiff3"; 32 | pull.ff = "only"; 33 | push.autoSetupRemote = "true"; 34 | }; 35 | 36 | # Set up SSH 37 | ssh = { 38 | enable = true; 39 | matchBlocks = secrets.users.aires.sshConfig; 40 | }; 41 | 42 | zsh = { 43 | enable = true; 44 | enableAutosuggestions = true; # Had to use the old name, otherwise nix-on-droid complains it doesn't exist 45 | syntaxHighlighting.enable = true; 46 | history.ignoreDups = true; # Do not enter command lines into the history list if they are duplicates of the previous event. 47 | prezto = { 48 | git.submoduleIgnore = "untracked"; # Ignore submodules when they are untracked. 49 | }; 50 | plugins = [ 51 | { 52 | name = "zsh-nix-shell"; 53 | file = "nix-shell.plugin.zsh"; 54 | src = pkgs.fetchFromGitHub { 55 | owner = "chisui"; 56 | repo = "zsh-nix-shell"; 57 | rev = "v0.8.0"; 58 | sha256 = "1lzrn0n4fxfcgg65v0qhnj7wnybybqzs4adz7xsrkgmcsr0ii8b7"; 59 | }; 60 | } 61 | ]; 62 | oh-my-zsh = { 63 | enable = true; 64 | theme = "gentoo"; 65 | plugins = [ 66 | "command-not-found" 67 | "cp" 68 | "direnv" 69 | "dotenv" 70 | "extract" 71 | "git" 72 | "systemd" 73 | ]; 74 | }; 75 | shellAliases = { 76 | z = "zellij"; 77 | update = "upgrade"; 78 | upgrade = "nix-on-droid switch --flake ~/nix-configuration"; 79 | }; 80 | }; 81 | }; 82 | } 83 | -------------------------------------------------------------------------------- /nix-on-droid/Skadi/modules/nix/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | namespace, 4 | pkgs, 5 | ... 6 | }: 7 | { 8 | nix = { 9 | settings = { 10 | # Enable Flakes 11 | experimental-features = [ 12 | "nix-command" 13 | "flakes" 14 | ]; 15 | 16 | # Set up Hevana and Lix as secondary binary caches 17 | substituters = [ 18 | "https://cache.nixos.org/" 19 | "https://${config.${namespace}.secrets.services.binary-cache.url}" 20 | "https://cache.lix.systems" 21 | ]; 22 | trusted-public-keys = [ 23 | config.${namespace}.secrets.services.binary-cache.pubcert 24 | "cache.lix.systems:aBnZUw8zA7H35Cz2RyKFVs3H4PlGTLawyY5KRbvJR8o=" 25 | ]; 26 | 27 | # Authentication for Hevana's binary cache 28 | netrc-file = 29 | with config.${namespace}.secrets.services.binary-cache; 30 | pkgs.writeText "netrc" '' 31 | machine ${url} login ${auth.username} password ${auth.password} 32 | ''; 33 | 34 | # Only allow these users to use Nix 35 | allowed-users = with config.users.users; [ 36 | root.name 37 | (lib.mkIf config.${namespace}.users.aires.enable aires.name) 38 | (lib.mkIf config.${namespace}.users.gremlin.enable gremlin.name) 39 | ]; 40 | 41 | # Avoid signature verification messages when doing remote builds 42 | trusted-users = with config.users.users; [ 43 | root.name 44 | (lib.mkIf config.${namespace}.users.aires.enable aires.name) 45 | ]; 46 | }; 47 | 48 | # Optimize the Nix store on each build 49 | settings.auto-optimise-store = true; 50 | # Enable garbage collection 51 | gc = { 52 | automatic = true; 53 | dates = "weekly"; 54 | options = "--delete-older-than 3d"; 55 | persistent = true; 56 | randomizedDelaySec = "1hour"; 57 | }; 58 | 59 | # Configure NixOS to use the same software channel as Flakes 60 | registry.nixpkgs.flake = pkgs; 61 | nixPath = [ "nixpkgs=${pkgs}" ]; 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /nix-on-droid/Skadi/modules/ssh/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | 3 | let 4 | port = 8022; 5 | in 6 | { 7 | environment = { 8 | etc."ssh/sshd_config".source = ./sshd_config; 9 | packages = [ 10 | (pkgs.writeScriptBin "sshd-start" '' 11 | #!${pkgs.runtimeShell} 12 | 13 | echo "Starting sshd in non-daemonized way on port ${toString port}" 14 | ${pkgs.openssh}/bin/sshd -f "/etc/ssh/sshd_config" -D 15 | '') 16 | ]; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /nix-on-droid/Skadi/modules/ssh/sshd_config: -------------------------------------------------------------------------------- 1 | HostKey /etc/ssh/ssh_host_ed25519_key 2 | AuthorizedKeysFile %h/.ssh/authorized_keys 3 | Port 8022 4 | PubkeyAuthentication yes 5 | PasswordAuthentication no 6 | KbdInteractiveAuthentication no -------------------------------------------------------------------------------- /overlays/pkgs/unstable/default.nix: -------------------------------------------------------------------------------- 1 | { channels, inputs, ... }: 2 | 3 | final: _prev: 4 | 5 | { 6 | unstable = import inputs.nixpkgs-unstable { 7 | system = final.system; 8 | config.allowUnfree = true; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /packages/duplicacy-web/default.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib }: 2 | 3 | pkgs.stdenv.mkDerivation rec { 4 | pname = "duplicacy-web"; 5 | version = "1.8.3"; 6 | 7 | src = builtins.fetchurl { 8 | url = "https://acrosync.com/${pname}/duplicacy_web_linux_x64_${version}"; 9 | sha256 = "9cdcaa875ae5fc0fcf93941df3a5133fb3c3ff92c89f87babddc511ba6dd7ef8"; 10 | }; 11 | 12 | doCheck = false; 13 | 14 | dontUnpack = true; 15 | 16 | installPhase = '' 17 | install -D $src $out/duplicacy-web 18 | chmod a+x $out/duplicacy-web 19 | ''; 20 | 21 | meta = { 22 | homepage = "https://duplicacy.com"; 23 | description = "A new generation cloud backup tool"; 24 | platforms = lib.platforms.linux; 25 | license = lib.licenses.unfreeRedistributable; 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /packages/freight-pro/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | pkgs, 5 | }: 6 | 7 | stdenv.mkDerivation rec { 8 | pname = "freight-pro-fonts"; 9 | version = "20240828T164047Z-001"; 10 | nativeBuildInputs = [ pkgs.unzip ]; 11 | buildInputs = [ pkgs.unzip ]; 12 | 13 | src = lib.snowfall.fs.get-file "modules/nixos/secrets/Freight-20240828T164047Z-001.zip"; 14 | 15 | unpackPhase = '' 16 | runHook preUnpack 17 | ${pkgs.unzip}/bin/unzip $src 18 | 19 | runHook postUnpack 20 | ''; 21 | 22 | installPhase = '' 23 | runHook preInstall 24 | 25 | install -m 644 -D Freight-${version}/*.otf -t $out/share/fonts/opentype 26 | 27 | runHook postInstall 28 | ''; 29 | } 30 | -------------------------------------------------------------------------------- /packages/languagetool-ngrams/default.nix: -------------------------------------------------------------------------------- 1 | # For a packaging example, see https://github.com/Janik-Haag/nix-languagetool-ngram/blob/main/ngram-template.nix 2 | { 3 | pkgs, 4 | lib, 5 | fetchzip, 6 | }: 7 | 8 | pkgs.stdenv.mkDerivation rec { 9 | pname = "languagetool-ngram-en"; 10 | version = "20150817"; 11 | language = "en"; 12 | 13 | src = fetchzip { 14 | url = "https://languagetool.org/download/ngram-data/ngrams-${language}-${version}.zip"; 15 | sha256 = "v3Ym6CBJftQCY5FuY6s5ziFvHKAyYD3fTHr99i6N8sE="; 16 | }; 17 | 18 | dontBuild = true; 19 | dontConfigure = true; 20 | dontFixup = true; 21 | 22 | installPhase = '' 23 | mkdir -p $out/share/languagetool/ngrams 24 | ln -s $src $out/share/languagetool/ngrams/${language} 25 | ''; 26 | 27 | meta = with lib; { 28 | homepage = "https://dev.languagetool.org/finding-errors-using-n-gram-data.html"; 29 | description = "LanguageTool can make use of large n-gram data sets to detect errors with words that are often confused, like their and there."; 30 | platforms = platforms.linux; 31 | license = licenses.cc-by-sa-40; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /systems/aarch64-linux/Pihole/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | pkgs, 4 | lib, 5 | namespace, 6 | ... 7 | }: 8 | let 9 | stateVersion = "24.05"; 10 | hostName = "Pihole"; 11 | in 12 | { 13 | imports = [ ./hardware-configuration.nix ]; 14 | 15 | system.stateVersion = stateVersion; 16 | networking = { 17 | hostName = hostName; 18 | 19 | # Connect to the network automagically 20 | networkmanager.enable = lib.mkForce false; 21 | wireless = { 22 | enable = true; 23 | networks = { 24 | "${config.${namespace}.secrets.networking.networks.home.SSID}" = { 25 | psk = "${config.${namespace}.secrets.networking.networks.home.password}"; 26 | }; 27 | }; 28 | }; 29 | }; 30 | 31 | # Disable smartd: daemon fails when it doesn't detect any drives to monitor on startup 32 | services.smartd.enable = lib.mkForce false; 33 | 34 | # Install Docker for Kubernetes in Docker (Kind) 35 | virtualisation.docker = { 36 | enable = true; 37 | autoPrune.enable = true; 38 | }; 39 | 40 | ${namespace} = { 41 | bootloader.enable = false; # Bootloader configured in hardware-configuration.nix 42 | 43 | packages = with pkgs; [ 44 | btrfs-progs 45 | cryptsetup 46 | libraspberrypi 47 | linuxKernel.kernels.linux_rpi4 48 | raspberrypifw 49 | raspberrypi-eeprom 50 | 51 | # Gremlin lab tools 52 | pkgs.unstable.kind 53 | pkgs.unstable.kubectl 54 | pkgs.unstable.kubernetes-helm 55 | ]; 56 | services = { 57 | autoUpgrade.enable = false; 58 | ssh = { 59 | enable = true; 60 | ports = [ config.${namespace}.secrets.hosts.hevana.ssh.port ]; 61 | }; 62 | }; 63 | users.aires.enable = true; 64 | }; 65 | } 66 | -------------------------------------------------------------------------------- /systems/aarch64-linux/Pihole/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Raspberry Pi 4B 2 | # See https://wiki.nixos.org/wiki/NixOS_on_ARM/Raspberry_Pi_4 3 | { 4 | config, 5 | lib, 6 | modulesPath, 7 | namespace, 8 | pkgs, 9 | ... 10 | }: 11 | 12 | { 13 | imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; 14 | 15 | boot = { 16 | kernelParams = [ 17 | # Enable audio 18 | "snd_bcm2835.enable_hdmi=1" 19 | "snd_bcm2835.enable_headphones=1" 20 | "dtparam=audio=on" 21 | # Enable cgroups memory for Kubernetes in Docker. See https://github.com/kubernetes-sigs/kind/issues/3503 22 | "cgroup_enable=memory" 23 | "cgroup_memory=1" 24 | ]; 25 | 26 | # Switch to a compatible bootloader 27 | loader = lib.mkForce { 28 | grub.enable = false; 29 | generic-extlinux-compatible.enable = true; 30 | }; 31 | }; 32 | 33 | fileSystems = { 34 | "/" = { 35 | device = "/dev/disk/by-uuid/44444444-4444-4444-8888-888888888888"; 36 | fsType = "ext4"; 37 | options = [ 38 | "lazytime" # Reduce atime writes: https://wiki.archlinux.org/title/Fstab#atime_options 39 | "data=journal" # Commit to the journal before writing to the filesystem. 40 | "journal_async_commit" 41 | ]; 42 | }; 43 | }; 44 | 45 | swapDevices = [ 46 | { 47 | device = "/swapfile"; 48 | } 49 | ]; 50 | 51 | hardware = { 52 | enableRedistributableFirmware = true; 53 | raspberry-pi."4" = { 54 | apply-overlays-dtmerge.enable = true; 55 | fkms-3d.enable = true; # Enable GPU 56 | }; 57 | 58 | deviceTree.enable = true; 59 | }; 60 | } 61 | -------------------------------------------------------------------------------- /systems/x86_64-linux/Hevana/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | inputs, 4 | pkgs, 5 | namespace, 6 | ... 7 | }: 8 | 9 | let 10 | # Do not change this value! This tracks when NixOS was installed on your system. 11 | stateVersion = "24.11"; 12 | hostName = "Hevana"; 13 | 14 | # Where to store service files 15 | services-root = "/storage/services"; 16 | 17 | # Credentials for interacting with the Porkbun API 18 | porkbunCredentials = { 19 | "PORKBUN_API_KEY_FILE" = "${pkgs.writeText "porkbun-api-key" '' 20 | ${config.${namespace}.secrets.networking.porkbun.api.apiKey} 21 | ''}"; 22 | "PORKBUN_SECRET_API_KEY_FILE" = "${pkgs.writeText "porkbun-secret-api-key" '' 23 | ${config.${namespace}.secrets.networking.porkbun.api.secretKey} 24 | ''}"; 25 | }; 26 | 27 | # Block list for Nginx 28 | nginxBlocklist = { 29 | locations."/robots.txt" = { 30 | alias = "${inputs.ai-blocklist}/robots.txt"; 31 | }; 32 | extraConfig = '' 33 | if ($http_user_agent ~* "(${builtins.readFile "${inputs.ai-blocklist}/robots.txt"})") { 34 | return 444; 35 | } 36 | ''; 37 | }; 38 | in 39 | { 40 | imports = [ ./hardware-configuration.nix ]; 41 | 42 | system.stateVersion = stateVersion; 43 | networking.hostName = hostName; 44 | 45 | services = { 46 | # Enable internal-only Nginx status page 47 | nginx.statusPage = true; 48 | 49 | # Monitor RAID drives using SMART 50 | smartd.devices = [ 51 | { device = "/dev/sda"; } 52 | { device = "/dev/sdb"; } 53 | { device = "/dev/sdc"; } 54 | { device = "/dev/sdd"; } 55 | ]; 56 | }; 57 | 58 | # Build Nix packages for other hosts. 59 | # Runs every Saturday morning at 4 AM 60 | systemd.services."build-hosts" = { 61 | serviceConfig = { 62 | Type = "oneshot"; 63 | User = "aires"; 64 | }; 65 | path = config.${namespace}.corePackages; 66 | script = '' 67 | /run/current-system/sw/bin/nixos-operations-script --operation build --hostname Khanda --flake ${ 68 | config.${namespace}.secrets.nixConfigFolder 69 | } 70 | ''; 71 | }; 72 | systemd.timers."build-hosts" = { 73 | wants = [ "network-online.target" ]; 74 | after = [ "network-online.target" ]; 75 | wantedBy = [ "timers.target" ]; 76 | timerConfig = { 77 | OnCalendar = "Sat, 04:00"; 78 | Persistent = true; 79 | Unit = "build-hosts.service"; 80 | }; 81 | }; 82 | 83 | # Configure the system. 84 | ${namespace} = { 85 | # Enable Secure Boot support. 86 | bootloader = { 87 | enable = true; 88 | secureboot.enable = true; 89 | tpm2.enable = true; 90 | }; 91 | 92 | # Enable GPU support. 93 | gpu.amd.enable = true; 94 | 95 | # Enable support for primary RAID array 96 | raid = { 97 | enable = true; 98 | mailAddr = config.${namespace}.secrets.users.aires.email; 99 | storage = { 100 | enable = true; 101 | keyFile = config.${namespace}.secrets.devices.storage.keyFile.path; 102 | }; 103 | }; 104 | 105 | services = { 106 | acme = { 107 | enable = true; 108 | defaultEmail = config.${namespace}.secrets.users.aires.email; 109 | certs = { 110 | "${config.${namespace}.secrets.networking.domains.primary}" = { 111 | dnsProvider = "porkbun"; 112 | domain = "*.${config.${namespace}.secrets.networking.domains.primary}"; 113 | webroot = null; # Required in order to prevent a failed assertion 114 | credentialFiles = porkbunCredentials; 115 | }; 116 | "${config.${namespace}.secrets.networking.domains.blog}" = { 117 | dnsProvider = "porkbun"; 118 | webroot = null; # Required in order to prevent a failed assertion 119 | credentialFiles = porkbunCredentials; 120 | }; 121 | }; 122 | }; 123 | apcupsd = { 124 | enable = true; 125 | configText = builtins.readFile ./etc/apcupsd.conf; 126 | }; 127 | archiveteam-warrior = { 128 | enable = true; 129 | useVPN = true; 130 | port = 8001; 131 | }; 132 | autoUpgrade = { 133 | enable = true; 134 | pushUpdates = true; # Update automatically and push updates back up to Forgejo 135 | onCalendar = "06:00"; 136 | configDir = config.${namespace}.secrets.nixConfigFolder; 137 | user = config.users.users.aires.name; 138 | }; 139 | binary-cache = { 140 | enable = true; 141 | secretKeyFile = "${services-root}/nixos-binary-cache/certs/cache-priv-key.pem"; 142 | url = config.${namespace}.secrets.services.binary-cache.url; 143 | auth = { 144 | user = config.${namespace}.secrets.services.binary-cache.auth.username; 145 | password = config.${namespace}.secrets.services.binary-cache.auth.password; 146 | }; 147 | }; 148 | duplicacy-web = { 149 | enable = true; 150 | home = "/storage/backups/settings/Haven"; 151 | homeBackupDir = "/home/aires/duplicacy-settings-backup-Hevana"; 152 | }; 153 | forgejo = { 154 | enable = true; 155 | home = "${services-root}/forgejo"; 156 | url = config.${namespace}.secrets.services.forgejo.url; 157 | }; 158 | jellyfin = { 159 | enable = true; 160 | home = "${services-root}/jellyfin"; 161 | url = config.${namespace}.secrets.services.jellyfin.url; 162 | }; 163 | languagetool = { 164 | enable = true; 165 | url = config.${namespace}.secrets.services.languagetool.url; 166 | port = 8100; 167 | auth = { 168 | user = config.${namespace}.secrets.services.languagetool.auth.user; 169 | password = config.${namespace}.secrets.services.languagetool.auth.password; 170 | }; 171 | ngrams.enable = true; 172 | }; 173 | msmtp = { 174 | enable = true; 175 | accounts.default = { 176 | host = config.${namespace}.secrets.services.msmtp.host; 177 | user = config.${namespace}.secrets.services.msmtp.user; 178 | password = config.${namespace}.secrets.services.msmtp.password; 179 | auth = true; 180 | tls = true; 181 | tls_starttls = true; 182 | port = 587; 183 | from = "${config.networking.hostName}@${config.${namespace}.secrets.networking.domains.primary}"; 184 | }; 185 | aliases = { 186 | text = '' 187 | default: ${config.${namespace}.secrets.users.aires.email} 188 | ''; 189 | mode = "0644"; 190 | }; 191 | }; 192 | nginx = { 193 | enable = true; 194 | virtualHosts = { 195 | "${config.${namespace}.secrets.networking.domains.primary}" = { 196 | default = true; 197 | enableACME = true; # Enable Let's Encrypt 198 | locations."/" = { 199 | # Catchall vhost, will redirect users to Forgejo 200 | return = "301 https://${config.${namespace}.secrets.services.forgejo.url}"; 201 | }; 202 | } // nginxBlocklist; 203 | # Personal blog website 204 | "${config.${namespace}.secrets.networking.domains.blog}" = { 205 | useACMEHost = config.${namespace}.secrets.networking.domains.blog; 206 | forceSSL = true; 207 | root = "${services-root}/nginx/sites/${config.${namespace}.secrets.networking.domains.blog}"; 208 | } // nginxBlocklist; 209 | # Work lab VM 210 | "${config.${namespace}.secrets.hosts.gremlin-lab.URI}" = { 211 | useACMEHost = config.${namespace}.secrets.networking.domains.primary; 212 | forceSSL = true; 213 | locations."/" = { 214 | proxyPass = "http://${config.${namespace}.secrets.hosts.gremlin-lab.IP}"; 215 | proxyWebsockets = true; 216 | extraConfig = "proxy_ssl_server_name on;"; 217 | }; 218 | }; 219 | }; 220 | }; 221 | observability = { 222 | enable = true; 223 | url = config.${namespace}.secrets.services.observability.url; 224 | grafana = { 225 | home = "${services-root}/observability/grafana"; 226 | smtp = with config.${namespace}.secrets.services.msmtp; { 227 | enabled = true; 228 | host = "${host}:465"; 229 | user = user; 230 | password = password; 231 | startTLS_policy = "MandatoryStartTLS"; 232 | from_name = "Grafana"; 233 | from_address = "admin@${config.${namespace}.secrets.networking.domains.primary}"; 234 | }; 235 | }; 236 | }; 237 | open-webui = { 238 | enable = true; 239 | url = config.${namespace}.secrets.services.open-webui.url; 240 | ollama.enable = true; 241 | }; 242 | qbittorrent = { 243 | enable = true; 244 | home = "${services-root}/qbittorrent"; 245 | url = config.${namespace}.secrets.services.qbittorrent.url; 246 | port = 8090; 247 | }; 248 | ssh = { 249 | enable = true; 250 | ports = [ config.${namespace}.secrets.hosts.hevana.ssh.port ]; 251 | }; 252 | syncthing = { 253 | enable = true; 254 | home = "${services-root}/syncthing/aires"; 255 | user = "aires"; 256 | web = { 257 | enable = true; 258 | public = true; 259 | }; 260 | }; 261 | tor = { 262 | enable = true; 263 | snowflake-proxy = { 264 | enable = true; 265 | capacity = 50; 266 | }; 267 | }; 268 | virtualization.host = { 269 | enable = true; 270 | vmBuilds = { 271 | enable = true; 272 | cores = 3; 273 | ram = 4096; 274 | }; 275 | }; 276 | vpn = { 277 | enable = true; 278 | auth = with config.${namespace}.secrets.services.private-internet-access.auth; { 279 | user = user; 280 | password = password; 281 | }; 282 | countries = [ 283 | "Switzerland" 284 | "Netherlands" 285 | ]; 286 | port = config.${namespace}.services.qbittorrent.port; 287 | }; 288 | }; 289 | 290 | users.aires.enable = true; 291 | }; 292 | } 293 | -------------------------------------------------------------------------------- /systems/x86_64-linux/Hevana/etc/apcupsd.conf: -------------------------------------------------------------------------------- 1 | ## apcupsd.conf v1.1 ## 2 | # 3 | # for apcupsd release 3.14.12 (29 March 2014) - debian 4 | # 5 | # "apcupsd" POSIX config file 6 | 7 | # 8 | # ========= General configuration parameters ============ 9 | # 10 | 11 | # UPSNAME xxx 12 | # Use this to give your UPS a name in log files and such. This 13 | # is particulary useful if you have multiple UPSes. This does not 14 | # set the EEPROM. It should be 8 characters or less. 15 | #UPSNAME 16 | 17 | # UPSCABLE 18 | # Defines the type of cable connecting the UPS to your computer. 19 | # 20 | # Possible generic choices for are: 21 | # simple, smart, ether, usb 22 | # 23 | # Or a specific cable model number may be used: 24 | # 940-0119A, 940-0127A, 940-0128A, 940-0020B, 25 | # 940-0020C, 940-0023A, 940-0024B, 940-0024C, 26 | # 940-1524C, 940-0024G, 940-0095A, 940-0095B, 27 | # 940-0095C, 940-0625A, M-04-02-2000 28 | # 29 | UPSCABLE usb 30 | 31 | # To get apcupsd to work, in addition to defining the cable 32 | # above, you must also define a UPSTYPE, which corresponds to 33 | # the type of UPS you have (see the Description for more details). 34 | # You must also specify a DEVICE, sometimes referred to as a port. 35 | # For USB UPSes, please leave the DEVICE directive blank. For 36 | # other UPS types, you must specify an appropriate port or address. 37 | # 38 | # UPSTYPE DEVICE Description 39 | # apcsmart /dev/tty** Newer serial character device, appropriate for 40 | # SmartUPS models using a serial cable (not USB). 41 | # 42 | # usb Most new UPSes are USB. A blank DEVICE 43 | # setting enables autodetection, which is 44 | # the best choice for most installations. 45 | # 46 | # net hostname:port Network link to a master apcupsd through apcupsd's 47 | # Network Information Server. This is used if the 48 | # UPS powering your computer is connected to a 49 | # different computer for monitoring. 50 | # 51 | # snmp hostname:port:vendor:community 52 | # SNMP network link to an SNMP-enabled UPS device. 53 | # Hostname is the ip address or hostname of the UPS 54 | # on the network. Vendor can be can be "APC" or 55 | # "APC_NOTRAP". "APC_NOTRAP" will disable SNMP trap 56 | # catching; you usually want "APC". Port is usually 57 | # 161. Community is usually "private". 58 | # 59 | # netsnmp hostname:port:vendor:community 60 | # OBSOLETE 61 | # Same as SNMP above but requires use of the 62 | # net-snmp library. Unless you have a specific need 63 | # for this old driver, you should use 'snmp' instead. 64 | # 65 | # dumb /dev/tty** Old serial character device for use with 66 | # simple-signaling UPSes. 67 | # 68 | # pcnet ipaddr:username:passphrase:port 69 | # PowerChute Network Shutdown protocol which can be 70 | # used as an alternative to SNMP with the AP9617 71 | # family of smart slot cards. ipaddr is the IP 72 | # address of the UPS management card. username and 73 | # passphrase are the credentials for which the card 74 | # has been configured. port is the port number on 75 | # which to listen for messages from the UPS, normally 76 | # 3052. If this parameter is empty or missing, the 77 | # default of 3052 will be used. 78 | # 79 | # modbus /dev/tty** Serial device for use with newest SmartUPS models 80 | # supporting the MODBUS protocol. 81 | # 82 | UPSTYPE usb 83 | DEVICE 84 | 85 | # POLLTIME 86 | # Interval (in seconds) at which apcupsd polls the UPS for status. This 87 | # setting applies both to directly-attached UPSes (UPSTYPE apcsmart, usb, 88 | # dumb) and networked UPSes (UPSTYPE net, snmp). Lowering this setting 89 | # will improve apcupsd's responsiveness to certain events at the cost of 90 | # higher CPU utilization. The default of 60 is appropriate for most 91 | # situations. 92 | #POLLTIME 60 93 | 94 | # LOCKFILE 95 | # Path for device lock file. Not used on Win32. 96 | LOCKFILE /var/lock 97 | 98 | # SCRIPTDIR 99 | # Directory in which apccontrol and event scripts are located. 100 | SCRIPTDIR /etc/apcupsd 101 | 102 | # PWRFAILDIR 103 | # Directory in which to write the powerfail flag file. This file 104 | # is created when apcupsd initiates a system shutdown and is 105 | # checked in the OS halt scripts to determine if a killpower 106 | # (turning off UPS output power) is required. 107 | PWRFAILDIR /etc/apcupsd 108 | 109 | # NOLOGINDIR 110 | # Directory in which to write the nologin file. The existence 111 | # of this flag file tells the OS to disallow new logins. 112 | NOLOGINDIR /etc 113 | 114 | 115 | # 116 | # ======== Configuration parameters used during power failures ========== 117 | # 118 | 119 | # The ONBATTERYDELAY is the time in seconds from when a power failure 120 | # is detected until we react to it with an onbattery event. 121 | # 122 | # This means that, apccontrol will be called with the powerout argument 123 | # immediately when a power failure is detected. However, the 124 | # onbattery argument is passed to apccontrol only after the 125 | # ONBATTERYDELAY time. If you don't want to be annoyed by short 126 | # powerfailures, make sure that apccontrol powerout does nothing 127 | # i.e. comment out the wall. 128 | ONBATTERYDELAY 6 129 | 130 | # 131 | # Note: BATTERYLEVEL, MINUTES, and TIMEOUT work in conjunction, so 132 | # the first that occurs will cause the initation of a shutdown. 133 | # 134 | 135 | # If during a power failure, the remaining battery percentage 136 | # (as reported by the UPS) is below or equal to BATTERYLEVEL, 137 | # apcupsd will initiate a system shutdown. 138 | BATTERYLEVEL 5 139 | 140 | # If during a power failure, the remaining runtime in minutes 141 | # (as calculated internally by the UPS) is below or equal to MINUTES, 142 | # apcupsd, will initiate a system shutdown. 143 | MINUTES 5 144 | 145 | # If during a power failure, the UPS has run on batteries for TIMEOUT 146 | # many seconds or longer, apcupsd will initiate a system shutdown. 147 | # A value of 0 disables this timer. 148 | # 149 | # Note, if you have a Smart UPS, you will most likely want to disable 150 | # this timer by setting it to zero. That way, you UPS will continue 151 | # on batteries until either the % charge remaing drops to or below BATTERYLEVEL, 152 | # or the remaining battery runtime drops to or below MINUTES. Of course, 153 | # if you are testing, setting this to 60 causes a quick system shutdown 154 | # if you pull the power plug. 155 | # If you have an older dumb UPS, you will want to set this to less than 156 | # the time you know you can run on batteries. 157 | TIMEOUT 0 158 | 159 | # Time in seconds between annoying users to signoff prior to 160 | # system shutdown. 0 disables. 161 | ANNOY 300 162 | 163 | # Initial delay after power failure before warning users to get 164 | # off the system. 165 | ANNOYDELAY 60 166 | 167 | # The condition which determines when users are prevented from 168 | # logging in during a power failure. 169 | # NOLOGON [ disable | timeout | percent | minutes | always ] 170 | NOLOGON disable 171 | 172 | # If KILLDELAY is non-zero, apcupsd will continue running after a 173 | # shutdown has been requested, and after the specified time in 174 | # seconds attempt to kill the power. This is for use on systems 175 | # where apcupsd cannot regain control after a shutdown. 176 | # KILLDELAY 0 disables 177 | KILLDELAY 0 178 | 179 | # 180 | # ==== Configuration statements for Network Information Server ==== 181 | # 182 | 183 | # NETSERVER [ on | off ] on enables, off disables the network 184 | # information server. If netstatus is on, a network information 185 | # server process will be started for serving the STATUS and 186 | # EVENT data over the network (used by CGI programs). 187 | NETSERVER on 188 | 189 | # NISIP 190 | # IP address on which NIS server will listen for incoming connections. 191 | # This is useful if your server is multi-homed (has more than one 192 | # network interface and IP address). Default value is 0.0.0.0 which 193 | # means any incoming request will be serviced. Alternatively, you can 194 | # configure this setting to any specific IP address of your server and 195 | # NIS will listen for connections only on that interface. Use the 196 | # loopback address (127.0.0.1) to accept connections only from the 197 | # local machine. 198 | NISIP 127.0.0.1 199 | 200 | # NISPORT default is 3551 as registered with the IANA 201 | # port to use for sending STATUS and EVENTS data over the network. 202 | # It is not used unless NETSERVER is on. If you change this port, 203 | # you will need to change the corresponding value in the cgi directory 204 | # and rebuild the cgi programs. 205 | NISPORT 3551 206 | 207 | # If you want the last few EVENTS to be available over the network 208 | # by the network information server, you must define an EVENTSFILE. 209 | EVENTSFILE /var/log/apcupsd.events 210 | 211 | # EVENTSFILEMAX 212 | # By default, the size of the EVENTSFILE will be not be allowed to exceed 213 | # 10 kilobytes. When the file grows beyond this limit, older EVENTS will 214 | # be removed from the beginning of the file (first in first out). The 215 | # parameter EVENTSFILEMAX can be set to a different kilobyte value, or set 216 | # to zero to allow the EVENTSFILE to grow without limit. 217 | EVENTSFILEMAX 10 218 | 219 | # 220 | # ========== Configuration statements used if sharing ============= 221 | # a UPS with more than one machine 222 | 223 | # 224 | # Remaining items are for ShareUPS (APC expansion card) ONLY 225 | # 226 | 227 | # UPSCLASS [ standalone | shareslave | sharemaster ] 228 | # Normally standalone unless you share an UPS using an APC ShareUPS 229 | # card. 230 | UPSCLASS standalone 231 | 232 | # UPSMODE [ disable | share ] 233 | # Normally disable unless you share an UPS using an APC ShareUPS card. 234 | UPSMODE disable 235 | 236 | # 237 | # ===== Configuration statements to control apcupsd system logging ======== 238 | # 239 | 240 | # Time interval in seconds between writing the STATUS file; 0 disables 241 | STATTIME 0 242 | 243 | # Location of STATUS file (written to only if STATTIME is non-zero) 244 | STATFILE /var/log/apcupsd.status 245 | 246 | # LOGSTATS [ on | off ] on enables, off disables 247 | # Note! This generates a lot of output, so if 248 | # you turn this on, be sure that the 249 | # file defined in syslog.conf for LOG_NOTICE is a named pipe. 250 | # You probably do not want this on. 251 | LOGSTATS off 252 | 253 | # Time interval in seconds between writing the DATA records to 254 | # the log file. 0 disables. 255 | DATATIME 0 256 | 257 | # FACILITY defines the logging facility (class) for logging to syslog. 258 | # If not specified, it defaults to "daemon". This is useful 259 | # if you want to separate the data logged by apcupsd from other 260 | # programs. 261 | #FACILITY DAEMON 262 | 263 | # 264 | # ========== Configuration statements used in updating the UPS EPROM ========= 265 | # 266 | 267 | # 268 | # These statements are used only by apctest when choosing "Set EEPROM with conf 269 | # file values" from the EEPROM menu. THESE STATEMENTS HAVE NO EFFECT ON APCUPSD. 270 | # 271 | 272 | # UPS name, max 8 characters 273 | #UPSNAME UPS_IDEN 274 | 275 | # Battery date - 8 characters 276 | #BATTDATE mm/dd/yy 277 | BATTDATE 07/08/19 278 | 279 | # Sensitivity to line voltage quality (H cause faster transfer to batteries) 280 | # SENSITIVITY H M L (default = H) 281 | #SENSITIVITY H 282 | 283 | # UPS delay after power return (seconds) 284 | # WAKEUP 000 060 180 300 (default = 0) 285 | #WAKEUP 60 286 | 287 | # UPS Grace period after request to power off (seconds) 288 | # SLEEP 020 180 300 600 (default = 20) 289 | #SLEEP 180 290 | 291 | # Low line voltage causing transfer to batteries 292 | # The permitted values depend on your model as defined by last letter 293 | # of FIRMWARE or APCMODEL. Some representative values are: 294 | # D 106 103 100 097 295 | # M 177 172 168 182 296 | # A 092 090 088 086 297 | # I 208 204 200 196 (default = 0 => not valid) 298 | #LOTRANSFER 208 299 | 300 | # High line voltage causing transfer to batteries 301 | # The permitted values depend on your model as defined by last letter 302 | # of FIRMWARE or APCMODEL. Some representative values are: 303 | # D 127 130 133 136 304 | # M 229 234 239 224 305 | # A 108 110 112 114 306 | # I 253 257 261 265 (default = 0 => not valid) 307 | #HITRANSFER 253 308 | 309 | # Battery charge needed to restore power 310 | # RETURNCHARGE 00 15 50 90 (default = 15) 311 | #RETURNCHARGE 15 312 | 313 | # Alarm delay 314 | # 0 = zero delay after pwr fail, T = power fail + 30 sec, L = low battery, N = never 315 | # BEEPSTATE 0 T L N (default = 0) 316 | BEEPSTATE N 317 | 318 | # Low battery warning delay in minutes 319 | # LOWBATT 02 05 07 10 (default = 02) 320 | #LOWBATT 2 321 | 322 | # UPS Output voltage when running on batteries 323 | # The permitted values depend on your model as defined by last letter 324 | # of FIRMWARE or APCMODEL. Some representative values are: 325 | # D 115 326 | # M 208 327 | # A 100 328 | # I 230 240 220 225 (default = 0 => not valid) 329 | #OUTPUTVOLTS 230 330 | 331 | # Self test interval in hours 336=2 weeks, 168=1 week, ON=at power on 332 | # SELFTEST 336 168 ON OFF (default = 336) 333 | #SELFTEST 336 334 | -------------------------------------------------------------------------------- /systems/x86_64-linux/Hevana/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Minisforum UM340 2 | { 3 | modulesPath, 4 | namespace, 5 | pkgs, 6 | ... 7 | }: 8 | let 9 | bootUUID = "D2E7-FE8F"; # The UUID of the boot partition. 10 | luksUUID = "7b9c756c-ba9d-43fc-b935-7c77a70f5f1b"; # The UUID of the locked LUKS partition. 11 | in 12 | { 13 | imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; 14 | 15 | boot = { 16 | kernelPackages = pkgs.linuxKernel.packages.linux_zen; 17 | kernelModules = [ "kvm-amd" ]; 18 | kernelParams = [ "nvme_core.default_ps_max_latency_us=0" ]; # (Allegedly) Fixes 84 degree reading on Samsung NVMe. See https://www.reddit.com/r/unRAID/comments/s4w79b/m2_drive_bad_temp_reading_seriously_84c/ 19 | 20 | initrd.kernelModules = [ 21 | "kvm-amd" 22 | "nvme" 23 | "xhci_pci" 24 | "ahci" 25 | "usb_storage" 26 | "usbhid" 27 | "sd_mod" 28 | ]; 29 | 30 | # Enable support for building ARM64 packages 31 | binfmt.emulatedSystems = [ "aarch64-linux" ]; 32 | }; 33 | 34 | # Configure the main filesystem. 35 | ${namespace}.filesystem = { 36 | enable = true; 37 | partitions = { 38 | boot = "/dev/disk/by-uuid/${bootUUID}"; 39 | luks = "/dev/disk/by-uuid/${luksUUID}"; 40 | }; 41 | swapFile = { 42 | enable = true; 43 | size = 16384; 44 | }; 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /systems/x86_64-linux/Khanda/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | options, 5 | namespace, 6 | ... 7 | }: 8 | 9 | let 10 | # Do not change this value! This tracks when NixOS was installed on your system. 11 | stateVersion = "24.05"; 12 | hostName = "Khanda"; 13 | in 14 | { 15 | imports = [ ./hardware-configuration.nix ]; 16 | 17 | system.stateVersion = stateVersion; 18 | networking.hostName = hostName; 19 | 20 | # Enable XWayland native scaling just for Khanda. 21 | # This is a workaround to get the Surface Pen working in Obsidian 22 | services.xserver.desktopManager.gnome.extraGSettingsOverrides = lib.mkForce '' 23 | [org.gnome.mutter] 24 | experimental-features = [ 'scale-monitor-framebuffer', 'xwayland-native-scaling', 'variable-refresh-rate' ] 25 | [org.gnome.shell] 26 | disable-extension-version-validation = true 27 | ''; 28 | 29 | ###*** Configure your system below this line. ***### 30 | # Configure the system. 31 | ${namespace} = { 32 | apps = { 33 | development.enable = true; 34 | media.enable = true; 35 | office.enable = true; 36 | recording.enable = true; 37 | social.enable = true; 38 | writing.enable = true; 39 | }; 40 | 41 | # Enable Secure Boot support. 42 | bootloader = { 43 | enable = true; 44 | secureboot.enable = true; 45 | tpm2.enable = true; 46 | }; 47 | 48 | # Enable GPU support. 49 | gpu.intel.enable = true; 50 | 51 | powerManagement.enable = true; 52 | 53 | services = { 54 | autoUpgrade = { 55 | enable = true; 56 | configDir = config.${namespace}.secrets.nixConfigFolder; 57 | onCalendar = "daily"; 58 | user = config.users.users.aires.name; 59 | }; 60 | syncthing = { 61 | enable = true; 62 | home = "/home/aires/.config/syncthing"; 63 | tray.enable = true; 64 | user = "aires"; 65 | web.enable = true; 66 | }; 67 | tor = { 68 | enable = true; 69 | browser.enable = true; 70 | snowflake-proxy.enable = true; 71 | }; 72 | virtualization = { 73 | enable = true; 74 | host = { 75 | enable = true; 76 | vmBuilds = { 77 | enable = true; 78 | cores = 4; 79 | ram = 3072; 80 | }; 81 | }; 82 | }; 83 | }; 84 | 85 | ui = { 86 | desktops.gnome.enable = true; 87 | flatpak = { 88 | # Enable Flatpak support. 89 | enable = true; 90 | 91 | # Define extra Flatpak packages to install. 92 | packages = options.${namespace}.ui.flatpak.packages.default ++ [ 93 | "org.keepassxc.KeePassXC" 94 | ]; 95 | 96 | useBindFS = true; 97 | }; 98 | }; 99 | 100 | users.aires.enable = true; 101 | }; 102 | } 103 | -------------------------------------------------------------------------------- /systems/x86_64-linux/Khanda/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Surface Pro 9 2 | { 3 | config, 4 | lib, 5 | pkgs, 6 | modulesPath, 7 | namespace, 8 | ... 9 | }: 10 | let 11 | bootUUID = "6579-B6CB"; # The UUID of the boot partition. 12 | luksUUID = "9936b186-96a5-4e43-9aba-0e0a0eb587df"; # The UUID of the locked LUKS partition. 13 | in 14 | { 15 | imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; 16 | 17 | boot = { 18 | # NOTE: Uncomment to use a default kernel and skip full kernel rebuilds 19 | #kernelPackages = lib.mkForce pkgs.linuxPackages_latest; 20 | 21 | kernelModules = [ "kvm-intel" ]; 22 | 23 | # NOTE: Loading the camera driver results in a kernel panic on 6.10 kernels. See https://github.com/linux-surface/linux-surface/issues/1516 24 | blacklistedKernelModules = [ 25 | "intel-ipu6" 26 | "intel-ipu6-isys" 27 | ]; 28 | 29 | # Enable antenna aggregation 30 | extraModprobeConfig = '' 31 | options iwlwifi 11n_disable=8 32 | ''; 33 | 34 | initrd.kernelModules = [ 35 | "kvm-intel" 36 | "surface_aggregator" 37 | "surface_aggregator_registry" 38 | "surface_aggregator_hub" 39 | "surface_hid_core" 40 | "surface_hid" 41 | "hid_multitouch" 42 | "8250_dw" 43 | "intel_lpss" 44 | "intel_lpss_pci" 45 | "xhci_pci" 46 | "thunderbolt" 47 | "nvme" 48 | "usb_storage" 49 | "sd_mod" 50 | "surface_kbd" 51 | "pinctrl_tigerlake" 52 | ]; 53 | 54 | kernelParams = [ 55 | "pci=hpiosize=0" # Prevent ACPI interrupt storm. See https://github.com/linux-surface/linux-surface/wiki/Surface-Pro-9#acpi-interrupt-storm 56 | "i915.perf_stream_paranoid=0" # Enable performance support. See https://wiki.archlinux.org/title/Intel_graphics#Enable_performance_support and https://github.com/NixOS/nixos-hardware/issues/1246 57 | ]; 58 | }; 59 | 60 | # Configure the main filesystem. 61 | ${namespace}.filesystem = { 62 | enable = true; 63 | partitions = { 64 | boot = "/dev/disk/by-uuid/${bootUUID}"; 65 | luks = "/dev/disk/by-uuid/${luksUUID}"; 66 | }; 67 | swapFile = { 68 | enable = true; 69 | size = 16384; 70 | }; 71 | }; 72 | 73 | hardware = { 74 | cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 75 | ipu6 = { 76 | enable = true; 77 | platform = "ipu6ep"; 78 | }; 79 | }; 80 | 81 | # Limit the number of cores Nix can use 82 | nix.settings.cores = 8; 83 | 84 | # Install/configure additional drivers, particularly for touch 85 | environment.systemPackages = with pkgs; [ libwacom-surface ]; 86 | } 87 | -------------------------------------------------------------------------------- /systems/x86_64-linux/Shura/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | options, 5 | namespace, 6 | pkgs, 7 | ... 8 | }: 9 | let 10 | # Do not change this value! This tracks when NixOS was installed on your system. 11 | stateVersion = "24.05"; 12 | hostName = "Shura"; 13 | 14 | # Use gremlin user's monitor configuration for GDM (desktop monitor primary). See https://discourse.nixos.org/t/gdm-monitor-configuration/6356/4 15 | monitorsXmlContent = builtins.readFile ./monitors.xml; 16 | monitorsConfig = pkgs.writeText "gdm_monitors.xml" monitorsXmlContent; 17 | in 18 | { 19 | imports = [ ./hardware-configuration.nix ]; 20 | 21 | system.stateVersion = stateVersion; 22 | networking.hostName = hostName; 23 | 24 | ${namespace} = { 25 | apps = { 26 | development.enable = true; 27 | gaming.enable = true; 28 | media = { 29 | enable = true; 30 | mixxx.enable = true; 31 | }; 32 | office.enable = true; 33 | recording.enable = true; 34 | social.enable = true; 35 | writing.enable = true; 36 | }; 37 | 38 | # Configure the bootloader. 39 | bootloader = { 40 | enable = true; 41 | secureboot.enable = true; 42 | tpm2.enable = true; 43 | }; 44 | 45 | # Enable GPU support. 46 | gpu.amd.enable = true; 47 | 48 | packages = with pkgs; [ 49 | keepassxc # Use native instead of Flatpak due to weird performance issues 50 | ]; 51 | 52 | # Keep one week of generations. 53 | nix.retention = "7d"; 54 | 55 | powerManagement.enable = true; 56 | 57 | services = { 58 | # Run daily automatic updates. 59 | autoUpgrade = { 60 | enable = true; 61 | configDir = config.${namespace}.secrets.nixConfigFolder; 62 | onCalendar = "daily"; 63 | operation = "boot"; 64 | user = config.users.users.aires.name; 65 | }; 66 | syncthing = { 67 | enable = true; 68 | home = "/home/aires/.config/syncthing"; 69 | tray.enable = true; 70 | user = "aires"; 71 | web.enable = true; 72 | }; 73 | tor = { 74 | enable = true; 75 | browser.enable = true; 76 | snowflake-proxy.enable = true; 77 | }; 78 | virtualization = { 79 | enable = true; 80 | host = { 81 | vmBuilds = { 82 | enable = true; 83 | cores = 4; 84 | ram = 4096; 85 | }; 86 | }; 87 | }; 88 | }; 89 | ui = { 90 | flatpak = { 91 | enable = true; 92 | useBindFS = true; 93 | packages = options.${namespace}.ui.flatpak.packages.default; 94 | }; 95 | desktops.gnome.enable = true; 96 | }; 97 | users = { 98 | aires.enable = true; 99 | gremlin.enable = true; 100 | }; 101 | }; 102 | 103 | # Mount Gremlin's Notes folder 104 | fileSystems."/home/gremlin/Documents/Notes" = { 105 | device = "/home/aires/Documents/Notes"; 106 | options = [ "bind" ]; 107 | }; 108 | 109 | # Install custom font 110 | fonts.packages = lib.mkIf config.${namespace}.users.gremlin.enable [ 111 | pkgs.${namespace}.freight-pro 112 | ]; 113 | 114 | systemd.tmpfiles.rules = [ 115 | # Use gremlin user's monitor config for GDM (defined above) 116 | "L+ /run/gdm/.config/monitors.xml - - - - ${monitorsConfig}" 117 | ]; 118 | 119 | } 120 | -------------------------------------------------------------------------------- /systems/x86_64-linux/Shura/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Lenovo Legion Slim 7 Gen 7 AMD (16ARHA7) 2 | { 3 | pkgs, 4 | modulesPath, 5 | namespace, 6 | ... 7 | }: 8 | let 9 | bootUUID = "AFCB-D880"; # The UUID of the boot partition. 10 | luksUUID = "bcf67e34-339e-40b9-8ffd-bec8f7f55248"; # The UUID of the locked LUKS partition. 11 | in 12 | { 13 | imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; 14 | 15 | # Configure the kernel. 16 | boot = { 17 | kernelPackages = pkgs.linuxKernel.packages.linux_zen; 18 | kernelModules = [ "kvm-amd" ]; 19 | 20 | # Hardware defaults detected by nixos-generate-configuration 21 | initrd.kernelModules = [ 22 | "kvm-amd" 23 | "nvme" 24 | "xhci_pci" 25 | "usbhid" 26 | "usb_storage" 27 | "sd_mod" 28 | "rtsx_pci_sdmmc" 29 | ]; 30 | }; 31 | 32 | # Configure the main filesystem. 33 | ${namespace}.filesystem = { 34 | enable = true; 35 | partitions = { 36 | boot = "/dev/disk/by-uuid/${bootUUID}"; 37 | luks = "/dev/disk/by-uuid/${luksUUID}"; 38 | }; 39 | swapFile = { 40 | enable = true; 41 | size = 16384; 42 | }; 43 | }; 44 | 45 | # Limit the number of cores Nix can use 46 | nix.settings.cores = 12; 47 | } 48 | -------------------------------------------------------------------------------- /systems/x86_64-linux/Shura/monitors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 0 5 | 0 6 | 1 7 | yes 8 | 9 | 10 | DP-2 11 | MSI 12 | MSI MAG401QR 13 | EA5H013900434 14 | 15 | 16 | 3440 17 | 1440 18 | 144.000 19 | 20 | 21 | 22 | 23 | 24 | eDP-2 25 | BOE 26 | 0x0a9b 27 | 0x00000000 28 | 29 | 30 | 31 | 32 | 33 | 0 34 | 0 35 | 1 36 | yes 37 | 38 | 39 | DP-1 40 | MSI 41 | MSI MAG401QR 42 | EA5H013900434 43 | 44 | 45 | 3440 46 | 1440 47 | 144.000 48 | 49 | 50 | 51 | 52 | 53 | eDP-2 54 | BOE 55 | 0x0a9b 56 | 0x00000000 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /systems/x86_64-linux/gremlin-lab/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | namespace, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | let 9 | # Do not change this value! This tracks when NixOS was installed on your system. 10 | stateVersion = "24.11"; 11 | hostName = "gremlin-lab"; 12 | in 13 | { 14 | imports = [ ./hardware-configuration.nix ]; 15 | 16 | system.stateVersion = stateVersion; 17 | networking.hostName = hostName; 18 | 19 | # Functionality for Kubernetes in Docker 20 | virtualisation.docker = { 21 | enable = true; 22 | storageDriver = "btrfs"; 23 | autoPrune.enable = true; 24 | }; 25 | environment.systemPackages = with pkgs.unstable; [ 26 | kind 27 | kubectl 28 | kubernetes-helm 29 | skaffold 30 | ]; 31 | networking.firewall = { 32 | allowedTCPPorts = [ 80 ]; 33 | # Required to get container <-> host networking. 34 | # See https://github.com/NixOS/nixpkgs/issues/298165 35 | checkReversePath = false; 36 | }; 37 | 38 | # Configure the system. 39 | ${namespace} = { 40 | # Enable Secure Boot support. 41 | bootloader = { 42 | enable = true; 43 | secureboot.enable = true; 44 | tpm2.enable = true; 45 | }; 46 | 47 | # Enable GPU support. 48 | gpu = { 49 | intel.enable = true; 50 | nvidia = { 51 | enable = true; 52 | hybrid = { 53 | enable = true; 54 | busIDs.nvidia = "PCI:3:0:0"; 55 | busIDs.intel = "PCI:0:2:0"; 56 | }; 57 | }; 58 | }; 59 | 60 | services = { 61 | autoUpgrade = { 62 | enable = true; 63 | pushUpdates = false; 64 | configDir = config.${namespace}.secrets.nixConfigFolder; 65 | onCalendar = "daily"; 66 | user = config.users.users.aires.name; 67 | }; 68 | ssh = { 69 | enable = true; 70 | ports = [ config.${namespace}.secrets.hosts.hevana.ssh.port ]; 71 | }; 72 | virtualization.host = { 73 | enable = true; 74 | vmBuilds = { 75 | enable = true; 76 | cores = 3; 77 | ram = 3072; 78 | }; 79 | }; 80 | }; 81 | 82 | users.aires.enable = true; 83 | }; 84 | } 85 | -------------------------------------------------------------------------------- /systems/x86_64-linux/gremlin-lab/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # MSI Prestge 15 2 | { 3 | config, 4 | lib, 5 | modulesPath, 6 | namespace, 7 | ... 8 | }: 9 | 10 | let 11 | bootUUID = "BB32-0650"; # The UUID of the boot partition. 12 | luksUUID = "688c96d9-61a0-4c26-9504-771f6c489c9c"; # The UUID of the locked LUKS partition. 13 | in 14 | { 15 | imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; 16 | 17 | boot = { 18 | # Enable antenna aggregation 19 | extraModprobeConfig = '' 20 | options iwlwifi 11n_disable=8 21 | ''; 22 | 23 | initrd.availableKernelModules = [ 24 | "xhci_pci" 25 | "nvme" 26 | "usb_storage" 27 | "sd_mod" 28 | "sdhci_pci" 29 | ]; 30 | kernelModules = [ "kvm-intel" ]; 31 | extraModulePackages = [ ]; 32 | 33 | # Enable support for building ARM64 packages 34 | binfmt.emulatedSystems = [ "aarch64-linux" ]; 35 | }; 36 | 37 | # Configure the main filesystem. 38 | ${namespace}.filesystem = { 39 | enable = true; 40 | partitions = { 41 | boot = "/dev/disk/by-uuid/${bootUUID}"; 42 | luks = "/dev/disk/by-uuid/${luksUUID}"; 43 | }; 44 | swapFile = { 45 | enable = true; 46 | size = 16384; 47 | }; 48 | }; 49 | 50 | # Disable suspend 51 | systemd.targets = { 52 | sleep.enable = false; 53 | suspend.enable = false; 54 | hibernate.enable = false; 55 | hybrid-sleep.enable = false; 56 | }; 57 | services = { 58 | xserver.displayManager.gdm.autoSuspend = 59 | lib.mkIf config.${namespace}.ui.desktops.gnome.enable 60 | false; 61 | logind = { 62 | lidSwitch = "lock"; 63 | lidSwitchDocked = "lock"; 64 | }; 65 | }; 66 | services.upower.ignoreLid = true; 67 | 68 | # Enable CPU microde updates 69 | hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 70 | } 71 | -------------------------------------------------------------------------------- /templates/module/default.nix: -------------------------------------------------------------------------------- 1 | # This is an example of a blank module. 2 | { 3 | config, 4 | lib, 5 | namespace, 6 | ... 7 | }: 8 | 9 | let 10 | cfg = config.${namespace}.services.myModule; 11 | in 12 | { 13 | options = { 14 | ${namespace}.services.myModule = { 15 | enable = lib.mkEnableOption "Enables this example module."; 16 | attributes = lib.mkOption { 17 | default = { }; 18 | type = lib.types.attrs; 19 | description = "An example of an attributes option."; 20 | }; 21 | string = lib.mkOption { 22 | default = ""; 23 | type = lib.types.str; 24 | description = "An example of a string option."; 25 | }; 26 | list = lib.mkOption { 27 | default = [ ]; 28 | type = lib.types.listOf lib.types.int; 29 | description = "An example of a list (of integers) option."; 30 | }; 31 | enum = lib.mkOption { 32 | default = "one"; 33 | type = lib.types.enum [ 34 | "one" 35 | "two" 36 | ]; 37 | description = "An example of an enum option."; 38 | }; 39 | }; 40 | 41 | }; 42 | 43 | config = lib.mkIf cfg.enable { 44 | # Define the changes applied by this module here. 45 | }; 46 | 47 | systemd.services = { 48 | # Tell systemd to wait for the module's configuration directory to be available before starting the service. 49 | myModule.unitConfig.RequiresMountsFor = cfg.home; 50 | 51 | # Tell Nginx to wait for the service to be available before coming online. 52 | nginx.wants = [ config.systemd.services.myModule.name ]; 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /templates/systems/default.nix: -------------------------------------------------------------------------------- 1 | # Template file for configuring a new host 2 | { 3 | namespace, 4 | ... 5 | }: 6 | let 7 | # Do not change this value! This tracks when NixOS was installed on your system. 8 | stateVersion = "24.11"; 9 | # The hostname for this system. 10 | hostName = "myHost"; 11 | in 12 | { 13 | # Generate hardware-configuration.nix by running this command on the host: 14 | # $ nixos-generate-config 15 | imports = [ ./hardware-configuration.nix ]; 16 | 17 | system.stateVersion = stateVersion; 18 | networking.hostName = hostName; 19 | 20 | # Main system configuration happens here. 21 | config.${namespace} = { 22 | apps = { 23 | # Define applications here 24 | }; 25 | services = { 26 | # Define services here 27 | }; 28 | users.aires = { 29 | enable = true; 30 | services.syncthing = { 31 | enable = true; 32 | home = "/home/aires/.config/syncthing"; 33 | }; 34 | }; 35 | }; 36 | 37 | # Additional configuration options go here 38 | } 39 | -------------------------------------------------------------------------------- /templates/systems/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Template for setting a new host's hardware configuration 2 | { 3 | modulesPath, 4 | namespace, 5 | ... 6 | }: 7 | let 8 | bootUUID = "ABCD-1234"; # The UUID of the boot partition. 9 | luksUUID = "1408f9cf-68b8-4063-b919-48edde3329a5"; # The UUID of the encrypted LUKS partition. 10 | in 11 | { 12 | imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; 13 | 14 | # Configure the kernel. 15 | boot = { 16 | # Run `nixos-generate-config --no-filesystems` to generate a baseline hardware configuration. 17 | initrd.availableKernelModules = [ 18 | "nvme" 19 | "xhci_pci" 20 | "usbhid" 21 | "usb_storage" 22 | "sd_mod" 23 | ]; 24 | 25 | kernelModules = [ ]; 26 | }; 27 | 28 | # Configure the main filesystem. 29 | ${namespace}.filesystem = { 30 | enable = true; 31 | partitions = { 32 | boot = "/dev/disk/by-uuid/${bootUUID}"; 33 | luks = "/dev/disk/by-uuid/${luksUUID}"; 34 | }; 35 | swapFile = { 36 | enable = true; 37 | size = 16384; 38 | }; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /treefmt.nix: -------------------------------------------------------------------------------- 1 | # Configure formatter for .nix and other repo files 2 | { pkgs, ... }: 3 | { 4 | projectRootFile = "flake.nix"; 5 | 6 | programs = { 7 | beautysh.enable = true; 8 | deadnix = { 9 | enable = true; 10 | no-lambda-pattern-names = true; 11 | }; 12 | nixfmt = { 13 | enable = true; 14 | package = pkgs.nixfmt-rfc-style; 15 | }; 16 | prettier.enable = true; 17 | yamlfmt.enable = true; 18 | }; 19 | 20 | settings = { 21 | on-unmatched = "info"; 22 | }; 23 | } 24 | --------------------------------------------------------------------------------