A freshly provisioned Hong Kong VPS with default settings is an open target. Within minutes of a new server going live with a public IP address, automated scanners begin probing for open ports, default credentials, and unpatched vulnerabilities. If you do not harden your server before deploying your application, you are racing against bots that run 24 hours a day.
This checklist covers the ten most impactful security measures for a Linux VPS — tested and applicable to Ubuntu 22.04 LTS, the recommended OS for Server.HK Hong Kong VPS deployments. Work through these steps in order immediately after provisioning, before installing any application software.
Step 1: Change the Default SSH Port
Port 22 is the default SSH port and the first port automated scanners check. Changing it to a non-standard port above 1024 eliminates the vast majority of automated brute-force attempts without any other configuration change — not because it is more secure by design, but because it filters out the enormous volume of unsophisticated automated attacks that only target port 22.
nano /etc/ssh/sshd_configFind the line #Port 22 and change it to a non-standard port (choose any unused port between 1025 and 65535, e.g. 2277):
Port 2277Save the file. Before restarting SSH, open the new port in your firewall to avoid locking yourself out:
ufw allow 2277/tcp
ufw deny 22/tcpNow restart SSH:
systemctl restart sshdOpen a new SSH session on the new port to verify it works before closing your existing session:
ssh -p 2277 root@YOUR_VPS_IPOnly close the original session after confirming the new port connects successfully.
Step 2: Disable Root Login and Use SSH Key Authentication
Password-based SSH authentication is vulnerable to brute-force attacks. SSH key authentication — where access requires possession of a private key file rather than knowledge of a password — is effectively immune to brute-force attempts because the key space is astronomically large.
Generate an SSH key pair on your local machine
ssh-keygen -t ed25519 -C "your-email@example.com"Ed25519 keys are recommended over RSA for new key generation — they are shorter, faster, and considered more secure. Save the key to the default location (~/.ssh/id_ed25519).
Copy the public key to your VPS
ssh-copy-id -p 2277 root@YOUR_VPS_IPOr manually append the public key to ~/.ssh/authorized_keys on the server:
cat ~/.ssh/id_ed25519.pub | ssh -p 2277 root@YOUR_VPS_IP \
"mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"Disable password authentication and root login
nano /etc/ssh/sshd_configSet the following values (uncomment lines if necessary):
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
X11Forwarding no
MaxAuthTries 3
LoginGraceTime 20Create a non-root sudo user if you have not already (you will use this to log in after disabling root):
adduser deploy
usermod -aG sudo deploy
# Copy authorized_keys to the new user
mkdir -p /home/deploy/.ssh
cp ~/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keysRestart SSH and verify you can log in as the non-root user with your key before closing the root session:
systemctl restart sshd
ssh -p 2277 deploy@YOUR_VPS_IPStep 3: Configure UFW Firewall with Minimal Open Ports
A firewall is the single most important network-level security control on a VPS. The principle is simple: deny everything by default, then explicitly allow only the ports your applications need.
# Set default policies
ufw default deny incoming
ufw default allow outgoing
# Allow SSH on your custom port
ufw allow 2277/tcp
# Allow HTTP and HTTPS for web applications
ufw allow 80/tcp
ufw allow 443/tcp
# Enable the firewall
ufw enable
ufw status verboseAdd application-specific ports only as needed (e.g. ufw allow 25565/tcp for Minecraft, ufw allow 27015/udp for CS2). Every open port is a potential attack surface — keep the list as short as possible.
Restrict SSH to your own IP address (highly recommended)
If you have a static IP address or a small set of known IPs from which you administer the server, restrict SSH access to those IPs only:
ufw delete allow 2277/tcp
ufw allow from YOUR_HOME_IP to any port 2277 proto tcpThis makes SSH brute-force attacks from external IPs impossible — the firewall drops the connection before SSH even sees it.
Step 4: Install and Configure Fail2Ban
Even with SSH keys enabled, Fail2Ban provides an additional layer of protection by monitoring log files for repeated authentication failures and temporarily banning the offending IP addresses at the firewall level.
apt install -y fail2banCreate a local configuration file (always use .local files to override defaults — they survive package updates):
nano /etc/fail2ban/jail.local[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
backend = systemd
[sshd]
enabled = true
port = 2277
logpath = %(sshd_log)s
maxretry = 3
bantime = 86400
[nginx-http-auth]
enabled = true
[nginx-limit-req]
enabled = true
filter = nginx-limit-req
action = iptables-multiport[name=ReqLimit, port="http,https", protocol=tcp]
logpath = /var/log/nginx/error.log
findtime = 600
maxretry = 10
bantime = 7200Start and enable Fail2Ban:
systemctl enable fail2ban
systemctl start fail2ban
fail2ban-client statusMonitor active bans:
fail2ban-client status sshdStep 5: Enable Automatic Security Updates
Unpatched software is the most common root cause of VPS compromises. The majority of successful attacks exploit known vulnerabilities for which patches have already been released — the attacker relies on administrators not applying updates promptly.
Ubuntu’s unattended-upgrades package automatically applies security updates without requiring manual intervention:
apt install -y unattended-upgrades apt-listchanges
dpkg-reconfigure -plow unattended-upgradesSelect Yes when prompted. Configure the behaviour:
nano /etc/apt/apt.conf.d/50unattended-upgradesEnsure the following lines are uncommented and configured:
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}-security";
"${distro_id}ESMApps:${distro_codename}-apps-security";
"${distro_id}ESM:${distro_codename}-infra-security";
};
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::MinimalSteps "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Mail "your@email.com";Setting Automatic-Reboot to false prevents unplanned reboots for kernel updates — you control when reboots happen. Set up email notifications so you know when security updates are applied.
Step 6: Secure Shared Memory
The /run/shm shared memory segment is writable by all users by default and has historically been exploited in privilege escalation attacks. Mount it as read-only with execution disabled:
nano /etc/fstabAdd the following line:
tmpfs /run/shm tmpfs defaults,noexec,nosuid,nodev 0 0Apply without rebooting:
mount -o remount /run/shmStep 7: Harden Kernel Network Parameters
Linux kernel network parameters can be tuned to protect against common network-based attacks including SYN floods, IP spoofing, and ICMP-based reconnaissance:
nano /etc/sysctl.confAdd the following security-focused parameters:
# Prevent SYN flood attacks
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5
# Prevent IP spoofing
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Disable IP source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# Disable ICMP redirect acceptance
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
# Ignore ICMP broadcast requests (Smurf attack protection)
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Ignore bogus ICMP error responses
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Log suspicious packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
# Disable IPv6 if not in use
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1Apply all changes:
sysctl -pStep 8: Install and Run Rootkit Detection
Rootkit detection tools scan your system for signs of compromise — hidden processes, modified system binaries, suspicious files, and known rootkit signatures. Run these tools regularly as part of your security monitoring routine.
Rkhunter (Rootkit Hunter)
apt install -y rkhunter
rkhunter --update
rkhunter --propupd
rkhunter --check --skip-keypressOn a freshly provisioned clean system, rkhunter should report no warnings. If warnings appear, investigate each one — some are false positives from legitimate software, others may indicate real issues.
Chkrootkit
apt install -y chkrootkit
chkrootkitSchedule weekly automated scans:
crontab -e
# Add:
0 3 * * 0 /usr/bin/rkhunter --check --skip-keypress --report-warnings-only | mail -s "rkhunter Weekly Scan: $(hostname)" your@email.comStep 9: Configure Log Monitoring and Alerting
Security events you do not know about cannot be responded to. Log monitoring ensures suspicious activity generates actionable alerts rather than disappearing silently into log files.
Install Logwatch for daily log summaries
apt install -y logwatch
nano /etc/logwatch/conf/logwatch.confOutput = mail
Format = html
MailTo = your@email.com
MailFrom = logwatch@YOUR_VPS_HOSTNAME
Range = yesterday
Detail = Med
Service = AllLogwatch sends a daily email digest summarising SSH login attempts, failed authentications, Nginx errors, sudo usage, and other security-relevant log events — giving you a daily overview without having to manually review log files.
Monitor authentication logs in real time
# Watch live SSH login attempts
journalctl -fu sshd
# View recent failed authentication attempts
grep "Failed password\|Invalid user" /var/log/auth.log | tail -50
# View Fail2Ban ban events
grep "Ban\|Unban" /var/log/fail2ban.log | tail -50Step 10: Enable and Test Regular Backups
Security hardening reduces the probability of compromise — but no hardening is perfect. The final layer of any security strategy is the ability to recover quickly and completely from a compromise or data loss event. Backups are not optional.
Automated daily backup to a remote location
Install restic — a modern, encrypted backup tool that works with any S3-compatible storage:
apt install -y resticInitialise a backup repository (example using any S3-compatible endpoint):
export AWS_ACCESS_KEY_ID=your_access_key
export AWS_SECRET_ACCESS_KEY=your_secret_key
restic -r s3:https://s3.your-provider.com/your-bucket initCreate a backup script:
nano /root/backup.sh#!/bin/bash
export AWS_ACCESS_KEY_ID=your_access_key
export AWS_SECRET_ACCESS_KEY=your_secret_key
RESTIC_PASSWORD=your_encryption_password
REPO="s3:https://s3.your-provider.com/your-bucket"
restic -r $REPO --password-command "echo $RESTIC_PASSWORD" backup \
/etc \
/home \
/var/www \
/var/lib/mysql \
--exclude /home/*/.cache \
--exclude /var/cache
# Keep last 7 daily, 4 weekly, 3 monthly snapshots
restic -r $REPO --password-command "echo $RESTIC_PASSWORD" forget \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 3 \
--prunechmod 700 /root/backup.shSchedule daily backups at 03:00:
crontab -e
# Add:
0 3 * * * /root/backup.sh >> /var/log/restic-backup.log 2>&1Test your backup
A backup you have never tested is not a backup — it is hope. Verify the backup is readable and restorable:
restic -r s3:https://s3.your-provider.com/your-bucket snapshots
restic -r s3:https://s3.your-provider.com/your-bucket checkSecurity Hardening Checklist Summary
| # | Action | Priority | Time Required |
|---|---|---|---|
| 1 | Change default SSH port | 🔴 Critical | 5 min |
| 2 | Disable root login + enable SSH key auth | 🔴 Critical | 10 min |
| 3 | Configure UFW firewall (deny by default) | 🔴 Critical | 5 min |
| 4 | Install and configure Fail2Ban | 🔴 Critical | 10 min |
| 5 | Enable automatic security updates | 🟠 High | 5 min |
| 6 | Secure shared memory | 🟠 High | 2 min |
| 7 | Harden kernel network parameters | 🟠 High | 5 min |
| 8 | Install rootkit detection tools | 🟡 Medium | 10 min |
| 9 | Configure log monitoring and alerting | 🟡 Medium | 15 min |
| 10 | Set up encrypted remote backups | 🔴 Critical | 20 min |
Total time to complete all 10 steps on a fresh VPS: approximately 90 minutes. This investment protects your server, your data, and your users for the entire lifetime of the deployment.
Conclusion
Server security is not a one-time setup — it is an ongoing practice. The 10 steps in this checklist establish the baseline that every production Hong Kong VPS should have in place before going live. Once configured, the maintenance burden is minimal: Fail2Ban and automatic updates run silently in the background, Logwatch delivers daily summaries, and restic handles backups on schedule.
The most important insight from this checklist: the biggest security risks on a VPS are not exotic zero-day exploits. They are default SSH passwords left unchanged, port 22 open to the world, no firewall configured, and no backups running. Fix those four things and you have eliminated the vast majority of real-world VPS compromise scenarios.
Looking for a Hong Kong VPS with DDoS protection included as standard? Server.HK’s Hong Kong VPS plans include network-level DDoS mitigation alongside KVM virtualisation, NVMe SSD storage, and CN2 GIA routing — giving you a secure, high-performance foundation to build on.
Frequently Asked Questions
Does changing the SSH port really improve security?
It does not make SSH cryptographically more secure, but it eliminates automated scanning attacks that only target port 22 — which represent the large majority of brute-force attempts on public-facing VPS servers. Combined with SSH key authentication and Fail2Ban, changing the port removes most of the noise from your authentication logs and reduces risk from unsophisticated attacks.
Is Fail2Ban enough to protect SSH without changing the port?
Fail2Ban alone provides meaningful protection by banning IPs after repeated failed attempts. However, it introduces a small delay — an attacker gets 3 attempts before a ban triggers. SSH key authentication is the more robust solution: without the private key, an attacker cannot authenticate regardless of how many attempts they make. Use both together for defence in depth.
How often should I run rkhunter on my Hong Kong VPS?
Weekly automated scans (as configured in Step 8) are appropriate for most VPS deployments. Run a manual scan immediately after any unusual server behaviour — unexpected high CPU usage, unexplained outbound traffic, or suspicious processes appearing in htop. Update rkhunter’s database monthly with rkhunter --update.
Should I disable IPv6 on my Hong Kong VPS?
If your application does not require IPv6 connectivity, disabling it reduces attack surface — there are fewer interfaces to monitor and secure. If you need IPv6 for your application or your users require it, leave it enabled and apply equivalent hardening rules to the IPv6 stack (ip6tables or UFW IPv6 rules).
Does Server.HK provide any built-in DDoS protection for Hong Kong VPS?
Yes. Server.HK includes network-level DDoS mitigation as standard on Hong Kong VPS plans. This handles volumetric attacks at the network level before traffic reaches your server — complementing the application-level security measures in this guide rather than replacing them.