FTP servers often go down, but you can make them highly available by setting up active-passive failover.
Here’s how it works: you have two FTP servers, one active and one passive. The active server handles all FTP traffic. If the active server fails, the passive server takes over and becomes the active server. This ensures that your FTP service remains available even if one server goes down.
Let’s walk through a typical setup. We’ll use two Linux servers, ftp-primary and ftp-secondary, both running vsftpd.
Server 1: ftp-primary (Active)
-
Install
vsftpd:sudo apt update && sudo apt install vsftpd -
Configure
vsftpd: Edit/etc/vsftpd.conf:listen=NO listen_ipv6=YES anonymous_enable=NO local_enable=YES write_enable=YES local_umask=022 dirmessage_enable=YES use_localtime=YES xferlog_enable=YES connect_from_port_20=YES xferlog_file=/var/log/vsftpd.log xferlog_std_format=YES chroot_local_user=YES allow_writeable_chroot=YES pam_service_name=vsftpd rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key ssl_enable=YES allow_anon_ssl=NO force_local_data_ssl=YES force_local_logins_ssl=YES ssl_tlsv1=YES ssl_sslv2=NO ssl_sslv3=NO require_ssl_reuse=NO ssl_ciphers=HIGHlisten=NOandlisten_ipv6=YESare important for active/passive setups as we’ll usexinetdorsystemdto manage the service.chroot_local_user=YESandallow_writeable_chroot=YESare for security, confining users to their home directories.ssl_enable=YESand related directives enforce secure FTP connections.
-
Restart
vsftpd:sudo systemctl restart vsftpd
Server 2: ftp-secondary (Passive)
-
Install
vsftpd:sudo apt update && sudo apt install vsftpd -
Configure
vsftpd: Use the exact same/etc/vsftpd.confas onftp-primary. Consistency is key. -
Restart
vsftpd:sudo systemctl restart vsftpd
Heartbeat and Failover Mechanism
We’ll use heartbeat (part of the pacemaker suite) to monitor the active server and trigger failover.
-
Install
pacemakerandcorosyncon both servers:sudo apt update && sudo apt install pacemaker corosync -
Configure
corosync: Onftp-primary, edit/etc/corosync/corosync.conf:totem { version: 2 cluster_name: my_ftp_cluster transport: knet interface { ringnumber: 0 bindnetaddr: 192.168.1.0 # Replace with your network subnet } secauth: on crypto_cipher: aes256 crypto_hash: sha256 } logging { fileline: off to_syslog: yes } nodelist { node { ring0_addr: 192.168.1.100 # IP of ftp-primary nodeid: 1 } node { ring0_addr: 192.168.1.101 # IP of ftp-secondary nodeid: 2 } }Copy this file to
ftp-secondaryand ensure thering0_addrvalues are correct for each server. -
Start
corosync: On both servers:sudo systemctl start corosync sudo systemctl enable corosync -
Configure
pacemaker: Onftp-primary(this is where you define the cluster resources):# Create a virtual IP address that will float between servers sudo pcs resource create VirtualIP ocf:heartbeat:IPaddr2 ip=192.168.1.200 cidr_netmask=24 op monitor interval=30s # Create a resource for vsftpd sudo pcs resource create FTP_Service ocf:heartbeat:LVM-Thin-Monitor op monitor interval=30s --clone # Create a resource that ensures vsftpd is running on the active node sudo pcs resource create FTP_Service ocf:heartbeat:Systemd systemd=vsftpd op monitor interval=30s # Define the failover order: VIP first, then FTP service sudo pcs constraint order promote VirtualIP then FTP_Service symmetrical=false # Define that FTP_Service should run on the same node as VirtualIP sudo pcs constraint colocation add FTP_Service with VirtualIP INFINITY # Set the cluster to start sudo pcs cluster start --allVirtualIP: This is a floating IP address. When the active server is running, this IP will be assigned to it. Clients connect to this IP. If the server fails,pacemakerwill move this IP to the passive server.FTP_Service: ThisSystemdresource tellspacemakerto manage thevsftpdservice. The--cloneflag is used here incorrectly in the example and should be removed if you intend to usecolocationandorderconstraints for active/passive. For a true active-passive, you’d typically usems(master/slave) resource types or a simpleclonewith no colocation if you wanted both to run but only one to be active via a floating IP. Let’s correct this for active-passive:
Corrected
pacemakerconfiguration for Active-Passive:On
ftp-primary:# Create a virtual IP address that will float between servers sudo pcs resource create VirtualIP ocf:heartbeat:IPaddr2 ip=192.168.1.200 cidr_netmask=24 op monitor interval=30s # Create an Fencing resource (essential for production) - Placeholder for illustration # sudo pcs stonith create fence_node fence_node ipaddr=192.168.1.100 pcmk_host_list=ftp-primary pcmk_reboot_timeout=60 # Create the vsftpd service as a master/slave resource # This makes one server the master (active) and the other the slave (passive) sudo pcs resource create FTP_Service ocf:heartbeat:Systemd systemd=vsftpd op monitor interval=30s meta master-max=1 master-node-max=1 clone-max=2 clone-node-max=1 # Define the failover order: VirtualIP should be started before FTP_Service sudo pcs constraint order promote VirtualIP then FTP_Service symmetrical=false # Define that FTP_Service should run on the same node as VirtualIP sudo pcs constraint colocation add FTP_Service with VirtualIP INFINITY # Enable the cluster sudo pcs cluster enable --allFTP_Serviceasmaster-max=1andclone-max=2sets it up as a master/slave resource, meaning only one instance will be active at a time.stonith(Shoot The Other Node In The Head) is crucial for production environments to ensure a failed node is truly down before the passive node takes over. This example omits the complexstonithsetup for brevity but is vital for preventing split-brain scenarios.
-
Verify Cluster Status: On either server:
sudo pcs statusYou should see
VirtualIPandFTP_Servicerunning on one of the nodes (the active one).
How Failover Works
corosync monitors the cluster nodes. If ftp-primary stops responding (e.g., network failure, crash), corosync on ftp-secondary detects this. pacemaker then:
- Stops
VirtualIPonftp-primary. - Starts
VirtualIPonftp-secondary. - Promotes
FTP_Serviceto master onftp-secondary(startingvsftpd).
Clients connecting to 192.168.1.200 will automatically reconnect to ftp-secondary once it becomes active.
Important Considerations:
- Shared Storage: For
chrootenvironments and user data, you’ll need shared storage (like NFS or SAN) that both servers can access. This ensures user home directories and files are available regardless of which server is active. - Firewall: Ensure your firewalls allow traffic on the FTP control port (21) and data ports (often ephemeral in passive mode, or ports 20 and a range if configured).
- Fencing (STONITH): In a real-world scenario, you must configure a STONITH device. This prevents two nodes from thinking they are both active simultaneously (split-brain), which can lead to data corruption.
The next step is to configure your clients to use the floating IP address 192.168.1.200 for all FTP connections.