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.rpmorremi-release-10.rpm(or derive it with$(rpm -E %rhel)), since Remi publishes the sameredismodule streams for those releases.
Related Content:
- How to install and configure Redis 6 on Ubuntu 22.04
- Using Ansible to install and configure Redis 6 on Debian 11
- How to install & configure Redis 6 on Rocky Linux/Centos 8
- How to using Ansible to install and configure Redis 6 on Ubuntu 20.04
- How to install and configure Ansible on Rocky Linux/Centos 8
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 supportedansible-corewill 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
shellwithargs: warn: noto silence the “use the dnf module instead” warning. Thatwarnparameter was deprecated in ansible-core 2.11 and removed in ansible-core 2.14, so a playbook that still carries it now fails outright withUnsupported parameters for (ansible.builtin.shell) module: warn. Drop theargsblock 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.0exposes Redis on every interface.requirepassis the only thing standing in front of it, and Redis authentication is fast enough to brute-force over a fast link. At minimum, keepprotected-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 of0.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.