HostCloud logo
Automation & DevOps

The first ten things to do on a new Linux VPS

The first hour on a fresh Ubuntu VPS decides whether it survives. Ten hardening steps in order, from SSH keys and firewall to fail2ban, automatic updates, swap and monitoring, with the reasoning behind each.

V Vinod Kulkarni
3 August 2026 · 13 min read
The first ten things to do on a new Linux VPS

The first ten things to do on a new Linux VPS

TL;DR: A fresh VPS with a public IP starts receiving automated SSH login attempts within minutes. Not because anyone targeted you, but because the entire IPv4 space is scanned continuously and a new host answering on port 22 is a new entry in someone's list.

The default configuration on most provider images is convenient rather than safe: root login enabled, password authentication on, no firewall, no update policy. Ten steps, about forty minutes, close nearly all of it. Do them before you install your application, because retrofitting security onto a server that is already serving traffic is harder and riskier than doing it on an empty box.

Before you start

Two things to have ready.

Your provider's console access. Web-based console, VNC, or recovery mode. You will change SSH configuration in these steps, and if you make a mistake you will lock yourself out. Console access is how you get back in. Confirm it works before you touch sshd_config, not after.

An SSH key pair on your own machine. If you do not have one, generate it locally with ssh-keygen -t ed25519 -C "your-label". Ed25519 is the current default recommendation: shorter keys, strong security, fast. Set a passphrase on the private key. The passphrase protects the key if your laptop is lost, and ssh-agent means you type it once per session rather than every connection.

Never generate the key pair on the server. The private key belongs on your machine and should never travel.

A note on the golden rule for everything that follows: keep your original session open. When you change SSH settings, open a second terminal and verify you can still connect before closing the first. That single habit prevents the most common self-inflicted lockout.

Layered security diagram showing a server surrounded by concentric rings for OS updates, SSH key authentication, firewall and fail2ban, with separate cards for swap, backups and monitoring

1. Update everything

First command on any new server:

sudo apt update && sudo apt upgrade -y

Provider images are built periodically and then reused, so a "fresh" Ubuntu image can easily be weeks or months behind on patches. Everything you install afterwards sits on top of whatever is underneath it, so this comes first.

If the upgrade touches the kernel, reboot. ls /var/run/reboot-required tells you whether one is pending. A kernel patch that is installed but not running is not protecting you.

While you are here, set the hostname to something meaningful with sudo hostnamectl set-hostname yourname-prod. Six months and four servers later, ubuntu-2204-x64 in a terminal title tells you nothing, and confusing two servers during an incident is a genuine risk.

2. Create a non-root user with sudo

Working as root means every command runs with unrestricted privileges, including the mistyped ones. A misplaced space in an rm -rf as root is unrecoverable.

adduser yourname
usermod -aG sudo yourname

The sudo group grants administrative access when you ask for it explicitly, which is the point. The friction is the feature: it forces a moment of attention before a destructive command.

There is a second reason that matters more than tidiness. Root is a username every attacker already knows. Disabling root login means an attacker must guess both a username and an authentication method rather than just one. Combined with key-only authentication, that closes the entire brute-force category.

Test the new user in a second terminal before proceeding: log in, run sudo whoami, confirm it returns root. Only then move on.

3. Set up SSH key authentication

Passwords are guessable, reusable and typed into things. Keys are neither guessed nor typed.

From your local machine:

ssh-copy-id yourname@your-server-ip

If ssh-copy-id is unavailable, append your public key to ~/.ssh/authorized_keys on the server manually and set permissions: 700 on ~/.ssh, 600 on authorized_keys. SSH refuses to use files with permissive modes, and this is the most common reason key auth silently fails.

Test it. Open a new terminal, connect as the new user, confirm you get in without a password prompt.

Do not proceed to step 4 until that works. Disabling password authentication before confirming key authentication works is the classic lockout, and it is exactly why you confirmed console access earlier.

For teams, each person gets their own key in authorized_keys. Shared keys cannot be revoked individually and give you no attribution in the logs.

4. Lock down the SSH daemon

Edit /etc/ssh/sshd_config and set:

PermitRootLogin no — root cannot log in over SSH at all. PasswordAuthentication no — keys only, which eliminates brute forcing outright. PubkeyAuthentication yes — usually already the default. X11Forwarding no — unnecessary attack surface on a server. MaxAuthTries 3 — limits attempts per connection. AllowUsers yourname — an explicit allowlist, so a compromised system account cannot be used to log in.

