Secure a new Linux server: first 10 steps (Ubuntu)

VPS & Servers

0 people found this article helpful

On a new Ubuntu server: install updates, create a sudo user with an SSH key, turn off root and password logins, then add UFW, Fail2ban and automatic updates.

Good to know: the commands are for Ubuntu 24.04 LTS. Ubuntu 26.04 LTS has the same packages in newer versions. Replace 203.0.113.10 with your server's IP address and alex with the username you want. Do the steps in this order: the order is what keeps you from locking yourself out.

1. Install all updates

Connect as root (see Connect to your server with SSH) and update the system:

apt update
apt full-upgrade -y

If the second command updated the kernel, the server needs a restart. This shows whether one is waiting:

cat /var/run/reboot-required

If it prints *** System restart required ***, restart with reboot and connect again after a minute. "No such file" means no restart is needed.

2. Create your own user with sudo rights

Work as a normal user and use sudo only for admin commands. Create the user and add it to the sudo group:

adduser alex
usermod -aG sudo alex

adduser asks for a password (you need it for sudo) and some optional details; press Enter to skip those. Some cloud images already come with a user such as ubuntu: you can use that one instead.

3. Give the new user your SSH key

If you already log in as root with an SSH key, copy it to the new user:

rsync --archive --chown=alex:alex ~/.ssh /home/alex

If you log in with a password and have no key yet, create one on your own computer and copy it to the server from there:

ssh-keygen -t ed25519
ssh-copy-id [email protected]

4. Test the new login before you change anything else

Keep the root session open. In a new terminal window on your computer, log in as the new user and check that sudo works:

ssh [email protected]
sudo whoami

sudo asks for alex's password and then prints root. Only go on when the key login and sudo both work. From now on, work as this user.

5. Turn off root login and password logins

Bots try passwords on every server all day. With these settings, only SSH keys are accepted and nobody can log in as root over SSH. Create a settings file:

sudo nano /etc/ssh/sshd_config.d/01-hardening.conf

Add these lines, then save with Ctrl+O, Enter, and close with Ctrl+X:

PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no

The name starts with 01 on purpose. SSH reads the files in that folder in alphabetical order and uses the first value it finds. Cloud images often have a file such as 50-cloud-init.conf there that turns password logins on; your file comes first and wins.

Check the settings for mistakes, then restart SSH:

sudo sshd -t
sudo systemctl restart ssh

sshd -t prints nothing when everything is fine. Confirm the values SSH really uses:

sudo sshd -T | grep -Ei '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication) '

All three should say no. Now test in a new terminal again: ssh [email protected] must still work, and ssh [email protected] should end with Permission denied (publickey). Close your old session only after that.

6. Switch on the firewall

Allow SSH first: if you switch on UFW without an SSH rule, you lose the connection and can't get back in over SSH.
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status verbose

Answer y when UFW warns that the command may disrupt existing SSH connections. Open the ports of the services you add later, for example sudo ufw allow 'Nginx Full' for a web server. More in Set up a firewall with UFW on Ubuntu.

7. Block password guessers with Fail2ban

Fail2ban watches the logins and blocks IP addresses that fail too often. On Ubuntu, the SSH protection is switched on as soon as it's installed:

sudo apt install fail2ban
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

The last command shows the failed attempts and the blocked addresses. To make sure you never block yourself, add your own IP address in a file of your own (never edit jail.conf, updates overwrite it):

sudo nano /etc/fail2ban/jail.local
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.25

Replace 203.0.113.25 with the IP address you work from, then reload with sudo systemctl restart fail2ban. To lift a block: sudo fail2ban-client set sshd unbanip 203.0.113.25.

8. Install security updates automatically

Ubuntu installs security updates by itself with unattended-upgrades. Check that it's switched on:

cat /etc/apt/apt.conf.d/20auto-upgrades

Both lines should end in "1". If the file is missing or shows "0", install and turn it on:

sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

