Install and Configure Redis 6 on Rocky Linux 8 With Ansible

Use Ansible to install and configure Redis 6 on Rocky Linux 8: a playbook that enables the Remi repo, installs Redis, sets a password and manages the service.

In this tutorial we are going to learn how to install and configure Redis 6 on Rocky Linux 8 using Ansible. This guide will also work on other RHEL 8 based servers like Oracle Linux and Alma Linux.

Redis is an in-memory data structure store, used as a distributed, in-memory key-value database, cache and message broker, with optional durability. Redis supports different kinds of abstract data structures, such as strings, lists, maps, sets, sorted sets, HyperLogLogs, bitmaps, streams, and spatial indices.

Ansible is an open-source software provisioning, configuration management, and application-deployment tool enabling infrastructure as code. It runs on many Unix-like systems, and can configure both Unix-like systems as well as Microsoft Windows.

Where Rocky Linux 8 stands today: Rocky Linux 8 left active support on 31 May 2024 and is now in a security-maintenance phase that runs until 31 May 2029, with 8.10 as the final point release. It still works, but for a new build prefer Rocky Linux 9 or 10. The playbook below ports over unchanged — swap the Remi release RPM for remi-release-9.rpm or remi-release-10.rpm (or derive it with $(rpm -E %rhel)), since Remi publishes the same redis module streams for those releases.

Related Content:

Prerequisites

To follow along, ensure that you have:

  • An updated Rocky Linux 8 server
  • Access to the Internet
  • Root access to the server or user with sudo access
  • Ansible on your workstation. Everything here uses modules from ansible.builtin, so any currently supported ansible-core will do.

Ansible tasks to ensure the server is up to date

Before proceeding, let us make sure that the server is up to date using these tasks:

- name: Upgrade packages
  ansible.builtin.dnf:
    name: "*"
    state: latest

Enabling the Remi Release repo

The Rocky Linux repos has redis in it’s default repos. But it is not the latest version. We are going to use the Remi repos to get the latest version of redis. Add the remi repo using this task

- name: Enable the remi repo
  ansible.builtin.dnf:
    name: "https://rpms.remirepo.net/enterprise/remi-release-8.rpm"
    state: present
    disable_gpg_check: true

The dnf module takes a URL directly, so there is no need to shell out. That also makes the task idempotent — on a second run dnf sees remi-release is already installed and reports ok instead of changed. disable_gpg_check is needed only for this one package: it is the RPM that installs Remi’s GPG key, so the key is not on the box yet when it is verified. Everything pulled from the repo afterwards is signature-checked normally.

If you are following an older copy of this playbook: the original version ran this through shell with args: warn: no to silence the “use the dnf module instead” warning. That warn parameter was deprecated in ansible-core 2.11 and removed in ansible-core 2.14, so a playbook that still carries it now fails outright with Unsupported parameters for (ansible.builtin.shell) module: warn. Drop the args block wherever you see it.

Enable the redis version 6 module

Redis is available in different versions. To enable the latest version of redis, we use a dnf module stream. This task achieves that.

- name: Check whether the Remi redis 6.2 stream is already enabled
  ansible.builtin.command:
    cmd: dnf -q module list --enabled redis
  register: redis_stream
  changed_when: false
  failed_when: false

- name: Switch the redis module stream to Remi 6.2
  ansible.builtin.command:
    cmd: dnf -y module switch-to redis:remi-6.2
  when: "'remi-6.2' not in redis_stream.stdout"

Two things changed here versus the original one-liner. First, dnf module enable is the wrong verb once the base AppStream redis module is already enabled at stream 6 — dnf refuses with “Cannot enable different stream for module”. dnf module switch-to handles the swap in one step, and it is what Remi’s own install instructions use. Second, there is no ansible.builtin.dnf option for switching a module stream, so command is still the right tool — but it is now guarded by a check so a re-run is a no-op rather than a permanent changed.

