---
title: Nix Package Manager (Advanced)
description: Install Seerr using Nix
sidebar_position: 3
---

import { SeerrVersion, NixpkgVersion } from '@site/src/components/SeerrVersion';
import Admonition from '@theme/Admonition';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# Nix Package Manager (Advanced)
:::info
This method is not recommended for most users. It is intended for advanced users who are using Nix as their package manager.
:::

export const VersionMismatchWarning = () => {
  let seerrVersion = null;
  let nixpkgVersions = null;
  try {
    seerrVersion = SeerrVersion();
    nixpkgVersions = NixpkgVersion();
  } catch (err) {
    return (
      <Admonition type="error">
        Failed to load version information. Error: {err.message || JSON.stringify(err)}
      </Admonition>
    );
  }

    if (!nixpkgVersions || nixpkgVersions.error) {
    return (
      <Admonition type="error">
        Failed to fetch Nixpkg versions: {nixpkgVersions?.error || 'Unknown error'}
      </Admonition>
    );
  }

  const isUnstableUpToDate = seerrVersion === nixpkgVersions.unstable;
  const isStableUpToDate = seerrVersion === nixpkgVersions.stable;

  return (
     <>
      {!isStableUpToDate ? (
  <Admonition type="warning">
    The{' '}
    <a href="https://github.com/NixOS/nixpkgs/blob/nixos-24.11/pkgs/servers/jellyseerr/default.nix#L14">
      upstream Jellyseerr Nix Package (v{nixpkgVersions.stable})
    </a>{' '}
    is not <b>up-to-date</b>. If you want to use <b>Jellyseerr v{seerrVersion}</b>,{' '}
    {isUnstableUpToDate ? (
      <>
        consider using the{' '}
        <a href="https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/by-name/je/jellyseerr/package.nix">
          unstable package
        </a>{' '}
        instead.
      </>
    ) : (
      <>
        you will need to{' '}
        <a href="#overriding-the-package-derivation">override the package derivation</a>.
      </>
    )}
  </Admonition>
) : null}
    </>
  );
};

<VersionMismatchWarning />

## Installation
To get up and running with jellyseerr using Nix, you can add the following to your `configuration.nix`:

```nix
{ config, pkgs, ... }:

{
  services.jellyseerr.enable = true;
}
```

If you want more advanced configuration options, you can use the following:

<Tabs groupId="nixpkg-methods" queryString>
  <TabItem value="default" label="Default Configurations">
```nix
{ config, pkgs, ... }:

{
  services.jellyseerr = {
    enable = true;
    port = 5055;
    openFirewall = true;
    package = pkgs.jellyseerr; # Use the unstable package if stable is not up-to-date
  };
}
```
  </TabItem>
  <TabItem value="custom" label="Database Configurations">
