diff --git a/.forgejo/workflows/activate.yml b/.forgejo/workflows/activate.yml new file mode 100644 index 0000000..869f0f4 --- /dev/null +++ b/.forgejo/workflows/activate.yml @@ -0,0 +1,41 @@ +name: Activate Homelab Configuration + +on: + workflow_dispatch: + push: + branches: [ main ] + +env: + PATH: /run/current-system/sw/bin:/run/wrappers/bin + +jobs: + rebuild: + runs-on: self-hosted + steps: + - name: Setup SSH key + run: | + mkdir -p ./ssh + echo "${{ secrets.DEPLOY_SSH_KEY }}" > ./ssh/deploy_key + chmod 600 ./ssh/deploy_key + + - name: Rebuild and switch + run: | + ssh -i ./ssh/deploy_key \ + -o PasswordAuthentication=no \ + -o StrictHostKeyChecking=no \ + -o UserKnownHostsFile=/dev/null \ + root@localhost \ + "bash -lc 'nixos-rebuild switch --refresh --flake git+http://localhost:5080/satr14/nix-flake#homelab -L'" + + - name: Show generation + if: always() + run: | + ssh -i ./ssh/deploy_key \ + -o PasswordAuthentication=no \ + -o StrictHostKeyChecking=no \ + -o UserKnownHostsFile=/dev/null \ + root@localhost "bash -lc 'nixos-version'" + + - name: Clean Up + if: always() + run: rm -f ./ssh/deploy_key \ No newline at end of file diff --git a/.sops.yaml b/.sops.yaml deleted file mode 100644 index a2c7b59..0000000 --- a/.sops.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# To set up sops-nix: -# 1. Generate an age key on each host: -# mkdir -p ~/.config/sops/age -# age-keygen -o ~/.config/sops/age/keys.txt -# Or derive from the host SSH key: -# nix-shell -p ssh-to-age --run 'cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age' -# -# 2. Replace the placeholder age keys below with the actual public keys. -# -# 3. Encrypt secret files: -# sops secrets/homelab.yaml -# -# 4. To re-key after changing keys: -# sops updatekeys secrets/homelab.yaml - -keys: - - &homelab age1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # replace with: ssh-to-age < /etc/ssh/ssh_host_ed25519_key.pub - - &admin age1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # replace with: age-keygen output from your admin machine - -creation_rules: - - path_regex: secrets/homelab\.yaml$ - key_groups: - - age: - - *homelab - - *admin \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a5a5a12 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "nixEnvSelector.suggestion": false +} \ No newline at end of file diff --git a/README.md b/README.md index 76cad4e..f8496c7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,18 @@ ![nix-flake](ss.png) -rewrite of my nixos flake with hopefully better structuring and modularity > [!WARNING] -> this flake is ment for personal use. code is not well documented and is not ment to be used by others. use at your own risk. \ No newline at end of file +> This flake is ment for personal use. The code is not well documented nor structured and is not ment to be used by others. **Use at your own risk.** + +## Hosts +- `thinkpad` - Thinkpad T480, i5 8350U, 16GB RAM, 256GB NVME +- `homelab` - i7 8700T, 32GB RAM, 512GB NVME, 1TB 2.5" SATA + +## Todo +- Automatic backups to external drives. +- Better documentation and code structure. +- Use NixOS modules system. + +## Credits +- [orangc's flake](https://git.orangc.net/c/dots) +- [vimjoyer's tutorials](https://www.youtube.com/@vimjoyer) +- [wallpaper source](https://github.com/er2de2/catppuccin_walls/blob/master/wallpapers_png/autumn_2.0.png) \ No newline at end of file diff --git a/flake.lock b/flake.lock index cc8baa0..5ab99ba 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1773146250, - "narHash": "sha256-azzOjRqTxAqByzRP87jUUsmfOQ85i7h/YkrgTX0jZgg=", + "lastModified": 1777734189, + "narHash": "sha256-kbIhdhDPaTP6gxAPkcRYeB+cqPFDpTM/bnw+m+26vkI=", "owner": "catppuccin", "repo": "nix", - "rev": "0fa0d06dd3cd09f37f76d19b389d7ff947dfd7e8", + "rev": "e68cf5deaf1a7afed2e548835dba2ae99f5a3ccb", "type": "github" }, "original": { @@ -18,6 +18,22 @@ "type": "github" } }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1747046372, + "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" @@ -62,11 +78,11 @@ ] }, "locked": { - "lastModified": 1773179137, - "narHash": "sha256-EdW2bwzlfme0vbMOcStnNmKlOAA05Bp6su2O8VLGT0k=", + "lastModified": 1777977606, + "narHash": "sha256-8ceIdvijN2tm9fIAUgnIZ8BM8TlsFx7pRYKRoxNsi1k=", "owner": "nix-community", "repo": "home-manager", - "rev": "3f98e2bbc661ec0aaf558d8a283d6955f05f1d09", + "rev": "7ef1c04d11f7ef69fd946b118c768c32de0b89a5", "type": "github" }, "original": { @@ -76,13 +92,33 @@ "type": "github" } }, + "mc": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": "nixpkgs_3", + "systems": "systems_2" + }, + "locked": { + "lastModified": 1777952170, + "narHash": "sha256-8dQ/DOUvQI8x5i6MZ309/xZLLVfV1CgWbD2+JiQ7Hd4=", + "owner": "Infinidoge", + "repo": "nix-minecraft", + "rev": "34a46e4de360c5004ee1866f5e3de78bf5e8b289", + "type": "github" + }, + "original": { + "owner": "Infinidoge", + "repo": "nix-minecraft", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1772773019, - "narHash": "sha256-E1bxHxNKfDoQUuvriG71+f+s/NT0qWkImXsYZNFFfCs=", + "lastModified": 1777268161, + "narHash": "sha256-bxrdOn8SCOv8tN4JbTF/TXq7kjo9ag4M+C8yzzIRYbE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "aca4d95fce4914b3892661bcb80b8087293536c6", + "rev": "1c3fe55ad329cbcb28471bb30f05c9827f724c76", "type": "github" }, "original": { @@ -109,11 +145,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1772963539, - "narHash": "sha256-9jVDGZnvCckTGdYT53d/EfznygLskyLQXYwJLKMPsZs=", + "lastModified": 1769461804, + "narHash": "sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI=", "owner": "nixos", "repo": "nixpkgs", - "rev": "9dcb002ca1690658be4a04645215baea8b95f31d", + "rev": "bfc1b8a4574108ceef22f02bafcf6611380c100d", "type": "github" }, "original": { @@ -125,16 +161,16 @@ }, "nixpkgs_4": { "locked": { - "lastModified": 1772736753, - "narHash": "sha256-au/m3+EuBLoSzWUCb64a/MZq6QUtOV8oC0D9tY2scPQ=", - "owner": "NixOS", + "lastModified": 1777578337, + "narHash": "sha256-Ad49moKWeXtKBJNy2ebiTQUEgdLyvGmTeykAQ9xM+Z4=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "917fec990948658ef1ccd07cef2a1ef060786846", + "rev": "15f4ee454b1dce334612fa6843b3e05cf546efab", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", + "owner": "nixos", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } @@ -144,26 +180,8 @@ "ctp": "ctp", "gl": "gl", "hm": "hm", - "nixpkgs": "nixpkgs_3", - "sops": "sops" - } - }, - "sops": { - "inputs": { + "mc": "mc", "nixpkgs": "nixpkgs_4" - }, - "locked": { - "lastModified": 1773096132, - "narHash": "sha256-M3zEnq9OElB7zqc+mjgPlByPm1O5t2fbUrH3t/Hm5Ag=", - "owner": "Mic92", - "repo": "sops-nix", - "rev": "d1ff3b1034d5bab5d7d8086a7803c5a5968cd784", - "type": "github" - }, - "original": { - "owner": "Mic92", - "repo": "sops-nix", - "type": "github" } }, "systems": { @@ -180,6 +198,21 @@ "repo": "default", "type": "github" } + }, + "systems_2": { + "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", diff --git a/flake.nix b/flake.nix index 692ca4d..3ccbd5c 100644 --- a/flake.nix +++ b/flake.nix @@ -6,19 +6,20 @@ url = "github:nix-community/home-manager/master"; inputs.nixpkgs.follows = "nixpkgs"; }; - - sops.url = "github:Mic92/sops-nix"; + gl.url = "github:nix-community/nixGL"; ctp.url = "github:catppuccin/nix"; + + mc.url = "github:Infinidoge/nix-minecraft"; }; - outputs = inputs: let + outputs = inputs: let pkgs = import inputs.nixpkgs { system = "x86_64-linux"; overlays = [ inputs.gl.overlay ]; config = { allowUnfree = true; - permittedInsecurePackages = [ "ventoy-qt5-1.1.10" ]; + permittedInsecurePackages = [ "ventoy-qt5-1.1.12" ]; }; }; args = { @@ -31,17 +32,15 @@ modules = [ ./hosts/${host}/config.nix inputs.ctp.nixosModules.catppuccin - inputs.sops.nixosModules.sops ]; }; - + nixosConfigWithHome = host: inputs.nixpkgs.lib.nixosSystem { inherit pkgs; specialArgs = args // { hostname = host; }; modules = [ ./hosts/${host}/config.nix inputs.ctp.nixosModules.catppuccin - inputs.sops.nixosModules.sops inputs.hm.nixosModules.home-manager { home-manager = { @@ -53,7 +52,7 @@ } ]; }; - + homeConfig = host: inputs.hm.lib.homeManagerConfiguration { extraSpecialArgs = args // { hostname = host; }; inherit pkgs; diff --git a/hosts/bootstrap/config.nix b/hosts/bootstrap/config.nix index 7eeca52..0e549ca 100644 --- a/hosts/bootstrap/config.nix +++ b/hosts/bootstrap/config.nix @@ -21,7 +21,7 @@ tailscale.enable = true; openssh = { enable = true; - settings.PermitRootLogin = "yes"; + settings.PermitRootLogin = "prohibit-password"; }; }; users.users."${username}" = { diff --git a/lib/options.nix b/lib/options.nix index b865080..9cc0282 100644 --- a/lib/options.nix +++ b/lib/options.nix @@ -1,4 +1,12 @@ -{ +let + d = dest: { inherit dest; auth = false; }; + da = dest: { inherit dest; auth = true; }; + + ext4 = path: { inherit path; type = "ext4"; }; + btrfs = path: { inherit path; type = "btrfs"; }; + + selfSigned = service: { inherit service; originRequest.noTLSVerify = true; }; +in { flake-path = "~/Projects/nix-flake"; # set this to the cloned repo path username = "satr14"; @@ -15,20 +23,78 @@ homelab = rec { domain = "satr14.my.id"; # root domain for dns, ssl certs, reverse proxy, etc. - cf-tunnel-id = "26318288-cdd7-4e58-904b-c45f10d3e40a"; + ssh-keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIESvQFXoUBafatqnxTd6qk3WEOcfwb3AIWVTstR3lHzX forgejo" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJtdH1YqRH9xhuHMivezLvj/hpH77yfH3HUCaRboB/hb forgejo-deploy-runner" + ]; disks = { - gallery = "/dev/disk/by-uuid/834f51c1-90ee-4601-ba76-ef0419198d67"; # disk for photo gallery - data = "/dev/disk/by-uuid/a5752dd6-092d-484c-969c-2fdc7cb4a5f0"; # disk for app data - host = "/dev/disk/by-uuid/968f14a4-631e-4325-8cd1-f9aec0da9e4d"; # disk for media collection (named host for backwards compatibility) + # gallery = ext4 "/dev/disk/by-uuid/834f51c1-90ee-4601-ba76-ef0419198d67"; # disk for photo gallery + # data = ext4 "/dev/disk/by-uuid/a5752dd6-092d-484c-969c-2fdc7cb4a5f0"; # disk for app data + # host = ext4 "/dev/disk/by-uuid/968f14a4-631e-4325-8cd1-f9aec0da9e4d"; # disk for media collection (named host for backwards compatibility) + # ^^ virtual disks + + # achive = ext4 "/dev/disk/by-uuid/"; # long term archival + data = ext4 "/dev/disk/by-uuid/aa453135-4b7a-4b12-8efc-f3dda093d2b7"; # app data + share = btrfs "/dev/disk/by-uuid/f1ee1d17-e852-4e02-ae86-eaf6116a2aeb"; # file server + }; + dash = [ + [ "PocketID" "authentik" "https://auth.${domain}" "http://localhost:1411/" ] + [ "Forgejo" "forgejo" "https://git.${domain}" "http://localhost:5080/" ] + [ "Copyparty" "files" "https://cdn.${domain}" "http://localhost:3923/" ] + [ "CryptPad" "cryptpad" "https://docs.${domain}" "http://localhost:7090/" ] + [ "CodeServer" "coder" "https://code.proxy.${domain}" "http://localhost:8443/" ] + [ "AdGuardHome" "adguard" "https://dns.proxy.${domain}" "http://localhost:8088/" ] + [ "Traefik" "traefikproxy" "https://dynamic.proxy.${domain}/dashboard/" "" ] + [ "Immich" "immich" "https://gallery.proxy.${domain}" "http://localhost:2283/" ] + [ "Jellyfin" "jellyfin" "https://media.proxy.${domain}" "http://localhost:8096/" ] + [ "VaultWarden" "vaultwarden" "https://pass.proxy.${domain}" "http://localhost:8060/" ] + [ "Ollama" "ollama" "https://ai.proxy.${domain}" "http://localhost:8080/" ] + [ "Ntfy" "ntfy" "https://notify.proxy.${domain}" "http://localhost:8067/" ] + [ "SearXNG" "searxng" "https://search.proxy.${domain}" "http://localhost:8091/" ] + [ "Dockge" "docker" "https://containers.proxy.${domain}" "http://localhost:5001/" ] + ]; + routes = { + "mc0.${domain}" = "tcp://localhost:25565"; + + "docs-sandbox.${domain}" = "http://localhost:7090"; + "docs.${domain}" = "http://localhost:7090"; + + "cdn.${domain}" = selfSigned "https://localhost:3923"; + + "git.${domain}" = "http://localhost:5080"; + "auth.${domain}" = "http://localhost:1411"; + "dash.${domain}" = "http://localhost:5070"; + "media.${domain}" = "http://localhost:8096"; + "gallery.${domain}" = "http://localhost:2284"; + }; + proxy = { + base = "proxy.${domain}"; + hosts = { + "containers" = da "http://localhost:5001"; + "code" = da "http://localhost:8443"; + "dns" = da "http://localhost:8088"; + + "gallery" = d "http://localhost:2283"; + "dynamic" = d "http://localhost:8082"; + "search" = d "http://localhost:8091"; + "notify" = d "http://localhost:8067"; + "media" = d "http://localhost:8096"; + "pass" = d "http://localhost:8060"; + "auth" = d "http://localhost:1411"; + "git" = d "http://localhost:5080"; + "cdn" = d "http://localhost:3923"; + "ai" = d "http://localhost:8080"; + "@" = d "http://localhost:5070"; + }; + redirects = { + "www" = "https://${proxy.base}"; + "dash" = "https://${proxy.base}"; + "immich" = "https://gallery.${proxy.base}"; + "2fa" = "https://2fa.${domain}"; + }; }; records = [ - [ "server.dns.${domain}" "10.3.14.69" ] - [ "router.dns.${domain}" "10.3.14.1" ] - [ "home.dns.${domain}" "10.3.14.235" ] - [ "workspace.dns.${domain}" "10.3.14.57" ] - [ "old-main.dns.${domain}" "10.3.14.42" ] # old main machine for connecting while migrating - - [ "main.dns.${domain}" "10.3.14.215" ] # this machine + [ "main.dns.${domain}" "100.113.147.93" ] # this machine [ "proxy.${domain}" "main.dns.${domain}" ] [ "*.proxy.${domain}" "proxy.${domain}" ] @@ -62,7 +128,9 @@ }; git = { # setup your git author - user = "Satria"; + username = "satr14"; # forgejo username + server = "https://git.satr14.my.id"; # forgejo server url + user = "satr14"; email = "admin@satr14.my.id"; }; } diff --git a/modules/hardware/homelab.nix b/modules/hardware/homelab.nix index 08bfec3..906b24b 100644 --- a/modules/hardware/homelab.nix +++ b/modules/hardware/homelab.nix @@ -1,14 +1,13 @@ { ... }: { imports = [ + # ./misc/cpu-hotplug.nix + # ./misc/serial.nix + # ./misc/qemu-virtio.nix + # ^^ only used if vm + ./core/firmware.nix ./core/igpu.nix ./misc/disks.nix - ./misc/serial.nix ]; - boot.initrd.availableKernelModules = [ "virtio_net" "virtio_pci" "virtio_mmio" "virtio_blk" "virtio_scsi" "virtio_console" ]; - services = { - qemuGuest.enable = true; - spice-vdagentd.enable = true; - }; } diff --git a/modules/hardware/misc/battery-power.nix b/modules/hardware/misc/battery-power.nix index bd8ee20..8c529e1 100644 --- a/modules/hardware/misc/battery-power.nix +++ b/modules/hardware/misc/battery-power.nix @@ -1,4 +1,4 @@ -{ pkgs, resume-dev, ... }: { +{ pkgs, username, resume-dev, ... }: { powerManagement.powertop.enable = true; services = { @@ -10,6 +10,20 @@ echo 85 > /sys/class/power_supply/BAT*/charge_control_end_threshold || true ''}" ''; + cron = { + enable = true; + systemCronJobs = [ + "* * * * * ${username} bash -x ${pkgs.writeShellScript "low-battery-notifier" '' + BAT_PCT=`${pkgs.acpi}/bin/acpi -b | ${pkgs.gnugrep}/bin/grep -P -o '[0-9]+(?=%)'` + BAT_STA=`${pkgs.acpi}/bin/acpi -b | ${pkgs.gnugrep}/bin/grep -P -o '\w+(?=,)'` + echo "`date` battery status:$BAT_STA percentage:$BAT_PCT" + export DISPLAY=:0 + export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus + test $BAT_PCT -le 30 && test $BAT_PCT -gt 15 && test $BAT_STA = "Discharging" && ${pkgs.libnotify}/bin/notify-send "Low Battery" "Battery remaining: $BAT_PCT%." + test $BAT_PCT -le 15 && test $BAT_STA = "Discharging" && ${pkgs.libnotify}/bin/notify-send -u critical "Low Battery" "Shutdown at 10%." + ''} > /tmp/cron.batt.log 2>&1" + ]; + }; upower = { enable = true; percentageCritical = 15; diff --git a/modules/hardware/misc/cpu-freq.nix b/modules/hardware/misc/cpu-freq.nix index 2b6476a..ad87022 100644 --- a/modules/hardware/misc/cpu-freq.nix +++ b/modules/hardware/misc/cpu-freq.nix @@ -51,7 +51,7 @@ enable = true; # wait for fix: https://github.com/AdnanHodzic/auto-cpufreq/issues/906 settings = { charger = { - governor = "performance"; + governor = "powersave"; # "performance"; energy_performance_preference = "performance"; turbo = "always"; platform_profile = "performance"; diff --git a/modules/hardware/misc/cpu-hotplug.nix b/modules/hardware/misc/cpu-hotplug.nix new file mode 100644 index 0000000..64cd3f9 --- /dev/null +++ b/modules/hardware/misc/cpu-hotplug.nix @@ -0,0 +1,5 @@ +{ ... }: { + services.udev.extraRules = '' + SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online}="1" + ''; +} \ No newline at end of file diff --git a/modules/hardware/misc/disks.nix b/modules/hardware/misc/disks.nix index ea0948a..b874ff7 100644 --- a/modules/hardware/misc/disks.nix +++ b/modules/hardware/misc/disks.nix @@ -1,13 +1,15 @@ { lib, homelab, ... }: let globalOpts = { - fsType = "ext4"; autoFormat = true; autoResize = true; }; in { fileSystems = { "/".autoResize = true; - } // lib.mapAttrs' (name: device: - lib.nameValuePair "/mnt/${name}" (globalOpts // { inherit device; }) + } // lib.mapAttrs' (name: dev: + lib.nameValuePair "/mnt/${name}" (globalOpts // { + device = dev.path; + fsType = dev.type; + }) ) homelab.disks; } \ No newline at end of file diff --git a/modules/hardware/misc/qemu-virtio.nix b/modules/hardware/misc/qemu-virtio.nix new file mode 100644 index 0000000..fef199b --- /dev/null +++ b/modules/hardware/misc/qemu-virtio.nix @@ -0,0 +1,14 @@ +{ ... }: { + boot.initrd.availableKernelModules = [ + "virtio_net" + "virtio_pci" + "virtio_mmio" + "virtio_blk" + "virtio_scsi" + "virtio_console" + ]; + services = { + qemuGuest.enable = true; + spice-vdagentd.enable = true; + }; +} \ No newline at end of file diff --git a/modules/hardware/thinkpad.nix b/modules/hardware/thinkpad.nix index c52765d..f7e193a 100644 --- a/modules/hardware/thinkpad.nix +++ b/modules/hardware/thinkpad.nix @@ -12,7 +12,7 @@ ]; boot = { - kernelPackages = pkgs.linuxPackages; + kernelPackages = pkgs.linuxPackages_zen; kernel.sysctl."vm.laptop_mode" = 5; initrd.availableKernelModules = [ "thinkpad_acpi" ]; kernelParams = [ diff --git a/modules/home/core/apps.nix b/modules/home/core/apps.nix index 13146b3..14d3701 100644 --- a/modules/home/core/apps.nix +++ b/modules/home/core/apps.nix @@ -1,44 +1,69 @@ { pkgs, ... }: { nixpkgs.config.allowUnfree = true; + xdg = { + autostart.enable = true; + mimeApps = { + enable = true; + defaultApplications = { + "text/plain" = "nvim.desktop"; + "text/html" = "brave-browser.desktop"; + "application/pdf" = "brave-browser.desktop"; + "x-scheme-handler/http" = "brave-browser.desktop"; + "x-scheme-handler/https" = "brave-browser.desktop"; + "x-terminal-emulator" = "kitty.desktop"; + "inode/directory" = "pcmanfm-qt.desktop"; + "audio/mpeg" = "vlc.desktop"; + "audio/mp3" = "vlc.desktop"; + "audio/wav" = "vlc.desktop"; + "audio/flac" = "vlc.desktop"; + "video/mp4" = "vlc.desktop"; + "video/x-matroska" = "vlc.desktop"; + "video/webm" = "vlc.desktop"; + "video/x-msvideo" = "vlc.desktop"; + }; + }; + }; + home.packages = with pkgs; [ - zed-editor - # kicad-small - # arduino-ide + zed-editor + # kicad-small + # arduino-ide - slack - discord - protonmail-desktop - - vlc - brave - libreoffice - appimage-run - # keepassxc + slack + discord + # protonmail-desktop # https://www.reddit.com/r/NixOS/comments/1rm9alf/protonmail_in_nixos/ + + vlc + brave + flameshot + libreoffice + appimage-run + # keepassxc - virt-manager - # winboat - - remmina - moonlight-qt - # rustdesk - - - # inkscape - # davinci-resolve - # kdePackages.kdenlive - (wrapOBS { - plugins = with obs-studio-plugins; [ - wlrobs - obs-backgroundremoval - obs-pipewire-audio-capture - ]; - }) + virt-manager + # winboat + + remmina + moonlight-qt + # rustdesk + + + # inkscape + # davinci-resolve + # kdePackages.kdenlive + (wrapOBS { + plugins = with obs-studio-plugins; [ + wlrobs + obs-backgroundremoval + obs-pipewire-audio-capture + ]; + }) - ferium - portablemc - prismlauncher - steamguard-cli - # modrinth-app - ]; + ferium + packwiz + portablemc + steamguard-cli + # modrinth-app + ]; } diff --git a/modules/home/core/cli.nix b/modules/home/core/cli.nix index 4d5cd63..4f2dbf6 100644 --- a/modules/home/core/cli.nix +++ b/modules/home/core/cli.nix @@ -44,13 +44,26 @@ enable = true; defaultEditor = true; vimAlias = true; + withRuby = false; + withPython3 = false; initLua = '' vim.opt.clipboard = "unnamedplus" vim.opt.termguicolors = true + vim.g.clipboard = { + name = "OSC 52", + copy = { + ["+"] = require("vim.ui.clipboard.osc52").copy("+"), + ["*"] = require("vim.ui.clipboard.osc52").copy("*"), + }, + paste = { + ["+"] = require("vim.ui.clipboard.osc52").paste("+"), + ["*"] = require("vim.ui.clipboard.osc52").paste("*"), + }, + } require("nvim-tree").setup() vim.api.nvim_create_autocmd("VimEnter", { callback = function() - -- vim.cmd("NvimTreeOpen") + vim.cmd("set nu") vim.cmd.wincmd 'p' end, }) @@ -63,7 +76,6 @@ telescope-file-browser-nvim nvim-tree-lua nvim-cmp - barbar-nvim indent-blankline-nvim markdown-preview-nvim ]; @@ -80,6 +92,7 @@ }; git = { enable = true; + signing.format = null; settings = { pull.rebase = "true"; credential.helper = "cache --timeout=3600"; diff --git a/modules/home/core/zed.nix b/modules/home/core/code.nix similarity index 70% rename from modules/home/core/zed.nix rename to modules/home/core/code.nix index 8c6ff8e..21268ff 100644 --- a/modules/home/core/zed.nix +++ b/modules/home/core/code.nix @@ -2,10 +2,18 @@ programs.zed-editor = { enable = true; package = pkgs.zed-editor; - extensions = [ "nix" ]; + extensions = [ + "html" "html-snippets" + "svelte" "svelte-snippets" + "wakatime" "discord-presence" + "catppuccin" "catppuccin-icons" + "git-firefly" + "nix" + ]; userSettings = { + diff_view_style = "unified"; + cli_default_open_behavior = "existing_window"; format_on_save = "off"; - features.edit_prediction_provider = "copilot"; vim_mode = true; git.inline_blame.enabled = true; gutter.line_numbers = true; @@ -19,6 +27,27 @@ file_types.tailwindcss = [ "*.css" ]; auto_install_extensions.catppuccin-icons = true; icon_theme = "Catppuccin Mocha"; + git_panel.tree_view = true; + diagnostics = { + button = true; + include_warnings = true; + inline = { + enabled = true; + update_debounce_ms = 150; + padding = 4; + min_column = 0; + max_severity = null; + }; + }; + agent = { + tool_permissions.default = "allow"; + default_model = { + provider = "copilot_chat"; + model = "claude-sonnet-4.6"; + effort = "high"; + enable_thinking = false; + }; + }; theme = { mode = "dark"; light = "Catppuccin Mocha (sapphire)"; diff --git a/modules/home/core/zsh.nix b/modules/home/core/shell.nix similarity index 85% rename from modules/home/core/zsh.nix rename to modules/home/core/shell.nix index a1c27ae..7c69e47 100644 --- a/modules/home/core/zsh.nix +++ b/modules/home/core/shell.nix @@ -1,4 +1,4 @@ -{ hostname, flake-path, zsh-theme, ... }: { +{ git, hostname, flake-path, zsh-theme, ... }: { programs = { pay-respects = { enable = true; @@ -32,14 +32,14 @@ ''; shellAliases = { "cd-gvfs" = "cd /run/user/$(id -u)/gvfs"; - "wlp-set" = "swww img --transition-type=grow --transition-duration=1"; + "wlp-set" = "awww img --transition-type=grow --transition-duration=1"; "ssh" = "TERM=xterm-256color ssh"; "cd" = "z"; "sys" = "sudo systemctl --runtime"; - "sys-log" = "journalctl -f -b -u"; + "sys-log" = "journalctl -o cat -f -b -u"; "user" = "systemctl --user --runtime"; - "user-log" = "journalctl -f -b --user-unit"; + "user-log" = "journalctl -o cat -f -b --user-unit"; "ts" = "sudo tailscale"; "tsip" = "tailscale ip -4"; @@ -64,9 +64,10 @@ "wm-disp" = "wm-ctl dispatch dpms"; "gh-author-setup" = "git config user.name $(gh api -H \"Accept: application/vnd.github+json\" -H \"X-GitHub-Api-Version: 2022-11-28\" /user | jq -r .login) && git config user.email $(gh api -H \"Accept: application/vnd.github+json\" -H \"X-GitHub-Api-Version: 2022-11-28\" /user/emails | jq -r \".[1].email\")"; + "fg-create-repo" = "git remote add origin ${git.server}/${git.username}/$(basename $PWDw).git && git push"; "convert-pdf" = "libreoffice --headless --convert-to pdf"; - "mcl" = "portablemc start -l $(cat .minecraft/portablemc-launch-params.json | jq -r .email) $(cat .minecraft/portablemc-launch-params.json | jq -r .version)"; + "mcl" = "portablemc start -l $(cat ~/.minecraft/portablemc-launch-params.json | jq -r .email) $(cat ~/.minecraft/portablemc-launch-params.json | jq -r .version)"; "mc" = "ferium upgrade; mcl"; }; initContent = '' diff --git a/modules/home/core/xdg.nix b/modules/home/core/xdg.nix deleted file mode 100644 index 141e9c0..0000000 --- a/modules/home/core/xdg.nix +++ /dev/null @@ -1,26 +0,0 @@ -{ ... }: { - xdg = { - autostart.enable = true; - mimeApps = { - enable = true; - defaultApplications = { - "text/plain" = "nvim.desktop"; - "text/html" = "brave-browser.desktop"; - "application/pdf" = "brave-browser.desktop"; - "x-scheme-handler/http" = "brave-browser.desktop"; - "x-scheme-handler/https" = "brave-browser.desktop"; - "x-scheme-handler/terminal" = "kitty.desktop"; - "x-terminal-emulator" = "kitty.desktop"; - "inode/directory" = "pcmanfm-qt.desktop"; - "audio/mpeg" = "vlc.desktop"; - "audio/mp3" = "vlc.desktop"; - "audio/wav" = "vlc.desktop"; - "audio/flac" = "vlc.desktop"; - "video/mp4" = "vlc.desktop"; - "video/x-matroska" = "vlc.desktop"; - "video/webm" = "vlc.desktop"; - "video/x-msvideo" = "vlc.desktop"; - }; - }; - }; -} \ No newline at end of file diff --git a/modules/home/default.nix b/modules/home/default.nix index 23334fd..00bbbb6 100644 --- a/modules/home/default.nix +++ b/modules/home/default.nix @@ -1,8 +1,16 @@ -{ username, ... }: { +{ username, ctp-opt, ... }: { imports = [ + ./core/shell.nix ./core/cli.nix - ./core/zsh.nix ]; + + catppuccin = { + enable = true; + hyprlock.useDefaultConfig = false; + + flavor = ctp-opt.flavor; + accent = ctp-opt.accent; + }; home = { stateVersion = "24.11"; diff --git a/modules/home/desktop.nix b/modules/home/desktop.nix index 3c71de0..9e34895 100644 --- a/modules/home/desktop.nix +++ b/modules/home/desktop.nix @@ -1,23 +1,23 @@ { pkgs, ... }: { imports = [ - ./rice/hyprland.nix - ./rice/hyprlock.nix - ./rice/waybar.nix - ./rice/rofi.nix - ./rice/wlogout.nix - ./rice/hypridle.nix - ./rice/dunst.nix + ./rice/compositor.nix + ./rice/lockscreen.nix + ./rice/keybinds.nix + ./rice/logout.nix + ./rice/notifs.nix ./rice/cursor.nix ./rice/theme.nix - ./rice/keybinds.nix - ./misc/kde-connect.nix + ./rice/menu.nix + ./rice/idle.nix + ./rice/bar.nix + ./misc/handlers.nix + ./misc/phone.nix ./core/apps.nix - ./core/zed.nix - ./core/xdg.nix + ./core/code.nix ]; services = { - swww.enable = true; + awww.enable = true; hyprpolkitagent.enable = true; }; diff --git a/modules/home/misc/handlers.nix b/modules/home/misc/handlers.nix new file mode 100644 index 0000000..dc7c0e8 --- /dev/null +++ b/modules/home/misc/handlers.nix @@ -0,0 +1,18 @@ +{ pkgs, ... }: +let + ferium-installer-script = pkgs.writeShellScript "ferium-installer" '' + mod=$(echo "$1" | awk -F'/' '{print $NF}') + ${pkgs.kitty}/bin/kitty sh -c "ferium add $mod; read" + ''; +in +{ + xdg.desktopEntries."ferium-installer" = { + name = "Intercept Modrinth Links to Ferium"; + exec = "${ferium-installer-script} %u"; + mimeType = [ "x-scheme-handler/modrinth" ]; + }; + + xdg.mimeApps.defaultApplications = { + "x-scheme-handler/modrinth" = "ferium-installer.desktop"; + }; +} \ No newline at end of file diff --git a/modules/home/misc/kde-connect.nix b/modules/home/misc/phone.nix similarity index 100% rename from modules/home/misc/kde-connect.nix rename to modules/home/misc/phone.nix diff --git a/modules/home/rice/waybar.nix b/modules/home/rice/bar.nix similarity index 96% rename from modules/home/rice/waybar.nix rename to modules/home/rice/bar.nix index 461bdac..27a04dd 100644 --- a/modules/home/rice/waybar.nix +++ b/modules/home/rice/bar.nix @@ -45,8 +45,8 @@ interval = 1; format = " {usage:2}% {avg_frequency}GHz"; on-click = "auto-cpufreq-gtk"; - on-click-right = "pkexec tlp power-saver && notify-send ${hostname} \"TLP set to: $(tlp-stat -s | grep 'Power profile' | awk -F '=' '{print $2}' | xargs)\""; - on-click-middle = "pkexec tlp start && notify-send ${hostname} \"TLP set to: $(tlp-stat -s | grep 'Power profile' | awk -F '=' '{print $2}' | xargs)\""; + on-click-right = "pkexec auto-cpufreq --force powersave && notify-send ${hostname} \"CPU Governor Powersave Overide\""; + on-click-middle = "pkexec auto-cpufreq --force reset && notify-send ${hostname} \"CPU Governor Overide Reset\""; }; "memory" = { states = { diff --git a/modules/home/rice/hyprland.nix b/modules/home/rice/compositor.nix similarity index 95% rename from modules/home/rice/hyprland.nix rename to modules/home/rice/compositor.nix index 2db9add..00f19e0 100644 --- a/modules/home/rice/hyprland.nix +++ b/modules/home/rice/compositor.nix @@ -30,7 +30,7 @@ #"dunst &" #"hypridle &" - #"swww-daemon &" + #"awww-daemon &" "uwsm app -s s -- waybar &" "uwsm app -s b -- sunshine &" @@ -51,6 +51,7 @@ "GTK_APPLICATION_PREFER_DARK_THEME,1" "GTK_THEME,Adwaita:dark" "QT_QPA_PLATFORMTHEME,kvantum" + "QT_STYLE_OVERRIDE,kvantum" ]; general = { @@ -140,7 +141,7 @@ layerrule = [ "no_anim on, match:namespace selection" # hyprshot overlay "no_anim on, match:namespace hyprpicker" - "animation fade, match:namespace swww-daemon" + "animation fade, match:namespace awww-daemon" "animation fade, match:namespace logout_dialog" "animation fade, match:namespace hyprshutdown" "above_lock 2, match:namespace notifications" @@ -155,7 +156,8 @@ "stay_focused on, suppress_event fullscreen maximize, dim_around on, float on, match:title ^(Hyprland Polkit Agent|Unlock Login Keyring|KeePassXC -.*)$" "float on, match:title ^(Open|Print|Save|Rename|Move|Copy|Confirm).*" "float on, match:title ^(Preferences|Settings|Options|About|Passbolt).*" - "float on, match:title ^(MainPicker|Volume Control|File Operation Progress|Network Connections|Choose an Application| )$" + "float on, match:title ^(MainPicker|Volume Control|File Operation Progress|Network Connections|Choose an Application)$" + "float on, match:title ^(Please wait)$" ]; }; }; diff --git a/modules/home/rice/hypridle.nix b/modules/home/rice/idle.nix similarity index 91% rename from modules/home/rice/hypridle.nix rename to modules/home/rice/idle.nix index 18d162d..80434de 100644 --- a/modules/home/rice/hypridle.nix +++ b/modules/home/rice/idle.nix @@ -6,7 +6,7 @@ lock_cmd = "hyprlock"; unlock_cmd = "pkill -USR1 hyprlock"; before_sleep_cmd = "hyprctl dispatch dpms off && hyprlock"; - after_sleep_cmd = "hyprctl dispatch dpms on && pkill -USR2 hyprlock"; + after_sleep_cmd = "hyprctl dispatch dpms on"; }; listener = [ { diff --git a/modules/home/rice/keybinds.nix b/modules/home/rice/keybinds.nix index d84ed78..c0d4634 100644 --- a/modules/home/rice/keybinds.nix +++ b/modules/home/rice/keybinds.nix @@ -95,10 +95,10 @@ "SUPER, N, exec, uwsm app -- rofi-network-manager" "SUPER, J, exec, notify-send -u critical ${hostname} 'Caffein Mode' && notify-send '(SUPER+X to reset)' && systemctl --user stop hypridle" - "SUPER, K, exec, notify-send -u critical ${hostname} 'Focus Mode' && notify-send '(SUPER+X to reset)' && systemctl --user stop swww && pkill -SIGUSR1 waybar && hyprctl --batch 'keyword decoration:inactive_opacity 1.0; keyword decoration:blur:enabled 0; keyword general:gaps_in 0; keyword general:gaps_out 0; keyword general:border_size 1; keyword decoration:rounding 0; keyword decoration:shadow:enabled false'" + "SUPER, K, exec, notify-send -u critical ${hostname} 'Focus Mode' && notify-send '(SUPER+X to reset)' && systemctl --user stop awww && pkill -SIGUSR1 waybar && hyprctl --batch 'keyword decoration:inactive_opacity 1.0; keyword decoration:blur:enabled 0; keyword general:gaps_in 0; keyword general:gaps_out 0; keyword general:border_size 1; keyword decoration:rounding 0; keyword decoration:shadow:enabled false'" "SUPER, B, submap, disabled-all-keybinds" "SUPER, H, exec, notify-send ${hostname} 'Animations Off' && hyprctl keyword animations:enabled 0" - "SUPER, X, exec, dunstctl close-all && hyprctl reload && hyprctl dispatch submap reset && pkill -SIGUSR2 waybar && systemctl --user restart swww hypridle fusuma" + "SUPER, X, exec, dunstctl close-all && hyprctl reload && hyprctl dispatch submap reset && pkill -SIGUSR2 waybar && systemctl --user restart awww hypridle fusuma" "SUPER, Z, exec, dunstctl close-all" "SUPER SHIFT, S, exec, hyprshot -zm region -o ~/Pictures/Screenshots; killall -9 hyprpicker hyprshot" @@ -106,9 +106,7 @@ ", PRINT, exec, hyprshot -zm region -o ~/Pictures/Screenshots; killall -9 hyprpicker hyprshot" "SUPER, R, exec, rofi -show drun -show-icons -display-drun '' -run-command \"uwsm app -- {cmd}\"" - "SUPER, RETURN, exec, rofi -show window -show-icons -drun-display '' -window-format '{c} {t}'" - "SUPER CTRL, RETURN, exec, rofi rofi -dmenu -p 'run nixpkgs' -lines 0 < /dev/null | xargs -r -I {} kitty -- nix run 'nixpkgs#{}'" - "SUPER ALT, RETURN, exec, rofi rofi -dmenu -p 'shell nixpkgs' -lines 0 < /dev/null | xargs -r -I {} kitty -- nde`ix shell 'nixpkgs#{}'" + "SUPER, RETURN, exec, ls ~/Projects | rofi -dmenu -p \"Open Project\" | xargs -I {} sh -c 'mkdir -p ~/Projects/\"{}\" && zeditor ~/Projects/\"{}\"'" "SUPER, V, exec, rofi -modi clipboard:cliphist-rofi-img -show clipboard -show-icons" # "SUPER, B, exec, rofi -show calc -modi calc -no-show-match -no-sort" @@ -126,8 +124,9 @@ "SUPER, W, fullscreen, 1" "SUPER, S, fullscreen, 0" "SUPER, F, togglefloating," - "SUPER, G, togglesplit," + "SUPER, G, layoutmsg, togglesplit" "SUPER, L, exec, loginctl lock-session" + "SUPER SHIFT, L, exec, hyprctl dispatch dpms off && loginctl lock-session && sleep 1 && hyprctl dispatch dpms on" "SUPER, down, togglespecialworkspace, hidden" "SUPER SHIFT, down, movetoworkspace, special:hidden" diff --git a/modules/home/rice/hyprlock.nix b/modules/home/rice/lockscreen.nix similarity index 100% rename from modules/home/rice/hyprlock.nix rename to modules/home/rice/lockscreen.nix diff --git a/modules/home/rice/wlogout.nix b/modules/home/rice/logout.nix similarity index 100% rename from modules/home/rice/wlogout.nix rename to modules/home/rice/logout.nix diff --git a/modules/home/rice/rofi.nix b/modules/home/rice/menu.nix similarity index 100% rename from modules/home/rice/rofi.nix rename to modules/home/rice/menu.nix diff --git a/modules/home/rice/dunst.nix b/modules/home/rice/notifs.nix similarity index 100% rename from modules/home/rice/dunst.nix rename to modules/home/rice/notifs.nix diff --git a/modules/home/rice/theme.nix b/modules/home/rice/theme.nix index 0b994c5..7946bf5 100644 --- a/modules/home/rice/theme.nix +++ b/modules/home/rice/theme.nix @@ -1,23 +1,16 @@ { lib, pkgs, ctp-opt, rice, ... }: { - catppuccin = { - enable = true; - hyprlock.useDefaultConfig = false; - - flavor = ctp-opt.flavor; - accent = ctp-opt.accent; - }; - dconf = { enable = true; settings."org/gnome/desktop/interface" = { color-scheme = "prefer-dark"; - gtk-theme = "Adwaita-dark"; + gtk-theme = lib.mkForce "Adwaita-dark"; }; }; gtk = { enable = true; gtk3.extraConfig.gtk-application-prefer-dark-theme = 1; + gtk4.theme = null; iconTheme = { name = "Papirus-Dark"; package = lib.mkForce pkgs.papirus-icon-theme; @@ -30,6 +23,11 @@ qt = { enable = true; + kvantum = { + enable = true; + themes = with pkgs; [ catppuccin-kvantum ]; + settings.General.theme = "catppuccin-${ctp-opt.flavor}-${ctp-opt.accent}"; + }; platformTheme.name = "kvantum"; style = { name = "kvantum"; diff --git a/modules/scans/homelab.nix b/modules/scans/homelab.nix index ae9dcbc..97b2ba6 100644 --- a/modules/scans/homelab.nix +++ b/modules/scans/homelab.nix @@ -5,26 +5,35 @@ { imports = - [ (modulesPath + "/profiles/qemu-guest.nix") + [ (modulesPath + "/installer/scan/not-detected.nix") ]; - boot.initrd.availableKernelModules = [ "uhci_hcd" "ehci_pci" "ahci" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ]; + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "uas" "usb_storage" "sd_mod" ]; boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-intel" ]; boot.extraModulePackages = [ ]; fileSystems."/" = - { device = "/dev/disk/by-uuid/e33ab472-e518-4b4d-89d1-d75cfecb9f06"; + { device = "/dev/disk/by-uuid/e5a7d45d-b9e9-43e7-ba5f-f4e67821bd0b"; fsType = "ext4"; }; fileSystems."/boot" = - { device = "/dev/disk/by-uuid/880C-9F0A"; + { device = "/dev/disk/by-uuid/EC01-36B5"; fsType = "vfat"; - options = [ "fmask=0077" "dmask=0077" ]; + 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.enp2s0.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp3s0.useDHCP = lib.mkDefault true; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; -} \ No newline at end of file + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} \ No newline at end of file diff --git a/modules/system/homelab/ai.nix b/modules/system/homelab/ai.nix index ba83a32..34dde0b 100644 --- a/modules/system/homelab/ai.nix +++ b/modules/system/homelab/ai.nix @@ -5,15 +5,16 @@ host = "127.0.0.1"; port = 11434; user = "ollama"; - home = "/mnt/data/ollama"; + home = "/mnt/data/apps/ollama"; loadModels = [ "gemma3n:e4b" # "gemma3n:e2b" - # "codellama:7b" "starcoder:3b" + "qwen3-coder-next:cloud" # "codellama:7b" "starcoder:3b" ]; }; open-webui = { enable = true; port = 8080; + environmentFile = "/mnt/data/apps/ollama/.env"; environment = { OLLAMA_BASE_URL = "http://localhost:11434"; # WEBUI_AUTH = "False"; diff --git a/modules/system/homelab/auth.nix b/modules/system/homelab/auth.nix index 62e4f39..a93350b 100644 --- a/modules/system/homelab/auth.nix +++ b/modules/system/homelab/auth.nix @@ -1,8 +1,8 @@ -{ config, homelab, ... }: { +{ homelab, ... }: { services.pocket-id = { enable = true; - credentials.ENCRYPTION_KEY = config.sops.secrets.pocketid_encryption_key.path; - dataDir = "/mnt/data/pocketid/data"; + credentials.ENCRYPTION_KEY = "/mnt/data/apps/pocketid/encryption-key"; + dataDir = "/mnt/data/apps/pocketid/data"; settings = { PORT = "1411"; HOST = "127.0.0.1"; diff --git a/modules/system/homelab/cdn.nix b/modules/system/homelab/cdn.nix new file mode 100644 index 0000000..a2bd042 --- /dev/null +++ b/modules/system/homelab/cdn.nix @@ -0,0 +1,14 @@ +{ pkgs, ... }: { + environment.systemPackages = with pkgs; [ copyparty-most ]; + + systemd.services.copyparty = { + description = "File Sharing Service"; + enable = true; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${pkgs.copyparty-most}/bin/copyparty -c /mnt/share/cfg/files.conf"; + Restart = "on-failure"; + }; + }; +} diff --git a/modules/system/homelab/code.nix b/modules/system/homelab/code.nix new file mode 100644 index 0000000..3d79fc7 --- /dev/null +++ b/modules/system/homelab/code.nix @@ -0,0 +1,12 @@ +{ username, ... }: { + services.code-server = { + enable = true; + host = "127.0.0.1"; + port = 8443; + user = username; + auth = "none"; + disableTelemetry = true; + extensionsDir = "/mnt/data/apps/code-server/extensions"; + userDataDir = "/mnt/data/apps/code-server/user-data"; + }; +} diff --git a/modules/system/homelab/containers.nix b/modules/system/homelab/containers.nix index abff513..2ca748c 100644 --- a/modules/system/homelab/containers.nix +++ b/modules/system/homelab/containers.nix @@ -1,5 +1,6 @@ { homelab, lib, ... }: let - stacks-dir = "/mnt/data/dockge/stacks"; + dockge-dir = "/mnt/data/apps/dockge"; + stacks-dir = "${dockge-dir}/stacks"; in { virtualisation.oci-containers.containers."dockge" = { image = "louislam/dockge:nightly"; @@ -8,7 +9,7 @@ in { }; volumes = [ "${stacks-dir}:${stacks-dir}:rw" - "/mnt/data/dockge/data:/app/data:rw" + "${dockge-dir}/data:/app/data:rw" "/var/run/docker.sock:/var/run/docker.sock:rw" ]; ports = [ diff --git a/modules/system/homelab/dash.nix b/modules/system/homelab/dash.nix index a27e591..e7d62bf 100644 --- a/modules/system/homelab/dash.nix +++ b/modules/system/homelab/dash.nix @@ -1,4 +1,4 @@ -{ config, timezone, homelab, ... }: let +{ timezone, homelab, ... }: let rss = [ "https://www.raspberrypi.com/news/feed/" "https://www.jeffgeerling.com/blog.xml" @@ -53,31 +53,9 @@ [ "Google Web Results Only" "!s" "https://google.com/search?udm=14&q={QUERY}" ] ]; monitor = [ - [ "Hypervisor" "https://10.3.14.69:8006/" ] - [ "Router" "http://10.3.14.1:80/" ] [ "DNS" "http://localhost:8088/" ] - [ "CDN" "http://nas.local:3000/" ] [ "Proxy" "https://proxy.${homelab.domain}/" ] ]; - external = [ - [ "Proxmox" "proxmox" "https://server.proxy.${homelab.domain}" "http://server.dns.${homelab.domain}:8006/" ] - [ "OpenWRT" "openwrt" "https://router.proxy.${homelab.domain}" "http://router.dns.${homelab.domain}:80/" ] - [ "HomeAssistant" "homeassistant" "https://home.proxy.${homelab.domain}" "http://home.dns.${homelab.domain}:8123/" ] - [ "OpenMediaVault" "openmediavault" "https://nas.local:80" "http://nas.local:80/" ] - [ "ApacheHTTPD" "apache" "https://nas.local:3000" "http://nas.local:3000/" ] - ]; - services = [ - [ "PocketID" "authentik" "https://auth.${homelab.domain}" "http://localhost:1411/" ] - [ "Forgejo" "forgejo" "https://git.${homelab.domain}" "http://localhost:5080/" ] - [ "AdGuardHome" "adguard" "https://dns.proxy.${homelab.domain}" "http://localhost:8088/" ] - [ "Traefik" "traefikproxy" "https://dynamic.proxy.${homelab.domain}/dashboard/" "http://localhost:81/dashboard/" ] - [ "Immich" "immich" "https://gallery.proxy.${homelab.domain}" "http://localhost:2283/" ] - [ "Jellyfin" "jellyfin" "https://media.proxy.${homelab.domain}" "http://localhost:8096/" ] - [ "VaultWarden" "vaultwarden" "https://pass.proxy.${homelab.domain}" "http://localhost:8060/" ] - [ "Ollama" "ollama" "https://ai.proxy.${homelab.domain}" "http://localhost:8080/" ] - [ "Dockge" "docker" "https://containers.proxy.${homelab.domain}" "http://localhost:5001/" ] - [ "Guacamole" "apacheguacamole" "https://remote.proxy.${homelab.domain}/guacamole" "http://localhost:8085/guacamole/" ] - ]; bookmarks = [ [ "Tailscale" "tailscale" "https://login.tailscale.com/" ] [ "Cloudflare" "cloudflare" "https://dash.cloudflare.com/" ] @@ -96,7 +74,6 @@ in { }; services.glance = { enable = true; - environmentFile = config.sops.secrets.glance_env.path; settings = { server = { host = "127.0.0.1"; @@ -112,6 +89,101 @@ in { }; pages = [ + { + name = "Dashboard"; + show-mobile-header = true; + width = "slim"; + columns = [ + { + size = "small"; + widgets = [ + { + type = "monitor"; + title = "Critical Systems"; + cache = "15s"; + style = "compact"; + show-failing-only = true; + sites = map (e: { + same-tab = true; + allow-insecure = true; + title = builtins.elemAt e 0; + url = builtins.elemAt e 1; + }) monitor; + } + { + type = "dns-stats"; + title = "DNS Stats"; + service = "adguard"; + url = "http://localhost:8088/"; + hour-format = "12h"; + } + { + type = "bookmarks"; + groups = [ + { + links = [{ + same-tab = true; + title = "NixFlake"; + icon = "si:nixos"; + url = "https://flake.satr14.my.id"; + }]; + } + { + links = map (e: { + same-tab = true; + title = builtins.elemAt e 0; + icon = "si:${builtins.elemAt e 1}"; + url = builtins.elemAt e 2; + alt-status-codes = [ 401 ]; + }) bookmarks; + } + ]; + } + { + type = "to-do"; + id = "tasks"; + } + ]; + } + { + size = "full"; + widgets = [ + { + type = "server-stats"; + servers = [{ + type = "local"; + mountpoints = { + "/boot".hide = true; + "/nix/store".hide = true; + "/var/lib/vaultwarden".hide = true; + "/var/lib/private/cryptpad".hide = true; + "/var/lib/acme/proxy.satr14.my.id".hide = true; + }; + }]; + } + { + type = "monitor"; + cache = "1m"; + title = "Services"; + sites = map (e: { + same-tab = true; + allow-insecure = true; + title = builtins.elemAt e 0; + icon = "si:${builtins.elemAt e 1}"; + url = builtins.elemAt e 2; + check-url = builtins.elemAt e 3; + }) homelab.dash; + } + { + type = "docker-containers"; + title = "Containers"; + format-container-names = true; + hide-by-default = true; + } + ]; + } + ]; + } { name = "Home"; show-mobile-header = true; @@ -210,107 +282,6 @@ in { } ]; } - { - name = "Dashboard"; - show-mobile-header = true; - width = "slim"; - columns = [ - { - size = "small"; - widgets = [ - { - type = "monitor"; - title = "Critical Systems"; - cache = "15s"; - style = "compact"; - show-failing-only = true; - sites = map (e: { - same-tab = true; - allow-insecure = true; - title = builtins.elemAt e 0; - url = builtins.elemAt e 1; - }) monitor; - } - { - type = "dns-stats"; - title = "DNS Stats"; - service = "adguard"; - url = "http://localhost:8088/"; - hour-format = "12h"; - } - { - type = "bookmarks"; - groups = [ - { - links = [{ - same-tab = true; - title = "NixFlake"; - icon = "si:nixos"; - url = "https://flake.satr14.my.id"; - }]; - } - { - links = map (e: { - same-tab = true; - title = builtins.elemAt e 0; - icon = "si:${builtins.elemAt e 1}"; - url = builtins.elemAt e 2; - }) bookmarks; - } - ]; - } - { - type = "to-do"; - id = "tasks"; - } - ]; - } - { - size = "full"; - widgets = [ - { - type = "server-stats"; - servers = [{ - type = "local"; - mountpoints."/nix/store".hide = true; - }]; - } - { - type = "monitor"; - cache = "1m"; - title = "External"; - sites = map (e: { - same-tab = true; - allow-insecure = true; - title = builtins.elemAt e 0; - icon = "si:${builtins.elemAt e 1}"; - url = builtins.elemAt e 2; - check-url = builtins.elemAt e 3; - }) external; - } - { - type = "monitor"; - cache = "1m"; - title = "Services"; - sites = map (e: { - same-tab = true; - allow-insecure = true; - title = builtins.elemAt e 0; - icon = "si:${builtins.elemAt e 1}"; - url = builtins.elemAt e 2; - check-url = builtins.elemAt e 3; - }) services; - } - { - type = "docker-containers"; - title = "Containers"; - format-container-names = true; - hide-by-default = true; - } - ]; - } - ]; - } ]; }; }; diff --git a/modules/system/homelab/db.nix b/modules/system/homelab/db.nix new file mode 100644 index 0000000..11cfedc --- /dev/null +++ b/modules/system/homelab/db.nix @@ -0,0 +1,7 @@ +{ pkgs, ... }: { + services.postgresql = { + enable = true; + dataDir = "/mnt/data/apps/postgresql"; + package = pkgs.postgresql_16; + }; +} \ No newline at end of file diff --git a/modules/system/homelab/docs.nix b/modules/system/homelab/docs.nix new file mode 100644 index 0000000..58d6738 --- /dev/null +++ b/modules/system/homelab/docs.nix @@ -0,0 +1,46 @@ +{ lib, pkgs, homelab, ... }: let + domain = "docs.${homelab.domain}"; + sandbox = "docs-sandbox.${homelab.domain}"; +in { + services.cryptpad = { + enable = true; + settings = { + websocketPort = 7091; + httpPort = 7090; + httpAddress = "127.0.0.1"; + httpUnsafeOrigin = "https://${domain}"; + httpSafeOrigin = "https://${sandbox}"; + blockDailyCheck = true; + disableIntegratedEviction = true; + adminKeys = [ + "[satr14@docs.satr14.my.id/f1A82fmBuqQka2bNqrCb1WbB9r2ex5A3rdys5xLX3Hc=]" + ]; + }; + }; + + systemd.tmpfiles.rules = lib.singleton "L+ /var/lib/cryptpad/customize/application_config.js - - - - ${pkgs.writeText "cryptpad-application-config.js" '' + (() => { + const factory = (AppConfig) => { + AppConfig.disableAnonymousPadCreation = true; + AppConfig.disableAnonymousStore = true; + AppConfig.defaultDarkTheme = true; + return AppConfig; + }; + + if (typeof(module) !== 'undefined' && module.exports) { + module.exports = factory( + require('../www/common/application_config_internal.js') + ); + } else if ((typeof(define) !== 'undefined' && define !== null) && (define.amd !== null)) { + define(['/common/application_config_internal.js'], factory); + } + })(); + ''}"; + + fileSystems."/var/lib/private/cryptpad" = { + device = "/mnt/data/apps/cryptpad"; + depends = [ "/mnt/data" ]; + options = [ "bind" "nofail" ]; + fsType = "none"; + }; +} diff --git a/modules/system/homelab/gallery.nix b/modules/system/homelab/gallery.nix index ef890f6..1b52208 100644 --- a/modules/system/homelab/gallery.nix +++ b/modules/system/homelab/gallery.nix @@ -1,4 +1,4 @@ -{ lib, homelab, ... }: { +{ lib, ... }: { users.users.immich.extraGroups = [ "video" "render" ]; services = { @@ -6,7 +6,7 @@ enable = true; port = 2283; host = "127.0.0.1"; - mediaLocation = "/mnt/gallery"; + mediaLocation = "/mnt/data/gallery"; accelerationDevices = null; environment.DB_URL = lib.mkForce "postgresql:///immich?host=/var/run/postgresql&user=immich"; # https://github.com/immich-app/immich/issues/26140 machine-learning.enable = true; diff --git a/modules/system/homelab/git.nix b/modules/system/homelab/git.nix index 68aa3d9..2544f90 100644 --- a/modules/system/homelab/git.nix +++ b/modules/system/homelab/git.nix @@ -1,48 +1,55 @@ { pkgs, homelab, ... }: { - services.forgejo = { - enable = true; - lfs.enable = true; - stateDir = "/mnt/data/forgejo"; - package = pkgs.forgejo; - #secrets = { - # oauth2.JWT_SECRET = "/mnt/data/forgejo/custom/conf/oauth2_jwt_secret"; - # server.LFS_JWT_SECRET = "/mnt/data/forgejo/custom/conf/lfs_jwt_secret"; - # security = { - # INTERNAL_TOKEN = "/mnt/data/forgejo/custom/conf/internal_token"; - # SECRET_KEY = "/mnt/data/forgejo/custom/conf/secret_key"; - # }; - #}; - settings = { - server = { - DISABLE_SSH = false; - START_SSH_SERVER = true; - SSH_DOMAIN = "main.dns.${homelab.domain}"; - SSH_LISTEN_HOST = "0.0.0.0"; - SSH_LISTEN_PORT = 5822; - SSH_PORT = 5822; - DOMAIN = "git.${homelab.domain}"; - HTTP_ADDR = "127.0.0.1"; - HTTP_PORT = 5080; - PROTOCOL = "http"; - ROOT_URL = "https://git.${homelab.domain}"; - LANDING_PAGE = "explore"; - }; - oauth2_client.ENABLE_AUTO_REGISTRATION=true; - service = { - DISABLE_REGISTRATION = true; - ENABLE_OPENID_SIGNIN = false; - ENABLE_OPENID_SIGNUP = false; - ENABLE_INTERNAL_SIGNIN = true; # TODO: set false after migration complete - SHOW_REGISTRATION_BUTTON = false; - ALLOW_ONLY_EXTERNAL_REGISTRATION = true; - ALLOW_ONLY_INTERNAL_REGISTRATION = false; - REQUIRE_EXTERNAL_REGISTRATION_PASSWORD = true; - }; - user.ENABLE_FOLLOWING = false; - repository = { - DISABLE_STARS = true; - DISABLE_FORKS = true; + services = { + forgejo = { + enable = true; + lfs.enable = true; + stateDir = "/mnt/data/apps/forgejo"; + package = pkgs.forgejo; + settings = { + server = { + DISABLE_SSH = false; + START_SSH_SERVER = true; + SSH_DOMAIN = "main.dns.${homelab.domain}"; + SSH_LISTEN_HOST = "0.0.0.0"; + SSH_LISTEN_PORT = 5822; + SSH_PORT = 5822; + DOMAIN = "git.${homelab.domain}"; + HTTP_ADDR = "127.0.0.1"; + HTTP_PORT = 5080; + PROTOCOL = "http"; + ROOT_URL = "https://git.${homelab.domain}"; + LANDING_PAGE = "explore"; + }; + oauth2_client.ENABLE_AUTO_REGISTRATION=true; + service = { + DISABLE_REGISTRATION = true; + ENABLE_OPENID_SIGNIN = false; + ENABLE_OPENID_SIGNUP = false; + ENABLE_INTERNAL_SIGNIN = false; + SHOW_REGISTRATION_BUTTON = false; + ALLOW_ONLY_EXTERNAL_REGISTRATION = true; + ALLOW_ONLY_INTERNAL_REGISTRATION = false; + REQUIRE_EXTERNAL_REGISTRATION_PASSWORD = true; + }; + user.ENABLE_FOLLOWING = false; + repository = { + DISABLE_STARS = true; + DISABLE_FORKS = true; + ENABLE_PUSH_CREATE_USER = true; + }; }; }; + gitea-actions-runner.instances.nixos-deploy = { + enable = true; + name = "nixos-server-runner"; + url = "http://localhost:5080"; #"https://git.proxy.${homelab.domain}"; + tokenFile = "/mnt/data/apps/forgejo/token-runner"; + labels = [ "self-hosted:host" ]; + hostPackages = with pkgs; [ bash coreutils git nix openssh bun ]; + }; + }; + systemd.services = { + "gitea-runner-nixos-deploy".restartIfChanged = false; + "forgejo".restartIfChanged = false; }; } diff --git a/modules/system/homelab/mc.nix b/modules/system/homelab/mc.nix new file mode 100644 index 0000000..90e2e76 --- /dev/null +++ b/modules/system/homelab/mc.nix @@ -0,0 +1,114 @@ +{ inputs, lib, pkgs, ... }: let + production = true; + ram-allocation-mb = 12288; + rcon-pass = "howdy"; + modpack = let + commit = "8523f89493ace13087eb68cd9fe3b5eb4f669440"; + path = if production then "commit/${commit}" else "branch/main"; + in pkgs.fetchPackwizModpack { + packHash = "sha256-xB9Oc/aneogSQ9r7L42vyVM6xwq+QkoTaXYNuUzeo6M="; + url = "https://git.satr14.my.id/satr14/server-modpack/raw/${path}/pack.toml"; + }; + +in { + imports = [ inputs.mc.nixosModules.minecraft-servers ]; + nixpkgs.overlays = [ inputs.mc.overlay ]; + + powerManagement.cpuFreqGovernor = "powersave"; # performance governor causes overheating and thermal throttling, works fine with powesave + boot.kernel.sysctl = { + "vm.nr_hugepages" = (ram-allocation-mb / 2) + 512; # (heap_mb / 2MB per page) + 512 pages (1GB) for ZGC off-heap overhead + "vm.swappiness" = 10; + }; + + services.minecraft-servers = { + enable = true; + eula = true; + managementSystem.systemd-socket.enable = true; + # ^^^ https://github.com/Infinidoge/nix-minecraft/issues/119 + + # TODO: figure out how to set gamerules on start + # gamerules to disable: locator_bar, mob_explosion_drop_decay, (and possibly) reduced_debug_info, global_sound_events + # gamerules to enable (temporarily): noend:disable_end + + servers.da-s3 = { + enable = true; + autoStart = true; + restart = "always"; + enableReload = production; + # extraReload = '' + # function rcon() { + # ${pkgs.rcon-cli}/bin/rcon-cli -p ${rcon-pass} $@ + # } + + # rcon "gamerule locator_bar false" + # rcon "gamerule mob_explosion_drop_decay false" + # rcon "gamerule reduced_debug_info false" + # rcon "gamerule global_sound_events false" + # ''; + + operators = lib.mkIf (!production) { + "satr14" = { + uuid = "54441a30-fe73-46e7-adca-c476bd4fc6d2"; + bypassesPlayerLimit = true; + level = 4; + }; + }; + + serverProperties = { + # server-ip = "localhost"; + server-port = 25565; + server-name = "Minecraft Server"; + motd = "§lSeason 3§r - §dExplorers Creativity 🔥"; + log-ips = false; # TODO: figure out how to get ips from cloudflared tunnel + + difficulty = "normal"; + gamemode = "survival"; + max-world-size = 25000; + spawn-protection = 0; + pvp = true; + + online-mode = true; + enable-query = true; + enforce-secure-profile = false; + pevent-proxy-connections = false; + allow-flight = false; + player-idle-timeout = 0; + + view-distance = 12; + simulation-distance = 4; + + enable-rcon = true; + sync-chunk-writes = false; + "rcon.password" = rcon-pass; + "rcon.port" = 25575; + }; + + symlinks = lib.mapAttrs' + (name: _: lib.nameValuePair "mods/${name}" "${modpack}/mods/${name}") + (builtins.readDir "${modpack}/mods"); + + package = pkgs.fabricServers.fabric-1_21_11.override { + jre_headless = pkgs.javaPackages.compiler.temurin-bin.jdk-25; + loaderVersion = "0.19.2"; + }; + + jvmOpts = let flags = [ + "-Xms${toString ram-allocation-mb}M" + "-Xmx${toString ram-allocation-mb}M" + + "-XX:+UseZGC" # Use ZGC (requires Java v25+, 8+ CPU cores, 10GB+ RAM) + "-XX:+UseCompactObjectHeaders" # Use compact object headers (requires Java v16+, saves a couple of bits per object) + + "--add-modules=jdk.incubator.vector" # Exposes SIMD instructions (requires full JDK, useful with performance mods) + "-XX:+UseLargePages" # Large pages support (requires hugepages configured on the system) + "-XX:+AlwaysPreTouch" # Pre-allocates memory on startup, OS claims it immediately for JVM instead of negotiating it + "-XX:+DisableExplicitGC" # Disables mods from manually invoking the GC + "-XX:+PerfDisableSharedMem" # Disables constant /tmp writes for JVM metrics + "-XX:ZAllocationSpikeTolerance=5" # Helps when server is active with many players + "-XX:SoftMaxHeapSize=${toString (ram-allocation-mb - 2048)}M" # Leave 2GB headroom + "-XX:ZCollectionInterval=1" # Force a GC cycle at minimum every second + "-XX:ConcGCThreads=8" # Threads ZGC uses for concurrent work + ]; in lib.concatStringsSep " " flags; + }; + }; +} \ No newline at end of file diff --git a/modules/system/homelab/media.nix b/modules/system/homelab/media.nix index 2393ccf..0c7a17f 100644 --- a/modules/system/homelab/media.nix +++ b/modules/system/homelab/media.nix @@ -5,6 +5,7 @@ services = { jellyfin = { enable = true; + dataDir = "/mnt/data/apps/jellyfin"; hardwareAcceleration = { enable = true; device = "/dev/dri/renderD128"; @@ -43,4 +44,4 @@ # port = 8191; # }; }; -} \ No newline at end of file +} diff --git a/modules/system/homelab/notify.nix b/modules/system/homelab/notify.nix new file mode 100644 index 0000000..48fbd12 --- /dev/null +++ b/modules/system/homelab/notify.nix @@ -0,0 +1,9 @@ +{ homelab, ... }: { + services.ntfy-sh = { + enable = true; + settings = { + listen-http = "127.0.0.1:8067"; + base-url = "https://ntfy.proxy.${homelab.domain}"; + }; + }; +} \ No newline at end of file diff --git a/modules/system/homelab/pass.nix b/modules/system/homelab/pass.nix index d3f5805..85b22e2 100644 --- a/modules/system/homelab/pass.nix +++ b/modules/system/homelab/pass.nix @@ -1,14 +1,20 @@ -{ config, homelab, ... }: { +{ homelab, ... }: { services.vaultwarden = { enable = true; domain = "pass.proxy.${homelab.domain}"; - backupDir = "/mnt/data/vaultwarden/backups"; - environmentFile = config.sops.secrets.vaultwarden_env.path; + backupDir = "/mnt/data/apps/vaultwarden/backups"; + environmentFile = "/mnt/data/apps/vaultwarden/.env"; config = { ROCKET_PORT = 8060; ROCKET_ADDRESS = "127.0.0.1"; ROCKET_LOG = "critical"; - SIGNUPS_ALLOWED = true; }; }; + + fileSystems."/var/lib/vaultwarden" = { + device = "/mnt/data/apps/vaultwarden/data"; + depends = [ "/mnt/data" ]; + options = [ "bind" "nofail" ]; + fsType = "none"; + }; } \ No newline at end of file diff --git a/modules/system/homelab/proxy.nix b/modules/system/homelab/proxy.nix index 37909e7..d977892 100644 --- a/modules/system/homelab/proxy.nix +++ b/modules/system/homelab/proxy.nix @@ -1,28 +1,5 @@ -{ config, homelab, lib, ... }: let - base = "proxy.${homelab.domain}"; - hosts = { - "server" = { dest = "https://server.dns.${homelab.domain}:8006"; auth = false; }; - "router" = { dest = "http://router.dns.${homelab.domain}:80"; auth = false; }; - "home" = { dest = "http://home.dns.${homelab.domain}:8123"; auth = false; }; - - "dynamic" = { dest = "http://127.0.0.1:8082"; auth = true; }; - "dns" = { dest = "http://localhost:8088"; auth = true; }; - - "containers" = { dest = "http://localhost:5001"; auth = false; }; - "gallery" = { dest = "http://localhost:2283"; auth = false; }; - "remote" = { dest = "http://localhost:8085"; auth = false; }; - "media" = { dest = "http://localhost:8096"; auth = false; }; - "pass" = { dest = "http://localhost:8060"; auth = false; }; - "auth" = { dest = "http://localhost:1411"; auth = false; }; - "git" = { dest = "http://localhost:5080"; auth = false; }; - "ai" = { dest = "http://localhost:8080"; auth = false; }; - "@" = { dest = "http://localhost:5070"; auth = false; }; - }; - redirects = { - "www" = "https://proxy.${homelab.domain}"; - "dash" = "https://${homelab.domain}"; - "immich" = "https://gallery.proxy${homelab.domain}"; - }; +{ pkgs, homelab, lib, ... }: let + htpasswd = "/mnt/data/apps/nginx/htpasswd"; exta-conf = '' # proxy_set_header X-Auth-User $remote_user; proxy_read_timeout 600s; @@ -41,24 +18,35 @@ in { security.acme = { acceptTerms = true; defaults.email = "admin@${homelab.domain}"; - certs."${base}" = { - domain = "*.${base}"; - extraDomainNames = [ base ]; + certs."${homelab.proxy.base}" = { + domain = "*.${homelab.proxy.base}"; + extraDomainNames = [ homelab.proxy.base ]; + environmentFile = "/mnt/data/apps/acme/cf-api.env"; dnsProvider = "cloudflare"; - environmentFile = config.sops.templates."cloudflare.env".path; + # ^^^contents: CLOUDFLARE_DNS_API_TOKEN=XXXXX }; }; + fileSystems."/var/lib/acme/${homelab.proxy.base}" = { + device = "/mnt/data/apps/acme/${homelab.proxy.base}"; + depends = [ "/mnt/data" ]; + options = [ "bind" "nofail" ]; + fsType = "none"; + }; + services = { nginx = { enable = true; + package = pkgs.angie; recommendedProxySettings = true; recommendedTlsSettings = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; virtualHosts = { "_" = { default = true; forceSSL = true; - useACMEHost = base; + useACMEHost = homelab.proxy.base; # locations."/".return = "404"; locations."/" = { proxyPass = "http://127.0.0.1:81"; # traefik for docker container dynamic proxy @@ -66,12 +54,12 @@ in { extraConfig = exta-conf; }; }; - } // lib.mapAttrs' (subdomain: cfg: lib.nameValuePair "${subdomain}.${base}" { - useACMEHost = base; + } // lib.mapAttrs' (subdomain: cfg: lib.nameValuePair "${subdomain}.${homelab.proxy.base}" { + useACMEHost = homelab.proxy.base; forceSSL = true; - locations."/".return = "301 ${base}"; - }) redirects // lib.mapAttrs' (subdomain: cfg: lib.nameValuePair (if subdomain == "@" then base else "${subdomain}.${base}") { - useACMEHost = base; + locations."/".return = "301 ${cfg}"; + }) homelab.proxy.redirects // lib.mapAttrs' (subdomain: cfg: lib.nameValuePair (if subdomain == "@" then homelab.proxy.base else "${subdomain}.${homelab.proxy.base}") { + useACMEHost = homelab.proxy.base; forceSSL = true; extraConfig = '' access_log /var/log/nginx/${subdomain}.access.log; @@ -80,13 +68,16 @@ in { locations."/" = { proxyPass = cfg.dest; proxyWebsockets = true; - basicAuthFile = if cfg.auth then config.sops.secrets.nginx_htpasswd.path else null; + basicAuthFile = if cfg.auth then htpasswd else null; extraConfig = exta-conf; }; - }) hosts; + }) homelab.proxy.hosts; }; traefik = { enable = true; + dynamicConfigOptions = { + http.middlewares.auth.basicAuth.usersFile = htpasswd; + }; staticConfigOptions = { entryPoints = { traefik.address = "127.0.0.1:8082"; @@ -106,9 +97,8 @@ in { providers.docker = { endpoint = "unix:///var/run/docker.sock"; exposedByDefault = false; - defaultRule = "Host(`ct-{{ normalize .Name }}.${base}`)"; }; }; }; }; -} \ No newline at end of file +} diff --git a/modules/system/homelab/remote.nix b/modules/system/homelab/remote.nix deleted file mode 100644 index 2eae11e..0000000 --- a/modules/system/homelab/remote.nix +++ /dev/null @@ -1,18 +0,0 @@ -{ ... }: { - services = { - guacamole-server = { - enable = true; - host = "127.0.0.1"; - port = 4822; - }; - guacamole-client = { - enable = true; - enableWebserver = true; - settings = { - guacd-hostname = "127.0.0.1"; - guacd-port = 4822; - }; - }; - tomcat.port = 8085; - }; -} \ No newline at end of file diff --git a/modules/system/homelab/search.nix b/modules/system/homelab/search.nix new file mode 100644 index 0000000..ba46b70 --- /dev/null +++ b/modules/system/homelab/search.nix @@ -0,0 +1,21 @@ +{ ... }: { + services.searx = { + enable = true; + redisCreateLocally = true; + environmentFile = "/mnt/data/apps/searxng/.env"; + settings = { + server = { + bind_address = "127.0.0.1"; + port = 8091; + secret_key = "$SECRET_KEY"; + }; + general = { + debug = false; + donation_url = false; + contact_url = false; + privacy_policy_url = false; + enable_metrics = true; + }; + }; + }; +} \ No newline at end of file diff --git a/modules/system/homelab/share.nix b/modules/system/homelab/share.nix deleted file mode 100644 index 6a01a39..0000000 --- a/modules/system/homelab/share.nix +++ /dev/null @@ -1,34 +0,0 @@ -{ ... }: { - services = { - httpd = { - enable = true; - virtualHosts."cdn" = { - listen = [{ ip = "127.0.0.1"; port = 3000; }]; - documentRoot = "/mnt/share"; - }; - }; - - samba = { - enable = true; - settings = { - global = { - workgroup = "WORKGROUP"; - "disable netbios" = "yes"; - "allow insecure wide links" = "yes"; - "server min protocol" = "SMB2_02"; - }; - "NAS" = { - path = "/mnt/share"; - browseable = "yes"; - "read only" = "no"; - "create mask" = "0664"; - "force create mode" = "0664"; - "directory mask" = "0775"; - "force directory mode" = "0775"; - "follow symlinks" = "yes"; - "wide links" = "yes"; - }; - }; - }; - }; -} \ No newline at end of file diff --git a/modules/system/homelab/sops.nix b/modules/system/homelab/sops.nix deleted file mode 100644 index 4ce61b7..0000000 --- a/modules/system/homelab/sops.nix +++ /dev/null @@ -1,59 +0,0 @@ -{ config, ... }: { - sops = { - defaultSopsFile = ../../../secrets/homelab.yaml; - age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; - - secrets = { - cloudflare_dns_api_token = { - owner = "acme"; - group = "acme"; - }; - - cloudflared_tunnel_credentials = { - owner = "cloudflared"; - group = "cloudflared"; - }; - - cloudflared_cert = { - owner = "cloudflared"; - group = "cloudflared"; - }; - - vaultwarden_env = { - owner = "vaultwarden"; - group = "vaultwarden"; - restartUnits = [ "vaultwarden.service" ]; - }; - - glance_env = { - owner = "glance"; - group = "glance"; - restartUnits = [ "glance.service" ]; - }; - - pocketid_encryption_key = { - owner = "root"; - group = "root"; - restartUnits = [ "pocket-id.service" ]; - }; - - tailscale_authkey = { - owner = "root"; - group = "root"; - restartUnits = [ "tailscaled.service" ]; - }; - - nginx_htpasswd = { - owner = "nginx"; - group = "nginx"; - restartUnits = [ "nginx.service" ]; - }; - }; - - templates."cloudflare.env" = { - owner = "acme"; - group = "acme"; - content = "CLOUDFLARE_DNS_API_TOKEN=${config.sops.placeholder.cloudflare_dns_api_token}"; - }; - }; -} \ No newline at end of file diff --git a/modules/system/homelab/tunnels.nix b/modules/system/homelab/tunnels.nix index 4c5402a..1ad43f7 100644 --- a/modules/system/homelab/tunnels.nix +++ b/modules/system/homelab/tunnels.nix @@ -1,19 +1,11 @@ -{ config, pkgs, lib, homelab, ... }: let - routes = { - "git.${homelab.domain}" = "http://localhost:5080"; - "auth.${homelab.domain}" = "http://localhost:1411"; - "dash.${homelab.domain}" = "http://localhost:5070"; - "media.${homelab.domain}" = "http://localhost:8096"; - "gallery.${homelab.domain}" = "http://localhost:2284"; - }; -in { +{ pkgs, lib, homelab, ... }: { services.cloudflared = { enable = true; tunnels.homelab = { - credentialsFile = config.sops.secrets.cloudflared_tunnel_credentials.path; - certificateFile = config.sops.secrets.cloudflared_cert.path; + credentialsFile = "/mnt/data/apps/cloudflared/homelab.json"; + certificateFile = "/mnt/data/apps/cloudflared/cert.pem"; default = "http_status:404"; - ingress = routes; + ingress = homelab.routes; }; }; @@ -31,7 +23,7 @@ in { script = lib.concatMapStringsSep "\n" (domain: '' echo "Ensuring DNS route for ${domain}..." - ${pkgs.cloudflared}/bin/cloudflared tunnel --origincert ${config.sops.secrets.cloudflared_cert.path} route dns ${homelab.cf-tunnel-id} ${domain} || true - '') (builtins.attrNames routes); + ${pkgs.cloudflared}/bin/cloudflared tunnel --origincert /mnt/data/apps/cloudflared/cert.pem route dns --overwrite-dns $(cat /mnt/data/apps/cloudflared/homelab.json | ${pkgs.jq}/bin/jq -r .TunnelID) ${domain} || true + '') (builtins.attrNames homelab.routes); }; } diff --git a/modules/system/misc/utilities.nix b/modules/system/misc/utilities.nix index 8f5be3a..a637e8d 100644 --- a/modules/system/misc/utilities.nix +++ b/modules/system/misc/utilities.nix @@ -1,60 +1,82 @@ { pkgs, ... }: { environment.systemPackages = with pkgs; [ + # Disk & Storage baobab - file-roller - gnome-network-displays gnome-disk-utility - - parted - smartmontools - lm_sensors - ntfs3g - virt-viewer - dconf2nix - pciutils gparted + parted + ntfs3g exfatprogs - pavucontrol - jq + smartmontools + rclone + ncdu + ventoy-full-qt + + # System Monitoring & Hardware + htop + sysstat powertop + lm_sensors fastfetch + pciutils + usbutils + stress + stress-ng + + # Networking + gnome-network-displays ethtool dig dnslookup - lsof - gucharmap - ncdu + nmap + netcat + traceroute + wakeonlan + cloudflared + cloud-utils + + # Archives & Compression + file-roller zip unzip + p7zip + + # GUI Utilities + pavucontrol + gucharmap + lxappearance blueman shared-mime-info - usbutils - - hplipWithPlugin - android-tools - scrcpy + # Virtualization & Containers + virt-viewer distrobox - ventoy-full-qt + # Android + android-tools + scrcpy + + # Remote Access + freerdp + + # Media ffmpeg + + # Printing + hplipWithPlugin + + # CLI Essentials vim wget curl openssl_3 - htop - nmap - sysstat - netcat - p7zip - stress - stress-ng - wakeonlan coreutils-full - traceroute - lxappearance - freerdp + jq + lsof + # Nix & Development + rcon-cli + dconf2nix home-manager nix-index nixd diff --git a/modules/system/server.nix b/modules/system/server.nix index 0b1e3d9..a2cef9f 100644 --- a/modules/system/server.nix +++ b/modules/system/server.nix @@ -1,8 +1,8 @@ -{ config, lib, homelab, ... }: let +{ lib, homelab, ... }: let ts-flags = [ "--advertise-exit-node" "--advertise-routes=10.3.14.0/24,192.168.1.0/24" - "--ssh" # "--webclient" + "--ssh" ]; in { imports = [ @@ -11,16 +11,21 @@ in { ./homelab/containers.nix ./homelab/gallery.nix ./homelab/tunnels.nix - ./homelab/remote.nix + ./homelab/notify.nix + ./homelab/search.nix ./homelab/media.nix ./homelab/proxy.nix ./homelab/auth.nix ./homelab/pass.nix ./homelab/dash.nix + ./homelab/code.nix + ./homelab/docs.nix ./homelab/dns.nix ./homelab/git.nix + ./homelab/cdn.nix ./homelab/ai.nix - ./homelab/sops.nix + ./homelab/db.nix + ./homelab/mc.nix ./core/swapfile.nix ./core/oom.nix @@ -28,14 +33,19 @@ in { ./base.nix ]; - services.tailscale = { - enable = true; - authKeyFile = config.sops.secrets.tailscale_authkey.path; - useRoutingFeatures = "server"; - extraUpFlags = ts-flags; - extraSetFlags = ts-flags; - }; + users.users.root.openssh.authorizedKeys.keys = homelab.ssh-keys; + services = { + netbird.enable = true; + tailscale = { + enable = true; + authKeyFile = "/mnt/data/apps/tailscale/authkey"; + useRoutingFeatures = "server"; + extraUpFlags = ts-flags; + extraSetFlags = ts-flags; + }; + }; + virtualisation = { oci-containers.backend = "docker"; docker = { diff --git a/modules/system/user.nix b/modules/system/user.nix index 44910e9..5f50a54 100644 --- a/modules/system/user.nix +++ b/modules/system/user.nix @@ -7,6 +7,7 @@ shell = pkgs.zsh; extraGroups = [ "networkmanager" + "minecraft" "wheel" "dialout" "libvirtd" diff --git a/scripts/check-sops.sh b/scripts/check-sops.sh deleted file mode 100755 index dd4daf2..0000000 --- a/scripts/check-sops.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -# Pre-commit hook: block commits containing unencrypted sops secret files. -# Install with: ln -sf ../../scripts/check-sops.sh .git/hooks/pre-commit - -set -euo pipefail - -staged_secrets=$(git diff --cached --name-only --diff-filter=ACM -- 'secrets/*.yaml' 'secrets/*.yml' 'secrets/*.json') - -if [ -z "$staged_secrets" ]; then - exit 0 -fi - -failed=0 - -for file in $staged_secrets; do - # sops-encrypted YAML/JSON files always contain a top-level "sops" key with metadata - if ! git show ":$file" | grep -q '"sops"\|sops:'; then - echo "ERROR: $file is not encrypted with sops! Encrypt it first:" - echo " sops $file" - echo - echo "hint: bypass with: git commit --no-verify" - failed=1 - fi -done - -if [ "$failed" -ne 0 ]; then - echo "" - echo "Commit aborted. Encrypt secret files before committing." - exit 1 -fi \ No newline at end of file diff --git a/secrets/homelab.yaml b/secrets/homelab.yaml deleted file mode 100644 index 93cb53a..0000000 --- a/secrets/homelab.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# This file should be encrypted with sops before committing. -# Run: sops secrets/homelab.yaml -# All values below are placeholders. Replace them with actual values. -cloudflare_dns_api_token: REPLACE_ME -cloudflared_tunnel_credentials: REPLACE_ME -cloudflared_cert: REPLACE_ME -vaultwarden_env: REPLACE_ME -glance_env: REPLACE_ME -pocketid_encryption_key: REPLACE_ME -tailscale_authkey: REPLACE_ME -nginx_htpasswd: REPLACE_ME