Set up and secure a Compute Instance

After you have successfully created a Compute Instance, there are a few initial configuration steps you should perform within your new Linux system. This includes updating your system, setting the timezone, configuring a custom hostname, adding a limited user, hardening SSH to prevent unauthorized access, and configuring a firewall. These steps ensure your instance is up to date, secure, and ready for use.

📘

While this guide is optional, it walks you through best practices and covers important steps to secure your server. It is recommended that you follow these instructions when deploying a new Compute Instance. Some guides within our library assume that you have performed these steps, such as setting your hostname and updating your software.

  1. View your Instance in Cloud Manager
  2. Connect to the instance
  3. Perform system updates
  4. Set the timezone
  5. Configure a custom hostname
  6. Add a Limited User Account
  7. Harden SSH access
  8. Configure a firewall
  9. Common lockout recovery steps

Before you begin

If you haven't done so already, review the following guides to learn more about using Linode and Compute Instances.

View your instance in Cloud Manager

Log in to Cloud Manager, click the Linodes link in the left menu, and select your Compute Instance from the list. This opens the details page for that instance, which lets you view key information and further configure it to meet your needs.

Details page in <<CLOUD_PORTAL>>

Connect to the instance

Once the Compute Instance has been created and has finished booting up, you can connect to it. Connecting to your instance is usually done through the SSH (Secure Shell) protocol, though you can use the Lish Console to bypass SSH and connect directly to your instance. The Lish Console can be accessed through a web browser (Weblish) or via SSH on the command line.

Perform system updates

Updating your system frequently is the single biggest security precaution you can take for any operating system. Software updates range from critical vulnerability patches to minor bug fixes and many software vulnerabilities are actually patched by the time they become public. Updating also provides you with the latest software versions available for your distribution.

  • Ubuntu, Debian, Kali Linux:

    apt update && apt upgrade
    

    📘

    When updating some packages, you may be prompted to use updated configuration files. If prompted, it is typically safer to keep the locally installed version.
    📘
    The Kali Linux distribution image is a minimum installation. You will likely want to install individual tools or metapackages, such as the kali-linux-headless metapackage.

  • CentOS/RHEL 8+, Fedora:

    This includes CentOS Stream 8 (and above), CentOS 8, other RHEL derivatives (including AlmaLinux 8 and Rocky Linux 8), and Fedora.

    dnf upgrade
    
  • CentOS 7:

    yum update
    
  • openSUSE:

    zypper update
    
  • Alpine:

    apk update && apk upgrade
    
  • Arch:

    pacman -Syu
    
  • Gentoo:

    emaint sync -a
    

    After running a sync, it may end with a message that you should upgrade Portage using a --oneshot emerge command. If so, run the Portage update. Then update the rest of the system:

    emerge -uDU --keep-going --with-bdeps=y @world
    
  • Slackware:

    slackpkg update
    slackpkg upgrade-all
    

Set the timezone

