Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ verified, tried, and decided belongs in the commit message and the PR body.
- **A value the `config.php` grammar cannot model is carried through as source text — never narrow `Raw` into a hard failure.** `occ` runs inside the service container, so a value that stops the read is a brick with no way to reach the command that would remove it. Malformed input must still fail loudly, which is what bounds `Raw` to a single line: `var_export` never spreads a scalar expression over two, so a run that reaches a newline is a broken file rather than an unmodelled value. A carried-through value is `{ __raw: <source> }`, so a PHP array whose only key is `__raw` and whose value is a string is indistinguishable from one.
- **Comments have to parse.** Nextcloud 34 prepends a banner comment between `<?php` and `$CONFIG` on every config write.
- **A `config.php` number the double cannot print back exactly is carried through as source text too**, so `9223372036854775807`, `1.0` and `1.0E+30` survive a write. Ordinary values stay real numbers, which is what keeps `maintenance_window_start` and `redis.port` reaching their validators — do not widen this into writing every integer as a float.
- **The FileBrowser Quantum mount's `idmap` (uid 1000 → `www-data` 33) is what makes the integration work at all**, and it needs StartOS 0.4.0-beta.10+. Files other services drop into FileBrowser Quantum's volume under a different uid surface as `nobody` until those services idmap their own mount to 1000 too.
- **Adding an external-storage source is a registry edit in `startos/externalStorage.ts` plus a typed mount.** FileBrowser Quantum is the shared hub most services route through, so a direct source is worth adding only for a service whose files live browsably on its own volume.
- **The external-storage mounts' `idmap` (uid 1000 → `www-data` 33) is what makes the integration work at all**, and it needs StartOS 0.4.0-beta.10+. Files other services drop into NextExplorer's or FileBrowser Quantum's volume under a different uid surface as `nobody` until those services idmap their own mount to 1000 too.
- **Adding an external-storage source is a registry edit in `startos/externalStorage.ts` plus a typed mount.** NextExplorer is the shared hub most services route through, so a direct source is worth adding only for a service whose files live browsably on its own volume. Keep NextExplorer's `dataDir` on the `Files` drive: its volume root also holds every account's private `_users` tree.
- **`richdocuments` drops the Microsoft formats the moment a second office connector is enabled** (`CapabilitiesService::hasOtherOOXMLApps` checks `onlyoffice` and `officeonline`), and the second app does not claim them unless it is configured — so Word, Excel and PowerPoint open in neither and silently download. That is what the `office-connectors` health check exists to catch; don't simplify it away because the reconcile disables the outgoing connector on a switch, which does not stop a user enabling one by hand.
- **`richdocuments:activate-config` fetches the discovery document as it runs, so the `office-suite` oneshot waits on the document server's own health check before it touches anything** — a bridge address resolves well before `coolwsd` accepts a connection. Do not turn that wait into a retry: a oneshot whose fn rejects is re-invoked on a widening backoff forever, so a suite selected against a stopped or uninstalled service would run `occ` for the life of the chain. Past the gate the steps do throw, and that same re-invocation is what retries them — gate first, so a server that goes away parks the retry.
- **Install and upgrade progress phases are driven by the stock entrypoint's own log lines** — `Initializing nextcloud`, `Starting nextcloud installation`, and the `pre-upgrade` hook scan. Re-read `/entrypoint.sh` when bumping the image: a reword leaves a bar indeterminate instead of failing anything, so nothing else will tell you.
24 changes: 13 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Three volumes.
| `db` | `/var/lib/postgresql` | The PostgreSQL data directory |
| `main` | — (host side) | `store.json`; never mounted into a container |

