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 - ''; -}