1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8 cfg = config.services.commafeed;
9in
10{
11 options.services.commafeed = {
12 enable = lib.mkEnableOption "CommaFeed";
13
14 package = lib.mkPackageOption pkgs "commafeed" { };
15
16 user = lib.mkOption {
17 type = lib.types.str;
18 description = "User under which CommaFeed runs.";
19 default = "commafeed";
20 };
21
22 group = lib.mkOption {
23 type = lib.types.str;
24 description = "Group under which CommaFeed runs.";
25 default = "commafeed";
26 };
27
28 stateDir = lib.mkOption {
29 type = lib.types.path;
30 description = "Directory holding all state for CommaFeed to run.";
31 default = "/var/lib/commafeed";
32 };
33
34 environment = lib.mkOption {
35 type = lib.types.attrsOf (
36 lib.types.oneOf [
37 lib.types.bool
38 lib.types.int
39 lib.types.str
40 ]
41 );
42 description = ''
43 Extra environment variables passed to CommaFeed, refer to
44 <https://github.com/Athou/commafeed/blob/master/commafeed-server/config.yml.example>
45 for supported values. The default user is `admin` and the default password is `admin`.
46 Correct configuration for H2 database is already provided.
47 '';
48 default = { };
49 example = {
50 CF_SERVER_APPLICATIONCONNECTORS_0_TYPE = "http";
51 CF_SERVER_APPLICATIONCONNECTORS_0_PORT = 9090;
52 };
53 };
54
55 environmentFile = lib.mkOption {
56 type = lib.types.nullOr lib.types.path;
57 description = ''
58 Environment file as defined in {manpage}`systemd.exec(5)`.
59 '';
60 default = null;
61 example = "/var/lib/commafeed/commafeed.env";
62 };
63 };
64
65 config = lib.mkIf cfg.enable {
66 systemd.services.commafeed = {
67 after = [ "network.target" ];
68 wantedBy = [ "multi-user.target" ];
69 environment = lib.mapAttrs (
70 _: v: if lib.isBool v then lib.boolToString v else toString v
71 ) cfg.environment;
72 serviceConfig = {
73 ExecStart = "${lib.getExe cfg.package} server ${cfg.package}/share/config.yml";
74 User = cfg.user;
75 Group = cfg.group;
76 StateDirectory = baseNameOf cfg.stateDir;
77 WorkingDirectory = cfg.stateDir;
78 # Hardening
79 CapabilityBoundingSet = [ "" ];
80 DevicePolicy = "closed";
81 DynamicUser = true;
82 LockPersonality = true;
83 NoNewPrivileges = true;
84 PrivateDevices = true;
85 PrivateUsers = true;
86 ProcSubset = "pid";
87 ProtectClock = true;
88 ProtectControlGroups = true;
89 ProtectHome = true;
90 ProtectHostname = true;
91 ProtectKernelLogs = true;
92 ProtectKernelModules = true;
93 ProtectKernelTunables = true;
94 ProtectProc = "invisible";
95 ProtectSystem = true;
96 RestrictAddressFamilies = [
97 "AF_INET"
98 "AF_INET6"
99 ];
100 RestrictNamespaces = true;
101 RestrictRealtime = true;
102 RestrictSUIDSGID = true;
103 SystemCallArchitectures = "native";
104 SystemCallFilter = [
105 "@system-service"
106 "~@privileged"
107 ];
108 UMask = "0077";
109 } // lib.optionalAttrs (cfg.environmentFile != null) { EnvironmentFile = cfg.environmentFile; };
110 };
111 };
112
113 meta.maintainers = [ lib.maintainers.raroh73 ];
114}