next image
next image
Adam KaczmarekMarch 27, 2026

Redis and Memurai ACLs: A Practical Security Guide for Development Teams

Technical articles and news about Memurai.

Redis® and Memurai are often used as shared resources accessed by multiple applications or services. Without fine-grained access control, all clients have the same, typically full, access to commands and data. This level of access is unacceptable in many environments.

Access Control Lists (ACLs) in Redis let you define individual users. Each user can have their own credentials and specific permissions for commands, keys, and pub/sub channels.

This guide explains how ACLs work in both Redis and Memurai. Memurai on Windows supports the same ACL features as Redis, so that you can use all the configuration examples here without any changes.

By the end of this article, you should be able to:

  • See how ACLs replaced the old single-password model.
  • Set up users with specific permissions for commands and keys.
  • Store and manage passwords safely.
  • Create rules for pub/sub access.
  • Use ACLs in real application scenarios.
  • Secure the built-in default user.

Before ACLs: The Legacy requirepass Model

Before Redis 6 and Memurai 3, authentication was handled by a single global setting in redis.conf or memurai.conf:

requirepass YourServerPassword

Clients would connect by sending the AUTH command with this password before running any other commands. All authenticated clients shared one identity and had full access.

This model has a fundamental limitation. Multiple services connecting to the same Redis instance, such as a cache layer, job queue, or session store, all share the same password and permissions. A bug, compromised credentials, or misconfigured client in one service can impact data belonging to others.

Redis 6 and Memurai 3, released in 2020, introduced the ACL system, replacing the single-password model with individual user accounts and detailed permissions.

ACLs in Redis 6 and Memurai 3: What Changed

With ACLs, the server maintains a list of named users. Each user has:

  • An enabled or disabled state
  • One or more passwords (or no password at all)
  • A set of permitted commands
  • A set of accessible key patterns
  • A set of accessible pub/sub channel patterns

The old requirepass setting is still present for backward compatibility, but it now sets the password for the default user via ACLs. Both methods work, but using ACLs is the recommended approach for managing authentication and permissions.

Every Redis installation has a default user. If you do not set up ACLs, this user has no password and full access, which might be fine for local development, but might require adjusting for shared and production environments.

Core ACL Concepts

To understand ACL rules, it helps to be familiar with several key concepts.

Users

Every ACL rule applies to a named user. Users can be enabled (on) or disabled (off). A disabled user cannot authenticate, regardless of whether they supply a valid password. The default user is used by clients that connect without explicit authentication. Its configuration determines the permissions for unauthenticated connections.

Passwords

A user can have multiple passwords. Any one of them is sufficient to authenticate. Passwords are specified with a > prefix:

user alice on >AliceSecret

The password is accepted at configuration time as plaintext, but Redis stores only the SHA-256 hash in process memory. The plaintext is discarded immediately and cannot be retrieved from a running server.

If you do not want to include a plaintext password in a configuration file, you can provide the pre-computed SHA-256 hash directly using a # prefix:

user alice on #<sha256-hex-of-password>

The nopass option lets a user log in with any password, or even without one. This is usually only for the default user during development, but it might not be suitable for named users in production.

The resetpass option deletes all the user's passwords. You will need to set a new password before that user can log in again.

Command Permissions

Permissions are granted or denied per command or per command category:

  • +<command> — allow a specific command (e.g. +get)
  • -<command> — deny a specific command
  • +@<category> — allow all commands in a category
  • -@<category> — deny all commands in a category
  • +@all — allow all commands
  • nocommands — deny all commands

Command categories group related commands. The examples use redis-cli, but you can use the same commands with memurai-cli on Windows. To see all available categories:

redis-cli ACL CAT

To list the commands within a specific category:

redis-cli ACL CAT read

Common categories include @read, @write, @string, @hash, @list, @set, @sortedset, @stream, @pubsub, @admin, @dangerous, and @fast.

Key Permissions

Key patterns control which keys a user can access:

  • ~<pattern> — read and write access to matching keys
  • %R~<pattern> — read-only access to matching keys
  • %W~<pattern> — write-only access to matching keys
  • allkeys — shorthand for ~*, access to all keys
  • resetkeys — remove all key patterns from this user

Patterns use glob syntax: ~cache:* matches any key starting with cache:, ~session:?? matches session keys with exactly two trailing characters, and so on.

Channel Permissions

