Sign inSign up

cplieger/docker-rsync-scheduler

By cplieger

Updated about 13 hours ago

Scheduled rsync+ssh push of local dirs to a remote — Go scheduler on Alpine, interval or exec-run

Image
Networking
Databases & storage
0

10K+

cplieger/docker-rsync-scheduler repository overview

docker-rsync-scheduler

Push local directories to a remote host over rsync-and-ssh on a schedule. Structured logs, no metrics, no open ports.

What it does

Reads a YAML config defining N sync jobs. For each job it runs rsync over ssh to push a local directory one-way to a remote host. Every pass executes inside the long-lived daemon regardless of how it was triggered, so its structured logs (logfmt, UTC timestamps) always land on the container's log stream, ready for a log aggregator (Alloy, Promtail) and alerting.

  • One-way mirror of each configured local directory to a [user@]host:/path
  • Per-job --delete, --chown=uid:gid, and exclude patterns
  • Empty-source guard: A job with an empty top-level source directory is skipped. This protects an unmounted source that Docker materialized as an empty directory from an unbounded --delete pass. A local path that does not exist fails the job. The guard is a preflight snapshot, and rsync rebuilds its file list after the check. It cannot protect a source that becomes empty during a pass; use max_delete as the backstop, as the example shows. The guard checks only the built-in global excludes, not per-job excludes. For a delete: true job whose own excludes can match every entry, set max_delete to cap the deletions. The cap fails only when more than N files would be deleted, so a value at or above the mirror's file count never fires.
  • Built-in interval scheduler, or hand scheduling to an external scheduler (cron, Ofelia, etc.) via the sync subcommand
  • File-marker healthcheck: unhealthy when any job fails, recovers on the next clean pass
  • Logs only: no Prometheus exporter, no HTTP server, no network listener (triggering uses an in-container unix socket)

Pull

docker pull cplieger/docker-rsync-scheduler:latest

Also published to ghcr.io/cplieger/docker-rsync-scheduler with identical images and tags. Release versions are tagged vX.Y.Z alongside latest.

Quick start

# Example compose for docker-rsync-scheduler. See the README for all configuration options and hardening.
services:
  rsync:
    image: ghcr.io/cplieger/docker-rsync-scheduler:latest
    container_name: rsync
    restart: unless-stopped

    environment:
      SYNC_INTERVAL: "6h"  # built-in cadence (Go duration); "off" = external trigger; see README "Scheduling modes"
      SYNC_TIMEOUT: "10m"  # per-job rsync timeout (Go duration)

    volumes:
      - "./config.yaml:/config/config.yaml:ro"
      - "./id_ed25519:/keys/id_ed25519:ro"  # dedicated SSH key, host file mode 0600
      - "./data:/data"  # last-run record; keeps the schedule across recreates and image updates (see README "Scheduling modes")
      # source directories referenced by the jobs in config.yaml:
      - "/srv/source/certs:/sources/certs:ro"
      - "/srv/source/appconfig:/sources/appconfig:ro"

Documentation

License

Apache-2.0. See LICENSE. The image carries the license text of every bundled component under /usr/share/licenses/. The Alpine packages in the image ship no license file upstream, so their license texts are kept under licenses/ in this repository and copied in.

The bundled component is rsync itself, which is GPL-3.0-or-later. The build fetches the pinned release tarball https://download.samba.org/pub/rsync/src/rsync-3.5.0.tar.gz (RSYNC_VERSION=v3.5.0), verifies the detached upstream signature and then the pinned SHA256, and applies no patches to the extracted source. rsync's own COPYING travels in the image at /usr/share/licenses/rsync/COPYING, and the upstream project is RsyncProject/rsync. That tarball and this repository's Dockerfile are the complete recipe for the rsync binary in the image, which is how anyone who receives it gets the corresponding source.

Tag summary

Content type

Image

Digest

sha256:953abaed7

Size

8.3 MB

Last updated

about 13 hours ago

docker pull cplieger/docker-rsync-scheduler