> ## Documentation Index
> Fetch the complete documentation index at: https://docs.controlplane.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Redis

> Deploy Redis on Control Plane using the Template Catalog. Covers configuration, volumes, scaling, and master-replica clustering with Sentinel automatic failover.

## Overview

Redis is a high-performance in-memory data store. This template deploys a Redis master-replica cluster with Redis Sentinel for automatic failover and leader election.

<Note>
  This template does not create a GVC. You must deploy it into an existing GVC.
</Note>

### What Gets Created

* **Stateful Redis Workload** — (`RELEASE_NAME-redis`): a master-replica cluster. Replica 0 starts as the primary; all others replicate from it.
* **Stateful Sentinel Workload** — (`RELEASE_NAME-sentinel`): monitors the Redis cluster and orchestrates automatic failover when the primary becomes unavailable.
* **Secret** — An opaque secret containing the Redis server configuration (`redis.conf`), mounted into each Redis container.
* **Secret** — An opaque secret containing the Sentinel configuration (`sentinel.conf`), mounted into each Sentinel container.
* **Secret** *(optional)* — A dictionary secret holding the Redis auth password, created when `redis.auth.password.enabled` is true.
* **Secret** *(optional)* — A dictionary secret holding the Sentinel auth password, created when `sentinel.auth.password.enabled` is true.
* **Identity & Policy** — Separate identities and policies for the Redis and Sentinel workloads, each with `reveal` access to their respective secrets, and cloud storage access when backup is enabled.
* **Volume Set** *(optional)* — Persistent storage for Redis data, created when `redis.persistence.enabled` is true.
* **Volume Set** *(optional)* — Persistent storage for Sentinel state, created when `sentinel.persistence.enabled` is true.
* **Domain** *(optional)* — External domain resources for Redis and/or Sentinel when `publicAccess.enabled` is true.
* **Backup Cron Workload** *(optional)* — A scheduled backup job that writes Redis snapshots to AWS S3 or GCS.

## Installation

This template has no external prerequisites unless backup or public access is enabled. To install, follow the instructions for your preferred method:

