The Real Problem: A Freshly Installed Server That Isn’t Ready to Use
The first time I set up a VPS running Fedora Server, my feeling after the install finished was “done, let’s go”. But just three days later, the logs showed hundreds of brute-force attempts on port 22, continuous root login attempts, and a firewall that was barely blocking anything significant because I hadn’t configured a single rule.
Fedora Server is not a “secure out of the box” distro. It gives you a clean foundation, but everything else — security, user management, network services — is on you. I’ve been using Fedora as my main development machine for 2 years and I’m quite happy with its package update cadence, but the server side needs a few extra configuration steps before it’s truly production-ready.
Understanding the Problem: Why Fedora Server Defaults Aren’t Enough
Fedora prioritizes flexibility over opinionated hardened defaults. After a minimal install, here’s what you’re working with:
- SSH daemon is running and allows password-based login by default — making it easy to brute-force.
- firewalld is enabled but the default
publiczone still exposes many unnecessary services. - SELinux is in Enforcing mode — good for security, but many people disable it when they hit errors without understanding why.
- No fail2ban — brute-force attempts can keep going indefinitely without being blocked.
- Root SSH login isn’t disabled in some install configurations.
The issue isn’t Fedora itself — it’s that many people skip the initial hardening steps, assuming it can be done later.
Your Options
Option 1: Automate with Ansible
If you manage multiple servers, Ansible is a solid choice. Write a playbook once and you’re done. The downside: it’s overkill for beginners, and you’ll need to understand YAML and module syntax first.
Option 2: A One-Time Shell Script
Write a bash script that handles everything, run it after provisioning. Faster than Ansible but harder to maintain, and prone to bugs if not thoroughly tested.
Option 3: Manual Step-by-Step Configuration (Recommended for Beginners)
Takes more time, but you understand what each step does. When something breaks later, you know exactly where to look. This is how I started, and I still use this approach when I need to debug.
The Best Approach: Step-by-Step Initial Configuration
Step 1: Install Fedora Server
Download the ISO from the official Fedora website. During installation, choose Fedora Server Edition with a minimal configuration to avoid installing unnecessary packages. During setup, create a root password and also create a non-root user.
After the first boot, update the system immediately:
sudo dnf update -y
sudo reboot
Why reboot: if the kernel was updated, you need to restart to run the new kernel.
Step 2: Create a User and Grant Sudo Privileges
The root account still exists after installation, but using it directly is bad practice — one wrong command can wipe the entire server with no checkpoint. Create a dedicated user and grant sudo access:
# Create a new user
useradd -m -s /bin/bash sysadmin
passwd sysadmin
# Add to the wheel group (sudo on Fedora)
usermod -aG wheel sysadmin
# Verify
id sysadmin
From now on, log in as this user — never use root directly.
Step 3: Properly Lock Down SSH
SSH is your only entry point to the server — and also the most frequently attacked service. I once skipped this step and paid for it with thousands of brute-force log entries every day, plus unusual CPU spikes in the middle of the night.
First, copy your SSH public key to the server (run this from your local machine):
# On your local machine
ssh-keygen -t ed25519 -C "[email protected]"
ssh-copy-id sysadmin@your_server_ip
Then, edit the SSH configuration file on the server:
sudo nano /etc/ssh/sshd_config
Find and update the following lines:
Port 2222 # Change the default port (optional but reduces noise)
PermitRootLogin no # Disable root login via SSH
PasswordAuthentication no # Use SSH keys only
PubkeyAuthentication yes
MaxAuthTries 3
LoginGraceTime 30
# Restart SSH (DO NOT close your current session)
sudo systemctl restart sshd
# Open a new terminal and test the connection before closing your current session
ssh -p 2222 sysadmin@your_server_ip
Important: if you change the SSH port, you must open that port in the firewall before restarting sshd. Skipping this step means locking yourself out of the server.
Step 4: Configure firewalld
Fedora uses firewalld with a zone-based approach. I find this quite convenient once you’re familiar with it.
# Check current active zones
sudo firewall-cmd --get-active-zones
# View existing rules
sudo firewall-cmd --list-all
# If you changed SSH port to 2222
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --permanent --remove-service=ssh # Remove the old port 22 rule
# Only open what you actually need (e.g., for a web server)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
# Reload to apply changes
sudo firewall-cmd --reload
# Verify
sudo firewall-cmd --list-all
Step 5: Keep SELinux — Don’t Disable It
Dozens of guides on Stack Overflow and Linux forums will tell you to “just disable SELinux to avoid the hassle”. I disagree with that advice. SELinux is your second layer of defense — it stops attackers even after they’ve bypassed the first layer, for example through a web application with an RCE vulnerability.
# Check SELinux status
sudo sestatus
# Ensure it's in Enforcing mode
sudo getenforce
If you encounter SELinux-related errors, use audit2allow to analyze them instead of disabling SELinux:
# View recent SELinux denials
sudo ausearch -m avc -ts recent
# Or use sealert if setroubleshoot is installed
sudo sealert -a /var/log/audit/audit.log
Step 6: Install fail2ban
fail2ban automatically blocks IPs after N failed login attempts. On my server, this tool blocks an average of 80–150 IPs per day — almost all of them are automated bots scanning from various botnets.
# Install
sudo dnf install fail2ban -y
# Create a local config file (don't modify the original)
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local
Add or update the [sshd] section. Fedora uses systemd-journald, so you need to specify the backend explicitly:
[sshd]
enabled = true
port = 2222
filter = sshd
backend = systemd
maxretry = 3
bantime = 3600
findtime = 600
# Enable and start the service
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# Check status
sudo fail2ban-client status sshd
Step 7: Set Up Automatic Security Updates
Fedora includes dnf-automatic for automatically installing security updates:
sudo dnf install dnf-automatic -y
# Edit the config: only download security updates
sudo nano /etc/dnf/automatic.conf
[commands]
upgrade_type = security
apply_updates = yes
# Enable the timer
sudo systemctl enable --now dnf-automatic.timer
sudo systemctl status dnf-automatic.timer
Full System Check After Configuration
# Currently running services
sudo systemctl list-units --type=service --state=running
# Check which ports are listening
sudo ss -tlnp
# View recent login attempts
sudo journalctl -u sshd --since "1 hour ago"
# Verify fail2ban is working
sudo fail2ban-client status
After completing these 7 steps, your server is solid enough for basic production use. It typically takes me around 30–45 minutes to complete this process on a new server, and every step can be scripted for future use.
One lesson I’ve learned: don’t wait for an incident before hardening your server. Do it right after installation — it saves a tremendous amount of headache down the road.

