From 36ae02372ca9c133f1017e96de2a1535982d5707 Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Thu, 26 Sep 2024 23:50:15 -0400 Subject: [PATCH] init --- .git-crypt/.gitattributes | 4 + ...5E4754FE1AEDA15A6D47029AB28AC10ECE533D.gpg | Bin 0 -> 735 bytes .gitattributes | 3 + configuration.nix | 231 ++++++++++++++++++ flake.lock | 48 ++++ flake.nix | 82 +++++++ hardware.nix | 46 ++++ secrets/hashedPass | Bin 0 -> 96 bytes secrets/mullvad.nix | Bin 0 -> 267 bytes secrets/murmur_password | Bin 0 -> 39 bytes services/caddy.nix | 41 ++++ services/git.nix | 40 +++ services/immich.nix | 26 ++ services/jellyfin.nix | 18 ++ services/quadlet.nix | 84 +++++++ 15 files changed, 623 insertions(+) create mode 100644 .git-crypt/.gitattributes create mode 100644 .git-crypt/keys/default/0/D15E4754FE1AEDA15A6D47029AB28AC10ECE533D.gpg create mode 100644 .gitattributes create mode 100644 configuration.nix create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 hardware.nix create mode 100644 secrets/hashedPass create mode 100644 secrets/mullvad.nix create mode 100644 secrets/murmur_password create mode 100644 services/caddy.nix create mode 100644 services/git.nix create mode 100644 services/immich.nix create mode 100644 services/jellyfin.nix create mode 100644 services/quadlet.nix diff --git a/.git-crypt/.gitattributes b/.git-crypt/.gitattributes new file mode 100644 index 0000000..665b10e --- /dev/null +++ b/.git-crypt/.gitattributes @@ -0,0 +1,4 @@ +# Do not edit this file. To specify the files to encrypt, create your own +# .gitattributes file in the directory where your files are. +* !filter !diff +*.gpg binary diff --git a/.git-crypt/keys/default/0/D15E4754FE1AEDA15A6D47029AB28AC10ECE533D.gpg b/.git-crypt/keys/default/0/D15E4754FE1AEDA15A6D47029AB28AC10ECE533D.gpg new file mode 100644 index 0000000000000000000000000000000000000000..1d65e96a4b3c019fb865e992ff37d734b430a914 GIT binary patch literal 735 zcmZo=;$fb(sp}x$xnNsH0fw2^{7*~?5PdH_XRh+@`KOlsedqD#2Cw$Yi!J+Q7qXy(h7)>TTcF+q)N@diE~tLFo+NlXtg%QF*bgIoH}Zjx)eUZRU%!k|7bH%36Gh zoYT)&8&7lA4QuiK?Iy!*U~Xxvx?=8(4~~BoZVBJfZnIB+l>IUILE{OlQ_By`_;b>8 z&gA=mNRVBlQ%eEr!_n&`Rxu1o(qV0WSQfjje(zL#`tQCix0G|1eLk@u%=lr`zFRB0Hg4!$_~0wE zw=Q4svyTic`*eQJ=$;U+e^lO3K3`G7R^`d2Ni&2PR4#PChkjYEAl0gSPbT*CO=V12 zwZY&Z*CBS-c>$lkT(Y0K&2<<5r<>QWezEDWm{7&IBs=kk*7<|Y&s_NXUwG=>h~2&E zyPjTSeLl;jU5aI2%G1iY3bdv$MM1P zx`^Hsan(0BkI!Q@XqA`MvRxY?@yubWMwf literal 0 HcmV?d00001 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..82c6e8a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +secrets/murmur_password filter=git-crypt diff=git-crypt +secrets/hashedPass filter=git-crypt diff=git-crypt +secrets/mullvad.nix filter=git-crypt diff=git-crypt diff --git a/configuration.nix b/configuration.nix new file mode 100644 index 0000000..96c790c --- /dev/null +++ b/configuration.nix @@ -0,0 +1,231 @@ +{ + config, + lib, + pkgs, + hostname, + username, + eth_interface, + service_configs, + ... +}: +{ + imports = [ + ./hardware.nix + # ./services/jellyfin.nix + ./services/caddy.nix + ./services/quadlet.nix + ./services/immich.nix + ./services/git.nix + ]; + + nix = { + #garbage collection and cleanup stuff + gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 7d"; + }; + + #optimize the store + optimise.automatic = true; + + #enable flakes! + settings.experimental-features = [ + "nix-command" + "flakes" + ]; + }; + + boot = { + kernelPackages = pkgs.linuxPackages_6_10; + + supportedFilesystems = [ "zfs" ]; + zfs.extraPools = [ "tank" ]; + loader = { + # Use the systemd-boot EFI boot loader. + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + }; + + # Set your time zone. + time.timeZone = "America/New_York"; + + # Enable the OpenSSH daemon. + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + PermitRootLogin = "no"; + }; + }; + + #Intel GPU stuff + nixpkgs.config.packageOverrides = pkgs: { + vaapiIntel = pkgs.vaapiIntel.override { enableHybridCodec = true; }; + }; + + hardware.graphics = { + enable = true; + extraPackages = with pkgs; [ + intel-media-driver + intel-vaapi-driver # previously vaapiIntel + vaapiVdpau + intel-compute-runtime # OpenCL filter support (hardware tonemapping and subtitle burn-in) + vpl-gpu-rt # QSV on 11th gen or newer + ]; + }; + + #fwupd for updating firmware + services.fwupd = { + enable = true; + extraRemotes = [ "lvfs-testing" ]; + }; + + environment.systemPackages = with pkgs; [ + helix + nixfmt-rfc-style + + lm_sensors + bottom + htop + + borgbackup + smartmontools + + nil + + ripgrep + + intel-gpu-tools + ]; + + services.zfs = { + autoScrub.enable = true; + autoSnapshot.enable = true; + }; + + systemd.services.no-rgb = + let + no-rgb = pkgs.writeScriptBin "no-rgb" '' + #!/bin/sh + NUM_DEVICES=$(${pkgs.openrgb}/bin/openrgb --noautoconnect --list-devices | ${pkgs.coreutils}/bin/grep -E '^[0-9]+: ' | ${pkgs.coreutils}/bin/wc -l) + + for i in $(${pkgs.coreutils}/bin/seq 0 $(($NUM_DEVICES - 1))); do + ${pkgs.openrgb}/bin/openrgb --noautoconnect --device $i --mode direct --color 000000 + done + ''; + in + { + description = "disable rgb"; + serviceConfig = { + ExecStart = "${no-rgb}/bin/no-rgb"; + Type = "oneshot"; + }; + wantedBy = [ "multi-user.target" ]; + }; + + services.hardware.openrgb = { + enable = true; + package = pkgs.openrgb-with-all-plugins; + motherboard = "amd"; + }; + + services.udev.packages = [ pkgs.openrgb-with-all-plugins ]; + hardware.i2c.enable = true; + + networking = { + nameservers = [ + "1.1.1.1" + "9.9.9.9" + ]; + + hostName = hostname; + hostId = "0f712d56"; + firewall.enable = true; + useDHCP = false; + + interfaces.${eth_interface} = { + ipv4.addresses = [ + { + address = "10.1.1.102"; + prefixLength = 24; + } + ]; + }; + defaultGateway = { + address = "10.1.1.1"; + interface = eth_interface; + }; + }; + + virtualisation = { + containers.enable = true; + podman = { + enable = true; + + # Required for containers under podman-compose to be able to talk to each other. + defaultNetwork.settings.dns_enabled = true; + }; + }; + + users.users.${username} = { + isNormalUser = true; + extraGroups = [ + "wheel" + "video" + "render" + ]; + hashedPasswordFile = "/etc/nixos/secrets/hashedPass"; + + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO4jL6gYOunUlUtPvGdML0cpbKSsPNqQ1jit4E7U1RyH" # laptop + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBJjT5QZ3zRDb+V6Em20EYpSEgPW5e/U+06uQGJdraxi" # desktop + ]; + }; + + # https://nixos.wiki/wiki/Fish#Setting_fish_as_your_shell + programs.fish.enable = true; + programs.bash = { + interactiveShellInit = '' + if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]] + then + shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION="" + exec ${pkgs.fish}/bin/fish $LOGIN_OPTION + fi + ''; + }; + + security = { + #lets use doas and not sudo! + doas.enable = true; + sudo.enable = false; + # Configure doas + doas.extraRules = [ + { + users = [ username ]; + keepEnv = true; + persist = true; + } + ]; + }; + + networking.firewall.allowedTCPPorts = [ + service_configs.ports.minecraft + ]; + + services.murmur = { + enable = true; + openFirewall = true; + welcometext = "meow meow meow meow meow :3 xd"; + password = builtins.readFile ./secrets/murmur_password; + }; + + services.postgresql = { + enable = true; + package = pkgs.postgresql_16; + dataDir = "/tank/services/sql"; + }; + + system.stateVersion = "24.05"; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..31ea209 --- /dev/null +++ b/flake.lock @@ -0,0 +1,48 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1727444619, + "narHash": "sha256-Y4X22oYrmYZcVVLa708GX/trYjSGkPgd2HpnOR0kTfg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c198f2dc39f569fadff23d199715be9c345a1383", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixpkgs", + "type": "github" + } + }, + "quadlet-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1727065535, + "narHash": "sha256-jX83vspAPZnnpFUylUYqP+J1RoZc9w10bbQtsEwD20A=", + "owner": "SEIAROTg", + "repo": "quadlet-nix", + "rev": "51e2beaaf127c8b4460d909c6c29ed9d60bfde0c", + "type": "github" + }, + "original": { + "owner": "SEIAROTg", + "repo": "quadlet-nix", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "quadlet-nix": "quadlet-nix" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..e08ed6f --- /dev/null +++ b/flake.nix @@ -0,0 +1,82 @@ +{ + description = "Flake for server muffin"; + + inputs = { + # nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + nixpkgs.url = "github:NixOS/nixpkgs/master"; + quadlet-nix.url = "github:SEIAROTg/quadlet-nix"; + quadlet-nix.inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = + { + nixpkgs, + quadlet-nix, + ... + }: + let + username = "primary"; + hostname = "muffin"; + eth_interface = "enp3s0"; + + service_configs = { + hdd_path = "/mnt/hdd"; + + # TODO: add checks to make sure none of these collide + ports = { + https = 443; + immich = 3001; + jellyfin = 8096; + torrent = 6011; + minecraft = 25565; + git-server = 3281; + }; + + https = { + certs = "/tank/services/http_certs"; + data_dir = "/tank/services/http"; + }; + + gitea = { + dir = "/tank/services/gitea"; + }; + + postgres = { + socket = "/run/postgresql"; + }; + + immich = { + dir = "/tank/services/immich"; + }; + + minecraft = { + dir = "/tank/services/minecraft"; + }; + + gluetun = { + dir = "/tank/services/gluetun"; + }; + + torrent = { + config_dir = "/tank/services/qbittorrent/config"; + download_dir = "${service_configs.hdd_path}/torrents"; + }; + }; + in + { + nixosConfigurations.${hostname} = nixpkgs.lib.nixosSystem { + specialArgs = { + inherit + username + hostname + eth_interface + service_configs + ; + }; + modules = [ + ./configuration.nix + quadlet-nix.nixosModules.quadlet + ]; + }; + }; +} diff --git a/hardware.nix b/hardware.nix new file mode 100644 index 0000000..2229c44 --- /dev/null +++ b/hardware.nix @@ -0,0 +1,46 @@ +{ + config, + lib, + pkgs, + service_configs, + ... +}: + +{ + boot.initrd.availableKernelModules = [ + "xhci_pci" + "ahci" + "usb_storage" + "usbhid" + "sd_mod" + ]; + boot.initrd.kernelModules = [ "dm-snapshot" ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = { + device = "/dev/disk/by-uuid/f467d1e8-5f00-40ee-aa67-55a999181918"; + fsType = "ext4"; + }; + + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/96DC-6E54"; + fsType = "vfat"; + options = [ + "fmask=0022" + "dmask=0022" + ]; + }; + + # 3tb HDD + fileSystems.${service_configs.hdd_path} = { + device = "/dev/disk/by-uuid/f69b8c84-20ca-448f-b580-8951f20b9fc1"; + fsType = "xfs"; + }; + + swapDevices = [ ]; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = true; + hardware.enableRedistributableFirmware = true; +} diff --git a/secrets/hashedPass b/secrets/hashedPass new file mode 100644 index 0000000000000000000000000000000000000000..fe3affff75466277bda5c56a5e61ad6fbb110877 GIT binary patch literal 96 zcmZQ@_Y83kiVO&0@VRxTU2fGot_6>$T6I54-8=Ws!~LDds#YF6@8ptx_E1WC7LU^Q z0L29L)?Koj=1)$j{>`^NUL^YNs@kre;Nz{f4Zm40+`QXaZ1U`3sQAn)*$-I{@E%?P E0M<<~XaE2J literal 0 HcmV?d00001 diff --git a/secrets/mullvad.nix b/secrets/mullvad.nix new file mode 100644 index 0000000000000000000000000000000000000000..4426bc5860ad5552e6c0b76ecd87e5ebce57fb7b GIT binary patch literal 267 zcmZQ@_Y83kiVO&0@YuQ0e$n;=n!&9P%AD@Z-_>z-L3FfY=9b7OeZ{#9qO;mfOkZ#B z|CCpKm)Z1P?ah}*Qj(=vcQ`R@pYzDGxVisJiGt~S{*z*>*4^@n(5s1$za4*|&|kr$ zGI#fn9B21)F6*=>u4o96zNc;IXkM_ouupGK{pq^-Lerk=EPtRqYn503Q{T3<=8j)% znb&%lmVb|&(R;UXbJmRMI)Qfmn?g=!hAwD4bV=c}i-@*5cd1_R^^3-gjJsT|ULQ}q zquS#*^HxgZVY%7)&zYLfW$qMXk(&8->v`^nvF1Ix+a64;5~$@^d(k4X^zC2aeKYeJ bFE+V9od3UU^MzBZ6B0|V?@iR45_Jp!XtROp literal 0 HcmV?d00001 diff --git a/secrets/murmur_password b/secrets/murmur_password new file mode 100644 index 0000000000000000000000000000000000000000..d1dd0c80284b03aa851d8dd7602c99ab7ac4a0be GIT binary patch literal 39 vcmZQ@_Y83kiVO&0IB`5$soc=q?oPuWji6M?8SlP!%6x literal 0 HcmV?d00001 diff --git a/services/caddy.nix b/services/caddy.nix new file mode 100644 index 0000000..eba481a --- /dev/null +++ b/services/caddy.nix @@ -0,0 +1,41 @@ +{ service_configs, ... }: +{ + services.caddy = { + enable = true; + virtualHosts = { + ":${builtins.toString service_configs.ports.https}".extraConfig = '' + tls ${service_configs.https.certs}/cert.crt ${service_configs.https.certs}/cert.key + + handle_path /torrent* { + reverse_proxy 127.0.0.1:${builtins.toString service_configs.ports.torrent} + } + + root * ${service_configs.https.data_dir} + file_server browse + ''; + + "immich.gardling.com".extraConfig = '' + reverse_proxy 127.0.0.1:${builtins.toString service_configs.ports.immich} + ''; + + "jellyfin.gardling.com".extraConfig = '' + reverse_proxy 127.0.0.1:${builtins.toString service_configs.ports.jellyfin} + request_body { + max_size 4096MB + } + ''; + + "git.gardling.com".extraConfig = '' + reverse_proxy 127.0.0.1:${builtins.toString service_configs.ports.git-server} + ''; + }; + }; + + networking.firewall.allowedTCPPorts = [ + service_configs.ports.https + ]; + + networking.firewall.allowedUDPPorts = [ + service_configs.ports.https + ]; +} diff --git a/services/git.nix b/services/git.nix new file mode 100644 index 0000000..867945a --- /dev/null +++ b/services/git.nix @@ -0,0 +1,40 @@ +{ + config, + service_configs, + ... +}: +{ + services.gitea = { + enable = true; + appName = "TBD name of my gitea server"; + stateDir = service_configs.gitea.dir; + database = { + type = "postgres"; + socket = service_configs.postgres.socket; + }; + settings = { + server = { + DOMAIN = "git.gardling.com"; + ROOT_URL = "https://git.gardling.com"; + HTTP_PORT = service_configs.ports.git-server; + }; + session = { + # https cookies or smth + COOKIE_SECURE = true; + }; + # only I shall use gitea + service.DISABLE_REGISTRATION = true; + }; + }; + + services.postgresql = { + ensureDatabases = [ config.services.gitea.user ]; + ensureUsers = [ + { + name = config.services.gitea.database.user; + ensureDBOwnership = true; + ensureClauses.login = true; + } + ]; + }; +} diff --git a/services/immich.nix b/services/immich.nix new file mode 100644 index 0000000..114b2d4 --- /dev/null +++ b/services/immich.nix @@ -0,0 +1,26 @@ +{ + service_configs, + pkgs, + config, + ... +}: +{ + services.immich = { + enable = true; + mediaLocation = service_configs.immich.dir; + port = service_configs.ports.immich; + host = "0.0.0.0"; + database = { + createDB = true; + }; + }; + + environment.systemPackages = with pkgs; [ + immich-go + ]; + + users.users.${config.services.immich.user}.extraGroups = [ + "video" + "render" + ]; +} diff --git a/services/jellyfin.nix b/services/jellyfin.nix new file mode 100644 index 0000000..8b78b74 --- /dev/null +++ b/services/jellyfin.nix @@ -0,0 +1,18 @@ +{ pkgs, config, ... }: +{ + environment.systemPackages = with pkgs; [ + jellyfin + jellyfin-web + jellyfin-ffmpeg + ]; + + services.jellyfin = { + enable = true; + openFirewall = true; + }; + + users.users.${config.services.jellyfin.user}.extraGroups = [ + "video" + "render" + ]; +} diff --git a/services/quadlet.nix b/services/quadlet.nix new file mode 100644 index 0000000..8e5ecee --- /dev/null +++ b/services/quadlet.nix @@ -0,0 +1,84 @@ +{ service_configs, ... }: +{ + virtualisation.quadlet = { + containers = + let + baseContainerConfig = { + autoUpdate = "registry"; + environments = { + PUID = 1000; + PGID = 1000; + }; + }; + in + { + minecraft-server.containerConfig = baseContainerConfig // { + image = "docker.io/itzg/minecraft-server:java21-graalvm"; + name = "minecraft"; + + environments = { + TYPE = "QUILT"; + MEMORY = "4G"; + MOD_PLATFORM = "MODRINTH"; + USE_AIKAR_FLAGS = true; + JVM_OPTS = "-XX:-UseJVMCICompiler"; + MODRINTH_MODPACK = "https://modrinth.com/modpack/sop"; + VERSION = "1.21.1"; + }; + + publishPorts = [ "${builtins.toString service_configs.ports.minecraft}:25565" ]; + volumes = [ "${service_configs.minecraft.dir}:/data:z" ]; + }; + + gluetun.containerConfig = baseContainerConfig // { + image = "docker.io/qmcgaw/gluetun"; + name = "gluetun"; + + addCapabilities = [ + "NET_ADMIN" + "MKNOD" + ]; + + environments = import ../secrets/mullvad.nix; + + publishPorts = [ + "6081:6081" + "6081:6081/udp" + "${builtins.toString service_configs.ports.torrent}:6011" + ]; + + volumes = [ "${service_configs.gluetun.dir}:/gluetun:z" ]; + podmanArgs = [ + "--device=/dev/net/tun" + "--security-opt label=disable" + ]; + }; + + qbittorrent = { + containerConfig = baseContainerConfig // { + image = "lscr.io/linuxserver/qbittorrent:latest"; + name = "qbittorrent"; + environments = { + WEBUI_PORT = service_configs.ports.torrent; + DOCKER_MODS = "ghcr.io/gabe565/linuxserver-mod-vuetorrent"; + }; + + volumes = [ + "${service_configs.torrent.config_dir}:/config:z" + "${service_configs.torrent.download_dir}:/downloads:z" + ]; + + networks = [ "container:gluetun" ]; + }; + + serviceConfig = { + requires = [ "gluetun.service" ]; + after = [ "gluetun.service" ]; + }; + }; + }; + networks = { + internal.networkConfig.subnets = [ "10.0.123.1/24" ]; + }; + }; +}