# LibrePortal Connect as a backup destination (design) **Status:** client side built, greyed out. There is no service yet. · **Scope:** what Connect has to be for backups, and what already exists · **Origin:** "maybe add a section of adding LibrePortal's connect service" (2026-08-28) --- ## 0. What Connect is promised to be From `docs/guide/promise.md`, which is where this starts and what it has to obey: > **LibrePortal Connect** — optional services for the tricky parts, like reaching > your server from your phone or keeping off-site backups. We work like a > courier carrying a sealed box: we move and store your data, but it stays > locked and *you* hold the only key. and: > Every paid service has a free, self-hostable equivalent in the open code. Both of those are load-bearing here, not marketing. The first says the service must never be able to read a backup. The second says shipping Connect must not make anything worse for someone who never uses it. ## 1. What already exists Almost all of it, because a Connect destination is not a new kind of thing. | Piece | Status | |---|---| | Client-side encryption with a key the server never sees | ✅ restic, always on | | A backend that stores packs over HTTP | ✅ `rest` location type | | Per-location URI, engine, retention, append-only | ✅ the location model | | A password the user keeps, escrowed locally | ✅ `passwords.txt`, 0600 | | Somewhere to enter a credential without it leaking | ✅ the secret channel | | A destination list in the wizard to hang it off | ✅ the Backups step | | **The service** | ❌ does not exist | So the client half is a REST repository with credentials in the URI. That is why `connect` resolves exactly like `rest` in `resticLocationUri` — it *is* one. It is a separate TYPE only so the UI can tell "LibrePortal Connect" apart from "a REST server I run myself", which are identical on disk. Anyone who wants the second can have it today, free, which is the promise's litmus test passing. ## 2. Shape of a Connect destination ``` CFG_BACKUP_LOC__TYPE=connect CFG_BACKUP_LOC__URI=rest:https://:@connect.libreportal.org/v1// CFG_BACKUP_LOC__PASSWORD= ``` The URI carries the device credentials; the PASSWORD is the encryption key and stays here. The service holds packs it cannot open. That is the sealed box, implemented rather than asserted. The device code the user pastes is a credential, so it travels through the secret channel (`scripts/webui/webui_secret.sh`) as a reference — never in the wizard payload, which is base64'd into a world-readable task file. ## 3. The not-yet-available state `CFG_BACKUP_CONNECT_ENDPOINT` decides it, and it is empty. The locations feed reports `connect: {available, endpoint}`, and the wizard renders from that: the option is present but disabled and labelled "not available yet", and its panel says what it will be and — more importantly — that SFTP and S3 do the same job today. Deliberately data-driven: **the day the service exists, setting that one value turns it on.** No release, no code change. Verified by setting it and watching the option go from disabled to a working device-code field, then unsetting it. Showing a disabled option at all is a judgement call: it advertises something that cannot be bought. It earns its place by answering the question the step otherwise raises — "is off-site a thing this can do?" — and by pointing at the free answer in the same breath. ## 4. What the service still has to provide None of this is client work: - accounts, and a device-code flow that yields a per-device credential - a restic-compatible REST endpoint per repository, scoped to that device - quota and retention policy the client can read, so the UI can say what is left - revocation, so a lost machine can be cut off without rotating the repo password ## 5. Open questions 1. **Per-device or per-account credentials?** Per-device is what allows revocation without re-keying every machine, but it means the service tracks devices — which is state about the user it does not otherwise need. 2. **Does Connect ever hold the repository password?** It must not. But then a user who loses it loses the backup, and a hosted service is exactly what someone buys to avoid that responsibility. The honest answer is that it cannot be both; the escrow file and saying so plainly is the current answer. 3. **What does the wizard do about quota before an account exists?** Nothing to show until the endpoint answers, so the step stays silent rather than guessing.