nixos/koito: init module

This commit is contained in:
ivann
2026-06-08 17:00:39 +02:00
parent e973b96985
commit 25851326c1
6 changed files with 171 additions and 1 deletions
@@ -24,6 +24,8 @@
- [Freescout](https://freescout.net/), a free, open source Helpdesk and shared mailbox. Available as [services.freescout](#opt-services.freescout.enable).
- [Koito](https://koito.io/), a modern, themeable scrobbler that you can use with any program that scrobbles to a custom ListenBrainz URL. Available as [services.koito](#opt-services.koito.enable).
- [FlapAlerted](https://github.com/Kioubit/FlapAlerted), detects BGP flapping events and provides statistics based on BGP update messages. Available as [services.flap-alerted](#opt-services.flap-alerted.enable).
- [Unpackerr](https://unpackerr.zip), extracts downloads for Radarr, Sonarr, Lidarr, Readarr, and/or a Watch folder. Available as [services.unpackerr](#opt-services.unpackerr.enable).
+1
View File
@@ -1707,6 +1707,7 @@
./services/web-apps/kavita.nix
./services/web-apps/keycloak.nix
./services/web-apps/kimai.nix
./services/web-apps/koito.nix
./services/web-apps/komga.nix
./services/web-apps/lanraragi.nix
./services/web-apps/lasuite-docs.nix
+140
View File
@@ -0,0 +1,140 @@
{
lib,
config,
pkgs,
...
}:
let
cfg = config.services.koito;
inherit (lib)
getExe
mkEnableOption
mkIf
mkOption
mkPackageOption
types
;
in
{
options.services.koito = {
enable = mkEnableOption "koito";
package = mkPackageOption pkgs "koito" { };
openFirewall = mkOption {
type = types.bool;
default = false;
description = "Open the appropriate ports in the firewall for Koito.";
};
environment = mkOption {
type = types.submodule {
freeformType = types.attrsOf types.str;
options = {
KOITO_BIND_ADDR = mkOption {
type = types.str;
default = "127.0.0.1";
example = "0.0.0.0";
description = "The IP address to bind the Koito server to.";
};
KOITO_LISTEN_PORT = mkOption {
type = types.port;
default = 4110;
description = "TCP port for the Koito server.";
};
KOITO_CONFIG_DIR = mkOption {
type = types.path;
default = "/var/lib/koito";
description = "Directory for Koito import folders and image caches.";
};
};
};
default = { };
example = {
KOITO_DEFAULT_THEME = "black";
KOITO_LOGIN_GATE = "true";
};
description = ''
Environment variables to pass to the Koito service.
See <https://koito.io/reference/configuration/> for available options.
'';
};
environmentFile = mkOption {
type = types.nullOr types.path;
example = "/run/secrets/koito";
default = null;
description = ''
Path of a file with extra environment variables to be loaded from disk.
This file is not added to the nix store, so it can be used to pass secrets to Koito.
See <https://koito.io/reference/configuration/> for available options.
'';
};
};
config = mkIf cfg.enable {
systemd.services.koito = {
description = "Koito - modern scrobbler";
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Environment = lib.mapAttrsToList (k: v: "${k}=${if builtins.isInt v then toString v else v}") (
lib.filterAttrs (_: v: v != null) cfg.environment
);
DynamicUser = true;
ExecStart = getExe cfg.package;
StateDirectory = "koito";
EnvironmentFile = cfg.environmentFile;
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
PrivateDevices = true;
PrivateMounts = true;
ProtectControlGroups = true;
ProtectKernelTunables = true;
RestrictSUIDSGID = true;
RemoveIPC = true;
UMask = "0077";
CapabilityBoundingSet = [ "" ];
NoNewPrivileges = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectClock = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
"~@resources"
];
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
PrivateUsers = true;
LockPersonality = true;
ProtectHostname = true;
RestrictRealtime = true;
RestrictNamespaces = true;
ProtectProc = "invisible";
ProcSubset = "pid";
DeviceAllow = [ "" ];
};
};
networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.environment.KOITO_LISTEN_PORT ];
};
};
meta = {
maintainers = with lib.maintainers; [ iv-nn ];
};
}
+1
View File
@@ -889,6 +889,7 @@ in
kmonad = runTest ./kmonad.nix;
kmscon = runTest ./kmscon.nix;
knot = runTest ./knot.nix;
koito = runTest ./web-apps/koito.nix;
komga = runTest ./komga.nix;
komodo-periphery = runTest ./komodo-periphery.nix;
krb5 = discoverTests (import ./krb5);
+20
View File
@@ -0,0 +1,20 @@
{ ... }:
{
name = "koito";
nodes.machine = {
services.koito.enable = true;
};
testScript =
{ nodes, ... }:
let
port = toString nodes.machine.services.koito.environment.KOITO_LISTEN_PORT;
in
''
machine.wait_for_unit('koito.service')
machine.wait_for_open_port(${port})
machine.succeed('curl --fail http://localhost:${port}')
'';
}
+7 -1
View File
@@ -6,6 +6,7 @@
pkg-config,
vips,
makeWrapper,
nixosTests,
}:
buildGoModule (finalAttrs: {
pname = "koito";
@@ -44,10 +45,15 @@ buildGoModule (finalAttrs: {
'';
passthru = {
updateScript = ./update.sh;
client = callPackage ./client.nix {
inherit (finalAttrs) src version;
};
tests = {
inherit (nixosTests) koito;
};
updateScript = ./update.sh;
};
meta = {