Install and Secure Redis on a VPS for Caching and Queues

Redis is an in-memory data store that most web stacks use for two jobs: caching expensive results and holding background job queues. Installing it takes one command. Configuring it safely takes a few more decisions: who can connect, how much memory it may use, what happens when memory runs out, and whether data must survive a restart. The right answers differ between a cache and a queue, and this guide explains both.
Step 1: Install Redis
On Ubuntu or Debian:
sudo apt update
sudo apt install redis-server
redis-server --version
sudo systemctl status redis-server
The distribution package is a stable, security-patched release and is fine for most apps. If you need a newer version, Redis publishes its own APT repository. Valkey, an open-source fork of Redis, uses the same configuration directives, so everything below applies to it too.
The main configuration file is /etc/redis/redis.conf. After every change, restart and check the log:
sudo systemctl restart redis-server
sudo journalctl -u redis-server -n 50
Step 2: Control who can connect (bind and protected-mode)
An exposed Redis without a password is one of the most common ways servers get compromised. Attackers connect, use CONFIG SET to change where Redis writes its data file, and write an SSH key or a cron job to disk. Two settings prevent this.
bind 127.0.0.1 -::1
protected-mode yes
port 6379
bind sets which network interfaces Redis listens on. The default above means local connections only. If your app runs on the same server, leave it like this.
If the app runs on a different server, bind to a private network address as well, never to 0.0.0.0 on a public interface:
bind 127.0.0.1 10.0.0.5
Then allow only the app server in the firewall:
sudo ufw allow from 10.0.0.4 to any port 6379 proto tcp
protected-mode is a safety net. When it is on and the default user has no password, Redis rejects connections that are not from loopback with an error that starts with DENIED Redis is running in protected mode because protected mode is enabled. If you see this, the fix is to set a password, not to turn protected mode off.
Check what Redis is actually listening on:
ss -tlnp | grep 6379
Step 3: Require authentication
Even on localhost, a password stops any other process or user on the server from reading your data. You have two options.
Option A: requirepass (one app, one password)
openssl rand -hex 32
requirepass 3f9c...your-64-character-hex-value...
A hex password avoids characters like / and + that need escaping in connection URLs. Clients without the password get NOAUTH Authentication required.
Option B: ACL users (several apps or roles)
Since Redis 6, access control lists let you create named users with limited commands and key patterns. Point Redis to an ACL file in redis.conf:
aclfile /etc/redis/users.acl
Then create /etc/redis/users.acl:
user default off
user app on >APP_PASSWORD_HERE ~app:* &app:* +@all -@dangerous
user admin on >ADMIN_PASSWORD_HERE ~* &* +@all
sudo chown redis:redis /etc/redis/users.acl
sudo chmod 640 /etc/redis/users.acl
This turns off the passwordless default user, gives the app access only to keys that start with app:, and blocks the @dangerous category, which includes FLUSHALL, CONFIG, KEYS and DEBUG. Use one approach: when you use an ACL file, define users there rather than with requirepass.
Test your queue or cache library after restricting commands. Some libraries call commands in the @dangerous category, such as INFO, and some use their own key prefix (BullMQ uses bull: by default). Adjust the rule, for example with +info or another key pattern, rather than giving the app full access.
Test the login:
export REDISCLI_AUTH='APP_PASSWORD_HERE'
redis-cli --user app ping
You should get PONG. A wrong password returns WRONGPASS invalid username-password pair or user is disabled. Using REDISCLI_AUTH keeps the password out of your shell history. Passing it with -a works, but redis-cli warns that it may not be safe.
Older guides use rename-command to hide commands. ACLs replace that approach and are easier to audit.
Step 4: Set a memory limit and an eviction policy
Without a limit, Redis grows until the kernel's OOM killer stops it, or stops something more important. Set maxmemory explicitly.
maxmemory 512mb
maxmemory-policy allkeys-lru
How much? As a rule of thumb, if persistence is on, keep maxmemory at or below about half to three quarters of the RAM you can give Redis. Saving to disk forks the process, and pages that change during the save are copied, so memory use can rise during a save.
The policy decides what happens when the limit is reached:
| Policy | Behavior | Use it for |
|---|---|---|
allkeys-lru | Evicts the least recently used key | A pure cache |
allkeys-lfu | Evicts the least frequently used key | A cache with a stable set of popular keys |
volatile-lru | Evicts only keys that have a TTL | Cache keys with TTL mixed with keys that must stay |
noeviction | Rejects writes with an error | Queues, sessions, anything you cannot lose |
The important point: a queue must never lose jobs silently. With noeviction, a full Redis returns OOM command not allowed when used memory > 'maxmemory'. Your app sees an error and can alert you. With an LRU policy, jobs would disappear without a trace. Because the policy applies to the whole instance, the cleanest setup is two Redis instances: one for cache with allkeys-lru, one for queues with noeviction.
Step 5: Choose a persistence mode
Redis keeps data in memory. Persistence decides what is left after a restart.
RDB snapshots write the whole dataset to
dump.rdbat intervals. Files are compact and restore quickly. You can lose the writes made since the last snapshot.AOF (append-only file) logs every write. With
appendfsync everysec, you lose at most about one second of writes in a crash. Files are larger, and Redis rewrites them in the background.None: nothing is saved. Fine for a cache that your app can rebuild from the database.
For a cache:
save ""
appendonly no
For queues and sessions:
appendonly yes
appendfsync everysec
save 3600 1 300 100 60 10000
Data is stored in /var/lib/redis. Copy the RDB file somewhere else on a schedule. A file on the same disk is not a backup.
Step 6: Fix the kernel warnings
When Redis starts, it checks a few kernel settings. The most common warning is WARNING Memory overcommit must be enabled!, which means a background save may fail when memory is tight. Fix it:
echo 'vm.overcommit_memory = 1' | sudo tee /etc/sysctl.d/99-redis.conf
sudo sysctl --system
sudo systemctl restart redis-server
Read the startup log again after the restart and handle any other warnings it prints.
Step 7: Connect from your app
Keep the password in an environment variable, not in your code. A connection URL with an ACL user looks like this:
redis://app:[email protected]:6379/0
In Node.js with ioredis:
const Redis = require('ioredis');
const redis = new Redis({
host: '127.0.0.1',
port: 6379,
username: 'app',
password: process.env.REDIS_PASSWORD,
});
If the app and Redis are in different data centers with no private network between them, do not send Redis traffic in the clear. Use Redis TLS, a WireGuard tunnel, or move them closer together.
Keep an eye on it
Set REDISCLI_AUTH to the admin password first, then run:
redis-cli --user admin INFO memory
redis-cli --user admin INFO persistence
redis-cli --user admin SLOWLOG GET 10
redis-cli --user admin --latency
Watch used_memory_human against your limit, evicted_keys on a cache instance, and rdb_last_bgsave_status or aof_last_write_status on a persistent one. A rising evicted_keys count on a cache is normal. On a queue instance it should always be zero.
Run it on IM HOST
Redis needs memory you can count on. A Linux VPS starts from $5/month with full root access on KVM, so you control redis.conf, the kernel settings and the firewall. Cloud VPS plans give you dedicated vCPU and RAM from $16/month, and you can upgrade anytime as your dataset grows. For large in-memory datasets, AMD dedicated servers offer bare metal with ECC memory and NVMe. Our engineers are available 24/7, and there are no setup fees.
More from our blog
Discover more practical guides and product insights from the IM Host team.
View all articles