
How to Secure Your Linux VPS — Clear, Safe Steps
1. Why logging in as root is unsafe
The root
account has full control. If its password is guessed via bruteforce, the attacker owns the server. Do not log in directly as root over SSH. Create a separate user and use sudo
for admin tasks.
2. Create a non-root user
Create the user and grant admin privileges. Don’t disable password auth yet; you’ll switch to keys after confirming access works.
# Debian/Ubuntu
sudo adduser username
sudo usermod -aG sudo username
# AlmaLinux/Rocky
sudo useradd -m -s /bin/bash username
sudo passwd username
sudo usermod -aG wheel username
Log in with the new user (temporarily on port 22) to verify access:
ssh username@SERVER_IP -p 22
3. SSH key authentication (recommended)
Generate a key on your computer, copy it to the server, and test key-based login before disabling passwords.
# On your computer (client)
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/mh-vps-ed25519
ssh-copy-id -i ~/.ssh/mh-vps-ed25519.pub username@SERVER_IP
# Test key login (still on port 22)
ssh -i ~/.ssh/mh-vps-ed25519 username@SERVER_IP -p 22
If ssh-copy-id
is unavailable, add the key manually:
# On the server (as username)
mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo 'PUBLIC_KEY_CONTENT' >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
4. Prepare the firewall (don’t change the SSH port yet)
Allow both the old port (22) and the new one (e.g., 2222), then enable the firewall. This prevents locking yourself out when you switch ports.
# Debian/Ubuntu — UFW
sudo apt update && sudo apt install -y ufw
sudo ufw allow 22/tcp comment 'SSH old'
sudo ufw allow 2222/tcp comment 'SSH new'
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable
sudo ufw status verbose
# AlmaLinux/Rocky — firewalld (and SELinux)
sudo dnf install -y firewalld policycoreutils-python-utils
sudo systemctl enable --now firewalld
sudo firewall-cmd --permanent --add-service=ssh # 22
sudo firewall-cmd --permanent --add-port=2222/tcp # 2222
sudo firewall-cmd --reload
# If SELinux is Enforcing, register the new port for sshd
sudo semanage port -a -t ssh_port_t -p tcp 2222 2>/dev/null || sudo semanage port -m -t ssh_port_t -p tcp 2222
sestatus # check SELinux state
5. Configure sshd — keep both ports temporarily
Edit OpenSSH. Keep Port 22
and add Port 2222
until you confirm access on the new port. Disable root login and passwords only after key login works.
sudoedit /etc/ssh/sshd_config # or: sudo nano /etc/ssh/sshd_config
Add or update the following:
# Keep both ports until access on 2222 is confirmed
Port 22
Port 2222
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
# (optional) Restrict to your user only
# AllowUsers username
Validate syntax and apply without dropping active sessions (reload, not restart):
# Syntax check
sudo sshd -t && echo "OK"
# Debian/Ubuntu
sudo systemctl reload ssh
# AlmaLinux/Rocky
sudo systemctl reload sshd
Test the new port from a separate terminal:
ssh -i ~/.ssh/mh-vps-ed25519 username@SERVER_IP -p 2222
6. After 2222 works, disable 22
Once key login on 2222 works, remove port 22 from sshd and the firewall, then reload.
# In sshd_config: keep ONLY the new port
sudo sed -i 's/^Port 22/# Port 22 (disabled)/' /etc/ssh/sshd_config
# or edit manually and keep only: Port 2222
# Apply safely
# Debian/Ubuntu
sudo systemctl reload ssh
# AlmaLinux/Rocky
sudo systemctl reload sshd
# Debian/Ubuntu — close 22 in UFW
sudo ufw delete allow 22/tcp
# AlmaLinux/Rocky — close 22 in firewalld
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
7. Verify listening ports
Confirm only the new port is open and SSH is listening on it.
sudo ss -tulpen | grep :2222
8. Bruteforce protection and automatic updates
Install fail2ban to block repeated attempts and enable automatic OS updates.
# Debian/Ubuntu — fail2ban + unattended upgrades
sudo apt install -y fail2ban unattended-upgrades
sudo tee /etc/fail2ban/jail.local >/dev/null <<'EOF'
[sshd]
enabled = true
port = 2222
maxretry = 5
findtime = 10m
bantime = 1h
EOF
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
# Enable automatic security updates
sudo dpkg-reconfigure --priority=low unattended-upgrades
# AlmaLinux/Rocky — fail2ban + dnf-automatic
sudo dnf install -y epel-release
sudo dnf install -y fail2ban dnf-automatic
sudo tee /etc/fail2ban/jail.local >/dev/null <<'EOF'
[sshd]
enabled = true
port = 2222
maxretry = 5
findtime = 10m
bantime = 1h
EOF
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
# Automatic updates
sudo sed -i 's/^apply_updates = .*/apply_updates = yes/' /etc/dnf/automatic.conf
sudo systemctl enable --now dnf-automatic.timer
9. More quick hardening tips
Disable or remove unused services (Telnet, FTP). Examples: sudo systemctl disable --now vsftpd
, sudo apt remove -y telnetd
/ sudo dnf remove -y telnet-server
.
Do not expose databases to the internet; bind to 127.0.0.1 or a private network only.
Schedule regular backups (files + databases) and test restores.
Use unique passwords + a password manager for non-SSH accounts (e.g., web apps).
10. Conclusion
Solid security means: a non-root user, SSH keys, a properly configured firewall, and a careful port migration (test first, then disable the old port). With fail2ban
and automatic updates, you significantly reduce risk on any distro.