docs(audiobookshelf): the phone app's connection facts and where its token lives #127

Merged
dank merged 1 commits from docs/abs-phone-app into main 2026-11-02 19:11:24 -08:00
Showing only changes of commit 03e0d84380 - Show all commits
@@ -65,6 +65,22 @@ never `/healthcheck`. It also reads files that are genuinely broken and logs
`[AudioFileScanner] Invalid data found when processing input` per file — that is `[AudioFileScanner] Invalid data found when processing input` per file — that is
the file, not the bind: the same line count grows while the total climbs. the file, not the bind: the same line count grows while the total climbs.
## Phone app
The official **Audiobookshelf** app connects with Server Address
`http://192.168.0.235:8000`, username `frank`, and the same password as the web UI —
no base-path prefix, plain HTTP. Verified from a second host 2026-11-03: `/healthcheck`
and `/ping` answer 200 across the LAN and `iptables -S INPUT` carries no rule for 8000,
so a phone on `192.168.0.0/24` connects with no further setup; `download: true` on the
root account is what makes offline listening work. Away from the LAN it cannot connect —
see the LAN-only law, and note that the guard chain is not the remedy there.
**The login token is at `user.token`, not top level.** `POST /login` answers
`{ user, serverSettings, ereaderDevices, Source, userDefaultLibraryId }` and the bearer sits
inside the user object. A client that reads `response.token` gets the empty string, sends
`Authorization: Bearer ` with nothing after it, and every `/api/*` call then answers `401`
as though the password were wrong.
## Laws ## Laws
- **Speak the image's env names, not the README's.** The server reads `PORT`, - **Speak the image's env names, not the README's.** The server reads `PORT`,
@@ -108,7 +124,10 @@ the file, not the bind: the same line count grows while the total climbs.
- **LAN-only until Frank says otherwise.** `0.0.0.0:8000` with no reverse proxy - **LAN-only until Frank says otherwise.** `0.0.0.0:8000` with no reverse proxy
in front. Any public vhost requires the Anubis + Authentik chain first, and the in front. Any public vhost requires the Anubis + Authentik chain first, and the
outpost proxy provider has to exist before the vhost flips (external exposure outpost proxy provider has to exist before the vhost flips (external exposure
policy in `AGENTS.md`). policy in `AGENTS.md`). That chain serves browsers: the phone app is a non-browser
client and cannot solve a challenge, so guarding a vhost does not make remote
listening work — remote listening wants a VPN into the LAN, after which the LAN
address in *Phone app* is correct unchanged.
- **There is no `/setup` route; the creation door is `POST /init`.** `/status` - **There is no `/setup` route; the creation door is `POST /init`.** `/status`
(no `/api` prefix) reports `isInit` = "a root user exists", `POST /init` with (no `/api` prefix) reports `isInit` = "a root user exists", `POST /init` with
`{"newRoot":{"username","password"}}` creates it, `POST /login` returns the `{"newRoot":{"username","password"}}` creates it, `POST /login` returns the