Back to tutorials
Tutorial

Server Hardening Tutorial (2026): Secure a New Ubuntu VPS for Web Hosting Without Locking Yourself Out

Server hardening tutorial for Ubuntu VPS in 2026: SSH keys, sudo, updates, firewall, fail2ban, audits, and safe rollback steps.

By Anurag Singh
Updated on Sep 26, 2026
Category: Tutorial
Share article
Server Hardening Tutorial (2026): Secure a New Ubuntu VPS for Web Hosting Without Locking Yourself Out

A new VPS doesn’t stay “quiet” for long. Within minutes, bots will probe SSH, scan common web paths, and hammer login prompts.

This server hardening tutorial gives you a clean baseline for an Ubuntu hosting VPS in 2026. You’ll set up SSH keys, least privilege, patching, firewall rules that keep you connected, and quick checks that catch mistakes before they cause outages.

If you’d rather not build the platform layer yourself, start with a HostMyCode VPS for full control. Or pick managed VPS hosting if you want updates, monitoring, and hardening reviewed by humans.

What you’ll harden (and what you won’t)

This guide focuses on controls that prevent most VPS compromises. That includes weak SSH access, stale packages, exposed admin ports, and services you didn’t mean to publish.

You won’t find “security theater” here. You also won’t find tweaks that add ongoing maintenance for questionable gains.

  • You will do: SSH key-only access, a non-root admin user, sane sudo, automatic security updates, UFW rules, Fail2ban, basic auditing, and log review.
  • You won’t do: complicated network overlays, Kubernetes policies, or custom kernel hardening. Good hosting security starts with simpler wins.

Prerequisites (quick checklist)

  • Ubuntu Server 24.04 LTS or 25.04 (commands work the same).
  • Console access via your VPS panel (for emergencies).
  • A domain name (optional today, required later for mail/SSL). You can register/point it via HostMyCode domains.
  • Local machine with OpenSSH client (macOS/Linux) or Windows Terminal + OpenSSH.

Step 0: Take a “before” snapshot (fast rollback insurance)

Make changes only when you can roll back fast. If your provider supports snapshots, take one before you touch SSH or firewall rules.

  1. Snapshot the VM/disk using your provider panel.
  2. Label it clearly: pre-hardening-ubuntu.

If you want a repeatable method you can run yourself, follow the approach in VPS Snapshot Tutorial (2026).

Step 1: Create a non-root admin user (and stop daily root logins)

Don’t live in root. Create an admin user, grant sudo, and use that account for normal work.

adduser admin
usermod -aG sudo admin

Before you change anything SSH-related, prove sudo works:

su - admin
sudo -v
sudo whoami

You want root as the output of sudo whoami.

Step 2: Set up SSH keys (and keep a safe session open)

Open a second terminal now. Keep your current session connected through Step 4. This one habit prevents most lockouts.

Generate a key on your laptop (if you don’t have one)

ssh-keygen -t ed25519 -a 64 -C "admin@yourdomain"

Accept the default path. Use a passphrase. If your laptop is stolen, the passphrase is what protects your server.

Copy the public key to the server

From your laptop:

ssh-copy-id -i ~/.ssh/id_ed25519.pub admin@SERVER_IP

If you’re on Windows and don’t have ssh-copy-id, paste the public key into /home/admin/.ssh/authorized_keys. Then fix permissions:

sudo mkdir -p /home/admin/.ssh
sudo nano /home/admin/.ssh/authorized_keys
sudo chown -R admin:admin /home/admin/.ssh
sudo chmod 700 /home/admin/.ssh
sudo chmod 600 /home/admin/.ssh/authorized_keys

Confirm key login works

ssh -i ~/.ssh/id_ed25519 admin@SERVER_IP

Do not continue until this works reliably.

Step 3: Tighten SSH daemon settings (without breaking access)

Now lock down SSH on the server side.