All new Compute Instances are set to UTC time by default. However, you may prefer to use the time zone which you live in so log file timestamps are relative to your local time.

  • Most Distributions:

    This includes CentOS Stream 8 (and newer), CentOS 7 (and newer), other RHEL derivatives (including AlmaLinux 8 and Rocky Linux 8), Fedora, and Arch. These instructions also work for most Ubuntu, Debian, and openSUSE distributions, though other methods may be preferred in those cases.

    1. Use timedatectl to output a list of available timezones.

      timedatectl list-timezones
      
    2. Use the arrow keys, Page Up, and Page Down to navigate through the list. Copy or make note of your desired time zone and press q to exit the list.

    3. Set the time zone using the command below, replacing America/New_York with your preferred time zone.

      timedatectl set-timezone 'America/New_York'
      
  • Ubuntu, Debian, Kali:

    The instructions under Most Distributions above (which outlines the timedatectl command) are valid. That said, both Ubuntu and Debian come with a more friendly tool called tzdata, outlined below.

    1. Open the tzdata tool.

      dpkg-reconfigure tzdata
      
    2. Select the continent of your choice using the arrow keys and press Enter.

    3. Select your region using the arrow keys and press Enter.

  • Alpine:

    1. Use the setup-timezone command to initiate the timezone selection process:

      setup-timezone
      
    2. Enter the timezone you are located within. If you aren't sure of the timezone string to use, enter ? to display a list of available timezones

    3. If you selected a region with sub-timezones, enter ? again to see a list of available sub-timezones and then enter the sub-timezone you are located within.

  • Gentoo:

    1. View a list of available time zones.

      ls /usr/share/zoneinfo
      
    2. Write the selected time zone to /etc/timezone (for example, EST for Eastern Standard Time).

      echo "EST" > /etc/timezone
      
    3. Configure the sys-libs/timezone-data package, which sets /etc/localtime.

      emerge --config sys-libs/timezone-data
      
  • openSUSE:

    The instructions under Most Distributions above (which outlines the timedatectl command) are valid. openSUSE also has a more friendly way to select a timezone, discussed below.

    1. Open the YaST2 timezone selector tool.

      yast2 timezone
      
    2. Use the arrow keys to select your region within the Region pane.

    3. Press tab to switch to the Time Zone pane and then use the arrow keys to select your time zone or sub-region.

    4. Press F10 to save the changes. Alternatively, press tab until the [OK] text button is highlighted. Then press enter.

  • Slackware:

    1. Run the timeconfig tool.

      timeconfig
      
    2. Select NO Hardware clock is set to local time.

    3. Select a timezone.

Check the time

Use the date command to view the current date and time according to your server.

root@localhost:~# date
Thu Feb 16 12:17:52 EST 2018

Configure a custom hostname

A hostname is used to identify your Compute Instance using an easy-to-remember name. It can be descriptive and structured (detailing what the system is used for) or a generic word or phrase. Here are some examples of hostnames:

  • Descriptive and/or Structured: web, staging, blog, or something more structured like [purpose]-[number]-[environment] (ex: web-01-prod).

  • Generic/Series: Such as the name of a fruit (apple, watermelon), a planet (mercury, venus), or animal (leopard, sloth).

This hostname can be used as part of a FQDN (fully qualified domain name) for the system (ex: web-01-prod.example.com).

  • Most distributions:

    This includes Ubuntu 16.04 (and newer), CentOS Stream 8 (and newer), CentOS 7 (and newer), other RHEL derivatives (including AlmaLinux 8 and Rocky Linux 8), Debian 8 (and newer), Fedora, openSUSE, Kali Linux, and Arch.

    Replace example-hostname with one of your choice.

    hostnamectl set-hostname example-hostname
    
  • Alpine:

    See Update your system's hosts file.

  • Gentoo:

    echo "HOSTNAME=\"example-hostname\"" > /etc/conf.d/hostname
    /etc/init.d/hostname restart
    
  • Slackware:

    echo "example-hostname" > /etc/HOSTNAME
    hostname -F /etc/HOSTNAME
    

After you've made the changes above, you may need to log out and log back in again to see the terminal prompt change from localhost to your new hostname. The command hostname should also show it correctly. See our guide on using the hosts file if you want to configure a fully qualified domain name.

Update your system's hosts file

The hosts file creates static associations between IP addresses and hostnames or domains which the system prioritizes before DNS for name resolution.

  1. Open the hosts file in a text editor, such as nano.

    nano /etc/hosts
    
  2. Add a line for your Compute Instance's public IP address. You can associate this address with your instance's Fully Qualified Domain Name (FQDN) if you have one, and with the local hostname you set in the steps above. In the example below, 203.0.113.10 is the public IP address, example-hostname is the local hostname, and example-hostname.example.com is the FQDN.

    127.0.0.1 localhost.localdomain localhost
    203.0.113.10 example-hostname.example.com example-hostname
    
  3. Add a line for your Compute Instance's IPv6 address. Applications requiring IPv6 will not work without this entry:

    127.0.0.1 localhost.localdomain localhost
    203.0.113.10 example-hostname.example.com example-hostname
    2600:3c01::a123:b456:c789:d012 example-hostname.example.com example-hostname
    

