Skip to content

Commit f806bf4

Browse files
Notify the desktop when automatic backup jobs fail
1 parent 2664070 commit f806bf4

3 files changed

Lines changed: 25 additions & 1 deletion

File tree

‎STRUCTURE.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,13 @@ same information for automation; exit 1 means attention or verification is neede
144144
Personal backup dates start being recorded after installing this version and
145145
completing a successful backup. An unknown date is not evidence of a failed backup.
146146
A personal backup older than 24 hours is flagged for review.
147+
148+
Automatic personal backup and Restic maintenance services use systemd `OnFailure`
149+
to display a persistent critical desktop notification. The notification includes
150+
the failed service name and points to `backup-health`; journals remain available
151+
when no desktop notification session is running. Manual command failures continue
152+
to report their errors in the terminal.
153+
154+
Captured system files are preserved verbatim, including upstream README files.
155+
The validator reports broken upstream links inside `system-backup/` without
156+
failing; broken links in maintained repository documentation still fail checks.

‎home-manager/modules/backup-automation.nix‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{ machine, ... }:
1+
{ machine, pkgs, ... }:
22

33
{
44
home.file.".local/bin/backup-on-mount" = {
@@ -16,9 +16,18 @@
1616
executable = true;
1717
};
1818

19+
systemd.user.services."backup-failure@" = {
20+
Unit.Description = "Notify about backup failure in %i";
21+
Service = {
22+
Type = "oneshot";
23+
ExecStart = "${pkgs.libnotify}/bin/notify-send --urgency=critical --expire-time=0 --app-name=Backups 'Backup service failed' '%i failed. Run backup-health and inspect its journal for details.'";
24+
};
25+
};
26+
1927
systemd.user.services.backup-on-mount = {
2028
Unit = {
2129
Description = "Run Restic backup when the backup drive is mounted";
30+
OnFailure = [ "backup-failure@%n.service" ];
2231
After = [ "graphical-session.target" ];
2332
};
2433

@@ -46,6 +55,7 @@
4655
systemd.user.services.restic-maintenance = {
4756
Unit = {
4857
Description = "Prune old Restic snapshots and verify repository";
58+
OnFailure = [ "backup-failure@%n.service" ];
4959
};
5060

5161
Service = {
@@ -73,6 +83,7 @@
7383
systemd.user.services.restic-deep-check = {
7484
Unit = {
7585
Description = "Deep Restic repository integrity check";
86+
OnFailure = [ "backup-failure@%n.service" ];
7687
};
7788

7889
Service = {

‎scripts/check‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ def main():
4444
path = unquote(urlsplit(link).path)
4545
target = ((ROOT / path.lstrip('/')) if path.startswith('/') else (document.parent / path)).resolve()
4646
if not target.exists():
47+
if document.relative_to(ROOT).parts[0] == 'system-backup':
48+
print(f'Upstream snapshot documentation link: {document.relative_to(ROOT)} -> {link}')
49+
continue
4750
raise SystemExit(f'Broken link in {document.name}: {link}')
4851
# A temporary path flake includes new, unstaged files without changing the Git index.
4952
# Keep configs beside home-manager because modules use ../.. relative sources.

0 commit comments

Comments
 (0)