Introduction

Redis is the most popular in-memory data store — used as a cache, message broker, session store, and database. Ansible automates the full Redis lifecycle: install, template configurations for standalone or clustered setups, deploy Sentinel for high availability, tune memory and persistence settings, and configure security.

Install Redis

---
- name: Deploy Redis
  hosts: redis_servers
  become: true
  vars:
    redis_version: "7.4"
    redis_port: 6379
    redis_bind: "{{ ansible_default_ipv4.address }} 127.0.0.1"
    redis_maxmemory: "{{ (ansible_memtotal_mb * 0.75) | int }}mb"
    redis_maxmemory_policy: allkeys-lru
    redis_password: "{{ vault_redis_password }}"
  tasks:
    - name: Install Redis (Ubuntu/Debian)
      block:
        - name: Add Redis repository
          ansible.builtin.apt_repository:
            repo: "ppa:redislabs/redis"
            state: present

        - name: Install Redis
          ansible.builtin.apt:
            name: redis-server
            state: present
      when: ansible_os_family == 'Debian'

    - name: Install Redis (RHEL)
      ansible.builtin.dnf:
        name: redis
        state: present
      when: ansible_os_family == 'RedHat'

    - name: Deploy Redis config
      ansible.builtin.template:
        src: redis.conf.j2
        dest: /etc/redis/redis.conf
        mode: '0640'
        owner: redis
        group: redis
      notify: restart redis

    - name: Configure system settings
      block:
        - ansible.posix.sysctl:
            name: vm.overcommit_memory
            value: '1'
            sysctl_set: true

        - ansible.posix.sysctl:
            name: net.core.somaxconn
            value: '65535'
            sysctl_set: true

        - name: Disable THP
          ansible.builtin.shell: echo never > /sys/kernel/mm/transparent_hugepage/enabled
          changed_when: true

    - name: Start Redis
      ansible.builtin.service:
        name: redis-server
        state: started
        enabled: true

  handlers:
    - name: restart redis
      ansible.builtin.service:
        name: redis-server
        state: restarted

Redis Config Template

# templates/redis.conf.j2
bind {{ redis_bind }}
port {{ redis_port }}
protected-mode yes
requirepass {{ redis_password }}

# Persistence
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis

# AOF persistence
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# Memory
maxmemory {{ redis_maxmemory }}
maxmemory-policy {{ redis_maxmemory_policy }}

# Logging
loglevel notice
logfile /var/log/redis/redis-server.log

# Performance
tcp-backlog 511
timeout 300
tcp-keepalive 300
databases 16

# Slow log
slowlog-log-slower-than 10000
slowlog-max-len 128

Redis Sentinel (High Availability)

---
- name: Deploy Redis Sentinel
  hosts: redis_sentinels
  become: true
  vars:
    redis_master_host: "{{ hostvars[groups['redis_master'][0]].ansible_default_ipv4.address }}"
    redis_master_port: 6379
    sentinel_port: 26379
    sentinel_quorum: 2
    sentinel_down_after: 5000
    sentinel_failover_timeout: 60000
  tasks:
    - name: Deploy Sentinel config
      ansible.builtin.template:
        src: sentinel.conf.j2
        dest: /etc/redis/sentinel.conf
        mode: '0640'
        owner: redis
      notify: restart sentinel

    - name: Start Sentinel
      ansible.builtin.service:
        name: redis-sentinel
        state: started
        enabled: true

  handlers:
    - name: restart sentinel
      ansible.builtin.service:
        name: redis-sentinel
        state: restarted
# templates/sentinel.conf.j2
port {{ sentinel_port }}
daemonize yes
pidfile /var/run/redis/redis-sentinel.pid
logfile /var/log/redis/sentinel.log

sentinel monitor mymaster {{ redis_master_host }} {{ redis_master_port }} {{ sentinel_quorum }}
sentinel auth-pass mymaster {{ redis_password }}
sentinel down-after-milliseconds mymaster {{ sentinel_down_after }}
sentinel failover-timeout mymaster {{ sentinel_failover_timeout }}
sentinel parallel-syncs mymaster 1

Replication Setup

# On replica nodes
- name: Configure Redis replica
  ansible.builtin.lineinfile:
    path: /etc/redis/redis.conf
    regexp: "^# replicaof"
    line: "replicaof {{ redis_master_host }} {{ redis_master_port }}"
  notify: restart redis

- name: Set master auth
  ansible.builtin.lineinfile:
    path: /etc/redis/redis.conf
    regexp: "^# masterauth"
    line: "masterauth {{ redis_password }}"
  notify: restart redis

