Skip to content

ssh:// URLs for current repositories - #10417

Merged
ThomasWaldmann merged 3 commits into
borgbackup:masterfrom
ThomasWaldmann:ssh-scheme-9765
Sep 24, 2026
Merged

ThomasWaldmann merged 3 commits into
borgbackup:masterfrom
ThomasWaldmann:ssh-scheme-9765

Conversation

@ThomasWaldmann

@ThomasWaldmann ThomasWaldmann commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

Fixes #9765.

ssh:// URLs for current repositories

  • ssh://[user@]host[:port]/path now addresses a current repository: borg runs borg serve --rest --backend FILE:<path> on the remote host via ssh and talks REST (HTTP over stdio) to it.
  • With --from-borg1, ssh:// addresses a legacy borg 1.x repository via the legacy RPC protocol, as before: the remote runs plain borg serve, which may also be a borg 1.x borg serve.
  • borg serve itself is unchanged: borg serve --rest serves current repositories, plain borg serve serves legacy ones. Forced commands for current repositories must use borg serve --rest.
  • The testsuite uses ssh://__testsuite__/path (like the legacy client) to run borg serve --rest locally instead of via ssh.

Clearer error if the remote borg serve fails to start

E.g. a borg 1.x borg serve does not know --rest, or borg 2 is not installed remotely. Instead of a "Local Exception" traceback:

Error: Could not access the repository via borg serve on the remote host: stdio server exited with code 2:
borg serve: error: unrecognized arguments: serve --rest --backend FILE:...
Is borg 2 installed there (see BORG_REMOTE_PATH)? For a borg 1.x repository, use --from-borg1.

Repository.close() no longer raises from closing a dead store while unwinding an error (like the lock release before it), which masked the original error.

Docs

ssh:// repository URLs everywhere (quickstart, FAQ, deployment, security internals, usage), borg serve epilog, change log entry. Generated usage docs / man pages are not regenerated.

Testing

  • Full suite locally (macOS): all pass except test_migrate_lock_alive, which fails identically on master (local macFUSE issue).
  • New/updated tests: ssh:// URL parsing, get_repository routing (ssh:// with and without --from-borg1), borg serve --rest command line, remote serve startup failure.
  • The borg 1.x server case was also checked manually with a fake ssh + fake borg 1.x borg serve.

🤖 Generated with Claude Code

@codecov

codecov Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.64516% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.38%. Comparing base (ccb0da5) to head (db0c4ac).
⚠️ Report is 5 commits behind head on master.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/borg/repository.py 75.00% 3 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #10417      +/-   ##
==========================================
+ Coverage   88.36%   88.38%   +0.02%     
==========================================
  Files         103      103              
  Lines       19021    19029       +8     
  Branches     2959     2961       +2     
==========================================
+ Hits        16807    16819      +12     
+ Misses       1545     1538       -7     
- Partials      669      672       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@ThomasWaldmann
ThomasWaldmann force-pushed the ssh-scheme-9765 branch 2 times, most recently from 97e95fd to 70b145f Compare September 24, 2026 13:24
@ThomasWaldmann ThomasWaldmann changed the title rename rest:// to ssh://, borg serve detects the client's protocol ssh:// URLs for current repositories, borg serve detects the client's protocol Sep 24, 2026
@ThomasWaldmann ThomasWaldmann changed the title ssh:// URLs for current repositories, borg serve detects the client's protocol ssh:// URLs for current repositories Sep 24, 2026
ThomasWaldmann and others added 3 commits September 24, 2026 15:54
ssh:// now addresses a current repository via REST over stdio over ssh
(served by a remote "borg serve --rest"); with --from-borg1, it still
addresses a legacy borg 1.x repository via the legacy RPC protocol.

The testsuite uses ssh://__testsuite__/path (like the legacy client) to
run "borg serve --rest" locally instead of via ssh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
If the first request to the remote "borg serve" fails (e.g. a borg 1.x
borg serve does not know --rest, or borg is not installed there), raise
an Error showing the server's stderr and a hint (BORG_REMOTE_PATH,
--from-borg1) instead of a "Local Exception" traceback.

Repository.close() does not raise from closing the store while unwinding
an error anymore (like the lock release before it): a dead store fails
to close, too, which masked the original error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Describe ssh:// repository URLs for current repositories (served by a
remote "borg serve --rest") and for legacy borg 1.x repositories (with
--from-borg1, served by a remote "borg serve") and add a change log
entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ThomasWaldmann
ThomasWaldmann merged commit e0fc008 into borgbackup:master Sep 24, 2026
27 of 28 checks passed
@ThomasWaldmann
ThomasWaldmann deleted the ssh-scheme-9765 branch September 24, 2026 14:58
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.

borg2: Rename rest: URI scheme to ssh:

1 participant