This is how to install and configure the pure-ftpd ftp server on your Ubuntu or Debian server or workstation.
First use apt to download and install the pure-ftpd package – it is available from default repositories :
root@box:~# apt-get install pure-ftpd
.
.
.
Setting up pure-ftpd (1.0.21-11ubuntu1) …
Starting ftp server: Running: /usr/sbin/pure-ftpd -l pam -u 1000 -E -O clf:/var/log/pure-ftpd/transfer.log -B
As the latest line of apt output tells us, the server is already started with some default options passed to the binary via the command line.
The way to configure pure-ftpd is quite different from to other Debian / Ubuntu software. When installed as a service and started during the init process, pure-ftpd is invoked by a script called pure-ftpd-wrapper. What’s unusual is that instead of reading a single configuration file for all options, the script uses a directory full of one-line files. Let’s have a look in /etc/pure-ftpd/conf :
root@box:~# cd /etc/pure-ftpd/conf/
root@box:/etc/pure-ftpd/conf# ls -la
total 24K
-rw-r–r– 1 root 36 2007-06-22 02:01 AltLog
-rw-r–r– 1 root 5 2007-06-22 02:01 MinUID
-rw-r–r– 1 root 4 2007-06-22 02:01 NoAnonymous
-rw-r–r– 1 root 4 2007-06-22 02:01 PAMAuthentication
-rw-r–r– 1 root 28 2007-06-22 02:01 PureDB
-rw-r–r– 1 root 3 2007-06-22 02:01 UnixAuthentication
Each of those files describes a command-line option of the pure-ftpd server. For example, the file AltLog contains the format of, and path to, the tranfer log file :
root@box:/etc/pure-ftpd/conf# cat AltLog
clf:/var/log/pure-ftpd/transfer.log
Let’s now set some of the basic options by editing those one-liners (our server will listen to port 21 on all available interfaces, and will use IP 12.34.56.78 and ports 4500-4600 for passive mode – don’t forget to forward those from your NAT router if you are behind one):
root@box:/etc/pure-ftpd/conf# echo ,21 > Bind
root@box:/etc/pure-ftpd/conf# echo 12.34.56.78 > ForcePassiveIP
root@box:/etc/pure-ftpd/conf# echo 4500 4600 > PassivePortRange
Now for some recommended security stuff :
root@box:/etc/pure-ftpd/conf# echo yes > ChrootEveryone
root@box:/etc/pure-ftpd/conf# echo yes > ProhibitDotFilesRead
root@box:/etc/pure-ftpd/conf# echo yes > ProhibitDotFilesWrite
root@box:/etc/pure-ftpd/conf# echo yes > NoChmod
root@box:/etc/pure-ftpd/conf# echo yes > BrokenClientsCompatibility
Let’s also set some limits to avoid abuse :
root@box:/etc/pure-ftpd/conf# echo 4 > MaxClientsPerIP
root@box:/etc/pure-ftpd/conf# echo 20 > MaxClientsNumber
Now the important thing we need to decide is what user authorization method(s) our server will support. Options include Unix Authentication (anyone with a login account on the server will have ftp access), but I chose PureDB authentication, which involves a dedicated pure-ftpd “virtual users” base.
So let’s disable Unix and PAM auth, set the path to the PureDB user file, and add PureDB as an auth method by linking to it from the /etc/pure-ftpd/auth directory :
root@box:/etc/pure-ftpd/conf# echo no > PAMAuthentication
root@box:/etc/pure-ftpd/conf# echo no > UnixAuthentication
root@box:/etc/pure-ftpd/conf# echo /etc/pure-ftpd/pureftpd.pdb > PureDB
root@box:/etc/pure-ftpd/conf# ln -s /etc/pure-ftpd/conf/PureDB ../auth/50pure
Let’s now create a (system) user and group that will be bound to all ftp virtual users. For security reasons, that special user should have no home directory (-d /dev/null) and no shell access (-s /bin/false) :
root@box:/etc/pure-ftpd/conf# groupadd -g 2001 ftpgroup
root@box:/etc/pure-ftpd/conf# useradd -u 2001 -s /bin/false -d /dev/null -c “pureftpd user” -g ftpgroup ftpuser
We can now use the pure-pw command to add our first virtual user (don’t forget the “pure-pw mkdb” command : it is required to commit/confirm changes to the user file)
root@box:/etc/pure-ftpd/conf# pure-pw useradd myfirstuser -u ftpuser -d /var/ftp/public/
Password:
Enter it again:
root@box:/etc/pure-ftpd/conf# pure-pw mkdb
Let’s add TLS/SSL support and generate a private certificate (you will be asked to provide some information to put in the cert)
root@box:/etc/pure-ftpd/conf# apt-get install openssl
root@box:/etc/pure-ftpd/conf# echo 1 > TLS
root@box:/etc/pure-ftpd/conf# openssl req -x509 -nodes -newkey rsa:1024 -keyout /etc/ssl/private/pure-ftpd.pem -out /etc/ssl/private/pure-ftpd.pem
Generating a 1024 bit RSA private key
.
.
.
root@box:/etc/pure-ftpd/conf# chmod 600 /etc/ssl/private/pure-ftpd.pem
Let’s finally restart the server with our all-new config :
root@box:/etc/pure-ftpd/conf# /etc/init.d/pure-ftpd restart
Restarting ftp server: Running: /usr/sbin/pure-ftpd -l puredb:/etc/pure-ftpd/pureftpd.pdb -X -b -u 1000 -C 4 -E -S ,21 -x -c 20 -R -A -p 4500:4600 -O clf:/var/log/pure-ftpd/transfer.log -Y 1 -P 12.34.56.78 -B
All done ! Enjoy a simple, robust and secure ftp server.

