1{ config, lib, pkgs, utils, ... }:
2with lib;
3let
4 cfg = config.services.unifi;
5 stateDir = "/var/lib/unifi";
6 cmd = "@${pkgs.jre}/bin/java java -jar ${stateDir}/lib/ace.jar";
7 mountPoints = [
8 {
9 what = "${pkgs.unifi}/dl";
10 where = "${stateDir}/dl";
11 }
12 {
13 what = "${pkgs.unifi}/lib";
14 where = "${stateDir}/lib";
15 }
16 {
17 what = "${pkgs.mongodb}/bin";
18 where = "${stateDir}/bin";
19 }
20 ];
21 systemdMountPoints = map (m: "${utils.escapeSystemdPath m.where}.mount") mountPoints;
22in
23{
24
25 options = {
26
27 services.unifi.enable = mkOption {
28 type = types.bool;
29 default = false;
30 description = ''
31 Whether or not to enable the unifi controller service.
32 '';
33 };
34
35 };
36
37 config = mkIf cfg.enable {
38
39 users.extraUsers.unifi = {
40 uid = config.ids.uids.unifi;
41 description = "UniFi controller daemon user";
42 home = "${stateDir}";
43 };
44
45 # We must create the binary directories as bind mounts instead of symlinks
46 # This is because the controller resolves all symlinks to absolute paths
47 # to be used as the working directory.
48 systemd.mounts = map ({ what, where }: {
49 bindsTo = [ "unifi.service" ];
50 partOf = [ "unifi.service" ];
51 unitConfig.RequiresMountsFor = stateDir;
52 options = "bind";
53 what = what;
54 where = where;
55 }) mountPoints;
56
57 systemd.services.unifi = {
58 description = "UniFi controller daemon";
59 wantedBy = [ "multi-user.target" ];
60 after = [ "network.target" ] ++ systemdMountPoints;
61 partOf = systemdMountPoints;
62 bindsTo = systemdMountPoints;
63 unitConfig.RequiresMountsFor = stateDir;
64
65 preStart = ''
66 # Ensure privacy of state
67 chown unifi "${stateDir}"
68 chmod 0700 "${stateDir}"
69
70 # Create the volatile webapps
71 rm -rf "${stateDir}/webapps"
72 mkdir -p "${stateDir}/webapps"
73 chown unifi "${stateDir}/webapps"
74 ln -s "${pkgs.unifi}/webapps/ROOT" "${stateDir}/webapps/ROOT"
75 '';
76
77 postStop = ''
78 rm -rf "${stateDir}/webapps"
79 '';
80
81 serviceConfig = {
82 Type = "simple";
83 ExecStart = "${cmd} start";
84 ExecStop = "${cmd} stop";
85 User = "unifi";
86 PermissionsStartOnly = true;
87 UMask = "0077";
88 WorkingDirectory = "${stateDir}";
89 };
90 };
91
92 };
93
94}