diff options
author | Rok Garbas <rok@garbas.si> | 2016-07-21 20:48:18 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-21 20:48:18 +0200 |
commit | d73c115aa4e754e12cf7fc129e85e7c678631a92 (patch) | |
tree | 6dc19cfbd85b54d1d286e94e4efbd60c8a14e1fd /nixos/modules | |
parent | 82f087944b70e2046ea63d23bf07561b29a34758 (diff) | |
parent | 98e419c0e27dd21e9dee0b915876ea603b833057 (diff) | |
download | nixlib-d73c115aa4e754e12cf7fc129e85e7c678631a92.tar nixlib-d73c115aa4e754e12cf7fc129e85e7c678631a92.tar.gz nixlib-d73c115aa4e754e12cf7fc129e85e7c678631a92.tar.bz2 nixlib-d73c115aa4e754e12cf7fc129e85e7c678631a92.tar.lz nixlib-d73c115aa4e754e12cf7fc129e85e7c678631a92.tar.xz nixlib-d73c115aa4e754e12cf7fc129e85e7c678631a92.tar.zst nixlib-d73c115aa4e754e12cf7fc129e85e7c678631a92.zip |
Merge pull request #16132 from zohl/tt-rss
tt-rss service: init at 16.3
Diffstat (limited to 'nixos/modules')
-rw-r--r-- | nixos/modules/module-list.nix | 3 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/tt-rss.nix | 567 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/phpfpm/default.nix (renamed from nixos/modules/services/web-servers/phpfpm.nix) | 34 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/phpfpm/pool-options.nix | 35 |
4 files changed, 617 insertions, 22 deletions
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index cd0ca6fcf35c..3e3d7c492807 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -462,6 +462,7 @@ ./services/ttys/gpm.nix ./services/ttys/kmscon.nix ./services/web-apps/pump.io.nix + ./services/web-apps/tt-rss.nix ./services/web-servers/apache-httpd/default.nix ./services/web-servers/caddy.nix ./services/web-servers/fcgiwrap.nix @@ -471,7 +472,7 @@ ./services/web-servers/lighttpd/gitweb.nix ./services/web-servers/lighttpd/inginious.nix ./services/web-servers/nginx/default.nix - ./services/web-servers/phpfpm.nix + ./services/web-servers/phpfpm/default.nix ./services/web-servers/shellinabox.nix ./services/web-servers/tomcat.nix ./services/web-servers/uwsgi.nix diff --git a/nixos/modules/services/web-apps/tt-rss.nix b/nixos/modules/services/web-apps/tt-rss.nix new file mode 100644 index 000000000000..8ab51c006f27 --- /dev/null +++ b/nixos/modules/services/web-apps/tt-rss.nix @@ -0,0 +1,567 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.services.tt-rss; + + configVersion = 26; + + boolToString = b: if b then "true" else "false"; + + cacheDir = "cache"; + lockDir = "lock"; + feedIconsDir = "feed-icons"; + + dbPort = if cfg.database.port == null + then (if cfg.database.type == "pgsql" then 5432 else 3306) + else cfg.database.port; + + poolName = "tt-rss"; + virtualHostName = "tt-rss"; + + tt-rss-config = pkgs.writeText "config.php" '' + <?php + + define('PHP_EXECUTABLE', '${pkgs.php}/bin/php'); + + define('LOCK_DIRECTORY', '${lockDir}'); + define('CACHE_DIR', '${cacheDir}'); + define('ICONS_DIR', '${feedIconsDir}'); + define('ICONS_URL', '${feedIconsDir}'); + define('SELF_URL_PATH', '${cfg.selfUrlPath}'); + + define('MYSQL_CHARSET', 'UTF8'); + + define('DB_TYPE', '${cfg.database.type}'); + define('DB_HOST', '${cfg.database.host}'); + define('DB_USER', '${cfg.database.user}'); + define('DB_NAME', '${cfg.database.name}'); + define('DB_PASS', '${escape ["'" "\\"] cfg.database.password}'); + define('DB_PORT', '${toString dbPort}'); + + define('AUTH_AUTO_CREATE', ${boolToString cfg.auth.autoCreate}); + define('AUTH_AUTO_LOGIN', ${boolToString cfg.auth.autoLogin}); + + define('FEED_CRYPT_KEY', '${escape ["'" "\\"] cfg.feedCryptKey}'); + + + define('SINGLE_USER_MODE', ${boolToString cfg.singleUserMode}); + + define('SIMPLE_UPDATE_MODE', ${boolToString cfg.simpleUpdateMode}); + define('CHECK_FOR_UPDATES', ${boolToString cfg.checkForUpdates}); + + define('FORCE_ARTICLE_PURGE', ${toString cfg.forceArticlePurge}); + define('SESSION_COOKIE_LIFETIME', ${toString cfg.sessionCookieLifetime}); + define('ENABLE_GZIP_OUTPUT', ${boolToString cfg.enableGZipOutput}); + + define('PLUGINS', '${builtins.concatStringsSep "," cfg.plugins}'); + + define('LOG_DESTINATION', '${cfg.logDestination}'); + define('CONFIG_VERSION', ${toString configVersion}); + + + define('PUBSUBHUBBUB_ENABLED', ${boolToString cfg.pubSubHubbub.enable}); + define('PUBSUBHUBBUB_HUB', '${cfg.pubSubHubbub.hub}'); + + define('SPHINX_SERVER', '${cfg.sphinx.server}'); + define('SPHINX_INDEX', '${builtins.concatStringsSep "," cfg.sphinx.index}'); + + define('ENABLE_REGISTRATION', ${boolToString cfg.registration.enable}); + define('REG_NOTIFY_ADDRESS', '${cfg.registration.notifyAddress}'); + define('REG_MAX_USERS', ${toString cfg.registration.maxUsers}); + + define('SMTP_SERVER', '${cfg.email.server}'); + define('SMTP_LOGIN', '${cfg.email.login}'); + define('SMTP_PASSWORD', '${escape ["'" "\\"] cfg.email.password}'); + define('SMTP_SECURE', '${cfg.email.security}'); + + define('SMTP_FROM_NAME', '${escape ["'" "\\"] cfg.email.fromName}'); + define('SMTP_FROM_ADDRESS', '${escape ["'" "\\"] cfg.email.fromAddress}'); + define('DIGEST_SUBJECT', '${escape ["'" "\\"] cfg.email.digestSubject}'); + ''; + + in { + + ###### interface + + options = { + + services.tt-rss = { + + enable = mkEnableOption "tt-rss"; + + user = mkOption { + type = types.str; + default = "nginx"; + example = "nginx"; + description = '' + User account under which both the service and the web-application run. + ''; + }; + + pool = mkOption { + type = types.str; + default = "${poolName}"; + description = '' + Name of existing phpfpm pool that is used to run web-application. + If not specified a pool will be created automatically with + default values. + ''; + }; + + virtualHost = mkOption { + type = types.str; + default = "${virtualHostName}"; + description = '' + Name of existing nginx virtual host that is used to run web-application. + If not specified a host will be created automatically with + default values. + ''; + }; + + database = { + type = mkOption { + type = types.enum ["pgsql" "mysql"]; + default = "pgsql"; + description = '' + Database to store feeds. Supported are pgsql and mysql. + ''; + }; + + host = mkOption { + type = types.str; + default = "localhost"; + description = '' + Host of the database. + ''; + }; + + name = mkOption { + type = types.str; + default = "tt_rss"; + description = '' + Name of the existing database. + ''; + }; + + user = mkOption { + type = types.str; + default = "tt_rss"; + description = '' + The database user. The user must exist and has access to + the specified database. + ''; + }; + + password = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The database user's password. + ''; + }; + + port = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + The database's port. If not set, the default ports will be provided (5432 + and 3306 for pgsql and mysql respectively). + ''; + }; + }; + + auth = { + autoCreate = mkOption { + type = types.bool; + default = true; + description = '' + Allow authentication modules to auto-create users in tt-rss internal + database when authenticated successfully. + ''; + }; + + autoLogin = mkOption { + type = types.bool; + default = true; + description = '' + Automatically login user on remote or other kind of externally supplied + authentication, otherwise redirect to login form as normal. + If set to true, users won't be able to set application language + and settings profile. + ''; + }; + }; + + pubSubHubbub = { + hub = mkOption { + type = types.str; + default = ""; + description = '' + URL to a PubSubHubbub-compatible hub server. If defined, "Published + articles" generated feed would automatically become PUSH-enabled. + ''; + }; + + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable client PubSubHubbub support in tt-rss. When disabled, tt-rss + won't try to subscribe to PUSH feed updates. + ''; + }; + }; + + sphinx = { + server = mkOption { + type = types.str; + default = "localhost:9312"; + description = '' + Hostname:port combination for the Sphinx server. + ''; + }; + + index = mkOption { + type = types.listOf types.str; + default = ["ttrss" "delta"]; + description = '' + Index names in Sphinx configuration. Example configuration + files are available on tt-rss wiki. + ''; + }; + }; + + registration = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Allow users to register themselves. Please be aware that allowing + random people to access your tt-rss installation is a security risk + and potentially might lead to data loss or server exploit. Disabled + by default. + ''; + }; + + notifyAddress = mkOption { + type = types.str; + default = ""; + description = '' + Email address to send new user notifications to. + ''; + }; + + maxUsers = mkOption { + type = types.int; + default = 0; + description = '' + Maximum amount of users which will be allowed to register on this + system. 0 - no limit. + ''; + }; + }; + + email = { + server = mkOption { + type = types.str; + default = ""; + example = "localhost:25"; + description = '' + Hostname:port combination to send outgoing mail. Blank - use system + MTA. + ''; + }; + + login = mkOption { + type = types.str; + default = ""; + description = '' + SMTP authentication login used when sending outgoing mail. + ''; + }; + + password = mkOption { + type = types.str; + default = ""; + description = '' + SMTP authentication password used when sending outgoing mail. + ''; + }; + + security = mkOption { + type = types.enum ["" "ssl" "tls"]; + default = ""; + description = '' + Used to select a secure SMTP connection. Allowed values: ssl, tls, + or empty. + ''; + }; + + fromName = mkOption { + type = types.str; + default = "Tiny Tiny RSS"; + description = '' + Name for sending outgoing mail. This applies to password reset + notifications, digest emails and any other mail. + ''; + }; + + fromAddress = mkOption { + type = types.str; + default = ""; + description = '' + Address for sending outgoing mail. This applies to password reset + notifications, digest emails and any other mail. + ''; + }; + + digestSubject = mkOption { + type = types.str; + default = "[tt-rss] New headlines for last 24 hours"; + description = '' + Subject line for email digests. + ''; + }; + }; + + sessionCookieLifetime = mkOption { + type = types.int; + default = 86400; + description = '' + Default lifetime of a session (e.g. login) cookie. In seconds, + 0 means cookie will be deleted when browser closes. + ''; + }; + + selfUrlPath = mkOption { + type = types.str; + description = '' + Full URL of your tt-rss installation. This should be set to the + location of tt-rss directory, e.g. http://example.org/tt-rss/ + You need to set this option correctly otherwise several features + including PUSH, bookmarklets and browser integration will not work properly. + ''; + example = "http://localhost"; + }; + + feedCryptKey = mkOption { + type = types.str; + default = ""; + description = '' + Key used for encryption of passwords for password-protected feeds + in the database. A string of 24 random characters. If left blank, encryption + is not used. Requires mcrypt functions. + Warning: changing this key will make your stored feed passwords impossible + to decrypt. + ''; + }; + + singleUserMode = mkOption { + type = types.bool; + default = true; + + description = '' + Operate in single user mode, disables all functionality related to + multiple users and authentication. Enabling this assumes you have + your tt-rss directory protected by other means (e.g. http auth). + ''; + }; + + simpleUpdateMode = mkOption { + type = types.bool; + default = false; + description = '' + Enables fallback update mode where tt-rss tries to update feeds in + background while tt-rss is open in your browser. + If you don't have a lot of feeds and don't want to or can't run + background processes while not running tt-rss, this method is generally + viable to keep your feeds up to date. + Still, there are more robust (and recommended) updating methods + available, you can read about them here: http://tt-rss.org/wiki/UpdatingFeeds + ''; + }; + + forceArticlePurge = mkOption { + type = types.int; + default = 0; + description = '' + When this option is not 0, users ability to control feed purging + intervals is disabled and all articles (which are not starred) + older than this amount of days are purged. + ''; + }; + + checkForUpdates = mkOption { + type = types.bool; + default = true; + description = '' + Check for updates automatically if running Git version + ''; + }; + + enableGZipOutput = mkOption { + type = types.bool; + default = true; + description = '' + Selectively gzip output to improve wire performance. This requires + PHP Zlib extension on the server. + Enabling this can break tt-rss in several httpd/php configurations, + if you experience weird errors and tt-rss failing to start, blank pages + after login, or content encoding errors, disable it. + ''; + }; + + plugins = mkOption { + type = types.listOf types.str; + default = ["auth_internal" "note"]; + description = '' + List of plugins to load automatically for all users. + System plugins have to be specified here. Please enable at least one + authentication plugin here (auth_*). + Users may enable other user plugins from Preferences/Plugins but may not + disable plugins specified in this list. + Disabling auth_internal in this list would automatically disable + reset password link on the login form. + ''; + }; + + logDestination = mkOption { + type = types.enum ["" "sql" "syslog"]; + default = "sql"; + description = '' + Log destination to use. Possible values: sql (uses internal logging + you can read in Preferences -> System), syslog - logs to system log. + Setting this to blank uses PHP logging (usually to http server + error.log). + ''; + }; + }; + }; + + + ###### implementation + + config = let + root = "/var/lib/tt-rss"; + in mkIf cfg.enable { + + services.phpfpm.pools = if cfg.pool == "${poolName}" then { + "${poolName}" = { + listen = "/var/run/phpfpm/${poolName}.sock"; + extraConfig = '' + listen.owner = nginx + listen.group = nginx + listen.mode = 0600 + user = nginx + pm = dynamic + pm.max_children = 75 + pm.start_servers = 10 + pm.min_spare_servers = 5 + pm.max_spare_servers = 20 + pm.max_requests = 500 + catch_workers_output = 1 + ''; + }; + } else {}; + + + services.nginx.virtualHosts = if cfg.virtualHost == "${virtualHostName}" then { + "${virtualHostName}" = { + root = "${root}"; + extraConfig = '' + access_log /var/log/nginx-${virtualHostName}-access.log; + error_log /var/log/nginx-${virtualHostName}-error.log; + ''; + + locations."/" = { + extraConfig = '' + index index.php; + ''; + }; + + locations."~ \.php$" = { + extraConfig = '' + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass unix:${config.services.phpfpm.pools."${cfg.pool}".listen}; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME ${root}/$fastcgi_script_name; + + include ${pkgs.nginx}/conf/fastcgi_params; + ''; + }; + }; + } else {}; + + + systemd.services.tt-rss = let + dbService = if cfg.database.type == "pgsql" then "postgresql.service" else "mysql.service"; + in { + + description = "Tiny Tiny RSS feeds update daemon"; + + preStart = let + callSql = if cfg.database.type == "pgsql" then (e: '' + ${optionalString (cfg.database.password != null) + "PGPASSWORD=${cfg.database.password}"} ${pkgs.postgresql95}/bin/psql \ + -U ${cfg.database.user} \ + -h ${cfg.database.host} \ + --port ${toString dbPort} \ + -c '${e}' \ + ${cfg.database.name}'') + + else if cfg.database.type == "mysql" then (e: '' + echo '${e}' | ${pkgs.mysql}/bin/mysql \ + ${optionalString (cfg.database.password != null) + "-p${cfg.database.password}"} \ + -u ${cfg.database.user} \ + -h ${cfg.database.host} \ + -P ${toString dbPort} \ + ${cfg.database.name}'') + + else ""; + + in '' + rm -rf "${root}/*" + mkdir -m 755 -p "${root}" + cp -r "${pkgs.tt-rss}/"* "${root}" + ln -sf "${tt-rss-config}" "${root}/config.php" + chown -R "${cfg.user}" "${root}" + chmod -R 755 "${root}" + '' + (optionalString (cfg.database.type == "pgsql") '' + + exists=$(${callSql "select count(*) > 0 from pg_tables where tableowner = user"} \ + | tail -n+3 | head -n-2 | sed -e 's/[ \n\t]*//') + + if [ "$exists" == 'f' ]; then + ${callSql "\\i ${pkgs.tt-rss}/schema/ttrss_schema_${cfg.database.type}.sql"} + else + echo 'The database contains some data. Leaving it as it is.' + fi; + '') + (optionalString (cfg.database.type == "mysql") '' + + exists=$(${callSql "select count(*) > 0 from information_schema.tables where table_schema = schema()"} \ + | tail -n+2 | sed -e 's/[ \n\t]*//') + + if [ "$exists" == '0' ]; then + ${callSql "\\. ${pkgs.tt-rss}/schema/ttrss_schema_${cfg.database.type}.sql"} + else + echo 'The database contains some data. Leaving it as it is.' + fi; + ''); + + serviceConfig = { + User = "${cfg.user}"; + ExecStart = "${pkgs.php}/bin/php /var/lib/tt-rss/update.php --daemon"; + StandardOutput = "syslog"; + StandardError = "syslog"; + PermissionsStartOnly = true; + }; + + wantedBy = [ "multi-user.target" ]; + requires = ["${dbService}"]; + after = ["network.target" "${dbService}"]; + }; + }; +} + diff --git a/nixos/modules/services/web-servers/phpfpm.nix b/nixos/modules/services/web-servers/phpfpm/default.nix index 2658d7117e37..6befddf9f522 100644 --- a/nixos/modules/services/web-servers/phpfpm.nix +++ b/nixos/modules/services/web-servers/phpfpm/default.nix @@ -9,6 +9,12 @@ let pidFile = "${stateDir}/phpfpm.pid"; + mkPool = n: p: '' + [${n}] + listen = ${p.listen} + ${p.extraConfig} + ''; + cfgFile = pkgs.writeText "phpfpm.conf" '' [global] pid = ${pidFile} @@ -16,7 +22,7 @@ let daemonize = yes ${cfg.extraConfig} - ${concatStringsSep "\n" (mapAttrsToList (n: v: "[${n}]\n${v}") cfg.poolConfigs)} + ${concatStringsSep "\n" (mapAttrsToList mkPool cfg.pools)} ''; phpIni = pkgs.writeText "php.ini" '' @@ -61,33 +67,19 @@ in { "Options appended to the PHP configuration file <filename>php.ini</filename>."; }; - poolConfigs = mkOption { - type = types.attrsOf types.lines; + pools = mkOption { + type = types.attrsOf (types.submodule (import ./pool-options.nix { + inherit lib; + })); default = {}; - example = literalExample '' - { mypool = ''' - listen = /run/phpfpm/mypool - user = nobody - pm = dynamic - pm.max_children = 75 - pm.start_servers = 10 - pm.min_spare_servers = 5 - pm.max_spare_servers = 20 - pm.max_requests = 500 - '''; - } - ''; description = '' - A mapping between PHP FPM pool names and their configurations. - See the documentation on <literal>php-fpm.conf</literal> for - details on configuration directives. If no pools are defined, - the phpfpm service is disabled. + If no pools are defined, the phpfpm service is disabled. ''; }; }; }; - config = mkIf (cfg.poolConfigs != {}) { + config = mkIf (cfg.pools != {}) { systemd.services.phpfpm = { wantedBy = [ "multi-user.target" ]; diff --git a/nixos/modules/services/web-servers/phpfpm/pool-options.nix b/nixos/modules/services/web-servers/phpfpm/pool-options.nix new file mode 100644 index 000000000000..cc688c2c48a2 --- /dev/null +++ b/nixos/modules/services/web-servers/phpfpm/pool-options.nix @@ -0,0 +1,35 @@ +{ lib }: + +with lib; { + + options = { + + listen = mkOption { + type = types.str; + example = "/path/to/unix/socket"; + description = '' + The address on which to accept FastCGI requests. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + example = '' + user = nobody + pm = dynamic + pm.max_children = 75 + pm.start_servers = 10 + pm.min_spare_servers = 5 + pm.max_spare_servers = 20 + pm.max_requests = 500 + ''; + + description = '' + Extra lines that go into the pool configuration. + See the documentation on <literal>php-fpm.conf</literal> for + details on configuration directives. + ''; + }; + }; +} + |