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.

Tested on Ubuntu 24.04 LTS

Before you start

  • 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, 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: 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.

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

Be first when orders open

Join the waitlist and we'll send you one email when VPSNine launches. Pick a plan if you already know which one you want, and we'll size the first servers around it.

  • One email, on launch day
  • Monthly or yearly, no lock-in
  • 14-day money-back guarantee