This skill should be used when the user asks to "secure server", "harden server", "server hardening", "setup server security", or needs to configure fail2ban, UFW, auditd, rkhunter, unattended-upgrades, or security alerting on Ubuntu servers.
Resources
3Install
npx skillscat add aviflombaum/claude-code-in-avinyc/secure-server Install via the SkillsCat registry.
Server Hardening Skill
Overview
This skill hardens Ubuntu servers with:
- fail2ban - Block IPs after failed SSH attempts
- UFW - Firewall with deny-by-default policy
- auditd - Monitor critical file changes
- rkhunter - Weekly rootkit scans
- unattended-upgrades - Automatic security patches
- Custom alerting - Sends alerts to Cloudflare Worker -> Ntfy push notifications
- Crypto miner detection - Detects suspicious CPU usage and mining pool connections
Prerequisites
Before running this skill, ensure:
- Cloudflare Worker is deployed (see
cloudflare-worker/directory) - You have the Worker URL and shared secret
- You have SSH access to target servers
- Ntfy topic is configured in the Worker
Instructions
When user invokes this skill, follow this interactive workflow:
Step 1: Gather Information
Ask the user:
- Which server(s) to harden (IP addresses or hostnames)
- The Cloudflare Worker alert endpoint URL
- The shared secret for authentication (or offer to generate one)
- The server role (web, database, worker, utility) - this determines UFW rules
Step 2: Verify Connectivity
Before making any changes:
ssh root@<server> "echo 'Connection successful' && uname -a"Confirm the user has a second SSH session open or Hetzner console access available.
Step 3: Deploy Alerting Infrastructure (Ask Permission)
What this does:
- Creates
/opt/server-security/directory structure - Deploys alert scripts (send-alert.sh, heartbeat.sh, health-check.sh, miner-detect.sh)
- Creates config file with Worker URL and secret
- Tests alert delivery
Commands to run:
# Create directory structure
ssh root@<server> "mkdir -p /opt/server-security/{scripts,config,logs}"
# Copy scripts (use scp or cat heredoc)
# Copy config template and fill in values
# Make scripts executable
ssh root@<server> "chmod +x /opt/server-security/scripts/*.sh"
# Test alert
ssh root@<server> "/opt/server-security/scripts/send-alert.sh test 'Hardening started' low"Step 4: Install Base Security Tools (Ask Permission)
What this does:
- Updates package list
- Installs fail2ban, ufw, auditd, rkhunter, unattended-upgrades
Commands:
ssh root@<server> "apt update && apt install -y fail2ban ufw auditd audispd-plugins rkhunter unattended-upgrades"Step 5: Configure SSH Hardening (Ask Permission)
What this does:
- Backs up current sshd_config
- Disables password authentication (keys only)
- Disables root password login (keys still work)
- Sets other security options
CRITICAL: Verify user has key-based access working before this step!
Commands:
# Backup
ssh root@<server> "cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup.$(date +%Y%m%d)"
# Apply hardening (show exact changes to user first)
ssh root@<server> "cat /etc/ssh/sshd_config" # Show current config
# Changes to make:
# PasswordAuthentication no
# PermitRootLogin prohibit-password
# PubkeyAuthentication yes
# PermitEmptyPasswords no
# X11Forwarding no
# MaxAuthTries 3
# Restart SSH (user should have second session ready!)
ssh root@<server> "systemctl restart sshd"Step 6: Configure UFW Firewall (Ask Permission)
Rules depend on server role:
| Role | Ports |
|---|---|
| All | 22 (SSH), 10.0.0.0/8 (private network) |
| Web | + 80, 443 |
| Database | + 5432, 6379 from 10.0.0.0/8 only |
| Worker | (no additional) |
Commands:
# Reset and set defaults
ssh root@<server> "ufw --force reset && ufw default deny incoming && ufw default allow outgoing"
# Allow SSH (CRITICAL - do this first!)
ssh root@<server> "ufw allow 22/tcp"
# Allow private network
ssh root@<server> "ufw allow from 10.0.0.0/8"
# Role-specific rules
# For web servers:
ssh root@<server> "ufw allow 80/tcp && ufw allow 443/tcp"
# For database (private network only):
ssh root@<server> "ufw allow from 10.0.0.0/8 to any port 5432"
ssh root@<server> "ufw allow from 10.0.0.0/8 to any port 6379"
# Enable (with confirmation)
ssh root@<server> "ufw --force enable"
# Verify
ssh root@<server> "ufw status verbose"Step 7: Configure fail2ban (Ask Permission)
What this does:
- Deploys jail.local config for SSH protection
- Deploys custom action to send alerts on ban
- Enables and starts fail2ban
Commands:
# Copy jail.local
# Copy security-alert.local action
ssh root@<server> "systemctl enable fail2ban && systemctl restart fail2ban"
# Verify
ssh root@<server> "fail2ban-client status sshd"Step 8: Configure auditd (Ask Permission)
What this does:
- Deploys rules to monitor: /etc/passwd, /etc/shadow, /etc/sudoers, SSH config, cron
- Enables and starts auditd
Commands:
# Copy security.rules to /etc/audit/rules.d/
ssh root@<server> "systemctl enable auditd && systemctl restart auditd"
# Verify
ssh root@<server> "auditctl -l"Step 9: Configure Unattended Upgrades (Ask Permission)
What this does:
- Enables automatic security updates
- Configures email notifications (optional)
- Sets auto-reboot to false (manual reboots preferred)
Commands:
# Copy 50unattended-upgrades to /etc/apt/apt.conf.d/
ssh root@<server> "dpkg-reconfigure -plow unattended-upgrades" # or use debconf-set-selections
# Verify
ssh root@<server> "cat /etc/apt/apt.conf.d/20auto-upgrades"Step 10: Configure rkhunter (Ask Permission)
What this does:
- Updates rkhunter database
- Sets up weekly scan with alerting
Commands:
ssh root@<server> "rkhunter --update && rkhunter --propupd"
# Weekly scan is handled by cron in next stepStep 11: Configure Process Whitelist (Ask Permission)
What this does:
- Deploys process whitelist for miner detection
- Customizes based on server role
Ask the user if they have additional processes that legitimately use high CPU on this server.
Default whitelist:
- ruby, rails, puma, sidekiq (Rails apps)
- postgres, redis-server (databases)
- node, python, python3 (other apps)
- docker, containerd, kamal (containers)
- nginx, caddy (web servers)
Step 12: Setup Cron Jobs (Ask Permission)
What this does:
- Heartbeat every 5 minutes
- Health check every 15 minutes
- Miner detection every 5 minutes
- rkhunter weekly scan (Sunday 3 AM)
Commands:
# Deploy cron file to /etc/cron.d/server-security
ssh root@<server> "cat > /etc/cron.d/server-security << 'EOF'
# Server Security Monitoring
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Heartbeat every 5 minutes
*/5 * * * * root /opt/server-security/scripts/heartbeat.sh >> /opt/server-security/logs/heartbeat.log 2>&1
# Health check every 15 minutes
*/15 * * * * root /opt/server-security/scripts/health-check.sh >> /opt/server-security/logs/health-check.log 2>&1
# Miner detection every 5 minutes
*/5 * * * * root /opt/server-security/scripts/miner-detect.sh >> /opt/server-security/logs/miner-detect.log 2>&1
# Weekly rkhunter scan (Sunday 3 AM)
0 3 * * 0 root /opt/server-security/scripts/rkhunter-scan.sh >> /opt/server-security/logs/rkhunter.log 2>&1
EOF"
# Verify
ssh root@<server> "cat /etc/cron.d/server-security"Step 13: Final Verification
Run through this checklist:
# SSH still works
ssh root@<server> "echo 'SSH OK'"
# UFW enabled
ssh root@<server> "ufw status | head -1"
# fail2ban running
ssh root@<server> "systemctl is-active fail2ban"
# Test alert delivery
ssh root@<server> "/opt/server-security/scripts/send-alert.sh test 'Hardening complete' low"
# Check heartbeat
ssh root@<server> "/opt/server-security/scripts/heartbeat.sh"
# Check health
ssh root@<server> "/opt/server-security/scripts/health-check.sh"
# auditd rules loaded
ssh root@<server> "auditctl -l | wc -l"
# Cron installed
ssh root@<server> "ls -la /etc/cron.d/server-security"Step 14: Document Completion
Record in conversation:
- Server IP
- Role
- Date hardened
- Any customizations made
- Any issues encountered
Rollback Commands
If something breaks, provide these to the user:
# Restore SSH config
ssh root@<server> "cp /etc/ssh/sshd_config.backup.* /etc/ssh/sshd_config && systemctl restart sshd"
# Disable firewall
ssh root@<server> "ufw disable"
# Stop security services
ssh root@<server> "systemctl stop fail2ban auditd"
# Remove cron
ssh root@<server> "rm /etc/cron.d/server-security"Files in This Skill
scripts/send-alert.sh- Send alerts to CF Workerscripts/heartbeat.sh- Send heartbeat with metricsscripts/health-check.sh- Check disk/memory/loadscripts/miner-detect.sh- Detect crypto minersscripts/rkhunter-scan.sh- Run rkhunter and alertconfig/alert.conf.template- Alert configuration templateconfig/process-whitelist.txt- Allowed high-CPU processesconfig/jail.local- fail2ban configurationconfig/security-alert.local- fail2ban alert actionconfig/security.rules- auditd rulesconfig/50unattended-upgrades- Auto-update configcloudflare-worker/worker.js- Alert hub Worker codecloudflare-worker/wrangler.toml- Worker deployment config