VPS Attack Surface Reduction Checklist
Attack surface is everything an attacker can reach, test or abuse from the outside. A secure VPS is not only a server with strong passwords. It is a system where unnecessary ports, services, users, files and dashboards are removed or protected.
Core principle
You cannot secure what you do not know is exposed. First list what is reachable, then close what does not need to be public.
Checklist
- List all listening ports.
- Identify which services are public.
- Identify which services should be private.
- Check provider firewall rules.
- Check UFW or server firewall rules.
- Close unused ports.
- Protect admin dashboards behind login, VPN, IP restriction or reverse proxy rules.
- Remove unused services.
- Review Docker published ports.
- Document the final exposure map.
Reusable lesson
This applies to WordPress, Nginx, MySQL, Redis, Docker, n8n, monitoring dashboards, API workers and internal admin tools.
When to Use This Checklist
Use this checklist when hardening a VPS before or after deploying websites, Docker apps, automation tools or admin dashboards.
Required Tools
SSH access, UFW, provider firewall, Nginx, Docker if used, service list, domain map
Before You Start
Do not expose a service publicly just because it works. Decide whether each service must be reachable from the internet.
Structured Checklist Steps
- List listening ports.
- Classify public services.
- Classify private services.
- Review provider firewall.
- Review UFW.
- Close unused ports.
- Protect dashboards.
- Remove unused services.
- Review Docker ports.
- Document exposure map.
Verification Steps
- Only required ports are public.
- Database ports are private.
- Admin dashboards are protected.
- Docker published ports are intentional.
- Firewall rules match the exposure map.
Rollback Plan
If closing a port breaks a required service, restore the previous firewall rule temporarily, then redesign access using a safer method such as reverse proxy, VPN or IP restriction.
Common Mistakes
- Opening all ports.
- Leaving test dashboards public.
- Forgetting Docker published ports.
- Relying only on application passwords.
- No written exposure map.
Related Commands
sudo ss -tulpn
sudo ufw status numbered
docker ps
systemctl list-units --type=service --state=running
curl -I https://example.com