Hetzner - DokuWiki



Pureftpd with mysql and TLS Support


  • 11.02.2010 Supplements for Debian Lenny
  • 23.07.2008 Adjustment to Etch installation, marking defaults on Debian

Author: Jan Scholten

devnull [at] rootsvr [dot] de

Copyright and License

Some Rights Reserved.gif

This content is licensed under a Creative Commons License.


Feedback on this document is of course welcome, simply send an email to the author.

Introduction / Abstract

Almost every server operator (at least if they have customers) will need or wish to use an FTP server.
The movement of data with FTP is normally not encrypted and even passwords are transmitted unencrypted. To close this potential weak spot, an FTP server can be used that at least encrypts the channel for transmitting passwords.

In this "Howto" I would like to explain the installation of Pure-FTPd Pure-FTPd. As far as possible, the focus is on Debian packages, which to my mind offer sensible parameters individually.

The support of mysql is used to set up and delete users via a web interface, which makes sense in a hosting environment.

I use this configuration in a suExec + FastCGI configuration, which means that each domain operates under one user.

The users which are created are mostly independent from the system users. One idea for a virtual user setup is to be found below.


We install the pure-ftpd-mysql package. Configuration takes place via single files in /etc/pure-ftpd/conf, each file is named after the parameter it represents and has the necessary values as content.

cerberus# apt-get install pure-ftpd-mysql

We create the following files in /etc/pure-ftpd/conf:

cd /etc/pure-ftpd/conf
echo yes > ChrootEveryone
echo yes > CreateHomeDir
echo 50 > MaxClientsNumber
echo 5  > MaxClientsPerIP
echo 95 > MaxDiskUsage
echo 1 > TLS
echo 117 007 > Umask
echo no > UnixAuthentication
echo no > PAMAuthentication

defaults on Debian (do not need to be changed):

echo clf:/var/log/pure-ftpd/transfer.log > AltLog
echo 1000 > MinUID
echo /etc/pure-ftpd/db/mysql.conf > MySQLConfigFile
echo yes > NoAnonymous
echo /etc/pure-ftpd/pureftpd.pdb > PureDB

