add seed timer & re-org

This commit is contained in:
Sebastian Cabrera 2026-06-25 10:35:11 -04:00
parent a3cd2f0fdd
commit 563ad690c2
Signed by: okseby
GPG key ID: 2DDBFDEE356CF3DE
9 changed files with 131 additions and 0 deletions

48
scripts/bash/adduser.sh Executable file
View file

@ -0,0 +1,48 @@
#!/usr/bin/env bash
PASSWD_FILE="/etc/squid/passwd"
# Ensure htpasswd is installed
if ! command -v htpasswd &>/dev/null; then
echo "❌ 'htpasswd' not found. Please install apache2-utils (Debian/Ubuntu) or httpd-tools (RHEL/CentOS)."
exit 1
fi
# Ensure script is run as root
if [[ $EUID -ne 0 ]]; then
echo "❌ This script must be run as root."
exit 1
fi
# Prompt for username
read -rp "👤 Enter Squid proxy username: " username
if [[ -z "$username" ]]; then
echo "❌ Username cannot be empty."
exit 1
fi
# Create the password file only if it doesn't exist
if [[ ! -f "$PASSWD_FILE" ]]; then
echo "🔧 Creating new password file at $PASSWD_FILE"
htpasswd -c "$PASSWD_FILE" "$username"
else
# Check if user exists
if grep -q "^$username:" "$PASSWD_FILE"; then
echo "⚠️ User '$username' already exists."
read -rp "🔄 Update password? (y/N): " answer
if [[ "$answer" =~ ^[Yy]$ ]]; then
htpasswd "$PASSWD_FILE" "$username"
else
echo "❌ Aborted."
exit 1
fi
else
htpasswd "$PASSWD_FILE" "$username"
fi
fi
# Fix permissions
chmod 640 "$PASSWD_FILE"
chown proxy:proxy "$PASSWD_FILE" 2>/dev/null || chown squid:squid "$PASSWD_FILE" 2>/dev/null
echo "✅ User '$username' is set up for Squid."

38
scripts/bash/dock.sh Executable file
View file

@ -0,0 +1,38 @@
#!/usr/bin/env bash
# Function to check dock size
check_dock() {
echo "Current Dock tile size:"
defaults read com.apple.dock tilesize
}
# Function to reset dock
reset_dock() {
echo "Resetting Dock to default settings..."
defaults delete com.apple.dock tilesize
killall Dock
echo "Dock has been reset and restarted."
}
# Show usage if no arguments provided
if [ $# -eq 0 ]; then
echo "Usage: $0 [check|reset]"
echo " check - Show current Dock tile size"
echo " reset - Reset Dock to default settings"
exit 1
fi
# Process command line arguments
case "$1" in
"check")
check_dock
;;
"reset")
reset_dock
;;
*)
echo "Invalid option: $1"
echo "Usage: $0 [check|reset]"
exit 1
;;
esac

118
scripts/bash/movefiles.sh Executable file
View file

