Step 1 — Verify Ubuntu 24.04 and the Redis package candidate
Confirm the operating system and architecture:
. /etc/os-release
printf '%s\n%s\n%s\n' "$PRETTY_NAME" "$VERSION_CODENAME" "$(dpkg --print-architecture)"
Expected Ubuntu values include:
Refresh package metadata and inspect the candidate:
sudo apt update
apt-cache policy redis redis-server redis-tools
Ubuntu 24.04 remains on the Redis 7.0 branch. At this revision, the security-updated package is 5:7.0.15-1ubuntu0.24.04.4.
Check memory and disk headroom:
Redis memory use is not just stored values. Account for key/value overhead, allocator overhead, client buffers, persistence, fork/copy-on-write behavior, and the operating system.
Verify: the host reports Ubuntu 24.04/Noble, APT shows the Ubuntu Redis 7.0 package line, and the VM has enough memory and disk headroom for the intended workload.
Step 2 — Install Redis Server and verify the service
Install Redis, CLI tools, OpenSSL, and UFW:
sudo apt install -y redis-server redis-tools openssl ufw
Enable and start the service:
sudo systemctl enable --now redis-server
Verify package and binary versions:
redis-server --version
redis-cli --version
apt-cache policy redis-server
Check service state:
systemctl is-active redis-server
systemctl is-enabled redis-server
sudo systemctl status redis-server --no-pager
Test the initial local connection:
Expected output:
Verify: redis-server is active and enabled, PING returns PONG, and APT shows Ubuntu as the installed package source.
Step 3 — Keep Redis local-only and preserve protected mode
Back up the configuration before editing it:
sudo cp -a /etc/redis/redis.conf \
"/etc/redis/redis.conf.$(date -u +%Y%m%dT%H%M%SZ).backup"
Inspect the network settings:
grep -nE '^[[:space:]]*(bind|protected-mode|port)[[:space:]]' \
/etc/redis/redis.conf
For a same-VM application, keep settings equivalent to:
bind 127.0.0.1 -::1
protected-mode yes
port 6379
Do not replace the bind line with 0.0.0.0. Redis is designed for trusted clients and should not be directly exposed to untrusted networks.
Restart after a configuration change:
sudo systemctl restart redis-server
systemctl is-active redis-server
sudo ss -lntp | grep ':6379' || true
Verify: Redis remains bound to loopback, protected mode stays enabled, and the service restarts cleanly.
Redis 6 and later supports Access Control Lists. Use an external ACL file so application and administrative identities are separate and persistent.
Create the ACL file while temporarily preserving the default local user:
sudo install -o redis -g redis -m 600 /dev/null /etc/redis/users.acl
echo 'user default on nopass ~* &* +@all' \
| sudo tee /etc/redis/users.acl >/dev/null
sudo chown redis:redis /etc/redis/users.acl
sudo chmod 600 /etc/redis/users.acl
Open /etc/redis/redis.conf and add:
aclfile /etc/redis/users.acl
Do not define the same users in both redis.conf and the external ACL file.
Restart and confirm the transition state works:
sudo systemctl restart redis-server
redis-cli PING
Generate separate passwords:
ADMIN_PASSWORD="$(openssl rand -hex 32)"
APP_PASSWORD="$(openssl rand -hex 32)"
printf 'Redis admin password: %s\n' "$ADMIN_PASSWORD"
printf 'Redis app password: %s\n' "$APP_PASSWORD"
Store both values in a secrets manager before continuing.
Create the administrator and a restricted application user:
redis-cli ACL SETUSER redisadmin \
reset on ">${ADMIN_PASSWORD}" '~*' '&*' +@all
redis-cli ACL SETUSER raffapp \
reset on ">${APP_PASSWORD}" '~raffapp:*' \
resetchannels +@read +@write +ping -@dangerous
redis-cli ACL SAVE
Authenticate as the new administrator, disable the unauthenticated default user, and persist the result:
export REDISCLI_AUTH="$ADMIN_PASSWORD"
redis-cli --user redisadmin PING
redis-cli --user redisadmin ACL SETUSER default off
redis-cli --user redisadmin ACL SAVE
redis-cli --user redisadmin ACL LIST
Unauthenticated access should now fail:
unset REDISCLI_AUTH
redis-cli PING
Expected result includes:
NOAUTH Authentication required
Clear generated values after they are stored safely:
unset ADMIN_PASSWORD APP_PASSWORD
Verify: the default user is off, redisadmin authenticates with administrative rights, raffapp exists with restricted key and command permissions, and ACL SAVE persists the users.
Step 5 — Verify the application ACL and REDISCLI_AUTH workflow
REDISCLI_AUTH lets redis-cli read the password from an environment variable instead of placing it directly in shell history or process arguments.
Read the application password securely:
read -rsp "Redis application password: " REDISCLI_AUTH
echo
export REDISCLI_AUTH
Authenticate as the application user and create a namespaced key:
redis-cli --user raffapp PING
redis-cli --user raffapp SET raffapp:health verified EX 300
redis-cli --user raffapp GET raffapp:health
redis-cli --user raffapp TTL raffapp:health
Expected results include PONG, OK, verified, and a positive TTL.
A key outside the permitted namespace should fail:
redis-cli --user raffapp SET other:health blocked
A dangerous administrative command should also fail:
redis-cli --user raffapp FLUSHALL
Remove the test key and clear the credential:
redis-cli --user raffapp DEL raffapp:health
unset REDISCLI_AUTH
Do not export REDISCLI_AUTH permanently in shell startup files. Set it only for the administrative session that needs it, then unset it.
Verify: raffapp works only inside raffapp:*, dangerous commands are denied, and the password disappears from the environment after unset REDISCLI_AUTH.
Inspect current Redis memory state as the administrator:
read -rsp "Redis administrator password: " REDISCLI_AUTH
echo
export REDISCLI_AUTH
redis-cli --user redisadmin INFO memory | \
grep -E 'used_memory_human|maxmemory_human|maxmemory_policy|mem_not_counted_for_evict'
Open /etc/redis/redis.conf and set a deliberate memory ceiling. For the original 2 GB tutorial VM used purely as a cache, this is an example rather than a universal recommendation:
maxmemory 1gb
maxmemory-policy allkeys-lru
Common policy choices include:
allkeys-lru when any cache key may be evicted;
allkeys-lfu when frequently accessed keys should survive longer;
volatile-lru or volatile-lfu when only expiring keys are eviction candidates;
noeviction when writes should fail rather than silently evict data.
Restart and verify persistence of the settings:
sudo systemctl restart redis-server
redis-cli --user redisadmin CONFIG GET maxmemory
redis-cli --user redisadmin CONFIG GET maxmemory-policy
unset REDISCLI_AUTH
Verify: maxmemory leaves headroom for the OS and Redis overhead, the eviction policy matches the workload, and both values survive restart.
Step 7 — Choose and verify a persistence model
Redis supports RDB snapshots, AOF, both, or no persistence. Choose based on the role of the data rather than enabling every option automatically.
A practical starting model is:
| Workload | Starting persistence choice |
|---|
| Rebuildable cache | RDB or no persistence |
| Sessions with fallback | RDB with tested recovery |
| Queue or important short-lived state | AOF, commonly appendfsync everysec |
| Primary durable system of record | Re-evaluate architecture, replication, backups, and failure semantics explicitly |
Inspect the current settings:
read -rsp "Redis administrator password: " REDISCLI_AUTH
echo
export REDISCLI_AUTH
redis-cli --user redisadmin CONFIG GET save
redis-cli --user redisadmin CONFIG GET appendonly
redis-cli --user redisadmin CONFIG GET appendfsync
If the workload requires AOF, edit /etc/redis/redis.conf:
appendonly yes
appendfsync everysec
Restart and verify:
sudo systemctl restart redis-server
redis-cli --user redisadmin CONFIG GET appendonly
redis-cli --user redisadmin CONFIG GET appendfsync
redis-cli --user redisadmin INFO persistence
unset REDISCLI_AUTH
With appendfsync everysec, Redis documents that roughly up to about one second of writes may be lost in a failure. Local persistence is not a substitute for an off-server backup.
Verify: persistence settings match the durability requirement and INFO persistence reports healthy RDB/AOF state after restart.
Step 8 — Create a validated Redis 7 RDB backup
Redis 8.10 introduced the newer BACKUP command family, but Ubuntu 24.04's distro Redis 7.0 package does not provide it. For this package line, create a completed RDB snapshot and copy the Redis configuration and ACL file with it.
Create a protected backup directory:
sudo install -d -m 700 /var/backups/redis
Authenticate as the administrator and read the active RDB location:
read -rsp "Redis administrator password: " REDISCLI_AUTH
echo
export REDISCLI_AUTH
REDIS_DIR="$(redis-cli --user redisadmin --raw CONFIG GET dir | tail -n 1)"
RDB_FILE="$(redis-cli --user redisadmin --raw CONFIG GET dbfilename | tail -n 1)"
printf 'RDB path: %s/%s\n' "$REDIS_DIR" "$RDB_FILE"
Trigger a background snapshot:
redis-cli --user redisadmin BGSAVE
Wait for completion:
while redis-cli --user redisadmin --raw INFO persistence \
| grep -q '^rdb_bgsave_in_progress:1'; do
sleep 1
done
redis-cli --user redisadmin INFO persistence | \
grep -E 'rdb_last_bgsave_status|rdb_last_save_time'
rdb_last_bgsave_status must be ok.
Copy the completed RDB and configuration files:
STAMP="$(date -u +%Y%m%d-%H%M%S)"
sudo cp "$REDIS_DIR/$RDB_FILE" \
"/var/backups/redis/dump-${STAMP}.rdb"
sudo tar -czf "/var/backups/redis/config-${STAMP}.tar.gz" \
/etc/redis/redis.conf \
/etc/redis/users.acl
sudo chmod 600 \
"/var/backups/redis/dump-${STAMP}.rdb" \
"/var/backups/redis/config-${STAMP}.tar.gz"
Validate the snapshot:
sudo redis-check-rdb "/var/backups/redis/dump-${STAMP}.rdb"
Clear the credential:
Keep the complete backup set off-server. Raff Object Storage can be used by S3-compatible backup tooling, while Data Protection provides an additional VM-level recovery layer.
Verify: the background save reports ok, redis-check-rdb validates the copied snapshot, configuration and ACL files are included, and production recovery includes an off-server copy.
Step 9 — Restore-test the RDB in an isolated Redis instance
A backup is not proven until it loads successfully. Prefer a disposable recovery VM. If you test on the same server, use a different loopback-only port and verify it is unused:
sudo ss -lntp | grep ':6380' || true
The backup directory is root-only in this tutorial. Select and copy the latest RDB with sudo, then hand only the disposable copy to your current user:
BACKUP_RDB="$(sudo find /var/backups/redis -maxdepth 1 -type f -name 'dump-*.rdb' -print | LC_ALL=C sort | tail -n 1)"
# Stop here if no readable backup was selected.
if [ -z "$BACKUP_RDB" ] || ! sudo test -s "$BACKUP_RDB"; then
printf '%s\n' 'No non-empty backup found. Do not continue with restore.' >&2
false
fi
RESTORE_DIR="$(mktemp -d)"
sudo cp "$BACKUP_RDB" "$RESTORE_DIR/dump.rdb"
sudo chown "$USER":"$(id -gn)" "$RESTORE_DIR/dump.rdb"
chmod 600 "$RESTORE_DIR/dump.rdb"
Start a disposable Redis process that listens only on loopback and does not create new persistence files:
redis-server \
--port 6380 \
--bind 127.0.0.1 \
--protected-mode yes \
--dir "$RESTORE_DIR" \
--dbfilename dump.rdb \
--appendonly no \
--save "" \
--daemonize yes \
--pidfile "$RESTORE_DIR/redis.pid" \
--logfile "$RESTORE_DIR/redis.log"
Verify the recovered dataset:
redis-cli -p 6380 PING
redis-cli -p 6380 DBSIZE
redis-cli -p 6380 INFO keyspace
For a production rehearsal, compare expected key counts and representative application keys rather than relying only on PING.
Shut down and remove the disposable instance:
redis-cli -p 6380 SHUTDOWN NOSAVE
rm -rf "$RESTORE_DIR"
This temporary restore instance intentionally has no ACL because it is loopback-only and disposable. A real recovery server must restore the protected Redis configuration and ACL model before serving application traffic.
Verify: the isolated process loads the RDB on port 6380, exposes the expected keyspace, shuts down cleanly, and leaves production Redis untouched.
Step 10 — Protect Redis with UFW without risking SSH access
Before changing UFW from a remote shell, open a second SSH session and inspect current rules:
If UFW is already active and Redis is local-only, add a deny rule if needed:
If UFW is inactive, follow Set Up UFW Firewall on Ubuntu 24.04 rather than enabling it blindly from a single SSH session.
Recheck the listener and firewall:
sudo ss -lntp | grep ':6379' || true
sudo ufw status numbered
Verify: port 6379 is not reachable through the public interface and SSH administration remains available after any firewall change.
Step 11 — Optionally allow one private application VM with TLS
Use this only when Redis and the application run on separate VMs connected through Raff VPC. Do not add a private Redis listener until the firewall is active and source-restricted.
Example addresses:
Redis private IP: 10.0.0.5
Application private IP: 10.0.0.10
Use certificates issued by a CA you control. Store them at protected paths such as:
/etc/redis/tls/ca.crt
/etc/redis/tls/redis.crt
/etc/redis/tls/redis.key
Protect the files:
sudo chown -R root:redis /etc/redis/tls
sudo chmod 750 /etc/redis/tls
sudo chmod 640 /etc/redis/tls/redis.key
sudo chmod 644 /etc/redis/tls/ca.crt /etc/redis/tls/redis.crt
Edit /etc/redis/redis.conf:
bind 127.0.0.1 -::1 10.0.0.5
protected-mode yes
port 6379
tls-port 6380
tls-cert-file /etc/redis/tls/redis.crt
tls-key-file /etc/redis/tls/redis.key
tls-ca-cert-file /etc/redis/tls/ca.crt
tls-auth-clients no
Restart and verify listeners:
sudo systemctl restart redis-server
systemctl is-active redis-server
sudo ss -lntp | grep -E ':6379|:6380'
Keep plaintext 6379 unavailable to the private network and allow only the application VM to the TLS listener:
sudo ufw deny 6379/tcp
sudo ufw allow from 10.0.0.10 to 10.0.0.5 port 6380 proto tcp
sudo ufw status numbered
Copy only the CA certificate to the application VM, then authenticate with the restricted ACL user:
read -rsp "Redis application password: " REDISCLI_AUTH
echo
export REDISCLI_AUTH
redis-cli \
--tls \
--cacert /path/to/ca.crt \
--host 10.0.0.5 \
--port 6380 \
--user raffapp \
PING
unset REDISCLI_AUTH
Do not create a public allow rule for either 6379 or 6380.
Verify: the private TLS listener is reachable only from the approved application VM, the client validates the CA and authenticates as raffapp, and plaintext/public Redis access remains blocked.
Step 12 — Apply Ubuntu patches and treat Redis 8.x as a planned upgrade
Check for Ubuntu Redis updates:
apt list --upgradable 2>/dev/null | grep -E '^redis' || true
Before patching Redis that contains important state:
- create and validate a fresh backup;
- copy it off-server;
- review the Ubuntu security or changelog entry;
- verify persistence health and free disk;
- choose a maintenance window appropriate for the workload.
Apply routine Ubuntu updates:
sudo apt update
sudo apt upgrade
Verify afterward:
systemctl is-active redis-server
redis-server --version
apt-cache policy redis-server
Upstream Redis 8.10 includes capabilities that do not exist in Ubuntu's Redis 7.0 package, including the newer BACKUP command family. Moving from Ubuntu's distro package to Redis's upstream APT repository and a new major release should be treated as a planned migration with client, ACL, configuration, persistence, and rollback testing.
Verify: routine patching keeps the intended Ubuntu package source, Redis restarts cleanly, and any 7.0-to-8.x move has a separate tested upgrade plan.
Step 13 — Verify Redis end to end
Check service, package, listener, and firewall state:
echo 'Service:'
systemctl is-active redis-server
systemctl is-enabled redis-server
echo 'Package:'
apt-cache policy redis-server | sed -n '1,10p'
echo 'Listeners:'
sudo ss -lntp | grep -E ':6379|:6380' || true
echo 'Firewall:'
sudo ufw status numbered
Authenticate as the administrator:
read -rsp "Redis administrator password: " REDISCLI_AUTH
echo
export REDISCLI_AUTH
Run the final Redis checks:
redis-cli --user redisadmin PING
redis-cli --user redisadmin ACL LIST
redis-cli --user redisadmin CONFIG GET protected-mode
redis-cli --user redisadmin CONFIG GET maxmemory
redis-cli --user redisadmin CONFIG GET maxmemory-policy
redis-cli --user redisadmin CONFIG GET appendonly
redis-cli --user redisadmin INFO persistence | \
grep -E 'rdb_last_bgsave_status|aof_enabled|aof_last_write_status'
redis-cli --user redisadmin INFO memory | \
grep -E 'used_memory_human|maxmemory_human|mem_not_counted_for_evict'
unset REDISCLI_AUTH
The installation is complete when all of these are true:
- Ubuntu 24.04 manages the intended Redis 7.0 package line;
- the service is active and enabled;
- public Redis access is blocked;
- protected mode is enabled;
- the unauthenticated default user is disabled;
- administrator and application ACL users are separate;
- the application user is constrained by key pattern and command permissions;
maxmemory and eviction behavior match the Redis role;
- persistence matches the durability requirement;
- the latest RDB backup validates successfully;
- Redis configuration and ACL files are included in recovery copies;
- an isolated restore test has succeeded;
- optional cross-VM access is private, source-restricted, and encrypted;
- a move to Redis 8.x is handled as a planned upgrade rather than an Ubuntu patch.
Verify: all checks above succeed and the application ACL, persistence, backup, and isolated restore paths have been exercised successfully.
Cleanup (optional)
Use this section only for resources created solely for this tutorial.
Remove the tutorial application ACL user while keeping your administrator account:
read -rsp "Redis administrator password: " REDISCLI_AUTH
echo
export REDISCLI_AUTH
redis-cli --user redisadmin ACL DELUSER raffapp
redis-cli --user redisadmin ACL SAVE
unset REDISCLI_AUTH
Warning: The next commands permanently delete all backups matching these tutorial filenames. Keep an off-server copy of anything you need. Run them only in a disposable tutorial environment:
sudo find /var/backups/redis -maxdepth 1 -type f -name 'dump-*.rdb' -print -delete
sudo find /var/backups/redis -maxdepth 1 -type f -name 'config-*.tar.gz' -print -delete
Delete only the firewall rules you added for this tutorial:
sudo ufw delete allow from 10.0.0.10 to 10.0.0.5 port 6380 proto tcp
sudo ufw delete deny 6379/tcp
If you enabled the private TLS listener only for this tutorial, edit the current configuration: remove 10.0.0.5 from bind, set tls-port 0, and remove only the TLS certificate directives added in Step 11. Preserve aclfile /etc/redis/users.acl, memory and persistence settings. Do not restore the Step 3 backup: it predates ACL hardening. Restart Redis, verify loopback-only listeners, confirm authenticated access works, and confirm unauthenticated PING still fails.
Do not delete redisadmin until you have another tested administrative access path.
Troubleshooting
redis-server.service is not found
Verify that the Ubuntu server package is installed:
dpkg -l | grep -E '^ii[[:space:]]+redis-server'
apt-cache policy redis-server
Install and start it if necessary:
sudo apt update
sudo apt install -y redis-server
sudo systemctl enable --now redis-server
NOAUTH Authentication required
Authentication is working. Use the correct ACL username and password:
read -rsp "Redis password: " REDISCLI_AUTH
echo
export REDISCLI_AUTH
redis-cli --user redisadmin PING
unset REDISCLI_AUTH
REDISCLI_AUTH is set but authentication still fails
REDISCLI_AUTH supplies the password only. With named ACL users you still need --user:
read -rsp "Redis application password: " REDISCLI_AUTH
echo
export REDISCLI_AUTH
redis-cli --user raffapp PING
unset REDISCLI_AUTH
Check the account definition as an administrator with ACL GETUSER raffapp if the username/password pair still fails.
The application receives NOPERM
Inspect the application ACL:
redis-cli --user redisadmin ACL GETUSER raffapp
Grant only the key patterns, channel patterns, and command categories the application genuinely requires. Do not solve an ACL error by granting +@all.
Redis uses more memory than expected
Inspect memory and eviction configuration:
redis-cli --user redisadmin INFO memory
redis-cli --user redisadmin CONFIG GET maxmemory
redis-cli --user redisadmin CONFIG GET maxmemory-policy
redis-cli --user redisadmin --bigkeys
maxmemory limits the dataset used for eviction decisions. It does not guarantee that total process RSS stays below the same number.
Redis cannot create an RDB snapshot
Inspect persistence state, disk space, and logs:
df -h /
redis-cli --user redisadmin INFO persistence
sudo journalctl -u redis-server --no-pager -n 100
An AOF file does not remove the need for off-server backups and restore testing.
Restore test returns permission denied
The production backup directory is intentionally root-only. Use the sudo ls, sudo cp, and chown sequence in Step 9 to copy only the selected RDB into the disposable restore directory.
TLS connections fail
Check the TLS listener, file permissions, and service log:
sudo ss -lntp | grep ':6380' || true
sudo ls -l /etc/redis/tls
sudo journalctl -u redis-server --no-pager -n 100
Verify that the application trusts the CA that issued the server certificate and that the certificate identity matches the host the client uses.
FAQ
How do I install Redis on Ubuntu 24.04?
Run sudo apt update, install redis-server redis-tools, enable redis-server, and verify the local service with redis-cli PING.
What Redis version does Ubuntu 24.04 install?
Ubuntu 24.04 maintains Redis 7.0.15. The current security-updated package is 5:7.0.15-1ubuntu0.24.04.4 at this revision.
What is the current upstream Redis release line?
Redis Open Source 8.10 is the current upstream release line in September 2026. It is separate from Ubuntu 24.04's distro-managed Redis 7.0 package path.
Should I use requirepass or Redis ACL users?
Use named ACL users for modern Redis. They let you restrict commands, keys, and channels per application instead of sharing one global password.
Should Redis port 6379 be public?
No. Keep it on loopback for same-VM applications. For another VM, use private networking, exact firewall source restrictions, ACL authentication, and TLS.
What does REDISCLI_AUTH do?
It lets redis-cli read the password from an environment variable. With named ACL users, still pass --user, and unset the variable after the administrative session.
How should I back up Redis 7 on Ubuntu 24.04?
Trigger BGSAVE, wait for a successful result, copy and validate the completed RDB, include redis.conf and the ACL file, keep an off-server copy, and restore-test it in isolation.
Should I self-host Redis or use managed Valkey?
Self-host when you need host-level control and can own patching, persistence, backup, monitoring, and incidents. Managed Valkey reduces that operational work while remaining Redis-compatible for common workloads.
Conclusion
You now have Redis 7.0 on a Raff Ubuntu 24.04 VM with named ACL users, private-by-default networking, deliberate memory and eviction settings, workload-appropriate persistence, validated RDB backups, and an isolated restore test.
The package distinction matters: Ubuntu 24.04 currently maintains Redis 7.0.15 with security updates, while upstream Redis is on the 8.10 release line. Keep routine Ubuntu security updates separate from a deliberate repository and major-version migration.
Continue with Redis Hosting, Redis Cache & Queue Strategy for SaaS Apps, and Raff Managed Valkey.
Sources