Redis Cluster (Sharding)

---
- name: Deploy Redis Cluster nodes
  hosts: redis_cluster
  become: true
  vars:
    redis_cluster_port: 6379
    redis_cluster_bus_port: 16379
  tasks:
    - name: Deploy cluster config
      ansible.builtin.template:
        src: redis-cluster.conf.j2
        dest: /etc/redis/redis.conf
        mode: '0640'
        owner: redis
      notify: restart redis

- name: Initialize Redis Cluster
  hosts: "{{ groups['redis_cluster'][0] }}"
  become: true
  tasks:
    - name: Create cluster
      ansible.builtin.command: >
        redis-cli --cluster create
        {% for host in groups['redis_cluster'] %}
        {{ hostvars[host].ansible_default_ipv4.address }}:6379
        {% endfor %}
        --cluster-replicas 1
        --cluster-yes
        -a {{ redis_password }}
      register: cluster_create
      changed_when: "'OK' in cluster_create.stdout"
      run_once: true
# templates/redis-cluster.conf.j2
port {{ redis_cluster_port }}
bind {{ ansible_default_ipv4.address }} 127.0.0.1
requirepass {{ redis_password }}
masterauth {{ redis_password }}

cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000

# Same persistence and memory settings as standalone
maxmemory {{ redis_maxmemory }}
maxmemory-policy {{ redis_maxmemory_policy }}
appendonly yes

TLS Encryption

- name: Configure Redis TLS
  ansible.builtin.blockinfile:
    path: /etc/redis/redis.conf
    block: |
      tls-port 6380
      port 0
      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 optional
      tls-replication yes
      tls-cluster yes
  notify: restart redis

ACL (Access Control)

- name: Configure Redis ACLs
  ansible.builtin.blockinfile:
    path: /etc/redis/redis.conf
    block: |
      # Application user — read/write on app:* keys
      user appuser on >{{ vault_app_redis_password }} ~app:* &* +@all -@dangerous
      # Read-only monitoring user
      user monitor on >{{ vault_monitor_password }} ~* &* +@read +info +ping
      # Disable default user (optional)
      # user default off
  notify: restart redis

Monitoring

- name: Install Redis Exporter for Prometheus
  ansible.builtin.get_url:
    url: "https://github.com/oliver006/redis_exporter/releases/download/v1.62.0/redis_exporter-v1.62.0.linux-amd64.tar.gz"
    dest: /tmp/redis_exporter.tar.gz

- name: Extract and install
  ansible.builtin.unarchive:
    src: /tmp/redis_exporter.tar.gz
    dest: /usr/local/bin/
    remote_src: true
    extra_opts: [--strip-components=1]

- name: Create systemd service
  ansible.builtin.copy:
    dest: /etc/systemd/system/redis-exporter.service
    content: |
      [Unit]
      Description=Redis Exporter
      After=redis-server.service
      [Service]
      ExecStart=/usr/local/bin/redis_exporter --redis.addr=redis://localhost:6379 --redis.password={{ redis_password }}
      User=redis
      [Install]
      WantedBy=multi-user.target
    mode: '0644'
  notify: start redis exporter

handlers:
  - name: start redis exporter
    ansible.builtin.systemd:
      name: redis-exporter
      state: started
      enabled: true
      daemon_reload: true

Health Check

- name: Redis health check
  ansible.builtin.command: redis-cli -a {{ redis_password }} ping
  register: redis_ping
  changed_when: false
  failed_when: redis_ping.stdout != 'PONG'

- name: Check memory usage
  ansible.builtin.command: redis-cli -a {{ redis_password }} info memory
  register: redis_memory
  changed_when: false

- name: Check replication status
  ansible.builtin.command: redis-cli -a {{ redis_password }} info replication
  register: redis_replication
  changed_when: false

Troubleshooting

"MISCONF Redis is configured to save RDB snapshots"

- ansible.posix.sysctl:
    name: vm.overcommit_memory
    value: '1'
    sysctl_set: true

High Latency

- name: Check slow log
  ansible.builtin.command: redis-cli -a {{ redis_password }} slowlog get 10
  register: slowlog
  changed_when: false

Conclusion

Ansible deploys Redis at any scale — standalone with persistence, Sentinel for automatic failover, or Cluster for sharding. Template configurations from variables, tune memory (maxmemory + eviction policy), enable AOF for durability, set up TLS for encryption, and configure ACLs for fine-grained access. Use the Redis Exporter for Prometheus metrics and scheduled health checks to keep your deployment healthy.