From d0c17b183b529cdf4e137bf5e076326a02c7247a Mon Sep 17 00:00:00 2001 From: Plom Heller Date: Mon, 28 Sep 2026 23:58:35 +0200 Subject: [PATCH] Have orgbackup auto-append to .config/orgsync/servers on --init. --- CLAUDE.md | 18 ++++++++++++------ home/user/.local/bin/lib/orgsync.py | 15 ++++++++++----- home/user/.local/bin/orgbackup | 20 +++++++++++++++----- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4f7f06c..dd37d92 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -847,8 +847,10 @@ in `.profile.d/` as `*.sh`, sourced by the loop line in `~/.profile`. on the one switched to. Borg archives rather than git or a live-sync tool, since `~/org`'s contents and changes don't follow software-development patterns and syncing follows machine switches. Every server listed in - `~/.config/orgsync/servers` (untracked; one per line, `#`/blank lines skipped) - holds an independent repo (see "`setup_borg_server.sh`"), each pushed to + `~/.config/orgsync/servers` (untracked; one per line, `#`/blank lines skipped; + `orgbackup --init ` appends its server there unless listed, the + other desktops' lists are edited by hand) holds an independent repo (see + "`setup_borg_server.sh`"), each pushed to separately — never copy a repo between servers, which would duplicate its ID and encryption nonce state. Shared code in `lib/orgsync.py` (below); `borgbackup` is in `to_install/t490s`. @@ -860,10 +862,14 @@ in `.profile.d/` as `*.sh`, sourced by the loop line in `~/.profile`. --init ` (refuses to overwrite) and copied by hand to every other desktop, plus one copy kept off all desktops and servers: losing every copy makes that server's backups unreadable. Never tracked - (secrets). Borg 2's `repo-create --other-repo` may allow one key for all; - revisit on migrating. The passphrase, the same for all repos, is asked - once per run into `BORG_PASSPHRASE`, unless that or `BORG_PASSCOMMAND` is - already set. + (secrets). The server list is deliberately not derived from these + filenames: a listed server lacking its keyfile here (e.g. one forgot to + copy) gets a skip warning instead of silently dropping out of the + guards below, and a server is disabled by editing the list, not by + moving a secret around. Borg 2's `repo-create --other-repo` may allow + one key for all; revisit on migrating. The passphrase, the same for all + repos, is asked once per run into `BORG_PASSPHRASE`, unless that or + `BORG_PASSCOMMAND` is already set. - SSH: `BORG_RSH` (`ssh -o StrictHostKeyChecking=accept-new`) logs in as `borg` with whatever key `ssh-agent` offers (see `ssh-agent.sh` above). `accept-new`: a never-contacted server's host key is accepted rather diff --git a/home/user/.local/bin/lib/orgsync.py b/home/user/.local/bin/lib/orgsync.py index 1000f9e..f08547b 100644 --- a/home/user/.local/bin/lib/orgsync.py +++ b/home/user/.local/bin/lib/orgsync.py @@ -159,15 +159,20 @@ def ensure_passphrase( environ['BORG_PASSPHRASE'] = passphrase +def server_names( + ) -> list[str]: + 'Read PATH_SERVERS: one server per line; blank, "#" lines skipped.' + lines = [line.strip() for line + in PATH_SERVERS.read_text(encoding='utf8').splitlines()] + return [line for line in lines if line and not line.startswith('#')] + + def load_servers( ) -> list[Server]: - 'Read PATH_SERVERS: one server per line; blank, "#" lines skipped.' + 'Servers listed in PATH_SERVERS, fail if no such file.' if not PATH_SERVERS.exists(): raise SyncError(f'no server list at {PATH_SERVERS}') - lines = [line.strip() for line - in PATH_SERVERS.read_text(encoding='utf8').splitlines()] - return [Server(line) for line in lines - if line and not line.startswith('#')] + return [Server(name) for name in server_names()] def probe_servers( diff --git a/home/user/.local/bin/orgbackup b/home/user/.local/bin/orgbackup index ae9955f..cd1f416 100755 --- a/home/user/.local/bin/orgbackup +++ b/home/user/.local/bin/orgbackup @@ -4,9 +4,9 @@ from datetime import datetime, timezone from socket import gethostname from lib.argparsing import ArgParser from lib.orgsync import ( - DIRNAME_ORG, PATH_HOME, PATH_ORG, Server, SyncError, current_manifest, - ensure_passphrase, load_state, newest_archive, probe_servers, - run_against_syncerror, save_state, warn) + DIRNAME_ORG, PATH_HOME, PATH_ORG, PATH_SERVERS, Server, SyncError, + current_manifest, ensure_passphrase, load_state, newest_archive, + probe_servers, run_against_syncerror, save_state, server_names, warn) APP_DESC = 'Back up ~/org to all reachable servers.' @@ -29,9 +29,19 @@ def main( print(f'{server.name}: creating repo, keyfile at {server.path_key} …') server.init() server.probe() + if not (PATH_SERVERS.exists() and server.name in server_names()): + servers_text = (PATH_SERVERS.read_text(encoding='utf8') + if PATH_SERVERS.exists() else '') + print(f'{server.name}: adding to server list at {PATH_SERVERS} …') + PATH_SERVERS.parent.mkdir(parents=True, exist_ok=True) + separator = ('\n' if servers_text + and not servers_text.endswith('\n') else '') + with PATH_SERVERS.open('a', encoding='utf8') as file: + file.write(f'{separator}{server.name}\n') print(f'{server.name}: repo created.\n' - 'Copy that keyfile to every other desktop, and keep one copy' - ' off all desktops and servers (e.g. printed: it is text).') + 'Copy that keyfile to every other desktop (and list the server' + ' there), and keep one copy off all desktops and servers (e.g.' + ' printed: it is text).') return if not PATH_ORG.is_dir(): -- 2.30.2