# ./nixos/homelab.nix { config, pkgs, lib, inputs, ... }: { imports = [ ../modules/nextcloud-setup.nix ../modules/media/qbittorrent.nix ../modules/media/arr-suite.nix # ../modules/home-assistant.nix # ../modules/home-assistant-vm.nix ../modules/vms/incus-base.nix ../modules/smb.nix ]; arrSuite.enable = true; services.samba.shares.Media.path = "/media/storage/media"; # nixpkgs.config.allowUnfree = true; boot.loader.systemd-boot.enable = true; # Or grub, as appropriate for your server boot.loader.efi.canTouchEfiVariables = true; powerManagement.cpuFreqGovernor = "ondemand"; # hopefully fix low cpu freq hardware.cpu.amd.updateMicrocode = true; # same networking.hostName = "homelab"; # Set the server's hostname boot.initrd.kernelModules = [ "dm_mod" "dm_thin_pool" ]; # Device mapper core boot.initrd.availableKernelModules = [ # For LVM thin provisioning # Add filesystem types you expect to find on these LVs, e.g., "ext4", "xfs", "zfs" (if using ZFS on LVM) "ext4" "xfs" ]; services.lvm.enable = true; services.lvm.boot.thin.enable = true; # Crucial for thin pools nix.settings.experimental-features = [ "nix-command" "flakes" ]; # Mount for your media LV (from /dev/sdd via media VG) fileSystems."/media" = { device = "/dev/media/vm-101-disk-0"; fsType = "ext4"; options = [ "defaults" "nofail" ]; }; time.timeZone = "America/Los_Angeles"; # Mount for your newly formatted storage LV fileSystems."/storage" = { device = "/dev/Storage/data_lv"; # Path to your new thick LV fsType = "ext4"; # Or xfs if you chose that options = [ "defaults" "nofail" ]; }; virtualisation.incus.enable = true; # Basic firewall networking.nftables.enable = true; networking.firewall.enable = true; networking.firewall.allowedTCPPorts = [ 22 53 8096 # jellyfin ]; networking.firewall.allowedUDPPorts = [ 53 # AdGuard Home DNS over UDP ]; # Bridge configuration for Incus VMs networking.bridges.br0.interfaces = [ "enp41s0" ]; networking.interfaces.br0 = { ipv4.addresses = [ { address = "192.168.0.116"; # <-- SET YOUR SERVER'S DESIRED STATIC IP prefixLength = 24; # <-- SET YOUR SUBNET MASK (24 = 255.255.255.0) } ]; }; networking.defaultGateway = "192.168.0.1"; # <-- SET YOUR ROUTER'S IP networking.nameservers = [ "192.168.0.116" ]; networking.interfaces.enp41s0.useDHCP = false; # Allow SSH networking.firewall.trustedInterfaces = [ "tailscale0" "docker0" "br0" ]; # <--- ADDED for Tailscale access # SSH Server configuration services.openssh = { enable = true; ports = [ 22 ]; openFirewall = true; settings.PasswordAuthentication = false; # Recommended: use SSH keys settings.PermitRootLogin = "no"; # Recommended }; # networking.firewall.checkReversePath = "loose"; services.tailscale = { enable = true; useRoutingFeatures = "both"; }; networking.firewall.checkReversePath = "loose"; # needed for tailscale nodes # Define the 'death916' user for the server #claimTokenFile = "/var/lib/netdata/cloud.d/token"; users.users.death916 = { isNormalUser = true; shell = pkgs.bash; extraGroups = [ "wheel" "media_services" "nextcloud" "docker" "qbittorent" "incus-admin" ]; # For sudo access openssh.authorizedKeys.keys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCte9KjJUSn4xBPEKCk9QER6+jF+C0uBatVl27zIamYsryyHdFrmqK2DAg7OhqTHqzjxID6sp6d57MsJqOUAtwXbUDMLffqBSerUxfTm+1SPDrhL0GSvo0QVjMLVseOEq8d2qXgW1R7dIk412VbO5e9SAump5aJOHI/SzT6VLoUczalmqrjnDacWQMeLu/TSOZHcfrhjYSg+b1xbc1vHp6C4obOb8JIj/anAieT/1P36MhlNW79ow6PWenLemBYeeezFrKtESF1oMc8jmcxogzgLamlqhKYAHlKhOuBF6u0nRneI5IPDbbMF5zwEv5szCEKj8XZJVYUk8uUg7ARyppjcA7yAXuaNKBNxa7tfjqWrDWOACn97ufE5FFJt0XH5JzkXcDh96K8ZSZaWxMRu2s+GlIu/1F415xtVfe1d79HYkWke/ewaQ4NqgOt8f7wRvyzabpQZDzkaXO0UoK65O2HyUur33XWCEmV+1pB6BrS8pD+1I4Tvbnc+rOgtHTTRfKqezKqZmaErEOxClBwvWjvn0PzhGSoClTGXPjhl239/sH0JGY09dTBh8GtAVbfv+jFO6nm6aR7O/OwSaohY3uOdRo8XyxJr4XyGAaBNRdm6BUJRnB4W51J49IQBZzIe2NUkNMHeUT4jkxFpfhkujnSFw2ZnOLkERpwkltAlbwuLw== tavn1992@gmail.com" # <<-- REPLACE THIS WITH YOUR SSH PUBLIC KEY for death916 # Add more keys if needed ]; # If 'death916' needs a password on the server (less secure than key-only) # initialPassword = "yoursecurepassword"; # Or use hashed password }; users.users.audiobookshelf = { isSystemUser = true; # System user, doesn't need a home directory by default for services group = "media_services"; # Primary group # extraGroups = [ "media_services" ]; # Alternatively, if you want a different primary group }; # users.users.nextcloud = { # This merges with the 'nextcloud' user definition from services.nextcloud in the imported module # extraGroups = [ "media_services" ]; #}; users.groups.media_services = { }; #users.groups.nextcloud = {}; # homelab services services.plex = { enable = true; openFirewall = true; user = "death916"; }; services.audiobookshelf = { enable = true; user = "audiobookshelf"; group = "media_services"; host = "0.0.0.0"; # <--- ADD THIS LINE to listen on all IPv4 interfaces port = 13378; }; #networking.firewall.allowedTCPPorts = [19999]; # services.netdata.package = pkgs.netdata.override { withCloud = true; }; services.netdata = { # package = pkgs.netdata.override { # withCloud = true; # }; enable = true; # claimTokenFile = "/var/lib/netdata/cloud.d"; config = { global = { "memory mode" = "ram"; "debug log" = "none"; "access log" = "none"; "error log" = "syslog"; }; }; }; users.users.qbittorrent.extraGroups = [ "media_services" ]; users.groups.qbittorrent = { }; services.qbittorrent = { enable = true; dataDir = "/media/storage/media/downloads/"; user = "qbittorrent"; group = "qbittorrent"; port = 8090; openFirewall = true; package = pkgs.qbittorrent-nox; }; systemd.tmpfiles.rules = [ "d /media/storage/media/downloads/qBittorrent 0775 root media_services - -" "d /storage/services/qbittorrent 0755 qbittorrent qbittorrent - -" "d /storage/services/qbittorrent/config 0755 qbittorrent qbittorrent - -" ]; services.jellyfin.enable = true; services.actual = { enable = true; settings = { port = 5006; # Default # listenAddress = "127.0.0.1"; }; }; virtualisation.docker.enable = true; # users.users.death916.extraGroups = [ "docker" ]; # If needed virtualisation.oci-containers = { backend = "docker"; containers = { dufs = { image = "sigoden/dufs:latest"; ports = [ "5000:5000" ]; volumes = [ "/media/storage/media/:/data" ]; # <-- Remember to change this path cmd = [ "/data" "-A" ]; #extraOptions = [ "--restart=unless-stopped" ]; }; c2c-scraper = { image = "death916/c2cscrape:latest"; volumes = [ "/media/storage/media/books/audio/podcasts/C2C:/downloads" "/media/storage/media/docker/volumes/c2cscrape:/app/data" ]; environment = { TZ = "America/Los_Angeles"; }; autoStart = true; # Consider adding if not already present # removeContainer = false; extraOptions = [ "--dns=8.8.8.8" ]; }; adguardhome = { image = "adguard/adguardhome:latest"; autoStart = true; ports = [ "53:53/tcp" "53:53/udp" "3000:3000/tcp" ]; volumes = [ "/storage/services/adguard/work:/opt/adguardhome/work" "/storage/services/adguard/data:/opt/adguardhome/conf" ]; # extraOptions = [ # "--network=host" # ]; }; }; }; boot.kernel.sysctl = { "net.ipv4.ip_forward" = 1; "net.ipv6.conf.all.forwarding" = 1; }; systemd.services.kopia-backup = { description = "Kopia backup service for NixOS server"; serviceConfig = { Type = "oneshot"; User = "root"; # Run as root to access all files and Kopia config ExecStart = "/usr/local/bin/nixos-kopia-backup.sh"; path = with pkgs; [ coreutils # Provides basic tools like `sh`, `cat`, etc. kopia # The kopia binary itself ]; }; }; systemd.timers.kopia-backup = { description = "Daily Kopia backup timer"; wantedBy = [ "timers.target" ]; partOf = [ "kopia-backup.service" ]; # Links timer to the service timerConfig = { OnCalendar = "hourly"; # Or "hourly", "*-*-* 02:00:00" for 2 AM daily, etc. Persistent = true; # Run on next boot if a scheduled run was missed Unit = "kopia-backup.service"; }; }; users.users.adguardhome = { isSystemUser = true; group = "adguardhome"; extraGroups = [ "adgaurdhome-access" ]; }; users.groups.adguardhome-access = { }; users.groups.adguardhome = { }; #services.homeAssistantVM.enable = true; # Sudo access for the wheel group (which death916 is part of) security.sudo.wheelNeedsPassword = true; # Or false if you prefer passwordless sudo for wheel # Essential server packages environment.systemPackages = with pkgs; [ git vim htop tmux tailscale lvm2 rsync multipath-tools # kpartx btop wget pkgs.jellyfin-web pkgs.jellyfin-ffmpeg pkgs.jellyfin unzip kopia manix qemu ]; # If you use custom overlays specific to this server: # nixpkgs.overlays = [(import ../overlays/homelab-overlay.nix)]; system.stateVersion = "24.11"; # Set to your NixOS version }