Skip to main content

Overview

Lightd includes a built-in SFTP server that provides secure file access to container volumes. Each container gets isolated SFTP access to its volume directory with automatic credential management.

Features

Secure Protocol

SSH File Transfer Protocol (SFTP) version 3

Automatic Credentials

Auto-generated or custom username/password

Path Isolation

Chrooted to container volume directory

Compatible Clients

Works with FileZilla, WinSCP, VS Code, and more

Specifications

  • Protocol: SSH File Transfer Protocol (SFTP) version 3
  • Port: 2022 (configurable in config.json)
  • Authentication: Username/password (bcrypt hashed)
  • Isolation: Each session is chrooted to the container’s volume directory
  • Security: No access to host filesystem or other containers

Supported Operations

File Operations
  • Read, write, create, delete, rename
Directory Operations
  • List, create, delete, navigate
File Attributes
  • Size, permissions, timestamps
Path Resolution
  • realpath, stat, lstat, fstat

Generate SFTP Credentials

Create or reset SFTP credentials for a container.
curl -X POST http://localhost:8070/containers/my-container/sftp/credentials \
  -H "Authorization: Bearer lightd_token" \
  -H "Accept: Application/vnd.pkglatv1+json" \
  -H "Content-Type: application/json" \
  -d '{}'
Request Body:
{
  "username": "custom_user",  // Optional: auto-generated if not provided
  "password": "custom_pass"   // Optional: auto-generated if not provided
}
Response:
{
  "username": "sftp_abc123",
  "password": "generated_secure_password",
  "host": "0.0.0.0",
  "port": 2022,
  "volume_path": "/home/container"
}

Get SFTP Connection Info

Retrieve existing SFTP credentials for a container.
curl -X GET http://localhost:8070/containers/my-container/sftp/info \
  -H "Authorization: Bearer lightd_token" \
  -H "Accept: Application/vnd.pkglatv1+json"
Response:
{
  "username": "sftp_abc123",
  "host": "0.0.0.0",
  "port": 2022,
  "volume_path": "/home/container",
  "created_at": 1706659200,
  "updated_at": 1706659200
}

Connecting with Clients

Command Line (sftp)

1

Remove old host key (if reconnecting)

ssh-keygen -R "[0.0.0.0]:2022"
2

Connect with SFTP

sftp -P 2022 username@0.0.0.0
3

Or use SCP to copy files

scp -P 2022 localfile.txt username@0.0.0.0:/remote/path/

FileZilla

1

Open Site Manager

File → Site Manager → New Site
2

Configure connection

  • Protocol: SFTP - SSH File Transfer Protocol
  • Host: 0.0.0.0 (or your server IP)
  • Port: 2022
  • Logon Type: Normal
  • User: Your SFTP username
  • Password: Your SFTP password
3

Connect

Click “Connect” button

VS Code Remote

1

Install extension

Install “Remote - SSH” extension
2

Add SSH config

Add to ~/.ssh/config:
Host my-container
    HostName 0.0.0.0
    Port 2022
    User your_username
3

Connect

Ctrl+Shift+P → “Remote-SSH: Connect to Host” → “my-container”

WinSCP

1

Create new session

Click “New Session”
2

Configure

  • File protocol: SFTP
  • Host name: 0.0.0.0
  • Port number: 2022
  • User name: Your SFTP username
  • Password: Your SFTP password
3

Login

Click “Login”

SFTP Commands

Once connected, you can use standard SFTP commands:
pwd                    # Print working directory
ls                     # List files
cd directory           # Change directory
cd ..                  # Go up one level

File Operations

get remote.txt         # Download file
put local.txt          # Upload file
get -r folder/         # Download directory recursively
put -r folder/         # Upload directory recursively

File Management

mkdir newfolder        # Create directory
rmdir emptyfolder      # Remove empty directory
rm file.txt            # Delete file
rename old.txt new.txt # Rename file

Information

stat file.txt          # Show file attributes
lstat link             # Show link attributes

Exit

bye                    # Disconnect
exit                   # Disconnect
quit                   # Disconnect

Configuration

Edit config.json to configure SFTP settings:
{
  "sftp": {
    "enabled": true,
    "port": 2022,
    "host": "0.0.0.0"
  }
}
Configuration Fields:
  • enabled - Enable/disable SFTP server
  • port - SFTP server port (default: 2022)
  • host - Bind address (default: 0.0.0.0)

Security

Credential Storage

Passwords are hashed using bcrypt with cost factor 10 for secure storage.
Credentials stored in Sled database: storage/sftp_credentials
Each container has unique credentials for isolation.

