nixos/freshrss: fix permissions and add database test

This commit is contained in:
Felix Buehler 2023-01-06 01:25:34 +01:00
parent 1a6f1bfe58
commit 0e2787884e
4 changed files with 78 additions and 23 deletions

View file

@ -60,7 +60,7 @@ in
}; };
port = mkOption { port = mkOption {
type = with types; nullOr port; type = types.nullOr types.port;
default = null; default = null;
description = mdDoc "Database port for FreshRSS."; description = mdDoc "Database port for FreshRSS.";
example = 3306; example = 3306;
@ -73,7 +73,7 @@ in
}; };
passFile = mkOption { passFile = mkOption {
type = types.nullOr types.str; type = types.nullOr types.path;
default = null; default = null;
description = mdDoc "Database password file for FreshRSS."; description = mdDoc "Database password file for FreshRSS.";
example = "/run/secrets/freshrss"; example = "/run/secrets/freshrss";
@ -116,12 +116,18 @@ in
with default values. with default values.
''; '';
}; };
};
user = mkOption {
type = types.str;
default = "freshrss";
description = lib.mdDoc "User under which Freshrss runs.";
};
};
config = config =
let let
systemd-hardening = { defaultServiceConfig = {
ReadWritePaths = "${cfg.dataDir}";
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ]; CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
DeviceAllow = ""; DeviceAllow = "";
LockPersonality = true; LockPersonality = true;
@ -146,6 +152,11 @@ in
SystemCallArchitectures = "native"; SystemCallArchitectures = "native";
SystemCallFilter = [ "@system-service" "~@resources" "~@privileged" ]; SystemCallFilter = [ "@system-service" "~@resources" "~@privileged" ];
UMask = "0007"; UMask = "0007";
Type = "oneshot";
User = cfg.user;
Group = config.users.users.${cfg.user}.group;
StateDirectory = "freshrss";
WorkingDirectory = cfg.package;
}; };
in in
mkIf cfg.enable { mkIf cfg.enable {
@ -199,12 +210,17 @@ in
}; };
}; };
users.users.freshrss = { users.users."${cfg.user}" = {
description = "FreshRSS service user"; description = "FreshRSS service user";
isSystemUser = true; 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 = systemd.services.freshrss-config =
let let
@ -228,30 +244,24 @@ in
{ {
description = "Set up the state directory for FreshRSS before use"; description = "Set up the state directory for FreshRSS before use";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
serviceConfig = { serviceConfig = defaultServiceConfig //{
Type = "oneshot"; Type = "oneshot";
User = "freshrss"; User = "freshrss";
Group = "freshrss"; Group = "freshrss";
StateDirectory = "freshrss"; StateDirectory = "freshrss";
WorkingDirectory = cfg.package; WorkingDirectory = cfg.package;
} // systemd-hardening; };
environment = { environment = {
FRESHRSS_DATA_PATH = cfg.dataDir; FRESHRSS_DATA_PATH = cfg.dataDir;
}; };
script = '' script = ''
# create files with correct permissions
mkdir -m 755 -p ${cfg.dataDir}
# do installation or reconfigure # do installation or reconfigure
if test -f ${cfg.dataDir}/config.php; then if test -f ${cfg.dataDir}/config.php; then
# reconfigure with settings # reconfigure with settings
./cli/reconfigure.php ${settingsFlags} ./cli/reconfigure.php ${settingsFlags}
./cli/update-user.php --user ${cfg.defaultUser} --password "$(cat ${cfg.passwordFile})" ./cli/update-user.php --user ${cfg.defaultUser} --password "$(cat ${cfg.passwordFile})"
else else
# Copy the user data template directory
cp -r ./data ${cfg.dataDir}
# check correct folders in data folder # check correct folders in data folder
./cli/prepare.php ./cli/prepare.php
# install with settings # install with settings
@ -269,14 +279,9 @@ in
environment = { environment = {
FRESHRSS_DATA_PATH = cfg.dataDir; FRESHRSS_DATA_PATH = cfg.dataDir;
}; };
serviceConfig = { serviceConfig = defaultServiceConfig //{
Type = "oneshot";
User = "freshrss";
Group = "freshrss";
StateDirectory = "freshrss";
WorkingDirectory = cfg.package;
ExecStart = "${cfg.package}/app/actualize_script.php"; ExecStart = "${cfg.package}/app/actualize_script.php";
} // systemd-hardening; };
}; };
}; };
} }

View file

@ -225,7 +225,8 @@ in {
fontconfig-default-fonts = handleTest ./fontconfig-default-fonts.nix {}; fontconfig-default-fonts = handleTest ./fontconfig-default-fonts.nix {};
freenet = handleTest ./freenet.nix {}; freenet = handleTest ./freenet.nix {};
freeswitch = handleTest ./freeswitch.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 {}; frr = handleTest ./frr.nix {};
fsck = handleTest ./fsck.nix {}; fsck = handleTest ./fsck.nix {};
ft2-clone = handleTest ./ft2-clone.nix {}; ft2-clone = handleTest ./ft2-clone.nix {};

View file

@ -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 '<title>Login · FreshRSS</title>' in response, "Login page didn't load successfully"
'';
})

View file

@ -7,6 +7,7 @@ import ./make-test-python.nix ({ lib, pkgs, ... }: {
enable = true; enable = true;
baseUrl = "http://localhost"; baseUrl = "http://localhost";
passwordFile = pkgs.writeText "password" "secret"; passwordFile = pkgs.writeText "password" "secret";
dataDir = "/srv/freshrss";
}; };
}; };