Pf
Storage Azure

Pure-FTPd on Ubuntu 24.04 on Azure User Guide

| Product: Pure-FTPd on Ubuntu 24.04 LTS on Azure

Overview

This image runs a production ready FTP file transfer server built on Pure-FTPd, a small, fast and security focused open source FTP daemon. The service is fully configured and hardened, so you can move files securely within minutes of launch without hand editing the daemon configuration.

The server is FTPS only: explicit FTP over TLS is required for both authentication and data transfer, so credentials and file contents never travel in the clear. Anonymous access is disabled. Users are virtual users held in a compact Pure-FTPd database (PureDB) rather than real Linux login accounts, and every user is locked into their own home directory with a chroot jail. User home directories live on a dedicated, independently resizable Azure data disk mounted at /srv/ftp, kept separate from the operating system disk. The data disk is part of the image, so every VM you deploy is provisioned with it automatically.

The image ships with no shared credentials. On the first boot of every deployed VM, a one shot service generates a self signed TLS certificate unique to that VM, creates a single FTP user named cloudimg with a strong random password unique to that VM, and records the details in a root only file. You can confirm the server works immediately, then add your own users. Two small management tools, pureftpd-adduser and pureftpd-listusers, wrap the underlying pure-pw utility for day to day administration.

What is included:

  • Pure-FTPd FTP server (Ubuntu 24.04 noble main), FTPS only with explicit TLS required
  • Virtual users in a PureDB database, each chroot jailed to its own home directory
  • Dedicated 50 GiB data disk at /srv/ftp (ext4) — separate from the OS disk, provisioned with every VM
  • Per VM self signed TLS certificate and per VM cloudimg FTP user created at first boot
  • Anonymous FTP disabled; a configured passive port range (30000-30009) for firewall friendly transfers
  • Management tools in /usr/local/sbin: pureftpd-adduser, pureftpd-listusers (plus pure-pw)
  • Per VM credentials recorded in /root/pure-ftpd-credentials.txt
  • 24/7 cloudimg support

Prerequisites

Before you deploy this image you need:

  • An active Microsoft Azure subscription where you can create virtual machines
  • An SSH key pair for administrator access to the VM
  • A virtual network and subnet in the target region, with a network security group (NSG) allowing inbound port 22 (SSH) from your admin network, inbound port 21 (FTP control) and the passive data port range 30000-30009 from the networks your FTP users connect from
  • The Azure CLI installed locally if you plan to deploy from the command line, and an FTPS capable client (the lftp command line tool, FileZilla, WinSCP or Cyberduck) to connect as a user

Standard_B2s (2 vCPU / 4 GiB RAM) is a balanced default; size the VM to the number of users and the transfer volume you expect.

Step 1: Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, and search the Marketplace for Pure-FTPd by cloudimg. Select the listing and choose Create.

On the Basics tab pick your subscription and resource group, a region, and a VM size (Standard_B2s or larger). Under Administrator account select SSH public key, set the username, and paste your public key. Under Inbound port rules allow SSH (22). Review the dedicated data disk on the Disks tab — it is included in the image and carries your FTP users' home directories. Select Review + create, then Create. First-boot initialisation (TLS certificate and the per-VM FTP user) completes within a few seconds of the VM reaching the Running state.

After the VM is running, add inbound NSG rules for FTP control (21) and the passive range (30000-30009) from the networks your FTP users connect from (see Step 8).

Step 2: Deploy from the Azure CLI

The following block creates a VM from the cloudimg Pure-FTPd image into an existing VNet and subnet. Replace the placeholders with your own values. The dedicated /srv/ftp data disk is part of the image and is attached automatically.

az vm create \
  --resource-group <your-rg> \
  --name pure-ftpd \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard

# Open the FTP control port and the passive data range
az vm open-port --resource-group <your-rg> --name pure-ftpd --port 21 --priority 1001
az vm open-port --resource-group <your-rg> --name pure-ftpd --port 30000-30009 --priority 1002

Step 3: Connect as the Administrator over SSH

Connect to the VM with SSH as the administrator user you set at deploy time (azureuser by default on Ubuntu). The administrator account is SSH key only.

ssh azureuser@<vm-public-ip>

Step 4: Read the Per-VM FTP Credentials

On first boot the server creates an FTP user named cloudimg with a password unique to your VM, and writes the details to a root only file. Read it:

sudo cat /root/pure-ftpd-credentials.txt

You will see the per-VM user, password and connection details (the password shown here is an example — yours will differ):

ftp.user=cloudimg
ftp.password=p27vGj3Cm1vGusRyXxbn
ftp.host=10.0.0.21
ftp.tls=explicit-required
ftp.passive_ports=30000-30009

