FTP Settings Example¶
This example demonstrates how to configure FTP server settings on a Qumulo cluster using the qumulo_ftp_settings resource. This is a singleton resource that controls global FTP behavior for the cluster.
Features¶
The qumulo_ftp_settings resource configures:
- FTP enable/disable for the entire cluster
- FTPS (FTP over TLS) enforcement for encrypted connections
- Chroot to restrict users to their home directories
- Anonymous FTP access with user mapping
- Custom greeting messages
- FXP attack prevention via remote host checking
- Wildcard expansion for directory listings
Architecture¶
┌─────────────────────────────────────────────────────────────────────────────┐
│ FTP SETTINGS SCOPE │
└─────────────────────────────────────────────────────────────────────────────┘
QUMULO CLUSTER
┌─────────────────────────────────────────────────────────────────────────────┐
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ FTP SERVER SETTINGS │ │
│ │ qumulo_ftp_settings (singleton) │ │
│ │ │ │
│ │ • Enabled: true │ │
│ │ • FTPS Only: true (allow_unencrypted = false) │ │
│ │ • Chroot Users: true │ │
│ │ • Check Remote Host: true (FXP protection) │ │
│ │ • Greeting: "Welcome to Qumulo FTP Server" │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ FILESYSTEM │ │
│ │ │ │
│ │ /home/alice ◄──── alice (chrooted to home) │ │
│ │ /home/bob ◄──── bob (chrooted to home) │ │
│ │ /ftp/pub ◄──── anonymous -> ftp_anonymous (mapped user) │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
│ Ports: 21 (control), 989-990 (FTPS), 1024-65535 (passive data) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
│ │ │
│ FTPS (TLS) │ FTPS (TLS) │ FTPS (TLS)
│ │ │
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ FileZilla │ │ WinSCP │ │ lftp │
│ Client │ │ Client │ │ (Linux) │
│ │ │ │ │ │
└───────────┘ └───────────┘ └───────────┘
Prerequisites¶
- Qumulo cluster with REST API access (port 8000)
- Admin credentials for the cluster
Usage¶
- Create a
terraform.tfvarsfile:
cluster_endpoint = "https://cluster.example.com:8000"
cluster_username = "admin"
cluster_password = "cluster-admin-password"
# FTP settings
enable_ftp = true
chroot_users = true
allow_unencrypted = false # FTPS only
enable_anonymous = false
ftp_greeting = "Welcome to Qumulo FTP Server"
- Initialize and apply:
Variables¶
| Name | Description | Type | Default |
|---|---|---|---|
cluster_endpoint |
Qumulo cluster REST API endpoint | string |
- |
cluster_username |
Qumulo cluster admin username | string |
"admin" |
cluster_password |
Qumulo cluster admin password | string |
- |
enable_ftp |
Enable FTP connections to the cluster | bool |
true |
chroot_users |
Restrict users to their home directories | bool |
true |
allow_unencrypted |
Allow unencrypted FTP (false = FTPS only) | bool |
false |
enable_anonymous |
Enable anonymous FTP access | bool |
false |
anonymous_user |
Local user to map anonymous logins to | string |
"ftp_anonymous" |
ftp_greeting |
Custom greeting message for FTP clients | string |
"Welcome..." |
Outputs¶
| Name | Description |
|---|---|
ftp_enabled |
Whether FTP is enabled on the cluster |
ftp_encrypted_only |
Whether unencrypted connections are blocked |
ftp_chroot_enabled |
Whether users are chrooted to home directories |
ftp_greeting |
FTP server greeting message |
Configuration Examples¶
Secure FTPS Only¶
Maximum security with encrypted connections only:
resource "qumulo_ftp_settings" "secure" {
connection_profile = "cluster1"
enabled = true
chroot_users = true
greeting = "Secure FTP Server - TLS Required"
# Security settings
allow_unencrypted_connections = false # FTPS only
check_remote_host = true # Prevent FXP attacks
log_operations = true # Audit logging
# No anonymous access
anonymous_user {
id_type = "LOCAL_USER"
id_value = "nobody" # Placeholder, not used
}
}
Anonymous FTP (Read-Only Public)¶
For public file distribution:
resource "qumulo_ftp_settings" "anonymous" {
connection_profile = "cluster1"
enabled = true
chroot_users = true
greeting = "Public FTP Server - Anonymous Access Allowed"
# Allow unencrypted for wider compatibility
allow_unencrypted_connections = true
# Enable wildcard expansion for directory listings
expand_wildcards = true
# Map anonymous logins to a restricted local user
anonymous_user {
id_type = "LOCAL_USER"
id_value = "ftp_public" # Create this user with read-only permissions
}
}
Note: Ensure the mapped user (ftp_public) has appropriate read-only permissions on the public directory.
Legacy Compatibility¶
For environments requiring plain FTP:
resource "qumulo_ftp_settings" "legacy" {
connection_profile = "cluster1"
enabled = true
chroot_users = false # Allow full filesystem access
greeting = "FTP Server"
# Allow unencrypted (not recommended)
allow_unencrypted_connections = true
check_remote_host = false # Disable FXP check for legacy clients
log_operations = true
anonymous_user {
id_type = "LOCAL_USER"
id_value = "nobody"
}
}
Warning: This configuration has reduced security. Use only when absolutely necessary.
Disabled FTP¶
To completely disable FTP access:
resource "qumulo_ftp_settings" "disabled" {
connection_profile = "cluster1"
enabled = false
# Other settings are ignored when disabled
chroot_users = true
allow_unencrypted_connections = false
anonymous_user {
id_type = "LOCAL_USER"
id_value = "nobody"
}
}
Security Considerations¶
FTPS vs Plain FTP¶
| Aspect | Plain FTP | FTPS (TLS) |
|---|---|---|
| Credentials | Sent in clear text | Encrypted |
| Data transfer | Unencrypted | Encrypted |
| Man-in-the-middle | Vulnerable | Protected |
| Recommendation | Avoid | Recommended |
Always set allow_unencrypted_connections = false unless you have specific legacy requirements.
Chroot Security¶
- Enabled: Users can only access their home directory and below
- Disabled: Users can navigate the entire filesystem (subject to permissions)
Recommendation: Always enable chroot_users = true for multi-tenant environments.
FXP Attack Prevention¶
The check_remote_host setting prevents FXP (File eXchange Protocol) bounce attacks where an attacker uses your server to transfer files to a third party.
Recommendation: Keep check_remote_host = true unless you specifically need FXP functionality.
Anonymous Access Risks¶
When enabling anonymous FTP:
- Create a dedicated local user with minimal permissions
- Restrict the user's home directory to a specific public folder
- Set permissions to read-only if possible
- Monitor for abuse
Full Configuration¶
# Example: Managing FTP Settings on a Qumulo Cluster
#
# This example demonstrates how to configure FTP server settings
# on a Qumulo cluster using the qumulo_ftp_settings resource.
#
# The resource supports:
# - Enabling/disabling FTP connections
# - Chroot users to their home directories
# - Requiring encrypted connections (FTPS)
# - Anonymous FTP access
# - Custom greeting messages
# - Wildcard expansion in LIST/NLST commands
#
# Note: This is a singleton resource - there is only one FTP
# configuration per cluster.
terraform {
required_providers {
qumulo = {
source = "qumulo-terraform-registry.s3.us-east-1.amazonaws.com/qumulo/qumulo"
version = "~> 1.0"
}
}
}
variable "cluster_endpoint" {
description = "Qumulo cluster REST API endpoint (e.g., https://cluster:8000)"
type = string
}
variable "cluster_username" {
description = "Qumulo cluster admin username"
type = string
default = "admin"
}
variable "cluster_password" {
description = "Qumulo cluster admin password"
type = string
sensitive = true
}
# Variables for FTP configuration
variable "enable_ftp" {
description = "Enable FTP connections to the cluster"
type = bool
default = true
}
variable "chroot_users" {
description = "Restrict users to their home directories"
type = bool
default = true
}
variable "allow_unencrypted" {
description = "Allow unencrypted FTP connections (set to false for FTPS only)"
type = bool
default = false
}
variable "enable_anonymous" {
description = "Enable anonymous FTP access"
type = bool
default = false
}
variable "anonymous_user" {
description = "Local user to map anonymous logins to (only used if enable_anonymous is true)"
type = string
default = "ftp_anonymous"
}
variable "ftp_greeting" {
description = "Custom greeting message for FTP clients"
type = string
default = "Welcome to Qumulo FTP Server"
}
# Define connection profile for the cluster
provider "qumulo" {
connection_profiles = [
{
name = "cluster1"
endpoint = var.cluster_endpoint
username = var.cluster_username
password = var.cluster_password
insecure_skip_verify = true # Required for clusters with self-signed certificates
}
]
}
# ------------------------------------------------------------------------------
# FTP Configuration
# ------------------------------------------------------------------------------
# Configure FTP server settings. The variables control:
# - allow_unencrypted: false = FTPS only (secure), true = allow plain FTP
# - enable_anonymous: whether to allow anonymous FTP logins
# - chroot_users: restrict users to their home directories
resource "qumulo_ftp_settings" "this" {
connection_profile = "cluster1"
# Core settings
enabled = var.enable_ftp
chroot_users = var.chroot_users
greeting = var.ftp_greeting
# Security settings
allow_unencrypted_connections = var.allow_unencrypted
check_remote_host = true # Prevent FXP attacks
# Logging
log_operations = true
# Enable wildcard expansion for directory listings (useful for anonymous)
expand_wildcards = var.enable_anonymous
# Anonymous user mapping (required by schema)
anonymous_user {
id_type = "LOCAL_USER"
id_value = var.anonymous_user
}
}
# Outputs
output "ftp_enabled" {
description = "Whether FTP is enabled on the cluster"
value = qumulo_ftp_settings.this.enabled
}
output "ftp_encrypted_only" {
description = "Whether unencrypted connections are blocked"
value = !qumulo_ftp_settings.this.allow_unencrypted_connections
}
output "ftp_chroot_enabled" {
description = "Whether users are chrooted to their home directories"
value = qumulo_ftp_settings.this.chroot_users
}
output "ftp_greeting" {
description = "FTP server greeting message"
value = qumulo_ftp_settings.this.greeting
}