rain ====
High-performance BitTorrent client and library in Go. Running in production at [put.io][putio-link] since 2019, processing thousands of torrents daily with minimal system resources.
![GoDoc][docs-link]
Features --------
Protocol Support
- BEP-003: Core protocol
- BEP-006: Fast extension
- BEP-009: Magnet links
- BEP-012: Multiple trackers
- BEP-015: UDP trackers
- BEP-005: DHT
- BEP-011: PEX
- BEP-019: WebSeed
- Message stream encryption
Client Features
- Fast resuming with BoltDB persistence
- Sequential downloading for streaming
- IP blocklist support
- JSON-RPC 2.0 server & client
- Interactive console UI
- Tools for creating & reading .torrent files
- Resource management (connections, memory, file handles)
Installing ----------
macOS
brew install cenkalti/rain/rain
Other Platforms
Download the latest binary from the releases page.From Source
go install github.com/cenkalti/rain/v2@latest
Quick Start -----------
Rain operates as a client-server application with a single binary.
1. Start the Server
# Start Rain server (using default config)
rain server
2. Add Your First Torrent
# Add a magnet link
rain client add "magnet:?xt=urn:btih:..."
Or add a torrent file
rain client add /path/to/file.torrent
Or add torrent from URL
rain client add "https://example.com/file.torrent"
3. Monitor Progress
# List all torrents
rain client list
Get stats for a torrent
rain client stats --id <torrent-id>
Watch progress in console UI
rain client console
4. Control Downloads
# Pause a torrent
rain client stop --id <torrent-id>
Resume a torrent
rain client start --id <torrent-id>
Remove completed torrent
rain client remove --id <torrent-id>
Use rain help or rain help for detailed information.
Usage as library ----------------
Rain can be embedded in Go applications as a powerful BitTorrent library.
import "github.com/cenkalti/rain/v2/torrent"
// Create session with default config
ses, _ := torrent.NewSession(torrent.DefaultConfig)
defer ses.Close()
// Add a magnet link
magnetLink := "magnet:?xt=urn:btih:..."
tor, _ := ses.AddURI(magnetLink, nil)
// Monitor download progress
for range time.Tick(time.Second) {
s := tor.Stats()
log.Printf("Status: %s, Downloaded: %d, Peers: %d", s.Status.String(), s.Bytes.Completed, s.Peers.Total)
}
More complete example can be found under handleDownload function at main.go file.
See [package documentation][docs-link] for complete API.
Configuration -------------
Rain works out of the box with sensible defaults, but can be customized with a YAML configuration file.
Basic Configuration
Default config location: ~/rain/config.yaml (defaults are used if file is missing)
Custom config:
rain server --config /path/to/config.yaml
Complete Reference
For all available configuration options, see config.go.
Note: Configuration keys use dash-separated format (e.g., port-begin, not portbegin) starting from v2.
Architecture ------------
Rain's architecture is designed specifically for high-performance server environments, with several unique characteristics:
Unique Design Decisions
Separate Port Per Torrent: Unlike other BitTorrent clients, Rain allocates a separate peer port for each torrent. This enables:
- Multiple downloads of the same torrent for different accounts on private trackers
- Accurate ratio tracking per account
- Better isolation between torrents
- Optimized for hundreds of concurrent torrents
- Minimal system resource usage
- Production-ready stability (running at put.io since 2019)
- JSON-RPC API for remote management
Project Structure
rain/
├── torrent/ # Core BitTorrent session and torrent logic
├── rainrpc/ # Shared types for JSON-RPC 2.0 API
├── internal/ # Internal packages (networking, protocol, storage, etc.)
└── main.go # Entry point
Component Architecture
Rain follows a layered architecture with clear separation of concerns:
Core Layer:
torrent/session.go- Main orchestrator managing torrents, DHT, and shared resourcestorrent/torrent.go- Individual torrent lifecycle management
- BitTorrent protocol implementation (
internal/peerprotocol/) - Tracker communication (
internal/tracker/,internal/announcer/) - DHT and PEX support (
internal/dht/,internal/pex/)
- Connection management (
internal/peer/,internal/peerconn/) - Message Stream Encryption (
internal/mse/) - Resource limiting (
internal/resourcemanager/)
- Piece management (
internal/piece/,internal/piececache/) - File I/O optimization (
internal/storage/) - Resume data persistence with BoltDB
The following features are not implemented in Rain. This list should not be considered a roadmap, as these features are intentionally omitted either because they don't provide sufficient value for our use case at [put.io][putio-link], or because implementing them would add unnecessary complexity to the codebase. We prefer to maintain a focused and efficient implementation that serves our specific needs.
- BEP-007: IPv6 tracker extension
- BEP-032: IPv6 extension for DHT
- BEP-029: uTorrent transport protocol
- BEP-016: Superseeding
- BEP-017: HTTP seeding
- BEP-030: Merkle tree torrent extension
- uPnP port forwarding
- Selective downloading
Rain is primarily developed to serve the specific requirements of [put.io][putio-link]. Due to this focused purpose, feature requests that do not align with put.io's needs will likely be rejected. Additionally, we maintain a strong preference for simplicity in implementation. Complex solutions, even if technically superior, will generally not be accepted. Please keep these guidelines in mind when submitting issues or pull requests.
Star History ------------
[putio-link]: https://put.io [docs-link]: https://pkg.go.dev/github.com/cenkalti/rain/v2/torrent