Configure Nginx Redis caching with SSL authentication and security hardening

Advanced 45 min Apr 05, 2026 18 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up high-performance Nginx caching with Redis backend using SSL/TLS encryption and authentication. This tutorial covers Redis 7 SSL configuration, Nginx cache module setup, and comprehensive security hardening for production environments.

Prerequisites

  • Root or sudo access
  • Basic Nginx knowledge
  • Understanding of SSL/TLS concepts
  • Redis fundamentals

What this solves

High-traffic websites need efficient caching to reduce database load and improve response times. This tutorial configures Nginx with Redis as a caching backend using SSL/TLS encryption and authentication for secure, production-ready caching. You'll learn to implement encrypted Redis connections, configure Nginx cache modules, and apply security hardening measures.

Step-by-step installation

Update system packages

Start by updating your system packages to ensure compatibility with the latest Redis and Nginx versions.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install Redis 7 and dependencies

Install Redis server with SSL support and necessary development tools for compilation.

sudo apt install -y redis-server redis-tools build-essential libssl-dev pkg-config
sudo dnf install -y redis redis-devel gcc gcc-c++ make openssl-devel pkgconfig

Install Nginx with additional modules

Install Nginx with the Redis module and SSL support for caching functionality.

sudo apt install -y nginx nginx-module-njs libnginx-mod-http-redis2
sudo dnf install -y nginx nginx-module-njs nginx-mod-http-redis2

Create SSL certificates for Redis

Generate self-signed certificates for Redis SSL encryption. In production, use certificates from a trusted CA.

sudo mkdir -p /etc/redis/ssl
sudo openssl req -x509 -nodes -newkey rsa:4096 -keyout /etc/redis/ssl/redis.key -out /etc/redis/ssl/redis.crt -days 365 -subj "/C=US/ST=State/L=City/O=Organization/CN=redis.example.com"

Set SSL certificate permissions

Configure proper ownership and permissions for Redis SSL certificates. The redis user needs read access to certificates.

sudo chown redis:redis /etc/redis/ssl/redis.key /etc/redis/ssl/redis.crt
sudo chmod 600 /etc/redis/ssl/redis.key
sudo chmod 644 /etc/redis/ssl/redis.crt
Never use chmod 777. It gives every user on the system full access to your files. SSL private keys should only be readable by the Redis user (600 permissions).

Configure Redis with SSL and authentication

Create a secure Redis configuration with SSL/TLS encryption, authentication, and performance optimizations.

# Network and SSL Configuration
port 0
tls-port 6380
tls-cert-file /etc/redis/ssl/redis.crt
tls-key-file /etc/redis/ssl/redis.key
tls-protocols "TLSv1.2 TLSv1.3"
tls-ciphersuites "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"
tls-ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256"

Authentication

requirepass "your_strong_redis_password_here_min_32_chars"

Security Settings

protected-mode yes bind 127.0.0.1 tcp-backlog 511 timeout 300 tcp-keepalive 300

Memory and Performance

maxmemory 1gb maxmemory-policy allkeys-lru save 900 1 save 300 10 save 60 10000

Logging

loglevel notice logfile /var/log/redis/redis-server.log syslog-enabled yes syslog-ident redis

Disable dangerous commands

rename-command FLUSHDB "" rename-command FLUSHALL "" rename-command KEYS "" rename-command CONFIG "CONFIG_9f2ca1d8b5a3e7f4c6d2a8b1e5f9c3d7" rename-command DEBUG "" rename-command EVAL "" rename-command SHUTDOWN SHUTDOWN_a8c2e4f6b9d1c3e5a7f2b8d4c6e9a1f3

Create Redis log directory

Set up the log directory with proper permissions for the Redis service.

sudo mkdir -p /var/log/redis
sudo chown redis:redis /var/log/redis
sudo chmod 755 /var/log/redis

Configure Nginx with Redis caching

Set up Nginx with Redis backend caching and SSL upstream connections. This configuration includes cache zones and security headers.

