Getting started

Installation

Binary releases

Download from GitHub Releases:

PlatformBinaryFIPS
Linux x86_64ocync-fips-linux-amd64Yes
Linux arm64ocync-fips-linux-arm64Yes
macOS arm64ocync-macos-arm64No
Windows x86_64ocync-windows-amd64.exeNo

Linux binaries statically link the AWS-LC FIPS module (see FIPS 140-3). macOS and Windows use aws-lc-rs without FIPS mode.

Each binary ships with a CycloneDX bill of materials (<binary>.cdx.json). GitHub holds build provenance and bill of materials attestations for each binary:

gh attestation verify ocync-fips-linux-amd64 --repo clowdhaus/ocync
gh attestation verify ocync-fips-linux-amd64 --repo clowdhaus/ocync \
    --predicate-type https://cyclonedx.org/bom

Homebrew

brew install clowdhaus/taps/ocync

macOS (arm64) and Linux (amd64, arm64). Linux builds use the AWS-LC FIPS module.

Docker

docker pull public.ecr.aws/clowdhaus/ocync:latest-fips

Multi-arch image (linux/amd64, linux/arm64) based on chainguard/static with zero CVEs, no shell, and no package manager.

The image is signed with cosign and carries build provenance. Each platform image also carries its own CycloneDX bill of materials attestation, so verify that against a platform tag such as <version>-fips-amd64:

gh attestation verify oci://public.ecr.aws/clowdhaus/ocync:latest-fips --repo clowdhaus/ocync
cosign verify-attestation --type cyclonedx \
    --certificate-identity-regexp '^https://github.com/clowdhaus/ocync/' \
    --certificate-oidc-issuer https://token.actions.githubusercontent.com \
    public.ecr.aws/clowdhaus/ocync:<version>-fips-amd64

Helm

helm install ocync oci://public.ecr.aws/clowdhaus/ocync --version 0.9.0

See the Helm chart guide for deployment modes and configuration.

Build from source

# FIPS build (default, requires CMake + Go + Perl)
cargo install --locked ocync

# Non-FIPS build (no extra dependencies)
cargo install --locked ocync --no-default-features --features non-fips

Minimum Rust version: 1.94 (edition 2024).

Verify installation

ocync version

Copy your first image

ocync copy cgr.dev/chainguard/nginx:latest \
    123456789012.dkr.ecr.us-east-1.amazonaws.com/nginx:latest

ocync auto-detects the registry type from the hostname and handles authentication automatically. For ECR, it uses your ambient AWS credentials (environment variables, config file, or instance role).

Config-driven sync

For syncing multiple images, create a config file:

registries:
  chainguard:
    url: cgr.dev
  ecr:
    url: 123456789012.dkr.ecr.us-east-1.amazonaws.com

target_groups:
  default:
    - ecr

defaults:
  source: chainguard
  targets: default
  tags:
    glob: "*"
    latest: 10
    sort: semver

mappings:
  - from: chainguard/nginx
    to: nginx
  - from: chainguard/python
    to: python

Run the sync:

ocync sync -c config.yaml

Preview what would sync without making changes:

ocync sync -c config.yaml --dry-run

Key concepts

Additive sync: ocync never deletes images or tags from the target registry. Registries handle lifecycle and retention through their own policies.

Blob deduplication: container images share layers. ocync tracks every blob it has seen in a sync run and transfers each unique blob exactly once, regardless of how many images reference it.

Cross-repo mounting: when a blob already exists in another repository on the same registry, ocync mounts it instead of uploading again. This is a registry-side operation with zero data transfer.

Transfer state cache: a persistent cache records which blobs already exist at each target. Subsequent runs skip HEAD checks for known-good blobs, reducing API calls.

Next steps