On modern Ubuntu, drop-in files under /etc/ssh/sshd_config.d/ are the cleaner place for these, since they survive package upgrades that rewrite the main config.

Validate before restarting: sudo sshd -t. This catches syntax errors that would otherwise stop the daemon starting and leave you locked out. Then sudo systemctl restart ssh.

Test in a new terminal, with your original session still open.

On changing the SSH port. Moving off 22 reduces log noise from automated scanning considerably. It is not a security control, since a port scan finds the new port in seconds, and it adds friction to every future connection and any tooling you point at the server. Reasonable either way. If you do change it, open the new port in the firewall first, and know that fail2ban needs telling about the change.

5. Configure the firewall

Default-deny inbound, allow only what you need.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

The order matters enormously. sudo ufw allow OpenSSH before sudo ufw enable. Enabling a default-deny firewall without permitting SSH first disconnects you immediately and is the single most common way people lock themselves out at this stage.

The principle for everything else: nothing else is exposed. Databases in particular should not be. MySQL on 3306 and PostgreSQL on 5432 have no business being reachable from the internet, and an exposed database with weak credentials is found within days by automated scanning.

If you need remote database access, use an SSH tunnel rather than opening the port. If a service must be reachable from one specific place, scope the rule: sudo ufw allow from 203.0.113.5 to any port 5432.

Verify with sudo ufw status verbose. Read the output and confirm nothing unexpected is open.

Docker deserves a specific warning. Docker manipulates iptables directly and can publish container ports past UFW, so a container started with -p 5432:5432 may be internet-reachable despite your firewall rules. Bind to localhost explicitly (-p 127.0.0.1:5432:5432) for anything that should not be public, and check with sudo ss -tulpn to see what is actually listening on which interface.

6. Install fail2ban

sudo apt install fail2ban

fail2ban watches log files for repeated failures and temporarily blocks the source IP. With key-only SSH the brute-force risk is already largely gone, but fail2ban does two useful things anyway: it dramatically reduces log noise, and it extends to other services later, WordPress login endpoints, mail, and anything else that logs failed attempts.

Configure in /etc/fail2ban/jail.local rather than editing jail.conf, which gets overwritten on package updates. A reasonable starting policy is three failures within ten minutes producing a one-hour ban, with your own IP allowlisted so you cannot ban yourself.

sudo fail2ban-client status sshd shows the jail's state and how many addresses it has banned. On a server that has been up a day, that number is educational.

7. Enable automatic security updates

The most common way small servers get compromised is not a targeted attack. It is a known vulnerability in an unpatched package, exploited by an automated scanner months after the fix shipped.

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

Configure it to apply security updates only, not all updates. Security patches are conservative and rarely break things. Feature updates occasionally do, and you want those applied deliberately.

Set a defined reboot window if you enable automatic reboots, so a kernel update does not restart your server mid-afternoon. Or disable automatic reboots and check /var/run/reboot-required on a schedule you actually keep.

Automatic updates are not a substitute for looking at the server. They handle the routine cases so your attention goes to the ones that matter.

8. Add swap and set the timezone

Swap. Many VPS images ship without any. Without swap, a memory spike triggers the OOM killer, which terminates whatever it judges most expendable, frequently your database. A modest swap file turns a hard kill into temporary slowness.

Create a swap file (2GB is a sensible default on a 4GB machine), set permissions to 600, enable it, and add it to /etc/fstab so it survives a reboot. Set vm.swappiness=10 so the kernel prefers RAM and uses swap only under real pressure.

Swap is a safety net, not capacity. A server swapping constantly needs more RAM, not more swap.

Timezone. sudo timedatectl set-timezone Asia/Kolkata

Default images run UTC. Every log entry, every cron schedule and every timestamp in your application inherits that. Cron jobs set for 2am run at 7:30am IST, backups fire during business hours, and reading logs during an incident requires mental arithmetic you do not want to be doing.

Set it before you schedule anything. Changing it afterwards means auditing every cron entry.

Confirm NTP is syncing with timedatectl status. Clock drift breaks TLS validation, token expiry and log correlation.

