Score:0

Systemd: why are files in /tmp or /run deleted after a few seconds?

br flag

I am using systemd to mount a Windows share using Kerberos. To make this work, I first run kinit in a .service file to create a Kerberos credential cache (ccache). The .service runs as root as the ccache needs to be owned by root (journalctl -xe helped me with that), as mount.cifs requires root. The .mount (and .automount) use the ccache to do the Kerberized mount. When I create the ccache interactively, this works well. However, when run inside the service unit, the ccache is quickly deleted and the (auto)mount fails. It does not matter if I save it to /tmp or /run/user/0.

  1. Why are files in /tmp or /run automatically deleted?
  2. What is the preferred location for these ccache files? Is PrivateTmp a better solution? If so, how do I refer to that private tmp dir inside the service file? I tried %T/krb5cc_root.ccache, but systemctl generates an error. Is JoinsNamespaceOf the way to use the same private tmp in the mount file?

I am using systemd 219 on linux CentOS 7. Below is my .service unit. Thanks in advance!

[Unit]
Description=Kinit keytab for /mnt/windows_staging
After=network.target
Requires=network.target

[Service]
Restart=always
RestartSec=30
PrivateTmp=yes
User=root
Group=users
ExecStartPre=-/bin/mkdir -p /mnt/windows_staging
ExecStartPre=-/bin/mkdir -p /run/user/0
Environment=KRB5_KTNAME=/home/albertjan@domain/myproject/etc/keytabs/albertjan.keytab
Environment=KRB5CCNAME=/run/user/0/krb5cc_root.ccache
ExecStart=/bin/kinit albertjan -kt ${KRB5_KTNAME} -c ${KRB5CCNAME}
ExecStartPost=/bin/sleep 2
ExecStop=-/bin/kdestroy -c ${KRB5CCNAME}

[Install]
WantedBy=multi-user.target
Score:0
fr flag

Why are files in /tmp or /run automatically deleted?

Because your service starts a "daemon" that immediately exits, therefore marking the service as "stopped" within seconds of starting, therefore causing the kdestroy from ExecStop= to be run.

  • Option 2: Change the .service definition to tell systemd that this is supposed to be a task that immediately exits, using these options:

    [Service]
    Type=oneshot
    RemainAfterExit=yes
    

    The Type=oneshot mode is additionally useful because will make systemd wait for ExecStart= to fully complete before the service is marked as "active", avoiding the need to add the arbitrary sleep 2. In other words, it lets you use After=kinit.service without worrying that other things will start "too early".

  • Option 1: Replace kinit with the k5start daemon from https://www.eyrie.org/~eagle/software/kstart/. This is a real daemon – a long-running process – and will be tracked as such. It will handle periodic renewal as well.

    If you use k5start with the -b option ("Detach on startup") and change the .service to Type=forking mode accordingly, you will also get the same "delay until success" behavior.

(There's also a third option of letting gssproxy handle all tickets, but cifs.upcall in CentOS doesn't support that yet. For other uses besides mounting filesystems, KRB5_CLIENT_KTNAME would let the program itself acquire tickets from keytab as needed, but it won't work in this case.)

What is the preferred location for these ccache files?

Personally I would stick with /tmp/krb5cc_* or /run/user/<uid>/krb5cc_*. (Those are the only locations NFS rpc.gssd checks.)

For SMB, cifs.upcall will look at the system default location for the UID that's performing the mount (i.e. whatever is defined in krb5.conf), which is usually /tmp/krb5cc_0 when systemd is doing so. (Although cifs.upcall can scrape KRB5CCNAME out of the invoker's environment, that doesn't help with automounts being involved, as cifs.upcall would only see systemd or autofsd as the caller.)

Is PrivateTmp a better solution?

PrivateTmp won't help, because it's not an external task that's deleting your file, it's the service itself doing so.

Albert-Jan Roskam avatar
br flag
Hi, thanks for helping me, I appreciate it. It sounds like `k5start` is the way to go. Too bad it's not yum-installable. I never realized that for type=simple systemd units, execStop is run. I thought this happened when `systemctl stop`, explicitly or implicitly via reboot/shutdown. So, the _proper_ way to renew the kerberos ticket (max lifetime 10h) is to turn the .service into a oneshot as per your recommendation and define a .timer which triggers the .service? And the _clunky_ way is to remove the `kdestroy` execStop, but keep the Restart* parts?
user1686 avatar
fr flag
It should be installable, the package is usually named `kstart` instead of k5start. ExecStop is run for any systemd service when it transitions to "stopped" regardless of type. Yes, it happens when you run `systemctl stop`, but it *also* happens **whenever the service stops on its own** (that is, when the daemon process exits) – the main goal of my post was to point out that your unit is immediately stopping on its own and not just staying "running" afterwards. You don't need to remove ExecStop if the unit has RemainAfterExit; that is the whole point of me suggesting RemainAfterExit.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.