@ -0,0 +1,118 @@
#!/usr/bin/env bash
# Default values
VERBOSE=false
INCLUDE_PART=false
# Function to display usage
usage() {
echo "Usage: $0 [options] <search_word> <source_directory> <destination_directory>"
echo "Options:"
echo " -v, --verbose Show detailed output"
echo " -p, --include-part Include files ending in .part (excluded by default)"
echo " -h, --help Show this help message"
exit 1
}
# Parse command line options
while [[ $# -gt 0 ]]; do
case $1 in
-v|--verbose)
VERBOSE=true
shift
;;
-p|--include-part)
INCLUDE_PART=true
shift
;;
-h|--help)
usage
;;
*)
break
;;
esac
done
# Check if we have exactly 3 arguments after options
if [ "$#" -ne 3 ]; then
usage
fi
SEARCH_WORD=$1
SOURCE_DIR=$2
DEST_DIR=$3
# Validate search word
if [ -z "$SEARCH_WORD" ]; then
echo "Error: Search word cannot be empty"
exit 1
fi
# Ensure source directory exists
if [ ! -d "$SOURCE_DIR" ]; then
echo "Error: Source directory '$SOURCE_DIR' does not exist."
exit 1
fi
# Initialize counter
moved_count=0
# Function to process files
process_files() {
local find_cmd="find \"$SOURCE_DIR\" -maxdepth 1 -type f -iname \"*$SEARCH_WORD*\""
# Exclude .part files and macOS resource fork files by default
if [ "$INCLUDE_PART" = false ]; then
find_cmd="$find_cmd -not -name \"*.part\""
fi
find_cmd="$find_cmd -not -name \"._*\""
# First, show what would be moved
echo "The following files would be moved:"
eval "$find_cmd"
# Count files that would be moved
local file_count=$(eval "$find_cmd" | wc -l)
if [ "$file_count" -eq 0 ]; then
echo "No matching files found."
exit 0
fi
# Show what actions will be taken
echo
if [ ! -d "$DEST_DIR" ]; then
echo "The destination directory '$DEST_DIR' will be created."
fi
echo "Files will be moved to: '$DEST_DIR'"
# Prompt for confirmation
echo -n "Do you want to proceed? (y/n): "
read -r response
if [[ "$response" =~ ^[Yy]$ ]]; then
# Create destination directory if needed
if [ ! -d "$DEST_DIR" ]; then
mkdir -p "$DEST_DIR"
fi
while IFS= read -r file; do
if [ "$VERBOSE" = true ]; then
echo "Moving: $file"
fi
if mv "$file" "$DEST_DIR"; then
((moved_count++))
else
echo "Error: Failed to move '$file'" >&2
fi
done < <(eval "$find_cmd")
echo "Operation completed. $moved_count file(s) moved to '$DEST_DIR'"
else
echo "Operation cancelled."
fi
}
# Execute the move operation
process_files

26
scripts/bash/rclone-sync.sh Executable file
View file

@ -0,0 +1,26 @@
#!/usr/bin/env bash
# Set timezone to US Eastern (handles both EST and EDT correctly)
export TZ="America/New_York"
# Define source and destination
SOURCE="$HOME/files/media"
DEST="goji-hetzner:"
# Create timestamped log file
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
LOGFILE="$HOME/logs/rclone-sync-$TIMESTAMP.log"
LOCKFILE="/tmp/rclone-sync.lock"
exec 9>"$LOCKFILE"
if ! flock -n 9; then
echo "rclone sync is already running. exiting...." | tee "$LOGFILE" >&2
exit 1
fi
# Run rclone and log output to both screen and file using tee (no --log-file!)
{
echo "=== rclone sync started at $(date) ==="
/usr/bin/rclone sync "$SOURCE" "$DEST" --log-level=INFO
echo "=== rclone sync finished at $(date) ==="
} 2>&1 | tee "$LOGFILE"

View file

@ -0,0 +1,14 @@
#!/usr/bin/env bash
# Check if the Metal HUD is currently enabled
MTL_STATUS=$(/bin/launchctl getenv MTL_HUD_ENABLED 2>/dev/null)
if [ "$MTL_STATUS" = "1" ]; then
# If enabled, disable it
/bin/launchctl unsetenv MTL_HUD_ENABLED
echo "Metal HUD disabled"
else
# If disabled, enable it
/bin/launchctl setenv MTL_HUD_ENABLED 1
echo "Metal HUD enabled"
fi

122
scripts/bash/toggle-ota.sh Executable file
View file