An external-storage source's volume is mounted into the Nextcloud container as well — FileBrowser Quantum's lands at `/mnt/filebrowser`, outside the `nextcloud` volume. **That mount uses `idmap`** to remap the source's on-disk uid to `www-data`, so Nextcloud simply owns the tree: it reads, writes, and moves files with no permission machinery, and the files it creates land back on disk under the source's own uid so the source can still manage them.
An external-storage source's volume is mounted into the Nextcloud container as well — NextExplorer's lands at `/mnt/nextexplorer` and FileBrowser Quantum's at `/mnt/filebrowser`, outside the `nextcloud` volume. NextExplorer's `files_external` entry exposes only its `Files` drive, because the volume root also holds every account's private `_users` tree. **That mount uses `idmap`** to remap the source's on-disk uid to `www-data`, so Nextcloud simply owns the tree: it reads, writes, and moves files with no permission machinery, and the files it creates land back on disk under the source's own uid so the source can still manage them.

## File Models

Expand Down Expand Up @@ -105,13 +105,14 @@ Three settings depart from what upstream would do:

## Dependencies

None are required. Both are optional and exist only while they are selected.
None are required. All are optional and exist only while they are selected.

| Dependency | Kind | Health checks | Required |
| ------------------ | --------- | ---------------- | ---------------------------------------------------------------------------------------------------- |
| `filebrowser` | `exists` | — | Only while chosen in the External Storage action |
| `coturn` | `running` | **none** | Only while Talk call relaying is on in the Configure action |
| `collabora-online` | `running` | `cool` | Only while chosen in the Office Suite action |
| Dependency | Kind | Health checks | Required |
| ------------------ | --------- | ---------------- | ----------------------------------------------------------------------------------------------------- |
| `nextexplorer` | `exists` | — | Only while chosen in the External Storage action |
| `filebrowser` | `exists` | — | Only while chosen in the External Storage action |
| `coturn` | `running` | **none** | Only while Talk call relaying is on in the Configure action |
| `collabora-online` | `running` | `cool` | Only while chosen in the Office Suite action |
| `onlyoffice-docs` | `running` | `documentserver` | Only while chosen in the Office Suite action; published to the Community Registry, not the Start9 one |

The External Storage action offers only the sources whose backing service is actually installed, so an uninstalled one never appears in the form.
Expand Down Expand Up @@ -192,7 +193,7 @@ Selects the document server that opens office files — Collabora Online, ONLYOF

The wait is a subscription, not a poll. It runs no commands, cannot fail, and releases the moment the service becomes ready — a few tens of seconds into an ordinary start, or whenever the user installs the service if they selected it first. A bridge address is not a usable readiness signal here: the port is bound, and the address therefore resolves, well before `coolwsd` accepts its first connection.

**A step that fails past that gate is retried, not reported.** The oneshot throws, so the SDK re-invokes it on a widening backoff capped at thirty seconds, and every attempt passes through the gate first — a document server that has gone away parks the retry rather than spinning it. The command's output is in the service log on each attempt, and the Office Connector check reads *Setting up …* until an attempt succeeds. Nothing else is needed to recover: an app installed by hand, or an app store that comes back, is picked up by the next attempt.
**A step that fails past that gate is retried, not reported.** The oneshot throws, so the SDK re-invokes it on a widening backoff capped at thirty seconds, and every attempt passes through the gate first — a document server that has gone away parks the retry rather than spinning it. The command's output is in the service log on each attempt, and the Office Connector check reads _Setting up …_ until an attempt succeeds. Nothing else is needed to recover: an app installed by hand, or an app store that comes back, is picked up by the next attempt.

**The `trusted_domains` entry is load-bearing.** A document server fetches and saves files over the host bridge, and without that entry Nextcloud answers every one of those requests with `Trusted domain error` — the editor opens and then fails to load the document. Nextcloud matches on the host alone, so the bare IP covers whatever port the binding was assigned.

Expand Down Expand Up @@ -253,9 +254,9 @@ A web-interface failure after the grace period is Nextcloud itself: an app that

The transient checks — Recognize Model Download, Memories Indexing, Memories Map Setup, File Scan, Repair — exist only while their task is pending, and report `loading` with a progress message throughout.

