How to Install and Secure Redis 8 on Rocky Linux 9 Using Ansible

A complete step-by-step guide to deploy and harden Redis 8 on Rocky Linux 9 with an idempotent Ansible playbook, including repository setup, service configuration, password protection, firewall, SELinux, and verification.

Redis 8 is the latest major release of the high‑performance in‑memory data store trusted for caching, message brokering, and real‑time workloads. In this hands‑on guide, you’ll learn how to use Ansible to install Redis 8 on Rocky Linux 9 and harden it for production. We’ll cover repository setup (Remi), secure configuration (passwords, binding, protected mode, disabling risky commands), service management, firewall and SELinux considerations, verification, and optional performance tuning.

If you prefer Ubuntu, check out my earlier Ansible guide for Redis 6: How to Use Ansible to Install and Configure Redis 6 on Ubuntu 20.04.

What you’ll build

  • Automated install: Enable the Remi repository and deploy Redis 8 with Ansible.
  • Security hardening: Bind to the right interface, enforce authentication, enable protected mode, and disable dangerous commands.
  • Operational readiness: Manage the systemd service, correct permissions, and optional firewall rules.
  • Verification: Validate with redis-cli and systemd status checks.

Prerequisites

  • A Rocky Linux 9 server with sudo privileges.
  • Ansible installed on your control machine.
  • SSH access to the target host(s).
  • A secure password you’ll use for Redis authentication.

Tip to install Ansible locally with pip:

1
pip install ansible

Why Ansible for Redis on Rocky 9?

  • Idempotent and repeatable deployments across environments.
  • Secure by default: Playbooks can enforce strong defaults and prevent drift.
  • Speed: Reprovision or update at any time with minimal effort.

Repository setup: Why Remi for Redis 8?

Rocky Linux 9’s default AppStream often lags behind Redis’s latest stable. Remi provides fresh, well‑maintained Redis 8 builds for Enterprise Linux 9. We’ll import Remi’s GPG key, install the repository, and enable the Redis 8 module stream.

The Ansible playbook (explained)

Below is a complete playbook with sane, secure defaults. Each block is annotated with what it does and why it matters.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
---
- name: Install and secure Redis 8 on Rocky Linux 9
  hosts: redis_servers
  become: yes
  gather_facts: yes

  vars:
    redis_version: "8.0"
    # CHANGE THIS IN PRODUCTION. Consider using Ansible Vault or a secret manager.
    redis_password: "ChangeMe-Strong-Long#2025!"
    # Bind to a specific interface or leave as 127.0.0.1 for local-only
    redis_bind_address: "127.0.0.1"
    # Optionally allow a trusted subnet through firewalld, e.g. "10.10.0.0/16"
    allowed_cidr: ""

  pre_tasks:
    - name: Ensure dnf metadata and packages are up to date
      ansible.builtin.dnf:
        update_cache: yes
        state: latest

  tasks:
    # --- Repositories ---
    - name: Install EPEL repository (required by some dependencies)
      ansible.builtin.dnf:
        name: epel-release
        state: present

    - name: Import Remi GPG key
      ansible.builtin.rpm_key:
        key: https://rpms.remirepo.net/enterprise/9/RPM-GPG-KEY-remi
        state: present

    - name: Install Remi repository for Rocky 9
      ansible.builtin.dnf:
        name: https://rpms.remirepo.net/enterprise/remi-release-9.rpm
        state: present
        disable_gpg_check: no

    - name: Enable Redis 8 module from Remi
      ansible.builtin.command:
        cmd: dnf -y module enable redis:remi-8.0
      register: enable_module
      changed_when: "'enabled' in enable_module.stdout or 'Nothing to do' not in enable_module.stdout"
      failed_when: enable_module.rc not in [0]

    # --- Install Redis 8 ---
    - name: Install Redis 8
      ansible.builtin.dnf:
        name: redis
        state: present

    # --- Secure Configuration ---
    - name: Ensure redis.conf has a stable pidfile
      ansible.builtin.lineinfile:
        path: /etc/redis/redis.conf
        regexp: '^pidfile'
        line: 'pidfile /var/run/redis/redis-server.pid'
      notify: [restart redis]

    - name: Bind Redis to the desired interface
      ansible.builtin.lineinfile:
        path: /etc/redis/redis.conf
        regexp: '^bind\s+'
        line: "bind {{ redis_bind_address }}"
      notify: [restart redis]

    - name: Ensure protected-mode is enabled
      ansible.builtin.lineinfile:
        path: /etc/redis/redis.conf
        regexp: '^protected-mode'
        line: 'protected-mode yes'
        state: present
      notify: [restart redis]

    - name: Require a strong password
      ansible.builtin.lineinfile:
        path: /etc/redis/redis.conf
        regexp: '^(#\s*)?requirepass'
        line: "requirepass {{ redis_password }}"
        state: present
      notify: [restart redis]

    - name: Disable dangerous administrative commands
      ansible.builtin.blockinfile:
        path: /etc/redis/redis.conf
        marker: "# {mark} Ansible managed disabled commands"
        block: |
          rename-command FLUSHALL ""
          rename-command FLUSHDB  ""
          rename-command CONFIG   ""
          rename-command SHUTDOWN ""
      notify: [restart redis]

    - name: Use systemd supervision (best with service managers)
      ansible.builtin.lineinfile:
        path: /etc/redis/redis.conf
        regexp: '^supervised'
        line: 'supervised systemd'
      notify: [restart redis]

    - name: Ensure correct permissions on redis.conf
      ansible.builtin.file:
        path: /etc/redis/redis.conf
        owner: redis
        group: redis
        mode: '0640'
      notify: [restart redis]

    # --- Firewall (optional but recommended) ---
    - name: Open Redis port 6379 only for allowed CIDR (if defined)
      when: allowed_cidr | length > 0
      ansible.builtin.command:
        cmd: firewall-cmd --add-rich-rule='rule family=ipv4 source address={{ allowed_cidr }} port protocol=tcp port=6379 accept' --permanent
      register: fw_rule
      changed_when: "'success' in fw_rule.stdout"
      failed_when: fw_rule.rc not in [0, 252]  # 252 when rule already exists

    - name: Reload firewalld to apply rules
      when: allowed_cidr | length > 0
      ansible.builtin.command: firewall-cmd --reload

    # --- SELinux (defaults work with 6379; adjust if you change the port) ---
    # Example if you change the port:
    # - name: Allow custom Redis port in SELinux
    #   community.general.seport:
    #     ports: 6380
    #     proto: tcp
    #     setype: redis_port_t
    #     state: present

    # --- Service Management ---
    - name: Enable and start Redis
      ansible.builtin.systemd:
        name: redis
        enabled: yes
        state: started

  handlers:
    - name: restart redis
      ansible.builtin.systemd:
        name: redis
        state: restarted

