← Back to DevBytes

Securing Fedora Servers: A Practical Checklist

Introduction to Securing Fedora Servers

Fedora is a popular, cutting-edge Linux distribution that serves as the upstream for Red Hat Enterprise Linux. Its rapid release cycle and modern kernel make it an attractive choice for developers and system administrators running production servers. However, a fresh Fedora installation is not secure by default — it requires deliberate hardening before exposure to the internet.

This tutorial provides a practical, actionable checklist for securing a Fedora server. Whether you are deploying a web server, a database host, or a container runtime, these steps will significantly reduce your attack surface and help you maintain a defensible infrastructure.

Why Server Hardening Matters

Every service you expose is a potential entry point for attackers. Default configurations are often optimized for convenience rather than security. By following a systematic hardening process, you:

1. System Updates and Package Management

The first step in securing any server is ensuring all installed packages are up to date. Fedora uses the DNF package manager, which makes it straightforward to apply security patches and enable automatic updates.

Applying Updates Manually

Start by updating the entire system immediately after installation:

# Update all packages
sudo dnf upgrade --refresh

# Check for available security updates only
sudo dnf check-update --security

# Apply only security-related updates
sudo dnf upgrade --security

Enabling Automatic Updates with dnf-automatic

Fedora provides the dnf-automatic package for unattended updates. This is especially useful for security patches that should be applied promptly.

# Install dnf-automatic
sudo dnf install -y dnf-automatic

# Edit the configuration to apply security updates automatically
sudo sed -i 's/^upgrade_type.*/upgrade_type = security/' /etc/dnf/automatic.conf
sudo sed -i 's/^apply_updates.*/apply_updates = yes/' /etc/dnf/automatic.conf
sudo sed -i 's/^emit_via.*/emit_via = motd/' /etc/dnf/automatic.conf

# Enable and start the timer
sudo systemctl enable --now dnf-automatic.timer

The timer runs daily by default. You can verify its schedule with:

systemctl list-timers dnf-automatic.timer

2. User Management and Access Control

Proper user management is foundational to server security. You should never perform routine tasks as the root user. Instead, create dedicated user accounts with sudo privileges and enforce strong authentication policies.

Creating a Sudo User

# Create a new user
sudo adduser deployuser

# Set a strong password
sudo passwd deployuser

# Add the user to the wheel group for sudo access
sudo usermod -aG wheel deployuser

# Verify group membership
groups deployuser

Configuring Sudo Policies

Edit the sudoers file to enforce strict policies, such as requiring password authentication for every sudo command:

# Open the sudoers file safely
sudo visudo -f /etc/sudoers.d/00_custom

# Add the following content
Defaults    requiretty
Defaults    !visiblepw
Defaults    use_pty
Defaults    logfile="/var/log/sudo.log"
Defaults    passwd_timeout=2
Defaults    timestamp_timeout=5

# Allow wheel group members full access with password
%wheel    ALL=(ALL)    ALL

Disabling Root Login Over SSH

Once you have a working sudo user, disable direct root login to prevent brute-force attacks against the most privileged account:

# Edit the SSH daemon configuration
sudo nano /etc/ssh/sshd_config

# Set the following directives
PermitRootLogin no

3. SSH Hardening

SSH is the primary remote administration protocol for Linux servers, making it a prime target for attackers. Hardening SSH involves key-based authentication, changing default ports, and limiting access.

Setting Up Key-Based Authentication

On your local machine, generate an SSH key pair:

# Generate an ed25519 key (recommended over RSA)
ssh-keygen -t ed25519 -C "admin@yourdomain.com" -f ~/.ssh/fedora_server

# Copy the public key to the server
ssh-copy-id -i ~/.ssh/fedora_server.pub deployuser@server_ip

Hardening the SSH Daemon Configuration

Edit /etc/ssh/sshd_config with the following hardened settings:

# Disable password authentication
PasswordAuthentication no

# Disable empty passwords
PermitEmptyPasswords no

# Change the default SSH port (optional but recommended)
Port 2222

# Limit authentication attempts
MaxAuthTries 3

# Set a login grace period
LoginGraceTime 30

# Disable X11 forwarding if not needed
X11Forwarding no

# Allow only specific users
AllowUsers deployuser

# Use strong ciphers and MACs
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group16-sha512

After saving the configuration, validate it before restarting the service:

# Validate the configuration
sudo sshd -t

