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


20 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