On Ubuntu, the main file is /etc/ssh/sshd_config. Some settings may also live in /etc/ssh/sshd_config.d/*.conf.

sudo nano /etc/ssh/sshd_config

Apply these settings (add them if missing). Only change the port if you’ll also open it in UFW in Step 4.

# Keep the default port unless you have a reason
Port 22

PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
UsePAM yes

# Limit who can SSH
AllowUsers admin

# Faster disconnect of dead sessions
ClientAliveInterval 300
ClientAliveCountMax 2

Validate the config before you reload SSH:

sudo sshd -t

If that returns nothing, reload SSH. Reload is safer than restart:

sudo systemctl reload ssh

Then test from a new terminal. Keep the original session open until the test login succeeds.

If you want a deeper pass (keys, 2FA, and rollback steps), see SSH Lockdown Tutorial (2026).

Step 4: Configure a firewall that doesn’t cut off SSH

Ubuntu ships with UFW. The classic mistake is enabling it before allowing SSH.

Always allow SSH first.

sudo ufw default deny incoming
sudo ufw default allow outgoing

# Allow SSH first
sudo ufw allow 22/tcp

# If this is a web server
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

sudo ufw enable
sudo ufw status verbose

If you run mail on this VPS, don’t open a pile of ports “just in case.” Open only what you use. Before you expose SMTP, verify deliverability prerequisites (rDNS/PTR, SPF/DKIM, etc.).

This guide stays grounded: VPS Email Setup Tutorial (2026).

Need a cloud firewall + UFW pattern that keeps SSH safe? Use the checklist in VPS Firewall Setup Guide Tutorial (2026).

Step 5: Patch baseline packages and enable unattended security updates

Most compromised VPSs weren’t “cleverly hacked.” They were simply behind on updates.

Bring the system current, then let Ubuntu apply security patches automatically.

sudo apt update
sudo apt -y full-upgrade
sudo apt -y autoremove --purge

Enable unattended upgrades:

sudo apt -y install unattended-upgrades apt-listchanges
sudo dpkg-reconfigure -plow unattended-upgrades

Check what it will do:

sudo systemctl status unattended-upgrades --no-pager
sudo unattended-upgrade --dry-run --debug | less

Kernel upgrades still require reboots. Plan for them.

If you want a production-safe approach (including reboot timing), follow VPS Security Update Tutorial (2026).

Step 6: Add Fail2ban for SSH noise and credential-stuffing

Even with password login disabled, Fail2ban cuts log spam and blocks repeat attempts.

It also gives you cover if you temporarily re-enable passwords during an incident.

sudo apt -y install fail2ban
sudo systemctl enable --now fail2ban

Create a minimal local config:

sudo nano /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true
mode = aggressive
bantime = 1h
findtime = 10m
maxretry = 5

Restart and confirm:

sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Pitfall: if you SSH from a VPN or jump host, add trusted IPs to ignoreip.

Don’t whitelist 0.0.0.0/0. That removes the protection.

Step 7: Reduce exposed services (quick audit)

Before you install a web stack, check what’s already listening.

A “clean” VPS sometimes includes extras you didn’t ask for.

sudo ss -tulpn

On a fresh Ubuntu VPS you’ll usually see SSH and a few local-only services.

If you see a public-facing port you don’t recognize, identify it before you go further:

sudo lsof -i -P -n | grep LISTEN
sudo systemctl status SERVICE_NAME --no-pager

Step 8: Basic system auditing you’ll actually read

Hardening doesn’t help if nobody looks at the output. Aim for a small daily report.

Also confirm logs rotate.

Install Logwatch

sudo apt -y install logwatch

Run a one-time report to see what shows up:

sudo logwatch --detail high --range yesterday --service all --mailto you@example.com

For a clean setup and mail delivery assumptions, use Logwatch Setup Tutorial (2026).

Confirm log rotation is active

systemctl status logrotate.timer --no-pager

Once you add Nginx/Apache/PHP, log rotation becomes a disk-space issue.

This guide is tuned for hosting workloads: Logrotate Tutorial (2026).

Step 9: Set correct hostname + time sync (prevents weird SSL and mail issues)

Time drift breaks TLS validation. It also makes incident timelines useless.

Hostname mismatches cause avoidable mail problems.

Set an FQDN hostname

sudo hostnamectl set-hostname vps1.yourdomain.com
hostnamectl

Confirm NTP/chrony is working

timedatectl

You want System clock synchronized: yes. If it’s not, troubleshoot with VPS Time Sync Troubleshooting Tutorial (2026).

Step 10: Add a “break glass” access path (jump host or console plan)

Your security improves if SSH isn’t exposed publicly at all.

A common setup is a bastion (jump host). Only the bastion allows inbound SSH from the internet. Your web/mail VPS allows SSH only from the bastion IP.

If that fits your environment, follow SSH Jump Host setup guide tutorial (2026).

At minimum, write this down somewhere your team can find:

  • Where your provider console is (and who has access).
  • How to revert a snapshot.
  • How to temporarily allow SSH from a known IP in UFW.

Step 11: Hosting-specific hardening notes (web stacks and control panels)

At this point, the OS baseline is in good shape. What comes next depends on how you host sites.

If you’re installing a control panel (cPanel/DirectAdmin/Plesk)

Control panels save time. They also expand the attack surface.

Keep the basics tight:

  • Restrict panel access to your office/VPN IPs where possible.
  • Use 2FA for every admin.
  • Separate nameservers if you run reseller hosting.
  • Backups are not optional; test restores monthly.

If you run cPanel, keep a dedicated security checklist. This guide stays specific: cPanel Hardening Tutorial (2026).

If you’re hosting WordPress without a control panel

Use least privilege per site. That means separate Unix users, per-site PHP-FPM pools, and predictable permissions.

After your stack is up, tune PHP-FPM so one noisy site can’t stall the whole VPS. This guide covers the practical settings: VPS PHP-FPM Pool Tuning Tutorial (2026).

Verification: a 5-minute hardening self-test

Run these checks once you finish the steps above.

  • SSH: password auth disabled
    sudo sshd -T | egrep 'passwordauthentication|permitrootlogin|kbdinteractiveauthentication'
    
  • Firewall: only required ports open
    sudo ufw status numbered
    sudo ss -tulpn | head
    
  • Updates: unattended upgrades running
    systemctl status unattended-upgrades --no-pager
    grep -R "Unattended-Upgrade" /var/log/unattended-upgrades/ | tail -n 20
    
  • Fail2ban: jail active
    sudo fail2ban-client ping
    sudo fail2ban-client status sshd
    
  • Reboot required:
    [ -f /var/run/reboot-required ] && cat /var/run/reboot-required || echo "No reboot required"
    

Common mistakes (and quick fixes)

  • You enabled UFW before allowing SSH. Use the provider console, then run ufw allow 22/tcp and ufw reload.
  • SSH key login fails. Fix perms: chmod 700 ~/.ssh, chmod 600 ~/.ssh/authorized_keys, and ensure correct ownership.
  • You locked SSH to one user, but used the wrong username. In console, edit /etc/ssh/sshd_config and reload SSH.
  • Fail2ban bans you. Unban from console: sudo fail2ban-client set sshd unbanip YOUR_IP. Then add your IP to ignoreip if appropriate.

Summary: your baseline for a hosting-grade Ubuntu VPS

You now have the basics done right: no root SSH, no password logins, a firewall that exposes only what you need, automatic security updates, and basic intrusion throttling.

It’s a solid foundation for WordPress, email, or a control panel—without turning every week into cleanup work.

If you’re building this for client sites or revenue workloads, consider starting on managed VPS hosting. That way, patching, monitoring, and security reviews don’t depend on your free time.

If you want full control at a predictable monthly cost, a HostMyCode VPS is a clean base for the steps in this tutorial.

Want a VPS that’s ready for real hosting work, not just a blank Linux image? HostMyCode offers VPS plans sized for everything from small sites to high-traffic workloads, plus managed VPS hosting when you want hardening, updates, and monitoring handled professionally.

FAQ

Should I change the SSH port from 22?

It reduces noise, not risk. Key-only auth + Fail2ban matters more. If you do change it, update UFW first and keep console access available.

Is UFW enough, or do I need a provider firewall too?

Use both if available. A provider firewall drops traffic before it hits your VM, while UFW protects you from mistakes inside the OS.

What’s the minimum open ports for a WordPress VPS?

Usually 22/tcp (SSH), 80/tcp (HTTP), and 443/tcp (HTTPS). Add mail ports only if you actually run mail on that server.

How often should I reboot for kernel updates?

As soon as practical after security kernel upgrades. Many teams schedule a weekly maintenance window, and reboot sooner for critical advisories.

Do I need Fail2ban if passwords are disabled?

It’s still useful for log noise reduction and as a safety net if password auth gets re-enabled during troubleshooting.