# How Do I Run Redis Stack and Redis Insight in a Cloud Sandbox?

> Redis 8 replaces Redis Stack, so run the official redis:8 image in a Sandboxer microVM with AOF on and --restart unless-stopped. JSON, search and vector sets are built in. Put Redis Insight on a private sbx host URL with --localhost, and reach Redis from your laptop with redis-cli over ssh -L. Data survived stop and resume.

Source: https://sandboxer.com/guides/run-redis-stack-in-a-sandbox. Updated 2026-10-27.

**Short answer:** Redis 8 replaces Redis Stack, so run the official redis:8 image in a Sandboxer microVM with AOF on and --restart unless-stopped. JSON, search and vector sets are built in. Put Redis Insight on a private sbx host URL with --localhost, and reach Redis from your laptop with redis-cli over ssh -L. Data survived stop and resume.

## What we ran

Everything below ran on a `default` sandbox (4 vCPU, 8 GB) on 2026-10-27. Sandbox ids and tokens are replaced with `$id` and `<token>`.

| Check | Result |
| - | - |
| Image | `redis:8` (Redis 8.10.3), modules `search`, `ReJSON`, `vectorset`, `timeseries`, `bf` loaded |
| Redis Insight | `redis/redisinsight:latest` (3.8.0), healthy 5 s after `docker run` |
| `redis-benchmark -q`, inside the VM | SET 75,245 req/s, GET 86,059 req/s; with `-P 16`, GET 990,099 req/s |
| `redis-cli --latency`, inside the VM | about 0.14 ms average |
| `redis-cli --latency` from our machine over `ssh -L` | 127 ms average, 124 ms minimum |
| Private Insight URL | `401` without the token, `302` with it, then `200` with the cookie |
| `sbx stop --wait`, then `sbx resume` | `memoryRestored: true`, every key, index and the Insight URL still there |
| `systemctl restart docker` (what a boot from disk looks like) | Both containers came back on their own, data reloaded from the AOF |

## Redis Stack or redis:8?