Channel patterns control access to Redis pub/sub:

  • &<pattern> — access to matching channels for subscribe and publish
  • allchannels — access to all channels
  • resetchannels — remove all channel patterns from this user

Note that a single-channel pattern grants access for both subscribing and publishing to matching channels. There is no built-in way to allow subscribing to a pattern while denying publishing to the same pattern within a single channel rule. Practical approaches to this limitation are discussed in the pub/sub scenarios below.

The reset Keyword

If you use reset at the start of an ACL SETUSER rule, it puts the user back to the default state: disabled, with no passwords or permissions. This is helpful when you want to set up a user from scratch.

ACL Configuration Methods

You can set up ACLs in three different ways. While you can mix them, it is usually best to stick with one method for consistency.

Inline in Redis.conf

ACL rules can be written directly in the main configuration file alongside other server settings:

user default off user appservice on >AppPassword ~app:* +@read +@write user readonly on >ReadPassword ~app:* +@read

This method works well for simple setups, but it gets hard to manage if you have many users.

When you issue CONFIG REWRITE, Redis rewrites redis.conf from its current in-memory state, including any inline user directives. Because Redis holds only SHA-256 hashes in memory, any passwords originally specified as >plaintext will be written back as #hash entries. This is covered in more detail in the Password Storage and Security section.

Dedicated ACL File

The preferred approach for non-trivial deployments is to keep user definitions in a separate file and reference it from redis.conf:

aclfile /etc/redis/users.acl

The users.acl file lists one user per line, using the same format as inline rules. Keeping user settings separate from the main server config makes it easier to audit, track changes, and manage users independently.

Unlike inline settings, CONFIG REWRITE does not change the ACL file. You save user changes with ACL SAVE and reload them with ACL LOAD. This lets you manage server settings and user accounts separately, often with different tools or processes.

Runtime Configuration

You can create or update users while the server is running by using the ACL SETUSER command. The changes happen right away, with no need to restart.

redis-cli ACL SETUSER alice on >AliceSecret ~data:* +@read

Changes you make at runtime will only last if you save them:

redis-cli ACL SAVE

ACL SAVE writes all current user settings to the ACL file specified by aclfile. If you do not have an ACL file set, ACL SAVE will give an error. If you restart the server without saving, you will lose any changes made at runtime.

To reload the ACL file from disk (discarding unsaved runtime changes):

redis-cli ACL LOAD

Password Storage and Security

Redis stores passwords as SHA-256 hashes. When you specify >YourPassword, Redis immediately hashes it and stores only the hash in process memory. The original plaintext is discarded and cannot be retrieved from a running server.

During initial setup, it is common to write plaintext passwords directly into the configuration file or ACL file, since it is the most straightforward way to get things running. For example:

user alice on >YourPassword ~* +@all

Because Redis stores only the hash in memory, writing that in-memory state back to disk naturally produces the hashed form. The plaintext is never written back. This means the simplest way to remove plaintext credentials from your files on a running server is to trigger a persist operation.

Removing Plaintext via Automatic Rewrite

Redis rewrites redis.conf from its current in-memory state. Any user directives that were loaded with >plaintext passwords will be written back as #hash entries, since that is what is held in memory.

For a dedicated ACL file, issue ACL SAVE:

redis-cli ACL SAVE

ACL SAVE writes the current ACL state to the configured aclfile. Because passwords are stored as hashes in memory, all entries are written in #hash form regardless of how they were originally specified.

After either operation, open the file to verify that no >plaintext entries remain.

Pre-Hashing Before the Server Starts

The automatic rewrite approach requires a running server. If you need to avoid plaintext credentials ever appearing on disk.

For example, when preparing configuration files for version control, secrets scanning pipelines, or a first-time deployment, you can compute the hash offline and write it directly into the file before the server starts.

To compute the SHA-256 hash of a password on Linux or macOS:

echo -n "YourPassword" | sha256sum

On Windows (PowerShell):

$hash = [System.Security.Cryptography.SHA256]::Create()
$bytes = [System.Text.Encoding]::UTF8.GetBytes("YourPassword")
[System.BitConverter]::ToString($hash.ComputeHash($bytes)).Replace("-", "").ToLower()

Use the resulting hash in your configuration file with the # prefix:

user alice on #<paste-hash-here> ~* +@all

