at 25.11-pre 8.7 kB view raw
1{ 2 config, 3 pkgs, 4 lib, 5 ... 6}: 7with lib; 8let 9 cfg = config.services.sogo; 10 11 preStart = pkgs.writeShellScriptBin "sogo-prestart" '' 12 ${ 13 if (cfg.configReplaces != { }) then 14 '' 15 # Insert secrets 16 ${concatStringsSep "\n" ( 17 mapAttrsToList (k: v: ''export ${k}="$(cat "${v}" | tr -d '\n')"'') cfg.configReplaces 18 )} 19 20 ${pkgs.perl}/bin/perl -p ${ 21 concatStringsSep " " ( 22 mapAttrsToList (k: v: ''-e 's/${k}/''${ENV{"${k}"}}/g;' '') cfg.configReplaces 23 ) 24 } /etc/sogo/sogo.conf.raw | install -m 640 -o sogo -g sogo /dev/stdin /etc/sogo/sogo.conf 25 '' 26 else 27 '' 28 install -m 640 -o sogo -g sogo /etc/sogo/sogo.conf.raw /etc/sogo/sogo.conf 29 '' 30 } 31 ''; 32 33in 34{ 35 options.services.sogo = with types; { 36 enable = mkEnableOption "SOGo groupware"; 37 38 vhostName = mkOption { 39 description = "Name of the nginx vhost"; 40 type = str; 41 default = "sogo"; 42 }; 43 44 timezone = mkOption { 45 description = "Timezone of your SOGo instance"; 46 type = str; 47 example = "America/Montreal"; 48 }; 49 50 language = mkOption { 51 description = "Language of SOGo"; 52 type = str; 53 default = "English"; 54 }; 55 56 ealarmsCredFile = mkOption { 57 description = "Optional path to a credentials file for email alarms"; 58 type = nullOr str; 59 default = null; 60 }; 61 62 configReplaces = mkOption { 63 description = '' 64 Replacement-filepath mapping for sogo.conf. 65 Every key is replaced with the contents of the file specified as value. 66 67 In the example, every occurrence of LDAP_BINDPW will be replaced with the text of the 68 specified file. 69 ''; 70 type = attrsOf str; 71 default = { }; 72 example = { 73 LDAP_BINDPW = "/var/lib/secrets/sogo/ldappw"; 74 }; 75 }; 76 77 extraConfig = mkOption { 78 description = "Extra sogo.conf configuration lines"; 79 type = lines; 80 default = ""; 81 }; 82 }; 83 84 config = mkIf cfg.enable { 85 environment.systemPackages = [ pkgs.sogo ]; 86 87 environment.etc."sogo/sogo.conf.raw".text = '' 88 { 89 // Mandatory parameters 90 SOGoTimeZone = "${cfg.timezone}"; 91 SOGoLanguage = "${cfg.language}"; 92 // Paths 93 WOSendMail = "/run/wrappers/bin/sendmail"; 94 SOGoMailSpoolPath = "/var/lib/sogo/spool"; 95 // Enable CSRF protection 96 SOGoXSRFValidationEnabled = YES; 97 // Remove dates from log (jornald does that) 98 NGLogDefaultLogEventFormatterClass = "NGLogEventFormatter"; 99 // Extra config 100 ${cfg.extraConfig} 101 } 102 ''; 103 104 systemd.services.sogo = { 105 description = "SOGo groupware"; 106 after = [ 107 "postgresql.service" 108 "mysql.service" 109 "memcached.service" 110 "openldap.service" 111 "dovecot2.service" 112 ]; 113 wantedBy = [ "multi-user.target" ]; 114 restartTriggers = [ config.environment.etc."sogo/sogo.conf.raw".source ]; 115 116 environment.LDAPTLS_CACERT = config.security.pki.caBundle; 117 118 serviceConfig = { 119 Type = "forking"; 120 ExecStartPre = "+" + preStart + "/bin/sogo-prestart"; 121 ExecStart = "${pkgs.sogo}/bin/sogod -WOLogFile - -WOPidFile /run/sogo/sogo.pid"; 122 123 ProtectSystem = "strict"; 124 ProtectHome = true; 125 PrivateTmp = true; 126 PrivateDevices = true; 127 ProtectKernelTunables = true; 128 ProtectKernelModules = true; 129 ProtectControlGroups = true; 130 RuntimeDirectory = "sogo"; 131 StateDirectory = "sogo/spool"; 132 133 User = "sogo"; 134 Group = "sogo"; 135 136 CapabilityBoundingSet = ""; 137 NoNewPrivileges = true; 138 139 LockPersonality = true; 140 RestrictRealtime = true; 141 PrivateMounts = true; 142 PrivateUsers = true; 143 MemoryDenyWriteExecute = true; 144 SystemCallFilter = "@basic-io @file-system @network-io @system-service @timer"; 145 SystemCallArchitectures = "native"; 146 RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; 147 }; 148 }; 149 150 systemd.services.sogo-tmpwatch = { 151 description = "SOGo tmpwatch"; 152 153 startAt = [ "hourly" ]; 154 script = '' 155 SOGOSPOOL=/var/lib/sogo/spool 156 157 find "$SOGOSPOOL" -type f -user sogo -atime +23 -delete > /dev/null 158 find "$SOGOSPOOL" -mindepth 1 -type d -user sogo -empty -delete > /dev/null 159 ''; 160 161 serviceConfig = { 162 Type = "oneshot"; 163 164 ProtectSystem = "strict"; 165 ProtectHome = true; 166 PrivateTmp = true; 167 PrivateDevices = true; 168 ProtectKernelTunables = true; 169 ProtectKernelModules = true; 170 ProtectControlGroups = true; 171 StateDirectory = "sogo/spool"; 172 173 User = "sogo"; 174 Group = "sogo"; 175 176 CapabilityBoundingSet = ""; 177 NoNewPrivileges = true; 178 179 LockPersonality = true; 180 RestrictRealtime = true; 181 PrivateMounts = true; 182 PrivateUsers = true; 183 PrivateNetwork = true; 184 SystemCallFilter = "@basic-io @file-system @system-service"; 185 SystemCallArchitectures = "native"; 186 RestrictAddressFamilies = ""; 187 }; 188 }; 189 190 systemd.services.sogo-ealarms = { 191 description = "SOGo email alarms"; 192 193 after = [ 194 "postgresql.service" 195 "mysqld.service" 196 "memcached.service" 197 "openldap.service" 198 "dovecot2.service" 199 "sogo.service" 200 ]; 201 restartTriggers = [ config.environment.etc."sogo/sogo.conf.raw".source ]; 202 203 startAt = [ "minutely" ]; 204 205 serviceConfig = { 206 Type = "oneshot"; 207 ExecStart = "${pkgs.sogo}/bin/sogo-ealarms-notify${ 208 optionalString (cfg.ealarmsCredFile != null) " -p ${cfg.ealarmsCredFile}" 209 }"; 210 211 ProtectSystem = "strict"; 212 ProtectHome = true; 213 PrivateTmp = true; 214 PrivateDevices = true; 215 ProtectKernelTunables = true; 216 ProtectKernelModules = true; 217 ProtectControlGroups = true; 218 StateDirectory = "sogo/spool"; 219 220 User = "sogo"; 221 Group = "sogo"; 222 223 CapabilityBoundingSet = ""; 224 NoNewPrivileges = true; 225 226 LockPersonality = true; 227 RestrictRealtime = true; 228 PrivateMounts = true; 229 PrivateUsers = true; 230 MemoryDenyWriteExecute = true; 231 SystemCallFilter = "@basic-io @file-system @network-io @system-service"; 232 SystemCallArchitectures = "native"; 233 RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; 234 }; 235 }; 236 237 # nginx vhost 238 services.nginx.virtualHosts."${cfg.vhostName}" = { 239 locations."/".extraConfig = '' 240 rewrite ^ https://$server_name/SOGo; 241 allow all; 242 ''; 243 244 # For iOS 7 245 locations."/principals/".extraConfig = '' 246 rewrite ^ https://$server_name/SOGo/dav; 247 allow all; 248 ''; 249 250 locations."^~/SOGo".extraConfig = '' 251 proxy_pass http://127.0.0.1:20000; 252 proxy_redirect http://127.0.0.1:20000 default; 253 254 proxy_set_header X-Real-IP $remote_addr; 255 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 256 proxy_set_header Host $host; 257 proxy_set_header x-webobjects-server-protocol HTTP/1.0; 258 proxy_set_header x-webobjects-remote-host 127.0.0.1; 259 proxy_set_header x-webobjects-server-port $server_port; 260 proxy_set_header x-webobjects-server-name $server_name; 261 proxy_set_header x-webobjects-server-url $scheme://$host; 262 proxy_connect_timeout 90; 263 proxy_send_timeout 90; 264 proxy_read_timeout 90; 265 proxy_buffer_size 64k; 266 proxy_buffers 8 64k; 267 proxy_busy_buffers_size 64k; 268 proxy_temp_file_write_size 64k; 269 client_max_body_size 50m; 270 client_body_buffer_size 128k; 271 break; 272 ''; 273 274 locations."/SOGo.woa/WebServerResources/".extraConfig = '' 275 alias ${pkgs.sogo}/lib/GNUstep/SOGo/WebServerResources/; 276 allow all; 277 ''; 278 279 locations."/SOGo/WebServerResources/".extraConfig = '' 280 alias ${pkgs.sogo}/lib/GNUstep/SOGo/WebServerResources/; 281 allow all; 282 ''; 283 284 locations."~ ^/SOGo/so/ControlPanel/Products/([^/]*)/Resources/(.*)$".extraConfig = '' 285 alias ${pkgs.sogo}/lib/GNUstep/SOGo/$1.SOGo/Resources/$2; 286 ''; 287 288 locations."~ ^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\\.(jpg|png|gif|css|js)$".extraConfig = 289 '' 290 alias ${pkgs.sogo}/lib/GNUstep/SOGo/$1.SOGo/Resources/$2; 291 ''; 292 }; 293 294 # User and group 295 users.groups.sogo = { }; 296 users.users.sogo = { 297 group = "sogo"; 298 isSystemUser = true; 299 description = "SOGo service user"; 300 }; 301 }; 302}