Path Isolation

  • Sessions are chrooted to container volume directory
  • Path traversal attempts are blocked
  • No access to:
    • Host filesystem
    • Other container volumes
    • Lightd configuration files

Network Security

  • SFTP runs on non-standard port (2022) to avoid conflicts
  • SSH protocol provides encryption in transit
  • Host key generated on startup (ED25519)

Troubleshooting

Problem: FileZilla or other clients timeout after 20 secondsSolution:
  • Check that lightd is running: make run
  • Verify SFTP is enabled in config.json
  • Check firewall allows port 2022
  • Try CLI first: sftp -P 2022 user@host
Problem: WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!Solution: Remove old host key:
ssh-keygen -R "[0.0.0.0]:2022"
Problem: Cannot read/write filesSolution:
  • Verify credentials are correct
  • Check container volume exists
  • Ensure volume has proper permissions
Problem: cd command shows “stat remote: Operation unsupported”Solution: Update to latest version where STAT/LSTAT are properly implemented.

Implementation Details

Architecture

Client (FileZilla, VS Code, etc.)

         │ SSH/SFTP Protocol (Port 2022)

    SFTP Server (russh)

         ├─► Session Handler
         │   ├─ Authentication
         │   ├─ Packet Parsing
         │   └─ Response Generation

         ├─► Protocol Handler
         │   ├─ File Operations
         │   ├─ Directory Operations
         │   └─ Path Resolution

         ├─► Credentials DB (Sled)
         │   └─ Bcrypt Hashed Passwords

         └─► Container Volume
             └─ /storage/volumes/{volume-uuid}/

Supported SFTP Packets

TypeNameDescription
1SSH_FXP_INITProtocol initialization
2SSH_FXP_VERSIONVersion response
3SSH_FXP_OPENOpen file
4SSH_FXP_CLOSEClose file/directory
5SSH_FXP_READRead from file
6SSH_FXP_WRITEWrite to file
7SSH_FXP_STATGet file attributes (follows symlinks)
8SSH_FXP_LSTATGet file attributes (no symlink follow)
9SSH_FXP_FSTATGet attributes by handle
11SSH_FXP_OPENDIROpen directory
12SSH_FXP_READDIRRead directory entries
13SSH_FXP_REMOVEDelete file
14SSH_FXP_MKDIRCreate directory
15SSH_FXP_RMDIRRemove directory
16SSH_FXP_REALPATHCanonicalize path
18SSH_FXP_RENAMERename file/directory

File Permissions

Files and directories are created with standard Unix permissions:
  • Files: 0o100644 (rw-r—r—)
  • Directories: 0o040755 (rwxr-xr-x)

Performance

  • Window Size: 2MB for efficient large file transfers
  • Packet Size: 32KB maximum
  • Timeout: 5 minutes of inactivity
  • Concurrent Sessions: Unlimited (one per container)

Complete Example

// Generate SFTP credentials for a container
const generateSFTPAccess = async (containerId) => {
  // Generate credentials
  const response = await fetch(`http://localhost:8070/containers/${containerId}/sftp/credentials`, {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer lightd_token',
      'Accept': 'Application/vnd.pkglatv1+json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({})
  });
  
  const credentials = await response.json();
  
  console.log('SFTP Access Created:');
  console.log(`Host: ${credentials.host}`);
  console.log(`Port: ${credentials.port}`);
  console.log(`Username: ${credentials.username}`);
  console.log(`Password: ${credentials.password}`);
  console.log(`\nConnect with:`);
  console.log(`sftp -P ${credentials.port} ${credentials.username}@${credentials.host}`);
  
  return credentials;
};

// Get existing SFTP info
const getSFTPInfo = async (containerId) => {
  const response = await fetch(`http://localhost:8070/containers/${containerId}/sftp/info`, {
    headers: {
      'Authorization': 'Bearer lightd_token',
      'Accept': 'Application/vnd.pkglatv1+json'
    }
  });
  
  const info = await response.json();
  console.log('SFTP Info:', info);
  
  return info;
};

// Usage
const containerId = 'my-container';
await generateSFTPAccess(containerId);
await getSFTPInfo(containerId);

Future Enhancements

  • Public key authentication
  • Symbolic link support
  • File locking
  • Resume interrupted transfers
  • Bandwidth limiting
  • Connection logging and auditing
  • Two-factor authentication
  • IP whitelisting

Compatible Clients

FileZilla

Free, cross-platform FTP/SFTP client

WinSCP

Windows SFTP and FTP client

Cyberduck

macOS and Windows file transfer client

VS Code

Remote development via SSH

JetBrains

Gateway for remote development

Command Line

sftp, scp, rsync