The value you assign as your system's FQDN should have an "A" record in DNS pointing to your Compute Instance's IPv4 address. For IPv6, you should also set up a DNS "AAAA" record pointing to your instance's IPv6 address.

See our DNS Manager guide for more information on configuring DNS. For more information about the hosts file, see Using your System's hosts File

Add a limited user account

Up to this point, you have accessed your Compute Instance as the root user, which has unlimited privileges and can execute any command--even one that could accidentally disrupt your server. We recommend creating a limited user account and using that at all times. Administrative tasks will be done using sudo to temporarily elevate your limited user's privileges so you can administer your server. Later, when you want to restrict sudo access for users, see Linux Users and Groups.

📘

Not all Linux distributions include sudo on the system by default, but all the images provided have sudo in their package repositories. If you get the output sudo: command not found, install sudo before continuing.

  • Ubuntu, Debian, Kali Linux:

    1. Create the user, replacing example_user with your desired username. You'll then be asked to assign the user a password:

      adduser example_user
      
    2. Add the user to the sudo group so you'll have administrative privileges:

      adduser example_user sudo
      
  • CentOS/RHEL, Fedora:

    1. Create the user, replacing example_user with your desired username, and assign a password:

      useradd example_user && passwd example_user
      
    2. Add the user to the wheel group for sudo privileges:

      usermod -aG wheel example_user
      

Log in as the new user

  1. After creating your limited user, disconnect from your Compute Instance:

    exit
    
  2. Log back in as your new user. Replace example_user with your username, and the example IP address with your instance's IP address:

    ssh example_user@192.0.2.17
    

Now you can administer your Compute Instance from your new user account instead of root. Nearly all superuser commands can be executed with sudo (example: sudo iptables -L -nv) and those commands will be logged to /var/log/auth.log.

Harden SSH access

By default, password authentication is used to connect to your Compute Instance via SSH. A cryptographic key-pair is more secure because a private key takes the place of a password, which is generally much more difficult to decrypt by brute-force. In this section we'll create a key-pair and configure your system to not accept passwords for SSH logins.

Create and upload your SSH key

