Skip to main content

mirror.py event plug-in that generates rsyncd.conf and rsyncd.secrets from the package list.

Project description

mirror.py rsync-server plugin

An event plugin for mirror.py that generates rsyncd.conf and rsyncd.secrets from the live mirror package list plus a sidecar rsync.json configuration file. The plugin regenerates both files automatically when the mirror daemon starts (MASTER.INIT.POST) and whenever the package set changes via mirror config reload (MASTER.CONFIG_RELOAD.POST).

How it works

The plugin listens on two mirror.py events:

  • MASTER.INIT.POST — fires once when the master daemon finishes starting up.
  • MASTER.CONFIG_RELOAD.POST — fires after mirror config reload has loaded a new configuration. Until the mirror.py core ships this event, regeneration happens at daemon start only; the listener signature accepts (*args, **kwargs) so it is forward-compatible.

File generation only. The plugin writes rsyncd.conf and rsyncd.secrets; it does not start, stop, or signal the rsyncd process. This is intentional: rsyncd re-reads rsyncd.conf and the secrets file on every incoming client connection, so adding or removing mirror modules takes effect immediately with no reload signal needed.

Writes are atomic (via a temporary file in the same directory followed by os.replace). If the generated content is identical to what is already on disk, the file is not rewritten. Regeneration runs under a module-level lock so concurrent event firings do not race.

Packages with settings.hidden: true are completely excluded — they appear in neither the public nor the private module list.

Installation

Install the plugin into the same Python environment as mirror.py:

pip install -e .

Enable the plugin in mirror.py's config.json:

"plugins": { "rsync-server": { "enabled": true } }

The plugin's own settings live in rsync.json, not in the plugins block of config.json. See the Configuration section below.

Configuration

rsync.json must live in the same directory as mirror.py's config.json (default path: /etc/mirror/rsync.json).

See rsync.json.example for a complete, realistic example.

All keys are optional and fall back to the defaults listed below.

Key Type Default Description
rsyncd_conf string (absolute path) /etc/rsyncd.conf Destination path for the generated rsyncd.conf.
secrets_file string (absolute path) /etc/rsyncd.secrets Destination path for the generated secrets file. Also emitted as secrets file in the global section of rsyncd.conf.
users object {} Map of username to password. Written to the secrets file in insertion order.
global object {} Raw rsyncd parameter passthrough. Keys and values are emitted in insertion order as key = value lines in the global section. Values may be strings, integers, or booleans (booleans render as true/false). The key secrets file is managed by the plugin and is rejected if placed here.
private_modules.enabled boolean true When false, no [.Name] private module sections are generated.
private_modules.auth_users string * Value written to auth users in every private module section.
private_modules.list boolean false Value written to list in every private module section.
private_modules.lock_file string (absolute path) /var/run/rsyncd-private.lock Value written to lock file in every private module section. The private modules share this lock file, giving them a separate max-connections accounting pool independent of the public modules.

Unknown top-level keys and unknown private_modules keys are rejected with a ValueError at load time (typo protection). Any validation failure leaves previously generated files untouched.

SECURITY NOTE: rsync.json contains plaintext passwords. Restrict its permissions:

chmod 600 /etc/mirror/rsync.json

The plugin logs a warning if rsync.json is group- or other-readable. The generated rsyncd.secrets file is always written with mode 0600, as required by rsyncd's strict modes.

Generated output

Given a package named ArchLinux with src = rsync://rsync.archlinux.org/ftp_tier1 and dst = /mirror/ftp/ArchLinux, and the global settings from rsync.json.example, the plugin produces:

# WARNING: DO NOT EDIT!! Generated by the mirror.py rsync-server plugin.
uid = rsync
gid = nogroup
use chroot = no
max connections = 20
motd file = /mirror/etc/motd
log file = /var/log/geoul/rsyncd/all.log
transfer logging = yes
log format = %o %a - %u [%t] "%P/%f" - %l
pid file = /var/run/rsyncd.pid
exclude = .~tmp~