# Restart the SSH service
sudo systemctl restart sshd
Warning: Always test your SSH configuration in a second terminal session before closing your current connection. A misconfiguration can lock you out of the server.

4. Firewall Configuration with firewalld

Fedora ships with firewalld, a dynamic firewall manager that uses zones to define trust levels for network connections. A properly configured firewall is essential for controlling inbound traffic.

Basic Firewall Setup

# Ensure firewalld is installed and running
sudo dnf install -y firewalld
sudo systemctl enable --now firewalld

# Check the default zone
sudo firewall-cmd --get-default-zone

# List all active rules
sudo firewall-cmd --list-all

Configuring Zones and Services

For a typical web server, you only need to allow SSH, HTTP, and HTTPS traffic:

# If you changed the SSH port, allow the custom port
sudo firewall-cmd --permanent --add-port=2222/tcp

# Allow web traffic
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https

# Remove unnecessary services
sudo firewall-cmd --permanent --remove-service=cockpit
sudo firewall-cmd --permanent --remove-service=dhcpv6-client

# Reload the firewall to apply changes
sudo firewall-cmd --reload

# Verify the final configuration
sudo firewall-cmd --list-all

Using Rich Rules for Advanced Control

Rich rules allow you to create more granular firewall policies, such as rate limiting:

# Limit SSH connections to 2 per minute from any source
sudo firewall-cmd --permanent --add-rich-rule='rule service name=ssh limit value=2/m accept'

# Allow SSH only from a specific IP range
sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=192.168.1.0/24 port port=2222 protocol=tcp accept'

# Drop all other SSH traffic
sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 port port=2222 protocol=tcp drop'

sudo firewall-cmd --reload

5. SELinux Configuration

SELinux (Security-Enhanced Linux) is enabled by default on Fedora and provides mandatory access control (MAC). While it can be complex, disabling SELinux is strongly discouraged. Instead, learn to configure it properly.

Checking SELinux Status

# Check current SELinux status
sestatus

# Check the current mode
getenforce

# View SELinux booleans related to common services
getsebool -a | grep -E 'httpd|ssh|ftp'

Configuring SELinux for Web Servers

If you are running a web server with non-standard document roots, you need to set the correct SELinux contexts:

# Set the httpd context for a custom web directory
sudo semanage fcontext -a -t httpd_sys_content_t '/var/www/mysite(/.*)?'
sudo restorecon -Rv /var/www/mysite

# Allow httpd to connect to a database
sudo setsebool -P httpd_can_network_connect_db on

# Allow httpd to make outbound network connections
sudo setsebool -P httpd_can_network_connect on

# Allow httpd to read user home directories (use with caution)
sudo setsebool -P httpd_read_user_content on

Troubleshooting SELinux Denials

# Install troubleshooting tools
sudo dnf install -y setroubleshoot-server

# View recent SELinux denials
sudo ausearch -m AVC,USER_AVC -ts recent

# Generate a report of denials with suggested fixes
sudo sealert -a /var/log/audit/audit.log

6. Fail2Ban for Intrusion Prevention

Fail2Ban monitors log files for repeated failed authentication attempts and temporarily bans offending IP addresses using firewall rules. It is an effective defense against brute-force attacks.

Installing and Configuring Fail2Ban

# Install Fail2Ban
sudo dnf install -y fail2ban

# Create a local configuration file
sudo nano /etc/fail2ban/jail.local

Add the following configuration to jail.local:

[DEFAULT]
# Ban duration in seconds (1 hour)
bantime = 3600

# Time window for counting failures (10 minutes)
findtime = 600

# Number of failures before ban
maxretry = 3

# Email notifications
destemail = admin@yourdomain.com
sender = fail2ban@yourdomain.com
action = %(action_)s

[sshd]
enabled = true
port = 2222
logpath = %(sshd_log)s
backend = systemd
maxretry = 3
bantime = 3600

Enable and start the Fail2Ban service:

# Enable and start Fail2Ban
sudo systemctl enable --now fail2ban

# Check the status of all jails
sudo fail2ban-client status

# Check the SSH jail specifically
sudo fail2ban-client status sshd

# Manually unban an IP address
sudo fail2ban-client set sshd unbanip 192.168.1.100

7. Securing Network Services

Beyond SSH and the firewall, individual network services require their own hardening. Here are configurations for common services.

Securing Nginx

# Install Nginx
sudo dnf install -y nginx

# Edit the main configuration
sudo nano /etc/nginx/nginx.conf

Add the following security headers in the http block:

