# How to install and secure Redis on Ubuntu 24.04

> Install Redis on Ubuntu 24.04, keep it on localhost, replace the open default user with ACL users, block dangerous commands and cap its memory.

Source: https://vpsnine.com/tutorials/install-redis-ubuntu · Updated: 2026-10-21

Difficulty: intermediate · Time: about 20 minutes · Tested on: Ubuntu 24.04 LTS

Prerequisites:

- A server running Ubuntu 24.04
- Root or a user with sudo
- An SSH session to the server

To install Redis on Ubuntu 24.04, run `sudo apt install redis-server`: you get Redis 7.0, running under systemd and listening on `127.0.0.1` and `::1` only. To secure it, keep it on localhost, turn the passwordless `default` user off, give your app its own ACL user with a password and without the dangerous commands, and set a memory limit so a growing cache can't take the whole server down.

Redis without a password on a public address is one of the most common ways servers get taken over: anyone who can reach port 6379 can rewrite its config and drop files on disk. Every step below closes part of that.

## Install Redis

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

Check the version and that it answers:

```bash
redis-server --version
redis-cli ping
```

The first prints `Redis server v=7.0.15 ...`; the second prints `PONG`. Redis runs as the `redis-server` service, reads `/etc/redis/redis.conf` and keeps its data in `/var/lib/redis`.

### Redis, Valkey and the license

