diff --git a/README.md b/README.md index 26ac6bda..bd4150c2 100644 --- a/README.md +++ b/README.md @@ -48,12 +48,13 @@ nix develop -c /etc/nixos/git/docs/setup.sh --- # To Do List -* [ ] Steam Deck config - * [ ] Jellyfin +* [x] Steam Deck config + * [x] Jellyfin * [x] Complete bakersfield-rpi4 image * [x] Secrets / Tailscale keys for: * [x] bakersfield-rpi4 * [x] steamdeck +* [ ] Fix sysctl backup script * [ ] 24.05 Updates: * [ ] Re-enable a few things "TODO" * [ ] Add sound to XRDP config diff --git a/nixos/common/software/cli/clean-hm.nix b/nixos/common/software/cli/clean-hm.nix new file mode 100644 index 00000000..6cccaa9b --- /dev/null +++ b/nixos/common/software/cli/clean-hm.nix @@ -0,0 +1,8 @@ +let + clean-hm = pkgs.writeScriptBin "clean-hm" "${builtins.readFile ./scripts/clean-hm.sh}"; +in { + environment.systemPackages = [ + clean-hm + ]; +} + diff --git a/nixos/common/software/cli/scripts/clean-hm.sh b/nixos/common/software/cli/scripts/clean-hm.sh new file mode 100644 index 00000000..55a701f3 --- /dev/null +++ b/nixos/common/software/cli/scripts/clean-hm.sh @@ -0,0 +1,244 @@ +#!/usr/bin/env bash +set -euo pipefail + +## Defaults +keepGensDef=30; keepDaysDef=30 +keepGens=$keepGensDef; keepDays=$keepDaysDef + +## Usage +usage () { + printf "Usage:\n\t ./trim-generations.sh \n\n +(defaults are: Keep-Gens=$keepGensDef Keep-Days=$keepDaysDef Profile=user)\n\n" + printf "If you enter any parameters, you must enter all three, or none to use defaults.\n" + printf "Example:\n\t trim-generations.sh 15 10 home-manager\n" + printf " this will work on the home-manager profile and keep all generations from the\n" + printf "last 10 days, and keep at least 15 generations no matter how old.\n" + printf "\nProfiles available are:\tuser, home-manager, channels, system (root)\n" + printf "\n-h or --help prints this help text." +} + +if [ $# -eq 1 ]; then # if help requested + if [ $1 = "-h" ]; then + usage + exit 1; + fi + if [ $1 = "--help" ]; then + usage + exit 2; + fi + printf "Dont recognise your option exiting..\n\n" + usage + exit 3; + + elif [ $# -eq 0 ]; then # print the defaults + printf "The current defaults are:\n Keep-Gens=$keepGensDef Keep-Days=$keepDaysDef \n\n" + read -p "Keep these defaults? (y/n):" answer + + case "$answer" in + [yY1] ) + printf "Using defaults..\n" + ;; + [nN0] ) printf "ok, doing nothing, exiting..\n" + exit 6; + ;; + * ) printf "%b" "Doing nothing, exiting.." + exit 7; + ;; + esac +fi + +## Handle parameters (and change if root) +if [[ $EUID -ne 0 ]]; then # if not root + profile=$(readlink /home/$USER/.nix-profile) +else + if [ -d /nix/var/nix/profiles/system ]; then # maybe this or the other + profile="/nix/var/nix/profiles/system" + elif [ -d /nix/var/nix/profiles/default ]; then + profile="/nix/var/nix/profiles/default" + else + echo "Cant find profile for root. Exiting" + exit 8 + fi +fi +if (( $# < 1 )); then + printf "Keeping default: $keepGensDef generations OR $keepDaysDef days, whichever is more\n" +elif [[ $# -le 2 ]]; then + printf "\nError: Not enough arguments.\n\n" >&2 + usage + exit 1 +elif (( $# > 4)); then + printf "\nError: Too many arguments.\n\n" >&2 + usage + exit 2 +else + if [ $1 -lt 1 ]; then + printf "using Gen numbers less than 1 not recommended. Setting to min=1\n" + read -p "is that ok? (y/n): " asnwer + #printf "$asnwer" + case "$asnwer" in + [yY1] ) + printf "ok, continuing..\n" + ;; + [nN0] ) + printf "ok, doing nothing, exiting..\n" + exit 6; + ;; + * ) + printf "%b" "Doing nothing, exiting.." + exit 7; + ;; + esac + fi + if [ $2 -lt 0 ]; then + printf "using negative days number not recommended. Setting to min=0\n" + read -p "is that ok? (y/n): " asnwer + + case "$asnwer" in + [yY1] ) + printf "ok, continuing..\n" + ;; + [nN0] ) + printf "ok, doing nothing, exiting..\n" + exit 6; + ;; + * ) + printf "%b" "Doing nothing, exiting.." + exit 7; + ;; + esac + fi + keepGens=$1; keepDays=$2; + (( keepGens < 1 )) && keepGens=1 + (( keepDays < 0 )) && keepDays=0 + if [[ $EUID -ne 0 ]]; then + if [[ $3 == "user" ]] || [[ $3 == "default" ]]; then + profile=$(readlink /home/$USER/.nix-profile) + elif [[ $3 == "home-manager" ]]; then + # home-manager defaults to $XDG_STATE_HOME; otherwise, use + # `home-manager generations` and `nix-store --query --roots + # /nix/store/...` to figure out what reference is keeping the old + # generations alive. + profile="${XDG_STATE_HOME:-$HOME/.local/state}/nix/profiles/home-manager" + elif [[ $3 == "channels" ]]; then + profile="/nix/var/nix/profiles/per-user/$USER/channels" + else + printf "\nError: Do not understand your third argument. Should be one of: (user / home-manager/ channels)\n\n" + usage + exit 3 + fi + else + if [[ $3 == "system" ]]; then + profile="/nix/var/nix/profiles/system" + elif [[ $3 == "user" ]] || [[ $3 == "default" ]]; then + profile="/nix/var/nix/profiles/default" + else + printf "\nError: Do not understand your third argument. Should be one of: (user / system)\n\n" + usage + exit 3 + fi + fi + printf "OK! \t Keep Gens = $keepGens \t Keep Days = $keepDays\n\n" +fi + +printf "Operating on profile: \t $profile\n\n" + +## Runs at the end, to decide whether to delete profiles that match chosen parameters. +choose () { + local default="$1" + local prompt="$2" + local answer + + read -p "$prompt" answer + [ -z "$answer" ] && answer="$default" + + case "$answer" in + [yY1] ) #printf "answered yes!\n" + nix-env --delete-generations -p $profile ${!gens[@]} + exit 0 + ;; + [nN0] ) printf "Ok doing nothing exiting..\n" + exit 6; + ;; + * ) printf "%b" "Unexpected answer '$answer'!" >&2 + exit 7; + ;; + esac +} # end of function choose + +# printf "profile = $profile\n\n" +## Query nix-env for generations list +IFS=$'\n' nixGens=( $(nix-env --list-generations -p $profile | sed 's:^\s*::; s:\s*$::' | tr '\t' ' ' | tr -s ' ') ) +timeNow=$(date +%s) + +## Get info on oldest generation +IFS=' ' read -r -a oldestGenArr <<< "${nixGens[0]}" +oldestGen=${oldestGenArr[0]} +oldestDate=${oldestGenArr[1]} +printf "%-30s %s\n" "oldest generation:" $oldestGen +#oldestDate=${nixGens[0]:3:19} +printf "%-30s %s\n" "oldest generation created:" $oldestDate +oldestTime=$(date -d "$oldestDate" +%s) +oldestElapsedSecs=$((timeNow-oldestTime)) +oldestElapsedMins=$((oldestElapsedSecs/60)) +oldestElapsedHours=$((oldestElapsedMins/60)) +oldestElapsedDays=$((oldestElapsedHours/24)) +printf "%-30s %s\n" "minutes before now:" $oldestElapsedMins +printf "%-30s %s\n" "hours before now:" $oldestElapsedHours +printf "%-30s %s\n\n" "days before now:" $oldestElapsedDays + +## Get info on current generation +for i in "${nixGens[@]}"; do + IFS=' ' read -r -a iGenArr <<< "$i" + genNumber=${iGenArr[0]} + genDate=${iGenArr[1]} + if [[ "$i" =~ current ]]; then + currentGen=$genNumber + printf "%-30s %s\n" "current generation:" $currentGen + currentDate=$genDate + printf "%-30s %s\n" "current generation created:" $currentDate + currentTime=$(date -d "$currentDate" +%s) + currentElapsedSecs=$((timeNow-currentTime)) + currentElapsedMins=$((currentElapsedSecs/60)) + currentElapsedHours=$((currentElapsedMins/60)) + currentElapsedDays=$((currentElapsedHours/24)) + printf "%-30s %s\n" "minutes before now:" $currentElapsedMins + printf "%-30s %s\n" "hours before now:" $currentElapsedHours + printf "%-30s %s\n\n" "days before now:" $currentElapsedDays + fi +done + +## Compare oldest and current generations +timeBetweenOldestAndCurrent=$((currentTime-oldestTime)) +elapsedDays=$((timeBetweenOldestAndCurrent/60/60/24)) +generationsDiff=$((currentGen-oldestGen)) + +## Figure out what we should do, based on generations and options +if [[ elapsedDays -le keepDays ]]; then + printf "All generations are no more than $keepDays days older than current generation. \nOldest gen days difference from current gen: $elapsedDays \n\n\tNothing to do!\n" + exit 4; +elif [[ generationsDiff -lt keepGens ]]; then + printf "Oldest generation ($oldestGen) is only $generationsDiff generations behind current ($currentGen). \n\n\t Nothing to do!\n" + exit 5; +else + printf "\tSomething to do...\n" + declare -a gens + for i in "${nixGens[@]}"; do + IFS=' ' read -r -a iGenArr <<< "$i" + genNumber=${iGenArr[0]} + genDiff=$((currentGen-genNumber)) + genDate=${iGenArr[1]} + genTime=$(date -d "$genDate" +%s) + elapsedSecs=$((timeNow-genTime)) + genDaysOld=$((elapsedSecs/60/60/24)) + if [[ genDaysOld -gt keepDays ]] && [[ genDiff -ge keepGens ]]; then + gens["$genNumber"]="$genDate, $genDaysOld day(s) old" + fi + done + printf "\nFound the following generation(s) to delete:\n" + for K in "${!gens[@]}"; do + printf "generation $K \t ${gens[$K]}\n" + done + printf "\n" + choose "y" "Do you want to delete these? [Y/n]: " +fi + diff --git a/nixos/hosts/backups-rpi4/backup-script.nix b/nixos/hosts/backups-rpi4/backup-script.nix index e0d8e94a..e6b143e0 100644 --- a/nixos/hosts/backups-rpi4/backup-script.nix +++ b/nixos/hosts/backups-rpi4/backup-script.nix @@ -16,3 +16,4 @@ in { sopsFile = ../../../secrets/hosts/backups-rpi4.yaml; }; } +