summaryrefslogtreecommitdiffstats
path: root/nixos/modules/services/web-apps/koito.nix
blob: f4b78770aed51dc7ec8ea14e31a39c77c991c61f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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 ];
  };
}