Privacy Tools Guide

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...

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'