This approach also applies when the server's configuration or ACL file is on a read-only filesystem, or when the server process does not have write access to its own configuration. In both cases, CONFIG REWRITE and ACL SAVE would fail, leaving pre-hashing as the only option.

Key Runtime Commands

Here are some commands you will use often to manage ACLs.

Inspecting Users

List all users and their rules in a format that can be copied directly back into an ACL file:

redis-cli ACL LIST

Inspect a specific user:

redis-cli ACL GETUSER alice

Check which user the current connection is authenticated as:

redis-cli ACL WHOAMI

Managing Users

Create or update a user:

redis-cli ACL SETUSER alice on >AliceSecret ~data:* +@read +@write

Delete a user:

redis-cli ACL DELUSER alice

Persisting and Reloading

Save runtime changes to the ACL file:

redis-cli ACL SAVE

Reload the ACL file, discarding unsaved runtime changes:

redis-cli ACL LOAD

Diagnostics

View recent authorization failures (commands that were rejected due to insufficient permissions). Useful for verifying rules are correct before deploying:

redis-cli ACL LOG

Clear the ACL log:

redis-cli ACL LOG RESET

Scenario: Read-Only Cache Reader

Consider a background service, such as a reporting job or monitoring agent, that reads cached data but must not modify it.

ACL Rule

user cachereader on >CacheReaderPassword %R~cache:* +@read

This user:

  • Is enabled and authenticates with a password
  • Has read-only access (%R~) to any key matching cache:*
  • Can execute only read commands (+@read)

The %R~ prefix makes sure that even if someone tries a write command, it will be blocked at the key permission level. This gives you an extra layer of protection.

Verification

redis-cli ACL GETUSER cachereader

Test that a write is correctly rejected:

redis-cli -u redis://cachereader:CacheReaderPassword@localhost:6379 SET cache:test value
#(error) NOPERM User cachereader has no permissions to run the 'set' command

Scenario: Namespace-Scoped Application User

An application service should be able to read and write its own keys, but should not access anything outside its own namespace.

ACL Rule

user orderservice on >OrderServicePassword ~orders:* +@read +@write

This user:

  • Can read and write keys matching orders:*
  • Cannot see or modify keys belonging to any other namespace
  • Cannot execute administrative or dangerous commands

If the service needs to read from a shared namespace but only write to its own, use separate read and write patterns:

user orderservice on >OrderServicePassword %R~shared:* ~orders:* +@read +@write

In this setup, %R~shared:* gives read-only access to shared keys, and ~orders:* gives full access to the service's own keys.

Scenario: Pub/Sub Access Control

Pub/sub access is managed separately from key access. Here are some examples of how to set up users for different pub/sub roles.

Subscribe-Only Consumer

A log aggregator or event listener that must receive messages on a set of channels but is not allowed to publish to them.

The channel pattern &events:* grants sub/publish access to all events: channels, but we then explicitly remove the PUBLISH command:

user eventlistener on >ListenerPassword resetchannels &events:* +subscribe +psubscribe -publish

This user:

  • Can subscribe to channels matching events:*
  • Cannot publish — PUBLISH is explicitly denied.
  • Has no key access (none granted)
redis-cli -u redis://eventlistener:ListenerPassword@localhost:6379 \
  SUBSCRIBE events:orders
# Reading messages...

redis-cli -u redis://eventlistener:ListenerPassword@localhost:6379 \
  PUBLISH events:orders "test"
# (error) NOPERM User eventlistener has no permissions to run the 'publish' command

Publisher-Only Producer

A service that emits events but should never listen on any channel:

user eventproducer on >ProducerPassword resetchannels &notifications:orders +publish -subscribe -psubscribe

This user:

  • Can only publish to the notifications:orders channel
  • Cannot subscribe to any channel

Subscribe to All Channels, Publish on Specific Ones Only

A monitoring service needs to listen across all channels to aggregate metrics but should only emit on its own control channel.

As mentioned earlier, channel patterns (using &pattern) apply to both subscribe and publish. There is no built-in way to separate these in one rule. The practical fix is to block publishing at the command level and use a separate, narrow channel pattern for publishing, while allowing broad access for subscribing:

user monitor on >MonitorPassword resetchannels allchannels +subscribe +psubscribe +publish

Since all channels match everything, the publish restriction must be enforced at the application level or by splitting the monitoring role into two users: one with all channels and +subscribe, and the other with -publish. A separate publisher user scoped to the control channel only:

