When configuring vsftpd with dynamic directory paths using environment variables like $USER
, you might encounter the error:
500 OOPS: cannot change directory:/home/$USER/public_html
Despite $USER
working correctly in shell environments, it fails to expand within the vsftpd configuration file.
This occurs because vsftpd doesn't perform shell-style variable expansion in its configuration file by default. The local_root
directive treats $USER
as literal text rather than substituting it with the actual username.
Verification steps:
- Command line:
echo $USER
returns correct username - vsftpd config:
local_root=/var/www/sites/$USER
remains unexpanded
Option 1: Use Per-User Configuration
Create individual config files in /etc/vsftpd_user_conf/
:
# In /etc/vsftpd.conf
user_config_dir=/etc/vsftpd_user_conf
Then create user-specific files:
# /etc/vsftpd_user_conf/johndoe
local_root=/var/www/sites/johndoe
Option 2: Use Template Expansion
For dynamic environments, generate the config file during user login:
#!/bin/bash
# /etc/vsftpd.conf.dynamic
cat <<EOF > /etc/vsftpd.conf.dynamic
$(sed "s/\$USER/$USER/g" /etc/vsftpd.conf.template)
EOF
Option 3: PAM Module Solution
For recent vsftpd versions (2.3.5+), use PAM to set environment variables:
# /etc/pam.d/vsftpd
session required pam_mkhomedir.so skel=/etc/skel/ umask=0022
session required pam_env.so
The original issue was reported on:
- vsftpd 2.2.2
- Ubuntu 10.04.1 LTS (Lucid)
Newer versions (3.0.0+) support more sophisticated variable expansion through different mechanisms.
Enable verbose logging to understand the exact failure point:
# /etc/vsftpd.conf
debug_ssl=YES
log_ftp_protocol=YES
xferlog_std_format=NO
Check logs with:
tail -f /var/log/vsftpd.log
While configuring vsftpd on Ubuntu 10.04 (Lucid Lynx), I encountered an issue where the $USER
variable in local_root=/var/www/sites/$USER
wasn't being interpreted. The server returned:
500 OOPS: cannot change directory:/home/$USER/public_html
Interestingly, when testing with echo $USER
in the shell, it correctly displays the username. The issue only occurs within the vsftpd configuration.
In vsftpd 2.2.2 (the version shipped with Ubuntu 10.04), environment variable interpolation in the config file isn't supported. The $USER
is treated literally rather than being expanded to the actual username.
This behavior differs from shell scripts where $VAR
notation automatically expands variables.
Here are several approaches to solve this:
1. Use vsftpd's user_config_dir Feature
Create per-user configuration files that contain their specific paths:
# In /etc/vsftpd.conf user_config_dir=/etc/vsftpd_user_conf
Then create individual files in that directory:
# /etc/vsftpd_user_conf/john local_root=/var/www/sites/john # /etc/vsftpd_user_conf/mary local_root=/var/www/sites/mary
2. Script-Based Configuration Generation
Create a script to generate vsftpd.conf with expanded variables:
#!/bin/bash # generate_vsftpd_conf.sh USER_PATH="/var/www/sites/$(whoami)" echo "local_root=$USER_PATH" > /etc/vsftpd.conf # Add other vsftpd settings...
Run this script whenever users change or the configuration needs updating.
3. Upgrade vsftpd
Newer versions of vsftpd (3.0.0+) support better variable handling. Consider upgrading:
sudo apt-get install ppa-purge sudo add-apt-repository ppa:thefrontiergroup/vsftpd sudo apt-get update sudo apt-get install vsftpd
After implementing any solution, test with:
sudo service vsftpd restart ftp localhost
Check that you can properly access user-specific directories without the $USER
interpolation error.
For simpler setups, consider creating symlinks:
sudo mkdir -p /var/www/sites for user in $(ls /home); do sudo ln -s /home/$user/public_html /var/www/sites/$user done
Then use a static path in vsftpd.conf:
local_root=/var/www/sites