Merge pull request #79175 from helsinki-systems/init/sogo

sogo: init at 4.3.2
This commit is contained in:
Lassulus 2020-05-22 11:04:39 +02:00 committed by GitHub
commit d84d8e802e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 460 additions and 2 deletions

View file

@ -847,6 +847,7 @@
./services/web-apps/matomo.nix
./services/web-apps/moinmoin.nix
./services/web-apps/restya-board.nix
./services/web-apps/sogo.nix
./services/web-apps/tt-rss.nix
./services/web-apps/trac.nix
./services/web-apps/trilium.nix

View file

@ -0,0 +1,272 @@
{ 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 "SOGo groupware";
vhostName = mkOption {
description = "Name of the nginx vhost";
type = str;
default = "sogo";
};
timezone = mkOption {
description = "Timezone of your SOGo instance";
type = str;
example = "America/Montreal";
};
language = mkOption {
description = "Language of SOGo";
type = str;
default = "English";
};
ealarmsCredFile = mkOption {
description = "Optional path to a credentials file for email alarms";
type = nullOr str;
default = null;
};
configReplaces = mkOption {
description = ''
Replacement-filepath mapping for sogo.conf.
Every key is replaced with the contents of the file specified as value.
In the example, every occurence 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 = "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";
SOGoZipPath = "${pkgs.zip}/bin/zip";
// 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 4k;
proxy_buffers 4 32k;
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";
};
};
}

View file

@ -292,6 +292,7 @@ in
slurm = handleTest ./slurm.nix {};
smokeping = handleTest ./smokeping.nix {};
snapper = handleTest ./snapper.nix {};
sogo = handleTest ./sogo.nix {};
solr = handleTest ./solr.nix {};
spacecookie = handleTest ./spacecookie.nix {};
spike = handleTest ./spike.nix {};

58
nixos/tests/sogo.nix Normal file
View file

@ -0,0 +1,58 @@
import ./make-test-python.nix ({ pkgs, ... }: {
name = "sogo";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ ajs124 das_j ];
};
nodes = {
sogo = { config, pkgs, ... }: {
services.nginx.enable = true;
services.mysql = {
enable = true;
package = pkgs.mysql;
ensureDatabases = [ "sogo" ];
ensureUsers = [{
name = "sogo";
ensurePermissions = {
"sogo.*" = "ALL PRIVILEGES";
};
}];
};
services.sogo = {
enable = true;
timezone = "Europe/Berlin";
extraConfig = ''
WOWorkersCount = 1;
SOGoUserSources = (
{
type = sql;
userPasswordAlgorithm = md5;
viewURL = "mysql://sogo@%2Frun%2Fmysqld%2Fmysqld.sock/sogo/sogo_users";
canAuthenticate = YES;
id = users;
}
);
SOGoProfileURL = "mysql://sogo@%2Frun%2Fmysqld%2Fmysqld.sock/sogo/sogo_user_profile";
OCSFolderInfoURL = "mysql://sogo@%2Frun%2Fmysqld%2Fmysqld.sock/sogo/sogo_folder_info";
OCSSessionsFolderURL = "mysql://sogo@%2Frun%2Fmysqld%2Fmysqld.sock/sogo/sogo_sessions_folder";
OCSEMailAlarmsFolderURL = "mysql://sogo@%2Frun%2Fmysqld%2Fmysqld.sock/sogo/sogo_alarms_folder";
OCSStoreURL = "mysql://sogo@%2Frun%2Fmysqld%2Fmysqld.sock/sogo/sogo_store";
OCSAclURL = "mysql://sogo@%2Frun%2Fmysqld%2Fmysqld.sock/sogo/sogo_acl";
OCSCacheFolderURL = "mysql://sogo@%2Frun%2Fmysqld%2Fmysqld.sock/sogo/sogo_cache_folder";
'';
};
};
};
testScript = ''
start_all()
sogo.wait_for_unit("multi-user.target")
sogo.wait_for_open_port(20000)
sogo.wait_for_open_port(80)
sogo.succeed("curl -sSfL http://sogo/SOGo")
'';
})

View file