**Office Connector** (`office-connectors`) — present only while an office suite is selected, and stateless: each poll re-derives its result from `store.json`, the dependency's status and Nextcloud's enabled-app list, so every state heals on its own. Until the `office-suite` oneshot has applied the selection it reports `loading`: *Waiting for Collabora Online to be ready* while the document server's own health check is not passing — the dependency entry on the service page already says why — and *Setting up Nextcloud Office (Collabora)…* once it is, while the connector is installed and configured. Once applied, it reads the enabled-app list and fails in two distinct cases, each with its own instruction. Reading that list boots PHP, so a passing check polls every two minutes and a failing one every fifteen seconds; the loading states, which read nothing from Nextcloud, poll every five. The two-minute ceiling is also how long a connector someone has just switched off keeps reading as enabled.
**Office Connector** (`office-connectors`) — present only while an office suite is selected, and stateless: each poll re-derives its result from `store.json`, the dependency's status and Nextcloud's enabled-app list, so every state heals on its own. Until the `office-suite` oneshot has applied the selection it reports `loading`: _Waiting for Collabora Online to be ready_ while the document server's own health check is not passing — the dependency entry on the service page already says why — and _Setting up Nextcloud Office (Collabora)…_ once it is, while the connector is installed and configured. Once applied, it reads the enabled-app list and fails in two distinct cases, each with its own instruction. Reading that list boots PHP, so a passing check polls every two minutes and a failing one every fifteen seconds; the loading states, which read nothing from Nextcloud, poll every five. The two-minute ceiling is also how long a connector someone has just switched off keeps reading as enabled.

**The selected suite's connector is not enabled.** It has been removed or switched off since the package set it up. The message says *Install* or *Enable* accordingly — telling someone to install what they already have is how a message stops being read — and names the other way out: selecting `None` in the Office Suite action. Without this the failure is silent: the document server runs, and nothing in Nextcloud opens in it.
**The selected suite's connector is not enabled.** It has been removed or switched off since the package set it up. The message says _Install_ or _Enable_ accordingly — telling someone to install what they already have is how a message stops being read — and names the other way out: selecting `None` in the Office Suite action. Without this the failure is silent: the document server runs, and nothing in Nextcloud opens in it.

**More than one office connector is enabled.** Everything is running and OpenDocument files still open; what breaks is Word, Excel and PowerPoint, silently. `richdocuments` demotes those formats the moment it sees a rival connector enabled, and the rival does not claim them unless it is configured too. The message names the app to disable.

Expand All @@ -281,7 +282,7 @@ Mixed, and each half is scoped deliberately.
5. **PostgreSQL and Valkey are private sidecars.** Neither can be shared with another service or replaced with an external instance.
6. **The admin password is shown once and then discarded.** Reset Admin Password is the only recovery.
7. **The long-running actions restart the service** to run their work, and continue after the action returns.
8. **External storage is limited to registered sources** — currently FileBrowser Quantum — and only while that service is installed.
8. **External storage is limited to registered sources** — NextExplorer and FileBrowser Quantum — and only while that service is installed.
9. **Talk's default `stun.nextcloud.com:443` is left in place** when relaying is enabled. Coturn's own STUN entry is added alongside it rather than replacing it, since removing an entry the package did not add is the admin's call; delete it in Talk's admin settings to keep reflexive discovery entirely on your own server.
10. **Talk call relaying is Coturn or nothing.** There is no field for an external TURN server — configure one directly in Talk's admin settings instead, and leave the toggle off.
11. **No riscv64 build.** x86_64 and aarch64 only.
Expand Down Expand Up @@ -321,6 +322,7 @@ startos_managed_env_vars:
- NEXTCLOUD_ADMIN_PASSWORD # install only
- NEXTCLOUD_UPDATE # the init-time upgrade run only
dependencies:
- nextexplorer # optional, exists; only while selected as an external-storage source
- filebrowser # optional, exists; only while selected as an external-storage source
- coturn # optional, running, no health checks; only while Talk call relaying is on
- collabora-online # optional, running, health check `cool`; only while selected as the office suite
Expand Down
4 changes: 2 additions & 2 deletions instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Point a Nextcloud desktop or mobile client (or any WebDAV client) at the **WebDA
### Actions

