[GH-ISSUE #39] Error Running Scripts due to Read-Only File System - NixOS #28

Closed
opened 2026-03-02 02:12:49 +03:00 by kerem · 3 comments
Owner

Originally created by @SoarinFerret on GitHub (Nov 24, 2023).
Original GitHub issue: https://github.com/amidaware/rmmagent/issues/39

github.com/amidaware/rmmagent@db17e3e28e/agent/utils.go (L342):L365

NixOS is a Linux distribution built on top of the Nix package manager. Its declarative configuration allows reliable system upgrades via several official channels. One of the features it has is the location where all the binaries are stored are a read-only filesystem.

I am able to successfully build and use the rmmagent on NixOS, except my scripts fail to run due to them trying to run in the same directory where the executable is located. Would the maintainers be open to a pull request adding a runtime feature flag allowing the tmp directory to be changed to a specific location (like --tmpdir /opt/trmm/scripts)? This would not change the default functionality, and could be easily specified in the systemd unit file that my nix package creates.

Originally created by @SoarinFerret on GitHub (Nov 24, 2023). Original GitHub issue: https://github.com/amidaware/rmmagent/issues/39 https://github.com/amidaware/rmmagent/blob/db17e3e28ec0351597c02c7049255f90c85c9e7a/agent/utils.go#L342:L365 NixOS is a Linux distribution built on top of the Nix package manager. Its declarative configuration allows reliable system upgrades via several official channels. One of the features it has is the location where all the binaries are stored are a read-only filesystem. I am able to successfully build and use the rmmagent on NixOS, except my scripts fail to run due to them trying to run in the same directory where the executable is located. Would the maintainers be open to a pull request adding a runtime feature flag allowing the tmp directory to be changed to a specific location (like `--tmpdir /opt/trmm/scripts`)? This would not change the default functionality, and could be easily specified in the systemd unit file that my nix package creates.
kerem closed this issue 2026-03-02 02:12:49 +03:00
Author
Owner

@SoarinFerret commented on GitHub (Nov 24, 2023):

In the meantime, for anyone interested, the following patch file does allow scripts to run correctly on agent v2.5.0 in NixOS. This sends the scripts to /opt/tacticalrmm (only accessible by the user running the agent, which is by default root)

diff --git a/agent/utils.go b/agent/utils.go
index 6eacaca..e731088 100644
--- a/agent/utils.go
+++ b/agent/utils.go
@@ -351,12 +351,17 @@ func getCwd() (string, error) {
 
 func createNixTmpFile() (*os.File, error) {
 	var f *os.File
-	cwd, err := getCwd()
-	if err != nil {
-		return f, err
+
+	dirPath := "/opt/tacticalrmm"
+
+	if _, err := os.Stat(dirPath); os.IsNotExist(err) {
+		err := os.MkdirAll(dirPath, 0750)
+		if err != nil {
+			return f, err
+		}
 	}
 
-	f, err = os.CreateTemp(cwd, "trmm")
+	f, err := os.CreateTemp(dirPath, "trmm")
 	if err != nil {
 		return f, err
 	}

<!-- gh-comment-id:1826083879 --> @SoarinFerret commented on GitHub (Nov 24, 2023): In the meantime, for anyone interested, the following patch file does allow scripts to run correctly on agent v2.5.0 in NixOS. This sends the scripts to `/opt/tacticalrmm` (only accessible by the user running the agent, which is by default root) ```patch diff --git a/agent/utils.go b/agent/utils.go index 6eacaca..e731088 100644 --- a/agent/utils.go +++ b/agent/utils.go @@ -351,12 +351,17 @@ func getCwd() (string, error) { func createNixTmpFile() (*os.File, error) { var f *os.File - cwd, err := getCwd() - if err != nil { - return f, err + + dirPath := "/opt/tacticalrmm" + + if _, err := os.Stat(dirPath); os.IsNotExist(err) { + err := os.MkdirAll(dirPath, 0750) + if err != nil { + return f, err + } } - f, err = os.CreateTemp(cwd, "trmm") + f, err := os.CreateTemp(dirPath, "trmm") if err != nil { return f, err } ```
Author
Owner

@truatpasteurdotfr commented on GitHub (Feb 5, 2024):

+1, that would also allow diskless linux machines to be used with read-only rootfs.

<!-- gh-comment-id:1926714256 --> @truatpasteurdotfr commented on GitHub (Feb 5, 2024): +1, that would also allow diskless linux machines to be used with read-only rootfs.
Author
Owner

@NiceGuyIT commented on GitHub (Aug 11, 2025):

To add to the above, here is the diff to relocate /opt/tacticalagent and /etc/tacticalagent on systems such as TrueNAS Scale where many of the system mount points are read-only and the files are kept on a mountpoint. Obviously the systemd service script will need to be adjusted.

diff --git a/agent/agent.go b/agent/agent.go
index 21d758b..e463756 100644
--- a/agent/agent.go
+++ b/agent/agent.go
@@ -89,9 +89,9 @@ const (
        winExeName           = "tacticalrmm.exe"
        winSvcName           = "tacticalrmm"
        meshSvcName          = "mesh agent"
-       etcConfig            = "/etc/tacticalagent"
-       nixAgentDir          = "/opt/tacticalagent"
-       nixMeshDir           = "/opt/tacticalmesh"
+       etcConfig            = "/mnt/data/system/etc/tacticalagent"
+       nixAgentDir          = "/mnt/data/system/opt/tacticalagent"
+       nixMeshDir           = "/mnt/data/system/opt/tacticalmesh"
        nixAgentBin          = nixAgentDir + "/tacticalagent"
        nixAgentBinDir       = nixAgentDir + "/bin"
        nixAgentEtcDir       = nixAgentDir + "/etc"
diff --git a/agent/agent_unix.go b/agent/agent_unix.go
index 83320a0..ea70fac 100644
--- a/agent/agent_unix.go
+++ b/agent/agent_unix.go
@@ -140,6 +140,7 @@ func NewAgentConfig() *rmm.AgentConfig {
        viper.SetConfigName("tacticalagent")
        viper.SetConfigType("json")
        viper.AddConfigPath("/etc/")
+       viper.AddConfigPath("/mnt/data/system/etc/")
        viper.AddConfigPath(".")
        err := viper.ReadInConfig()
<!-- gh-comment-id:3176932481 --> @NiceGuyIT commented on GitHub (Aug 11, 2025): To add to the above, here is the diff to relocate `/opt/tacticalagent` and `/etc/tacticalagent` on systems such as TrueNAS Scale where many of the system mount points are read-only and the files are kept on a mountpoint. Obviously the systemd service script will need to be adjusted. ```diff diff --git a/agent/agent.go b/agent/agent.go index 21d758b..e463756 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -89,9 +89,9 @@ const ( winExeName = "tacticalrmm.exe" winSvcName = "tacticalrmm" meshSvcName = "mesh agent" - etcConfig = "/etc/tacticalagent" - nixAgentDir = "/opt/tacticalagent" - nixMeshDir = "/opt/tacticalmesh" + etcConfig = "/mnt/data/system/etc/tacticalagent" + nixAgentDir = "/mnt/data/system/opt/tacticalagent" + nixMeshDir = "/mnt/data/system/opt/tacticalmesh" nixAgentBin = nixAgentDir + "/tacticalagent" nixAgentBinDir = nixAgentDir + "/bin" nixAgentEtcDir = nixAgentDir + "/etc" diff --git a/agent/agent_unix.go b/agent/agent_unix.go index 83320a0..ea70fac 100644 --- a/agent/agent_unix.go +++ b/agent/agent_unix.go @@ -140,6 +140,7 @@ func NewAgentConfig() *rmm.AgentConfig { viper.SetConfigName("tacticalagent") viper.SetConfigType("json") viper.AddConfigPath("/etc/") + viper.AddConfigPath("/mnt/data/system/etc/") viper.AddConfigPath(".") err := viper.ReadInConfig() ```
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/rmmagent#28
No description provided.