diff --git a/builders/mirai.nix b/builders/mirai.nix index a9a55ac9..c532dce7 100644 --- a/builders/mirai.nix +++ b/builders/mirai.nix @@ -1,7 +1,7 @@ { hostName = "sh.darksailor.dev"; sshUser = "remotebuilder"; - system = "x86_64-linux"; + systems = ["x86_64-linux" "aarch64-linux"]; protocol = "ssh-ng"; supportedFeatures = ["nixos-test" "benchmark" "big-parallel" "kvm"]; } diff --git a/deploy.nix b/deploy.nix index 641f61a9..958912b6 100644 --- a/deploy.nix +++ b/deploy.nix @@ -12,11 +12,13 @@ user = "root"; }; }; - rpi = { - hostname = "rpi"; + tsuba = { + hostname = "192.168.0.125"; + # hostname = "tsuba.darksailor.dev"; profiles.system = { sshUser = "servius"; - path = inputs.deploy-rs.lib.x86_64-linux.activate.home-manager self.homeConfigurations.rpi; + path = inputs.deploy-rs.lib.aarch64-linux.activate.nixos self.nixosConfigurations.tsuba; + user = "root"; }; }; ryu = { diff --git a/flake.lock b/flake.lock index 68edb2aa..fa3543bb 100644 --- a/flake.lock +++ b/flake.lock @@ -2061,11 +2061,11 @@ "nixos-images": { "inputs": { "nixos-stable": [ - "nixos-rpi", + "nixos-raspberrypi", "nixpkgs" ], "nixos-unstable": [ - "nixos-rpi", + "nixos-raspberrypi", "nixpkgs" ] }, @@ -2084,7 +2084,7 @@ "type": "github" } }, - "nixos-rpi": { + "nixos-raspberrypi": { "inputs": { "argononed": "argononed", "nixos-images": "nixos-images", @@ -2589,7 +2589,7 @@ "nix-darwin": "nix-darwin", "nix-index-database": "nix-index-database", "nix-minecraft": "nix-minecraft", - "nixos-rpi": "nixos-rpi", + "nixos-raspberrypi": "nixos-raspberrypi", "nixpkgs": "nixpkgs_7", "nixpkgs-master": "nixpkgs-master", "nixpkgs-stable": "nixpkgs-stable", diff --git a/flake.nix b/flake.nix index dece3d0e..aac176d7 100644 --- a/flake.nix +++ b/flake.nix @@ -134,7 +134,7 @@ url = "github:hercules-ci/arion"; inputs.nixpkgs.follows = "nixpkgs"; }; - nixos-rpi = { + nixos-raspberrypi = { url = "github:nvmd/nixos-raspberrypi/main"; }; zen-browser = { @@ -194,7 +194,7 @@ anyrun, nur, deploy-rs, - nixos-rpi, + nixos-raspberrypi, ... } @ inputs: let devices = { @@ -298,7 +298,7 @@ }) // ( import ./nixos/tsuba { - inherit inputs nixpkgs home-manager overlays nur nixos-rpi; + inherit inputs nixpkgs home-manager overlays nur nixos-raspberrypi; devices = rpi_devices; } ); diff --git a/home/linux/gui.nix b/home/linux/gui.nix index a3c8287b..8d920e9e 100644 --- a/home/linux/gui.nix +++ b/home/linux/gui.nix @@ -4,7 +4,7 @@ lib, ... }: { - systemd.user.services.onepassword-gui = lib.optionalAttrs pkgs.stdenv.isLinux { + systemd.user.services.onepassword-gui = lib.optionalAttrs (pkgs.stdenv.isLinux && device.hasGui) { Unit = { Description = "1Password GUI"; BindsTo = ["graphical-session.target"]; @@ -20,7 +20,7 @@ }; }; home.packages = with pkgs; - lib.optionals pkgs.stdenv.isLinux [ + lib.optionals (pkgs.stdenv.isLinux && device.hasGui) [ nautilus totem ffmpegthumbnailer diff --git a/nixos/deoxys/configuration.nix b/nixos/deoxys/configuration.nix index d9f27dec..e7bc3fd4 100644 --- a/nixos/deoxys/configuration.nix +++ b/nixos/deoxys/configuration.nix @@ -34,15 +34,7 @@ options = "--delete-older-than +5"; }; package = pkgs.nixVersions.latest; - buildMachines = [ - { - hostName = "sh.darksailor.dev"; - sshUser = "remotebuilder"; - system = "x86_64-linux"; - protocol = "ssh-ng"; - supportedFeatures = ["nixos-test" "benchmark" "big-parallel" "kvm"]; - } - ]; + buildMachines = []; distributedBuilds = true; }; diff --git a/nixos/mirai/mirai.nix b/nixos/mirai/mirai.nix index a0e62f1e..83e8c5ba 100644 --- a/nixos/mirai/mirai.nix +++ b/nixos/mirai/mirai.nix @@ -17,6 +17,7 @@ boot.initrd.kernelModules = ["dm-snapshot"]; boot.kernelModules = ["kvm-amd"]; boot.extraModulePackages = []; + boot.binfmt.emulatedSystems = ["aarch64-linux"]; fileSystems."/var/lib/nextcloud" = { device = "/media/nextcloud"; diff --git a/nixos/ryu/configuration.nix b/nixos/ryu/configuration.nix index a3826629..a48a5642 100644 --- a/nixos/ryu/configuration.nix +++ b/nixos/ryu/configuration.nix @@ -101,7 +101,7 @@ buildMachines = [ ../../builders/mirai.nix ../../builders/shiro.nix - ../../builders/tsuba.nix + # ../../builders/tsuba.nix ]; distributedBuilds = true; }; diff --git a/nixos/ryu/ryu.nix b/nixos/ryu/ryu.nix index 47687a0e..2697687e 100644 --- a/nixos/ryu/ryu.nix +++ b/nixos/ryu/ryu.nix @@ -36,6 +36,9 @@ firmware = [pkgs.linux-firmware]; }; + # nixpkgs.localSystem = {system = "x86_64-linux";}; + # nixpkgs.crossSystem = {system = "aarch64-linux";}; + boot.binfmt.emulatedSystems = ["aarch64-linux"]; services.fprintd.enable = true; services.sshd.enable = true; boot.loader.systemd-boot.consoleMode = "max"; diff --git a/nixos/tsuba/configuration.nix b/nixos/tsuba/configuration.nix index 091ff78a..09d137a4 100644 --- a/nixos/tsuba/configuration.nix +++ b/nixos/tsuba/configuration.nix @@ -2,27 +2,32 @@ config, pkgs, lib, + device, ... }: { + nixpkgs.config.allowUnfree = true; + security.sudo.wheelNeedsPassword = false; + sops = { + defaultSopsFile = ../../secrets/secrets.yaml; + defaultSopsFormat = "yaml"; + age.keyFile = "/home/servius/.config/sops/age/keys.txt"; + }; nix = { settings = { auto-optimise-store = true; extra-experimental-features = "nix-command flakes auto-allocate-uids"; - trusted-users = ["root" "fs0c131y" "remotebuilder"]; + trusted-users = ["root" "remotebuilder" device.user]; substituters = [ "https://nix-community.cachix.org" - # "https://sh.darksailor.dev" ]; trusted-public-keys = [ "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" - # "mirai:bcVPoFGBZ0i7JAKMXIqLj2GY3CulLC4kP7rQyqes1RM=" ]; }; extraOptions = '' build-users-group = nixbld extra-nix-path = nixpkgs=flake:nixpkgs builders-use-substitutes = true - secret-key-files = ${config.sops.secrets."builder/mirai/cache/private".path} ''; gc = { automatic = true; @@ -37,12 +42,21 @@ ../../builders/tsuba.nix ]; }; - users.users.servius = { + users.users.${device.user} = { isNormalUser = true; extraGroups = ["wheel"]; + initialPassword = "aaa"; openssh.authorizedKeys.keyFiles = [ ../../secrets/id_ed25519.pub ../../secrets/id_ios.pub ]; }; + users.users.remotebuilder = { + isNormalUser = true; + openssh.authorizedKeys.keyFiles = [ + ../../secrets/id_ed25519.pub + ]; + }; + system.stateVersion = "25.05"; + services.openssh.enable = true; } diff --git a/nixos/tsuba/default.nix b/nixos/tsuba/default.nix index 6f03c346..98e61a28 100644 --- a/nixos/tsuba/default.nix +++ b/nixos/tsuba/default.nix @@ -5,41 +5,33 @@ overlays, home-manager, nur, - nixos-rpi, + nixos-raspberrypi, ... }: (builtins.mapAttrs ( name: device: - nixos-rpi.lib.nixosSystemFull { - inherit nixpkgs; + nixos-raspberrypi.lib.nixosSystem { + specialArgs = + inputs + // { + inherit device; + }; system = device.system; - specialArgs = { - inherit device; - nixos-raspberrypi = inputs.nixos-raspberrypi; - stablePkgs = inputs.nixpkgs-stable.legacyPackages.${device.system}; - }; modules = [ + inputs.disko.nixosModules.disko + nur.modules.nixos.default + inputs.sops-nix.nixosModules.sops { - imports = with nixos-rpi.nixosModules; [ - nixos-raspberrypi.lib.inject-overlays + nixpkgs.overlays = overlays; + imports = with nixos-raspberrypi.nixosModules; [ raspberry-pi-5.base raspberry-pi-5.display-vc4 raspberry-pi-5.bluetooth - trusted-nix-caches - nixpkgs-rpi - nixos-raspberrypi.lib.inject-overlays-global ]; - networking.hostName = name; } ./configuration.nix + ./disk-config.nix + ./services ./${name}.nix - {nixpkgs.overlays = overlays;} - nur.modules.nixos.default - inputs.sops-nix.nixosModules.sops - home-manager.nixosModules.home-manager - inputs.arion.nixosModules.arion - { - nixpkgs.config.allowUnfree = true; - } ]; } ) diff --git a/nixos/tsuba/disk-config.nix b/nixos/tsuba/disk-config.nix new file mode 100644 index 00000000..95755ef7 --- /dev/null +++ b/nixos/tsuba/disk-config.nix @@ -0,0 +1,142 @@ +{ + config, + lib, + ... +}: let + firmwarePartition = lib.recursiveUpdate { + # label = "FIRMWARE"; + priority = 1; + + type = "0700"; # Microsoft basic data + # attributes = [ + # 0 # Required Partition + # ]; + + size = "1024M"; + content = { + type = "filesystem"; + format = "vfat"; + # mountpoint = "/boot/firmware"; + mountOptions = [ + "noatime" + "noauto" + "x-systemd.automount" + "x-systemd.idle-timeout=1min" + ]; + }; + }; + + espPartition = lib.recursiveUpdate { + # label = "ESP"; + + type = "EF00"; # EFI System Partition (ESP) + # attributes = [ + # 2 # Legacy BIOS Bootable, for U-Boot to find extlinux config + # ]; + + size = "1024M"; + content = { + type = "filesystem"; + format = "vfat"; + # mountpoint = "/boot"; + mountOptions = [ + "noatime" + "noauto" + "x-systemd.automount" + "x-systemd.idle-timeout=1min" + "umask=0077" + ]; + }; + }; +in { + disko.devices = { + disk = { + one = { + type = "disk"; + device = "/dev/nvme0n1"; + content = { + type = "gpt"; + partitions = { + FIRMWARE = firmwarePartition { + label = "FIRMWARE"; + content.mountpoint = "/boot/firmware"; + }; + ESP = espPartition { + label = "ESP"; + content.mountpoint = "/boot"; + }; + primary = { + size = "100%"; + content = { + type = "lvm_pv"; + vg = "pool"; + }; + }; + }; + }; + }; + two = { + type = "disk"; + device = "/dev/nvme1n1"; + content = { + type = "gpt"; + partitions = { + primary = { + size = "100%"; + content = { + type = "lvm_pv"; + vg = "pool"; + }; + }; + }; + }; + }; + }; + lvm_vg = { + pool = { + type = "lvm_vg"; + lvs = { + root = { + size = "64G"; + lvm_type = "mirror"; + content = { + type = "filesystem"; + format = "ext4"; + mountpoint = "/"; + mountOptions = [ + "defaults" + ]; + }; + }; + nix = { + size = "256G"; + lvm_type = "raid0"; + content = { + type = "filesystem"; + format = "ext4"; + mountpoint = "/nix"; + }; + }; + home = { + size = "256G"; + lvm_type = "raid0"; + content = { + type = "filesystem"; + format = "ext4"; + mountpoint = "/home"; + }; + }; + media = { + size = "100%"; + lvm_type = "raid0"; + content = { + type = "filesystem"; + format = "ext4"; + mountpoint = "/volumes/media"; + }; + }; + }; + }; + }; + }; +} diff --git a/nixos/tsuba/services/caddy.nix b/nixos/tsuba/services/caddy.nix new file mode 100644 index 00000000..4a8d3325 --- /dev/null +++ b/nixos/tsuba/services/caddy.nix @@ -0,0 +1,37 @@ +{ + config, + pkgs, + ... +}: { + sops = { + secrets."hetzner/api_key".owner = config.services.caddy.user; + templates = { + "HETZNER_API_KEY.env".content = '' + HETZNER_API_KEY=${config.sops.placeholder."hetzner/api_key"} + ''; + }; + }; + services = { + caddy = { + enable = true; + extraConfig = '' + (hetzner) { + tls { + propagation_timeout -1 + propagation_delay 30s + dns hetzner {env.HETZNER_API_KEY} + } + } + ''; + package = pkgs.caddy.withPlugins { + plugins = ["github.com/caddy-dns/hetzner@v1.0.0"]; + hash = "sha256-9ea0CfOHG7JhejB73HjfXQpnonn+ZRBqLNz1fFRkcDQ="; + }; + }; + }; + systemd.services.caddy = { + serviceConfig = { + EnvironmentFile = config.sops.templates."HETZNER_API_KEY.env".path; + }; + }; +} diff --git a/nixos/tsuba/services/default.nix b/nixos/tsuba/services/default.nix new file mode 100644 index 00000000..ef211bc1 --- /dev/null +++ b/nixos/tsuba/services/default.nix @@ -0,0 +1,12 @@ +{...}: { + imports = [ + ./tailscale.nix + ./samba.nix + ./jellyfin.nix + ./caddy.nix + ./sonarr.nix + ./radarr.nix + ./prowlarr.nix + ./deluge.nix + ]; +} diff --git a/nixos/tsuba/services/deluge.nix b/nixos/tsuba/services/deluge.nix new file mode 100644 index 00000000..68c5acfb --- /dev/null +++ b/nixos/tsuba/services/deluge.nix @@ -0,0 +1,11 @@ +{...}: { + services = { + deluge.enable = true; + caddy = { + virtualHosts."deluge.tsuba.darksailor.dev".extraConfig = '' + import hetzner + reverse_proxy localhost:8112 + ''; + }; + }; +} diff --git a/nixos/tsuba/services/jellyfin.nix b/nixos/tsuba/services/jellyfin.nix new file mode 100644 index 00000000..adf46722 --- /dev/null +++ b/nixos/tsuba/services/jellyfin.nix @@ -0,0 +1,11 @@ +{...}: { + services = { + # jellyfin.enable = true; + jellyseerr.enable = true; + caddy = { + virtualHosts."jellyfin.tsuba.darksailor.dev".extraConfig = '' + reverse_proxy localhost:8096 + ''; + }; + }; +} diff --git a/nixos/tsuba/services/prowlarr.nix b/nixos/tsuba/services/prowlarr.nix new file mode 100644 index 00000000..e1e17e57 --- /dev/null +++ b/nixos/tsuba/services/prowlarr.nix @@ -0,0 +1,11 @@ +{...}: { + services = { + prowlarr.enable = true; + caddy = { + virtualHosts."prowlarr.tsuba.darksailor.dev".extraConfig = '' + import hetzner + reverse_proxy localhost:9696 + ''; + }; + }; +} diff --git a/nixos/tsuba/services/radarr.nix b/nixos/tsuba/services/radarr.nix new file mode 100644 index 00000000..44fdf9e8 --- /dev/null +++ b/nixos/tsuba/services/radarr.nix @@ -0,0 +1,11 @@ +{...}: { + services = { + radarr.enable = true; + caddy = { + virtualHosts."radarr.tsuba.darksailor.dev".extraConfig = '' + import hetzner + reverse_proxy localhost:7878 + ''; + }; + }; +} diff --git a/nixos/tsuba/services/samba.nix b/nixos/tsuba/services/samba.nix new file mode 100644 index 00000000..5d5c346b --- /dev/null +++ b/nixos/tsuba/services/samba.nix @@ -0,0 +1,38 @@ +{...}: { + services = { + samba = { + enable = true; + openFirewall = true; + settings = { + global = { + "workgroup" = "WORKGROUP"; + "server string" = "tsuba"; + "netbios name" = "tsuba"; + "security" = "user"; + # "hosts allow" = "192.168.0. 127.0.0.1 localhost "; + # "hosts deny" = "0.0.0.0/0"; + "guest account" = "nobody"; + "map to guest" = "bad user"; + "min protocol" = "SMB2"; + "max protocol" = "SMB3"; + }; + + nas = { + "path" = "/volumes/media"; + "browseable" = "yes"; + "read only" = "no"; + "guest ok" = "no"; + "create mask" = "0644"; + "directory mask" = "0755"; + # "force user" = "username"; + # "force group" = "groupname"; + }; + }; + }; + samba-wsdd = { + enable = true; + openFirewall = true; + }; + }; + networking.firewall.allowPing = true; +} diff --git a/nixos/tsuba/services/sonarr.nix b/nixos/tsuba/services/sonarr.nix new file mode 100644 index 00000000..b28eb1a0 --- /dev/null +++ b/nixos/tsuba/services/sonarr.nix @@ -0,0 +1,11 @@ +{...}: { + services = { + sonarr.enable = true; + caddy = { + virtualHosts."sonarr.tsuba.darksailor.dev".extraConfig = '' + import hetzner + reverse_proxy localhost:8989 + ''; + }; + }; +} diff --git a/nixos/tsuba/services/tailscale.nix b/nixos/tsuba/services/tailscale.nix new file mode 100644 index 00000000..3ce346d7 --- /dev/null +++ b/nixos/tsuba/services/tailscale.nix @@ -0,0 +1,22 @@ +{ + pkgs, + lib, + ... +}: { + services = { + tailscale = { + enable = true; + # useRoutingFeatures = "both"; + # extraUpFlags = ["--advertise-routes=192.168.0.0/24"]; + }; + # networkd-dispatcher = { + # enable = true; + # rules."50-tailscale" = { + # onState = ["routable"]; + # script = '' + # ${lib.getExe pkgs.ethtool} -K en01 rx-udp-gro-forwarding on rg-xgro-list off + # ''; + # }; + # }; + }; +} diff --git a/nixos/tsuba/tsuba.nix b/nixos/tsuba/tsuba.nix index 20dd810f..2b2984da 100644 --- a/nixos/tsuba/tsuba.nix +++ b/nixos/tsuba/tsuba.nix @@ -1,11 +1,12 @@ { config, pkgs, + device, lib, ... }: { - # networking.hostName = "tsuba"; - networking.filrewall.logRefusedConnections = lib.mkDefault false; + networking.hostName = device.name; + networking.firewall.logRefusedConnections = lib.mkDefault false; networking.useNetworkd = true; systemd.services.NetworkManager-wait-online.enable = false; systemd.network.wait-online.enable = false; @@ -18,16 +19,37 @@ config.boot.kernelPackages.kernel.version ]; - hardware.raspberry-pi.config = { - dtparam = "audio=on"; - camera_auto_detect = 0; - display_auto_detect = 0; - auto_initramfs = 1; - disable_fw_kms_setup = 1; - arm_boost = 1; - arm_64bit = 1; - all = { - usb_max_current_enable = 1; - }; - }; + # hardware.raspberry-pi.config = { + # all = { + # "dtparam" = [ + # "pciex1" + # "pciex1_gen=2" + # ]; + # }; + # }; + hardware.raspberry-pi.extra-config = '' + [all] + dtparam=pciex1 + dtparam=pciex1_gen=2 + ''; } +# ({ +# config, +# pkgs, +# lib, +# ... +# }: { +# +# system.nixos.tags = let +# cfg = config.boot.loader.raspberryPi; +# in [ +# "raspberry-pi-${cfg.variant}" +# cfg.bootloader +# config.boot.kernelPackages.kernel.version +# ]; +# # hardware.raspberry-pi.config = { +# # }; +# system.stateVersion = "25.05"; +# services.openssh.enable = true; +# }) + diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml index 30fb0be2..75fe3eab 100644 --- a/secrets/secrets.yaml +++ b/secrets/secrets.yaml @@ -6,6 +6,8 @@ paperless: llama: user: ENC[AES256_GCM,data:qWbhnc/XLotWzqbEa6ekuMe5kD/GwC9SW8omXvgWqCG1BPPCOI3DtlS4YqKxsIhYmw8MQw+4DPnaWHqjrbIsVSrQ79M=,iv:VeqkKb1N9NSKfuilG6dzYdha8cO4JqJ+YUzmkjrPU+0=,tag:SYwR1oU6VWzNoCBPsMg0uQ==,type:str] api_key: ENC[AES256_GCM,data:wib+xbb25sTY2K9pacc1mU5eVSyQRurHiCMZyDVSqCAmG4yjkzEykvBevpThNbTZlsk6GZuK4hH0SYJM,iv:GTU6CQ83chXHAuuL0bFMf4L+UWqlcVfXnEE0/SxLzj4=,tag:0LkOSQsuuQd6TK3KHE95TA==,type:str] +hetzner: + api_key: ENC[AES256_GCM,data:8lDAf8wyM5b7SH/TaQxXyfITStiiO0obDMdWuRHHxHA=,iv:tHwpmW1Unr8DQXOUKutqyssOKOxtNYMIEc2aMXcmSbE=,tag:N2o9tsdaeoi/cm0ETf3UTQ==,type:str] openai: api_key: ENC[AES256_GCM,data:d6z9TySB6r2myUYu4u9aZwdoy1qL+DdU4MIuel1lFMMKD4XAqn5U9Vc3t5sJ/E3hDXud,iv:500n8CY8Qd/tg+MuT+RDRAyjgy6E9Aolud/2KrRyyqk=,tag:nCowF/czJMkYoNuSl1c3ZA==,type:str] openrouter: @@ -44,7 +46,7 @@ sops: VGZKdHpVeFRpQUxtSEkyaEhLMlBJcGsKLb0DvPNZosPBUuiX6qz1s5IO5INQh8CK ZtXTVClwMSmaUYhdSB2gKFrKVZHXTJZ4oAL5t/BpC0pOHyr+o96T3Q== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-07-09T07:01:27Z" - mac: ENC[AES256_GCM,data:1owtam5J+NvAZovXp1XyvbpouibOAYWyMAhwZ7mHQYOM9lYbJFqYm1L6Wwh0NzHUOvY3FlARzp9XlRRg5Wbq1RwL+LJFFozdgoqUi6/7v0gIM9N7hSFlJO6AH/zNIkke9AyI+pqcMfJad01H2GjClirW0tu99nUSkyIZOqote04=,iv:BJfGJiEX+l81JhrPQbj1ykqO5a4qtRSN+/btAiSCGho=,tag:AtlV2p1JB5qSgYcnT2LNzQ==,type:str] + lastmodified: "2025-07-12T11:46:28Z" + mac: ENC[AES256_GCM,data:wBXotjaIYnMuXf1p+UAUUl1qDdy3Gm+yXAZo9/dnKBh+RPY7D5+nqdRq3ogSfXwtF7z+s7Mu3pZykapgw7oUuNzsi2N1beEFC4OgWGPDEorVNmy7WjPUCDKvurarUoXMoRCVU5VXR6kC5U7T7bAER8wC52F+ryeMn8IVaQtMT4U=,iv:Xgm0gqHG0DUS/JBYWtmn0E/1g3PxVy2hRCA57sqSxXM=,tag:1TYL2S+VWXmt22Rhwk36wg==,type:str] unencrypted_suffix: _unencrypted version: 3.10.2