FTP Symbolic Link Setup: Allowing Users to Upload Outside Home Directory While Maintaining Security


4 views

Many web developers face this dilemma: how to allow FTP users to upload files to specific directories outside their home folder without compromising server security. The traditional symbolic link approach works fine when linking from the web root to the user's directory, but the reverse scenario presents unique challenges.

Most FTP servers (vsftpd, ProFTPD, etc.) enforce chroot restrictions that prevent users from traversing outside their home directory. This security measure means symbolic links pointing outside the chroot jail won't be followable by FTP clients, even if the underlying filesystem permissions allow it.

Here are three practical approaches to solve this:

1. Bind Mounts (Linux-specific)

Instead of symbolic links, create a bind mount in the user's directory:

sudo mount --bind /path/to/target/directory /home/user/accessible_directory

Then add to /etc/fstab for persistence:

/path/to/target/directory /home/user/accessible_directory none bind 0 0

2. FTP Server Configuration Tweaks

For ProFTPD, enable follow-symlinks:

<Directory /home/user>
    AllowOverwrite on
    FollowSymlinks on
</Directory>

For vsftpd, set:

allow_writeable_chroot=YES
follow_symlinks=YES

3. SFTP + ACL Configuration

If using OpenSSH's SFTP, combine symlinks with proper ACLs:

setfacl -R -m u:username:rwx /path/to/target/directory
ln -s /path/to/target/directory /home/user/accessible_directory

Here's a complete workflow for vsftpd:

# Create target directory
sudo mkdir -p /var/www/uploads/client_assets
sudo chown -R clientuser:www-data /var/www/uploads/client_assets

# Configure vsftpd
echo "allow_writeable_chroot=YES" | sudo tee -a /etc/vsftpd.conf
echo "follow_symlinks=YES" | sudo tee -a /etc/vsftpd.conf

# Create symlink in user's home
ln -s /var/www/uploads/client_assets /home/clientuser/uploads

# Restart service
sudo systemctl restart vsftpd

Always remember:

  • Never use symlinks that point to sensitive system directories
  • Regularly audit symlink targets
  • Consider filesystem quotas to prevent disk space abuse
  • Implement proper umask settings (022 recommended)

When managing web servers, we often need to provide clients FTP access to specific directories without exposing the entire website root. While symbolic links (symlinks) work perfectly for web server access, most FTP servers (like vsftpd or proftpd) won't follow symlinks out of the user's home directory due to security restrictions.

Consider this typical setup:

# Web root structure
/var/www/html/
└── client_uploads -> /home/client/uploads  # Symlink works for web access

# FTP access fails when:
/home/client/
└── web_images -> /var/www/images  # Symlink won't be traversable via FTP

The FTP protocol implementations typically enforce chroot jail restrictions that prevent following symlinks pointing outside the user's home directory.

1. Bind Mounts (Linux Specific)

For systems where you have root access:

sudo mount --bind /var/www/images /home/client/web_images

This creates a "mirror" of the target directory that appears to be part of the client's home directory. Add to /etc/fstab for persistence:

/var/www/images /home/client/web_images none bind 0 0

2. FTP Server Configuration Tweaks

For vsftpd, enable these settings in /etc/vsftpd.conf:

follow_symlinks=YES
allow_writeable_chroot=YES

Then carefully configure permissions:

chown -R client:client /var/www/images
chmod 755 /var/www/images

3. SSHFS as Alternative

For more advanced users, consider replacing FTP with SSHFS:

sudo apt install sshfs
sshfs user@yourserver:/var/www/images /home/client/web_images
  • Always set correct directory ownership (client:www-data for web folders)
  • Use 755 for directories and 644 for files in web-accessible locations
  • Consider filesystem quotas to prevent disk space abuse

Create a maintenance script (/usr/local/bin/sync_ftp_perms.sh):

#!/bin/bash
WEB_GROUP="www-data"
FTP_USER="client"
TARGET_DIR="/var/www/images"

# Set group ownership
chown -R $FTP_USER:$WEB_GROUP $TARGET_DIR

# Apply permissions
find $TARGET_DIR -type d -exec chmod 775 {} \;
find $TARGET_DIR -type f -exec chmod 664 {} \;

# Set SGID to maintain group ownership
chmod g+s $TARGET_DIR