A previous release had provenance metadata, but this release does not. View details.
s3syncy
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.yamlcontrols everything (S3 target, threads, bandwidth, conflict strategy, integrity, logging). - Gitignore-style exclusions —
.syncignorefile 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 resolution —
local_wins,remote_wins,newest_wins, orskip— with optional.bakbackup 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, ordelete_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
Metadata
Release files for s3syncy 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Loss of provenance
These files do not have provenance metadata, despite files in a prior release including this data.
We recommend further investigation before installing these files. View details.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| s3syncy-1.2.0.tar.gz | 40.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| s3syncy-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 68.0 kB
Release files / s3syncy-1.2.0.tar.gz
Loss of provenance
This file belongs to a release without provenance metadata, despite a prior release including this data.
We recommend further investigation before installing this file. View details.
| Download URL | s3syncy-1.2.0.tar.gz |
|---|---|
| Size | 40.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
525c190222735eacd2b3bddab3fe8b19bc486dc181a7825f739042d8afe86344
|
|
BLAKE2b-256 checksum How to use checksums |
e6fbfe52ba785e2f25b54443ae72d7cf516e2939160a8f93cd29224fbe0b7615
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / s3syncy-1.2.0-py3-none-any.whl
Loss of provenance
This file belongs to a release without provenance metadata, despite a prior release including this data.
We recommend further investigation before installing this file. View details.
| Download URL | s3syncy-1.2.0-py3-none-any.whl |
|---|---|
| Size | 27.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
309ecb670dbc1132b55e79765abb642e61745b70cd7ae94c5d3fb93256254045
|
|
BLAKE2b-256 checksum How to use checksums |
f25fc08e82b9d0c48ab22c542fe761850a3f966f1f1c244f9205d304b3d3b049
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Security for s3syncy 1.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Loss of provenance
A previous release of these files had provenance metadata, but this release does not.
While this could reflect a routine change by the project maintainers, it may also indicate that the release files have been compromised.
Release comparison
- Removed 0.1.1 2 files With provenance
- Added 1.2.0 2 files Without provenance
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.