parsync Documentation

repository·master·Indexed 20 days ago

https://github.com/alpindale/parsync

A high-throughput, resumable synchronization tool for SSH remotes and local-to-local transfers. Version 0.2.0 features parallel transfers, block-delta sync, and a specialized RDMA fast path for Linux environments. It supports recursive directory syncing, metadata preservation (permissions, owner, group, ACLs, xattrs), and configurable parallel worker jobs.

Tokens
14.5K
Snippets
47
Records
58
Agent score
67%

What's inside parsync

  1. Install parsync

    master

    You can install parsync using several methods depending on your operating system:

    Linux and macOS

    Use the install script via curl:

    curl -fsSL https://alpindale.net/install.sh | bash

    Windows

    Use PowerShell:

    powershell -ExecutionPolicy Bypass -c "irm https://alpindale.net/install.ps1 | iex"

    Rust/Cargo

    If you have Rust installed, use cargo:

    cargo install parsync

    From Source

    Clone the repository and use make:

    make build
    make install
    curl -fsSL https://alpindale.net/install.sh | bash
  2. Use parsync for file transfers

    master

    Use parsync to perform high-throughput, resumable transfers between SSH remotes and local paths, or between local directories.

    Basic Syntax

    parsync [options] <source> <destination>

    SSH Remote Syntax

    To sync from a remote host, use the user@host:/path format. If the remote host uses a non-default SSH port, specify it as user@host:port:/path.

    Supported Features

    • Parallel file transfers.
    • Optional block-delta sync.
    • SSH config host aliases are supported.
    parsync -vrPlu user@example.com:/remote/path /local/destination
  3. Configure the RDMA fast path

    master

    On Linux, parsync can use a direct RDMA fast path for large whole-file copies (minimum 64 MiB by default) if both hosts have RDMA devices and rdma-core librdmacm rsockets available. This is enabled in auto mode by default for SSH sources.

    CLI Options

    • --rdma=<mode>: Set the RDMA mode. Use require to force RDMA or off to disable it.
    • --rdma-bind <ipv4>: Specify a local IPv4 address to bind the RDMA receiver to. Use this if the RDMA fabric uses a different address than the SSH route.
    • --rdma-min-size <bytes>: Set the minimum file size required to trigger the RDMA fast path.

    Environment Variables

    You can configure these settings using the following environment variables:

    • PARSYNC_RDMA
    • PARSYNC_RDMA_BIND
    • PARSYNC_RDMA_MIN_SIZE
    • PARSYNC_RDMA_HELPER

    Configuration File Keys

    If using a configuration file, use these keys:

    • rdma_mode
    • rdma_bind
    • rdma_min_size
    • rdma_helper
    parsync --rdma=require user@example.com:/remote/path /local/destination
  4. Handle sync interruptions gracefully

    master

    Parsync handles system interrupts (like Ctrl+C) using a two-stage approach:

    1. First Interrupt: The application catches the signal, sets an INTERRUPTED flag, and prints a message: [parsync] interrupt received, stopping after current operation.... The current file operation is allowed to finish to maintain state integrity.
    2. Second Interrupt: If a second interrupt is received while waiting for the first to finish, the process forces an immediate exit with exit code 130.
  5. Manage remote connections with ConnectionPool

    master

    To handle multiple concurrent workers, use ConnectionPool. It manages a set of reusable Connection objects to avoid the overhead of repeated SSH handshakes.

    Workflow:

    1. Initialize the pool with ConnectionPool::new(target, pool_size). This eagerly opens one connection to validate authentication.
    2. Use pool.checkout() to acquire a PooledConnection. This will either return an idle connection or create a new one if the max_size hasn't been reached. If the pool is full, it will block until a connection is returned.
    3. The PooledConnection implements Drop, so when it goes out of scope, the connection is automatically returned to the pool via checkin rather than being closed.
    let pool = ConnectionPool::new(target, 4)?;
    {
        let mut conn = pool.checkout()?;
        conn.exec("whoami")?;
    }
    // conn is automatically checked back into the pool here
  6. Validate destination paths for security

    master

    To prevent directory traversal attacks and ensure sync integrity, parsync validates destination paths using validate_destination_path.

    Security Rules:

    • No Absolute Paths: Remote entries must not contain absolute paths.
    • No Traversal: Path components like .. (ParentDir), / (RootDir), or platform-specific prefixes are forbidden.
    • Symlink Protection: The destination path must not traverse a symlink that exists outside of the designated sync root.
    • Directory Integrity: If a path component is expected to be a directory (e.g., for a file inside a folder), the system verifies that the component actually exists as a directory on the local filesystem.
  7. How delta transfers work

    master

    Delta transfers allow for efficient synchronization by only downloading the parts of a file that have changed, rather than the entire file.

    The Process:

    1. Signature Generation: A signature of the local (basis) file is built using blocks of a specific size (delta_block_size).
    2. Planning: The signature is sent to the remote, which generates a DeltaPlan containing a sequence of operations (DeltaOp) to transform the local file into the remote version.
    3. Execution: The local client applies these operations to a partial file (part_path).
    4. Verification: Once operations are complete, the final file is hashed. If the digest matches the plan's expected final_digest_hex, the file is renamed to the destination.

    Key Constraints:

    • If the number of literal bytes in the plan exceeds delta_max_literals, the transfer is aborted.
    • If the remote file changes during the planning phase, the transfer is aborted to prevent corruption.
  8. Configuration precedence in parsync

    master

    parsync resolves configuration settings using a specific hierarchy of precedence. When a setting is defined in multiple places, the one higher in this list takes priority:

    1. CLI Flags: Arguments passed directly to the parsync command.
    2. Environment Variables: Variables prefixed with PARSYNC_.
    3. Configuration File: Settings defined in the TOML configuration file.
    4. Defaults: Built-in default values used if no other configuration is provided.

    This allows you to set global defaults in a config file, override them for specific sessions using environment variables, or apply one-off overrides via CLI flags.

  9. How RDMA and fast-copy transfers work

    master

    Parsync supports high-performance transfer modes like RDMA and fast-copy.

    RDMA (Remote Direct Memory Access):

    • Uses a specialized fast path for data transfer.
    • If strict_durability is enabled, the partial file is synced to disk (sync_all) before verification.
    • If the remote file's size or modification time changes during the RDMA transfer, the system will either fail (if RdmaMode::Require is set) or fall back to a full transfer.

    Fast-copy:

    • A secondary fast path that uses remote.try_fast_copy to move data into a partial file.
    • Like RDMA, it supports strict_durability via sync_all on the partial file.
    • If the fast-copy fails, the partial file is removed.
  10. SSH Authentication mechanisms

    master

    The Connection logic attempts authentication in the following order:

    1. SSH Agent: Checks if the user is already authenticated via an active SSH agent.
    2. Public Key Files: Tries configured identity files, then defaults to ~/.ssh/id_ed25519 and ~/.ssh/id_rsa.
    3. Environment Variable: If the above fail, it attempts to use the password provided in the PARSYNC_SSH_PASSWORD environment variable.

    If all methods fail, authentication will error.

  11. Configure file metadata preservation

    master

    When syncing files, you can preserve various metadata attributes from the remote source to the local destination.

    Supported attributes include:

    • Permissions: Uses preserve_perms to set file modes.
    • Owner/Group: Uses preserve_owner and preserve_group to set UID/GID (Unix).
    • Extended Attributes (xattrs): Uses preserve_xattrs to sync key-value pairs.
    • ACLs: Uses preserve_acls to sync Access Control Lists (Unix via setfacl).

    Platform Notes:

    • Unix: Full support for permissions, owner, group, xattrs, and ACLs.
    • Windows: Support for permissions is limited (sets readonly based on mode). Owner, group, xattrs, and ACLs are generally unsupported. If strict_windows_metadata is enabled, attempting to preserve these unsupported attributes will cause the sync to fail with an error.
  12. Configure SyncOptions for parsync

    master

    The SyncOptions struct defines the behavior of a synchronization run. When using the library programmatically, you can use the opts() function to get a default configuration.

    Key configuration categories include:

    • General: verbose, debug, recursive, links, update, dry_run.
    • Performance: jobs (concurrency), chunk_size, chunk_threshold.
    • Reliability: retries, resume, strict_durability, verify_existing.
    • Delta Sync: delta_enabled, delta_min_size, delta_block_size, delta_max_literals, delta_helper, delta_fallback.
    • SFTP/Remote: sftp_read_concurrency, sftp_read_chunk_size.
    • RDMA (Linux only): rdma_mode, rdma_bind, rdma_min_size, rdma_helper.
    • Metadata: preserve_perms, preserve_owner, preserve_group, preserve_acls, preserve_xattrs, strict_windows_metadata.

    Note that delta_helper defaults to "parsync --internal-remote-helper" and rdma_helper (on Linux) defaults to "parsync --internal-rdma-send".

    let mut options = opts();
    options.delta_enabled = true;
    options.delta_min_size = Some(8 * 1024 * 1024);
    // ... use options in run_sync_with_client