feat: init kapowarr setup
All checks were successful
Discord / discord commits (push) Has been skipped
All checks were successful
Discord / discord commits (push) Has been skipped
This commit is contained in:
parent
3dbdacdd6e
commit
ecaf765bb5
11 changed files with 405 additions and 0 deletions
|
@ -147,6 +147,7 @@ in {
|
|||
prowlarr.reverseProxy = "${nosIP}:9696";
|
||||
radarr.reverseProxy = "${nosIP}:7878";
|
||||
sonarr.reverseProxy = "${nosIP}:8989";
|
||||
kapowarr.reverseProxy = "${nosIP}:5676";
|
||||
|
||||
jdownloader2 = {
|
||||
subDirName = "jd2";
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{...}: {
|
||||
imports = [
|
||||
./jdownloader2
|
||||
./kapowarr
|
||||
./komga
|
||||
];
|
||||
}
|
||||
|
|
11
configurations/nos/modules/comics/kapowarr/default.nix
Normal file
11
configurations/nos/modules/comics/kapowarr/default.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
{mainUser, ...}: {
|
||||
imports = [./module.nix];
|
||||
|
||||
services.kapowarr = {
|
||||
enable = true;
|
||||
port = 5676;
|
||||
|
||||
user = mainUser;
|
||||
group = "users";
|
||||
};
|
||||
}
|
116
configurations/nos/modules/comics/kapowarr/module.nix
Normal file
116
configurations/nos/modules/comics/kapowarr/module.nix
Normal file
|
@ -0,0 +1,116 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
getExe
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
mkPackageOption
|
||||
types
|
||||
;
|
||||
|
||||
cfg = config.services.kapowarr;
|
||||
in {
|
||||
options.services.kapowarr = {
|
||||
enable = mkEnableOption "kapowarr";
|
||||
package = mkPackageOption pkgs.selfPackages "kapowarr" {};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "kapowarr";
|
||||
description = "The user account under which Kapowarr runs.";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "kapowarr";
|
||||
description = "The group under which Kapowarr runs.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 5656;
|
||||
description = "Port where kapowarr should listen for incoming requests.";
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/kapowarr/";
|
||||
description = "The directory where Kapowarr stores its data files.";
|
||||
};
|
||||
|
||||
downloadDir = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.dataDir}/temp_downloads";
|
||||
defaultText = "/var/lib/kapowarr/temp_downloads";
|
||||
description = "The directory where Kapowarr stores its downloaded files.";
|
||||
};
|
||||
|
||||
logDir = mkOption {
|
||||
type = types.path;
|
||||
default = cfg.dataDir;
|
||||
defaultText = "/var/lib/kapowarr";
|
||||
description = "The directory where Kapowarr stores its log file.";
|
||||
};
|
||||
|
||||
openFirewall = mkEnableOption "Open ports in the firewall for Kapowarr.";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.kapowarr = {
|
||||
description = "Kapowarr";
|
||||
after = ["network.target"];
|
||||
wantedBy = ["multi-user.target"];
|
||||
|
||||
environment = {
|
||||
KAPOWARR_PORT = toString cfg.port;
|
||||
KAPOWARR_LOG_DIR = cfg.logDir;
|
||||
KAPOWARR_STATE_DIR = cfg.dataDir;
|
||||
KAPOWARR_DOWNLOAD_DIR = cfg.downloadDir;
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
StateDirectory = mkIf (cfg.dataDir == "/var/lib/kapowar") "kapowarr";
|
||||
ExecStart = "${getExe cfg.package} -d ${cfg.dataDir}";
|
||||
|
||||
# Hardening from komga service
|
||||
RemoveIPC = true;
|
||||
NoNewPrivileges = true;
|
||||
CapabilityBoundingSet = "";
|
||||
SystemCallFilter = ["@system-service"];
|
||||
ProtectSystem = "full";
|
||||
PrivateTmp = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectClock = true;
|
||||
ProcSubset = "pid";
|
||||
PrivateUsers = true;
|
||||
PrivateDevices = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelTunables = true;
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_NETLINK"
|
||||
];
|
||||
LockPersonality = true;
|
||||
RestrictNamespaces = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectKernelModules = true;
|
||||
SystemCallArchitectures = "native";
|
||||
RestrictSUIDSGID = true;
|
||||
RestrictRealtime = true;
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall = mkIf cfg.openFirewall {allowedTCPPorts = [cfg.port];};
|
||||
};
|
||||
}
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
jmusicbot = final.callPackage ./jmusicbot {};
|
||||
|
||||
kapowarr = import ./kapowarr final;
|
||||
|
||||
komf = final.callPackage ./komf {};
|
||||
|
||||
libratbag = final.callPackage ./libratbag {
|
||||
|
|
17
packages/kapowarr/bencoding/default.nix
Normal file
17
packages/kapowarr/bencoding/default.nix
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
# nix build inputs
|
||||
buildPythonPackage,
|
||||
fetchPypi,
|
||||
...
|
||||
}: let
|
||||
pname = "bencoding";
|
||||
version = "0.2.6";
|
||||
in
|
||||
buildPythonPackage {
|
||||
inherit pname version;
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
hash = "sha256-Q8zjHUhj4p1rxhFVHU6fJlK+KZXp1eFbRtg4PxgNREA=";
|
||||
};
|
||||
}
|
14
packages/kapowarr/default.nix
Normal file
14
packages/kapowarr/default.nix
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
# nix build inputs
|
||||
python3Packages,
|
||||
...
|
||||
}: let
|
||||
pyPkgs = python3Packages.override {
|
||||
overrides = pyFinal: pyPrev: {
|
||||
bencoding = pyFinal.callPackage ./bencoding {};
|
||||
tenacity = pyFinal.callPackage ./tenacity {};
|
||||
typing-extensions = pyFinal.callPackage ./typing-extensions {};
|
||||
};
|
||||
};
|
||||
in
|
||||
pyPkgs.callPackage ./main {}
|
145
packages/kapowarr/main/default.nix
Normal file
145
packages/kapowarr/main/default.nix
Normal file
|
@ -0,0 +1,145 @@
|
|||
{
|
||||
# nix build inputs
|
||||
lib,
|
||||
buildPythonApplication,
|
||||
fetchFromGitHub,
|
||||
python,
|
||||
# deps
|
||||
aiohttp,
|
||||
beautifulsoup4,
|
||||
bencoding, # from overrides
|
||||
flask,
|
||||
flask-socketio,
|
||||
pycryptodome,
|
||||
requests,
|
||||
setuptools,
|
||||
simplejson,
|
||||
tenacity, # from overrides
|
||||
typing-extensions, # from overrides
|
||||
waitress,
|
||||
...
|
||||
}: let
|
||||
pname = "kapowarr";
|
||||
version = "1.1.1";
|
||||
in
|
||||
buildPythonApplication {
|
||||
inherit pname version;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Casvt";
|
||||
repo = "Kapowarr";
|
||||
rev = "V${version}";
|
||||
hash = "sha256-EeDzgi37f0cA86lQ1Z6hzLgpE3ORfz0YPoMWp5R4uPs=";
|
||||
};
|
||||
|
||||
patches = [./raise-errors.patch];
|
||||
|
||||
postPatch = ''
|
||||
# Insert import for following substituteInPlace
|
||||
sed -i '/# -\*- coding: utf-8 -\*-/a from os import environ' ./backend/base/logging.py
|
||||
|
||||
substituteInPlace ./backend/base/logging.py --replace-fail \
|
||||
"return folder_path(Constants.LOGGER_FILENAME)" \
|
||||
"return f\"{environ.get('KAPOWARR_LOG_DIR')}/{Constants.LOGGER_FILENAME}\""
|
||||
|
||||
substituteInPlace ./backend/internals/settings.py \
|
||||
--replace-fail \
|
||||
"from os import urandom" \
|
||||
"from os import urandom, environ" \
|
||||
--replace-fail \
|
||||
"port: int = 5656" \
|
||||
"port: int = int(environ.get('KAPOWARR_PORT'))" \
|
||||
--replace-fail \
|
||||
"download_folder: str = folder_path('temp_downloads')" \
|
||||
"download_folder: str = environ.get('KAPOWARR_DOWNLOAD_DIR')" \
|
||||
--replace-fail \
|
||||
"filename = folder_path('frontend', 'static', 'json', 'pwa_manifest.json')" \
|
||||
"filename = f\"{environ.get('KAPOWARR_STATE_DIR')}/pwa_manifest.json\""
|
||||
'';
|
||||
|
||||
build-system = [setuptools];
|
||||
|
||||
dependencies = [
|
||||
typing-extensions
|
||||
requests
|
||||
beautifulsoup4
|
||||
flask
|
||||
waitress
|
||||
pycryptodome
|
||||
tenacity
|
||||
bencoding
|
||||
simplejson
|
||||
aiohttp
|
||||
flask-socketio
|
||||
];
|
||||
|
||||
preBuild = ''
|
||||
cat > setup.py << EOF
|
||||
from setuptools import setup, find_packages, find_namespace_packages
|
||||
|
||||
with open('requirements.txt') as f:
|
||||
install_requires = f.read().splitlines()
|
||||
|
||||
setup(
|
||||
name='${pname}',
|
||||
version = '${version}',
|
||||
install_requires=install_requires,
|
||||
packages=[
|
||||
'frontend',
|
||||
'backend',
|
||||
'backend.base',
|
||||
'backend.features',
|
||||
'backend.implementations',
|
||||
'backend.implementations.torrent_clients',
|
||||
'backend.internals',
|
||||
'backend.lib',
|
||||
],
|
||||
scripts=[
|
||||
'Kapowarr.py'
|
||||
],
|
||||
)
|
||||
EOF
|
||||
'';
|
||||
|
||||
# Use XDG-ish dirs for configuration. These would otherwise be in the kapowarr package.
|
||||
#
|
||||
# Using --run as `makeWrapper` evaluates variables for --set and --set-default at build
|
||||
# time and then single quotes the vars in the wrapper, thus they wouldn't get expanded.
|
||||
# But using --run allows setting default vars that are evaluated on run and not during
|
||||
# build time.
|
||||
makeWrapperArgs = [
|
||||
"--set-default KAPOWARR_PORT 5656"
|
||||
''
|
||||
--run "OUTDIR=\"$out\""
|
||||
--run '
|
||||
configDir="''${XDG_CONFIG_HOME:-$HOME/.config}/kapowarr"
|
||||
export KAPOWARR_STATE_DIR="''${KAPOWARR_STATE_DIR-$configDir}"
|
||||
export KAPOWARR_LOG_DIR="''${KAPOWARR_LOG_DIR-$configDir}"
|
||||
export KAPOWARR_DOWNLOAD_DIR="''${KAPOWARR_DOWNLOAD_DIR-$configDir/temp_downloads}"
|
||||
mkdir -p "$KAPOWARR_STATE_DIR" "$KAPOWARR_LOG_DIR"
|
||||
|
||||
if [ ! -f "$KAPOWARR_STATE_DIR/pwa_manifest.json" ]; then
|
||||
cat "$OUTDIR/${python.sitePackages}/frontend/static/json/pwa_manifest.json" > "$KAPOWARR_STATE_DIR/pwa_manifest.json"
|
||||
fi
|
||||
'
|
||||
''
|
||||
];
|
||||
|
||||
postFixup = ''
|
||||
# I prefer a clean name for the executable
|
||||
mv $out/bin/Kapowarr.py $out/bin/${pname}
|
||||
|
||||
# Add missing resources that Kapowarr uses at runtime in sitePackages
|
||||
cp -r ./frontend/{static,templates} "$out/${python.sitePackages}/frontend"
|
||||
'';
|
||||
|
||||
meta = {
|
||||
mainProgram = pname;
|
||||
license = lib.licenses.gpl3Only;
|
||||
homepage = "https://casvt.github.io/Kapowarr";
|
||||
description = ''
|
||||
Kapowarr is a software to build and manage a comic book library,
|
||||
fitting in the *arr suite of software
|
||||
'';
|
||||
};
|
||||
}
|
26
packages/kapowarr/main/raise-errors.patch
Normal file
26
packages/kapowarr/main/raise-errors.patch
Normal file
|
@ -0,0 +1,26 @@
|
|||
Kapowarr.py | 9 +++++++--
|
||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/Kapowarr.py b/Kapowarr.py
|
||||
index 0e9da56..306976c 100644
|
||||
--- a/Kapowarr.py
|
||||
+++ b/Kapowarr.py
|
||||
@@ -185,8 +185,13 @@ if __name__ == "__main__":
|
||||
db_folder=db_folder
|
||||
)
|
||||
|
||||
- except ValueError:
|
||||
- parser.error("The value for -d/--DatabaseFolder is not a folder")
|
||||
+ except ValueError as e:
|
||||
+ if e.args and e.args[0] == 'Database location is not a folder':
|
||||
+ parser.error(
|
||||
+ "The value for -d/--DatabaseFolder is not a folder"
|
||||
+ )
|
||||
+ else:
|
||||
+ raise e
|
||||
|
||||
else:
|
||||
rc = Kapowarr()
|
||||
--
|
||||
2.48.1
|
||||
|
49
packages/kapowarr/tenacity/default.nix
Normal file
49
packages/kapowarr/tenacity/default.nix
Normal file
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
# nix build inputs
|
||||
lib,
|
||||
buildPythonPackage,
|
||||
fetchPypi,
|
||||
# deps
|
||||
pbr,
|
||||
pytest-asyncio,
|
||||
pytestCheckHook,
|
||||
pythonOlder,
|
||||
setuptools-scm,
|
||||
tornado,
|
||||
typeguard,
|
||||
...
|
||||
}: let
|
||||
pname = "tenacity";
|
||||
version = "8.2.3";
|
||||
in
|
||||
buildPythonPackage {
|
||||
inherit pname version;
|
||||
format = "pyproject";
|
||||
|
||||
disabled = pythonOlder "3.6";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
hash = "sha256-U5jvDXjmP0AAfB+0wL/5bhkROU0vqNGU93YZwF/2zIo=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
pbr
|
||||
setuptools-scm
|
||||
];
|
||||
|
||||
nativeCheckInputs = [
|
||||
pytest-asyncio
|
||||
pytestCheckHook
|
||||
tornado
|
||||
typeguard
|
||||
];
|
||||
|
||||
pythonImportsCheck = [pname];
|
||||
|
||||
meta = {
|
||||
homepage = "https://github.com/jd/tenacity";
|
||||
description = "Retrying library for Python";
|
||||
license = lib.licenses.asl20;
|
||||
};
|
||||
}
|
23
packages/kapowarr/typing-extensions/default.nix
Normal file
23
packages/kapowarr/typing-extensions/default.nix
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
# nix build inputs
|
||||
buildPythonPackage,
|
||||
fetchPypi,
|
||||
# deps
|
||||
flit-core,
|
||||
...
|
||||
}: let
|
||||
pname = "typing_extensions";
|
||||
version = "4.12.2";
|
||||
in
|
||||
buildPythonPackage {
|
||||
inherit pname version;
|
||||
format = "pyproject";
|
||||
|
||||
build-system = [flit-core];
|
||||
dependencies = [flit-core];
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
hash = "sha256-Gn6tVcflWd1N7ohW46iLQSJav+HOjfV7fBORX+Eh/7g=";
|
||||
};
|
||||
}
|
Loading…
Add table
Reference in a new issue