Why these hardening steps?

  • Bind address: Restricts where Redis listens (default is 127.0.0.1). Expose only if needed.
  • Protected mode: Blocks dangerous commands from unauthenticated or remote clients.
  • requirepass: Enforces authentication. Use a long, unique password (store via Vault).
  • Disable FLUSH/CONFIG/SHUTDOWN*: Prevent accidental or malicious data loss/admin actions.
  • Permissions on redis.conf: Prevents credential leakage.
  • Systemd supervision: Integrates process lifecycle with the OS for robust operation.
  • Firewalld/SELinux: Defense‑in‑depth around the network and OS policy layers.

Inventory file

Create hosts.yaml and make sure Ansible can SSH to your Rocky 9 host.

1
2
3
4
5
6
7
all:
  children:
    redis_servers:
      hosts:
        rocky9-redis:
          ansible_host: 10.2.11.10
          ansible_user: rocky

Adjust ansible_user and IP to your environment. You can also use SSH keys and group_vars.

Running the playbook

Save the playbook as setup-redis-rocky9.yml and run:

1
ansible-playbook -i hosts.yaml setup-redis-rocky9.yml -vv

For secrets, prefer Ansible Vault:

1
2
ansible-vault create group_vars/redis_servers/vault.yml
# add: redis_password: "your-strong-secret"

Then load it in the playbook or via vars_files.

Verification

  • Check service:
1
2
systemctl status redis --no-pager
ss -ltpn | grep 6379
  • Test locally:
1
2
redis-cli -a 'your-strong-secret' ping
# PONG
  • Test from a remote machine (only if you exposed the port and firewall allows it):
1
redis-cli -h <redis_host> -a 'your-strong-secret' PING
  • Confirm disabled commands:
1
2
redis-cli -a 'your-strong-secret' FLUSHALL
# (error) ERR unknown command 'FLUSHALL'

Optional performance tuning (advanced)

  • Disable Transparent Huge Pages (THP) and set vm.overcommit_memory=1 if you push high memory load. These can reduce latency spikes.
  • Tune tcp-keepalive, maxmemory + eviction policy if using Redis as a cache.
  • Persist with RDB/AOF based on your durability/SLA requirements.

Example tasks (optional):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
- name: Set vm.overcommit_memory=1
  ansible.posix.sysctl:
    name: vm.overcommit_memory
    value: '1'
    state: present
    reload: yes

- name: Disable THP at boot (grubby)
  ansible.builtin.command: grubby --update-kernel=ALL --args="transparent_hugepage=never"
  when: ansible_facts['os_family'] == 'RedHat'

Reboot required for THP change.

Troubleshooting

  • Unable to connect remotely: Verify bind, protected-mode, requirepass, firewall, and SELinux.
  • Module enable issues: Ensure Remi repo is installed and network egress is allowed.
  • Authentication errors: Confirm the password in redis.conf matches your variable.

Conclusion

You now have a production‑ready Redis 8 on Rocky Linux 9, deployed with Ansible and hardened with strong defaults. The approach is idempotent and easy to re‑run, ensuring consistency across environments. For Ubuntu users or more Ansible patterns, see my earlier Redis guides linked above.

comments powered by Disqus
Citizix Ltd
Built with Hugo
Theme Stack designed by Jimmy