Documentation is not quite finished yet. pyftpd is a is a multiplatform (currently tested only on linux, solaris, hp/ux and windows95/98/NT/2000) ftp daemon written in python. It can work under normal user account and does not require any special rights to start. Thanks to the modular design, there are possible many different authentification schemes, most notably anonymous user authentification, authentification from internal database of users (these are virtual users, independent from the operating system users), and authentification against PAM[1]. pyftpd uses its own permission modules, and can pinpoint user permissions down to a simple file and simple ftp operation. pyftpd uses python threads; if your python interpreter was compiled without thread support, it will use forking instead, with limited functionality (limiting number of simultaneously logged users and some other options won't work). If neither threads nor fork is available, pyftpd will serve just one connection at a time. The main pyftpd configuration is in file config.py. Configuration for additional modules is in files modulename_configure.py. You can change configuration either by editing appropriate file, or by running graphical configuration tool (Tkinter required). Configuration tool for config.py file is called configure_configure.py, configuration tools for other modules are called configure_modulename.py. When you launch configure_configure.py, in the window you are configuring only the list of authentification modules (Edit button is a bit misleading - it does not edit, but rather replace the module with another one). Global options are accessible via the Option button. To configure individual modules, you have to run appropriate configure_*.py scripts. On virtual and real paths: Path to a file or directory, as seen on the disk, is a real path. This is the path you enter in perm_acl_module. However, path as visible to ftp clients can be mangled in some ways[2]. The mangled visible path is called virtual path, and this is the path you enter as Initial dir or in auth_cwd_module. On performance: pyftpd, when possible, uses multiple threads, which means it manages the memory (which is the decisive factor when serving many clients) in quite an efficient way. As an example, on my Debian Linux with python 1.5.2, idle server takes 1564kB RAM, of which 588kB is shareable with eventual other python interpreter. Each connected client takes additional 44kB memory, and some more kB when up/downloading a file (this is configurable via sbufsize and rbufsize options). Compare with proftpd 1.2.0, which (in standalone mode) takes 532kB (not counting libc and other system libraries) and each connected client takes additional 312kB memory. Or with wu-ftpd, which takes 492kB memory, and each connection takes additional 344kB. This is due to multithreaded model of pyftpd, compared to forking of other daemons. On the other hand, there is a little nice single-threaded ftp server, using non blocking sockets and poll, called betaftpd (http://members.xoom.com/sneeze/betaftpd-lynx.html), which takes 220kB memory, and each connections takes additional 12kB. This shows up the efficiency of C over python :-). [1] It is currently not quite functioning. [2] For example you can use virtual root directories via auth_chroot module, or posix path emulation on MS Windows.