initial commit

This commit is contained in:
mr0xb 2026-07-13 15:10:55 -04:00
commit f1374f54c4
46 changed files with 4121 additions and 0 deletions

View file

@ -0,0 +1,90 @@
#!/usr/bin/env bash
set -Eeuo pipefail
usage() {
cat <<'USAGE'
Usage: fedora-backup-home DESTINATION [options]
Rsync your home folder to an external drive or mounted network share.
Dry-run is the default. Add --run when the preview looks right.
Examples:
fedora-backup-home /run/media/$USER/BackupDrive
fedora-backup-home /run/media/$USER/BackupDrive --run
fedora-backup-home /mnt/nas/backups --run --delete
Options:
--run Actually copy files. Without this, rsync runs in dry-run mode.
--delete Delete files in the backup that no longer exist in your home folder.
-h, --help Show this help.
USAGE
}
log() { printf '\n\033[1m==> %s\033[0m\n' "$*"; }
die() { printf '\033[31mERROR:\033[0m %s\n' "$*" >&2; exit 1; }
[[ $# -gt 0 ]] || { usage; exit 1; }
DEST_ROOT=""
RUN=false
DELETE=false
while [[ $# -gt 0 ]]; do
case "$1" in
--run) RUN=true ;;
--delete) DELETE=true ;;
-h|--help) usage; exit 0 ;;
-*) die "Unknown option: $1" ;;
*)
if [[ -z "$DEST_ROOT" ]]; then DEST_ROOT="$1"; else die "Unexpected extra argument: $1"; fi
;;
esac
shift
done
[[ -n "$DEST_ROOT" ]] || die "Missing DESTINATION."
command -v rsync >/dev/null 2>&1 || die "rsync is not installed. Run: sudo dnf5 install rsync"
[[ -d "$DEST_ROOT" ]] || die "Destination does not exist: $DEST_ROOT"
HOST="$(hostname -s 2>/dev/null || hostname)"
DEST="$DEST_ROOT/${HOST}-${USER}-home"
mkdir -p "$DEST"
# Prevent accidental recursive backup if destination is inside $HOME.
case "$(realpath -m "$DEST")" in
"$(realpath -m "$HOME")"/*) die "Destination is inside your home folder; choose an external path." ;;
esac
RSYNC_OPTS=(-aAXH --human-readable --info=progress2)
[[ "$RUN" == "false" ]] && RSYNC_OPTS+=(--dry-run --itemize-changes)
[[ "$DELETE" == "true" ]] && RSYNC_OPTS+=(--delete)
EXCLUDES=(
--exclude='/.cache/'
--exclude='/.local/share/Trash/'
--exclude='/.var/app/*/cache/'
--exclude='/Downloads/*.iso'
--exclude='/Downloads/*.img'
--exclude='/Downloads/*.qcow2'
--exclude='/.npm/_cacache/'
--exclude='/.cargo/registry/'
--exclude='/.cargo/git/'
--exclude='/.gradle/caches/'
--exclude='/**/node_modules/'
--exclude='/**/.venv/'
)
log "Backing up $HOME to $DEST"
if [[ "$RUN" == "false" ]]; then
printf 'Mode: DRY RUN. Add --run to actually copy files.\n'
else
printf 'Mode: REAL RUN.\n'
fi
[[ "$DELETE" == "true" ]] && printf 'Delete mode: enabled.\n'
rsync "${RSYNC_OPTS[@]}" "${EXCLUDES[@]}" "$HOME/" "$DEST/"
log "Done"
if [[ "$RUN" == "false" ]]; then
printf 'Review the dry-run above, then rerun with --run when ready.\n'
fi

View file

