How to Audit and Harden a Self-Hosted VPS Setup

Team 7 min read

#security

#vps

#hardening

#audit

Introduction

Self-hosted VPS setups give you full control, but with that control comes responsibility. A secure baseline is not a one-off task; it’s an ongoing process of auditing, hardening, monitoring, and updating. This guide walks you through a practical workflow to audit a VPS, reduce attack surface, and establish repeatable hardening practices you can automate or reproduce.

Define your threat model and scope

Before diving into fixes, clarify what you’re protecting and what you’re willing to trade off.

  • What services run on the VPS (web server, database, VPN, CI runners, etc.)?
  • What is the critical data you host, and where is it backed up?
  • Who needs access, and how do you authenticate them?
  • What are acceptable downtime and recovery targets?

A focused scope helps you prioritize hardening steps and verify improvements during audits.

Establish a baseline

Start with a snapshot of your current state to measure progress.

  • OS and kernel: what distribution and version are you on? Check with:
    • cat /etc/os-release
    • uname -r
  • Package inventory: what is installed and what is outdated?
    • Debian/Ubuntu: apt list —installed
    • Red Hat/CentOS: rpm -qa
  • Open ports and listening services:
    • ss -tulnpf
    • lsof -i -P -n | grep LISTEN
  • User accounts and authentication:
    • cat /etc/passwd
    • cat /etc/shadow
    • cat /etc/sudoers
  • SSH configuration and remote access methods:
    • grep -E “PermitRootLogin|PasswordAuthentication|PubkeyAuthentication” /etc/ssh/sshd_config

Document your findings in a simple checklist. This baseline helps you validate improvements later and shows auditors that you’re methodical.

Run an external security audit (tools and goals)

Use lightweight, widely adopted tools to get an objective read on the server.

  • Lynis: a comprehensive security audit tool for Linux systems
    • Install: sudo apt-get install lynis (Debian/Ubuntu) or sudo yum install lynis (RHEL/CentOS)
    • Run: sudo lynis audit system
    • Focus on high-risk items and recommended remediations from the report
  • Filesystem integrity: AIDE or OSSEC-style monitoring
    • Install and initialize AIDE to watch for changes in critical paths
  • Basic host integrity and malware checks (optional but helpful)
    • rkhunter or chkrootkit to scan for rootkits
  • Log health and anomaly detection
    • Ensure rsyslog or journald is collecting logs and rotating them properly

Interpreting results quickly is key. Prioritize high-severity issues (remote access, root privileges, exposed services, weak configurations) and mark them for remediation.

SSH hardening (the single most impactful change)

SSH access is often the most direct path for attackers. Harden it with a few robust steps.

  • Use key-based authentication and disable password login
    • Edit: sudo nano /etc/ssh/sshd_config
    • Changes to apply:
      • PasswordAuthentication no
      • PermitRootLogin no
      • PubkeyAuthentication yes
      • ChallengeResponseAuthentication no
      • UsePAM yes (keep if you rely on PAM stacks)
      • Protocol 2
    • Restart: sudo systemctl reload sshd
  • Change default port only if you have a good reason
    • If you move off port 22, ensure you update your firewall rules and monitoring. Custom ports are security-by-obscurity; they don’t replace proper hardening.
  • Restrict who can log in
    • Allow only specific users: Match User in sshd_config or use AllowUsers
  • Port-knocking or two-factor on SSH (optional)
    • Consider two-factor authentication for SSH or a jump host for admin access
  • Hardening reminders
    • Enable LoginGraceTime to a short value (e.g., 60 seconds)
    • Set MaxAuthTries to a small number (e.g., 3)
    • Set MaxSessions to a small number (e.g., 2)
    • Disable empty passwords
  • Test SSH access after changes
    • Do not close your current session before validating a new connection works

Firewall and network protection

A good firewall is the last line of defense and the first line of defense against unauthorized access.

  • Default posture
    • Deny all inbound traffic by default; allow outbound as needed
  • Allow only required services
    • SSH: allow the port you configured (default 22 or your custom port)
    • Web server: open port 80 (and 443 if TLS is used)
    • Management endpoints (if any) on a restricted network or VPN
  • Example (Ubuntu/Debian with UFW)
    • sudo ufw default deny incoming
    • sudo ufw default allow outgoing
    • sudo ufw allow 22/tcp # or your custom SSH port
    • sudo ufw allow 80/tcp
    • sudo ufw allow 443/tcp
    • sudo ufw enable
    • Important: test connectivity from another session before disabling your current one
  • Consider more advanced firewalls
    • nftables (modern replacement for iptables)
    • firewalld (for RHEL-based distros)
  • Rate limiting
    • Add simple rate limits for SSH to mitigate brute-force attempts

Automatic updates and package hygiene