Step Command or file Locks you out if wrong Verify with
Update packages apt update && apt upgrade No ls /var/run/reboot-required
Create sudo user adduser, usermod -aG sudo No sudo whoami in a new session
SSH keys ssh-copy-id No Log in from a second terminal
Harden sshd /etc/ssh/sshd_config Yes sshd -t before restart
Firewall ufw allow OpenSSH then enable Yes ufw status verbose
fail2ban /etc/fail2ban/jail.local Yes, if you ban yourself fail2ban-client status sshd
Auto updates unattended-upgrades No /var/log/unattended-upgrades/
Swap and timezone /etc/fstab, timedatectl No free -h, timedatectl status
Backups Provider snapshots plus offsite No Test restore
Monitoring Uptime check plus disk alert No Trigger a test alert

9. Set up backups before you need them

Backups configured after the incident are not backups.

Three layers, and you want at least two.

Provider snapshots. Whole-server images, usually a click or an API call. Excellent for rolling back a bad upgrade, restoring quickly after a compromise, or cloning to a bigger instance. Limitation: they live on the provider's infrastructure, so they do not protect against account-level problems.

Application-level backups. Database dumps and file archives, taken on a schedule, pushed somewhere off the server. These are what you need for granular recovery, when the whole server is fine but one table is not.

Offsite copies. Object storage or another provider. A backup on the same machine protects against nothing that actually kills a server.

The 3-2-1 approach applies here as much as anywhere: three copies, two media, one offsite.

And the step everyone skips: test a restore. Spin up a throwaway instance, restore into it, confirm the application runs. An untested backup is a hypothesis, and you find out whether it was correct at the worst possible moment. Once a quarter is enough.

While you are here, set backup retention deliberately. Indefinite retention means personal data persisting long past any purpose, which under India's data protection framework is a problem rather than caution.

10. Add monitoring and log retention

Silent failure is the default state of an unmonitored server. Problems accumulate for weeks and get discovered by a customer.

The minimum worth having:

An external uptime check. Something outside the server, hitting a URL every few minutes and alerting on failure. Internal monitoring cannot tell you the server is down.

Disk space alerts. Full disks are one of the most common causes of sudden server failure and one of the most predictable. Logs grow, backups accumulate, Docker images pile up. Alert at 80%.

Memory and CPU trends. Not for real-time alerting but for knowing whether you are approaching your allocation.

Failed service alerts. If a service dies and does not restart, you want to know within minutes. Restart=always in the systemd unit plus an alert on repeated restarts.

Log retention of ninety days minimum, shipped off the server. This is the one people cut, and it is the one that determines whether you can investigate an incident later. Configure logrotate to keep enough history and push a copy somewhere the server itself cannot delete, because clearing logs is among the first things an intruder does.

Log retention is also a compliance capability, not just an ops one. India's breach reporting obligations require a detailed account within 72 hours of becoming aware, and reconstructing an incident from seven days of logs is usually impossible. The breach response playbook covers what that report has to contain.

Vertical infographic showing an ongoing server maintenance rhythm: weekly log review, monthly package updates and access review, quarterly restore test and credential rotation

The checklist, condensed

Order matters. Some steps depend on the previous one being verified.

Confirm console access works. Generate a local SSH key pair. Update packages and reboot if the kernel changed. Set a meaningful hostname. Create a non-root sudo user and verify sudo works in a second session. Copy your public key and verify key login works before changing anything else. Harden sshd_config, validate with sshd -t, restart, verify in a new terminal with the old one open. Allow OpenSSH in UFW, then enable UFW, then verify. Install and configure fail2ban with your own IP allowlisted. Enable unattended security upgrades. Add swap and set the timezone to Asia/Kolkata. Configure backups at two layers and test a restore. Add an uptime check, disk alert and ninety-day off-server log retention.

Then install your application.

The ongoing rhythm afterwards is short: check fail2ban-client status and disk usage weekly, review who has access and what is listening monthly, test a restore and rotate credentials quarterly.

Twenty minutes a month is enough to keep a small server healthy. Zero minutes a month is how a VPS becomes someone else's mining rig.

FAQs

What should I do first on a new Ubuntu VPS?

Update all packages, then create a non-root user with sudo privileges, then set up SSH key authentication and verify it works before disabling passwords. Do this before installing your application, since hardening an empty server is far safer than retrofitting security onto one already serving traffic. Confirm your provider's console access works first, in case you lock yourself out.

Should I disable root SSH login?

