commit af29737887794a26ade7a71c3a091621c5dfb865 Author: ray Date: Sun Jul 12 10:15:25 2026 -0400 Initial commit: homelab maintenance and automation scripts diff --git a/README.md b/README.md new file mode 100644 index 0000000..1d48a84 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# homelab-scripts + +Collection of maintenance, monitoring, and automation scripts for my self-hosted homelab. + +## Contents + +- **healthcheck.sh** — Quick Docker health check (container status) +- **cleanup.sh** — Docker system cleanup (prune images, containers, volumes) +- **backup-notify.sh** — Backup reminder / notification pattern +- **git-autosave.sh** — Auto-commit and push changes to Gitea + +## Usage + +Scripts are designed to be run manually or via cron jobs. Make them executable: + +```bash +chmod +x *.sh +``` + +## Cron Examples + +``` +# Daily health check +0 8 * * * /home/ray/homelab-scripts/healthcheck.sh + +# Weekly cleanup +0 3 * * 0 /home/ray/homelab-scripts/cleanup.sh + +# Backup reminder +0 20 * * * /home/ray/homelab-scripts/backup-notify.sh +``` diff --git a/backup-notify.sh b/backup-notify.sh new file mode 100755 index 0000000..e03eb85 --- /dev/null +++ b/backup-notify.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Backup reminder — placeholder for triggering backup routines +# Replace with actual backup logic for your services +set -euo pipefail + +LOG_FILE="${HOME}/homelab-scripts/backups.log" + +echo "=== Backup Reminder — $(date) ===" | tee -a "$LOG_FILE" + +# Placeholder — add your backup commands here: +# rsync -a /path/to/data /backup/location/ +# docker exec postgres pg_dump ... +# restic backup ... + +echo "📋 Backup check: review and run backups for critical services" | tee -a "$LOG_FILE" +echo " - Docker volumes" | tee -a "$LOG_FILE" +echo " - Config files in ~/.hermes/" | tee -a "$LOG_FILE" +echo " - Any other important data" | tee -a "$LOG_FILE" +echo "" | tee -a "$LOG_FILE" diff --git a/cleanup.sh b/cleanup.sh new file mode 100755 index 0000000..02107ec --- /dev/null +++ b/cleanup.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Docker system cleanup — prune unused images, containers, volumes, networks +set -euo pipefail + +echo "=== Docker Cleanup — $(date) ===" +echo "" + +echo "Disk usage before cleanup:" +docker system df 2>/dev/null || echo "(Docker not accessible)" +echo "" + +echo "Pruning unused data..." +docker system prune -f --volumes 2>/dev/null || echo "⚠️ Prune failed — is Docker running?" +echo "" + +echo "Disk usage after cleanup:" +docker system df 2>/dev/null || echo "(Docker not accessible)" +echo "" +echo "✅ Cleanup complete" diff --git a/git-autosave.sh b/git-autosave.sh new file mode 100755 index 0000000..0de1f1f --- /dev/null +++ b/git-autosave.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# Auto-save any repos with uncommitted changes to Gitea +# Runs daily via cron — stdout is delivered to Telegram + +set -euo pipefail + +DATE=$(date '+%Y-%m-%d') +LOGFILE="$HOME/.hermes/logs/git-autosave.log" +mkdir -p "$HOME/.hermes/logs" + +REPOS=( + "/mnt/seagate8tb/Websites/ShopProQuote.backup-20260626-2058/spq-v2:main:" + "/mnt/seagate8tb/docker:main:" + "/etc/nginx:main:sudo" + "/home/ray/.hermes:main:" + "/home/ray/homelab-scripts:main:" +) + +SAVED=() +CLEAN=() +ERRORS=() + +for entry in "${REPOS[@]}"; do + DIR="${entry%%:*}" + BRANCH="${entry##*:}" + NAME=$(basename "$DIR") + + if [ ! -d "$DIR/.git" ]; then + echo "[$DATE] SKIP $DIR — no .git" >> "$LOGFILE" + continue + fi + + cd "$DIR" + + if [ -z "$(git status --porcelain 2>/dev/null)" ]; then + echo "[$DATE] CLEAN $NAME" >> "$LOGFILE" + CLEAN+=("$NAME") + continue + fi + + git pull --rebase origin "$BRANCH" 2>/dev/null || true + + git add -A + if git commit -m "auto-save $DATE"; then + if git push origin "$BRANCH" 2>/dev/null; then + echo "[$DATE] SAVED $NAME" >> "$LOGFILE" + SAVED+=("$NAME") + else + echo "[$DATE] PUSH FAILED $NAME" >> "$LOGFILE" + ERRORS+=("$NAME (push failed)") + fi + else + echo "[$DATE] COMMIT FAILED $NAME" >> "$LOGFILE" + ERRORS+=("$NAME (commit failed)") + fi +done + +# Build stdout message for delivery +MSG="" +if [ ${#SAVED[@]} -gt 0 ]; then + MSG="${MSG}✓ Saved: ${SAVED[*]}\n" +fi +if [ ${#CLEAN[@]} -gt 0 ]; then + MSG="${MSG}— Clean: ${CLEAN[*]}\n" +fi +if [ ${#ERRORS[@]} -gt 0 ]; then + MSG="${MSG}✗ Errors: ${ERRORS[*]}\n" +fi + +if [ -n "$MSG" ]; then + echo -e "Gitea auto-save $DATE\n${MSG}" +fi diff --git a/healthcheck.sh b/healthcheck.sh new file mode 100755 index 0000000..60b7a15 --- /dev/null +++ b/healthcheck.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Quick Docker health check — list running containers +set -euo pipefail + +echo "=== Docker Health Check — $(date) ===" +echo "" + +RUNNING=$(docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Image}}' 2>/dev/null) + +if [ -n "$RUNNING" ]; then + echo "$RUNNING" + echo "" + echo "✅ $(docker ps -q 2>/dev/null | wc -l) container(s) running" +else + echo "⚠️ No running containers found (or Docker not accessible)" +fi