server {
    listen 80 default_server;
    server_name _;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2 default_server;
    server_name yourdomain.com;

    # SSL configuration
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Content-Security-Policy "default-src 'self';" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # Hide server version
    server_tokens off;

    # Disable unnecessary HTTP methods
    if ($request_method !~ ^(GET|POST|HEAD|OPTIONS)$ ) {
        return 405;
    }

    location / {
        root /var/www/html;
        index index.html index.htm;
    }
}

Securing PostgreSQL

# Edit PostgreSQL configuration
sudo nano /var/lib/pgsql/data/pg_hba.conf

# Restrict connections to localhost only
# TYPE  DATABASE  USER  ADDRESS       METHOD
local   all       all                 peer
host    all       all   127.0.0.1/32  scram-sha-256
host    all       all   ::1/128       scram-sha-256

# Edit the main PostgreSQL configuration
sudo nano /var/lib/pgsql/data/postgresql.conf

# Set the following directives
listen_addresses = 'localhost'
password_encryption = scram-sha-256
ssl = on
log_connections = on
log_disconnections = on

# Restart PostgreSQL
sudo systemctl restart postgresql

8. Kernel and System Hardening

The Linux kernel exposes many tunable parameters that affect security. Fedora uses sysctl for runtime configuration.

Applying Sysctl Security Parameters

# Create a custom sysctl configuration file
sudo nano /etc/sysctl.d/99-security.conf

Add the following hardening parameters:

# Disable IP forwarding (unless this is a router)
net.ipv4.ip_forward = 0

# Disable packet redirect
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# Enable reverse path filtering
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Log suspicious packets (martians)
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

# Disable ICMP redirect acceptance
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0

# Disable source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0

# Enable TCP SYN cookies
net.ipv4.tcp_syncookies = 1

# Ignore ICMP broadcast requests (smurf attacks)
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Restrict kernel pointers in /proc
kernel.kptr_restrict = 2

# Restrict access to dmesg
kernel.dmesg_restrict = 1

# Restrict access to kernel performance events
kernel.perf_event_paranoid = 2

# Enable ASLR
kernel.randomize_va_space = 2

# Restrict unprivileged use of BPF
kernel.unprivileged_bpf_disabled = 1

# Restrict user namespaces
kernel.unprivileged_userns_clone = 0

# Protect hardlinks and symlinks
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
fs.protected_fifos = 2
fs.protected_regular = 2

Apply the changes immediately:

sudo sysctl --system

9. Audit and Logging

Comprehensive logging is essential for detecting security incidents and performing forensic analysis. Fedora includes rsyslog and auditd for system and security auditing.

Configuring Auditd

# Install and enable auditd
sudo dnf install -y audit
sudo systemctl enable --now auditd

# Edit the audit configuration
sudo nano /etc/audit/auditd.conf

Configure the following settings:

log_file = /var/log/audit/audit.log
log_format = RAW
log_group = root
priority_boost = 4
flush = INCREMENTAL_ASYNC
freq = 50
max_log_file = 100
num_logs = 5
max_log_file_action = ROTATE
space_left = 75
space_left_action = EMAIL
action_mail_acct = root
admin_space_left = 50
admin_space_left_action = HALT
disk_full_action = HALT
disk_error_action = HALT

Adding Audit Rules

Create custom audit rules to monitor critical system files and activities:

# Create a custom rules file
sudo nano /etc/audit/rules.d/99_custom.rules

# Add the following rules
# Monitor changes to /etc/passwd
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/security/opasswd -p wa -k identity

# Monitor sudoers files
-w /etc/sudoers -p wa -k scope
-w /etc/sudoers.d/ -p wa -k scope

# Monitor SSH configuration
-w /etc/ssh/sshd_config -p wa -k ssh_config

# Monitor login and logout events
-w /var/log/lastlog -p wa -k logins
-w /var/run/faillock/ -p wa -k logins

# Monitor system time changes
-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time-change
-w /etc/localtime -p wa -k time-change

# Monitor kernel module loading
-w /sbin/insmod -p x -k modules
-w /sbin/rmmod -p x -k modules
-w /sbin/modprobe -p x -k modules
-a always,exit -F arch=b64 -S init_module,delete_module -k modules

# Restart auditd to apply rules
sudo systemctl restart auditd

Sending Logs to a Remote Server

For production environments, forward logs to a centralized logging server to prevent tampering:

# Edit rsyslog configuration
sudo nano /etc/rsyslog.conf

