Mount FTP Sites as Local Folders in Linux 2025: Complete curlftpfs & FUSE Integration Guide
Mounting FTP sites as local directories transforms remote file management by integrating FTP servers seamlessly into your Linux filesystem. This comprehensive guide covers curlftpfs installation, advanced mounting techniques, security best practices, performance optimization, and enterprise-scale FTP storage integration.
FTP Mounting Overview
Understanding FUSE and curlftpfs
What is FUSE?
FUSE (Filesystem in Userspace) enables non-privileged users to create custom filesystems without modifying kernel code. Key benefits include:
- User-space Implementation: No kernel modules required
- Security: Runs with user privileges, not root
- Flexibility: Support for various remote protocols
- Compatibility: Works with standard filesystem tools
- Performance: Efficient caching and buffering
curlftpfs Architecture
curlftpfs leverages libcurl to provide FTP filesystem access:
- Protocol Support: FTP, FTPS, SFTP via curl backend
- Caching: Local file caching for performance
- Threading: Multi-threaded operations for concurrent access
- Compatibility: Works with any FTP server
Comprehensive Installation Guide
Multi-Distribution Installation
Ubuntu/Debian Installation
#!/bin/bash
# Complete installation script for Ubuntu/Debian
# Update package lists
sudo apt update
# Install curlftpfs and dependencies
sudo apt install -y curlftpfs fuse3 curl
# Install additional utilities
sudo apt install -y lftp ncftp filezilla # Alternative FTP clients
sudo apt install -y sshfs davfs2 # Other network filesystems
# Enable FUSE for current user
sudo usermod -a -G fuse $USER
# Load FUSE module
sudo modprobe fuse
# Verify installation
curlftpfs --version
RHEL/CentOS/Fedora Installation
#!/bin/bash
# Installation for Red Hat based systems
# Enable EPEL repository for CentOS/RHEL
sudo yum install -y epel-release
# Install curlftpfs
sudo yum install -y curlftpfs fuse fuse-libs
# For Fedora
sudo dnf install -y curlftpfs fuse3
# Enable and start FUSE
sudo systemctl enable fuse
sudo systemctl start fuse
# Add user to fuse group
sudo usermod -a -G fuse $USER
Arch Linux Installation
#!/bin/bash
# Arch Linux installation
# Install from official repositories
sudo pacman -S curlftpfs fuse3
# Enable FUSE module
sudo modprobe fuse
# Add to modules-load for persistence
echo "fuse" | sudo tee /etc/modules-load.d/fuse.conf
Building from Source
#!/bin/bash
# Build curlftpfs from source for latest features
# Install build dependencies
sudo apt install -y build-essential libcurl4-openssl-dev \
libfuse3-dev libglib2.0-dev pkg-config
# Download source
git clone https://github.com/rzvncj/curlftpfs.git
cd curlftpfs
# Build and install
./autogen.sh
./configure --prefix=/usr/local
make
sudo make install
# Update library cache
sudo ldconfig
Advanced Mounting Techniques
Basic Mount Operations
Simple Mount Command
# Basic mount syntax
curlftpfs ftp://username:password@ftp.example.com /mnt/ftp
# Mount with specific directory
curlftpfs ftp://username:password@ftp.example.com/path/to/dir /mnt/ftp
# Anonymous FTP
curlftpfs ftp://ftp.example.com /mnt/ftp -o user=anonymous:anonymous@
Advanced Mount Options Script
#!/bin/bash
# Advanced FTP mounting script with options
# Configuration
FTP_HOST="ftp.example.com"
FTP_USER="username"
FTP_PASS="password"
MOUNT_POINT="/mnt/ftp"
LOG_FILE="/var/log/curlftpfs.log"
# Function to mount FTP with comprehensive options
mount_ftp_advanced() {
local options=""
# Build mount options
options+="-o allow_other" # Allow other users access
options+=" -o uid=$(id -u)" # Set owner UID
options+=" -o gid=$(id -g)" # Set owner GID
options+=" -o umask=0022" # Set file permissions
options+=" -o nonempty" # Allow mounting on non-empty dir
options+=" -o connect_timeout=30" # Connection timeout
options+=" -o cache_timeout=120" # Cache timeout in seconds
options+=" -o cache_stat_timeout=30" # Stat cache timeout
options+=" -o cache_dir_timeout=60" # Directory cache timeout
options+=" -o cache_link_timeout=60" # Symlink cache timeout
options+=" -o ftp_port=-" # Use any port for data connection
options+=" -o custom_list='LIST -la'" # Custom LIST command
# Create mount point if needed
sudo mkdir -p "$MOUNT_POINT"
# Mount FTP
echo "Mounting FTP: $FTP_HOST to $MOUNT_POINT"
curlftpfs "ftp://$FTP_USER:$FTP_PASS@$FTP_HOST" "$MOUNT_POINT" $options
# Verify mount
if mountpoint -q "$MOUNT_POINT"; then
echo "✓ FTP mounted successfully"
df -h "$MOUNT_POINT"
else
echo "✗ FTP mount failed"
return 1
fi
}
# Execute mount
mount_ftp_advanced
Secure Authentication Methods
Using .netrc for Credentials
#!/bin/bash
# Secure credential storage with .netrc
# Create .netrc file
cat > ~/.netrc << EOF
machine ftp.example.com
login myusername
password mypassword
machine ftp2.example.com
login user2
password pass2
EOF
# Secure the file
chmod 600 ~/.netrc
# Mount using .netrc
curlftpfs ftp://ftp.example.com /mnt/ftp -o netrc
Environment Variable Authentication
#!/bin/bash
# Use environment variables for credentials
# Set credentials (add to ~/.bashrc for persistence)
export FTP_USER="myusername"
export FTP_PASS="mypassword"
# Mount script using environment variables
mount_ftp_env() {
local ftp_host="$1"
local mount_point="$2"
if [[ -z "$FTP_USER" ]] || [[ -z "$FTP_PASS" ]]; then
echo "Error: FTP_USER and FTP_PASS must be set"
return 1
fi
curlftpfs "ftp://$FTP_USER:$FTP_PASS@$ftp_host" "$mount_point" \
-o allow_other,uid=$(id -u),gid=$(id -g)
}
# Usage
mount_ftp_env "ftp.example.com" "/mnt/ftp"
Credential File Method
#!/bin/bash
# Secure credential file approach
# Create credentials file
sudo tee /etc/ftp-credentials/site1.cred << EOF
username=myuser
password=mypass
host=ftp.example.com
port=21
EOF
# Secure the file
sudo chmod 600 /etc/ftp-credentials/site1.cred
sudo chown root:root /etc/ftp-credentials/site1.cred
# Mount function using credential file
mount_ftp_creds() {
local cred_file="$1"
local mount_point="$2"
# Source credentials
source "$cred_file"
# Mount FTP
curlftpfs "ftp://$username:$password@$host:$port" "$mount_point" \
-o allow_other,ssl,utf8
}
# Usage
mount_ftp_creds "/etc/ftp-credentials/site1.cred" "/mnt/ftp1"
Enterprise FTP Mount Management
Automated Mount Management System
#!/bin/bash
# Enterprise FTP mount management framework
# Configuration directory
CONFIG_DIR="/etc/ftpmount"
LOG_DIR="/var/log/ftpmount"
STATE_DIR="/var/lib/ftpmount"
# Create required directories
sudo mkdir -p "$CONFIG_DIR" "$LOG_DIR" "$STATE_DIR"
# Mount configuration structure
cat > "$CONFIG_DIR/mounts.conf" << 'EOF'
# FTP Mount Configuration
# Format: name|host|user|pass|mountpoint|options
production|ftp.prod.example.com|produser|prodpass|/mnt/ftp/prod|ssl,allow_other
staging|ftp.stage.example.com|stageuser|stagepass|/mnt/ftp/stage|ssl,cache_timeout=300
backup|backup.example.com|backupuser|backuppass|/mnt/ftp/backup|ssl,utf8,cache_dir_timeout=600
EOF
# FTP mount manager class
cat > /usr/local/bin/ftp-mount-manager << 'SCRIPT'
#!/bin/bash
# FTP Mount Manager
# Manages multiple FTP mount points with monitoring
set -euo pipefail
# Configuration
CONFIG_FILE="/etc/ftpmount/mounts.conf"
LOG_FILE="/var/log/ftpmount/manager.log"
STATE_FILE="/var/lib/ftpmount/state"
HEALTH_CHECK_INTERVAL=300 # 5 minutes
# Logging function
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
# Mount single FTP
mount_ftp() {
local name="$1"
local host="$2"
local user="$3"
local pass="$4"
local mountpoint="$5"
local options="${6:-}"
log "Mounting $name ($host) to $mountpoint"
# Create mount point
mkdir -p "$mountpoint"
# Build mount command
local mount_cmd="curlftpfs ftp://$user:$pass@$host $mountpoint"
if [[ -n "$options" ]]; then
mount_cmd+=" -o $options"
fi
# Execute mount
if eval "$mount_cmd" 2>&1 | tee -a "$LOG_FILE"; then
log "✓ Successfully mounted $name"
echo "$name|mounted|$(date +%s)" >> "$STATE_FILE"
return 0
else
log "✗ Failed to mount $name"
echo "$name|failed|$(date +%s)" >> "$STATE_FILE"
return 1
fi
}
# Unmount FTP
unmount_ftp() {
local name="$1"
local mountpoint="$2"
log "Unmounting $name from $mountpoint"
if fusermount -u "$mountpoint" 2>&1 | tee -a "$LOG_FILE"; then
log "✓ Successfully unmounted $name"
sed -i "/^$name|/d" "$STATE_FILE"
return 0
else
log "✗ Failed to unmount $name"
return 1
fi
}
# Mount all configured FTPs
mount_all() {
log "Starting mount all operation"
while IFS='|' read -r name host user pass mountpoint options; do
[[ "$name" =~ ^#.*$ ]] && continue # Skip comments
[[ -z "$name" ]] && continue # Skip empty lines
mount_ftp "$name" "$host" "$user" "$pass" "$mountpoint" "$options"
done < "$CONFIG_FILE"
}
# Unmount all FTPs
unmount_all() {
log "Starting unmount all operation"
while IFS='|' read -r name host user pass mountpoint options; do
[[ "$name" =~ ^#.*$ ]] && continue
[[ -z "$name" ]] && continue
if mountpoint -q "$mountpoint" 2>/dev/null; then
unmount_ftp "$name" "$mountpoint"
fi
done < "$CONFIG_FILE"
}
# Check mount health
check_health() {
local unhealthy=0
log "Performing health check"
while IFS='|' read -r name host user pass mountpoint options; do
[[ "$name" =~ ^#.*$ ]] && continue
[[ -z "$name" ]] && continue
if mountpoint -q "$mountpoint" 2>/dev/null; then
# Test mount accessibility
if timeout 10 ls "$mountpoint" >/dev/null 2>&1; then
log "✓ $name is healthy"
else
log "✗ $name is not responding"
((unhealthy++))
# Attempt remount
log "Attempting to remount $name"
unmount_ftp "$name" "$mountpoint"
sleep 2
mount_ftp "$name" "$host" "$user" "$pass" "$mountpoint" "$options"
fi
else
log "✗ $name is not mounted"
((unhealthy++))
# Attempt mount
mount_ftp "$name" "$host" "$user" "$pass" "$mountpoint" "$options"
fi
done < "$CONFIG_FILE"
return $unhealthy
}
# Monitor daemon
monitor_daemon() {
log "Starting FTP mount monitor daemon"
while true; do
check_health
sleep "$HEALTH_CHECK_INTERVAL"
done
}
# Status report
status_report() {
echo "FTP Mount Status Report"
echo "======================="
echo ""
while IFS='|' read -r name host user pass mountpoint options; do
[[ "$name" =~ ^#.*$ ]] && continue
[[ -z "$name" ]] && continue
printf "%-20s: " "$name"
if mountpoint -q "$mountpoint" 2>/dev/null; then
local size=$(df -h "$mountpoint" 2>/dev/null | tail -1 | awk '{print $2}')
local used=$(df -h "$mountpoint" 2>/dev/null | tail -1 | awk '{print $5}')
echo "Mounted (Size: $size, Used: $used)"
else
echo "Not mounted"
fi
done < "$CONFIG_FILE"
}
# Performance statistics
performance_stats() {
echo "FTP Mount Performance Statistics"
echo "================================"
echo ""
while IFS='|' read -r name host user pass mountpoint options; do
[[ "$name" =~ ^#.*$ ]] && continue
[[ -z "$name" ]] && continue
if mountpoint -q "$mountpoint" 2>/dev/null; then
echo "Mount: $name"
echo "Path: $mountpoint"
# Test read performance
echo -n "Read Speed: "
dd if="$mountpoint/testfile" of=/dev/null bs=1M count=10 2>&1 | \
grep -oP '\d+\.\d+ [MG]B/s' || echo "N/A"
# Test write performance (if writable)
if touch "$mountpoint/.write_test" 2>/dev/null; then
echo -n "Write Speed: "
dd if=/dev/zero of="$mountpoint/.write_test" bs=1M count=10 2>&1 | \
grep -oP '\d+\.\d+ [MG]B/s' || echo "N/A"
rm -f "$mountpoint/.write_test"
else
echo "Write Speed: Read-only"
fi
echo ""
fi
done < "$CONFIG_FILE"
}
# Main command handler
case "${1:-}" in
mount)
mount_all
;;
unmount)
unmount_all
;;
remount)
unmount_all
sleep 2
mount_all
;;
status)
status_report
;;
check)
check_health
;;
monitor)
monitor_daemon
;;
performance)
performance_stats
;;
*)
echo "Usage: $0 {mount|unmount|remount|status|check|monitor|performance}"
exit 1
;;
esac
SCRIPT
# Make executable
sudo chmod +x /usr/local/bin/ftp-mount-manager
Systemd Service Integration
FTP Mount Service
# Create systemd service for FTP mounts
sudo tee /etc/systemd/system/ftp-mounts.service << 'EOF'
[Unit]
Description=FTP Mount Manager Service
After=network-online.target
Wants=network-online.target
[Service]
Type=forking
ExecStart=/usr/local/bin/ftp-mount-manager mount
ExecStop=/usr/local/bin/ftp-mount-manager unmount
ExecReload=/usr/local/bin/ftp-mount-manager remount
RemainAfterExit=yes
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
# Create monitoring service
sudo tee /etc/systemd/system/ftp-mount-monitor.service << 'EOF'
[Unit]
Description=FTP Mount Monitor Daemon
After=ftp-mounts.service
Requires=ftp-mounts.service
[Service]
Type=simple
ExecStart=/usr/local/bin/ftp-mount-manager monitor
Restart=always
RestartSec=30
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
# Enable services
sudo systemctl daemon-reload
sudo systemctl enable ftp-mounts.service
sudo systemctl enable ftp-mount-monitor.service
sudo systemctl start ftp-mounts.service
sudo systemctl start ftp-mount-monitor.service
Performance Optimization
Cache Configuration and Tuning
#!/bin/bash
# FTP mount performance optimization script
# Optimize mount for different use cases
optimize_ftp_mount() {
local mount_type="$1" # streaming, backup, interactive
local ftp_url="$2"
local mount_point="$3"
case "$mount_type" in
"streaming")
# Optimized for streaming large files
curlftpfs "$ftp_url" "$mount_point" \
-o cache_timeout=3600 \
-o cache_stat_timeout=3600 \
-o cache_dir_timeout=3600 \
-o cache_link_timeout=3600 \
-o ftp_port=- \
-o tcp_nodelay \
-o connect_timeout=60 \
-o ssl_control \
-o ssl_try \
-o no_verify_hostname \
-o no_verify_peer
;;
"backup")
# Optimized for backup operations
curlftpfs "$ftp_url" "$mount_point" \
-o cache_timeout=30 \
-o cache_stat_timeout=30 \
-o cache_dir_timeout=60 \
-o direct_io \
-o max_background=100 \
-o congestion_threshold=100 \
-o no_remote_lock \
-o ssl
;;
"interactive")
# Optimized for interactive use
curlftpfs "$ftp_url" "$mount_point" \
-o cache_timeout=5 \
-o cache_stat_timeout=2 \
-o cache_dir_timeout=5 \
-o max_read=65536 \
-o ssl_try \
-o connect_timeout=10
;;
*)
echo "Unknown mount type: $mount_type"
return 1
;;
esac
}
# Network buffer tuning
tune_network_buffers() {
# Increase network buffers for better FTP performance
sudo sysctl -w net.core.rmem_max=134217728
sudo sysctl -w net.core.wmem_max=134217728
sudo sysctl -w net.ipv4.tcp_rmem="4096 87380 134217728"
sudo sysctl -w net.ipv4.tcp_wmem="4096 65536 134217728"
# Make permanent
cat | sudo tee -a /etc/sysctl.conf << EOF
# FTP performance tuning
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
EOF
}
# Parallel FTP operations
parallel_ftp_operations() {
local mount_point="$1"
local operation="$2" # download, upload, sync
case "$operation" in
"download")
# Parallel download using GNU parallel
find "$mount_point" -type f -name "*.dat" | \
parallel -j 4 cp {} /local/destination/
;;
"upload")
# Parallel upload
find /local/source -type f -name "*.dat" | \
parallel -j 4 cp {} "$mount_point"/
;;
"sync")
# Parallel sync with rsync
rsync -av --parallel=4 /local/source/ "$mount_point"/
;;
esac
}
Connection Pooling and Management
#!/bin/bash
# Advanced connection management for FTP mounts
# Connection pool manager
cat > /usr/local/bin/ftp-connection-manager << 'SCRIPT'
#!/bin/bash
# FTP Connection Pool Manager
# Manages multiple FTP connections for load balancing
# Configuration
MAX_CONNECTIONS=10
CONNECTION_TIMEOUT=300
IDLE_TIMEOUT=60
# Connection pool array
declare -A connection_pool
# Initialize connection
init_connection() {
local conn_id="$1"
local ftp_url="$2"
local mount_point="/mnt/ftp_pool/conn_$conn_id"
mkdir -p "$mount_point"
if curlftpfs "$ftp_url" "$mount_point" -o connect_timeout=30; then
connection_pool[$conn_id]="active|$(date +%s)|$mount_point"
echo "Connection $conn_id initialized"
return 0
else
echo "Failed to initialize connection $conn_id"
return 1
fi
}
# Get least loaded connection
get_connection() {
local least_loaded=""
local min_load=999999
for conn_id in "${!connection_pool[@]}"; do
IFS='|' read -r status timestamp mount_point <<< "${connection_pool[$conn_id]}"
if [[ "$status" == "active" ]]; then
# Check connection load (number of open files)
local load=$(lsof "$mount_point" 2>/dev/null | wc -l)
if [[ $load -lt $min_load ]]; then
min_load=$load
least_loaded=$conn_id
fi
fi
done
echo "$least_loaded"
}
# Connection health check
check_connection_health() {
for conn_id in "${!connection_pool[@]}"; do
IFS='|' read -r status timestamp mount_point <<< "${connection_pool[$conn_id]}"
if [[ "$status" == "active" ]]; then
if ! mountpoint -q "$mount_point" || ! timeout 5 ls "$mount_point" >/dev/null 2>&1; then
echo "Connection $conn_id is unhealthy, reconnecting..."
fusermount -u "$mount_point" 2>/dev/null
init_connection "$conn_id" "$FTP_URL"
fi
fi
done
}
# Load balancer
load_balance_operation() {
local operation="$1"
local file="$2"
local conn_id=$(get_connection)
if [[ -z "$conn_id" ]]; then
echo "No available connections"
return 1
fi
IFS='|' read -r status timestamp mount_point <<< "${connection_pool[$conn_id]}"
case "$operation" in
"read")
cat "$mount_point/$file"
;;
"write")
cat > "$mount_point/$file"
;;
"list")
ls -la "$mount_point/$file"
;;
esac
}
# Initialize connection pool
for ((i=1; i<=MAX_CONNECTIONS; i++)); do
init_connection "$i" "$FTP_URL"
done
# Main loop
while true; do
check_connection_health
sleep 30
done
SCRIPT
chmod +x /usr/local/bin/ftp-connection-manager
Security Best Practices
Secure FTP (FTPS) Configuration
#!/bin/bash
# Secure FTPS mounting configuration
# Mount with SSL/TLS encryption
mount_ftps() {
local host="$1"
local user="$2"
local pass="$3"
local mount_point="$4"
# Create mount point
mkdir -p "$mount_point"
# Mount with SSL options
curlftpfs "ftp://$user:$pass@$host" "$mount_point" \
-o ssl \
-o ssl_control \
-o ssl_try \
-o no_verify_hostname \
-o no_verify_peer \
-o tlsv1_2 \
-o cipher_list="ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256"
}
# Certificate-based authentication
mount_ftps_cert() {
local host="$1"
local mount_point="$2"
local cert_file="$3"
local key_file="$4"
curlftpfs "ftps://$host" "$mount_point" \
-o ssl \
-o cert="$cert_file" \
-o key="$key_file" \
-o cacert="/etc/ssl/certs/ca-certificates.crt"
}
# Secure credential management
secure_credential_manager() {
# Use system keyring for credentials
local site_name="$1"
# Store credentials in keyring
echo -n "Enter FTP username: "
read -r username
echo -n "Enter FTP password: "
read -rs password
echo
# Store in system keyring (requires libsecret-tools)
echo "$password" | secret-tool store --label="FTP $site_name" \
service ftp \
username "$username" \
host "$site_name"
# Retrieve for mounting
local stored_pass=$(secret-tool lookup service ftp host "$site_name")
echo "Credentials stored securely"
}
# SELinux context management
configure_selinux_contexts() {
local mount_point="$1"
# Set appropriate SELinux context for FTP mounts
sudo semanage fcontext -a -t public_content_rw_t "$mount_point(/.*)?"
sudo restorecon -Rv "$mount_point"
# Allow FUSE mounts in SELinux
sudo setsebool -P allow_mount_anyfile 1
sudo setsebool -P ftpd_use_fusefs 1
}
# Firewall configuration for FTP
configure_firewall_ftp() {
# Allow FTP control port
sudo firewall-cmd --permanent --add-service=ftp
# Allow passive FTP ports
sudo firewall-cmd --permanent --add-port=30000-31000/tcp
# Reload firewall
sudo firewall-cmd --reload
}
Access Control and Permissions
#!/bin/bash
# FTP mount access control implementation
# Create restricted FTP mount
create_restricted_mount() {
local ftp_url="$1"
local mount_point="$2"
local allowed_user="$3"
local allowed_group="$4"
# Create mount point with specific permissions
sudo mkdir -p "$mount_point"
sudo chown "$allowed_user:$allowed_group" "$mount_point"
sudo chmod 750 "$mount_point"
# Mount with restricted access
sudo -u "$allowed_user" curlftpfs "$ftp_url" "$mount_point" \
-o uid=$(id -u "$allowed_user") \
-o gid=$(id -g "$allowed_group") \
-o umask=0027 \
-o allow_other \
-o default_permissions
# Set ACLs for fine-grained control
sudo setfacl -R -m u:"$allowed_user":rwx "$mount_point"
sudo setfacl -R -m g:"$allowed_group":rx "$mount_point"
sudo setfacl -R -m o::--- "$mount_point"
# Set default ACLs for new files
sudo setfacl -d -m u:"$allowed_user":rwx "$mount_point"
sudo setfacl -d -m g:"$allowed_group":rx "$mount_point"
sudo setfacl -d -m o::--- "$mount_point"
}
# Audit FTP mount access
audit_ftp_access() {
local mount_point="$1"
local audit_log="/var/log/ftp_mount_audit.log"
# Enable audit logging
cat > /etc/audit/rules.d/ftp-mount.rules << EOF
# Audit FTP mount access
-w $mount_point -p rwxa -k ftp_mount_access
EOF
# Reload audit rules
sudo augenrules --load
sudo systemctl restart auditd
# Monitor access in real-time
sudo aureport -f | grep "$mount_point" | tail -20
}
# Implement mount quotas
implement_mount_quotas() {
local mount_point="$1"
local max_size="$2" # e.g., "10G"
# Create quota filesystem overlay
local quota_img="/var/lib/ftp_quotas/$(basename "$mount_point").img"
sudo mkdir -p /var/lib/ftp_quotas
sudo dd if=/dev/zero of="$quota_img" bs=1 count=0 seek="$max_size"
sudo mkfs.ext4 "$quota_img"
# Mount with quota support
local quota_mount="/mnt/quota_$(basename "$mount_point")"
sudo mkdir -p "$quota_mount"
sudo mount -o loop,usrquota,grpquota "$quota_img" "$quota_mount"
# Set up quotas
sudo quotacheck -cug "$quota_mount"
sudo quotaon "$quota_mount"
# Bind mount over FTP mount
sudo mount --bind "$quota_mount" "$mount_point"
}
Troubleshooting and Diagnostics
Common Issues and Solutions
#!/bin/bash
# Comprehensive FTP mount troubleshooting toolkit
# Diagnostic function
diagnose_ftp_mount() {
local mount_point="$1"
echo "FTP Mount Diagnostics"
echo "===================="
# Check if mount point exists
if [[ ! -d "$mount_point" ]]; then
echo "✗ Mount point does not exist"
return 1
fi
# Check if mounted
if ! mountpoint -q "$mount_point"; then
echo "✗ Mount point is not mounted"
# Check FUSE
if ! lsmod | grep -q fuse; then
echo " → FUSE module not loaded"
echo " → Run: sudo modprobe fuse"
fi
# Check user permissions
if ! groups | grep -q fuse; then
echo " → User not in fuse group"
echo " → Run: sudo usermod -a -G fuse $USER"
fi
return 1
fi
echo "✓ Mount point is active"
# Check accessibility
echo -n "Checking accessibility: "
if timeout 5 ls "$mount_point" >/dev/null 2>&1; then
echo "✓ Accessible"
else
echo "✗ Not accessible"
# Check network connectivity
local ftp_host=$(mount | grep "$mount_point" | grep -oP 'ftp://[^@]+@\K[^/]+')
if [[ -n "$ftp_host" ]]; then
echo -n " → Testing FTP host connectivity: "
if nc -zv "$ftp_host" 21 -w 5 >/dev/null 2>&1; then
echo "✓ Host reachable"
else
echo "✗ Host unreachable"
fi
fi
fi
# Check performance
echo -n "Testing read performance: "
local start_time=$(date +%s.%N)
if dd if="$mount_point/testfile" of=/dev/null bs=1M count=1 >/dev/null 2>&1; then
local end_time=$(date +%s.%N)
local duration=$(echo "$end_time - $start_time" | bc)
echo "✓ ${duration}s"
else
echo "✗ Read test failed"
fi
# Check logs
echo ""
echo "Recent errors in system log:"
sudo journalctl -u ftp-mounts.service --since "10 minutes ago" | grep -i error | tail -5
}
# Fix common mount issues
fix_mount_issues() {
local mount_point="$1"
echo "Attempting to fix mount issues..."
# Force unmount if hung
if mountpoint -q "$mount_point"; then
echo "Force unmounting..."
sudo umount -l "$mount_point" 2>/dev/null || sudo fusermount -uz "$mount_point"
sleep 2
fi
# Clean up mount point
sudo rm -rf "$mount_point"/.fuse_hidden*
# Reload FUSE
sudo modprobe -r fuse
sudo modprobe fuse
# Reset permissions
sudo chmod 755 "$mount_point"
echo "✓ Cleanup complete"
}
# Performance analysis
analyze_mount_performance() {
local mount_point="$1"
local test_file="$mount_point/.perftest"
echo "FTP Mount Performance Analysis"
echo "=============================="
# Write test
echo "Write Test (10MB):"
dd if=/dev/zero of="$test_file" bs=1M count=10 conv=fsync 2>&1 | grep -v records
# Read test
echo ""
echo "Read Test (10MB):"
dd if="$test_file" of=/dev/null bs=1M 2>&1 | grep -v records
# Latency test
echo ""
echo "Latency Test (small file operations):"
local start_time=$(date +%s.%N)
for i in {1..100}; do
touch "$mount_point/.latency_test_$i"
rm -f "$mount_point/.latency_test_$i"
done
local end_time=$(date +%s.%N)
local total_time=$(echo "$end_time - $start_time" | bc)
local avg_time=$(echo "scale=4; $total_time / 100" | bc)
echo "Average operation time: ${avg_time}s"
# Clean up
rm -f "$test_file"
}
# Debug mode mounting
debug_mount() {
local ftp_url="$1"
local mount_point="$2"
echo "Mounting in debug mode..."
# Enable curl verbose output
export CURLFTPFS_DEBUG=2
# Mount with debug options
curlftpfs "$ftp_url" "$mount_point" \
-o debug \
-o verbose \
-o log_level=7 \
-f # Run in foreground
}
Monitoring and Alerting
#!/bin/bash
# FTP mount monitoring and alerting system
# Create monitoring script
cat > /usr/local/bin/ftp-mount-monitor << 'SCRIPT'
#!/bin/bash
# FTP Mount Monitoring System
# Monitors mount health and sends alerts
# Configuration
ALERT_EMAIL="admin@example.com"
SLACK_WEBHOOK=""
CHECK_INTERVAL=300 # 5 minutes
ALERT_THRESHOLD=3 # Number of failures before alert
# State tracking
declare -A failure_count
# Check single mount health
check_mount_health() {
local name="$1"
local mount_point="$2"
# Check if mounted
if ! mountpoint -q "$mount_point"; then
return 1
fi
# Check accessibility
if ! timeout 10 ls "$mount_point" >/dev/null 2>&1; then
return 2
fi
# Check free space
local usage=$(df "$mount_point" | tail -1 | awk '{print $5}' | sed 's/%//')
if [[ $usage -gt 90 ]]; then
return 3
fi
return 0
}
# Send alert
send_alert() {
local name="$1"
local mount_point="$2"
local error_type="$3"
local message="FTP Mount Alert: $name\n"
message+="Mount Point: $mount_point\n"
message+="Error: $error_type\n"
message+="Time: $(date)\n"
message+="Host: $(hostname)\n"
# Email alert
if [[ -n "$ALERT_EMAIL" ]]; then
echo -e "$message" | mail -s "FTP Mount Alert: $name" "$ALERT_EMAIL"
fi
# Slack alert
if [[ -n "$SLACK_WEBHOOK" ]]; then
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"$message\"}" \
"$SLACK_WEBHOOK"
fi
# Log alert
logger -t ftp-mount-monitor "$message"
}
# Monitor loop
monitor_loop() {
while IFS='|' read -r name host user pass mount_point options; do
[[ "$name" =~ ^#.*$ ]] && continue
[[ -z "$name" ]] && continue
check_mount_health "$name" "$mount_point"
health_status=$?
case $health_status in
0)
# Healthy - reset failure count
failure_count[$name]=0
;;
1)
# Not mounted
((failure_count[$name]++))
if [[ ${failure_count[$name]} -ge $ALERT_THRESHOLD ]]; then
send_alert "$name" "$mount_point" "Mount not active"
failure_count[$name]=0
fi
;;
2)
# Not accessible
((failure_count[$name]++))
if [[ ${failure_count[$name]} -ge $ALERT_THRESHOLD ]]; then
send_alert "$name" "$mount_point" "Mount not accessible"
failure_count[$name]=0
fi
;;
3)
# Low space
send_alert "$name" "$mount_point" "Low disk space (>90% used)"
;;
esac
done < /etc/ftpmount/mounts.conf
}
# Main monitoring loop
while true; do
monitor_loop
sleep "$CHECK_INTERVAL"
done
SCRIPT
chmod +x /usr/local/bin/ftp-mount-monitor
# Create systemd service for monitoring
sudo tee /etc/systemd/system/ftp-mount-monitor.service << 'EOF'
[Unit]
Description=FTP Mount Health Monitor
After=ftp-mounts.service
[Service]
Type=simple
ExecStart=/usr/local/bin/ftp-mount-monitor
Restart=always
RestartSec=60
[Install]
WantedBy=multi-user.target
EOF
# Enable monitoring
sudo systemctl enable ftp-mount-monitor.service
sudo systemctl start ftp-mount-monitor.service
Integration with Other Systems
Docker Integration
#!/bin/bash
# Docker volume driver for FTP mounts
# Create Docker volume plugin
cat > /usr/local/bin/docker-ftp-volume-driver << 'SCRIPT'
#!/bin/bash
# Docker FTP Volume Driver
# Provides FTP mounts as Docker volumes
VOLUME_ROOT="/var/lib/docker-ftp-volumes"
CONFIG_FILE="/etc/docker-ftp/volumes.conf"
# Create volume
create_volume() {
local volume_name="$1"
local ftp_url="$2"
local mount_point="$VOLUME_ROOT/$volume_name"
mkdir -p "$mount_point"
# Mount FTP
curlftpfs "$ftp_url" "$mount_point" -o allow_other,uid=0,gid=0
# Return mount point
echo "$mount_point"
}
# Remove volume
remove_volume() {
local volume_name="$1"
local mount_point="$VOLUME_ROOT/$volume_name"
fusermount -u "$mount_point"
rmdir "$mount_point"
}
# Docker Compose example
cat > docker-compose-ftp-example.yml << 'EOF'
version: '3.8'
services:
app:
image: nginx:alpine
volumes:
- type: bind
source: /var/lib/docker-ftp-volumes/remote-data
target: /usr/share/nginx/html
read_only: true
ftp-mounter:
image: alpine
privileged: true
command: |
sh -c '
apk add --no-cache curlftpfs
mkdir -p /mnt/ftp
curlftpfs ftp://user:pass@ftp.example.com /mnt/ftp
tail -f /dev/null
'
volumes:
- /var/lib/docker-ftp-volumes:/mnt:shared
EOF
SCRIPT
chmod +x /usr/local/bin/docker-ftp-volume-driver
Kubernetes PersistentVolume Integration
# FTP PersistentVolume for Kubernetes
apiVersion: v1
kind: PersistentVolume
metadata:
name: ftp-pv
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: ftp-storage
flexVolume:
driver: "example.com/ftp"
options:
server: "ftp.example.com"
path: "/data"
username: "ftpuser"
password: "ftppass"
---
# DaemonSet for FTP mount provisioner
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ftp-mount-provisioner
namespace: kube-system
spec:
selector:
matchLabels:
name: ftp-mount-provisioner
template:
metadata:
labels:
name: ftp-mount-provisioner
spec:
hostNetwork: true
containers:
- name: ftp-mounter
image: alpine:latest
securityContext:
privileged: true
command:
- sh
- -c
- |
apk add --no-cache curlftpfs
mkdir -p /mnt/ftp
curlftpfs ftp://user:pass@ftp.example.com /mnt/ftp -o allow_other
while true; do
sleep 3600
if ! mountpoint -q /mnt/ftp; then
curlftpfs ftp://user:pass@ftp.example.com /mnt/ftp -o allow_other
fi
done
volumeMounts:
- name: host-mnt
mountPath: /mnt
mountPropagation: Bidirectional
volumes:
- name: host-mnt
hostPath:
path: /mnt
This comprehensive guide provides enterprise-level knowledge for mounting FTP sites as local folders in Linux, covering everything from basic installation to advanced performance optimization, security hardening, and container integration strategies.