To see which streams Remi is offering, run dnf module list redis on the server. Alongside remi-6.2 you will find newer streams (remi-7.2, and the Redis 8.x series). This guide stays on 6.2 — it is still receiving security patches — but if you want a newer Redis, change the stream name in both tasks above and nothing else in the playbook needs to move. Do note the licence changes if you jump forward: Redis was BSD-licensed through the 7.2 line, moved to a choice of RSALv2 or SSPLv1 from 7.4, and added AGPLv3 as a third option from 8.0 onward.

Install Redis 6 server

Finally we can install redis.

- name: Install redis
  ansible.builtin.dnf:
    name: redis
    state: latest

We are using dnf to ensure that we have latest redis installed. Since we enabled the module for redis 6.2, that will be installed.

Configuring Redis 6 server

Next we are to configure the server to be production ready.

The Remi package keeps its configuration at /etc/redis/redis.conf — you can confirm this on a running instance with redis-cli info server | grep config_file.

Add a line to allow the server to write to a pid file

- name: Set redis server pid file
  ansible.builtin.lineinfile:
    path: /etc/redis/redis.conf
    regexp: "^pidfile"
    line: "pidfile /var/run/redis/redis-server.pid"
  notify:
    - Restart Redis

In the above, we are updating the redis config file to append the line pidfile /var/run/redis/redis-server.pid so it can write a pid file. We are also setting up a handler to restart the service when the playbook is done executing.

Next, let us set up a password for out redis server to boost security.

- name: Secure redis with a password
  ansible.builtin.lineinfile:
    dest: /etc/redis/redis.conf
    regexp: '^(# )?requirepass \w*$'
    line: 'requirepass {{ redis_password }}'
    state: present
  notify:
    - Restart Redis

In the above, we are updating the redis config file to append the line requirepass {{ redis_password }} so it can set the password to be the value set. We are also setting up a handler to restart the service when the playbook is done executing.

Finally, let us bind the service to 0.0.0.0 so it is accessible externally using bind 0.0.0.0

- name: Bind redis to 0.0.0.0
  ansible.builtin.lineinfile:
    dest: /etc/redis/redis.conf
    regexp: '^bind\s'
    line: 'bind 0.0.0.0'
    state: present
  notify:
    - Restart Redis

The regex here is looser than it looks like it should be, and deliberately so. Redis 6.2 ships bind 127.0.0.1 -::1 as its default — the IPv4 address is followed by an optional IPv6 address. The tighter pattern this guide originally used (^bind \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b$) anchors on $ immediately after the IPv4 octets, so it never matches that default line. lineinfile then falls through to appending bind 0.0.0.0 at the end of the file, leaving two bind directives in the config. Redis honours the last one it parses, so it happens to work — but you are left with a confusing config file. Matching on ^bind\s replaces the real line.

Do not do this on an internet-facing host without a firewall. Binding to 0.0.0.0 exposes Redis on every interface. requirepass is the only thing standing in front of it, and Redis authentication is fast enough to brute-force over a fast link. At minimum, keep protected-mode yes, restrict port 6379 with firewalld to the hosts that actually need it, and use a long random password. If the client is on a known subnet, bind to the private address instead of 0.0.0.0.

Setting up the handlers

Let us set up the handlers listed above. Handlers are just like normal tasks in an Ansible playbook but they run only when if the Task contains a notify directive. It also indicates that it changed something.

- name: Restart Redis
  ansible.builtin.systemd_service:
    name: redis
    state: restarted

- name: Start Redis
  ansible.builtin.systemd_service:
    name: redis
    state: started

- name: Stop Redis
  ansible.builtin.systemd_service:
    name: redis
    state: stopped

- name: Enable Redis
  ansible.builtin.systemd_service:
    name: redis
    enabled: yes

Those handlers will be run after the tasks to restart and enable the service.

The module used to be called systemd; it was renamed to systemd_service to better reflect its scope. ansible.builtin.systemd is kept as an alias, so older playbooks keep working — but systemd_service is the current name and the one worth writing in anything new.