The Redis docs now say that [Redis 8 in Redis Open Source replaces Redis Stack](https://redis.io/docs/latest/operate/oss_and_stack/), and the [Docker install page](https://redis.io/docs/latest/operate/oss_and_stack/install/install-stack/docker/) uses the `redis:<version>` image. The JSON, search and vector features that used to need Redis Stack ship inside `redis:8`. Redis Insight, which the old Stack image bundled, is now its own image, [`redis/redisinsight`](https://redis.io/docs/latest/operate/redisinsight/install/install-on-docker/). So this guide runs two containers.

## 1. Start Redis with AOF and a restart policy

Docker is preinstalled in every sandbox (see [Docker and nested KVM inside a sandbox](/guides/docker-and-kvm-inside-an-agent-sandbox)).

```bash
sbx new --type default --name redis-stack-1
id=sb_xxxxxxxxxx    # the id it printed

sbx exec $id "docker network create redis-net && docker volume create redis-data && \
  docker run -d --name redis --network redis-net --restart unless-stopped \
    -p 127.0.0.1:6379:6379 -v redis-data:/data \
    redis:8 redis-server --appendonly yes --appendfsync everysec"
```

Two choices matter here:

- **`127.0.0.1:6379`, not `6379`.** Redis has no password by default. Every sandbox has a public IPv6 address. Its firewall (`ufw`) is closed except SSH ([Security](/docs/security)), but Docker can [bypass ufw rules](https://docs.docker.com/engine/network/packet-filtering-firewalls/#docker-and-ufw) on some setups. Binding to loopback keeps Redis off the network whatever the firewall does. You reach it over SSH instead.
- **`--appendonly yes`.** Redis writes every change to an append-only file in the `redis-data` volume and fsyncs once a second, so a restart loses at most about a second of writes.

Check it:

```bash
sbx exec $id "docker exec redis redis-cli INFO server | grep redis_version; \
  docker exec redis redis-cli MODULE LIST; docker exec redis redis-cli CONFIG GET appendonly"
```

```text
redis_version:8.10.3
name
search
ver
81001
path
/usr/local/lib/redis/modules//redisearch.so
…
name
vectorset
…
name
ReJSON
…
appendonly
yes
```

The module list also shows `bf` (Bloom and other probabilistic types) and `timeseries`.

## 2. Strings, a JSON document, search and a vector query

Save this as `demo.sh`, copy it in with `sbx scp demo.sh $id:/home/user/` and run `sbx exec $id "bash demo.sh"`. It calls `redis-cli` inside the container, one command per line.

```bash
r() { docker exec redis redis-cli "$@"; }

r SET greeting "hello from the sandbox"
r GET greeting
r JSON.SET doc:1 '$' '{"title":"Pause a sandbox","tags":["stop","resume"],"views":12}'
r JSON.NUMINCRBY doc:1 '$.views' 1
r JSON.GET doc:1 '$.title' '$.views'
r JSON.SET doc:2 '$' '{"title":"Fork a sandbox","tags":["fork"],"views":40}'

# Index the JSON documents, then query them
r FT.CREATE idx:docs ON JSON PREFIX 1 doc: SCHEMA \
  '$.title' AS title TEXT '$.tags[*]' AS tags TAG '$.views' AS views NUMERIC SORTABLE
r FT.SEARCH idx:docs 'sandbox @views:[10 50]' SORTBY views DESC RETURN 2 title views
r FT.SEARCH idx:docs '@tags:{resume}' RETURN 1 title

# A vector set: add three 3-dimensional vectors, find the two closest to a query
r VADD emb VALUES 3 0.9 0.1 0.0 cat
r VADD emb VALUES 3 0.8 0.2 0.1 dog
r VADD emb VALUES 3 0.0 0.1 0.9 car
r VSIM emb VALUES 3 0.85 0.15 0.05 WITHSCORES COUNT 2
```

```text
OK
hello from the sandbox
OK
[13]
{"$.views":[13],"$.title":["Pause a sandbox"]}
OK
OK
2
doc:2
views
40
title
Fork a sandbox
doc:1
views
13
title
Pause a sandbox
1
doc:1
title
Pause a sandbox
1
1
1
cat
0.9978907108306885
dog
0.9973737895488739
```

The first search finds both documents, sorted by `views`. The tag search finds only `doc:1`. [Vector sets](https://redis.io/docs/latest/develop/data-types/vector-sets/) are new in Redis 8 and take plain numbers, so you can try similarity search from the shell without encoding binary vectors. `FT.SEARCH` with a `VECTOR` field and a `KNN` query also works, but needs the query vector as a binary blob, which is easier from a client library.

## 3. Redis Insight on a private URL

Run Insight on the same Docker network, so it reaches Redis by the name `redis`. Bind it to loopback too, and host it with `--localhost`, which makes the sandbox relay the hosted URL to `127.0.0.1` (see [Give a sandbox port an HTTPS URL](/guides/give-a-sandbox-port-an-https-url)).

```bash
sbx exec $id "docker run -d --name redisinsight --network redis-net --restart unless-stopped \
  -p 127.0.0.1:5540:5540 -v redisinsight:/data redis/redisinsight:latest"
sbx exec $id "curl -s 127.0.0.1:5540/api/health/"     # {"status":"up"}
sbx host $id 5540 --localhost --title "Redis Insight"
```

```text
https://lunar-happy-coral-5540.box.sandboxer.com?_token=<token>
```

The URL is private by default:

```bash
curl -s -o /dev/null -w "%{http_code}\n" https://lunar-happy-coral-5540.box.sandboxer.com/
# 401
curl -s -c jar -o /dev/null -w "%{http_code}\n" "https://lunar-happy-coral-5540.box.sandboxer.com/?_token=<token>"
# 302
curl -s -b jar https://lunar-happy-coral-5540.box.sandboxer.com/ | grep -o "<title>.*</title>"
# <title>Redis Insight</title>
```

In the browser, open the token link, choose **Add Redis database**, and enter host `redis`, port `6379`. We did the same through Insight's own API, and it detected the modules:

```bash
sbx exec $id "curl -s -X POST 127.0.0.1:5540/api/databases -H content-type:application/json \
  -d '{\"name\":\"sandbox-redis\",\"host\":\"redis\",\"port\":6379}'"
```

```text
{… "host":"redis","port":6379,"name":"sandbox-redis", … "provider":"REDIS_COMMUNITY_EDITION" …}
```

The Redis Insight docs list `RI_REDIS_HOST`, `RI_REDIS_PORT` and `RI_REDIS_ALIAS` for [preconfiguring a connection](https://redis.io/docs/latest/operate/redisinsight/configuration/). With Insight 3.8.0 in our run, setting them didn't add a database (`/api/databases` returned `[]`), so we added it by hand.

## 4. redis-cli from your laptop over ssh -L

Redis listens on `127.0.0.1` inside the VM, so forward a local port to it over SSH. Save the stanza that `sbx ssh-config` prints and pass it with `-F`, as in the [MySQL guide](/guides/run-mysql-or-mariadb-in-a-sandbox):

```bash
sbx ssh-config > sbx_ssh_config
ssh -F ./sbx_ssh_config -f -N -o ExitOnForwardFailure=yes -L 6380:127.0.0.1:6379 $id.sbx

redis-cli -p 6380 PING
redis-cli -p 6380 GET greeting
redis-cli -p 6380 JSON.GET doc:1 '$.views'
redis-cli -p 6380 VSIM emb ELE car COUNT 1
redis-cli -p 6380 --latency
```

```text
PONG
hello from the sandbox
[13]
car
min: 124.382, max: 249.666, avg: 127.468 (58 samples)
```

The tunnel goes through the Sandboxer API over HTTPS, so each round trip from our test machine cost about 127 ms, against 0.14 ms inside the VM. Use the tunnel for inspecting and debugging. Run anything chatty (a worker, a test suite, a benchmark) inside the sandbox. In our run the same tunnel kept working across the stop and resume below.

## 5. A measured number: redis-benchmark

```bash
sbx exec $id "docker exec redis redis-benchmark -q -n 100000 -t set,get,incr,lpush,lpop"
sbx exec $id "docker exec redis redis-benchmark -q -n 100000 -P 16 -t set,get"
```

```text
SET: 75244.55 requests per second, p50=0.319 msec
GET: 86058.52 requests per second, p50=0.239 msec
INCR: 81300.81 requests per second, p50=0.287 msec
LPUSH: 77459.34 requests per second, p50=0.287 msec
LPOP: 99403.58 requests per second, p50=0.223 msec

SET: 591716.00 requests per second, p50=1.007 msec
GET: 990099.00 requests per second, p50=0.415 msec
```

That is with AOF on (`everysec`), 50 clients and the benchmark running on the same 4 vCPUs as Redis. The benchmark writes keys such as `key:__rand_int__`, so run it on a scratch database or `FLUSHALL` afterwards, and run `BGREWRITEAOF` to shrink the append-only file (ours grew to 19 MB and went back to 616 bytes).

## 6. What survives a stop and resume

```bash
sbx exec $id "docker exec redis redis-cli SET before_stop \"\$(date -u +%T)\""   # OK
sbx stop $id --wait
sbx resume $id
sbx info $id --json | grep -o '"memoryRestored":[a-z]*'                       # "memoryRestored":true
sbx exec $id "docker exec redis redis-cli GET before_stop"                    # "10:29:33"
```

While the sandbox was stopped, the Insight URL returned `404`. After `sbx resume` it returned `200` with the old cookie, `DBSIZE` was unchanged, and the containers had kept running.

Resume restores memory in the normal case. When it boots from disk instead (for example after a resume onto a different CPU type), files are kept and processes are not. That is where the restart policy and AOF earn their place. To check that path without waiting for it, we restarted the Docker daemon:

```bash
sbx exec $id "systemctl is-enabled docker; sudo systemctl restart docker; sleep 5; \
  docker ps --format '{{.Names}} {{.Status}}'; docker exec redis redis-cli GET before_stop"
```

```text
enabled
redisinsight Up 5 seconds
redis Up 5 seconds
10:29:33
```

Docker starts at boot, `unless-stopped` brings both containers back, and Redis reloads its data, search index and vector set from the AOF.

## Size and cost

Idle, Redis used 6.5 MiB and Redis Insight 163 MiB, and the two images are 149 MB and 370 MB. A `small` sandbox is enough to try it. We used `default` ($0.036/hour while running) for the benchmark. A stopped sandbox isn't billed.

## Clean up

```bash
sbx delete $id --yes
```

## FAQ

### Is redis/redis-stack still the image to use?

Redis's docs say Redis 8 replaces Redis Stack, and their Docker page uses `redis:<version>`. JSON, search, time series, probabilistic types and vector sets come built in, and Redis Insight is a separate `redis/redisinsight` image.

### Should I set a Redis password?

Set one with `--requirepass` if anything other than you can reach the port. In this setup Redis is bound to `127.0.0.1` inside the VM, so only processes in the sandbox and your SSH tunnel can reach it. Don't publish 6379 on `0.0.0.0` without a password.

### Can I host Redis itself on an HTTPS URL?

No. `sbx host` serves HTTP and WebSockets through an HTTPS proxy, and Redis speaks its own TCP protocol. Reach Redis over an SSH tunnel from your laptop, as in step 4, and host only Redis Insight.

### Will my data survive an auto-stop?

Yes. An auto-stop is the same memory-preserving stop as `sbx stop`. If a resume boots from disk, Docker restarts the containers and Redis reloads from the AOF in the `redis-data` volume.

### Why is redis-cli slow from my laptop?

The SSH tunnel crosses the Sandboxer API, so each command is a full round trip over the internet (about 127 ms in our test). Pipelines and `--pipe` help. For real load, run the client in the sandbox.

## Related

- [Run MySQL or MariaDB in a sandbox](/guides/run-mysql-or-mariadb-in-a-sandbox)
- [Run Postgres with pgvector in a sandbox](/guides/run-postgres-with-pgvector-in-a-sandbox)
- [Give a sandbox port an HTTPS URL](/guides/give-a-sandbox-port-an-https-url)
- [SSH and file transfer](/docs/ssh)
