Installing and Configuring Redis on Fedora Server: Handling SELinux and firewalld for High-Performance Cache Server Deployment

Fedora tutorial - IT technology blog
Fedora tutorial - IT technology blog

2 AM. The production app keeps returning connection timeout errors. I open the logs and see the Redis client can’t connect. I had just finished installing Redis on a freshly set up Fedora Server that afternoon — redis-cli ping returned a clean PONG locally — but requests from another server were timing out completely.

This was the first lesson I learned working with Fedora: it’s not Ubuntu. SELinux enforcing and firewalld are considerably stricter, and if you don’t handle all three layers — bind address, firewall, SELinux — you’ll be debugging until sunrise.

The Real Problem

After installing Redis, starting the service, and testing on the server itself, everything looked fine. But when a Node.js app running on a separate server in the same internal network tried to connect, it timed out after exactly 30 seconds.

I checked /var/log/redis/redis.log — nothing unusual. Checked systemctl status redis — running. Suspected the firewall, checked firewall-cmd --list-ports — no port 6379. Opened the port, reloaded, tested again — still timing out.

That’s when it clicked: Fedora enforces SELinux by default. Ubuntu typically uses AppArmor with much more permissive profiles. Fedora runs strict SELinux from day one, and nobody had warned me about that.

Root Cause Analysis

Tracing through the problem, there were three things that needed to be handled simultaneously — debugging them one at a time was what cost me an hour:

  • Redis bind address: By default, Redis only listens on 127.0.0.1 — local access only, so apps on other servers have no way to connect
  • firewalld: Port 6379 is completely blocked by default, no exceptions
  • SELinux: Even after opening the firewall, SELinux can still block Redis from binding to a port or deny network connections from other processes

All three need to be addressed. Miss one and you’re back to debugging.

Installing Redis on Fedora Server

Step 1: Install Redis from the Default Repository

I’ve been using Fedora as my main development machine for two years — Redis in the Fedora repo is usually fairly recent, currently 7.x, so there’s no need to add an external repo. The policycoreutils-python-utils package is installed alongside it to get audit2allow and audit2why, which we’ll need in the SELinux step later.

sudo dnf install redis policycoreutils-python-utils -y

# Check version
redis-server --version

Step 2: Configure Redis

The main configuration file is at /etc/redis/redis.conf. Back it up before making changes:

sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
sudo nano /etc/redis/redis.conf

Lines to change:

# Bind to both localhost and the server's internal IP
# Replace 192.168.1.100 with the actual IP of your internal network interface
bind 127.0.0.1 192.168.1.100

# Set a password — required if exposing to the network
# Redis 6+ supports more powerful ACLs, but requirepass is sufficient for simple setups
requirepass YourStrongPassword123!

# Limit memory — rule of thumb: ~25-30% of total server RAM
# 512mb is appropriate for a 2-4GB RAM server
maxmemory 512mb
maxmemory-policy allkeys-lru

# Default port
port 6379

On bind address: If your app and Redis are on the same server, keep 127.0.0.1. If you need connections from another server, add the internal interface IP. Avoid using 0.0.0.0 in production unless your firewall rules are airtight.

Step 3: Enable and Start the Service

sudo systemctl enable redis --now
sudo systemctl status redis

Resolving SELinux Issues

This part gets skipped most often — the majority of Redis tutorials are written for Ubuntu and don’t touch SELinux at all. Fedora is a different story: enforcing mode from day one, and you shouldn’t disable it with setenforce 0. The right approach is to create a policy.

Check Whether SELinux Is Blocking

# View recent denials related to Redis
sudo ausearch -m avc -ts recent | grep redis

# View setroubleshoot messages
sudo journalctl -t setroubleshoot | tail -50

If you see a line like avc: denied \{ name_connect \} related to Redis — that’s it, SELinux is blocking it.

Option 1: Enable an Existing SELinux Boolean

# List all booleans related to Redis
sudo getsebool -a | grep redis

# Allow the necessary network connections
sudo setsebool -P redis_can_network_connect on

Boolean names vary by Fedora version — if redis_can_network_connect isn’t in the list, skip straight to Option 2.

Option 2: Generate an SELinux Policy from Audit Logs (Most Precise)

This is the approach I prefer — generating a policy based on what was actually blocked, no guesswork:

# See why it was blocked
sudo ausearch -m avc -ts recent | grep redis | audit2why

# Generate a policy module
sudo ausearch -m avc -ts recent | grep redis | audit2allow -M redis_custom

# Apply the policy
sudo semodule -i redis_custom.pp

# Verify the module loaded
sudo semodule -l | grep redis

If You Change Redis’s Data Directory

When moving the data directory away from the default /var/lib/redis, you must reassign the SELinux context:

# Example: moving to /data/redis
sudo semanage fcontext -a -t redis_db_t "/data/redis(/.*)?" 
sudo restorecon -Rv /data/redis

Configuring firewalld

Opening the Port — the Right Way

Opening port 6379 to all IPs is quick but insecure. Use a rich rule to restrict access to the internal subnet only:

# Only allow subnet 192.168.1.0/24 to connect to Redis
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="6379" protocol="tcp" accept'
sudo firewall-cmd --reload

# Verify the rules were applied
sudo firewall-cmd --list-rich-rules

If only one specific app server needs to connect:

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.50" port port="6379" protocol="tcp" accept'
sudo firewall-cmd --reload

Using the Internal Zone Instead of Rich Rules

Have a dedicated internal network interface (e.g., eth1)? The internal zone is cleaner and easier to manage long-term:

# Add the internal interface to the internal zone
sudo firewall-cmd --permanent --zone=internal --add-interface=eth1

# Open the Redis port in the internal zone
sudo firewall-cmd --permanent --zone=internal --add-port=6379/tcp
sudo firewall-cmd --reload

Secure Redis Deployment Checklist for Fedora

After a few 2 AM incidents, here’s the process I now run for production — follow it in this order:

# 1. Install
sudo dnf install redis policycoreutils-python-utils -y

# 2. Configure Redis with a password and bind address
sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
# Edit bind, requirepass, maxmemory in /etc/redis/redis.conf

# 3. Start the service
sudo systemctl enable redis --now

# 4. Let it run for ~5 minutes so SELinux generates audit events, then create policy
sudo ausearch -m avc -ts recent | grep redis | audit2allow -M redis_custom
sudo semodule -i redis_custom.pp

# 5. Open firewall for the internal subnet
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="6379" protocol="tcp" accept'
sudo firewall-cmd --reload

# 6. Test from another machine on the network
redis-cli -h 192.168.1.100 -p 6379 -a YourStrongPassword123! ping

Post-Setup Verification

# Confirm Redis is listening on the correct interface
sudo ss -tlnp | grep redis

# Test authentication
redis-cli -h 127.0.0.1 -a YourStrongPassword123! ping

# View server information
redis-cli -a YourStrongPassword123! info server | grep -E "redis_version|uptime|connected_clients"

Optional: Limit Resources via systemd

One more layer worth adding — systemd-level limits as a safeguard against memory leaks or request floods:

sudo systemctl edit redis

Add the following:

[Service]
LimitNOFILE=65535
MemoryMax=512M
sudo systemctl daemon-reload
sudo systemctl restart redis

Three layers of protection — SELinux, firewalld, and password authentication — complement each other. Dropping any one of them creates an unnecessary vulnerability. Spending an extra 15 minutes setting things up correctly from the start beats losing 2 hours debugging at 2 AM.

Share: