Linux Post-Installation Checklist: Initial Server Configuration | INTROSERV
EUR
european

EUR

usa

USD

English En
Ex. VAT Ex. VAT 0%

Linux Post-Installation Checklist: Initial Server Configuration

Level: Beginner / Intermediate
Estimated time: ~40 minutes
Goal: Complete the essential initial server configuration on a Linux VPS - harden SSH access, create a sudo user, configure a firewall, set up automatic security updates, and schedule basic maintenance tasks with cron.

Introduction

The first 30 minutes after provisioning a VPS are the most important. A freshly installed Linux server is wide open: root login over SSH is usually enabled, no firewall rules are in place, and packages are already outdated. This linux post-installation checklist covers every step that matters for a production-ready or dev environment setup - from creating a sudo user and configuring SSH key authentication, to enabling UFW and scheduling automatic security updates. Following this guide once protects you from the most common attack vectors before you deploy anything on top.

This guide covers Ubuntu, Debian, and AlmaLinux (RHEL-compatible) VPS instances.

Prerequisites

Before you begin, make sure the following conditions are met:

  • Operating system: Ubuntu 20.04/22.04/24.04 LTS, Debian 11/12/13, or AlmaLinux 8/9/10
  • Access: Root SSH access to the server (password or key - you will harden this during the guide)
  • Local machine: SSH client available (ssh on Linux/macOS, PuTTY or Windows Terminal on Windows)
  • Required knowledge: Basic Linux command line usage - navigating directories, editing files with nano
  • Estimated time: ~40 minutes for a clean first run

Info

This guide is tested on Ubuntu 24.04 LTS, Debian 12/13, and AlmaLinux 9/10. The steps are identical unless noted otherwise.

Step 1: Set the Server Hostname

A proper hostname makes logs readable and prevents confusion when managing multiple servers.

First, update /etc/hosts so the system can resolve its new hostname locally. Open the file:

sudo nano /etc/hosts

Add or update the line for 127.0.1.1 (or 127.0.0.1 if 127.0.1.1 does not exist) to match your new hostname. For example, if you plan to use web-01:

127.0.1.1 web-01

Save and exit (Ctrl+O, Enter, Ctrl+X).

Next, set the hostname globally with hostnamectl:

sudo hostnamectl set-hostname <YOUR_HOSTNAME>

Verify it was applied:

hostnamectl

Expected output:

Static hostname: web-01 Icon name: computer-vm Chassis: vm Machine ID: a1b2c3d4e5f6... Boot ID: ... Operating System: Ubuntu 24.04.1 LTS Kernel: Linux 6.8.0-31-generic Architecture: x86-64

Tip

Many services - including Postfix (mail) and SSL certificate tools like Certbot - rely on the hostname being resolvable locally. Updating /etc/hosts before running hostnamectl avoids subtle resolution failures.

Step 2: Update All Packages

Run a full system update immediately. Packages shipped with a fresh VPS image are almost always behind.

Ubuntu/Debian (APT):

sudo apt update && sudo apt upgrade -y

AlmaLinux/RHEL (DNF):

sudo dnf update -y

After the update completes, check whether a reboot is required.

Debian/Ubuntu:

cat /var/run/reboot-required 2>/dev/null && echo "Reboot required" || echo "No reboot needed"

AlmaLinux/RHEL:

sudo dnf install -y dnf-utils needs-restarting -r

If a reboot is required, reboot now before continuing - some kernel and library updates only take effect after a restart:

sudo reboot

Warning

Skipping the reboot when it is required means your running kernel and some libraries remain on the old version. This can leave known vulnerabilities unpatched even after the update.

Step 3: Create a Sudo User

Logging in as root for day-to-day work is unsafe and bad practice. Create a regular user and grant it sudo privileges.

3.1 Add the user

sudo adduser <YOUR_USERNAME>

On Ubuntu/Debian, the command will prompt you to set a password and fill in optional contact fields. Fill in the password; skip the rest by pressing Enter.

On AlmaLinux/RHEL, adduser is a symlink to useradd and runs non-interactively without prompting for a password, leaving the account locked. You must set the password manually:

sudo passwd <YOUR_USERNAME>

3.2 Grant sudo privileges

Ubuntu/Debian - add the user to the sudo group:

sudo usermod -aG sudo <YOUR_USERNAME>

AlmaLinux/RHEL - add the user to the wheel group:

sudo usermod -aG wheel <YOUR_USERNAME>

3.3 Verify access

Switch to the new user and test sudo:

su - <YOUR_USERNAME> sudo whoami

Expected output:

root

If you see root, the user has working sudo privileges. You can now log out of the root session:

exit

Info

On AlmaLinux, wheel group membership is defined in /etc/sudoers via the %wheel ALL=(ALL) ALL line, which is enabled by default. On Ubuntu/Debian, the sudo group serves the same purpose.

