Skip to main content

A minimal bidirectional SCP server for network automation

Project description

TinySCP

A minimal, embeddable SCP server for network automation workflows.

PyPI version Python 3.9+ License: MIT

Why TinySCP?

There are plenty of SCP clients for Python, but no lightweight SCP server. TinySCP fills that gap—a simple, drop-in SCP server you can embed in your automation workflows or run standalone for:

  • Firmware staging — Network devices push/pull images
  • Config distribution — Centralized config server for network gear
  • File collection — Devices upload logs, captures, or backups
  • Lab environments — Quick file server without spinning up full SSH infrastructure

Installation

pip install tinyscp

For YAML config file support:

pip install tinyscp[yaml]

Quick Start

CLI Usage

# Generate a config file
tinyscp --init-config config.yaml

# Edit config.yaml to set your users, then run:
tinyscp

# Or run without config file:
tinyscp --no-config -u admin:secret -p 2222

Development Mode

If running from source without installing:

# Clone and setup
git clone https://github.com/scottpeterman/tinyscp.git
cd tinyscp
python -m venv .venv
source .venv/bin/activate  # Linux/macOS
# .venv\Scripts\activate   # Windows
pip install -e ".[yaml]"

# Run via module
python -m tinyscp.cli --help
python -m tinyscp.cli --init-config config.yaml
python -m tinyscp.cli -d

Client Usage

Modern macOS/Linux defaults to SFTP mode for scp. Use -O to force legacy SCP protocol:

# Upload to server
scp -O -P 2222 firmware.bin admin@server:/uploads/

# Download from server
scp -O -P 2222 admin@server:/downloads/startup-config.txt ./

Python API

from tinyscp import TinySCPServer

# Basic usage
server = TinySCPServer(
    port=2222,
    users={'admin': 'secret'},
    upload_dir='./uploads',
    download_dir='./downloads'
)
server.start()

# With callbacks for post-transfer actions
def on_upload(filepath, size, filename):
    print(f"Received {filename}, verifying checksum...")
    # Validate firmware, trigger deployment, etc.

server = TinySCPServer(
    port=2222,
    users={'admin': 'secret'},
    on_upload_complete=on_upload
)
server.start()

# Non-blocking mode
server.start(blocking=False)
# ... do other things ...
server.stop()

Configuration

Config File (YAML)

host: 0.0.0.0
port: 2222
host_key: ./tinyscp_host_key
upload_dir: ./uploads
download_dir: ./downloads
users:
  admin: changeme
  neteng: firmware123
  backup_svc: b4ckup!

CLI Options

usage: tinyscp [-h] [-d] [-p PORT] [-H HOST] [-c CONFIG] [--no-config]
               [--init-config FILE] [-u USER:PASS] [--upload-dir DIR]
               [--download-dir DIR] [--host-key FILE] [-v]

Options:
  -d, --debug           Enable debug output
  -p, --port PORT       Port to listen on (default: 2222)
  -H, --host HOST       Host to bind to (default: 0.0.0.0)
  -c, --config FILE     Path to YAML config file (default: config.yaml)
  --no-config           Ignore config file, use CLI args only
  --init-config FILE    Generate a default config file and exit
  -u, --user USER:PASS  Add user credentials (can be repeated)
  --upload-dir DIR      Directory for uploads (default: ./uploads)
  --download-dir DIR    Directory for downloads (default: ./downloads)
  --host-key FILE       Path to host key file
  -v, --version         Show version and exit

Features

  • Bidirectional transfers — Both upload (sink) and download (source) modes
  • Persistent host keys — No more "host key changed" warnings on restart
  • YAML configuration — Simple config file for users and settings
  • Callback hooks — Trigger actions on upload/download completion
  • Path traversal protection — Filenames are sanitized
  • Concurrent connections — Threaded client handling
  • Embeddable — Use as a library in your own applications
  • No dependencies — Just Paramiko (PyYAML optional for config files)

Security Considerations

TinySCP is designed for trusted network environments (labs, internal infrastructure, automation pipelines). It is not intended as a public-facing service.

  • Passwords are stored in plain text in config files
  • No rate limiting or brute-force protection
  • No chroot/jail for uploaded files (though path traversal is blocked)

For production use, consider:

  • Running behind a firewall
  • Using SSH key authentication (PR welcome!)
  • Restricting to specific source IPs

Contributing

Contributions welcome! Areas of interest:

  • SSH key authentication
  • SFTP subsystem support
  • Transfer progress callbacks
  • Recursive directory transfers
  • Upload size limits / quotas

License

MIT License - See LICENSE for details.

Author

Scott Peterman (@scottpeterman)

Part of the network automation toolkit alongside:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tinyscp-0.1.0.tar.gz (13.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tinyscp-0.1.0-py3-none-any.whl (12.5 kB view details)

Uploaded Python 3

File details

Details for the file tinyscp-0.1.0.tar.gz.

File metadata

  • Download URL: tinyscp-0.1.0.tar.gz
  • Upload date:
  • Size: 13.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for tinyscp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 883d690a7dcf4c940cbe84537d0bb2828586b5406c2e72a5b5dbe3d151255ce5
MD5 9ef78ac682f226d06e4b72c986292204
BLAKE2b-256 ba3bfdd3b1463c7fc3fdb17579f7b6c5cc4972a415713221faabff5f5242de78

See more details on using hashes here.

File details

Details for the file tinyscp-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: tinyscp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for tinyscp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 02578e8245367c9f93ae9eb129e24b1e7d27c70ff7b965cd2c9f89c57ecc48ef
MD5 b2dde1481abaa7b7a3ca6cd42174489e
BLAKE2b-256 44206df2d5126d66540a319e7d0b8251d389fade14f687717c2bb08568690879

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page