ProFTPD’s configuration can feel like a black box, but its modular design actually makes it surprisingly flexible once you understand how directives cascade.
Let’s get ProFTPD installed and set up for basic FTP access.
First, installation. On Debian/Ubuntu systems:
sudo apt update
sudo apt install proftpd-basic
On RHEL/CentOS/Fedora:
sudo dnf install proftpd
During installation on Debian/Ubuntu, you might be prompted to choose between inetd and standalone. Always choose standalone for ProFTPD. inetd is an older, less efficient way to manage services.
The main configuration file is usually located at /etc/proftpd/proftpd.conf. Let’s start with a minimal, secure configuration.
ServerName "My FTP Server"
ServerType standalone
DefaultRoot ~
RequireValidShell off
UseIPv6 on
AllowOverwrite on
TransferLog /var/log/proftpd/transfer.log
SystemLog /var/log/proftpd/proftpd.log
PidFile /var/run/proftpd.pid
<Directory />
<Limit WRITE>
DenyGroup *
</Limit>
</Directory>
<Directory /home/*/public_html>
<Limit READ>
AllowUser *
</Limit>
</Directory>
Let’s break this down:
ServerName: A descriptive name for your FTP server that clients will see.ServerType standalone: As discussed, this is crucial for ProFTPD to run as its own daemon.DefaultRoot ~: This is a powerful directive. It means each user will be "jailed" or "chrooted" into their home directory (~). They won’t be able to navigate outside of it.RequireValidShell off: By default, ProFTPD might require users to have a valid login shell (like/bin/bash) to log in. Setting this tooffallows users without a valid shell to log in, which is common for FTP-only accounts.UseIPv6 on: Enables IPv6 support if your network is configured for it.AllowOverwrite on: Permits users to overwrite existing files. If you want stricter control, you can set this tooff.TransferLogandSystemLog: Essential for tracking who uploads/downloads what and for debugging. Make sure the/var/log/proftpddirectory exists and is writable by theproftpduser.sudo mkdir -p /var/log/proftpd sudo chown proftpd:proftpd /var/log/proftpdPidFile: Specifies where the process ID file is stored, useful for managing the daemon.
The <Directory> blocks are where you define access controls.
- The first
<Directory />block:<Limit WRITE>: Applies to write operations (uploading, deleting, renaming).DenyGroup *: This is a broad security measure. It denies write access to all users for the root directory (/). This means no one can upload or delete files directly from the server’s root.
- The second
<Directory /home/*/public_html>block:- This is more specific. It targets directories named
public_htmlwithin any user’s home directory (e.g.,/home/alice/public_html,/home/bob/public_html). <Limit READ>: Applies to read operations.AllowUser *: This allows any authenticated user to read files within thesepublic_htmldirectories.
- This is more specific. It targets directories named
To make this configuration active, you need to restart ProFTPD:
sudo systemctl restart proftpd
Check its status:
sudo systemctl status proftpd
You should see it running.
Now, let’s create a user for testing.
sudo useradd ftpuser
sudo passwd ftpuser
When prompted for the password, enter a strong one. This user will be jailed to their home directory (/home/ftpuser). If you want them to upload files, you’ll need to create a directory within their home and adjust permissions.
For example, to allow ftpuser to upload to a directory called uploads within their home:
- Create the directory:
sudo mkdir /home/ftpuser/uploads - Change ownership to the user:
sudo chown ftpuser:ftpuser /home/ftpuser/uploads - Edit
proftpd.confand add a new directory block:<Directory /home/ftpuser/uploads> <Limit WRITE> AllowUser ftpuser </Limit> </Directory> - Restart ProFTPD again.
Now, ftpuser can connect and upload files into /home/ftpuser/uploads. They can also read files in /home/ftpuser/public_html if you create that directory and place files in it.
One of the most unintuitive aspects of ProFTPD’s access control is the order of evaluation. Directives are processed based on the directory path they apply to, starting from the most specific and moving to the least specific. If a rule is found that matches the current directory and operation, it’s applied, and processing for that operation might stop. This means a Deny rule in a child directory can override an Allow rule in a parent directory, and vice-versa, depending on the exact path.
The next thing you’ll likely want to tackle is enabling SFTP (which ProFTPD doesn’t directly handle – it’s an SSH feature) or securing FTP with TLS/SSL.