In this tutorial, you’ll install Redis on Ubuntu 24.04 from Ubuntu’s supported repository, verify the service, keep Redis local to the VM, configure authentication, test common cache operations, choose a persistence model, set a memory policy, and protect port 6379 from public access.
Redis is an in-memory data store commonly used for caching, sessions, rate limiting, queues, pub/sub, and short-lived application state. Because most operations are served from RAM, Redis can reduce pressure on relational databases and improve application response times when it is sized and secured correctly.
Raff supports 3,000+ customers and 15,000+ VMs in its us-east region. Raff Linux VMs provide KVM virtualization, full root access, DDR5 memory, NVMe storage, and 3 Gbps unmetered bandwidth for self-hosted Redis workloads.
Prerequisites:
- A Raff Linux VM running Ubuntu 24.04
- SSH access with a user that has sudo privileges
- At least 2 GB RAM for development or light caching workloads
- A defined cache size and eviction policy before production use
- Port
22/tcpavailable for SSH administration
📌 Local-first design: This tutorial keeps Redis bound to the loopback interface. Applications on the same VM can connect locally, while port
6379remains unavailable from the public internet.
The original workflow was tested on a Raff VM with 1 vCPU and 2 GB RAM. Package, authentication, persistence, and memory-policy guidance was reviewed against current Redis documentation in July 2026.
Step 1 — Update Ubuntu and install Redis
Update the package index and install current system updates:
sudo apt update sudo apt upgrade -y
Install Redis Server, OpenSSL, and UFW:
sudo apt install -y redis-server openssl ufw
Verify the installed version:
redis-server --version redis-cli --version
Ubuntu 24.04 provides the Redis 7.0 series through its supported repositories. The exact patch revision changes as Ubuntu publishes maintenance and security updates.
Step 2 — Verify the Redis service
Redis should start automatically after installation. Confirm the service state:
systemctl is-active redis-server systemctl is-enabled redis-server
Expected output:
active enabled
View the complete service state without opening a pager:
sudo systemctl status redis-server --no-pager
Test the local connection:
redis-cli ping
Expected output:
PONG
Confirm that Redis listens only on loopback:
sudo ss -lntp | grep ':6379'
Expected output includes:
127.0.0.1:6379 [::1]:6379
Step 3 — Back up the Redis configuration
Create a timestamped backup before editing the configuration:
sudo cp /etc/redis/redis.conf \ "/etc/redis/redis.conf.$(date -u +%Y%m%dT%H%M%SZ).backup"
Verify the active configuration path and service command:
systemctl cat redis-server | grep -E 'ExecStart|redis.conf'
Ubuntu normally starts Redis with:
/etc/redis/redis.conf
Step 4 — Keep Redis local and enable protected mode
Open the Redis configuration:
sudo nano /etc/redis/redis.conf
Verify these settings:
bind 127.0.0.1 -::1 protected-mode yes port 6379
Do not change the bind address to 0.0.0.0. A public Redis listener can expose application data and administrative commands to internet scanning and credential attacks.
Restart Redis after saving the file:
sudo systemctl restart redis-server systemctl is-active redis-server
Verify the effective bind address and protected mode:
redis-cli CONFIG GET bind redis-cli CONFIG GET protected-mode
Expected output includes:
127.0.0.1 -::1 yes
Step 5 — Configure Redis authentication
For a simple local deployment with one application credential, Redis supports setting a password for the default user through requirepass. For multi-application or multi-tenant deployments, use Redis ACL users instead of sharing one global password.
Generate a strong hexadecimal password:
REDIS_PASSWORD="$(openssl rand -hex 32)" printf 'Store this Redis password securely: %s\n' "$REDIS_PASSWORD"
Copy the value into your secrets manager or another protected credential store.
Open the Redis configuration again:
sudo nano /etc/redis/redis.conf
Find the commented requirepass directive and set the generated password:
requirepass REPLACE_WITH_THE_GENERATED_PASSWORD
Save the file and restart Redis:
sudo systemctl restart redis-server systemctl is-active redis-server
Remove the password from the shell variable after storing it safely:
unset REDIS_PASSWORD
Verify that unauthenticated access is rejected:
redis-cli ping
Expected output:
(error) NOAUTH Authentication required.
Authenticate without placing the password directly in the command history:
read -rsp "Redis password: " REDISCLI_AUTH echo export REDISCLI_AUTH redis-cli ping
Expected output:
PONG
Keep REDISCLI_AUTH only for the current administrative session and remove it when finished:
unset REDISCLI_AUTH
⚠️ Credential rule: Avoid
redis-cli -a PASSWORDin scripts and documentation. Command-line arguments can be visible in shell history and process listings.
Step 6 — Optional: use a dedicated ACL application user
Redis ACLs allow separate users, key patterns, and command permissions. This is the stronger choice when multiple applications share one Redis instance.
Authenticate as the default administrative user:
read -rsp "Redis administrator password: " REDISCLI_AUTH echo export REDISCLI_AUTH
Generate an application password:
APP_REDIS_PASSWORD="$(openssl rand -hex 32)" printf 'Store this Redis application password securely: %s\n' "$APP_REDIS_PASSWORD"
Create an application user restricted to keys beginning with raffapp: and common read/write commands:
redis-cli ACL SETUSER raffapp \ on \ ">${APP_REDIS_PASSWORD}" \ '~raffapp:*' \ +@read \ +@write \ +ping \ -@dangerous
Verify the ACL user:
redis-cli ACL GETUSER raffapp
Expected output includes:
flags on passwords commands keys ~raffapp:*
Redis ACL changes created with ACL SETUSER are runtime changes unless you configure an ACL file and save them. For production, define an aclfile in /etc/redis/redis.conf, store ACL users in that root-controlled file, and test the configuration before disabling the default user.
Test the restricted user:
unset REDISCLI_AUTH read -rsp "Redis application password: " REDISCLI_AUTH echo export REDISCLI_AUTH redis-cli --user raffapp SET raffapp:health verified redis-cli --user raffapp GET raffapp:health
Expected output:
OK verified
A key outside the allowed pattern should fail:
redis-cli --user raffapp SET other:health blocked
Expected output includes an ACL permission error.
Remove the temporary test key and environment variable:
redis-cli --user raffapp DEL raffapp:health unset REDISCLI_AUTH APP_REDIS_PASSWORD
Step 7 — Test common Redis operations
Authenticate as the configured Redis user:
read -rsp "Redis password: " REDISCLI_AUTH echo export REDISCLI_AUTH
Set and retrieve a string:
redis-cli SET raffapp:greeting "Hello from Redis on Raff" redis-cli GET raffapp:greeting
Expected output:
OK Hello from Redis on Raff
Create a session-style key with a one-hour expiry:
redis-cli SET raffapp:session:user123 session_data EX 3600 redis-cli TTL raffapp:session:user123
Expected TTL output is a positive value below 3600.
Store and retrieve a hash:
redis-cli HSET raffapp:user:1 \ name Alice \ email [email protected] \ plan standard redis-cli HGETALL raffapp:user:1
Verify memory usage and client connections:
redis-cli INFO memory | grep -E 'used_memory_human|maxmemory_human|maxmemory_policy' redis-cli INFO clients | grep connected_clients
Remove the tutorial keys:
redis-cli DEL \ raffapp:greeting \ raffapp:session:user123 \ raffapp:user:1
Remove the credential from the shell:
unset REDISCLI_AUTH
Step 8 — Choose a persistence model
Redis supports two primary persistence mechanisms:
- RDB snapshots periodically write a compact dataset snapshot to disk.
- AOF records write operations and can reduce the amount of data lost after a crash.
Choose persistence based on Redis’s role:
| Redis workload | Recommended starting point |
|---|---|
| Disposable cache | RDB only or persistence disabled |
| Sessions that can be recreated | RDB with tested application fallback |
| Queue or important short-lived state | AOF with appendfsync everysec |
| Primary durable data store | Use a database designed for durable primary storage, or design Redis replication and recovery explicitly |
Open the configuration:
sudo nano /etc/redis/redis.conf
To enable AOF alongside RDB snapshots, set:
appendonly yes appendfsync everysec
Restart Redis:
sudo systemctl restart redis-server
Authenticate and verify the persistence settings:
read -rsp "Redis password: " REDISCLI_AUTH echo export REDISCLI_AUTH redis-cli CONFIG GET save redis-cli CONFIG GET appendonly redis-cli CONFIG GET appendfsync
Expected output includes:
appendonly yes appendfsync everysec
Redis documentation describes RDB and AOF trade-offs in its persistence guide.
📌 Recovery rule: Redis persistence is not a substitute for off-server backups when the stored state matters. Protect persistent Redis data with a tested backup and recovery plan.
Step 9 — Configure a memory limit and eviction policy
Redis can consume available RAM until the operating system is under memory pressure unless you configure maxmemory. Production cache deployments should define a limit and an eviction policy.
Check the VM’s available memory:
free -h
Open the configuration:
sudo nano /etc/redis/redis.conf
For a dedicated 2 GB cache VM, an example starting point is:
maxmemory 1gb maxmemory-policy allkeys-lru
Do not copy this value blindly. Leave memory for the operating system, Redis overhead, fork-based persistence, and monitoring agents.
Common policies include:
allkeys-lru— evict less-recently-used keys across the entire datasetallkeys-lfu— evict less-frequently-used keysvolatile-lru— evict only keys with an expirynoeviction— reject writes when the limit is reached
Restart and verify:
sudo systemctl restart redis-server read -rsp "Redis password: " REDISCLI_AUTH echo export REDISCLI_AUTH redis-cli CONFIG GET maxmemory redis-cli CONFIG GET maxmemory-policy unset REDISCLI_AUTH
Redis documents the policies and their behavior in its key eviction guide.
Step 10 — Protect port 6379 with UFW
Allow SSH before enabling UFW:
sudo ufw allow OpenSSH
If the OpenSSH profile is unavailable, allow the SSH port directly:
sudo ufw allow 22/tcp
Add a deny rule for Redis as defense in depth and enable UFW:
sudo ufw deny 6379/tcp sudo ufw --force enable
Verify the firewall rules:
sudo ufw status numbered
Expected output includes:
OpenSSH ALLOW IN 6379/tcp DENY IN
📌 Important: UFW does not replace
bind 127.0.0.1 -::1andprotected-mode yes. The bind address prevents Redis from listening on public interfaces; protected mode and the firewall provide additional controls.
For separate application and Redis VMs, use a private network, bind Redis to the specific private IP, restrict UFW to the application VM’s exact private address, and configure TLS or a secure tunnel when traffic crosses an untrusted network. Never expose Redis directly to the public internet.
Step 11 — Run the final verification
Run the service and network checks:
echo "Redis service:" systemctl is-active redis-server echo "Boot status:" systemctl is-enabled redis-server echo "Listening socket:" sudo ss -lntp | grep ':6379' echo "Firewall:" sudo ufw status numbered
Authenticate and verify Redis state:
read -rsp "Redis password: " REDISCLI_AUTH echo export REDISCLI_AUTH redis-cli PING redis-cli CONFIG GET protected-mode redis-cli CONFIG GET maxmemory redis-cli CONFIG GET maxmemory-policy redis-cli INFO persistence | grep -E 'rdb_last_bgsave_status|aof_enabled|aof_last_write_status' unset REDISCLI_AUTH
The installation is complete when:
- Redis is installed and the service is active and enabled
- Unauthenticated commands are rejected
- Redis listens only on loopback, or on one approved private IP
- Protected mode is enabled
- A memory limit and eviction policy match the workload
- Persistence settings match the durability requirement
- UFW blocks public access to port
6379