@ -2,13 +2,13 @@
stdenv.mkDerivation rec {
pname = "libobjc2";
version = "2.0";
version = "1.9";
src = fetchFromGitHub {
owner = "gnustep";
repo = "libobjc2";
rev = "v${version}";
sha256 = "1b4h0a4pqr8j6300qr2wmi33r7ysvp705gs0ypx69hbmifln0mlf";
sha256 = "00pscl3ly3rv6alf9vk70kxnnxq2rfgpc1ylcv6cgjs9jxdnrqmn";
};
nativeBuildInputs = [ cmake ];

View file

@ -0,0 +1,46 @@
{ gnustep, lib, fetchFromGitHub , libxml2, openssl_1_1
, openldap, mysql, libmysqlclient, postgresql }: with lib; gnustep.stdenv.mkDerivation rec {
pname = "sope";
version = "4.3.2";
src = fetchFromGitHub {
owner = "inverse-inc";
repo = pname;
rev = "SOPE-${version}";
sha256 = "0ny1ihx38gd25w8f3dfybyswvyjfljvb2fhfmkajgg6hhjrkfar2";
};
nativeBuildInputs = [ gnustep.make ];
buildInputs = flatten ([ gnustep.base libxml2 openssl_1_1 ]
++ optional (openldap != null) openldap
++ optionals (mysql != null) [ libmysqlclient mysql ]
++ optional (postgresql != null) postgresql);
postPatch = ''
# Exclude NIX_ variables
sed -i 's/grep GNUSTEP_/grep ^GNUSTEP_/g' configure
'';
preConfigure = ''
export DESTDIR="$out"
'';
configureFlags = [ "--prefix=" "--disable-debug" "--enable-xml" "--with-ssl=ssl" ]
++ optional (openldap != null) "--enable-openldap"
++ optional (mysql != null) "--enable-mysql"
++ optional (postgresql != null) "--enable-postgresql";
# Yes, this is ugly.
preFixup = ''
cp -rlPa $out/nix/store/*/* $out
rm -rf $out/nix/store
'';
meta = {
description = "SOPE is an extensive set of frameworks which form a complete Web application server environment";
license = licenses.publicDomain;
homepage = "https://github.com/inverse-inc/sope";
platforms = platforms.linux;
maintainers = with maintainers; [ ajs124 das_j ];
};
}

View file

@ -0,0 +1,76 @@
{ gnustep, lib, fetchFromGitHub, fetchpatch, makeWrapper, python2, lndir
, openssl_1_1, openldap, sope, libmemcached, curl }: with lib; gnustep.stdenv.mkDerivation rec {
pname = "SOGo";
version = "4.3.2";
src = fetchFromGitHub {
owner = "inverse-inc";
repo = pname;
rev = "SOGo-${version}";
sha256 = "1xxad23a8zy6w850x5nrrf54db0x73lc9drmc5kpfk870fk2lmr0";
};
nativeBuildInputs = [ gnustep.make makeWrapper python2 ];
buildInputs = [ gnustep.base sope openssl_1_1 libmemcached (curl.override { openssl = openssl_1_1; }) ]
++ optional (openldap != null) openldap;
patches = [
# TODO: take a closer look at other patches in https://sources.debian.org/patches/sogo/ and https://github.com/Skrupellos/sogo-patches
(fetchpatch {
url = "https://sources.debian.org/data/main/s/sogo/4.3.0-1/debian/patches/0005-Remove-build-date.patch";
sha256 = "0lrh3bkfj3r0brahfkyb0g7zx7r2jjd5cxzjl43nqla0fs09wsh8";
})
];
postPatch = ''
# Exclude NIX_ variables
sed -i 's/grep GNUSTEP_/grep ^GNUSTEP_/g' configure
# Disable argument verification because $out is not a GNUStep prefix
sed -i 's/^validateArgs$//g' configure
# Patch exception-generating python scripts
patchShebangs .
# Move all GNUStep makefiles to a common directory
mkdir -p makefiles
cp -r {${gnustep.make},${sope}}/share/GNUstep/Makefiles/* makefiles
# Modify the search path for GNUStep makefiles
find . -type f -name GNUmakefile -exec sed -i "s:\\$.GNUSTEP_MAKEFILES.:$PWD/makefiles:g" {} +
'';
configureFlags = [ "--disable-debug" "--with-ssl=ssl" ];
preFixup = ''
# Create gnustep.conf
mkdir -p $out/share/GNUstep
cp ${gnustep.make}/etc/GNUstep/GNUstep.conf $out/share/GNUstep/
sed -i "s:${gnustep.make}:$out:g" $out/share/GNUstep/GNUstep.conf
# Link in GNUstep base
${lndir}/bin/lndir ${gnustep.base}/lib/GNUstep/ $out/lib/GNUstep/
# Link in sope
${lndir}/bin/lndir ${sope}/ $out/
# sbin fixup
mkdir -p $out/bin
mv $out/sbin/* $out/bin
rmdir $out/sbin
# Make sogo find its files
for bin in $out/bin/*; do
wrapProgram $bin --prefix LD_LIBRARY_PATH : $out/lib/sogo --prefix GNUSTEP_CONFIG_FILE : $out/share/GNUstep/GNUstep.conf
done
'';
meta = {
description = "SOGo is a very fast and scalable modern collaboration suite (groupware)";
license = with licenses; [ gpl2 lgpl21 ];
homepage = "https://sogo.nu/";
platforms = platforms.linux;
maintainers = with maintainers; [ ajs124 das_j ];
};
}

View file

@ -14612,6 +14612,8 @@ in
sonic = callPackage ../development/libraries/sonic { };
sope = callPackage ../development/libraries/sope { };
soprano = callPackage ../development/libraries/soprano { };
soqt = callPackage ../development/libraries/soqt { };
@ -16222,6 +16224,8 @@ in
smcroute = callPackage ../servers/smcroute { };
sogo = callPackage ../servers/web-apps/sogo { };
spawn_fcgi = callPackage ../servers/http/spawn-fcgi { };
spring-boot-cli = callPackage ../development/tools/spring-boot-cli { };