Step 4: Configure SSH Key Authentication

Password-based SSH is vulnerable to brute-force attacks. SSH key authentication replaces the password with a cryptographic key pair - much harder to attack. This is one of the most important SSH configuration best practices you can apply.

4.1 Generate an SSH key pair (on your local machine)

If you do not already have an SSH key pair, generate one on your local machine (not the server):

ssh-keygen -t ed25519 -C "<YOUR_USERNAME>@<YOUR_HOSTNAME>"

Accept the default file location. Set a passphrase when prompted - this protects the key if your local machine is ever compromised.

Info

ed25519 is the preferred key type. It is faster, shorter, and more secure than the older rsa (2048-bit). If your SSH client does not support it, use ssh-keygen -t rsa -b 4096 instead.

4.2 Copy the public key to the server

From your local machine, copy the key to the new user's account:

ssh-copy-id <YOUR_USERNAME>@<YOUR_SERVER_IP>

If ssh-copy-id is not available (e.g., Windows), manually copy the contents of ~/.ssh/id_ed25519.pub and append it to ~/.ssh/authorized_keys on the server.

4.3 Test the key-based login

Open a new terminal window (do not close the current session yet) and test the login:

ssh <YOUR_USERNAME>@<YOUR_SERVER_IP>

You should log in without being asked for a password (only the key passphrase, if you set one).

Warning

Do not close your existing SSH session until you have confirmed the key-based login works. If something is misconfigured, you will still have the existing session to fix it.

Step 5: Harden SSH Configuration and Disable Root Login

With key-based login confirmed (Step 4), lock down the SSH daemon. Disabling root login and password authentication over SSH is one of the most effective steps in any Linux server hardening checklist.