<CardGroup cols={2}>
  <Card title="UI" href="/template-catalog/install-manage/ui" icon="laptop">
    Browse, install, and manage templates visually
  </Card>

  <Card title="CLI" href="/template-catalog/install-manage/cli" icon="terminal">
    Manage templates from your terminal
  </Card>

  <Card title="Terraform" href="/template-catalog/install-manage/terraform" icon={<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M77.941 44.5v36.836L46.324 62.918V26.082zm0 0" fill="#5c4ee5"/><path d="M81.41 81.336l31.633-18.418V26.082L81.41 44.5zm0 0" fill="#4040b2"/><path d="M11.242 42.36L42.86 60.776V23.941L11.242 5.523zm0 0M77.941 85.375L46.324 66.957v36.82l31.617 18.418zm0 0" fill="#5c4ee5"/></g></svg>}>
    Declare templates in your Terraform configurations
  </Card>

  <Card
    title="Pulumi"
    href="/template-catalog/install-manage/pulumi"
    icon={<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" id="Pulumi-Icon--Streamline-Svg-Logos" height="24" width="24">
    <desc>
        Pulumi Icon Streamline Icon: https://streamlinehq.com
    </desc>
    <path fill="#f26e7e" d="M4.683025 13.3318c0.869125 -0.5018 0.870575 -2.1264 0.003225 -3.62865s-2.27504 -2.313275 -3.1441725 -1.811475C0.672945 8.3935 0.6715 10.0181 1.53885 11.52035c0.86735 1.502275 2.27505 2.313275 3.144175 1.81145Zm0.0052 3.2167c0.86735 1.502275 0.865925 3.126875 -0.003225 3.628675 -0.86915 0.5018 -2.2768275 -0.309225 -3.144175 -1.81145 -0.8673525 -1.50225 -0.8659075 -3.126875 0.003225 -3.628675 0.8691325 -0.5018 2.276825 0.309225 3.144175 1.81145Zm5.922875 3.4243c0.86735 1.50225 0.8659 3.126775 -0.003225 3.62875 -0.869125 0.501775 -2.27685 -0.309325 -3.1442 -1.81155 -0.867325 -1.50225 -0.865875 -3.12685 0.00325 -3.628675 0.869125 -0.5018 2.276825 0.309225 3.144175 1.811475Zm-0.001925 -6.845275c0.86735 1.50225 0.8659 3.12685 -0.003225 3.628675 -0.869125 0.5018 -2.276825 -0.309225 -3.144175 -1.811475 -0.86735 -1.50225 -0.8659 -3.12685 0.003225 -3.62865 0.869125 -0.501825 2.276825 0.3092 3.144175 1.81145Z" stroke-width="0.25"></path>
    <path fill="#8a3391" d="M22.45775 11.524125c0.86725 -1.502225 0.865925 -3.12685 -0.003225 -3.62865 -0.869125 -0.501825 -2.276825 0.3092 -3.144175 1.811475 -0.86735 1.50225 -0.8659 3.126825 0.003225 3.62865 0.869125 0.501825 2.276825 -0.3092 3.144175 -1.811475Zm0.000175 3.2151c0.869075 0.5018 0.870625 2.1264 0.003225 3.62865 -0.86735 1.50225 -2.27505 2.313275 -3.144175 1.81145 -0.869125 -0.5018 -0.870575 -2.126425 -0.003225 -3.62865 0.86735 -1.50225 2.27505 -2.313275 3.144175 -1.81145ZM16.536225 18.157875c0.86915 0.501825 0.8706 2.126425 0.00325 3.628675 -0.86735 1.502125 -2.275075 2.313225 -3.1442 1.81145 -0.869125 -0.50175 -0.870575 -2.126425 -0.003225 -3.62865 0.867375 -1.502275 2.27505 -2.3133 3.144175 -1.811475Zm-0.003325 -6.843775c0.869125 0.5018 0.870575 2.126425 0.003225 3.628675s-2.27505 2.313275 -3.1442 1.811475c-0.869125 -0.501825 -0.870575 -2.126425 -0.003225 -3.628675 0.86735 -1.502275 2.27505 -2.313275 3.1442 -1.811475Z" stroke-width="0.25"></path>
    <path fill="#f7bf2a" d="M15.138225 2.06721c0 1.003615 -1.40625 1.817215 -3.14095 1.817215 -1.7347 0 -3.14095 -0.8136 -3.14095 -1.817215C8.856325 1.06359 10.262575 0.25 11.997275 0.25c1.7347 0 3.14095 0.81359 3.14095 1.81721ZM9.2166 5.482375c0 1.003625 -1.40625 1.8172 -3.14095 1.8172 -1.7347 0 -3.14095 -0.813575 -3.14095 -1.8172s1.40625 -1.817225 3.14095 -1.817225c1.7347 0 3.14095 0.8136 3.14095 1.817225Zm8.71005 1.8172c1.7347 0 3.14095 -0.813575 3.14095 -1.8172s-1.40625 -1.817225 -3.14095 -1.817225c-1.7347 0 -3.14095 0.8136 -3.14095 1.817225s1.40625 1.8172 3.14095 1.8172Zm-2.788425 1.605625c0 1.003625 -1.40625 1.8172 -3.14095 1.8172 -1.7347 0 -3.14095 -0.813575 -3.14095 -1.8172 0 -1.0036 1.40625 -1.8172 3.14095 -1.8172 1.7347 0 3.14095 0.8136 3.14095 1.8172Z" stroke-width="0.25"></path>
    </svg>}
  >
    Declare templates in your Pulumi programs
  </Card>
</CardGroup>

## Configuration

The default `values.yaml` for this template:

```yaml theme={null}
redis:
  image: redis:7.4
  resources:
    cpu: 200m
    memory: 256Mi
    minCpu: 80m
    minMemory: 128Mi
  replicas: 3
  timeoutSeconds: 15
  multiZone: false
  replicaDirect: false
  auth:
    fromSecret:
      enabled: false
      name: example-redis-auth-password
      passwordKey: password
    password:
      enabled: false
      value: your-password
  serverCommand: redis-server
  # extraArgs: "--maxclients 20000 --maxmemory 200mb --maxmemory-policy allkeys-lru"
  publicAccess:
    enabled: false
    address: redis-test.example-cpln.com
  firewall:
    internal_inboundAllowType: same-gvc # Options: same-org / same-gvc / workload-list
    # external_inboundAllowCIDR: 0.0.0.0/0
    # inboundAllowWorkload:
    #   - //gvc/GVC_NAME/workload/WORKLOAD_NAME
    # external_outboundAllowCIDR: 0.0.0.0/0
  env: []
  tags: {}
  requestRetryPolicy: {}
  replication:
    backlogSize: 1gb
    timeout: 300
    slaveOutputBufferLimit: "2gb 512mb 300"
  probes:
    readiness:
      failureThreshold: 10
      initialDelaySeconds: 10
      periodSeconds: 5
      timeoutSeconds: 4
    liveness:
      failureThreshold: 5
      initialDelaySeconds: 30
      periodSeconds: 10
      timeoutSeconds: 5
  exporter:
    enabled: false  # adds a redis_exporter sidecar that exposes metrics at :9121/metrics
    image: oliver006/redis_exporter:v1.67.0-alpine
    resources:
      cpu: 50m
      memory: 64Mi
      minCpu: 25m
      minMemory: 32Mi
    dropMetrics: []  # e.g., ["redis_command_.*", "redis_keyspace_.*"]
  dataDir: /data
  persistence:
    enabled: false
    volumes:
      data:
        initialCapacity: 10 # In GiB
        performanceClass: general-purpose-ssd # general-purpose-ssd / high-throughput-ssd (Min 1000 GiB)
        fileSystemType: ext4 # ext4 / xfs
        snapshots:
          retentionDuration: 7d
          schedule: "0 0 * * *" # UTC
        autoscaling:
          maxCapacity: 100 # In GiB
          minFreePercentage: 20
          scalingFactor: 1.2
        # customEncryption:
        #   enabled: true
        #   region: aws-us-east-1
        #   keyId: arn:aws:kms:us-east-1:1234567890:key/YOUR_KEY_ID

sentinel:
  image: redis:7.4
  resources:
    cpu: 200m
    memory: 256Mi
    minCpu: 80m
    minMemory: 128Mi
  replicas: 3
  timeoutSeconds: 10
  multiZone: false
  replicaDirect: false
  quorumAutoCalculation: true # Quorum = (replicas / 2) + 1
  quorumOverride: null        # Only used if quorumAutoCalculation is false
  auth:
    fromSecret:
      enabled: false
      name: example-redis-auth-password
      passwordKey: password
    password:
      enabled: false
      value: your-password
  publicAccess:
    enabled: false
    address: redis-sentinel-test.example-cpln.com
  firewall:
    internal_inboundAllowType: same-gvc # Options: same-org / same-gvc
    # external_inboundAllowCIDR: 0.0.0.0/0
    # inboundAllowWorkload:
    #   - //gvc/GVC_NAME/workload/WORKLOAD_NAME
    # external_outboundAllowCIDR: 0.0.0.0/0
  env: []
  tags: {}
  requestRetryPolicy: {}
  persistence:
    enabled: false
    volumes:
      data:
        initialCapacity: 10 # In GiB
        performanceClass: general-purpose-ssd
        fileSystemType: ext4
        snapshots:
          retentionDuration: 7d
          schedule: "0 0 * * *"
        autoscaling:
          maxCapacity: 50 # In GiB
          minFreePercentage: 20
          scalingFactor: 1.2
        # customEncryption:
        #   enabled: true
        #   region: aws-us-east-1
        #   keyId: arn:aws:kms:us-east-1:1234567890:key/YOUR_KEY_ID

backup:
  enabled: false
  image: controlplanecorporation/redis-backup:1.0 # compatible with all Redis versions
  schedule: "0 2 * * *"   # daily at 2am UTC

  resources:
    cpu: 100m
    memory: 128Mi

  provider: aws # Options: aws or gcp

  aws:
    bucket: my-backup-bucket
    region: us-east-1
    cloudAccountName: my-backup-cloudaccount
    policyName: my-backup-policy
    prefix: redis/backups

  gcp:
    bucket: my-backup-bucket
    cloudAccountName: my-backup-cloudaccount
    prefix: redis/backups

grafana:
  dashboard:
    enabled: false          # K8s clusters only — set to true to provision via Grafana Operator
  folder: Redis             # Grafana folder the dashboard is placed in
  datasource: metrics       # name of the Prometheus datasource in your Grafana instance
  instanceSelector:
    matchLabels:
      dashboards: grafana   # must match the label on your Grafana CR
```

### Authentication

Authentication is disabled by default. Both the Redis workload and the Sentinel workload support independent auth configuration. Only one method can be enabled at a time per workload.

**Option 1 — Inline password** (creates a secret automatically):

```yaml theme={null}
redis:
  auth:
    password:
      enabled: true
      value: your-password
```

**Option 2 — Reference an existing secret**:

```yaml theme={null}
redis:
  auth:
    fromSecret:
      enabled: true
      name: my-redis-secret   # Name of an existing Control Plane secret
      passwordKey: password   # Key within the secret containing the password
```

Sentinel can be configured with a separate password for Sentinel-to-Sentinel communication using the same options under `sentinel.auth`.

### Redis Cluster

* `redis.replicas` — Number of Redis replicas. Defaults to `3`. Replica 0 is always the initial primary.
* `redis.resources.cpu` / `redis.resources.memory` — Maximum CPU and memory per replica.
* `redis.resources.minCpu` / `redis.resources.minMemory` — Minimum CPU and memory guaranteed per replica.
* `redis.multiZone` — Spread replicas across availability zones within the location.
* `redis.extraArgs` — Additional Redis server arguments (e.g. `--maxmemory 200mb --maxmemory-policy allkeys-lru`).

### Sentinel

Sentinel monitors the Redis cluster and automatically promotes a replica when the primary fails.

* `sentinel.replicas` — Number of Sentinel replicas. A minimum of 3 is required for a majority quorum.
* `sentinel.quorumAutoCalculation` — When `true`, the quorum is calculated automatically as `(replicas / 2) + 1`. Set to `false` to use `sentinel.quorumOverride`.
* `sentinel.quorumOverride` — Manual quorum value, used only when `quorumAutoCalculation` is `false`.
* `sentinel.resources.cpu` / `sentinel.resources.memory` — Maximum CPU and memory per Sentinel replica.
* `sentinel.resources.minCpu` / `sentinel.resources.minMemory` — Minimum CPU and memory guaranteed per Sentinel replica.
* `sentinel.multiZone` — Spread Sentinel replicas across availability zones.

### Replication Tuning

The `redis.replication` block controls low-level replication behavior. The defaults are sized for production workloads and typically do not need adjustment.

* `replication.backlogSize` — Replication backlog size. The default `1gb` covers \~5 minutes of disconnect at \~3 MB/s of writes. The Redis default of `1mb` will trigger a full RDB resync on any brief disconnect.
* `replication.timeout` — Timeout in seconds for full-resync transfers. The default `300s` covers datasets up to \~30 GB. The Redis default of `60s` is too low for large datasets.
* `replication.slaveOutputBufferLimit` — Format: `<hard> <soft> <seconds>`. The default `"2gb 512mb 300"` sustains full resyncs of large datasets at high write rates. The Redis default `"256mb 64mb 60"` can cause the master to kill a replica mid-stream.

### Health Checks

Probe settings for the Redis workload are configurable under `redis.probes`. This is most useful when persistence is enabled and large datasets require additional time to load before the replica is ready.

The startup probe window is derived from the readiness probe settings:

```
startup window = initialDelaySeconds + (30 × periodSeconds)
```

The default (`10 + 30×5 = 160s`) is sufficient for small datasets. If AOF load takes longer, increase `periodSeconds`:

```yaml theme={null}
redis:
  probes:
    readiness:
      initialDelaySeconds: 35   # clears the AOF load window
      periodSeconds: 20          # startup window = 35 + (30×20) = 635s
```

| Field                           | Default | Description                                                            |
| ------------------------------- | ------- | ---------------------------------------------------------------------- |
| `readiness.initialDelaySeconds` | `10`    | Seconds to wait before first readiness check                           |
| `readiness.periodSeconds`       | `5`     | How often to run the readiness check; also controls the startup window |
| `readiness.failureThreshold`    | `10`    | Number of failures before the replica is marked not ready              |
| `readiness.timeoutSeconds`      | `4`     | Timeout per probe attempt                                              |
| `liveness.initialDelaySeconds`  | `30`    | Seconds before the first liveness check                                |
| `liveness.periodSeconds`        | `10`    | How often to run the liveness check                                    |
| `liveness.failureThreshold`     | `5`     | Number of failures before the container is restarted                   |
| `liveness.timeoutSeconds`       | `5`     | Timeout per probe attempt                                              |

### Metrics

A `redis_exporter` sidecar can be enabled to expose Prometheus metrics. When enabled, Control Plane scrapes `:9121/metrics` automatically every 30 seconds and makes the metrics available in the console.

* `redis.exporter.enabled` — Set to `true` to add the exporter sidecar to each Redis replica.
* `redis.exporter.image` — Exporter image (default: `oliver006/redis_exporter:v1.67.0-alpine`).
* `redis.exporter.resources` — CPU and memory limits/requests for the sidecar container.
* `redis.exporter.dropMetrics` — List of regex patterns matched against metric names. Use to filter high-cardinality series before they are stored.

```yaml theme={null}
redis:
  exporter:
    enabled: true
    dropMetrics:
      - "redis_commands_latencies_usec_bucket"
      - "redis_latency_percentiles_usec"
```

### Grafana Dashboard

A pre-built Grafana dashboard can be provisioned automatically via the [Grafana Operator](https://grafana.github.io/grafana-operator/). This is opt-in and intended for Kubernetes clusters running the Grafana Operator — on Control Plane's managed platform where no operator is present, leave this disabled.

<Note>
  Enabling the dashboard requires `redis.exporter.enabled: true` for the Redis-specific panels. CPU and memory panels are always available.
</Note>

**Included panels:**

| Panel             | Requires exporter |
| ----------------- | ----------------- |
| CPU Usage         | No                |
| Memory Usage      | No                |
| Connected Clients | Yes               |
| Redis Memory      | Yes               |
| Commands/sec      | Yes               |
| Cache Hit Rate    | Yes               |

The dashboard includes template variables for datasource, GVC, workload, and replica so you can filter by deployment without editing the dashboard.

**Prerequisites:**

1. The [Grafana Operator](https://grafana.github.io/grafana-operator/) must be installed in your cluster with a Kubernetes secret containing your Grafana service account token:

   ```bash theme={null}
   kubectl create secret generic grafana-admin-credentials \
     --from-literal=GF_SECURITY_ADMIN_USER=admin \
     --from-literal=GF_SECURITY_ADMIN_PASSWORD=<grafana-api-token> \
     -n grafana-operator
   ```

2. A `Grafana` CR with a label matching `grafana.instanceSelector.matchLabels`:

   ```yaml theme={null}
   apiVersion: grafana.integreatly.org/v1beta1
   kind: Grafana
   metadata:
     name: grafana
     labels:
       dashboards: grafana
   spec:
     external:
       url: https://your-org.grafana.cpln.io
       adminPassword:
         name: grafana-admin-credentials
         key: GF_SECURITY_ADMIN_PASSWORD
   ```

**Configuration:**

* `grafana.dashboard.enabled` — Set to `true` to provision the `GrafanaDashboard` CRD.
* `grafana.folder` — Grafana folder the dashboard appears in (default: `Redis`).
* `grafana.datasource` — Name of the Prometheus datasource configured in your Grafana instance (default: `metrics`).
* `grafana.instanceSelector.matchLabels` — Label selector that must match the label on your `Grafana` CR.

### Storage

Persistence is disabled by default. When enabled, a Volume Set is created to store data across restarts.

**Redis persistence:**

* `redis.persistence.enabled` — Enable persistent storage for Redis data.
* `redis.persistence.volumes.data.initialCapacity` — Initial volume size in GiB. Minimum 1000 GiB for `high-throughput-ssd`.
* `redis.persistence.volumes.data.performanceClass` — `general-purpose-ssd` or `high-throughput-ssd`.
* `redis.persistence.volumes.data.fileSystemType` — `ext4` or `xfs`.
* `redis.persistence.volumes.data.snapshots.retentionDuration` — How long to retain volume snapshots.
* `redis.persistence.volumes.data.snapshots.schedule` — Cron expression for snapshot frequency.
* `redis.persistence.volumes.data.autoscaling.maxCapacity` — Maximum volume size in GiB.
* `redis.persistence.volumes.data.autoscaling.minFreePercentage` — Trigger scaling when free space drops below this percentage.
* `redis.persistence.volumes.data.autoscaling.scalingFactor` — Multiply current capacity by this factor when scaling up.

**Sentinel persistence** uses the same options under `sentinel.persistence`.

### Firewall

Both Redis and Sentinel firewall settings are configured independently.

* `redis.firewall.internal_inboundAllowType` / `sentinel.firewall.internal_inboundAllowType`:

| Value           | Description                                                   |
| --------------- | ------------------------------------------------------------- |
| `same-gvc`      | Allow access from all workloads in the same GVC (recommended) |
| `same-org`      | Allow access from all workloads in the same organization      |
| `workload-list` | Allow access only from specific workloads                     |

* `redis.firewall.inboundAllowWorkload` — List of specific workload links when using `workload-list`.
* `redis.firewall.external_inboundAllowCIDR` — Comma-separated CIDR ranges for external inbound access.
* `redis.firewall.external_outboundAllowCIDR` — Comma-separated CIDR ranges for external outbound access.

### Public Access

Redis and Sentinel can be exposed over the internet via TCP using Control Plane's domain resource with per-replica port routing.

#### Prerequisites

1. **Enable Dedicated Load Balancer on your GVC** — This is required for arbitrary TCP port routing. Navigate to your GVC settings in the Control Plane console and enable the Dedicated Load Balancer option.

2. **Add DNS records before deploying** — Control Plane verifies domain ownership when the domain resource is first created. If the records are not in place, the deploy will fail with an `Unable to apply domain` error. Add the following records in your DNS provider for each address you configure, and **disable any proxy** (TCP must pass through directly):

| Type  | Name                | Value                                 |
| ----- | ------------------- | ------------------------------------- |
| TXT   | `_cpln-<subdomain>` | Your Control Plane org name or org ID |
| CNAME | `<subdomain>`       | `<gvc-alias>.cpln.app`                |

Your GVC alias is visible under GVC settings in the Control Plane console.

#### Configuration

Enable public access for Redis and/or Sentinel, set the subdomain address, and open the external firewall:

```yaml theme={null}
redis:
  publicAccess:
    enabled: true
    address: redis.your-domain.com
  firewall:
    internal_inboundAllowType: same-gvc
    external_inboundAllowCIDR: "0.0.0.0/0"  # or restrict to specific CIDRs

sentinel:
  publicAccess:
    enabled: true
    address: redis-sentinel.your-domain.com
  firewall:
    internal_inboundAllowType: same-gvc
    external_inboundAllowCIDR: "0.0.0.0/0"
```

<Note>
  `external_inboundAllowCIDR` must be set when public access is enabled — without it, inbound traffic from the internet will be blocked even though the domain is configured.
</Note>

#### Port Mapping

Each replica is assigned its own external port. Port numbers increment per replica starting at:

* **Redis**: `6380`, `6381`, `6382`, ... (replica 0, 1, 2, ...)
* **Sentinel**: `26380`, `26381`, `26382`, ... (replica 0, 1, 2, ...)

#### Connecting Externally

```bash theme={null}
# Redis replica 0 (append -a <password> if auth is enabled)
redis-cli -h redis.your-domain.com -p 6380 ping

# Redis replica 1
redis-cli -h redis.your-domain.com -p 6381 ping

# Sentinel replica 0
redis-cli -h redis-sentinel.your-domain.com -p 26380 ping
```

After deploying, verify the domain is resolving correctly:

```bash theme={null}
dig redis.your-domain.com CNAME   # should return <gvc-alias>.cpln.app
dig <gvc-alias>.cpln.app          # should return an IP address
```

### Connecting to Redis

Connect to Redis internally from within the same GVC:

```text theme={null}
RELEASE_NAME-redis.GVC_NAME.cpln.local:6379
```

For Sentinel-aware clients, connect through Sentinel to always reach the current primary:

```text theme={null}
RELEASE_NAME-sentinel.GVC_NAME.cpln.local:26379
```

The Sentinel master name is `mymaster`.

### Ports

| Workload          | Port                  | Description                                        |
| ----------------- | --------------------- | -------------------------------------------------- |
| Redis             | `6379`                | Internal Redis data port                           |
| Sentinel          | `26379`               | Internal Sentinel discovery port                   |
| Redis (public)    | `6380`, `6381`, ...   | One port per replica when public access is enabled |
| Sentinel (public) | `26380`, `26381`, ... | One port per replica when public access is enabled |

## Backup

Backup is disabled by default. When enabled, a cron workload runs on the configured schedule and uploads a Redis snapshot to AWS S3 or GCS. The backup image is compatible with all Redis versions.

* `backup.enabled` — Enable scheduled backups.
* `backup.schedule` — Cron expression for backup frequency (default: daily at 2am UTC).
* `backup.provider` — `aws` or `gcp`.
* `backup.resources.cpu` / `backup.resources.memory` — Resources for the backup cron container.

### AWS S3

Before enabling backup with `provider: aws`, complete the following in your AWS account:

1. Create an S3 bucket. Set `backup.aws.bucket` to its name and `backup.aws.region` to its region.
2. If you do not have a Cloud Account set up, refer to the docs to [Create a Cloud Account](/guides/create-cloud-account). Set `backup.aws.cloudAccountName` to its name.
3. Create an IAM policy with the following JSON, replacing `YOUR_BUCKET_NAME`:

```json theme={null}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject",
                "s3:ListBucket",
                "s3:GetObjectVersion",
                "s3:DeleteObjectVersion"
            ],
            "Resource": [
                "arn:aws:s3:::YOUR_BUCKET_NAME",
                "arn:aws:s3:::YOUR_BUCKET_NAME/*"
            ]
        }
    ]
}
```

4. Set `backup.aws.policyName` to the name of the policy created in step 3.
5. Set `backup.aws.prefix` to the folder path where backups will be stored.

### GCS

Before enabling backup with `provider: gcp`, complete the following in your GCP account:

1. Create a GCS bucket. Set `backup.gcp.bucket` to its name.
2. If you do not have a Cloud Account set up, refer to the docs to [Create a Cloud Account](/guides/create-cloud-account). Set `backup.gcp.cloudAccountName` to its name.
3. Add the **Storage Admin** role to the GCP service account associated with the Cloud Account.
4. Set `backup.gcp.prefix` to the folder path where backups will be stored.

## Restoring a Backup

Download the `.rdb` backup file from your bucket and restore it into a running Redis instance. For GCS, replace `aws s3 cp s3://...` with `gsutil cp gs://...`.

```sh theme={null}
aws s3 cp s3://BUCKET_NAME/PREFIX/BACKUP_FILE.rdb /tmp/dump.rdb
redis-cli \
  -h RELEASE_NAME-redis.GVC_NAME.cpln.local \
  -p 6379 \
  --rdb /tmp/dump.rdb
```

## External References

<CardGroup cols={2}>
  <Card title="Redis Documentation" icon="book" href="https://redis.io/docs/">
    Official Redis documentation
  </Card>

  <Card title="Redis Sentinel Documentation" icon="book" href="https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel/">
    Redis Sentinel setup and client configuration
  </Card>

  <Card title="Backup Image Source" icon="github" href="https://github.com/controlplane-com/backup-images/tree/main/redis-backup">
    Source code for the Redis backup container image
  </Card>

  <Card title="Redis Template" icon="github" href="https://github.com/controlplane-com/templates/tree/main/redis">
    View the source files, default values, and chart definition
  </Card>
</CardGroup>
