diff --git a/hosts/hainich/configuration.nix b/hosts/hainich/configuration.nix
index 5cc94e0..1ca4859 100644
--- a/hosts/hainich/configuration.nix
+++ b/hosts/hainich/configuration.nix
@@ -19,6 +19,7 @@
./services/syncthing.nix
./services/monitoring.nix
./services/workadventure.nix
+ ./services/limesurvey.nix
];
boot.loader.grub.enable = true;
boot.loader.grub.version = 2;
diff --git a/hosts/hainich/services/limesurvey.nix b/hosts/hainich/services/limesurvey.nix
new file mode 100644
index 0000000..23b93ba
--- /dev/null
+++ b/hosts/hainich/services/limesurvey.nix
@@ -0,0 +1,74 @@
+{config, pkgs, lib, ...}:
+
+{
+
+ containers.limesurvey = {
+ autoStart = true;
+ privateNetwork = true;
+ hostAddress = "192.168.100.40";
+ localAddress = "192.168.100.41";
+
+ config = {config, pkgs, lib, ...}: {
+ imports = [ ./../../../modules/limesurvey.nix ];
+
+ services.limesurvey-patched = {
+ enable = true;
+ domain = "localhost";
+
+ config = {
+ name = "LimeSurvey";
+ components = {
+ db = {
+ connectionString = "pgsql:dbname=limesurvey;host=localhost;port=5432;user=limesurvey";
+ username = "limesurvey";
+ tablePrefix = "limesurvey_";
+ };
+ assetManager.basePath = "/var/lib/limesurvey/tmp/assets";
+ urlManager = {
+ urlFormat = "path";
+ showScriptName = false;
+ };
+ };
+ config = {
+ siteadminemail = "info@infra4future.de";
+ defaultlang = "de";
+ };
+ };
+
+ package = pkgs.limesurvey.overrideAttrs (old: rec {
+ version = "4.4.12+210308";
+ src = pkgs.fetchFromGitHub {
+ owner = "LimeSurvey";
+ repo = "LimeSurvey";
+ rev = version;
+ sha256 = "0kjya8if751mh35symzas186ya27nq62adzp2j58agd5ssrb2a8f";
+ };
+ meta.knownVulnerabilities = [];
+ });
+ };
+
+
+ services.postgresql = {
+ enable = true;
+ ensureDatabases = [ "limesurvey" ];
+ ensureUsers = [ {
+ name = "limesurvey";
+ ensurePermissions = { "DATABASE limesurvey" = "ALL PRIVILEGES"; };
+ } ];
+
+ authentication = lib.mkForce ''
+ # Generated file; do not edit!
+ local all all trust
+ host limesurvey limesurvey ::1/128 trust
+ '';
+ };
+ networking.firewall.allowedTCPPorts = [ 80 ];
+ };
+ };
+
+ services.nginx.virtualHosts."survey.infra4future.de" = {
+ locations."/".proxyPass = "http://${config.containers.limesurvey.localAddress}";
+ enableACME = true;
+ forceSSL = true;
+ };
+}
diff --git a/modules/limesurvey.nix b/modules/limesurvey.nix
new file mode 100644
index 0000000..fb1684e
--- /dev/null
+++ b/modules/limesurvey.nix
@@ -0,0 +1,162 @@
+{ config, lib, pkgs, ... }:
+
+let
+
+ inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption;
+ inherit (lib) literalExample mapAttrs optional optionalString types;
+
+ cfg = config.services.limesurvey-patched;
+ fpm = config.services.phpfpm.pools.limesurvey;
+
+ user = "limesurvey";
+ group = config.services.nginx.group;
+ stateDir = cfg.stateDir;
+
+ pkg = cfg.package;
+
+ configType = with types; oneOf [ (attrsOf configType) str int bool ] // {
+ description = "limesurvey config type (str, int, bool or attribute set thereof)";
+ };
+
+ limesurveyConfig = pkgs.writeText "config.php" ''
+
+ '';
+in
+{
+ # interface
+
+ options.services.limesurvey-patched = {
+ enable = mkEnableOption "Limesurvey web application.";
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.limesurvey;
+ description = "The Limesurvey package to use";
+ };
+
+ domain = mkOption {
+ type = types.str;
+ default = "";
+ example = "example.org";
+ description = "the domain name of limesurvey";
+ };
+
+ poolConfig = mkOption {
+ type = with types; attrsOf (oneOf [ str int bool ]);
+ default = {
+ "pm" = "dynamic";
+ "pm.max_children" = 32;
+ "pm.start_servers" = 2;
+ "pm.min_spare_servers" = 2;
+ "pm.max_spare_servers" = 4;
+ "pm.max_requests" = 500;
+ };
+ description = ''
+ Options for the LimeSurvey PHP pool. See the documentation on php-fpm.conf
+ for details on configuration directives.
+ '';
+ };
+
+ config = mkOption {
+ type = configType;
+ default = {};
+ description = ''
+ LimeSurvey configuration. Refer to
+
+ for details on supported values.
+ '';
+ };
+
+ stateDir = mkOption {
+ type = types.str;
+ default = "/var/lib/limesurvey";
+ description = ''
+ LimeSurvey keeps its state in here. For a variety of stupid php reasons, it will also keep a complete
+ copy of itself in here.
+ '';
+ };
+ };
+
+ # implementation
+
+ config = mkIf cfg.enable {
+
+ services.limesurvey-patched.config = mapAttrs (name: mkDefault) {
+ runtimePath = "${stateDir}/tmp/runtime";
+ components = {
+ assetManager.basePath = "${stateDir}/tmp/assets";
+ urlManager = {
+ urlFormat = "path";
+ showScriptName = false;
+ };
+ };
+ };
+
+ services.phpfpm.pools.limesurvey = {
+ inherit user group;
+ phpEnv.LIMESURVEY_CONFIG = "/var/lib/limesurvey/config/config.php";
+ settings = {
+ "listen.owner" = config.services.nginx.user;
+ "listen.group" = config.services.nginx.group;
+ } // cfg.poolConfig;
+ };
+
+ services.nginx = {
+ enable = true;
+
+ virtualHosts.${cfg.domain} = {
+ root = stateDir;
+ locations."/".tryFiles = "$uri /index.php?$args";
+
+ locations."~ [^/]\\.php(/|$)".extraConfig = ''
+ fastcgi_split_path_info ^(.+?\.php)(/.*)$;
+ if (!-f $document_root$fastcgi_script_name) {
+ return 404;
+ }
+ fastcgi_pass unix:${fpm.socket};
+ fastcgi_index index.php;
+ '';
+ };
+ };
+
+ systemd.tmpfiles.rules = [
+ "C ${stateDir} 0750 ${user} ${group} - ${pkg}/share/limesurvey"
+ "d ${stateDir}/tmp 0750 ${user} ${group} - -"
+ "d ${stateDir}/tmp/assets 0750 ${user} ${group} - -"
+ "d ${stateDir}/tmp/runtime 0750 ${user} ${group} - -"
+ "d ${stateDir}/tmp/upload 0750 ${user} ${group} - -"
+ ];
+
+ systemd.services.limesurvey-init = {
+ wantedBy = [ "multi-user.target" ];
+ before = [ "phpfpm-limesurvey.service" ];
+ after = [ "postgresql.service" ];
+ environment.LIMESURVEY_CONFIG = "/var/lib/limesurvey/config/config.php";
+ script = ''
+
+ chmod -R +w ${stateDir}
+ mkdir -p ${stateDir}/config
+ cp -f ${limesurveyConfig} ${stateDir}/config/config.php
+
+ # update or install the database as required
+ ${pkgs.php}/bin/php /var/lib/limesurvey/application/commands/console.php updatedb || \
+ ${pkgs.php}/bin/php /var/lib/limesurvey/application/commands/console.php install admin password admin admin@example.com verbose
+ '';
+ serviceConfig = {
+ User = user;
+ Group = group;
+ Type = "oneshot";
+ };
+ };
+
+ #systemd.services.httpd.after = [ "postgresql.service" ];
+ systemd.services.nginx.after = [ "postgresql.service" ];
+
+ users.users.${user} = {
+ group = group;
+ isSystemUser = true;
+ };
+ };
+}