Synopsis #
Pure-FTPd is a package-provided FTP server with support for TLS, chrooted sessions, passive port ranges, virtual users, quotas, and several authentication backends. It is an alternative to the base-system ftpd , vsftpd , and ProFTPD servers.
FTP does not encrypt credentials or transferred data by default. Pure-FTPd must be configured for TLS before it is used across an untrusted network. For new deployments that require only authenticated file transfer, SFTP through sshd usually has fewer protocol and firewall requirements.
Installation #
Install the package with pkg_add(1) :
# pkg_add pure-ftpd
The package installs /usr/local/sbin/pure-ftpd, the /etc/rc.d/pure_ftpd service script, an example configuration at /usr/local/share/examples/pure-ftpd/pure-ftpd.conf.sample, and supporting documentation under /usr/local/share/doc/pure-ftpd/.
The package also creates the _pure-ftpd account for daemon privilege separation. This account is not an FTP login account and should not own uploaded content.
Service Configuration #
The rcctl(8)
service name is pure_ftpd, with an underscore. Display the current service settings and command-line flags with:
# rcctl get pure_ftpd
# rcctl get pure_ftpd flags
The packaged service uses these flags by default:
-A -B -H -u1000
Their effects are:
| Flag | Effect |
|---|---|
-A | Chroot every authenticated user except root to the user’s home directory. |
-B | Run the standalone server in the background. |
-H | Log numeric client addresses without reverse DNS lookups. |
-u1000 | Refuse authenticated accounts with a UID below 1000. |
Enable and start the service after its access policy has been configured:
# rcctl enable pure_ftpd
# rcctl start pure_ftpd
# rcctl check pure_ftpd
Command-Line Flags #
Small configurations can remain in daemon flags. This example keeps the packaged defaults, refuses anonymous logins, and restricts passive data connections to a defined port range:
# rcctl set pure_ftpd flags "-A -B -E -H -u1000 -p50000:50100"
The rcctl set command replaces the complete flag string. Required defaults must therefore remain in the new value. The setting is stored in /etc/rc.conf.local.
Configuration File #
Pure-FTPd can also read a configuration file. Copy the packaged example and restrict its permissions:
# cp /usr/local/share/examples/pure-ftpd/pure-ftpd.conf.sample /etc/pure-ftpd.conf
# chmod 600 /etc/pure-ftpd.conf
The packaged rc script starts pure-ftpd directly and does not load the example file automatically. Pass the copied file as the service argument:
# rcctl set pure_ftpd flags "/etc/pure-ftpd.conf"
Replacing the default flags with a configuration file also removes the policy expressed by those flags. A local-user configuration should contain equivalent directives:
ChrootEveryone yes
Daemonize yes
DontResolve yes
MinUID 1000
NoAnonymous yes
UnixAuthentication yes
PassivePortRange 50000 50100
The sample file documents the other supported directives. Use either command-line flags or a configuration file as the primary service configuration so that the active policy remains easy to inspect.
Local Users #
With Unix authentication enabled, Pure-FTPd checks local system accounts. The account home directory becomes the FTP root when ChrootEveryone is enabled. The MinUID setting rejects service and system accounts below the configured UID threshold.
Local accounts must have a login shell accepted by Pure-FTPd. Because the FTP password is also the system account password, local-user access must not be enabled without TLS on an untrusted network.
Virtual Users #
The OpenBSD package is built with PureDB support and installs pure-pw(8). Virtual FTP users can have passwords and home directories that are separate from interactive system accounts.
Create one unprivileged system identity to own the virtual users’ files:
# groupadd ftpvirtual
# useradd -g ftpvirtual -d /var/empty -s /sbin/nologin ftpvirtual
# install -d -o ftpvirtual -g ftpvirtual -m 0750 /srv/ftp/alice
Create a virtual user and compile the text password database into the indexed PureDB file:
# pure-pw useradd alice -u ftpvirtual -d /srv/ftp/alice
# pure-pw mkdb
The useradd command asks for the FTP password. The -d option records a chrooted home directory. The default files are /etc/pureftpd.passwd and /etc/pureftpd.pdb.
Enable PureDB and disable system-account authentication in /etc/pure-ftpd.conf:
UnixAuthentication no
PureDB /etc/pureftpd.pdb
Changes to the text database do not take effect until the PureDB file is rebuilt. The -m option applies a change and rebuilds the database in one operation:
# pure-pw show alice
# pure-pw passwd alice -m
# pure-pw userdel alice -m
Deleting a virtual user does not delete that user’s files.
Passive Ports and PF #
FTP uses a control connection and separate data connections. A fixed passive range makes the data connections compatible with a restrictive pf(4) policy.
For command-line configuration, use -p50000:50100. For /etc/pure-ftpd.conf, use:
PassivePortRange 50000 50100
Permit the control port and the same passive range in /etc/pf.conf:
ext_if = "em0"
pass in on $ext_if proto tcp to ($ext_if) port 21
pass in on $ext_if proto tcp to ($ext_if) port 50000:50100
Validate and reload the rules:
# pfctl -nf /etc/pf.conf
# pfctl -f /etc/pf.conf
When the server is behind NAT and advertises the wrong address in passive replies, set the public address or resolvable hostname:
ForcePassiveIP ftp.example.com
The PF range and the Pure-FTPd range must match.
TLS #
The OpenBSD port is built with TLS support. Pure-FTPd can read a certificate and private key from separate files. An /etc/pure-ftpd.conf configuration using certificates maintained by acme-client(1)
can contain:
TLS 3
CertFileAndKey "/etc/ssl/ftp.example.com.fullchain.pem" "/etc/ssl/private/ftp.example.com.key"
TLS 1 accepts both cleartext and encrypted sessions. TLS 2 refuses sessions that do not negotiate TLS. TLS 3 also requires encrypted data connections. A public service should use the strictest setting supported by all required clients.
Restart the service after changing its listener, authentication, passive-port, or TLS configuration:
# rcctl restart pure_ftpd
# rcctl check pure_ftpd
The certificate name must match the hostname used by FTP clients. The private key must remain readable only by root.
Operational Checks #
Review the active rc configuration and confirm that the daemon is running:
# rcctl get pure_ftpd
# rcctl check pure_ftpd
The package manual and installed documentation describe all available flags, configuration directives, virtual-user options, and authentication flavors:
$ man pure-ftpd
$ man pure-pw
$ ls /usr/local/share/doc/pure-ftpd/
Keep anonymous access disabled unless it is an explicit service requirement. Restrict the passive port range in both Pure-FTPd and PF, require TLS for credentials and data, and prefer SFTP when compatibility with FTP is not required.