Scale up as you grow — whether you're running one virtual machine or ten thousand.

From GPU-powered inference and Kubernetes to managed databases and storage, get everything you need to build, scale, and deploy intelligent applications.

This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.
This comment has been deleted
The issue you’re experiencing is actually in the following text:
# You may specify an explicit list of local users to chroot() to their home
# directory. If chroot_local_user is YES, then this list becomes a list of
# users to NOT chroot().
# (Warning! chroot'ing can be very dangerous. If using chroot, make sure that
# the user does not have write access to the top level directory within the
# chroot)
Your current configuration is:
chroot_local_user=YES
chroot_list_enable=YES
# (default follows)
chroot_list_file=/etc/vsftpd.chroot_list
In the above, if chroot_local_user is set to YES, then the list you provide becomes a list of users not to chroot.
So if you have users in that list and those users happen to be the users you’re having issues with, they need to be removed. Or, you can simply comment out the last two lines.
chroot_local_user=YES
#chroot_list_enable=YES
# (default follows)
#chroot_list_file=/etc/vsftpd.chroot_list
You would then save and restart vsftp.
…
As a general note, FTP is relatively insecure and I would honestly recommend using SFTP over FTP for the security. SFTP is built-in to SSH (OpenSSH) which is already installed (it’s what you use to get in to your Droplet via SSH), and requires only a few small configuration changes to a single file.
When setup properly, the only thing you need to worry about is making sure each user is a member of the right group.
For example, on Ubuntu, we’d be working with this file:
/etc/ssh/sshd_config
To start, we’d open the file:
nano /etc/ssh/sshd_config
Find:
Subsystem sftp /usr/lib/openssh/sftp-server
Replace it with:
Subsystem sftp internal-sftp
Find:
UsePAM yes
Below it, add:
Match Group sftpusers
ChrootDirectory %h
ForceCommand internal-sftp
X11Forwarding no
AllowTCPForwarding no
PasswordAuthentication yes
… save and close the file.
Add the group sftpusers using:
groupadd sftpusers
Restart SSH:
service ssh restart
…
Now when we want to add a new user, we’d do the following.
Create a Home Directory
mkdir -p /home/newuser/public
Create a New User
Passing -d tells useradd that the directory we specify is the users home directory.
useradd -d /home/newuser newuser
Add User to sftpusers Group
usermod -aG sftpusers newuser
Setup Initial Permissions
The root directory, /home/newuser needs to be owned by root, which is why we’re using the added /* at the end of this command. It ensures that we’re only changing ownership of the files and directories inside of this directory, and not the directory itself.
chown -R newuser:newuser /home/newuser/*
Set a Password
passwd newuser
With that, the user newuser is chroot’ed to /home/newuser.
…
You could even automate this with a Bash Script so you’re not having to type in those commands every single time you want to create a new user.
#!/usr/bin/env bash
username="${1}"
userhome="/home/${username}"
usercheck=$(id -u ${username} > /dev/null 2>&1; echo $?)
if [ "${usercheck}" -eq 0 ]; then
echo "User already exists."
exit 1
else
mkdir -p ${userhome}/{public,private} \
&& useradd -d ${userhome} ${username} \
&& usermod -aG sftpusers ${username} \
&& chown -R ${username}:${username} ${userhome}/*
fi
You can modify {public,private} to be whatever directories you wish to create for new users. If you wanted, that could be {public_html,private_html} or any combination you need. The brackets are there for expansion and prevent having to run mkdir on each directory.
mkdir -p ${userhome}/{public,private} is equivalent to:
mkdir -p ${userhome}/public
mkdir -p ${userhome}/private
Simply copy and paste that in to a file – for example newuser.sh – then:
chmod +x adduser.sh
And run it with a single argument passed – the user you wish to create.
./adduser.sh newuser
./adduser.sh mynewuser
./adduser.sh demouser
It’s just a quick way to add new users. It won’t modify existing users, though you can use the commands above to modify any existing user too.
You’d still need to use passwd to set the password for each user. Also, users would be connecting over SFTP on Port 22, instead of FTP on Port 21.