2 giờ sáng. App production liên tục trả về lỗi connection timeout. Mình mở log ra thì thấy Redis client không kết nối được. Mình vừa xong việc cài Redis trên Fedora Server mới setup buổi chiều — test local thì redis-cli ping ra PONG ngon lành — nhưng app từ server khác thì timeout hoàn toàn.
Đây là bài học đầu tiên mình học được khi làm việc với Fedora: nó không phải Ubuntu. SELinux enforcing và firewalld cứng hơn nhiều, và nếu không xử lý cả ba lớp — bind address, firewall, SELinux — thì ngồi debug đến sáng cũng không ra.
Vấn đề thực tế gặp phải
Cài Redis xong, start service, test ngay trên server thì ổn. Nhưng app Node.js chạy trên server khác trong cùng mạng nội bộ connect vào thì timeout sau đúng 30 giây.
Check /var/log/redis/redis.log — không có gì bất thường. Check systemctl status redis — running. Nghi firewall, check firewall-cmd --list-ports — không có port 6379. Mở port, reload, test lại — vẫn timeout.
Đến đây mình mới nhớ: Fedora enforcing SELinux từ mặc định. Ubuntu thường dùng AppArmor với profile lỏng hơn nhiều. Fedora thì SELinux strict from day one, không ai nói trước cho mình cả.
Phân tích nguyên nhân
Ngồi trace lại thì có ba thứ phải xử lý đồng thời — debug từng cái một là nguyên nhân mất cả tiếng:
- Redis bind address: Mặc định Redis chỉ lắng nghe
127.0.0.1— chỉ local access, app từ server khác không tài nào kết nối được - firewalld: Port 6379 mặc định bị block hoàn toàn, không exception
- SELinux: Ngay cả khi đã mở firewall, SELinux vẫn có thể chặn Redis bind port hoặc block network connection từ process khác
Ba cái này phải xử lý cả ba. Bỏ sót một là ngồi debug tiếp.
Cài đặt Redis trên Fedora Server
Bước 1: Cài Redis từ repo mặc định
Mình dùng Fedora làm máy development chính đã 2 năm — Redis trên repo Fedora thường khá mới, hiện tại là 7.x, không cần thêm repo bên ngoài. Package policycoreutils-python-utils cài kèm để có audit2allow và audit2why dùng ở bước SELinux sau.
sudo dnf install redis policycoreutils-python-utils -y
# Kiểm tra version
redis-server --version
Bước 2: Cấu hình Redis
File cấu hình chính tại /etc/redis/redis.conf. Backup trước khi sửa:
sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
sudo nano /etc/redis/redis.conf
Các dòng cần thay đổi:
# Bind cả localhost và IP nội bộ của server
# Thay 192.168.1.100 bằng IP thực của interface mạng nội bộ
bind 127.0.0.1 192.168.1.100
# Đặt password — bắt buộc nếu expose ra network
# Redis 6+ hỗ trợ ACL mạnh hơn, nhưng requirepass đủ cho setup đơn giản
requirepass YourStrongPassword123!
# Giới hạn memory — rule of thumb: ~25-30% tổng RAM server
# 512mb phù hợp cho server 2-4GB RAM
maxmemory 512mb
maxmemory-policy allkeys-lru
# Port mặc định
port 6379
Về bind address: Nếu app và Redis cùng server, giữ 127.0.0.1. Nếu cần kết nối từ server khác, thêm IP interface nội bộ. Tránh dùng 0.0.0.0 trên production trừ khi firewall đã chặt chẽ.
Bước 3: Enable và start service
sudo systemctl enable redis --now
sudo systemctl status redis
Giải quyết vấn đề SELinux
Phần này hay bị skip nhất — hầu hết tutorial Redis viết cho Ubuntu, không đả động đến SELinux. Trên Fedora thì khác: enforcing mode từ ngày đầu, và không nên tắt bằng setenforce 0. Cách đúng là tạo policy.
Kiểm tra SELinux có đang block không
# Xem denial gần đây liên quan Redis
sudo ausearch -m avc -ts recent | grep redis
# Xem thông báo setroubleshoot
sudo journalctl -t setroubleshoot | tail -50
Nếu thấy dòng kiểu avc: denied \{ name_connect \} liên quan Redis — đúng rồi, SELinux đang block.
Cách 1: Bật boolean SELinux có sẵn
# Xem toàn bộ boolean liên quan Redis
sudo getsebool -a | grep redis
# Cho phép các kết nối mạng cần thiết
sudo setsebool -P redis_can_network_connect on
Tên boolean phụ thuộc vào Fedora version — nếu redis_can_network_connect không có trong danh sách, skip thẳng xuống Cách 2.
Cách 2: Tạo SELinux policy từ audit log (chính xác nhất)
Cách này mình hay dùng hơn — tạo policy từ chính những gì bị block thực tế, không guess:
# Xem lý do bị block
sudo ausearch -m avc -ts recent | grep redis | audit2why
# Tạo policy module
sudo ausearch -m avc -ts recent | grep redis | audit2allow -M redis_custom
# Apply policy
sudo semodule -i redis_custom.pp
# Kiểm tra module đã load
sudo semodule -l | grep redis
Nếu đổi thư mục data của Redis
Khi thay đổi data dir khỏi mặc định /var/lib/redis, phải gán lại SELinux context:
# Ví dụ đổi sang /data/redis
sudo semanage fcontext -a -t redis_db_t "/data/redis(/.*)?"
sudo restorecon -Rv /data/redis
Cấu hình firewalld
Mở port — nhưng đúng cách
Mở toàn bộ port 6379 cho mọi IP là cách nhanh nhưng không an toàn. Dùng rich rule để chỉ cho phép subnet nội bộ:
# Chỉ cho phép subnet 192.168.1.0/24 kết nối 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
# Kiểm tra rules đã apply
sudo firewall-cmd --list-rich-rules
Nếu chỉ có một app server cụ thể cần kết nối:
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
Dùng zone internal thay vì rich rules
Có interface mạng nội bộ riêng (ví dụ eth1)? Zone internal sạch hơn và dễ quản lý về sau:
# Thêm interface nội bộ vào zone internal
sudo firewall-cmd --permanent --zone=internal --add-interface=eth1
# Mở Redis port trong zone internal
sudo firewall-cmd --permanent --zone=internal --add-port=6379/tcp
sudo firewall-cmd --reload
Checklist triển khai Redis bảo mật trên Fedora
Sau vài lần gặp sự cố 2 giờ sáng, đây là quy trình mình đang chạy cho production — theo thứ tự này:
# 1. Cài đặt
sudo dnf install redis policycoreutils-python-utils -y
# 2. Cấu hình Redis với password và bind address
sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
# Sửa bind, requirepass, maxmemory trong /etc/redis/redis.conf
# 3. Start service
sudo systemctl enable redis --now
# 4. Chạy thử ~5 phút để SELinux tạo audit events, rồi tạo policy
sudo ausearch -m avc -ts recent | grep redis | audit2allow -M redis_custom
sudo semodule -i redis_custom.pp
# 5. Mở firewall cho subnet nội bộ
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 từ máy khác trong mạng
redis-cli -h 192.168.1.100 -p 6379 -a YourStrongPassword123! ping
Kiểm tra sau khi setup
# Xác nhận Redis đang listen đúng interface
sudo ss -tlnp | grep redis
# Test authentication
redis-cli -h 127.0.0.1 -a YourStrongPassword123! ping
# Xem thông tin server
redis-cli -a YourStrongPassword123! info server | grep -E "redis_version|uptime|connected_clients"
Tùy chọn: Giới hạn tài nguyên qua systemd
Một lớp kiểm soát nữa đáng thêm — giới hạn ở cấp systemd phòng khi Redis gặp memory leak hay bị flood request:
sudo systemctl edit redis
Thêm nội dung:
[Service]
LimitNOFILE=65535
MemoryMax=512M
sudo systemctl daemon-reload
sudo systemctl restart redis
Ba lớp bảo vệ — SELinux, firewalld và password authentication — bổ sung cho nhau. Bỏ bất kỳ lớp nào cũng tạo ra điểm yếu không cần thiết. Mất thêm 15 phút setup đúng từ đầu thì đỡ mất 2 tiếng debug lúc 2 giờ sáng.

