#!/bin/bash # audit-server.sh — Comprehensive server inventory script # Runs remotely via SSH on each Hetzner server. # Saves output to ~/audit-server-output.txt for collection. set -euo pipefail OUTPUT="/tmp/audit-$(hostname)-$(date +%Y%m%d).txt" exec > "$OUTPUT" 2>&1 echo "=== SYSTEM INFO ===" echo "Hostname: $(hostname)" echo "OS: $(cat /etc/os-release 2>/dev/null | head -3)" echo "Kernel: $(uname -r)" echo "Uptime: $(uptime -p)" echo "CPU: $(nproc) cores" echo "RAM: $(free -h | grep Mem | awk '{print $2}')" echo "Disk: $(df -h / | tail -1 | awk '{print $3 " used / " $2 " (" $5 ")" }')" echo "" echo "=== DOCKER CONTAINERS ===" if command -v docker &>/dev/null; then docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}" || echo "Docker not running" else echo "No Docker installed" fi echo "" echo "=== LISTENING PORTS (TCP) ===" ss -tlnp | grep -v "127.0.0.1\|::1" echo "" echo "=== LISTENING PORTS (UDP) ===" ss -ulnp | grep -v "127.0.0.1\|::1" | head -15 echo "" echo "=== WEB SERVERS ===" which nginx apache2 caddy 2>/dev/null || echo "No web servers found" ls /etc/nginx/sites-enabled/ 2>/dev/null | head -5 || echo "No nginx sites" echo "" echo "=== DATABASES ===" which mysql mysqld psql postgres sqlite3 2>/dev/null || echo "No databases found" systemctl is-active mariadb mysql postgresql 2>/dev/null || echo "No DB services running" echo "" echo "=== SYSTEMD SERVICES (non-standard) ===" # Custom services (not default Ubuntu/system packages) systemctl list-units --type=service --state=running --no-pager --no-legend 2>/dev/null | grep -vE "systemd|ssh|cron|rsyslog|networkd|resolved|timesyncd|getty|user@|dbus|polkit|syslog|ufw|apparmor|irqbalance" echo "" echo "=== HOME DIRECTORIES ===" ls /home/ 2>/dev/null || echo "No /home/ users" echo "" echo "=== CRON ===" crontab -l 2>/dev/null || echo "No crontab" echo "" echo "=== ROOT SCRIPTS ===" ls /root/*.sh /root/*.py 2>/dev/null || echo "No root scripts" echo "" echo "=== AUDIT COMPLETE ===" echo "Output file: $OUTPUT"