Created
February 1, 2026 15:59
-
-
Save afuggini/352c1e11aee7861ddc4ee6542585a00f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # openclaw-security-check.sh - Verify server security configuration | |
| # Run this periodically to check security status | |
| # Usage: ./openclaw-security-check.sh | |
| echo "==========================================" | |
| echo "OpenClaw Security Status Check" | |
| echo "$(date)" | |
| echo "==========================================" | |
| echo "" | |
| PASS=0 | |
| FAIL=0 | |
| WARN=0 | |
| check_pass() { | |
| echo "✓ $1" | |
| ((PASS++)) | |
| } | |
| check_fail() { | |
| echo "✗ $1" | |
| ((FAIL++)) | |
| } | |
| check_warn() { | |
| echo "⚠ $1" | |
| ((WARN++)) | |
| } | |
| # Check UFW status | |
| if sudo ufw status | grep -q "Status: active"; then | |
| check_pass "Firewall (UFW) is active" | |
| else | |
| check_fail "Firewall (UFW) is NOT active" | |
| fi | |
| # Check Fail2Ban | |
| if sudo systemctl is-active --quiet fail2ban; then | |
| check_pass "Fail2Ban is running" | |
| BANNED=$(sudo fail2ban-client status sshd | grep "Currently banned" | awk '{print $4}') | |
| echo " → Currently banned IPs: $BANNED" | |
| else | |
| check_fail "Fail2Ban is NOT running" | |
| fi | |
| # Check SSH config | |
| if sudo grep -q "^PermitRootLogin no" /etc/ssh/sshd_config.d/99-hardening.conf 2>/dev/null; then | |
| check_pass "SSH root login disabled" | |
| else | |
| check_fail "SSH root login is ENABLED" | |
| fi | |
| if sudo grep -q "^PasswordAuthentication no" /etc/ssh/sshd_config.d/99-hardening.conf 2>/dev/null; then | |
| check_pass "SSH password authentication disabled" | |
| else | |
| check_warn "SSH password authentication is ENABLED" | |
| fi | |
| # Check for security updates | |
| UPDATES=$(apt list --upgradable 2>/dev/null | grep -i security | wc -l) | |
| if [ $UPDATES -eq 0 ]; then | |
| check_pass "No pending security updates" | |
| else | |
| check_warn "$UPDATES security updates available" | |
| fi | |
| # Check Docker running | |
| if sudo systemctl is-active --quiet docker; then | |
| check_pass "Docker is running" | |
| else | |
| check_fail "Docker is NOT running" | |
| fi | |
| # Check disk space | |
| DISK_USAGE=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//') | |
| if [ $DISK_USAGE -lt 80 ]; then | |
| check_pass "Disk usage: ${DISK_USAGE}%" | |
| else | |
| check_warn "Disk usage: ${DISK_USAGE}% (high)" | |
| fi | |
| # Check for failed login attempts | |
| FAILED_LOGINS=$(sudo grep "Failed password" /var/log/auth.log | wc -l) | |
| if [ $FAILED_LOGINS -lt 10 ]; then | |
| check_pass "Failed login attempts: $FAILED_LOGINS (last 24h)" | |
| else | |
| check_warn "Failed login attempts: $FAILED_LOGINS (last 24h) - potential attack" | |
| fi | |
| # Check listening ports | |
| LISTENING=$(sudo ss -tulpn | grep LISTEN | wc -l) | |
| echo "" | |
| echo "Open ports: $LISTENING" | |
| sudo ss -tulpn | grep LISTEN | awk '{print $5}' | sort -u | |
| echo "" | |
| echo "==========================================" | |
| echo "Security Score" | |
| echo "==========================================" | |
| echo "✓ Passed: $PASS" | |
| echo "⚠ Warnings: $WARN" | |
| echo "✗ Failed: $FAIL" | |
| echo "" | |
| if [ $FAIL -gt 0 ]; then | |
| echo "❌ CRITICAL ISSUES FOUND - Fix immediately!" | |
| exit 1 | |
| elif [ $WARN -gt 0 ]; then | |
| echo "⚠️ Warnings found - review recommended" | |
| exit 0 | |
| else | |
| echo "✅ All security checks passed" | |
| exit 0 | |
| fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # openclaw-server-hardening.sh - Secure VPS for OpenClaw multi-tenant deployment | |
| # Run this ONCE on a fresh Ubuntu 22.04 LTS VPS as root | |
| # Usage: curl -sSL https://yourgist.com/hardening.sh | sudo bash | |
| set -e | |
| echo "==========================================" | |
| echo "OpenClaw Server Hardening Script" | |
| echo "==========================================" | |
| echo "" | |
| # Check if running as root | |
| if [[ $EUID -ne 0 ]]; then | |
| echo "❌ This script must be run as root (use sudo)" | |
| exit 1 | |
| fi | |
| # ==================== 1. UPDATE SYSTEM ==================== | |
| echo "==> Step 1/12: Updating system packages..." | |
| apt-get update -qq | |
| apt-get upgrade -y -qq | |
| apt-get autoremove -y -qq | |
| echo "✓ System updated" | |
| # ==================== 2. CREATE NON-ROOT USER ==================== | |
| echo "" | |
| echo "==> Step 2/12: Creating non-root user for OpenClaw..." | |
| read -p "Enter username for OpenClaw admin (default: openclaw): " ADMIN_USER | |
| ADMIN_USER=${ADMIN_USER:-openclaw} | |
| if id "$ADMIN_USER" &>/dev/null; then | |
| echo "⚠ User $ADMIN_USER already exists, skipping creation" | |
| else | |
| adduser --disabled-password --gecos "" $ADMIN_USER | |
| usermod -aG sudo $ADMIN_USER | |
| echo "$ADMIN_USER ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/$ADMIN_USER | |
| echo "✓ User $ADMIN_USER created with sudo access" | |
| fi | |
| # Set up SSH key for new user | |
| echo "" | |
| read -p "Do you have an SSH public key to add? (y/n): " -n 1 -r | |
| echo | |
| if [[ $REPLY =~ ^[Yy]$ ]]; then | |
| mkdir -p /home/$ADMIN_USER/.ssh | |
| chmod 700 /home/$ADMIN_USER/.ssh | |
| echo "Paste your SSH public key (entire line from id_rsa.pub):" | |
| read SSH_KEY | |
| echo "$SSH_KEY" > /home/$ADMIN_USER/.ssh/authorized_keys | |
| chmod 600 /home/$ADMIN_USER/.ssh/authorized_keys | |
| chown -R $ADMIN_USER:$ADMIN_USER /home/$ADMIN_USER/.ssh | |
| echo "✓ SSH key added for $ADMIN_USER" | |
| else | |
| echo "⚠ Skipping SSH key setup - you'll need password authentication" | |
| fi | |
| # ==================== 3. SECURE SSH ==================== | |
| echo "" | |
| echo "==> Step 3/12: Hardening SSH configuration..." | |
| # Backup original config | |
| cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup | |
| # SSH Hardening | |
| cat > /etc/ssh/sshd_config.d/99-hardening.conf <<EOF | |
| # Disable root login | |
| PermitRootLogin no | |
| # Disable password authentication (use SSH keys only) | |
| PasswordAuthentication no | |
| PubkeyAuthentication yes | |
| # Disable empty passwords | |
| PermitEmptyPasswords no | |
| # Disable X11 forwarding | |
| X11Forwarding no | |
| # Limit authentication attempts | |
| MaxAuthTries 3 | |
| MaxSessions 10 | |
| # Use only secure protocols | |
| Protocol 2 | |
| # Set login grace time | |
| LoginGraceTime 60 | |
| # Only allow specific user | |
| AllowUsers $ADMIN_USER | |
| # Disable unused authentication methods | |
| ChallengeResponseAuthentication no | |
| KerberosAuthentication no | |
| GSSAPIAuthentication no | |
| # Enable strict mode | |
| StrictModes yes | |
| # Set client alive interval (prevent idle disconnects) | |
| ClientAliveInterval 300 | |
| ClientAliveCountMax 2 | |
| EOF | |
| # Restart SSH (but don't disconnect current session) | |
| systemctl reload sshd | |
| echo "✓ SSH hardened (root login disabled, key-only auth)" | |
| # ==================== 4. CONFIGURE FIREWALL (UFW) ==================== | |
| echo "" | |
| echo "==> Step 4/12: Configuring firewall..." | |
| apt-get install -y -qq ufw | |
| # Default policies | |
| ufw --force default deny incoming | |
| ufw --force default allow outgoing | |
| # Allow SSH (critical - don't lock yourself out!) | |
| ufw allow 22/tcp comment 'SSH' | |
| # Allow HTTP/HTTPS for your web platform | |
| ufw allow 80/tcp comment 'HTTP' | |
| ufw allow 443/tcp comment 'HTTPS' | |
| # Allow OpenClaw gateway port range (customer instances) | |
| ufw allow 20000:30000/tcp comment 'OpenClaw Instances' | |
| # Enable UFW | |
| ufw --force enable | |
| echo "✓ Firewall configured and enabled" | |
| ufw status numbered | |
| # ==================== 5. INSTALL FAIL2BAN ==================== | |
| echo "" | |
| echo "==> Step 5/12: Installing Fail2Ban (brute force protection)..." | |
| apt-get install -y -qq fail2ban | |
| # Configure Fail2Ban for SSH | |
| cat > /etc/fail2ban/jail.d/sshd.conf <<EOF | |
| [sshd] | |
| enabled = true | |
| port = ssh | |
| filter = sshd | |
| logpath = /var/log/auth.log | |
| maxretry = 3 | |
| bantime = 3600 | |
| findtime = 600 | |
| EOF | |
| systemctl enable fail2ban | |
| systemctl restart fail2ban | |
| echo "✓ Fail2Ban installed (3 failed attempts = 1hr ban)" | |
| # ==================== 6. DISABLE UNNECESSARY SERVICES ==================== | |
| echo "" | |
| echo "==> Step 6/12: Disabling unnecessary services..." | |
| # List of services to disable (if they exist) | |
| SERVICES_TO_DISABLE=( | |
| "avahi-daemon" | |
| "cups" | |
| "isc-dhcp-server" | |
| "isc-dhcp-server6" | |
| "rpcbind" | |
| "rsync" | |
| "nfs-server" | |
| ) | |
| for service in "${SERVICES_TO_DISABLE[@]}"; do | |
| if systemctl is-enabled --quiet $service 2>/dev/null; then | |
| systemctl disable $service | |
| systemctl stop $service | |
| echo " ✓ Disabled $service" | |
| fi | |
| done | |
| echo "✓ Unnecessary services disabled" | |
| # ==================== 7. KERNEL HARDENING (SYSCTL) ==================== | |
| echo "" | |
| echo "==> Step 7/12: Applying kernel hardening..." | |
| cat > /etc/sysctl.d/99-openclaw-hardening.conf <<EOF | |
| # IP Forwarding (disable unless needed for Docker) | |
| net.ipv4.ip_forward = 1 | |
| # Disable IPv6 (unless needed) | |
| net.ipv6.conf.all.disable_ipv6 = 0 | |
| net.ipv6.conf.default.disable_ipv6 = 0 | |
| # Prevent IP spoofing | |
| net.ipv4.conf.all.rp_filter = 1 | |
| net.ipv4.conf.default.rp_filter = 1 | |
| # Ignore ICMP redirects | |
| net.ipv4.conf.all.accept_redirects = 0 | |
| net.ipv4.conf.default.accept_redirects = 0 | |
| net.ipv4.conf.all.secure_redirects = 0 | |
| net.ipv4.conf.default.secure_redirects = 0 | |
| # Don't send ICMP redirects | |
| net.ipv4.conf.all.send_redirects = 0 | |
| net.ipv4.conf.default.send_redirects = 0 | |
| # Ignore ICMP ping requests (optional - prevents ping flood) | |
| # net.ipv4.icmp_echo_ignore_all = 1 | |
| # Log suspicious packets | |
| net.ipv4.conf.all.log_martians = 1 | |
| net.ipv4.conf.default.log_martians = 1 | |
| # Ignore broadcast pings | |
| net.ipv4.icmp_echo_ignore_broadcasts = 1 | |
| # Protect against SYN flood attacks | |
| net.ipv4.tcp_syncookies = 1 | |
| net.ipv4.tcp_max_syn_backlog = 2048 | |
| net.ipv4.tcp_synack_retries = 2 | |
| net.ipv4.tcp_syn_retries = 5 | |
| # Disable source packet routing | |
| net.ipv4.conf.all.accept_source_route = 0 | |
| net.ipv4.conf.default.accept_source_route = 0 | |
| # Increase local port range | |
| net.ipv4.ip_local_port_range = 10000 65535 | |
| # Protect against time-wait assassination | |
| net.ipv4.tcp_rfc1337 = 1 | |
| # Kernel hardening | |
| kernel.kptr_restrict = 2 | |
| kernel.dmesg_restrict = 1 | |
| kernel.yama.ptrace_scope = 1 | |
| # Limit core dumps | |
| fs.suid_dumpable = 0 | |
| EOF | |
| sysctl -p /etc/sysctl.d/99-openclaw-hardening.conf > /dev/null | |
| echo "✓ Kernel hardening applied" | |
| # ==================== 8. INSTALL DOCKER SECURELY ==================== | |
| echo "" | |
| echo "==> Step 8/12: Installing Docker with security configurations..." | |
| # Install Docker | |
| apt-get install -y -qq apt-transport-https ca-certificates curl software-properties-common | |
| curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg | |
| echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null | |
| apt-get update -qq | |
| apt-get install -y -qq docker-ce docker-ce-cli containerd.io docker-compose-plugin | |
| # Add user to docker group | |
| usermod -aG docker $ADMIN_USER | |
| # Docker security configuration | |
| mkdir -p /etc/docker | |
| cat > /etc/docker/daemon.json <<EOF | |
| { | |
| "log-driver": "json-file", | |
| "log-opts": { | |
| "max-size": "10m", | |
| "max-file": "3" | |
| }, | |
| "live-restore": true, | |
| "userland-proxy": false, | |
| "no-new-privileges": true, | |
| "icc": false, | |
| "userns-remap": "default" | |
| } | |
| EOF | |
| # Enable user namespace remapping for container isolation | |
| mkdir -p /etc/subuid /etc/subgid | |
| echo "dockremap:231072:65536" >> /etc/subuid | |
| echo "dockremap:231072:65536" >> /etc/subgid | |
| systemctl restart docker | |
| echo "✓ Docker installed with security hardening" | |
| # ==================== 9. SETUP AUTOMATED SECURITY UPDATES ==================== | |
| echo "" | |
| echo "==> Step 9/12: Configuring automatic security updates..." | |
| apt-get install -y -qq unattended-upgrades apt-listchanges | |
| cat > /etc/apt/apt.conf.d/50unattended-upgrades <<EOF | |
| Unattended-Upgrade::Allowed-Origins { | |
| "\${distro_id}:\${distro_codename}-security"; | |
| }; | |
| Unattended-Upgrade::AutoFixInterruptedDpkg "true"; | |
| Unattended-Upgrade::MinimalSteps "true"; | |
| Unattended-Upgrade::Remove-Unused-Kernel-Packages "true"; | |
| Unattended-Upgrade::Remove-Unused-Dependencies "true"; | |
| Unattended-Upgrade::Automatic-Reboot "false"; | |
| Unattended-Upgrade::Automatic-Reboot-Time "03:00"; | |
| EOF | |
| cat > /etc/apt/apt.conf.d/20auto-upgrades <<EOF | |
| APT::Periodic::Update-Package-Lists "1"; | |
| APT::Periodic::Download-Upgradeable-Packages "1"; | |
| APT::Periodic::AutocleanInterval "7"; | |
| APT::Periodic::Unattended-Upgrade "1"; | |
| EOF | |
| systemctl enable unattended-upgrades | |
| systemctl restart unattended-upgrades | |
| echo "✓ Automatic security updates enabled" | |
| # ==================== 10. SETUP MONITORING & LOGGING ==================== | |
| echo "" | |
| echo "==> Step 10/12: Configuring logging and monitoring..." | |
| # Install monitoring tools | |
| apt-get install -y -qq htop iotop nethogs | |
| # Configure log rotation for Docker | |
| cat > /etc/logrotate.d/docker-containers <<EOF | |
| /var/lib/docker/containers/*/*.log { | |
| rotate 7 | |
| daily | |
| compress | |
| missingok | |
| delaycompress | |
| copytruncate | |
| } | |
| EOF | |
| # Setup audit logging for sensitive directories | |
| apt-get install -y -qq auditd audispd-plugins | |
| cat > /etc/audit/rules.d/openclaw.rules <<EOF | |
| # Monitor OpenClaw instance directories | |
| -w /root/.openclaw-instances/ -p wa -k openclaw_instances | |
| # Monitor Docker socket | |
| -w /var/run/docker.sock -p wa -k docker_socket | |
| # Monitor system authentication | |
| -w /etc/passwd -p wa -k passwd_changes | |
| -w /etc/group -p wa -k group_changes | |
| -w /etc/shadow -p wa -k shadow_changes | |
| # Monitor sudo | |
| -w /etc/sudoers -p wa -k sudoers_changes | |
| EOF | |
| systemctl restart auditd | |
| echo "✓ Logging and monitoring configured" | |
| # ==================== 11. SETUP INTRUSION DETECTION (OPTIONAL) ==================== | |
| echo "" | |
| read -p "Install AIDE (intrusion detection)? This takes time. (y/n): " -n 1 -r | |
| echo | |
| if [[ $REPLY =~ ^[Yy]$ ]]; then | |
| echo "==> Step 11/12: Installing AIDE (this may take 10-15 minutes)..." | |
| apt-get install -y -qq aide aide-common | |
| # Initialize AIDE database | |
| echo "⏳ Building AIDE database (this takes time, be patient)..." | |
| aideinit | |
| mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db | |
| # Setup daily AIDE check via cron | |
| cat > /etc/cron.daily/aide-check <<EOF | |
| #!/bin/bash | |
| /usr/bin/aide --check | mail -s "AIDE Report for \$(hostname)" root | |
| EOF | |
| chmod +x /etc/cron.daily/aide-check | |
| echo "✓ AIDE installed (daily integrity checks enabled)" | |
| else | |
| echo "⊘ Skipping AIDE installation" | |
| fi | |
| # ==================== 12. CUSTOMER INSTANCE ISOLATION ==================== | |
| echo "" | |
| echo "==> Step 12/12: Setting up customer instance isolation..." | |
| # Create base directory structure | |
| mkdir -p /home/$ADMIN_USER/.openclaw-instances | |
| chown -R $ADMIN_USER:$ADMIN_USER /home/$ADMIN_USER/.openclaw-instances | |
| chmod 750 /home/$ADMIN_USER/.openclaw-instances | |
| # Create iptables rules for container network isolation | |
| cat > /etc/iptables/openclaw-isolation.rules <<EOF | |
| # Allow containers to access internet | |
| -A FORWARD -i docker0 -o eth0 -j ACCEPT | |
| -A FORWARD -i eth0 -o docker0 -m state --state RELATED,ESTABLISHED -j ACCEPT | |
| # Prevent containers from accessing each other (unless on same network) | |
| -A DOCKER-USER -i docker0 -o docker0 -j DROP | |
| # Prevent containers from accessing host services | |
| -A INPUT -i docker0 -j DROP | |
| EOF | |
| echo "✓ Customer isolation rules created" | |
| # ==================== RATE LIMITING FOR API ENDPOINTS ==================== | |
| echo "" | |
| echo "Setting up rate limiting for OpenClaw instances..." | |
| # Install nginx for reverse proxy with rate limiting | |
| apt-get install -y -qq nginx | |
| # Disable default site | |
| rm -f /etc/nginx/sites-enabled/default | |
| # Create rate limit config | |
| cat > /etc/nginx/conf.d/rate-limit.conf <<EOF | |
| # Define rate limit zones | |
| limit_req_zone \$binary_remote_addr zone=openclaw_general:10m rate=10r/s; | |
| limit_req_zone \$binary_remote_addr zone=openclaw_api:10m rate=5r/s; | |
| # Connection limits | |
| limit_conn_zone \$binary_remote_addr zone=addr:10m; | |
| EOF | |
| systemctl restart nginx | |
| echo "✓ Nginx installed for rate limiting" | |
| # ==================== GENERATE SECURITY REPORT ==================== | |
| echo "" | |
| echo "==========================================" | |
| echo "Security Hardening Complete!" | |
| echo "==========================================" | |
| echo "" | |
| # Create security report | |
| REPORT_FILE="/home/$ADMIN_USER/security-report.txt" | |
| cat > $REPORT_FILE <<EOF | |
| OpenClaw Server Security Report | |
| Generated: $(date) | |
| Hostname: $(hostname) | |
| IP Address: $(curl -s ifconfig.me) | |
| ======================================== | |
| SECURITY MEASURES APPLIED | |
| ======================================== | |
| ✓ System packages updated | |
| ✓ Non-root user created: $ADMIN_USER | |
| ✓ SSH hardened (root login disabled, key-only auth) | |
| ✓ Firewall configured (UFW): | |
| - SSH: Port 22 | |
| - HTTP/HTTPS: Ports 80/443 | |
| - OpenClaw: Ports 20000-30000 | |
| ✓ Fail2Ban installed (brute force protection) | |
| ✓ Unnecessary services disabled | |
| ✓ Kernel hardening applied | |
| ✓ Docker installed with security configs | |
| ✓ Automatic security updates enabled | |
| ✓ Logging and monitoring configured | |
| ✓ Customer instance isolation configured | |
| ✓ Rate limiting enabled (Nginx) | |
| ======================================== | |
| NEXT STEPS | |
| ======================================== | |
| 1. LOGOUT and login as: $ADMIN_USER | |
| ssh $ADMIN_USER@$(curl -s ifconfig.me) | |
| 2. VERIFY SSH key authentication works | |
| 3. NEVER login as root again | |
| 4. TEST firewall rules: | |
| sudo ufw status | |
| 5. MONITOR logs: | |
| sudo tail -f /var/log/auth.log | |
| sudo fail2ban-client status sshd | |
| 6. SETUP SSL certificates (Let's Encrypt): | |
| sudo apt install certbot python3-certbot-nginx | |
| sudo certbot --nginx -d yourdomain.com | |
| 7. BACKUP this report file: | |
| $(pwd)/$REPORT_FILE | |
| ======================================== | |
| SECURITY CHECKLIST | |
| ======================================== | |
| [ ] Changed default SSH port? (optional) | |
| Edit: /etc/ssh/sshd_config.d/99-hardening.conf | |
| Add: Port 2222 | |
| Update UFW: ufw allow 2222/tcp | |
| [ ] Setup monitoring/alerts? (recommended) | |
| Options: UptimeRobot, Datadog, Prometheus | |
| [ ] Configured backups? (critical) | |
| Options: Vultr snapshots, rsnapshot, Backblaze B2 | |
| [ ] Setup SSL certificates? (required for production) | |
| Use: Let's Encrypt (free) | |
| [ ] Configured email alerts? | |
| For: Fail2Ban, AIDE, security updates | |
| [ ] Documented recovery procedures? | |
| What to do if server is compromised | |
| [ ] Setup 2FA for admin account? (highly recommended) | |
| Use: Google Authenticator via PAM | |
| ======================================== | |
| SECURITY MAINTENANCE | |
| ======================================== | |
| DAILY: | |
| - Check Fail2Ban logs: sudo fail2ban-client status | |
| - Monitor Docker containers: docker ps | |
| WEEKLY: | |
| - Review auth logs: sudo grep -i "failed\|error" /var/log/auth.log | |
| - Check disk space: df -h | |
| - Review active connections: sudo netstat -tupln | |
| MONTHLY: | |
| - Update system: sudo apt update && sudo apt upgrade | |
| - Review UFW rules: sudo ufw status numbered | |
| - Audit Docker images: docker images | |
| - Check for rootkits: sudo rkhunter --check | |
| QUARTERLY: | |
| - Review all user accounts: cat /etc/passwd | |
| - Audit sudo access: sudo cat /etc/sudoers | |
| - Test backup restoration | |
| - Review and rotate SSH keys | |
| ======================================== | |
| EMERGENCY CONTACTS | |
| ======================================== | |
| If server is compromised: | |
| 1. Disconnect from network: sudo ufw deny out | |
| 2. Take snapshot: via Vultr dashboard | |
| 3. Analyze logs: /var/log/auth.log, /var/log/syslog | |
| 4. Contact Vultr support | |
| 5. Restore from clean backup | |
| ======================================== | |
| USEFUL COMMANDS | |
| ======================================== | |
| # Check open ports | |
| sudo netstat -tupln | |
| # View firewall status | |
| sudo ufw status verbose | |
| # Check Fail2Ban status | |
| sudo fail2ban-client status sshd | |
| # View recent login attempts | |
| sudo lastlog | |
| # Check for listening services | |
| sudo ss -tulpn | |
| # View Docker container logs | |
| docker logs <container_name> | |
| # Check system resources | |
| htop | |
| # Monitor network traffic | |
| sudo nethogs | |
| # View audit logs | |
| sudo ausearch -k openclaw_instances | |
| ======================================== | |
| ADDITIONAL HARDENING (OPTIONAL) | |
| ======================================== | |
| 1. Install ClamAV (antivirus): | |
| sudo apt install clamav clamav-daemon | |
| sudo freshclam | |
| sudo clamscan -r /home | |
| 2. Setup ModSecurity (WAF): | |
| sudo apt install libapache2-mod-security2 | |
| 3. Enable AppArmor profiles: | |
| sudo aa-enforce /etc/apparmor.d/* | |
| 4. Install Tripwire (file integrity): | |
| sudo apt install tripwire | |
| 5. Setup centralized logging: | |
| Forward logs to external service (Papertrail, Loggly) | |
| ======================================== | |
| EOF | |
| chown $ADMIN_USER:$ADMIN_USER $REPORT_FILE | |
| chmod 600 $REPORT_FILE | |
| echo "✓ Security report generated: $REPORT_FILE" | |
| echo "" | |
| echo "==========================================" | |
| echo "⚠️ IMPORTANT NEXT STEPS" | |
| echo "==========================================" | |
| echo "" | |
| echo "1. SAVE this security report:" | |
| echo " $REPORT_FILE" | |
| echo "" | |
| echo "2. LOGOUT and test SSH key login:" | |
| echo " ssh $ADMIN_USER@$(curl -s ifconfig.me)" | |
| echo "" | |
| echo "3. NEVER use root account again" | |
| echo "" | |
| echo "4. SETUP SSL certificates before going live" | |
| echo "" | |
| echo "==========================================" | |
| echo "" | |
| # Create reminder to disable root password | |
| echo "" | |
| read -p "Disable root password now? (recommended) (y/n): " -n 1 -r | |
| echo | |
| if [[ $REPLY =~ ^[Yy]$ ]]; then | |
| passwd -l root | |
| echo "✓ Root password disabled" | |
| else | |
| echo "⚠ Root password still active - disable it manually later:" | |
| echo " sudo passwd -l root" | |
| fi | |
| echo "" | |
| echo "🎉 Server hardening complete!" | |
| echo "" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment