Valkey is an open-source key-value store forked from Redis 7.2.4 in 2024, after Redis moved away from the BSD license. It is developed under the Linux Foundation, keeps the BSD license and remains compatible with the Redis protocol, commands and client libraries. In this tutorial you will build Valkey from source on Ubuntu 24.04, run it as a hardened systemd service with authentication and persistence, and migrate the data of an existing Redis server to it.
Prerequisites
To follow this guide you need:
- A server running Ubuntu 24.04 LTS, for example a CubePath VPS, with a non-root user with
sudoprivileges. - At least 1 GB of RAM.
- For the migration section, an existing Redis server installed from the Ubuntu repositories (
redis-server).
Ubuntu 24.04 does not include Valkey in its repositories, so this guide builds the latest stable release from the official source code. Building takes one or two minutes on a small server. On newer distributions that package it, such as Debian 13, you can install the valkey-server package with apt instead and continue from Step 4, adapting the paths.
Step 1 - Building Valkey from source
Install the compiler and the libraries needed for TLS and systemd support:
sudo apt update
sudo apt install build-essential pkg-config libssl-dev libsystemd-dev
Check the latest stable version on the Valkey releases page (https://github.com/valkey-io/valkey/releases) and set it in a variable. This guide uses 9.0.0 as an example:
VALKEY_VERSION=9.0.0
Download and extract the source:
cd /tmp
curl -fsSL -o "valkey-${VALKEY_VERSION}.tar.gz" "https://github.com/valkey-io/valkey/archive/refs/tags/${VALKEY_VERSION}.tar.gz"
tar -xzf "valkey-${VALKEY_VERSION}.tar.gz"
cd "valkey-${VALKEY_VERSION}"
Compile with TLS and systemd support. USE_SYSTEMD=yes lets Valkey tell systemd when it is ready to accept connections:
make -j"$(nproc)" BUILD_TLS=yes USE_SYSTEMD=yes
Install the binaries into /usr/local/bin:
sudo make install
Verify the installation:
valkey-server --version
Valkey server v=9.0.0 sha=00000000:0 malloc=jemalloc-5.3.0 bits=64 build=...
Step 2 - Creating the user, directories and kernel setting
Valkey should run as an unprivileged user. Create a system user and group, a data directory and a configuration directory:
sudo adduser --system --group --no-create-home --home /var/lib/valkey valkey
sudo install -d -o valkey -g valkey -m 0750 /var/lib/valkey
sudo install -d -m 0755 /etc/valkey
Valkey forks a child process to write snapshots. With the default kernel memory overcommit policy that fork can fail on a busy server, and Valkey logs a warning at startup. Allow overcommit permanently:
echo 'vm.overcommit_memory = 1' | sudo tee /etc/sysctl.d/99-valkey.conf
sudo sysctl --system
Step 3 - Writing the configuration file
The source tree includes a fully commented valkey.conf with every option. Keep it as a reference and write a short configuration with only the settings you change. First, generate a strong password:
openssl rand -base64 32
sudo cp /tmp/valkey-${VALKEY_VERSION}/valkey.conf /etc/valkey/valkey.conf.example
sudo nano /etc/valkey/valkey.conf
Add the following, replacing your_strong_password with the password you generated:
bind 127.0.0.1 -::1
port 6379
protected-mode yes
supervised systemd
daemonize no
logfile ""
dir /var/lib/valkey
save 3600 1 300 100 60 10000
dbfilename dump.rdb
appendonly yes
appendfsync everysec
requirepass your_strong_password
maxmemory 512mb
maxmemory-policy allkeys-lru
What these settings do:
bind 127.0.0.1 -::1andprotected-mode yes: accept connections only from the server itself. The-before::1means Valkey still starts if IPv6 is unavailable.supervised systemd,daemonize noandlogfile "": run in the foreground under systemd and send the logs to the journal.save: write an RDB snapshot after 3600 seconds if at least 1 key changed, after 300 seconds if 100 changed, or after 60 seconds if 10,000 changed.appendonly yeswithappendfsync everysec: also log every write to the append-only file (AOF), so a crash loses at most about one second of data.requirepass: clients must authenticate with this password.maxmemoryandmaxmemory-policy allkeys-lru: limit memory to 512 MB and evict the least recently used keys when full. If Valkey stores data you cannot lose (queues, sessions you must keep), usenoevictioninstead, which returns an error when memory is full.
Protect the file, since it contains the password:
sudo chown root:valkey /etc/valkey/valkey.conf
sudo chmod 0640 /etc/valkey/valkey.conf
Step 4 - Running Valkey as a systemd service
Create the unit file:
sudo nano /etc/systemd/system/valkey.service
[Unit]
Description=Valkey key-value store
Documentation=https://valkey.io/docs/
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
User=valkey
Group=valkey
ExecStart=/usr/local/bin/valkey-server /etc/valkey/valkey.conf
Restart=on-failure
LimitNOFILE=65535
TimeoutStartSec=90
TimeoutStopSec=90
NoNewPrivileges=true
ProtectSystem=full
ProtectHome=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Type=notify works together with supervised systemd: systemd marks the service as started only when Valkey has finished loading its data. When stopped, Valkey receives SIGTERM, saves its data and exits cleanly.
Load the unit and start the service:
sudo systemctl daemon-reload
sudo systemctl enable --now valkey
Check its status and logs:
systemctl status valkey --no-pager
sudo journalctl -u valkey -n 20 --no-pager
● valkey.service - Valkey key-value store
Loaded: loaded (/etc/systemd/system/valkey.service; enabled; preset: enabled)
Active: active (running) since ...
The journal should end with Ready to accept connections tcp and should not contain the memory overcommit warning.
Step 5 - Testing the server
Connect with valkey-cli. The --askpass option prompts for the password so it does not end up in your shell history:
valkey-cli --askpass
Run a few commands:
127.0.0.1:6379> PING
PONG
127.0.0.1:6379> SET app:greeting "hello valkey" EX 300
OK
127.0.0.1:6379> GET app:greeting
"hello valkey"
127.0.0.1:6379> TTL app:greeting
(integer) 297
127.0.0.1:6379> CONFIG GET maxmemory-policy
1) "maxmemory-policy"
2) "allkeys-lru"
Check the server information:
127.0.0.1:6379> INFO server
The output contains valkey_version with the real version and redis_version:7.2.4. Valkey reports that fixed Redis version so that client libraries that check the server version keep working.
Existing applications connect exactly as they would to Redis. In most libraries the connection URL looks like this:
redis://:[email protected]:6379/0
To measure throughput on your hardware, run the included benchmark tool:
valkey-benchmark -a your_strong_password -n 100000 -c 50 -t set,get -q
SET: 142857.14 requests per second, p50=0.183 msec
GET: 153846.16 requests per second, p50=0.175 msec
Step 6 - Migrating data from Redis
If Redis runs on the same server, you can move its data to Valkey by copying the RDB snapshot. Valkey loads RDB files produced by Redis 7.2 and earlier, which includes Redis 7.0 from the Ubuntu 24.04 repositories. Files written by Redis 7.4 or later use a newer format that Valkey may refuse to load; check the version with redis-server --version before you start.
First, make Redis write a fresh snapshot, then stop it so no new writes are lost. If your Redis has a password, add --askpass:
redis-cli SAVE
sudo systemctl disable --now redis-server
Stop Valkey and remove the empty AOF it created on the first start. With AOF enabled, Valkey loads data from the AOF instead of the RDB, so the old empty AOF would hide the imported data:
sudo systemctl stop valkey
sudo rm -rf /var/lib/valkey/appendonlydir
WarningOnly remove
appendonlydiron a fresh Valkey installation. On a server that already holds data, this deletes it.
Copy the Redis snapshot into the Valkey data directory:
sudo cp /var/lib/redis/dump.rdb /var/lib/valkey/dump.rdb
sudo chown valkey:valkey /var/lib/valkey/dump.rdb
Temporarily disable the AOF so Valkey starts from the RDB file:
sudo sed -i 's/^appendonly yes/appendonly no/' /etc/valkey/valkey.conf
sudo systemctl start valkey
Compare the number of keys with what Redis had:
valkey-cli --askpass DBSIZE
Now enable the AOF at runtime. Valkey writes a new AOF from the data in memory:
valkey-cli --askpass CONFIG SET appendonly yes
Wait until the rewrite finishes. The following command must show aof_rewrite_in_progress:0 and aof_enabled:1:
valkey-cli --askpass INFO persistence | grep -E 'aof_enabled|aof_rewrite_in_progress'
Finally, set appendonly yes back in the configuration file and restart to confirm the data loads from the new AOF:
sudo sed -i 's/^appendonly no/appendonly yes/' /etc/valkey/valkey.conf
sudo systemctl restart valkey
valkey-cli --askpass DBSIZE
The key count must match. Your applications can now connect to port 6379 with Valkey's password without other changes. Once you have confirmed everything works, remove Redis with sudo apt purge redis-server.
Step 7 - Allowing access from other servers (optional)
When your application runs on another server, add this server's private IP to the bind line in /etc/valkey/valkey.conf, replacing your_private_ip:
bind 127.0.0.1 -::1 your_private_ip
Restart Valkey and allow only your application server through UFW:
sudo systemctl restart valkey
sudo ufw allow from your_app_server_ip to any port 6379 proto tcp
Never expose port 6379 to the internet. From the application server, valkey-cli -h your_private_ip --askpass ping should return PONG. For traffic that leaves a private network, enable TLS, which you compiled in with BUILD_TLS=yes.
Troubleshooting
The service fails with Address already in use. Another process, usually Redis, is listening on port 6379. Find it with sudo ss -tlnp | grep 6379 and stop it or change port in the Valkey configuration.
NOAUTH Authentication required. The client did not send the password. Use valkey-cli --askpass or include the password in the connection URL.
DBSIZE returns 0 after the migration. Valkey loaded an existing AOF instead of the RDB file. Repeat Step 6 and make sure appendonlydir was removed and appendonly no was set before starting Valkey.
Valkey refuses to load the RDB file. Check the file with valkey-check-rdb /var/lib/valkey/dump.rdb. An error about an unsupported RDB version means the file comes from a Redis release newer than 7.2; migrate by replaying the data from your application or with a key-by-key copy tool instead.
OOM command not allowed when used memory > 'maxmemory'. Memory is full and the policy is noeviction. Raise maxmemory if the server has free RAM (free -h) or switch to an eviction policy if the data is a cache.
Conclusion
Valkey is now running on Ubuntu 24.04 as a systemd service, listening only on localhost, protected by a password and persisting data with both RDB snapshots and an AOF, with your Redis data migrated to it. As next steps, add a replica on a second server with replicaof and masterauth, set up Valkey Sentinel for automatic failover, and copy the files in /var/lib/valkey to off-site storage as part of your backups.
