From 0a5754541bb01e96021ca7ee74f1256a8ee68bc4 Mon Sep 17 00:00:00 2001 From: tdback Date: Sat, 21 Dec 2024 15:32:13 -0500 Subject: initial commit to self-hosted git --- LICENSE | 21 ++++ README.md | 24 +++++ flake.lock | 148 +++++++++++++++++++++++++++++ flake.nix | 78 +++++++++++++++ hosts/eden/default.nix | 52 ++++++++++ hosts/eden/hardware.nix | 38 ++++++++ hosts/hive/default.nix | 44 +++++++++ hosts/hive/hardware.nix | 39 ++++++++ hosts/oasis/default.nix | 51 ++++++++++ hosts/oasis/hardware.nix | 39 ++++++++ hosts/raindog/default.nix | 44 +++++++++ hosts/raindog/hardware.nix | 38 ++++++++ hosts/sparrow/default.nix | 43 +++++++++ hosts/sparrow/hardware.nix | 41 ++++++++ hosts/woodpecker/default.nix | 39 ++++++++ hosts/woodpecker/hardware.nix | 44 +++++++++ modules/containers/freshrss/default.nix | 30 ++++++ modules/containers/jellyfin/default.nix | 27 ++++++ modules/containers/pinchflat/default.nix | 23 +++++ modules/containers/vaultwarden/default.nix | 34 +++++++ modules/containers/watchtower/default.nix | 15 +++ modules/customs/cgit/default.nix | 134 ++++++++++++++++++++++++++ modules/customs/soft-serve/default.nix | 60 ++++++++++++ modules/default.nix | 26 +++++ modules/profiles/common/default.nix | 46 +++++++++ modules/profiles/fstrim/default.nix | 7 ++ modules/profiles/libvirtd/default.nix | 21 ++++ modules/profiles/nvidia/default.nix | 16 ++++ modules/profiles/pipewire/default.nix | 13 +++ modules/profiles/podman/default.nix | 12 +++ modules/profiles/security/default.nix | 16 ++++ modules/profiles/share/default.nix | 11 +++ modules/profiles/steam/default.nix | 8 ++ modules/profiles/upgrade/default.nix | 30 ++++++ modules/profiles/vpn/default.nix | 18 ++++ modules/profiles/wireguard/default.nix | 15 +++ modules/profiles/wireshark/default.nix | 14 +++ modules/profiles/x11/default.nix | 33 +++++++ modules/profiles/zfs/default.nix | 28 ++++++ modules/retired/forgejo/default.nix | 65 +++++++++++++ modules/retired/kavita/default.nix | 28 ++++++ modules/retired/mealie/default.nix | 22 +++++ modules/retired/mumble/default.nix | 11 +++ modules/retired/navidrome/default.nix | 31 ++++++ modules/retired/pihole/default.nix | 52 ++++++++++ modules/retired/stirling-pdf/default.nix | 23 +++++ modules/retired/xonotic/default.nix | 25 +++++ modules/scripts/motd/default.nix | 99 +++++++++++++++++++ modules/scripts/pushover/default.nix | 47 +++++++++ modules/services/blocky/default.nix | 93 ++++++++++++++++++ modules/services/cgit/default.nix | 28 ++++++ modules/services/fediverse/default.nix | 26 +++++ modules/services/immich/default.nix | 18 ++++ modules/services/proxy/default.nix | 9 ++ modules/services/searx/default.nix | 33 +++++++ modules/services/sftpgo/default.nix | 21 ++++ modules/services/ssh/default.nix | 17 ++++ modules/services/web/default.nix | 10 ++ modules/users/default.nix | 15 +++ secrets/pushoverAppToken.age | 13 +++ secrets/pushoverUserToken.age | Bin 0 -> 683 bytes secrets/secrets.nix | 19 ++++ users/default.nix | 3 + users/tdback/default.nix | 32 +++++++ users/tdback/desktop.nix | 70 ++++++++++++++ users/tdback/modules/alacritty/default.nix | 71 ++++++++++++++ users/tdback/modules/dunst/default.nix | 30 ++++++ users/tdback/modules/email/default.nix | 78 +++++++++++++++ users/tdback/modules/firefox/default.nix | 101 ++++++++++++++++++++ users/tdback/modules/git/default.nix | 9 ++ users/tdback/modules/irc/default.nix | 30 ++++++ users/tdback/modules/mpd/default.nix | 34 +++++++ users/tdback/modules/ncmpcpp/default.nix | 65 +++++++++++++ users/tdback/modules/neomutt/default.nix | 69 ++++++++++++++ users/tdback/modules/polybar/default.nix | 112 ++++++++++++++++++++++ users/tdback/modules/rofi/default.nix | 81 ++++++++++++++++ users/tdback/modules/shell/default.nix | 59 ++++++++++++ users/tdback/modules/tmux/default.nix | 52 ++++++++++ users/tdback/modules/x11/default.nix | 94 ++++++++++++++++++ 79 files changed, 3115 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 hosts/eden/default.nix create mode 100644 hosts/eden/hardware.nix create mode 100644 hosts/hive/default.nix create mode 100644 hosts/hive/hardware.nix create mode 100644 hosts/oasis/default.nix create mode 100644 hosts/oasis/hardware.nix create mode 100644 hosts/raindog/default.nix create mode 100644 hosts/raindog/hardware.nix create mode 100644 hosts/sparrow/default.nix create mode 100644 hosts/sparrow/hardware.nix create mode 100644 hosts/woodpecker/default.nix create mode 100644 hosts/woodpecker/hardware.nix create mode 100644 modules/containers/freshrss/default.nix create mode 100644 modules/containers/jellyfin/default.nix create mode 100644 modules/containers/pinchflat/default.nix create mode 100644 modules/containers/vaultwarden/default.nix create mode 100644 modules/containers/watchtower/default.nix create mode 100644 modules/customs/cgit/default.nix create mode 100644 modules/customs/soft-serve/default.nix create mode 100644 modules/default.nix create mode 100644 modules/profiles/common/default.nix create mode 100644 modules/profiles/fstrim/default.nix create mode 100644 modules/profiles/libvirtd/default.nix create mode 100644 modules/profiles/nvidia/default.nix create mode 100644 modules/profiles/pipewire/default.nix create mode 100644 modules/profiles/podman/default.nix create mode 100644 modules/profiles/security/default.nix create mode 100644 modules/profiles/share/default.nix create mode 100644 modules/profiles/steam/default.nix create mode 100644 modules/profiles/upgrade/default.nix create mode 100644 modules/profiles/vpn/default.nix create mode 100644 modules/profiles/wireguard/default.nix create mode 100644 modules/profiles/wireshark/default.nix create mode 100644 modules/profiles/x11/default.nix create mode 100644 modules/profiles/zfs/default.nix create mode 100644 modules/retired/forgejo/default.nix create mode 100644 modules/retired/kavita/default.nix create mode 100644 modules/retired/mealie/default.nix create mode 100644 modules/retired/mumble/default.nix create mode 100644 modules/retired/navidrome/default.nix create mode 100644 modules/retired/pihole/default.nix create mode 100644 modules/retired/stirling-pdf/default.nix create mode 100644 modules/retired/xonotic/default.nix create mode 100644 modules/scripts/motd/default.nix create mode 100644 modules/scripts/pushover/default.nix create mode 100644 modules/services/blocky/default.nix create mode 100644 modules/services/cgit/default.nix create mode 100644 modules/services/fediverse/default.nix create mode 100644 modules/services/immich/default.nix create mode 100644 modules/services/proxy/default.nix create mode 100644 modules/services/searx/default.nix create mode 100644 modules/services/sftpgo/default.nix create mode 100644 modules/services/ssh/default.nix create mode 100644 modules/services/web/default.nix create mode 100644 modules/users/default.nix create mode 100644 secrets/pushoverAppToken.age create mode 100644 secrets/pushoverUserToken.age create mode 100644 secrets/secrets.nix create mode 100644 users/default.nix create mode 100644 users/tdback/default.nix create mode 100644 users/tdback/desktop.nix create mode 100644 users/tdback/modules/alacritty/default.nix create mode 100644 users/tdback/modules/dunst/default.nix create mode 100644 users/tdback/modules/email/default.nix create mode 100644 users/tdback/modules/firefox/default.nix create mode 100644 users/tdback/modules/git/default.nix create mode 100644 users/tdback/modules/irc/default.nix create mode 100644 users/tdback/modules/mpd/default.nix create mode 100644 users/tdback/modules/ncmpcpp/default.nix create mode 100644 users/tdback/modules/neomutt/default.nix create mode 100644 users/tdback/modules/polybar/default.nix create mode 100644 users/tdback/modules/rofi/default.nix create mode 100644 users/tdback/modules/shell/default.nix create mode 100644 users/tdback/modules/tmux/default.nix create mode 100644 users/tdback/modules/x11/default.nix diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f177f32 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Tyler Dunneback + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..4fc6aab --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# Flake Layout +- `hosts/` + - `eden/` - my media server and makeshift NAS. Media is stored in a RAID-Z2 + ZFS pool for redundancy, with a caching drive for increased read performance. + - `hive/` - my "social" server, responsible for hosting my fediverse server + and a few websites. + - `oasis/` - my SFTP and git forge server. + - `raindog/` - my DNS server and SearXNG host. The name is inspired by one of + my beautiful dogs, Rainey. + - `sparrow/` - my laptop. + - `woodpecker/` - my desktop. +- `modules/` + - `containers/` - podman/docker container configurations. + - `customs/` - custom modules or overrides for existing modules in nixpkgs. + - `profiles/` - configurations intended to be imported into a given system. + - `retired/` - modules or configurations I don't use anymore, but want to + keep around for reference. + - `scripts/` - custom shell scripts wrapped in nix (primarily for servers). + - `services/` - service/daemon configurations. + - `users/` - default user configuration for my systems. +- `secrets/` - [age](https://github.com/FiloSottile/age) encrypted secrets, via + [agenix](https://github.com/ryantm/agenix) +- `users/` - [home-manager](https://github.com/nix-community/home-manager) + configuration per user. diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..b5ffc9d --- /dev/null +++ b/flake.lock @@ -0,0 +1,148 @@ +{ + "nodes": { + "agenix": { + "inputs": { + "darwin": "darwin", + "home-manager": "home-manager", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1723293904, + "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=", + "owner": "ryantm", + "repo": "agenix", + "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "darwin": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1700795494, + "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d", + "type": "github" + }, + "original": { + "owner": "lnl7", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1703113217, + "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733050161, + "narHash": "sha256-lYnT+EYE47f5yY3KS/Kd4pJ6CO9fhCqumkYYkQ3TK20=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "62d536255879be574ebfe9b87c4ac194febf47c5", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "release-24.11", + "repo": "home-manager", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1733120037, + "narHash": "sha256-En+gSoVJ3iQKPDU1FHrR6zIxSLXKjzKY+pnh9tt+Yts=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "f9f0d5c5380be0a599b1fb54641fa99af8281539", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-24.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1733212471, + "narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "55d15ad12a74eb7d4646254e13638ad0c4128776", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "agenix": "agenix", + "home-manager": "home-manager_2", + "nixpkgs": "nixpkgs", + "nixpkgs-unstable": "nixpkgs-unstable" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..30d31b3 --- /dev/null +++ b/flake.nix @@ -0,0 +1,78 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; + nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; + home-manager = { + url = "github:nix-community/home-manager/release-24.11"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + agenix = { + url = "github:ryantm/agenix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { ... }@inputs: + let + helpers = import ./modules { inherit inputs; }; + inherit (helpers) mergeSets makeSystem; + in + { + nixosConfigurations = mergeSets [ + (makeSystem "woodpecker" inputs.nixpkgs [ + { + type = "profiles"; + modules = [ "common" "fstrim" "libvirtd" "nvidia" "pipewire" "security" "steam" "wireshark" "x11" ]; + } + ]) + (makeSystem "sparrow" inputs.nixpkgs [ + { + type = "profiles"; + modules = [ "common" "pipewire" "security" "vpn" "x11" ]; + } + ]) + (makeSystem "raindog" inputs.nixpkgs [ + { + type = "profiles"; + modules = [ "common" "security" "upgrade" ]; + } + { type = "scripts"; modules = [ "motd" "pushover" ]; } + { type = "services"; modules = [ "blocky" "searx" "ssh" ]; } + ]) + (makeSystem "oasis" inputs.nixpkgs [ + { + type = "profiles"; + modules = [ "common" "podman" "security" "upgrade" "wireguard" "zfs" ]; + } + { type = "scripts"; modules = [ "motd" "pushover" ]; } + { + type = "services"; + modules = [ "cgit" "proxy" "sftpgo" "ssh" ]; + } + ]) + (makeSystem "hive" inputs.nixpkgs [ + { + type = "profiles"; + modules = [ "common" "security" "upgrade" "wireguard" ]; + } + { type = "scripts"; modules = [ "motd" "pushover" ]; } + { + type = "services"; + modules = [ "fediverse" "proxy" "ssh" "web" ]; + } + ]) + (makeSystem "eden" inputs.nixpkgs [ + { + type = "containers"; + modules = [ "freshrss" "jellyfin" "pinchflat" "vaultwarden" "watchtower" ]; + } + { + type = "profiles"; + modules = [ "common" "podman" "security" "share" "upgrade" "wireguard" "zfs" ]; + } + { type = "scripts"; modules = [ "motd" "pushover" ]; } + { type = "services"; modules = [ "immich" "proxy" "ssh" ]; } + ]) + ]; + }; +} diff --git a/hosts/eden/default.nix b/hosts/eden/default.nix new file mode 100644 index 0000000..02be58f --- /dev/null +++ b/hosts/eden/default.nix @@ -0,0 +1,52 @@ +{ lib, inputs, ... }: +{ + system.stateVersion = "24.05"; + + imports = [ ./hardware.nix ]; + + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + users = import "${inputs.self}/users"; + extraSpecialArgs = { + inherit inputs; + headless = true; + }; + }; + + networking = { + hostName = "eden"; + hostId = "bd03847d"; # Required for ZFS support. + nameservers = [ "10.44.0.1" ]; + defaultGateway.address = "10.44.0.1"; + interfaces.eno1 = { + useDHCP = false; + ipv4.addresses = [{ + address = "10.44.4.101"; + prefixLength = 16; + }]; + }; + }; + + time.timeZone = "America/Detroit"; + + boot = { + loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + zfs.extraPools = [ "lagoon" ]; + }; + + motd = { + networkInterfaces = lib.lists.singleton "eno1"; + servicesToCheck = [ + "caddy" + "immich-machine-learning" + "immich-server" + "postgresql" + "redis-immich" + "zfs-zed" + ]; + }; +} diff --git a/hosts/eden/hardware.nix b/hosts/eden/hardware.nix new file mode 100644 index 0000000..00210c4 --- /dev/null +++ b/hosts/eden/hardware.nix @@ -0,0 +1,38 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "sr_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/f3bedccb-3f2b-49ae-9be4-5ec9fe683027"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/78C3-E7F8"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.eno1.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/hive/default.nix b/hosts/hive/default.nix new file mode 100644 index 0000000..c164b92 --- /dev/null +++ b/hosts/hive/default.nix @@ -0,0 +1,44 @@ +{ lib, inputs, ... }: +{ + system.stateVersion = "24.05"; + + imports = [ ./hardware.nix ]; + + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + users = import "${inputs.self}/users"; + extraSpecialArgs = { + inherit inputs; + headless = true; + }; + }; + + networking = { + hostName = "hive"; + nameservers = [ "10.44.0.1" ]; + defaultGateway.address = "10.44.0.1"; + interfaces.eno1 = { + useDHCP = false; + ipv4.addresses = [{ + address = "10.44.4.102"; + prefixLength = 16; + }]; + }; + }; + + time.timeZone = "America/Detroit"; + + boot.loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + + motd = { + networkInterfaces = lib.lists.singleton "eno1"; + servicesToCheck = [ + "caddy" + "gotosocial" + ]; + }; +} diff --git a/hosts/hive/hardware.nix b/hosts/hive/hardware.nix new file mode 100644 index 0000000..9e7a2f0 --- /dev/null +++ b/hosts/hive/hardware.nix @@ -0,0 +1,39 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "ehci_pci" "usb_storage" "usbhid" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/e336b96d-b3b4-4098-a0ca-9001fd381f88"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/F804-40A9"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.eno1.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp6s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/oasis/default.nix b/hosts/oasis/default.nix new file mode 100644 index 0000000..8ef44f9 --- /dev/null +++ b/hosts/oasis/default.nix @@ -0,0 +1,51 @@ +{ lib, inputs, ... }: +{ + system.stateVersion = "24.05"; + + imports = [ ./hardware.nix ]; + + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + users = import "${inputs.self}/users"; + extraSpecialArgs = { + inherit inputs; + headless = true; + }; + }; + + networking = { + hostName = "oasis"; + hostId = "7a7d723a"; # Required for ZFS support. + nameservers = [ "10.44.0.1" ]; + defaultGateway.address = "10.44.0.1"; + interfaces.enp59s0 = { + useDHCP = false; + ipv4.addresses = [{ + address = "10.44.4.103"; + prefixLength = 16; + }]; + }; + }; + + time.timeZone = "America/Detroit"; + + boot = { + loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + zfs.extraPools = [ "tank" ]; + }; + + motd = { + networkInterfaces = lib.lists.singleton "enp59s0"; + servicesToCheck = [ + "caddy" + "sftpgo" + "zfs-zed" + ]; + }; + + services.sftpgo.dataDir = "/tank/sftpgo"; +} diff --git a/hosts/oasis/hardware.nix b/hosts/oasis/hardware.nix new file mode 100644 index 0000000..3870379 --- /dev/null +++ b/hosts/oasis/hardware.nix @@ -0,0 +1,39 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "sd_mod" "sdhci_pci" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/3e333010-7dae-47cf-9288-85d58ddda699"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/8430-1FF8"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp59s0.useDHCP = lib.mkDefault true; + # networking.interfaces.wlo1.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/raindog/default.nix b/hosts/raindog/default.nix new file mode 100644 index 0000000..0eb2d30 --- /dev/null +++ b/hosts/raindog/default.nix @@ -0,0 +1,44 @@ +{ lib, inputs, ... }: +{ + system.stateVersion = "24.05"; + + imports = [ ./hardware.nix ]; + + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + users = import "${inputs.self}/users"; + extraSpecialArgs = { + inherit inputs; + headless = true; + }; + }; + + networking = { + hostName = "raindog"; + nameservers = [ "10.44.0.1" ]; + defaultGateway.address = "10.44.0.1"; + interfaces.eno1 = { + useDHCP = false; + ipv4.addresses = [{ + address = "10.44.4.100"; + prefixLength = 16; + }]; + }; + }; + + time.timeZone = "America/Detroit"; + + boot.loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + + motd = { + networkInterfaces = lib.lists.singleton "eno1"; + servicesToCheck = [ + "blocky" + "searx" + ]; + }; +} diff --git a/hosts/raindog/hardware.nix b/hosts/raindog/hardware.nix new file mode 100644 index 0000000..b2a5571 --- /dev/null +++ b/hosts/raindog/hardware.nix @@ -0,0 +1,38 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/d62103eb-e154-4b71-b813-54ca76815a80"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/5972-1878"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.eno1.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/sparrow/default.nix b/hosts/sparrow/default.nix new file mode 100644 index 0000000..824f5df --- /dev/null +++ b/hosts/sparrow/default.nix @@ -0,0 +1,43 @@ +{ inputs, pkgs, ... }: +{ + system.stateVersion = "24.05"; + + imports = [ ./hardware.nix ]; + + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + users = import "${inputs.self}/users"; + extraSpecialArgs = { + inherit inputs; + headless = false; + }; + }; + + networking = { + hostName = "sparrow"; + networkmanager.enable = true; + }; + + time.timeZone = "America/Detroit"; + + boot = { + loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + binfmt.emulatedSystems = [ "aarch64-linux" "riscv64-linux" ]; + }; + + # Since I don't always carry my split keyboard, remap CAPS to left CTRL. + console.useXkbConfig = true; + services = { + xserver.xkb.options = "ctrl:swapcaps"; + libinput.enable = true; + }; + + environment.systemPackages = with pkgs; [ + acpi + unstable.qbittorrent + ]; +} diff --git a/hosts/sparrow/hardware.nix b/hosts/sparrow/hardware.nix new file mode 100644 index 0000000..d40b232 --- /dev/null +++ b/hosts/sparrow/hardware.nix @@ -0,0 +1,41 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/d296f7a3-68d2-406f-963d-8ec39ab0ea64"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/B159-723B"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + + swapDevices = [{ + device = "/.swapfile"; + }]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp0s31f6.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp59s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/woodpecker/default.nix b/hosts/woodpecker/default.nix new file mode 100644 index 0000000..4f1dc2f --- /dev/null +++ b/hosts/woodpecker/default.nix @@ -0,0 +1,39 @@ +{ inputs, ... }: +{ + system.stateVersion = "24.05"; + + imports = [ ./hardware.nix ]; + + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + users = import "${inputs.self}/users"; + extraSpecialArgs = { + inherit inputs; + headless = false; + }; + }; + + networking = { + hostName = "woodpecker"; + nameservers = [ "10.44.0.1" ]; + defaultGateway.address = "10.44.0.1"; + interfaces.enp42s0 = { + useDHCP = false; + ipv4.addresses = [{ + address = "10.44.4.50"; + prefixLength = 16; + }]; + }; + }; + + time.timeZone = "America/Detroit"; + + boot = { + loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + binfmt.emulatedSystems = [ "aarch64-linux" "riscv64-linux" ]; + }; +} diff --git a/hosts/woodpecker/hardware.nix b/hosts/woodpecker/hardware.nix new file mode 100644 index 0000000..3fc71e9 --- /dev/null +++ b/hosts/woodpecker/hardware.nix @@ -0,0 +1,44 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/90ec7fc1-192e-4bb5-9bb5-5e2776435f8d"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/3A26-C3FB"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + + fileSystems."/home" = + { device = "/dev/disk/by-uuid/cd7e081e-cd0b-4dc5-b41c-8dda26437a78"; + fsType = "ext4"; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp42s0.useDHCP = lib.mkDefault true; + # networking.interfaces.enp5s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/modules/containers/freshrss/default.nix b/modules/containers/freshrss/default.nix new file mode 100644 index 0000000..3854a8e --- /dev/null +++ b/modules/containers/freshrss/default.nix @@ -0,0 +1,30 @@ +{ lib, ... }: +let + directory = "/opt/freshrss"; + port = "8888"; +in +{ + systemd.tmpfiles.rules = + map (x: "d ${x} 0755 share share - -") (lib.lists.singleton directory); + + virtualisation.oci-containers.containers.freshrss = { + image = "freshrss/freshrss:latest"; + autoStart = true; + ports = [ + "${port}:80" + ]; + volumes = [ + "${directory}/data:/var/www/FreshRSS/data" + "${directory}/extensions:/var/www/FreshRSS/extensions" + ]; + environment = { + TZ = "America/Detroit"; + CRON_MIN = "*/20"; + }; + }; + + services.caddy.virtualHosts."fresh.brownbread.net".extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:${port} + ''; +} diff --git a/modules/containers/jellyfin/default.nix b/modules/containers/jellyfin/default.nix new file mode 100644 index 0000000..96b6deb --- /dev/null +++ b/modules/containers/jellyfin/default.nix @@ -0,0 +1,27 @@ +{ lib, ... }: +let + directory = "/opt/jellyfin"; +in +{ + systemd.tmpfiles.rules = + map (x: "d ${x} 0755 share share - -") (lib.lists.singleton directory); + + virtualisation.oci-containers.containers.jellyfin = { + image = "jellyfin/jellyfin:latest"; + autoStart = true; + user = "994:994"; + ports = [ + "8096:8096/tcp" + ]; + volumes = [ + "${directory}/config:/config" + "${directory}/cache:/cache" + "/lagoon/media:/media" + ]; + }; + + services.caddy.virtualHosts."buttered.brownbread.net".extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:8096 + ''; +} diff --git a/modules/containers/pinchflat/default.nix b/modules/containers/pinchflat/default.nix new file mode 100644 index 0000000..9428c32 --- /dev/null +++ b/modules/containers/pinchflat/default.nix @@ -0,0 +1,23 @@ +{ ... }: +let + directories = [ + "/opt/pinchflat" + ]; +in +{ + systemd.tmpfiles.rules = map (x: "d ${x} 0755 share share - -") directories; + virtualisation.oci-containers.containers.pinchflat = { + image = "keglin/pinchflat:latest"; + autoStart = true; + ports = [ + "8945:8945" + ]; + volumes = [ + "/opt/pinchflat:/config" + "/lagoon/media/yt:/downloads" + ]; + environment = { + TZ = "America/Detroit"; + }; + }; +} diff --git a/modules/containers/vaultwarden/default.nix b/modules/containers/vaultwarden/default.nix new file mode 100644 index 0000000..cc6b86f --- /dev/null +++ b/modules/containers/vaultwarden/default.nix @@ -0,0 +1,34 @@ +{ lib, ... }: +let + directory = "/opt/vaultwarden"; + domain = "steel-mountain.brownbread.net"; + port = "11001"; +in +{ + systemd.tmpfiles.rules = + map (x: "d ${x} 0755 share share - -") (lib.lists.singleton directory); + + virtualisation.oci-containers.containers.vaultwarden = { + image = "vaultwarden/server:latest"; + autoStart = true; + ports = [ + "${port}:80" + ]; + volumes = [ + "${directory}/data:/data" + ]; + environment = { + DOMAIN = domain; + WEBSOCKET_ENABLED = "true"; + SIGNUPS_ALLOWED = "false"; + SHOW_PASSWORD_HINT = "false"; + }; + }; + + services.caddy.virtualHosts.${domain}.extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:${port} { + header_up X-Real-IP {remote_host} + } + ''; +} diff --git a/modules/containers/watchtower/default.nix b/modules/containers/watchtower/default.nix new file mode 100644 index 0000000..bc819cd --- /dev/null +++ b/modules/containers/watchtower/default.nix @@ -0,0 +1,15 @@ +{ ... }: +{ + virtualisation.oci-containers.containers.watchtower = { + image = "containrrr/watchtower:latest"; + autoStart = true; + volumes = [ + "/var/run/podman/podman.sock:/var/run/docker.sock:ro" + "/etc/localtime:/etc/localtime:ro" + ]; + environment = { + WATCHTOWER_CLEANUP = "true"; + WATCHTOWER_SCHEDULE = "0 0 5 * * *"; + }; + }; +} diff --git a/modules/customs/cgit/default.nix b/modules/customs/cgit/default.nix new file mode 100644 index 0000000..19eac01 --- /dev/null +++ b/modules/customs/cgit/default.nix @@ -0,0 +1,134 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.services.cgit; + + mkCgitrc = cfg: + pkgs.writeText "cgitrc" (let + cgitConfig = { + css = "/cgit.css"; + logo = "/cgit.png"; + favicon = "/favicon.ico"; + about-filter = "${cfg.package}/lib/cgit/filters/about-formatting.sh"; + source-filter = "${cfg.package}/lib/cgit/filters/syntax-highlighting.py"; + enable-git-config = 1; + # Disable cgit's HTTP "dumb" protocol and use git itself to provide the + # HTTP "smart" protocol instead. + enable-http-clone = 0; + remove-suffix = 1; + clone-url = "https://${cfg.virtualHost}/$CGIT_REPO_URL.git"; + scan-path = cfg.scanPath; + }; + in + generators.toKeyValue { } (cfg.settings // cgitConfig) + ); + + mkCgitAssets = pkg: files: + builtins.map (f: '' + handle_path /${f} { + root * ${pkg}/cgit/${f} + file_server + } + '') files |> strings.concatStringsSep "\n"; +in +{ + disabledModules = [ "services/networking/cgit.nix" ]; + + options = { + services.cgit = { + enable = mkEnableOption "cgit"; + package = mkPackageOption pkgs "cgit" { }; + user = mkOption { + description = "User to run cgit service as"; + type = types.str; + default = "git"; + }; + group = mkOption { + description = "Group to run cgit service as"; + type = types.str; + default = "git"; + }; + scanPath = mkOption { + description = "A path which will be scanned for repositories"; + type = types.path; + default = "/var/lib/cgit"; + }; + virtualHost = mkOption { + description = "Virtual host to serve cgit on"; + type = types.str; + default = null; + }; + authorizedKeys = mkOption { + description = "SSH keys for authorized git users"; + type = types.listOf types.str; + default = [ ]; + }; + settings = mkOption { + description = "Additional cgit configuration. see cgitrc(5)"; + type = with types; let settingType = oneOf [ bool int str ]; in + attrsOf (oneOf [ + settingType + (listOf settingType) + ]); + default = { }; + }; + }; + }; + + config = mkIf cfg.enable { + programs.git = { + enable = true; + config.init.defaultBranch = "main"; + }; + + # Setup git user with git-shell for authenticated pushes. + users.users.${cfg.user} = { + isSystemUser = true; + home = cfg.scanPath; + group = cfg.group; + shell = "${pkgs.git}/bin/git-shell"; + openssh.authorizedKeys.keys = cfg.authorizedKeys; + }; + + users.groups.${cfg.group} = {}; + + # Harden git user to prevent SSH port forwarding to other servers. + services.openssh = { + enable = true; + settings.AllowUsers = [ cfg.user ]; + extraConfig = '' + Match user ${cfg.user} + AllowTCPForwarding no + AllowAgentForwarding no + PasswordAuthentication no + PermitTTY no + X11Forwarding no + ''; + }; + + # Configure fcgiwrap instance for caddy to properly serve cgi scripts. + # Reference: https://github.com/NixOS/nixpkgs/blob/nixos-24.11/nixos/modules/services/networking/cgit.nix + services.fcgiwrap.instances.cgit = { + process = { inherit (cfg) user group; }; + socket = { inherit (config.services.caddy) user group; }; + }; + + services.caddy.virtualHosts.${cfg.virtualHost}.extraConfig = + let + socket = config.services.fcgiwrap.instances.cgit.socket.address; + in '' + encode zstd gzip + + reverse_proxy unix/${socket} { + transport fastcgi { + env SCRIPT_FILENAME ${cfg.package}/cgit/cgit.cgi + env CGIT_CONFIG ${mkCgitrc cfg} + } + } + + ${mkCgitAssets cfg.package [ + "cgit.css" "cgit.png" "favicon.ico" "robots.txt" + ]} + ''; + }; +} diff --git a/modules/customs/soft-serve/default.nix b/modules/customs/soft-serve/default.nix new file mode 100644 index 0000000..05156fd --- /dev/null +++ b/modules/customs/soft-serve/default.nix @@ -0,0 +1,60 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.services.soft-serve; + cfgFile = format.generate "config.yaml" cfg.settings; + format = pkgs.formats.yaml { }; + dataDir = cfg.dataDir; + docUrl = "https://github.com/charmbracelet/soft-serve"; +in +{ + disabledModules = [ "services/misc/soft-serve.nix" ]; + + options = { + services.soft-serve = { + enable = mkEnableOption "soft-serve"; + package = mkPackageOption pkgs "soft-serve" { }; + dataDir = mkOption { + type = types.str; + default = "/var/lib/soft-serve"; + description = '' + The directory where soft-serve stores its data files. + ''; + }; + settings = mkOption { + type = format.type; + default = { }; + description = '' + soft-serve server configurations stored under your data directory. + See <${docUrl}>. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.tmpfiles.rules = [ + "L+ ${dataDir}/config.yaml - - - - ${cfgFile}" + ]; + + systemd.services.soft-serve = { + description = "Soft Serve git server"; + documentation = lists.singleton docUrl; + requires = lists.singleton "network-online.target"; + after = lists.singleton "network-online.target"; + wantedBy = lists.singleton "multi-user.target"; + environment.SOFT_SERVE_DATA_PATH = dataDir; + serviceConfig = { + Type = "simple"; + Restart = "always"; + RestartSec = 1; + ExecStart = "${getExe cfg.package} serve"; + WorkingDirectory = dataDir; + }; + }; + + environment.systemPackages = with pkgs; [ + git + ]; + }; +} diff --git a/modules/default.nix b/modules/default.nix new file mode 100644 index 0000000..4930139 --- /dev/null +++ b/modules/default.nix @@ -0,0 +1,26 @@ +{ inputs }: +let + genModules = { type, modules }: + builtins.map (module: "${inputs.self}/modules/${type}/${module}") modules; + + makeModules = moduleAttrList: + builtins.concatMap (moduleAttr: genModules moduleAttr) moduleAttrList; +in +{ + makeSystem = hostname: nixpkgsVersion: modules: { + ${hostname} = nixpkgsVersion.lib.nixosSystem { + system = "x86_64-linux"; + modules = (makeModules modules) ++ [ + "${inputs.self}/hosts/${hostname}" + "${inputs.self}/modules/users" + inputs.home-manager.nixosModules.home-manager + inputs.agenix.nixosModules.default + ]; + specialArgs = { inherit inputs; }; + }; + }; + + mergeSets = inputs.nixpkgs.lib.lists.foldl' ( + x: y: inputs.nixpkgs.lib.attrsets.recursiveUpdate x y + ) { }; +} diff --git a/modules/profiles/common/default.nix b/modules/profiles/common/default.nix new file mode 100644 index 0000000..c25fece --- /dev/null +++ b/modules/profiles/common/default.nix @@ -0,0 +1,46 @@ +{ inputs, lib, pkgs, ... }: +{ + nix = { + settings = { + trusted-users = [ "@wheel" "root" ]; + experimental-features = lib.mkDefault [ + "nix-command" + "flakes" + "pipe-operators" + ]; + auto-optimise-store = true; + }; + gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 14d"; + }; + }; + + nixpkgs = { + config = { + allowUnfree = true; + allowUnfreePredicate = (_: true); + }; + overlays = [ + (final: prev: { + unstable = import inputs.nixpkgs-unstable { + system = final.system; + config.allowUnfree = true; + }; + }) + ]; + }; + + programs = { + git.enable = true; + htop.enable = true; + neovim = { + enable = true; + package = pkgs.unstable.neovim-unwrapped; + viAlias = true; + vimAlias = true; + defaultEditor = true; + }; + }; +} diff --git a/modules/profiles/fstrim/default.nix b/modules/profiles/fstrim/default.nix new file mode 100644 index 0000000..03da691 --- /dev/null +++ b/modules/profiles/fstrim/default.nix @@ -0,0 +1,7 @@ +{ ... }: +{ + services.fstrim = { + enable = true; + interval = "weekly"; + }; +} diff --git a/modules/profiles/libvirtd/default.nix b/modules/profiles/libvirtd/default.nix new file mode 100644 index 0000000..fa617d1 --- /dev/null +++ b/modules/profiles/libvirtd/default.nix @@ -0,0 +1,21 @@ +{ config, ... }: +{ + virtualisation.libvirtd = { + enable = true; + qemu = { + ovmf.enable = true; + runAsRoot = false; + }; + onBoot = "ignore"; + onShutdown = "shutdown"; + }; + + programs.virt-manager.enable = true; + + # Add any users in the 'wheel' group to the 'libvirtd' group. + users.groups.libvirtd.members = let users = config.users.users; in + builtins.attrNames users + |> builtins.filter ( + x: builtins.elem "wheel" users.${x}.extraGroups + ); +} diff --git a/modules/profiles/nvidia/default.nix b/modules/profiles/nvidia/default.nix new file mode 100644 index 0000000..50e0f6f --- /dev/null +++ b/modules/profiles/nvidia/default.nix @@ -0,0 +1,16 @@ +{ config, ... }: +{ + hardware.nvidia = { + package = config.boot.kernelPackages.nvidiaPackages.stable; + open = false; + nvidiaSettings = true; + forceFullCompositionPipeline = true; + modesetting.enable = true; + powerManagement = { + enable = false; + finegrained = false; + }; + }; + + services.xserver.videoDrivers = [ "nvidia" ]; +} diff --git a/modules/profiles/pipewire/default.nix b/modules/profiles/pipewire/default.nix new file mode 100644 index 0000000..ac70f08 --- /dev/null +++ b/modules/profiles/pipewire/default.nix @@ -0,0 +1,13 @@ +{ ... }: +{ + services.pipewire = { + enable = true; + alsa = { + enable = true; + support32Bit = true; + }; + pulse.enable = true; + }; + + security.rtkit.enable = true; +} diff --git a/modules/profiles/podman/default.nix b/modules/profiles/podman/default.nix new file mode 100644 index 0000000..1ec3406 --- /dev/null +++ b/modules/profiles/podman/default.nix @@ -0,0 +1,12 @@ +{ ... }: +{ + virtualisation = { + containers.enable = true; + oci-containers.backend = "podman"; + podman = { + enable = true; + dockerCompat = true; + defaultNetwork.settings.dns_enabled = true; + }; + }; +} diff --git a/modules/profiles/security/default.nix b/modules/profiles/security/default.nix new file mode 100644 index 0000000..47fe1a3 --- /dev/null +++ b/modules/profiles/security/default.nix @@ -0,0 +1,16 @@ +{ lib, ... }: +{ + security = { + polkit.enable = true; + + sudo.enable = lib.mkDefault false; + doas = { + enable = lib.mkDefault true; + extraRules = [{ + groups = [ "wheel" ]; + keepEnv = true; + persist = true; + }]; + }; + }; +} diff --git a/modules/profiles/share/default.nix b/modules/profiles/share/default.nix new file mode 100644 index 0000000..c4ee4ff --- /dev/null +++ b/modules/profiles/share/default.nix @@ -0,0 +1,11 @@ +{ ... }: +{ + users = { + users.share = { + uid = 994; + isSystemUser = true; + group = "share"; + }; + groups.share.gid = 994; + }; +} diff --git a/modules/profiles/steam/default.nix b/modules/profiles/steam/default.nix new file mode 100644 index 0000000..c8008f9 --- /dev/null +++ b/modules/profiles/steam/default.nix @@ -0,0 +1,8 @@ +{ ... }: +{ + programs.steam = { + enable = true; + remotePlay.openFirewall = true; + dedicatedServer.openFirewall = true; + }; +} diff --git a/modules/profiles/upgrade/default.nix b/modules/profiles/upgrade/default.nix new file mode 100644 index 0000000..32c49a8 --- /dev/null +++ b/modules/profiles/upgrade/default.nix @@ -0,0 +1,30 @@ +{ inputs, config, ... }: +{ + system.autoUpgrade = { + enable = true; + flake = inputs.self.outPath; + flags = [ + "--update-input" + "nixpkgs" + "-L" + ]; + dates = "Sat *-*-* 06:00:00"; + randomizedDelaySec = "45min"; + allowReboot = true; + }; + + systemd.services."reboot-alert" = + let + hostname = config.networking.hostName; + dependencies = [ "network-online.target" ]; + in { + wantedBy = [ "multi-user.target" ]; + wants = dependencies; + after = dependencies; + serviceConfig.Type = "oneshot"; + script = '' + /run/current-system/sw/bin/pushover -t "${hostname} restarted" \ + "${hostname} has restarted on $(date '+%a, %b %d at %T %p %Z')." + ''; + }; +} diff --git a/modules/profiles/vpn/default.nix b/modules/profiles/vpn/default.nix new file mode 100644 index 0000000..0482c31 --- /dev/null +++ b/modules/profiles/vpn/default.nix @@ -0,0 +1,18 @@ +{ pkgs, ... }: +{ + networking.nameservers = [ "9.9.9.9" ]; + + services = { + mullvad-vpn = { + enable = true; + package = pkgs.mullvad-vpn; + }; + + resolved = { + enable = true; + dnssec = "true"; + domains = [ "~." ]; + dnsovertls = "true"; + }; + }; +} diff --git a/modules/profiles/wireguard/default.nix b/modules/profiles/wireguard/default.nix new file mode 100644 index 0000000..8c25d7a --- /dev/null +++ b/modules/profiles/wireguard/default.nix @@ -0,0 +1,15 @@ +{ ... }: +let + port = 51820; +in +{ + networking = { + firewall.allowedUDPPorts = [ port ]; + + wg-quick.interfaces.wg0 = { + autostart = true; + listenPort = port; + configFile = "/etc/wireguard/wg0.conf"; + }; + }; +} diff --git a/modules/profiles/wireshark/default.nix b/modules/profiles/wireshark/default.nix new file mode 100644 index 0000000..d4d0627 --- /dev/null +++ b/modules/profiles/wireshark/default.nix @@ -0,0 +1,14 @@ +{ config, pkgs, ... }: +{ + programs.wireshark = { + enable = true; + package = pkgs.wireshark; + }; + + # Add any users in the 'wheel' group to the 'wireshark' group. + users.groups.wireshark.members = let users = config.users.users; in + builtins.attrNames users + |> builtins.filter ( + x: builtins.elem "wheel" users.${x}.extraGroups + ); +} diff --git a/modules/profiles/x11/default.nix b/modules/profiles/x11/default.nix new file mode 100644 index 0000000..52e7975 --- /dev/null +++ b/modules/profiles/x11/default.nix @@ -0,0 +1,33 @@ +{ pkgs, ... }: +{ + services = { + xserver = { + enable = true; + xkb.layout = "us"; + displayManager.lightdm.enable = true; + windowManager.bspwm.enable = true; + }; + + displayManager.autoLogin = { + enable = true; + user = "tdback"; + }; + }; + + hardware.graphics.enable32Bit = true; + + environment.systemPackages = with pkgs.xorg; [ + libX11 + xset + ]; + + fonts.packages = with pkgs; [ + dejavu_fonts + dina-font + iosevka-comfy.comfy-motion-fixed + liberation_ttf + noto-fonts + noto-fonts-emoji + ubuntu_font_family + ]; +} diff --git a/modules/profiles/zfs/default.nix b/modules/profiles/zfs/default.nix new file mode 100644 index 0000000..8344450 --- /dev/null +++ b/modules/profiles/zfs/default.nix @@ -0,0 +1,28 @@ +{ lib, pkgs, ... }: +{ + boot = { + zfs.forceImportRoot = false; + supportedFilesystems.zfs = lib.mkForce true; + }; + + services.zfs = { + autoScrub.enable = true; + zed = { + enableMail = false; + settings = { + ZED_DEBUG_LOG = "/tmp/zed.debug.log"; + ZED_EMAIL_ADDR = [ "root" ]; + ZED_EMAIL_PROG = "/run/current-system/sw/bin/pushover"; + ZED_EMAIL_OPTS = "-t '@SUBJECT@'"; + ZED_NOTIFY_INTERVAL_SECS = 3600; + ZED_NOTIFY_VERBOSE = true; + ZED_USE_ENCLOSURE_LEDS = true; + ZED_SCRUB_AFTER_RESILVER = true; + }; + }; + }; + + environment.systemPackages = with pkgs; [ + zfs + ]; +} diff --git a/modules/retired/forgejo/default.nix b/modules/retired/forgejo/default.nix new file mode 100644 index 0000000..9db55b2 --- /dev/null +++ b/modules/retired/forgejo/default.nix @@ -0,0 +1,65 @@ +{ inputs, config, lib, pkgs, ... }: +let + domain = "git.tdback.net"; + port = 3000; +in +{ + services.forgejo = { + enable = true; + package = pkgs.unstable.forgejo; + stateDir = "/tank/forgejo"; + database.type = "postgres"; + lfs.enable = true; + settings = { + server = { + DOMAIN = domain; + ROOT_URL = "https://${domain}/"; + HTTP_PORT = port; + }; + service.DISABLE_REGISTRATION = true; + actions = { + ENABLED = true; + DEFAULT_ACTIONS_URL = "https://${domain}"; + }; + }; + }; + + age.secrets.forgejoAdminPass = { + file = "${inputs.self}/secrets/forgejoAdminPass.age"; + mode = "770"; + owner = "forgejo"; + group = "forgejo"; + }; + + systemd.services.forgejo.preStart = + let + adminCmd = "${lib.getExe config.services.forgejo.package} admin user"; + password = config.age.secrets.forgejoAdminPass.path; + user = "tdback"; + email = "tyler@tdback.net"; + in '' + ${adminCmd} create --admin --email ${email} --username ${user} --password "$(tr -d '\n' < ${password})" || true + ''; + + services.openssh.settings.AllowUsers = [ "forgejo" ]; + + services.caddy.virtualHosts.${domain}.extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:${builtins.toString port} + ''; + + age.secrets.forgejoRunnerToken.file = "${inputs.self}/secrets/forgejoRunnerToken.age"; + services.gitea-actions-runner = { + package = pkgs.unstable.forgejo-runner; + instances.default = { + enable = true; + name = "monolith"; + url = "https://${domain}"; + tokenFile = config.age.secrets.forgejoRunnerToken.path; + labels = [ + "ubuntu-latest:docker://node:20-bookworm" + "ubuntu-22.04:docker://node:20-bookworm" + ]; + }; + }; +} diff --git a/modules/retired/kavita/default.nix b/modules/retired/kavita/default.nix new file mode 100644 index 0000000..c72aca6 --- /dev/null +++ b/modules/retired/kavita/default.nix @@ -0,0 +1,28 @@ +{ ... }: +let + directories = [ + "/opt/kavita" + ]; +in +{ + systemd.tmpfiles.rules = map (x: "d ${x} 0755 share share - -") directories; + virtualisation.oci-containers.containers.kavita = { + image = "jvmilazz0/kavita:latest"; + autoStart = true; + ports = [ + "5000:5000" + ]; + volumes = [ + "/opt/kavita/config:/kavita/config" + "/lagoon/media/library/Books:/books" + ]; + environment = { + TZ = "America/Detroit"; + }; + }; + + services.caddy.virtualHosts."library.tdback.net".extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:5000 + ''; +} diff --git a/modules/retired/mealie/default.nix b/modules/retired/mealie/default.nix new file mode 100644 index 0000000..2d869ce --- /dev/null +++ b/modules/retired/mealie/default.nix @@ -0,0 +1,22 @@ +{ config, pkgs, ... }: +let + domain = "toasted.brownbread.net"; +in +{ + services.mealie = { + enable = true; + package = pkgs.unstable.mealie; + settings = { + BASE_URL = domain; + DB_ENGINE = "sqlite"; + ALLOW_SIGNUP = "false"; + SECURITY_MAX_LOGIN_ATTEMPTS = 3; + TZ = "America/Detroit"; + }; + }; + + services.caddy.virtualHosts.${domain}.extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:${builtins.toString config.services.mealie.port} + ''; +} diff --git a/modules/retired/mumble/default.nix b/modules/retired/mumble/default.nix new file mode 100644 index 0000000..29e3339 --- /dev/null +++ b/modules/retired/mumble/default.nix @@ -0,0 +1,11 @@ +{ pkgs, ... }: +{ + services.murmur = { + enable = true; + package = pkgs.murmur; + port = 64738; + openFirewall = true; + environmentFile = "/var/lib/murmur/murmurd.env"; + password = "$MURMURD_PASSWORD"; + }; +} diff --git a/modules/retired/navidrome/default.nix b/modules/retired/navidrome/default.nix new file mode 100644 index 0000000..d98117b --- /dev/null +++ b/modules/retired/navidrome/default.nix @@ -0,0 +1,31 @@ +{ lib, ... }: +let + directory = "/opt/navidrome"; +in +{ + systemd.tmpfiles.rules = + map (x: "d ${x} 0755 share share - -") (lib.lists.singleton directory); + + virtualisation.oci-containers.containers.navidrome = { + image = "deluan/navidrome:latest"; + autoStart = true; + ports = [ + "4533:4533" + ]; + volumes = [ + "${directory}/data:/data" + "/lagoon/media/music:/music:ro" + ]; + environment = { + ND_SCANSCHEDULE = "1h"; + ND_LOGLEVEL = "info"; + ND_SESSIONTIMEOUT = "24h"; + ND_ENABLEUSEREDITING = "false"; + }; + }; + + services.caddy.virtualHosts."radioactive.brownbread.net".extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:4533 + ''; +} diff --git a/modules/retired/pihole/default.nix b/modules/retired/pihole/default.nix new file mode 100644 index 0000000..034c91b --- /dev/null +++ b/modules/retired/pihole/default.nix @@ -0,0 +1,52 @@ +{ inputs, config, lib, ... }: +let + # TODO: Think about changing this to config.networking.interface... + # Will have to pull the first value in the list, which might be messy but it + # will definitely make it more producible across machines. + ip = "10.0.0.203"; + interface = "eno1"; + directory = "/opt/pihole"; +in +{ + systemd.tmpfiles.rules = + map (x: "d ${x} 0755 share share - -") (lib.lists.singleton directory); + + virtualisation.oci-containers.containers.pihole = { + image = "pihole/pihole:latest"; + autoStart = true; + ports = [ + "53:53/udp" + "53:53/tcp" + "80:80/tcp" + ]; + volumes = [ + "${directory}/etc:/etc/pihole" + "${directory}/etc-dnsmasq.d:/etc/dnsmasq.d" + ]; + environment = { + TZ = "America/Detroit"; + FTLCONF_LOCAL_IPV4 = ip; + INTERFACE = interface; + }; + extraOptions = [ "--network=host" ]; + }; + + age.secrets.piholeAdminPass = { + file = "${inputs.self}/secrets/piholeAdminPass.age"; + mode = "770"; + owner = "share"; + group = "share"; + }; + + systemd.services.podman-pihole.postStart = + let + password = config.age.secrets.piholeAdminPass.path; + in '' + podman exec -it pihole pihole -a -p "$(tr -d '\n' < ${password})" + ''; + + networking.firewall = { + allowedTCPPorts = [ 53 80 ]; + allowedUDPPorts = [ 53 ]; + }; +} diff --git a/modules/retired/stirling-pdf/default.nix b/modules/retired/stirling-pdf/default.nix new file mode 100644 index 0000000..904fd6d --- /dev/null +++ b/modules/retired/stirling-pdf/default.nix @@ -0,0 +1,23 @@ +{ ... }: +let + directories = [ + "/opt/stirling" + ]; +in +{ + systemd.tmpfiles.rules = map (x: "d ${x} 0755 share share - -") directories; + virtualisation.oci-containers.containers.pdf-tools = { + image = "frooodle/s-pdf:latest"; + autoStart = true; + ports = [ + "8060:8080" + ]; + volumes = [ + "/opt/stirling/training-data:/usr/share/tesseract-ocr/4.00/tessdata" + "/opt/stirling/configs:/configs" + ]; + environment = { + DOCKER_ENABLE_SECURITY = "false"; + }; + }; +} diff --git a/modules/retired/xonotic/default.nix b/modules/retired/xonotic/default.nix new file mode 100644 index 0000000..7ae5442 --- /dev/null +++ b/modules/retired/xonotic/default.nix @@ -0,0 +1,25 @@ +{ pkgs, ... }: +{ + services.xonotic = { + enable = true; + package = pkgs.xonotic-dedicated; + openFirewall = true; + settings = { + hostname = "tdback's Xonotic Server"; + net_address = "0.0.0.0"; + port = 26000; + sv_motd = "GLHF! Please report any issues to @tdback on irc.libera.chat"; + + # Specify bots and player count. + maxplayers = 8; + minplayers = 4; + minplayers_per_team = 2; + + # Configure mutators. + g_instagib = 0; + g_grappling_hook = 1; + g_jetpack = 0; + g_vampire = 0; + }; + }; +} diff --git a/modules/scripts/motd/default.nix b/modules/scripts/motd/default.nix new file mode 100644 index 0000000..d59f787 --- /dev/null +++ b/modules/scripts/motd/default.nix @@ -0,0 +1,99 @@ +{ config, lib, pkgs, ... }: +let + motd = + pkgs.writeShellScriptBin "motd" '' + #!/usr/bin/env bash + RED="\e[31m" + GREEN="\e[32m" + YELLOW="\e[33m" + BOLD="\e[1m" + ENDCOLOR="\e[0m" + + case "$(date +'%H')" in + [0-9]|1[0-1]) + TIME="morning" + ;; + 1[2-7]) + TIME="afternoon" + ;; + *) + TIME="evening" + ;; + esac + + UPTIME=$(cat /proc/uptime | cut -f1 -d.) + UPDAYS=$((UPTIME/60/60/24)) + UPHOURS=$((UPTIME/60/60%24)) + UPMINS=$((UPTIME/60%60)) + UPSECS=$((UPTIME%60)) + + MEMORY=$(free -m | awk 'NR == 2 { printf "%s/%sMB (%.2f%%)\n", $3, $2, ($3 * 100) / $2 }') + + SERVICES=$(systemctl list-units | grep -P 'podman-|${lib.strings.concatStringsSep "|" config.motd.servicesToCheck}') + + printf "\n" + printf "''${BOLD}Good $TIME $(whoami), welcome to $(hostname)!$ENDCOLOR\n" + printf "\n" + ${lib.strings.concatStrings (lib.lists.forEach config.motd.networkInterfaces (x: + "printf \"$BOLD * %-20s$ENDCOLOR %s\\n\" \"IPv4 ${x}\" \"$(ip -4 addr show ${x} | grep -oP '(?<=inet\\s)\\d+(\\.\\d+){3}')\"\n" + ))} + printf "$BOLD * %-20s$ENDCOLOR %s\n" "Release" "$(awk -F= '/PRETTY_NAME/ { print $2 }' /etc/os-release | tr -d '"')" + printf "$BOLD * %-20s$ENDCOLOR %s\n" "Kernel" "$(uname -rs)" + printf "\n" + printf "$BOLD * %-20s$ENDCOLOR %s\n" "CPU Usage" "$(awk '{ print $1 ", " $2 ", " $3 }' /proc/loadavg) (1, 5, 15 min)" + printf "$BOLD * %-20s$ENDCOLOR %s\n" "Memory" "$MEMORY" + printf "$BOLD * %-20s$ENDCOLOR %s\n" "System Uptime" "$UPDAYS days $UPHOURS hours $UPMINS minutes $UPSECS seconds" + printf "\n" + + [ -z "$SERVICES" ] && exit + + printf "''${BOLD}Service status:$ENDCOLOR\n" + while IFS= read -r line; do + if [[ ! $line =~ ".service" ]] || [[ $line =~ ".mount" ]]; then + continue + fi + if echo "$line" | grep -q 'failed'; then + name=$(echo "$line" | awk '{ print $1 }' | sed 's/podman-//g') + printf "$RED• $ENDCOLOR%-50s $RED[failed]$ENDCOLOR\n" "$name" + elif echo "$line" | grep -q 'running'; then + name=$(echo "$line" | awk '{ print $1 }' | sed 's/podman-//g') + printf "$GREEN• $ENDCOLOR%-50s $GREEN[active]$ENDCOLOR\n" "$name" + elif echo "$line" | grep -q 'exited'; then + name=$(echo "$line" | awk '{ print $1 }' | sed 's/podman-//g') + printf "$YELLOW• $ENDCOLOR%-50s $YELLOW[exited]$ENDCOLOR\n" "$name" + else + echo "service status unknown" + fi + done <<< "$SERVICES" + printf "\n" + ''; +in +{ + options.motd = { + networkInterfaces = lib.mkOption { + description = "Network interfaces to monitor."; + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + + servicesToCheck = lib.mkOption { + description = "Services to validate alongside podman containers."; + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + }; + + config = { + environment.systemPackages = [ + motd + ]; + + programs.bash.loginShellInit = '' + [ -z "$PS1" ] && return + + if command -v motd &> /dev/null; then + motd + fi + ''; + }; +} diff --git a/modules/scripts/pushover/default.nix b/modules/scripts/pushover/default.nix new file mode 100644 index 0000000..f20a5be --- /dev/null +++ b/modules/scripts/pushover/default.nix @@ -0,0 +1,47 @@ +{ inputs, config, pkgs, ... }: +let + pushover = + pkgs.writeShellScriptBin "pushover" '' + #!/bin/sh + + die() { echo "$0: $*" >&2; exit 111; } + + APP=$(cat ${config.age.secrets.pushoverAppToken.path}) + USER=$(cat ${config.age.secrets.pushoverUserToken.path}) + + while getopts ":t:" args; do + case "$args" in + t) + TITLE="$OPTARG" + ;; + :) + die "missing option argument for -$OPTARG" + ;; + *) + die "invalid option -$OPTARG" + ;; + esac + done + shift $((OPTIND - 1)) + + MESSAGE="$*" + if [ -z "$MESSAGE" ] || [ "$MESSAGE" = " " ]; then + MESSAGE="No errors to report." + fi + + /run/current-system/sw/bin/curl -s \ + --form-string "token=$APP" \ + --form-string "user=$USER" \ + --form-string "title=$TITLE" \ + --form-string "message=$MESSAGE" \ + https://api.pushover.net/1/messages.json + ''; +in +{ + age.secrets = { + pushoverAppToken.file = "${inputs.self}/secrets/pushoverAppToken.age"; + pushoverUserToken.file = "${inputs.self}/secrets/pushoverUserToken.age"; + }; + + environment.systemPackages = [ pushover ]; +} diff --git a/modules/services/blocky/default.nix b/modules/services/blocky/default.nix new file mode 100644 index 0000000..ca58f4f --- /dev/null +++ b/modules/services/blocky/default.nix @@ -0,0 +1,93 @@ +{ pkgs, ... }: +{ + services.blocky = { + enable = true; + package = pkgs.blocky; + settings = { + upstreams = { + init.strategy = "fast"; + groups.default = [ + "9.9.9.9" + "149.112.112.112" + ]; + }; + bootstrapDns = [{ + upstream = "https://dns.quad9.net/dns-query"; + ips = [ "9.9.9.9" ]; + }]; + ports = { + dns = 53; + tls = 853; + https = 443; + }; + blocking = { + denylists = { + ads = [ + "https://adaway.org/hosts.txt" + "https://v.firebog.net/hosts/AdguardDNS.txt" + "https://v.firebog.net/hosts/Admiral.txt" + "https://raw.githubusercontent.com/anudeepND/blacklist/master/adservers.txt" + "https://v.firebog.net/hosts/Easylist.txt" + "https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext" + "https://raw.githubusercontent.com/FadeMind/hosts.extras/master/UncheckyAds/hosts" + "https://raw.githubusercontent.com/bigdargon/hostsVN/master/hosts" + ]; + malicious = [ + "https://osint.digitalside.it/Threat-Intel/lists/latestdomains.txt" + "https://v.firebog.net/hosts/Prigent-Crypto.txt" + "https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.Risk/hosts" + "https://phishing.army/download/phishing_army_blocklist_extended.txt" + "https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-malware.txt" + "https://raw.githubusercontent.com/Spam404/lists/master/main-blacklist.txt" + "https://raw.githubusercontent.com/AssoEchap/stalkerware-indicators/master/generated/hosts" + "https://urlhaus.abuse.ch/downloads/hostfile/" + "https://v.firebog.net/hosts/Prigent-Malware.txt" + ]; + other = [ + "https://zerodot1.gitlab.io/CoinBlockerLists/hosts_browser" + ]; + suspicious = [ + "https://raw.githubusercontent.com/PolishFiltersTeam/KADhosts/master/KADhosts.txt" + "https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.Spam/hosts" + "https://v.firebog.net/hosts/static/w3kbl.txt" + "https://raw.githubusercontent.com/matomo-org/referrer-spam-blacklist/master/spammers.txt" + "https://someonewhocares.org/hosts/zero/hosts" + "https://raw.githubusercontent.com/VeleSila/yhosts/master/hosts" + "https://winhelp2002.mvps.org/hosts.txt" + "https://v.firebog.net/hosts/neohostsbasic.txt" + "https://raw.githubusercontent.com/RooneyMcNibNug/pihole-stuff/master/SNAFU.txt" + "https://paulgb.github.io/BarbBlock/blacklists/hosts-file.txt" + ]; + tracking-telemetry = [ + "https://v.firebog.net/hosts/Easyprivacy.txt" + "https://v.firebog.net/hosts/Prigent-Ads.txt" + "https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.2o7Net/hosts" + "https://raw.githubusercontent.com/crazy-max/WindowsSpyBlocker/master/data/hosts/spy.txt" + "https://hostfiles.frogeye.fr/firstparty-trackers-hosts.txt" + "https://www.github.developerdan.com/hosts/lists/ads-and-tracking-extended.txt" + "https://raw.githubusercontent.com/Perflyst/PiHoleBlocklist/master/android-tracking.txt" + "https://raw.githubusercontent.com/Perflyst/PiHoleBlocklist/master/SmartTV.txt" + "https://raw.githubusercontent.com/Perflyst/PiHoleBlocklist/master/AmazonFireTV.txt" + "https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-blocklist.txt" + ]; + }; + clientGroupsBlock.default = [ + "ads" + "malicious" + "other" + "suspicious" + "tracking-telemetry" + ]; + loading = { + concurrency = 16; + strategy = "failOnError"; + }; + }; + }; + }; + + networking.firewall = { + allowedTCPPorts = [ 53 443 853 ]; + allowedUDPPorts = [ 53 ]; + }; +} diff --git a/modules/services/cgit/default.nix b/modules/services/cgit/default.nix new file mode 100644 index 0000000..5309e6f --- /dev/null +++ b/modules/services/cgit/default.nix @@ -0,0 +1,28 @@ +{ inputs, lib, pkgs, ... }: +let + scanPath = "/tank/git"; + domain = "git.tdback.net"; +in +{ + imports = lib.lists.singleton "${inputs.self}/modules/customs/cgit"; + + services.cgit = { + enable = true; + package = pkgs.cgit; + scanPath = scanPath; + virtualHost = domain; + authorizedKeys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEzLpTEoej7P04KoNzokQ9IOnNZiKyi2+YQ8yU5WSKCb" + ]; + settings = { + root-title = domain; + root-desc = "tdback's git repositories"; + enable-index-links = 1; + enable-index-owner = 0; + enable-commit-graph = 1; + enable-log-filecount = 1; + enable-log-linecount = 1; + readme = ":README.md"; + }; + }; +} diff --git a/modules/services/fediverse/default.nix b/modules/services/fediverse/default.nix new file mode 100644 index 0000000..0c3c696 --- /dev/null +++ b/modules/services/fediverse/default.nix @@ -0,0 +1,26 @@ +{ pkgs, ... }: +let + domain = "social.tdback.net"; + port = 8080; +in +{ + services.gotosocial = { + enable = true; + package = pkgs.unstable.gotosocial; + settings = { + application-name = "gotosocial"; + host = "${domain}"; + protocol = "https"; + bind-address = "localhost"; + port = port; + db-type = "sqlite"; + db-address = "/var/lib/gotosocial/database.sqlite"; + storage-local-base-path = "/var/lib/gotosocial/storage"; + }; + }; + + services.caddy.virtualHosts.${domain}.extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:${builtins.toString port} + ''; +} diff --git a/modules/services/immich/default.nix b/modules/services/immich/default.nix new file mode 100644 index 0000000..e33dd97 --- /dev/null +++ b/modules/services/immich/default.nix @@ -0,0 +1,18 @@ +{ pkgs, ... }: +{ + services.immich = { + enable = true; + package = pkgs.immich; + host = "localhost"; + port = 2283; + mediaLocation = "/lagoon/media/immich"; + environment = { + IMMICH_LOG_LEVEL = "log"; + }; + }; + + services.caddy.virtualHosts."photographs.brownbread.net".extraConfig = '' + encode zstd gzip + reverse_proxy http://localhost:2283 + ''; +} diff --git a/modules/services/proxy/default.nix b/modules/services/proxy/default.nix new file mode 100644 index 0000000..e11beab --- /dev/null +++ b/modules/services/proxy/default.nix @@ -0,0 +1,9 @@ +{ pkgs, ... }: +{ + services.caddy = { + enable = true; + package = pkgs.caddy; + }; + + networking.firewall.allowedTCPPorts = [ 80 443 ]; +} diff --git a/modules/services/searx/default.nix b/modules/services/searx/default.nix new file mode 100644 index 0000000..2b4a9d8 --- /dev/null +++ b/modules/services/searx/default.nix @@ -0,0 +1,33 @@ +{ pkgs, ... }: +let + port = 8888; +in +{ + services.searx = { + enable = true; + package = pkgs.searxng; + environmentFile = "/var/lib/searx/env"; + settings = { + general = { + debug = false; + instance_name = "searx"; + }; + search = { + safe_search = 1; + autocomplete = "duckduckgo"; + autocomplete_min = 4; + default_lang = "en-US"; + }; + server = { + port = port; + bind_address = "0.0.0.0"; + secret_key = "@SEARX_SECRET_KEY@"; + public_instance = false; + image_proxy = true; + }; + ui.static_use_hash = true; + }; + }; + + networking.firewall.allowedTCPPorts = [ port ]; +} diff --git a/modules/services/sftpgo/default.nix b/modules/services/sftpgo/default.nix new file mode 100644 index 0000000..27318b2 --- /dev/null +++ b/modules/services/sftpgo/default.nix @@ -0,0 +1,21 @@ +{ config, pkgs, ... }: +{ + services.sftpgo = { + enable = true; + package = pkgs.sftpgo; + settings = { + httpd.bindings = [{ + port = 8080; + address = "0.0.0.0"; + enable_web_client = true; + enable_web_admin = true; + }]; + }; + }; + + services.caddy.virtualHosts."${config.networking.hostName}.brownbread.net".extraConfig = '' + root * /web/client + encode zstd gzip + reverse_proxy http://localhost:8080 + ''; +} diff --git a/modules/services/ssh/default.nix b/modules/services/ssh/default.nix new file mode 100644 index 0000000..ec8f188 --- /dev/null +++ b/modules/services/ssh/default.nix @@ -0,0 +1,17 @@ +{ lib, ... }: +let + ports = lib.lists.singleton 2222; +in +{ + services.openssh = { + enable = lib.mkDefault true; + ports = ports; + openFirewall = true; + startWhenNeeded = true; + settings = { + AllowUsers = [ "tdback" ]; + PermitRootLogin = "no"; + PasswordAuthentication = lib.mkDefault false; + }; + }; +} diff --git a/modules/services/web/default.nix b/modules/services/web/default.nix new file mode 100644 index 0000000..b6a45af --- /dev/null +++ b/modules/services/web/default.nix @@ -0,0 +1,10 @@ +{ ... }: +{ + services.caddy.virtualHosts = { + "tdback.net".extraConfig = '' + root * /var/www/tdback.net/ + encode zstd gzip + file_server + ''; + }; +} diff --git a/modules/users/default.nix b/modules/users/default.nix new file mode 100644 index 0000000..027ca0f --- /dev/null +++ b/modules/users/default.nix @@ -0,0 +1,15 @@ +{ pkgs, ... }: +{ + users = { + users.tdback = { + isNormalUser = true; + uid = 1000; + home = "/home/tdback"; + group = "tdback"; + extraGroups = [ "wheel" "users" "networkmanager" "video" "audio" ]; + shell = pkgs.bash; + ignoreShellProgramCheck = true; + }; + groups.tdback.gid = 1000; + }; +} diff --git a/secrets/pushoverAppToken.age b/secrets/pushoverAppToken.age new file mode 100644 index 0000000..e81a894 --- /dev/null +++ b/secrets/pushoverAppToken.age @@ -0,0 +1,13 @@ +age-encryption.org/v1 +-> ssh-ed25519 gpkhBg F2i4P0GuB+EC6ZbH+QtkogDxEOH3p71aJ3dp3s8CEgM +4/pDhOscOh7HHGojnkpTae9BYz9p8Nt9EDpT0cdrITU +-> ssh-ed25519 NJIOsA rRfKrypbNoKe4ja1LIg6RbApf3la3ZV5OzcGHADdJws +G59Dy/689mkNc9UBVOGa288iucWATUQw1TQS9hmTE9w +-> ssh-ed25519 D2VkFQ NJNZDmBYw5GY+rRnCJRH44kbxDTrmjwyhgfSOf+8rDU +f2SaYKM7bk7vQ0E7My3v5l5MC3b/2+vnezYYoZxPIB0 +-> ssh-ed25519 VoJMUA q4mjpsmZlHQUxsDT45t2TR3rs9vZ4YP2Wxc51zyphSI +LeAd0zYKvt6Nm4MtEIxMi+QcHTqfAXU60QsfudfOqsI +-> ssh-ed25519 WAT7cQ rgJZHOEQImza/yE7mgHf/oVdcQ4sCqhINajQxWay11M +lynXczF6QwsPeLpcWmfPO9eXeETTgjbu0T6nCy9sQsc +--- KACyQUO0R39fLv1hSz8rz0jVzdXwkkXPtbErA9t+1xU +`YCjy!}cg`9?W4*emxl䠡7^>.; \ No newline at end of file diff --git a/secrets/pushoverUserToken.age b/secrets/pushoverUserToken.age new file mode 100644 index 0000000..6284ec7 Binary files /dev/null and b/secrets/pushoverUserToken.age differ diff --git a/secrets/secrets.nix b/secrets/secrets.nix new file mode 100644 index 0000000..f007165 --- /dev/null +++ b/secrets/secrets.nix @@ -0,0 +1,19 @@ +let + systems = { + eden = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIByi8x1IgXBC6iw6MJoO7xIkkU4bdIaQ3Mi6zEtm+IJh"; + hive = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGEn+C6ktSqvvwNVf1zUeNKKtZJ1QgLVhQjU83+0RvSY"; + oasis = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICCvgPNEJrWjeCUmF/izLhIzaAwSNYHW9o5meYmGHGzj"; + raindog = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINq0rMkFlizGPijlHKMYS9CGWJ2T1ZJHqaLozWdoySz2"; + }; + + users = { + tdback = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIErXJtbnTYwxgqv7v5HJgd0OUAlOeEzxX7TxEyBDM+at"; + }; + + allSystems = builtins.attrValues systems; + allUsers = builtins.attrValues users; +in +{ + "pushoverAppToken.age".publicKeys = allSystems ++ allUsers; + "pushoverUserToken.age".publicKeys = allSystems ++ allUsers; +} diff --git a/users/default.nix b/users/default.nix new file mode 100644 index 0000000..2eb2feb --- /dev/null +++ b/users/default.nix @@ -0,0 +1,3 @@ +{ + tdback = import ./tdback; +} diff --git a/users/tdback/default.nix b/users/tdback/default.nix new file mode 100644 index 0000000..8457428 --- /dev/null +++ b/users/tdback/default.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, headless ? true, ... }: +{ + # Hacky way to import our desktop modules if we aren't a headless system. + imports = (lib.optional (!headless) ./desktop.nix) ++ [ + ./modules/git + ./modules/shell + ]; + + home = { + username = "tdback"; + homeDirectory = "/home/tdback"; + stateVersion = "24.05"; + packages = with pkgs.unstable; [ + age + bat + croc + dig + file + fzf + jq + neovim + nixd + ripgrep + tealdeer + unzip + zip + ]; + }; + + # Let home manager install and manage itself. + programs.home-manager.enable = true; +} diff --git a/users/tdback/desktop.nix b/users/tdback/desktop.nix new file mode 100644 index 0000000..e2f754b --- /dev/null +++ b/users/tdback/desktop.nix @@ -0,0 +1,70 @@ +{ config, pkgs, ... }: +let + dirs = [ "desktop" "documents" "download" "music" "pictures" "publicShare" "templates" "videos" ]; + defined = { + "documents" = "${config.home.homeDirectory}/documents"; + "download" = "${config.home.homeDirectory}/downloads"; + }; + userDirs = + builtins.map (dir: { name = dir; value = defined.${dir} or null; }) dirs + |> builtins.listToAttrs; +in +{ + imports = [ + ./modules/alacritty + ./modules/dunst + ./modules/email + ./modules/firefox + ./modules/irc + ./modules/mpd + ./modules/ncmpcpp + ./modules/neomutt + ./modules/polybar + ./modules/rofi + ./modules/tmux + ./modules/x11 + ]; + + home.packages = with pkgs.unstable; [ + clang + feh + (ffmpeg.override { withXcb = true; }) + flameshot + gimp + gitu + mpc-cli + mpv + pavucontrol + pamixer + pciutils + signal-desktop + sxiv + tidal-dl + xclip + yt-dlp + zathura + ]; + + xdg = { + enable = true; + userDirs = { + enable = true; + createDirectories = true; + } // userDirs; + }; + + qt = { + enable = true; + platformTheme.name = "gtk3"; + style = { + name = "adwaita-dark"; + package = pkgs.adwaita-qt; + }; + }; + + gtk = { + enable = true; + gtk3.extraConfig.gtk-application-prefer-dark-theme = 1; + gtk4.extraConfig.gtk-application-prefer-dark-theme = 1; + }; +} diff --git a/users/tdback/modules/alacritty/default.nix b/users/tdback/modules/alacritty/default.nix new file mode 100644 index 0000000..6955536 --- /dev/null +++ b/users/tdback/modules/alacritty/default.nix @@ -0,0 +1,71 @@ +{ pkgs, ... }: +{ + programs.alacritty = { + enable = true; + package = pkgs.alacritty; + settings = { + env.TERM = "xterm-256color"; + mouse.hide_when_typing = true; + scrolling.history = 10000; + + window = { + decorations = "None"; + opacity = 1.0; + title = "Alacritty"; + padding.x = 4; + }; + + cursor.style.blinking = "Never"; + + font = { + size = 14.0; + normal = { + family = "Iosevka Comfy Motion Fixed"; + style = "Regular"; + }; + italic = { + family = "Iosevka Comfy Motion Fixed"; + style = "Italic"; + }; + bold = { + family = "Iosevka Comfy Motion Fixed"; + style = "Bold"; + }; + bold_italic = { + family = "Iosevka Comfy Motion Fixed"; + style = "Bold Italic"; + }; + }; + + # Tomorrow Night Bright colorscheme. + colors = { + draw_bold_text_with_bright_colors = true; + + primary = { + background = "#000000"; + foreground = "#eaeaea"; + }; + normal = { + black = "#000000"; + red = "#d54e53"; + green = "#b9ca4a"; + yellow = "#e6c547"; + blue = "#7aa6da"; + magenta = "#c397d8"; + cyan = "#70c0ba"; + white = "#424242"; + }; + bright = { + black = "#666666"; + red = "#ff3334"; + green = "#9ec400"; + yellow = "#e7c547"; + blue = "#7aa6da"; + magenta = "#b77ee0"; + cyan = "#54ced6"; + white = "#2a2a2a"; + }; + }; + }; + }; +} diff --git a/users/tdback/modules/dunst/default.nix b/users/tdback/modules/dunst/default.nix new file mode 100644 index 0000000..132e32b --- /dev/null +++ b/users/tdback/modules/dunst/default.nix @@ -0,0 +1,30 @@ +{ pkgs, ... }: +{ + services.dunst = { + enable = true; + package = pkgs.dunst; + + settings = { + global = { + width = 300; + height = 300; + offset = "30x50"; + origin = "top-right"; + frame_color = "#2c363c"; + font = "Iosevka Comfy Motion Fixed 12"; + }; + + urgency_normal = { + background = "#37474f"; + foreground = "eceff1"; + timeout = 5; + }; + }; + + iconTheme = { + name = "Papirus-Dark"; + package = pkgs.papirus-icon-theme; + size = "16x16"; + }; + }; +} diff --git a/users/tdback/modules/email/default.nix b/users/tdback/modules/email/default.nix new file mode 100644 index 0000000..3321462 --- /dev/null +++ b/users/tdback/modules/email/default.nix @@ -0,0 +1,78 @@ +{ pkgs, ... }: +{ + accounts.email = { + maildirBasePath = "mail"; + + accounts.fastmail = { + primary = true; + address = "tyler@tdback.net"; + userName = "tyler@tdback.net"; + realName = "Tyler Dunneback"; + passwordCommand = "${pkgs.age}/bin/age -d -i ~/.ssh/mail ~/.mail.age"; + + folders = { + inbox = "Inbox"; + drafts = "Drafts"; + sent = "Sent"; + trash = "Trash"; + }; + + imap = { + host = "imap.fastmail.com"; + port = 993; + tls = { + enable = true; + certificatesFile = "/etc/ssl/certs/ca-certificates.crt"; + }; + }; + + smtp = { + host = "smtp.fastmail.com"; + port = 465; + tls = { + enable = true; + useStartTls = false; + certificatesFile = "/etc/ssl/certs/ca-certificates.crt"; + }; + }; + + mbsync = { + enable = true; + create = "both"; + expunge = "none"; + subFolders = "Verbatim"; + patterns = [ "*" ]; + }; + + msmtp = { + enable = true; + extraConfig = { + logfile = "~/.cache/msmtp/msmtp.log"; + }; + }; + + neomutt = { + enable = true; + sendMailCommand = "msmtp"; + mailboxType = "maildir"; + extraMailboxes = [ + "Drafts" + "Sent" + "Trash" + "Archive" + ]; + }; + }; + }; + + programs = { + mbsync.enable = true; + msmtp.enable = true; + }; + + services.mbsync = { + enable = true; + package = pkgs.isync; + frequency = "*:0/5"; + }; +} diff --git a/users/tdback/modules/firefox/default.nix b/users/tdback/modules/firefox/default.nix new file mode 100644 index 0000000..dde8742 --- /dev/null +++ b/users/tdback/modules/firefox/default.nix @@ -0,0 +1,101 @@ +{ config, pkgs, ... }: +let + lock-false = { + Value = false; + Status = "locked"; + }; + lock-true = { + Value = true; + Status = "locked"; + }; +in +{ + programs.firefox = { + enable = true; + package = pkgs.firefox; + + policies = { + # about:policies + DisableTelemetry = true; + DisableFirefoxStudies = true; + DisablePocket = true; + DisableFirefoxAccounts = true; + DisableAccounts = true; + DisplayBookmarksToolbar = "newtab"; + DisplayMenuBar = "default-off"; + SearchBar = "unified"; + OfferToSaveLogins = false; + EnableTrackingProtection = { + Value= true; + Locked = true; + Cryptomining = true; + Fingerprinting = true; + }; + + # about:config + Preferences = { + "browser.contentblocking.category" = { Value = "strict"; Status = "locked"; }; + "extensions.pocket.enabled" = lock-false; + "extensions.screenshots.disabled" = lock-true; + "browser.topsites.contile.enabled" = lock-false; + "browser.formfill.enable" = lock-false; + "browser.search.suggest.enabled" = lock-false; + "browser.search.suggest.enabled.private" = lock-false; + "browser.urlbar.suggest.searches" = lock-false; + "browser.urlbar.showSearchSuggestionsFirst" = lock-false; + "browser.newtabpage.activity-stream.feeds.section.topstories" = lock-false; + "browser.newtabpage.activity-stream.feeds.snippets" = lock-false; + "browser.newtabpage.activity-stream.section.highlights.includePocket" = lock-false; + "browser.newtabpage.activity-stream.section.highlights.includeBookmarks" = lock-false; + "browser.newtabpage.activity-stream.section.highlights.includeDownloads" = lock-false; + "browser.newtabpage.activity-stream.section.highlights.includeVisited" = lock-false; + "browser.newtabpage.activity-stream.showSponsored" = lock-false; + "browser.newtabpage.activity-stream.system.showSponsored" = lock-false; + "browser.newtabpage.activity-stream.showSponsoredTopSites" = lock-false; + }; + + ExtensionSettings = { + # Block all extensions except those defined below. + "*".installation_mode = "blocked"; + + # uBlock Origin + "uBlock0@raymondhill.net" = { + install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; + installation_mode = "force_installed"; + }; + + # Bitwarden + "{446900e4-71c2-419f-a6a7-df9c091e268b}" = { + install_url = "https://addons.mozilla.org/firefox/downloads/latest/bitwarden-password-manager/latest.xpi"; + installation_mode = "force_installed"; + }; + + # Dark Reader + "addon@darkreader.org" = { + install_url = "https://addons.mozilla.org/firefox/downloads/latest/darkreader/latest.xpi"; + installation_mode = "force_installed"; + }; + }; + }; + + profiles.${config.home.username}.search = { + force = true; + default = "searx"; + order = [ "searx" ]; + engines = { + "Amazon.com".metaData.hidden = true; + "Bing".metaData.hidden = true; + "eBay".metaData.hidden = true; + "Google".metaData.hidden = true; + "Wikipedia (en)".metaData.alias = "@w"; + "searx" = { + urls = [{ + template = "http://10.44.4.100:8888/?q={searchTerms}"; + }]; + updateInterval = 24 * 60 * 60 * 1000; + definedAliases = [ "@sx" ]; + }; + }; + }; + }; +} diff --git a/users/tdback/modules/git/default.nix b/users/tdback/modules/git/default.nix new file mode 100644 index 0000000..c608c6b --- /dev/null +++ b/users/tdback/modules/git/default.nix @@ -0,0 +1,9 @@ +{ ... }: +{ + programs.git = { + enable = true; + userName = "tdback"; + userEmail = "tyler@tdback.net"; + extraConfig.init.defaultBranch = "main"; + }; +} diff --git a/users/tdback/modules/irc/default.nix b/users/tdback/modules/irc/default.nix new file mode 100644 index 0000000..bc96909 --- /dev/null +++ b/users/tdback/modules/irc/default.nix @@ -0,0 +1,30 @@ +{ ... }: +let + user = "tdback"; +in +{ + programs.irssi = { + enable = true; + + extraConfig = '' + settings = { core = { real_name = "${user}"; }; }; + ''; + + networks = { + liberachat = { + nick = "${user}"; + saslExternal = true; + server = { + address = "irc.libera.chat"; + port = 6697; + autoConnect = true; + ssl = { + enable = true; + verify = true; + certificateFile = "/home/${user}/.irssi/certs/libera.pem"; + }; + }; + }; + }; + }; +} diff --git a/users/tdback/modules/mpd/default.nix b/users/tdback/modules/mpd/default.nix new file mode 100644 index 0000000..d7338cb --- /dev/null +++ b/users/tdback/modules/mpd/default.nix @@ -0,0 +1,34 @@ +{ pkgs, ... }: +{ + services.mpd = { + enable = true; + package = pkgs.mpd; + + network = { + listenAddress = "127.0.0.1"; + port = 6600; + }; + + musicDirectory = "~/media/music"; + + extraConfig = '' + log_file "syslog" + max_output_buffer_size "16384" + + restore_paused "yes" + auto_update "yes" + + audio_output { + type "pulse" + name "pulseaudio" + } + + audio_output { + type "fifo" + name "Visualizer feed" + path "/tmp/mpd.fifo" + format "44100:16:2" + } + ''; + }; +} diff --git a/users/tdback/modules/ncmpcpp/default.nix b/users/tdback/modules/ncmpcpp/default.nix new file mode 100644 index 0000000..a201e88 --- /dev/null +++ b/users/tdback/modules/ncmpcpp/default.nix @@ -0,0 +1,65 @@ +{ pkgs, ... }: +{ + programs.ncmpcpp = { + enable = true; + package = pkgs.ncmpcpp.override { visualizerSupport = true; }; + mpdMusicDir = "~/Media/Music"; + settings = { + ncmpcpp_directory = "~/.config/ncmpcpp"; + lyrics_directory = "~/.local/share/lyrics"; + song_list_format = "{%a - }{%t}|{$8%f$9}$R{$3%l$9}"; + song_status_format = "{{%a{ \"%b\"{ (%y)}} - }{%t}}|{%f}"; + song_library_format = "{%n - }{%t}|{%f}"; + alternative_header_first_line_format = "$b$1$aqqu$/a$9 {%t}|{%f} $1$atqq$/a$9$/b"; + alternative_header_second_line_format = "{{$4$b%a$/b$9}{ - $7%b$9}{ ($4%y$9)}}|{%D}"; + current_item_prefix = "$(yellow)$r"; + current_item_suffix = "$/r$(end)"; + current_item_inactive_column_prefix = "$(white)$r"; + current_item_inactive_column_suffix = "$/r$(end)"; + now_playing_prefix = "$b"; + now_playing_suffix = "$/b"; + browser_playlist_prefix = "$2playlist$9 "; + selected_item_prefix = "$6"; + selected_item_suffix = "$9"; + modified_item_prefix = "$3> $9"; + song_window_title_format = "{%a - }{%t}|{%f}"; + browser_sort_mode = "type"; + browser_sort_format = "{%a - }{%t}|{%f} {%l}"; + visualizer_data_source = "/tmp/mpd.fifo"; + visualizer_output_name = "Visualizer feed"; + visualizer_in_stereo = true; + visualizer_type = "spectrum"; + visualizer_look = "●▮"; + visualizer_color = "blue, cyan, green, yellow, magenta, red"; + visualizer_spectrum_smooth_look = true; + }; + + bindings = [ + { key = "j"; command = "scroll_down"; } + { key = "k"; command = "scroll_up"; } + { key = "h"; command = [ "previous_column" "jump_to_parent_directory" ]; } + { key = "l"; command = [ "next_column" "enter_directory" "run_action" "play_item" ]; } + { key = "u"; command = "page_up"; } + { key = "d"; command = "page_down"; } + { key = "ctrl-u"; command = "page_up"; } + { key = "ctrl-d"; command = "page_down"; } + { key = "g"; command = "move_home"; } + { key = "G"; command = "move_end"; } + { key = "n"; command = "next_found_item"; } + { key = "N"; command = "previous_found_item"; } + { key = "J"; command = "move_sort_order_down"; } + { key = "K"; command = "move_sort_order_up"; } + { key = "f"; command = [ "show_browser" "change_browse_mode" ]; } + { key = "s"; command = [ "reset_search_engine" "show_search_engine" ]; } + { key = "m"; command = "toggle_media_library_columns_mode"; } + { key = "x"; command = "delete_playlist_items"; } + { key = "U"; command = "update_database"; } + { key = "P"; command = "show_playlist"; } + { key = "t"; command = "show_tag_editor"; } + { key = "v"; command = "show_visualizer"; } + { key = "."; command = "show_lyrics"; } + { key = "+"; command = "show_clock"; } + { key = "="; command = "volume_up"; } + ]; + }; +} diff --git a/users/tdback/modules/neomutt/default.nix b/users/tdback/modules/neomutt/default.nix new file mode 100644 index 0000000..243aa6b --- /dev/null +++ b/users/tdback/modules/neomutt/default.nix @@ -0,0 +1,69 @@ +{ pkgs, ... }: +{ + programs.neomutt = { + enable = true; + package = pkgs.neomutt; + + vimKeys = true; + sort = "reverse-date"; + + checkStatsInterval = 60; + + sidebar = { + enable = true; + shortPath = true; + width = 20; + }; + + binds = [ + { + map = [ "index" "pager" ]; + key = "\\Cp"; + action = "sidebar-prev"; + } + { + map = [ "index" "pager" ]; + key = "\\Cn"; + action = "sidebar-next"; + } + { + map = [ "index" "pager" ]; + key = "\\Cy"; + action = "sidebar-open"; + } + ]; + + macros = [ + { + map = [ "index" "pager" ]; + key = "gi"; + action = "=Inbox"; + } + { + map = [ "index" "pager" ]; + key = "gs"; + action = "=Sent"; + } + { + map = [ "index" "pager" ]; + key = "gd"; + action = "=Drafts"; + } + { + map = [ "index" "pager" ]; + key = "gt"; + action = "=Trash"; + } + { + map = [ "index" "pager" ]; + key = "ga"; + action = "=Archive"; + } + { + map = [ "index" ]; + key = "S"; + action = "${pkgs.isync}/bin/mbsync -a"; + } + ]; + }; +} diff --git a/users/tdback/modules/polybar/default.nix b/users/tdback/modules/polybar/default.nix new file mode 100644 index 0000000..833a260 --- /dev/null +++ b/users/tdback/modules/polybar/default.nix @@ -0,0 +1,112 @@ +{ lib, pkgs, ... }: +{ + services.polybar = { + enable = true; + package = pkgs.polybar.override { pulseSupport = true; }; + script = "polybar main &"; + settings = + let + colors = { + alert = "#505050"; + foreground = "#F1F1F1"; + background = "#050505"; + background-alt = "#373B41"; + }; + in + { + "bar/main" = { + bottom = true; + width = "100%"; + height = "16pt"; + line.size = "3pt"; + font = [ "Iosevka Comfy Motion Fixed:size=8" ]; + + foreground = "${colors.foreground}"; + background = "${colors.background}"; + + separator = "|"; + padding = { + left = 1; + right = 1; + }; + + module.margin = 1; + modules = { + left = "bspwm"; + center = "time"; + right = "volume cpu memory date"; + }; + + wm.restack = "bspwm"; + cursor.click = "pointer"; + }; + + "module/bspwm" = { + type = "internal/bspwm"; + pin.workspaces = true; + label = { + focused = { + text = "%index%"; + foreground = "${colors.foreground}"; + padding = 1; + }; + occupied = { + text = "%index%"; + foreground = "${colors.alert}"; + padding = 1; + }; + urgent = { + text = "%index%"; + foreground = "${colors.foreground}"; + background = "${colors.background-alt}"; + padding = 1; + }; + empty.text = ""; + }; + }; + + "module/cpu" = { + type = "internal/cpu"; + interval = 3; + label = "CPU %percentage%%"; + }; + + "module/memory" = { + type = "internal/memory"; + interval = 3; + label = "RAM %percentage_used%%"; + }; + + "module/volume" = { + type = "internal/pulseaudio"; + label = { + volume = "VOL %percentage%%"; + muted = "VOL 0%"; + }; + click.right = "${lib.getExe pkgs.pavucontrol}"; + }; + + "module/time" = { + type = "internal/date"; + interval = 1; + label = "%time%"; + time = "%H:%M"; + }; + + "module/date" = { + type = "internal/date"; + interval = 1; + label = "%date%"; + date = "%m.%d.%Y"; + }; + + "settings" = { + screenchange.reload = true; + pseudo.transparency = true; + }; + }; + }; + + # Make sure polybar starts only during graphical sessions. + systemd.user.services.polybar.Install.WantedBy = [ "graphical-session.target" ]; +} diff --git a/users/tdback/modules/rofi/default.nix b/users/tdback/modules/rofi/default.nix new file mode 100644 index 0000000..e3264df --- /dev/null +++ b/users/tdback/modules/rofi/default.nix @@ -0,0 +1,81 @@ +{ config, pkgs, ... }: +{ + programs.rofi = { + enable = true; + package = pkgs.rofi; + font = "Iosevka Comfy Motion Fixed 12"; + location = "center"; + extraConfig = { + modi = "window,run,drun"; + icon-theme = "Papirus"; + show-icons = true; + display-drun = ""; + display-window = ""; + drun-display-format = "{icon} {name}"; + }; + theme = + let + inherit (config.lib.formats.rasi) mkLiteral; + in + { + "*" = { + bg = mkLiteral "#050505"; + bg-alt = mkLiteral "#191919"; + fg = mkLiteral "#FFFFFF"; + fg-alt = mkLiteral"#787c99"; + background-color = mkLiteral "@bg"; + border = 0; + margin = 0; + padding = 0; + spacing = 0; + }; + + "window" = { + width = mkLiteral "40%"; + }; + + "element" = { + padding = 12; + text-color = mkLiteral "@fg-alt"; + }; + + "element selected" = { + text-color = mkLiteral "@fg"; + }; + + "element-text" = { + background-color = mkLiteral "inherit"; + text-color = mkLiteral "inherit"; + vertical-align = mkLiteral "0.5"; + }; + + "element-icon" = { + size = 38; + }; + + "entry" = { + background-color = mkLiteral "@bg-alt"; + text-color = mkLiteral "@fg"; + padding = 14; + placeholder = "Search..."; + }; + + "inputbar" = { + children = map mkLiteral [ "prompt" "entry" ]; + }; + + "listview" = { + columns = 2; + lines = 6; + background-color = mkLiteral "@bg"; + }; + + "prompt" = { + enabled = true; + background-color = mkLiteral "@bg-alt"; + text-color = mkLiteral "@fg"; + padding = mkLiteral "14 10 0 14"; + }; + }; + }; +} diff --git a/users/tdback/modules/shell/default.nix b/users/tdback/modules/shell/default.nix new file mode 100644 index 0000000..be63547 --- /dev/null +++ b/users/tdback/modules/shell/default.nix @@ -0,0 +1,59 @@ +{ pkgs, ... }: +{ + programs = { + zoxide = { + enable = true; + enableBashIntegration = true; + options = [ "--cmd cd" ]; + }; + + bash = { + enable = true; + historyFile = "~/.bash_history"; + historyControl = [ "ignoredups" "ignorespace" ]; + shellOptions = [ "histappend" ]; + initExtra = '' + PS1=" + \[\e[34m\]\u\[\e[33m\] at \[\e[34m\]\h\[\e[33m\] in \[\e[34m\]\w + \[\e[33m\]λ\[\e[0m\] " + + # Set sane options. + set -o noclobber + set -o vi + bind "\C-l":clear-screen + bind "\C-p":previous-history + bind "\C-n":next-history + ''; + + profileExtra = '' + # Add script directories to PATH. + PATH=$PATH:$HOME/scripts + PATH=$PATH:$HOME/.local/bin + + # Clean up duplicate entries in PATH while preserving directory order. + PATH="$(echo $PATH | tr ':' '\n' | awk '!a[$0]++' | tr '\n' ':' | sed 's/:$//')" + ''; + + sessionVariables = { + BROWSER = "firefox"; + EDITOR = "vi"; + KEYTIMEOUT = 1; + LC_ALL = "en_US.UTF-8"; + LESSHISTFILE = "-"; + MANPAGER = "less -R --use-color -Dd+r -Du+b"; + }; + + shellAliases = { + cp = "cp -i"; + mv = "mv -i"; + rm = "rm -I"; + ls = "ls --color=auto"; + cat = "bat -pp"; + grep = "grep --color=auto"; + diff = "diff --color=auto"; + song = "yt-dlp --continue --no-check-certificate --format=bestaudio -x --add-metadata --audio-format=flac"; + mkdir = "mkdir -p"; + }; + }; + }; +} diff --git a/users/tdback/modules/tmux/default.nix b/users/tdback/modules/tmux/default.nix new file mode 100644 index 0000000..8ac1c74 --- /dev/null +++ b/users/tdback/modules/tmux/default.nix @@ -0,0 +1,52 @@ +{ pkgs, ... }: +{ + programs.tmux = { + enable = true; + package = pkgs.tmux; + terminal = "tmux-256color"; + escapeTime = 0; + baseIndex = 0; + historyLimit = 10000; + mouse = true; + clock24 = true; + secureSocket = true; + aggressiveResize = true; + prefix = "C-t"; + extraConfig = '' + # Prevent detaching from tmux when closing a session. + set -g detach-on-destroy off + + # Kill the current session. + bind X kill-session + + # Splitting panes. + unbind v + unbind h + unbind % + unbind '"' + bind v split-window -h -c "#{pane_current_path}" # split vertically + bind h split-window -v -c "#{pane_current_path}" # split horizontally + + # Navigating panes. + bind ^ last-window + bind C-h select-pane -L + bind C-j select-pane -D + bind C-k select-pane -U + bind C-l select-pane -R + + # Copy mode movements. + set-window-option -g mode-keys vi + unbind -T copy-mode-vi Space; + unbind -T copy-mode-vi Enter; + bind -T copy-mode-vi v send-keys -X begin-selection + bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "xclip -in -selection clipboard" + + # Customizing status bar. + set -g status-position bottom + set -g status-style "bg=#050505 fg=#C5C8C6" + set -g status-right "" + setw -g window-status-current-format " #I#[fg=colour250]:#[fg=colour255]#W#[fg=colour50]#F" + setw -g window-status-format " #I#[fg=colour237]:#[fg=colour250]#W#[fg=colour244]#F" + ''; + }; +} diff --git a/users/tdback/modules/x11/default.nix b/users/tdback/modules/x11/default.nix new file mode 100644 index 0000000..41025a4 --- /dev/null +++ b/users/tdback/modules/x11/default.nix @@ -0,0 +1,94 @@ +{ pkgs, ... }: +{ + xsession.windowManager.bspwm = { + enable = true; + package = pkgs.bspwm; + settings = let color = "#3B4252"; in { + window_gap = 0; + top_padding = 0; + bottom_padding = 0; + right_padding = 0; + left_padding = 0; + top_monocle_padding = 0; + bottom_monocle_padding = 0; + right_monocle_padding = 0; + left_monocle_padding = 0; + split_ratio = 0.5; + borderless_monocle = true; + gapless_monocle = true; + normal_border_color = color; + active_border_color = color; + focused_border_color = color; + }; + + rules = { + "Zathura".state = "tiled"; + }; + + startupPrograms = [ + "${pkgs.xorg.setxkbmap}/bin/setxkbmap -layout us" + "${pkgs.xorg.xsetroot}/bin/xsetroot -cursor_name left_ptr" + "${pkgs.xorg.xset}/bin/xset r rate 350 40" + "~/.fehbg" + ]; + + extraConfig = '' + ${pkgs.bspwm}/bin/bspc monitor -d 1 2 3 4 5 6 7 8 9 + ''; + }; + + services.sxhkd = { + enable = true; + package = pkgs.sxhkd; + keybindings = { + # Program hotkeys. + "alt + Tab" = "rofi -show window"; + "super + r" = "rofi -show drun"; + "super + x" = "alacritty"; + "super + b" = "firefox"; + "super + p" = "flameshot full -p $HOME/.local/screenshots"; + "super + shift + p" = "flameshot gui -p $HOME/.local/screenshots"; + "super + Escape" = "systemctl --user restart polybar"; + "super + alt + {q,r}" = "bspc {quit,wm -r}"; + + # Function hotkeys. + "XF86AudioPrev" = "mpc prev"; + "XF86AudioNext" = "mpc next"; + "XF86AudioPlay" = "mpc toggle"; + "XF86AudioLowerVolume" = "pamixer -d 5"; + "XF86AudioRaiseVolume" = "pamixer -i 5"; + "XF86AudioMute" = "pamixer -t"; + + # Manipulate window manager. + "super + q" = "bspc node -{c,k}"; + "super + f" = "bspc node focused.tiled -t fullscreen"; + "super + t" = "bspc node focused.fullscreen -t tiled"; + "super + shift + f" = "bspc node focused.tiled -t floating"; + "super + shift + t" = "bspc node focused.floating -t tiled"; + "super + {_,shift + }{h,j,k,l}" = "bspc node -{f,s} {west,south,north,east}"; + "super + {_,shift}c" = "bspc node -f {next,prev}.local.!hidden.window"; + "super + bracket{left,right}" = "bspc desktop -f {prev,next}.local"; + "super + {grave,Tab}" = "bspc {node,desktop} -f last"; + "super + {o,i}" = "bspc wm -h off; bspc node {older,newer} -f; bspc wm -h on"; + "super + {_,shift + }{1-9,0}" = "bspc {desktop -f, node -d} '^{1-9,10}'"; + "super + alt + {h,j,k,l}" = "bspc node -z {left -20 0, bottom 0 20, top 0 -20, right 20 0}"; + "super + alt + shift {h,j,k,l}" = "bspc node -z {right -20 0, top 0 20, bottom 0 -20, left 20 0}"; + "super + {Left,Down,Up,Right}" = "bspc node -v {-20 0,0 20,0 -20,20 0}"; + }; + }; + + # Generate X11 init scripts. + home.file = { + ".xinitrc".text = '' + [ -f ~/.xprofile ] && . ~/.xprofile + [ -f ~/.Xresources ] && xrdb -merge ~/.Xresources + exec bspwm + ''; + ".xprofile".text = '' + xrandr --output DP-0 --primary --mode 1920x1080 --rotate normal --rate 165 + ''; + ".Xresources".text = '' + Xcursor.size: 24 + ''; + }; +} -- cgit v1.2.3