Skip to main content

s3syncy

Tests PyPI version License: MIT

Cross-platform, multithreaded S3 file synchronisation daemon.

Features

  • Continuous sync — watches directories for changes in real-time (via watchdog) and runs periodic full scans as a safety net.
  • Daemon controls — start in background and control with stop, pause, resume, reload, daemon-status.
  • Multithreaded — configurable thread pool for parallel uploads/downloads.
  • Bandwidth throttling — token-bucket rate limiter (upload & download independently).
  • Resource-friendly — chunked streaming (no full-file buffering), optional soft memory cap, bounded thread pool.
  • Configurable — single config.yaml controls everything (S3 target, threads, bandwidth, conflict strategy, integrity, logging).
  • Gitignore-style exclusions.syncignore file uses the same pattern syntax as .gitignore.
  • Auto-reload — config and exclusion files are reloaded automatically on change.
  • Searchable local index — SQLite metadata database with full-text search on file paths and folder-prefix listing.
  • Conflict resolutionlocal_wins, remote_wins, newest_wins, or skip — with optional .bak backup before overwriting.
  • Remote delete self-heal — if an object is deleted directly from S3 but still exists locally, daemon restores it on the next scan.
  • Integrity checks — post-upload hash verification (MD5 via S3 ETag, or SHA256). Configurable reaction: warn, retry, or delete_remote.
  • Cross-platform — macOS, Linux, Windows (Python 3.10+).

Quick Start

# Install from PyPI
pip install s3syncy

# Initialize configuration
s3syncy init

# Edit config.yaml with your S3 bucket and sync directories
# Then run:
s3syncy start -c config.yaml --background

# Check status
s3syncy status -c config.yaml

CLI Commands

Command Description
s3syncy start -c config.yaml Start the sync daemon
s3syncy start -c config.yaml --background Start daemon in background
s3syncy stop -c config.yaml Stop background daemon
s3syncy pause -c config.yaml Pause syncing (daemon stays alive)
s3syncy resume -c config.yaml Resume syncing after pause
s3syncy reload -c config.yaml Reload config + exclusions immediately
s3syncy daemon-status -c config.yaml Show daemon PID/running/state info
s3syncy search "report" -c config.yaml Search the index for files matching "report"
s3syncy ls "photos/2024" -c config.yaml List synced files under a path prefix
s3syncy pull "docs/file.pdf" ./local.pdf -c config.yaml Download a single file from S3
s3syncy status -c config.yaml Show index statistics (total files, synced count, total size)
s3syncy init Create starter config.yaml and .syncignore

Configuration

See config.yaml for full documentation. Key settings:

sync_dirs:
  - ~/Documents/sync
  - ~/Desktop/uploads

s3:
  bucket: "my-bucket"
  prefix: "backups"
  region: "us-east-1"

threads: 4
scan_interval_seconds: 300

bandwidth:
  upload_limit_mbps: 10    # 0 = unlimited
  download_limit_mbps: 0

conflict:
  strategy: "newest_wins"  # local_wins | remote_wins | newest_wins | skip
  backup_before_overwrite: true

integrity:
  enabled: true
  algorithm: "md5"         # md5 | sha256
  on_failure: "warn"       # warn | retry | delete_remote

When multiple sync_dirs are configured, one daemon handles all of them.
S3 keys are namespaced per root (for example Documents/file.txt, uploads-2/file.txt) to avoid collisions.

.syncignore

Works exactly like .gitignore:

# OS junk
.DS_Store
Thumbs.db

# Build artefacts
node_modules/
__pycache__/
*.pyc

# Secrets
.env
*.pem

Signals (Unix)

  • SIGINT / SIGTERM — graceful shutdown (finish in-flight transfers, close index).
  • SIGHUP — reload config and exclusions.
  • SIGUSR1 — pause syncing.
  • SIGUSR2 — resume syncing.

Architecture

┌─────────────┐     events      ┌─────────────┐    ThreadPool    ┌──────────┐
│  watchdog   │ ──────────────▸ │   watcher   │ ──────────────▸ │  engine  │
│  (OS-level) │   debounced     │  (handler)  │   submit tasks   │ (upload/ │
└─────────────┘                 └──────┬──────┘                  │ download)│
                                       │                         └────┬─────┘
                          periodic     │                              │
                          full scan    ▼                              ▼
                                ┌─────────────┐              ┌──────────────┐
                                │   daemon    │              │   S3 (boto3) │
                                │ (main loop) │              │  + throttle  │
                                └─────────────┘              │  + integrity │
                                       │                     └──────────────┘
                                       ▼
                                ┌─────────────┐
                                │   SQLite    │
                                │   index     │
                                └─────────────┘

Development

Setup Development Environment

# Clone the repository
git clone https://github.com/mtahle/s3syncy.git
cd s3syncy

# Install in development mode
pip install -e .

# Install development dependencies
pip install -r requirements-dev.txt

Running Tests

# Run all tests
pytest

# Run with coverage
pytest --cov=s3syncy --cov-report=html

# Run only unit tests
pytest tests/unit -m unit

# Run specific test file
pytest tests/unit/test_config.py

Code Quality

# Format code
black s3syncy tests

# Sort imports
isort s3syncy tests

# Type checking
mypy s3syncy

# Linting
ruff check s3syncy tests

License

MIT

Download files

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

Source Distribution

s3syncy-1.1.0.tar.gz (40.5 kB view details)

Uploaded Source

Built Distribution

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

s3syncy-1.1.0-py3-none-any.whl (26.8 kB view details)

Uploaded Python 3

File details

Details for the file s3syncy-1.1.0.tar.gz.

File metadata

  • Download URL: s3syncy-1.1.0.tar.gz
  • Upload date:
  • Size: 40.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for s3syncy-1.1.0.tar.gz
Algorithm Hash digest
SHA256 e89ce50185aadea17c4934253a7fa6e19c3f778c19d13ef44ad3f99a9b5a04a2
MD5 633cac36fa0921c8c0ca1af0710d693c
BLAKE2b-256 38649d7ca67e01e2752b41f0d4de70b85001a549c7dea8ea67418611a58c6c98

See more details on using hashes here.

File details

Details for the file s3syncy-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: s3syncy-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 26.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for s3syncy-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 112d34a2372cb0b5f84b3a89297664bf13d1213381d1e28516338f0dc05f76ce
MD5 74b0f5f9ed81bdeda7590625525b6813
BLAKE2b-256 eaf8bf8d09e935a77624b857620ac0cb3066d2a7e5597179c93cbdfade5e3816

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