To protect your user account with public key authentication, you first need to create an SSH key pair and upload the public key to your server.

  1. Locate your existing SSH public key or, if you don't yet have one, create a new SSH key pair.

    • If you have an existing SSH key, find the public key on your local machine. SSH keys are typically stored in a hidden .ssh directory within the user's home directory:

      • Linux: /home/username/.ssh/
      • macOS: /Users/username/.ssh/
      • Windows: C:\Users\Username\.ssh\

      Since SSH keys are generated as a private and public key pair, there should be two files for each SSH key. They have similar filenames, with the public key using a .pub extension and the private key using no extension. While SSH keys can have custom filenames, many people generate them using their default names. These default filenames start with id_ followed by the type of key, such as id_rsa, id_ed25519, and id_ecdsa. See example private and public key filenames below:

      • Private key: id_ed25519
      • Public key: id_ed25519.pub
    • If you do not yet have an SSH key pair, generate one now. We recommend using the Ed25519 algorithm with a secure passphrase. The command below works for Linux, macOS, and most fully updated Windows 10 and 11 machines. Replace user@domain.tld with your own email address or whatever custom comment string you wish to use. This helps with differentiate SSH keys and identify the owner.

      ssh-keygen -t ed25519 -C "user@domain.tld"
      

      When prompted for the filename, you can press Enter to use the defaults. When prompted for the optional passphrase, we recommend using a string similar to a strong password (with a mix of letters, numbers, and symbols).

      For more detailed instructions, on creating an SSH key, review the Generate an SSH Key Pair guide. Users of Windows 7 and earlier should review the PuTTY section.

  2. Upload the public key to your Compute Instance. Replace example_user with the name of the user you plan to administer the server as and 192.0.2.17 with your instance's IP address.

    • Linux:

      From your local computer:

      ssh-copy-id example_user@192.0.2.17
      
    • macOS:

      On your Compute Instance (while signed in as your limited user):

      mkdir -p ~/.ssh && sudo chmod -R 700 ~/.ssh/
      

      From your local computer:

      scp ~/.ssh/id_rsa.pub example_user@203.0.113.10:~/.ssh/authorized_keys
      

      📘

      ssh-copy-id is available in Homebrew if you prefer it over SCP. Install with brew install ssh-copy-id.

    • Windows 10 or 11:

      On your Compute Instance (while signed in as your limited user):

      mkdir -p ~/.ssh && sudo chmod -R 700 ~/.ssh/
      

      From your local computer:

      scp C:\Users\MyUserName\.ssh/id_rsa.pub example_user@192.0.2.17:~/.ssh/authorized_keys
      
    • Earlier Windows Versions:

      • Option 1: This can be done using WinSCP. In the login window, enter your Compute Instance's public IP address as the hostname, and your non-root username and password. Click Login to connect.

        Once WinSCP has connected, you'll see two main sections. The section on the left shows files on your local computer and the section on the right shows files on your instance. Using the file explorer on the left, navigate to the file where you've saved your public key, select the public key file, and click Upload in the toolbar above.

        You'll be prompted to enter a path where you'd like to place the file on your Compute Instance. Upload the file to /home/example_user/.ssh/authorized_keys, replacing example_user with your username.

      • Option 2: Copy the public key directly from the PuTTY key generator into the terminal emulator connected to your Compute Instance (as a non-root user):

        mkdir ~/.ssh; nano ~/.ssh/authorized_keys
        

        The above command will open a blank file called authorized_keys in a text editor. Copy the public key into the text file, making sure it is copied as a single line exactly as it was generated by PuTTY. Press CTRL+X, then Y, then Enter to save the file.

  3. Finally, you'll want to set permissions for the public key directory and the key file itself. On your Compute Instance, run the following command:

    sudo chmod -R 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys
    

    This provides an extra layer of security by preventing other users from accessing the public key directory as well as the file itself. For more information on how this works, see our guide on how to modify file permissions.

  4. Now exit and log back in to your Compute Instance. In most cases, the first authentication method attempted will be public key authentication. If you've successfully uploaded a public key for your user, you should be logged in without entering your user's password (though you will need to enter the passphrase for the SSH key).

This should trigger If you specified a passphrase for your private key, you'll need to enter it.

SSH daemon options

Lastly, edit the SSH configuration file to disallow root login and disable password authentication over SSH.

  1. Open the SSH configuration file on your Compute Instance using a Linux text editor, such as nano or vim:

    sudo nano /etc/ssh/sshd_config
    
  2. Disallow root logins over SSH. This requires all SSH connections be by non-root users. Once a limited user account is connected, administrative privileges are accessible either by using sudo or changing to a root shell using su -.

    # Authentication:
    ...
    PermitRootLogin no
    
  3. Disable SSH password authentication. This requires all users connecting via SSH to use key authentication. Depending on the Linux distribution, the line PasswordAuthentication may need to be added, or uncommented by removing the leading #.

    # Change to no to disable tunnelled clear text passwords
    PasswordAuthentication no
    

    📘

    You may want to leave password authentication enabled if you connect to your Compute Instance from many different computers. This will allow you to authenticate with a password instead of generating and uploading a key-pair for every device.

  4. Listen on only one internet protocol. The SSH daemon listens for incoming connections over both IPv4 and IPv6 by default. Unless you need to SSH into your Compute Instance using both protocols, disable whichever you do not need. This does not disable the protocol system-wide, it is only for the SSH daemon. Depending on the Linux distribution, the line AddressFamily may need to be added, or uncommented by removing the leading #

    Use the option:

    • AddressFamily inet to listen only on IPv4.
    • AddressFamily inet6 to listen only on IPv6.
    # Port 22
    AddressFamily inet
    
  5. Restart the SSH service to load the new configuration.

    • Distributions with systemd: If you’re using a Linux distribution which uses systemd (CentOS 7, Debian 8, Fedora, Ubuntu 15.10+), restart the service using systemctl:

      sudo systemctl restart sshd
      
    • Ubuntu 22.10+: If you are using Ubuntu 22.10 or later, sshd uses socket-based activation. Run this command instead of restarting the service.

      systemctl enable --now ssh.service
      
    • Distributions without systemd: If your init system is SystemV or Upstart (CentOS 6, Debian 7, Ubuntu 14.04), run the command below to restart the service:

      sudo service sshd restart
      

