---
verify:
  image: images:debian/13
  type: virtual-machine
  network: true
  run_as: user
  blocks: [1, 2, 3, 4, 6]
  signal:
    type: exit
---
# Install Redis on Debian 13

Redis is an in-memory key-value store. Debian 13 (trixie) ships it in the main archive, so no third-party repo is needed.

## Install

```bash
sudo apt-get update
sudo apt-get install -y redis-server
```

## Bind to localhost and require a password

The stock `/etc/redis/redis.conf` listens broadly and has no password. The commands below rewrite both directives in place. They are idempotent: any existing (or commented-out) `bind` / `requirepass` line is deleted and one canonical line is appended, so re-running them always leaves the file in the same state.

```bash
CONF=/etc/redis/redis.conf

# Listen on loopback only.
sudo sed -i -E '/^[[:space:]]*#?[[:space:]]*bind[[:space:]]/d' "$CONF"
printf 'bind 127.0.0.1 ::1\n' | sudo tee -a "$CONF" >/dev/null

# Reject any command that is not authenticated.
sudo sed -i -E '/^[[:space:]]*#?[[:space:]]*requirepass[[:space:]]/d' "$CONF"
printf 'requirepass change-me-now\n' | sudo tee -a "$CONF" >/dev/null
```

> Use a real secret instead of `change-me-now`, and use the same value in the verification commands below.

Restart the service so the new directives take effect:

```bash
sudo systemctl restart redis-server
sudo systemctl is-active --quiet redis-server \
  || { echo 'FAIL: redis-server is not running — check: journalctl -u redis-server' >&2; exit 1; }
```

## Check it works

The check fails loudly (non-zero exit + message on stderr) if Redis is reachable without a password, or if the configured password does not work.

```bash
# 1. Auth must be enforced: an unauthenticated PING has to be refused.
if redis-cli ping 2>/dev/null | grep -qx 'PONG'; then
  echo 'FAIL: Redis answered PING without a password — requirepass is not in effect.' >&2
  exit 1
fi
echo 'PASS: unauthenticated PING was refused.'

# 2. The configured password must work.
if ! redis-cli --no-auth-warning -a change-me-now ping 2>/dev/null | grep -qx 'PONG'; then
  echo 'FAIL: authenticated PING did not return PONG — check requirepass and that the service restarted.' >&2
  exit 1
fi
echo 'PASS: authenticated PING returned PONG.'
```

Expected output:

```output
PASS: unauthenticated PING was refused.
PASS: authenticated PING returned PONG.
```

If both checks fail, Redis is most likely not running at all — inspect it with `sudo systemctl status redis-server`.

Optional: confirm the socket is bound to loopback only.

```bash
if sudo ss -ltn | grep -q '0.0.0.0:6379'; then
  echo 'FAIL: Redis is listening on a non-loopback address.' >&2
  exit 1
fi
echo 'PASS: Redis is not listening on 0.0.0.0.'
```