Commit 4fa82b9e authored by sternenseemann's avatar sternenseemann
Browse files

Merge remote-tracking branch 'origin/master' into haskell-updates

parents 94c2ac51 feae6010
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ In addition to numerous new and upgraded packages, this release has the followin
- [Cloudlog](https://www.magicbug.co.uk/cloudlog/), a web-based Amateur Radio logging application. Available as [services.cloudlog](#opt-services.cloudlog.enable).

- [fzf](https://github.com/junegunn/fzf), a command line fuzzyfinder. Available as [programs.fzf](#opt-programs.fzf.fuzzyCompletion).
- [readarr](https://github.com/Readarr/Readarr), Book Manager and Automation (Sonarr for Ebooks). Available as [services.readarr](options.html#opt-services.readarr.enable).

- [gemstash](https://github.com/rubygems/gemstash), a RubyGems.org cache and private gem server. Available as [services.gemstash](#opt-services.gemstash.enable).

+2 −0
Original line number Diff line number Diff line
@@ -665,6 +665,7 @@
  ./services/misc/prowlarr.nix
  ./services/misc/pykms.nix
  ./services/misc/radarr.nix
  ./services/misc/readarr.nix
  ./services/misc/redmine.nix
  ./services/misc/ripple-data-api.nix
  ./services/misc/rippled.nix
@@ -803,6 +804,7 @@
  ./services/networking/bitlbee.nix
  ./services/networking/blockbook-frontend.nix
  ./services/networking/blocky.nix
  ./services/networking/cgit.nix
  ./services/networking/charybdis.nix
  ./services/networking/chisel-server.nix
  ./services/networking/cjdns.nix
+88 −0
Original line number Diff line number Diff line
{ config, pkgs, lib, ... }:

with lib;

let
  cfg = config.services.readarr;
in
{
  options = {
    services.readarr = {
      enable = mkEnableOption (lib.mdDoc "Readarr");

      dataDir = mkOption {
        type = types.str;
        default = "/var/lib/readarr/";
        description = lib.mdDoc "The directory where Readarr stores its data files.";
      };

      package = mkOption {
        type = types.package;
        default = pkgs.readarr;
        defaultText = literalExpression "pkgs.readarr";
        description = lib.mdDoc "The Readarr package to use";
      };

      openFirewall = mkOption {
        type = types.bool;
        default = false;
        description = lib.mdDoc ''
          Open ports in the firewall for Readarr
        '';
      };

      user = mkOption {
        type = types.str;
        default = "readarr";
        description = lib.mdDoc ''
          User account under which Readarr runs.
        '';
      };

      group = mkOption {
        type = types.str;
        default = "readarr";
        description = lib.mdDoc ''
          Group under which Readarr runs.
        '';
      };
    };
  };

  config = mkIf cfg.enable {
    systemd.tmpfiles.rules = [
      "d '${cfg.dataDir}' 0700 ${cfg.user} ${cfg.group} - -"
    ];

    systemd.services.readarr = {
      description = "Readarr";
      after = [ "network.target" ];
      wantedBy = [ "multi-user.target" ];

      serviceConfig = {
        Type = "simple";
        User = cfg.user;
        Group = cfg.group;
        ExecStart = "${cfg.package}/bin/Readarr -nobrowser -data='${cfg.dataDir}'";
        Restart = "on-failure";
      };
    };

    networking.firewall = mkIf cfg.openFirewall {
      allowedTCPPorts = [ 8787 ];
    };

    users.users = mkIf (cfg.user == "readarr") {
      readarr = {
        description = "Readarr service";
        home = cfg.dataDir;
        group = cfg.group;
        isSystemUser = true;
      };
    };

    users.groups = mkIf (cfg.group == "readarr") {
      readarr = { };
    };
  };
}
+203 −0
Original line number Diff line number Diff line
{ config, lib, pkgs, ...}:

with lib;

let
  cfgs = config.services.cgit;

  settingType = with types; oneOf [ bool int str ];

  genAttrs' = names: f: listToAttrs (map f names);

  regexEscape =
    let
      # taken from https://github.com/python/cpython/blob/05cb728d68a278d11466f9a6c8258d914135c96c/Lib/re.py#L251-L266
      special = [
        "(" ")" "[" "]" "{" "}" "?" "*" "+" "-" "|" "^" "$" "\\" "." "&" "~"
        "#" " " "\t" "\n" "\r" "\v" "\f"
      ];
    in
      replaceStrings special (map (c: "\\${c}") special);

  stripLocation = cfg: removeSuffix "/" cfg.nginx.location;

  regexLocation = cfg: regexEscape (stripLocation cfg);

  mkFastcgiPass = cfg: ''
    ${if cfg.nginx.location == "/" then ''
      fastcgi_param PATH_INFO $uri;
    '' else ''
      fastcgi_split_path_info ^(${regexLocation cfg})(/.+)$;
      fastcgi_param PATH_INFO $fastcgi_path_info;
    ''
    }fastcgi_pass unix:${config.services.fcgiwrap.socketAddress};
  '';

  cgitrcLine = name: value: "${name}=${
    if value == true then
      "1"
    else if value == false then
      "0"
    else
      toString value
  }";

  mkCgitrc = cfg: pkgs.writeText "cgitrc" ''
    # global settings
    ${concatStringsSep "\n" (
        mapAttrsToList
          cgitrcLine
          ({ virtual-root = cfg.nginx.location; } // cfg.settings)
      )
    }
    ${optionalString (cfg.scanPath != null) (cgitrcLine "scan-path" cfg.scanPath)}

    # repository settings
    ${concatStrings (
        mapAttrsToList
          (url: settings: ''
            ${cgitrcLine "repo.url" url}
            ${concatStringsSep "\n" (
                mapAttrsToList (name: cgitrcLine "repo.${name}") settings
              )
            }
          '')
          cfg.repos
      )
    }

    # extra config
    ${cfg.extraConfig}
  '';

  mkCgitReposDir = cfg:
    if cfg.scanPath != null then
      cfg.scanPath
    else
      pkgs.runCommand "cgit-repos" {
        preferLocalBuild = true;
        allowSubstitutes = false;
      } ''
        mkdir -p "$out"
        ${
          concatStrings (
            mapAttrsToList
              (name: value: ''
                ln -s ${escapeShellArg value.path} "$out"/${escapeShellArg name}
              '')
              cfg.repos
          )
        }
      '';

in
{
  options = {
    services.cgit = mkOption {
      description = mdDoc "Configure cgit instances.";
      default = {};
      type = types.attrsOf (types.submodule ({ config, ... }: {
        options = {
          enable = mkEnableOption (mdDoc "cgit");

          package = mkPackageOptionMD pkgs "cgit" {};

          nginx.virtualHost = mkOption {
            description = mdDoc "VirtualHost to serve cgit on, defaults to the attribute name.";
            type = types.str;
            default = config._module.args.name;
            example = "git.example.com";
          };

          nginx.location = mkOption {
            description = mdDoc "Location to serve cgit under.";
            type = types.str;
            default = "/";
            example = "/git/";
          };

          repos = mkOption {
            description = mdDoc "cgit repository settings, see cgitrc(5)";
            type = with types; attrsOf (attrsOf settingType);
            default = {};
            example = {
              blah = {
                path = "/var/lib/git/example";
                desc = "An example repository";
              };
            };
          };

          scanPath = mkOption {
            description = mdDoc "A path which will be scanned for repositories.";
            type = types.nullOr types.path;
            default = null;
            example = "/var/lib/git";
          };

          settings = mkOption {
            description = mdDoc "cgit configuration, see cgitrc(5)";
            type = types.attrsOf settingType;
            default = {};
            example = literalExpression ''
              {
                enable-follow-links = true;
                source-filter = "''${pkgs.cgit}/lib/cgit/filters/syntax-highlighting.py";
              }
            '';
          };

          extraConfig = mkOption {
            description = mdDoc "These lines go to the end of cgitrc verbatim.";
            type = types.lines;
            default = "";
          };
        };
      }));
    };
  };

  config = mkIf (any (cfg: cfg.enable) (attrValues cfgs)) {
    assertions = mapAttrsToList (vhost: cfg: {
      assertion = !cfg.enable || (cfg.scanPath == null) != (cfg.repos == {});
      message = "Exactly one of services.cgit.${vhost}.scanPath or services.cgit.${vhost}.repos must be set.";
    }) cfgs;

    services.fcgiwrap.enable = true;

    services.nginx.enable = true;

    services.nginx.virtualHosts = mkMerge (mapAttrsToList (_: cfg: {
      ${cfg.nginx.virtualHost} = {
        locations = (
          genAttrs'
            [ "cgit.css" "cgit.png" "favicon.ico" "robots.txt" ]
            (name: nameValuePair "= ${stripLocation cfg}/${name}" {
              extraConfig = ''
                alias ${cfg.package}/cgit/${name};
              '';
            })
        ) // {
          "~ ${regexLocation cfg}/.+/(info/refs|git-upload-pack)" = {
            fastcgiParams = rec {
              SCRIPT_FILENAME = "${pkgs.git}/libexec/git-core/git-http-backend";
              GIT_HTTP_EXPORT_ALL = "1";
              GIT_PROJECT_ROOT = mkCgitReposDir cfg;
              HOME = GIT_PROJECT_ROOT;
            };
            extraConfig = mkFastcgiPass cfg;
          };
          "${stripLocation cfg}/" = {
            fastcgiParams = {
              SCRIPT_FILENAME = "${cfg.package}/cgit/cgit.cgi";
              QUERY_STRING = "$args";
              HTTP_HOST = "$server_name";
              CGIT_CONFIG = mkCgitrc cfg;
            };
            extraConfig = mkFastcgiPass cfg;
          };
        };
      };
    }) cfgs);
  };
}
+2 −0
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ in {
  ceph-single-node-bluestore = handleTestOn ["x86_64-linux"] ./ceph-single-node-bluestore.nix {};
  certmgr = handleTest ./certmgr.nix {};
  cfssl = handleTestOn ["aarch64-linux" "x86_64-linux"] ./cfssl.nix {};
  cgit = handleTest ./cgit.nix {};
  charliecloud = handleTest ./charliecloud.nix {};
  chromium = (handleTestOn ["aarch64-linux" "x86_64-linux"] ./chromium.nix {}).stable or {};
  chrony-ptp = handleTestOn ["aarch64-linux" "x86_64-linux"] ./chrony-ptp.nix {};
@@ -584,6 +585,7 @@ in {
  radarr = handleTest ./radarr.nix {};
  radicale = handleTest ./radicale.nix {};
  rasdaemon = handleTest ./rasdaemon.nix {};
  readarr = handleTest ./readarr.nix {};
  redis = handleTest ./redis.nix {};
  redmine = handleTest ./redmine.nix {};
  restartByActivationScript = handleTest ./restart-by-activation-script.nix {};
Loading