Deployment guide

ProFTPD

Overview

ProFTPD is a highly configurable, widely deployed FTP server for Unix and Linux. This SecureAnyCloud Azure Marketplace image runs it on Ubuntu 24.04 in an FTPS-first posture. Explicit TLS is required on both the control channel and the data channel, so credentials and file contents are never sent in the clear.

What you get:

  • ProFTPD 1.3 from the Ubuntu 24.04 apt archive, run under systemd as proftpd.service
  • FTPS (explicit TLS) required on the control and data channels (TLSRequired on), so a plaintext FTP login is refused
  • A per-instance unique FTP user and password and a unique self-signed TLS certificate, generated on first boot and written to /root/proftpd-credentials.txt (mode 0600)
  • Every user chrooted to its own home directory under /srv/ftp, so that an account sees only its own files
  • No anonymous access, and login restricted to members of the dedicated sacftp group
  • A defined passive port range (40000 to 40009) and a MasqueradeAddress set to this VM's address for passive mode behind network address translation

The image installs ProFTPD 1.3 from the official Ubuntu 24.04 apt archive with the mod_tls module, run under systemd as proftpd.service. The server listens for the FTP control channel on tcp port 21 and uses a passive data port range of 40000 to 40009.

There is no web interface and no database in this image. The configuration tree under /etc/proftpd is the whole configuration.

Secure by default, with no known bootstrap credential. The stock package ships no usable login in this image. On the first boot of every VM, a one-shot service creates a unique FTP user with a strong random password. It generates a unique self-signed TLS certificate for that specific machine and sets the passive mode masquerade address to the instance address. It then writes the user, password and host to a root-owned credentials file.

Every user is chrooted to its own home directory, and anonymous access is refused. Only members of a dedicated login group may authenticate, so no two instances share a credential.

Prerequisites

  • A VM launched from this SecureAnyCloud ProFTPD image on Azure
  • An Azure Network Security Group that allows inbound tcp 21 (FTP control) and tcp 40000 to 40009 (FTPS passive data), scoped to your client addresses only. Do not expose FTP to the whole internet
  • SSH access to the VM as azureuser

FTPS uses one connection for control and a separate connection for each transfer, so both port 21 and the passive range must be open to your clients.

The passive range is small by design. If you expect many concurrent transfers, widen it in /etc/proftpd/conf.d/sac.conf and in the NSG.

Verify the FTPS server is running

Connect over SSH as azureuser. Then confirm that proftpd.service is active, the mod_tls module is loaded and the server is listening on port 21.

sudo systemctl is-active proftpd proftpd -vv 2>/dev/null | grep -i mod_tls | head -1 sudo ss -tlnH | grep -E ':21 '

You should see active, the mod_tls module listed, and a listener bound to *:21 for the FTP control channel.

Retrieve the per-instance credentials and test a secure transfer

On the first boot of your VM, ProFTPD generated a unique FTP user, a unique password and a unique TLS certificate. The user, password and host are stored in the root-owned credentials file:

sudo cat /root/proftpd-credentials.txt

The file contains FTP_USER, FTP_PASSWORD and FTP_HOST, each unique to this VM.

Test a secure transfer end to end with curl. It negotiates explicit TLS with --ssl-reqd and accepts the self-signed certificate with --insecure. The block below reads the generated user and password, uploads a file over FTPS, downloads it back, and confirms that the contents match:

FTP_USER=$(sudo grep '^FTP_USER=' /root/proftpd-credentials.txt | cut -d= -f2-)
FTP_PASSWORD=$(sudo grep '^FTP_PASSWORD=' /root/proftpd-credentials.txt | cut -d= -f2-)
echo "sac FTPS round trip $(date)" > /tmp/upload.txt curl --ssl-reqd --insecure -u "$FTP_USER:$FTP_PASSWORD" -T /tmp/upload.txt ftp://127.0.0.1/upload.txt curl --ssl-reqd --insecure -u "$FTP_USER:$FTP_PASSWORD" ftp://127.0.0.1/upload.txt -o /tmp/download.txt cat /tmp/download.txt

The upload and download both succeed over explicit TLS, and the downloaded contents match what you uploaded. This proves that the FTPS pipeline works end to end: TLS negotiation, the per-instance user and password, and the chrooted home directory.

Confirm plaintext, anonymous and out-of-jail access are refused

