diff --git a/nixos/doc/manual/release-notes/rl-1909.xml b/nixos/doc/manual/release-notes/rl-1909.xml
index b78c3e08b79..1c35c25eea4 100644
--- a/nixos/doc/manual/release-notes/rl-1909.xml
+++ b/nixos/doc/manual/release-notes/rl-1909.xml
@@ -107,6 +107,29 @@
+
+ Backward Incompatibilities
+
+
+ When upgrading from a previous release, please be aware of the following
+ incompatible changes:
+
+
+
+
+
+ The limesurvey apache subservice was replaced with a full NixOS module.
+ One can configure it using the
+ and options.
+
+
+
+
+
+ '';
+
+ mysqlLocal = cfg.database.createLocally && cfg.database.type == "mysql";
+ pgsqlLocal = cfg.database.createLocally && cfg.database.type == "pgsql";
+
+in
+{
+ # interface
+
+ options.services.limesurvey = {
+ enable = mkEnableOption "Limesurvey web application.";
+
+ database = {
+ type = mkOption {
+ type = types.enum [ "mysql" "pgsql" "odbc" "mssql" ];
+ example = "pgsql";
+ default = "mysql";
+ description = "Database engine to use.";
+ };
+
+ host = mkOption {
+ type = types.str;
+ default = "localhost";
+ description = "Database host address.";
+ };
+
+ port = mkOption {
+ type = types.int;
+ default = if cfg.database.type == "pgsql" then 5442 else 3306;
+ defaultText = "3306";
+ description = "Database host port.";
+ };
+
+ name = mkOption {
+ type = types.str;
+ default = "limesurvey";
+ description = "Database name.";
+ };
+
+ user = mkOption {
+ type = types.str;
+ default = "limesurvey";
+ description = "Database user.";
+ };
+
+ passwordFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ example = "/run/keys/limesurvey-dbpassword";
+ description = ''
+ A file containing the password corresponding to
+ .
+ '';
+ };
+
+ socket = mkOption {
+ type = types.nullOr types.path;
+ default =
+ if mysqlLocal then "/run/mysqld/mysqld.sock"
+ else if pgsqlLocal then "/run/postgresql"
+ else null
+ ;
+ defaultText = "/run/mysqld/mysqld.sock";
+ description = "Path to the unix socket file to use for authentication.";
+ };
+
+ createLocally = mkOption {
+ type = types.bool;
+ default = cfg.database.type == "mysql";
+ defaultText = "true";
+ description = ''
+ Create the database and database user locally.
+ This currently only applies if database type "mysql" is selected.
+ '';
+ };
+ };
+
+ virtualHost = mkOption {
+ type = types.submodule ({
+ options = import ../web-servers/apache-httpd/per-server-options.nix {
+ inherit lib;
+ forMainServer = false;
+ };
+ });
+ example = {
+ hostName = "survey.example.org";
+ enableSSL = true;
+ adminAddr = "webmaster@example.org";
+ sslServerCert = "/var/lib/acme/survey.example.org/full.pem";
+ sslServerKey = "/var/lib/acme/survey.example.org/key.pem";
+ };
+ description = ''
+ Apache configuration can be done by adapting services.httpd.virtualHosts.<name>.
+ See for further information.
+ '';
+ };
+
+ poolConfig = mkOption {
+ type = types.lines;
+ 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 LimeSurvey's 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.
+ '';
+ };
+ };
+
+ # implementation
+
+ config = mkIf cfg.enable {
+
+ assertions = [
+ { assertion = cfg.database.createLocally -> cfg.database.type == "mysql";
+ message = "services.limesurvey.createLocally is currently only supported for database type 'mysql'";
+ }
+ { assertion = cfg.database.createLocally -> cfg.database.user == user;
+ message = "services.limesurvey.database.user must be set to ${user} if services.limesurvey.database.createLocally is set true";
+ }
+ { assertion = cfg.database.createLocally -> cfg.database.socket != null;
+ message = "services.limesurvey.database.socket must be set if services.limesurvey.database.createLocally is set to true";
+ }
+ { assertion = cfg.database.createLocally -> cfg.database.passwordFile == null;
+ message = "a password cannot be specified if services.limesurvey.database.createLocally is set to true";
+ }
+ ];
+
+ services.limesurvey.config = mapAttrs (name: mkDefault) {
+ runtimePath = "${stateDir}/tmp/runtime";
+ components = {
+ db = {
+ connectionString = "${cfg.database.type}:dbname=${cfg.database.name};host=${if pgsqlLocal then cfg.database.socket else cfg.database.host};port=${toString cfg.database.port}" +
+ optionalString mysqlLocal ";socket=${cfg.database.socket}";
+ username = cfg.database.user;
+ password = mkIf (cfg.database.passwordFile != null) "file_get_contents(\"${toString cfg.database.passwordFile}\");";
+ tablePrefix = "limesurvey_";
+ };
+ assetManager.basePath = "${stateDir}/tmp/assets";
+ urlManager = {
+ urlFormat = "path";
+ showScriptName = false;
+ };
+ };
+ config = {
+ tempdir = "${stateDir}/tmp";
+ uploaddir = "${stateDir}/upload";
+ force_ssl = mkIf cfg.virtualHost.enableSSL "on";
+ config.defaultlang = "en";
+ };
+ };
+
+ services.mysql = mkIf mysqlLocal {
+ enable = true;
+ package = mkDefault pkgs.mariadb;
+ ensureDatabases = [ cfg.database.name ];
+ ensureUsers = [
+ { name = cfg.database.user;
+ ensurePermissions = {
+ "${cfg.database.name}.*" = "SELECT, CREATE, INSERT, UPDATE, DELETE, ALTER, DROP, INDEX";
+ };
+ }
+ ];
+ };
+
+ services.phpfpm.pools.limesurvey = {
+ phpPackage = php;
+ listen = "/run/phpfpm/limesurvey.sock";
+ extraConfig = ''
+ listen.owner = ${config.services.httpd.user};
+ listen.group = ${config.services.httpd.group};
+ user = ${user};
+ group = ${group};
+
+ env[LIMESURVEY_CONFIG] = ${limesurveyConfig}
+
+ ${cfg.poolConfig}
+ '';
+ };
+
+ services.httpd = {
+ enable = true;
+ adminAddr = mkDefault cfg.virtualHost.adminAddr;
+ extraModules = [ "proxy_fcgi" ];
+ virtualHosts = [
+ (cfg.virtualHost // {
+ documentRoot = mkForce "${pkg}/share/limesurvey";
+ extraConfig = ''
+ Alias "/tmp" "${stateDir}/tmp"
+
+ AllowOverride all
+ Require all granted
+ Options -Indexes +FollowSymlinks
+
+
+ Alias "/upload" "${stateDir}/upload"
+
+ AllowOverride all
+ Require all granted
+ Options -Indexes
+
+
+
+
+
+ SetHandler "proxy:unix:/run/phpfpm/limesurvey.sock|fcgi://localhost/"
+
+
+
+ AllowOverride all
+ Options -Indexes
+ DirectoryIndex index.php
+
+ '';
+ })
+ ];
+ };
+
+ systemd.tmpfiles.rules = [
+ "d ${stateDir} 0750 ${user} ${group} - -"
+ "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} - -"
+ "C ${stateDir}/upload 0750 ${user} ${group} - ${pkg}/share/limesurvey/upload"
+ ];
+
+ systemd.services.limesurvey-init = {
+ wantedBy = [ "multi-user.target" ];
+ before = [ "phpfpm-limesurvey.service" ];
+ after = optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.service";
+ environment.LIMESURVEY_CONFIG = limesurveyConfig;
+ script = ''
+ # update or install the database as required
+ ${php}/bin/php ${pkg}/share/limesurvey/application/commands/console.php updatedb || \
+ ${php}/bin/php ${pkg}/share/limesurvey/application/commands/console.php install admin password admin admin@example.com verbose
+ '';
+ serviceConfig = {
+ User = user;
+ Group = group;
+ Type = "oneshot";
+ };
+ };
+
+ systemd.services.httpd.after = optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.service";
+
+ users.users."${user}".group = group;
+
+ };
+}
diff --git a/nixos/modules/services/web-servers/apache-httpd/limesurvey.nix b/nixos/modules/services/web-servers/apache-httpd/limesurvey.nix
deleted file mode 100644
index 5c387700a5d..00000000000
--- a/nixos/modules/services/web-servers/apache-httpd/limesurvey.nix
+++ /dev/null
@@ -1,196 +0,0 @@
-{ config, lib, pkgs, serverInfo, ... }:
-
-with lib;
-
-let
-
- httpd = serverInfo.serverConfig.package;
-
- version24 = !versionOlder httpd.version "2.4";
-
- allGranted = if version24 then ''
- Require all granted
- '' else ''
- Order allow,deny
- Allow from all
- '';
-
- limesurveyConfig = pkgs.writeText "config.php" ''
-
- '';
-
- limesurveyRoot = "${pkgs.limesurvey}/share/limesurvey/";
-
-in rec {
-
- extraConfig = ''
- Alias ${config.urlPrefix}/tmp ${config.dataDir}/tmp
-
-
- ${allGranted}
- Options -Indexes +FollowSymlinks
-
-
- Alias ${config.urlPrefix}/upload ${config.dataDir}/upload
-
-
- ${allGranted}
- Options -Indexes
-
-
- ${if config.urlPrefix != "" then ''
- Alias ${config.urlPrefix} ${limesurveyRoot}
- '' else ''
- RewriteEngine On
- RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
- RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
- ''}
-
-
- DirectoryIndex index.php
-
- '';
-
- globalEnvVars = [
- { name = "LIMESURVEY_CONFIG"; value = limesurveyConfig; }
- ];
-
- documentRoot = if config.urlPrefix == "" then limesurveyRoot else null;
-
- enablePHP = true;
-
- options = {
-
- id = mkOption {
- default = "main";
- description = ''
- A unique identifier necessary to keep multiple Limesurvey server
- instances on the same machine apart. This is used to
- disambiguate the administrative scripts, which get names like
- mediawiki-$id-change-password.
- '';
- };
-
- urlPrefix = mkOption {
- default = "";
- description = "Url prefix for site.";
- type = types.str;
- };
-
- dbType = mkOption {
- default = "pgsql";
- description = "Type of database for limesurvey, for now, only pgsql.";
- type = types.enum ["pgsql"];
- };
-
- dbName = mkOption {
- default = "limesurvey";
- description = "Name of the database that holds the limesurvey data.";
- type = types.str;
- };
-
- dbHost = mkOption {
- default = "localhost";
- description = "Limesurvey database host.";
- type = types.str;
- };
-
- dbPort = mkOption {
- default = 5432;
- description = "Limesurvey database port.";
- type = types.int;
- };
-
- dbUser = mkOption {
- default = "limesurvey";
- description = "Limesurvey database user.";
- type = types.str;
- };
-
- dbPassword = mkOption {
- example = "foobar";
- description = "Limesurvey database password.";
- type = types.str;
- };
-
- adminUser = mkOption {
- description = "Limesurvey admin username.";
- default = "admin";
- type = types.str;
- };
-
- adminPassword = mkOption {
- description = "Default limesurvey admin password.";
- default = "admin";
- type = types.str;
- };
-
- adminEmail = mkOption {
- description = "Limesurvey admin email.";
- default = "admin@admin.com";
- type = types.str;
- };
-
- forceSSL = mkOption {
- default = false;
- description = "Force use of HTTPS connection.";
- type = types.bool;
- };
-
- siteName = mkOption {
- default = "LimeSurvey";
- description = "LimeSurvey name of the site.";
- type = types.str;
- };
-
- defaultLang = mkOption {
- default = "en";
- description = "LimeSurvey default language.";
- type = types.str;
- };
-
- dataDir = mkOption {
- default = "/var/lib/limesurvey";
- description = "LimeSurvey data directory.";
- type = types.path;
- };
- };
-
- startupScript = pkgs.writeScript "limesurvey_startup.sh" ''
- if [ ! -f ${config.dataDir}/.created ]; then
- mkdir -p ${config.dataDir}/{tmp/runtime,tmp/assets,tmp/upload,upload}
- chmod -R ug+rw ${config.dataDir}
- chmod -R o-rwx ${config.dataDir}
- chown -R wwwrun:wwwrun ${config.dataDir}
-
- ${pkgs.postgresql}/bin/createuser --no-superuser --no-createdb --no-createrole "${config.dbUser}" || true
- ${pkgs.postgresql}/bin/createdb "${config.dbName}" -O "${config.dbUser}" || true
- ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/psql -U postgres -d postgres -c "alter user ${config.dbUser} with password '${config.dbPassword}';" || true
-
- ${pkgs.limesurvey}/bin/limesurvey-console install '${config.adminUser}' '${config.adminPassword}' '${config.adminUser}' '${config.adminEmail}'
-
- touch ${config.dataDir}/.created
- fi
- '';
-}