WESERVER / KNOWLEDGE BASE

How to secure a new VDS: first security steps

On a new Linux VDS, update packages, create a sudo user, switch to SSH keys, disable root and password login, then turn on the firewall. Commands, the right order and common mistakes.

Short answer

When you get a new Linux VDS, start by updating packages, creating a separate user with sudo rights, adding your SSH key to that user and disabling root and password login. Then turn on a firewall that only allows the ports you actually use. It all fits into one session, and automated password guessing stops getting anywhere.

The commands use apt for Ubuntu and Debian and dnf for AlmaLinux and Rocky Linux. In the examples the server IP is 203.0.113.10 and the new user is deploy. Windows Server VDS instances are reached over RDP; see the Remote Desktop guide for that side.

In what order should you secure a new server?

Some of these steps lock you out if you run them in the wrong order. Keep your root session open until you finish, and work through this list:

  • Log in as root over SSH
  • Update packages and reboot if needed
  • Create the sudo user and add your SSH key to it
  • Test logging in as the new user from a second window
  • Disable root and password login, restart SSH, and test again from a second window
  • Allow SSH in the firewall first, then enable the firewall
  • Install Fail2ban and check exposed ports with ss

How do you update the system and automate security updates?

OS images ship with the packages that were current when the image was built, so a fresh server is missing every security fix released since. Run apt update && apt upgrade -y on Ubuntu and Debian, or dnf upgrade -y on AlmaLinux and Rocky Linux. On Ubuntu, if /var/run/reboot-required exists, the kernel was updated too and you need to reboot.

To install security fixes automatically on Ubuntu and Debian, install unattended-upgrades and enable it with dpkg-reconfigure -plow unattended-upgrades. On AlmaLinux and Rocky Linux, run dnf install dnf-automatic, set apply_updates = yes in /etc/dnf/automatic.conf and start the timer with systemctl enable --now dnf-automatic.timer. With default settings neither tool reboots after a kernel update, so schedule reboots for your maintenance window.

How do you create a sudo user instead of using root?

If you work as root every day, a single mistyped command or a hijacked session affects the whole system. Working as a regular user and taking admin rights through sudo only when needed limits the damage, and the logs show who ran which command.

  • Ubuntu and Debian: create the user and password with adduser deploy, then add it to the sudo group with usermod -aG sudo deploy. If a minimal Debian image has no sudo, run apt install sudo first.
  • AlmaLinux and Rocky Linux: create the user with useradd -m deploy, set a password with passwd deploy and add it to the wheel group with usermod -aG wheel deploy.
  • Check: switch with su - deploy and run sudo whoami. If it prints root, sudo works.
  • This password is asked for sudo commands, not at SSH login. Still pick a strong one you do not use anywhere else.

How do you add an SSH key and disable root and password login?

If your key is already on the root account, run rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy as root; it copies authorized_keys to the new user with the right ownership and permissions. If no key was added yet, run ssh-copy-id [email protected] from your own computer. Then open a second terminal and confirm that ssh [email protected] lets you in without a password prompt.

Once that works, tighten the SSH settings. Instead of editing the main file, create /etc/ssh/sshd_config.d/00-guvenlik.conf with three lines: PermitRootLogin no, PasswordAuthentication no and KbdInteractiveAuthentication no. sshd uses the first value it reads for each option. A file whose name starts with 00 is read before files like 50-cloud-init.conf, which some cloud images ship with PasswordAuthentication yes, so your setting wins.

Before restarting, check the syntax with sshd -t; no output means no errors. Then run systemctl restart ssh on Ubuntu and Debian or systemctl restart sshd on AlmaLinux and Rocky Linux. sshd -T | grep -Ei "permitrootlogin|passwordauthentication" shows the values the server is actually using. Before you close the root session, connect once more as deploy from a new window.

How do you set up the firewall and which ports should be open?

Block all incoming connections and allow only the services you use. On a web server that is usually SSH plus ports 80 and 443. Keep databases, Redis and admin panels off the public internet; if you need remote access, allow only the specific IP address.

  • Ubuntu and Debian (ufw): ufw allow OpenSSH, ufw allow 80/tcp, ufw allow 443/tcp, then ufw enable. Check the result with ufw status verbose. Debian may not ship ufw; add it with apt install ufw.
  • AlmaLinux and Rocky Linux (firewalld): start the service with systemctl enable --now firewalld. The ssh service is already allowed in the default zone. For web traffic add firewall-cmd --permanent --add-service=http and firewall-cmd --permanent --add-service=https, then run firewall-cmd --reload; firewall-cmd --list-all lists the active rules.
  • Allowing a single IP: ufw allow from 198.51.100.7 to any port 3306 proto tcp

Does a server with IPv6 need separate firewall rules?

WeServer VDS instances come with both IPv4 and IPv6, so check that your rules apply to both protocols. With IPV6=yes in /etc/default/ufw, ufw adds every rule for IPv4 and IPv6 together. firewalld already handles both protocols in the same zone.

