diff --git a/hosts/temmie/services/nfs-mounts.nix b/hosts/temmie/services/nfs-mounts.nix index b63f6f0..c0b7a2e 100644 --- a/hosts/temmie/services/nfs-mounts.nix +++ b/hosts/temmie/services/nfs-mounts.nix @@ -88,8 +88,9 @@ in [[ -d "$dir" ]] || continue uid="$(stat -c '%u' "$dir")" + username="$(basename "$dir")" - mountpoint="/run/pvvhome/by-uid/$uid" + mountpoint="/run/pvvhome/by-uid/$uid/$1/$username" mkdir -p "$mountpoint" unit_name=$(systemd-escape --path --suffix=mount "$mountpoint") diff --git a/hosts/temmie/services/userweb/default.nix b/hosts/temmie/services/userweb/default.nix index 18534fd..7698075 100644 --- a/hosts/temmie/services/userweb/default.nix +++ b/hosts/temmie/services/userweb/default.nix @@ -1,5 +1,6 @@ { imports = [ + ./fcgiwrap.nix ./httpd.nix ./log-processor.nix ./mail.nix diff --git a/hosts/temmie/services/userweb/fcgiwrap.nix b/hosts/temmie/services/userweb/fcgiwrap.nix new file mode 100644 index 0000000..958390f --- /dev/null +++ b/hosts/temmie/services/userweb/fcgiwrap.nix @@ -0,0 +1,85 @@ +{ config, lib, pkgs, ... }: +let + mcfg = config.services.pvv-userweb; +in +{ + config = lib.mkIf mcfg.enable { + systemd.slices.system-userweb-fcgiwrap = { }; + + # NOTE: expected %i here is the UID of the user + systemd.sockets."userweb-fcgiwrap@" = { + description = "UserWeb fcgiwrap server for user %i"; + socketConfig = { + ListenStream = "/run/userweb-fcgiwrap/%i.sock"; + RemoveOnStop = true; + + SocketUser = "wwwrun"; + SocketGroup = "wwwrun"; + SocketMode = "0660"; + }; + }; + + systemd.services."userweb-fcgiwrap@" = { + after = [ + "httpd-passwd-sync.service" + ]; + requires = [ + "httpd-passwd-sync.service" + ]; + documentation = [ "man:fcgiwrap(8)" ]; + + unitConfig = { + AssertPathExists = "/run/pvvhome/by-uid/%i"; + }; + + serviceConfig = { + + Slice = "system-userweb-fcgiwrap.slice"; + Type = "simple"; + User = "%i"; + + ExecStart = "${lib.getExe pkgs.fcgiwrap}"; + + RuntimeDirectoryMode = "0750"; + RuntimeDirectory = [ + "fcgiwrap/%i/root-mnt" + ]; + RootDirectory = "/run/fcgiwrap/%i/root-mnt"; + MountAPIVFS = true; + BindReadOnlyPaths = [ + builtins.storeDir + "/etc" + + # TODO: set up minimal fake passwd + group in `ExecStartPre` instead + "/var/lib/httpd-passwd-sync/passwd:/etc/passwd" + "/var/lib/httpd-passwd-sync/group:/etc/group" + + "${pkgs.writeText "userweb-fake-nsswitch.conf" '' + passwd: files + group: files + shadow: files + sudoers: files + + hosts: mymachines resolve [!UNAVAIL=return] files myhostname dns + networks: files + + ethers: files + services: files + protocols: files + rpc: files + + subuid: files + subgid: files + ''}:/etc/nsswitch.conf" + ] ++ lib.optionals mcfg.debugMode [ + "/bin" + ] ++ mcfg.fhsBindPaths; + + # TODO: handle /amd/homepvv${l} + BindPaths = [ + "/run/pvvhome/by-uid/%i:/home/pvv" + ]; + }; + }; + }; +} diff --git a/hosts/temmie/services/userweb/httpd.nix b/hosts/temmie/services/userweb/httpd.nix index 4df6dfa..c3e5994 100644 --- a/hosts/temmie/services/userweb/httpd.nix +++ b/hosts/temmie/services/userweb/httpd.nix @@ -277,30 +277,7 @@ in "/dev/null" "/var/lib/acme" "/var/run/nscd" - "${mcfg.fhsEnv}/bin:/bin" - "${mcfg.fhsEnv}/sbin:/sbin" - "${mcfg.fhsEnv}/lib:/lib" - "${mcfg.fhsEnv}/share:/share" - ] ++ (lib.mapCartesianProduct ({ parent, child }: "${mcfg.fhsEnv}${child}:${parent}${child}") { - parent = [ - "/local" - "/opt" - "/opt/local" - "/store" - "/store/gnu" - "/usr" - "/usr/local" - "/run/current-system/sw" - ]; - child = [ - "/bin" - "/sbin" - "/lib" - "/libexec" - "/include" - "/share" - ]; - }); + ] ++ mcfg.fhsBindPaths; BindPaths = (lib.mapCartesianProduct ({ directoryFn, letter }: "/run/pvvhome/${letter}:${directoryFn letter}${letter}") { directoryFn = [ (_: "/home/pvv/") diff --git a/hosts/temmie/services/userweb/module.nix b/hosts/temmie/services/userweb/module.nix index 4a7d4df..3770bbf 100644 --- a/hosts/temmie/services/userweb/module.nix +++ b/hosts/temmie/services/userweb/module.nix @@ -106,6 +106,36 @@ in ]; }; }; + + fhsBindPaths = lib.mkOption { + type = lib.types.listOf lib.types.str; + readOnly = true; + default = [ + "${cfg.fhsEnv}/bin:/bin" + "${cfg.fhsEnv}/sbin:/sbin" + "${cfg.fhsEnv}/lib:/lib" + "${cfg.fhsEnv}/share:/share" + ] ++ (lib.mapCartesianProduct ({ parent, child }: "${cfg.fhsEnv}${child}:${parent}${child}") { + parent = [ + "/local" + "/opt" + "/opt/local" + "/store" + "/store/gnu" + "/usr" + "/usr/local" + "/run/current-system/sw" + ]; + child = [ + "/bin" + "/sbin" + "/lib" + "/libexec" + "/include" + "/share" + ]; + }); + }; }; config = lib.mkIf cfg.enable {