In order to use postgres, you will need to add override the default module of jellyseerr with the following as the current default module is not compatible with postgres:
```nix
{
  config,
  pkgs,
  lib,
  ...
}:
with lib;
let
  cfg = config.services.jellyseerr;
in
{
  meta.maintainers = [ maintainers.camillemndn ];

  disabledModules = [ "services/misc/jellyseerr.nix" ];

  options.services.jellyseerr = {
    enable = mkEnableOption ''Jellyseerr, a requests manager for Jellyfin'';

    openFirewall = mkOption {
      type = types.bool;
      default = false;
      description = ''Open port in the firewall for the Jellyseerr web interface.'';
    };

    port = mkOption {
      type = types.port;
      default = 5055;
      description = ''The port which the Jellyseerr web UI should listen to.'';
    };

    package = mkOption {
      type = types.package;
      default = pkgs.jellyseerr;
      defaultText = literalExpression "pkgs.jellyseerr";
      description = ''
        Jellyseerr package to use.
      '';
    };

    databaseConfig = mkOption {
      type = types.attrsOf types.str;
      default = {
        type = "sqlite";
        configDirectory = "config";
        logQueries = "false";
      };
      description = ''
        Database configuration. For "sqlite", only "type", "configDirectory", and "logQueries" are relevant.
        For "postgres", include host, port, user, pass, name, and optionally socket.
        Example:
        {
          type = "postgres";
          socket = "/run/postgresql";
          user = "jellyseerr";
          name = "jellyseerr";
          logQueries = "false";
        }
        or
        {
          type = "postgres";
          host = "localhost";
          port = "5432";
          user = "dbuser";
          pass = "password";
          name = "jellyseerr";
          logQueries = "false";
        }
        or
        {
          type = "sqlite";
          configDirectory = "config";
          logQueries = "false";
        }
      '';
    };
  };

  config = mkIf cfg.enable {
    systemd.services.jellyseerr = {
      description = "Jellyseerr, a requests manager for Jellyfin";
      after = [ "network.target" ];
      wantedBy = [ "multi-user.target" ];
      environment =
        let
          dbConfig = cfg.databaseConfig;
        in
        {
          PORT = toString cfg.port;
          DB_TYPE = toString dbConfig.type;
          CONFIG_DIRECTORY = toString dbConfig.configDirectory or "";
          DB_LOG_QUERIES = toString dbConfig.logQueries;
          DB_HOST = if dbConfig.type == "postgres" && !(hasAttr "socket" dbConfig) then toString dbConfig.host or "" else "";
          DB_PORT = if dbConfig.type == "postgres" && !(hasAttr "socket" dbConfig) then toString dbConfig.port or "" else "";
          DB_SOCKET_PATH = if dbConfig.type == "postgres" && hasAttr "socket" dbConfig then toString dbConfig.socket or "" else "";
          DB_USER = if dbConfig.type == "postgres" then toString dbConfig.user or "" else "";
          DB_PASS = if dbConfig.type == "postgres" then toString dbConfig.pass or "" else "";
          DB_NAME = if dbConfig.type == "postgres" then toString dbConfig.name or "" else "";
        };
      serviceConfig = {
        Type = "exec";
        StateDirectory = "jellyseerr";
        WorkingDirectory = "${cfg.package}/libexec/jellyseerr";
        DynamicUser = true;
        ExecStart = "${cfg.package}/bin/jellyseerr";
        BindPaths = [ "/var/lib/jellyseerr/:${cfg.package}/libexec/jellyseerr/config/" ];
        Restart = "on-failure";
        ProtectHome = true;
        ProtectSystem = "strict";
        PrivateTmp = true;
        PrivateDevices = true;
        ProtectHostname = true;
        ProtectClock = true;
        ProtectKernelTunables = true;
        ProtectKernelModules = true;
        ProtectKernelLogs = true;
        ProtectControlGroups = true;
        NoNewPrivileges = true;
        RestrictRealtime = true;
        RestrictSUIDSGID = true;
        RemoveIPC = true;
        PrivateMounts = true;
      };
    };

    networking.firewall = mkIf cfg.openFirewall { allowedTCPPorts = [ cfg.port ]; };
  };
}
```
Then, import the module into your `configuration.nix`:
```nix
{ config, pkgs, ... }:
{
  imports = [ ./modules/jellyseerr.nix ];

  services.jellyseerr = {
    enable = true;
    port = 5055;
    openFirewall = true;
    package = pkgs.unstable.jellyseerr; # use the unstable package if stable is not up-to-date
    databaseConfig = {
      type = "postgres";
      host = "localhost"; # or socket: "/run/postgresql"
      port = "5432"; # if using socket, this is not needed
      user = "jellyseerr";
      pass = "jellyseerr";
      name = "jellyseerr";
      logQueries = "false";
    };
  }
}
```
  </TabItem>
</Tabs>

After adding the configuration to your `configuration.nix`, you can run the following command to install jellyseerr:

```bash
nixos-rebuild switch
```
After rebuild is complete jellyseerr should be running, verify that it is with the following command.
```bash
systemctl status jellyseerr
```

:::info
You can now access Seerr by visiting `http://localhost:5055` in your web browser.
:::

