{ config, lib, pkgs, ... }: let # Based on https://github.com/wallabag/wallabag/blob/2.6.6/app/config/parameters.yml.dist settings = { database_driver = "${cfg.database_type}"; database_host = null; database_port = 5432; database_name = "wallabag"; database_user = "wallabag"; database_password = null; database_path = null; database_table_prefix = "wallabag_"; database_socket = "/run/postgresql"; database_charset = "utf8"; domain_name = "http://${cfg.domain}"; server_name = "Wallabag"; # Needs an explicit command since Symfony version used by Wallabag does not yet support the `native` transport # and the `sendmail` transport does not respect `sendmail_path` configured in `php.ini`. mailer_dsn = "sendmail://default?command=/run/wrappers/bin/sendmail%%20-t%%20-i"; locale = "en"; # A secret key that's used to generate certain security-related tokens. # "env(SECRET_FILE)" = "/run/secrets/wallabag"; # secret = "%env(file:resolve:SECRET_FILE)%"; # two factor stuff twofactor_auth = false; twofactor_sender = ""; # fosuser stuff fosuser_registration = false; fosuser_confirmation = false; # how long the access token should live in seconds for the API fos_oauth_server_access_token_lifetime = 3600; # how long the refresh token should life in seconds for the API fos_oauth_server_refresh_token_lifetime = 1209600; from_email = "wallabag@read.mossnet.lan"; # RabbitMQ processing redis_scheme = "unix"; redis_host = ""; # Ignored for unix scheme redis_port = 0; # Ignored for unix scheme redis_path = config.services.redis.servers.wallabag.unixSocket; redis_password = null; # Redis processing rabbitmq_host = ""; rabbitmq_port = 0; rabbitmq_user = ""; rabbitmq_password = ""; rabbitmq_prefetch_count = 0; # sentry logging sentry_dsn = null; } // cfg.parameters; php = cfg.php.package.withExtensions ({ enabled, all }: enabled ++ (with all; [ imagick tidy ])); commonServiceConfig = { CacheDirectory = "wallabag"; # Stores sessions. CacheDirectoryMode = "700"; ConfigurationDirectory = "wallabag"; LogsDirectory = "wallabag"; StateDirectory = "wallabag"; # Stores site-credentials-secret-key.txt. StateDirectoryMode = "700"; }; cfg = config.services.wallabag; in { options.services.wallabag = with lib; { enable = mkEnableOption (mdDoc "Wallabag read-it-later service"); package = mkOption { type = types.package; default = pkgs.wallabag; }; php.package = mkOption { type = types.package; default = pkgs.php; }; parameters = mkOption { type = types.attrsOf types.str; default = {}; description = mdDoc "Parameters to override from the default. See for values."; }; database_type = mkOption { type = types.enum [ "pdo_sqlite3" "pdo_pgsql" ]; default = if config.services.postgresql.enable then "pdo_pgsql" else "pdo_sqlite3"; defaultText = '' if config.services.postgresql.enable then "pdo_pgsql" else "pdo_sqlite3" ''; description = mdDoc '' The database engine name. Can be pdo_sqlite3 or pdo_pgsql. ''; }; domain = mkOption { type = types.str; description = "Bare domain name for Wallabag"; }; virtualHost.enable = mkEnableOption (mdDoc "Define nginx virtualhost for Wallabag"); }; config = lib.mkIf cfg.enable { environment.etc."wallabag/parameters.yml" = { source = pkgs.writeTextFile { name = "wallabag-config"; text = builtins.toJSON { parameters = settings; }; }; }; services.nginx = lib.mkIf cfg.virtualHost.enable { enable = true; virtualHosts = { "${cfg.domain}" = { root = "${pkgs.wallabag}/web"; extraConfig = '' add_header X-Frame-Options SAMEORIGIN; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; ''; locations."/" = { extraConfig = '' try_files $uri /app.php$is_args$args; ''; }; locations."/assets".root = "${pkgs.wallabag}/app/web"; locations."~ ^/app\\.php(/|$)" = { extraConfig = '' fastcgi_pass unix:${config.services.phpfpm.pools.wallabag.socket}; include ${config.services.nginx.package}/conf/fastcgi.conf; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; fastcgi_param SCRIPT_FILENAME ${pkgs.wallabag}/web/$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT ${pkgs.wallabag}/web; fastcgi_read_timeout 120; internal; ''; }; locations."~ /(?!app)\\.php$" = { extraConfig = '' return 404; ''; }; }; }; }; services.phpfpm.pools.wallabag = { user = config.users.users.wallabag.name; phpPackage = php; settings = { "catch_workers_output" = true; "listen.owner" = config.services.nginx.user; "listen.group" = "root"; "pm" = "dynamic"; "pm.max_children" = 5; "pm.start_servers" = 2; "pm.min_spare_servers" = 1; "pm.max_spare_servers" = 3; "php_admin_value[error_log]" = "/var/log/wallabag/error.log"; "php_admin_value[access_log]" = "/var/log/wallabag/access.log"; "php_admin_flag[log_errors]" = true; }; phpOptions = '' ; Set up $_ENV superglobal. ; http://php.net/request-order variables_order = "EGPCS" # Wallabag will crash on start-up. # https://github.com/wallabag/wallabag/issues/6042 # error_reporting = E_ALL & ~E_USER_DEPRECATED & ~E_DEPRECATED ''; settings = { # Accept settings from the systemd service. clear_env = false; }; }; users.users.wallabag = { isSystemUser = true; group = "wallabag"; }; users.groups.wallabag = {}; services.redis.servers.wallabag = { enable = true; user = "wallabag"; }; services.rabbitmq.enable = false; systemd.services.phpfpm-wallabag.serviceConfig = commonServiceConfig; systemd.services.wallabag-install = { description = "Wallabag install service"; wantedBy = [ "multi-user.target" ]; before = [ "phpfpm-wallabag.service" ]; after = [ "postgresql.service" ]; path = with pkgs; [ coreutils php phpPackages.composer ]; serviceConfig = { User = "wallabag"; Type = "oneshot"; } // commonServiceConfig; script = '' if [ ! -f "$STATE_DIRECTORY/installed" ]; then php ${pkgs.wallabag}/bin/console --env=prod wallabag:install touch "$STATE_DIRECTORY/installed" else php ${pkgs.wallabag}/bin/console --env=prod doctrine:migrations:migrate --no-interaction fi php ${pkgs.wallabag}/bin/console --env=prod cache:clear ''; }; }; }