@ -0,0 +1,122 @@
#!/usr/bin/env bash
# toggle_apple_updates.sh
# Toggles Apple OTA update domains in /etc/hosts between blocked and unblocked.
HOSTS_FILE="/etc/hosts"
APPLE_DOMAINS=(
"swscan.apple.com"
"swdownload.apple.com"
"swcdn.apple.com"
"swdist.apple.com"
"appldnld.apple.com"
"mesu.apple.com"
"gdmf.apple.com"
)
BLOCK_IP="0.0.0.0"
SECTION_COMMENT="# Block OTA"
# ── Colours ──────────────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
RESET='\033[0m'
# ── Banner ────────────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}+----------------------------------------------+${RESET}"
echo -e "${BOLD}| Apple OTA Update Toggle Utility |${RESET}"
echo -e "${BOLD}+----------------------------------------------+${RESET}"
echo ""
# ── Root warning ──────────────────────────────────────────────────────────────
echo -e "${YELLOW}⚠ WARNING: This script modifies ${HOSTS_FILE}.${RESET}"
echo -e "${YELLOW} Root (administrator) privileges are required.${RESET}"
echo ""
# ── Authenticate via sudo ─────────────────────────────────────────────────────
echo -e "${CYAN}Please enter your password to continue:${RESET}"
sudo -v 2>/dev/null
if [[ $? -ne 0 ]]; then
echo -e "${RED}✖ Authentication failed or was cancelled. Exiting.${RESET}"
exit 1
fi
echo ""
# ── Detect current state ──────────────────────────────────────────────────────
# Check if the first domain is currently blocked (present and uncommented)
FIRST_DOMAIN="${APPLE_DOMAINS[0]}"
if sudo grep -qE "^${BLOCK_IP}[[:space:]]+${FIRST_DOMAIN}" "${HOSTS_FILE}"; then
CURRENT_STATE="blocked"
else
CURRENT_STATE="unblocked"
fi
CURRENT_STATE_UPPER=$(echo "${CURRENT_STATE}" | tr '[:lower:]' '[:upper:]')
echo -e " Current state: ${BOLD}Apple updates are ${CURRENT_STATE_UPPER}${RESET}"
echo ""
# ── Toggle ────────────────────────────────────────────────────────────────────
if [[ "${CURRENT_STATE}" == "blocked" ]]; then
# ── UNBLOCK: comment out the block section ────────────────────────────────
echo -e "${CYAN}→ Unblocking Apple update domains...${RESET}"
# Comment out the section header and each domain line
sudo sed -i '.bak' "s|^${SECTION_COMMENT}$|#${SECTION_COMMENT}|g" "${HOSTS_FILE}"
for domain in "${APPLE_DOMAINS[@]}"; do
sudo sed -i '.bak' "s|^${BLOCK_IP}[[:space:]][[:space:]]*${domain}|# ${BLOCK_IP} ${domain}|g" "${HOSTS_FILE}"
done
NEW_STATE="UNBLOCKED"
STATE_COLOR="${GREEN}"
STATE_MSG="Apple software updates are now ${GREEN}${BOLD}ENABLED${RESET}."
STATE_DETAIL="Your Mac can reach Apple's update servers normally."
else
# ── BLOCK: uncomment or add the block section ─────────────────────────────
echo -e "${CYAN}→ Blocking Apple update domains...${RESET}"
# Uncomment lines that were previously commented out by this script
sudo sed -i '.bak' "s|^#${SECTION_COMMENT}$|${SECTION_COMMENT}|g" "${HOSTS_FILE}"
for domain in "${APPLE_DOMAINS[@]}"; do
# If the commented-out version exists, uncomment it
if sudo grep -qE "^#[[:space:]]*${BLOCK_IP}[[:space:]]+${domain}" "${HOSTS_FILE}"; then
sudo sed -i '.bak' "s|^#[[:space:]]*${BLOCK_IP}[[:space:]][[:space:]]*${domain}|${BLOCK_IP} ${domain}|g" "${HOSTS_FILE}"
# If the domain isn't present at all, append the block section
elif ! sudo grep -qE "${domain}" "${HOSTS_FILE}"; then
# Append section header if it doesn't exist
if ! sudo grep -q "^${SECTION_COMMENT}$" "${HOSTS_FILE}"; then
echo "" | sudo tee -a "${HOSTS_FILE}" > /dev/null
echo "${SECTION_COMMENT}" | sudo tee -a "${HOSTS_FILE}" > /dev/null
fi
echo "${BLOCK_IP} ${domain}" | sudo tee -a "${HOSTS_FILE}" > /dev/null
fi
done
NEW_STATE="BLOCKED"
STATE_COLOR="${RED}"
STATE_MSG="Apple software updates are now ${RED}${BOLD}BLOCKED${RESET}."
STATE_DETAIL="Your Mac cannot reach Apple's update servers."
fi
# ── Result ────────────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}+----------------------------------------------+${RESET}"
printf "${BOLD}|${RESET} New state: ${STATE_COLOR}%-33s${RESET}${BOLD}|${RESET}\n" "${NEW_STATE}"
echo -e "${BOLD}+----------------------------------------------+${RESET}"
echo ""
echo -e " ${STATE_MSG}"
echo -e " ${STATE_DETAIL}"
echo ""
echo -e " Domains affected:"
for domain in "${APPLE_DOMAINS[@]}"; do
echo -e " ${STATE_COLOR}${RESET} ${domain}"
done
echo ""
echo -e " A backup of your previous hosts file was saved as:"
echo -e " ${BOLD}${HOSTS_FILE}.bak${RESET}"
echo ""