This creates homedirs which, do not exist yet, limit each user to its directory, permit 50 parallel connections but no more than 5 per IP address, with a minimum gid of 1000 (at least with suExec Apache/fcgi otherwise MinUID should be set to 33 (standard www-data account on Debian). Anonymous logins are forbidden, likewise Unix authentication, rather only users from the database are authenticated. The MaxDiskUsage parameter prevents the FTP from filling more than 95% of disk space.


We edit the data for our database in file /etc/pure-ftpd/db/mysql.conf.

vi /etc/pure-ftpd/db/mysql.conf
#MYSQLServer     localhost
#MYSQLPort       3306
MYSQLSocket     /var/run/mysqld/mysqld.sock
MYSQLUser       pureftpd-user
MYSQLPassword   DasistunserPW!
MYSQLDatabase   pureftpd
MYSQLCrypt      crypt
MYSQLGetPW      SELECT Password FROM users WHERE User="\L"
MYSQLGetDir     SELECT Dir FROM users WHERE User="\L"
MySQLGetQTAFS   SELECT QuotaFiles FROM users WHERE User="\L"
MySQLGetQTASZ   SELECT QuotaSize FROM users WHERE User="\L"
MySQLGetBandwidthUL SELECT ULBandwidth FROM users WHERE User="\L"
MySQLGetBandwidthDL SELECT DLBandwidth FROM users WHERE User="\L"

Mysql Users and Table Structure

We create a user and a database in the mysql server:

Creating Mysql Users

mysql -u root -p
   ON pureftpd.* TO 'pureftpd-user'@'localhost'
   IDENTIFIED BY 'DasistunserPW!';

Table Structure

USE pureftpd;
User varchar(16) NOT NULL default ,
Password varchar(64) NOT NULL default ,
Uid int(11) NOT NULL default '-1',
Gid int(11) NOT NULL default '-1',
Dir varchar(128) NOT NULL default ,
QuotaFiles int(11) NOT NULL default '10000',
QuotaSize int(11) NOT NULL default '1000',
ULBandwidth int(11) NOT NULL default '500',
DLBandwidth int(11) NOT NULL default '500',


Briefly test to see if the user can log in:

mysql -u pureftpd-user -p pureftpd
select * from users;


Then make sure that the files are only readable by root, as database passwords are to be found there.

chmod 600 /etc/pure-ftpd/db/mysql.conf
chown root:root /etc/pure-ftpd/db/mysql.conf

Set Up SSL Certificate for TLS

The SSL certificate is expected at /etc/ssl/private/pure-ftpd.pem, if you already have one for Apache this can simply be copied and used. If you wish to set one up yourself:

mkdir -p /etc/ssl/private/
openssl req -x509 -nodes -newkey rsa:1024 -keyout \
/etc/ssl/private/pure-ftpd.pem \
-out /etc/ssl/private/pure-ftpd.pem
chmod 600 /etc/ssl/private/*.pem

Adding Users

Entries are made per phpmyadmin or with a self-written script..

Log in to PhpMyAdmin as a pureftpd user, create new lines in the users table:

Password('TheUserPassword')  (select "Encrypt" from the dropdown menu)
UID/GID     from the account, for "simple" setups 33 (www-data), for fastcgi/suexec or suPHP, the domain user
dir         in normal circumstances /var/www/domain
Quotafiles  max number of files
Quotasize   max size of all files in MB
Bandwidth UPload/DownLoad limit in kb/s

Via mysql on the command line:

mysql -u pureftpd-user -p
use pureftpd;
insert into users (User, Password, UID, GID, dir, Quotafiles,  Quotasize) \
Values ('TestUsername', ENCRYPT('TestseinPW'), 33,33,'/var/www/testdomain.de',1000,1000);

The password prompt can be executed using my.cf and the database can be specified. In this way, things can be directly blown into mysql by script.

Remember root is not possible!

If a MySQL user entry has a root (0) uid and/or gid, Pure-FTPd will refuse to log him in.
Without this preventive restriction, if your MySQL server ever gets
compromised, the attacker could also easily compromise the FTP server.
Security barriers are also implemented to avoid bad implications if wrong data types (eg. binary blobs instead of plain text) are fetched with SQL queries.

Client Configuration

Right, now a TLS compatible client is needed (e.g. SmartFTP/FileZilla) and you can get started.

It is best to read up on how to adjust your FTP client and which TLS it is comptabile with or to try it out. http://download.pureftpd.org/pub/pure-ftpd/doc/README.TLS

Further Comments

If MD5 or mysql password is selected for password encryption, this has to be adjusted (in /etc/pure-ftpd-mysql/db/mysql.conf and in the users which have been created, if necessary simply try "any" and hope that pureftpd will find the right password ..)


The inetd route did not work for me and/or is not installed in minimal Debian. Then change




If you then start /etc/init.d/pure-ftpd-mysql this should be started as daemon and listen to port 21 (netstat -plaunt), if not

less /var/log/syslog

Virtual Users

If all of it is used with suexec/php, you will not want the following as it is quite important to have separate users.

No one is forced to take different UIDs for the users. For a virtual setup (probably not self-tested) proceed as follows:

adduser ftpuser
mkdir /var/ftp
chown ftpuser:ftpuser /var/ftp

Read the UID/GID from /etc/passwd or /etc/group and create new users with this UID/GID and set your homedir to /var/ftp/user1 or /var/www/user2

On first logging in, the user directories are set up and the users are chrootet there. (Not tested with a request for feedback) If necessary one still needs to set virtualchroot to yes in /etc/default/pure-ftpd-common.

© 2019. Hetzner Online GmbH. Alle Rechte vorbehalten.