Commit Graph

1887 Commits

Author SHA1 Message Date
Pablo Zmdl 84341f4c71 Use test path that exists on macos, too
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-06-25 17:22:06 +02:00
Simon L. 3d13a55e10 PHP dependency updates (#8375) 2026-06-25 14:58:06 +02:00
Simon L. 6fc913bc41 eurooffice should only get enabled on new instances
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-24 14:58:40 +02:00
szaimen 0bfcb3696c php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-24 12:41:14 +00:00
Simon L. fc7ddf26e8 increase to v13.3.0
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-23 16:07:41 +02:00
Simon L. cd61f66467 add desec (#7995)
## Summary
- Integrates Desec into the AIO interface which simplifies the domain
registration and domain setup.
- You can either create a new account directly or use an existing
account.
- You have a button that you can open where the process will be done.
After the process is done, the whole page reloads and you can continue
with the setup.
- Caddy and dnsmasq community containers will be activated during the
process which will take over the cert generation and enable split-brain
dns.
- Community containers will work automatically for example Vaultwarden
as the subdomains of the desec domain point automatically via a wildcard
dns entry towards the main desec domain.
- Playwright tests are added to ensure that the system works as expected
in the future
- the desec api is mocked via a small node js based file.
- the qa and other docs were updated to mention desec
2026-06-23 15:05:42 +02:00
Simon L. e0c208da19 Apply suggestion from @szaimen
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-23 14:53:54 +02:00
Simon L. 1fdda55421 Apply suggestions from code review
Co-authored-by: Pablo Zmdl <57864086+pabzm@users.noreply.github.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-23 14:52:05 +02:00
Simon L. 7e50969d02 feat(desec): keep the typed slug across the registration flow
A slug typed into the deSEC form was lost when the form re-rendered after a
201 redirect (e.g. on the awaiting-verification step), forcing the user to
re-enter it. Persist the requested slug in the AIO config when register()
runs and pre-fill the slug input from it on every step, then clear it once a
domain is set. Stored in configuration.json rather than a URL parameter so it
survives the multi-step flow without leaking into the iframe address.

Signed-off-by: Simon L. <szaimen@e.mail.de>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 16:04:36 +02:00
Simon L. 0d2ce61af3 fix(desec): only reveal the deSEC password for AIO-created accounts
The containers page showed "Reveal deSEC password" for every deSEC domain,
but when the user logs in with their own existing account AIO stores an
empty password, so the reveal exposed nothing useful. Gate the reveal on a
stored password: AIO-created accounts show the generated credentials as
before; existing accounts now just say the domain is managed via that
account and to log in at desec.io with your own password.

Also clear the stored generated password in the awaiting-verification path
when the user logs in with their own password (the email already had an
account), so a non-empty stored password reliably means "AIO generated this
account" — and report the account as not-new so no wildcard CNAME is created
on a domain the user manages themselves.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-22 16:04:36 +02:00
Simon L. ebad4fd06f fix spelling
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-22 16:04:35 +02:00
Simon L. 9cfd5b41f6 fix(desec): reuse an existing slug the user already owns
Logging in with an existing deSEC account and entering a slug you already
own failed with "Domain limit exceeded": registerDomain() always tried to
POST /domains/, which deSEC rejects (403 when the account is at its quota,
400/409 when the name is taken) even though the domain belongs to you.

Now, for a user-specified slug, a 400/403/409 triggers an ownership check
(GET /domains/{name}/); if the account already owns the domain it is reused
and registration completes. Otherwise a clear message is shown (over-limit
vs. taken by someone else). Random-slug registration is unchanged.

Update the deSEC mock to mirror the real status codes (per-account ownership,
domain limit -> 403, taken name -> 400, GET /domains/{name}/) and add a spec
that exercises the over-limit ownership-recovery path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-22 16:04:35 +02:00
Simon L. b5e35c90d8 move the desec template another time
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-22 16:04:35 +02:00
Simon L. ac112f3b42 docs(dnsmasq): note auto IP detection is Linux-only, not Docker Desktop
dnsmasq runs in host network mode and auto-detects the host's LAN IP. On
Docker Desktop (Windows/macOS) containers run inside a Linux VM isolated
from the real host LAN, so detection yields the wrong IP and local DNS
resolution does not work. Call this out in the dnsmasq readme and the
in-app deSEC domain notice.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-22 16:04:35 +02:00
Simon L. ee1bf5f88a ci(desec): drop obsolete SKIP_DOMAIN_VALIDATION from the deSEC test step
The deSEC registration entry point now renders regardless of
SKIP_DOMAIN_VALIDATION (it was moved out of the skip-validation guard), and
the deSEC flow already sets the domain with validation skipped internally.
Remove the now-unnecessary SKIP_DOMAIN_VALIDATION=false override from the
deSEC Playwright steps in both workflows and update the stale spec comment.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-22 16:04:34 +02:00
Simon L. ef7e320c61 fix(desec): keep modal markup and script with the moved entry block
The deSEC entry <details> was moved up above the domain submit form, but the
#desec-modal container and desec-modal.js were left behind inside the
skip_domain_validation block. Move them up to sit directly after the entry
block so the open button, modal, and wiring script are always rendered
together (and present even when domain validation is skipped). This restores
the modal flow the Playwright tests drive via #desec-frame.

Signed-off-by: Simon L. <szaimen@e.mail.de>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-22 16:04:34 +02:00
Simon L. 64d49c1b59 move desec futher up in the containers template
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-22 16:04:34 +02:00
Simon L. b4e4ff8fd7 fix a detail
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-22 16:04:34 +02:00
Simon L. d2fbb711d2 feat(desec): surface domain notice at top, drop in-flow credentials
Hide the "Your deSEC login credentials" block during the in-flight
register/verify steps — the credentials are still shown in the dedicated
"deSEC account credentials" section once the domain is registered.

Extract the deSEC domain info/dnsmasq-caution notice into a reusable include
and also show it at the top of the initial-install flow, directly above the
"download and start containers" explanation, while keeping it in the
Community Containers section where it already appeared.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-22 16:04:34 +02:00
Simon L. 13c762c720 fix(desec): style the email field and stack the modal form inputs
The email input was unstyled because input[type="email"] was missing from
the text/password input rules, and the deSEC form's inline-block inputs
flowed side by side. Add the email type to the input styling rules and lay
the deSEC modal form out as a vertical stack with full-width inputs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-22 16:04:33 +02:00
szaimen 8ace9ef096 php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-22 13:49:23 +00:00
Simon L. 454905c852 feat(desec): run registration flow in a modal iframe
Move the deSEC "register a free domain" flow out of the inline containers
page form and into a modal backed by a dedicated /desec view loaded in an
iframe. The multi-step register -> verify -> domain process now re-renders
inside the modal, so the user can adjust the details and complete email
verification without reloading the whole page each step. Only once the
domain is fully registered does the view reload the parent containers page.

- add /desec route + desec.twig standalone view
- add desec-modal.js (open/close, backdrop + Escape) and desec-done.js
  (parent reload on completion)
- redirect register POST to the /desec view so steps stay in the modal
- drop the redundant <details> wrapper in desec-register.twig, add heading
- style the modal and let <button class="button"> pick up button styles
- drive the modal iframe in the Playwright specs and update the QA checklist

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-22 13:24:50 +02:00
dependabot[bot] 5005242b9a build(deps): bump guzzlehttp/guzzle from 7.12.0 to 7.12.1 in /php
Bumps [guzzlehttp/guzzle](https://github.com/guzzle/guzzle) from 7.12.0 to 7.12.1.
- [Release notes](https://github.com/guzzle/guzzle/releases)
- [Changelog](https://github.com/guzzle/guzzle/blob/7.12/CHANGELOG.md)
- [Commits](https://github.com/guzzle/guzzle/compare/7.12.0...7.12.1)

---
updated-dependencies:
- dependency-name: guzzlehttp/guzzle
  dependency-version: 7.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-19 12:02:45 +00:00
szaimen 37fb09442c php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-18 13:05:20 +00:00
Simon L. 4c8012adcd test(desec): end-to-end Playwright coverage against a local mock
- desec-mock.mjs: a dependency-free Node mock of the deSEC API endpoints the code
  uses, with the real status-code semantics (202 on account creation, 403 until
  verified then 200 + token, 201/409 on domain creation) plus /__control hooks to
  verify and reset state.
- desec-register.spec.js / desec-existing.spec.js drive the real AIO UI through
  the register -> verify -> domain flow and the existing-account login flow;
  desec-helpers.js holds the shared login helper. Each scenario ends by setting a
  domain, so they run as separate CI steps with a re-seed in between.
- seed-desec-mock-config.php points desec_api_base / desec_update_url at the mock
  (config key only, no env override, so production is unaffected) and seeds a
  known master password, since seeding configuration.json makes AIO consider
  itself already installed and /setup no longer shows a generated password.
- Both Playwright workflows start the mock, mount ./community-containers so the
  caddy/dnsmasq definitions enabled by the flow are present, seed the config, and
  run the two deSEC specs with a re-seed between them.

Co-Authored-By: szaimen <42591237+szaimen@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-18 13:19:16 +02:00
Simon L. 0753c6c902 feat(desec): wire caddy/dnsmasq community containers into the flow
- caddy.json: pass DESEC_TOKEN to the caddy container so it can solve the DNS-01
  challenge for the registered dedyn.io domain.
- community-containers.twig: when the domain was registered via deSEC, explain
  that caddy and dnsmasq were enabled automatically and link the required dnsmasq
  router change, with a caution to disable dnsmasq on publicly reachable hosts.
- compose.yaml: mention the built-in deSEC free domain option alongside Tailscale
  in the reverse-proxy hint.

Co-Authored-By: szaimen <42591237+szaimen@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-18 13:19:16 +02:00
Simon L. 1868738f56 feat(desec): add register -> verify -> domain UI
- includes/desec-register.twig renders the multi-step deSEC flow: enter email
  (optionally an existing password), the awaiting-verification step, and the
  account-registered step, with friendly messaging for the ambiguous "email
  already registered" case (deSEC returns 202 either way to prevent enumeration).
- containers.twig includes the deSEC section under the domain-entry UI; index.php
  passes the deSEC config/state (email, password, registered/awaiting flags) to
  the view.
- Move the deSEC password reveal from an inline style to a CSS class (no inline
  CSS/JS in templates) and bump the style.css cache-buster to v13 in layout.twig
  and log.twig.

Co-Authored-By: szaimen <42591237+szaimen@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-18 13:19:16 +02:00
Simon L. f7987b26ac feat(desec): add deSEC account + domain registration backend
Add the server-side deSEC (dedyn.io) free dynamic-DNS flow so users without a
domain can obtain one from the AIO interface.

- DesecManager drives the full flow against the deSEC API, matching its real
  semantics: account creation returns HTTP 202 + email verification (no token),
  a token is obtained via /auth/login/ only after the email is verified, domain
  registration handles 201/409, and a wildcard CNAME rrset is created for new
  accounts. Existing accounts can be used by supplying a password.
- The "awaiting verification" step is derived from the stored credentials (email
  + generated password but no token and no domain yet), not a separate flag.
  register() returns false for that state so the controller can re-render the
  awaiting-verification UI instead of surfacing it as an error.
- DesecController exposes POST /api/desec/register; DependencyInjection wires the
  manager; account credentials (email, generated password, token) are stored in
  the AIO configuration and DESEC_TOKEN is exposed to the caddy container.
- The dynamic-DNS record is refreshed with the current public IP on container
  start (DockerController) and via the cron path (Cron/UpdateDesecIp, cron.sh).
- Fix an undefined-variable bug in the desecToken/desecPassword config setters
  that prevented credentials from being persisted.

Co-Authored-By: szaimen <42591237+szaimen@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-18 13:19:16 +02:00
Simon L. 0baf4b4f79 aio-interface: show better instructions what should be done if you did not see a password (#8349) 2026-06-17 14:32:54 +02:00
dependabot[bot] 453f0542ad build(deps): bump guzzlehttp/guzzle from 7.11.2 to 7.12.0 in /php
Bumps [guzzlehttp/guzzle](https://github.com/guzzle/guzzle) from 7.11.2 to 7.12.0.
- [Release notes](https://github.com/guzzle/guzzle/releases)
- [Changelog](https://github.com/guzzle/guzzle/blob/7.12/CHANGELOG.md)
- [Commits](https://github.com/guzzle/guzzle/compare/7.11.2...7.12.0)

---
updated-dependencies:
- dependency-name: guzzlehttp/guzzle
  dependency-version: 7.12.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-17 12:03:04 +00:00
Simon L. 787fa22a81 remove the registry.gitlab.collabora.com/collabora-online/docker:latest image
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-17 12:18:16 +02:00
Simon L. dc24f16fdd aio-interface: show better instructions what should be done if you did not see a password
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-17 11:52:50 +02:00
Copilot fc4bb548a4 aio-interface: fix nginx reverse proxy read timeout blocks AIO from starting consecutive containers (#8016)
* Fix: prevent nginx proxy read timeout from blocking AIO container startup

When AIO runs behind an nginx reverse proxy and a user clicks Start,
image pulls produce no streaming output for minutes at a time. nginx's
proxy_read_timeout fires, drops the upstream connection, and PHP then
aborts on the next write attempt (ignore_user_abort defaults to false),
leaving all containers after the first one never started.

Two fixes:
1. startStreamingResponse(): add ignore_user_abort(true) so PHP never
   terminates if the connection is already gone.
2. PullImage(): stream the Docker NDJSON pull response and write a
   "Pulling image" heartbeat at most once every 5 s, keeping the nginx
   connection alive.  Also surfaces Docker-level stream errors that the
   old buffered call silently ignored, guards against malformed
   newline-free responses with a 1 MB buffer limit, and unifies the
   duplicate catch-block retry logic.

Agent-Logs-Url: https://github.com/nextcloud/all-in-one/sessions/4fd13605-63fb-4693-8a95-89ccec31f7d3

Co-authored-by: szaimen <42591237+szaimen@users.noreply.github.com>

* As heartbeat send a dot regularly

Rather than repeating the message, send a "magic" dot, which gets
appended to the previous line.

Previously the heartbeats weren't sent regulary because reading the data
into a buffer caused a lag.

Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>

* Remove left-over constants

Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>

* Reduce timeout to stay within nginx's default timeout of 5s

Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>

* Fix duplicated library namespace inclusion

Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>

* Deal with preg_replace possibly returning null

Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>

* update the version tag

Signed-off-by: Simon L. <szaimen@e.mail.de>

---------

Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: szaimen <42591237+szaimen@users.noreply.github.com>
Co-authored-by: Pablo Zmdl <pablo@nextcloud.com>
Co-authored-by: Simon L. <szaimen@e.mail.de>
2026-06-16 17:49:18 +02:00
szaimen 894f68ea6c php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-16 13:39:24 +00:00
dependabot[bot] 69c8f1b9bb build(deps): bump guzzlehttp/guzzle from 7.11.1 to 7.11.2 in /php
Bumps [guzzlehttp/guzzle](https://github.com/guzzle/guzzle) from 7.11.1 to 7.11.2.
- [Release notes](https://github.com/guzzle/guzzle/releases)
- [Changelog](https://github.com/guzzle/guzzle/blob/7.11/CHANGELOG.md)
- [Commits](https://github.com/guzzle/guzzle/compare/7.11.1...7.11.2)

---
updated-dependencies:
- dependency-name: guzzlehttp/guzzle
  dependency-version: 7.11.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-16 12:09:24 +00:00
Pablo Zmdl 403ff688f8 Fix fetching logs on podman initially
Podman doesn't like an empty `since` URL parameter.

Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-06-16 08:42:04 +02:00
Simon L. 599c1835bb PHP dependency updates (#8308) 2026-06-15 11:21:59 +02:00
szaimen 220e0d65a1 php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-13 12:32:20 +00:00
tobiasKaminsky 13e0842cff Previously the mapping was just $this->installLatestMajor ? 'yes' : '', so a stored value of 'no' was truthy and would have been turned into INSTALL_LATEST_MAJOR=yes in the Nextcloud container — the opposite of what the user intended. Now both ''
and 'no' result in an empty env value, which the entrypoint's [ "$INSTALL_LATEST_MAJOR" = yes ] check treats as disabled, while any other value (e.g. the '34' set by the start button or upgrade button) still maps to yes.

  Assisted-by: Claude
2026-06-12 14:35:40 +02:00
James Manuel 40ce65b6e0 feat: enable EuroOffice by default for new installs
Flips isEuroofficeEnabled default to true and isCollaboraEnabled
default to false in ConfigurationManager.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: James Manuel <moodyjmz@users.noreply.github.com>
2026-06-10 13:05:40 +02:00
szaimen 7c2d0128ff php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-09 12:54:58 +00:00
Simon L. 3de2d79cd6 aio-interface: mark Onlyoffice as deprecated (#8283) 2026-06-09 14:47:43 +02:00
Simon L. 5b17e9368e makemkv: allow it to access the necessary devices (#8276) 2026-06-09 14:45:19 +02:00
Simon L. f22ed12c4b aio-interface: add background to log overlay and use monospace font (#8271) 2026-06-09 14:42:10 +02:00
Simon L. e30f416d55 makemkv: allow it to access the necessary devices
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-09 14:33:34 +02:00
Simon L. 0ca4307bcb allow scrutiny to access all block devices (#8275) 2026-06-09 14:32:48 +02:00
Simon L. 313c39d2bc Apply suggestion from @szaimen
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-09 14:31:23 +02:00
Simon L. f7f107a3e5 aio-interface: mark Onlyoffice as deprecated
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-09 14:25:48 +02:00
dependabot[bot] 39f4808376 build(deps): bump guzzlehttp/guzzle from 7.11.0 to 7.11.1 in /php
Bumps [guzzlehttp/guzzle](https://github.com/guzzle/guzzle) from 7.11.0 to 7.11.1.
- [Release notes](https://github.com/guzzle/guzzle/releases)
- [Changelog](https://github.com/guzzle/guzzle/blob/7.11/CHANGELOG.md)
- [Commits](https://github.com/guzzle/guzzle/compare/7.11.0...7.11.1)

---
updated-dependencies:
- dependency-name: guzzlehttp/guzzle
  dependency-version: 7.11.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-08 12:05:10 +00:00
Simon L. aadadf4460 allow scrutiny to access all block devices
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-06-08 11:49:54 +02:00