A fresh server is exposed with password root login and gets brute-forced immediately. Close the basic holes in ten minutes: a sudo user, key login, sshd, ufw, auto-updates.
A fresh HIP server with Ubuntu 24.04 comes up with a public IP and password-based root login. Automated scanners start hitting it within minutes of the IP going live - on our test box the failed-login counter passed 17,000 in a few hours. This initial server setup closes the basic holes in about ten minutes: a non-root user, key-only login, no password auth, a firewall, and automatic security updates. The commands below were run on a clean Ubuntu 24.04 box.
TL;DR. Log in as root, create a sudo user, add your SSH key to it. In a second terminal confirm key login works. Disable root login and password auth in sshd, enable ufw (allow SSH first) and unattended-upgrades. After that sshd no longer accepts password authentication, so brute-forcing the password over SSH stops making sense.
deploy with sudo - you work as this user, not root.sshd.ufw firewall: only port 22 open inbound.The IP address and root password are on the server page in the panel, under How to connect. The same page has the web console button - you will need it if you ever lock yourself out of SSH. If you do not have a server yet, create one first - see "How to create a server in the HIP panel".
Connect from your machine (Windows - PuTTY or the built-in ssh; macOS and Linux - ssh in a terminal):
ssh root@YOUR-IPRunning as root full-time is risky: every mistake runs with full privileges, and root over SSH is the number-one brute-force target. Create a regular user and grant it sudo.
adduser deployusermod -aG sudo deployid deployid deploy should show the sudo group:
uid=1001(deploy) gid=1001(deploy) groups=1001(deploy),27(sudo)adduser creates the user and home directory and asks for a password - you need one, sudo will prompt for it. On Ubuntu, membership in the sudo group is what grants sudo.
A key is a pair of files on your machine: the private half stays with you, the public half goes on the server. Whoever presents the private key gets in - no password, and a key cannot be brute-forced. If you have no key yet, run ssh-keygen -t ed25519 on your machine; the .pub file is what you copy.
install -d -m 700 -o deploy -g deploy /home/deploy/.sshnano /home/deploy/.ssh/authorized_keys # paste one line from your .pubchmod 600 /home/deploy/.ssh/authorized_keyschown deploy:deploy /home/deploy/.ssh/authorized_keysRecommended modes are 700 for .ssh and 600 for authorized_keys. What actually matters is that the directory, the file and the home directory are not writable by other users: with an unsafe owner or permissions, sshd under StrictModes can refuse the key - and the reason is in the sshd/journal logs.
Do not skip this. Before you disable anything in sshd, open another terminal and confirm the new user logs in with the key and that sudo works. Keep the first session open as a safety net.
ssh deploy@YOUR-IPdeploy@server:~$ sudo whoamirootsshd is the SSH service on the server. Don't edit the main config - drop a file into /etc/ssh/sshd_config.d/ so your changes survive package upgrades.
nano /etc/ssh/sshd_config.d/99-hardening.confPermitRootLogin noPasswordAuthentication noPubkeyAuthentication yesKbdInteractiveAuthentication noX11Forwarding noMaxAuthTries 3Check the syntax and apply without dropping open sessions:
sshd -t && echo OKsystemctl reload sshPermitRootLogin no - no root over SSH. PasswordAuthentication no - key only. sshd -t is mandatory before reloading: a broken config keeps sshd from starting and you are locked out.
Ubuntu cloud-image gotcha. Runsshd -T | grep -i passwordauthenticationafterwards and you will probably still seeyes. On Ubuntu cloud images,50-cloud-init.confin the same directory already setsPasswordAuthentication yes, andsshdtakes the first value it finds for such keys. Your99-*file is read later and ignored. Fix: name it so it is read first:
grep -R -n -i passwordauthentication /etc/ssh/sshd_config.d/mv /etc/ssh/sshd_config.d/99-hardening.conf /etc/ssh/sshd_config.d/00-hardening.confsshd -t && systemctl reload sshsshd -T | grep -Ei 'permitrootlogin|passwordauthentication|kbdinteractiveauthentication|maxauthtries'
The output should now show permitrootlogin no, passwordauthentication no, kbdinteractiveauthentication no and maxauthtries 3.
The config is applied - but keep the current root session open. Open a NEW SSH session as deploy, confirm it logs in with the applied config, and run sudo -v. Only when that works, close the old root session.
ssh deploy@YOUR-IP
sudo -v
ufw is a thin wrapper over the Linux firewall. Add the SSH rule first: enable ufw with a deny-inbound policy and no rule for port 22, and your session drops with no way back in.
ufw allow OpenSSHufw --force enableufw status verboseufw app info OpenSSH
The OpenSSH profile is 22/tcp. If you have moved SSH to another port, allow that port explicitly (ufw allow 2222/tcp) instead of the profile.
Add web-server profiles (Nginx Full, etc.) later, once the web server is installed.
Unpatched known vulnerabilities are one of the main risks for a public server. unattended-upgrades installs security updates once a day on its own.
On Ubuntu 24.04 unattended-upgrades is usually already installed and enabled - check before changing anything:
systemctl status unattended-upgrades.service
apt-config dump | grep -Ei 'Periodic::(Update-Package-Lists|Unattended-Upgrade)'
Two "1" lines and an active service mean it is on. If it is off:
apt-get install -y unattended-upgradesdpkg-reconfigure -f noninteractive unattended-upgradescat /etc/apt/apt.conf.d/20auto-upgradesTwo "1" lines in 20auto-upgrades mean the package-list refresh and the upgrade step are both on. The server does not reboot after a kernel update by default; enable Unattended-Upgrade::Automatic-Reboot if you want that.
Root over SSH must be rejected; the new user with the key must work:
ssh root@YOUR-IProot@YOUR-IP: Permission denied (publickey).ssh deploy@YOUR-IPdeploy@server:~$fail2ban - bans IPs after repeated failures; mostly log-noise reduction once passwords are off.SSH is not the only way in. The server page in the panel has a web console (serial console) that bypasses sshd and the firewall - use it to log in as root with the password and fix the config. Keep the panel root password even after disabling SSH password auth.
Three things: a separate sudo user, SSH key login, and disabling password and root login in sshd. Then the ufw firewall and automatic updates. That is the baseline initial server setup; everything else depends on the workload.
A remote SSH login straight into a privileged account is not needed for day-to-day work. A separate user plus sudo keeps privilege escalation a distinct step and limits what runs directly as UID 0.
/etc/ssh/sshd_config.d/50-cloud-init.conf sets PasswordAuthentication yes and is read before your file, and sshd takes the first match. Name your file 00-hardening.conf or edit 50-cloud-init.conf.
Log in as root via the panel's web console, add a new public key to authorized_keys, temporarily set PasswordAuthentication yes if needed.
Yes. Services tend to appear - install a database and it may listen on 0.0.0.0. With ufw that port stays closed until you add an explicit rule.
sudo user.sshd.00-hardening.conf or 50-cloud-init.conf overrides it.ufw before enabling the firewall.unattended-upgrades so known holes close without you.