user monitor-subscriber on >MonitorSubPassword resetchannels allchannels +subscribe +psubscribe -publish
user monitor-publisher  on >MonitorPubPassword resetchannels &monitor:control +publish -subscribe -psubscribe

The application should use two different connections, one for each user and operation. This keeps the roles separate and gives you clear control over what each connection can do.

Hardening the Default User

The default user is the identity used by any client that connects without calling AUTH. In a fresh Redis installation, it is enabled, has no password (nopass), and has full access to all commands and keys. This is convenient for local development but might be inappropriate in a shared or production environment

Option 1: Require a Password on the Default User

This preserves backward compatibility with clients that do not supply a username, while still requiring authentication:

user default on >DefaultPassword ~* +@all

This is equivalent to the legacy requirepass setting, now expressed as an ACL rule.

Option 2: Disable the Default User Entirely

The most secure posture is to disable the default user and require all clients to authenticate as a named user:

user default off
user appservice on >AppPassword ~app:* +@read +@write

Any client that connects without a username will receive an authentication error immediately, regardless of the password it tries.

Option 3: Restrict the Default User's Permissions

In environments that must support unauthenticated connections for operational reasons (for example, local redis-cli usage during maintenance), you can reduce the default user's permissions rather than disabling it entirely:

user default on nopass ~* +@read -@write -@admin -@dangerous

This setup lets users read data without a password, but blocks writes and admin commands from unauthenticated connections.

For production, it is best to disable the default user and create named users with only the permissions each application or service needs.

Common Pitfalls

Forgetting ACL SAVE After Runtime Changes

ACL SETUSER changes are in-memory only. A server restart will revert to whatever is in the configuration file or ACL file. Always run ACL SAVE after making runtime changes you intend to persist.

Mixing requirepass and ACL user default

Setting requirepass in redis.conf is equivalent to setting the password on the default user. Defining both a requirepass directive and an explicit user-default rule in an ACL file can cause unexpected behavior. Use one approach: either requirepass for simple single-password setups, or ACL for everything else.

Using nopass on Named Users

nopass means a user can authenticate with any string, including an empty one. It is occasionally mistakenly set on named users. Reserve nopass for the default user in trusted environments only.

Channel Patterns Apply to Both Subscribe and Publish

As mentioned earlier, you cannot give subscribe access to a wide channel pattern and block publish in the same rule. If you need this, create two users: one for subscribing (with -publish) and another for publishing (with a narrow channel pattern and -subscribe -psubscribe).

Broad Permissions in Development Carried to Production

A common shortcut in development is to allow +@all ~* allchannels. This is okay for local work, but do not use these rules in production without first checking them. Use ACL LOG in staging to see which commands and keys each service really uses before you tighten permissions.

Not Testing Rules Before Deployment

Always check your ACL rules with ACL LOG before you deploy. Run the real commands your app will use with the actual keys and channels and ensure there are no authorization errors in the log. This helps you catch overly strict rules before they cause problems in production.

Summary

Redis ACLs replace the old single-password system with individual user accounts and detailed control over what each user can do.

Key points:

  • Every user has independent credentials, command permissions, key patterns, and channel patterns.
  • Passwords are stored as SHA-256 hashes in process memory; the server never persists plaintext.
  • Command permissions are set per command or per category, with categories providing a practical shorthand for common groupings.
  • Key permissions can be separated into read-only (%R~) and write-only (%W~) patterns, independently of command permissions.
  • Channel patterns apply uniformly to subscribe and publish; achieving asymmetric pub/sub access requires two separate users.
  • The default user should be disabled or restricted in any non-development environment.
  • Runtime ACL changes require an explicit ACL SAVE to persist across restarts.

Memurai fully supports Redis ACLs. All the configuration examples and redis-cli commands in this article work with Memurai on Windows without any changes. You can use memurai-cli instead of redis-cli wherever needed.

Explore Simple Redis-compatible Workloads on Windows

Ready to put everything you've learned into practice?

Memurai brings the full power of Redis ACLs and permission controls to Windows-native development without sacrificing performance or compatibility. Download Memurai (free for development and testing) today and start locking down access in minutes.

Redis® is a registered trademark of Redis Ltd. Any rights therein are reserved to Redis Ltd. Memurai is a separate product developed by Janea Systems and is compatible with the Redis® API, but is not a Redis Ltd. product.

Categories