selfhostblocks/modules/services/arr/docs/default.md
2026-02-24 20:00:36 +01:00

7.4 KiB

*Arr Service

Defined in /modules/services/arr.nix.

This NixOS module sets up multiple Servarr services.

Features

Compared to the stock module from nixpkgs, this one sets up, in a fully declarative manner LDAP and SSO integration as well as the API key.

Usage

Initial Configuration

The following snippet assumes a few blocks have been setup already:

{
  shb.certs.certs.letsencrypt.${domain}.extraDomains = [
    "moviesdl.${domain}"
    "seriesdl.${domain}"
    "subtitlesdl.${domain}"
    "booksdl.${domain}"
    "musicdl.${domain}"
    "indexer.${domain}"
  ];

  shb.arr = {
    radarr = {
      inherit domain;
      enable = true;
      ssl = config.shb.certs.certs.letsencrypt.${domain};
      authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
    };
    sonarr = {
      inherit domain;
      enable = true;
      ssl = config.shb.certs.certs.letsencrypt."${domain}";
      authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
    };
    bazarr = {
      inherit domain;
      enable = true;
      ssl = config.shb.certs.certs.letsencrypt."${domain}";
      authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
    };
    readarr = {
      inherit domain;
      enable = true;
      ssl = config.shb.certs.certs.letsencrypt."${domain}";
      authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
    };
    lidarr = {
      inherit domain;
      enable = true;
      ssl = config.shb.certs.certs.letsencrypt."${domain}";
      authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
    };
    jackett = {
      inherit domain;
      enable = true;
      ssl = config.shb.certs.certs.letsencrypt."${domain}";
      authEndpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
    };
  };
}

The user and admin LDAP groups are created automatically.

API Keys

The API keys for each arr service can be created declaratively.

First, generate one secret for each service with nix run nixpkgs#openssl -- rand -hex 64 and store it in your secrets file (for example the SOPS file).

Then, add the API key to each service:

{
  shb.arr = {
    radarr = {
      settings = {
        ApiKey.source = config.shb.sops.secret."radarr/apikey".result.path;
      };
    };
    sonarr = {
      settings = {
        ApiKey.source = config.shb.sops.secret."sonarr/apikey".result.path;
      };
    };
    bazarr = {
      settings = {
        ApiKey.source = config.shb.sops.secret."bazarr/apikey".result.path;
      };
    };
    readarr = {
      settings = {
        ApiKey.source = config.shb.sops.secret."readarr/apikey".result.path;
      };
    };
    lidarr = {
      settings = {
        ApiKey.source = config.shb.sops.secret."lidarr/apikey".result.path;
      };
    };
    jackett = {
      settings = {
        ApiKey.source = config.shb.sops.secret."jackett/apikey".result.path;
      };
    };
  };

  shb.sops.secret."radarr/apikey".request = {
    mode = "0440";
    owner = "radarr";
    group = "radarr";
    restartUnits = [ "radarr.service" ];
  };
  shb.sops.secret."sonarr/apikey".request = {
    mode = "0440";
    owner = "sonarr";
    group = "sonarr";
    restartUnits = [ "sonarr.service" ];
  };
  shb.sops.secret."bazarr/apikey".request = {
    mode = "0440";
    owner = "bazarr";
    group = "bazarr";
    restartUnits = [ "bazarr.service" ];
  };
  shb.sops.secret."readarr/apikey".request = {
    mode = "0440";
    owner = "readarr";
    group = "readarr";
    restartUnits = [ "readarr.service" ];
  };
  shb.sops.secret."lidarr/apikey".request = {
    mode = "0440";
    owner = "lidarr";
    group = "lidarr";
    restartUnits = [ "lidarr.service" ];
  };
  shb.sops.secret."jackett/apikey".request = {
    mode = "0440";
    owner = "jackett";
    group = "jackett";
    restartUnits = [ "jackett.service" ];
  };
}

Application Dashboard

Integration with the dashboard contract is provided by the various dashboard options.

For example using the Homepage service:

{
  shb.homepage.servicesGroups.Media.services.Radarr = {
    sortOrder = 10;
    dashboard.request = config.shb.arr.radarr.dashboard.request;
    apiKey.result = config.shb.sops.secret."radarr/homepageApiKey".result;
  };
  shb.sops.secret."radarr/homepageApiKey" = {
    settings.key = "radarr/apikey";
    request = config.shb.homepage.servicesGroups.Media.services.Radarr.apiKey.request;
  };
  shb.homepage.servicesGroups.Media.services.Sonarr = {
    sortOrder = 11;
    dashboard.request = config.shb.arr.sonarr.dashboard.request;
    apiKey.result = config.shb.sops.secret."sonarr/homepageApiKey".result;
  };
  shb.sops.secret."sonarr/homepageApiKey" = {
    settings.key = "sonarr/apikey";
    request = config.shb.homepage.servicesGroups.Media.services.Sonarr.apiKey.request;
  };
  shb.homepage.servicesGroups.Media.services.Bazarr = {
    sortOrder = 12;
    dashboard.request = config.shb.arr.bazarr.dashboard.request;
    apiKey.result = config.shb.sops.secret."bazarr/homepageApiKey".result;
  };
  shb.sops.secret."bazarr/homepageApiKey" = {
    settings.key = "bazarr/apikey";
    request = config.shb.homepage.servicesGroups.Media.services.Bazarr.apiKey.request;
  };
  shb.homepage.servicesGroups.Media.services.Readarr = {
    sortOrder = 13;
    dashboard.request = config.shb.arr.readarr.dashboard.request;
    apiKey.result = config.shb.sops.secret."readarr/homepageApiKey".result;
  };
  shb.sops.secret."readarr/homepageApiKey" = {
    settings.key = "readarr/apikey";
    request = config.shb.homepage.servicesGroups.Media.services.Readarr.apiKey.request;
  };
  shb.homepage.servicesGroups.Media.services.Lidarr = {
    sortOrder = 14;
    dashboard.request = config.shb.arr.lidarr.dashboard.request;
    apiKey.result = config.shb.sops.secret."lidarr/homepageApiKey".result;
  };
  shb.sops.secret."lidarr/homepageApiKey" = {
    settings.key = "lidarr/apikey";
    request = config.shb.homepage.servicesGroups.Media.services.Lidarr.apiKey.request;
  };
  shb.homepage.servicesGroups.Media.services.Jackett = {
    sortOrder = 15;
    dashboard.request = config.shb.arr.jackett.dashboard.request;
    apiKey.result = config.shb.sops.secret."jackett/homepageApiKey".result;
  };
  shb.sops.secret."jackett/homepageApiKey" = {
    settings.key = "jackett/apikey";
    request = config.shb.homepage.servicesGroups.Media.services.Jackett.apiKey.request;
  };
}

This example reuses the API keys generated declaratively from the previous section.

Jackett Proxy

The Jackett service can be made to use a proxy with:

{
  shb.arr.jackett = {
    settings = {
      ProxyType = "0";
      ProxyUrl = "127.0.0.1:1234";
    };
  };
};

Options Reference

id-prefix: services-arr-options-
list-id: selfhostblocks-service-arr-options
source: @OPTIONS_JSON@