How to Disable systemd’s Private /tmp for Apache2 and Fix File Saving Path Issues


2 views

When working with Apache2 on modern Linux distributions using systemd, you might encounter an unexpected behavior where files intended for /tmp end up in paths like:

/tmp/systemd-private-015eb2e9f67b4eef862c68e99fe0ba30-apache2.service-9h6i08/tmp/somename

This occurs because systemd creates private temporary directories for services by default, a feature called PrivateTmp.

The PrivateTmp feature provides several security benefits:

  • Isolates temporary files between services
  • Prevents information leaks through /tmp
  • Cleans up all temporary files when service stops

To disable this behavior and use the regular /tmp directory:

sudo systemctl edit apache2.service

Add these lines to the override file:

[Service]
PrivateTmp=false

Then reload systemd and restart Apache:

sudo systemctl daemon-reload
sudo systemctl restart apache2

If you prefer to keep PrivateTmp enabled but need consistent paths, modify your PHP code:

// Get the actual temp directory
$temp_dir = sys_get_temp_dir();

// Use it in your file operations
$file_path = $temp_dir . '/somename/file.txt';
file_put_contents($file_path, $data);

Check if the change took effect:

systemctl show apache2.service | grep PrivateTmp

Should return: PrivateTmp=no

Before disabling PrivateTmp, consider:

  • Review why your application needs files in /tmp
  • Implement proper file permissions (chmod 600 for sensitive files)
  • Consider using your application's private storage instead

Add this to your PHP script for debugging:

error_log("Actual temp directory: " . sys_get_temp_dir());
error_log("Intended path: /tmp/somename");
error_log("Full path: " . sys_get_temp_dir() . '/somename');

When running Apache under systemd, you might notice files being saved to paths like:

/tmp/systemd-private-*-apache2.service-*/tmp/somename

instead of the expected /tmp/somename. This occurs because systemd enables PrivateTmp by default for service isolation.

This security feature creates:

  • Process isolation through namespace separation
  • Protection against /tmp race conditions
  • Cleaner cleanup when services restart
  • Prevention of /tmp information leaks

To disable this behavior:

# Edit the Apache service file
sudo systemctl edit apache2.service

# Add these contents:
[Service]
PrivateTmp=false

# Then reload and restart
sudo systemctl daemon-reload
sudo systemctl restart apache2

If you need to maintain security while working with /tmp:

// PHP code to handle both scenarios
$tmp_base = is_dir('/tmp/systemd-private-*') ? 
    glob('/tmp/systemd-private-*/tmp')[0] : 
    '/tmp';

$file_path = $tmp_base . '/somename/file.txt';
file_put_contents($file_path, $data);

For permanent changes across all services:

# Edit systemd's global config
sudo nano /etc/systemd/system.conf

# Add or modify:
DefaultPrivateTmp=no

Check the effective settings with:

systemctl show apache2 | grep PrivateTmp

You should see PrivateTmp=no after making these changes.

Before disabling PrivateTmp, consider:

  • Using application-specific directories in /var/tmp
  • Implementing proper file permissions
  • Setting up tmpwatch or similar cleanup mechanisms
  • Using PHP's sys_get_temp_dir() for portable temp paths