secrets file = /mirror/etc/rsyncd.secrets

[ArchLinux]
    path = /mirror/ftp/ArchLinux
    comment = from rsync://rsync.archlinux.org/ftp_tier1

[.ArchLinux]
    path = /mirror/ftp/ArchLinux
    comment = private module for ArchLinux without connection limits for authorized mirrors
    auth users = *
    list = false
    lock file = /var/run/rsyncd-private.lock

Each package produces a public/private module pair:

  • [Name] is the public module. It is visible in rsync host:: listings and carries a comment = from <upstream src> line. The comment line is omitted when a package has no upstream src (for example, locally synced packages).
  • [.Name] is the authenticated, unlisted private twin. The leading dot hides it from rsync host:: listings. Access is gated by auth users and the secrets file. This module has its own lock file, so its connection accounting is independent of the public module's max connections limit.

Modules are sorted by package name. The static header contains no timestamp so that identical content is detected and the file is not rewritten unnecessarily.

The secrets file (rsyncd.secrets) contains one username:password line per entry in users, written in insertion order, with no header line.

Running rsyncd

Point rsyncd at the generated configuration file:

rsync --daemon --config=/etc/rsyncd.conf

Operational notes

Changing users or rsync settings. Edit rsync.json, then run:

mirror config reload

No daemon restart is needed for module or authentication changes. rsyncd picks up the new rsyncd.conf and rsyncd.secrets on the next incoming client connection.

Parameters that require an rsyncd restart. Daemon-socket parameters such as port, address, and pid file are read by rsyncd only at startup. Changing them in rsync.json and running mirror config reload will update the generated file, but rsyncd itself must be restarted for these to take effect. Module-level parameters (path, auth, comment, etc.) apply per connection and do not require a restart.

Private module connection accounting. The private modules share the lock file specified by private_modules.lock_file. This gives them a separate max-connections pool rather than unlimited connections — the pool size is controlled by rsyncd's global max connections parameter applied against that lock file independently from the public modules' lock file.

Development

Set up a virtual environment and install the plugin alongside mirror.py:

uv venv
uv pip install -e /path/to/mirror.py -e . pytest

Run the test suite:

uv run pytest

License

Apache-2.0

Project details


Download files

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

Source Distribution

mirror_py_rsync_server-1.0.0.tar.gz (20.8 kB view details)

Uploaded Source

Built Distribution

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

mirror_py_rsync_server-1.0.0-py3-none-any.whl (16.1 kB view details)

Uploaded Python 3

File details

Details for the file mirror_py_rsync_server-1.0.0.tar.gz.

File metadata

  • Download URL: mirror_py_rsync_server-1.0.0.tar.gz
  • Upload date:
  • Size: 20.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mirror_py_rsync_server-1.0.0.tar.gz
Algorithm Hash digest
SHA256 d8bd678ed2b1ac72cb5c2050614de7778920ed8cb4c143cc01ef94d4609d4dd2
MD5 0394f473b6d370e4569f610aae0b3d6f
BLAKE2b-256 f6b639d3d34907d82235bd08c79cae76b332d96d97e74a46be66cea9896c0f51

See more details on using hashes here.

Provenance

The following attestation bundles were made for mirror_py_rsync_server-1.0.0.tar.gz:

Publisher: pypi.yaml on sparcs-kaist/mirror.py-rsync-server

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mirror_py_rsync_server-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for mirror_py_rsync_server-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d771bd3eb9e86cd77d159c852932573493d5bd3c3370871877e9e9e719f625a8
MD5 e152645d6eecb40ca622d4288e68ce30
BLAKE2b-256 ce5985b4d7e968fd431a38d2fa7ec5ec0f495326117522c9b50adeb582793d15

See more details on using hashes here.

Provenance

The following attestation bundles were made for mirror_py_rsync_server-1.0.0-py3-none-any.whl:

Publisher: pypi.yaml on sparcs-kaist/mirror.py-rsync-server

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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