In a few of our previous blog posts, we’ve seen how to get started with Valkey/Redis by running a simple docker container and how to persist some configuration settings to disk. In this post, let’s take a step back and go over a few configuration best practices.
Connections
The Valkey/Redis config file is typically located at /etc/valkey/valkey.conf, but you can store it anywhere and simply include a reference to it when launching the Valkey daemon. (Ex: valkey-server /etc/valkey/6379.conf)
Interface binding
By default, Valkey uses the following default for binding to interfaces on the server:
1 | bind 127.0.0.1 -::1 |
Protected mode
Valkey/Redis is designed to be accessed only from internal networks and trusted clients. If you modify the configuration to bind to all interfaces and do not set a password for the default user, Valkey enters protected mode. This mode only allows connections from localhost. Connections from other interfaces are denied.
Be absolutely sure that you want to bind Valkey/Redis on all interfaces without any user authentication.
Keep-alive
By default, Valkey/Redis uses a 300s keep-alive timeout, which means 600s are needed to force close a connection. 5 minutes is a “long time” to have a connection sit idle, especially in a busy environment. Something closer to 20-30s may be more ideal.
1 | tcp-keepalive 30 |
SSL/TLS connectivity
SSL/TLS connectivity to Valkey/Redis is not enabled by default. Consider enabling this, especially if you are in the cloud or other shared environments, and provide SSL certificates to encrypt all your Valkey connections between client and server. The following parameters are the minimum configuration needed to support encrypted connections.
1 2 3 4 5 6 7 8 9 10 11 12 | # Disable non-encrypted port port 0 # Use default port for encrypted connections tls-port 6379 tls-cert-file /data/server-cert.pem tls-key-file /data/server-key.pem tls-ca-cert-file /data/ca.pem # Do not use SSL certificates for client authentication tls-auth-clients no |
The last parameter, tls-auth-clients, allows you to use SSL/TLS certificates as the authentication mechanism for client connections. If you enable this, you must use a client certificate, key, and the CA in order to establish a connection. Having this disabled still forces SSL/TLS connections but does not handle authentication.
Disk persistence
Did you know that Valkey/Redis has disk persistence? It sure does! Does it persist in a way similar to traditional MySQL/PGSQL databases? Not really.
Snapshots
Have a look at this default configuration line:
1 | save 3600 1 300 100 60 10000 |
The above says that Valkey/Redis will save to disk:
- Every 3600 seconds, if at least 1 write has happened
- Or, every 300 seconds if at least 100 writes have happened
- Or, every 60 seconds if at least 10000 writes have happened
Once you understand your application’s write capacity, you can tweak these values to suit your business requirements.
Where is the snapshot file located?
1 2 | dir /path/to/somewhere dbfilename dump.rdb |
The above will store the snapshot file at ‘/path/to/somewhere/dump.rdb’
Snapshots are good for a base backup, but what if you need something a bit more close to “commit”-level of recovery?
Append-Only File (AOF)
Valkey/Redis has the ability to record every statement and flush this file to disk once per second or after every write. This is known as ‘appendonly’, and it is off by default.
1 2 3 | appendonly yes appenddirname "appenddir" appendfsync everysec |
The above configuration will create enable AOF inside a directory, “appenddir”, inside $dir, from above, and will flush the current AOF file every 1 second. You can change $appendfsync to ‘always’, which will flush after every write, or ‘no’, to allow the filesystem to flush according to its rules.
Users
Valkey/Redis supports a single generic user, ‘default user’, or can also handle multiple users. Using the default user is very easy, and is the default behavior. We can set a password for this user to increase security just a bit:
1 | requirepass secretpass |
This will force any clients to execute “AUTH secretpass” after connecting before they can run any other commands.
The downside to the default user is that this user has access to everything. Ideally, we would want to segregate some functionality. Our monitoring user, for example, should not be able to fetch any keys or subscribe to any channels. We can create such a user as follows:
1 | user monitor on +@admin >monitorpass |
After we authenticate as this user, we will not have access to any keys:
1 2 3 4 5 6 7 8 9 | # valkey-cli --tls --cert client-cert.pem --key client-key.pem --cacert ca.pem 127.0.0.1:6379> SET foo bar (error) NOAUTH Authentication required. 127.0.0.1:6379> AUTH monitor monitorpass OK 127.0.0.1:6379> SET foo bar (error) NOPERM User monitor has no permissions to run the 'set' command 127.0.0.1:6379> GET foo (error) NOPERM User monitor has no permissions to run the 'get' command |
Working under the ‘give users the least privileges needed’ theory, we can create an application user that cannot run KEYS, or SCAN, or any configuration commands:
1 2 3 4 5 6 7 8 9 10 | # valkey.conf user app on +@all -KEYS -SCAN -CONFIG >appsecret # valkey-cli --tls --cert client-cert.pem --key client-key.pem --cacert ca.pem 127.0.0.1:6379> SET goo bar (error) NOAUTH Authentication required. 127.0.0.1:6379> AUTH app appsecret OK 127.0.0.1:6379> KEYS * (error) NOPERM User app has no permissions to run the 'keys' command |
The user ACL system in Valkey/Redis is quite complex and allows for very fine-grained restrictions. Be sure to read over the documentation in the example config file.
Memory
Servers have finite amounts of memory, so it is probably a good idea to limit how much memory Valkey/Redis can use. Otherwise, you might reach the dreaded OOM (out-of-memory) kernel panic.
1 2 | maxmemory 4GB maxmemory-policy noeviction |
The above configuration limits Valkey/Redis to a maximum of 4GB of memory for data storage and other operations buffers. Once the maximum memory is reached, the policy defined above, noevection, will return error messages to clients that are attempting to perform write options. There are other policies, such as:
- allkeys-lru – Evict keys that have not been used recently (LRU).
- allkeys-lfu – Evict keys that have been used least frequently (LFU).
- allkeys-random – Randomly remove a key
There are other policies as well. Check the configuration example for more details.
Conclusion
In this blog, we took a look at some best practices for configuring Valkey/Redis. We learned not to run Valkey bound to every interface on the server and not to run Valkey without basic passwords or user accounts. We looked at how to handle disk persistence so our data is safe and how to configure Valkey’s behavior if it runs out of assigned memory. Stay tuned for more Valkey/Redis blogs in the near future!