- **Configure** — set the default locale, default phone region, how long deleted files are kept before Nextcloud removes them for good (**Delete Files in Trash** — by default they are kept at least 30 days and then cleared only when disk space runs short, so trash can pile up on a server with room to spare), the UTC start hour of Nextcloud's nightly maintenance window for background jobs, a toggle to stop seeding new user accounts with Nextcloud's default skeleton files (sample documents, photos, README), and **Relay Talk Calls Through Coturn** (see below).
- **External Storage** — surface another StartOS service's storage as a folder in your Nextcloud **Files**, using Nextcloud's built-in External Storage app. The action lists a dropdown for each supported service **you have installed** (today just **FileBrowser Quantum** → a `/FileBrowser` folder). Each dropdown is **Not mounted** (off), **Available to all users**, or **Available to specific users** (which then lets you pick exactly which Nextcloud users see it). The folder is read-write, so you can **move files out of it into Nextcloud**. Nextcloud must be **running** to run this action (it reads your live user list). Files other services add to FileBrowser Quantum appear automatically when you open the folder — so FileBrowser Quantum acts as the shared hub: point any service that should be visible in Nextcloud at FileBrowser Quantum.
- **External Storage** — surface another StartOS service's storage as a folder in your Nextcloud **Files**, using Nextcloud's built-in External Storage app. The action lists a dropdown for each supported service **you have installed** (**NextExplorer** → a `/NextExplorer` folder showing its Files drive, **FileBrowser Quantum** → a `/FileBrowser` folder). Each dropdown is **Not mounted** (off), **Available to all users**, or **Available to specific users** (which then lets you pick exactly which Nextcloud users see it). The folder is read-write, so you can **move files out of it into Nextcloud**. Nextcloud must be **running** to run this action (it reads your live user list). Files other services add to NextExplorer or FileBrowser Quantum appear automatically when you open the folder — so NextExplorer acts as the shared hub: point any service that should be visible in Nextcloud at NextExplorer.
- **Reset Admin Password** — pick an admin user and generate a new random password. Use this if the admin password is lost or you want to rotate it.
- **Disable Maintenance Mode** (Maintenance group) — runs `occ maintenance:mode --off`. Brief maintenance mode after an update or restart is normal — wait at least 15 minutes before resorting to this. Nextcloud version updates now run as part of the StartOS update step and roll back cleanly if they fail, so you should rarely need this.
- **Disable Non-default Apps** (Maintenance group) — disables every enabled app that Nextcloud does not ship, keeping the bundled set plus Calendar and Contacts. Use this if a third-party app has broken the UI with an Internal Server Error. The result lists what was disabled, and separately anything that could not be, so a single stuck app does not stop the rest. Stable apps must then be re-enabled individually from the Nextcloud Apps page.
Expand Down Expand Up @@ -80,7 +80,7 @@ For one document that costs you nothing — you would never notice, and you coul

## Limitations

- **No arbitrary host directory mounts.** You can surface another StartOS service's files with the **External Storage** action (currently FileBrowser Quantum), and you can attach remote storage (S3, WebDAV, SMB, etc.) through Nextcloud's built-in External Storage app. StartOS does not expose arbitrary host directories to the container.
- **No arbitrary host directory mounts.** You can surface another StartOS service's files with the **External Storage** action (NextExplorer or FileBrowser Quantum), and you can attach remote storage (S3, WebDAV, SMB, etc.) through Nextcloud's built-in External Storage app. StartOS does not expose arbitrary host directories to the container.
- **No built-in SMTP.** Configure email under Nextcloud's **Administration settings → Basic settings → Email server**.
- **PHP memory limit is 1024 MB and the per-file upload limit is 20 GB.** These are not user-configurable.
- **Update one major Nextcloud version at a time.** Nextcloud only supports upgrading a single major version per step. An update that would jump more than one major version at once is refused with a clear message before anything changes; install the release it names from the version list, then update again. Keep the service updated regularly rather than letting several releases pile up.
Loading
Loading