Garnet is an open-source cache store from Microsoft Research that speaks the Redis protocol (RESP), so existing Redis clients, redis-cli and most Redis commands work against it unchanged. It is written in C# on .NET and is designed to use many CPU cores and scale with many client connections. In this tutorial you will install Garnet on Ubuntu 24.04 as a .NET tool, run it as a systemd service with password authentication and on-disk checkpoints, connect with redis-cli and measure its throughput.

Prerequisites

To follow this tutorial you need:

  • A server running Ubuntu 24.04 LTS with at least 2 GB of RAM, for example a CubePath VPS.
  • A non-root user with sudo privileges and UFW enabled with OpenSSH allowed.
  • Port 6379 free. If Redis or Valkey is installed on the same server, stop it or choose another port for Garnet.

Step 1 - Installing the .NET SDK

Garnet is distributed as a .NET tool on NuGet, so you need the .NET SDK to install it and the .NET runtime to run it. Ubuntu 24.04 ships .NET 8 in its own archive, which receives security updates through the normal apt upgrade:

sudo apt update
sudo apt install -y dotnet-sdk-8.0

Confirm the SDK and runtime versions:

dotnet --list-sdks
dotnet --list-runtimes
8.0.1xx [/usr/lib/dotnet/sdk]
Microsoft.AspNetCore.App 8.0.x [/usr/lib/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 8.0.x [/usr/lib/dotnet/shared/Microsoft.NETCore.App]

Step 2 - Installing Garnet

The NuGet package is called garnet-server. Instead of a per-user global tool, install it into a fixed directory so the systemd service can run it regardless of which user installed it:

sudo dotnet tool install garnet-server --tool-path /opt/garnet
You can invoke the tool using the following command: garnet-server
Tool 'garnet-server' (version '1.x.x') was successfully installed.

Check that the server starts and list its options:

/opt/garnet/garnet-server --help | head -20

Also install the Redis command line tools, which you will use as the client and benchmark tool. They do not install a Redis server:

sudo apt install -y redis-tools

Step 3 - Creating a service user and configuration

Create a system user and the directory where Garnet writes its checkpoints:

sudo useradd --system --home-dir /var/lib/garnet --shell /usr/sbin/nologin garnet
sudo install -d -o garnet -g garnet -m 0750 /var/lib/garnet

Store the password in an environment file that only root can read. systemd reads it and substitutes the variable in the start command:

sudo install -d -m 0755 /etc/garnet
sudo nano /etc/garnet/garnet.env
GARNET_PASSWORD=your_strong_password

Replace your_strong_password with a long random string, for example the output of openssl rand -base64 32, then protect the file:

sudo chmod 0600 /etc/garnet/garnet.env

Step 4 - Running Garnet with systemd

Create the unit file:

sudo nano /etc/systemd/system/garnet.service
[Unit]
Description=Garnet cache server
Documentation=https://microsoft.github.io/garnet/
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=garnet
Group=garnet
WorkingDirectory=/var/lib/garnet
EnvironmentFile=/etc/garnet/garnet.env
Environment=DOTNET_ROOT=/usr/lib/dotnet
ExecStart=/opt/garnet/garnet-server --bind 127.0.0.1 --port 6379 --memory 1g --index 64m --auth Password --password ${GARNET_PASSWORD} --checkpointdir /var/lib/garnet --recover
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/garnet

[Install]
WantedBy=multi-user.target

What the options do:

  • --bind 127.0.0.1 --port 6379: listen only on localhost on the standard Redis port. Change the address to a private IP when other servers need access (see Step 7).
  • --memory 1g: size of the in-memory log that holds the main store. Garnet rounds it down to a power of two. Size it to your working set and leave room for the operating system.
  • --index 64m: size of the hash index. Increase it if you store tens of millions of keys.
  • --auth Password --password: require the AUTH command before any other command.
  • --checkpointdir and --recover: write checkpoints (created by SAVE or BGSAVE) to /var/lib/garnet and load the latest one at startup.

Start the service and enable it at boot:

sudo systemctl daemon-reload
sudo systemctl enable --now garnet
sudo systemctl status garnet --no-pager
● garnet.service - Garnet cache server
     Loaded: loaded (/etc/systemd/system/garnet.service; enabled; preset: enabled)
     Active: active (running) since Fri 2026-09-25 11:20:43 UTC; 3s ago

Confirm it is listening:

sudo ss -tlnp | grep 6379
LISTEN 0      512        127.0.0.1:6379      0.0.0.0:*    users:(("garnet-server",pid=4121,fd=...))

Step 5 - Connecting with redis-cli

Export the password in the REDISCLI_AUTH variable so it does not appear in your shell history as a command argument. Type the password when read waits for input:

read -rs REDISCLI_AUTH && export REDISCLI_AUTH
redis-cli -p 6379 PING
PONG

Without the password, commands are rejected:

env -u REDISCLI_AUTH redis-cli -p 6379 GET anykey
(error) NOAUTH Authentication required.

Try the common data types:

redis-cli SET greeting "hello from garnet" EX 300
redis-cli GET greeting
redis-cli HSET user:1 name Alice role admin
redis-cli HGETALL user:1
redis-cli ZADD leaderboard 100 player1 250 player2
redis-cli ZREVRANGE leaderboard 0 -1 WITHSCORES
OK
"hello from garnet"
(integer) 2
1) "name"
2) "Alice"
3) "role"
4) "admin"
(integer) 2
1) "player2"
2) "250"
3) "player1"
4) "100"

