Operations note

Server Maintenance Checklist After OS Installation

A freshly installed server should not be considered ready immediately after the operating system is deployed. Before installing application services, it is useful to perform a short baseline configuration: update the system, check network and time settings, create a regular administrative user, restrict remote access, enable a firewall and add basic protection against repeated login attempts.

This checklist is written for Debian-based and RPM-based Linux systems. Commands that are identical are shown once. Separate blocks are used only where package managers, service names or firewall tools differ.

Important: keep an existing SSH session open until the new login method, SSH port and firewall rules are tested from a separate terminal window.

1. Confirm the installed system

Start by checking the current user, operating system, kernel and hostname.

whoami
id
cat /etc/os-release
uname -a
hostnamectl

2. Check network configuration

Verify addresses, routing and DNS resolver configuration before installing additional services.

ip -br addr
ip route
cat /etc/resolv.conf

Optional connectivity checks:

ping -c 4 1.1.1.1
ping -c 4 example.org

3. Update the system

Debian / Ubuntu

apt update
apt full-upgrade -y

RHEL / Rocky / AlmaLinux / Fedora

dnf check-update || true
dnf upgrade -y

On older RPM-based systems, yum may be used instead:

yum check-update || true
yum update -y

If the kernel or important system libraries were updated, reboot and verify the result:

reboot

After reconnecting:

cat /etc/os-release
uname -a
uptime

4. Install basic administration tools

A minimal installation often lacks useful troubleshooting utilities.

Debian / Ubuntu

apt install -y \
  sudo curl wget ca-certificates gnupg lsb-release \
  nano vim less htop tmux unzip zip tar jq \
  dnsutils iproute2 iputils-ping traceroute tcpdump \
  chrony fail2ban

RHEL / Rocky / AlmaLinux / Fedora

dnf install -y \
  sudo curl wget ca-certificates gnupg2 \
  nano vim less htop tmux unzip zip tar jq \
  bind-utils iproute iputils traceroute tcpdump \
  chrony fail2ban

5. Set hostname

Choose a clear hostname that identifies the server role.

hostnamectl set-hostname example-host
hostnamectl

Update /etc/hosts if necessary:

nano /etc/hosts

Basic example:

127.0.0.1       localhost
127.0.1.1       example-host

::1             localhost ip6-localhost ip6-loopback

Check the result:

hostname
hostnamectl
cat /etc/hosts

6. Check time synchronization

Correct time is important for logs, scheduled jobs and certificates.

Debian / Ubuntu

systemctl enable --now chrony
timedatectl
systemctl status chrony --no-pager -l

RHEL / Rocky / AlmaLinux / Fedora

systemctl enable --now chronyd
timedatectl
systemctl status chronyd --no-pager -l

Optional timezone example:

timedatectl set-timezone UTC
timedatectl

7. Create a regular administrative user

A regular administrative user should be used for routine access instead of direct root login.

Debian / Ubuntu

adduser example-admin
usermod -aG sudo example-admin
id example-admin
groups example-admin

RHEL / Rocky / AlmaLinux / Fedora

useradd -m example-admin
passwd example-admin
usermod -aG wheel example-admin
id example-admin
groups example-admin

Check sudo access:

su - example-admin
sudo whoami

Expected result:

root

8. Add SSH key authentication

Generate a key on the administrator workstation:

ssh-keygen -t ed25519 -a 100 -f ~/.ssh/example-server-admin

Copy the public key to the server:

ssh-copy-id -i ~/.ssh/example-server-admin.pub example-admin@SERVER_IP

If ssh-copy-id is not available, add the public key manually on the server:

mkdir -p /home/example-admin/.ssh
nano /home/example-admin/.ssh/authorized_keys
chown -R example-admin:example-admin /home/example-admin/.ssh
chmod 700 /home/example-admin/.ssh
chmod 600 /home/example-admin/.ssh/authorized_keys

Test login from a new terminal session:

ssh -i ~/.ssh/example-server-admin example-admin@SERVER_IP
Do not close the existing session yet. First confirm that key-based login works from a second terminal window.

