If you have ever created a custom directory inside /var/run only to find it gone after a reboot, you are not alone. This is one of the most common surprises for Linux administrators. This guide explains why it happens and how to make your directories persist across reboots using systemd-tmpfiles.
Why /var/run Is Volatile
The /var/run directory (and its modern equivalent /run) is mounted as a tmpfs filesystem — a RAM-based filesystem that exists only in memory. Ubuntu allocates a portion of your RAM (typically around 10%) for this mount.
You can verify this with:
df -h /run
# Output:
# Filesystem Size Used Avail Use% Mounted on
# tmpfs 1.6G 1.2M 1.6G 1% /run
mount | grep tmpfs | grep run
# Output:
# tmpfs on /run type tmpfs (rw,nosuid,nodev,noexec,relatime,size=1632548k,mode=755)
Applications use /var/run to store:
- PID files — process IDs for running daemons (e.g.,
/run/nginx.pid) - Socket files — Unix domain sockets for inter-process communication (e.g.,
/run/php/php-fpm.sock) - Lock files — to prevent multiple instances of a process
- Runtime state — temporary data needed only while the system is running
Because this data is in RAM, access is extremely fast — but everything is lost on reboot.
Note: On modern Ubuntu (15.04+),
/var/runis a symlink to/run. They are the same location.
ls -la /var/run
# Output:
# lrwxrwxrwx 1 root root 4 ... /var/run -> /run
The Solution: systemd-tmpfiles
The systemd-tmpfiles service is responsible for creating, deleting, and cleaning up volatile and temporary files and directories at boot. It reads configuration files from three locations (in order of priority):
/etc/tmpfiles.d/— Local administrator overrides (highest priority)/run/tmpfiles.d/— Runtime configuration/usr/lib/tmpfiles.d/— Package-provided defaults (lowest priority)
Step 1: Create a Configuration File
Create a .conf file in /etc/tmpfiles.d/:
sudo nano /etc/tmpfiles.d/myapp.conf
Step 2: Add the Directory Definition
The configuration format is:
# Type Path Mode User Group Age Argument
d /run/myapp 0755 myuser mygroup - -
Each field means:
| Field | Description | Example |
|---|---|---|
| Type | d = create directory | d |
| Path | Full path to create | /run/myapp |
| Mode | Permissions (octal) | 0755 |
| User | Owner user | www-data |
| Group | Owner group | www-data |
| Age | Auto-cleanup after this age (- = never) | 10d or - |
| Argument | Additional arguments (usually -) | - |
Step 3: Apply Immediately (Without Rebooting)
sudo systemd-tmpfiles --create /etc/tmpfiles.d/myapp.conf
Step 4: Verify
ls -la /run/myapp
# Output:
# drwxr-xr-x 2 myuser mygroup 40 ... /run/myapp
Practical Examples
Nginx PID Directory
# /etc/tmpfiles.d/nginx.conf
d /run/nginx 0755 www-data www-data -
PHP-FPM Socket Directory
# /etc/tmpfiles.d/php-fpm.conf
d /run/php 0755 www-data www-data -
Custom Application with Multiple Subdirectories
# /etc/tmpfiles.d/myapp.conf
d /run/myapp 0755 appuser appgroup -
d /run/myapp/pids 0755 appuser appgroup -
d /run/myapp/sock 0750 appuser appgroup -
Directory with Automatic Cleanup (remove files older than 30 days)
# /etc/tmpfiles.d/myapp-tmp.conf
D /run/myapp/tmp 0755 appuser appgroup 30d
Note the uppercase D — this cleans up the directory contents based on the age parameter.
Other tmpfiles.d Types
Beyond directories, tmpfiles.d can manage other resources:
# Create an empty file
f /run/myapp/status 0644 appuser appgroup -
# Create a symlink
L /run/myapp/current - - - - /opt/myapp/latest
# Write content to a file
f+ /run/myapp/config 0644 appuser appgroup - "key=value"
The Legacy Approach (Pre-systemd)
On very old Ubuntu systems (before 15.04) that do not use systemd, the equivalent mechanism was modifying /etc/rc.local or creating init scripts:
# /etc/rc.local (legacy — do NOT use on systemd systems)
mkdir -p /var/run/myapp
chown myuser:mygroup /var/run/myapp
chmod 0755 /var/run/myapp
Warning: Do not use
/etc/rc.localon modern Ubuntu. Usetmpfiles.dinstead — it is the proper systemd mechanism and integrates correctly with the boot process.
Troubleshooting
Directory Not Created After Reboot
- Verify the config file syntax:
sudo systemd-tmpfiles --create --dry-run /etc/tmpfiles.d/myapp.conf
- Check for syntax errors in the journal:
journalctl -u systemd-tmpfiles-setup.service
Permission Denied
Make sure the user and group specified in the config file exist:
id myuser
getent group mygroup
Viewing Current tmpfiles Configuration
List all active tmpfiles rules:
systemd-tmpfiles --cat-config
Or check what a specific package configured:
cat /usr/lib/tmpfiles.d/nginx.conf
Summary
Directories in /var/run (or /run) disappear on reboot because they live on a tmpfs RAM disk. To create persistent directories that are automatically recreated at boot:
- Create a file in
/etc/tmpfiles.d/yourapp.conf - Define your directories with the
dtype, specifying path, permissions, and ownership - Apply with
sudo systemd-tmpfiles --create
This is the standard systemd mechanism used by all major packages (Nginx, PHP-FPM, MySQL, etc.) to manage their runtime directories.