Test it without changing anything with sudo unattended-upgrade -v --dry-run. The logs are in /var/log/unattended-upgrades/. Kernel updates still need a restart: check /var/run/reboot-required now and then, or set Unattended-Upgrade::Automatic-Reboot "true"; and a time such as Unattended-Upgrade::Automatic-Reboot-Time "03:00"; in /etc/apt/apt.conf.d/50unattended-upgrades.

9. Check what's open to the internet

sudo ss -tulpn

The list shows every program that listens on a port. Addresses like 0.0.0.0, * or [::] mean "reachable from outside" (if the firewall lets it through). Remove or stop anything you don't need.

10. Plan for the day something goes wrong

  • Find out how to reach your server without SSH, for example a VNC or rescue console, before you need it.
  • Set up backups that are stored away from the server: Back up a server with rsync and cron.
  • Keep your private SSH key safe and make a backup of it. Without it, and with password logins off, you can only get in through a console.

Common problems

Permission denied (publickey) for your own user

The key isn't in /home/alex/.ssh/authorized_keys, or the file's permissions are too open. As root (or through the console), check that the file contains your public key, then fix the owner and permissions:

chown -R alex:alex /home/alex/.ssh
chmod 700 /home/alex/.ssh
chmod 600 /home/alex/.ssh/authorized_keys

Password logins still work after step 5

Another file sets the value first. Run sudo grep -ri passwordauthentication /etc/ssh/sshd_config /etc/ssh/sshd_config.d/ to find it. Make sure your file's name sorts before the others, then restart SSH.

SSH doesn't come back after the restart

Usually a typing mistake in the settings file. Log in through the console, run sudo sshd -t to see the error, fix the file and restart SSH. This is why you test in a second window and keep the first one open.

You're locked out by the firewall or Fail2ban

Use the console. sudo ufw allow OpenSSH adds the missing rule; sudo fail2ban-client set sshd unbanip followed by your IP address removes a block.

Related articles

Still stuck? Open a support ticket and we'll help.


Was this answer helpful?

