5e9e1146e1
GitOrigin-RevId: 18036c0be90f4e308ae3ebcab0e14aae0336fe42
271 lines
8.3 KiB
Nix
271 lines
8.3 KiB
Nix
{ config, pkgs, lib, ... }: with lib; let
|
|
cfg = config.services.sogo;
|
|
|
|
preStart = pkgs.writeShellScriptBin "sogo-prestart" ''
|
|
touch /etc/sogo/sogo.conf
|
|
chown sogo:sogo /etc/sogo/sogo.conf
|
|
chmod 640 /etc/sogo/sogo.conf
|
|
|
|
${if (cfg.configReplaces != {}) then ''
|
|
# Insert secrets
|
|
${concatStringsSep "\n" (mapAttrsToList (k: v: ''export ${k}="$(cat "${v}" | tr -d '\n')"'') cfg.configReplaces)}
|
|
|
|
${pkgs.perl}/bin/perl -p ${concatStringsSep " " (mapAttrsToList (k: v: '' -e 's/${k}/''${ENV{"${k}"}}/g;' '') cfg.configReplaces)} /etc/sogo/sogo.conf.raw > /etc/sogo/sogo.conf
|
|
'' else ''
|
|
cp /etc/sogo/sogo.conf.raw /etc/sogo/sogo.conf
|
|
''}
|
|
'';
|
|
|
|
in {
|
|
options.services.sogo = with types; {
|
|
enable = mkEnableOption (lib.mdDoc "SOGo groupware");
|
|
|
|
vhostName = mkOption {
|
|
description = lib.mdDoc "Name of the nginx vhost";
|
|
type = str;
|
|
default = "sogo";
|
|
};
|
|
|
|
timezone = mkOption {
|
|
description = lib.mdDoc "Timezone of your SOGo instance";
|
|
type = str;
|
|
example = "America/Montreal";
|
|
};
|
|
|
|
language = mkOption {
|
|
description = lib.mdDoc "Language of SOGo";
|
|
type = str;
|
|
default = "English";
|
|
};
|
|
|
|
ealarmsCredFile = mkOption {
|
|
description = lib.mdDoc "Optional path to a credentials file for email alarms";
|
|
type = nullOr str;
|
|
default = null;
|
|
};
|
|
|
|
configReplaces = mkOption {
|
|
description = lib.mdDoc ''
|
|
Replacement-filepath mapping for sogo.conf.
|
|
Every key is replaced with the contents of the file specified as value.
|
|
|
|
In the example, every occurrence of LDAP_BINDPW will be replaced with the text of the
|
|
specified file.
|
|
'';
|
|
type = attrsOf str;
|
|
default = {};
|
|
example = {
|
|
LDAP_BINDPW = "/var/lib/secrets/sogo/ldappw";
|
|
};
|
|
};
|
|
|
|
extraConfig = mkOption {
|
|
description = lib.mdDoc "Extra sogo.conf configuration lines";
|
|
type = lines;
|
|
default = "";
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
environment.systemPackages = [ pkgs.sogo ];
|
|
|
|
environment.etc."sogo/sogo.conf.raw".text = ''
|
|
{
|
|
// Mandatory parameters
|
|
SOGoTimeZone = "${cfg.timezone}";
|
|
SOGoLanguage = "${cfg.language}";
|
|
// Paths
|
|
WOSendMail = "/run/wrappers/bin/sendmail";
|
|
SOGoMailSpoolPath = "/var/lib/sogo/spool";
|
|
// Enable CSRF protection
|
|
SOGoXSRFValidationEnabled = YES;
|
|
// Remove dates from log (jornald does that)
|
|
NGLogDefaultLogEventFormatterClass = "NGLogEventFormatter";
|
|
// Extra config
|
|
${cfg.extraConfig}
|
|
}
|
|
'';
|
|
|
|
systemd.services.sogo = {
|
|
description = "SOGo groupware";
|
|
after = [ "postgresql.service" "mysql.service" "memcached.service" "openldap.service" "dovecot2.service" ];
|
|
wantedBy = [ "multi-user.target" ];
|
|
restartTriggers = [ config.environment.etc."sogo/sogo.conf.raw".source ];
|
|
|
|
environment.LDAPTLS_CACERT = "/etc/ssl/certs/ca-certificates.crt";
|
|
|
|
serviceConfig = {
|
|
Type = "forking";
|
|
ExecStartPre = "+" + preStart + "/bin/sogo-prestart";
|
|
ExecStart = "${pkgs.sogo}/bin/sogod -WOLogFile - -WOPidFile /run/sogo/sogo.pid";
|
|
|
|
ProtectSystem = "strict";
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
PrivateDevices = true;
|
|
ProtectKernelTunables = true;
|
|
ProtectKernelModules = true;
|
|
ProtectControlGroups = true;
|
|
RuntimeDirectory = "sogo";
|
|
StateDirectory = "sogo/spool";
|
|
|
|
User = "sogo";
|
|
Group = "sogo";
|
|
|
|
CapabilityBoundingSet = "";
|
|
NoNewPrivileges = true;
|
|
|
|
LockPersonality = true;
|
|
RestrictRealtime = true;
|
|
PrivateMounts = true;
|
|
PrivateUsers = true;
|
|
MemoryDenyWriteExecute = true;
|
|
SystemCallFilter = "@basic-io @file-system @network-io @system-service @timer";
|
|
SystemCallArchitectures = "native";
|
|
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
|
};
|
|
};
|
|
|
|
systemd.services.sogo-tmpwatch = {
|
|
description = "SOGo tmpwatch";
|
|
|
|
startAt = [ "hourly" ];
|
|
script = ''
|
|
SOGOSPOOL=/var/lib/sogo/spool
|
|
|
|
find "$SOGOSPOOL" -type f -user sogo -atime +23 -delete > /dev/null
|
|
find "$SOGOSPOOL" -mindepth 1 -type d -user sogo -empty -delete > /dev/null
|
|
'';
|
|
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
|
|
ProtectSystem = "strict";
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
PrivateDevices = true;
|
|
ProtectKernelTunables = true;
|
|
ProtectKernelModules = true;
|
|
ProtectControlGroups = true;
|
|
StateDirectory = "sogo/spool";
|
|
|
|
User = "sogo";
|
|
Group = "sogo";
|
|
|
|
CapabilityBoundingSet = "";
|
|
NoNewPrivileges = true;
|
|
|
|
LockPersonality = true;
|
|
RestrictRealtime = true;
|
|
PrivateMounts = true;
|
|
PrivateUsers = true;
|
|
PrivateNetwork = true;
|
|
SystemCallFilter = "@basic-io @file-system @system-service";
|
|
SystemCallArchitectures = "native";
|
|
RestrictAddressFamilies = "";
|
|
};
|
|
};
|
|
|
|
systemd.services.sogo-ealarms = {
|
|
description = "SOGo email alarms";
|
|
|
|
after = [ "postgresql.service" "mysqld.service" "memcached.service" "openldap.service" "dovecot2.service" "sogo.service" ];
|
|
restartTriggers = [ config.environment.etc."sogo/sogo.conf.raw".source ];
|
|
|
|
startAt = [ "minutely" ];
|
|
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
ExecStart = "${pkgs.sogo}/bin/sogo-ealarms-notify${optionalString (cfg.ealarmsCredFile != null) " -p ${cfg.ealarmsCredFile}"}";
|
|
|
|
ProtectSystem = "strict";
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
PrivateDevices = true;
|
|
ProtectKernelTunables = true;
|
|
ProtectKernelModules = true;
|
|
ProtectControlGroups = true;
|
|
StateDirectory = "sogo/spool";
|
|
|
|
User = "sogo";
|
|
Group = "sogo";
|
|
|
|
CapabilityBoundingSet = "";
|
|
NoNewPrivileges = true;
|
|
|
|
LockPersonality = true;
|
|
RestrictRealtime = true;
|
|
PrivateMounts = true;
|
|
PrivateUsers = true;
|
|
MemoryDenyWriteExecute = true;
|
|
SystemCallFilter = "@basic-io @file-system @network-io @system-service";
|
|
SystemCallArchitectures = "native";
|
|
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
|
};
|
|
};
|
|
|
|
# nginx vhost
|
|
services.nginx.virtualHosts."${cfg.vhostName}" = {
|
|
locations."/".extraConfig = ''
|
|
rewrite ^ https://$server_name/SOGo;
|
|
allow all;
|
|
'';
|
|
|
|
# For iOS 7
|
|
locations."/principals/".extraConfig = ''
|
|
rewrite ^ https://$server_name/SOGo/dav;
|
|
allow all;
|
|
'';
|
|
|
|
locations."^~/SOGo".extraConfig = ''
|
|
proxy_pass http://127.0.0.1:20000;
|
|
proxy_redirect http://127.0.0.1:20000 default;
|
|
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header x-webobjects-server-protocol HTTP/1.0;
|
|
proxy_set_header x-webobjects-remote-host 127.0.0.1;
|
|
proxy_set_header x-webobjects-server-port $server_port;
|
|
proxy_set_header x-webobjects-server-name $server_name;
|
|
proxy_set_header x-webobjects-server-url $scheme://$host;
|
|
proxy_connect_timeout 90;
|
|
proxy_send_timeout 90;
|
|
proxy_read_timeout 90;
|
|
proxy_buffer_size 64k;
|
|
proxy_buffers 8 64k;
|
|
proxy_busy_buffers_size 64k;
|
|
proxy_temp_file_write_size 64k;
|
|
client_max_body_size 50m;
|
|
client_body_buffer_size 128k;
|
|
break;
|
|
'';
|
|
|
|
locations."/SOGo.woa/WebServerResources/".extraConfig = ''
|
|
alias ${pkgs.sogo}/lib/GNUstep/SOGo/WebServerResources/;
|
|
allow all;
|
|
'';
|
|
|
|
locations."/SOGo/WebServerResources/".extraConfig = ''
|
|
alias ${pkgs.sogo}/lib/GNUstep/SOGo/WebServerResources/;
|
|
allow all;
|
|
'';
|
|
|
|
locations."~ ^/SOGo/so/ControlPanel/Products/([^/]*)/Resources/(.*)$".extraConfig = ''
|
|
alias ${pkgs.sogo}/lib/GNUstep/SOGo/$1.SOGo/Resources/$2;
|
|
'';
|
|
|
|
locations."~ ^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\\.(jpg|png|gif|css|js)$".extraConfig = ''
|
|
alias ${pkgs.sogo}/lib/GNUstep/SOGo/$1.SOGo/Resources/$2;
|
|
'';
|
|
};
|
|
|
|
# User and group
|
|
users.groups.sogo = {};
|
|
users.users.sogo = {
|
|
group = "sogo";
|
|
isSystemUser = true;
|
|
description = "SOGo service user";
|
|
};
|
|
};
|
|
}
|