View file

@ -0,0 +1,100 @@
#!/usr/bin/env bash
set -euo pipefail
# ── helpers ────────────────────────────────────────────────────────────────────
die() { echo "Error: $*" >&2; exit 1; }
# Returns the latest vX.Y.Z tag for a given X.Y prefix (or overall latest if no prefix)
fetch_latest_version() {
local prefix="$1" # e.g. "11.0" or "" for absolute latest
local tags
tags=$(curl -fsSL \
"https://codeberg.org/api/v1/repos/forgejo/forgejo/tags?limit=50" \
2>/dev/null) || die "Could not reach Codeberg API — check your connection."
# Extract tag names, filter to release tags (vX.Y.Z, no pre-release suffix)
local versions
versions=$(echo "$tags" | grep -oP '"name"\s*:\s*"\Kv[0-9]+\.[0-9]+\.[0-9]+"' \
| tr -d '"' | sort -V)
if [[ -z "$prefix" ]]; then
echo "$versions" | tail -1
else
echo "$versions" | grep "^v${prefix}\." | tail -1
fi
}
# ── detect architecture ────────────────────────────────────────────────────────
case "$(uname -m)" in
x86_64) ARCH="amd64" ;;
aarch64) ARCH="arm64" ;;
armv7l) ARCH="arm-6" ;;
*) die "Unsupported architecture: $(uname -m)" ;;
esac
# ── version prompt ─────────────────────────────────────────────────────────────
echo "Fetching latest Forgejo release…"
LATEST_OVERALL=$(fetch_latest_version "")
LATEST_OVERALL="${LATEST_OVERALL#v}" # strip leading 'v'
echo
echo "Latest available release: ${LATEST_OVERALL}"
echo
read -rp "Version to install [MAJOR.MINOR or MAJOR.MINOR.PATCH, Enter = ${LATEST_OVERALL}]: " INPUT
INPUT="${INPUT:-$LATEST_OVERALL}"
# Normalise: strip a leading 'v' if the user typed one
INPUT="${INPUT#v}"
# Determine if the user gave a full version (X.Y.Z) or a partial one (X.Y)
if [[ "$INPUT" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
# Full version supplied — use as-is
VERSION="$INPUT"
elif [[ "$INPUT" =~ ^[0-9]+\.[0-9]+$ ]]; then
# Partial (X.Y) — resolve the latest patch on that line
echo "Resolving latest patch for ${INPUT}.x…"
RESOLVED=$(fetch_latest_version "$INPUT")
[[ -z "$RESOLVED" ]] && die "No releases found for ${INPUT}.x"
VERSION="${RESOLVED#v}"
echo "→ Using ${VERSION}"
else
die "Unrecognised version format '${INPUT}'. Use X.Y or X.Y.Z"
fi
# ── confirm ────────────────────────────────────────────────────────────────────
BINARY="forgejo-${VERSION}-linux-${ARCH}"
echo
echo " Version : ${VERSION}"
echo " Binary : ${BINARY}"
echo " Arch : ${ARCH}"
echo
read -rp "Proceed with installation? [Y/n]: " CONFIRM
CONFIRM="${CONFIRM:-Y}"
[[ "$CONFIRM" =~ ^[Yy]$ ]] || { echo "Aborted."; exit 0; }
# ── download & install ─────────────────────────────────────────────────────────
URL="https://codeberg.org/forgejo/forgejo/releases/download/v${VERSION}/${BINARY}"
echo
echo "Downloading ${URL}"
wget --show-progress -q "$URL" || die "Download failed — is v${VERSION} a valid release?"
chmod +x "$BINARY"
echo "Stopping forgejo…"
systemctl stop forgejo
echo "Installing binary…"
cp "$BINARY" /usr/local/bin/forgejo
rm -f "$BINARY" # clean up the downloaded file
echo "Starting forgejo…"
systemctl start forgejo
echo
echo "Done — Forgejo ${VERSION} is running."