note: This article is intended for a technical audience -- you should use extreme caution when modifying a production system -- caveat emptor.
This is one of those 'it's not broken until you trip over it' things that I wish i'd known about earlier, in posting it here -- i'm hoping other people can find it without wasting the amount of time I did.
So, I had reason to set up a new VPS box with the LAMP stack, SSH/SCP and VSFTPd for FTP use -- my usual command says something like:
useradd -n --gid www-data -s /bin/false [username]
In a nutshell, this:
Does not create a new group specific to the user.
Makes the user's primary group www-data (useful for users being able to access / upload / modify their own web code).
Sets the default shell to /bin/false, which does not allow the account to login interactively.
However, when you use an FTP client, it bails out with a 530 error, telling the user either their username or password are wrong.
So, the next step is to reset their password and try again -- nope, no difference.
Try changing the shell from /bin/false to /bin/bash with chsh though:
chsh -s /bin/bash [username]
... and everything works correctly.
We don't want to use /bin/bash though, because (amongst other things) it allows interactive logins via SSH or the console, which poses a security risk for the other users of the box.
Ubuntu & Red Hat (and probably a whole bunch of others) include the nologin command, which does exactly what we want (provides a message that the user cannot login, and exits).
chsh -s /sbin/nologin [username]
It still errors.
As it turns out, the reason it errors is due to it not being included in the /etc/shells file that VSFTPd and other system daemons use to determine if your shell is valid.
Turns out, it's a very easy thing to fix -- simply:
echo /sbin/nologin >> /etc/shells
note: Some distributions ship this as /usr/sbin/nologin -- you may wish to run whereis nologin first to determine where your copy is.
Try FTP again.