From dcbb484754f51fd75f7be28d82fb894605ae6aaa Mon Sep 17 00:00:00 2001 From: Daria Korenieva Date: Wed, 12 Aug 2026 09:23:39 -0700 Subject: [PATCH 1/4] docs(platform): document the cache and coordination engine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The self-hosting docs never described the Redis-compatible layer the platform depends on, so two things were invisible to self-hosters: - The backend always connects with a cluster client (`RedisClient = RedisCluster`), so a standalone node cannot work. Nothing said so, and the failure mode is a confusing connection error. - The two distributions already run different engines — the Compose stack ships `redis:7`, the single-container image runs Valkey — which is only discoverable by reading the Compose file and the entrypoint. Adds a "Cache and coordination engine" section to Advanced Setup covering the required topology, how to substitute Valkey into the Compose stack via an override file, what a managed or external deployment must support, and the engine version floor implied by the commands the backend issues. Every load-bearing claim was verified against a running stack rather than read off the source: - The Valkey image ships `redis-server`/`redis-cli` as symlinks, so the Compose command lines and health checks work unaltered. - `user: "999:999"` is required in the override. Valkey's entrypoint only drops privileges when invoked as `valkey-server`, and the Compose command lines call the `redis-server` symlink — without the pin the shards run as root, which stock `redis:7` does not. uid 999 is `redis` in `redis:7` and `valkey` in `valkey/valkey:8.1`, so the numeric form is correct for both. - `REDIS_HOST`/`REDIS_PORT` are hardcoded in `x-backend-env`, so neither shell environment nor `backend/.env` can move them; `REDIS_PASSWORD` is not in that block and so does work from `backend/.env`. - `docker compose up -d db rabbitmq clamav falkordb migrate` starts without pulling in the bundled shards. Also corrects the `make start-core` row in the self-hosting guide: it brings up PostgreSQL, the three-shard cache cluster, RabbitMQ, FalkorDB and ClamAV and runs migrations — not "Supabase, Redis, RabbitMQ". --- docs/platform/advanced_setup.md | 94 ++++++++++++++++++++++++++++++++ docs/platform/getting-started.md | 2 +- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/docs/platform/advanced_setup.md b/docs/platform/advanced_setup.md index 227c2a6a01c9..67eb8d3b8ec4 100644 --- a/docs/platform/advanced_setup.md +++ b/docs/platform/advanced_setup.md @@ -65,6 +65,100 @@ cd ../backend prisma migrate dev --schema postgres/schema.prisma ``` +## Cache and coordination engine + +Alongside PostgreSQL and RabbitMQ, the platform depends on a Redis-compatible engine for caching, distributed locking, rate limiting, spend and usage counters, session metadata, pending-message buffers, and the server-sent-event streams that carry agent output to the browser. + +The Docker Compose stack ships `redis:7`; the single-container image runs Valkey. Either engine serves this workload. The sections below cover the topology both must provide, how to substitute Valkey into the Compose stack, and what a managed deployment has to support. + +### Cluster mode is required + +The backend always connects with a cluster client, so **a single standalone node will not work** — regardless of which engine you pick. Local development deliberately runs a real multi-shard cluster so that cross-slot bugs surface on a laptop rather than in production. + +The self-hosting distributions each bring up a three-shard, no-replica cluster on ports `17000`, `17001` and `17002` (cluster bus ports `27000`–`27002`): + +| Distribution | Engine | How the cluster is formed | +|---|---|---| +| Docker Compose stack (`autogpt_platform/docker-compose.platform.yml`) | `redis:7` | Three `redis-server` containers plus a one-shot `redis-init` sidecar that runs `redis-cli --cluster create`. Each shard announces its own Compose hostname. | +| Single-container image (`autogpt_platform/single-container`) | Valkey | Three supervised `valkey-server` processes inside the container, formed by `valkey-cli --cluster create`. Each shard announces `127.0.0.1`. | + +{% hint style="info" %} +`make start-core` brings up this cluster along with the platform's other dependencies — PostgreSQL, RabbitMQ, FalkorDB, ClamAV and the database migration job — not a single cache node. +{% endhint %} + +FalkorDB is a separate service that also speaks the Redis protocol, but it is the CoPilot graph store and depends on the FalkorDB graph module. It is not part of the cache and coordination layer, and Redis or Valkey cannot serve it. + +### Running the Compose stack on Valkey + +Connection settings are engine-neutral: `REDIS_HOST`, `REDIS_PORT` and `REDIS_PASSWORD` mean the same thing for both engines and need no change. (`REDIS_CLUSTER_HOST` and `REDIS_CLUSTER_PORT` take precedence over the first two when they are set.) The Valkey image ships `redis-server` and `redis-cli` as symlinks, so the cluster command lines and health checks in the Compose file work unaltered. + +Create a Compose override file in `autogpt_platform/`: + +```yaml +# autogpt_platform/docker-compose.override.yml +x-valkey-node: &valkey-node + image: valkey/valkey:8.1 + # The Valkey entrypoint only drops privileges when it is invoked as + # `valkey-server`, and the Compose command lines call the `redis-server` + # symlink — so pin the unprivileged account explicitly. 999:999 is + # `valkey` in the Valkey image and `redis` in the Redis image. + user: "999:999" + +services: + redis-0: *valkey-node + redis-1: *valkey-node + redis-2: *valkey-node + redis-init: *valkey-node +``` + +Then bring the stack up as usual — Docker Compose merges `docker-compose.override.yml` automatically: + +```bash +cd autogpt_platform/ +docker compose up -d deps +``` + +The service names stay `redis-0`/`redis-1`/`redis-2` and the sidecar stays `redis-init`. + +{% hint style="warning" %} +Omit the `user:` line and the shards run as root, which the stock `redis:7` image does not do. Keep it unless you have a reason not to. +{% endhint %} + +### Using a managed or external deployment + +For a cluster you run yourself — Amazon ElastiCache for Valkey, Google Memorystore for Valkey, or a self-managed cluster — the deployment must provide: + +- **Cluster mode enabled.** A single-node or cluster-mode-disabled deployment cannot serve this platform, because the backend speaks only the cluster protocol. +- **Sharded pub/sub** (`SPUBLISH`, `SSUBSCRIBE`, `SUNSUBSCRIBE`). Agent output streaming and websocket reconnection depend on it; it is not optional. +- **Announced shard addresses that resolve from the platform**, together with `REDIS_USE_ANNOUNCED_ADDRESS=true`. Without that variable the backend rewrites every shard address to the seed host, keeping only the announced port. Managed clusters give each shard a distinct hostname on a shared port, so the rewrite collapses all shards onto one node and sharded pub/sub is pinned to the wrong shard. The Compose stack already sets this variable; set it yourself if you run the backend outside Compose. + +To point the Compose stack at an external cluster, change `REDIS_HOST` and `REDIS_PORT` in the `x-backend-env` block of `docker-compose.platform.yml`. The backend services take their values from there, so editing `backend/.env` alone will not move them. `REDIS_PASSWORD` is the exception: it is absent from that block, so `backend/.env` does set it. + +If you would rather not edit a tracked file, set the same variables per backend service in `docker-compose.override.yml` — a service-level `environment:` entry overrides the value merged in from `x-backend-env`. You have to list every backend service you run, which is why the block above is the shorter route. + +Then start the dependencies you still need directly instead of through `deps`, which always brings up the bundled shards: + +```bash +docker compose up -d db rabbitmq clamav falkordb migrate +``` + +### Engine version floor + +The commands the backend issues imply these minimums, for either engine: + +| Requirement | Commands | +|---|---| +| Redis 7.0-equivalent semantics | Sharded pub/sub (`SPUBLISH`/`SSUBSCRIBE`/`SUNSUBSCRIBE`), `EXPIRE … NX` | +| Redis 6.2-equivalent semantics | `LPOP` with a `count` argument, `GETEX` | + +Valkey 8.1 and Redis 7 both clear this floor. + +The cache and coordination layer uses **no Redis modules** — no `FT.*`, `JSON.*`, `BF.*` or `TS.*` commands appear in the backend — so there is no module bundle to install or license on either engine. It does rely on Redis Streams, server-side Lua (`EVAL`), and transactions within a single hash slot, which a thin protocol proxy may not implement in full. + +{% hint style="warning" %} +This guidance covers self-hosting and local development. Behaviour under sustained production load, failover and persistence tuning depends on how you size and operate the deployment, and is outside the scope of these instructions. +{% endhint %} + ## AutoGPT Agent Server Advanced set up This guide walks you through a dockerized set up, with an external DB (postgres) diff --git a/docs/platform/getting-started.md b/docs/platform/getting-started.md index dfb5199a2a06..f8e592209f32 100644 --- a/docs/platform/getting-started.md +++ b/docs/platform/getting-started.md @@ -121,7 +121,7 @@ Inside the `autogpt_platform` directory, you can use: | Command | What it Does | |------------------------|-------------------------------------------------------------------------------| | `make init-env` | Create missing `.env` files from `.env.default` (`autogpt_platform`, `backend`, and `frontend`) | -| `make start-core` | Start just the core services (Postgres, Redis, RabbitMQ) in background | +| `make start-core` | Start just the dependency services (PostgreSQL, the three-shard cache cluster, RabbitMQ, FalkorDB, ClamAV) and run migrations, in background | | `make stop-core` | Stop the core services | | `make logs-core` | Tail the logs for core services | | `make format` | Format & lint backend (Python) and frontend (TypeScript) code | From ac54e7ec91f6343ac18f6ff072e855f06ed286a0 Mon Sep 17 00:00:00 2001 From: Daria Korenieva Date: Wed, 12 Aug 2026 12:56:27 -0700 Subject: [PATCH 2/4] docs(platform): frame Valkey as a Redis alternative, not a workaround The section landed with Valkey as a substitution recipe buried behind a docker-compose.override.yml. It is more than that: Valkey is the engine inside the single-container distribution and now selectable in the Compose stack via REDIS_IMAGE, so present it as an alternative readers can pick on operational grounds. - Lead with Redis-as-default / Valkey-as-tested-alternative plus a comparison table of where each engine is used. - Replace the override recipe with the REDIS_IMAGE one-liner, and say which .env file compose actually interpolates from. - Keep the uid 999 privilege-drop caveat as a hint, since it still applies to anyone writing their own override. - Note the earlier-checkout fallback, so the page is usable before REDIS_IMAGE exists. - Generalise the managed-deployment guidance: ElastiCache and Memorystore both offer Redis- and Valkey-flavoured clusters. Depends on the backend change that adds REDIS_IMAGE. --- docs/platform/advanced_setup.md | 52 +++++++++++++++------------------ 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/docs/platform/advanced_setup.md b/docs/platform/advanced_setup.md index 67eb8d3b8ec4..63d51250fbad 100644 --- a/docs/platform/advanced_setup.md +++ b/docs/platform/advanced_setup.md @@ -69,7 +69,16 @@ prisma migrate dev --schema postgres/schema.prisma Alongside PostgreSQL and RabbitMQ, the platform depends on a Redis-compatible engine for caching, distributed locking, rate limiting, spend and usage counters, session metadata, pending-message buffers, and the server-sent-event streams that carry agent output to the browser. -The Docker Compose stack ships `redis:7`; the single-container image runs Valkey. Either engine serves this workload. The sections below cover the topology both must provide, how to substitute Valkey into the Compose stack, and what a managed deployment has to support. +Redis is the default. **Valkey is a tested alternative:** it is the engine inside the single-container image, and the Compose stack can be pointed at it with a single variable. Valkey forked from Redis 7.2 and speaks the same protocol — nothing the backend does distinguishes the two. + +| | Redis | Valkey | +|---|---|---| +| Docker Compose stack | Default (`redis:7`) | Opt-in, via `REDIS_IMAGE` | +| Single-container image | Not used | The engine it ships | +| Backend CI | Every test leg | One additional, advisory leg | +| Connection settings | `REDIS_HOST`, `REDIS_PORT`, `REDIS_PASSWORD` | Identical — nothing to change | + +There is no functional reason to prefer one over the other for this workload: both clear the [version floor](#engine-version-floor) below, and the platform uses no Redis modules. Choose on operational grounds — which engine your managed provider offers, and which licence terms you want. The two projects' licences differ and the Redis side has changed more than once, so check the licence of the specific tag you pin. ### Cluster mode is required @@ -79,7 +88,7 @@ The self-hosting distributions each bring up a three-shard, no-replica cluster o | Distribution | Engine | How the cluster is formed | |---|---|---| -| Docker Compose stack (`autogpt_platform/docker-compose.platform.yml`) | `redis:7` | Three `redis-server` containers plus a one-shot `redis-init` sidecar that runs `redis-cli --cluster create`. Each shard announces its own Compose hostname. | +| Docker Compose stack (`autogpt_platform/docker-compose.platform.yml`) | `redis:7`, or whatever `REDIS_IMAGE` names | Three `redis-server` containers plus a one-shot `redis-init` sidecar that runs `redis-cli --cluster create`. Each shard announces its own Compose hostname. | | Single-container image (`autogpt_platform/single-container`) | Valkey | Three supervised `valkey-server` processes inside the container, formed by `valkey-cli --cluster create`. Each shard announces `127.0.0.1`. | {% hint style="info" %} @@ -88,45 +97,30 @@ The self-hosting distributions each bring up a three-shard, no-replica cluster o FalkorDB is a separate service that also speaks the Redis protocol, but it is the CoPilot graph store and depends on the FalkorDB graph module. It is not part of the cache and coordination layer, and Redis or Valkey cannot serve it. -### Running the Compose stack on Valkey - -Connection settings are engine-neutral: `REDIS_HOST`, `REDIS_PORT` and `REDIS_PASSWORD` mean the same thing for both engines and need no change. (`REDIS_CLUSTER_HOST` and `REDIS_CLUSTER_PORT` take precedence over the first two when they are set.) The Valkey image ships `redis-server` and `redis-cli` as symlinks, so the cluster command lines and health checks in the Compose file work unaltered. - -Create a Compose override file in `autogpt_platform/`: - -```yaml -# autogpt_platform/docker-compose.override.yml -x-valkey-node: &valkey-node - image: valkey/valkey:8.1 - # The Valkey entrypoint only drops privileges when it is invoked as - # `valkey-server`, and the Compose command lines call the `redis-server` - # symlink — so pin the unprivileged account explicitly. 999:999 is - # `valkey` in the Valkey image and `redis` in the Redis image. - user: "999:999" +### Switching the Compose stack to Valkey -services: - redis-0: *valkey-node - redis-1: *valkey-node - redis-2: *valkey-node - redis-init: *valkey-node -``` - -Then bring the stack up as usual — Docker Compose merges `docker-compose.override.yml` automatically: +`REDIS_IMAGE` sets the image for all three shards and the init sidecar: ```bash cd autogpt_platform/ -docker compose up -d deps +REDIS_IMAGE=valkey/valkey:8.1 docker compose up -d deps ``` -The service names stay `redis-0`/`redis-1`/`redis-2` and the sidecar stays `redis-init`. +To make it permanent, set it in `autogpt_platform/.env` — the file `make init-env` creates from `.env.default`, where `REDIS_IMAGE` is listed commented out. Note that this is the file Compose interpolates from; `backend/.env` is passed *into* the containers and cannot reach it. + +Nothing else changes. Connection settings are engine-neutral — `REDIS_HOST`, `REDIS_PORT` and `REDIS_PASSWORD` mean the same thing to both engines. (`REDIS_CLUSTER_HOST` and `REDIS_CLUSTER_PORT` take precedence over the first two when they are set.) The service names stay `redis-0`/`redis-1`/`redis-2` with the `redis-init` sidecar, and the Valkey image ships `redis-server` and `redis-cli` as symlinks, so the cluster command lines and health checks in the Compose file work unaltered. + +{% hint style="info" %} +The shards run as uid 999 under either engine, pinned in the Compose file. This matters if you write your own override: Valkey's entrypoint only drops privileges when it is invoked as `valkey-server`, and the Compose command lines call the `redis-server` symlink — so an override that sets `image:` without also setting `user: "999:999"` runs the shards as root. +{% endhint %} {% hint style="warning" %} -Omit the `user:` line and the shards run as root, which the stock `redis:7` image does not do. Keep it unless you have a reason not to. +`REDIS_IMAGE` arrived with this page. On an earlier checkout the same substitution needs a `docker-compose.override.yml` setting `image:` and `user: "999:999"` on `redis-0`, `redis-1`, `redis-2` and `redis-init`. {% endhint %} ### Using a managed or external deployment -For a cluster you run yourself — Amazon ElastiCache for Valkey, Google Memorystore for Valkey, or a self-managed cluster — the deployment must provide: +For a cluster you buy or run yourself — Amazon ElastiCache or Google Memorystore, both of which offer Redis- and Valkey-flavoured clusters, or a self-managed cluster of either engine — the deployment must provide: - **Cluster mode enabled.** A single-node or cluster-mode-disabled deployment cannot serve this platform, because the backend speaks only the cluster protocol. - **Sharded pub/sub** (`SPUBLISH`, `SSUBSCRIBE`, `SUNSUBSCRIBE`). Agent output streaming and websocket reconnection depend on it; it is not optional. From 1eb91eedee0f2ac045c519fafede61f716c5fc2f Mon Sep 17 00:00:00 2001 From: Daria Korenieva Date: Fri, 14 Aug 2026 11:53:53 -0700 Subject: [PATCH 3/4] docs(platform): trim the make start-core table row MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address review nit: the row was ~2.5x longer than its peers, stretching the rendered column. Drops "just" and "the three-shard" — the shard count is already documented in advanced_setup.md. --- docs/platform/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/platform/getting-started.md b/docs/platform/getting-started.md index f8e592209f32..da96414b3b76 100644 --- a/docs/platform/getting-started.md +++ b/docs/platform/getting-started.md @@ -121,7 +121,7 @@ Inside the `autogpt_platform` directory, you can use: | Command | What it Does | |------------------------|-------------------------------------------------------------------------------| | `make init-env` | Create missing `.env` files from `.env.default` (`autogpt_platform`, `backend`, and `frontend`) | -| `make start-core` | Start just the dependency services (PostgreSQL, the three-shard cache cluster, RabbitMQ, FalkorDB, ClamAV) and run migrations, in background | +| `make start-core` | Start dependency services (PostgreSQL, cache cluster, RabbitMQ, FalkorDB, ClamAV) and run migrations, in background | | `make stop-core` | Stop the core services | | `make logs-core` | Tail the logs for core services | | `make format` | Format & lint backend (Python) and frontend (TypeScript) code | From e13e5aebd1058ef9ca6e7b40c1b68b26131c1385 Mon Sep 17 00:00:00 2001 From: Daria Korenieva Date: Fri, 14 Aug 2026 12:22:42 -0700 Subject: [PATCH 4/4] docs(platform): describe the Valkey switch via a Compose override The section documented REDIS_IMAGE, a variable that does not exist on dev, which coupled this page to a separate config PR. Describe what works on the current codebase instead: a docker-compose.override.yml setting image and user on the three shards and the init sidecar. Two further claims were dependent on that same unmerged change and are now corrected rather than deferred: - the comparison table credited Valkey with an advisory backend CI leg. Valkey's real coverage today is the single-container image, which platform-single-container-docker.yml builds and smoke-tests on every change under autogpt_platform/. - the uid 999 note said the pin lives in the Compose file. It does not; it is something the reader has to supply in the override, so it is now a warning on the override itself rather than an aside. The uid 999 requirement is the sharp edge here and it fails silently, so it is stated where someone writing the override will hit it. --- docs/platform/advanced_setup.md | 42 ++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/docs/platform/advanced_setup.md b/docs/platform/advanced_setup.md index 63d51250fbad..0760663da29e 100644 --- a/docs/platform/advanced_setup.md +++ b/docs/platform/advanced_setup.md @@ -69,13 +69,13 @@ prisma migrate dev --schema postgres/schema.prisma Alongside PostgreSQL and RabbitMQ, the platform depends on a Redis-compatible engine for caching, distributed locking, rate limiting, spend and usage counters, session metadata, pending-message buffers, and the server-sent-event streams that carry agent output to the browser. -Redis is the default. **Valkey is a tested alternative:** it is the engine inside the single-container image, and the Compose stack can be pointed at it with a single variable. Valkey forked from Redis 7.2 and speaks the same protocol — nothing the backend does distinguishes the two. +Redis is the default. **Valkey is a tested alternative:** it is the engine inside the single-container image, which CI builds and smoke-tests on every change to the platform. Valkey forked from Redis 7.2 and speaks the same protocol — nothing the backend does distinguishes the two. | | Redis | Valkey | |---|---|---| -| Docker Compose stack | Default (`redis:7`) | Opt-in, via `REDIS_IMAGE` | +| Docker Compose stack | Default (`redis:7`) | Opt-in, via a Compose override | | Single-container image | Not used | The engine it ships | -| Backend CI | Every test leg | One additional, advisory leg | +| CI coverage | Every backend test leg | The single-container image build and smoke test | | Connection settings | `REDIS_HOST`, `REDIS_PORT`, `REDIS_PASSWORD` | Identical — nothing to change | There is no functional reason to prefer one over the other for this workload: both clear the [version floor](#engine-version-floor) below, and the platform uses no Redis modules. Choose on operational grounds — which engine your managed provider offers, and which licence terms you want. The two projects' licences differ and the Redis side has changed more than once, so check the licence of the specific tag you pin. @@ -88,7 +88,7 @@ The self-hosting distributions each bring up a three-shard, no-replica cluster o | Distribution | Engine | How the cluster is formed | |---|---|---| -| Docker Compose stack (`autogpt_platform/docker-compose.platform.yml`) | `redis:7`, or whatever `REDIS_IMAGE` names | Three `redis-server` containers plus a one-shot `redis-init` sidecar that runs `redis-cli --cluster create`. Each shard announces its own Compose hostname. | +| Docker Compose stack (`autogpt_platform/docker-compose.platform.yml`) | `redis:7` by default | Three `redis-server` containers plus a one-shot `redis-init` sidecar that runs `redis-cli --cluster create`. Each shard announces its own Compose hostname. | | Single-container image (`autogpt_platform/single-container`) | Valkey | Three supervised `valkey-server` processes inside the container, formed by `valkey-cli --cluster create`. Each shard announces `127.0.0.1`. | {% hint style="info" %} @@ -99,24 +99,38 @@ FalkorDB is a separate service that also speaks the Redis protocol, but it is th ### Switching the Compose stack to Valkey -`REDIS_IMAGE` sets the image for all three shards and the init sidecar: +The shard image is set in `docker-compose.platform.yml`, which is a tracked file. To run the cluster on Valkey without editing it, override the image for all three shards and the init sidecar in `autogpt_platform/docker-compose.override.yml`: + +```yaml +services: + redis-0: + image: valkey/valkey:8.1 + user: "999:999" + redis-1: + image: valkey/valkey:8.1 + user: "999:999" + redis-2: + image: valkey/valkey:8.1 + user: "999:999" + redis-init: + image: valkey/valkey:8.1 + user: "999:999" +``` + +Then bring the dependencies up as usual: ```bash cd autogpt_platform/ -REDIS_IMAGE=valkey/valkey:8.1 docker compose up -d deps +docker compose up -d deps ``` -To make it permanent, set it in `autogpt_platform/.env` — the file `make init-env` creates from `.env.default`, where `REDIS_IMAGE` is listed commented out. Note that this is the file Compose interpolates from; `backend/.env` is passed *into* the containers and cannot reach it. - -Nothing else changes. Connection settings are engine-neutral — `REDIS_HOST`, `REDIS_PORT` and `REDIS_PASSWORD` mean the same thing to both engines. (`REDIS_CLUSTER_HOST` and `REDIS_CLUSTER_PORT` take precedence over the first two when they are set.) The service names stay `redis-0`/`redis-1`/`redis-2` with the `redis-init` sidecar, and the Valkey image ships `redis-server` and `redis-cli` as symlinks, so the cluster command lines and health checks in the Compose file work unaltered. +{% hint style="warning" %} +`user: "999:999"` is not optional, and omitting it fails quietly. Valkey's entrypoint only drops privileges when it is invoked as `valkey-server`, and the Compose command lines call the `redis-server` symlink — so an override that sets `image:` alone runs the shards as **root**. Stock `redis:7` drops to uid 999 on its own, so this is a difference you only hit after switching engines. -{% hint style="info" %} -The shards run as uid 999 under either engine, pinned in the Compose file. This matters if you write your own override: Valkey's entrypoint only drops privileges when it is invoked as `valkey-server`, and the Compose command lines call the `redis-server` symlink — so an override that sets `image:` without also setting `user: "999:999"` runs the shards as root. +The one numeric value is correct for either engine: uid 999 is `redis` in `redis:7` and `valkey` in `valkey/valkey:8.1`, and it owns the `/data` workdir where `nodes.conf` is written. {% endhint %} -{% hint style="warning" %} -`REDIS_IMAGE` arrived with this page. On an earlier checkout the same substitution needs a `docker-compose.override.yml` setting `image:` and `user: "999:999"` on `redis-0`, `redis-1`, `redis-2` and `redis-init`. -{% endhint %} +Nothing else changes. Connection settings are engine-neutral — `REDIS_HOST`, `REDIS_PORT` and `REDIS_PASSWORD` mean the same thing to both engines. (`REDIS_CLUSTER_HOST` and `REDIS_CLUSTER_PORT` take precedence over the first two when they are set.) The service names stay `redis-0`/`redis-1`/`redis-2` with the `redis-init` sidecar, and the Valkey image ships `redis-server` and `redis-cli` as symlinks, so the cluster command lines and health checks in the Compose file work unaltered. ### Using a managed or external deployment