ftpsrv

package
v0.44.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 25, 2026 License: MIT Imports: 40 Imported by: 0

Documentation

Overview

Package ftpsrv serves FTPS: filex, reached by the equipment that only ever learned one protocol.

Why, when SFTP already exists

The plan that scoped this work said "defer FTPS, revisit when a named counterparty cannot speak SFTP". The symmetry rule overrode that: filex has an FTP storage driver, so it can CONNECT to an FTP server — and a product that can connect to something it refuses to be is asymmetric by design. The audience is also real and cannot be argued with: scan-to-FTP multifunction printers, EDI counterparties, and lab equipment whose firmware was finished a decade ago.

The one non-negotiable

⚠⚠ TLS IS MANDATORY. Plain FTP sends the password in the clear and then sends the file in the clear after it. filex is a file server people keep their own things in; offering a protocol that publishes their credentials to anything on the path would be a defect no configuration flag makes acceptable. This server speaks FTPS (explicit TLS, `AUTH TLS`) and refuses everything else — a client that will not negotiate TLS is refused before it can send a password, not after.

The part that fails as a hang rather than an error

Passive mode is where FTP deployments break, and they break silently: the server replies with an address the client cannot reach and the client waits until it gives up. Neither side logs anything useful. So the passive port range and the advertised address are explicit configuration, and both are stated in the connection guide rather than left to be discovered.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// Enabled — FILEX_FTPS kill switch. OFF by default: it opens a control
	// port AND a range of data ports, which is not something to do for
	// somebody who did not ask.
	Enabled bool
	// Addr is the control channel's listen address (2121 by convention for an
	// application FTP server; 21 needs root on Linux).
	Addr string
	// PublicHost is the address passive-mode replies advertise.
	//
	// ⚠⚠ This is THE setting FTP deployments get wrong, and it fails as a hang
	// rather than an error: the server answers PASV with an address the client
	// cannot route to, and the client waits until it times out. Behind NAT or
	// in Docker it must be the address the CLIENT would use, which is not the
	// address the process sees. Empty means "answer with the control
	// connection's local address", which is right for a direct connection and
	// wrong behind NAT.
	PublicHost string
	// PassivePortMin/Max bound the data ports. They must be published in the
	// firewall and, in Docker, mapped one-for-one — a range that is open on the
	// server and closed at the edge is the same hang as a wrong PublicHost.
	PassivePortMin int
	PassivePortMax int
	// CertFile/KeyFile are the TLS material. Empty generates a self-signed pair
	// into CertDir — usable, and honestly labelled as such in the guide, since
	// most FTPS clients will not verify a certificate they were not given.
	CertFile string
	KeyFile  string
	CertDir  string
	// Banner is the greeting. Some equipment logs it, nothing parses it.
	Banner string
	// IdleTimeout in seconds. FTP holds a control connection open between
	// commands, so an unbounded one is a socket leak with a login attached.
	IdleTimeout int

	Store    db.Store
	Auth     *protocolauth.Resolver
	ACL      *acl.Resolver
	Resolver func(int64) (storage.Driver, error)
	Body     *filebody.Resolver
	Quota    *quota.Service
	Index    *search.Index
	Thumbs   *thumb.Pipeline
	// SpoolDir is where uploads are spooled before they are committed.
	SpoolDir string
	// MaxSpool caps one upload. 0 uses defaultMaxSpool.
	MaxSpool    int64
	MultiTenant bool
}

Config wires the server to the shared services.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is a running FTPS endpoint.

func New

func New(cfg Config) (*Server, error)

New builds a server. It does not listen yet.

func (*Server) Addr

func (s *Server) Addr() string

Addr is the address actually bound.

func (*Server) Close

func (s *Server) Close() error

Close stops the listener.

func (*Server) ListenAndServe

func (s *Server) ListenAndServe() error

ListenAndServe blocks until Close.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL