# how to secure Redis before exposing it to the network

## TL;DR

Redis ships with no auth and dangerous commands enabled, which is why exposed Redis servers get cryptomined within hours. Before it touches a network: bind it to the right interface, set up ACL users, rename or disable commands like FLUSHALL, enable TLS, and firewall everything else. Covers Redis 6 and later.

```text
how to secure Redis before exposing it to the network
```

## Use this when

- You are about to expose Redis beyond the loopback interface for the first time
- A scan found your Redis reachable from the internet (fix this today)
- You inherited a Redis setup with no auth
- You are writing the Redis section of a hardening runbook

## Not for this skill when

- Redis only listens on the loopback interface and only local apps use it (still set a password, but the rest is optional)
- You need Redis Cluster or Sentinel auth internals (different topic)
- You are tuning Redis performance

## Steps

### 1. Bind to the right interface and enable protected mode

Redis should only listen where it needs to. If your app is on the same host, the loopback interface is enough.

```bash
grep -E "^(bind|protected-mode|port)" /etc/redis/redis.conf
```

Expected: `bind` points at the loopback address, `protected-mode` is yes, and the port is the default unless you changed it deliberately.

### 2. Set up ACL users instead of one shared password

Redis 6 added real ACLs. Give each client its own user with only the commands and keys it needs.

```bash
redis-cli ACL SETUSER appuser on "[a strong password]" "~app:*" "+@all" "-@dangerous"
redis-cli ACL LIST
```

Expected: `ACL LIST` shows the new user with `on`, its key patterns, and the command rules. Once ACL users exist, the default user should be off or heavily restricted.

### 3. Disable or rename dangerous commands

FLUSHALL, CONFIG, DEBUG, and EVAL can ruin your day in the wrong hands. Rename them to unguessable names or disable them.

```bash
echo 'rename-command FLUSHALL ""' | sudo tee -a /etc/redis/redis.conf
echo 'rename-command CONFIG "[unguessable name]"' | sudo tee -a /etc/redis/redis.conf
sudo systemctl restart redis-server
```

Expected: `redis-cli FLUSHALL` returns "unknown command". Keep the renamed CONFIG name in your secrets manager, not in chat.

### 4. Enable TLS for traffic between nodes and clients

If Redis traffic crosses a network, encrypt it. Redis 6 and later support TLS natively with cert files.

```bash
grep -E "^tls-" /etc/redis/redis.conf | head -5
```

Expected: tls-port, tls-cert-file, tls-key-file, and tls-ca-cert-file are set. Generate certs with your internal CA and test with `redis-cli --tls`.

### 5. Firewall everything except your app hosts

Even with auth, Redis should not be reachable from the whole internet. Allow only your app servers.

```bash
sudo ufw allow from [app server IP] to any port 6379
sudo ufw deny 6379
```

Expected: `sudo ufw status` shows the allow rule above the deny, and a connection attempt from anywhere else times out.

## Why this happens

Redis was designed as a fast in-memory store for trusted networks, so its defaults assume nobody hostile can reach it. The internet proved that assumption wrong years ago, and scanners still find open Redis daily. Every step here adds one layer between "reachable" and "owned".

## Edge cases and pitfalls

- Renaming CONFIG breaks monitoring tools that call it; check your exporters before renaming.
- `redis-cli` without `--tls` fails confusingly against a TLS-only port; always match the client flags to the server config.
- ACL rules are order-sensitive in subtle ways; test each user with `redis-cli --user appuser` before deploying.
- Replicas need the same ACL and TLS config, or the primary is hardened and the replica is wide open.
- Do not rely on protected mode alone; it is a speed bump, not a firewall.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_HVZjr60GzMjHwsB68tYM4A
