{ config, options, lib, pkgs, ... }: with lib; let cfg = config.services.wallabag; poolName = "wallabag"; configFile = pkgs.writeTextFile { name = "wallabag-config"; text = cfg.conf; destination = "/app/config/parameters.yml"; }; appDir = pkgs.buildEnv { name = "wallabag-app-dir"; ignoreCollisions = true; checkCollisionContents = false; paths = [ configFile "${cfg.package}" ]; pathsToLink = [ "/app" "/src" "/translations" ]; }; # See there for available commands: # https://doc.wallabag.org/en/admin/console_commands.html # A user can be made admin with the fos:user:promote --super command console = pkgs.writeShellScriptBin "wallabag-console" '' export WALLABAG_DATA="${cfg.dataDir}" cd "${cfg.dataDir}" ${pkgs.php}/bin/php ${pkgs.wallabag}/bin/console --env=prod $@ ''; in { options = { services.wallabag = { enable = mkEnableOption "wallabag"; user = mkOption { type = types.str; default = "nginx"; description = '' User account under which both the update daemon and the web-application run. ''; }; dataDir = mkOption { type = types.path; default = "/var/lib/wallabag"; description = '' Data directory. ''; }; package = mkOption { type = types.package; default = pkgs.wallabag; description = '' Wallabag package to use. ''; }; hostName = mkOption { type = types.str; description = '' Name of the nginx virtualhost to use and setup. ''; }; poolConfig = mkOption { type = types.lines; default = '' pm = dynamic pm.max_children = 75 pm.start_servers = 1 pm.min_spare_servers = 1 pm.max_spare_servers = 20 pm.max_requests = 500 catch_workers_output = 1 ''; description = '' Options for wallabag's PHP pool. See the documentation on php-fpm.conf for details on configuration directives. ''; }; conf = mkOption { type = types.str; description = '' Contents of the wallabag configuration file (parameters.yml) ''; }; }; }; config = mkIf cfg.enable { services.phpfpm.pools."${poolName}" = { user = "${cfg.user}"; group = "nginx"; phpPackage = pkgs.php; phpEnv = { WALLABAG_DATA = cfg.dataDir; PATH = lib.makeBinPath [pkgs.php]; }; settings = { "listen.owner" = "nginx"; "listen.group" = "nginx"; "listen.mode" = "0600"; "user" = "${cfg.user}"; "group" = "nginx"; "pm" = "dynamic"; "pm.max_children" = "75"; "pm.min_spare_servers" = "5"; "pm.max_spare_servers" = "20"; "pm.max_requests" = "10"; "catch_workers_output" = "1"; "php_admin_value[error_log]" = "stderr"; "php_admin_flag[log_errors]" = true; }; }; services.phpfpm.phpOptions = '' max_execution_time = 120 ''; services.nginx.enable = mkDefault true; environment.systemPackages = [ console ]; # services.nginx.virtualHosts."${cfg.hostName}" = { # forceSSL = false; # enableACME = false; # extraConfig = '' # error_log /var/log/nginx/wallabag_error.log; # access_log /var/log/nginx/wallabag_access.log; # ''; # root = "${cfg.package}/web"; # locations."/" = { # priority = 10; # tryFiles = "$uri /app.php$is_args$args"; # }; # locations."/assets".root = "${cfg.dataDir}/web"; # locations."~ ^/app\\.php(/|$)" = { # priority = 100; # fastcgiParams = { # SCRIPT_FILENAME = "$realpath_root$fastcgi_script_name"; # DOCUMENT_ROOT = "$realpath_root"; # }; # extraConfig = '' # fastcgi_pass unix:${config.services.phpfpm.pools."${poolName}".socket}; # include ${config.services.nginx.package}/conf/fastcgi_params; # include ${config.services.nginx.package}/conf/fastcgi.conf; # internal; # ''; # }; # locations."~ \\.php$" = { # priority = 1000; # return = "404"; # }; # }; services.nginx.virtualHosts."${cfg.hostName}" = { enableACME = false; forceSSL = false; root = "${cfg.package}/web"; extraConfig = '' add_header X-Frame-Options SAMEORIGIN; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; ''; locations."/" = { tryFiles = "$uri /app.php$is_args$args"; }; locations."/assets".root = "${cfg.dataDir}/web"; locations."~ ^/app\\.php(/|$)" = { fastcgiParams = { SCRIPT_FILENAME = "$realpath_root$fastcgi_script_name"; DOCUMENT_ROOT = "$realpath_root"; }; extraConfig = '' fastcgi_pass unix:${config.services.phpfpm.pools."${poolName}".socket}; include ${config.services.nginx.package}/conf/fastcgi_params; include ${config.services.nginx.package}/conf/fastcgi.conf; internal; ''; # extraConfig = '' # fastcgi_pass unix:${config.services.phpfpm.pools."${poolName}".socket}; # fastcgi_split_path_info ^(.+\.php)(/.*)$; # include ${pkgs.nginx}/conf/fastcgi_params; # fastcgi_param SCRIPT_FILENAME ${cfg.package}/web/$fastcgi_script_name; # fastcgi_param DOCUMENT_ROOT ${cfg.package}/web; # fastcgi_read_timeout 120; # internal; # ''; }; locations."~ /(?!app)\\.php$" = { extraConfig = '' return 404; ''; }; }; systemd.services.wallabag-install = { description = "Wallabag install service"; wantedBy = [ "multi-user.target" ]; before = [ "phpfpm-wallabag.service" ]; after = [ "mysql.service" "postgresql.service" ]; path = with pkgs; [ coreutils php phpPackages.composer ]; serviceConfig = { User = cfg.user; Type = "oneshot"; RemainAfterExit = "yes"; PermissionsStartOnly = true; }; preStart = '' mkdir -p "${cfg.dataDir}" chown ${cfg.user}:nginx "${cfg.dataDir}" ''; script = '' echo "Setting up wallabag files in ${cfg.dataDir} ..." cd "${cfg.dataDir}" rm -rf var/cache/* rm -f app src translations ln -sf ${appDir}/app app ln -sf ${appDir}/src src ln -sf ${appDir}/translations translations ln -sf ${cfg.package}/composer.{json,lock} . export WALLABAG_DATA="${cfg.dataDir}" if [ ! -f installed ]; then echo "Install file not found, installing ..." php ${cfg.package}/bin/console --env=prod doctrine:database:create --if-not-exists --no-interaction php ${cfg.package}/bin/console --env=prod doctrine:migrations:migrate --no-interaction # Until https://github.com/wallabag/wallabag/issues/3662 is fixed # yes no | php ${cfg.package}/bin/console --env=prod wallabag:install touch installed else php ${cfg.package}/bin/console --env=prod doctrine:migrations:migrate --no-interaction fi php ${cfg.package}/bin/console --env=prod cache:clear ''; }; }; meta = with stdenv.lib; { maintainers = with maintainers; [ nadrieril ]; }; }