From 0e2787884e7d6c60e51da9e1c158e75406cac7a9 Mon Sep 17 00:00:00 2001 From: Felix Buehler Date: Fri, 6 Jan 2023 01:25:34 +0100 Subject: [PATCH] nixos/freshrss: fix permissions and add database test --- nixos/modules/services/web-apps/freshrss.nix | 49 ++++++++++--------- nixos/tests/all-tests.nix | 3 +- nixos/tests/freshrss-pgsql.nix | 48 ++++++++++++++++++ .../{freshrss.nix => freshrss-sqlite.nix} | 1 + 4 files changed, 78 insertions(+), 23 deletions(-) create mode 100644 nixos/tests/freshrss-pgsql.nix rename nixos/tests/{freshrss.nix => freshrss-sqlite.nix} (94%) diff --git a/nixos/modules/services/web-apps/freshrss.nix b/nixos/modules/services/web-apps/freshrss.nix index c05e7b2c4f7f..89e29f7ccb51 100644 --- a/nixos/modules/services/web-apps/freshrss.nix +++ b/nixos/modules/services/web-apps/freshrss.nix @@ -60,7 +60,7 @@ in }; port = mkOption { - type = with types; nullOr port; + type = types.nullOr types.port; default = null; description = mdDoc "Database port for FreshRSS."; example = 3306; @@ -73,7 +73,7 @@ in }; passFile = mkOption { - type = types.nullOr types.str; + type = types.nullOr types.path; default = null; description = mdDoc "Database password file for FreshRSS."; example = "/run/secrets/freshrss"; @@ -116,12 +116,18 @@ in with default values. ''; }; - }; + user = mkOption { + type = types.str; + default = "freshrss"; + description = lib.mdDoc "User under which Freshrss runs."; + }; + }; config = let - systemd-hardening = { + defaultServiceConfig = { + ReadWritePaths = "${cfg.dataDir}"; CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ]; DeviceAllow = ""; LockPersonality = true; @@ -146,6 +152,11 @@ in SystemCallArchitectures = "native"; SystemCallFilter = [ "@system-service" "~@resources" "~@privileged" ]; UMask = "0007"; + Type = "oneshot"; + User = cfg.user; + Group = config.users.users.${cfg.user}.group; + StateDirectory = "freshrss"; + WorkingDirectory = cfg.package; }; in mkIf cfg.enable { @@ -199,12 +210,17 @@ in }; }; - users.users.freshrss = { + users.users."${cfg.user}" = { description = "FreshRSS service user"; isSystemUser = true; - group = "freshrss"; + group = "${cfg.user}"; + home = cfg.dataDir; }; - users.groups.freshrss = { }; + users.groups."${cfg.user}" = { }; + + systemd.tmpfiles.rules = [ + "d '${cfg.dataDir}' - ${cfg.user} ${config.users.users.${cfg.user}.group} - -" + ]; systemd.services.freshrss-config = let @@ -228,30 +244,24 @@ in { description = "Set up the state directory for FreshRSS before use"; wantedBy = [ "multi-user.target" ]; - serviceConfig = { + serviceConfig = defaultServiceConfig //{ Type = "oneshot"; User = "freshrss"; Group = "freshrss"; StateDirectory = "freshrss"; WorkingDirectory = cfg.package; - } // systemd-hardening; + }; environment = { FRESHRSS_DATA_PATH = cfg.dataDir; }; script = '' - # create files with correct permissions - mkdir -m 755 -p ${cfg.dataDir} - # do installation or reconfigure if test -f ${cfg.dataDir}/config.php; then # reconfigure with settings ./cli/reconfigure.php ${settingsFlags} ./cli/update-user.php --user ${cfg.defaultUser} --password "$(cat ${cfg.passwordFile})" else - # Copy the user data template directory - cp -r ./data ${cfg.dataDir} - # check correct folders in data folder ./cli/prepare.php # install with settings @@ -269,14 +279,9 @@ in environment = { FRESHRSS_DATA_PATH = cfg.dataDir; }; - serviceConfig = { - Type = "oneshot"; - User = "freshrss"; - Group = "freshrss"; - StateDirectory = "freshrss"; - WorkingDirectory = cfg.package; + serviceConfig = defaultServiceConfig //{ ExecStart = "${cfg.package}/app/actualize_script.php"; - } // systemd-hardening; + }; }; }; } diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 83ad7c48a089..e5dc4a82e1b4 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -225,7 +225,8 @@ in { fontconfig-default-fonts = handleTest ./fontconfig-default-fonts.nix {}; freenet = handleTest ./freenet.nix {}; freeswitch = handleTest ./freeswitch.nix {}; - freshrss = handleTest ./freshrss.nix {}; + freshrss-sqlite = handleTest ./freshrss-sqlite.nix {}; + freshrss-pgsql = handleTest ./freshrss-pgsql.nix {}; frr = handleTest ./frr.nix {}; fsck = handleTest ./fsck.nix {}; ft2-clone = handleTest ./ft2-clone.nix {}; diff --git a/nixos/tests/freshrss-pgsql.nix b/nixos/tests/freshrss-pgsql.nix new file mode 100644 index 000000000000..055bd51ed43d --- /dev/null +++ b/nixos/tests/freshrss-pgsql.nix @@ -0,0 +1,48 @@ +import ./make-test-python.nix ({ lib, pkgs, ... }: { + name = "freshrss"; + meta.maintainers = with lib.maintainers; [ etu stunkymonkey ]; + + nodes.machine = { pkgs, ... }: { + services.freshrss = { + enable = true; + baseUrl = "http://localhost"; + passwordFile = pkgs.writeText "password" "secret"; + dataDir = "/srv/freshrss"; + database = { + type = "pgsql"; + port = 5432; + user = "freshrss"; + passFile = pkgs.writeText "db-password" "db-secret"; + }; + }; + + services.postgresql = { + enable = true; + ensureDatabases = [ "freshrss" ]; + ensureUsers = [ + { + name = "freshrss"; + ensurePermissions = { + "DATABASE freshrss" = "ALL PRIVILEGES"; + }; + } + ]; + initialScript = pkgs.writeText "postgresql-password" '' + CREATE ROLE freshrss WITH LOGIN PASSWORD 'db-secret' CREATEDB; + ''; + }; + + systemd.services."freshrss-config" = { + requires = [ "postgresql.service" ]; + after = [ "postgresql.service" ]; + }; + }; + + testScript = '' + machine.wait_for_unit("multi-user.target") + machine.wait_for_open_port(5432) + machine.wait_for_open_port(80) + response = machine.succeed("curl -vvv -s -H 'Host: freshrss' http://127.0.0.1:80/i/") + assert 'Login ยท FreshRSS' in response, "Login page didn't load successfully" + ''; +}) diff --git a/nixos/tests/freshrss.nix b/nixos/tests/freshrss-sqlite.nix similarity index 94% rename from nixos/tests/freshrss.nix rename to nixos/tests/freshrss-sqlite.nix index 7bdbf29e9230..b821c98a7e7a 100644 --- a/nixos/tests/freshrss.nix +++ b/nixos/tests/freshrss-sqlite.nix @@ -7,6 +7,7 @@ import ./make-test-python.nix ({ lib, pkgs, ... }: { enable = true; baseUrl = "http://localhost"; passwordFile = pkgs.writeText "password" "secret"; + dataDir = "/srv/freshrss"; }; };