help me find the optimal solution.
I have a compiled application (written in Go if it matters). The application should run as a daemon in Linux and write logs to the user’s home directory. The problem is that the daemon will be launched as root, and the home directory will be that of root.
I tried to add the following line to the postinst script of the deb package:
sed -i "s:%homedir%:${HOME}:g" /lib/systemd/system/mydemon.service
(My application has a CLI parameter that accepts the directory for log writing.)
But if the installation is done with sudo, then we’ll get the wrong directory.
I also tried getting the user’s home directory in the program itself using os.UserHomeDir()
, but it returns the root directory if the application runs under root.
Perhaps there’s a way to obtain the home directory based on the session. For example, in Windows, my service also runs under the "SYSTEM" account, but I get the current user’s directory through the session (using WinAPI, getting the UserToken, then GetUserProfileDirectory).
Is there something similar that can be done in Linux?
2
Answers
I answer my question, if you refine the postinst script, then everything works (it seems)
If you have a system daemon runs as root, it absolutely should not write anything to one specific user’s home directory – neither logs nor something else. That’s just wrong on several levels.
System services should store their data and logs in
/var
on Linux,C:ProgramData
on Windows. They can use ACLs to give that user read access to the log files, although tying that to a single user still seems off; usually such access is tied to a group (e.g. traditionally theadm
group on Linux has general log access).If it is related to one specific user, then it should not run as root – it should run as that user – and it should perhaps not be a system service at all.
You can get the session of the user who’s performing the installation, but it doesn’t make sense to do the same later when the service starts – in general there is no ‘the’ session; not even on Windows. There can always be multiple sessions, with none of them being ‘the’ session; and when a system daemon starts, there will be no sessions yet.
The API for getting logon sessions would be the systemd-logind seat- and session-related functions that are part of
libsystemd
.The API for getting a user profile directory on Linux is
getpwnam()
/getpwuid()
, which returns the user’s passwd entry. There is no guarantee that the home directory will be accessible while the user is not yet logged in; it could be on the network, or it could be encrypted normally and unlocked via PAM (such as what you’d find on Ubuntu).