[Timer]
OnBootSec=15min
OnUnitActiveSec=1d
[Timer]
OnBootSec=15min
OnUnitActiveSec=1d
[Timer]
OnBootSec=15min
OnUnitActiveSec=1d
ExecStart=systemd-tmpfiles --clean
ExecStart=systemd-tmpfiles --clean
ExecStart=systemd-tmpfiles --clean
d /var/cache/myapp-downloads 0750 root root 7d
d /var/cache/myapp-downloads 0750 root root 7d
d /var/cache/myapp-downloads 0750 root root 7d
sudo systemd-tmpfiles --create /etc/tmpfiles.d/myapp-downloads.conf
sudo systemd-tmpfiles --create /etc/tmpfiles.d/myapp-downloads.conf
sudo systemd-tmpfiles --create /etc/tmpfiles.d/myapp-downloads.conf
sudo systemd-tmpfiles --dry-run --clean /etc/tmpfiles.d/myapp-downloads.conf
sudo systemd-tmpfiles --dry-run --clean /etc/tmpfiles.d/myapp-downloads.conf
sudo systemd-tmpfiles --dry-run --clean /etc/tmpfiles.d/myapp-downloads.conf
sudo systemd-tmpfiles --clean /etc/tmpfiles.d/myapp-downloads.conf
sudo systemd-tmpfiles --clean /etc/tmpfiles.d/myapp-downloads.conf
sudo systemd-tmpfiles --clean /etc/tmpfiles.d/myapp-downloads.conf
e /var/lib/myapp/scratch 0750 myapp myapp 3d
e /var/lib/myapp/scratch 0750 myapp myapp 3d
e /var/lib/myapp/scratch 0750 myapp myapp 3d
TESTROOT=$(mktemp -d /tmp/tmpfiles-demo.XXXXXX)
mkdir -p "$TESTROOT/cache"
printf 'old\n' > "$TESTROOT/cache/a.bin"
printf 'new\n' > "$TESTROOT/cache/b.bin" cat > "$TESTROOT/demo.conf" <<EOF
e $TESTROOT/cache 0755 $(id -un) $(id -gn) 0
EOF systemd-tmpfiles --dry-run --clean "$TESTROOT/demo.conf"
systemd-tmpfiles --clean "$TESTROOT/demo.conf"
find "$TESTROOT" -maxdepth 2 -type f | sort
TESTROOT=$(mktemp -d /tmp/tmpfiles-demo.XXXXXX)
mkdir -p "$TESTROOT/cache"
printf 'old\n' > "$TESTROOT/cache/a.bin"
printf 'new\n' > "$TESTROOT/cache/b.bin" cat > "$TESTROOT/demo.conf" <<EOF
e $TESTROOT/cache 0755 $(id -un) $(id -gn) 0
EOF systemd-tmpfiles --dry-run --clean "$TESTROOT/demo.conf"
systemd-tmpfiles --clean "$TESTROOT/demo.conf"
find "$TESTROOT" -maxdepth 2 -type f | sort
TESTROOT=$(mktemp -d /tmp/tmpfiles-demo.XXXXXX)
mkdir -p "$TESTROOT/cache"
printf 'old\n' > "$TESTROOT/cache/a.bin"
printf 'new\n' > "$TESTROOT/cache/b.bin" cat > "$TESTROOT/demo.conf" <<EOF
e $TESTROOT/cache 0755 $(id -un) $(id -gn) 0
EOF systemd-tmpfiles --dry-run --clean "$TESTROOT/demo.conf"
systemd-tmpfiles --clean "$TESTROOT/demo.conf"
find "$TESTROOT" -maxdepth 2 -type f | sort
Would remove "/tmp/tmpfiles-demo.../cache/a.bin"
Would remove "/tmp/tmpfiles-demo.../cache/b.bin"
Would remove "/tmp/tmpfiles-demo.../cache/a.bin"
Would remove "/tmp/tmpfiles-demo.../cache/b.bin"
Would remove "/tmp/tmpfiles-demo.../cache/a.bin"
Would remove "/tmp/tmpfiles-demo.../cache/b.bin"
systemctl cat systemd-tmpfiles-clean.timer
systemctl cat systemd-tmpfiles-clean.service
systemd-tmpfiles --cat-config | less
systemctl cat systemd-tmpfiles-clean.timer
systemctl cat systemd-tmpfiles-clean.service
systemd-tmpfiles --cat-config | less
systemctl cat systemd-tmpfiles-clean.timer
systemctl cat systemd-tmpfiles-clean.service
systemd-tmpfiles --cat-config | less
grep -R . /usr/lib/tmpfiles.d /etc/tmpfiles.d 2>/dev/null | less
grep -R . /usr/lib/tmpfiles.d /etc/tmpfiles.d 2>/dev/null | less
grep -R . /usr/lib/tmpfiles.d /etc/tmpfiles.d 2>/dev/null | less
d /var/tmp/inbox-import 0750 importer importer 2d
d /var/tmp/inbox-import 0750 importer importer 2d
d /var/tmp/inbox-import 0750 importer importer 2d
sudo systemd-tmpfiles --create /etc/tmpfiles.d/inbox-import.conf
sudo systemd-tmpfiles --dry-run --clean /etc/tmpfiles.d/inbox-import.conf
sudo systemctl start systemd-tmpfiles-clean.service
sudo journalctl -u systemd-tmpfiles-clean.service -n 50 --no-pager
sudo systemd-tmpfiles --create /etc/tmpfiles.d/inbox-import.conf
sudo systemd-tmpfiles --dry-run --clean /etc/tmpfiles.d/inbox-import.conf
sudo systemctl start systemd-tmpfiles-clean.service
sudo journalctl -u systemd-tmpfiles-clean.service -n 50 --no-pager
sudo systemd-tmpfiles --create /etc/tmpfiles.d/inbox-import.conf
sudo systemd-tmpfiles --dry-run --clean /etc/tmpfiles.d/inbox-import.conf
sudo systemctl start systemd-tmpfiles-clean.service
sudo journalctl -u systemd-tmpfiles-clean.service -n 50 --no-pager - stale files in /tmp
- forgotten payloads in /var/tmp
- application scratch directories that grow forever
- caches that should be disposable, but never get expired automatically - create this directory if it should exist
- set the right mode and ownership
- clean old contents on a schedule
- preview what would happen before deleting anything - tmpfiles.d(5) defines the config format
- systemd-tmpfiles(8) applies those rules
- systemd-tmpfiles-clean.timer typically runs cleanup daily
- systemd-tmpfiles-clean.service runs systemd-tmpfiles --clean - /tmp is for smaller, temporary data and is often cleared on reboot
- /var/tmp is for temporary data that should survive reboot - a path should exist independent of a single service lifecycle
- you want age-based cleanup for directory contents
- you want a declarative replacement for custom cleanup scripts
- you need predictable permissions on a scratch or cache path - RuntimeDirectory= for /run
- StateDirectory= for /var/lib
- CacheDirectory= for /var/cache
- LogsDirectory= for /var/log
- ConfigurationDirectory= for /etc - d creates a directory, and optionally cleans its contents by age
- D is like d, but its contents are also removed when --remove is used
- e cleans an existing directory by age without requiring tmpfiles to create it - use d when you want tmpfiles to create and manage the directory
- use e when the application creates the directory itself, but you want cleanup policy applied to its contents - d creates the directory if missing
- mode becomes 0750
- owner/group become root:root
- contents older than 7d become eligible during cleanup runs - adjust mode and ownership if needed
- clean old contents in that existing directory
- leave directory creation to the application or package - /etc/tmpfiles.d/*.conf
- /run/tmpfiles.d/*.conf
- /usr/local/lib/tmpfiles.d/*.conf
- /usr/lib/tmpfiles.d/*.conf - vendor packages ship rules in /usr/lib/tmpfiles.d
- local admin overrides belong in /etc/tmpfiles.d - directory created if missing
- owned by the importer account
- stale leftovers cleaned after 2 days - browser profiles
- databases and queues
- anything under /var/lib unless you are certain it is disposable scratch data
- upload staging paths that users may still need
- application caches you have not confirmed are rebuildable and safe to lose - avoid guessable file names in shared temporary directories
- prefer service isolation like PrivateTmp= where appropriate - inspect existing rules first
- create one small .conf file in /etc/tmpfiles.d/
- run --create if needed
- run --dry-run --clean
- test on a disposable directory before touching important paths
- check logs after the first real cleanup run - declarative directory policy
- age-based cleanup
- repeatable permissions
- built-in scheduling on many distros
- a dry-run path for safer changes - systemd-tmpfiles(8): https://man7.org/linux/man-pages/man8/systemd-tmpfiles.8.html
- tmpfiles.d(5): https://manpages.ubuntu.com/manpages/focal/man5/tmpfiles.d.5.html
- systemd, "Using /tmp/ and /var/tmp/ Safely": https://systemd.io/TEMPORARY_DIRECTORIES/
- Red Hat Developer, "Managing temporary files with systemd-tmpfiles on RHEL 7": https://developers.redhat.com/blog/2016/09/20/managing-temporary-files-with-systemd-tmpfiles-on-rhel7