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 # This a HACK to fix missing dependencies of dynamic libs extracted from jars
65 environment.LD_LIBRARY_PATH = with pkgs.stdenv; "${cc.cc}/lib";
66
67 preStart = ''
68 # Ensure privacy of state
69 chown unifi "${stateDir}"
70 chmod 0700 "${stateDir}"
71
72 # Create the volatile webapps
73 rm -rf "${stateDir}/webapps"
74 mkdir -p "${stateDir}/webapps"
75 chown unifi "${stateDir}/webapps"
76 ln -s "${pkgs.unifi}/webapps/ROOT" "${stateDir}/webapps/ROOT"
77 '';
78
79 postStop = ''
80 rm -rf "${stateDir}/webapps"
81 '';
82
83 serviceConfig = {
84 Type = "simple";
85 ExecStart = "${cmd} start";
86 ExecStop = "${cmd} stop";
87 User = "unifi";
88 PermissionsStartOnly = true;
89 UMask = "0077";
90 WorkingDirectory = "${stateDir}";
91 };
92 };
93
94 };
95
96}