Keeping software up to date reduces a broad class of vulnerabilities.

  • Enable automatic security updates where appropriate
    • Debian/Ubuntu: sudo apt-get install unattended-upgrades
      • Configure in /etc/apt/apt.conf.d/20auto-upgrades
    • RHEL/CentOS: use dnf-automatic or a similar mechanism
  • Regular audits of installed software
    • Periodically run apt list —upgradable (Debian/Ubuntu) or yum/dnf check-update
  • Remove unused packages
    • sudo apt-get autoremove
    • Identify services you do not need and disable or remove the corresponding packages

Accounts, sudo, and access hygiene

Prevent privilege abuse and lateral movement by tightening account controls.

  • Principle of least privilege
    • Only grant sudo to users who truly need it
    • Prefer limited sudo privileges via visudo with careful command allowances
  • Sudo hygiene
    • Avoid NOPASSWD for routine admin tasks; require a password
    • Consider using a time-limited or command-limited sudo rule for automation tasks
  • Password hygiene
    • Enforce strong password policies if you still maintain password-based accounts
    • Disable password-based SSH and rely on key-based authentication (see SSH hardening)
  • Regular access review
    • Reconcile who has access to the VPS and remove stale accounts

Service hardening and minimization

Limit the attack surface by removing unnecessary services and hardening those you must run.

  • Inventory and disable
    • List enabled services: systemctl list-unit-files | grep enabled
    • Stop and disable services not required for your workload
  • Web server hardening
    • Use TLS (Let’s Encrypt or another CA)
    • Disable directory listing and weak ciphers
    • Enable HTTP security headers
  • Database and application services
    • Bind services to localhost where possible
    • Use strong, unique credentials and proper user permissions
  • Network services
    • Disable IPv6 if not used (or secure it similarly)
    • Keep services bound to localhost when possible for admin interfaces
  • Kernel and system hardening
    • Review sysctl.conf for security-relevant knobs (net.ipv4.ip_forward, net.bridge.bridge-nf-call-iptables, etc.)
    • Consider enabling AIDE for integrity checks on critical paths

Logging, monitoring, and anomaly detection

Visibility is essential for detecting and responding to incidents quickly.

  • Centralized logging
    • Ensure logs are written to persistent storage and rotated
    • Consider remote logging or a centralized log collector if you operate multiple servers
  • Basic monitoring
    • Collect CPU, memory, disk usage, and network I/O
    • Alert on abnormal patterns (e.g., unusual CPU spikes, high disk I/O, many failed SSH attempts)
  • Integrity and anomaly checks
    • Use AIDE to monitor filesystem changes
  • Intrusion detection basics
    • Fail2ban or similar tools can block repeated failed login attempts
    • Regularly review security-related logs (auth.log, syslog, journal)

Backups and disaster recovery

Backups are essential even in well-hardened environments.

  • Backup strategy
    • Regular backups of critical data and configuration
    • Offsite or cloud backups in addition to local copies
  • Test restore
    • Periodically verify you can restore from backups
    • Document restoration steps to ensure you can recover quickly
  • Secure backups
    • Encrypt sensitive backups and protect access keys
    • Use least privilege for backup access

Automation, reproducibility, and configuration management

Make your hardening repeatable and auditable.

  • Use configuration management tools
    • Ansible, Puppet, or Chef to enforce security baselines
  • Version your configuration
    • Store configuration files and playbooks in version control
  • Immutable or reproducible server images
    • Build and snapshot server images that you can redeploy quickly
  • Runbooks and run verification
    • Maintain runbooks for common incidents
    • Periodically re-audit to ensure controls remain effective

Ongoing maintenance and audit cadence

Security is ongoing, not a one-time task.

  • Schedule regular audits
    • Quarterly or after significant changes to the stack
  • Track findings and remediations
    • Maintain a simple issue-tracking record for security tasks
  • Stay informed
    • Subscribe to security advisories relevant to your OS and services
  • Document changes
    • Keep a changelog of security-related updates and configurations

Quick actionable checklist (starter)

  • Baseline inventory of OS, kernel, packages, users, and open ports
  • SSH hardening: key-based auth, disable root login, restrict users
  • Firewall rules: deny all inbound by default; allow necessary ports
  • Automatic security updates enabled
  • Remove unused services and minimize exposure
  • Install and run Lynis; address high-risk findings
  • Install integrity monitoring (AIDE) and log monitoring
  • Set up backups and test restore
  • Document procedures and implement a repeatable automation workflow

Conclusion

Auditing and hardening a self-hosted VPS is a continual discipline, not a single checkbox. Start with a solid baseline, apply targeted hardening to SSH and perimeters, minimize exposed services, and put monitoring and backups in place. Use repeatable processes and automation to ensure you stay secure as your workload evolves. With a methodical approach, you’ll reduce attack surface, improve resilience, and gain confidence in your self-hosted environment.