Redis 7.0, the version in Ubuntu 24.04, is under the BSD license like every release before it. From Redis 7.4 the project moved to source-available licenses (RSALv2 and SSPLv1), and Redis 8.0 added the AGPLv3 as a third option. In response the Linux Foundation forked Redis 7.2 as [Valkey](https://valkey.io), which stays BSD-licensed and speaks the same protocol.

For a cache or queue on your own server, any of them works and your app won't know the difference. Ubuntu 24.04 also packages Valkey 7.2 (`sudo apt install valkey-server`); Debian 13 and Ubuntu 26.04 ship both Redis 8.0 and Valkey (8.1 and 9.0 respectively). This tutorial uses `redis-server`. On Valkey the same settings live in `/etc/valkey/valkey.conf` and the client is `valkey-cli`.

## Keep it on localhost

Open `/etc/redis/redis.conf` and check these three lines. They are Ubuntu's defaults; don't change them unless another server must reach Redis:

```ini
bind 127.0.0.1 -::1
protected-mode yes
port 6379
```

- `bind` lists the addresses Redis listens on. The `-` before `::1` means "skip it if IPv6 isn't available" instead of failing to start.
- `protected-mode yes` is a safety net: if Redis ever listens on a public address while the `default` user has no password, it refuses every connection that doesn't come from localhost.

### Check it worked

```bash
sudo ss -ltnp | grep 6379
```

```text
LISTEN 0      511        127.0.0.1:6379      0.0.0.0:*    users:(("redis-server",...))
LISTEN 0      511            [::1]:6379         [::]:*    users:(("redis-server",...))
```

Only the loopback addresses. If you see `0.0.0.0:6379` or `*:6379`, fix `bind` before going on.

## Replace the default user with ACL users

Since Redis 6, users and their rights are managed with ACLs. Out of the box there is one user, `default`, with no password and every right. The old `requirepass` setting only gives `default` a password: every app and admin then shares one password with full access, including `FLUSHALL` and `CONFIG`.

Instead, switch `default` off and create named users. Make up two long random passwords (`openssl rand -hex 32` twice), then create the ACL file:

```bash
sudo nano /etc/redis/users.acl
```

```text
user default off
user admin on >ADMIN_PASSWORD ~* &* +@all
user app on >APP_PASSWORD ~* &* +@all -@dangerous
```

Each line is a user: `on` enables it, `>` sets a password, `~*` allows every key, `&*` every Pub/Sub channel, and `+@all -@dangerous` allows every command except the [dangerous category](https://redis.io/docs/latest/operate/oss_and_stack/management/security/acl/#command-categories): `FLUSHALL`, `FLUSHDB`, `CONFIG`, `KEYS`, `DEBUG`, `SHUTDOWN`, `MIGRATE`, `INFO` and others. `admin` keeps everything for you.

Make the file readable by Redis only, and point the config at it by uncommenting this line in `/etc/redis/redis.conf`:

```bash
sudo chown redis:redis /etc/redis/users.acl
sudo chmod 640 /etc/redis/users.acl
```

```ini
aclfile /etc/redis/users.acl
```

The old way to block commands, `rename-command CONFIG ""`, still works but is deprecated and applies to every user, admin included. ACLs do the job per user.

Restart Redis:

```bash
sudo systemctl restart redis-server
```

If the ACL file has a typo, Redis refuses to start; `sudo journalctl -u redis-server -n 20` names the line.

### Check it worked

Without a user, Redis now refuses to talk:

```bash
redis-cli ping
```

```text
NOAUTH Authentication required.
```

As the app user, normal commands work and dangerous ones don't. `REDISCLI_AUTH` passes the password without putting it in your shell history or the process list:

```bash
export REDISCLI_AUTH='APP_PASSWORD'
redis-cli --user app set greeting hello
redis-cli --user app get greeting
redis-cli --user app flushall
unset REDISCLI_AUTH
```

```text
OK
"hello"
(error) NOPERM this user has no permissions to run the 'flushall' command
```

Your app connects with a URL in this form (most client libraries accept it):

```text
redis://app:APP_PASSWORD@127.0.0.1:6379/0
```

## Limit keys per app (optional)

If two apps share one Redis, give each its own key prefix and a user that can only touch it. As `admin`:

```bash
export REDISCLI_AUTH='ADMIN_PASSWORD'
redis-cli --user admin acl setuser shop on '>SHOP_PASSWORD' '~shop:*' '+@all' '-@dangerous'
redis-cli --user admin acl save
unset REDISCLI_AUTH
```

`ACL SAVE` writes the change back to `/etc/redis/users.acl`, with passwords stored as SHA-256 hashes. The `shop` user gets `NOPERM this user has no permissions to access one of the keys used as arguments` for any key outside `shop:*`. Set your app's client library to use the `shop:` prefix.

## Cap the memory

By default Redis grows until the server runs out of memory, and then the kernel kills something, often Redis itself. Set a limit and tell Redis what to do when it is reached. In `/etc/redis/redis.conf`:

```ini
maxmemory 256mb
maxmemory-policy allkeys-lru
```

Pick the policy by what you keep in Redis:

| You use Redis as | Policy | What happens at the limit |
| --- | --- | --- |
| A cache only | `allkeys-lru` | The least recently used keys are dropped to make room. |
| A cache with some keys that must stay | `volatile-lru` | Only keys with an expiry (`EX`/`TTL`) are dropped. |
| A queue or session store (Sidekiq, BullMQ, Celery) | `noeviction` (the default) | Writes fail with an error instead of losing jobs. Size `maxmemory` with room to spare. |

Restart with `sudo systemctl restart redis-server`, then check it took:

```bash
REDISCLI_AUTH='ADMIN_PASSWORD' redis-cli --user admin info memory | grep -E 'maxmemory_human|maxmemory_policy'
```

```text
maxmemory_human:256.00M
maxmemory_policy:allkeys-lru
```

## Decide about persistence

Ubuntu's config saves a snapshot (`dump.rdb` in `/var/lib/redis`) every so often and leaves the append-only file off. That suits a cache: after a restart you get recent data back, or lose a few minutes of it. For a job queue, turn on the append-only file so at most about a second of writes is lost:

```ini
appendonly yes
```

For a pure cache you can turn saving off entirely with `save ""`. Either way, Redis's data isn't a backup of anything important; keep that in a database like [PostgreSQL](https://vpsnine.com/tutorials/install-postgresql-ubuntu).

## Troubleshooting

**`NOAUTH Authentication required.`** The client connected without a user and password. Set the user and password in your app's Redis URL, or use `redis-cli --user ...` with `REDISCLI_AUTH`.

**`WRONGPASS invalid username-password pair or user is disabled.`** Wrong password, a user that is `off`, or a client that only sends a password (old libraries send `AUTH <password>`, which logs in as `default`). Upgrade the client or pass the user name in the URL.

**`NOPERM this user has no permissions to run the 'info' command`** (or `'keys'`, `'config|get'`). Some libraries run `INFO` or `CONFIG GET` at startup, and both are in `@dangerous`. Grant that one command back: `acl setuser app +info`, then `acl save`.

**Redis won't start after you edited the config.** `sudo journalctl -u redis-server -n 30` or `/var/log/redis/redis-server.log` shows the reason. A bad line in the ACL file looks like `Aborting Redis startup because of ACL errors: /etc/redis/users.acl:4: Syntax error.`, with the line number; a missing ACL file also stops it.

## Next steps

- Use it from an app: [Node.js with PM2 and nginx](https://vpsnine.com/tutorials/deploy-nodejs-app-pm2-nginx-ubuntu) or [FastAPI with Gunicorn and nginx](https://vpsnine.com/tutorials/deploy-fastapi-gunicorn-nginx).
- Keep port 6379 closed in your [firewall](https://vpsnine.com/help/firewall-with-ufw); Redis on localhost doesn't need a rule. If another server must reach it, connect them over [WireGuard](https://vpsnine.com/tutorials/wireguard-vpn-server-ubuntu) and bind Redis to the tunnel address only.
- The [Redis security guide](https://redis.io/docs/latest/operate/oss_and_stack/management/security/) covers TLS and more ACL options.
