
If you’ve spent any real time running production infrastructure, you already know that “installing Redis” and “running Redis safely in production” are two very different projects. Anyone can type apt install redis-server and call it done. The problem is that a default Redis install on a fresh Ubuntu 26.04 box is wide open, unauthenticated by default in some configurations, and tuned for absolutely nothing specific to your workload. That’s fine for a laptop experiment. It’s a liability on a server handling session data, rate limiting, or a job queue for an e-commerce checkout flow.
Ubuntu 26.04 LTS (“Resolute Raccoon”) ships Redis 8.0.5 directly in its default repositories, which is a nice change from older LTS releases where you’d often get stuck with an ancient Redis build and have to chase down third-party PPAs just to get something recent. That said, “available in the repo” doesn’t automatically mean “correctly configured for your use case.” There’s a meaningful difference between the version APT gives you and the version Redis’s own official repository maintains, and depending on whether you need bleeding-edge features (Redis 8 introduced meaningful improvements to memory efficiency and data structure handling) or rock-solid stability, you’ll want to pick your install path deliberately.
This guide walks through both installation methods — the Ubuntu-native APT repo and the official Redis.io APT repo — plus the configuration work that actually matters once the binary is on disk: authentication, network binding, persistence strategy, memory limits, and the systemd integration that keeps Redis alive across reboots and crashes. We’ll also cover troubleshooting scenarios that show up repeatedly in real deployments, not textbook edge cases nobody encounters. By the end, you’ll have a Redis instance that’s not just “installed” but actually defensible in a code review or a security audit.
One thing worth saying up front: Redis is deceptively simple to stand up and deceptively easy to misconfigure. The commands are short. The consequences of skipping the security section are not.
Prerequisites Before You Start
Before touching a package manager, confirm a few basics. None of this is glamorous, but skipping it is how people end up debugging phantom issues three weeks later.
- A fresh or existing Ubuntu 26.04 LTS server (physical, VM, or cloud instance — DigitalOcean, Hetzner, AWS EC2, it doesn’t matter).
- A non-root user with
sudoprivileges. Running everything as root works but builds bad habits, especially on shared infrastructure. - At least 1GB of RAM free for anything beyond toy workloads — Redis is an in-memory store, so RAM is your real constraint, not disk.
- Outbound internet access on the server (for package downloads) and, if you’re behind a corporate proxy, the relevant proxy environment variables set for
aptandcurl. ufwor another firewall tool installed and at least minimally configured, since we’ll be locking down port 6379 later.
Check your Ubuntu version first — it’s a two-second command that saves you from following instructions meant for a different release entirely:
lsb_release -a
You should see 26.04 in the output. If you’re still on 24.04 or 22.04, most of this guide still applies almost verbatim, since the Redis packaging story hasn’t changed dramatically across these releases, but version numbers in the repos will differ.
Method 1: Installing Redis from the Ubuntu Default Repository
This is the path most people should take unless they have a specific reason not to. It’s simpler, it’s what Canonical tests and supports, and on Ubuntu 26.04 it already gets you Redis 8.0.5 — recent enough for the vast majority of use cases.
Step 1: Update Your Package Index
sudo apt update && sudo apt upgrade -y
Don’t skip the upgrade. A stale package cache on a freshly provisioned VM is one of the more common causes of dependency resolution errors during install — you’d be surprised how often “Unable to locate package” turns out to be nothing more than a package index that’s a few days out of date.
Step 2: Install Redis Server and CLI Tools
sudo apt install -y redis-server redis-tools
The redis-tools package gives you redis-cli, redis-benchmark, and other utilities you’ll want for testing and diagnostics even if you never touch the server package directly (useful, for instance, if you’re only connecting to a remote Redis instance from an app server).
Step 3: Verify the Installed Version
redis-server --version
Expect something like Redis server v=8.0.5. If APT installed an older build, your mirrors may be stale — run sudo apt update again or check /etc/apt/sources.list.d/ for conflicting entries.
Step 4: Confirm the Service Is Running
Ubuntu’s package post-install script typically starts and enables Redis automatically:
sudo systemctl status redis-server
You want to see active (running). If it’s not running, start it manually:
sudo systemctl enable --now redis-server
The enable --now combo is one of those small habits worth internalizing — it enables the service for boot persistence and starts it in a single command, instead of the two-step dance of enable then start.
Method 2: Installing Redis via the Official Redis.io Repository
There’s a legitimate reason to bypass Ubuntu’s repo: if you need a specific Redis point release, want the absolute latest patch faster than Ubuntu’s release cycle allows, or are standardizing configuration across mixed environments (some CentOS/AlmaLinux, some Ubuntu) and want packaging consistency. The official Redis repo delivers that.
Step 1: Install Prerequisite Tools
sudo apt update
sudo apt install -y lsb-release curl gpg
Step 2: Add the Redis GPG Signing Key
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
sudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg
That chmod isn’t optional decoration — without correct read permissions on the keyring file, APT will silently fail signature verification later and throw a confusing “NO_PUBKEY” error that has nothing obviously to do with file permissions.
Step 3: Add the Redis APT Repository
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
The $(lsb_release -cs) piece automatically substitutes your Ubuntu codename. Don’t hardcode a codename you copied from a five-year-old blog post — it’s a fast way to pull packages built for the wrong release.
Step 4: Update and Install
sudo apt update
sudo apt install -y redis
Note the package name here is just redis, not redis-server — the official repo bundles the server, CLI, and sentinel tooling under a single meta-package.
Step 5: Confirm Auto-Start Behavior
sudo systemctl status redis-server
sudo systemctl enable redis-server
sudo systemctl start redis-server
Redis generally starts automatically after this installation method and persists across reboots, but running the enable command explicitly costs nothing and removes any ambiguity.
Testing the Installation
Regardless of which method you used, confirm Redis actually responds before moving on to configuration:
redis-cli ping
A healthy instance replies with PONG. If you get “Connection refused,” the service isn’t running or is bound to an interface redis-cli can’t reach — check systemctl status redis-server and the logs at /var/log/redis/redis-server.log.
Run a quick functional test to be thorough:
redis-cli
127.0.0.1:6379> SET testkey "hello redis"
127.0.0.1:6379> GET testkey
127.0.0.1:6379> exit
If GET testkey returns your string, the data path — write, in-memory store, read — is working end to end.
Configuring Redis for Production Use
This is the section most tutorials rush through, and it’s exactly where real-world incidents originate. An unauthenticated Redis instance bound to 0.0.0.0 was, for years, one of the most common causes of ransomware and cryptomining infections on cloud servers — attackers scan for open port 6379, connect with zero credentials, and either exfiltrate data or drop a cron job through Redis’s own persistence mechanism. None of that is theoretical; it’s a documented, recurring attack pattern.
Locate and Open the Configuration File
sudo nano /etc/redis/redis.conf
Make a backup before editing anything:
sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
Bind to Localhost (or a Private Interface Only)
By default, recent Redis builds already bind to 127.0.0.1, but verify it explicitly:
grep '^bind' /etc/redis/redis.conf
You should see:
bind 127.0.0.1 -::1
If your application server and Redis instance live on separate machines, bind to the private network interface instead of exposing Redis on the public IP — and pair that with a firewall rule restricting access to known application server IPs only. Never bind Redis directly to a public-facing interface without a compelling, carefully mitigated reason.
Enable Authentication
Set a strong password with requirepass:
requirepass Str0ng-Unique-P@ssphrase-Here
Redis 6 and later also support ACLs, which let you create scoped users instead of relying purely on a single shared password — genuinely useful if multiple services or teams touch the same Redis instance and you want to limit blast radius if one credential leaks.
After editing, restart Redis and authenticate:
sudo systemctl restart redis-server
redis-cli
127.0.0.1:6379> AUTH Str0ng-Unique-P@ssphrase-Here
127.0.0.1:6379> PING
A PONG after AUTH confirms the password is active and correctly applied.
Set Supervised Mode to systemd
Ubuntu manages services through systemd, so tell Redis to cooperate with it rather than fork its own process management logic:
supervised systemd
Without this, systemd and Redis can disagree about process state during restarts, occasionally leading to services that report “active” while the underlying Redis process has actually died — a maddening thing to debug at 2 a.m. during an incident.
Disable or Rename Dangerous Commands
Commands like FLUSHALL, FLUSHDB, CONFIG, and SHUTDOWN are powerful and dangerous in the wrong hands — including an attacker who somehow gets past authentication, or a junior engineer running commands against production by mistake. Rename them to obscure strings, or disable them entirely, using rename-command:
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command CONFIG CONFIG_9f83a2
Setting the target to an empty string disables the command outright. This is a small addition to redis.conf that has saved more than one production dataset from an accidental wipe.
Firewall and Network Hardening
Assuming Redis needs to accept connections from another host (common in multi-tier architectures), configure ufw to allow traffic only from trusted sources rather than the whole internet:
sudo ufw allow from 10.0.0.0/24 to any port 6379 proto tcp comment "Redis - app subnet only"
sudo ufw enable
If Redis only ever talks to processes on the same machine — which is the case for a huge share of caching setups behind a single web app — skip opening the port entirely. Localhost communication doesn’t need a firewall rule; it needs bind 127.0.0.1 and nothing more.
For cross-host setups where a firewall alone doesn’t feel sufficient, consider TLS support (available natively since Redis 6) or tunneling connections through an SSH tunnel or a VPN mesh like WireGuard or Tailscale, especially across cloud regions or providers where the “private network” isn’t as private as the dashboard implies.
Persistence Strategy: RDB vs AOF
Redis offers two persistence mechanisms, and picking the wrong one for your workload is a subtle but real source of data-loss incidents.
RDB (snapshotting) takes point-in-time snapshots of the dataset at configured intervals. It’s compact and fast to restore from, but you can lose everything written since the last snapshot if the process crashes.
AOF (append-only file) logs every write operation, giving you much stronger durability, at the cost of larger files and slightly higher disk I/O overhead.
For most caching workloads — session storage, API response caching, rate limiting — RDB alone is often sufficient, since losing a few seconds of cache data on crash is a non-event. For workloads where Redis is doubling as a lightweight primary store — job queues, leaderboard data that matters, counters tied to billing — enable AOF alongside RDB:
appendonly yes
appendfsync everysec
everysec is the pragmatic middle ground: it fsyncs once per second rather than on every write, balancing durability against disk I/O pressure. Only use appendfsync always if you have a specific compliance requirement demanding it, since it will noticeably hurt write throughput on busy instances.
Memory Management and Eviction Policy
Redis with no maxmemory cap set will happily consume all available RAM until the OS’s out-of-memory killer steps in and terminates something — sometimes Redis itself, sometimes an unrelated process on the same box. Set an explicit ceiling:
maxmemory 512mb
maxmemory-policy allkeys-lru
The eviction policy choice actually matters more than people give it credit for. allkeys-lru evicts the least recently used keys once the memory cap is hit — great for pure caching. volatile-lru only evicts keys that have an expiry set, leaving keys without a TTL untouched, which is the right call when Redis holds a mix of cache data and something more permanent. noeviction simply refuses new writes once full, which is appropriate only if data loss is genuinely unacceptable and you’d rather the application handle the error explicitly.
Set maxmemory conservatively — somewhere around 70–75% of available system RAM if Redis is the primary tenant on the box, leaving headroom for the OS page cache, connection overhead, and Redis’s own internal bookkeeping structures (which aren’t free, contrary to what the “in-memory key-value store” mental model suggests).
Performance Tuning Beyond the Defaults
A handful of OS-level and Redis-level tweaks consistently pay off under real traffic:
- Disable Transparent Huge Pages (THP). THP conflicts with Redis’s memory allocation patterns and can cause latency spikes during background saves. Disable it with
echo never > /sys/kernel/mm/transparent_hugepage/enabled, and make the change persistent via a systemd service or/etc/rc.local. - Tune
vm.overcommit_memory. Setvm.overcommit_memory = 1in/etc/sysctl.confand reload withsudo sysctl -p. This prevents fork() failures during background RDB saves under memory pressure. - Increase the TCP backlog. Set
net.core.somaxconn = 512and match it with Redis’s owntcp-backlog 511directive for high-connection-count workloads. - Watch persistence I/O on spinning disks. If you’re still running Redis on rotational storage (rare these days, but it happens on legacy hardware), AOF rewrites and RDB snapshots can cause noticeable latency spikes under load. SSD-backed storage isn’t a luxury here — it’s close to a requirement for anything beyond light traffic.
- Use pipelining from the client side. This isn’t a server config, but it’s worth mentioning because it’s the single highest-leverage change many developers skip: batching commands via pipelining cuts round-trip latency dramatically compared to sending commands one at a time.
Troubleshooting Common Redis Issues
“Could not connect to Redis at 127.0.0.1:6379: Connection refused”
Almost always means the service isn’t running, or it’s bound to a different interface than expected. Check:
sudo systemctl status redis-server
grep '^bind' /etc/redis/redis.conf
“NOAUTH Authentication required”
You’ve enabled requirepass but haven’t authenticated in your current CLI session. Run AUTH <password> immediately after connecting, or pass it directly: redis-cli -a yourpassword.
Redis Crashes or Restarts Unexpectedly Under Load
Check dmesg for OOM killer activity:
sudo dmesg | grep -i "out of memory"
If Redis shows up there, your maxmemory setting is either missing or set too high relative to available RAM. Lower it and re-test.
High Latency on Specific Commands
Use Redis’s built-in latency monitoring:
redis-cli --latency
redis-cli LATENCY HISTORY command
Commands like KEYS * on large datasets are a classic latency trap — they’re O(n) and block the single-threaded event loop. Use SCAN instead in any production code path.
Permission Denied Errors on the Config or Log Files
Usually a leftover from manual file edits as root that changed ownership away from the redis user:
sudo chown redis:redis /etc/redis/redis.conf /var/log/redis/redis-server.log