systemd tmpfiles.d: make folder, clear old files
Your /run/myapp folder dey lost after reboot and /tmp dey chop your small disk? Use tmpfiles.d and RuntimeDirectory= on Ubuntu 24.04 to fix both, with tests.
Wetin systemd tmpfiles.d dey do for your server
systemd tmpfiles.d na where you go tell systemd: make this folder for boot, give am this owner, and clear old files inside am after some days. If your app socket folder for /run/myapp dey lost after every reboot, one short line inside /etc/tmpfiles.d go bring am back. If /tmp and /var/tmp dey chop your small disk, the same kind of file fit clear old things for you. For a folder wey belong to only one service, RuntimeDirectory= inside the unit file fit do the /run part more simple.
This guide na for Ubuntu 24.04. When you dey pay for every GB of disk, junk files wey nobody dey watch na money wey you dey waste. So run every command here on your own box and read the output. No just copy and go.
Why /run/myapp dey disappear after every reboot
/run no be normal disk folder. Na tmpfs, meaning say e dey inside RAM. The Linux file system hierarchy spec describe /run as the place for runtime data like socket files, and e talk say the directory "is flushed on boot". So any folder wey you create with hand inside /run go vanish when the machine restart. Your app start after boot, e try write /run/myapp/app.sock, e no see the folder, and e fail.
Check am yourself:
findmnt /runFor the FSTYPE column you go see tmpfs. That one confirm am. The problem no be your app. The folder just no exist again, because nothing create am back after boot.
/tmp and /var/tmp: wetin Ubuntu 24.04 dey really do
Many posts talk say Linux dey clear /tmp after 10 days and /var/tmp after 30 days. That one na the plain upstream systemd file. Ubuntu 24.04 no follow am. Ubuntu patch the systemd package (changelog entry 255.4-1ubuntu2, LP: #2019026), and the patched tmp.conf get these two lines:
D /tmp 1777 root root 30d
#q /var/tmp 1777 root root 30dThe first line mean say /tmp go empty for every boot, because of the D. E also mean say files wey old pass 30 days go clear even if the server no restart. The second line get # for front, so na comment. This file no dey clean /var/tmp at all. Na there old uploads and build files dey gather until the disk full.
No just believe wetin I write. Check wetin your own box get:
cat /usr/lib/tmpfiles.d/tmp.conf
dpkg -S /usr/lib/tmpfiles.d/tmp.conf
findmnt /tmpThe cat show you the real lines. The dpkg -S tell you which package own the file. For findmnt /tmp, empty output mean say /tmp no be im own mount, so e no be tmpfs and e dey use real disk. The Ubuntu systemd package source get this comment: "we don't want /tmp to be a tmpfs by default". So on 24.04 expect empty output there, and know say every file inside /tmp dey chop real disk space.
If you dey run Ubuntu 26.04, no carry these 24.04 values go there. Run the same cat and read wetin your box really get.
If the disk don already full and df and du no gree agree, read why df and du dey show different numbers when disk full first. A file wey you delete but one process still hold open no go show for du, so cleaning /tmp no go help that case.
How one systemd tmpfiles.d line take build
Each line get up to seven fields, with space between them:
#Type Path Mode User Group Age Argument
d /run/myapp 0750 www-data www-data -- Type: one letter wey talk wetin to do. The next section explain the ones you need.
- Path: the full path of the file or folder.
- Mode: the permission, for octal, like
0750. If you write-, a directory get 0755 and other files get 0644. If you put:for front of the mode, systemd only use am when e dey create new thing. If the thing already exist, e leave the mode as e be. - User and Group: the owner. If you write
-, e use the user wey run systemd-tmpfiles, and for boot na root. The user must already exist. On Ubuntu,www-datadey there from the start. - Age: how old a file go be before cleanup remove am, like
7dor12h. If you write-, no cleanup go happen. If you write0, cleanup go clear am every time e run. - Argument: only some types use am. For
L, na the symlink target.
Where the file go stay: /etc/tmpfiles.d/ na for you, the admin. Packages put their own inside /usr/lib/tmpfiles.d/. If your file for /etc/tmpfiles.d get the same name as one for /usr/lib/tmpfiles.d, your own win. systemd dey read the files for alphabet order of the filename. If two lines name the same path, the one wey come first win. The filename must end with .conf.
The six types wey you go use pass
d: create the directory if e no dey. Fix the mode and owner if you give them. With Age, e clean old files inside too.D: same asd, but when--removerun, e empty everything inside. Boot dey run remove, so aDfolder always start empty after reboot.e: e no create anything. E only adjust a directory wey already exist, and e clear the inside by age. With age0, the inside go clear every time--cleanrun.L: create a symlink if e no dey yet. The target go for the Argument field.z: fix the mode, owner and SELinux label of something wey already exist. E no create.x: no clean this path. Use am to protect one folder inside a bigger folder wey get age cleanup.
e, x and z accept shell glob like * inside the path. For e, give at least one of mode, user, group or age. If you no give any, the line no do anything.
Fix the /run/myapp problem with tmpfiles.d
Write one line inside a new file, then ask systemd-tmpfiles to apply only that file:
echo 'd /run/myapp 0750 www-data www-data -' | sudo tee /etc/tmpfiles.d/myapp.conf
sudo systemd-tmpfiles --create /etc/tmpfiles.d/myapp.conf
stat -c '%A %U:%G %n' /run/myappHealthy output na drwxr-x--- www-data:www-data /run/myapp. If stat say "No such file or directory", the create no run, or systemd-tmpfiles reject the line. Read wetin --create print. A user name wey no exist go make am print error, and the folder no go appear.
Why this one go survive reboot: during boot, systemd-tmpfiles-setup.service dey run systemd-tmpfiles --create --remove --boot over all the config files, before sysinit.target. So your folder dey there before your app service start. You fit see am yourself with systemctl cat systemd-tmpfiles-setup.service.
Wetin reboot go do, test am without reboot
Reboot run create and remove together. You fit copy that one on a test folder, with no restart at all:
echo 'D /run/tmpfiles-demo 0755 root root -' | sudo tee /etc/tmpfiles.d/demo.conf
sudo systemd-tmpfiles --create /etc/tmpfiles.d/demo.conf
sudo touch /run/tmpfiles-demo/old.sock
ls -A /run/tmpfiles-demo
sudo systemd-tmpfiles --create --remove /etc/tmpfiles.d/demo.conf
ls -A /run/tmpfiles-demoThe first ls show old.sock. The second ls show nothing. The folder still dey, but the inside empty. Na exactly wetin boot do to /tmp on Ubuntu 24.04, because the tmp.conf line na D.
Never run --remove against the real tmp.conf on a live server. Apps wey dey run fit dey use files inside /tmp, and you go remove them from under the app. When you finish the test, clean am:
sudo rm /etc/tmpfiles.d/demo.conf
sudo rm -r /run/tmpfiles-demoStop /var/tmp and /tmp from chopping your disk
First, look how much space dey there and how old the files be:
sudo du -sh /tmp /var/tmp
sudo find /var/tmp -xdev -type f -mtime +14 | head -n 20If na Docker images and build cache hold the space, tmpfiles.d no be the tool for am. Read how to clean Docker disk with prune on a VPS instead.
The safe way na to give your app im own folder with im own age, no be to clear the whole /var/tmp. This line keep uploads for 7 days:
echo 'd /var/tmp/myapp-uploads 0750 www-data www-data 7d' | sudo tee /etc/tmpfiles.d/myapp-uploads.conf
sudo systemd-tmpfiles --create /etc/tmpfiles.d/myapp-uploads.conf
sudo systemd-tmpfiles --clean /etc/tmpfiles.d/myapp-uploads.confPoint your app upload temp setting to /var/tmp/myapp-uploads. If you still want a rule for the whole /var/tmp, put d /var/tmp 1777 root root 30d inside /etc/tmpfiles.d/var-tmp.conf. Before you do am, read the find output well. If one program you know dey keep im files there on purpose, protect that folder with a line like x /var/tmp/keep-this inside the same file.
To change Ubuntu own /tmp age, copy the file to /etc with the same name. Your copy go win:
sudo cp /usr/lib/tmpfiles.d/tmp.conf /etc/tmpfiles.d/tmp.conf
sudo nano /etc/tmpfiles.d/tmp.confChange 30d to the age you want, like 7d, and save. Keep the D and the 1777 the way dem be.
Why systemd-tmpfiles --clean no delete my old test file
Many people test cleanup like this, and dem confuse when the file still dey:
echo 'd /var/tmp/age-test 0755 root root 10d' | sudo tee /etc/tmpfiles.d/age-test.conf
sudo systemd-tmpfiles --create /etc/tmpfiles.d/age-test.conf
sudo touch -d '40 days ago' /var/tmp/age-test/old.log
stat /var/tmp/age-test/old.log
sudo systemd-tmpfiles --clean /etc/tmpfiles.d/age-test.conf
ls -l /var/tmp/age-testLook the stat output well. Access and Modify show 40 days ago. But Change and Birth show today. touch -d only fit set access time and modify time. The kernel set the change time to now any time the file metadata change, and the birth time na when the file first appear.
Now the rule for tmpfiles.d(5), version 255: by default systemd look all the timestamps, access, birth, change and modify (only directory change time no count). If any one of them recent pass the age, the file stay. For this test, Change and Birth na today, so by that rule the file go remain. Run am and confirm with the ls. A real old upload no get this problem, because all im timestamps old together.
You fit choose which timestamps count. Put the letters before the age with : (a access, b birth, c change, m modify, and the capital letters for directories). Test any such line on a test folder first, the way we do here. Clean up after:
sudo rm /etc/tmpfiles.d/age-test.conf
sudo rm -r /var/tmp/age-testWhen the age cleanup dey run
Boot no be the only time. A timer run systemd-tmpfiles --clean for the whole system. Check the schedule on your box:
systemctl list-timers systemd-tmpfiles-clean.timer
systemctl cat systemd-tmpfiles-clean.timerFor upstream systemd 255, the timer file get OnBootSec=15min and OnUnitActiveSec=1d. That mean 15 minutes after boot, then one time every day. The list-timers output show you the NEXT and LAST run for your own box, so trust that one pass wetin I write here.
RuntimeDirectory=: when the folder belong to one service
If only one service dey use the folder, let systemd create am when the service start. Make a throwaway service to see am work:
sudo tee /etc/systemd/system/rundir-demo.service >/dev/null <<'EOF'
[Unit]
Description=RuntimeDirectory demo
[Service]
Type=simple
ExecStart=/usr/bin/sleep infinity
RuntimeDirectory=rundir-demo
RuntimeDirectoryMode=0750
EOF
sudo systemctl daemon-reload
sudo systemctl start rundir-demo
stat -c '%A %U:%G %n' /run/rundir-demo
sudo systemctl stop rundir-demo
ls -ld /run/rundir-demoWhile the service dey run, stat show drwxr-x--- root:root /run/rundir-demo. Na root own am because the unit no set User=. After the stop, ls say "No such file or directory". systemd remove the folder because RuntimeDirectoryPreserve= default na no.
For your real app, add User=myapp and Group=myapp, and systemd go give the folder to that user. Without RuntimeDirectoryMode=, the mode na 0755. Watch restart: if your unit get Restart=on-failure, every automatic restart go also remove the folder and create am again. Set RuntimeDirectoryPreserve=restart if your app need the files to survive a restart. How systemd Restart= policies work explain when those restarts dey happen.
Remove the demo when you finish:
sudo rm /etc/systemd/system/rundir-demo.service
sudo systemctl daemon-reloadIf your unit dey use ProtectSystem=strict, read how ProtectSystem and PrivateTmp lock down a service to see how RuntimeDirectory= fit inside that setup.
tmpfiles.d or RuntimeDirectory=: which one to pick
Use RuntimeDirectory= when the folder belong to one service, and e no need exist when the service stop. systemd create am with the right owner on start, and e clean am on stop. You no need any extra file.
Use tmpfiles.d when the folder must exist even when the service no dey run, when two services share am, or when you want age cleanup. Uploads, build cache and anything for /tmp or /var/tmp belong here. On a small plan where disk cost money, that age field na the line wey save you.
FAQ
Why my /run/myapp folder dey disappear after every reboot?
/run na tmpfs inside RAM, and e dey empty for every boot. Nothing create your folder back, so your app no see am. Put d /run/myapp 0750 www-data www-data - inside /etc/tmpfiles.d/myapp.conf, change the user to your app user, and run sudo systemd-tmpfiles --create /etc/tmpfiles.d/myapp.conf. If only one service use the folder, RuntimeDirectory=myapp inside the unit file do the same job.
Does Ubuntu 24.04 clean /var/tmp by itself?
Ubuntu 24.04 patch tmp.conf so the /var/tmp line na comment (#q /var/tmp 1777 root root 30d), so that file no clean /var/tmp at all. /tmp dey empty for every boot, and files wey old pass 30 days dey clear. Run cat /usr/lib/tmpfiles.d/tmp.conf to see wetin your box really get, then add your own rule inside /etc/tmpfiles.d if you need am.
Why systemd-tmpfiles --clean no delete the file I backdate with touch -d?
By default tmpfiles.d look access, birth, change and modify time, and any one wey recent go keep the file. touch -d only set access and modify time, so change time and birth time still show today. Check with stat. A real old file get all old timestamps, so cleanup go remove am normally.
Should I use tmpfiles.d or RuntimeDirectory= for my socket folder?
Use RuntimeDirectory= if the folder belong to one service. systemd create am on start and remove am on stop. Use tmpfiles.d if the folder must exist without the service, if many services share am, or if you need age cleanup for old files.