upstream redis_backend {
    server 127.0.0.1:6380;
    keepalive 32;
}

Cache zones

proxy_cache_path /var/cache/nginx/redis levels=1:2 keys_zone=redis_cache:10m max_size=1g inactive=60m use_temp_path=off; proxy_cache_path /var/cache/nginx/static levels=1:2 keys_zone=static_cache:10m max_size=2g inactive=24h use_temp_path=off; server { listen 80; listen [::]:80; server_name example.com www.example.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com www.example.com; # SSL Configuration ssl_certificate /etc/nginx/ssl/nginx.crt; ssl_certificate_key /etc/nginx/ssl/nginx.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers off; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; # Security Headers add_header X-Frame-Options DENY always; add_header X-Content-Type-Options nosniff always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy strict-origin-when-cross-origin always; add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';" always; # Cache configuration location ~* \.(jpg|jpeg|png|gif|ico|css|js|pdf|txt)$ { proxy_cache static_cache; proxy_cache_valid 200 301 302 24h; proxy_cache_valid 404 1m; proxy_cache_key $scheme$proxy_host$uri$is_args$args; proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; proxy_cache_lock on; expires 1y; add_header Cache-Control "public, immutable"; add_header X-Cache-Status $upstream_cache_status always; proxy_pass http://backend; } # API and dynamic content caching with Redis location /api/ { # Redis cache lookup set $redis_key "api:$uri$is_args$args"; redis2_query auth your_strong_redis_password_here_min_32_chars; redis2_query get $redis_key; redis2_pass redis_backend; # Handle cache miss error_page 404 502 504 = @fallback; } location @fallback { proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # Cache the response in Redis proxy_cache redis_cache; proxy_cache_valid 200 301 302 10m; proxy_cache_valid 404 1m; proxy_cache_key $scheme$proxy_host$uri$is_args$args; proxy_cache_use_stale error timeout invalid_header updating; add_header X-Cache-Status $upstream_cache_status always; } # Main location location / { proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # Basic caching proxy_cache redis_cache; proxy_cache_valid 200 301 302 5m; proxy_cache_valid 404 1m; proxy_cache_key $scheme$proxy_host$uri$is_args$args; proxy_cache_bypass $http_pragma $http_authorization; proxy_no_cache $http_pragma $http_authorization; add_header X-Cache-Status $upstream_cache_status always; } }

Backend application servers

upstream backend { server 127.0.0.1:8080; server 127.0.0.1:8081 backup; keepalive 16; }

Create Nginx SSL certificates

Generate SSL certificates for Nginx. Replace with valid certificates in production.

sudo mkdir -p /etc/nginx/ssl
sudo openssl req -x509 -nodes -newkey rsa:4096 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt -days 365 -subj "/C=US/ST=State/L=City/O=Organization/CN=example.com"

Create cache directories

Set up Nginx cache directories with proper permissions for the web server user.

sudo mkdir -p /var/cache/nginx/redis /var/cache/nginx/static
sudo chown -R www-data:www-data /var/cache/nginx
sudo chmod -R 755 /var/cache/nginx

Configure Nginx main settings

Update the main Nginx configuration to load Redis modules and optimize for caching workloads.

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

Load Redis module

load_module modules/ndk_http_module.so; load_module modules/ngx_http_redis2_module.so; events { worker_connections 2048; use epoll; multi_accept on; } http { # Basic Settings sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; server_tokens off; client_max_body_size 64M; # Buffer settings for performance proxy_buffering on; proxy_buffer_size 128k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; # Cache settings proxy_temp_path /var/cache/nginx/temp; proxy_cache_lock on; proxy_cache_lock_timeout 5s; proxy_cache_use_stale updating; # MIME types include /etc/nginx/mime.types; default_type application/octet-stream; # Logging log_format cache_status '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' 'rt=$request_time ut="$upstream_response_time" ' 'cs="$upstream_cache_status"'; access_log /var/log/nginx/access.log cache_status; error_log /var/log/nginx/error.log; # Gzip Settings gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json; # Rate limiting limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s; # Include site configurations include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }

Enable the site configuration

Link the Redis cache configuration and remove the default site.

sudo ln -sf /etc/nginx/sites-available/redis-cache /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default

Configure Redis security hardening

Apply additional security measures to the Redis systemd service and system configuration.

[Service]

Security hardening

NoNewPrivileges=true PrivateTmp=true PrivateDevices=true ProtectHome=true ProtectSystem=strict ReadWritePaths=/var/lib/redis /var/log/redis ProtectKernelTunables=true ProtectKernelModules=true ProtectControlGroups=true RestrictRealtime=true RestrictSUIDSGID=true LockPersonality=true MemoryDenyWriteExecute=true RestrictNamespaces=true SystemCallFilter=@system-service SystemCallErrorNumber=EPERM

Create systemd override directory

Create the directory for Redis service overrides if it doesn't exist.

sudo mkdir -p /etc/systemd/system/redis.service.d

Configure system limits

Set appropriate system limits for Redis and Nginx to handle high connection loads.

# Redis limits
redis soft nofile 65535
redis hard nofile 65535
redis soft memlock unlimited
redis hard memlock unlimited

Nginx limits

www-data soft nofile 65535 www-data hard nofile 65535

Configure kernel parameters

Optimize kernel parameters for Redis and Nginx performance with high connection loads.

# Redis optimizations
vm.overcommit_memory = 1
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 5000

TCP optimizations

net.ipv4.tcp_max_syn_backlog = 65535 net.ipv4.tcp_keepalive_time = 600 net.ipv4.tcp_keepalive_intvl = 60 net.ipv4.tcp_keepalive_probes = 3

File descriptor limits

fs.file-max = 2097152

Apply kernel parameter changes

Load the new kernel parameters without requiring a reboot.

sudo sysctl -p /etc/sysctl.d/99-redis-nginx.conf

Start and enable services

Reload systemd configuration and start both Redis and Nginx services with auto-start on boot.

sudo systemctl daemon-reload
sudo systemctl enable --now redis-server
sudo systemctl enable --now nginx

Verify your setup

Test the Redis SSL connection, Nginx configuration, and cache functionality.

# Check Redis SSL connectivity
redis-cli --tls --cert /etc/redis/ssl/redis.crt --key /etc/redis/ssl/redis.key --cacert /etc/redis/ssl/redis.crt -p 6380 ping

Test Redis authentication

redis-cli --tls --cert /etc/redis/ssl/redis.crt --key /etc/redis/ssl/redis.key --cacert /etc/redis/ssl/redis.crt -p 6380 -a your_strong_redis_password_here_min_32_chars ping

Verify Nginx configuration

sudo nginx -t

Check service status

sudo systemctl status redis-server nginx

Test cache functionality

curl -H "Host: example.com" https://localhost/api/test curl -I -H "Host: example.com" https://localhost/api/test

For more comprehensive monitoring, consider setting up Prometheus and Grafana monitoring to track cache performance metrics.

Common issues

SymptomCauseFix
Redis connection refusedSSL configuration errorCheck certificate paths and permissions in /etc/redis/redis.conf
Authentication failedWrong Redis passwordVerify password in Redis config matches Nginx upstream auth
Cache not workingRedis module not loadedEnsure ngx_http_redis2_module is loaded in nginx.conf
Permission denied errorsIncorrect file ownershipsudo chown redis:redis /etc/redis/ssl/* and sudo chown www-data:www-data /var/cache/nginx
SSL handshake failureIncompatible TLS versionsCheck TLS protocol configuration in Redis and ensure client supports TLS 1.2+
High memory usageNo memory limits setConfigure maxmemory and maxmemory-policy in Redis configuration

Next steps

Automated install script

Run this to automate the entire setup

#nginx #redis #ssl #caching #performance

Need help?

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.

Talk to an engineer