# Add at the end of the file
*.* @@logserver.yourdomain.com:6514

# Configure TLS for secure log transmission
$DefaultNetstreamDriver gtls
$DefaultNetstreamDriverCAFile /etc/pki/rsyslog/ca.pem
$DefaultNetstreamDriverCertFile /etc/pki/rsyslog/client-cert.pem
$DefaultNetstreamDriverKeyFile /etc/pki/rsyslog/client-key.pem
$ActionSendStreamDriverMode 1
$ActionSendStreamDriverAuthMode x509/name
$ActionSendStreamDriverPermittedPeer logserver.yourdomain.com

sudo systemctl restart rsyslog

10. Automated Vulnerability Scanning

Regular vulnerability scanning helps identify weaknesses before attackers do. OpenSCAP is the standard tool for scanning Fedora systems against security baselines.

Running a Security Scan with OpenSCAP

# Install OpenSCAP and SCAP security guide
sudo dnf install -y openscap-utils scap-security-guide

# Find available scan profiles
ls /usr/share/xml/scap/ssg/content/

# Run a scan against the OSPP (Protection Profile) baseline
sudo oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_ospp \
  --results scan-results.xml \
  --report scan-report.html \
  /usr/share/xml/scap/ssg/content/ssg-fedora-ds.xml

# View the HTML report
sudo cp scan-report.html /var/www/html/

Generating a Remediation Script

# Generate a bash script to fix identified issues
sudo oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_ospp \
  --remediate \
  --results remediation-results.xml \
  --report remediation-report.html \
  /usr/share/xml/scap/ssg/content/ssg-fedora-ds.xml
Tip: Always review remediation scripts in a test environment before applying them to production servers. Some fixes may affect service availability.

11. Regular Maintenance Checklist

Security is not a one-time task but an ongoing process. Create a maintenance schedule to ensure your server remains secure over time.

Weekly Tasks

Monthly Tasks

Quarterly Tasks

Running Lynis for Comprehensive Auditing

# Install Lynis
sudo dnf install -y lynis

# Run a full system audit
sudo lynis audit system

# View the report
sudo cat /var/log/lynis-report.dat

# Run with warnings and suggestions only
sudo lynis audit system --quiet

12. Additional Hardening Measures

Disabling Unnecessary Services

# List all enabled services
sudo systemctl list-unit-files --type=service --state=enabled

# Disable services you do not need
sudo systemctl disable --now avahi-daemon
sudo systemctl disable --now cups
sudo systemctl disable --now bluetooth
sudo systemctl disable --now ModemManager

# Mask services to prevent them from being started manually
sudo systemctl mask avahi-daemon

Configuring Automatic Time Synchronization

# Enable chronyd for NTP synchronization
sudo dnf install -y chrony
sudo systemctl enable --now chronyd

# Verify synchronization
chronyc tracking
chronyc sources

Setting Up AIDE for File Integrity Monitoring

# Install AIDE
sudo dnf install -y aide

# Initialize the AIDE database
sudo aide --init

# Move the database to the proper location
sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

# Run a manual check
sudo aide --check

# Set up a daily cron job for integrity checks
echo "0 3 * * * root /usr/sbin/aide --check | mail -s 'AIDE Report' admin@yourdomain.com" | sudo tee /etc/cron.d/aide

Limiting Process and Resource Usage

Configure resource limits to prevent denial-of-service attacks from consuming all system resources:

# Edit limits configuration
sudo nano /etc/security/limits.conf

# Add the following limits
*    soft    nofile    65535
*    hard    nofile    65535
*    soft    nproc     4096
*    hard    nproc     8192
*    soft    core      0
*    hard    core      0

# Configure systemd resource limits for specific services
sudo systemctl edit nginx.service

In the systemd override file:

[Service]
LimitNOFILE=65535
LimitNPROC=4096
MemoryMax=2G
CPUQuota=200%
TasksMax=512

Conclusion

Securing a Fedora server requires a multi-layered approach that addresses system updates, access control, network filtering, kernel hardening, and continuous monitoring. By following this practical checklist, you establish a strong security baseline that protects against common attack vectors while maintaining the flexibility and performance that make Fedora an excellent server platform. Remember that security is an ongoing process — regularly review your configurations, apply updates promptly, audit your systems, and stay informed about emerging threats. The time invested in hardening your server today will pay dividends in preventing costly security incidents tomorrow.

— Ad —

Google AdSense will appear here after approval

← Back to all articles