Skip to content
Development
Skill

/vps-security-hardening

Audit and harden VPS security — fail2ban, SSH hardening, firewall setup

From plugin
kevinnft-ai-agent-skills
14169 skills
Install
$ npx -y skills add kevinnft/ai-agent-skills --skill vps-security-hardening --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/vps-security-hardening

Context preview

The summary Claude sees to decide when to auto-load this skill.

Audit and harden VPS security — fail2ban, SSH hardening, firewall setup

SKILL.md

vps-security-hardening.SKILL.md
name: vps-security-hardening
description: Audit and harden VPS security — fail2ban, SSH hardening, firewall setup
tags: [security, vps, ssh, fail2ban, linux, ubuntu]
origin: unknown
source_license: see upstream
language: en

VPS Security Hardening

Audit and harden VPS security with fail2ban (brute-force protection), SSH hardening, and optional firewall setup.

When to Use

  • New VPS setup (initial hardening)
  • Security audit requested
  • SSH brute-force attacks detected
  • User wants to "secure VPS" or "protect server"

Prerequisites: Establishing SSH Access

**Before hardening, ensure you can SSH into the VPS.**

If Password Auth is Disabled (PublicKey only)

VPS providers often disable password auth by default. You need to add your SSH key first.

Option 1: Via VPS Web Console (Recommended)

1. **Generate SSH key locally** (if not exists):

   ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N '' -C "user@machine"
   cat ~/.ssh/id_ed25519.pub

2. **Login to VPS via web console** (provider dashboard → Console/Terminal)

3. **Add public key to VPS**:

   mkdir -p ~/.ssh
   echo "ssh-ed25519 AAAA... user@machine" >> ~/.ssh/authorized_keys
   chmod 700 ~/.ssh
   chmod 600 ~/.ssh/authorized_keys

4. **Test from local machine**:

   ssh root@VPS_IP

Option 2: Via Provider Dashboard

Most providers (DigitalOcean, Vultr, Biznet, etc.) have "Add SSH Key" in dashboard:

  • Copy public key (`cat ~/.ssh/id_ed25519.pub`)
  • Paste into provider's SSH key management
  • Rebuild/restart VPS (some providers require this)

Option 3: Enable Password Auth Temporarily

**Only if web console is unavailable:**

1. Login via web console 2. Edit SSH config:

   echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config.d/99-temp-password.conf
   systemctl reload sshd

3. SSH in with password, add your key 4. Remove temp config:

   rm /etc/ssh/sshd_config.d/99-temp-password.conf
   systemctl reload sshd

Common Pitfall: sshpass with PublicKey-Only VPS

**Problem:** `sshpass -p 'password' ssh user@host` fails with "Permission denied (publickey)" even with correct password.

**Why:** VPS has `PasswordAuthentication no` in sshd_config — password auth is disabled at server level.

**Solution:** Use web console to add SSH key first (see Option 1 above).

Workflow

Phase 1: Security Audit

1. **Check running processes**

   ps aux --sort=-%mem | head -20
   systemctl list-units --type=service --state=running

2. **Check listening ports**

   sudo ss -tulpn
   sudo netstat -tulpn

3. **Check for rootkits/malware**

   # Hidden processes
   ps aux | wc -l
   ls /proc | grep -E '^[0-9]+$' | wc -l
   
   # Recent failed logins
   sudo grep "Failed password" /var/log/auth.log | tail -20

4. **Check user accounts**

   cat /etc/passwd | grep -E '/bin/(bash|sh)$'
   sudo lastlog

5. **Resource usage**

   free -h
   df -h
   uptime

Phase 2: Install fail2ban

# Install
sudo apt-get update
sudo apt-get install -y fail2ban

# Enable and start
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Phase 3: Configure fail2ban

Create `/etc/fail2ban/jail.local`:

[DEFAULT]
bantime  = 3600        # Ban for 1 hour
findtime = 600         # Count failures in last 10 minutes
maxretry = 5           # Ban after 5 failures

[sshd]
enabled = true
port    = 22
logpath = /var/log/auth.log
maxretry = 5

Restart:

sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Phase 4: SSH Hardening

Create `/etc/ssh/sshd_config.d/99-hardening.conf`:

# Disable root login
PermitRootLogin no

# Enable public key auth
PubkeyAuthentication yes

# Disable empty passwords
PermitEmptyPasswords no

# Limit auth attempts
MaxAuthTries 3

# Disable X11 forwarding
X11Forwarding no

# Disable TCP forwarding
AllowTcpForwarding no

# Disable agent forwarding
AllowAgentForwarding no

# Set login grace time
LoginGraceTime 30

# Limit sessions
MaxSessions 2

# Strong ciphers only
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com

# Strong MACs only
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

# Strong key exchange
KexAlgorithms curve25519-sha256,diffie-hellman-group-exchange-sha256

Test and reload:

sudo sshd -t
sudo systemctl reload sshd

Phase 5: Verify

# fail2ban status
sudo fail2ban-client status sshd

# SSH config
sudo sshd -T | grep -E '(permitrootlogin|maxauthtries|x11forwarding)'

# Check banned IPs
sudo fail2ban-client get sshd banip

Important: Password vs SSH Key Decision

**DO NOT automatically disable password authentication!**

Check First

# Check if user has SSH keys
cat ~/.ssh/authorized_keys

# Check how user is currently connected
sudo grep "Accepted" /var/log/auth.log | tail -5

Decision Logic

**If user logs in with PASSWORD:**

  • ✅ Keep `PasswordAuthentication yes`
  • ✅ fail2ban provides brute-force protection
  • ⚠️ Disabling password = user gets locked out

**If user logs in with SSH KEY:**

  • ✅ Can disable `PasswordAuthentication no`
  • ✅ Maximum security (impossible to brute-force)

User Preference Handling

**CRITICAL:** If user says "keep password" or "tanpa ssh key" or similar:

  • ✅ Accept their decision
  • ✅ Explain security is already good with fail2ban
  • ❌ DO NOT keep suggesting SSH keys
  • ❌ DO NOT say "but SSH keys are better"
  • ❌ DO NOT make them feel their choice is wrong

**User knows their use case better than you:**

  • They might need portability (login from anywhere)
  • They might not want key file management
  • They might prefer convenience over maximum security
  • **Respect their decision and move on**

Pitfalls

1. Disabling Password Auth Too Early

**Problem:** User currently uses password, you disable it, user gets locked out.

**Solution:**

  • A
Read more
Ships withkevinnft-ai-agent-skills

191 attribution-first agent skills for Hermes Agent, Claude Code, Cursor — one installer, 28 categories, searchable catalog. See NOTICE for upstream attribution.

Get the whole plugin

Other skills on kevinnft-ai-agent-skills.