A secure FTP server must refuse anything less than TLS. This image requires explicit TLS, refuses anonymous logins, and chroots each user to its home directory.

The block below tests all three. A plaintext login, an anonymous login and an attempt to read a file outside the user's home directory each fail.

FTP_USER=$(sudo grep '^FTP_USER=' /root/proftpd-credentials.txt | cut -d= -f2-)
FTP_PASSWORD=$(sudo grep '^FTP_PASSWORD=' /root/proftpd-credentials.txt | cut -d= -f2-)
curl -sS -u "$FTP_USER:$FTP_PASSWORD" ftp://127.0.0.1/ -o /dev/null || echo "plaintext FTP refused (TLS required)"
curl -sS --ssl-reqd --insecure -u "anonymous:x@x" ftp://127.0.0.1/ -o /dev/null || echo "anonymous login refused"
curl -sS --ssl-reqd --insecure -u "$FTP_USER:$FTP_PASSWORD" ftp://127.0.0.1/etc/passwd -o /dev/null || echo "chroot enforced: /etc/passwd is not reachable"

Each attempt is rejected:

  • The plaintext login is refused because TLS is required.
  • The anonymous login is refused because only members of the sacftp group may authenticate.
  • The request for /etc/passwd fails because the user is chrooted and its filesystem root is its own home directory.

Review the hardening configuration

All of the hardening lives in one readable drop-in file, /etc/proftpd/conf.d/sac.conf, which the main proftpd.conf includes:

grep -vE '^[[:space:]]*#|^[[:space:]]*$' /etc/proftpd/conf.d/sac.conf

The drop-in enforces these settings:

  • TLSEngine on and TLSRequired on (explicit TLS on control and data)
  • DefaultRoot ~ (chroot every user to its home)
  • A global <Limit LOGIN> that allows only the sacftp group and denies everything else
  • TLSOptions NoSessionReuseRequired for broad client interoperability
  • The PassivePorts 40000 40009 range

The passive mode address for this specific VM is written to /etc/proftpd/conf.d/sac-masq.conf on first boot. After you edit either file, apply the change with sudo systemctl restart proftpd.

Connect from an FTPS client

From your own workstation, connect with any FTPS-capable client using explicit TLS (also called FTP over TLS, or AUTH TLS). Use the FTP_USER, FTP_PASSWORD and FTP_HOST values from the credentials file, use port 21, and enable explicit TLS.

The certificate is self-signed, so accept it on first connection or replace it with your own certificate. For example, with curl from your workstation:

# Replace the host and password with the values from /root/proftpd-credentials.txt.
curl --ssl-reqd --insecure -u FTP_USER:FTP_PASSWORD -T report.pdf ftp://FTP_HOST/report.pdf
curl --ssl-reqd --insecure -u FTP_USER:FTP_PASSWORD ftp://FTP_HOST/report.pdf -o report.pdf

Graphical clients such as FileZilla and WinSCP work the same way. Choose the protocol FTP with Require explicit FTP over TLS. Set the host to FTP_HOST, the port to 21, and the mode to passive.

Make sure that your Azure Network Security Group allows inbound tcp 21 and tcp 40000 to 40009 from your client address.

Add more users and replace the certificate

Each FTP account is a normal system user in the sacftp group, with a home directory under /srv/ftp and a nologin shell. To add another isolated FTP account, create a user in that group and give it a strong password and its own home. The user can then log in over FTPS, chrooted to that directory.

To use a certificate signed by a certificate authority instead of the per-instance self-signed one, replace /etc/proftpd/tls/proftpd.crt and /etc/proftpd/tls/proftpd.key, and then reload the service.

For larger deployments, you can move to virtual users backed by a file, LDAP or SQL, and add quotas and bandwidth controls. All of this lives within the ProFTPD configuration tree.

Support

SecureAnyCloud provides 24/7 technical support for this ProFTPD image by email (sales@secureanycloud.com) and live chat. Critical issues receive a one hour average response time.

Support covers:

  • Connecting FTPS clients
  • Managing users and directories
  • Configuring chroot and quotas
  • Opening the control port and passive range in your network security group
  • Setting the masquerade address behind network address translation
  • Moving to virtual users with LDAP or SQL backends
  • TLS certificate management
  • Version upgrades and troubleshooting

All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.

Deploy on Azure

Launch ProFTPD 1.3 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure