grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / web-apps / wakapi.nix
blob2dbfb6d9b3d548e43fb28bbbc1f10564d93cf054
2   lib,
3   pkgs,
4   config,
5   ...
6 }:
7 let
8   cfg = config.services.wakapi;
10   settingsFormat = pkgs.formats.yaml { };
11   settingsFile = settingsFormat.generate "wakapi-settings" cfg.settings;
13   inherit (lib)
14     getExe
15     mkOption
16     mkEnableOption
17     mkPackageOption
18     types
19     mkIf
20     optional
21     mkMerge
22     singleton
23     ;
26   options.services.wakapi = {
27     enable = mkEnableOption "Wakapi";
28     package = mkPackageOption pkgs "wakapi" { };
30     settings = mkOption {
31       inherit (settingsFormat) type;
32       default = { };
33       description = ''
34         Settings for Wakapi.
36         See [config.default.yml](https://github.com/muety/wakapi/blob/master/config.default.yml) for a list of all possible options.
37       '';
38     };
40     passwordSalt = mkOption {
41       type = types.nullOr types.str;
42       default = null;
43       description = ''
44         The password salt to use for Wakapi.
45       '';
46     };
47     passwordSaltFile = mkOption {
48       type = types.nullOr types.path;
49       default = null;
50       description = ''
51         The path to a file containing the password salt to use for Wakapi.
52       '';
53     };
55     smtpPassword = mkOption {
56       type = types.nullOr types.str;
57       default = null;
58       description = ''
59         The password used for the smtp mailed to used by Wakapi.
60       '';
61     };
62     smtpPasswordFile = mkOption {
63       type = types.nullOr types.path;
64       default = null;
65       description = ''
66         The path to a file containing the password for the smtp mailer used by Wakapi.
67       '';
68     };
69   };
71   config = mkIf cfg.enable {
72     systemd.services.wakapi = {
73       description = "Wakapi (self-hosted WakaTime-compatible backend)";
74       wants = [
75         "network-online.target"
76       ] ++ optional (cfg.settings.db.dialect == "postgres") "postgresql.service";
77       after = [
78         "network-online.target"
79       ] ++ optional (cfg.settings.db.dialect == "postgres") "postgresql.service";
80       wantedBy = [ "multi-user.target" ];
82       script = ''
83         exec ${getExe cfg.package} -config ${settingsFile}
84       '';
86       serviceConfig = {
87         Environment = mkMerge [
88           (mkIf (cfg.passwordSalt != null) "WAKAPI_PASSWORD_SALT=${cfg.passwordSalt}")
89           (mkIf (cfg.smtpPassword != null) "WAKAPI_MAIL_SMTP_PASS=${cfg.smtpPassword}")
90         ];
91         EnvironmentFile = [
92           (optional (cfg.passwordSaltFile != null) cfg.passwordSaltFile)
93           (optional (cfg.smtpPasswordFile != null) cfg.smtpPasswordFile)
94         ];
96         User = config.users.users.wakapi.name;
97         Group = config.users.users.wakapi.group;
99         DynamicUser = true;
100         ProtectHome = true;
101         ProtectHostname = true;
102         ProtectKernelLogs = true;
103         ProtectKernelModules = true;
104         ProtectKernelTunables = true;
105         ProtectProc = "invisible";
106         ProtectSystem = "strict";
107         RestrictAddressFamilies = [
108           "AF_INET"
109           "AF_INET6"
110           "AF_UNIX"
111         ];
112         RestrictNamespaces = true;
113         RestrictRealtime = true;
114         RestrictSUIDSGID = true;
115         StateDirectoryMode = "0700";
116         Restart = "always";
117       };
118     };
120     services.wakapi.settings = {
121       env = lib.mkDefault "production";
122     };
124     assertions = [
125       {
126         assertion = cfg.passwordSalt != null || cfg.passwordSaltFile != null;
127         message = "Either `services.wakapi.passwordSalt` or `services.wakapi.passwordSaltFile` must be set.";
128       }
129       {
130         assertion = cfg.passwordSalt != null -> cfg.passwordSaltFile != null;
131         message = "Both `services.wakapi.passwordSalt` `services.wakapi.passwordSaltFile` should not be set at the same time.";
132       }
133       {
134         assertion = cfg.smtpPassword != null -> cfg.smtpPasswordFile != null;
135         message = "Both `services.wakapi.smtpPassword` `services.wakapi.smtpPasswordFile` should not be set at the same time.";
136       }
137     ];
139     users = {
140       users.wakapi = {
141         group = "wakapi";
142         createHome = false;
143         isSystemUser = true;
144       };
145       groups.wakapi = { };
146     };
148     services.postgresql = mkIf (cfg.settings.db.dialect == "postgres") {
149       enable = true;
151       ensureDatabases = singleton cfg.settings.db.name;
152       ensureUsers = singleton {
153         name = cfg.settings.db.user;
154         ensureDBOwnership = true;
155       };
157       authentication = ''
158         host ${cfg.settings.db.name} ${cfg.settings.db.user} 127.0.0.1/32 trust
159       '';
160     };
161   };
163   meta.maintainers = with lib.maintainers; [ isabelroses ];