1{
2 lib,
3 ...
4}:
5
6let
7 userStoragePath = "/var/lib/foobar";
8 pluginPath = "${userStoragePath}/node_modules";
9in
10{
11 name = "homebridge";
12 meta.maintainers = with lib.maintainers; [ fmoda3 ];
13
14 nodes.homebridge =
15 { pkgs, ... }:
16 {
17 services.homebridge = {
18 enable = true;
19 inherit userStoragePath pluginPath;
20
21 settings = {
22 bridge = {
23 name = "Homebridge";
24 port = 51826;
25 };
26 };
27
28 uiSettings = {
29 port = 8581;
30 };
31 };
32
33 # Cause a configuration change inside `config.json` and verify that the process is being reloaded.
34 specialisation.differentName = {
35 inheritParentConfig = true;
36 configuration.services.homebridge.settings.bridge.name = lib.mkForce "Test Home";
37 };
38 };
39
40 testScript =
41 { nodes, ... }:
42 let
43 system = nodes.homebridge.system.build.toplevel;
44 in
45 ''
46 import json
47
48 start_all()
49
50
51 def get_homebridge_journal_cursor() -> str:
52 exit, out = homebridge.execute("journalctl -u homebridge.service -n1 -o json-pretty --output-fields=__CURSOR")
53 assert exit == 0
54 return json.loads(out)["__CURSOR"]
55
56
57 def wait_for_homebridge(cursor):
58 homebridge.wait_until_succeeds(f"journalctl --after-cursor='{cursor}' -u homebridge.service | grep -q 'Logging to'")
59
60
61 homebridge.wait_for_unit("homebridge.service")
62 homebridge_cursor = get_homebridge_journal_cursor()
63
64 with subtest("Check that JSON configuration file is in place"):
65 homebridge.succeed("test -f ${userStoragePath}/config.json")
66
67 with subtest("Check that Homebridge's web interface and API can be reached"):
68 wait_for_homebridge(homebridge_cursor)
69 homebridge.wait_for_open_port(51826)
70 homebridge.wait_for_open_port(8581)
71 homebridge.succeed("curl --fail http://localhost:8581/")
72
73 with subtest("Check service restart from SIGHUP"):
74 homebridge_pid = homebridge.succeed("systemctl show --property=MainPID homebridge.service")
75 homebridge_cursor = get_homebridge_journal_cursor()
76 homebridge.succeed("${system}/specialisation/differentName/bin/switch-to-configuration test")
77 wait_for_homebridge(homebridge_cursor)
78 new_homebridge_pid = homebridge.succeed("systemctl show --property=MainPID homebridge.service")
79 assert homebridge_pid != new_homebridge_pid, "The PID of the homebridge process must change after sending SIGHUP"
80
81 with subtest("Check that no errors were logged"):
82 homebridge.fail("journalctl -u homebridge -o cat | grep -q ERROR")
83
84 with subtest("Check systemd unit hardening"):
85 homebridge.log(homebridge.succeed("systemctl cat homebridge.service"))
86 homebridge.log(homebridge.succeed("systemd-analyze security homebridge.service"))
87 '';
88}