aboutsummaryrefslogtreecommitdiffstats
path: root/docs/USERGUIDE.md
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-19 01:49:11 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-19 01:49:56 +0200
commit3e7c7eba8e512df852da38a6b9ddd8467ec4d4e7 (patch)
treeac529c48cb40cb4c795a61345365fca07f47e965 /docs/USERGUIDE.md
parentc2c49182e6d4f1f1ef3ed3ba5e8699912f9a27bd (diff)
downloadmeshbay-3e7c7eba8e512df852da38a6b9ddd8467ec4d4e7.tar.gz
docs: add a quickstart and a user guide
QUICKSTART takes one Linux machine from downloaded packages to a working group with a second member. USERGUIDE covers using a group and running a node, for a reader who is not a developer. Windows stays in PACKAGING-GUIDE.md. Both are written from the code — the CLI, ops.py, the systemd units and the interface catalogue — rather than from the specification, and they state what is not built as readily as what is. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'docs/USERGUIDE.md')
-rw-r--r--docs/USERGUIDE.md861
1 files changed, 861 insertions, 0 deletions
diff --git a/docs/USERGUIDE.md b/docs/USERGUIDE.md
new file mode 100644
index 0000000..9f7cea7
--- /dev/null
+++ b/docs/USERGUIDE.md
@@ -0,0 +1,861 @@
+# MeshBay — User Guide
+
+This guide is for people who **use** MeshBay and for people who **run** a node.
+
+If you have not installed anything yet, start with
+[`QUICKSTART.md`](QUICKSTART.md) and come back here.
+
+**Contents**
+
+1. [What MeshBay is](#1-what-meshbay-is)
+2. [Your account](#2-your-account)
+3. [Your devices](#3-your-devices)
+4. [Joining a group](#4-joining-a-group)
+5. [Using a group](#5-using-a-group)
+6. [Running a node](#6-running-a-node)
+7. [Managing people](#7-managing-people)
+8. [What is private, and what is not](#8-what-is-private-and-what-is-not)
+9. [When something breaks](#9-when-something-breaks)
+10. [Reference](#10-reference)
+11. [Running your own hub](#11-running-your-own-hub)
+12. [What this software does not do yet](#12-what-this-software-does-not-do-yet)
+
+---
+
+## 1. What MeshBay is
+
+MeshBay gives a small group of people — a family, a household, a few friends —
+private access to files that live on **somebody's own machine**, with
+applications over them: a chat, a file explorer, a video library, a music
+player, a photo album.
+
+It is not a public file-sharing network and it is not a cloud. Nothing is
+uploaded to a company. The files stay where they already are.
+
+### The three parts
+
+**The hub** (meshbay.org, or one you run) holds accounts and the list of
+groups, and introduces two machines to each other. Under a kilobyte of
+connection setup passes through it. For a private group — the default, and what
+this guide assumes — it never sees a file, a message, a file name or a key. §8
+says exactly where that stops.
+
+**The node** is a daemon on the machine that holds the files. It holds the
+group's encryption key, and it is the only thing that decides who gets served.
+Not the hub — the node. If the hub invented an account and put it in your
+group, the node would still refuse it.
+
+**The client** is either the web application the hub serves, or the desktop
+application you install. Both are the same interface.
+
+### The one idea that explains the rest
+
+> **Everything about a group lives on the machine that hosts it.**
+
+The files, the list of them, who has been let in, invitations, chat history,
+which folders allow uploads, how each application is set up — all of it on that
+machine. The hub keeps accounts, group names and who belongs to what, and
+nothing more.
+
+That is why the person running the group sends you the invitation code rather
+than the website. It is why a hub having a bad day loses nothing. And it is why
+there is no "I forgot my group" button to press.
+
+### What a group is
+
+A group is **people + directories + applications**.
+
+```
+ A group's contents, as members see it
+ ─────────────────────────────────────
+ /
+ ├── Films/ → /mnt/library/films on the operator's machine
+ ├── Music/ → /mnt/audio an external drive
+ └── Documents/ → /home/them/share read-write: members may upload
+```
+
+Each of those is a **root** — a named directory. Members see the names; they
+never see, and never name, a path on the operator's disk.
+
+---
+
+## 2. Your account
+
+Your account lives on a hub. It is a username, an email address, and a
+passphrase — and the passphrase is the part worth understanding.
+
+### Your passphrase is not a password
+
+It never reaches the hub. Your browser turns it into two separate values: one
+that proves who you are to the hub, and one that encrypts **your identity keys**
+where they are stored — on each node you have joined.
+
+Two consequences:
+
+- **The hub can reset your sign-in. Nobody can reset your keys.** A hub
+ operator, a node operator and the authors of this software are all equally
+ unable to open your keys. There is no back door, no support ticket, no
+ recovery from a database.
+- **A good passphrase is worth more here than anywhere else.** Twelve
+ characters is the minimum the sign-up page accepts; four unrelated words is
+ the shape that really protects you. The locked copy of your keys on each
+ machine you join is only as strong as what locks it.
+
+### Your recovery key
+
+Shown **once**, at sign-up. It is a long random secret rendered as words. Put it
+in a password manager.
+
+What it is for: a second, recovery-encrypted copy of your identity is stored on
+each node beside the passphrase-encrypted one. With the recovery key, a
+passphrase reset also restores your access to your groups. Without it, a reset
+restores your sign-in only, and every group has to be rejoined by hand with a
+fresh code from its operator.
+
+If you missed it at sign-up, or you signed in from a new browser: **Settings →
+Recovery key → Enter recovery key** adds the backup copies to every group whose
+node is reachable.
+
+### Forgetting your passphrase
+
+**Sign-in → "Forgot your passphrase?"** You need your username **and** the
+email address on the account — the page says the same thing either way, so if
+no code arrives, one of the two did not match.
+
+A code arrives by email. Enter it with a new passphrase, and your recovery key
+if you have one.
+
+A reset also signs out every device that had been signing in by itself, so each
+one asks for your passphrase once more. That is on purpose: if you are
+resetting because something may have gone astray, a laptop that still lets
+itself in is the thing you want stopped.
+
+### Changing a passphrase you still know
+
+**Settings → Passphrase → Change passphrase.**
+
+Your keys are re-encrypted on every group whose node is online **before**
+anything changes on the hub — so if it fails half way, nothing has changed.
+Groups whose nodes were offline are listed by name afterwards; for each one,
+ask its operator to unpin you and send a fresh code.
+
+### Deleting your account
+
+**Settings → Delete account.** It removes your account, memberships and
+notifications from the hub, and frees your username.
+
+What it cannot reach is anything sitting on other people's machines: files you
+uploaded stay where their operator keeps them, and each node remembers you
+until its operator says otherwise. Connection logs are kept for a year, as the
+law requires.
+
+---
+
+## 3. Your devices
+
+You can use one account from several devices — a laptop browser, a phone, the
+desktop application. Each one gets **its own key on each machine you join** —
+they are not copies of one key, and the key you hold on one person's machine
+means nothing on another's.
+
+### Adding a device
+
+The first time a new browser opens a group, it says *"This browser is not
+linked to this node yet"* and offers a code. You then approve it **from a
+device that is already linked** — Members tab → *"Linking a new device? Enter
+the code it is showing."*
+
+No operator is involved and the code never passes through the hub — one of
+your own devices vouches for the new one, which is what stops anybody else
+adding a device to your account.
+
+A few limits: **five devices per account on each machine**, a code lasts an
+hour, and five wrong codes in a row stop the attempt.
+
+### Removing a device
+
+**Settings** on the node's group, or the Members tab: *Remove*. It loses access
+to that node until it is linked again. Removing a device also moves the chat
+key on, so it cannot read anything written from then on.
+
+### One passphrase, several browsers
+
+A second browser on a machine you have already joined picks up the *same*
+identity: it asks for your passphrase, unlocks the copy of your keys kept
+there, and you are in. No second code, nobody to ask — which is another reason
+the passphrase is worth choosing well.
+
+### The desktop application
+
+Worth installing if you use MeshBay more than occasionally:
+
+| | Browser | Desktop application |
+|---|---|---|
+| Install | none | a package |
+| Interface comes from | the hub, on every visit | inside the package, from disk |
+| Keys | in the browser, plus a copy on each node | in the OS keyring, never bundled anywhere |
+| Downloads | to disk where the browser allows it | native, streamed, no size limit |
+| Casting to a TV | — | yes |
+
+The difference that matters: a browser fetches its code from the hub every time
+you open it, while the application carries its own and never asks the hub for
+any. So the application is the one to prefer for anything you care about. The
+browser stays, and is a perfectly reasonable way to use MeshBay — being able to
+open a group on someone else's laptop with nothing installed is worth having.
+
+---
+
+## 4. Joining a group
+
+Someone who runs a node invites you. You need an account on the same hub first.
+
+1. **They send you a code** — eight characters like `K7P2-9WQX`, by message,
+ mail, or read out loud. It is good for 7 days by default, works once, and
+ only for your account in that one group.
+2. **You sign in**, and the group is already in your sidebar.
+3. **You open it.** It says *"This node needs to recognise you"*. Paste the
+ code.
+4. Done — the machine hosting the group recognises you from now on, and the
+ files appear.
+
+You will not be asked again on that browser, or on that machine.
+
+**The code never passes through the hub**, and that is the whole reason it
+exists: it proves the invitation came from the person running the group, and
+not from the service in the middle.
+
+### Leaving
+
+Group menu → **Leave group**. You lose access to its files and chat. Anything
+you uploaded stays on the machine hosting the group, which also remembers you
+until its operator says otherwise.
+
+---
+
+## 5. Using a group
+
+A group is a set of tabs. Which ones you see is the operator's choice; **Files**
+and **Settings** are always there.
+
+### Files
+
+The explorer. Roots are the top-level folders; below that it behaves like any
+file browser — sort, select, download, preview.
+
+- **Upload** appears only where the current folder is in a **read-write** root.
+ You can also drag files and whole folders onto the file list.
+- **A drop is decided before anything is sent.** A name already in the folder,
+ or a name the node cannot store, cancels the whole drop and tells you which
+ name caused it — so you never end up with half a copy.
+- **Download a folder as a zip**, built in your browser from the same encrypted
+ chunks as any other download. The node never compresses anything.
+- **Delete** — you can remove a file you uploaded yourself; anything else is
+ the operator's to remove. A folder has to be empty first, so nothing here can
+ sweep away files you cannot see.
+
+### Chat
+
+Per-group messages, always encrypted, with threads, attachments and link
+previews.
+
+- **Attachments** need a read-write folder in the group. Where there is none,
+ the paperclip is off and says so.
+- **Link previews** are fetched **by the node** — the machine hosting the group
+ makes a request to whatever site somebody linked. The operator can turn it
+ off.
+- **History is kept on the node**, and stays readable to members. A member
+ removed from the group cannot read anything written after their removal.
+- Sometimes a message reads *"Written before this device could read this
+ conversation"* — that is a device added later, not an error. A message marked
+ *"the signature does not match the sender"* is different and worth asking
+ about.
+
+### Videos
+
+A poster browser over the folders the operator chose for it. Two modes: a
+poster grid with artwork and summaries, and a plain folder-driven list that
+needs no third-party service at all.
+
+- **Nothing appears until the operator chooses at least one folder** — the tab
+ tells you so, rather than just looking empty.
+- Films and shows are **one card each**, not one per file; a show expands into
+ seasons and episodes.
+- The operator can **correct a wrong match**, and the correction applies to the
+ whole show rather than one episode.
+- Streaming has **seeking, audio-track selection and subtitles**. Picture-based
+ subtitle tracks (the ones stored as images rather than text) are not offered:
+ they would need text recognition to display, so they are left out rather than
+ listed and blank.
+- A library is read **a page at a time**; the page size is your own preference
+ in Settings, not the group's.
+
+### Music
+
+An album browser and a player, over the folders the operator chose for it.
+
+- Tags in your files come first, then folder and filename, then a lookup for
+ cover art or canonical spelling.
+- **The player survives leaving the tab** — go to Files, go to another group,
+ the music keeps playing.
+- **Playlists are yours, not the group's**, and follow you across groups and
+ devices. Favourites, queues saved as playlists, drag to reorder.
+
+### Photos
+
+An album browser over the folders the operator chose for it, where **an album
+is a folder**. Thumbnails come from the node, already rotated correctly.
+
+**Location data is never shown.** Photos shows when a picture was taken and
+what took it, and no coordinates anywhere. Worth knowing, though: the
+coordinates are still inside the photo itself, as your phone wrote them, so
+anyone who downloads the original file has them. Strip them before sharing if
+that matters to you.
+
+### Search
+
+The magnifying glass in the sidebar searches **across every group you are in**
+at once, with a Files / Videos / Music / Photos view each.
+
+A file that two groups both have is **one result**, not two — identity is the
+content, not the path. Each result says which group it came from, or how many.
+
+An operator can keep a group out of Search. It is a tidiness setting and
+protects nothing: members still see everything by opening the group.
+
+### Transfers
+
+The transfers panel shows what is moving. Downloads queue, run, pause and
+resume.
+
+- The node runs a limited number at once, and each member has their own share
+ so nobody can take the machine. Queued transfers say what they are waiting
+ for.
+- **Pausing needs a download folder** chosen in Settings → Downloads. Without
+ one, your browser decides where files go and a transfer cannot be resumed.
+- **Browsing is never queued.** Posters, thumbnails, opening a photo or a
+ document to look at it — none of it takes a transfer slot. A busy group
+ browses exactly like an idle one.
+
+### Casting to a TV
+
+**Desktop application only.** A film playing in the application can be sent to a
+cast-capable TV or dongle on the same network: *Cast to device* in the player,
+pick one from the list.
+
+The application decrypts the film and relays it to the TV itself, over your LAN.
+The TV is not a group member and holds no key — which is also why the relay's
+ports have to be reachable on the local network (§10).
+
+Subtitles travel with it. Other TV protocols — the UPnP/DLNA family — are
+designed and not built.
+
+### Notifications and settings worth knowing
+
+**Settings → Downloads** — save automatically to a folder, or ask every time.
+**Settings → Defaults** — which tab a group opens on, how many items per page.
+**Settings → Appearance** — theme and language (ten languages ship).
+**Group menu → Mute** — stop notifications for one group.
+
+---
+
+## 6. Running a node
+
+This section is for the person whose machine holds the files.
+
+### What you decide
+
+Your node, not the hub, decides who gets served and what gets served — from a
+list you build yourself with invitation codes. Two things follow from that:
+
+- The hub can tell somebody your group exists and point them at your machine,
+ but it cannot get them let in. Only your invitation does that.
+- **Your own browser counts as a stranger until you pair it**
+ (`meshbay-node operator pair`). Until then it cannot invite anyone or delete
+ anything — which is a little surprising the first time, and is what keeps the
+ decision yours.
+
+### Two ways in
+
+| | |
+|---|---|
+| **The CLI**, over SSH | no browser needed, and it works while the daemon is stopped |
+| **A paired browser** | the group's Settings and Members tabs, and the Node page in the desktop application |
+
+On a headless server the CLI is the only path, and it covers everything you
+need to run a group. One gap is known: removing **one** device of one member is
+only doable from the interface (§7). Start with:
+
+```bash
+meshbay-node status
+```
+
+It reports what is configured, what is running, and — when something is
+missing — the command that fixes it.
+
+### Directories (roots)
+
+A group's content is a set of **named directories**. The name members see is
+the directory's own basename, fixed when you add it.
+
+```bash
+meshbay-node root list
+meshbay-node root add /mnt/library/films --name Films
+meshbay-node root add /mnt/usb/archive --removable
+meshbay-node root set Films --writable
+meshbay-node root remove Films
+```
+
+Rules that will bite you if you do not know them:
+
+- **Two roots cannot share a basename**, even on different drives. `/mnt/a/Films`
+ and `/mnt/b/Films` is refused; name one of them explicitly.
+- **No root inside another.** The same bytes would be indexed twice under two
+ identities.
+- **Renaming a root rewrites every path under it**, so it is an explicit act,
+ not a cosmetic one.
+- The first directory of a new group is **read-write**; every root added later
+ is **read-only** unless you say otherwise.
+
+### Read-only and read-write
+
+A read-only directory is read-only **for everybody, including you**. That is
+intentional: a library you have published as read-only should stay as you
+arranged it, and an accidental drag-and-drop from your own browser is as
+unwelcome as anyone else's.
+
+Whether uploads are allowed is decided per directory and nowhere else. A group
+can have several directories open for uploads, or none at all — a group nobody
+can add to is a perfectly normal thing to want.
+
+### External drives
+
+Mark a root `--removable` and you get **Eject** and **Plug in** beside it.
+
+Eject before you unplug. It stops watching that directory and freezes its files
+in the index — they stay listed and are reported as unavailable, rather than
+looking to every member as though you deleted your library. Plug in checks the
+path is really back, then rescans.
+
+If a removable root's path disappears without an eject, the node ejects it for
+you. Nothing is deleted: index entries, thumbnails, metadata and chat history
+referring to those files all survive.
+
+Remember the systemd drop-in for anything outside your home directory — both
+`ReadWritePaths` and `RequiresMountsFor`. It is in
+[`QUICKSTART.md` Step 5](QUICKSTART.md#step-5--start-the-node).
+
+### Indexing
+
+The node watches its directories and re-checks them periodically — the periodic
+pass is not a backstop, it is required, because filesystem events are dropped
+under load and are unreliable on network and FUSE mounts.
+
+Files over 40 MB are identified by reading their beginning, end and middle
+rather than the whole file. A 4 TB library does not need 4 TB of reading to be
+catalogued.
+
+Group → Settings has the re-check interval and how long the node waits after a
+file changes before indexing it. Members see indexing progress while it runs.
+
+One thing that surprises people: **two identical files in one group are one
+entry**, because a file is identified by its content. A scan that reports ten
+files and indexes nine has not lost anything.
+
+### Applications and their folders
+
+Group → **Members → Applications** turns applications on and off for everyone.
+Files and Settings always stay.
+
+Group → **Settings** points each application at folders:
+
+- **Videos**, **Music** and **Photos** — as many folders as you like for each.
+ A library is rarely in one place, so pick every folder that belongs to it and
+ leave out the rest. Each tab stays empty until at least one is chosen.
+- **Chat** — one folder, for attachments. It has to be one members can write
+ to.
+
+This is not a personal view: it decides what **everyone** in the group sees in
+that tab. The change is signed by your paired browser and reaches connected
+members straight away.
+
+### Metadata from third parties
+
+**Videos** uses a film and TV database for posters, summaries and cast. It ships
+with a default credential and you can set your own; the language is a
+group-wide setting, because there is one shared cache rather than a request per
+viewer. Turn it off and Videos falls back to thumbnails and cleaned filenames,
+with no outside request at all.
+
+**Music** uses a music database for cover art and canonical spelling when a
+track carries none. It needs no credential.
+
+Both lookups are made **by the node**, once per title, for everybody. Your
+members' devices never talk to a third party.
+
+### Node settings
+
+Group Settings covers a group; **Node settings** covers the machine. From the
+desktop application's Node page, or by editing `~/.config/meshbay/node.toml`
+and running `meshbay-node reload`:
+
+| Setting | Default | What it decides |
+|---|---|---|
+| `invite_ttl_hours` | 168 (7 days) | how long an invitation stays usable |
+| `pair_ttl_hours` | 24 | how long an operator pairing code lasts |
+| `device_request_ttl_minutes` | 60 | how long a device request waits for approval |
+| `max_concurrent_streams` | 8 | how many people can watch video at once |
+| `max_concurrent_downloads` | 8 | node-wide download slots |
+| `max_concurrent_uploads` | 8 | node-wide upload slots |
+| `max_upload_gb` | 8 | the largest single file a member may send you |
+| `transcode_incompatible_video` | true | re-encode video no browser can play |
+| `hardware_video_encode` | true | use the GPU for that, if one actually works |
+
+`max_concurrent_streams` is the one to think about: a stream costs a video
+process for as long as the film lasts, so this counts **viewers**, not
+requests.
+
+`max_upload_gb` is the only one of these about your disk rather than this
+machine's work. Fractions are allowed — `0.5` is 512 MB — and the new ceiling
+applies to an upload already in progress, so raising it unblocks a file that
+was about to be refused. There is no total quota behind it: a member who can
+write to a folder can still fill the disk one capped file at a time.
+
+Turning transcoding off does two different things depending on the video: one
+your viewers' browsers can decode by themselves plays as it is, and one they
+cannot is refused with a message pointing at this setting.
+
+Changes are saved to the database for immediate effect **and** written back
+into `node.toml` so they survive a reinstall. Your hand-written comments in
+that file are left alone.
+
+---
+
+## 7. Managing people
+
+### Inviting
+
+```bash
+meshbay-node member invite alice_dupont
+```
+
+Or the group's **Members** tab, from a paired browser.
+
+They need an account on the same hub first. The invitation registers their
+membership on the hub and produces a code that never goes near it. Send the
+code out of band; they enter it the first time they open the group. You do not
+need to be online then.
+
+### Seeing who is in
+
+```bash
+meshbay-node member list
+```
+
+Names, roles, when each identity was pinned and how, plus any pending
+invitations.
+
+### Removing someone
+
+```bash
+meshbay-node member revoke alice_dupont
+meshbay-node gek rotate --group "Family Photos"
+```
+
+**Both lines, and the second one matters.** Revoking means the node stops
+handing them the group key on their next connection. It does not take back the
+key they already have — no protocol can. Rotating replaces it: every member
+still in the group gets the new one automatically, and the person you removed
+keeps the old one, which opens nothing written from now on.
+
+Anything they already downloaded stays theirs. Once a file has been copied, no
+software can reach back and take it away.
+
+If you mistype the username, `member revoke` says so rather than quietly doing
+nothing.
+
+### Unpinning, and when to use it
+
+```bash
+meshbay-node member unpin alice_dupont
+```
+
+This forgets **every device** of theirs on this node, so they can pair again
+with a new key. It is the fix for two specific situations:
+
+- Someone lost their passphrase and had no recovery key. Unpin, then send a new
+ invitation code.
+- Someone changed their passphrase while your node was offline, and their group
+ is now unreadable to them.
+
+### Devices
+
+A member's devices are managed **from the interface, not from the CLI** — their
+own *Your devices on this node* list, or your group's Members tab from a paired
+browser. A removed device is remembered as removed, so the same key cannot
+quietly reappear later.
+
+`meshbay-node member unpin <user>` is the CLI's blunt version: it removes
+**every** device that person has on this node, and they pair again from scratch.
+There is no per-device CLI verb today — noted in
+[`MESHBAY_DESIGN.md` §15.3](MESHBAY_DESIGN.md#153-open-and-why-each-is-where-it-is).
+
+### Rotating the group key
+
+```bash
+meshbay-node gek rotate --group "Family Photos"
+```
+
+Connected members get the new key with no action on their part. Anyone revoked
+keeps the old one and loses everything from that point on. Nothing already
+downloaded is affected.
+
+### The audit log
+
+Every admission, refusal, invitation and deletion is recorded on the node. The
+desktop application's Node page shows it and exports it as CSV.
+
+---
+
+## 8. What is private, and what is not
+
+**The short version: your files stay on the machine that hosts them.** They
+travel encrypted and directly to the people that machine has been told to
+serve. The hub that introduced everybody never holds them, and cannot read
+them.
+
+For most people that is the whole answer. The rest of this section is for
+deciding what belongs in a group and what is better kept elsewhere.
+
+### What you can rely on
+
+- **Nothing goes through the hub** — not your files, not their names, not even
+ the list of them. Your devices talk to the node directly.
+- **The hub cannot open your group.** It holds none of the keys, and for a
+ private group it does not know what is in it.
+- **The hub cannot let anybody in.** Only the node decides who it serves, from
+ the list its operator built with invitation codes. An account the hub added by
+ itself gets nowhere.
+- **Only your own devices can add another of your devices.** The hub cannot,
+ and neither can an operator.
+- **You get separate keys in each group you join**, so two people hosting you
+ cannot work out that you are the same person.
+- **Chat history is encrypted where it is stored.**
+- **Your client remembers each node** and refuses one whose identity has
+ changed — which is what stops a machine being quietly swapped for another.
+- **People you have already seen in a group stay checked** every time they post
+ after that.
+
+### Worth knowing before you share something
+
+- **Whoever hosts a group can read what is in it.** The files sit on their
+ machine in the ordinary way, because that is what hosting is. It is the same
+ trust you extend to a friend keeping a spare key to your flat — reasonable,
+ and worth being conscious of.
+- **Everyone in a group sees everything in it.** There is nothing below group
+ level: no per-person permissions, no private corner inside a shared library.
+ If two sets of people should not see the same things, make two groups.
+- **The desktop application protects you a little better than a browser.** A
+ browser downloads its code from the hub every time you open it; the
+ application carries its own and never asks the hub for any. For anything you
+ would rather not stake on the hub behaving, prefer the application.
+- **Your passphrase is what guards your keys.** A copy of them, locked with it,
+ sits on each machine you have joined. A long one puts that out of reach; a
+ guessable one does not. This is the single thing most worth getting right.
+- **An open group is open.** Anybody can walk into one, which is what open
+ means. Invite-only is the default, and is what you want for anything personal.
+- **The hub sees who is in which group, and when.** Never what was said or
+ shared — but the pattern of it is visible to whoever runs the hub.
+- **Deleting your account does not delete what you shared.** Files you uploaded
+ stay on the machines hosting them, and each node remembers you until its
+ operator says otherwise. Ask them if it matters.
+
+## 9. When something breaks
+
+### Start here
+
+```bash
+meshbay-node status
+journalctl --user -u meshbay-node -f
+```
+
+`status` works whether or not the daemon is running, and names the command for
+anything missing.
+
+### The common ones
+
+**"No nodes are currently online for this group."**
+The node is not running, is not reachable, or has not linked its key to the
+hub. On the node: `meshbay-node status`, then Step 4 and 5 of the quickstart.
+
+**A member sees the group but no files.**
+They never redeemed an invitation code, or the group has no key
+(`meshbay-node gek init`), or nothing has been indexed yet.
+
+**Members on other networks connect, members on your own LAN do not.**
+The firewall. A browser on your LAN has to be able to call the node, and a node
+refusing unsolicited inbound UDP cannot be called. See
+[`QUICKSTART.md` Step 9](QUICKSTART.md#step-9--let-people-reach-you).
+
+**A shared directory reads as empty and everything else looks right.**
+A mount the service cannot see. The systemd drop-in needs
+`RequiresMountsFor` as well as `ReadWritePaths` — the service has its own mount
+namespace, so a volume mounted after it started is invisible to it.
+
+**"Invitations are signed with the key this node pinned for your browser."**
+The browser is not paired. `meshbay-node operator pair`, then enter the code in
+the Members tab.
+
+**A member changed their passphrase while the node was down.**
+`meshbay-node member unpin <user>`, then a fresh invitation code.
+
+**Video says the codec is not supported.**
+The source codec has no decoder in that browser and transcoding is off, or
+ffmpeg is missing. Check `transcode_incompatible_video` and that ffmpeg is
+installed.
+
+**"Server busy" when starting a film.**
+Every streaming slot is taken. `max_concurrent_streams` counts viewers, and
+each one holds a slot for the whole film.
+
+**A download stops near the end in the browser.**
+Choose a download folder in Settings → Downloads, which switches the browser to
+writing straight to disk, and retry. The desktop application does not have this
+class of problem.
+
+**Nothing appears in Videos, Music or Photos.**
+No folders have been chosen for that application yet. Group → Settings. The tab
+says so rather than just looking empty, but it is easy to miss.
+
+### After changing config by hand
+
+```bash
+meshbay-node reload # re-read node.toml without dropping anyone
+meshbay-node restart-daemon # full restart — drops live streams
+```
+
+Prefer `reload`. A restart kills every connection, which for someone watching a
+film looks like a failure they caused.
+
+---
+
+## 10. Reference
+
+### Node commands
+
+```
+meshbay-node status what is configured and running
+meshbay-node init first-time setup
+meshbay-node reset erase all node state (destructive)
+
+meshbay-node group list|add|remove groups this node hosts
+meshbay-node root list|add|remove|set directories in a group
+meshbay-node root eject|plug removable drives
+meshbay-node gek init|rotate the group's encryption key
+
+meshbay-node operator pair authorise a browser
+meshbay-node member list|invite|revoke|unpin people
+
+meshbay-node file list|rm files, from the machine itself
+meshbay-node chat status|rotate|encrypt-history|prune
+meshbay-node transfers show|set|max-size|per-member
+ transfer limits, and the
+ largest single upload
+meshbay-node denylist show|clear
+meshbay-node stun list|add|remove|reset NAT traversal servers
+meshbay-node video rematch re-resolve video metadata
+
+meshbay-node reload re-read node.toml, hot
+meshbay-node restart-daemon full restart
+```
+
+`--group <name>` selects a group where you host more than one. `--yes` skips
+the confirmation on destructive commands. `man meshbay-node` has the full page.
+
+### Where things live
+
+| | |
+|---|---|
+| `~/.config/meshbay/node.toml` | configuration — hand-edited, commented, preserved |
+| `~/.config/meshbay/node.env` | environment: keystore unlock, third-party tokens |
+| `~/.config/meshbay/keystore.enc` | the node's own keys. **Back this up.** |
+| `~/.config/meshbay/unlock.key` | what opens the keystore. Mode 0600. |
+| `~/.local/share/meshbay/` | roster, indexes, chat, caches, thumbnails |
+| `/opt/meshbay-common/venv/` | the shared Python environment |
+
+Losing the keystore means a new node identity: every group has to be re-linked
+and every member re-admitted. It is small — back it up somewhere safe.
+
+### Ports
+
+| | |
+|---|---|
+| **inbound UDP, ephemeral** | peer connections. Scope the rule to your LAN. |
+| **127.0.0.1:18000** | the node's own control API. Loopback only, behind a per-run token, never exposed. |
+| **TCP 19550-19553, UDP 5353** | casting to a TV, desktop application only, LAN only |
+
+### Defaults worth remembering
+
+| | |
+|---|---|
+| Invitation code | 7 days, single use, one account, one group |
+| Operator pairing code | 24 hours |
+| Device linking code | 1 hour |
+| Devices per account per node | 5 |
+| Upload size limit | 8 GB per file, settable on the node |
+| Transfers at once | 8 node-wide, 2 per member per group |
+| Video streams at once | 8 |
+
+---
+
+## 11. Running your own hub
+
+You do not need to. meshbay.org exists, is free, and sees nothing of your
+content. Run your own if you want nobody else holding your account list, or you
+want a hub that is not reachable from the internet at all.
+
+A hub is a Linux server with PostgreSQL, a reverse proxy for HTTPS, and
+somewhere to send mail from. The steps are in:
+
+- [`PACKAGING-GUIDE.md`](PACKAGING-GUIDE.md) — install, database, configuration, first start
+- [`HTTPS.md`](HTTPS.md) — the reverse proxy and certificates
+- [`MAIL-SERVER.md`](MAIL-SERVER.md) — outgoing mail, which sign-up and recovery need
+
+Two things to know before you start. **Your hub serves the web application**,
+so anyone using a browser against it is trusting you with their keys — the
+same relationship you have with meshbay.org, pointed at you. And **a hub cannot
+be moved**: accounts, group registrations and node links are all on it.
+
+---
+
+## 12. What this software does not do yet
+
+Better to know now than to go looking for it:
+
+- **Packages are not signed**, and there is no signed repository yet, so there
+ is nothing to check a download against and no updates through your
+ distribution. Until that ships, take them from the download page and from
+ nowhere else.
+- **There is no Android client.** A phone browser works.
+- **A node cannot be hosted on Android**, and is not planned to be.
+- **Hubs do not talk to each other yet.** Everyone in a group needs an account
+ on the same hub.
+- **Casting reaches Chromecast devices** from the desktop application. Support
+ for other TV protocols is designed but not built.
+- **Some subtitle tracks cannot be shown** — the ones stored as images rather
+ than text, roughly one embedded track in five. Displaying them would need
+ text recognition.
+- **There is no overall storage quota.** Files are capped at 8 GB each — lower
+ or raise it on the node, above — but somebody can still fill a disk one file
+ at a time. Worth a glance now and then if you have opened a folder to people
+ you do not know well.
+- **Searching the film database by hand has no per-member limit**, and it draws
+ on the node's own quota. Only likely to matter on a large group.
+- **The record of who uploaded what belongs to the node.** It is kept and it is
+ accurate, but other members have no way to check it for themselves.
+- **Chat history stays readable to everyone in the group**, including people
+ who join later. That is what makes it a shared history rather than
+ disappearing messages — but if a conversation should leave no trace, it does
+ not belong here.
+- **Your client remembers each node's identity, but not the hub's.** It matters
+ less than it sounds: a stand-in hub still cannot read anything, and cannot
+ touch the desktop application at all.