Applications connect the same way they connect to Redis: point the client at 127.0.0.1:6379 with the password. Garnet implements most, but not all, Redis commands; check the compatibility list in the Garnet documentation if your application uses modules or rare commands.

Step 6 - Testing persistence

Garnet keeps data in memory. With --checkpointdir and --recover, you can take a checkpoint and have it loaded on the next start. Create a key, save, and restart:

redis-cli SET persistent:test "survives restarts"
redis-cli SAVE
sudo systemctl restart garnet
redis-cli GET persistent:test
OK
OK
"survives restarts"

Data written after the last checkpoint is lost if the process stops. For a cache this is usually acceptable. If you need every write on disk, Garnet also supports an append-only file (--aof); read the durability section of the documentation before enabling it, since it trades throughput for durability.

Step 7 - Allowing access from other servers

To let application servers on your private network use Garnet, change --bind 127.0.0.1 in /etc/systemd/system/garnet.service to the server's private IP, then reload:

sudo systemctl daemon-reload
sudo systemctl restart garnet

Allow the port only from that network. Replace 10.0.0.0/24 with your private subnet, and never open 6379 to the whole internet:

sudo ufw allow from 10.0.0.0/24 to any port 6379 proto tcp

From an application server, test the connection with redis-cli -h your_private_ip PING after exporting REDISCLI_AUTH.

Step 8 - Benchmarking Garnet

redis-benchmark works unchanged against Garnet. It reads the password from -a, so pass the variable you already exported. This runs 1,000,000 SET and GET requests from 50 connections using 4 client threads:

redis-benchmark -p 6379 -a "$REDISCLI_AUTH" -t set,get -n 1000000 -c 50 --threads 4 -q
SET: 185528.77 requests per second, p50=0.231 msec
GET: 201207.25 requests per second, p50=0.215 msec

Real applications often send commands in batches. Pipelining 16 commands per round trip shows much higher numbers:

redis-benchmark -p 6379 -a "$REDISCLI_AUTH" -t set,get -n 1000000 -c 50 -P 16 --threads 4 -q

Your results depend on the CPU, the number of cores and whether the benchmark runs on the same server. For a fair comparison with Redis or Valkey, run them on the same machine with the same flags and value size (-d), and run the client from a separate server.

Troubleshooting

The service fails with Address already in use. Another server owns port 6379. Find it with sudo ss -tlnp | grep 6379, then stop it (for example sudo systemctl disable --now redis-server) or change --port.

The service fails immediately with a .NET error. Run sudo -u garnet DOTNET_ROOT=/usr/lib/dotnet /opt/garnet/garnet-server --help to see the message. You must install or update .NET means the tool needs a newer runtime than the one installed; install the matching dotnet-sdk-* or dotnet-runtime-* package.

Memory usage is higher than --memory. The value covers the main store log only; the index, the object store (lists, hashes, sets) and the .NET runtime use memory on top of it. Check the real usage with systemctl status garnet and lower --memory if needed.

Updating Garnet. Update the tool in place and restart the service:

sudo dotnet tool update garnet-server --tool-path /opt/garnet
sudo systemctl restart garnet

Conclusion

Garnet is now running on Ubuntu 24.04 as an unprivileged systemd service, protected by a password, recovering from checkpoints after restarts and reachable with any Redis client. As next steps, move your application's cache connection string to Garnet and compare latency under real traffic, schedule BGSAVE if you rely on checkpoints, and explore Garnet's cluster mode and TLS options in the official documentation when a single node is no longer enough.