Appearance
Golang FTP Server 
This FTP server is a gateway between old-school FTP devices and modern cloud based file systems, using the afero's Fs interface and acting as a reference implementation of the ftpserverlib.
At the current stage, supported backend are:
- Local disk
 - S3 through afero-s3
 - Dropbox (see doc) through afero-dropbox
 - Google Drive (see doc) through afero-gdrive
 - SFTP through afero's sftpfs
 - Email through go-mail thanks to @x-way
 - Telegram through telebot by @slayer, see doc
 
And with those are supported common parameters to switch them to read-only, enable login access, or use a temporary directory file (see doc).
Current status of the project 
Features 
FTP protocol 
These features are brought by ftpserverlib itself:
- Uploading and downloading files
 - Directory listing (LIST + MLST)
 - File and directory deletion and renaming
 - TLS support (AUTH + PROT)
 - File download/upload resume support (REST)
 - Complete driver for all the above features
 - Passive socket connections (EPSV and PASV commands)
 - Active socket connections (PORT command)
 - Small memory footprint
 - Only relies on the standard library except for: 
- go-kit log for logging
 - afero for generic file systems handling
 
 - Supported extensions:
 
Getting started 
Get it 
Download it 
Fetch a binary from the latest release and run it.
Build & run it locally 
bash
go install github.com/fclairamb/ftpserver@main
ftpserver &Run it with docker 
There's also a containerized version of the server (31MB, based on alpine).
sh
# Creating a directory
mkdir -p files
# Starting the sample FTP server
docker run --rm -d -p 2121-2130:2121-2130 -v $(pwd)/files:/tmp -v $(pwd):/app fclairamb/ftpserverRun it with docker compose 
yml
# docker-compose.yml
version: '3.3'
services:
  ftpserver:
    ports:
      - '2121-2130:2121-2130'
    volumes:
      - ./files:/tmp
      - .:/app
    image: fclairamb/ftpserversh
docker-compose up -dTest it 
This is a quick way to see if it's working correctly:
sh
# Download some file
[ -f kitty.jpg ] || (curl -o kitty.jpg.tmp https://placekitten.com/2048/2048 && mv kitty.jpg.tmp kitty.jpg)
# Upload it to the server
curl -v -T kitty.jpg ftp://test:test@localhost:2121/
# Download it back
curl ftp://test:test@localhost:2121/kitty.jpg -o kitty2.jpg
# Compare it
diff kitty.jpg kitty2.jpgConfig file 
If you don't create a ftpserver.json file, one will be created for you.
Here is a sample config file:
json
{
   "version": 1,
   "passive_transfer_port_range": {
      "start": 2122,
      "end": 2130
   },
   "tls": {
      "server_cert": {
         "cert": "cert.pem",
         "key": "key.pem"
      }
   },
   "accesses": [
      {
         "user": "test",
         "pass": "test",
         "fs": "os",
         "params": {
            "basePath": "/tmp"
         }
      },
      {
         "user": "test",
         "pass": "test",
         "fs": "os",
         "params": {
            "basePath": "/tmp"
         }
      },
      {
         "user": "dropbox",
         "pass": "dropbox",
         "fs": "dropbox",
         "params": {
            "token": "..."
         }
      },
      {
         "user": "gdrive",
         "pass": "gdrive",
         "fs": "gdrive",
         "params": {
            "google_client_id": "***.apps.googleusercontent.com",
            "google_client_secret": "****",
            "base_path": "ftp"
         }
      },
      {
         "user": "s3",
         "pass": "s3",
         "fs": "s3",
         "params": {
            "endpoint": "https://s3.amazonaws.com",
            "region": "eu-west-1",
            "bucket": "my-bucket",
            "access_key_id": "AKIA....",
            "secret_access_key": "IDxd....",
            "disable_ssl": "false",
            "path_style": "false"
         }
      },
      {
         "user": "sftp",
         "pass": "sftp",
         "fs": "sftp",
         "params": {
            "username": "user",
            "password": "password",
            "hostname": "192.168.168.11:22"
         }
      },
      {
         "user": "telegram",
         "pass": "telegram",
         "fs": "telegram",
         "shared": true,
         "params": {
            "Token": "<OBTAIN_TOKEN_FROM_BOTFATHER>",
            "ChatID": "<INSERT_CHAT_ID_HERE>"
         }
      }
   ]
}You can generate the TLS key pair files with the following command:
bash
openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out cert.pem -keyout key.pem