# Redis and Valkey

> Create Redis and Valkey instances with Falak, connect from sites, containers and other servers over private networks, and tune memory and persistence.

Source: https://falak.sh/docs/databases/redis-and-valkey/

Since v0.7.0, Redis and Valkey are database engines next to PostgreSQL, MySQL and MariaDB: create an instance from the canvas, connect with `REDIS_*` variables, and tune memory, eviction and persistence from the panel. Since v0.7.1, an instance is reachable from containers on its own server and from the other servers of its environment over a private network, and a Compose stack's `redis` or `valkey` service can become a Falak instance.

There are no backups or restores for Redis/Valkey yet (phase 3), and an instance is never reachable on a public address. See [Limits](#limits).

## What it is

Every Falak Redis or Valkey is its own `redis-server@falak-<name>` (or `valkey-server@falak-<name>`) process: own port, password, memory limit, eviction policy and persistence. Data in one instance can never be read through another, and a stock Redis or Valkey the server already runs (port 6379, no password) is left exactly as it was — Falak's instances can't read, reload or overwrite it, and it can't touch theirs.

Falak's instances use ports **6380–6479**; the control plane allocates the lowest free one per server.

## Prerequisites

A server with a cache engine: an **app** server with Redis or Valkey chosen under Software, a dedicated **cache** server, or an app server that [gets one later](#install-an-engine-on-an-existing-server).

| Engine | Value | Default port | Installed from |
|---|---|---|---|
| Redis | `redis` | `6379` (stock), 6380–6479 (instances) | Distribution packages |
| Valkey | `valkey` | `6379` (stock), 6380–6479 (instances) | Distribution packages |

See [Versions per OS](#versions-per-os) for what each distribution ships.

## Install an engine on an existing server

An **app** server created without a cache engine can get one later: server page → **Settings → Database engine**, pick Redis or Valkey, then **Install**. The server applies its provisioning plan with the engine added, which takes a minute or two.

- Only active **app** servers without a cache engine can add one. A **cache** server always has one.
- Needs `servers.manage`. Through the API: [`POST /api/v1/servers/{server}/database-engine`](/docs/api/servers/#post-apiv1serversserverdatabase-engine--serversmanage).
- A server can run one engine of a kind: adding Valkey where Redis (or vice versa) already runs is refused.

## Create an instance

1. On the canvas: **+ Create → Database**.
2. Pick **Redis** or **Valkey** and a server that has it.
3. Name the instance (for example `cache`); the name is what references use. Adjust memory limit, eviction and persistence under **Advanced** if the defaults don't fit.
4. Create. The card turns **Active** once the agent has started the instance.

| Field | Rule |
|---|---|
| Name | `^[a-z][a-z0-9_-]{0,40}$`, reserved: `default`, `falak` |
| Memory limit | Default 128 MB, capped at ¾ of the server's RAM |
| Eviction policy | Default `noeviction`; see [Memory and eviction](#memory-and-eviction) |
| Persistence | Default `rdb`; see [Persistence](#persistence) |

Each instance has exactly one user, `default`, holding the `requirepass` password. Extra users, grants and the Databases & users tab don't apply to Redis and Valkey instances.

## The instance panel

| Tab | Contents |
|---|---|
| **Overview** | `REDIS_URL` with reveal, the `REDIS_*` block for `.env`, a `redis-cli` line (password via `REDISCLI_AUTH`), **Rotate password**, reference keys, and [**Who can connect**](#who-can-connect) |
| **Settings** | Memory limit, eviction, persistence, engine version |

Backups and the Databases & users tab are hidden for Redis and Valkey until backups land (phase 3).

## Memory and eviction

Memory limit defaults to 128 MB, capped at ¾ of the server's reported RAM. Eviction decides what happens once an instance is full:

| Policy | Use it for |
|---|---|
| `noeviction` (default) | Queues and anything that must never silently lose a key — writes fail instead with `OOM` |
| `allkeys-lru` / `allkeys-lfu` | A pure cache: evict the least recently/frequently used key regardless of TTL |
| `allkeys-random` | A cache where recency doesn't matter |
| `volatile-lru` / `volatile-lfu` / `volatile-random` | Evict only keys with a TTL set, by the same logic |
| `volatile-ttl` | Evict the key closest to expiring |

Memory limit, eviction, the password and persistence all change **live**: Falak applies them through Redis's own `CONFIG SET` and rewrites the config file to match, with no restart. Changing the port or an advanced option that needs a different bind address restarts the instance.

## Persistence

| Mode | Behavior |
|---|---|
| `rdb` (default) | Periodic point-in-time snapshots (`dump.rdb`) |
| `aof` | Every write logged to an append-only file; survives a crash with less data loss than `rdb` |
| `none` | Nothing written to disk |

Switching between `rdb` and `aof` keeps the existing data. Switching to `none` does not:

With persistence set to `none`, every restart — a reboot, a port change, an engine upgrade, even a live settings change that needs a restart — starts the instance **empty**. Use it only for data you can afford to lose, such as a pure cache fed from somewhere else.

## Connect a site

Reference the instance from a site's variables:

```dotenv
REDIS_URL=${{ cache.REDIS_URL }}
```

| Key | Value |
|---|---|
| `REDIS_URL` | `redis://default:<password>@<host>:<port>` |
| `REDIS_HOST` | The instance's host |
| `REDIS_PORT` | The instance's own port (6380–6479) |
| `REDIS_PASSWORD` | The `default` user's password |
| `REDIS_CLIENT` | `phpredis` |

`REDIS_HOST` and `REDIS_URL` depend on where the site runs:

| The site runs… | `REDIS_HOST` |
|---|---|
| Natively (Laravel, Node.js, …) on the instance's server | `127.0.0.1` |
| In a container on the instance's server (Docker site, Compose stack, function) | The Docker bridge's address (`docker0`, `172.17.0.1` out of the box) — see [Connecting from containers](#connecting-from-containers) |
| On another server of the environment (native, containers, or a site spanning both) | The instance server's address on a private network both share — see [Connecting from other servers](#connecting-from-other-servers) |

See [Variable references](/docs/guides/variable-references/) for syntax and resolution rules.

## Network access

An instance always listens on `127.0.0.1`. Since v0.7.1 it also listens where its consumers need it, and nowhere else: on the Docker bridge when containers on its server may use it, and on a private address when a site of its environment runs on another server. It **never** listens on a public address — the agent refuses public and wildcard bind addresses (`0.0.0.0`, `::`) outright. The password, `protected-mode` and the disabled commands stay in place on every address.

Network access needs an agent with the `db.redis.network` feature (agent v0.7.1 or newer). An instance on a server with an older agent keeps listening on `127.0.0.1` only: native sites on that server still connect, and every other consumer gets a deploy error telling you to update the agent. [Upgrade the agent](/docs/servers/agent-upgrades/), then deploy again. Downgrading an agent below v0.7.1 turns network access off and moves its instances back to `127.0.0.1`.

When an agent gains the feature, Falak re-applies that server's instances with their new addresses, which restarts each one once. The data is kept — except on an instance with persistence `none`, which [keeps nothing across a restart](#persistence). Later address changes (a site moving to another server, a private network added) restart the instance the same way.

### Connecting from containers

Containers on the instance's own server — Docker sites, Compose stacks, functions — connect over the Docker bridge. The instance listens on `docker0`'s address (`172.17.0.1` out of the box), and `REDIS_HOST` resolves to it for every container on that server, whatever Docker network the container is on: the server delivers traffic to its own address from any bridge.

The server's firewall opens the instance's port to the Docker address ranges arriving on the Docker bridges (`docker0`, `br-*`) only, not on the public interface. Nothing outside the server reaches the instance through this path.

Docker installed by hand on a server that is already active is picked up too: once the agent reports Docker, Falak re-applies the server's instances with the bridge address.

### Connecting from other servers

A site on another server of the instance's **environment** reaches the instance over a private network the two servers share. Falak picks the instance server's address in this order:

1. A **Falak private network** (WireGuard) that both servers are members of.
2. Otherwise, the **provider's private network** — only where both servers are on it for sure: both created by Falak with the **same provider credential**, in the **same region**, on **DigitalOcean** or **Lightsail** (whose servers of one account and region share a private network by default). Hetzner, Vultr and Linode private networks are opt-in, so Falak doesn't assume them; custom servers never use this path. Use a Falak private network for those.

The **public IP is never used**. Servers that share no private network get a deploy error instead of a host:

```text title="Example deployment error"
… shares no private network with <server>, and the Redis instance … is never exposed on a public address. Add both servers to a private network (Network → Private networks)
```

Create the network under **Network → Private networks** (see [Private networks](/docs/servers/firewall-and-networking/#private-networks-wireguard)), add both servers, then deploy again.

The instance listens on its private address only while a site of its environment runs on another server, and the firewall opens its port to those servers' addresses only, on the interface they arrive on — not to every member of the private network. Right after a network change the agent may not listen on the new address yet; the reference then says the instance `does not listen on <address> yet` — deploy again once the instance has been re-applied.

### Who can connect

The **Overview** tab's **Who can connect** list shows every site of the instance's environment with the host it gets, or the reason it can't connect (no shared private network, agent too old, address not up yet). The Connect card shows the hosts the agent actually reported: **Same server**, **Containers**, and **Private network** or **Provider private IP**.

### After a reboot

An instance listening on the Docker bridge or a WireGuard address needs those to exist before it can start. Since v0.7.1 instances wait for Docker and the server's Falak WireGuard interfaces to come up at boot, and systemd keeps retrying while they don't. The agent also checks every minute that each running instance listens on all its addresses and restarts one that is missing an address once it is back (backing off 1, 2, 5, then every 10 minutes while that doesn't help), and starts an instance that failed or stopped.

## Rotate the password

From the instance's menu in the panel → **Rotate password**. The change applies live; sites pick up the new password on their next deploy.

## Isolation and security

- Each instance runs as its own system user, `falak-redis-<name>` or `falak-valkey-<name>` (no login, no home), confined to its own data directory and config.
- Config: `/etc/falak-<engine>/<name>.conf`, mode `0640`, owned by `root` and the instance's group — readable only by root and the instance itself.
- Data: `/var/lib/falak-<engine>/<name>`, mode `0700`, owned by the instance user.
- Dangerous commands are renamed or disabled on every instance: `CONFIG` is renamed to a random, per-instance name only the agent knows; `DEBUG`, `MODULE`, `SHUTDOWN`, `REPLICAOF`, `SLAVEOF`, `MIGRATE`, `ACL`, `MONITOR`, `SLOWLOG` and, on Valkey 8.1 and newer, `COMMANDLOG` are disabled outright.
- The password never appears on a command line or in a process list: the agent and `redis-cli` pass it through `REDISCLI_AUTH`.

A stock Redis or Valkey the server already runs (no password, default commands) can't reach an instance's data or config, and an instance can't reach another instance's or the stock service's.

## Versions per OS

Versions come from the distribution's packages (checked against packages.ubuntu.com / packages.debian.org, 2026-10); a detected version outside this list is kept and flagged.

| OS | Redis | Valkey |
|---|---|---|
| Ubuntu 22.04 | 6.0 | — |
| Ubuntu 24.04 | 7.0 | 7.2 |
| Debian 12 | ✓ (distribution version) | — |
| Debian 13 | 8.0 | 8.1 |
| Ubuntu 26.04 | 8.0 | 9.0 |

Valkey is only offered where the distribution packages it. Where it isn't (Ubuntu 22.04, Debian 12), the Redis/Valkey picker only shows Redis.

## Limits

As of v0.7.1:

- **Backups and restore (phase 3).** Redis and Valkey instances have no backup schedules, on-demand backups or restores yet; the Backups tab is hidden for them.
- **No public access.** An instance is reachable from its own server (native and containers) and from servers of its environment over a shared private network only. Clients outside the environment, or servers without a shared private network, can't reach it — there is no remote access through the public IP.
- **Provider private networks** are used only on DigitalOcean and Lightsail, between servers of the same provider credential and region. Elsewhere, add the servers to a Falak private network.
- **Network access** needs agent v0.7.1 (`db.redis.network`); older agents keep instances on `127.0.0.1`.
- **Compose apps.** A Compose stack's `redis` or `valkey` service can become a Falak instance (see [Compose apps from git](/docs/guides/compose-apps/#a-falak-redis-or-valkey)), but the container's data is not copied into it.
- The agent needs the `db.redis` feature to create or manage instances; an older agent gets "Update the agent on &lt;server&gt; first" — see [Troubleshooting](#troubleshooting).
- Out of scope for now: Redis Cluster and Sentinel, replicas, per-app ACL users, modules (RedisJSON, search), and TLS for Redis.

## Troubleshooting

| Message | Meaning |
|---|---|
| `Update the agent on <server> first` | The server's agent predates `db.redis` support. [Upgrade the agent](/docs/servers/agent-upgrades/), then create the instance again. |
| `… shares no private network with <server> … Add both servers to a private network (Network → Private networks)` | The site runs on another server that shares no private network with the instance's server. Add both to a [private network](/docs/servers/firewall-and-networking/#private-networks-wireguard), then deploy again. |
| `… does not listen on <address> … yet` | The instance is being re-applied with a new address (one restart, data kept). Deploy again once it is done. |
| A reference error telling you to update the agent | The instance's server runs an agent without `db.redis.network`; only native sites on that server can connect. [Upgrade the agent](/docs/servers/agent-upgrades/). |
| `port 6381 is in use by <process>` | Something else took the port between allocation and start. Create (or restart) the instance again; Falak allocates the next free port. |
| `… is installed, but this server is set up for Valkey` (or Redis) | Falak won't run two cache engines of a kind on one machine. Remove the other one, or use the engine that's already installed. |

## Permissions

| Action | Permission | Roles |
|---|---|---|
| View | `databases.view` | all |
| Create/delete instances, change settings, rotate password | `databases.manage` | owner, admin, developer |
| Reveal the password | `databases.credentials.reveal` | owner, admin, developer |

## Next steps
