The documentation here is for an unreleased version of Recyclarr.
Visit the documentation site for the Current Version instead.Kubernetes (Helm)
Recyclarr has an official Helm chart that runs the Recyclarr server in Kubernetes. It is published to the GitHub Container Registry as an OCI chart:
oci://ghcr.io/recyclarr/charts/recyclarr
The chart version is the Recyclarr version: chart 9.0.0 deploys Recyclarr 9.0.0. A new chart
version comes out with each Recyclarr release, and fixes to the chart itself ship with the next
release. By default the chart uses the ghcr.io/recyclarr/recyclarr image tagged with that same
version.
Example
This example keeps the server's API key and the Sonarr and Radarr API keys in Secrets you create:
kubectl create secret generic recyclarr-api-key \
--from-literal=api-key="$(openssl rand -hex 32)"
kubectl create secret generic recyclarr-servarr-keys \
--from-literal=SONARR_API_KEY=your-sonarr-api-key \
--from-literal=RADARR_API_KEY=your-radarr-api-key
# values.yaml
apiKey:
existingSecret: recyclarr-api-key
configs:
files:
sonarr.yml: |
sonarr:
main:
base_url: http://sonarr:8989
api_key: !env_var SONARR_API_KEY
radarr.yml: |
radarr:
main:
base_url: http://radarr:7878
api_key: !env_var RADARR_API_KEY
settings:
content: |
server:
schedule:
cron: 0 4 * * *
env:
- name: TZ
value: America/Santiago
envFrom:
- secretRef:
name: recyclarr-servarr-keys
helm install recyclarr oci://ghcr.io/recyclarr/charts/recyclarr -f values.yaml
The server syncs on its built-in schedule. TZ sets the schedule's time zone (default
UTC). The pod becomes ready after the first TRaSH Guides download, which can take a few minutes.
API Key
The server does not start without an API key, so the chart requires one. Set exactly one
of these; helm install fails if you set neither or both:
apiKey.existingSecret: the name of a Secret you manage, for example one created by hand or by External Secrets Operator. The chart reads the key from the Secret'sapi-keyentry. SetapiKey.existingSecretKeyto use a different entry.apiKey.value: the key itself, at least 32 characters. The chart creates a Secret for it. This puts the key in your values file, so preferexistingSecretwhen the values file is in version control.
The chart mounts the key as a file and sets RECYCLARR_API_KEY_FILE to its path. The server reads
the file on every request, so you can rotate the key in the Secret without restarting the pod.
Configuration Files
The chart mounts your files read-only in the config directory. Each source can come from your values or from a ConfigMap you manage, but not both:
| Values | Mounted at |
|---|---|
configs.files or configs.existingConfigMap | /config/configs/ |
includes.files or includes.existingConfigMap | /config/includes/ |
settings.content or settings.existingConfigMap | /config/settings.yml |
configs.files and includes.files map each file name to its contents. File names in
configs.files must end in .yml or .yaml. settings.content holds the contents of
settings.yml. Without it, the server uses default settings. Write every file's contents as a
string (with |), as in the example. Helm then passes YAML tags such as !env_var
through unchanged.
In an existing ConfigMap, each key is a file name and its value is the file's contents. A settings
ConfigMap must have a settings.yml key. If you generate it with a Kustomize configMapGenerator,
set disableNameSuffixHash: true, because Kustomize does not rewrite names inside Helm values.
The server applies edits to its YAML configuration files without a restart (see
Configuration Changes), but reads settings.yml and environment variables
only when it starts. helm upgrade restarts the pod when files or the API key in your values
change. When you change a configs or includes ConfigMap you manage, Kubernetes updates the mounted
files after a short delay, and the server picks up the edit. After you change a settings ConfigMap
you manage, or a Secret the container reads through env or envFrom, restart the Deployment
yourself or use a tool such as Reloader.
Environment Variables
env and envFrom add environment variables to the container, usually Sonarr and Radarr API keys
that your configuration reads with !env_var.
The chart does not mount a secrets.yml file. Set each API key with api_key: !env_var ... from a
Secret as shown above. !secret references and the implicit
<instance>_api_key lookups from secrets.yml are not available with the chart.
Storage
The chart puts the state directory (sync state and job history) on a
PersistentVolumeClaim and the data directory (downloaded guides and log files) in an
emptyDir volume, which Recyclarr rebuilds when the pod starts again.
| Value | Default | Description |
|---|---|---|
persistence.enabled | true | Store state on a PersistentVolumeClaim |
persistence.existingClaim | none | Use this claim instead of creating one |
persistence.storageClass | none | StorageClass for the claim; none uses the cluster default |
persistence.accessMode | ReadWriteOnce | Access mode for the claim |
persistence.size | 1Gi | Size of the claim |
Uninstalling the chart keeps the claim, so a later install with the same release name picks up the same state. Delete the claim yourself when you no longer need it.
With persistence.enabled: false, state lives in an emptyDir and is lost whenever the pod is
recreated. Recyclarr then no longer knows which Sonarr and Radarr resources it created (see
State Directory).
Log files in the data directory are lost when the pod is recreated. Kubernetes collects the server's
console output, so you may want to turn off log files with server.logging.files
in settings.content.
Running CLI Commands
The recyclarr CLI in the pod sends commands to the server in the same pod with the same API key,
so it needs no setup. helm install prints the exact command for your release:
kubectl exec deploy/recyclarr -- recyclarr sync --preview
Network and Monitoring
The chart creates a Service with two ports:
| Port | Name | Serves |
|---|---|---|
7982 | http | The HTTP API |
7983 | management | Health probes (/livez, /readyz) and /metrics |
The chart creates no Ingress or HTTPRoute. The API is meant for clients inside the cluster, such as
the CLI in the pod or your own scripts. Change the API port on the Service with service.port and
the Service type with service.type. See Network Security before you expose the
API outside the cluster.
The pod has startup, liveness, and readiness probes on the management port. To have the Prometheus
Operator scrape metrics, set serviceMonitor.enabled: true. Set
serviceMonitor.interval to change the scrape interval and serviceMonitor.labels to add labels
your Prometheus selects on.
To export telemetry to an OpenTelemetry Collector, set the OpenTelemetry variables in env:
env:
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: http://otel-collector.monitoring:4317
- name: OTEL_RESOURCE_ATTRIBUTES
value: deployment.environment=home
Other Values
The chart runs one replica with the Recreate update strategy, because only one server can use the
state volume at a time. The container runs as UID and GID 1000, as a non-root user, with a
read-only root filesystem.
Other values follow common Helm chart conventions: image, imagePullSecrets, nameOverride,
fullnameOverride, serviceAccount, podAnnotations, podLabels, podSecurityContext,
securityContext, resources, nodeSelector, tolerations, and affinity. To see every value
and its default, run:
helm show values oci://ghcr.io/recyclarr/charts/recyclarr
Without the Chart
If you write your own manifests, these are the parts the chart handles for you:
- Image
ghcr.io/recyclarr/recyclarr:9. It runs as UID and GID1000and works with a read-only root filesystem when/tmpis a writable volume. - Container ports
7982(API) and7983(management). See Monitoring. startupProbeandlivenessProbeon/livez,readinessProbeon/readyz, all on the management port. The server opens no port until the first guide download finishes, so give the startup probe several minutes.- The API key in a Secret volume, with
RECYCLARR_API_KEY_FILEset to the file path. Without asubPathmount, Kubernetes updates the file when the Secret changes, and the server uses the new key without a restart. - Config files mounted read-only under
/config, a PersistentVolumeClaim for the state directory (RECYCLARR_STATE_DIR), and anemptyDirfor the data directory (RECYCLARR_DATA_DIR). - One replica with the
Recreatestrategy.
Dev Chart
Each dev image has a matching dev chart. These are extremely unstable and not for
production Sonarr or Radarr instances. The dev chart for a branch has version 0.0.0-<branch>, with
the branch name changed the same way as the image tag, and it defaults to that branch's dev image:
helm install recyclarr oci://ghcr.io/recyclarr/charts-dev/recyclarr \
--version 0.0.0-master -f values.yaml
The image tag moves with each build, but the chart's default image.pullPolicy is IfNotPresent,
so a node keeps using the image it already pulled. Set image.pullPolicy: Always and restart the
pod to get the latest build. Dev chart versions follow the same retention as dev
images.