Skip to content

cleanup: scheduled auto-cleanup via systemd timer#29

Merged
fosskar merged 2 commits into
mainfrom
cleanup-timer
Jul 10, 2026
Merged

cleanup: scheduled auto-cleanup via systemd timer#29
fosskar merged 2 commits into
mainfrom
cleanup-timer

Conversation

@fosskar

@fosskar fosskar commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Session files accumulate without bound; ssync cleanup exists but is manual. This adds scheduled auto-cleanup per issue #24 — scheduling belongs to systemd timers, not a daemon-internal scheduler.

CLI (plain-binary deployments)

ssync cleanup-timer enable|disable|status installs a ssync-cleanup.service/.timer pair running ssync cleanup … --apply:

  • user units as a regular user; system units as root with --user/--config, same mode rules and access checks as ssync service install
  • the oneshot reuses the daemon's hardening set, sandboxed to the session dirs
  • --every accepts 2d/7d periods, weekly, or a raw calendar expression (validated with systemd-analyze calendar at enable time — one loud error instead of a timer that never fires). Expressible durations normalize to calendar shorthands and gain Persistent=true catch-up; other day counts run on unit uptime (OnUnitActiveSec)
  • --keep defaults to 90d unless --unnamed is the only selector; keep/agent are validated at enable time
  • non-systemd fallback documented as a cron line (cleanup is already non-interactive)

NixOS / home-manager modules

services.ssync.autoCleanup = { enable, schedule, keep, unnamed } generates the same oneshot + timer (Persistent=true, RandomizedDelaySec=1h, After=ssync.service). The shared hardening set is factored into one attrset used by both the daemon and the cleanup service. An assertion rejects a configuration that selects nothing.

Semantics (documented in setup.md)

  • Deletions propagate mesh-wide: cleanup deletes local files, the daemon tombstones them, every peer follows. A timer on one machine prunes all machines — that is the feature, stated loudly next to the options.
  • One machine with a timer is enough; several are harmless but redundant.
  • The existing wipe guard still refuses a run that would delete all of an agent's sessions (protects against an empty/unmounted session dir).

Testing

  • 14 new unit tests: schedule mapping, --keep defaulting, unit rendering (oneshot/ExecStart/User/ReadWritePaths, persistent vs monotonic timer), unit-hostile value rejection
  • vm-module test extended: enabled timer, rendered ExecStart … cleanup --keep 90d --unnamed --apply, and a live oneshot run under hardening — passing locally
  • clippy -D warnings, full workspace tests, nix fmt -- --ci all clean

Version bumped 0.11.1 → 0.12.0 (feature).

Closes #24.

fosskar added 2 commits July 10, 2026 19:55
Session files accumulate without bound; ssync cleanup exists but is
manual. Add scheduling via systemd timers, not a daemon-internal
scheduler (issue #24).

New subcommand: ssync cleanup-timer enable|disable|status installs a
ssync-cleanup.service/.timer pair running ssync cleanup --apply, user
units as a regular user, system units as root with --user/--config
under the same mode rules as service install. The oneshot reuses the
daemon hardening set, sandboxed to the session dirs.

--every accepts 2d/7d-style periods, weekly, or a raw calendar
expression (validated with systemd-analyze at enable time).
Expressible durations become calendar shorthands and gain
Persistent=true catch-up; other day counts run on unit uptime via
OnUnitActiveSec. --keep defaults to 90d unless --unnamed is the only
selector.

NixOS and home-manager modules gain services.ssync.autoCleanup
{ enable, schedule, keep, unnamed }; the shared hardening set is
factored into one attrset used by both the daemon and the cleanup
oneshot. The vm-module test covers the rendered ExecStart, the enabled
timer, and a live oneshot run.

Deletions propagate mesh-wide through the tombstone path: a timer on
one machine prunes all machines. Documented loudly in setup.md next to
the options.

Closes #24.
Review of the cleanup-timer PR found one real hazard and a set of
polish items:

- hm-module: pull RuntimeDirectory and ReadWritePaths out of the shared
  hardening set into per-unit Service blocks. systemd does not
  ref-count runtime dirs shared between units (systemd#5394): every
  cleanup oneshot exit removed /run/user/$UID/ssync under the running
  daemon, silently demoting SecretFile from the runtime tmpfs to
  PrivateTmp. The oneshot also loses its needless dataDir write grant.
- cleanup-timer enable: re-check access on pre-existing session dirs
  after create_write_paths, same as service install — a root-owned
  leaf otherwise fails only when the timer first fires.
- schedule_of: checked_mul on the --every day/week count; an
  overflowing count is now a loud error instead of a wrap.
- --keep help: match the code — the 90d default is skipped whenever
  --unnamed is given, not only when it is the only selector.
- extract ensure_install_mode and remove_units into service.rs, shared
  by service install/uninstall and cleanup-timer enable/disable.
- bundle keep/unnamed/agent into CleanupSelectors; drops the
  too_many_arguments allow.
@fosskar fosskar enabled auto-merge July 10, 2026 18:30
@fosskar fosskar merged commit de49594 into main Jul 10, 2026
2 checks passed
@fosskar fosskar deleted the cleanup-timer branch July 10, 2026 18:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cleanup: scheduled auto-cleanup via systemd timer (CLI + NixOS/HM module options)

1 participant