9. Move SSH to a non-default port

This does not replace proper authentication, but it reduces noise from automated scans.

cat > /etc/ssh/sshd_config.d/10-custom-port.conf <<'EOF'
Port 2222
EOF

sshd -t

Debian / Ubuntu

systemctl reload ssh

RHEL / Rocky / AlmaLinux / Fedora

If SELinux is enforcing, allow the new SSH port first:

dnf install -y policycoreutils-python-utils
semanage port -a -t ssh_port_t -p tcp 2222
systemctl reload sshd

Check listening ports:

ss -tulpn | grep sshd

Test the new port from a separate terminal:

ssh -p 2222 -i ~/.ssh/example-server-admin example-admin@SERVER_IP

10. Harden SSH access

After key-based access on the new port is confirmed, disable direct root login and password authentication.

cat > /etc/ssh/sshd_config.d/20-basic-hardening.conf <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
AllowUsers example-admin

X11Forwarding no
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
EOF

sshd -t

Debian / Ubuntu

systemctl reload ssh

RHEL / Rocky / AlmaLinux / Fedora

systemctl reload sshd

Verify effective SSH settings:

sshd -T | egrep '^(port|permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|authenticationmethods|allowusers|maxauthtries|x11forwarding)'

11. Configure firewall

Only required ports should be open. A simple baseline may allow SSH, HTTP and HTTPS.

Debian / Ubuntu with UFW

apt install -y ufw

ufw default deny incoming
ufw default allow outgoing

ufw allow 2222/tcp comment 'ssh'
ufw allow 80/tcp comment 'http'
ufw allow 443/tcp comment 'https'

ufw --force enable
ufw status verbose

If the old SSH port was temporarily allowed, remove it only after confirming that the new port works:

ufw delete allow 22/tcp
ufw status numbered

RHEL / Rocky / AlmaLinux / Fedora with firewalld

dnf install -y firewalld
systemctl enable --now firewalld

firewall-cmd --permanent --add-port=2222/tcp
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
firewall-cmd --list-all

If the default SSH service should not remain open, remove it only after confirming the new SSH port:

firewall-cmd --permanent --remove-service=ssh
firewall-cmd --reload
firewall-cmd --list-all

12. Enable fail2ban

Fail2ban helps reduce repeated authentication attempts against SSH.

Debian / Ubuntu

apt install -y fail2ban

RHEL / Rocky / AlmaLinux / Fedora

dnf install -y fail2ban fail2ban-systemd

Create the SSH jail:

cat > /etc/fail2ban/jail.d/sshd.local <<'EOF'
[sshd]
enabled = true
port = 2222
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h
ignoreip = 127.0.0.1/8 ::1
EOF

systemctl enable --now fail2ban
systemctl restart fail2ban
fail2ban-client status
fail2ban-client status sshd

13. Final baseline verification

Save the final state in server notes.

echo "=== OS ==="
cat /etc/os-release

echo
echo "=== HOSTNAME ==="
hostnamectl

echo
echo "=== TIME ==="
timedatectl

echo
echo "=== NETWORK ==="
ip -br addr
ip route

echo
echo "=== LISTEN PORTS ==="
ss -tulpn

echo
echo "=== SSH EFFECTIVE CONFIG ==="
sshd -T | egrep '^(port|permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|authenticationmethods|allowusers|maxauthtries|x11forwarding)'
echo
echo "=== FAIL2BAN ==="
fail2ban-client status
fail2ban-client status sshd

Debian / Ubuntu firewall check

ufw status verbose

RHEL / Rocky / AlmaLinux / Fedora firewall check

firewall-cmd --list-all

14. Maintenance record template

Date:
Server:
OS:
Kernel:
Hostname:
Administrative user:
SSH port:
Firewall status:
Time synchronization:
Fail2ban status:
Open ports:
Changes made:
Verification commands:
Notes:

The purpose of the checklist is not to make the server complex. It is to create a known-good baseline: updated system, correct time, limited remote access, active firewall and basic protection against repeated login attempts.

← Back to notes