1{
2 config,
3 pkgs,
4 lib,
5 ...
6}:
7let
8 cfg = config.services.silverbullet;
9 defaultUser = "silverbullet";
10 defaultGroup = defaultUser;
11 defaultSpaceDir = "/var/lib/silverbullet";
12in
13{
14 options = {
15 services.silverbullet = {
16 enable = lib.mkEnableOption "Silverbullet, an open-source, self-hosted, offline-capable Personal Knowledge Management (PKM) web application";
17
18 package = lib.mkPackageOption pkgs "silverbullet" { };
19
20 openFirewall = lib.mkOption {
21 type = lib.types.bool;
22 default = false;
23 description = "Open port in the firewall.";
24 };
25
26 listenPort = lib.mkOption {
27 type = lib.types.int;
28 default = 3000;
29 description = "Port to listen on.";
30 };
31
32 listenAddress = lib.mkOption {
33 type = lib.types.str;
34 default = "127.0.0.1";
35 description = "Address or hostname to listen on. Defaults to 127.0.0.1.";
36 };
37
38 spaceDir = lib.mkOption {
39 type = lib.types.path;
40 default = defaultSpaceDir;
41 example = "/home/yourUser/silverbullet";
42 description = ''
43 Folder to store Silverbullet's space/workspace.
44 By default it is located at `${defaultSpaceDir}`.
45 '';
46 };
47
48 user = lib.mkOption {
49 type = lib.types.str;
50 default = defaultUser;
51 example = "yourUser";
52 description = ''
53 The user to run Silverbullet as.
54 By default, a user named `${defaultUser}` will be created whose space
55 directory is [spaceDir](#opt-services.silverbullet.spaceDir).
56 '';
57 };
58
59 group = lib.mkOption {
60 type = lib.types.str;
61 default = defaultGroup;
62 example = "yourGroup";
63 description = ''
64 The group to run Silverbullet under.
65 By default, a group named `${defaultGroup}` will be created.
66 '';
67 };
68
69 envFile = lib.mkOption {
70 type = lib.types.nullOr lib.types.path;
71 default = null;
72 example = "/etc/silverbullet.env";
73 description = ''
74 File containing extra environment variables. For example:
75
76 ```
77 SB_USER=user:password
78 SB_AUTH_TOKEN=abcdefg12345
79 ```
80 '';
81 };
82
83 extraArgs = lib.mkOption {
84 type = lib.types.listOf lib.types.str;
85 default = [ ];
86 example = [ "--db /path/to/silverbullet.db" ];
87 description = "Extra arguments passed to silverbullet.";
88 };
89 };
90 };
91
92 config = lib.mkIf cfg.enable {
93 systemd.services.silverbullet = {
94 description = "Silverbullet service";
95 after = [ "network.target" ];
96 wantedBy = [ "multi-user.target" ];
97
98 preStart = lib.mkIf (!lib.hasPrefix "/var/lib/" cfg.spaceDir) "mkdir -p '${cfg.spaceDir}'";
99 serviceConfig = {
100 Type = "simple";
101 User = "${cfg.user}";
102 Group = "${cfg.group}";
103 EnvironmentFile = lib.mkIf (cfg.envFile != null) "${cfg.envFile}";
104 StateDirectory = lib.mkIf (lib.hasPrefix "/var/lib/" cfg.spaceDir) (
105 lib.last (lib.splitString "/" cfg.spaceDir)
106 );
107 ExecStart =
108 "${lib.getExe cfg.package} --port ${toString cfg.listenPort} --hostname '${cfg.listenAddress}' '${cfg.spaceDir}' "
109 + lib.concatStringsSep " " cfg.extraArgs;
110 Restart = "on-failure";
111 };
112 };
113
114 networking.firewall = lib.mkIf cfg.openFirewall {
115 allowedTCPPorts = [ cfg.listenPort ];
116 };
117
118 users.users.${defaultUser} = lib.mkIf (cfg.user == defaultUser) {
119 isSystemUser = true;
120 group = cfg.group;
121 description = "Silverbullet daemon user";
122 };
123
124 users.groups.${defaultGroup} = lib.mkIf (cfg.group == defaultGroup) { };
125 };
126
127 meta.maintainers = with lib.maintainers; [ aorith ];
128}