diff --git a/pkgs/os-specific/bsd/freebsd/patches/14.0/rc-user.patch b/pkgs/os-specific/bsd/freebsd/patches/14.0/rc-user.patch
new file mode 100644
index 000000000000..27e8f9a13f21
--- /dev/null
+++ b/pkgs/os-specific/bsd/freebsd/patches/14.0/rc-user.patch
@@ -0,0 +1,17 @@
+diff --git a/libexec/rc/rc b/libexec/rc/rc
+index 0ea61a4b2c0a..d9bfb228224c 100644
+--- a/libexec/rc/rc
++++ b/libexec/rc/rc
+@@ -87,6 +87,12 @@ if ! [ -e ${firstboot_sentinel} ]; then
+ 	skip_firstboot="-s firstboot"
+ fi
+ 
++if [ -z "$USER_LOGIN" ]; then
++        skip="$skip -s user"
++else
++        skip="$skip -k user"
++fi
++
+ # Do a first pass to get everything up to $early_late_divider so that
+ # we can do a second pass that includes $local_startup directories
+ #
diff --git a/pkgs/os-specific/bsd/freebsd/pkgs/rc.nix b/pkgs/os-specific/bsd/freebsd/pkgs/rc.nix
new file mode 100644
index 000000000000..92b645851b9c
--- /dev/null
+++ b/pkgs/os-specific/bsd/freebsd/pkgs/rc.nix
@@ -0,0 +1,76 @@
+{
+  mkDerivation,
+  lib,
+  sysctl,
+  bash,
+  rcorder,
+  bin,
+  stat,
+  id,
+  protect,
+  mount,
+}:
+let
+  rcDepsPath = lib.makeBinPath [
+    sysctl
+    bin
+    bash
+    rcorder
+    stat
+    id
+    mount
+    protect
+  ];
+in
+mkDerivation {
+  path = "libexec/rc";
+  MK_TESTS = "no";
+
+  postPatch =
+    ''
+      substituteInPlace "$BSDSRCDIR/libexec/rc/rc.d/Makefile" "$BSDSRCDIR/libexec/rc/Makefile" --replace-fail /etc $out/etc
+      substituteInPlace "$BSDSRCDIR/libexec/rc/rc.d/Makefile" --replace-fail /var $out/var
+    ''
+    + (
+      let
+        bins = [
+          "/sbin/sysctl"
+          "/usr/bin/protect"
+          "/usr/bin/id"
+          "/bin/ps"
+          "/bin/cpuset"
+          "/usr/bin/stat"
+          "/bin/rm"
+          "/bin/chmod"
+          "/bin/cat"
+          "/bin/sync"
+          "/bin/sleep"
+          "/bin/date"
+        ];
+        scripts = [
+          "rc"
+          "rc.initdiskless"
+          "rc.shutdown"
+          "rc.subr"
+          "rc.suspend"
+          "rc.resume"
+        ];
+        scriptPaths = "$BSDSRCDIR/libexec/rc/{${lib.concatStringsSep "," scripts}}";
+      in
+      # set PATH correctly in scripts
+      ''
+        sed -E -i -e "s|PATH=.*|PATH=${rcDepsPath}|g" ${scriptPaths}
+      ''
+      # replace executable absolute filepaths with PATH lookups
+      + lib.concatMapStringsSep "\n" (fname: ''
+        sed -E -i -e "s|${fname}|${lib.last (lib.splitString "/" fname)}|g" \
+          ${scriptPaths}'') bins
+    );
+
+  skipIncludesPhase = true;
+
+  postInstall = ''
+    makeFlags="$(sed -E -e 's/CONFDIR=[^ ]*//g' <<<"$makeFlags")"
+    make $makeFlags installconfig
+  '';
+}