Hand-written iptables rules only cover IPv4; IPv6 needs its own rules in ip6tables. Skip that and a service that looks closed over IPv4 is still reachable on its IPv6 address. To test from outside, run something like nc -zv -6 server-ipv6-address 3306 from another machine and see whether the port answers.

Do you need Fail2ban, and how do you set it up?

With password login disabled, brute-force attempts against SSH already fail; in that case Fail2ban mainly cuts log noise and wasted connection load. For services that have to keep password login, it is one of the main defences.

  • Install: apt install fail2ban on Ubuntu and Debian. On AlmaLinux and Rocky Linux the package lives in EPEL: run dnf install epel-release, then dnf install fail2ban.
  • In /etc/fail2ban/jail.local, under an [sshd] header, add enabled = true, maxretry = 5 and bantime = 1h. On Debian 12, SSH logs go to the journal rather than a file, so add backend = systemd as well.
  • Start it with systemctl enable --now fail2ban. fail2ban-client status sshd lists the banned IP addresses.
  • If you ban your own IP by accident, lift it with fail2ban-client set sshd unbanip 198.51.100.7.

How do you check which services are exposed?

ss -tulpn lists every listening TCP and UDP port along with the program that opened it. An address of 0.0.0.0 or [::] means the service is reachable on all network interfaces. 127.0.0.1 or [::1] means only the server itself can reach it.

If a service you do not use shows up, stop and disable it with systemctl disable --now <service>. When MySQL, PostgreSQL or Redis only serve an application on the same server, listening on 127.0.0.1 is enough. The firewall is a second line of defence; if a service listens on the wrong address, fix it in that service’s own config first.

What other first settings matter, such as time zone, hostname and backups?

  • Time zone: timedatectl set-timezone Europe/Istanbul (or your own zone). A correct clock makes comparing logs and debugging scheduled jobs much easier.
  • Hostname: hostnamectl set-hostname web01. When you are connected to several servers at once, the prompt tells you which one you are on.
  • Backups: if your provider offers backups or snapshots, get the scope and retention period in writing. For critical data, keep a regular copy outside the server and test that it restores.
  • Reinstalls: if you reinstall the OS from the WE1 customer panel, none of these settings carry over. Repeat the steps and remove the old host key on your computer with ssh-keygen -R 203.0.113.10.

Common first-setup mistakes and how to fix them

Most mistakes that lock you out or leave a service exposed are one of these:

  • SSH dropped right after ufw enable. Cause: the firewall was enabled before SSH was allowed. Fix: log in through your provider’s console and run ufw allow OpenSSH; if there is no console, ask the support team for help.
  • Password login is disabled but SSH still asks for a password. Cause: another file under sshd_config.d overrides the setting, or the service was not restarted. Fix: check the effective value with sshd -T, fix the file name order and restart the service.
  • The new user gets Permission denied (publickey). Cause: authorized_keys is still owned by root, or the permissions are wrong. Fix: chown -R deploy:deploy /home/deploy/.ssh, chmod 700 /home/deploy/.ssh and chmod 600 /home/deploy/.ssh/authorized_keys.
  • sudo says “deploy is not in the sudoers file”. Cause: the user is not in the sudo or wheel group, or the session started before the group change. Fix: run the usermod -aG command again as root and log in as the user again.
  • A database port shows as open from outside. Cause: the service listens on 0.0.0.0 or [::] and IPv6 rules are missing. Fix: make the service listen on 127.0.0.1 and check IPV6=yes in ufw.

Frequently asked questions

Should I change the SSH port? It reduces the traces automated scans leave in your logs, but it does not stop a targeted attack. Key-based login with password login disabled is the real protection. If you do change the port, open the new one in the firewall before closing the old one.

Do these steps apply to a Windows Server VDS? The idea is the same, the tools differ: Windows Update for patches, a strong password on the administrator account, and RDP access limited to the IP addresses you need in Windows Defender Firewall. The RDP connection guide covers the details.

If there is a filter on the network side, do I still need a firewall on the server? The two complement each other. The server firewall is fully under your control and lets you write per-service rules, so the server stays protected even if network-side rules change.

Should I disable SELinux? On AlmaLinux and Rocky Linux, SELinux runs in enforcing mode by default and adds an extra layer of protection. If an application breaks, find the blocked action with ausearch -m avc and fix the context or rule instead of turning SELinux off.

What should I check regularly after setup? Look over pending updates, the output of fail2ban-client status sshd and the ss -tulpn list from time to time. That list is where a newly installed service that quietly opened a public port usually shows up.

Browse related productsAsk on WhatsApp← Back to category

RELATED

Related articles

ALL IN WE1

Let’s build your infrastructure.

Share your requirements and we will help you choose the right resources and server type.

Talk on WhatsApp