The per-VM Pure-FTPd credentials file, the running pure-ftpd service, and the dedicated /srv/ftp data disk mount

Step 5: Confirm the Service and the Data Disk

Check that Pure-FTPd is active and that the dedicated data disk is mounted at /srv/ftp:

systemctl is-active pure-ftpd
findmnt -no SOURCE,TARGET,FSTYPE,SIZE /srv/ftp

List the FTP users held in the PureDB database:

sudo pureftpd-listusers

The cloudimg first-boot user is listed with its chroot home directory:

cloudimg    /srv/ftp/cloudimg/./

Step 6: Verify FTPS Works Locally

You can confirm an encrypted round-trip directly on the VM using the bundled lftp client. This reads the per-VM password from the credentials file, connects over explicit FTPS, uploads a file and downloads it again. The local test uses active mode (passive-mode false) so it works over the loopback address regardless of the ForcePassiveIP setting used by external clients:

FTP_USER=$(sudo awk -F= '/^ftp.user=/{print $2; exit}' /root/pure-ftpd-credentials.txt)
FTP_PW=$(sudo awk -F= '/^ftp.password=/{print $2; exit}' /root/pure-ftpd-credentials.txt)
echo "hello from cloudimg" > /tmp/hello.txt
lftp -u "$FTP_USER","$FTP_PW" \
  -e "set ssl:verify-certificate no; set ftp:ssl-force true; set ftp:ssl-protect-data true; set ftp:passive-mode false; put /tmp/hello.txt -o hello.txt; ls; get hello.txt -o /tmp/hello.dl; bye" \
  127.0.0.1
cat /tmp/hello.dl

The listing shows the uploaded file and the download is byte-identical:

-rw-r--r--    1 999        ftpvirtual         20 Jul 19 05:23 hello.txt
hello from cloudimg

An explicit-FTPS round-trip with lftp on the VM: connect over required TLS, upload a file, list it, and download it byte-identical

Step 7: Add Your Own FTP Users

Create additional FTP users with pureftpd-adduser. Each user is chroot-jailed to its own home directory under /srv/ftp. Omit the password to have a strong one generated for you:

sudo pureftpd-adduser project-uploads
sudo pureftpd-listusers

The tool prints the generated password and confirms the chroot home:

FTPS virtual user "project-uploads" ready.
  chroot home : /srv/ftp/project-uploads
  TLS         : required (explicit FTPS)
  GENERATED PASSWORD for project-uploads: cECwfzp4AqhgFVClA5Ut

To set a specific password instead, use sudo pureftpd-adduser project-uploads --password 'YourStrongPassword'. For advanced operations (changing a password, quotas, bandwidth limits) use the underlying pure-pw tool, for example sudo pure-pw passwd project-uploads -m.

Creating a chroot-jailed FTP user with pureftpd-adduser and listing all virtual users with pureftpd-listusers

Step 8: Connect from Your Workstation

Connect from any FTPS capable client. The server requires explicit FTP over TLS — plain FTP is rejected.

With the lftp command line client, replacing the host with your VM's public IP:

lftp -u cloudimg,'<your-password>' \
  -e "set ftp:ssl-force true; set ftp:ssl-protect-data true; set ssl:verify-certificate no; ls; bye" \
  <vm-public-ip>

In FileZilla: set Protocol to FTP - File Transfer Protocol, Encryption to Require explicit FTP over TLS, Host to your VM's public IP, Port to 21, and enter the user and password. Accept the self-signed certificate on first connect.

Passive mode and the NSG. FTP uses a second connection for data transfer. This image ships with a fixed passive port range (30000-30009) and sets ForcePassiveIP to your VM's public IP on first boot, so passive-mode clients work through NAT. You must open TCP 21 and TCP 30000-30009 in your Azure NSG for the networks your users connect from.

Step 9: Where Things Live

  • FTP user home directories (chroot roots): /srv/ftp/<user> on the dedicated data disk
  • Virtual user database: /etc/pure-ftpd/pureftpd.pdb (managed with pure-pw / pureftpd-adduser)
  • Configuration (one file per directive): /etc/pure-ftpd/conf/
  • TLS certificate (per VM, self-signed): /etc/ssl/private/pure-ftpd.pem
  • Per-VM credentials: /root/pure-ftpd-credentials.txt
  • Transfer and connection log: sudo journalctl -u pure-ftpd

Support

This image is maintained by cloudimg with security patching and 24/7 support. For help contact support@cloudimg.co.uk. For the underlying software see the Pure-FTPd documentation.