Use fail2ban for SSH login protection

Fail2Ban is an application that bans IP addresses from logging in to your server after too many failed login attempts. Since legitimate logins usually take no more than three tries to succeed (and with SSH keys, no more than one), a server being spammed with unsuccessful logins indicates attempted malicious access.

Fail2Ban can monitor a variety of protocols including SSH, HTTP, and SMTP. By default, Fail2Ban monitors SSH only, and is a helpful security deterrent for any server since the SSH daemon is usually configured to run constantly and listen for connections from any remote IP address.

For complete instructions on installing and configuring Fail2Ban, see our guide: Using Fail2ban to Secure Your Server.

Configure a firewall

📘

The free Cloud Firewalls service can be used to replace or supplement internal firewall configuration. For more information on Cloud Firewalls, see our Getting Started with Cloud Firewalls guide. For help with solving general firewall issues, see the troubleshooting guide.

Using a firewall to block unwanted inbound traffic to your Compute Instance provides a highly effective security layer. By being very specific about the traffic you allow in, you can prevent intrusions and network mapping. A best practice is to allow only the traffic you need, and deny everything else. See our documentation on some of the most common firewall applications:

  • nftables or its predecessor, iptables, is the controller for netfilter, the Linux kernel's packet filtering framework. One of these utilities is included in most Linux distributions by default.

  • firewalld is a firewall management tool that serves as a front end to nftables or iptables. It is preinstalled on the RHEL family of distributions (and others), including CentOS, AlmaLinux, Rocky Linux, Fedora, and openSUSE Leap.

  • UFW is another firewall management tool that operates as a front end to nftables or iptables. It is used by default on Ubuntu and is also available on other Debian-based distributions.

Common lockout recovery steps

If for whatever reason you find yourself locked out of your Compute Instance after putting your security controls into place, there are still a number of ways that you can regain access to your instance.

  • Access your Compute Instance through our out-of-band Lish Console to regain access to the internals of your system without relying on SSH.

  • If you need to re-enable password authentication and/or root login over ssh to your instance, you can do this by reversing the following sections of this file to reflect these changes

    # Authentication:
    ...
    PermitRootLogin yes
    ...
    PasswordAuthentication yes
    

    From there, you just need to restart SSH.

    If you’re using a Linux distribution which uses systemd (CentOS 7, Debian 8, Fedora, Ubuntu 15.10+)

    sudo systemctl restart sshd
    

    If your init system is SystemV or Upstart (CentOS 6, Debian 7, Ubuntu 14.04):

    sudo service sshd restart
    
  • If you need to remove your public key from your Compute Instance, you can enter the following command:

    rm ~/.ssh/authorized_keys
    

    You can then replace your key by re-following the instructions in Create and upload your SSH key.

Next steps

These are the most basic steps to harden any Linux server, but further security layers will depend on its intended use. Additional techniques can include application configurations, using intrusion detection, installing a form of access control, fine tuning sudo access, removing exposed services, and more.

Now you can begin setting up your Compute Instance for any purpose you choose. We have a library of documentation to assist you with a variety of topics ranging from migration from shared hosting to enabling two-factor authentication to hosting a website.

🚧

Email restrictions on our Platform

In an effort to fight spam originating from our platform, outbound connections on ports 25, 465, and 587 are blocked by default on Compute Instances for some new accounts. These restrictions prevent applications from sending email. If you intend to send email from a Compute Instance, see Send email on the Linode platform to learn more about our email policies and to request the removal of these restrictions.