On all three distributions, /etc/ssh/sshd_config has an Include /etc/ssh/sshd_config.d/*.conf line near the top of the file, and SSH applies the first value it finds for each setting. Vendor drop-in files are already present and override anything you add later in the main file:

  • Ubuntu 24.04: 50-cloud-init.conf sets PasswordAuthentication yes
  • AlmaLinux: 50-redhat.conf sets X11Forwarding yes

For that reason, editing the main sshd_config is unreliable. Instead, create a hardening drop-in with a low number (00-) so it is read first and overrides the vendor files. The same file works on all three distributions.

Create the drop-in file:

sudo tee /etc/ssh/sshd_config.d/00-hardening.conf > /dev/null <<'EOF' PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys X11Forwarding no EOF

A 00- prefix guarantees this file is parsed before vendor drop-ins like 50-cloud-init.conf and 50-redhat.conf. Because SSH uses first-match-wins, you do not need to edit those files.

Validate the configuration syntax before restarting the service:

sudo sshd -t

If the command returns no output, the syntax is valid. Now verify the effective settings the daemon will actually use:

sudo sshd -T | grep -iE "permitrootlogin|passwordauthentication|x11forwarding"

Expected output:

permitrootlogin no passwordauthentication no x11forwarding no

Warning

Confirm all three values are correct before restarting. If passwordauthentication still shows yes, a vendor drop-in is overriding your file – check that 00-hardening.conf was saved correctly. Do not close your existing SSH session until you have verified that key-based login still works.

Restart the SSH daemon to apply the changes.

Ubuntu 24.04 (socket activation):

sudo systemctl restart ssh.socket

Debian and older Ubuntu:

sudo systemctl restart ssh

AlmaLinux/RHEL:

sudo systemctl restart sshd

Verify the service is running (use sshd on AlmaLinux, ssh.socket on Ubuntu 24.04):

sudo systemctl status ssh

You should see Active: active (running) (or active (listening) for socket-activated SSH).

Now confirm that root login is blocked. From your local machine:

ssh root@<YOUR_SERVER_IP>

Expected result: the connection is refused with Permission denied (publickey). Root login over SSH is now disabled.

Step 6: Configure Firewall (UFW)

UFW (Uncomplicated Firewall) is the standard firewall tool on Ubuntu and Debian. On AlmaLinux, firewalld is the default, but UFW can be installed there too. This step covers both approaches.

Warning

Before enabling any firewall, make sure SSH (port 22) is explicitly allowed. Getting this wrong will lock you out of the server.

6.1 UFW (Ubuntu/Debian)

On Debian (especially Debian 13), ufw might not be installed by default. Install it first:

sudo apt update && sudo apt install -y ufw

Check current status:

sudo ufw status

Allow SSH before enabling the firewall:

sudo ufw allow ssh

Allow HTTP and HTTPS if you plan to run a web server:

sudo ufw allow http sudo ufw allow https

Enable the firewall:

sudo ufw enable

Verify the active rules:

sudo ufw status verbose

Expected output:

Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) To Action From -- ------ ---- 22/tcp ALLOW IN Anywhere 80/tcp ALLOW IN Anywhere 443/tcp ALLOW IN Anywhere

6.2 Firewalld (AlmaLinux/RHEL)

Enable and start firewalld:

sudo systemctl enable --now firewalld

Allow SSH, HTTP, and HTTPS:

sudo firewall-cmd --permanent --add-service=ssh sudo firewall-cmd --permanent --add-service=http sudo firewall-cmd --permanent --add-service=https sudo firewall-cmd --reload

Verify:

sudo firewall-cmd --list-all

Info

configure firewall linux means choosing the right tool for your distribution and not running two firewall daemons at once. If you installed UFW on AlmaLinux, disable firewalld first with sudo systemctl disable --now firewalld.

Step 7: Synchronize the System Clock (NTP)

Accurate time is required for security protocols (SSL/TLS validation, Kerberos), correct log timestamps, and scheduled jobs. An out-of-sync clock can cause SSL certificate errors, failed authentication, and confusing log entries.

Check the current synchronization state:

timedatectl status

Expected output:

System clock synchronized: yes NTP service: active

Info

On Ubuntu 24.04 and Debian 13, NTP is typically active via systemd-timesyncd. On AlmaLinux 10, it is usually active via chrony. If timedatectl shows System clock synchronized: yes and NTP service: active, you do not need to change anything.

If NTP service shows as inactive or n/a, install and enable chrony - the recommended NTP daemon for production servers:

Ubuntu/Debian:

sudo apt install chrony -y sudo systemctl enable --now chrony

Tip

On Debian 13, installing chrony might cause `timedatectl` to show `NTP service: n/a`. Use `chronyc tracking` to verify instead.

AlmaLinux/RHEL:

sudo dnf install chrony -y sudo systemctl enable --now chronyd

Wait 30–60 seconds after starting the service, then verify synchronization is active:

chronyc tracking

Look for Leap status: Normal. That confirms the system clock is synchronized and NTP is working correctly.

Tip

If you manage servers in multiple time zones, set the system time zone before configuring NTP so that log timestamps are in the expected local time. Example: sudo timedatectl set-timezone Europe/Warsaw.

Step 8: Enable Automatic Security Updates

Manual updates work, but they depend on you remembering to do them. Automatic security updates are a safety net - especially critical for unattended VPS instances. This is how you configure automatic security updates linux without affecting stability.

8.1 Ubuntu/Debian - unattended-upgrades

Install the package:

sudo apt install unattended-upgrades -y

Enable and configure it:

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

Warning

It is critical to select Yes when prompted. If you select No, the necessary configuration file (/etc/apt/apt.conf.d/20auto-upgrades) will not be created, and subsequent checks will fail with a "No such file or directory" error. This enables automatic installation of security updates only - regular feature updates remain manual.

Verify the configuration:

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

Expected output:

APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1";

To test without applying changes:

sudo unattended-upgrade --dry-run --debug

8.2 AlmaLinux/RHEL - dnf-automatic

Install:

sudo dnf install dnf-automatic -y

Open the configuration file and set the upgrade type to security only. First, make a backup:

sudo cp /etc/dnf/automatic.conf /etc/dnf/automatic.conf.bak sudo nano /etc/dnf/automatic.conf

Find and set:

apply_updates = yes upgrade_type = security

Enable and start the timer:

sudo systemctl enable --now dnf-automatic.timer

Verify:

sudo systemctl status dnf-automatic.timer

Step 9: Schedule Basic Maintenance with Cron

Cron handles scheduled tasks - things that need to happen regularly without manual intervention. A simple cron job for tasks like log cleanup or certificate renewal checks is standard practice on any managed server.

AlmaLinux/RHEL preparation:

On a clean AlmaLinux 10 system, nano might not be installed, and crontab -e will open vi. To use nano instead, run this single line to execute it cleanly in sequence and ensure the environment variable persists:

sudo dnf install nano -y && export EDITOR=nano && crontab -e

For other systems (like Ubuntu/Debian), just open the crontab for the current user:

crontab -e

On the first run (on Ubuntu/Debian), you will be asked to choose an editor. Select nano (option 1).

Common cron job examples

Run a task every night at 2:00 AM:

0 2 * * * /usr/local/bin/my-maintenance-script.sh >> /var/log/maintenance.log 2>&1

Renew SSL certificates weekly (for Certbot users):

0 3 * * 0 certbot renew --quiet >> /var/log/certbot-renew.log 2>&1

Clear temporary files monthly:

0 4 1 * * find /tmp -type f -atime +30 -delete

Info

Cron uses the format minute hour day-of-month month day-of-week command. The >> /var/log/task.log 2>&1 part redirects both stdout and stderr to a log file, so you can review what happened.

Verify your cron jobs are registered:

crontab -l

You should see the entries you added. Cron reads the file automatically - no reload needed. To check if the cron service is running, use:

Ubuntu/Debian:

sudo systemctl status cron

AlmaLinux/RHEL:

sudo systemctl status crond

Verification

Run through this checklist to confirm everything was applied correctly:

Check the hostname:

hostnamectl | grep hostname

Confirm no root SSH login and password authentication are disabled (this checks the active runtime configuration):

sudo sshd -T | grep -iE "permitrootlogin|passwordauthentication"

Expected:

permitrootlogin no passwordauthentication no

Confirm the SSH service is running:

# For Ubuntu 24.04: sudo systemctl status ssh.socket # For Debian / Older Ubuntu: sudo systemctl status ssh # For AlmaLinux: sudo systemctl status sshd

Check firewall status (Ubuntu/Debian):

sudo ufw status verbose

Check NTP sync:

timedatectl status | grep -E "synchronized|NTP"

Expected:

System clock synchronized: yes NTP service: active

Check automatic updates (Ubuntu/Debian):

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

List active cron jobs:

crontab -l

Rollback

To undo specific steps if something went wrong:

Re-enable root SSH login (if you locked yourself out and are recovering via console):

# Re-enable root/password login temporarily for recovery sudo rm /etc/ssh/sshd_config.d/00-hardening.conf sudo sshd -t # Restart SSH (use the variant for your system): sudo systemctl restart ssh.socket # Ubuntu 24.04 sudo systemctl restart ssh # Debian / older Ubuntu sudo systemctl restart sshd # AlmaLinux/RHEL

Disable UFW:

sudo ufw disable

Remove unattended-upgrades (Ubuntu/Debian):

sudo apt remove unattended-upgrades -y

Remove dnf-automatic (AlmaLinux):

sudo systemctl disable --now dnf-automatic.timer sudo dnf remove dnf-automatic -y

Remove a cron job:

crontab -e # Delete the relevant line, save and exit

Warning

Re-enabling root login or password authentication undoes most of the security hardening done in this guide. Only do this temporarily to recover access, then lock it back down.

Conclusion

That covers the full linux post-installation checklist. You now have a server with a proper hostname, fully updated packages, a non-root sudo user, SSH key authentication in place, root login disabled, a firewall configured, NTP synchronized, automatic security updates running, and a cron job schedule ready to extend. This is the baseline linux server setup after install that every VPS should have before anything else is deployed on it.

From here, the logical next steps depend on what the server is for:

  • Web server: Install Nginx or Apache, set up a virtual host, and configure SSL with Certbot
  • Database: Install and harden MySQL/MariaDB or PostgreSQL
  • Monitoring: Set up log aggregation (e.g., logrotate) or a lightweight monitoring agent
  • Access control: Review sudoers configuration and add team members using the same pattern from Step 3

The initial server configuration linux checklist does not end here - it evolves as the server's role grows. But this baseline is the non-negotiable starting point.

Document Version: 1.0
Last Updated: May 2026
Owner: Technical Documentation Team

VAT

  • Other

    Ex. VAT

    0%
  • austria

    Austria

    20%
  • Belgium

    Belgium

    21%
  • Bulgaria

    Bulgaria

    20%
  • Croatia

    Croatia

    25%
  • Cyprus

    Cyprus

    19%
  • Czech Republic

    Czech Republic

    21%
  • Denmark

    Denmark

    25%
  • Estonia

    Estonia

    22%
  • France

    France

    20%
  • Finland

    Finland

    24%
  • Germany

    Germany

    19%
  • Greece

    Greece

    24%
  • Hungary

    Hungary

    27%
  • Ireland

    Ireland

    23%
  • Italy

    Italy

    22%
  • Latvia

    Latvia

    21%
  • Lithuania

    Lithuania

    21%
  • Luxembourg

    Luxembourg

    17%
  • Malta

    Malta

    18%
  • Netherlands

    Netherlands

    21%
  • Poland

    Poland

    23%
  • Portugal

    Portugal

    23%
  • Romania

    Romania

    19%
  • Slovakia

    Slovakia

    20%
  • Slovenia

    Slovenia

    22%
  • Spain

    Spain

    21%
  • Sweden

    Sweden

    25%
  • USA

    USA

    0%
european
states
  • germany
  • Español
  • Italiano
  • Poland
  • Русский
  • Slovenski
  • Türkçe
  • kingdom
  • French
  • Hrvatska
  • Other
  • Austria
  • Belgium
  • Bulgaria
  • Croatia
  • Cyprus
  • Czech Republic
  • Denmark
  • Estonia
  • Finland
  • France
  • Germany
  • Greece
  • Hungary
  • Ireland
  • Italy
  • Latvia
  • Lithuania
  • Luxembourg
  • Malta
  • Netherlands
  • Poland
  • Portugal
  • Romania
  • Slovakia
  • Slovenia
  • Spain
  • Sweden
  • USA