@ -0,0 +1,82 @@
#!/usr/bin/env bash
set -Eeuo pipefail
usage() {
cat <<'USAGE'
Usage: fedora-clean [options]
Clean common Fedora desktop clutter.
Options:
--aggressive Also clear thumbnails, browser crash dumps, and offer Podman prune.
-y, --yes Accept this script's prompts and pass -y where possible.
-h, --help Show this help.
USAGE
}
log() { printf '\n\033[1m==> %s\033[0m\n' "$*"; }
warn() { printf '\033[33mWARN:\033[0m %s\n' "$*" >&2; }
die() { printf '\033[31mERROR:\033[0m %s\n' "$*" >&2; exit 1; }
have() { command -v "$1" >/dev/null 2>&1; }
confirm() {
local prompt="$1" answer
if [[ "${ASSUME_YES}" == "true" ]]; then return 0; fi
read -r -p "$prompt [y/N] " answer
[[ "$answer" =~ ^[Yy]$ ]]
}
DNF="$(command -v dnf5 || command -v dnf || true)"
[[ -n "$DNF" ]] || die "Could not find dnf5 or dnf."
AGGRESSIVE=false
ASSUME_YES=false
while [[ $# -gt 0 ]]; do
case "$1" in
--aggressive) AGGRESSIVE=true ;;
-y|--yes) ASSUME_YES=true ;;
-h|--help) usage; exit 0 ;;
*) die "Unknown option: $1" ;;
esac
shift
done
YUM_YES=()
[[ "$ASSUME_YES" == "true" ]] && YUM_YES=(-y)
log "Disk usage before cleanup"
df -hT -x tmpfs -x devtmpfs / "$HOME" 2>/dev/null || df -hT -x tmpfs -x devtmpfs
log "Removing unused RPM packages"
sudo "$DNF" autoremove "${YUM_YES[@]}" || warn "DNF autoremove did not complete. Review the output above."
log "Cleaning downloaded DNF packages"
sudo "$DNF" clean packages || warn "DNF clean packages failed."
if have flatpak; then
log "Removing unused Flatpak runtimes"
flatpak uninstall --unused "${YUM_YES[@]}" || warn "Flatpak unused-runtime cleanup did not complete."
fi
if have journalctl; then
log "Current journal disk usage"
journalctl --disk-usage || true
if confirm "Vacuum systemd journal to 14 days?"; then
sudo journalctl --vacuum-time=14d
fi
fi
if [[ "$AGGRESSIVE" == "true" ]]; then
log "Aggressive user-cache cleanup"
if confirm "Clear GNOME thumbnail cache?"; then
rm -rf -- "$HOME/.cache/thumbnails"/* 2>/dev/null || true
fi
if confirm "Clear user crash-report cache under ~/.cache/abrt?"; then
rm -rf -- "$HOME/.cache/abrt"/* 2>/dev/null || true
fi
if have podman && confirm "Prune unused Podman images/containers/networks?"; then
podman system prune -a
fi
fi
log "Disk usage after cleanup"
df -hT -x tmpfs -x devtmpfs / "$HOME" 2>/dev/null || df -hT -x tmpfs -x devtmpfs

View file

@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -Eeuo pipefail
usage() {
cat <<'USAGE'
Usage: fedora-reset-audio
Restart the common Fedora Workstation audio user services:
pipewire, pipewire-pulse, wireplumber
Useful when Bluetooth/audio devices disappear or sound gets weird.
USAGE
}
[[ "${1:-}" == "-h" || "${1:-}" == "--help" ]] && { usage; exit 0; }
printf '\nRestarting audio user services...\n'
systemctl --user restart pipewire pipewire-pulse wireplumber
printf '\nStatus:\n'
systemctl --user --no-pager --full status pipewire pipewire-pulse wireplumber || true

View file

@ -0,0 +1,108 @@
#!/usr/bin/env bash
set -Eeuo pipefail
usage() {
cat <<'USAGE'
Usage: fedora-update [options]
Update Fedora RPM packages, Flatpaks, and firmware.
Options:
--offline Prepare the DNF transaction as an offline update, then ask before rebooting.
--no-flatpak Skip Flatpak updates.
--no-firmware Skip fwupd firmware checks/updates.
-y, --yes Pass -y to DNF/Flatpak where possible and accept prompts from this script.
-h, --help Show this help.
USAGE
}
log() { printf '\n\033[1m==> %s\033[0m\n' "$*"; }
warn() { printf '\033[33mWARN:\033[0m %s\n' "$*" >&2; }
die() { printf '\033[31mERROR:\033[0m %s\n' "$*" >&2; exit 1; }
have() { command -v "$1" >/dev/null 2>&1; }
confirm() {
local prompt="$1" answer
if [[ "${ASSUME_YES}" == "true" ]]; then return 0; fi
read -r -p "$prompt [y/N] " answer
[[ "$answer" =~ ^[Yy]$ ]]
}
DNF="$(command -v dnf5 || command -v dnf || true)"
[[ -n "$DNF" ]] || die "Could not find dnf5 or dnf."
OFFLINE=false
DO_FLATPAK=true
DO_FIRMWARE=true
ASSUME_YES=false
while [[ $# -gt 0 ]]; do
case "$1" in
--offline) OFFLINE=true ;;
--no-flatpak) DO_FLATPAK=false ;;
--no-firmware) DO_FIRMWARE=false ;;
-y|--yes) ASSUME_YES=true ;;
-h|--help) usage; exit 0 ;;
*) die "Unknown option: $1" ;;
esac
shift
done
YUM_YES=()
[[ "$ASSUME_YES" == "true" ]] && YUM_YES=(-y)
log "Refreshing and updating RPM packages with $(basename "$DNF")"
if [[ "$OFFLINE" == "true" ]]; then
sudo "$DNF" upgrade --refresh --offline "${YUM_YES[@]}"
log "DNF offline transaction prepared"
else
sudo "$DNF" upgrade --refresh "${YUM_YES[@]}"
fi
if [[ "$DO_FLATPAK" == "true" ]]; then
if have flatpak; then
log "Updating Flatpaks"
flatpak update "${YUM_YES[@]}"
log "Removing unused Flatpak runtimes"
flatpak uninstall --unused "${YUM_YES[@]}" || true
else
warn "flatpak not found; skipping Flatpak updates."
fi
fi
if [[ "$DO_FIRMWARE" == "true" ]]; then
if have fwupdmgr; then
log "Checking firmware updates with fwupd"
sudo fwupdmgr refresh --force || warn "fwupdmgr refresh failed; continuing."
sudo fwupdmgr get-updates || true
if confirm "Run firmware updates now?"; then
sudo fwupdmgr update || warn "Firmware update command returned a non-zero status."
fi
else
warn "fwupdmgr not found; install fwupd to manage firmware updates."
fi
fi
log "Checking whether a reboot is recommended"
NEEDS_RESTARTING_OUTPUT="$(mktemp)"
set +e
sudo "$DNF" needs-restarting >"$NEEDS_RESTARTING_OUTPUT" 2>&1
status=$?
set -e
if [[ $status -eq 0 ]]; then
printf 'No reboot required according to dnf needs-restarting.\n'
elif grep -qiE 'No such command|unknown command|unrecognized|Unable to resolve|not found' "$NEEDS_RESTARTING_OUTPUT"; then
warn "Could not run '$(basename "$DNF") needs-restarting'. Try: sudo $DNF install dnf5-plugins"
else
cat "$NEEDS_RESTARTING_OUTPUT"
warn "A reboot is recommended."
fi
rm -f "$NEEDS_RESTARTING_OUTPUT"
if [[ "$OFFLINE" == "true" ]]; then
if confirm "Reboot now to run the offline DNF transaction?"; then
sudo "$DNF" offline reboot
else
printf 'Run this later to apply it: sudo %s offline reboot\n' "$DNF"
fi
fi