Remove the short pobsync aliases for global config, host config, and
schedule changes so the public CLI no longer points operators toward the
old configuration workflow.
Keep operational aliases for backup, discovery, retention, worker, and
scheduler debugging, and document explicit Django management commands for
automation use.
Extend the restore guidance with directory and single-file dry-run
examples so operators can restore a focused path without copying an
entire snapshot.
Render the examples on snapshot detail pages using the selected
snapshot's data path and the host-specific staging destination.
Document the manual restore workflow in the README and surface snapshot-
specific restore commands on the snapshot detail page.
The guidance keeps restores intentionally manual for now: inspect the
snapshot data directory, run rsync with --dry-run, restore to staging
first, and treat hardlinked snapshot files as read-only.
Make queued, running, warning, and failed run states more visible at the
top of the dashboard with contextual status summaries and highlighted
summary metrics.
Also show an all-clear message when configured hosts have no active or
problematic runs.
Replace the dashboard trend metric grid with an operational summary that
explains storage usage, runway, average new data, link-dest savings, and
average duration in a more readable way.
Also add an empty state for fresh installs before completed backup stats
exist.
Add per-host status chips for queued, running, warning, and failed runs so
the dashboard shows operational pressure without needing to open each host.
Restructure host cards into clearer backup activity and snapshot health
sections, with less visual clutter and better mobile wrapping.
Split dashboard host cards into last successful backup and latest warning
or failed run so operators can quickly see whether a host is protected even
when recent activity produced an issue.
Also add queued and warning run counts to the dashboard summary metrics.
Record planned delete counts, max-delete settings, base protection, and
ignored incomplete snapshots in retention apply results.
Surface those details on run detail pages so scheduled and manual prune
outcomes are understandable without reading the raw JSON payload.
Update the scheduler to reflect the actual scheduled BackupRun status after
a run completes, so prune warnings are shown as schedule warnings instead
of being reported as successful schedule executions.
Make manual retention application more explicit by requiring operators to
confirm both the host name and the current number of planned deletions.
This reduces the risk of applying a stale or misunderstood retention plan
when the delete set changes between review and confirmation.
Show host-level retention warnings on run detail pages so successful or
warning runs still expose scheduled prune limit issues and incomplete
snapshots that need operator attention.
Show keep/delete reasons in the retention plan, surface scheduled prune
limit warnings, and explain base snapshot protection before retention is
applied.
Also surface incomplete snapshots from the retention views without deleting
them automatically, so interrupted backups are visible on the dashboard,
host detail, and retention plan.
Surface dry-run status, transfer estimates, file counts, warnings, and the full
rsync log link directly on the run detail page.
Keep raw rsync output and JSON available, but make the common review path easier
to scan before starting a real backup.
Add an on-demand host preflight action that verifies SSH reachability,
remote rsync availability, and remote source root access.
Persist the latest preflight result on the host config, render it in Django,
and block real backups when the last remote preflight failed.
Introduce a host preflight layer that separates dry-run blockers from real backup blockers.
Show the effective per-host backup configuration in Django before queueing a run.
Block real backup queueing when failed host checks remain, while still allowing dry-runs
when only local storage preparation is missing.
Extend the Django logs view with filters for service unit, severity, time
window, host, run id, and message text. Pass severity and time window directly
to journalctl, then apply host/run/message filtering to the returned pobsync
journal lines.
This makes failed or slow backups easier to investigate from the control panel
without needing shell access.
Restructure the run detail page into clearer sections for summary, failure
classification, requested options, rsync command, rsync log output, stats,
retention, and raw result data.
Show recent rsync log output inline with a link to the full log, and promote
failure and retention warning details out of the JSON payload so failed or slow
runs are easier to debug from the control panel.
Extend the runtime self check with native install diagnostics for the
environment file, service user, backup root ownership, and SQLite database
path. Export install metadata from the systemd units and pobsync-manage wrapper
so custom env files and service users are visible to Django checks.
Document restart, journal log inspection, and rollback steps in the README so
production updates have a clear recovery path.
Add check_pobsync_install so native deployments can run the same runtime
diagnostics from the terminal that are available in the Django Self Check view.
The command prints every check with status, returns a failing exit code when
install-critical checks fail, supports fail-on-warning for stricter automation,
and is documented in the installer output and README update flow.
Delete the old scripts/deploy path that installed pobsync into /opt/pobsync/lib
with a standalone /opt/pobsync/bin wrapper.
Production deployment is now owned by the native systemd installer and updater,
so keeping the legacy deploy script would make the supported install story less
clear and easier to misuse.
Add scripts/update-systemd as a safer routine deploy entrypoint for native
systemd installations. The wrapper keeps updates non-interactive, preserves the
existing environment file, skips OS package installation, and avoids superuser
creation prompts while still reusing the installer refresh flow.
Document the update path in the README and capture the maintenance expectation
in the development notes.
Add a pobsync-manage wrapper that loads the native environment file before
running Django management commands, so production commands use the same
database and runtime settings as the systemd services.
Install the wrapper from the systemd installer, use it for migrations,
static collection, SSH key setup, and superuser creation, and document it
in the README for operational commands.
Create the 1.0 milestone and roadmap issues in Gitea, making Gitea the
leading tracker for release work.
Remove the repository roadmap document and README reference now that the
roadmap is tracked as milestone issues.
Document the remaining 1.0 work as ordered, reviewable chunks with
checkboxes for install/update flow, logging, preflight validation,
retention UX, dashboard polish, restore docs, config cleanup, and release
hardening.
Link the roadmap from the README and note how it can later be mirrored into
Gitea milestones and issues.
Drop the Global Configs metric from the dashboard because pobsync only uses
one default global configuration.
Keep global config management available through the existing dashboard
action and setup prompt.
Record the final rsync log path for successful real backup runs, matching
the existing dry-run and failure result payloads.
Add a staff-only run log endpoint and surface the link on run detail pages,
including fallback log discovery for older runs based on snapshot_path.
Cover direct log links and inferred scheduled backup logs with view tests.
Split each dashboard host card into a timeline area and a compact stats area
so snapshot, run, and schedule details have more room to scan.
Keep the same operational information visible while reducing cramped
column-like wrapping on desktop and mobile layouts.
Restructure the dashboard Hosts section into a card per host so snapshot,
run, schedule, retention, and data metrics have room to breathe.
Add reusable host-card styling and keep the same links and operational data
available without forcing everything into a wide table.
Drop the legacy schedule user setting from the Django model, form, defaults,
and configure command.
Schedules are executed by the pobsync scheduler service under the configured
systemd service user, while remote SSH login users are configured separately
on global or host backup config.
Add a migration to remove the unused database column and update schedule
view tests around the simplified form.
Make SQL retention delete the snapshot root when records point at the
snapshot data directory, matching how backup metadata is stored on disk.
Before removing a snapshot tree, temporarily add user write permission to
directories inside that snapshot so rsync-preserved source permissions do
not block cleanup.
Add a regression test for pruning snapshots whose data directory mirrors a
read-only remote root.
Add a warning status for BackupRun records so successful snapshots are not
reported as failed when post-run SQL retention fails.
Keep the prune error in the run result, link the successful snapshot, and
let the management command complete with a warning instead of raising a
backup failure.
Include warning runs in backup trend summaries and add a regression test
for successful backups with failed retention cleanup.
Only apply default schedule initial values when creating a new schedule.
Avoid passing default initial data while editing an existing ScheduleConfig,
so the form renders the active cron-style expression, user, and retention
settings from the database.
Add a regression test that reopens an existing schedule and verifies the
stored values are shown instead of defaults.
Prompt for the scheduler timezone during interactive installs and support
a --time-zone flag for scripted installs.
Detect a sensible default from POBSYNC_TIME_ZONE, timedatectl, or
/etc/timezone before falling back to UTC, and validate the value with
Python zoneinfo before writing it to pobsync.env.
Document that schedules are evaluated in POBSYNC_TIME_ZONE so production
installs can avoid UTC/local-time ambiguity.
Separate operational latest-run display from trend-stat collection so
successful backups without parsed stats still appear in dashboard host rows.
Keep trend summaries limited to runs with stats, but use all successful
real runs for the host latest-run indicator.
Render next scheduled run times with an explicit timezone label to avoid
ambiguity between UTC and local scheduler time.
Add a scheduler helper that calculates the next due time for a cron-style
schedule expression and surface that value on the dashboard and host detail
pages.
Show the latest run type in host summaries and backup trend tables so
manual and scheduled backups are distinguishable in the Django UI.
Keep the calculation derived from existing ScheduleConfig data without
adding a migration.
Rename the schedule form label from "Cron expression" to "Schedule
expression" and explain that cron-style timing is evaluated by the
pobsync scheduler service rather than host cron.
Update host detail and schedule form copy so operators can see that
schedules are SQL-backed and dispatched by pobsync itself.
Extend derived backup statistics with average daily new data and an
estimated days-until-full forecast based on recent successful real runs.
Show the new forecast metrics on the dashboard and add compact per-run
trend bars on the host detail page so new data and matched link-dest data
are easier to compare at a glance.
Keep the implementation migration-free by deriving everything from the
existing BackupRun result stats payload.
Add a stats summary layer that aggregates recent successful real backup runs
into dashboard and host-level trend metrics.
Show backup-root usage, available space, average new data, average duration,
estimated runs until full, and link-dest savings on the dashboard. Add a host
trend table with recent run duration, file count, new data, matched data, and
snapshot links.
Keep the implementation based on existing run and snapshot stats JSON so the
UI gains useful trend visibility without introducing a schema migration yet.
Parse rsync --stats output into structured run metrics for file counts,
transferred bytes, literal data, matched data, speedup, and estimated
link-dest savings.
Store collected stats on backup run results and successful snapshot metadata,
including snapshot data usage and backup-root capacity details for future
dashboard graphs and disk-full projections.
Render the collected metrics on run and snapshot detail pages, with tests
covering parsing, metadata persistence, and UI output.
Expose a verbose rsync output option in the Django manual backup form and
store the selected value with the queued run request.
Propagate the option through the worker, direct management command, and
rsync command builder so real backups can emit itemized changes, file-list
progress, and stats when requested. Dry-runs continue to use verbose output
by default and report that consistently in requested options.
Cover the queue, worker, view, and rsync command behavior with focused
tests.
Classify rsync failures in run results so transport issues such as exit
255 and broken pipes show clearer diagnostic hints.
Teach the worker to reconcile running dry-runs when their log already
contains a terminal rsync error, and to fail stale dry-runs after their
timeout window. This prevents failed rsync processes from leaving runs
stuck in the running state indefinitely.
Add default dry-run rsync output flags so long-running dry-runs expose
file-list, progress, stats, and itemized change information in their
run-specific log files.
Avoid duplicating user-supplied itemize or --info arguments so operators
can still tune rsync output from global or host configuration.
Add a cancel action for queued and running backup runs. Queued runs are
cancelled immediately, while running runs are marked for cancellation and
the worker terminates the active rsync process group.
Make dry-run log paths run-specific and add a defensive default dry-run
timeout so stuck dry-runs do not remain running indefinitely.
Remove rsync exit codes from run overview tables while keeping detailed
diagnostics available on the run detail payload.
Introduce reusable configuration checks for global settings and effective
host runtime configuration. The checks now surface risky backup settings
such as missing recursive rsync args, missing critical root excludes,
invalid SSH settings, missing credentials, and retention gaps.
Show these checks on the global config form, host edit form, and host
detail page so operators can validate the compounded host/global config
before starting real backup runs.