How to Mount a Subdirectory to a Separate Hard Drive in Linux (Using Bind Mounts for /var/www/upload)


2 views

Let's consider a system with two mounted drives:

/dev/sda1 mounted on / (drive A)
/dev/sdb1 mounted on /mnt/drive_b (drive B)

Currently, all files under /var/www and its subdirectories (including /var/www/upload) are stored on drive A. We want to redirect only /var/www/upload to store files on drive B while keeping the rest on drive A.

Linux provides a powerful feature called "bind mounts" that allows mounting a directory to another location in the filesystem hierarchy. Here's how to implement it:

# Step 1: Create the target directory on drive B
sudo mkdir -p /mnt/drive_b/uploads

# Step 2: Move existing uploads (if any) to the new location
sudo mv /var/www/upload/* /mnt/drive_b/uploads/

# Step 3: Remove the original directory (it will be replaced by the mount)
sudo rmdir /var/www/upload

# Step 4: Create the bind mount
sudo mount --bind /mnt/drive_b/uploads /var/www/upload

To ensure the mount persists after reboots, add this line to /etc/fstab:

/mnt/drive_b/uploads  /var/www/upload  none  bind  0  0

After setting up, verify the mount points with:

mount | grep /var/www/upload

You should see output similar to:

/mnt/drive_b/uploads on /var/www/upload type none (rw,bind)

While bind mounts are the proper solution, some might consider symbolic links. However, this approach has limitations:

# Not recommended for this use case:
sudo ln -s /mnt/drive_b/uploads /var/www/upload

The limitation is that some applications might not follow symlinks correctly, and permissions can become more complex to manage.

Ensure the web server (e.g., Apache or Nginx) has proper permissions on the new location:

sudo chown -R www-data:www-data /mnt/drive_b/uploads
sudo chmod -R 755 /mnt/drive_b/uploads

For more complex setups, you might consider mounting drive B directly to /var/www/upload:

# In /etc/fstab:
/dev/sdb1  /var/www/upload  ext4  defaults  0  2

This approach skips the bind mount but requires the partition to be dedicated to this single purpose.


When working with web servers in Linux, we often need to separate high-traffic directories like upload folders onto different physical drives. Consider this common setup:

Drive A (root):
/var/
/var/www/
/var/www/index.html

Drive B (mounted separately):
(empty)

Currently, all files including uploads go to Drive A. This creates performance bottlenecks when upload directory grows.

The most effective way is using a bind mount. Here's how to implement it:

# Step 1: Create mount point on Drive B
sudo mkdir -p /mnt/driveb/uploads

# Step 2: Move existing uploads (if any)
sudo mv /var/www/upload/* /mnt/driveb/uploads/

# Step 3: Create bind mount entry in fstab
echo "/mnt/driveb/uploads /var/www/upload none bind 0 0" | sudo tee -a /etc/fstab

# Step 4: Apply changes
sudo mount -a

To confirm the setup works correctly:

# Create test files
sudo touch /var/www/testfile
sudo touch /var/www/upload/testupload

# Check storage locations
lsblk -o NAME,MOUNTPOINT | grep -A 5 "sd[b]"
df -h /var/www /var/www/upload

While less robust than bind mounts, symlinks can work for simpler cases:

# First move the directory
sudo mv /var/www/upload /mnt/driveb/

# Then create symlink
sudo ln -s /mnt/driveb/upload /var/www/upload

Note: Some applications may not follow symlinks properly, especially with strict security policies.

Ensure proper permissions after mounting:

sudo chown -R www-data:www-data /mnt/driveb/uploads
sudo chmod -R 755 /mnt/driveb/uploads

If uploads fail after setup:

  1. Check mount | grep upload to verify mounting
  2. Verify SELinux contexts match: ls -Z /var/www/ /var/www/upload
  3. Test with simple file operations as root first

For high-traffic servers, consider these additional steps:

# Mount with noatime option in /etc/fstab:
UUID=xxxx-xxxx /mnt/driveb ext4 defaults,noatime,bind 0 0

This reduces write operations for frequently accessed upload directories.