
File Transfer
Move files to and from any agent in your mesh. Grab a config file from a remote server, deploy scripts to multiple machines, or exfiltrate data through your tunnel.
# Download a file from a remote agent
muti-metroo download abc123 /etc/passwd ./passwd.txt
# Upload a script to a remote agent
muti-metroo upload abc123 ./deploy.sh /tmp/deploy.sh
# Transfer entire directories
muti-metroo upload abc123 ./tools /opt/tools
See File Transfer Configuration for all options including path restrictions, size limits, and authentication.
CLI Usage
Upload File
muti-metroo upload <agent-id> <local-path> <remote-path>
# Example
muti-metroo upload abc123 ./data.bin /tmp/data.bin
Upload Directory
muti-metroo upload abc123 ./mydir /tmp/mydir
Download File
muti-metroo download <agent-id> <remote-path> <local-path>
# Example
muti-metroo download abc123 /etc/config.yaml ./config.yaml
With Authentication
muti-metroo upload -p password abc123 ./file.txt /tmp/file.txt
HTTP API
Upload
POST /agents/{agent-id}/file/upload
Multipart form data:
file: File to uploadpath: Remote destination pathpassword: Auth password (optional)directory: "true" if directory tar
Download
POST /agents/{agent-id}/file/download
Request:
{
"password": "secret",
"path": "/tmp/file.txt"
}
Response: Binary file data
File Browsing
Browse the filesystem on remote agents. Uses the same allowed_paths and authentication as file transfer -- no additional configuration needed.
# List directory contents
curl -X POST http://localhost:8080/agents/abc123/file/browse \
-H "Content-Type: application/json" \
-d '{"action":"list","path":"/tmp"}'
# Get info about a specific file
curl -X POST http://localhost:8080/agents/abc123/file/browse \
-H "Content-Type: application/json" \
-d '{"action":"stat","path":"/tmp/config.yaml"}'
# Discover browsable root paths
curl -X POST http://localhost:8080/agents/abc123/file/browse \
-H "Content-Type: application/json" \
-d '{"action":"roots"}'
# Change file permissions
curl -X POST http://localhost:8080/agents/abc123/file/browse \
-H "Content-Type: application/json" \
-d '{"action":"chmod","path":"/tmp/script.sh","mode":"0755"}'
# Delete a file
curl -X POST http://localhost:8080/agents/abc123/file/browse \
-H "Content-Type: application/json" \
-d '{"action":"delete","path":"/tmp/old-config.yaml"}'
# Delete a non-empty directory
curl -X POST http://localhost:8080/agents/abc123/file/browse \
-H "Content-Type: application/json" \
-d '{"action":"delete","path":"/tmp/old-logs","recursive":true}'
The list action supports pagination with offset and limit parameters (default limit: 100, max: 200). Entries are sorted with directories first, then files, alphabetically by name. The delete action removes files and empty directories directly; non-empty directories require "recursive": true.
See API - File Transfer for full request/response details.
Implementation Details
- Streaming: Files transferred in 16KB chunks
- No size limits: Stream directly without memory buffering
- Directories: Automatically tar/gzip with permission preservation
- Authentication: bcrypt password hashing
- Permissions: File mode preserved (Unix)
Rate Limiting
Limit transfer speed to avoid saturating network links.
# Upload at max 100 KB/s
muti-metroo upload --rate-limit 100KB abc123 ./large.iso /tmp/large.iso
# Download at max 1 MB/s
muti-metroo download --rate-limit 1MB abc123 /data/backup.tar.gz ./backup.tar.gz
Supported size formats:
- Decimal:
100KB,1MB,10GB(1 KB = 1000 bytes) - Binary:
100KiB,1MiB,10GiB(1 KiB = 1024 bytes) - Plain bytes:
1024000
Rate limiting is applied by the sending agent:
- Upload: Your local agent limits the upload speed
- Download: The remote agent limits the download speed
Resume Support
Continue interrupted transfers without starting over.
# Resume interrupted download
muti-metroo download --resume abc123 /data/large.iso ./large.iso
# Resume interrupted upload
muti-metroo upload --resume abc123 ./huge.iso /tmp/huge.iso
# Combine with rate limiting
muti-metroo download --rate-limit 500KB --resume abc123 /data/huge.iso ./huge.iso
How It Works
- Partial data is written to
<filename>.partial - Progress is tracked in
<filename>.partial.json - On resume, transfer continues from the last byte written
- On completion,
.partialis renamed to the final filename
Validation
Resume uses file size comparison to detect if the source file changed:
- If the original file size matches, transfer resumes from the offset
- If size differs, transfer restarts from the beginning
Resume is not supported for directory transfers. If a directory transfer is interrupted, it will restart from the beginning.
Troubleshooting
Permission Denied
Error: path not allowed: /etc/passwd
Cause: The path is not in the agent's allowed_paths configuration.
Solutions:
- Check the agent's
allowed_pathssetting - Use a path that's explicitly allowed
- Contact the agent administrator to add the path
Authentication Failed
Error: authentication required
Cause: The agent requires password authentication for file transfers.
Solution: Provide the password with -p:
muti-metroo upload -p mypassword abc123 ./file.txt /tmp/file.txt
File Too Large
Error: file exceeds maximum size limit
Cause: The file exceeds the agent's max_file_size setting.
Solutions:
- Check the size limit:
max_file_size: 0means unlimited - Split the file into smaller parts
- Contact the agent administrator to increase the limit
Agent Not Reachable
Error: no route to agent abc123
Cause: The target agent is not connected to the mesh or routes haven't propagated.
Solutions:
# Check if agent is known
curl http://localhost:8080/agents
# Verify connectivity
curl http://localhost:8080/healthz | jq '.peers'
Transfer Interrupted
If a transfer is interrupted, use --resume to continue:
# Resume from where it left off
muti-metroo download --resume abc123 /data/large.iso ./large.iso
Note: Resume is not supported for directory transfers.
Related
- CLI - File Transfer - CLI reference
- API - File Transfer - HTTP API reference
- Security - Access Control - Path restrictions
- Troubleshooting - Common Issues - File transfer issues