/tmp Cleanup Best Practices - tmpfiles.d and systemd-tmpfiles
What You'll Learn
- How
/tmp,/var/tmp, and/runare managed by systemd - How to write
tmpfiles.drules for custom cleanup - How to run
systemd-tmpfilesmanually and on a schedule
Quick Summary
- Automatic
/tmpcleanup is handled bysystemd-tmpfiles-clean.timer - Custom rules go in
/etc/tmpfiles.d/*.conf - Rule format:
type path mode uid gid age argument
Prerequisites
- OS: Ubuntu or any systemd-based Linux
- Root or sudo access required
Why Does /tmp Need Cleanup?
/tmp is where applications write temporary files. On most Ubuntu systems it is a tmpfs in RAM — wiped on reboot. Long-running servers, however, accumulate temp files between reboots, which can exhaust disk space and cause stale PID or socket file references.
- Typical uses: intermediate files from compression, session data, socket files
- Ubuntu default:
/tmpis mounted astmpfs, so it is cleared on reboot /var/tmp: persists across reboots by design — requires explicit management
$ mount | grep /tmp tmpfs on /tmp type tmpfs (rw,nosuid,nodev)
If /tmp is tmpfs, files vanish on reboot. If it is disk-backed, cleanup is even more critical. Check usage with df -h /tmp.
What Is systemd-tmpfiles?
systemd-tmpfiles is the declarative tool for managing temporary directories — creating them on boot, setting permissions, and deleting stale files on a schedule.
Three operation modes:
| Mode | Flag | Action |
|---|---|---|
| Create | --create |
Create files/dirs per rules |
| Clean | --clean |
Delete entries older than their age threshold |
| Remove | --remove |
Delete everything matching the rules |
$ sudo systemd-tmpfiles --create $ sudo systemd-tmpfiles --clean $ sudo systemd-tmpfiles --remove
Two systemd units run these automatically:
systemd-tmpfiles-setup.service— runs--createat bootsystemd-tmpfiles-clean.timer— runs--cleanperiodically (default: 15 min after boot, then daily)
How to Write tmpfiles.d Rules
Drop config files in /etc/tmpfiles.d/. System defaults live in /usr/lib/tmpfiles.d/ — never edit those directly, since package updates overwrite them.
Format
type path mode uid gid age argument
| Field | Description | Example |
|---|---|---|
| type | Operation type | d, f, x, e |
| path | Target path | /tmp/myapp |
| mode | Permissions (octal) | 0755 |
| uid/gid | Owner (- = keep current) |
root / - |
| age | Delete threshold for --clean |
7d, 1h, - (never) |
| argument | Initial content for files | - |
Common Types
| Type | Meaning |
|---|---|
d |
Create directory if missing; --clean removes aged files inside |
D |
Like d, but --remove also deletes directory contents |
f |
Create file if missing |
f+ |
Create or truncate file |
x |
Exclude from --clean and --remove |
e |
Set permissions on an existing entry |
z |
Set permissions and SELinux labels |
How to Run Periodic Cleanup
Check the cleanup timer:
$ systemctl status systemd-tmpfiles-clean.timer
● systemd-tmpfiles-clean.timer - Daily Cleanup of Temporary Directories
Loaded: loaded (/lib/systemd/system/systemd-tmpfiles-clean.timer; static)
Active: active (waiting) since Mon 2024-01-01 00:00:00 UTC; 3h ago
Trigger: Tue 2024-01-02 00:15:30 UTC; 20h left
Trigger an immediate cleanup:
$ sudo systemctl start systemd-tmpfiles-clean
--clean only acts on entries where the age field is set. An entry with age - is never deleted automatically.
Practical Examples
Example 1: Per-app temp directory with auto-cleanup
# /etc/tmpfiles.d/myapp.conf d /tmp/myapp 0750 myapp myapp 1d
Creates /tmp/myapp owned by myapp:myapp with mode 0750, and deletes files inside that are older than 1 day.
Example 2: Clean app logs in /var/tmp after 7 days
# /etc/tmpfiles.d/clean-var-tmp.conf d /var/tmp/app-logs 0755 root root 7d
Example 3: Create /run directory at boot with no auto-delete
# /etc/tmpfiles.d/myapp-run.conf d /run/myapp 0755 myapp myapp -
Age - means: create at boot, never auto-delete.
Example 4: Exclude a path from cleanup
# /etc/tmpfiles.d/exclude.conf x /tmp/persistent-cache
--clean skips /tmp/persistent-cache regardless of age.
Apply and verify rules immediately
# Apply create rules now $ sudo systemd-tmpfiles --create /etc/tmpfiles.d/myapp.conf # Dry run: preview what --clean would delete $ sudo systemd-tmpfiles --clean --dry-run /etc/tmpfiles.d/myapp.conf
Always use --dry-run before running --clean on a new rule. It shows what would be deleted without making any changes.
Common Issues
Files are not being deleted
Check that the age field is not -. Also note that --clean uses atime (last access time) as the threshold, not mtime.
$ stat /tmp/myfile | grep Access
If the filesystem is mounted with noatime, atime is never updated, so files may appear older than they are. Use touch -a /tmp/myfile to update atime manually when testing.
Rules not taking effect
Validate the config directly:
$ sudo systemd-tmpfiles --create /etc/tmpfiles.d/myapp.conf
Check the journal for errors:
$ journalctl -u systemd-tmpfiles-setup
Override a system rule in /usr/lib/tmpfiles.d/
Drop a file with the same name in /etc/tmpfiles.d/ — it takes priority. Load order: /etc > /run > /usr/lib.
# View the system rule $ cat /usr/lib/tmpfiles.d/tmp.conf # Create your override and edit it $ sudo cp /usr/lib/tmpfiles.d/tmp.conf /etc/tmpfiles.d/tmp.conf
What not to do
- Edit files under
/usr/lib/tmpfiles.d/directly — package updates will overwrite them - Use type
Don a critical directory without an age limit —--removewill delete all contents