8 cfg = config.services.wakapi;
10 settingsFormat = pkgs.formats.yaml { };
11 settingsFile = settingsFormat.generate "wakapi-settings" cfg.settings;
26 options.services.wakapi = {
27 enable = mkEnableOption "Wakapi";
28 package = mkPackageOption pkgs "wakapi" { };
31 inherit (settingsFormat) type;
36 See [config.default.yml](https://github.com/muety/wakapi/blob/master/config.default.yml) for a list of all possible options.
40 passwordSalt = mkOption {
41 type = types.nullOr types.str;
44 The password salt to use for Wakapi.
47 passwordSaltFile = mkOption {
48 type = types.nullOr types.path;
51 The path to a file containing the password salt to use for Wakapi.
55 smtpPassword = mkOption {
56 type = types.nullOr types.str;
59 The password used for the smtp mailed to used by Wakapi.
62 smtpPasswordFile = mkOption {
63 type = types.nullOr types.path;
66 The path to a file containing the password for the smtp mailer used by Wakapi.
71 config = mkIf cfg.enable {
72 systemd.services.wakapi = {
73 description = "Wakapi (self-hosted WakaTime-compatible backend)";
75 "network-online.target"
76 ] ++ optional (cfg.settings.db.dialect == "postgres") "postgresql.service";
78 "network-online.target"
79 ] ++ optional (cfg.settings.db.dialect == "postgres") "postgresql.service";
80 wantedBy = [ "multi-user.target" ];
83 exec ${getExe cfg.package} -config ${settingsFile}
87 Environment = mkMerge [
88 (mkIf (cfg.passwordSalt != null) "WAKAPI_PASSWORD_SALT=${cfg.passwordSalt}")
89 (mkIf (cfg.smtpPassword != null) "WAKAPI_MAIL_SMTP_PASS=${cfg.smtpPassword}")
92 (optional (cfg.passwordSaltFile != null) cfg.passwordSaltFile)
93 (optional (cfg.smtpPasswordFile != null) cfg.smtpPasswordFile)
96 User = config.users.users.wakapi.name;
97 Group = config.users.users.wakapi.group;
101 ProtectHostname = true;
102 ProtectKernelLogs = true;
103 ProtectKernelModules = true;
104 ProtectKernelTunables = true;
105 ProtectProc = "invisible";
106 ProtectSystem = "strict";
107 RestrictAddressFamilies = [
112 RestrictNamespaces = true;
113 RestrictRealtime = true;
114 RestrictSUIDSGID = true;
115 StateDirectory = "wakapi";
116 StateDirectoryMode = "0700";
121 services.wakapi.settings = {
122 env = lib.mkDefault "production";
127 assertion = cfg.passwordSalt != null || cfg.passwordSaltFile != null;
128 message = "Either `services.wakapi.passwordSalt` or `services.wakapi.passwordSaltFile` must be set.";
131 assertion = cfg.passwordSalt != null -> cfg.passwordSaltFile != null;
132 message = "Both `services.wakapi.passwordSalt` `services.wakapi.passwordSaltFile` should not be set at the same time.";
135 assertion = cfg.smtpPassword != null -> cfg.smtpPasswordFile != null;
136 message = "Both `services.wakapi.smtpPassword` `services.wakapi.smtpPasswordFile` should not be set at the same time.";
149 services.postgresql = mkIf (cfg.settings.db.dialect == "postgres") {
152 ensureDatabases = singleton cfg.settings.db.name;
153 ensureUsers = singleton {
154 name = cfg.settings.db.user;
155 ensureDBOwnership = true;
159 host ${cfg.settings.db.name} ${cfg.settings.db.user} 127.0.0.1/32 trust
164 meta.maintainers = with lib.maintainers; [ isabelroses ];