at 17.09-beta 4.7 kB view raw
1{ config, lib, pkgs, utils, ... }: 2with lib; 3let 4 cfg = config.services.unifi; 5 stateDir = "/var/lib/unifi"; 6 cmd = '' 7 @${pkgs.jre}/bin/java java \ 8 ${optionalString (cfg.initialJavaHeapSize != null) "-Xms${(toString cfg.initialJavaHeapSize)}m"} \ 9 ${optionalString (cfg.maximumJavaHeapSize != null) "-Xmx${(toString cfg.maximumJavaHeapSize)}m"} \ 10 -jar ${stateDir}/lib/ace.jar 11 ''; 12 mountPoints = [ 13 { 14 what = "${pkgs.unifi}/dl"; 15 where = "${stateDir}/dl"; 16 } 17 { 18 what = "${pkgs.unifi}/lib"; 19 where = "${stateDir}/lib"; 20 } 21 { 22 what = "${pkgs.mongodb}/bin"; 23 where = "${stateDir}/bin"; 24 } 25 { 26 what = "${cfg.dataDir}"; 27 where = "${stateDir}/data"; 28 } 29 ]; 30 systemdMountPoints = map (m: "${utils.escapeSystemdPath m.where}.mount") mountPoints; 31in 32{ 33 34 options = { 35 36 services.unifi.enable = mkOption { 37 type = types.bool; 38 default = false; 39 description = '' 40 Whether or not to enable the unifi controller service. 41 ''; 42 }; 43 44 services.unifi.dataDir = mkOption { 45 type = types.str; 46 default = "${stateDir}/data"; 47 description = '' 48 Where to store the database and other data. 49 50 This directory will be bind-mounted to ${stateDir}/data as part of the service startup. 51 ''; 52 }; 53 54 services.unifi.openPorts = mkOption { 55 type = types.bool; 56 default = true; 57 description = '' 58 Whether or not to open the minimum required ports on the firewall. 59 60 This is necessary to allow firmware upgrades and device discovery to 61 work. For remote login, you should additionally open (or forward) port 62 8443. 63 ''; 64 }; 65 66 services.unifi.initialJavaHeapSize = mkOption { 67 type = types.nullOr types.int; 68 default = null; 69 example = 1024; 70 description = '' 71 Set the initial heap size for the JVM in MB. If this option isn't set, the 72 JVM will decide this value at runtime. 73 ''; 74 }; 75 76 services.unifi.maximumJavaHeapSize = mkOption { 77 type = types.nullOr types.int; 78 default = null; 79 example = 4096; 80 description = '' 81 Set the maximimum heap size for the JVM in MB. If this option isn't set, the 82 JVM will decide this value at runtime. 83 ''; 84 }; 85 86 }; 87 88 config = mkIf cfg.enable { 89 90 users.extraUsers.unifi = { 91 uid = config.ids.uids.unifi; 92 description = "UniFi controller daemon user"; 93 home = "${stateDir}"; 94 }; 95 96 networking.firewall = mkIf cfg.openPorts { 97 # https://help.ubnt.com/hc/en-us/articles/204910084-UniFi-Change-Default-Ports-for-Controller-and-UAPs 98 allowedTCPPorts = [ 99 8080 # Port for UAP to inform controller. 100 8880 # Port for HTTP portal redirect, if guest portal is enabled. 101 8843 # Port for HTTPS portal redirect, ditto. 102 ]; 103 allowedUDPPorts = [ 104 3478 # UDP port used for STUN. 105 10001 # UDP port used for device discovery. 106 ]; 107 }; 108 109 # We must create the binary directories as bind mounts instead of symlinks 110 # This is because the controller resolves all symlinks to absolute paths 111 # to be used as the working directory. 112 systemd.mounts = map ({ what, where }: { 113 bindsTo = [ "unifi.service" ]; 114 partOf = [ "unifi.service" ]; 115 unitConfig.RequiresMountsFor = stateDir; 116 options = "bind"; 117 what = what; 118 where = where; 119 }) mountPoints; 120 121 systemd.services.unifi = { 122 description = "UniFi controller daemon"; 123 wantedBy = [ "multi-user.target" ]; 124 after = [ "network.target" ] ++ systemdMountPoints; 125 partOf = systemdMountPoints; 126 bindsTo = systemdMountPoints; 127 unitConfig.RequiresMountsFor = stateDir; 128 # This a HACK to fix missing dependencies of dynamic libs extracted from jars 129 environment.LD_LIBRARY_PATH = with pkgs.stdenv; "${cc.cc.lib}/lib"; 130 131 preStart = '' 132 # Ensure privacy of state and data. 133 chown unifi "${stateDir}" "${stateDir}/data" 134 chmod 0700 "${stateDir}" "${stateDir}/data" 135 136 # Create the volatile webapps 137 rm -rf "${stateDir}/webapps" 138 mkdir -p "${stateDir}/webapps" 139 chown unifi "${stateDir}/webapps" 140 ln -s "${pkgs.unifi}/webapps/ROOT" "${stateDir}/webapps/ROOT" 141 ''; 142 143 postStop = '' 144 rm -rf "${stateDir}/webapps" 145 ''; 146 147 serviceConfig = { 148 Type = "simple"; 149 ExecStart = "${(removeSuffix "\n" cmd)} start"; 150 ExecStop = "${(removeSuffix "\n" cmd)} stop"; 151 User = "unifi"; 152 PermissionsStartOnly = true; 153 UMask = "0077"; 154 WorkingDirectory = "${stateDir}"; 155 }; 156 }; 157 158 }; 159 160}