Project Titanicarus: How to configure SFTP and FTP with ProFTPD

I personally hate & never use FTP, but some people prefer/need it for their development tools to work. Today we’re going to install ProFTPd on our servers using MySQL based virtual users. The following instructions are adapted from this really good howto, if I’ve missed something you may want to check the original version which I’ve recreated here just in case the other one goes away.


I’ve added a section at the bottom explaining how to use SFTP instead of FTP. If you don’t know what SFTP is – it is SSH’s method of transferring files. It is much easier to get through firewalls and it is also encrypted, I would use it in preference of FTP if I were you.

Important Note – Security

ProFTPD has a horrendous history of security issues, many many many sites have been hacked due to poorly configured or out of date versions of servers. Make sure you patch regularly and you know what every setting you change in your config does or you could be asking for trouble. I strongly suggest you carefully consider how you’re going to rollout FTP access, if at all, before you turn the daemon on. In my mind FTP is not a good choice of file transfer protocol, however I have written this post because I had someone provide me with a pretty solid reason why they needed it. If you’re as much of a pushover as me, make sure you do everything you can to minimise the attack surface. Lock access down to specific IP’s using firewalls AND the application level security options.


  1. Install ProFTPD
    apt-get install proftpd-basic proftpd-mod-mysql
  2. Create a Database for the Users
  3. Create a User for the Database
  4. Stick the following SQL into the database:
      `groupname` varchar(16) COLLATE utf8_general_ci NOT NULL,
      `gid` smallint(6) NOT NULL DEFAULT '5500',
      `members` varchar(16) COLLATE utf8_general_ci NOT NULL,
      KEY `groupname` (`groupname`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='ProFTP group table';
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `userid` varchar(32) COLLATE utf8_general_ci NOT NULL DEFAULT '',
      `passwd` varchar(32) COLLATE utf8_general_ci NOT NULL DEFAULT '',
      `uid` smallint(6) NOT NULL DEFAULT '5500',
      `gid` smallint(6) NOT NULL DEFAULT '5500',
      `homedir` varchar(255) COLLATE utf8_general_ci NOT NULL DEFAULT '',
      `shell` varchar(16) COLLATE utf8_general_ci NOT NULL DEFAULT '/sbin/nologin',
      `count` int(11) NOT NULL DEFAULT '0',
      `accessed` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
      `modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
      PRIMARY KEY (`id`),
      UNIQUE KEY `userid` (`userid`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='ProFTP user table';
  5. Create a user in PHPMyAdmin, make sure you assign them user ID 33 (www-data) and assign them to the right directory for the site they are working on so they can only see their own data.

    FTP Server Create User

    You’ll need to generate a password on the command line using:

    /bin/echo "{md5}"`/bin/echo -n "password" | openssl dgst -binary -md5 | openssl enc -base64`

    FTP Server Create Password

  6. ConfigureProFTPD
    1. nano /etc/proftpd/proftpd.conf
    2. Uncomment "DefaultRoot ~"

      ProFTPD DefaultRoot

    3. Add to bottomofconfig:
      Include /etc/proftpd/sql.conf
      RequireValidShell         off
    4. Create /etc/proftpd/sql.conf Add the following info to the file, make sure you change the database, user & password info to suityourconfig.
      SQLBackend        mysql
      #Passwords in MySQL are encrypted using CRYPT
      SQLAuthTypes            OpenSSL Crypt
      SQLAuthenticate         users groups
      # used to connect to the database
      # databasename@host database_user user_password
      SQLConnectInfo  mysql_database@localhost mysql_user mysql_password
      # Here we tell ProFTPd the names of the database columns in the "usertable"
      # we want it to interact with. Match the names with those in the db
      SQLUserInfo     ftpuser userid passwd uid gid homedir shell
      # Here we tell ProFTPd the names of the database columns in the "grouptable"
      # we want it to interact with. Again the names match with those in the db
      SQLGroupInfo    ftpgroup groupname gid members
      # set min UID and GID - otherwise these are 999 each
      SQLMinID        33
      # Update count every time user logs in
      SQLLog PASS updatecount
      SQLNamedQuery updatecount UPDATE "count=count+1, accessed=now() WHERE userid='%u'" ftpuser
      # Update modified everytime user uploads or deletes a file
      SQLLog  STOR,DELE modified
      SQLNamedQuery modified UPDATE "modified=now() WHERE userid='%u'" ftpuser
      SqlLogFile /var/log/proftpd/sql.log
    5. Next edit /etc/proftpd/modules.conf anduncomment the following:
      LoadModule mod_sql.c
      LoadModule mod_sql_mysql.c
  7. service proftpd restart
  8. Test it and you should be good to go!

Distribute Configs

Now you’ve got a working FTP service, you will want to move the configs to your synchronised etc directory.

mv /etc/proftpd/ /data/config/etc/
ln -s /data/config/etc/

Now when you install onto other servers all you need to do is symlink to the syncronised directory and the server should come up properly – remember not only are your configs synced, your database is too :-)

Network Edge

If you’ve setup the load balancers, btsync daemon and the rest of the garb I’ve used in this project you will need to add farms to the load balancers to point at your FTP servers. I’ve also made sure that the farms are redirecting to backend servers based on Client IP, so you don’t get bits of files written to different backend servers resulting in data corruption.

Other Options

If you’re as sketchy about using ProFTPD as me, you’re no doubt looking for other ways to skin this cat, well here’s a few which I may write up later on down the track:

  • BTSYNC – remember we’re using it for the backend data synchronisation? well theres nothing stopping you from sharing individual website directories too and giving your client a BTSYNC key that they use to sync their site to their computer with. This is something I’m playing with at home and its pretty good so far, just like developing on a local dropbox share only it uploads to your server instead of dropbox!
  • SCP/SFTP – good but by default it requires local users and isn’t simple to setup so data written to web directories uses the web servers user ID. I know there are options ut there, but they were not easy to find or execute when I was searching. happy to be pointed at any solutions if you find one :)

Thats it! Next week we’re starting to build mail servers, if anyone has a new fandangled Open Source  Spam filterng solution, I’m keen to hear about it in the comments below!

Update: Adding SFTP into the Mix

To add SFTP functionality into your ProFTPD config, all you have to do is:

  1. Uncomment “LoadModule mod_sftp.c” in /etc/proftpd/modules.conf
  2. Create a virtual host file called sftp.conf in /etc/proftpd/conf.d/ with the content below in it.
  3. Restart proftpd.
<IfModule mod_sftp.c>
 # <-- Change to your servers IP address
        SFTPEngine on
        Port 2222
        SFTPLog /var/log/proftpd/sftp.log
        # Configure both the RSA and DSA host keys, using the same host key
        # files that OpenSSH uses.
        SFTPHostKey /etc/ssh/ssh_host_rsa_key
        SFTPHostKey /etc/ssh/ssh_host_dsa_key
        # Enable compression
        SFTPCompression delayed
        Include /etc/proftpd/sql.conf
        # Use this to jail all users in their homes
        DefaultRoot                     ~
        # Users require a valid shell listed in /etc/shells to login.
        # Use this directive to release that constrain.
        RequireValidShell               off

After you’ve restarted ProFTPD the server will be answering on both normal FTP ports and port 2222 for SFTP.

Last updated by at .

17 Replies to “Project Titanicarus: How to configure SFTP and FTP with ProFTPD”

  1. ProFTP comes with an SFTP module which you can very easily chroot users. I doubt you’d need to waste your time with LDAP either. Just ProFTP with SFTP module and jail users into their homes. Auth using *only* SSH keys too makes for a very secure setup. Also, using SSH keys, when websites are being developed by more than one developer, setting the login for a “website” (vhost, or other) can be a single system account but auth’d by various SSH keys. This way you don’t get your developers in a twist when one file is owned by the other developer. It also allows you to easily host using suPHP.

  2. well since you are stuck with ProFTP for the general FTP support may as well extend it. The only other way I’ve seen is to use opensshd’s sftp-only / jail option and combine with pam_*insert_horror_backend_here*

  3. Ooh Craig I think I did see that one before but jumped over it because it relied on ProFTPD and I was hoping to find something better.

  4. Most of the solutions rely on pam modules that are absolutely crap at best. The only kind of good option as Doug and I have discovered before is the LDAP one and even that is full of caveats.

  5. Doug – yup they do but this client has an application that can’t do that yet. The other issue is I don’t want local users for sftp and tbh ldap is a pita so I really want MySQL virtual users. Every solution I found was too hard with the time I had.

  6. I went hunting for up to date info on SpamAssassin rule sets and addons the other day and really didn’t find much.

    I’ve been using spamassassin, amavisd and postgrey for ages but its not as good as it used to be..

    Josh – does Maia have anything extra on top of its SpamAssassin backend?

  7. for email, I use spamassassin & amavisd for antivirus, plus SPF filter. Not the best I’m sure, but suits me personal needs well. Been meaning to try policyd-weight for postfix.

  8. Most devs these days use software that uses SFTP. If you’re deploying something new, why not go with that? Drop the passwords too and go with SSH keys.

  9. Its been a long time since I plated with spam filtering, if anyone has a really good open source spam filtering solution I’d love to hear what you’re using!

Comments are closed.