1{
2 lib,
3 config,
4 pkgs,
5 ...
6}:
7let
8 cfg = config.services.sitespeed-io;
9 format = pkgs.formats.json { };
10in
11{
12 options.services.sitespeed-io = {
13 enable = lib.mkEnableOption "Sitespeed.io";
14
15 user = lib.mkOption {
16 type = lib.types.str;
17 default = "sitespeed-io";
18 description = "User account under which sitespeed-io runs.";
19 };
20
21 package = lib.mkOption {
22 type = lib.types.package;
23 default = pkgs.sitespeed-io;
24 defaultText = "pkgs.sitespeed-io";
25 description = "Sitespeed.io package to use.";
26 };
27
28 dataDir = lib.mkOption {
29 default = "/var/lib/sitespeed-io";
30 type = lib.types.str;
31 description = "The base sitespeed-io data directory.";
32 };
33
34 period = lib.mkOption {
35 type = lib.types.str;
36 default = "hourly";
37 description = ''
38 Systemd calendar expression when to run. See {manpage}`systemd.time(7)`.
39 '';
40 };
41
42 runs = lib.mkOption {
43 default = [ ];
44 description = ''
45 A list of run configurations. The service will call sitespeed-io once
46 for every run listed here. This lets you examine different websites
47 with different sitespeed-io settings.
48 '';
49 type = lib.types.listOf (
50 lib.types.submodule {
51 options = {
52 urls = lib.mkOption {
53 type = with lib.types; listOf str;
54 default = [ ];
55 description = ''
56 URLs the service should monitor.
57 '';
58 };
59
60 settings = lib.mkOption {
61 type = lib.types.submodule {
62 freeformType = format.type;
63 options = { };
64 };
65 default = { };
66 description = ''
67 Configuration for sitespeed-io, see
68 <https://www.sitespeed.io/documentation/sitespeed.io/configuration/>
69 for available options. The value here will be directly transformed to
70 JSON and passed as `--config` to the program.
71 '';
72 };
73
74 extraArgs = lib.mkOption {
75 type = with lib.types; listOf str;
76 default = [ ];
77 description = ''
78 Extra command line arguments to pass to the program.
79 '';
80 };
81 };
82 }
83 );
84 };
85 };
86
87 config = lib.mkIf cfg.enable {
88 assertions = [
89 {
90 assertion = cfg.runs != [ ];
91 message = "At least one run must be configured.";
92 }
93 {
94 assertion = lib.all (run: run.urls != [ ]) cfg.runs;
95 message = "All runs must have at least one url configured.";
96 }
97 ];
98
99 systemd.services.sitespeed-io = {
100 description = "Check website status";
101 startAt = cfg.period;
102 serviceConfig = {
103 WorkingDirectory = cfg.dataDir;
104 User = cfg.user;
105 };
106 preStart = "chmod u+w -R ${cfg.dataDir}"; # Make sure things are writable
107 script =
108 (lib.concatMapStrings (run: ''
109 ${lib.getExe cfg.package} \
110 --config ${format.generate "sitespeed.json" run.settings} \
111 ${lib.escapeShellArgs run.extraArgs} \
112 ${builtins.toFile "urls.txt" (lib.concatLines run.urls)} &
113 '') cfg.runs)
114 + ''
115 wait
116 '';
117 };
118
119 users = {
120 extraUsers.${cfg.user} = {
121 isSystemUser = true;
122 group = cfg.user;
123 home = cfg.dataDir;
124 createHome = true;
125 homeMode = "755";
126 };
127 extraGroups.${cfg.user} = { };
128 };
129 };
130}