A Kubernetes operator for Sonarr written in Rust using kube-rs.
This operator allows you to manage Sonarr resources declaratively through Kubernetes Custom Resources, enabling GitOps workflows for TV series management.
- Declarative Configuration: Define Sonarr resources as Kubernetes manifests
- GitOps Ready: Manage Sonarr configuration through version control
- Multi-Instance Support: Manage multiple Sonarr instances from a single operator
- Automatic Synchronization: Resources are continuously reconciled with Sonarr
- Finalizers: Clean up resources in Sonarr when Kubernetes resources are deleted
- 19 CRDs: Comprehensive coverage of Sonarr configuration options
The operator manages 19 CRDs in the devopsarr.io/v1alpha1 API group:
- Sonarr - The Sonarr server instance configuration
- SonarrSeries - TV series management
- SonarrQualityProfile - Quality profiles for downloads
- SonarrLanguageProfile - Language preferences
- SonarrDelayProfile - Delay settings for releases
- SonarrDownloadClient - Download clients (qBittorrent, SABnzbd, etc.)
- SonarrIndexer - Indexers for searching torrents/usenet
- SonarrNotification - Notifications (Discord, Telegram, etc.)
- SonarrImportList - Import lists for automatic series discovery
- SonarrTag - Tags for organizing series
- SonarrAutoTag - Automatic tagging rules
- SonarrRootFolder - Root folders for media storage
- SonarrQualityDefinition - Quality definitions
- SonarrCustomFormat - Custom format specifications
- SonarrMetadata - Metadata providers
- SonarrMediaManagementConfig - File management settings
- SonarrNamingConfig - Episode/series naming patterns
- SonarrIndexerConfig - Global indexer settings
- SonarrDownloadClientConfig - Global download client settings
For detailed API specifications, see the CRD Reference.
- Kubernetes cluster (1.28+)
- Helm 3.8+ (for OCI registry support)
- k3d for local development (optional)
Install the operator and its CRDs from the OCI chart on GHCR:
helm install sonarr-operator \
oci://ghcr.io/devopsarr/charts/sonarr-operator \
--namespace sonarr-operator-system \
--create-namespaceThe chart installs the operator Deployment, RBAC, and all 19 CRDs. CRDs are annotated helm.sh/resource-policy: keep, so they (and any Sonarr resources) survive a helm uninstall.
To install a specific version, pass --version <X.Y.Z>. To skip CRD installation (when managing them out-of-band), pass --set crds.install=false. To allow helm uninstall to remove CRDs as well, pass --set crds.keep=false. See the chart README for the full values reference.
Render the chart locally or use the per-release CRD asset:
# Option A: render from chart source
helm template sonarr-operator charts/sonarr-operator \
--namespace sonarr-operator-system | kubectl apply -f -
# Option B: download CRDs from a release and apply the static deploy/ manifests
kubectl apply -f https://github.com/devopsarr/k8s-operator-sonarr/releases/latest/download/crds.yaml
kubectl apply -f deploy/namespace.yaml
kubectl apply -f deploy/rbac.yaml
kubectl apply -f deploy/deployment.yamlA minimal example lives at deploy/examples/sonarr-minimal.yaml.
# Optional: pre-create an API key Secret (omit to have the operator generate one)
kubectl create secret generic sonarr-api-key \
--from-literal=api-key="$(openssl rand -hex 16)"
kubectl apply -f deploy/examples/sonarr-minimal.yaml
kubectl wait sonarr/sonarr --for=condition=Ready --timeout=5mapiVersion: devopsarr.io/v1alpha1
kind: SonarrTag
metadata:
name: anime
spec:
sonarrInstanceRef:
name: sonarr
label: "anime"
---
apiVersion: devopsarr.io/v1alpha1
kind: SonarrRootFolder
metadata:
name: tv-shows
spec:
sonarrInstanceRef:
name: my-sonarr
path: "/media/tv"make build # Release binary
make build-debug # Debug binary
make crds # Generate CRD manifests
make docs # Generate CRD documentationmake lint # Format check + clippy
make test # Unit tests
make integration-test # Integration tests (requires cluster with CRDs)The local E2E workflow uses k3d to create a cluster with Sonarr:
# Terminal 1: Create cluster + deploy Sonarr
make e2e-up
# Terminal 2: Run the operator locally
make run-debug
# Terminal 3: Run E2E tests
make e2e
# Cleanup
make e2e-downSee docs/TESTING.md for more details.
make deploy # Build image, import into k3d, deploy operator
make undeploy # Remove operator from clusterThe operator implements the Kubernetes Operator pattern to declaratively manage Sonarr configuration. It runs as a Deployment in the cluster and watches 19 CRDs in the devopsarr.io/v1alpha1 API group.
Kubernetes Cluster
┌─────────────────────────────────────────────────────────────┐
│ │
│ ┌──────────────┐ watches ┌───────────────────────────┐ │
│ │ Sonarr │◄───────────│ Sonarr Operator │ │
│ │ CRDs (19) │ │ (Rust / kube-rs) │ │
│ │ │ │ │ │
│ │ devopsarr.io │ status │ ┌───────────────────────┐ │ │
│ │ /v1alpha1 │◄───────────│ │ 19 Controllers │ │ │
│ └──────────────┘ updates │ │ (one per CRD type) │ │ │
│ │ └───────────┬───────────┘ │ │
│ ┌──────────────┐ └─────────────┼─────────────┘ │
│ │ K8s Secrets │ │ │
│ │ (API keys) │──────────────────────────┤ │
│ └──────────────┘ credentials │ │
│ │ HTTP REST API │
│ │ (v3/v4) │
│ ▼ │
│ ┌───────────────────────────┐ │
│ │ Sonarr Instance(s) │ │
│ │ (Pods / Services) │ │
│ └───────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
All sub-resource CRDs reference a parent Sonarr instance via sonarrInstanceRef:
Sonarr (instance connection: URL + API key)
├── Content: SonarrSeries
├── Profiles: SonarrQualityProfile, SonarrLanguageProfile, SonarrDelayProfile
├── Integrations: SonarrDownloadClient, SonarrIndexer, SonarrNotification, SonarrImportList
├── Organization: SonarrTag, SonarrAutoTag, SonarrRootFolder
├── Quality: SonarrQualityDefinition, SonarrCustomFormat
├── Metadata: SonarrMetadata
└── Config: SonarrMediaManagementConfig, SonarrNamingConfig,
SonarrIndexerConfig, SonarrDownloadClientConfig
Each controller runs an independent reconciliation loop:
- Watch — Detect create/update/delete events on the CRD
- Resolve — Look up the
SonarrInstanceRefto get URL and API key from the Sonarr CR and its Secret - Apply — Call the Sonarr REST API to create or update the resource
- Status — Write the Sonarr resource ID and a
Readycondition back to the CRD status - Finalize — On deletion, remove the resource from Sonarr before allowing the CR to be garbage-collected
- Requeue — Re-reconcile every 5 minutes to catch out-of-band changes (errors requeue after 60 seconds)
| Variable | Description | Default |
|---|---|---|
RUST_LOG |
Log level (trace, debug, info, warn, error) | info |
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes using Conventional Commits (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the GPL-3.0 License - see the LICENSE file for details.