Merge branch 'master' into staging-next
This commit is contained in:
@@ -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
nixos/modules/services/misc/readarr.nix
Normal file
88
nixos/modules/services/misc/readarr.nix
Normal file
@@ -0,0 +1,88 @@
|
||||
{ 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
nixos/modules/services/networking/cgit.nix
Normal file
203
nixos/modules/services/networking/cgit.nix
Normal file
@@ -0,0 +1,203 @@
|
||||
{ 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);
|
||||
};
|
||||
}
|
||||
@@ -203,7 +203,7 @@ in
|
||||
PrivateMounts = true;
|
||||
# System Call Filtering
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [ "~@cpu-emulation @debug @keyring @mount @obsolete @privileged @resources" "@clock" "@setuid" "capset" "chown" ] ++ lib.optional pkgs.stdenv.hostPlatform.isAarch64 "fchownat";
|
||||
SystemCallFilter = [ "~@cpu-emulation @debug @keyring @mount @obsolete @privileged @resources" "@clock" "@setuid" "capset" "@chown" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user