2FA 301 redirect 3D Secure 404 page 500 error 550 error A record accept quote access log account credit account details account password Account Preferences account security add funds addon domain address importer affiliate program AI assistant AlmaLinux 9 Android email Apache Apache virtual host API token Apple Mail Ask AI auth code authenticator app auto-renew automatic payment automatic updates autoresponder AutoSSL bandwidth billing address billing contact billing section block editor block IP bounce bounce message BoxTrapper build a WordPress website bulk email accounts business email buy domain buy hosting buy SSL certificate CalDAV calendar sync callback can't log in cancel hosting cancellation card declined CardDAV catch-all Certbot change domain WordPress change email change nameserver change package change password change payment checklist checkout choose a plan client accounts client area clone WordPress cloud server coming soon page commission company name confirmation link contact contact form Contact Information contacts control panel cPanel cPanel API cPanel contact email cPanel DNS cPanel domains cPanel email cPanel install cPanel language cPanel layout cPanel login cPanel password cPanel SSL cPanel update cPanel users create cPanel account create mailbox credit card cron cron job CRT key CA bundle CSF firewall CSV import currency custom error page Custom Nameservers custom offer dashboard data center database password database privileges database user Database Wizard date.timezone DDNS deceptive site ahead default address delete database delete old emails deny access deploy deposit device email settings Directory Privacy disk space disk usage DKIM DMARC DNS cache DNS explained DNS Records DNS Zone Management document root domain alias domain grace period Domain Hosting Domain Management domain name domain renewal domain transfer downgrade download invoice due date dynamic DNS ElySpace email account email account exists email backup email client email delivery email disk usage email filters email forwarder email history email hosting email login email migration email password email ports email preferences email quota email routing email signature email test email verification EPP code error error log error pages EV SSL expired domain expiry expiry date export database export emails fake email faster support feedback File Manager file permissions firewall first website flush DNS folder force HTTPS forgot password form email not received forward email free migration free SSL FTP account's password FTP password Galaxy email setup getting started Git GitHub Gmail Gmail app GoDaddy good ticket Google malware warning Google sign-in Google Workspace GST number Gzip compression hacked website hacked WordPress hardening help help center home server hosting hosting addons hosting glossary hosting location hosting plan Hosting Service hosting terms hosting tools hosting types hostname hostname SSL hostnamectl hotlink protection HOW TO ADD NAME SERVERS TO MY DOMAIN NAME How to create additional FTP accounts in cPanel How to create FTP accounts in cPanel How to setup name-servers for a domain htaccess htaccess redirect HTTP to HTTPS image theft IMAP IMAP settings IMAP SMTP settings import emails import SQL Imunify360 index.php virus INR install plugin install SSL certificate install WordPress instant answers invite user invoice invoice details invoice emails invoice PDF invoices IP address IP Blocker iPad iPhone email knowledgebase language large database leech protection LEMP Let's Encrypt LFD linked accounts LiteSpeed Cache live chat locked out log out login login email login problem lost email Mac Mac email mail rules mailbox mailbox check mailbox full mailbox size mailing list Mailman maintenance maintenance mode malware removal malware scan manage services mass payment max_execution_time members area memory_limit menu migrate WordPress migration request migration ticket mobile webmail money-back guarantee move email move website move WordPress site MultiPHP INI Editor MultiPHP Manager multiple accounts multiple websites MX record MX records my domains MySQL MySQL database MySQL user mysqldump nameserver Nameservers network drive new account new order newsletter Nginx Node.js notifications npm nvm open ticket Optimize Website or delete order order email out of office outage Outlook Outlook app Outlook IMAP Outlook mobile Outlook password prompt OX App Suite OX webmail page speed password protect pay all pay invoice payment payment details payment failed payment method payment methods PayPal permalinks permissions phishing phone support PHP errors PHP timezone PHP version PHP-FPM php.ini PHPMailer phpMyAdmin plugin updates point domain print invoice printer SMTP product addons products professional email profile public_html publish a post quick start quota quote quotes rating Raw Access raw access logs reading settings redemption period redirect referral link refund register register domain remove user renew domain renewal repair database reseller hosting reset admin password reset password resource usage restore WordPress revoke access revoke privileges root login Roundcube Roundcube export Roundcube identities Roundcube signature rsync backup Samsung Email scam scan to email scheduled task search Search Console self-hosted WordPress send and receive send as server IP address server location server security server status service details services session setup setup domain i setup domain name shared passwords shared vs VPS sign up single sign-on site address Sitejet Builder SMTP SMTP settings spam spam filter SpamAssassin SPF SSH SSH hardening SSH key SSL certificate static front page strong password subaccount subdomain suggestions support ticket support ticket tips support tickets suspension switch account tar test site Thunderbird ticket reply ticket status track delivery transfer website troubleshooting two-factor authentication UAPI Ubuntu Ubuntu 24.04 UFW unpaid invoice unsubscribe unzip upcp upgrade hosting UPI upload files upload_max_filesize URL forwarding user management User Manager username vacation reply VAT ID verify email Web Disk web hosting web hosting basics web server WebDAV webmail webmail From address webmail on phone webmail password website builder website email website migration website not loading Website Performance website security welcome email WhatsApp WhatsApp support whitelist WHM wildcard SSL WordPress 404 WordPress backup WordPress caching WordPress critical error WordPress email WordPress errors WordPress homepage WordPress hosting WordPress login WordPress malware WordPress Management WordPress menu WordPress offline WordPress pages WordPress password WordPress plugins WordPress post WordPress security WordPress SMTP WordPress speed WordPress staging WordPress themes WordPress transfer WordPress update WordPress URL WordPress.org vs WordPress.com WP Mail SMTP wp-admin wp-admin login wp-cron zip Zone Editor zone templates