ClouduxeDocs

Securing a new server

A hardening checklist in the order that matters, starting with the mistakes that actually get servers taken over.

A new server is reachable from the whole internet the moment it finishes building, and automated scanners find new addresses on their own, without anyone choosing you. This page is the order to work in, with the things that actually get servers compromised at the top.

Almost nothing on this list is clever. Servers are lost to a guessed password, a database left listening on a public address, or a piece of third-party code someone downloaded from a forum. Work down the list and stop worrying about the exotic attacks until the ordinary ones are closed.

The checklist

  1. Get the credentials right. Key-based SSH, password sign-in off, and no password reused from anywhere else.
  2. Close what should not be listening. Everything on a public address is a way in. Most services do not need one.
  3. Keep software patched, including the code you did not write. Automatic OS updates, and real care with game server resources and plugins.
  4. Stop signing in as root. A separate user with sudo limits what one mistake or one stolen session can do.
  5. Slow down brute force. Fail2ban and a sane SSH port policy.
  6. Have backups you have restored. The control that decides how bad the worst day is.
  7. Secure the account that controls the server. Your Clouduxe sign-in can rebuild the machine. Treat it accordingly.

Items 1 and 2 are not first because they are quick. They are first because almost every compromised server this documentation exists for was lost to one of them. A fully patched machine with a weak root password is still lost, and so is a hardened SSH configuration on a box with an unauthenticated database on a public port.

Credentials, first

Use a key, then turn password sign-in off

A password on port 22 is guessed at continuously by software that does nothing else. A key is not guessable in the same way, and once password authentication is off, the entire category of attack stops working against you rather than being slowed down.

The order matters, because doing this in the wrong order locks you out:

  1. Add your public key to the server and confirm you can sign in with it in a second terminal, without closing the first.
  2. Only then set PasswordAuthentication no in the SSH server config and reload the service.

SSH hardening has the full procedure, the exact config lines, and how to get back in if you do lock yourself out.

Careful

Keys added in the panel are injected when a server is built, so adding one there does nothing for a machine that is already running. On a running server, add the key on the machine itself.

One password per thing, and none of them reused

The password on your server, the password on your Clouduxe account, the one on your game server's admin panel, and the one on your database are four different secrets. Reusing one means a leak anywhere becomes a break-in everywhere, and the leak is usually somewhere you do not control.

Use a password manager and generate them. A password you can remember for a service you sign into twice a year is a password worth attacking.

Change every credential that arrived with the software

Admin panels, game server frameworks, and database images ship with default or first-run credentials, and the defaults are public. Anything that came with a password you did not choose gets a new one before that service is reachable.

Then, what is listening

Every service bound to a public address is a way in, whether you meant to expose it or not. Databases, cache servers, admin panels, and management ports are regularly found open because a package's default configuration listened on all interfaces and nobody checked.

List what is actually reachable on the machine:

Shell
sudo ss -tulpn

Read the Local Address:Port column. An entry showing 0.0.0.0: or [::]: is listening on every interface, which includes your public IP. An entry showing 127.0.0.1: or [::1]: is local only and cannot be reached from outside.

For each line that is public, decide which of three things it is:

  • Something players or users need, such as your game port or a web port. Keep it, and put a rate-bounded rule in front of it. See Port rules.
  • Something only you need, such as SSH, a database, or an admin panel. Bind it to 127.0.0.1 in that service's own config and reach it over an SSH tunnel, or restrict it to your own address in the firewall.
  • Something you did not know was running. Find out what it is before you decide, and if nothing needs it, disable the service rather than only firewalling it.
Databases and caches do not belong on a public address

MySQL, PostgreSQL, MongoDB, Redis, Memcached, and Elasticsearch are found and emptied by automated scanning as a matter of routine, and several of them historically shipped with no authentication at all. If your application runs on the same machine as its database, the database should listen on 127.0.0.1 and nothing else.

Then put a host firewall in front of everything, with a default of deny inbound and explicit rules for what you opened above. The Linux firewall covers ufw on Debian and Ubuntu, and firewalld on AlmaLinux, Rocky and RHEL, including how to avoid locking yourself out.

Clouduxe Prism is not a substitute for this

The protection layer filters traffic arriving at the ports you open, and it is very good at that. It does not stop someone signing in with a password they guessed, and it does not close a database you exposed. See How protection works for what each layer does.

Then, patching

Turn on automatic security updates so this is not a thing you have to remember.

On Debian and Ubuntu:

Shell
sudo apt update
sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades

On AlmaLinux, Rocky and RHEL:

Shell
sudo dnf install dnf-automatic
sudo systemctl enable --now dnf-automatic.timer

dnf-automatic downloads updates but does not install them until you set apply_updates = yes in /etc/dnf/automatic.conf. Edit that file before you consider this done.

Kernel and core library updates need a reboot to take effect. On Ubuntu, the file /run/reboot-required exists while one is pending, and Debian creates it too once update-notifier-common is installed. On the RHEL family, dnf needs-restarting -r, from the dnf-utils package, reports whether a reboot is needed.

The updates that get skipped are the ones that matter

OS packages are the half that automates itself, and they are not where most game servers are broken into. The risky code is the code you added:

  • Game server frameworks and their resources or plugins. Track upstream releases and update deliberately.
  • Anything downloaded from a forum, a Discord server, or a marketplace you cannot identify. Leaked and re-uploaded scripts are a well-known delivery route for backdoors, and the backdoor is usually the reason the copy was free. If you cannot read the source, you are trusting a stranger with root-adjacent access to your machine.
  • Web applications and their dependencies, which are exposed on a port by definition.

A normal user and sudo

Create a user for yourself, give it sudo, and stop using the root account for day-to-day work. Two things improve: a mistake in a command affects less, and your services can run as their own unprivileged users instead of as root, so a flaw in one of them does not immediately hand over the whole machine.

Never run a game server as root. See Users and permissions.

Rate-limit the attempts

With password sign-in already off, brute force against SSH cannot succeed, but it still fills your logs and burns CPU. Fail2ban watches the auth log and blocks addresses that keep failing, and it works for more than SSH: it can watch a web server or a game panel's log too. See Fail2ban.

Moving SSH to a non-standard port reduces noise in the logs. It is not security on its own, and it does not replace anything above it on this page.

The rest of the list

  • Backups you have actually restored. Everything above reduces the chance of a bad day. Backups decide how bad the bad day is. See Planning backups that actually work.
  • Your Clouduxe account. Whoever holds it can rebuild the server and read its billing history. It needs a unique password and 2FA. See Securing your Clouduxe account.
  • Know what normal looks like. Baseline your CPU, memory, and player counts now, while things are healthy. You cannot recognise the abnormal without it, and the same baseline is what you size your protection rules against.
  • Read your logs occasionally, rather than for the first time during an incident.
  • Windows servers. The same priorities apply with different tools, and the single biggest one is not leaving RDP open to the entire internet. See Hardening Remote Desktop.

When something is already wrong

If you are reading this because a server is behaving strangely rather than because it is new, stop here and go to What to do if your server is compromised. Hardening a machine that is already in someone else's hands does not remove them.