#!/bin/bash # Pi-Kit DietPi image prep script # Cleans host-unique data, logs, caches, and temp files per pikit-prep-spec. set -euo pipefail status() { printf '[%s] %s\n' "$1" "$2"; } clean_logs_dir() { local dir="$1" pattern="${2:-*}" if [ -d "$dir" ]; then find "$dir" -type f -name "$pattern" -print -delete 2>/dev/null | sed 's/^/[CLEANED] /' || true status CLEANED "logs $pattern in $dir" else status SKIP "$dir (missing)" fi } truncate_file() { local file="$1" if [ -e "$file" ]; then :> "$file" && status CLEANED "truncated $file" || status FAIL "truncate $file" else status SKIP "$file (missing)" fi } clean_file() { local path="$1" if [ -e "$path" ]; then rm -f "$path" && status CLEANED "$path" || status FAIL "$path" else status SKIP "$path (missing)" fi } clean_dir_files() { local dir="$1" pattern="$2" if [ -d "$dir" ]; then find "$dir" -type f -name "$pattern" -print -delete 2>/dev/null | sed 's/^/[CLEANED] /' || true status CLEANED "files $pattern in $dir" else status SKIP "$dir (missing)" fi } truncate_dir() { local dir="$1" if [ -d "$dir" ]; then # keep systemd-private dirs intact while services run find "$dir" -mindepth 1 -maxdepth 1 ! -path "$dir/systemd-private-*" -exec rm -rf {} + 2>/dev/null status CLEANED "$dir" else status SKIP "$dir (missing)" fi } clean_backups() { local dir="$1" if [ -d "$dir" ]; then find "$dir" -type f \( -name '*~' -o -name '*.bak*' -o -name '*.orig*' \) -print -delete 2>/dev/null | sed 's/^/[CLEANED] /' || true status CLEANED "backup/editor files in $dir" else status SKIP "$dir (missing)" fi } # --- Identity --- # Keep machine-id file present but empty so systemd regenerates cleanly on next boot. truncate -s 0 /etc/machine-id && status CLEANED /etc/machine-id || status FAIL /etc/machine-id mkdir -p /var/lib/dbus || true rm -f /var/lib/dbus/machine-id ln -s /etc/machine-id /var/lib/dbus/machine-id && status CLEANED "/var/lib/dbus/machine-id -> /etc/machine-id" || status FAIL "/var/lib/dbus/machine-id" clean_file /var/lib/systemd/random-seed # --- SSH host keys --- if ls /etc/ssh/ssh_host_* >/dev/null 2>&1; then rm -f /etc/ssh/ssh_host_* && status CLEANED "SSH host keys" || status FAIL "SSH host keys" else status SKIP "SSH host keys (none)" fi # --- SSH client traces --- :> /root/.ssh/known_hosts 2>/dev/null && status CLEANED "/root/.ssh/known_hosts" || status SKIP "/root/.ssh/known_hosts" :> /home/dietpi/.ssh/known_hosts 2>/dev/null && status CLEANED "/home/dietpi/.ssh/known_hosts" || status SKIP "/home/dietpi/.ssh/known_hosts" :> /home/dietpi/.ssh/authorized_keys 2>/dev/null && status CLEANED "/home/dietpi/.ssh/authorized_keys" || status SKIP "/home/dietpi/.ssh/authorized_keys" :> /root/.ssh/authorized_keys 2>/dev/null && status CLEANED "/root/.ssh/authorized_keys" || status SKIP "/root/.ssh/authorized_keys" # --- Shell history --- :> /root/.bash_history 2>/dev/null && status CLEANED "/root/.bash_history" || status SKIP "/root/.bash_history" :> /home/dietpi/.bash_history 2>/dev/null && status CLEANED "/home/dietpi/.bash_history" || status SKIP "/home/dietpi/.bash_history" # --- Ready flag --- clean_file /var/run/pikit-ready # --- Backup/editor cruft --- clean_backups /var/www/pikit-web clean_backups /usr/local/bin # --- Logs --- clean_dir_files /var/log "*" clean_dir_files /var/log/nginx "*" # systemd journal (persistent) if present if [ -d /var/log/journal ]; then find /var/log/journal -type f -print -delete 2>/dev/null | sed 's/^/[CLEANED] /' || true status CLEANED "/var/log/journal" else status SKIP "/var/log/journal (missing)" fi # crash dumps if [ -d /var/crash ]; then find /var/crash -type f -print -delete 2>/dev/null | sed 's/^/[CLEANED] /' || true status CLEANED "/var/crash" else status SKIP "/var/crash (missing)" fi # Service-specific logs (best-effort, skip if absent) if command -v pihole >/dev/null 2>&1; then pihole -f >/dev/null 2>&1 && status CLEANED "pihole logs via pihole -f" || status FAIL "pihole -f" clean_logs_dir /var/log/pihole '*' clean_file /etc/pihole/pihole-FTL.db # resets long-term query history; leave gravity.db untouched fi if [ -x /opt/AdGuardHome/AdGuardHome ]; then clean_logs_dir /var/opt/AdGuardHome/data/logs '*' clean_file /opt/AdGuardHome/data/querylog.db fi if command -v ufw >/dev/null 2>&1; then truncate_file /var/log/ufw.log fi if command -v fail2ban-client >/dev/null 2>&1; then truncate_file /var/log/fail2ban.log fi clean_logs_dir /var/log/unbound '*' clean_logs_dir /var/log/dnsmasq '*' clean_logs_dir /var/log/powerdns '*' clean_logs_dir /var/lib/technitium-dns/Logs '*' clean_logs_dir /var/log/jellyfin '*' clean_logs_dir /var/lib/jellyfin/log '*' clean_logs_dir /var/log/jellyseerr '*' clean_logs_dir /opt/jellyseerr/logs '*' clean_logs_dir /var/log/ustreamer '*' clean_logs_dir /var/log/gitea '*' clean_logs_dir /var/lib/gitea/log '*' clean_logs_dir /var/log/fmd '*' clean_logs_dir /var/log/uptime-kuma '*' clean_logs_dir /opt/uptime-kuma/data/logs '*' clean_logs_dir /var/log/romm '*' clean_logs_dir /var/log/privatebin '*' clean_logs_dir /var/log/crafty '*' clean_logs_dir /var/log/rustdesk '*' clean_logs_dir /var/log/memos '*' clean_logs_dir /var/lib/memos/logs '*' clean_logs_dir /var/log/traccar '*' clean_logs_dir /var/log/webmin '*' clean_logs_dir /var/log/homarr '*' clean_logs_dir /var/log/termix '*' clean_logs_dir /var/log/syncthing '*' clean_logs_dir /var/log/netdata '*' clean_logs_dir /var/lib/netdata/dbengine '*' clean_logs_dir /var/log/AdGuardHome '*' # DB / metrics / web stacks clean_logs_dir /var/log/mysql '*' clean_logs_dir /var/log/mariadb '*' clean_logs_dir /var/log/postgresql '*' truncate_file /var/log/redis/redis-server.log clean_logs_dir /var/log/influxdb '*' clean_logs_dir /var/log/prometheus '*' clean_logs_dir /var/log/grafana '*' clean_logs_dir /var/log/loki '*' clean_logs_dir /var/log/caddy '*' clean_logs_dir /var/log/apache2 '*' clean_logs_dir /var/log/lighttpd '*' clean_logs_dir /var/log/samba '*' clean_logs_dir /var/log/mosquitto '*' clean_logs_dir /var/log/openvpn '*' clean_logs_dir /var/log/wireguard '*' clean_logs_dir /var/log/node-red '*' truncate_file /var/log/nodered-install.log clean_logs_dir /var/log/transmission-daemon '*' clean_logs_dir /var/log/deluge '*' clean_logs_dir /var/log/qbittorrent '*' clean_logs_dir /var/log/paperless-ngx '*' clean_logs_dir /var/log/photoprism '*' clean_logs_dir /var/log/navidrome '*' clean_logs_dir /var/log/minio '*' clean_logs_dir /var/log/nzbget '*' clean_logs_dir /var/log/sabnzbd '*' clean_logs_dir /var/log/jackett '*' clean_logs_dir /var/log/radarr '*' clean_logs_dir /var/log/sonarr '*' clean_logs_dir /var/log/lidarr '*' clean_logs_dir /var/log/prowlarr '*' clean_logs_dir /var/log/bazarr '*' clean_logs_dir /var/log/overseerr '*' clean_logs_dir /var/log/emby-server '*' # App-specific logs stored with app data (truncate, keep structure) truncate_file /home/homeassistant/.homeassistant/home-assistant.log clean_logs_dir /home/homeassistant/.homeassistant/logs '*' truncate_file /var/www/nextcloud/data/nextcloud.log truncate_file /var/www/owncloud/data/owncloud.log # Docker container JSON logs if [ -d /var/lib/docker/containers ]; then find /var/lib/docker/containers -type f -name '*-json.log' -print0 2>/dev/null | while IFS= read -r -d '' f; do :> "$f" && status CLEANED "truncated $f" || status FAIL "truncate $f" done else status SKIP "/var/lib/docker/containers (missing)" fi clean_file /var/log/wtmp.db clean_dir_files /var/tmp/dietpi/logs "*" # --- Caches --- apt-get clean >/dev/null 2>&1 && status CLEANED "apt cache" || status FAIL "apt cache" rm -rf /var/lib/apt/lists/* /var/cache/apt/* 2>/dev/null && status CLEANED "apt lists/cache" || status FAIL "apt lists/cache" find /var/cache/debconf -type f -print -delete 2>/dev/null | sed 's/^/[CLEANED] /' || true status CLEANED "/var/cache/debconf files" # --- Temp directories --- truncate_dir /tmp truncate_dir /var/tmp # --- DHCP leases --- clean_file /var/lib/dhcp/dhclient.eth0.leases # --- Nginx caches --- if [ -d /var/lib/nginx ]; then find /var/lib/nginx -mindepth 1 -maxdepth 1 -type d -exec rm -rf {} + 2>/dev/null status CLEANED "/var/lib/nginx/*" else status SKIP "/var/lib/nginx" fi status DONE "Prep complete" # Self-delete to avoid leaving the prep tool on the image. rm -- "$0"