The whole playbook to install and set up Redis 6

This is the final playbook. I have the file saved as setup-redis-rocky.yaml

---
- name: Install and set up Redis 6 in Rocky Linux 8
  hosts: rockylinuxsrv
  become: yes
  gather_facts: False
  vars:
    redis_password: j2GfJuLFR8
  tasks:
    - name: Upgrade packages
      ansible.builtin.dnf:
        name: "*"
        state: latest

    - name: Enable the remi repo
      ansible.builtin.dnf:
        name: "https://rpms.remirepo.net/enterprise/remi-release-8.rpm"
        state: present
        disable_gpg_check: true

    - name: Check whether the Remi redis 6.2 stream is already enabled
      ansible.builtin.command:
        cmd: dnf -q module list --enabled redis
      register: redis_stream
      changed_when: false
      failed_when: false

    - name: Switch the redis module stream to Remi 6.2
      ansible.builtin.command:
        cmd: dnf -y module switch-to redis:remi-6.2
      when: "'remi-6.2' not in redis_stream.stdout"

    - name: Install redis
      ansible.builtin.dnf:
        name: redis
        state: latest

    - name: Set redis server pid file
      ansible.builtin.lineinfile:
        path: /etc/redis/redis.conf
        regexp: "^pidfile"
        line: "pidfile /var/run/redis/redis-server.pid"
      notify:
        - Restart Redis

    - name: Secure redis with a password
      ansible.builtin.lineinfile:
        dest: /etc/redis/redis.conf
        regexp: '^(# )?requirepass \w*$'
        line: 'requirepass {{ redis_password }}'
        state: present
      notify:
        - Restart Redis
        - Enable Redis

    - name: Bind redis to 0.0.0.0
      ansible.builtin.lineinfile:
        dest: /etc/redis/redis.conf
        regexp: '^bind\s'
        line: 'bind 0.0.0.0'
        state: present
      notify:
        - Restart Redis
        - Enable Redis

  handlers:
    - name: Restart Redis
      ansible.builtin.systemd_service:
        name: redis
        state: restarted

    - name: Start Redis
      ansible.builtin.systemd_service:
        name: redis
        state: started

    - name: Stop Redis
      ansible.builtin.systemd_service:
        name: redis
        state: stopped

    - name: Enable Redis
      ansible.builtin.systemd_service:
        name: redis
        enabled: yes

One thing to fix before you use this for real: redis_password is sitting in plaintext in the playbook. Move it into an encrypted file with Ansible Vault instead — ansible-vault create group_vars/all/vault.yml, put redis_password in there, and run the playbook with --ask-vault-pass (or --vault-password-file). The task that consumes it does not change at all.

Creating the hosts file

Create a hosts.yaml file with this content. Ensure that you can connect to the server added here.

all:
  hosts:
    rockylinuxsrv:
      ansible_host: 10.2.11.10
      ansible_user: rocky

ansible_ssh_host and ansible_ssh_user are the pre-2.0 spellings. They still resolve through an alias, but ansible_host and ansible_user are the current names — use those in new inventories.

Running the playbook

You need Ansible installed locally. The OS package manager works, and so does pip. On any recent distribution, though, a bare pip install ansible into the system Python is blocked by PEP 668 with an externally-managed-environment error, so install it in its own environment instead:

pipx install --include-deps ansible

If you would rather stay with pip, install into the user site directory or a virtualenv:

python3 -m pip install --user ansible

To run the playbook use this command:

ansible-playbook -i hosts.yaml setup-redis-rocky.yaml -vv

Once it finishes, confirm Redis is up and that the password took effect:

systemctl status redis
redis-cli -a '<your-password>' ping

A healthy instance answers PONG. Without -a you should get a NOAUTH Authentication required error — which is the point.

Conclusion

In this guide, we learnt how to use ansible to install and configure Redis 6 in Rocky Linux 8.

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