Introduction
After successfully installing AlmaLinux, proper post-installation configuration is crucial for creating a secure, optimized, and production-ready system. This comprehensive guide walks through essential configuration steps that every system administrator should perform after a fresh AlmaLinux installation, ensuring your system is properly secured, updated, and configured for your specific use case.
Initial System Access and Verification
Verify System Installation
# Check system information
hostnamectl
# Verify AlmaLinux version
cat /etc/almalinux-release
cat /etc/os-release
# Check kernel version
uname -r
# Verify system architecture
arch
# Check available disk space
df -h
# Review memory configuration
free -h
# Check CPU information
lscpu
# Verify network interfaces
ip addr show
Set System Hostname
# Set a meaningful hostname
hostnamectl set-hostname server01.example.com
# Verify hostname change
hostnamectl
# Update /etc/hosts file
echo "127.0.0.1 localhost localhost.localdomain" > /etc/hosts
echo "::1 localhost localhost.localdomain" >> /etc/hosts
echo "$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d/ -f1 | head -1) $(hostname) $(hostname -s)" >> /etc/hosts
# Verify hosts file
cat /etc/hosts
System Updates and Package Management
Configure DNF and Update System
# Configure DNF for better performance
cat >> /etc/dnf/dnf.conf << 'EOF'
# Performance optimizations
fastestmirror=True
max_parallel_downloads=10
keepcache=True
clean_requirements_on_remove=True
skip_if_unavailable=True
deltarpm=True
EOF
# Clean DNF cache
dnf clean all
# Update GPG keys
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux-9
# Perform full system update
dnf update -y
# Install essential packages
dnf install -y \
vim \
nano \
wget \
curl \
net-tools \
bind-utils \
bash-completion \
policycoreutils-python-utils \
yum-utils \
lsof \
iotop \
htop \
git \
tmux \
tree \
unzip \
tar \
gzip \
bzip2 \
rsync \
tcpdump \
telnet \
traceroute \
mtr \
nmap-ncat
# Install development tools (if needed)
dnf groupinstall -y "Development Tools"
# Remove unnecessary packages
dnf autoremove -y
Enable Additional Repositories
# Install EPEL repository
dnf install -y epel-release
# Install ELRepo (for newer kernels and hardware drivers)
dnf install -y https://www.elrepo.org/elrepo-release-9.el9.elrepo.noarch.rpm
# Install RPM Fusion (optional, for multimedia support)
dnf install -y --nogpgcheck https://mirrors.rpmfusion.org/free/el/rpmfusion-free-release-$(rpm -E %rhel).noarch.rpm
# Update repository cache
dnf makecache
# List enabled repositories
dnf repolist
# Configure repository priorities (optional)
dnf install -y dnf-plugins-core
dnf config-manager --set-enabled powertools
Network Configuration
Configure Network Settings
# Check current network configuration
nmcli device status
nmcli connection show
# Configure static IP (if needed)
# Replace ens33 with your interface name
INTERFACE="ens33"
nmcli connection modify $INTERFACE ipv4.method manual
nmcli connection modify $INTERFACE ipv4.addresses 192.168.1.100/24
nmcli connection modify $INTERFACE ipv4.gateway 192.168.1.1
nmcli connection modify $INTERFACE ipv4.dns "8.8.8.8 8.8.4.4"
nmcli connection modify $INTERFACE ipv4.dns-search "example.com"
# Apply changes
nmcli connection up $INTERFACE
# Configure IPv6 (if needed)
nmcli connection modify $INTERFACE ipv6.method auto
nmcli connection modify $INTERFACE ipv6.dns "2001:4860:4860::8888 2001:4860:4860::8844"
# Set connection to auto-connect
nmcli connection modify $INTERFACE connection.autoconnect yes
# Configure hostname via NetworkManager
nmcli general hostname server01.example.com
Network Performance Tuning
# Optimize network stack for better performance
cat > /etc/sysctl.d/99-network-performance.conf << 'EOF'
# Network performance tuning
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
net.ipv4.tcp_congestion_control = bbr
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_mtu_probing = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.core.somaxconn = 65535
net.ipv4.ip_local_port_range = 10000 65000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 30
EOF
# Apply sysctl settings
sysctl -p /etc/sysctl.d/99-network-performance.conf
Security Configuration
Configure Firewall
# Enable and start firewalld
systemctl enable --now firewalld
# Check firewall status
firewall-cmd --state
firewall-cmd --get-default-zone
# Set default zone
firewall-cmd --set-default-zone=public
# Configure basic services
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
# Configure custom ports (example)
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --permanent --add-port=3306/tcp
# Remove unnecessary services
firewall-cmd --permanent --remove-service=cockpit
firewall-cmd --permanent --remove-service=dhcpv6-client
# Reload firewall
firewall-cmd --reload
# List all rules
firewall-cmd --list-all
SELinux Configuration
# Check SELinux status
sestatus
# Ensure SELinux is enforcing
setenforce 1
# Make it permanent
sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config
# Install SELinux utilities
dnf install -y policycoreutils policycoreutils-python-utils selinux-policy-targeted
# Check for SELinux denials
ausearch -m avc -ts recent
# Configure common SELinux booleans
# Allow httpd to connect to network
setsebool -P httpd_can_network_connect on
# Allow httpd to send mail
setsebool -P httpd_can_sendmail on
# List all SELinux booleans
getsebool -a
SSH Hardening
# Backup original SSH configuration
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup
# Create secure SSH configuration
cat > /etc/ssh/sshd_config.d/99-secure.conf << 'EOF'
# Security hardening
Protocol 2
Port 22
PermitRootLogin no
PasswordAuthentication yes
PubkeyAuthentication yes
PermitEmptyPasswords no
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
UseDNS no
X11Forwarding no
AllowUsers *@*
DenyUsers root
LoginGraceTime 60
MaxStartups 10:30:60
Banner /etc/issue.net
# Strong cryptography
Ciphers [email protected],[email protected],aes256-ctr
MACs [email protected],[email protected]
KexAlgorithms curve25519-sha256,[email protected]
HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256
EOF
# Create SSH banner
cat > /etc/issue.net << 'EOF'
***************************************************************************
AUTHORIZED ACCESS ONLY
***************************************************************************
This system is for authorized use only. All activity is monitored and
reported. Unauthorized access is strictly prohibited and will be prosecuted
to the full extent of the law.
***************************************************************************
EOF
# Test SSH configuration
sshd -t
# Restart SSH service
systemctl restart sshd
# Configure SSH key for administrative user
mkdir -p ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
User and Permission Management
Create Administrative Users
# Create admin group
groupadd -g 2000 admins
# Create administrative user
useradd -m -u 1001 -g admins -G wheel -s /bin/bash sysadmin
passwd sysadmin
# Configure sudo access
cat > /etc/sudoers.d/admins << 'EOF'
# Admin group sudo configuration
%admins ALL=(ALL) ALL
%wheel ALL=(ALL) ALL
# Allow specific commands without password (optional)
%admins ALL=(ALL) NOPASSWD: /usr/bin/systemctl, /usr/bin/journalctl
EOF
# Verify sudo configuration
visudo -c
# Set password policies
authconfig --passalgo=sha512 --passminlen=12 --passminclass=3 --passmaxrepeat=3 --update
# Configure password aging
chage -M 90 -m 7 -W 14 sysadmin
Configure User Limits
# Set system limits
cat > /etc/security/limits.d/99-custom.conf << 'EOF'
# Custom resource limits
* soft nofile 65536
* hard nofile 65536
* soft nproc 32768
* hard nproc 32768
* soft memlock unlimited
* hard memlock unlimited
* soft stack 10240
* hard stack 32768
# Specific user limits
@admins soft nofile 131072
@admins hard nofile 131072
@admins soft nproc 65536
@admins hard nproc 65536
EOF
# Configure systemd limits
cat > /etc/systemd/system.conf.d/limits.conf << 'EOF'
[Manager]
DefaultLimitNOFILE=65536
DefaultLimitNPROC=32768
DefaultTasksMax=infinity
EOF
# Reload systemd configuration
systemctl daemon-reload
System Monitoring and Logging
Configure System Logging
# Configure rsyslog
cat > /etc/rsyslog.d/99-custom.conf << 'EOF'
# Custom logging configuration
# Log authentication messages
auth,authpriv.* /var/log/secure
# Log all kernel messages
kern.* /var/log/kernel.log
# Log cron messages
cron.* /var/log/cron
# Log mail messages
mail.* -/var/log/maillog
# Emergency messages
*.emerg :omusrmsg:*
# Remote logging (optional)
# *.* @@remote-syslog-server:514
EOF
# Configure log rotation
cat > /etc/logrotate.d/custom << 'EOF'
/var/log/kernel.log
/var/log/custom/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 0640 root root
sharedscripts
postrotate
/usr/bin/systemctl reload rsyslog > /dev/null 2>&1 || true
endscript
}
EOF
# Configure journald
mkdir -p /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/99-custom.conf << 'EOF'
[Journal]
Storage=persistent
Compress=yes
SplitMode=uid
SyncIntervalSec=5m
RateLimitInterval=30s
RateLimitBurst=10000
MaxRetentionSec=3month
MaxFileSec=1week
ForwardToSyslog=yes
EOF
# Restart logging services
systemctl restart rsyslog
systemctl restart systemd-journald
Enable System Auditing
# Install and configure auditd
dnf install -y audit
# Enable auditd service
systemctl enable --now auditd
# Configure audit rules
cat > /etc/audit/rules.d/99-custom.rules << 'EOF'
# Delete all rules
-D
# Set buffer size
-b 8192
# Failure mode
-f 1
# Monitor authentication
-w /etc/passwd -p wa -k passwd_changes
-w /etc/group -p wa -k group_changes
-w /etc/shadow -p wa -k shadow_changes
-w /etc/sudoers -p wa -k sudoers_changes
-w /etc/sudoers.d/ -p wa -k sudoers_changes
# Monitor SSH
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /etc/ssh/sshd_config.d/ -p wa -k sshd_config
# Monitor system calls
-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time_change
-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -F auid>=1000 -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S chown -S fchown -S fchownat -S lchown -F auid>=1000 -F auid!=4294967295 -k perm_mod
# Monitor privileged commands
-a always,exit -F path=/usr/bin/passwd -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
-a always,exit -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged
# Make configuration immutable
-e 2
EOF
# Load audit rules
augenrules --load
# Verify audit rules
auditctl -l
Performance Optimization
System Performance Tuning
# Install tuned for performance optimization
dnf install -y tuned
# Enable and start tuned
systemctl enable --now tuned
# List available profiles
tuned-adm list
# Set appropriate profile
# For virtual guests
tuned-adm profile virtual-guest
# For physical servers
# tuned-adm profile throughput-performance
# For database servers
# tuned-adm profile postgresql
# Verify active profile
tuned-adm active
# Custom kernel parameters
cat > /etc/sysctl.d/99-performance.conf << 'EOF'
# Performance tuning
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.vfs_cache_pressure = 50
kernel.pid_max = 4194304
fs.file-max = 2097152
kernel.threads-max = 2097152
vm.max_map_count = 262144
kernel.sched_migration_cost_ns = 5000000
kernel.sched_autogroup_enabled = 0
EOF
# Apply sysctl settings
sysctl -p /etc/sysctl.d/99-performance.conf
Configure Swap
# Check current swap
swapon --show
# Create swap file (if needed)
# Create 4GB swap file
dd if=/dev/zero of=/swapfile bs=1G count=4
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
# Make swap permanent
echo '/swapfile none swap sw 0 0' >> /etc/fstab
# Configure swap usage
echo 'vm.swappiness=10' >> /etc/sysctl.d/99-swap.conf
sysctl -p /etc/sysctl.d/99-swap.conf
Service Management
Disable Unnecessary Services
# List all services
systemctl list-unit-files --type=service
# Disable unnecessary services
systemctl disable --now bluetooth.service
systemctl disable --now cups.service
systemctl disable --now avahi-daemon.service
systemctl disable --now ModemManager.service
# Mask services to prevent accidental start
systemctl mask bluetooth.service
systemctl mask cups.service
# Enable essential services
systemctl enable --now crond.service
systemctl enable --now sshd.service
systemctl enable --now NetworkManager.service
systemctl enable --now firewalld.service
Configure Time Synchronization
# Install chrony
dnf install -y chrony
# Configure chrony
cat > /etc/chrony.conf << 'EOF'
# Use public NTP servers
server 0.pool.ntp.org iburst
server 1.pool.ntp.org iburst
server 2.pool.ntp.org iburst
server 3.pool.ntp.org iburst
# Record the rate at which the system clock gains/losses time
driftfile /var/lib/chrony/drift
# Allow the system clock to be stepped in the first three updates
makestep 1.0 3
# Enable kernel synchronization
rtcsync
# Enable logging
logdir /var/log/chrony
# Allow NTP client access from local network
#allow 192.168.0.0/16
# Serve time even if not synchronized to a time source
#local stratum 10
# Specify file containing keys for NTP authentication
keyfile /etc/chrony.keys
# Disable logging of client accesses
noclientlog
# Send a message to syslog if a clock adjustment is larger than 0.5 seconds
logchange 0.5
EOF
# Enable and start chrony
systemctl enable --now chronyd
# Check time synchronization
chronyc sources
chronyc tracking
timedatectl
Backup Configuration
Setup Basic Backup Strategy
# Create backup directories
mkdir -p /backup/{system,config,data,scripts}
chmod 700 /backup
# Create backup script
cat > /backup/scripts/system-backup.sh << 'EOF'
#!/bin/bash
# System backup script
BACKUP_DIR="/backup/system"
DATE=$(date +%Y%m%d_%H%M%S)
HOSTNAME=$(hostname -s)
BACKUP_FILE="$BACKUP_DIR/backup_${HOSTNAME}_${DATE}.tar.gz"
# Create backup directory if it doesn't exist
mkdir -p "$BACKUP_DIR"
# Backup important directories
tar -czf "$BACKUP_FILE" \
--exclude=/backup \
--exclude=/proc \
--exclude=/sys \
--exclude=/dev \
--exclude=/run \
--exclude=/tmp \
--exclude=/mnt \
--exclude=/media \
--exclude=/lost+found \
--exclude=/var/cache \
--exclude=/var/tmp \
/etc \
/root \
/home \
/var/log \
/usr/local \
/opt 2>/dev/null
# Keep only last 7 backups
find "$BACKUP_DIR" -name "backup_${HOSTNAME}_*.tar.gz" -mtime +7 -delete
echo "Backup completed: $BACKUP_FILE"
EOF
chmod +x /backup/scripts/system-backup.sh
# Create backup cron job
cat > /etc/cron.d/system-backup << 'EOF'
# System backup - daily at 2 AM
0 2 * * * root /backup/scripts/system-backup.sh >> /var/log/backup.log 2>&1
EOF
# Create configuration backup script
cat > /backup/scripts/config-backup.sh << 'EOF'
#!/bin/bash
# Configuration backup script
CONFIG_DIR="/backup/config"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$CONFIG_DIR"
# Backup package list
rpm -qa | sort > "$CONFIG_DIR/installed-packages-$DATE.txt"
# Backup repository configuration
tar -czf "$CONFIG_DIR/repos-$DATE.tar.gz" /etc/yum.repos.d/
# Backup network configuration
tar -czf "$CONFIG_DIR/network-$DATE.tar.gz" /etc/sysconfig/network-scripts/
# Backup firewall rules
firewall-cmd --list-all-zones > "$CONFIG_DIR/firewall-rules-$DATE.txt"
# Backup SELinux configuration
sestatus -v > "$CONFIG_DIR/selinux-status-$DATE.txt"
getsebool -a > "$CONFIG_DIR/selinux-booleans-$DATE.txt"
echo "Configuration backup completed"
EOF
chmod +x /backup/scripts/config-backup.sh
System Documentation
Create System Documentation
# Create documentation directory
mkdir -p /root/documentation
# Generate system documentation
cat > /root/documentation/system-info.md << 'EOF'
# System Documentation
## System Information
- **Hostname**: $(hostname)
- **OS Version**: $(cat /etc/almalinux-release)
- **Kernel**: $(uname -r)
- **Architecture**: $(arch)
- **Installation Date**: $(stat / | grep Birth | cut -d' ' -f3-)
## Hardware Information
- **CPU**: $(lscpu | grep "Model name" | cut -d':' -f2 | xargs)
- **Cores**: $(nproc)
- **Memory**: $(free -h | grep Mem | awk '{print $2}')
- **Disk**: $(df -h / | tail -1 | awk '{print $2}')
## Network Configuration
- **IP Address**: $(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | head -1)
- **Gateway**: $(ip route | grep default | awk '{print $3}')
- **DNS Servers**: $(grep nameserver /etc/resolv.conf | awk '{print $2}' | tr '\n' ' ')
## Services
- **SSH Port**: $(grep "^Port" /etc/ssh/sshd_config | awk '{print $2}')
- **Firewall**: $(systemctl is-active firewalld)
- **SELinux**: $(getenforce)
## Administrative Users
$(grep -E "^[^:]+:[^:]+:(1[0-9]{3}|[2-9][0-9]{3}):" /etc/passwd | cut -d: -f1,3,5)
## Backup Configuration
- **Backup Directory**: /backup
- **Backup Schedule**: Daily at 2:00 AM
- **Retention**: 7 days
## Monitoring
- **Log Directory**: /var/log
- **Audit Log**: /var/log/audit/audit.log
- **System Journal**: journalctl
## Notes
- System configured on: $(date)
- Configuration performed by: $(whoami)
EOF
# Create quick reference card
cat > /root/documentation/quick-reference.txt << 'EOF'
# AlmaLinux Quick Reference
## System Commands
systemctl status <service> # Check service status
systemctl restart <service> # Restart service
journalctl -u <service> -f # Follow service logs
df -h # Check disk space
free -h # Check memory usage
top / htop # Monitor processes
ss -tulpn # Check listening ports
## Firewall Commands
firewall-cmd --list-all # List firewall rules
firewall-cmd --add-port=<port>/tcp --permanent
firewall-cmd --reload # Apply changes
## SELinux Commands
getenforce # Check SELinux status
setenforce 1 # Enable SELinux
ausearch -m avc -ts recent # Check SELinux denials
## User Management
useradd -m -g <group> <user> # Add user
passwd <user> # Set password
usermod -aG <group> <user> # Add user to group
## Package Management
dnf update # Update all packages
dnf install <package> # Install package
dnf search <keyword> # Search packages
dnf info <package> # Package information
## Network Commands
ip addr show # Show IP addresses
ip route show # Show routing table
ss -tulpn # Show listening ports
nmcli connection show # NetworkManager connections
EOF
Final Steps and Verification
System Health Check
# Create system health check script
cat > /usr/local/bin/system-health-check.sh << 'EOF'
#!/bin/bash
# System health check script
echo "=== System Health Check ==="
echo "Date: $(date)"
echo
# Check system uptime
echo "Uptime:"
uptime
echo
# Check disk usage
echo "Disk Usage:"
df -h | grep -E "^/dev|^Filesystem"
echo
# Check memory usage
echo "Memory Usage:"
free -h
echo
# Check system load
echo "System Load:"
cat /proc/loadavg
echo
# Check failed services
echo "Failed Services:"
systemctl --failed
echo
# Check SELinux status
echo "SELinux Status:"
getenforce
echo
# Check for recent errors
echo "Recent Errors (last 10):"
journalctl -p err -n 10 --no-pager
echo
# Check network connectivity
echo "Network Connectivity:"
ping -c 2 8.8.8.8 >/dev/null 2>&1 && echo "Internet: OK" || echo "Internet: FAILED"
echo
# Check for security updates
echo "Security Updates Available:"
dnf check-update --security | grep -E "^[a-zA-Z]" | wc -l
echo
echo "=== Health Check Complete ==="
EOF
chmod +x /usr/local/bin/system-health-check.sh
# Run initial health check
/usr/local/bin/system-health-check.sh
Create Maintenance Schedule
# Create maintenance cron jobs
cat > /etc/cron.d/system-maintenance << 'EOF'
# System maintenance schedule
# Daily health check at 6 AM
0 6 * * * root /usr/local/bin/system-health-check.sh > /var/log/health-check.log 2>&1
# Weekly security updates check - Sundays at 1 AM
0 1 * * 0 root dnf check-update --security > /var/log/security-updates.log 2>&1
# Monthly full system update check - 1st of month at 2 AM
0 2 1 * * root dnf check-update > /var/log/system-updates.log 2>&1
# Bi-weekly configuration backup - 1st and 15th at 3 AM
0 3 1,15 * * root /backup/scripts/config-backup.sh > /var/log/config-backup.log 2>&1
EOF
Conclusion
Your AlmaLinux system is now properly configured with essential post-installation settings. This configuration provides:
- Security: Hardened SSH, firewall rules, SELinux enforcement, and audit logging
- Performance: Optimized kernel parameters, network tuning, and resource limits
- Monitoring: Comprehensive logging, system auditing, and health checks
- Backup: Automated backup strategies for system and configuration files
- Documentation: System documentation and quick reference guides
Remember to:
- Regularly update your system with security patches
- Monitor system logs and audit trails
- Test your backup and recovery procedures
- Review and update security configurations periodically
- Keep documentation current with system changes
This foundation ensures your AlmaLinux system is production-ready, secure, and optimized for reliable operation.