From fb1b3606270ce8ceaea8534a046eb1dda08c54dc Mon Sep 17 00:00:00 2001 From: Chris Toph Date: Mon, 28 Apr 2025 17:52:47 -0400 Subject: [PATCH] Initial commit, hopefully in working state. --- flake.nix | 253 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ readme.md | 0 2 files changed, 253 insertions(+) create mode 100644 flake.nix create mode 100644 readme.md diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..58681ac --- /dev/null +++ b/flake.nix @@ -0,0 +1,253 @@ +{ + description = "The definitive all-in-one SnapRAID script on Linux"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + + snapraid-aio-src = { + url = "github:auanasgheps/snapraid-aio-script/a46c7362af385eac945e86a2a0f6097dbe7ca3fb"; # v3.4-beta3 + flake = false; + }; + }; + + outputs = + { + self, + nixpkgs, + flake-utils, + snapraid-aio-src, + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + dependencies = with pkgs; [ + apprise + bash + bc + coreutils + curl + findutils + gnugrep + gnused + hostname # Added for the hostname command + jq + mailutils # For mailx + procps + (python3.withPackages (ps: with ps; [ markdown ])) # Fixed Python with markdown module + python3Packages.pipx + smartmontools # For smartctl + snapraid + util-linux # For lsblk + ]; + in + { + packages = rec { + default = snapraid-aio; + + snapraid-aio = pkgs.stdenv.mkDerivation rec { + pname = "snapraid-aio"; + version = "3.4-beta3"; + src = snapraid-aio-src; + + nativeBuildInputs = [ pkgs.makeWrapper ]; + buildInputs = dependencies; + + dontBuild = true; + + installPhase = '' + # Create directories + mkdir -p $out/bin + mkdir -p $out/share/snapraid-aio + + # 1. PATCH CONFIG: Modify the config file to not overwrite PATH + cat script-config.conf | sed 's|^PATH=.*$|# PATH is managed by Nix wrapper|' > $out/share/snapraid-aio/default-config.conf + cp README.md $out/share/snapraid-aio/ + + # 2. PATCH SCRIPT: Add PATH protection to the main script and fix paths + cat snapraid-aio-script.sh > temp_script.sh + + # Insert code to save PATH before sourcing config + sed -i '/#shellcheck source=script-config.conf/i # Save original PATH\nORIGINAL_PATH="$PATH"' temp_script.sh + + # Insert code to restore PATH after sourcing config + sed -i '/source "$CONFIG_FILE"/a # Restore original PATH\nPATH="$ORIGINAL_PATH"' temp_script.sh + + # Fix the process substitution issue + sed -i 's/exec > >(tee/exec > >(PATH="$PATH" tee/g' temp_script.sh + + # Fix specific command paths + sed -i 's|MAIL_BIN=/usr/bin/mailx|MAIL_BIN=${pkgs.mailutils}/bin/mailx|g' temp_script.sh + sed -i 's|command -v dpkg >/dev/null|false|g' temp_script.sh + sed -i 's|python3 -m markdown|${ + pkgs.python3.withPackages (ps: with ps; [ markdown ]) + }/bin/python3 -m markdown|g' temp_script.sh + + # Copy the patched script + cp temp_script.sh $out/share/snapraid-aio/snapraid-aio-script.sh + chmod +x $out/share/snapraid-aio/snapraid-aio-script.sh + rm temp_script.sh + + # 3. EXPLICIT PATH IN WRAPPER: Create wrapper script with explicit PATH setting + cat > $out/bin/snapraid-aio << EOF + #!${pkgs.bash}/bin/bash + + # Set PATH explicitly to include all dependencies + export PATH="${pkgs.lib.makeBinPath dependencies}:$PATH" + + # Create a writable temp directory if needed + TEMP_DIR="\$HOME/.cache/snapraid-aio" + mkdir -p "\$TEMP_DIR" + + # Define default config path + DEFAULT_CONFIG="$out/share/snapraid-aio/default-config.conf" + + # Export environment variables the script needs + export TMP_OUTPUT="\$TEMP_DIR/snapRAID.out" + export SYNC_WARN_FILE="\$TEMP_DIR/snapRAID.warnCount" + export SCRUB_COUNT_FILE="\$TEMP_DIR/snapRAID.scrubCount" + + # If user specified a config, use it + if [ "\$1" ] && [ -f "\$1" ]; then + exec ${pkgs.bash}/bin/bash $out/share/snapraid-aio/snapraid-aio-script.sh "\$@" + exit 0 + fi + + # Otherwise use the default config + exec ${pkgs.bash}/bin/bash $out/share/snapraid-aio/snapraid-aio-script.sh "\$DEFAULT_CONFIG" "\$@" + EOF + chmod +x $out/bin/snapraid-aio + + # Still use wrapProgram as a 4th layer of protection + wrapProgram $out/share/snapraid-aio/snapraid-aio-script.sh \ + --prefix PATH : ${pkgs.lib.makeBinPath dependencies} + ''; + + meta = with pkgs.lib; { + description = "All-in-one SnapRAID helper script"; + homepage = "https://github.com/auanasgheps/snapraid-aio-script"; + license = licenses.gpl3; + platforms = platforms.linux; + }; + }; + + }; + } + ) + // { + # NixOS module for system-wide installation + nixosModules.default = + { + config, + lib, + pkgs, + ... + }: + with lib; + let + cfg = config.services.snapraid-aio; + in + { + options.services.snapraid-aio = { + enable = mkEnableOption "snapraid-aio script"; + + configFile = mkOption { + type = types.nullOr types.path; + default = null; + description = "Path to custom snapraid-aio configuration file"; + }; + + schedule = mkOption { + type = types.str; + default = "daily"; + description = "Systemd calendar expression for when to run snapraid-aio"; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ self.packages.${pkgs.system}.default ]; + + systemd.services.snapraid-aio = { + description = "SnapRAID maintenance with snapraid-aio"; + serviceConfig = { + Type = "oneshot"; + ExecStart = + if cfg.configFile != null then + "${self.packages.${pkgs.system}.default}/bin/snapraid-aio ${cfg.configFile}" + else + "${self.packages.${pkgs.system}.default}/bin/snapraid-aio"; + }; + }; + + systemd.timers.snapraid-aio = { + description = "Run snapraid-aio on schedule"; + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = cfg.schedule; + Persistent = true; + }; + }; + }; + }; + + # Home-manager module + homeManagerModules.default = + { + config, + lib, + pkgs, + ... + }: + with lib; + let + cfg = config.services.snapraid-aio; + in + { + options.services.snapraid-aio = { + enable = mkEnableOption "snapraid-aio script"; + + configFile = mkOption { + type = types.nullOr types.path; + default = null; + description = "Path to custom snapraid-aio configuration file"; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ self.packages.${pkgs.system}.default ]; + + # For home-manager, we'll add a systemd user service instead + systemd.user.services.snapraid-aio = { + Unit = { + Description = "SnapRAID maintenance with snapraid-aio"; + }; + + Service = { + Type = "oneshot"; + ExecStart = + if cfg.configFile != null then + "${self.packages.${pkgs.system}.default}/bin/snapraid-aio ${cfg.configFile}" + else + "${self.packages.${pkgs.system}.default}/bin/snapraid-aio"; + }; + }; + + systemd.user.timers.snapraid-aio = { + Unit = { + Description = "Run snapraid-aio daily"; + }; + + Timer = { + OnCalendar = "daily"; + Persistent = true; + }; + + Install = { + WantedBy = [ "timers.target" ]; + }; + }; + }; + }; + }; +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..e69de29