| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  | { config, lib, pkgs, ... }: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | with lib; | 
					
						
							|  |  |  | let | 
					
						
							|  |  |  |   cfg = config.services.tt-rss; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   configVersion = 26; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   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"; | 
					
						
							| 
									
										
										
										
											2018-12-19 22:42:29 +01:00
										 |  |  |   phpfpmSocketName = "/run/phpfpm/${poolName}.sock"; | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   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}'); | 
					
						
							| 
									
										
										
										
											2016-08-27 12:18:04 -07:00
										 |  |  |       define('DB_HOST', '${optionalString (cfg.database.host != null) cfg.database.host}'); | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |       define('DB_USER', '${cfg.database.user}'); | 
					
						
							|  |  |  |       define('DB_NAME', '${cfg.database.name}'); | 
					
						
							| 
									
										
										
										
											2018-09-30 12:06:07 +01:00
										 |  |  |       define('DB_PASS', ${ | 
					
						
							|  |  |  |         if (cfg.database.password != null) then | 
					
						
							|  |  |  |           "'${(escape ["'" "\\"] cfg.database.password)}'" | 
					
						
							|  |  |  |         else if (cfg.database.passwordFile != null) then | 
					
						
							|  |  |  |           "file_get_contents('${cfg.database.passwordFile}')" | 
					
						
							|  |  |  |         else | 
					
						
							| 
									
										
										
										
											2019-02-19 16:24:17 -08:00
										 |  |  |           "''" | 
					
						
							| 
									
										
										
										
											2018-09-30 12:06:07 +01:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |       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}); | 
					
						
							| 
									
										
										
										
											2019-02-05 20:44:48 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       // Never check for updates - the running version of the code should be | 
					
						
							|  |  |  |       // controlled entirely by the version of TT-RSS active in the current Nix | 
					
						
							|  |  |  |       // profile. If TT-RSS updates itself to a version requiring a database | 
					
						
							|  |  |  |       // schema upgrade, and then the SystemD tt-rss.service is restarted, the | 
					
						
							|  |  |  |       // old code copied from the Nix store will overwrite the updated version, | 
					
						
							|  |  |  |       // causing the code to detect the need for a schema "upgrade" (since the | 
					
						
							|  |  |  |       // schema version in the database is different than in the code), but the | 
					
						
							|  |  |  |       // update schema operation in TT-RSS will do nothing because the schema | 
					
						
							|  |  |  |       // version in the database is newer than that in the code. | 
					
						
							|  |  |  |       define('CHECK_FOR_UPDATES', false); | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |       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}'); | 
					
						
							| 
									
										
										
										
											2018-06-04 14:14:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       ${cfg.extraConfig} | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |   '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  in { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ###### interface | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   options = { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     services.tt-rss = { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       enable = mkEnableOption "tt-rss"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-27 12:08:32 -07:00
										 |  |  |       root = mkOption { | 
					
						
							|  |  |  |         type = types.path; | 
					
						
							|  |  |  |         default = "/var/lib/tt-rss"; | 
					
						
							|  |  |  |         example = "/var/lib/tt-rss"; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Root of the application. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |       user = mkOption { | 
					
						
							|  |  |  |         type = types.str; | 
					
						
							| 
									
										
										
										
											2018-01-02 21:45:42 +02:00
										 |  |  |         default = "tt_rss"; | 
					
						
							|  |  |  |         example = "tt_rss"; | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |         description = ''
 | 
					
						
							| 
									
										
										
										
											2016-08-27 12:10:30 -07:00
										 |  |  |           User account under which both the update daemon and the web-application run. | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       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. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-27 12:20:28 -07:00
										 |  |  |       virtualHost = mkOption { | 
					
						
							|  |  |  |         type = types.nullOr types.str; | 
					
						
							|  |  |  |         default = "tt-rss"; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Name of the nginx virtualhost to use and setup. If null, do not setup any virtualhost. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |       database = { | 
					
						
							|  |  |  |         type = mkOption { | 
					
						
							|  |  |  |           type = types.enum ["pgsql" "mysql"]; | 
					
						
							|  |  |  |           default = "pgsql"; | 
					
						
							|  |  |  |           description = ''
 | 
					
						
							|  |  |  |             Database to store feeds. Supported are pgsql and mysql. | 
					
						
							|  |  |  |           '';
 | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         host = mkOption { | 
					
						
							| 
									
										
										
										
											2016-08-27 12:18:04 -07:00
										 |  |  |           type = types.nullOr types.str; | 
					
						
							|  |  |  |           default = null; | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |           description = ''
 | 
					
						
							| 
									
										
										
										
											2016-08-27 12:18:04 -07:00
										 |  |  |             Host of the database. Leave null to use Unix domain socket. | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |           '';
 | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         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. | 
					
						
							|  |  |  |           '';
 | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-30 12:06:07 +01:00
										 |  |  |         passwordFile = mkOption { | 
					
						
							|  |  |  |           type = types.nullOr types.str; | 
					
						
							|  |  |  |           default = null; | 
					
						
							|  |  |  |           description = ''
 | 
					
						
							|  |  |  |             The database user's password. | 
					
						
							|  |  |  |           '';
 | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |         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; | 
					
						
							| 
									
										
										
										
											2016-08-27 12:23:19 -07:00
										 |  |  |         default = false; | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       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. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-04 14:14:57 +02:00
										 |  |  |       pluginPackages = mkOption { | 
					
						
							|  |  |  |         type = types.listOf types.package; | 
					
						
							|  |  |  |         default = []; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           List of plugins to install. The list elements are expected to | 
					
						
							|  |  |  |           be derivations. All elements in this derivation are automatically | 
					
						
							|  |  |  |           copied to the <literal>plugins.local</literal> directory. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       themePackages = mkOption { | 
					
						
							|  |  |  |         type = types.listOf types.package; | 
					
						
							|  |  |  |         default = []; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           List of themes to install. The list elements are expected to | 
					
						
							|  |  |  |           be derivations. All elements in this derivation are automatically | 
					
						
							|  |  |  |           copied to the <literal>themes.local</literal> directory. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |       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). | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2018-06-04 14:14:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       extraConfig = mkOption { | 
					
						
							|  |  |  |         type = types.lines; | 
					
						
							|  |  |  |         default = ""; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Additional lines to append to <literal>config.php</literal>. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |     }; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-05 20:44:48 -08:00
										 |  |  |   imports = [ | 
					
						
							|  |  |  |     (mkRemovedOptionModule ["services" "tt-rss" "checkForUpdates"] ''
 | 
					
						
							|  |  |  |       This option was removed because setting this to true will cause TT-RSS | 
					
						
							|  |  |  |       to be unable to start if an automatic update of the code in | 
					
						
							|  |  |  |       services.tt-rss.root leads to a database schema upgrade that is not | 
					
						
							|  |  |  |       supported by the code active in the Nix store. | 
					
						
							|  |  |  |     '')
 | 
					
						
							|  |  |  |   ]; | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ###### implementation | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-27 12:08:32 -07:00
										 |  |  |   config = mkIf cfg.enable { | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-30 12:06:07 +01:00
										 |  |  |     assertions = [ | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         assertion = cfg.database.password != null -> cfg.database.passwordFile == null; | 
					
						
							|  |  |  |         message = "Cannot set both password and passwordFile"; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-14 13:27:30 +01:00
										 |  |  |     services.phpfpm.pools = mkIf (cfg.pool == "${poolName}") { | 
					
						
							|  |  |  |       "${poolName}" = { | 
					
						
							|  |  |  |         listen = "/var/run/phpfpm/${poolName}.sock"; | 
					
						
							|  |  |  |         extraConfig = ''
 | 
					
						
							|  |  |  |           listen.owner = nginx | 
					
						
							|  |  |  |           listen.group = nginx | 
					
						
							|  |  |  |           listen.mode = 0600 | 
					
						
							|  |  |  |           user = ${cfg.user} | 
					
						
							|  |  |  |           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 | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2016-08-27 12:20:28 -07:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-17 11:44:52 +02:00
										 |  |  |     # NOTE: No configuration is done if not using virtual host | 
					
						
							|  |  |  |     services.nginx = mkIf (cfg.virtualHost != null) { | 
					
						
							| 
									
										
										
										
											2018-01-02 21:48:00 +02:00
										 |  |  |       enable = true; | 
					
						
							| 
									
										
										
										
											2018-04-17 11:44:52 +02:00
										 |  |  |       virtualHosts = { | 
					
						
							| 
									
										
										
										
											2018-01-02 21:48:00 +02:00
										 |  |  |         "${cfg.virtualHost}" = { | 
					
						
							|  |  |  |           root = "${cfg.root}"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           locations."/" = { | 
					
						
							|  |  |  |             index = "index.php"; | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           locations."~ \.php$" = { | 
					
						
							|  |  |  |             extraConfig = ''
 | 
					
						
							|  |  |  |               fastcgi_split_path_info ^(.+\.php)(/.+)$; | 
					
						
							| 
									
										
										
										
											2018-10-14 13:27:30 +01:00
										 |  |  |               fastcgi_pass unix:${config.services.phpfpm.pools.${cfg.pool}.listen}; | 
					
						
							| 
									
										
										
										
											2018-01-02 21:48:00 +02:00
										 |  |  |               fastcgi_index index.php; | 
					
						
							|  |  |  |             '';
 | 
					
						
							|  |  |  |           }; | 
					
						
							| 
									
										
										
										
											2016-08-27 12:20:28 -07:00
										 |  |  |         }; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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 | 
					
						
							| 
									
										
										
										
											2016-08-27 12:18:04 -07:00
										 |  |  |           callSql = e: | 
					
						
							|  |  |  |               if cfg.database.type == "pgsql" then ''
 | 
					
						
							|  |  |  |                   ${optionalString (cfg.database.password != null) "PGPASSWORD=${cfg.database.password}"} \ | 
					
						
							| 
									
										
										
										
											2019-02-17 01:13:36 +01:00
										 |  |  |                   ${optionalString (cfg.database.passwordFile != null) "PGPASSWORD=$(cat ${cfg.database.passwordFile})"} \ | 
					
						
							| 
									
										
										
										
											2018-01-05 14:17:35 +01:00
										 |  |  |                   ${pkgs.sudo}/bin/sudo -u ${cfg.user} ${config.services.postgresql.package}/bin/psql \ | 
					
						
							| 
									
										
										
										
											2016-08-27 12:18:04 -07:00
										 |  |  |                     -U ${cfg.database.user} \ | 
					
						
							|  |  |  |                     ${optionalString (cfg.database.host != null) "-h ${cfg.database.host} --port ${toString dbPort}"} \ | 
					
						
							|  |  |  |                     -c '${e}' \ | 
					
						
							|  |  |  |                     ${cfg.database.name}''
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               else if cfg.database.type == "mysql" then ''
 | 
					
						
							| 
									
										
										
										
											2018-03-06 03:10:24 +00:00
										 |  |  |                   echo '${e}' | ${pkgs.sudo}/bin/sudo -u ${cfg.user} ${config.services.mysql.package}/bin/mysql \ | 
					
						
							| 
									
										
										
										
											2016-08-27 12:18:04 -07:00
										 |  |  |                     -u ${cfg.database.user} \ | 
					
						
							|  |  |  |                     ${optionalString (cfg.database.password != null) "-p${cfg.database.password}"} \ | 
					
						
							|  |  |  |                     ${optionalString (cfg.database.host != null) "-h ${cfg.database.host} -P ${toString dbPort}"} \ | 
					
						
							|  |  |  |                     ${cfg.database.name}''
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               else ""; | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |         in ''
 | 
					
						
							| 
									
										
										
										
											2016-08-27 12:08:32 -07:00
										 |  |  |           rm -rf "${cfg.root}/*" | 
					
						
							|  |  |  |           mkdir -m 755 -p "${cfg.root}" | 
					
						
							|  |  |  |           cp -r "${pkgs.tt-rss}/"* "${cfg.root}" | 
					
						
							| 
									
										
										
										
											2018-06-04 14:14:57 +02:00
										 |  |  |           ${optionalString (cfg.pluginPackages != []) ''
 | 
					
						
							|  |  |  |             for plugin in ${concatStringsSep " " cfg.pluginPackages}; do | 
					
						
							|  |  |  |               cp -r "$plugin"/* "${cfg.root}/plugins.local/"
 | 
					
						
							|  |  |  |             done | 
					
						
							|  |  |  |           ''}
 | 
					
						
							|  |  |  |           ${optionalString (cfg.themePackages != []) ''
 | 
					
						
							|  |  |  |             for theme in ${concatStringsSep " " cfg.themePackages}; do | 
					
						
							|  |  |  |               cp -r "$theme"/* "${cfg.root}/themes.local/"
 | 
					
						
							|  |  |  |             done | 
					
						
							|  |  |  |           ''}
 | 
					
						
							| 
									
										
										
										
											2016-08-27 12:08:32 -07:00
										 |  |  |           ln -sf "${tt-rss-config}" "${cfg.root}/config.php" | 
					
						
							|  |  |  |           chown -R "${cfg.user}" "${cfg.root}" | 
					
						
							|  |  |  |           chmod -R 755 "${cfg.root}" | 
					
						
							| 
									
										
										
										
											2016-08-27 12:18:04 -07:00
										 |  |  |         ''
 | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-27 12:18:04 -07:00
										 |  |  |         + (optionalString (cfg.database.type == "pgsql") ''
 | 
					
						
							| 
									
										
										
										
											2018-01-05 14:17:35 +01:00
										 |  |  |           ${optionalString (cfg.database.host == null && cfg.database.password == null) ''
 | 
					
						
							|  |  |  |             if ! [ -e ${cfg.root}/.db-created ]; then | 
					
						
							|  |  |  |               ${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} ${config.services.postgresql.package}/bin/createuser ${cfg.database.user} | 
					
						
							|  |  |  |               ${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} ${config.services.postgresql.package}/bin/createdb -O ${cfg.database.user} ${cfg.database.name} | 
					
						
							|  |  |  |               touch ${cfg.root}/.db-created | 
					
						
							|  |  |  |             fi | 
					
						
							|  |  |  |           ''}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |           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; | 
					
						
							| 
									
										
										
										
											2016-08-27 12:18:04 -07:00
										 |  |  |         '')
 | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-27 12:18:04 -07:00
										 |  |  |         + (optionalString (cfg.database.type == "mysql") ''
 | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |           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}"; | 
					
						
							| 
									
										
										
										
											2016-08-27 12:08:32 -07:00
										 |  |  |           ExecStart = "${pkgs.php}/bin/php ${cfg.root}/update.php --daemon"; | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |           StandardOutput = "syslog"; | 
					
						
							|  |  |  |           StandardError = "syslog"; | 
					
						
							|  |  |  |           PermissionsStartOnly = true; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         wantedBy = [ "multi-user.target" ]; | 
					
						
							|  |  |  |         requires = ["${dbService}"]; | 
					
						
							|  |  |  |         after = ["network.target" "${dbService}"]; | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2018-01-02 21:45:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-02 21:48:40 +02:00
										 |  |  |     services.mysql = optionalAttrs (cfg.database.type == "mysql") { | 
					
						
							|  |  |  |       enable = true; | 
					
						
							| 
									
										
										
										
											2018-01-05 14:17:35 +01:00
										 |  |  |       package = mkDefault pkgs.mysql; | 
					
						
							| 
									
										
										
										
											2018-01-02 21:48:40 +02:00
										 |  |  |       ensureDatabases = [ cfg.database.name ]; | 
					
						
							|  |  |  |       ensureUsers = [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           name = cfg.user; | 
					
						
							|  |  |  |           ensurePermissions = { | 
					
						
							|  |  |  |             "${cfg.database.name}.*" = "ALL PRIVILEGES"; | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       ]; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-05 14:17:35 +01:00
										 |  |  |     services.postgresql = optionalAttrs (cfg.database.type == "pgsql") { | 
					
						
							|  |  |  |       enable = mkDefault true; | 
					
						
							| 
									
										
										
										
											2018-01-02 21:45:42 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-05 14:17:35 +01:00
										 |  |  |     users = optionalAttrs (cfg.user == "tt_rss") { | 
					
						
							| 
									
										
										
										
											2018-09-18 21:42:50 +02:00
										 |  |  |       users.tt_rss = { | 
					
						
							|  |  |  |         description = "tt-rss service user"; | 
					
						
							|  |  |  |         isSystemUser = true; | 
					
						
							|  |  |  |         group = "tt_rss"; | 
					
						
							|  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2018-06-30 01:58:35 +02:00
										 |  |  |       groups.tt_rss = {}; | 
					
						
							| 
									
										
										
										
											2018-01-05 14:17:35 +01:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2016-06-05 21:55:46 +03:00
										 |  |  |   }; | 
					
						
							|  |  |  | } |