Redis has no authentication by default and listens on all interfaces. Thousands of Redis instances are exposed to the internet with no password. attackers scan for them, dump their contents, and use them as launching pads for further attacks. This guide covers every layer of Redis hardening from network binding to ACLs.
Step 1 - Bind to Localhost Only
The most critical setting. Open /etc/redis/redis.conf:
sudo nano /etc/redis/redis.conf
Find and set:
Bind only to localhost and Unix socket
bind 127.0.0.1 ::1
Or bind to a specific internal IP if app servers need access
bind 127.0.0.1 10.0.0.5
Disable listening on external interfaces completely
protected-mode yes
Never set bind 0.0.0.0 on a production Redis instance. If application servers on other machines need Redis access, use a private network interface or SSH tunnel. not public exposure.
Step 2 - Enable Authentication
Simple Password (Redis 6+ Legacy)
In redis.conf
requirepass "use-a-very-long-random-password-here"
Generate a strong password:
openssl rand -base64 48
Output - something like Xk7mP2nQ8vR3tL5sJ9wH1dF4...
ACL-Based Authentication (Redis 6+ Recommended)
Redis 6 introduced ACLs (Access Control Lists) for fine-grained per-user permissions. Create an ACL file:
sudo nano /etc/redis/users.acl
Disable the default user (critical. default user has full access)
user default off nopass nocommands
Read-only user for monitoring
user monitor on >monitorpassword ~* &* +INFO +MONITOR +KEYS +GET +HGET +LRANGE
Application user - full key access but cannot modify server config
user appuser on >strongapppassword ~* &* +@read +@write +@string +@hash +@list +@set +@sortedset -CONFIG -DEBUG -SHUTDOWN -REPLICAOF -SLAVEOF
Admin user - full access (use only for admin tasks)
user admin on >adminpassword allkeys allchannels allcommands
Reference the ACL file in redis.conf:
aclfile /etc/redis/users.acl
Connect with a specific user:
redis-cli -u redis://appuser:strongapppassword@127.0.0.1:6379
Or
redis-cli AUTH appuser strongapppassword
Step 3 - Disable Dangerous Commands
Commands that can be weaponized if Redis is exposed:
In redis.conf. rename dangerous commands to empty string to disable
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command DEBUG ""
rename-command CONFIG ""
rename-command SHUTDOWN "SHUTDOWN_SAFE_KEY_9f3k2"
rename-command SLAVEOF ""
rename-command REPLICAOF ""
rename-command KEYS "" # Use SCAN instead for production
If you need CONFIG in your application (some frameworks require it), rename it to a long random string instead of disabling it, and share only the renamed command with application code.
Step 4 - Enable TLS (Redis 6+)
If Redis must communicate over a network (e.g., between app servers), use TLS:
Generate TLS certificates
mkdir -p /etc/redis/tls && cd /etc/redis/tls
CA
openssl req -new -x509 -days 3650 -nodes \
-keyout ca.key -out ca.crt \
-subj "/CN=Redis-CA"
Server cert
openssl req -new -nodes -keyout server.key -out server.csr \
-subj "/CN=redis.internal"
openssl x509 -req -days 1825 \
-in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt
chmod 600 /etc/redis/tls/*.key
chown redis:redis /etc/redis/tls/*
In redis.conf:
Disable plain port
port 0
Enable TLS
tls-port 6380
tls-cert-file /etc/redis/tls/server.crt
tls-key-file /etc/redis/tls/server.key
tls-ca-cert-file /etc/redis/tls/ca.crt
tls-auth-clients yes
tls-protocols "TLSv1.2 TLSv1.3"
tls-ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"
Connect with TLS:
redis-cli --tls \
--cert /etc/redis/tls/client.crt \
--key /etc/redis/tls/client.key \
--cacert /etc/redis/tls/ca.crt \
-p 6380 AUTH appuser strongapppassword
Step 5 - Run as a Non-Root User
Redis should run as the redis system user, not root:
Verify service user
grep User /lib/systemd/system/redis-server.service
Should show - User=redis
If not, create override
sudo systemctl edit redis-server
Add:
[Service]
User=redis
Group=redis
Set file permissions:
sudo chown -R redis:redis /var/lib/redis /etc/redis
sudo chmod 750 /var/lib/redis
sudo chmod 640 /etc/redis/redis.conf /etc/redis/users.acl
Step 6 - Memory and Resource Limits
Prevent Redis from consuming all available memory:
Maximum memory (adjust for your server)
maxmemory 512mb
Eviction policy when maxmemory is reached
allkeys-lru: evict least recently used keys (good for caches)
maxmemory-policy allkeys-lru
Prevent fork exhausting RAM during AOF rewrite
active-expire-enabled yes
lazyfree-lazy-eviction yes
Step 7 - Persistence Security
Disable persistence if Redis is only used as a cache (reduces attack surface):
Disable RDB snapshots
save ""
Disable AOF (append-only file)
appendonly no
If you need persistence, set safe file paths:
dir /var/lib/redis
dbfilename dump.rdb
appendfilename "appendonly.aof"
Step 8 - Network Firewall Rules
Even with bind 127.0.0.1, add UFW rules as defense-in-depth:
Block the default Redis port from all external sources
sudo ufw deny 6379/tcp
sudo ufw deny 6380/tcp
Only allow from specific app servers on private network
sudo ufw allow from 10.0.0.0/24 to any port 6380 proto tcp
sudo ufw reload
Verify Your Security
Test that unauthenticated access is blocked
redis-cli PING
Should return - NOAUTH Authentication required
Test that bound interfaces are correct
ss -tlnp | grep redis
Should show - 127.0.0.1:6379 only
Check ACL list
redis-cli AUTH admin adminpassword ACL LIST
Verify CONFIG is disabled (if renamed)
redis-cli AUTH appuser strongapppassword CONFIG GET maxmemory
Should return - ERR unknown command 'CONFIG'
Related Reading
- Securing Docker Containers Best Practices
- How to Configure UFW Firewall on Ubuntu
- Anonymous Domain Registration How To Buy Domain
- AI Coding Assistant Session Data Lifecycle
-
Best AI Tools for Container Security Scanning in Deployment
Related Articles