How to change line ProhibitDotFiles read, I made msitake miss one letter. And the server shows error, how to disable that line
I followed your letter to the T, but when I attempt to login using the user I created I get a password failure, I re-ran the user add portion to create another user with the same results, any ideas?
Same error as Brandon. What’s wrong?
I have the same error and Brandon also. I cannot log in.. I also tried with TLS set to 0 using regular http://FTP… same. Transcript:
220———- Welcome to Pure-FTPd [privsep] [TLS] ———-
220-You are user number 1 of 12 allowed.
220-Local time is now 22:53. Server port: 21.
220-This is a private system – No anonymous login
220 You will be disconnected after 15 minutes of inactivity.
USER example
331 User example OK. Password required
PASS ********
530 Login authentication failed
Other than that (rather serious problem) you guide was great! Would perhaps also benefit from some additional commentary to help people know what’s going on and what they might want to change and what they should not!
Thanks for your efforts.
SOLUTION: I suspected it was a problem with the PureDB linking. Referring to another guide similar to this (this one is better actually) I recreated the link and it worked. Here’s the difference: it worked when the link was made the reverse way, FROM the auth directory back to the conf directory:
root@box:/etc/pure-ftpd/auth# ln -s ../conf/PureDB
Then restart the server. Should work!
@Casey : you are right, my linking was wrong ! I have just corrected it by adding the full path :
root@box:/etc/pure-ftpd/conf# ln -s /etc/pure-ftpd/conf/PureDB ../auth/50pure
instead of previously (wrong syntax) :
root@box:/etc/pure-ftpd/conf# ln -s PureDB ../auth/50pure
Thanks a lot for letting me know and sorry about the typo.
Is it possible to allow a virtual user to transverse downward through the directory tree while restricting them from transversing up the tree?
EXAMPLE:
newuser Home directory: /var/ftp/public
Requirements: Allow ‘newuser’ to log in and not be allowed to view /var/ftp, but allow them to view /var/ftp/public (and anything below).
newuser needs r/w access to ‘public’ and read only to anything below ‘public’.
Thank you for the tips!
Can someone please help me out. I followed this instructions and even tried the PureDB fix mentioned in the comments here, however I still get password errors when I try to log in! Any ideas?
Make sure that you have the /var/ftp/public path.
Hi,
I have a Problem with the Homedirectory “/bin/null”. Do I have to create this directory? But even after creating this directory with 777 privileges it doesen’t work.
My FTP- Client says ” Home directory not available – aborting “.
Has someone any ideas?
Hi again,
I found the mistake myself…… sorry…… everything works….
Thank you for the great howto
Hi Thomas and thank you for your lovely guide! I have this site saved as a bookmark, incase I would forget something 🙂
But I also noticed that this only works with explicit SSL, but how can I get implicit SSL? Tried to google for it in hours but no success at all.
Regards
/iskall
If someone needs to delete the users used in this tutorial in reverse order he will need to do the following:
pure-pw userdel myfirstuser
userdel -r ftpuser
groupdel ftpgroup
And then you can redo step 8 (Let’s now create a (system) user and group that will be bound to all ftp virtual users.) with different names.
This seems to work but does someone know how to change the time out interval. I can log on from a windows box on a ftp client but i can’t create anything and then I get disconnected after about 15 sek
I cannot connect to the server with my user.
WinSock 2.0 — OpenSSL 0.9.7g 11 Apr 2005
[R] Connecting to Ubuntu -> IP=192.168.0.4 PORT=1980
[R] Connected to Ubuntu
[R] 220———- Welcome to Pure-FTPd [privsep] [TLS] ———-
[R] 220-You are user number 1 of 20 allowed.
[R] 220-Local time is now 00:48. Server port: 1980.
[R] 220-This is a private system – No anonymous login
[R] 220-IPv6 connections are also welcome on this server.
[R] 220 You will be disconnected after 15 minutes of inactivity.
[R] USER afo
[R] 331 User afo OK. Password required
[R] PASS (hidden)
[R] 530 Login authentication failed
[R] Connection failed
[R] Delaying for 120 seconds before reconnect attempt #1
Any ide?
I would just like to add my thanks for a fantastic how-to.
Worked first time and did exactly what I needed.
The only other thing I wanted was to allow *ONLY* TLS encrypted connections.
I achieved this by setting the TLS option to a higher number. (as explained in the README.TLS doc)
eg:
echo 2 > TLS
according to the docs, valid values are 0 to 3 – here is a quick summary
0: no encryption enabled
1: encryption enabled but optional
2: encryption required on control channel but option on data channels
3: encryption require for all communications
I actually wanted to use option 3 but looking at the man page for my install, it appears my version does not support it.
Just did a fresh Install and configuration from the above tutorial, and when I attempt to connect I get this.
root@dragon-server:/etc/pure-ftpd/conf# ftp 192.168.1.201
Connected to 192.168.1.201.
220———- Welcome to Pure-FTPd [privsep] [TLS] ———-
220-You are user number 1 of 20 allowed.
220-Local time is now 10:17. Server port: 21.
220-This is a private system – No anonymous login
220-IPv6 connections are also welcome on this server.
220 You will be disconnected after 15 minutes of inactivity.
Name (192.168.1.201:jamie): jamie
331 User jamie OK. Password required
Password:
421 Service not available, remote server has closed connection
Login failed.
No control connection for command: No such file or directory
ftp>
It appears to be work as far as I can tell.
root@dragon-server:/etc/pure-ftpd/conf# sudo /etc/init.d/pure-ftpd restart
Restarting ftp server: Running: /usr/sbin/pure-ftpd -l puredb:/etc/pure-ftpd/pureftpd.pdb -x -c 20 -Y 1 -C 4 -R -p 4500:4600 -X -b -P 192.168.1.201 -O clf:/var/log/pure-ftpd/transfer.log -A -u 1000 -E -S ,21 -B
root@dragon-server:/etc/pure-ftpd/conf#
Any Idea?
I tried both filenames ‘TLS’ and ‘tls’ but Ubuntu karmic gives this error when trying to use TLS option as described above:
sudo /etc/init.d/pure-ftpd restart
Restarting ftp server: /usr/sbin/pure-ftpd-wrapper: Invalid configuration file /etc/pure-ftpd/conf/tls: No corresponding directive
Is the version available through the repositories not compiled with TLS/SSL support? That would be a major boner.
Thanks for any help.
Please help me here. I have followed this to the letter (since the changes you made) and it is still not working.
When I goto restart I get this error
Restarting FTP Server: /usr/sbin/pure-ftp-wrapper: Invalid Configuratin file / etc/pure-ftpd/conf/50pure: No corresponding directive
I am running karmic.
Connected to 192.168.1.4.
220———- Welcome to Pure-FTPd [privsep] [TLS] ———-
220-You are user number 1 of 20 allowed.
220-Local time is now 21:50. Server port: 21.
220-This is a private system – No anonymous login
220-IPv6 connections are also welcome on this server.
220 You will be disconnected after 15 minutes of inactivity.
Name (192.168.1.4:braincheese): beavis
331 User beavis OK. Password required
Password:
421 Service not available, remote server has closed connection
Login failed.
No control connection for command: No such file or directory
ftp>
I even fixed the link but get this error. ?
I fixed it. It was a pure-pw.pdb problem. Just deleted it and ran pure-pw mkdb
Great guide!
I’m interested in a reference to a complete list of files considered in the conf directory – do you have that?
Thanks!
This is the best howto for pure-ftpd on Debian. Thank You!!!!!!!!
Great tutorial! Exactly what I was looking for.
One quick question for you if at all possible, though: I seem to be having the MLSD problem where the connection is successful until the client (filezilla) calls the MLSD command is run, then it times out. And I’m not quite sure what MLSD/T is supposed to do, exactly. Supposedly if one were to change the MLSD protocol to MLST, it fixes this issue. I have no idea how to do this, though. Any thoughts?
No idea sorry, maybe other readers have ran into similar issues, personally I didn’t.
Thanks for reading my posts and good luck with your server !
Thank you so much for this tutorial. After two days of searching all over the internet it solved my issues. People with Ispconfig 3: this will enable TLS for you without recompile!
Great tutorial!
Was looking around for some tutorial for virtual users and how to set up with tls/ssl support and this was just what i needed. Many thanks. However I did some changes to fit me better and tried to figger out the documentation from pure-FTPD’s web page and then a question aroused, how or where did you find/learn the part where you write for example echo 1 > TLS in conf directory?? I have read and searched for something about it but found nothing. It works really great and I would learn to make more of those especially how to write the umask.
Thanks again for a great tutorial
/Tordlil
I started pure-ftpd using a configuration file with:
./pure-config.pl /etc/pure-ftpd.conf
using provided Perl and conf example files. My question is: what command should I run to STOP it afterwards ?
Hi,
I have a Problem with the Homedirectory “/bin/null”. Do I have to create this directory? But even after creating this directory with 777 privileges it doesen’t work.
My FTP- Client says ” Home directory not available – aborting “.
Has someone any ideas?
PROBLEM IS ACTUAL, HELP TO SOLVE IT
root@vps:/etc/pure-ftpd/conf# /etc/init.d/pure-ftpd restart
Restarting ftp server: Running: /usr/sbin/pure-ftpd -l puredb:/etc/pure-ftpd/pureftpd.pdb -S ,21 -C 5 -b -E -A -X -O clf:/var/log/pure-ftpd/transfer.log -c 20 -x -R -P 46.4.176.134 -u 1000 -p 4500:4600 -8 UTF-8 -B
421 Unable to switch capabilities : Operation not permitted
root@vps:/etc/pure-ftpd/conf# /etc/init.d/pure-ftpd start
Starting ftp server: Running: /usr/sbin/pure-ftpd -l puredb:/etc/pure-ftpd/pureftpd.pdb -S ,21 -C 5 -b -E -A -X -O clf:/var/log/pure-ftpd/transfer.log -c 20 -x -R -P 46.4.176.134 -u 1000 -p 4500:4600 -8 UTF-8 -B
421 Unable to switch capabilities : Operation not permitted
Hi Braincheese.. I have some problem with you
Pure-FTPd was running but it cannot login
Status: Connection established, waiting for welcome message…
Response: 220———- Welcome to Pure-FTPd [privsep] [TLS] ———-
Response: 220-You are user number 1 of 50 allowed.
Response: 220-Local time is now 23:08. Server port: 21.
Response: 220-This is a private system – No anonymous login
Response: 220-IPv6 connections are also welcome on this server.
Response: 220 You will be disconnected after 15 minutes of inactivity.
Command: USER softzers
Response: 331 User softzers OK. Password required
Command: PASS *****
Response: 530 Login authentication failed
Error: Critical error
Error: Could not connect to server
You say to delete pure-pw.pdb How to deleted it? Because i search and i cannot find that files, thankyou.
Thomas,
Thank you very much for posting the steps you took to get PureFTPD up and running. I had used a tutorial on Howtoforge.com, but I ran into a problem using Pureftpd with an external customer. Your tutorial saved me an incredible amount of time and effort.
The info that was key for me was the port forwarding on the router and then the running of the following steps:
root@box:/etc/pure-ftpd/conf# echo ,21 > Bind
root@box:/etc/pure-ftpd/conf# echo xx.xx.xx.xx > ForcePassiveIP
root@box:/etc/pure-ftpd/conf# echo 4500 4600 > PassivePortRange
Once I had run the commands, restarted Pureftpd and forwarded the ports on my router, my customer was able to upload files using passive FTPS.
Thank you for the great tutorial. Please keep up the good work!
Vixaz, ‘/bin/null’ can be a typo, other tutorials use ‘/dev/null’
@Vixaz and @Typo : “/bin/null” was actually a typo, I edited it to “/dev/null”, thanks for noticing !
@Vixaz: Just create /var/ftp/public and you should fix this problem. – At least tis helped with my “problem” seeming the same like yours.
Hello,
nice tutorial but I have problem when I bind different port (2221).
220 You will be disconnected after 15 minutes of inactivity.
AUTH TLS
500 This security scheme is not implemented
AUTH SSL
500 This security scheme is not implemented
When I use port 21 it is ok. Can You help? I use filezilla client.
I had an issue with being unable to login. The issue was I had already had a ftpuser and ftpgroup on my machine with uid of 115 and gid of 125 (ubuntu 11.04 default?). I had to change the MinUID in /etc/pure-ftpd/conf/ to be 115.
Thanks for the info provided..helped a lot
Perfect ^.^
Thank you, thomas. You’re awesome…
How should I configure the SSL cert usage? Because I already have one for a website running on the same address.
In other words, how should I point pure-ftpd to use my existent ssl cert?
Regards,
Thank you for a great tutorial. I had problem with connection timing out, using both Cyberduck and Filezilla.
The problem were that I had to open a Firewall range according to
echo 4500 4600 > PassivePortRange
After that all worked well!