diff --git a/api/backups.ts b/api/backups.ts
index 851bb7b..629a4cb 100644
--- a/api/backups.ts
+++ b/api/backups.ts
@@ -113,16 +113,19 @@ export function checkHost(host: string): string {
}
/**
- * An absolute path on the far side.
+ * A directory on the far side, absolute or relative.
*
- * This one IS interpreted by the remote shell — `ssh host mkdir -p /path` runs through it — so the
- * characters a shell would act on are refused rather than escaped. Refusing is checkable by reading it;
- * escaping is checkable by being right about every shell.
+ * RELATIVE IS NORMAL, and requiring a leading slash was simply wrong. `scp file host:db-backups/fofos/`
+ * lands under the remote account's home, which is what every ssh tool does and what anybody typing a
+ * destination expects — the home directory is the one place they are certain to be able to write.
+ *
+ * What is still refused: the characters a shell would act on. This value IS interpreted remotely —
+ * `ssh host mkdir -p ` runs through a shell — so they are rejected rather than escaped. Refusing
+ * is checkable by reading this function; escaping is checkable only by being right about every shell.
*/
export function checkRemotePath(path: string): string {
const trimmed = path.trim();
if (!trimmed) throw new Error('A remote directory is required.');
- if (!trimmed.startsWith('/')) throw new Error('The remote directory must be an absolute path.');
if (/["'`$;&|<>()\\\s]/.test(trimmed)) {
throw new Error('The remote directory may not contain spaces, quotes or shell characters.');
}
diff --git a/web/BackupsRow.tsx b/web/BackupsRow.tsx
index a2674b7..1db5095 100644
--- a/web/BackupsRow.tsx
+++ b/web/BackupsRow.tsx
@@ -175,7 +175,7 @@ export const BackupsRow = () => {
{configured && settings.sshHost ? (
{' '}
- → {settings.sshHost}:{settings.sshPath}
+ → {settings.sshHost}:{settings.sshPath?.startsWith('/') ? settings.sshPath : `~/${settings.sshPath}`}
) : null}
@@ -278,7 +278,7 @@ export const BackupsRow = () => {
setSshPath(event.target.value)}
- placeholder="/srv/backups/fofos"
+ placeholder="db-backups/fofos"
className="w-full font-mono text-xs"
autoComplete="off"
spellCheck={false}
@@ -296,7 +296,10 @@ export const BackupsRow = () => {
{/* No password field, and there will not be one: this runs with nobody at a terminal, so it
authenticates with the owner's SSH key and stores no credential of its own. */}
-
Authenticated with this machine’s SSH key.
+
+ Authenticated with this machine’s SSH key. A path without a leading slash is relative to
+ the remote home.
+