Yes. Root is a username every attacker already knows, so leaving it enabled means they need to guess only the authentication factor. Set PermitRootLogin no in sshd_config after confirming your non-root sudo user can log in with a key. Combined with disabled password authentication, this eliminates SSH brute forcing as a threat.

Are SSH keys really more secure than a strong password?

Yes, meaningfully. A password can be guessed, reused across services, phished or captured by a keylogger. An SSH key is never transmitted and is computationally infeasible to brute force. Add a passphrase to the private key so a stolen laptop does not hand over server access, and use ssh-agent so you enter it once per session.

Do I need to change the default SSH port?

Not for security. A port scan finds the new port in seconds, so it is obscurity rather than protection. It does substantially reduce automated scanning noise in your logs, which some people value. If you change it, open the new port in the firewall before restarting SSH and update fail2ban's configuration to match.

What firewall rules should a web server have?

Default deny incoming, allow outgoing, and permit only SSH, port 80 and port 443. Nothing else should be exposed, particularly databases: MySQL on 3306 and PostgreSQL on 5432 have no reason to be internet-reachable. Use an SSH tunnel for remote database access, or scope the rule to a single source IP if it is genuinely required.

Why did my firewall lock me out?

Almost always because UFW was enabled before SSH was allowed. Run sudo ufw allow OpenSSH before sudo ufw enable, never the other way around. If it has already happened, use your provider's web console or recovery mode to disable UFW and reconfigure.

Is fail2ban necessary if I use SSH keys only?

Not for SSH brute-force protection, which key-only authentication already eliminates. It remains worthwhile because it cuts log noise substantially and because it extends to other services, including WordPress login endpoints and mail, where brute forcing is still viable. It is a few minutes of setup for ongoing benefit.

Should I enable automatic updates on a production server?

Enable automatic security updates, which are conservative and rarely break anything, and apply feature updates deliberately. Configure a defined reboot window or disable automatic reboots and check /var/run/reboot-required on a schedule you actually keep. Unpatched known vulnerabilities are the most common cause of small-server compromise.

Does a VPS need swap space?

Usually yes, even with adequate RAM. Without swap, a memory spike triggers the OOM killer, which terminates processes, often the database. A 2GB swap file on a 4GB server turns a hard kill into temporary slowness. Set vm.swappiness=10 so the kernel prefers RAM. A server swapping constantly needs more memory, not more swap.

Why should I set the server timezone to Asia/Kolkata?

Because default images run UTC, so every log timestamp and cron schedule is offset by five and a half hours. A cron job set for 2am runs at 7:30am IST, backups fire during business hours, and reading logs during an incident requires constant conversion. Set it before scheduling anything, since changing it later means auditing every cron entry.

How long should I keep server logs?

Ninety days minimum, shipped off the server so a compromise cannot erase them. Shorter retention is fine for debugging and useless for investigating an incident that began earlier. India's breach reporting rules require a detailed account of nature, timing and scope within 72 hours of awareness, and that report is reconstructed from logs.

How do I avoid locking myself out while hardening SSH?

Keep your original session open at all times, and verify each change from a second terminal before closing the first. Validate sshd_config with sudo sshd -t before restarting the service. Confirm your provider's console or recovery access works before you begin, since that is the only way back in if something goes wrong.

Conclusion

A new VPS is not neutral ground. It is a public host answering on a scanned address space, and the default image is configured for your convenience during setup rather than for surviving a month.

The ten steps take about forty minutes. Updates, a non-root user, SSH keys, a hardened daemon, a default-deny firewall, fail2ban, automatic security patches, swap and timezone, backups at two layers, and monitoring with real log retention.

Two of them will lock you out if done in the wrong order, and both are avoidable with the same habit: keep the original session open, verify in a second terminal, and confirm console access before you start.

Do all of it before your application goes on. Retrofitting security onto a live server means either accepting downtime or accepting risk, and the empty box is the only time this is genuinely easy.

Then keep the rhythm. Weekly glance at fail2ban and disk usage, monthly access review, quarterly restore test. Twenty minutes a month is the difference between a server that runs for years and one that becomes a problem you inherit from yourself.

HostCloud runs Linux VPS plans from ₹999 a month on NVMe with full root access, Indian data centres, snapshot backups from the panel and console access if you ever need it. If you would rather not own this checklist, our managed server option applies it for you and keeps it applied.

Related posts