Compare commits

...

160 commits

Author SHA1 Message Date
Simon L.
b51943d8a1 aio-interface: show sub-steps for starting containers
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-28 15:12:30 +01:00
Simon L.
e9108e3660
Merge pull request #7392 from nextcloud/configmanager-property-hooks
Use property hooks to replace classic getter and setter methods.
2026-01-28 15:10:34 +01:00
Simon L.
27020e608d
fix get-configurable-aio-variables.sh script
Signed-off-by: Simon L. <szaimen@e.mail.de>

Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-28 13:28:07 +01:00
Simon L.
d813314494
Merge pull request #7499 from nextcloud/aio-dependency-update
PHP dependency updates
2026-01-28 13:16:56 +01:00
szaimen
0ee76078ad php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-28 12:03:53 +00:00
Pablo Zmdl
5ba678c082 Non-functional addition to camelizing nextcloud_mount to nextcloudMount
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 12:08:07 +01:00
Pablo Zmdl
5b6e0f30a6 Fix assignment of INSTALL_LATEST_MAJOR from env replacement
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
d9d4e3680f Fix residue from change to use start/commitTransaction()
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
659b1ca383 Fix calling booleanize
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
ec66b359e0 Check arguments to camelize() for usefulness
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
078f3caf8a Move all properties to the top of the file
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
3cfe307a5c Make nextcloudKeepDisabledApps an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
5bdcfd67eb Make 'enableNvidiaGpu' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
5fc4951ba0 Make 'nextcloudEnableDriDevice' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
0cb79a387f Make 'disableBackupSection' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
08438aff42 Make 'apacheAdditionalNetwork' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
dc5dc0215c Make 'collaboraSeccompDisabled' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
22a26268e0 Helper to booleanize environment-or-config-values
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
c3477a7eb2 Make 'nextcloudAdditionalPhpExtensions' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
d50dc2db1d Make 'nextcloudAdditionalApks' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
4ad8fcf258 Make 'trustedCacertsDir' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
63245430ef Make 'dockerSocketPath' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
bfa2b64674 Make 'fulltextsearchJavaOptions' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
365e1e34e4 Make 'borgRetentionPolicy' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
0ed83c5258 Move get-configurable-aio-variables.sh into php/ folder
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
8b8f60f76b Camelize property nextcloud_memory_limit => nextcloudMemoryLimit
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
bbf41cfdd3 Camelize property nextcloud_upload_limit => nextcloudUploadLimit
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
f5cf7903ad Camelize property nextcloud_datadir_mount => nextcloudDatadirMount
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
f35a0b4367 Camelize property nextcloud_mount => nextcloudMount
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
f7c5115c70 Camelize property talk_port => talkPort
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
567f072ee0 Camelize property apache_port => apachePort
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
00ce78d703 Camelize property turn_domain => turnDomain
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
c4aa148bff Camelize property aio_community_containers => aioCommunityContainers
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
b499001501 Camelize property collabora_additional_options => collaboraAdditionalOptions
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
5373471ed8 Camelize property collabora_dictionaries => collaboraDictionaries
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
efe8317446 Camelize property nextcloud_max_time => nextcloudMaxTime
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:57 +01:00
Pablo Zmdl
41c92b814f Camelize key names from aio_variables from container specs
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
f17db4fac1 Camelize property apache_ip_binding => apacheIpBinding
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
5cac2dcf12 Camelize property borg_restore_password => borgRestorePassword
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
284411c369 Camelize property borg_remote_repo => borgRemoteRepo
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
62856e78bb Camelize property borg_backup_host_location => borgBackupHostLocation
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
2425a07772 Camelize property install_latest_major => installLatestMajor
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
68f811b25f Camelize property AIO_URL => aioUrl
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
62a21dd34a Camelize property instance_restore_attempt => instanceRestoreAttempt
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
dd5d51cb2a Camelize property AIO_TOKEN => aioToken
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
27fd1e82ab Turn install_latest_major property into a string so we can save a version string or number
I chose a string instead of an integer so we have more freedom what to
actually save (maybe we want to include minor version digits at one point).

Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
3bb2ce6e4c Type-cast get values to fix handling old config data
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
dac5cfd917 Don't write the default value to disk
This matches the previous behaviour and should not be changed silently.

Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
76d475f2b2 Replace setMultiple() by startTransaction() and commitTransaction()
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
6bf45fb507 A script to list AIO variables that are configurable through aio_variables in community containers
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
c65ccd2db0 Make aio-variables code more robust and psalm-compatible
Now the input gets checked for being useful. It's user-generated data in the
end, which might be "funny" in curious ways.

psalm complained about the possibly unset second array key in the
destructuring assignment of `$key` and `$value`, which won't happen due to the
check for a present equal sign earlier, but nonetheless this way the code is
more robust.

Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
77bec5898f Type for Closure argument
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
662840bc25 Make psalm accept the property-hooks for virtual attributes
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
fd308d4b80 Simplify some code a little bit
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
844831a899 Move handling ENV-var replacement into ConfigurationManger
It's the more appropriate place to have this code, and we had to touch
it anyways to make it assign the values to the attributes.

Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
9c9ad02f8a Set multiple attributes at once
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
c997332e47 Remove residue code
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
f1ffd0771c Privatize GetConfig() and WriteConfig()
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
367e847cc8 Make nextcloud_max_time an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
c1f8ac6989 Make nextcloud_memory_limit an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
3e19fa66d0 Make nextcloud_datadir_mount an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
4de73dd75b Make nextcloud_mount an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
903aed1e34 Make nextcloud_upload_limit an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
96c9c1a6f9 Make talk_port an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
dc28eb6737 Make apache_port an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
4e373cb2f8 Make apache_ip_binding an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
0a22384cd9 Make turn_domain an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
6c04cd055f Make aio_community_containers an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
228440f2a8 Make collabora_additional_options an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
ca35006a85 Make collabora_dictionaries an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
6e5237cd20 Make timezone an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
6033a4486c Make borg_restore_password an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
a361ab9d20 Make borg_remote_repo an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
b4d198f72b Make borg_backup_host_location an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
5b0b9ef826 Make domain an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
f737d2f598 Make isFulltextsearchEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
f16f5b233d Make isImaginaryEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
190d47810b Make isTalkRecordingEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
e009abdd54 Make isTalkEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:56 +01:00
Pablo Zmdl
cd1c2276e5 Make isCollaboraEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:51:26 +01:00
Pablo Zmdl
0c3d919618 Make isOnlyofficeEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:50:34 +01:00
Pablo Zmdl
f8a244bee2 Make isClamavEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:48:05 +01:00
Pablo Zmdl
bebae7069b Make instance_restore_attempt an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:43:36 +01:00
Pablo Zmdl
f235af29e3 Make isDockerSocketProxyEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:43:36 +01:00
Pablo Zmdl
6576d3c1e9 Make backupMode an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:43:36 +01:00
Pablo Zmdl
881e77cca5 Make isWhiteboardEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:43:36 +01:00
Pablo Zmdl
c968e9e310 Make restoreExcludePreviews an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:43:36 +01:00
Pablo Zmdl
b8130958c5 Make selectedRestoreTime an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:43:36 +01:00
Pablo Zmdl
1d11a4682b Make install_latest_major an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:43:36 +01:00
Pablo Zmdl
06fdf31c87 Make AIO_URL an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:43:36 +01:00
Pablo Zmdl
484ff79943 Make wasStartButtonClicked an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:43:36 +01:00
Pablo Zmdl
4d8e959608 Make password an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:43:36 +01:00
Pablo Zmdl
b2f992d955 Make AIO_TOKEN an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:43:36 +01:00
Pablo Zmdl
a9b648e18f Adapt GetAndGenerateSecret() to get() and set()
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:43:36 +01:00
Pablo Zmdl
21b14a4a5d Adapt GetEnvironmentalVariableOrConfig() to get() and set()
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:43:36 +01:00
Pablo Zmdl
0b6c0733ab Cache config, introduce get() and set() helpers to guide new way to set attributes
Use cached config, use set() for single attributes, setMultiple to wrap
multiple calls to set()

Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-28 11:43:36 +01:00
Julius Knorr
3f4eecaa96
feat: Add office switcher with feature comparison (#7421)
Some checks failed
Codespell / Check spelling (push) Waiting to run
Docker Lint / docker-lint (push) Waiting to run
Lint php / php-lint (push) Waiting to run
Lint php / php-lint-summary (push) Blocked by required conditions
PHP Deprecation Detector / PHP Deprecation Detector (push) Waiting to run
Playwright Tests on push / test (push) Waiting to run
Static analysis / static-psalm-analysis (push) Waiting to run
Twig Lint / twig-lint (push) Has been cancelled
Signed-off-by: Julius Knorr <jus@bitgrid.net>
Signed-off-by: Simon L. <szaimen@e.mail.de>
Signed-off-by: Andrew Backhouse <andrew.backhouse@nextcloud.com>
Co-authored-by: Simon L. <szaimen@e.mail.de>
Co-authored-by: Andrew Backhouse <andrew.backhouse@nextcloud.com>
2026-01-28 09:53:53 +01:00
Simon L.
8939104d10
Merge pull request #7498 from nextcloud/dependabot/docker/Containers/talk/nats-2.12.4-scratch
build(deps): bump nats from 2.12.3-scratch to 2.12.4-scratch in /Containers/talk
2026-01-28 08:47:30 +01:00
dependabot[bot]
0213d8e548
build(deps): bump nats in /Containers/talk
Bumps nats from 2.12.3-scratch to 2.12.4-scratch.

---
updated-dependencies:
- dependency-name: nats
  dependency-version: 2.12.4-scratch
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-28 04:08:45 +00:00
Simon L.
ba899255c1
Merge pull request #7497 from nextcloud/dependabot/docker/Containers/mastercontainer/docker-29.2.0-cli
Some checks are pending
Codespell / Check spelling (push) Waiting to run
Docker Lint / docker-lint (push) Waiting to run
build(deps): bump docker from 29.1.5-cli to 29.2.0-cli in /Containers/mastercontainer
2026-01-27 14:54:49 +01:00
dependabot[bot]
59e0776808
build(deps): bump docker in /Containers/mastercontainer
Bumps docker from 29.1.5-cli to 29.2.0-cli.

---
updated-dependencies:
- dependency-name: docker
  dependency-version: 29.2.0-cli
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-27 04:06:09 +00:00
Simon L.
9c6bb67542
Merge pull request #7492 from nextcloud/dependabot/github_actions/dot-github/workflows/actions/checkout-6.0.2
Some checks failed
Codespell / Check spelling (push) Waiting to run
Docker Lint / docker-lint (push) Waiting to run
Lint php / php-lint (push) Has been cancelled
PHP Deprecation Detector / PHP Deprecation Detector (push) Has been cancelled
Playwright Tests on push / test (push) Has been cancelled
Static analysis / static-psalm-analysis (push) Has been cancelled
Shellcheck / Check Shell (push) Has been cancelled
Twig Lint / twig-lint (push) Has been cancelled
Lint php / php-lint-summary (push) Has been cancelled
build(deps): bump actions/checkout from 6.0.1 to 6.0.2 in /.github/workflows
2026-01-26 14:13:08 +01:00
dependabot[bot]
3f85f10bfb
build(deps): bump actions/checkout in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6.0.1...de0fac2e4500dabe0009e67214ff5f5447ce83dd)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-26 13:08:44 +00:00
Simon L.
9cd519b285
Merge pull request #7491 from nextcloud/aio-dependency-update
PHP dependency updates
2026-01-26 13:50:29 +01:00
szaimen
3e6deb8802 php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-26 12:04:00 +00:00
Simon L.
6babbf776a
Merge pull request #7473 from nextcloud/enh/noid/pin-all-actions
pin all actions via commit hash
2026-01-26 13:00:49 +01:00
Simon L.
27eae80466 pin all actions via commit hash
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-26 12:59:05 +01:00
Simon L.
ebe3d7ee83 increase to v12.6.0
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-26 11:55:19 +01:00
Simon L.
07c20f5daa
Merge pull request #7485 from nextcloud/enh/noid/more-strict-check
mastercontainer: make check for correct volume name more strict
2026-01-26 10:15:45 +01:00
Simon L.
0df6c0a645 mastercontainer: make check for correct volume name more strict
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-25 17:31:43 +01:00
Simon L.
845fa94afa
Merge pull request #7486 from nextcloud/aio-dependency-update
Some checks are pending
Codespell / Check spelling (push) Waiting to run
Lint php / php-lint (push) Waiting to run
Lint php / php-lint-summary (push) Blocked by required conditions
PHP Deprecation Detector / PHP Deprecation Detector (push) Waiting to run
Playwright Tests on push / test (push) Waiting to run
Static analysis / static-psalm-analysis (push) Waiting to run
PHP dependency updates
2026-01-25 15:01:21 +01:00
szaimen
7e2e0d11da php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-25 12:03:33 +00:00
Simon L.
44f659ad69
Merge pull request #7482 from nextcloud/aio-dependency-update
Some checks are pending
Codespell / Check spelling (push) Waiting to run
Lint php / php-lint (push) Waiting to run
Lint php / php-lint-summary (push) Blocked by required conditions
PHP Deprecation Detector / PHP Deprecation Detector (push) Waiting to run
Playwright Tests on push / test (push) Waiting to run
Static analysis / static-psalm-analysis (push) Waiting to run
PHP dependency updates
2026-01-24 14:07:57 +01:00
szaimen
d2940b0dc8 php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-24 12:03:23 +00:00
Simon L.
74443aaacc
Merge pull request #7477 from nextcloud/docjyJ-patch-2
Some checks failed
Codespell / Check spelling (push) Has been cancelled
Validate community containers / Validate community containers (push) Has been cancelled
Json Validator / Json Validator (push) Has been cancelled
deprecate nocodb community container
2026-01-23 14:22:42 +01:00
Simon L.
33614b276b
Merge pull request #7475 from nextcloud/dev/ench/noid/conduct
Add Code of conduct
2026-01-23 14:18:45 +01:00
Simon L.
034c6edea9
Merge pull request #7479 from nextcloud/dependabot/github_actions/dot-github/workflows/actions/checkout-6.0.2
build(deps): bump actions/checkout from 6.0.1 to 6.0.2 in /.github/workflows
2026-01-23 14:17:38 +01:00
dependabot[bot]
0e868c4570
build(deps): bump actions/checkout in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v6.0.1...v6.0.2)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-23 12:08:36 +00:00
Jean-Yves
e1718faf0b
Update README with licensing and maintenance notes
Added caution and note about NocoDB licensing and maintenance status.

Signed-off-by: Jean-Yves <7360784+docjyJ@users.noreply.github.com>
2026-01-22 21:24:35 +01:00
Jean-Yves
db07c79db1
novodb: add (deprecated) to its display name
Signed-off-by: Jean-Yves <7360784+docjyJ@users.noreply.github.com>
2026-01-22 21:20:36 +01:00
Jean-Yves
664ca0b26d
Add Code of conduct
See: https://github.com/nextcloud/server/blob/master/CODE_OF_CONDUCT.md

Signed-off-by: Jean-Yves <7360784+docjyJ@users.noreply.github.com>
2026-01-22 21:08:08 +01:00
Simon L.
49c9669fe1
Merge pull request #7468 from nextcloud/enh/7466/insert-max-shutdown-time
Some checks failed
Codespell / Check spelling (push) Waiting to run
Lint php / php-lint (push) Has been cancelled
PHP Deprecation Detector / PHP Deprecation Detector (push) Has been cancelled
Playwright Tests on push / test (push) Has been cancelled
Static analysis / static-psalm-analysis (push) Has been cancelled
Lint php / php-lint-summary (push) Has been cancelled
`CreateContainer`: also insert the max shutdown time into the container itself
2026-01-22 17:53:06 +01:00
Simon L.
4d51f11282
Merge pull request #7471 from nextcloud/imaginary-container-update
Some checks failed
Codespell / Check spelling (push) Waiting to run
Lint php / php-lint (push) Waiting to run
Lint php / php-lint-summary (push) Blocked by required conditions
PHP Deprecation Detector / PHP Deprecation Detector (push) Waiting to run
Playwright Tests on push / test (push) Waiting to run
Static analysis / static-psalm-analysis (push) Waiting to run
Docker Lint / docker-lint (push) Has been cancelled
Helm Chart Releaser / release (push) Has been cancelled
Shellcheck / Check Shell (push) Has been cancelled
Twig Lint / twig-lint (push) Has been cancelled
Imaginary update
2026-01-22 14:40:09 +01:00
szaimen
c47ace7718 imaginary-update automated change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-22 13:33:38 +00:00
Simon L.
dd60066644
Merge pull request #7470 from nextcloud/aio-helm-update
Helm Chart updates
2026-01-22 14:14:33 +01:00
szaimen
00688a52bd Helm Chart updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-22 13:12:02 +00:00
Simon L.
8fb3126ce7 CreateContainer: also insert the max shutdown time into the container itself
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-22 14:07:41 +01:00
Simon L.
a7c091a5b2 mastercontainer: also add wud.watch label
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-22 12:21:26 +01:00
Simon L.
dc09422030
Merge pull request #7467 from nextcloud/watchtower-container-update
watchtower container update
2026-01-22 12:16:36 +01:00
Simon L.
b9e35f01ba
Merge pull request #7464 from nextcloud/dependabot/docker/Containers/whiteboard/nextcloud-releases/whiteboard-v1.5.3
build(deps): bump nextcloud-releases/whiteboard from v1.5.1 to v1.5.3 in /Containers/whiteboard
2026-01-22 12:16:16 +01:00
Simon L.
571e07996e
Merge pull request #7461 from nextcloud/dependabot/docker/Containers/watchtower/golang-1.25.6-alpine3.23
build(deps): bump golang from 1.25.5-alpine3.23 to 1.25.6-alpine3.23 in /Containers/watchtower
2026-01-22 12:16:04 +01:00
Simon L.
9b1d468e24
Merge pull request #7460 from nextcloud/dependabot/docker/Containers/imaginary/golang-1.25.6-alpine3.23
build(deps): bump golang from 1.25.5-alpine3.23 to 1.25.6-alpine3.23 in /Containers/imaginary
2026-01-22 12:15:51 +01:00
Simon L.
2eaa288596
Merge pull request #7452 from nextcloud/dependabot/docker/Containers/nextcloud/php-8.3.30-fpm-alpine3.23
build(deps): bump php from 8.3.29-fpm-alpine3.23 to 8.3.30-fpm-alpine3.23 in /Containers/nextcloud
2026-01-22 12:15:38 +01:00
Simon L.
be54fa8805
Merge pull request #7451 from nextcloud/dependabot/docker/Containers/mastercontainer/docker-29.1.5-cli
build(deps): bump docker from 29.1.4-cli to 29.1.5-cli in /Containers/mastercontainer
2026-01-22 12:15:25 +01:00
Simon L.
f5a06034dd
Merge pull request #7435 from nextcloud/aio-dependency-update
PHP dependency updates
2026-01-22 12:15:12 +01:00
Simon L.
47dd8d25ca
Merge pull request #7431 from nextcloud/dependabot/docker/Containers/mastercontainer/php-8.4.17-fpm-alpine3.23
build(deps): bump php from 8.4.16-fpm-alpine3.23 to 8.4.17-fpm-alpine3.23 in /Containers/mastercontainer
2026-01-22 12:14:57 +01:00
Simon L.
9e3acb9f68
Merge pull request #7457 from nextcloud/enh/6878/pull-3-times
DockeractionManager: rewrite `PullImage` function to re-try 3 times before failing
2026-01-22 12:11:27 +01:00
Simon L.
3f581a11b3
Merge pull request #7455 from nextcloud/enh/7434/add-wud-label
add `wud.watch=false` to all containers
2026-01-22 12:11:18 +01:00
Simon L.
8124554d90
Merge pull request #7454 from nextcloud/enh/7447/recording-server-disabling
nextcloud-entrypoint: make recording server dependent on `REMOVE_DISABLED_APPS`
2026-01-22 12:11:10 +01:00
Simon L.
74138dd838
Merge pull request #7436 from nextcloud/enh/noid/move-version
move version to a dedicated file
2026-01-22 12:10:27 +01:00
Simon L.
52f8c97d45
Merge pull request #7406 from nextcloud/ench/noid/parm
refactor: change private properties to public in Container class
2026-01-22 12:10:15 +01:00
Simon L.
10a3b8213f
Merge pull request #7442 from nextcloud/nextcloud-container-update
Nextcloud dependency update
2026-01-22 12:10:03 +01:00
dependabot[bot]
8eed705a90
build(deps): bump php in /Containers/nextcloud
Bumps php from 8.3.29-fpm-alpine3.23 to 8.3.30-fpm-alpine3.23.

---
updated-dependencies:
- dependency-name: php
  dependency-version: 8.3.30-fpm-alpine3.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-22 04:08:35 +00:00
dependabot[bot]
f59b2776c7
build(deps): bump php in /Containers/mastercontainer
Bumps php from 8.4.16-fpm-alpine3.23 to 8.4.17-fpm-alpine3.23.

---
updated-dependencies:
- dependency-name: php
  dependency-version: 8.4.17-fpm-alpine3.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-22 04:08:30 +00:00
szaimen
708e542270 nextcloud-update automated change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-21 12:16:29 +00:00
szaimen
b12c36f675 watchtower-update automated change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-21 12:12:48 +00:00
szaimen
2c968917eb php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-21 12:03:53 +00:00
Simon L.
3b3eea7ef0 don't ask for a cute anmial picture
Some checks are pending
Codespell / Check spelling (push) Waiting to run
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-21 10:54:39 +01:00
dependabot[bot]
fcdd000731
build(deps): bump nextcloud-releases/whiteboard
Bumps nextcloud-releases/whiteboard from v1.5.1 to v1.5.3.

---
updated-dependencies:
- dependency-name: nextcloud-releases/whiteboard
  dependency-version: v1.5.3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-21 04:10:21 +00:00
Simon L.
88a45d1a80 add cooldown to dependabot
Some checks failed
Codespell / Check spelling (push) Waiting to run
Docker Lint / docker-lint (push) Has been cancelled
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-20 13:20:09 +01:00
Simon L.
f117a441fe
Merge pull request #7462 from nextcloud/enh/noid/fix-mysql-config
postgres.config.php: fix `PDO::MYSQL_ATTR_SSL_CA`
2026-01-20 13:13:36 +01:00
Simon L.
b7d63253db postgres.config.php: fix PDO::MYSQL_ATTR_SSL_CA
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-20 11:50:04 +01:00
Simon L.
f58465f930 DockeractionManager: rewrite PullImage function to re-try 3 times before failing
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-20 10:48:17 +01:00
dependabot[bot]
dbabfe14f0
build(deps): bump golang in /Containers/watchtower
Bumps golang from 1.25.5-alpine3.23 to 1.25.6-alpine3.23.

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.25.6-alpine3.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-20 04:09:56 +00:00
dependabot[bot]
c5b146f84c
build(deps): bump golang in /Containers/imaginary
Bumps golang from 1.25.5-alpine3.23 to 1.25.6-alpine3.23.

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.25.6-alpine3.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-20 04:08:44 +00:00
Simon L.
0e22f38d16 add wud.watch=false to all containers
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-19 17:10:22 +01:00
Simon L.
9822a63c44 nextcloud-entrypoint: make recording server dependent on REMOVE_DISABLED_APPS
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-19 10:07:52 +01:00
dependabot[bot]
4a65c04e3d
build(deps): bump docker in /Containers/mastercontainer
Bumps docker from 29.1.4-cli to 29.1.5-cli.

---
updated-dependencies:
- dependency-name: docker
  dependency-version: 29.1.5-cli
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-19 04:28:14 +00:00
Simon L.
59ad7dc98b move version to a dedicated file
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-16 15:12:44 +01:00
Jean-Yves
cdd21ae1ff
refactor: change private properties to public in Container class and update related methods
Signed-off-by: Jean-Yves <7360784+docjyJ@users.noreply.github.com>
2026-01-10 15:07:08 +01:00
104 changed files with 1410 additions and 1235 deletions

View file

@ -37,5 +37,3 @@ labels: 0. Needs triage
#### Output of `sudo docker ps -a`
#### Other valuable info <!--- (like additional logs, screenshots & Co.) -->
#### A picture of a cute animal <!--- (not mandatory but encouraged) -->

View file

@ -10,6 +10,8 @@ updates:
labels:
- 3. to review
- dependencies
cooldown:
default-days: 7
- package-ecosystem: composer
directory: "/php/"
schedule:

View file

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check spelling
uses: codespell-project/actions-codespell@8f01853be192eb0f849a5c7d721450e7a467c579 # v2
with:

View file

@ -10,7 +10,7 @@ jobs:
name: update collabora
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Run collabora-profile-update
run: |
rm -f php/cool-seccomp-profile.json

View file

@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Validate structure
run: |
CONTAINERS="$(find ./community-containers -mindepth 1 -maxdepth 1 -type d)"

View file

@ -10,7 +10,7 @@ jobs:
name: Run dependency update script
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2
with:
php-version: 8.4

View file

@ -25,7 +25,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install hadolint
run: |

View file

@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Turnstyle
uses: softprops/turnstyle@e565d2d86403c5d23533937e95980570545e5586 # v2

View file

@ -10,7 +10,7 @@ jobs:
name: update to latest imaginary commit on master branch
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Run imaginary-update
run: |
# Imaginary

View file

@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Validate Json
run: |
sudo apt-get update

View file

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0

View file

@ -36,7 +36,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v5.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

View file

@ -24,7 +24,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.1
with:
persist-credentials: false

View file

@ -11,7 +11,7 @@ jobs:
name: Run nextcloud-update script
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Run nextcloud-update script
run: |
# Inspired by https://github.com/nextcloud/docker/blob/master/update.sh

View file

@ -16,7 +16,7 @@ jobs:
name: PHP Deprecation Detector
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up php
uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2
with:

View file

@ -24,9 +24,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@v6
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6
with:
node-version: lts/*
@ -114,7 +114,7 @@ jobs:
exit 1
fi
- uses: actions/upload-artifact@v6
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
if: ${{ !cancelled() }}
with:
name: playwright-report

View file

@ -13,9 +13,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-node@v6
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6
with:
node-version: lts/*
@ -82,7 +82,7 @@ jobs:
exit 1
fi
- uses: actions/upload-artifact@v6
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
if: ${{ !cancelled() }}
with:
name: playwright-report

View file

@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up php
uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2

View file

@ -32,7 +32,7 @@ jobs:
name: static-psalm-analysis
steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v5.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

View file

@ -15,7 +15,7 @@ jobs:
name: Check Shell
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Run Shellcheck
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0
with:

View file

@ -10,7 +10,7 @@ jobs:
name: update talk
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Run talk-container-update
run: |
# Recording

View file

@ -24,7 +24,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2

View file

@ -8,4 +8,4 @@ jobs:
name: update copyright
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

View file

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: update helm chart
run: |
set -x

View file

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: update yaml files
run: |
sudo bash manual-install/update-yaml.sh

View file

@ -10,7 +10,7 @@ jobs:
name: update watchtower
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Run watchtower-container-update
run: |
# Watchtower

13
CODE_OF_CONDUCT.md Normal file
View file

@ -0,0 +1,13 @@
<!--
- SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
In the Nextcloud community, participants from all over the world come together to create Free Software for a free internet. This is made possible by the support, hard work and enthusiasm of thousands of people, including those who create and use Nextcloud software.
Our code of conduct offers some guidance to ensure Nextcloud participants can cooperate effectively in a positive and inspiring atmosphere, and to explain how together we can strengthen and support each other.
The Code of Conduct is shared by all contributors and users who engage with the Nextcloud team and its community services. It presents a summary of the shared values and “common sense” thinking in our community.
You can find our full code of conduct on our website: https://nextcloud.com/code-of-conduct/
Please, keep our CoC in mind when you contribute! That way, everyone can be a part of our community in a productive, positive, creative and fun way.

View file

@ -88,4 +88,5 @@ CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"]
HEALTHCHECK CMD /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -24,5 +24,6 @@ ENTRYPOINT ["/start.sh"]
USER root
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"
ENV BORG_RETENTION_POLICY="--keep-within=7d --keep-weekly=4 --keep-monthly=6"

View file

@ -33,5 +33,6 @@ VOLUME /var/lib/clamav
ENTRYPOINT ["/start.sh"]
CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"]
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"
HEALTHCHECK --start-period=60s --retries=9 CMD /healthcheck.sh

View file

@ -12,4 +12,5 @@ USER 1001
HEALTHCHECK --start-period=60s --retries=9 CMD /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -11,4 +11,5 @@ USER 1001
HEALTHCHECK --start-period=60s --retries=9 CMD /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -19,4 +19,5 @@ COPY --chmod=664 haproxy.cfg /haproxy.cfg
ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -18,4 +18,5 @@ ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD nc -z 127.0.0.1 $APACHE_PORT || exit 1
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -22,5 +22,6 @@ USER 1000:0
HEALTHCHECK --interval=10s --timeout=5s --start-period=1m --retries=5 CMD /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"
ENV ES_JAVA_OPTS="-Xms512M -Xmx512M"

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
FROM golang:1.25.5-alpine3.23 AS go
FROM golang:1.25.6-alpine3.23 AS go
ENV IMAGINARY_HASH=6a274b488759a896aff02f52afee6e50b5e3a3ee
@ -43,4 +43,5 @@ ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -1,12 +1,12 @@
# syntax=docker/dockerfile:latest
# Docker CLI is a requirement
FROM docker:29.1.4-cli AS docker
FROM docker:29.2.0-cli AS docker
# Caddy is a requirement
FROM caddy:2.10.2-alpine AS caddy
# From https://github.com/docker-library/php/blob/master/8.4/alpine3.23/fpm/Dockerfile
FROM php:8.4.16-fpm-alpine3.23
FROM php:8.4.17-fpm-alpine3.23
EXPOSE 80
EXPOSE 8080
@ -127,6 +127,7 @@ RUN set -ex; \
# hadolint ignore=DL3048
LABEL org.label-schema.vendor="Nextcloud" \
wud.watch="false" \
com.docker.compose.project="nextcloud-aio"
# hadolint ignore=DL3002

View file

@ -166,7 +166,7 @@ elif ! sudo -E -u www-data docker volume ls --format "{{.Name}}" | grep -q "^nex
print_red "It seems like you did not give the mastercontainer volume the correct name? (The 'nextcloud_aio_mastercontainer' volume was not found.)
Using a different name is not supported since the built-in backup solution will not work in that case!"
exit 1
elif ! sudo -E -u www-data docker inspect nextcloud-aio-mastercontainer | grep -q "nextcloud_aio_mastercontainer"; then
elif ! sudo -E -u www-data docker inspect nextcloud-aio-mastercontainer --format '{{.Mounts}}' | grep -q " nextcloud_aio_mastercontainer "; then
print_red "It seems like you did not attach the 'nextcloud_aio_mastercontainer' volume to the mastercontainer?
This is not supported since the built-in backup solution will not work in that case!"
exit 1

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
FROM php:8.3.29-fpm-alpine3.23
FROM php:8.3.30-fpm-alpine3.23
ENV PHP_MEMORY_LIMIT=512M
ENV PHP_UPLOAD_LIMIT=16G
@ -8,7 +8,7 @@ ENV SOURCE_LOCATION=/usr/src/nextcloud
ENV REDIS_DB_INDEX=0
# AIO settings start # Do not remove or change this line!
ENV NEXTCLOUD_VERSION=32.0.4
ENV NEXTCLOUD_VERSION=32.0.5
ENV AIO_TOKEN=123456
ENV AIO_URL=localhost
# AIO settings end # Do not remove or change this line!
@ -264,4 +264,5 @@ CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"]
HEALTHCHECK CMD /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -10,7 +10,7 @@ if (getenv('NEXTCLOUD_TRUSTED_CERTIFICATES_POSTGRES')) {
if (getenv('NEXTCLOUD_TRUSTED_CERTIFICATES_MYSQL')) {
$CONFIG = array(
'dbdriveroptions' => array(
'PDO::MYSQL_ATTR_SSL_CA' => '/var/www/html/data/certificates/ca-bundle.crt',
PDO::MYSQL_ATTR_SSL_CA => '/var/www/html/data/certificates/ca-bundle.crt',
),
);
}

View file

@ -894,7 +894,9 @@ if [ -d "/var/www/html/custom_apps/spreed" ]; then
RECORDING_SERVERS_STRING="{\"servers\":[{\"server\":\"http://$TALK_RECORDING_HOST:1234/\",\"verify\":true}],\"secret\":\"$RECORDING_SECRET\"}"
php /var/www/html/occ config:app:set spreed recording_servers --value="$RECORDING_SERVERS_STRING"
else
php /var/www/html/occ config:app:delete spreed recording_servers
if [ "$REMOVE_DISABLED_APPS" = yes ]; then
php /var/www/html/occ config:app:delete spreed recording_servers
fi
fi
fi

View file

@ -23,4 +23,5 @@ ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -8,4 +8,5 @@ COPY --chmod=775 healthcheck.sh /healthcheck.sh
HEALTHCHECK --start-period=60s --retries=9 CMD /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -44,4 +44,5 @@ ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -21,4 +21,5 @@ ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -58,4 +58,5 @@ CMD ["python", "-m", "nextcloud.talk.recording", "--config", "/conf/recording.co
HEALTHCHECK CMD /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
FROM nats:2.12.3-scratch AS nats
FROM nats:2.12.4-scratch AS nats
FROM eturnal/eturnal:1.12.2-alpine AS eturnal
FROM strukturag/nextcloud-spreed-signaling:2.0.4 AS signaling
FROM alpine:3.23.2 AS janus
@ -107,4 +107,5 @@ CMD ["supervisord", "-c", "/supervisord.conf"]
HEALTHCHECK CMD /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -1,13 +1,13 @@
# syntax=docker/dockerfile:latest
FROM golang:1.25.5-alpine3.23 AS go
FROM golang:1.25.6-alpine3.23 AS go
ENV WATCHTOWER_COMMIT_HASH=f6a7b29c312bec5f389a4fb52259919f0678800b
ENV WATCHTOWER_COMMIT_HASH=f522ce27e1fbe4618da54833025a95be62aa838a
RUN set -ex; \
apk upgrade --no-cache -a; \
apk add --no-cache \
build-base; \
go install github.com/nicholas-fedor/watchtower@$WATCHTOWER_COMMIT_HASH # v1.13.1
go install github.com/nicholas-fedor/watchtower@$WATCHTOWER_COMMIT_HASH # v1.14.0
FROM alpine:3.23.2
@ -24,4 +24,5 @@ USER root
ENTRYPOINT ["/start.sh"]
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:latest
# Probably from this file: https://github.com/nextcloud/whiteboard/blob/main/Dockerfile
FROM ghcr.io/nextcloud-releases/whiteboard:v1.5.1
FROM ghcr.io/nextcloud-releases/whiteboard:v1.5.3
USER root
RUN set -ex; \
@ -23,4 +23,5 @@ WORKDIR /tmp
ENTRYPOINT ["/start.sh"]
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -2,7 +2,7 @@
"aio_services_v1": [
{
"container_name": "nextcloud-aio-nocodb",
"display_name": "NocoDB",
"display_name": "NocoDB (deprecated)",
"documentation": "https://github.com/nextcloud/all-in-one/tree/main/community-containers/nocodb",
"image": "nocodb/nocodb",
"image_tag": "latest",

View file

@ -1,3 +1,8 @@
> [!CAUTION]
> NocoDB is licensed under a non-free license.
>
> And is no longer maintained.
> [!NOTE]
> This container is there to compensate for the lack of functionality in Nextcloud Tables.
>

View file

@ -1,6 +1,6 @@
name: nextcloud-aio-helm-chart
description: A generated Helm Chart for Nextcloud AIO from Skippbox Kompose
version: 12.4.0
version: 12.5.0
apiVersion: v2
keywords:
- latest

View file

@ -2,7 +2,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-apache
name: nextcloud-aio-apache
@ -17,7 +17,7 @@ spec:
template:
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-apache
spec:
@ -61,7 +61,7 @@ spec:
value: "{{ .Values.TIMEZONE }}"
- name: WHITEBOARD_HOST
value: nextcloud-aio-whiteboard
image: ghcr.io/nextcloud-releases/aio-apache:20260114_114729
image: ghcr.io/nextcloud-releases/aio-apache:20260122_105751
readinessProbe:
exec:
command:

View file

@ -2,7 +2,7 @@ apiVersion: v1
kind: Service
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-apache
name: nextcloud-aio-apache

View file

@ -3,7 +3,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-clamav
name: nextcloud-aio-clamav
@ -18,7 +18,7 @@ spec:
template:
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-clamav
spec:
@ -36,7 +36,7 @@ spec:
{{- end }}
initContainers:
- name: init-subpath
image: ghcr.io/nextcloud-releases/aio-alpine:20260114_114729
image: ghcr.io/nextcloud-releases/aio-alpine:20260122_105751
command:
- mkdir
- "-p"
@ -59,7 +59,7 @@ spec:
value: "{{ .Values.NEXTCLOUD_UPLOAD_LIMIT }}"
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-clamav:20260114_114729
image: ghcr.io/nextcloud-releases/aio-clamav:20260122_105751
readinessProbe:
exec:
command:

View file

@ -3,7 +3,7 @@ apiVersion: v1
kind: Service
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-clamav
name: nextcloud-aio-clamav

View file

@ -3,7 +3,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-collabora
name: nextcloud-aio-collabora
@ -16,7 +16,7 @@ spec:
template:
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-collabora
spec:
@ -36,9 +36,9 @@ spec:
- name: server_name
value: "{{ .Values.NC_DOMAIN }}"
{{- if contains "--o:support_key=" (join " " (.Values.ADDITIONAL_COLLABORA_OPTIONS | default list)) }}
image: ghcr.io/nextcloud-releases/aio-collabora-online:20260114_114729
image: ghcr.io/nextcloud-releases/aio-collabora-online:20260122_105751
{{- else }}
image: ghcr.io/nextcloud-releases/aio-collabora:20260114_114729
image: ghcr.io/nextcloud-releases/aio-collabora:20260122_105751
{{- end }}
readinessProbe:
exec:

View file

@ -3,7 +3,7 @@ apiVersion: v1
kind: Service
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-collabora
name: nextcloud-aio-collabora

View file

@ -2,7 +2,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-database
name: nextcloud-aio-database
@ -17,7 +17,7 @@ spec:
template:
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-database
spec:
@ -35,7 +35,7 @@ spec:
{{- end }}
initContainers:
- name: init-subpath
image: ghcr.io/nextcloud-releases/aio-alpine:20260114_114729
image: ghcr.io/nextcloud-releases/aio-alpine:20260122_105751
command:
- mkdir
- "-p"
@ -64,7 +64,7 @@ spec:
value: nextcloud
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-postgresql:20260114_114729
image: ghcr.io/nextcloud-releases/aio-postgresql:20260122_105751
readinessProbe:
exec:
command:

View file

@ -2,7 +2,7 @@ apiVersion: v1
kind: Service
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-database
name: nextcloud-aio-database

View file

@ -3,7 +3,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-fulltextsearch
name: nextcloud-aio-fulltextsearch
@ -18,13 +18,13 @@ spec:
template:
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-fulltextsearch
spec:
initContainers:
- name: init-volumes
image: ghcr.io/nextcloud-releases/aio-alpine:20260114_114729
image: ghcr.io/nextcloud-releases/aio-alpine:20260122_105751
command:
- chmod
- "777"
@ -54,7 +54,7 @@ spec:
value: basic
- name: xpack.security.enabled
value: "false"
image: ghcr.io/nextcloud-releases/aio-fulltextsearch:20260114_114729
image: ghcr.io/nextcloud-releases/aio-fulltextsearch:20260122_105751
readinessProbe:
exec:
command:

View file

@ -3,7 +3,7 @@ apiVersion: v1
kind: Service
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-fulltextsearch
name: nextcloud-aio-fulltextsearch

View file

@ -3,7 +3,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-imaginary
name: nextcloud-aio-imaginary
@ -16,7 +16,7 @@ spec:
template:
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-imaginary
spec:
@ -38,7 +38,7 @@ spec:
value: "{{ .Values.IMAGINARY_SECRET }}"
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-imaginary:20260114_114729
image: ghcr.io/nextcloud-releases/aio-imaginary:20260122_105751
readinessProbe:
exec:
command:

View file

@ -3,7 +3,7 @@ apiVersion: v1
kind: Service
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-imaginary
name: nextcloud-aio-imaginary

View file

@ -2,7 +2,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-nextcloud
name: nextcloud-aio-nextcloud
@ -17,7 +17,7 @@ spec:
template:
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-nextcloud
spec:
@ -38,7 +38,7 @@ spec:
# AIO settings start # Do not remove or change this line!
initContainers:
- name: init-volumes
image: ghcr.io/nextcloud-releases/aio-alpine:20260114_114729
image: ghcr.io/nextcloud-releases/aio-alpine:20260122_105751
command:
- chmod
- "777"
@ -190,7 +190,7 @@ spec:
value: "{{ .Values.WHITEBOARD_ENABLED }}"
- name: WHITEBOARD_SECRET
value: "{{ .Values.WHITEBOARD_SECRET }}"
image: ghcr.io/nextcloud-releases/aio-nextcloud:20260114_114729
image: ghcr.io/nextcloud-releases/aio-nextcloud:20260122_105751
{{- if eq (.Values.RPSS_ENABLED | default "no") "yes" }} # AIO-config - do not change this comment!
securityContext:
# The items below only work in container context

View file

@ -2,7 +2,7 @@ apiVersion: v1
kind: Service
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-nextcloud
name: nextcloud-aio-nextcloud

View file

@ -2,7 +2,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-notify-push
name: nextcloud-aio-notify-push
@ -17,7 +17,7 @@ spec:
template:
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-notify-push
spec:
@ -57,7 +57,7 @@ spec:
value: "6379"
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-notify-push:20260114_114729
image: ghcr.io/nextcloud-releases/aio-notify-push:20260122_105751
readinessProbe:
exec:
command:

View file

@ -2,7 +2,7 @@ apiVersion: v1
kind: Service
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-notify-push
name: nextcloud-aio-notify-push

View file

@ -3,7 +3,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-onlyoffice
name: nextcloud-aio-onlyoffice
@ -18,13 +18,13 @@ spec:
template:
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-onlyoffice
spec:
initContainers:
- name: init-volumes
image: ghcr.io/nextcloud-releases/aio-alpine:20260114_114729
image: ghcr.io/nextcloud-releases/aio-alpine:20260122_105751
command:
- chmod
- "777"
@ -42,7 +42,7 @@ spec:
value: "{{ .Values.ONLYOFFICE_SECRET }}"
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-onlyoffice:20260114_114729
image: ghcr.io/nextcloud-releases/aio-onlyoffice:20260122_105751
readinessProbe:
exec:
command:

View file

@ -3,7 +3,7 @@ apiVersion: v1
kind: Service
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-onlyoffice
name: nextcloud-aio-onlyoffice

View file

@ -2,7 +2,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-redis
name: nextcloud-aio-redis
@ -17,7 +17,7 @@ spec:
template:
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-redis
spec:
@ -39,7 +39,7 @@ spec:
value: "{{ .Values.REDIS_PASSWORD }}"
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-redis:20260114_114729
image: ghcr.io/nextcloud-releases/aio-redis:20260122_105751
readinessProbe:
exec:
command:

View file

@ -2,7 +2,7 @@ apiVersion: v1
kind: Service
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-redis
name: nextcloud-aio-redis

View file

@ -3,7 +3,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-talk
name: nextcloud-aio-talk
@ -16,7 +16,7 @@ spec:
template:
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-talk
spec:
@ -52,7 +52,7 @@ spec:
value: "{{ .Values.TURN_SECRET }}"
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-talk:20260114_114729
image: ghcr.io/nextcloud-releases/aio-talk:20260122_105751
readinessProbe:
exec:
command:

View file

@ -3,7 +3,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-talk-recording
name: nextcloud-aio-talk-recording
@ -18,7 +18,7 @@ spec:
template:
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-talk-recording
spec:
@ -44,7 +44,7 @@ spec:
value: "{{ .Values.RECORDING_SECRET }}"
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-talk-recording:20260114_114729
image: ghcr.io/nextcloud-releases/aio-talk-recording:20260122_105751
readinessProbe:
exec:
command:

View file

@ -3,7 +3,7 @@ apiVersion: v1
kind: Service
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-talk-recording
name: nextcloud-aio-talk-recording

View file

@ -4,7 +4,7 @@ apiVersion: v1
kind: Service
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-talk
name: nextcloud-aio-talk-public
@ -27,7 +27,7 @@ apiVersion: v1
kind: Service
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-talk
name: nextcloud-aio-talk

View file

@ -3,7 +3,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-whiteboard
name: nextcloud-aio-whiteboard
@ -16,7 +16,7 @@ spec:
template:
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-whiteboard
spec:
@ -50,7 +50,7 @@ spec:
value: redis
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-whiteboard:20260114_114729
image: ghcr.io/nextcloud-releases/aio-whiteboard:20260122_105751
readinessProbe:
exec:
command:

View file

@ -3,7 +3,7 @@ apiVersion: v1
kind: Service
metadata:
annotations:
kompose.version: 1.37.0 (fb0539e64)
kompose.version: 1.38.0 (a8f5d1cbd)
labels:
io.kompose.service: nextcloud-aio-whiteboard
name: nextcloud-aio-whiteboard

View file

@ -407,7 +407,7 @@ rm latest.yml
mv latest.yml.backup latest.yml
# Get version of AIO
AIO_VERSION="$(grep 'Nextcloud AIO ' ../php/templates/containers.twig | grep -oP '[0-9]+.[0-9]+.[0-9]+')"
AIO_VERSION="$(grep 'Nextcloud AIO ' ../php/templates/includes/aio-version.twig | grep -oP '[0-9]+.[0-9]+.[0-9]+')"
sed -i "s|^version:.*|version: $AIO_VERSION|" ../helm-chart/Chart.yaml
# Conversion of sample.conf

108
php/composer.lock generated
View file

@ -1644,16 +1644,16 @@
},
{
"name": "twig/twig",
"version": "v3.22.2",
"version": "v3.23.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "946ddeafa3c9f4ce279d1f34051af041db0e16f2"
"reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/946ddeafa3c9f4ce279d1f34051af041db0e16f2",
"reference": "946ddeafa3c9f4ce279d1f34051af041db0e16f2",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9",
"reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9",
"shasum": ""
},
"require": {
@ -1707,7 +1707,7 @@
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v3.22.2"
"source": "https://github.com/twigphp/Twig/tree/v3.23.0"
},
"funding": [
{
@ -1719,7 +1719,7 @@
"type": "tidelift"
}
],
"time": "2025-12-14T11:28:47+00:00"
"time": "2026-01-23T21:00:41+00:00"
}
],
"packages-dev": [
@ -3111,20 +3111,20 @@
},
{
"name": "league/uri",
"version": "7.7.0",
"version": "7.8.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri.git",
"reference": "8d587cddee53490f9b82bf203d3a9aa7ea4f9807"
"reference": "4436c6ec8d458e4244448b069cc572d088230b76"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/uri/zipball/8d587cddee53490f9b82bf203d3a9aa7ea4f9807",
"reference": "8d587cddee53490f9b82bf203d3a9aa7ea4f9807",
"url": "https://api.github.com/repos/thephpleague/uri/zipball/4436c6ec8d458e4244448b069cc572d088230b76",
"reference": "4436c6ec8d458e4244448b069cc572d088230b76",
"shasum": ""
},
"require": {
"league/uri-interfaces": "^7.7",
"league/uri-interfaces": "^7.8",
"php": "^8.1",
"psr/http-factory": "^1"
},
@ -3138,11 +3138,11 @@
"ext-gmp": "to improve IPV4 host parsing",
"ext-intl": "to handle IDN host with the best performance",
"ext-uri": "to use the PHP native URI class",
"jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain",
"league/uri-components": "Needed to easily manipulate URI objects components",
"league/uri-polyfill": "Needed to backport the PHP URI extension for older versions of PHP",
"jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain",
"league/uri-components": "to provide additional tools to manipulate URI objects components",
"league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP",
"php-64bit": "to improve IPV4 host parsing",
"rowbot/url": "to handle WHATWG URL",
"rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
"symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
},
"type": "library",
@ -3197,7 +3197,7 @@
"docs": "https://uri.thephpleague.com",
"forum": "https://thephpleague.slack.com",
"issues": "https://github.com/thephpleague/uri-src/issues",
"source": "https://github.com/thephpleague/uri/tree/7.7.0"
"source": "https://github.com/thephpleague/uri/tree/7.8.0"
},
"funding": [
{
@ -3205,20 +3205,20 @@
"type": "github"
}
],
"time": "2025-12-07T16:02:06+00:00"
"time": "2026-01-14T17:24:56+00:00"
},
{
"name": "league/uri-interfaces",
"version": "7.7.0",
"version": "7.8.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri-interfaces.git",
"reference": "62ccc1a0435e1c54e10ee6022df28d6c04c2946c"
"reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/62ccc1a0435e1c54e10ee6022df28d6c04c2946c",
"reference": "62ccc1a0435e1c54e10ee6022df28d6c04c2946c",
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c5c5cd056110fc8afaba29fa6b72a43ced42acd4",
"reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4",
"shasum": ""
},
"require": {
@ -3231,7 +3231,7 @@
"ext-gmp": "to improve IPV4 host parsing",
"ext-intl": "to handle IDN host with the best performance",
"php-64bit": "to improve IPV4 host parsing",
"rowbot/url": "to handle WHATWG URL",
"rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
"symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
},
"type": "library",
@ -3281,7 +3281,7 @@
"docs": "https://uri.thephpleague.com",
"forum": "https://thephpleague.slack.com",
"issues": "https://github.com/thephpleague/uri-src/issues",
"source": "https://github.com/thephpleague/uri-interfaces/tree/7.7.0"
"source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.0"
},
"funding": [
{
@ -3289,7 +3289,7 @@
"type": "github"
}
],
"time": "2025-12-07T16:03:21+00:00"
"time": "2026-01-15T06:54:53+00:00"
},
{
"name": "netresearch/jsonmapper",
@ -3455,16 +3455,16 @@
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "6.0.0",
"version": "6.0.1",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "02600c041e7d0f4b7d1fe1d260565ec525472fa9"
"reference": "2f5cbed597cb261d1ea458f3da3a9ad32e670b1e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/02600c041e7d0f4b7d1fe1d260565ec525472fa9",
"reference": "02600c041e7d0f4b7d1fe1d260565ec525472fa9",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/2f5cbed597cb261d1ea458f3da3a9ad32e670b1e",
"reference": "2f5cbed597cb261d1ea458f3da3a9ad32e670b1e",
"shasum": ""
},
"require": {
@ -3514,9 +3514,9 @@
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/6.0.0"
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/6.0.1"
},
"time": "2026-01-07T20:22:53+00:00"
"time": "2026-01-20T15:30:42+00:00"
},
{
"name": "phpdocumentor/type-resolver",
@ -3578,16 +3578,16 @@
},
{
"name": "phpstan/phpdoc-parser",
"version": "2.3.1",
"version": "2.3.2",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374"
"reference": "a004701b11273a26cd7955a61d67a7f1e525a45a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/16dbf9937da8d4528ceb2145c9c7c0bd29e26374",
"reference": "16dbf9937da8d4528ceb2145c9c7c0bd29e26374",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a",
"reference": "a004701b11273a26cd7955a61d67a7f1e525a45a",
"shasum": ""
},
"require": {
@ -3619,9 +3619,9 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.1"
"source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.2"
},
"time": "2026-01-12T11:33:04+00:00"
"time": "2026-01-25T14:56:51+00:00"
},
{
"name": "revolt/event-loop",
@ -3890,16 +3890,16 @@
},
{
"name": "symfony/console",
"version": "v6.4.31",
"version": "v6.4.32",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "f9f8a889f54c264f9abac3fc0f7a371ffca51997"
"reference": "0bc2199c6c1f05276b05956f1ddc63f6d7eb5fc3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/f9f8a889f54c264f9abac3fc0f7a371ffca51997",
"reference": "f9f8a889f54c264f9abac3fc0f7a371ffca51997",
"url": "https://api.github.com/repos/symfony/console/zipball/0bc2199c6c1f05276b05956f1ddc63f6d7eb5fc3",
"reference": "0bc2199c6c1f05276b05956f1ddc63f6d7eb5fc3",
"shasum": ""
},
"require": {
@ -3964,7 +3964,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v6.4.31"
"source": "https://github.com/symfony/console/tree/v6.4.32"
},
"funding": [
{
@ -3984,7 +3984,7 @@
"type": "tidelift"
}
],
"time": "2025-12-22T08:30:34+00:00"
"time": "2026-01-13T08:45:59+00:00"
},
{
"name": "symfony/filesystem",
@ -4058,16 +4058,16 @@
},
{
"name": "symfony/finder",
"version": "v6.4.31",
"version": "v6.4.33",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "5547f2e1f0ca8e2e7abe490156b62da778cfbe2b"
"reference": "24965ca011dac87431729640feef8bcf7b5523e0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/5547f2e1f0ca8e2e7abe490156b62da778cfbe2b",
"reference": "5547f2e1f0ca8e2e7abe490156b62da778cfbe2b",
"url": "https://api.github.com/repos/symfony/finder/zipball/24965ca011dac87431729640feef8bcf7b5523e0",
"reference": "24965ca011dac87431729640feef8bcf7b5523e0",
"shasum": ""
},
"require": {
@ -4102,7 +4102,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v6.4.31"
"source": "https://github.com/symfony/finder/tree/v6.4.33"
},
"funding": [
{
@ -4122,7 +4122,7 @@
"type": "tidelift"
}
],
"time": "2025-12-11T14:52:17+00:00"
"time": "2026-01-26T13:03:48+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
@ -4460,16 +4460,16 @@
},
{
"name": "symfony/string",
"version": "v7.4.0",
"version": "v7.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003"
"reference": "1c4b10461bf2ec27537b5f36105337262f5f5d6f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/d50e862cb0a0e0886f73ca1f31b865efbb795003",
"reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003",
"url": "https://api.github.com/repos/symfony/string/zipball/1c4b10461bf2ec27537b5f36105337262f5f5d6f",
"reference": "1c4b10461bf2ec27537b5f36105337262f5f5d6f",
"shasum": ""
},
"require": {
@ -4527,7 +4527,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v7.4.0"
"source": "https://github.com/symfony/string/tree/v7.4.4"
},
"funding": [
{
@ -4547,7 +4547,7 @@
"type": "tidelift"
}
],
"time": "2025-11-27T13:27:24+00:00"
"time": "2026-01-12T10:54:30+00:00"
},
{
"name": "vimeo/psalm",

View file

@ -0,0 +1,3 @@
#!/usr/bin/env bash
awk '/^ public [^f][^u][^n]/ { sub(/\$/, "", $3); print $3 }' src/Data/ConfigurationManager.php | sort

View file

@ -20,5 +20,10 @@
</extraFiles>
<issueHandlers>
<ClassMustBeFinal errorLevel="suppress" />
<MissingConstructor>
<errorLevel type="suppress">
<file name="src/Data/ConfigurationManager.php" /> <!-- We're using property hooks with virtual properties in that file, which Psalm wrongly complains about. See <https://github.com/vimeo/psalm/issues/11435>. -->
</errorLevel>
</MissingConstructor>
</issueHandlers>
</psalm>

View file

@ -1,7 +1,9 @@
document.addEventListener("DOMContentLoaded", function () {
// Hide submit button initially
const optionsFormSubmit = document.getElementById("options-form-submit");
optionsFormSubmit.style.display = 'none';
const optionsFormSubmit = document.querySelectorAll(".options-form-submit");
optionsFormSubmit.forEach(element => {
element.style.display = 'none';
});
const communityFormSubmit = document.getElementById("community-form-submit");
communityFormSubmit.style.display = 'none';
@ -12,6 +14,14 @@ document.addEventListener("DOMContentLoaded", function () {
const optionsContainersCheckboxes = document.querySelectorAll("#options-form input[type='checkbox']");
const communityContainersCheckboxes = document.querySelectorAll("#community-form input[type='checkbox']");
// Office suite radio buttons
const collaboraRadio = document.getElementById('office-collabora');
const onlyofficeRadio = document.getElementById('office-onlyoffice');
const noneRadio = document.getElementById('office-none');
const collaboraHidden = document.getElementById('collabora');
const onlyofficeHidden = document.getElementById('onlyoffice');
let initialOfficeSelection = null;
optionsContainersCheckboxes.forEach(checkbox => {
initialStateOptionsContainers[checkbox.id] = checkbox.checked; // Use checked property to capture actual initial state
});
@ -20,6 +30,17 @@ document.addEventListener("DOMContentLoaded", function () {
initialStateCommunityContainers[checkbox.id] = checkbox.checked; // Use checked property to capture actual initial state
});
// Store initial office suite selection
if (collaboraRadio && onlyofficeRadio && noneRadio) {
if (collaboraRadio.checked) {
initialOfficeSelection = 'collabora';
} else if (onlyofficeRadio.checked) {
initialOfficeSelection = 'onlyoffice';
} else {
initialOfficeSelection = 'none';
}
}
// Function to compare current states to initial states
function checkForOptionContainerChanges() {
let hasChanges = false;
@ -30,8 +51,32 @@ document.addEventListener("DOMContentLoaded", function () {
}
});
// Check office suite changes and sync to hidden inputs
if (collaboraRadio && onlyofficeRadio && noneRadio && collaboraHidden && onlyofficeHidden) {
let currentOfficeSelection = null;
if (collaboraRadio.checked) {
currentOfficeSelection = 'collabora';
collaboraHidden.value = 'on';
onlyofficeHidden.value = '';
} else if (onlyofficeRadio.checked) {
currentOfficeSelection = 'onlyoffice';
collaboraHidden.value = '';
onlyofficeHidden.value = 'on';
} else {
currentOfficeSelection = 'none';
collaboraHidden.value = '';
onlyofficeHidden.value = '';
}
if (currentOfficeSelection !== initialOfficeSelection) {
hasChanges = true;
}
}
// Show or hide submit button based on changes
optionsFormSubmit.style.display = hasChanges ? 'block' : 'none';
optionsFormSubmit.forEach(element => {
element.style.display = hasChanges ? 'block' : 'none';
});
}
// Function to compare current states to initial states
@ -82,6 +127,13 @@ document.addEventListener("DOMContentLoaded", function () {
// Initialize talk-recording visibility on page load
handleTalkVisibility(); // Ensure talk-recording is correctly initialized
// Add event listeners for office suite radio buttons
if (collaboraRadio && onlyofficeRadio && noneRadio) {
collaboraRadio.addEventListener('change', checkForOptionContainerChanges);
onlyofficeRadio.addEventListener('change', checkForOptionContainerChanges);
noneRadio.addEventListener('change', checkForOptionContainerChanges);
}
// Initial call to check for changes
checkForOptionContainerChanges();
checkForCommunityContainerChanges();

View file

@ -1,5 +1,5 @@
document.addEventListener("DOMContentLoaded", function(event) {
// Collabora
let collabora = document.getElementById("collabora");
const collabora = document.getElementById("office-collabora");
collabora.disabled = true;
});

View file

@ -1,7 +1,5 @@
document.addEventListener("DOMContentLoaded", function(event) {
// OnlyOffice
let onlyoffice = document.getElementById("onlyoffice");
if (onlyoffice) {
onlyoffice.disabled = true;
}
const onlyoffice = document.getElementById("office-onlyoffice");
onlyoffice.disabled = true;
});

View file

@ -91,10 +91,10 @@ $app->get('/containers', function (Request $request, Response $response, array $
$skip_domain_validation = isset($params['skip_domain_validation']);
return $view->render($response, 'containers.twig', [
'domain' => $configurationManager->GetDomain(),
'apache_port' => $configurationManager->GetApachePort(),
'borg_backup_host_location' => $configurationManager->GetBorgBackupHostLocation(),
'borg_remote_repo' => $configurationManager->GetBorgRemoteRepo(),
'domain' => $configurationManager->domain,
'apache_port' => $configurationManager->apachePort,
'borg_backup_host_location' => $configurationManager->borgBackupHostLocation,
'borg_remote_repo' => $configurationManager->borgRemoteRepo,
'borg_public_key' => $configurationManager->GetBorgPublicKey(),
'nextcloud_password' => $configurationManager->GetAndGenerateSecret('NEXTCLOUD_PASSWORD'),
'containers' => (new \AIO\ContainerDefinitionFetcher($container->get(\AIO\Data\ConfigurationManager::class), $container))->FetchDefinition(),
@ -103,45 +103,59 @@ $app->get('/containers', function (Request $request, Response $response, array $
'has_backup_run_once' => $configurationManager->hasBackupRunOnce(),
'is_backup_container_running' => $dockerActionManager->isBackupContainerRunning(),
'backup_exit_code' => $dockerActionManager->GetBackupcontainerExitCode(),
'is_instance_restore_attempt' => $configurationManager->isInstanceRestoreAttempt(),
'borg_backup_mode' => $configurationManager->GetBackupMode(),
'was_start_button_clicked' => $configurationManager->wasStartButtonClicked(),
'is_instance_restore_attempt' => $configurationManager->instanceRestoreAttempt,
'borg_backup_mode' => $configurationManager->backupMode,
'was_start_button_clicked' => $configurationManager->wasStartButtonClicked,
'has_update_available' => $dockerActionManager->isAnyUpdateAvailable(),
'last_backup_time' => $configurationManager->GetLastBackupTime(),
'backup_times' => $configurationManager->GetBackupTimes(),
'current_channel' => $dockerActionManager->GetCurrentChannel(),
'is_clamav_enabled' => $configurationManager->isClamavEnabled(),
'is_onlyoffice_enabled' => $configurationManager->isOnlyofficeEnabled(),
'is_collabora_enabled' => $configurationManager->isCollaboraEnabled(),
'is_talk_enabled' => $configurationManager->isTalkEnabled(),
'borg_restore_password' => $configurationManager->GetBorgRestorePassword(),
'is_clamav_enabled' => $configurationManager->isClamavEnabled,
'is_onlyoffice_enabled' => $configurationManager->isOnlyofficeEnabled,
'is_collabora_enabled' => $configurationManager->isCollaboraEnabled,
'is_talk_enabled' => $configurationManager->isTalkEnabled,
'borg_restore_password' => $configurationManager->borgRestorePassword,
'daily_backup_time' => $configurationManager->GetDailyBackupTime(),
'is_daily_backup_running' => $configurationManager->isDailyBackupRunning(),
'timezone' => $configurationManager->GetTimezone(),
'timezone' => $configurationManager->timezone,
'skip_domain_validation' => $configurationManager->shouldDomainValidationBeSkipped($skip_domain_validation),
'talk_port' => $configurationManager->GetTalkPort(),
'collabora_dictionaries' => $configurationManager->GetCollaboraDictionaries(),
'collabora_additional_options' => $configurationManager->GetAdditionalCollaboraOptions(),
'talk_port' => $configurationManager->talkPort,
'collabora_dictionaries' => $configurationManager->collaboraDictionaries,
'collabora_additional_options' => $configurationManager->collaboraAdditionalOptions,
'automatic_updates' => $configurationManager->areAutomaticUpdatesEnabled(),
'is_backup_section_enabled' => $configurationManager->isBackupSectionEnabled(),
'is_imaginary_enabled' => $configurationManager->isImaginaryEnabled(),
'is_fulltextsearch_enabled' => $configurationManager->isFulltextsearchEnabled(),
'is_backup_section_enabled' => !$configurationManager->disableBackupSection,
'is_imaginary_enabled' => $configurationManager->isImaginaryEnabled,
'is_fulltextsearch_enabled' => $configurationManager->isFulltextsearchEnabled,
'additional_backup_directories' => $configurationManager->GetAdditionalBackupDirectoriesString(),
'nextcloud_datadir' => $configurationManager->GetNextcloudDatadirMount(),
'nextcloud_mount' => $configurationManager->GetNextcloudMount(),
'nextcloud_upload_limit' => $configurationManager->GetNextcloudUploadLimit(),
'nextcloud_max_time' => $configurationManager->GetNextcloudMaxTime(),
'nextcloud_memory_limit' => $configurationManager->GetNextcloudMemoryLimit(),
'is_dri_device_enabled' => $configurationManager->isDriDeviceEnabled(),
'is_nvidia_gpu_enabled' => $configurationManager->isNvidiaGpuEnabled(),
'is_talk_recording_enabled' => $configurationManager->isTalkRecordingEnabled(),
'is_docker_socket_proxy_enabled' => $configurationManager->isDockerSocketProxyEnabled(),
'is_whiteboard_enabled' => $configurationManager->isWhiteboardEnabled(),
'nextcloud_datadir' => $configurationManager->nextcloudDatadirMount,
'nextcloud_mount' => $configurationManager->nextcloudMount,
'nextcloud_upload_limit' => $configurationManager->nextcloudUploadLimit,
'nextcloud_max_time' => $configurationManager->nextcloudMaxTime,
'nextcloud_memory_limit' => $configurationManager->nextcloudMemoryLimit,
'is_dri_device_enabled' => $configurationManager->nextcloudEnableDriDevice,
'is_nvidia_gpu_enabled' => $configurationManager->enableNvidiaGpu,
'is_talk_recording_enabled' => $configurationManager->isTalkRecordingEnabled,
'is_docker_socket_proxy_enabled' => $configurationManager->isDockerSocketProxyEnabled,
'is_whiteboard_enabled' => $configurationManager->isWhiteboardEnabled,
'community_containers' => $configurationManager->listAvailableCommunityContainers(),
'community_containers_enabled' => $configurationManager->GetEnabledCommunityContainers(),
'community_containers_enabled' => $configurationManager->aioCommunityContainers,
'bypass_container_update' => $bypass_container_update,
]);
})->setName('profile');
// Server-Sent Events endpoint for container events (container-start)
$app->get('/events/containers', function (Request $request, Response $response, array $args) use ($container) {
// Only allow authenticated sessions to access SSE
$authManager = $container->get(\AIO\Auth\AuthManager::class);
if (!$authManager->IsAuthenticated()) {
return $response->withStatus(401);
}
// Delegate streaming logic to the DockerController
$dockerController = $container->get(\AIO\Controller\DockerController::class);
return $dockerController->StreamContainerEvents($response);
});
$app->get('/login', function (Request $request, Response $response, array $args) use ($container) {
$view = Twig::fromRequest($request);
/** @var \AIO\Docker\DockerActionManager $dockerActionManager */

27
php/public/overlay-log.js Normal file
View file

@ -0,0 +1,27 @@
document.addEventListener("DOMContentLoaded", function(event) {
function displayOverlayLogMessage(message) {
const overlayLogElement = document.getElementById('overlay-log');
if (!overlayLogElement) {
return;
}
overlayLogElement.textContent = message;
}
// Attempt to connect to Server-Sent Events at /events/containers and listen for 'container-start' events
if (typeof EventSource !== 'undefined') {
try {
const serverSentEventSource = new EventSource('events/containers');
serverSentEventSource.addEventListener('container-start', function(serverSentEvent) {
try {
let parsedPayload = JSON.parse(serverSentEvent.data);
displayOverlayLogMessage(parsedPayload.name || serverSentEvent.data);
} catch (parseError) {
displayOverlayLogMessage(serverSentEvent.data);
}
});
serverSentEventSource.onerror = function() { serverSentEventSource.close(); };
} catch (connectionError) {
/* ignore if Server-Sent Events are not available */
}
}
});

View file

@ -28,7 +28,7 @@
--border-radius-large: 12px;
--default-font-size: 13px;
--checkbox-size: 16px;
--max-width: 500px;
--max-width: 580px;
--container-top-margin: 20px;
--container-bottom-margin: 20px;
--container-padding: 2px;
@ -37,9 +37,9 @@
--main-padding: 50px;
}
/* Breakpoint calculation: 500px (max-width) + 100px (main-padding * 2) + 200px (additional space) = 800px
/* Breakpoint calculation: 580px (max-width) + 100px (main-padding * 2) + 200px (additional space) = 880px
Note: Unfortunately, it's not possible to calculate this dynamically using CSS variables in media queries */
@media only screen and (max-width: 800px) {
@media only screen and (max-width: 880px) {
:root {
--container-top-margin: 50px;
--container-bottom-margin: 0px;
@ -549,3 +549,160 @@ input[type="checkbox"]:disabled:not(:checked) + label {
#theme-toggle:not(:hover) #theme-icon {
opacity: 0.6; /* Slightly transparent */
}
/* Office Suite Feature Cards */
.office-suite-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 16px;
margin: 20px 0;
align-items: stretch;
}
.office-radio {
display: none;
}
.office-card {
position: relative;
border: 2px solid var(--color-border-maxcontrast);
border-radius: var(--border-radius-large);
padding: 20px;
cursor: pointer;
transition: all 0.3s ease;
background-color: var(--color-main-background);
display: flex;
flex-direction: column;
}
.office-card-disabled {
opacity: 50%;
pointer-events: none;
}
.office-card:hover {
border-color: var(--color-primary-element);
box-shadow: 0 4px 12px rgba(0, 130, 201, 0.15);
transform: translateY(-2px);
}
#office-collabora:checked + .office-card,
#office-onlyoffice:checked + .office-card {
border-color: var(--color-nextcloud-blue);
background: linear-gradient(135deg, rgba(0, 130, 201, 0.08) 0%, rgba(0, 130, 201, 0.02) 100%);
}
[data-theme="dark"] #office-collabora:checked + .office-card,
[data-theme="dark"] #office-onlyoffice:checked + .office-card {
background: linear-gradient(135deg, rgba(0, 145, 242, 0.15) 0%, rgba(0, 145, 242, 0.03) 100%);
}
.office-card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.office-card h4 {
margin: 0;
height: 24px;
font-size: 18px;
font-weight: 600;
color: var(--color-main-text);
}
.office-checkmark {
flex-shrink: 0;
display: none;
}
#office-collabora:checked + .office-card .office-checkmark,
#office-onlyoffice:checked + .office-card .office-checkmark {
display: block;
}
.office-features {
list-style: none;
padding: 0;
margin: 0;
}
.office-features li {
position: relative;
padding-left: 20px;
margin-bottom: 4px;
font-size: var(--default-font-size);
line-height: 1.5;
color: var(--color-main-text);
}
.office-features li::before {
content: '•';
position: absolute;
left: 6px;
color: var(--color-nextcloud-blue);
font-weight: bold;
}
.office-checkbox {
position: absolute;
opacity: 0;
pointer-events: none;
}
.office-learn-more {
display: inline-flex;
align-items: center;
margin-top: 12px;
color: var(--color-primary-element);
text-decoration: none;
font-size: var(--default-font-size);
font-weight: 500;
transition: color 0.2s ease;
}
.office-learn-more:hover {
color: var(--color-primary-element-hover);
}
.office-learn-more svg {
transition: transform 0.2s ease;
}
.office-learn-more:hover svg {
transform: translateX(3px);
}
.office-none-card {
text-align: center;
margin: 12px 0 20px 0;
}
.office-none-label {
display: inline-flex;
align-items: center;
font-size: 13px;
color: var(--color-primary-element);
cursor: pointer;
opacity: 0.7;
transition: opacity 0.2s ease;
padding: 8px 12px;
border-radius: var(--border-radius);
}
.office-none-label:hover {
opacity: 1;
background-color: var(--color-primary-element-light);
}
#office-none:checked + .office-none-label {
opacity: 1;
font-weight: 600;
}
/* Responsive adjustments for mobile */
@media only screen and (max-width: 800px) {
.office-suite-cards {
grid-template-columns: 1fr;
}
}

View file

@ -15,11 +15,11 @@ readonly class AuthManager {
}
public function CheckCredentials(string $password) : bool {
return hash_equals($this->configurationManager->GetPassword(), $password);
return hash_equals($this->configurationManager->password, $password);
}
public function CheckToken(string $token) : bool {
return hash_equals($this->configurationManager->GetToken(), $token);
return hash_equals($this->configurationManager->aioToken, $token);
}
public function SetAuthState(bool $isLoggedIn) : void {

View file

@ -5,121 +5,56 @@ namespace AIO\Container;
use AIO\Data\ConfigurationManager;
use AIO\Docker\DockerActionManager;
use AIO\ContainerDefinitionFetcher;
use JsonException;
readonly class Container {
public function __construct(
private string $identifier,
private string $displayName,
private string $containerName,
private string $restartPolicy,
private int $maxShutdownTime,
private ContainerPorts $ports,
private string $internalPorts,
private ContainerVolumes $volumes,
private ContainerEnvironmentVariables $containerEnvironmentVariables,
public string $identifier,
public string $displayName,
public string $containerName,
public string $restartPolicy,
public int $maxShutdownTime,
public ContainerPorts $ports,
public string $internalPorts,
public ContainerVolumes $volumes,
public ContainerEnvironmentVariables $containerEnvironmentVariables,
/** @var string[] */
private array $dependsOn,
public array $dependsOn,
private string $uiSecret,
/** @var string[] */
private array $devices,
private bool $enableNvidiaGpu,
public array $devices,
public bool $enableNvidiaGpu,
/** @var string[] */
private array $capAdd,
private int $shmSize,
private bool $apparmorUnconfined,
public array $capAdd,
public int $shmSize,
public bool $apparmorUnconfined,
/** @var string[] */
private array $backupVolumes,
private array $nextcloudExecCommands,
private bool $readOnlyRootFs,
private array $tmpfs,
private bool $init,
private string $imageTag,
private AioVariables $aioVariables,
private string $documentation,
public array $backupVolumes,
public array $nextcloudExecCommands,
public bool $readOnlyRootFs,
public array $tmpfs,
public bool $init,
public string $imageTag,
public AioVariables $aioVariables,
public string $documentation,
private DockerActionManager $dockerActionManager
) {
}
public function GetIdentifier() : string {
return $this->identifier;
}
public function GetDisplayName() : string {
return $this->displayName;
}
public function GetContainerName() : string {
return $this->containerName;
}
public function GetRestartPolicy() : string {
return $this->restartPolicy;
}
public function GetImageTag() : string {
return $this->imageTag;
}
public function GetReadOnlySetting() : bool {
return $this->readOnlyRootFs;
}
public function GetInit() : bool {
return $this->init;
}
public function GetShmSize() : int {
return $this->shmSize;
}
public function isApparmorUnconfined() : bool {
return $this->apparmorUnconfined;
}
public function GetMaxShutdownTime() : int {
return $this->maxShutdownTime;
}
public function GetUiSecret() : string {
return $this->dockerActionManager->GetAndGenerateSecretWrapper($this->uiSecret);
}
public function GetTmpfs() : array {
return $this->tmpfs;
}
public function GetDevices() : array {
return $this->devices;
}
public function isNvidiaGpuEnabled() : bool {
return $this->enableNvidiaGpu;
}
public function GetCapAdds() : array {
return $this->capAdd;
}
public function GetBackupVolumes() : array {
return $this->backupVolumes;
}
public function GetPorts() : ContainerPorts {
return $this->ports;
}
public function GetInternalPort() : string {
return $this->internalPorts;
}
public function GetVolumes() : ContainerVolumes {
return $this->volumes;
}
/**
* @throws JsonException
*/
public function GetRunningState() : ContainerState {
return $this->dockerActionManager->GetContainerRunningState($this);
}
/**
* @throws JsonException
*/
public function GetRestartingState() : ContainerState {
return $this->dockerActionManager->GetContainerRestartingState($this);
}
@ -131,27 +66,4 @@ readonly class Container {
public function GetStartingState() : ContainerState {
return $this->dockerActionManager->GetContainerStartingState($this);
}
/**
* @return string[]
*/
public function GetDependsOn() : array {
return $this->dependsOn;
}
public function GetNextcloudExecCommands() : array {
return $this->nextcloudExecCommands;
}
public function GetEnvironmentVariables() : ContainerEnvironmentVariables {
return $this->containerEnvironmentVariables;
}
public function GetAioVariables() : AioVariables {
return $this->aioVariables;
}
public function GetDocumentation() : string {
return $this->documentation;
}
}

View file

@ -25,7 +25,7 @@ readonly class ContainerDefinitionFetcher {
$containers = $this->FetchDefinition();
foreach ($containers as $container) {
if ($container->GetIdentifier() === $id) {
if ($container->identifier === $id) {
return $container;
}
}
@ -41,7 +41,7 @@ readonly class ContainerDefinitionFetcher {
$data = json_decode((string)file_get_contents(DataConst::GetContainersDefinitionPath()), true, 512, JSON_THROW_ON_ERROR);
$additionalContainerNames = [];
foreach ($this->configurationManager->GetEnabledCommunityContainers() as $communityContainer) {
foreach ($this->configurationManager->aioCommunityContainers as $communityContainer) {
if ($communityContainer !== '') {
$path = DataConst::GetCommunityContainersDirectory() . '/' . $communityContainer . '/' . $communityContainer . '.json';
$additionalData = json_decode((string)file_get_contents($path), true, 512, JSON_THROW_ON_ERROR);
@ -56,42 +56,42 @@ readonly class ContainerDefinitionFetcher {
$containers = [];
foreach ($data['aio_services_v1'] as $entry) {
if ($entry['container_name'] === 'nextcloud-aio-clamav') {
if (!$this->configurationManager->isClamavEnabled()) {
if (!$this->configurationManager->isClamavEnabled) {
continue;
}
} elseif ($entry['container_name'] === 'nextcloud-aio-onlyoffice') {
if (!$this->configurationManager->isOnlyofficeEnabled()) {
if (!$this->configurationManager->isOnlyofficeEnabled) {
continue;
}
} elseif ($entry['container_name'] === 'nextcloud-aio-collabora') {
if (!$this->configurationManager->isCollaboraEnabled()) {
if (!$this->configurationManager->isCollaboraEnabled) {
continue;
}
if ($this->configurationManager->isCollaboraSubscriptionEnabled()) {
$entry['image'] = 'ghcr.io/nextcloud-releases/aio-collabora-online';
}
} elseif ($entry['container_name'] === 'nextcloud-aio-talk') {
if (!$this->configurationManager->isTalkEnabled()) {
if (!$this->configurationManager->isTalkEnabled) {
continue;
}
} elseif ($entry['container_name'] === 'nextcloud-aio-talk-recording') {
if (!$this->configurationManager->isTalkRecordingEnabled()) {
if (!$this->configurationManager->isTalkRecordingEnabled) {
continue;
}
} elseif ($entry['container_name'] === 'nextcloud-aio-imaginary') {
if (!$this->configurationManager->isImaginaryEnabled()) {
if (!$this->configurationManager->isImaginaryEnabled) {
continue;
}
} elseif ($entry['container_name'] === 'nextcloud-aio-fulltextsearch') {
if (!$this->configurationManager->isFulltextsearchEnabled()) {
if (!$this->configurationManager->isFulltextsearchEnabled) {
continue;
}
} elseif ($entry['container_name'] === 'nextcloud-aio-docker-socket-proxy') {
if (!$this->configurationManager->isDockerSocketProxyEnabled()) {
if (!$this->configurationManager->isDockerSocketProxyEnabled) {
continue;
}
} elseif ($entry['container_name'] === 'nextcloud-aio-whiteboard') {
if (!$this->configurationManager->isWhiteboardEnabled()) {
if (!$this->configurationManager->isWhiteboardEnabled) {
continue;
}
}
@ -113,34 +113,34 @@ readonly class ContainerDefinitionFetcher {
if (isset($entry['volumes'])) {
foreach ($entry['volumes'] as $value) {
if($value['source'] === '%BORGBACKUP_HOST_LOCATION%') {
$value['source'] = $this->configurationManager->GetBorgBackupHostLocation();
$value['source'] = $this->configurationManager->borgBackupHostLocation;
if($value['source'] === '') {
continue;
}
}
if($value['source'] === '%NEXTCLOUD_MOUNT%') {
$value['source'] = $this->configurationManager->GetNextcloudMount();
$value['source'] = $this->configurationManager->nextcloudMount;
if($value['source'] === '') {
continue;
}
} elseif ($value['source'] === '%NEXTCLOUD_DATADIR%') {
$value['source'] = $this->configurationManager->GetNextcloudDatadirMount();
$value['source'] = $this->configurationManager->nextcloudDatadirMount;
if ($value['source'] === '') {
continue;
}
} elseif ($value['source'] === '%WATCHTOWER_DOCKER_SOCKET_PATH%') {
$value['source'] = $this->configurationManager->GetDockerSocketPath();
$value['source'] = $this->configurationManager->dockerSocketPath;
if($value['source'] === '') {
continue;
}
} elseif ($value['source'] === '%NEXTCLOUD_TRUSTED_CACERTS_DIR%') {
$value['source'] = $this->configurationManager->GetTrustedCacertsDir();
$value['source'] = $this->configurationManager->trustedCacertsDir;
if($value['source'] === '') {
continue;
}
}
if ($value['destination'] === '%NEXTCLOUD_MOUNT%') {
$value['destination'] = $this->configurationManager->GetNextcloudMount();
$value['destination'] = $this->configurationManager->nextcloudMount;
if($value['destination'] === '') {
continue;
}
@ -168,39 +168,39 @@ readonly class ContainerDefinitionFetcher {
}
foreach ($valueDependsOn as $value) {
if ($value === 'nextcloud-aio-clamav') {
if (!$this->configurationManager->isClamavEnabled()) {
if (!$this->configurationManager->isClamavEnabled) {
continue;
}
} elseif ($value === 'nextcloud-aio-onlyoffice') {
if (!$this->configurationManager->isOnlyofficeEnabled()) {
if (!$this->configurationManager->isOnlyofficeEnabled) {
continue;
}
} elseif ($value === 'nextcloud-aio-collabora') {
if (!$this->configurationManager->isCollaboraEnabled()) {
if (!$this->configurationManager->isCollaboraEnabled) {
continue;
}
} elseif ($value === 'nextcloud-aio-talk') {
if (!$this->configurationManager->isTalkEnabled()) {
if (!$this->configurationManager->isTalkEnabled) {
continue;
}
} elseif ($value === 'nextcloud-aio-talk-recording') {
if (!$this->configurationManager->isTalkRecordingEnabled()) {
if (!$this->configurationManager->isTalkRecordingEnabled) {
continue;
}
} elseif ($value === 'nextcloud-aio-imaginary') {
if (!$this->configurationManager->isImaginaryEnabled()) {
if (!$this->configurationManager->isImaginaryEnabled) {
continue;
}
} elseif ($value === 'nextcloud-aio-fulltextsearch') {
if (!$this->configurationManager->isFulltextsearchEnabled()) {
if (!$this->configurationManager->isFulltextsearchEnabled) {
continue;
}
} elseif ($value === 'nextcloud-aio-docker-socket-proxy') {
if (!$this->configurationManager->isDockerSocketProxyEnabled()) {
if (!$this->configurationManager->isDockerSocketProxyEnabled) {
continue;
}
} elseif ($value === 'nextcloud-aio-whiteboard') {
if (!$this->configurationManager->isWhiteboardEnabled()) {
if (!$this->configurationManager->isWhiteboardEnabled) {
continue;
}
}

View file

@ -67,63 +67,34 @@ readonly class ConfigurationController {
}
if (isset($request->getParsedBody()['delete_timezone'])) {
$this->configurationManager->DeleteTimezone();
$this->configurationManager->deleteTimezone();
}
if (isset($request->getParsedBody()['timezone'])) {
$timezone = $request->getParsedBody()['timezone'] ?? '';
$this->configurationManager->SetTimezone($timezone);
$this->configurationManager->timezone = $timezone;
}
if (isset($request->getParsedBody()['options-form'])) {
if (isset($request->getParsedBody()['collabora']) && isset($request->getParsedBody()['onlyoffice'])) {
throw new InvalidSettingConfigurationException("Collabora and Onlyoffice are not allowed to be enabled at the same time!");
}
if (isset($request->getParsedBody()['clamav'])) {
$this->configurationManager->SetClamavEnabledState(1);
$officeSuiteChoice = $request->getParsedBody()['office_suite_choice'] ?? '';
if ($officeSuiteChoice === 'collabora') {
$this->configurationManager->isCollaboraEnabled = true;
$this->configurationManager->isOnlyofficeEnabled = false;
} elseif ($officeSuiteChoice === 'onlyoffice') {
$this->configurationManager->isCollaboraEnabled = false;
$this->configurationManager->isOnlyofficeEnabled = true;
} else {
$this->configurationManager->SetClamavEnabledState(0);
}
if (isset($request->getParsedBody()['onlyoffice'])) {
$this->configurationManager->SetOnlyofficeEnabledState(1);
} else {
$this->configurationManager->SetOnlyofficeEnabledState(0);
}
if (isset($request->getParsedBody()['collabora'])) {
$this->configurationManager->SetCollaboraEnabledState(1);
} else {
$this->configurationManager->SetCollaboraEnabledState(0);
}
if (isset($request->getParsedBody()['talk'])) {
$this->configurationManager->SetTalkEnabledState(1);
} else {
$this->configurationManager->SetTalkEnabledState(0);
}
if (isset($request->getParsedBody()['talk-recording'])) {
$this->configurationManager->SetTalkRecordingEnabledState(1);
} else {
$this->configurationManager->SetTalkRecordingEnabledState(0);
}
if (isset($request->getParsedBody()['imaginary'])) {
$this->configurationManager->SetImaginaryEnabledState(1);
} else {
$this->configurationManager->SetImaginaryEnabledState(0);
}
if (isset($request->getParsedBody()['fulltextsearch'])) {
$this->configurationManager->SetFulltextsearchEnabledState(1);
} else {
$this->configurationManager->SetFulltextsearchEnabledState(0);
}
if (isset($request->getParsedBody()['docker-socket-proxy'])) {
$this->configurationManager->SetDockerSocketProxyEnabledState(1);
} else {
$this->configurationManager->SetDockerSocketProxyEnabledState(0);
}
if (isset($request->getParsedBody()['whiteboard'])) {
$this->configurationManager->SetWhiteboardEnabledState(1);
} else {
$this->configurationManager->SetWhiteboardEnabledState(0);
$this->configurationManager->isCollaboraEnabled = false;
$this->configurationManager->isOnlyofficeEnabled = false;
}
$this->configurationManager->isClamavEnabled = isset($request->getParsedBody()['clamav']);
$this->configurationManager->isTalkEnabled = isset($request->getParsedBody()['talk']);
$this->configurationManager->isTalkRecordingEnabled = isset($request->getParsedBody()['talk-recording']);
$this->configurationManager->isImaginaryEnabled = isset($request->getParsedBody()['imaginary']);
$this->configurationManager->isFulltextsearchEnabled = isset($request->getParsedBody()['fulltextsearch']);
$this->configurationManager->isDockerSocketProxyEnabled = isset($request->getParsedBody()['docker-socket-proxy']);
$this->configurationManager->isWhiteboardEnabled = isset($request->getParsedBody()['whiteboard']);
}
if (isset($request->getParsedBody()['community-form'])) {
@ -137,7 +108,7 @@ readonly class ConfigurationController {
$enabledCC[] = $item;
}
}
$this->configurationManager->SetEnabledCommunityContainers($enabledCC);
$this->configurationManager->aioCommunityContainers = $enabledCC;
}
if (isset($request->getParsedBody()['delete_collabora_dictionaries'])) {
@ -146,16 +117,16 @@ readonly class ConfigurationController {
if (isset($request->getParsedBody()['collabora_dictionaries'])) {
$collaboraDictionaries = $request->getParsedBody()['collabora_dictionaries'] ?? '';
$this->configurationManager->SetCollaboraDictionaries($collaboraDictionaries);
$this->configurationManager->collaboraDictionaries = $collaboraDictionaries;
}
if (isset($request->getParsedBody()['delete_collabora_additional_options'])) {
$this->configurationManager->DeleteAdditionalCollaboraOptions();
$this->configurationManager->deleteAdditionalCollaboraOptions();
}
if (isset($request->getParsedBody()['collabora_additional_options'])) {
$additionalCollaboraOptions = $request->getParsedBody()['collabora_additional_options'] ?? '';
$this->configurationManager->SetAdditionalCollaboraOptions($additionalCollaboraOptions);
$this->configurationManager->collaboraAdditionalOptions = $additionalCollaboraOptions;
}
if (isset($request->getParsedBody()['delete_borg_backup_location_vars'])) {

View file

@ -8,6 +8,7 @@ use AIO\Docker\DockerActionManager;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use AIO\Data\ConfigurationManager;
use AIO\Data\DataConst;
readonly class DockerController {
private const string TOP_CONTAINER = 'nextcloud-aio-apache';
@ -23,7 +24,7 @@ readonly class DockerController {
$container = $this->containerDefinitionFetcher->GetContainerById($id);
// Start all dependencies first and then itself
foreach($container->GetDependsOn() as $dependency) {
foreach($container->dependsOn as $dependency) {
$this->PerformRecursiveContainerStart($dependency, $pullImage);
}
@ -34,6 +35,15 @@ readonly class DockerController {
return;
}
// Emit a container-start event for frontend clients (one JSON line per event)
try {
$this->pruneEventsFileIfTooLarge();
$this->writeEventsToFile(['event' => 'Starting container', 'name' => $id, 'time' => time()]);
} catch (\Throwable $e) {
// non-fatal, just log
error_log('Could not write container-start event: ' . $e->getMessage());
}
$this->dockerActionManager->DeleteContainer($container);
$this->dockerActionManager->CreateVolumes($container);
$this->dockerActionManager->PullImage($container, $pullImage);
@ -46,7 +56,7 @@ readonly class DockerController {
$container = $this->containerDefinitionFetcher->GetContainerById($id);
// Pull all dependencies first and then itself
foreach($container->GetDependsOn() as $dependency) {
foreach($container->dependsOn as $dependency) {
$this->PerformRecursiveImagePull($dependency);
}
@ -89,7 +99,7 @@ readonly class DockerController {
}
public function startBackup(bool $forceStopNextcloud = false) : void {
$this->configurationManager->SetBackupMode('backup');
$this->configurationManager->backupMode = 'backup';
$id = self::TOP_CONTAINER;
$this->PerformRecursiveContainerStop($id, $forceStopNextcloud);
@ -109,29 +119,25 @@ readonly class DockerController {
}
public function checkBackup() : void {
$this->configurationManager->SetBackupMode('check');
$this->configurationManager->backupMode = 'check';
$id = 'nextcloud-aio-borgbackup';
$this->PerformRecursiveContainerStart($id);
}
private function listBackup() : void {
$this->configurationManager->SetBackupMode('list');
$this->configurationManager->backupMode = 'list';
$id = 'nextcloud-aio-borgbackup';
$this->PerformRecursiveContainerStart($id);
}
public function StartBackupContainerRestore(Request $request, Response $response, array $args) : Response {
$this->configurationManager->SetBackupMode('restore');
$config = $this->configurationManager->GetConfig();
$config['selected-restore-time'] = $request->getParsedBody()['selected_restore_time'] ?? '';
if (isset($request->getParsedBody()['restore-exclude-previews'])) {
$config['restore-exclude-previews'] = 1;
} else {
$config['restore-exclude-previews'] = '';
}
$this->configurationManager->WriteConfig($config);
$this->configurationManager->startTransaction();
$this->configurationManager->backupMode = 'restore';
$this->configurationManager->selectedRestoreTime = $request->getParsedBody()['selected_restore_time'] ?? '';
$this->configurationManager->restoreExcludePreviews = isset($request->getParsedBody()['restore-exclude-previews']);
$this->configurationManager->commitTransaction();
$id = self::TOP_CONTAINER;
$forceStopNextcloud = true;
@ -144,22 +150,22 @@ readonly class DockerController {
}
public function StartBackupContainerCheckRepair(Request $request, Response $response, array $args) : Response {
$this->configurationManager->SetBackupMode('check-repair');
$this->configurationManager->backupMode = 'check-repair';
$id = 'nextcloud-aio-borgbackup';
$this->PerformRecursiveContainerStart($id);
// Restore to backup check which is needed to make the UI logic work correctly
$this->configurationManager->SetBackupMode('check');
$this->configurationManager->backupMode = 'check';
return $response->withStatus(201)->withHeader('Location', '.');
}
public function StartBackupContainerTest(Request $request, Response $response, array $args) : Response {
$this->configurationManager->SetBackupMode('test');
$config = $this->configurationManager->GetConfig();
$config['instance_restore_attempt'] = 0;
$this->configurationManager->WriteConfig($config);
$this->configurationManager->startTransaction();
$this->configurationManager->backupMode = 'test';
$this->configurationManager->instanceRestoreAttempt = false;
$this->configurationManager->commitTransaction();
$id = self::TOP_CONTAINER;
$this->PerformRecursiveContainerStop($id);
@ -182,20 +188,19 @@ readonly class DockerController {
}
if (isset($request->getParsedBody()['install_latest_major'])) {
$installLatestMajor = 32;
$installLatestMajor = '32';
} else {
$installLatestMajor = "";
$installLatestMajor = '';
}
$config = $this->configurationManager->GetConfig();
$this->configurationManager->startTransaction();
$this->configurationManager->installLatestMajor = $installLatestMajor;
// set AIO_URL
$config['AIO_URL'] = $host . ':' . (string)$port . $path;
$this->configurationManager->aioUrl = $host . ':' . (string)$port . $path;
// set wasStartButtonClicked
$config['wasStartButtonClicked'] = 1;
// set install_latest_major
$config['install_latest_major'] = $installLatestMajor;
$this->configurationManager->WriteConfig($config);
$this->configurationManager->wasStartButtonClicked = true;
$this->configurationManager->commitTransaction();
// Do not pull container images in case 'bypass_container_update' is set via url params
// Needed for local testing
$pullImage = !isset($request->getParsedBody()['bypass_container_update']);
@ -213,10 +218,7 @@ readonly class DockerController {
}
public function startTopContainer(bool $pullImage) : void {
$config = $this->configurationManager->GetConfig();
// set AIO_TOKEN
$config['AIO_TOKEN'] = bin2hex(random_bytes(24));
$this->configurationManager->WriteConfig($config);
$this->configurationManager->aioToken = bin2hex(random_bytes(24));
// Stop domaincheck since apache would not be able to start otherwise
$this->StopDomaincheckContainer();
@ -244,7 +246,7 @@ readonly class DockerController {
// This is a hack but no better solution was found for the meantime
// Stop Collabora first to make sure it force-saves
// See https://github.com/nextcloud/richdocuments/issues/3799
if ($id === self::TOP_CONTAINER && $this->configurationManager->isCollaboraEnabled()) {
if ($id === self::TOP_CONTAINER && $this->configurationManager->isCollaboraEnabled) {
$this->PerformRecursiveContainerStop('nextcloud-aio-collabora');
}
@ -255,7 +257,7 @@ readonly class DockerController {
// We want to stop the Nextcloud container after 10s and not wait for the configured stop_grace_period
$this->dockerActionManager->StopContainer($container, $forceStopNextcloud);
}
foreach($container->GetDependsOn() as $dependency) {
foreach($container->dependsOn as $dependency) {
$this->PerformRecursiveContainerStop($dependency, $forceStopNextcloud);
}
}
@ -269,6 +271,48 @@ readonly class DockerController {
return $response->withStatus(201)->withHeader('Location', '.');
}
public function StreamContainerEvents(Response $response): Response {
$eventsFile = \AIO\Data\DataConst::GetContainerEventsFile();
if (!file_exists($eventsFile)) {
@touch($eventsFile);
}
$body = $response->getBody();
$response = $response
->withHeader('Content-Type', 'text/event-stream')
->withHeader('Cache-Control', 'no-cache')
->withHeader('Connection', 'keep-alive');
$fileHandle = fopen($eventsFile, 'r');
if ($fileHandle === false) {
$body->write('');
return $response;
}
// Start at end of file so only new events are streamed
fseek($fileHandle, 0, SEEK_END);
while (!connection_aborted()) {
clearstatcache(false, $eventsFile);
$line = fgets($fileHandle);
if ($line !== false) {
$data = trim($line);
// Write SSE event
$body->write("event: container-start\n");
$body->write("data: $data\n\n");
$body->flush();
// Small pause to avoid tight loop
usleep(100000);
} else {
// No new data, wait a moment
usleep(200000);
}
}
fclose($fileHandle);
return $response;
}
public function stopTopContainer() : void {
$id = self::TOP_CONTAINER;
$this->PerformRecursiveContainerStop($id);
@ -277,7 +321,7 @@ readonly class DockerController {
public function StartDomaincheckContainer() : void
{
# Don't start if domain is already set
if ($this->configurationManager->GetDomain() !== '' || $this->configurationManager->wasStartButtonClicked()) {
if ($this->configurationManager->domain !== '' || $this->configurationManager->wasStartButtonClicked) {
return;
}
@ -315,4 +359,32 @@ readonly class DockerController {
$id = 'nextcloud-aio-domaincheck';
$this->PerformRecursiveContainerStop($id);
}
// Write container event to events file and prune old events
private function writeEventsToFile(array $payload): void {
$eventJson = json_encode($payload);
// Append new event (atomic via LOCK_EX)
file_put_contents($eventsFile, $eventJson . PHP_EOL, FILE_APPEND | LOCK_EX);
}
// Truncate the events file to keep only the last $maxBytes bytes, aligned to a newline boundary.
private function pruneEventsFileIfTooLarge(): void {
$eventsFile = DataConst::GetContainerEventsFile();
$maxBytes = 512 * 1024; // 512 KB
$maxLines = 1000; // keep last 1000 events
if (!file_exists($eventsFile) || filesize($eventsFile) <= $maxBytes) {
return;
}
$lines = file($eventsFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if ($lines !== false) {
$total = count($lines);
$start = max(0, $total - $maxLines);
$keep = array_slice($lines, $start);
// rewrite file with kept lines
file_put_contents($eventsFile, implode(PHP_EOL, $keep) . PHP_EOL, LOCK_EX);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -66,4 +66,8 @@ class DataConst {
public static function GetContainersDefinitionPath() : string {
return (string)realpath(__DIR__ . '/../../containers.json');
}
public static function GetContainerEventsFile() : string {
return self::GetDataDirectory() . '/container_events.log';
}
}

View file

@ -17,7 +17,7 @@ readonly class Setup {
}
$password = $this->passwordGenerator->GeneratePassword(8);
$this->configurationManager->SetPassword($password);
$this->configurationManager->password = $password;
return $password;
}

View file

@ -36,15 +36,15 @@ readonly class DockerActionManager {
}
private function BuildImageName(Container $container): string {
$tag = $container->GetImageTag();
$tag = $container->imageTag;
if ($tag === '%AIO_CHANNEL%') {
$tag = $this->GetCurrentChannel();
}
return $container->GetContainerName() . ':' . $tag;
return $container->containerName . ':' . $tag;
}
public function GetContainerRunningState(Container $container): ContainerState {
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($container->GetIdentifier())));
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($container->identifier)));
try {
$response = $this->guzzleClient->get($url);
} catch (RequestException $e) {
@ -64,7 +64,7 @@ readonly class DockerActionManager {
}
public function GetContainerRestartingState(Container $container): ContainerState {
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($container->GetIdentifier())));
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($container->identifier)));
try {
$response = $this->guzzleClient->get($url);
} catch (RequestException $e) {
@ -84,16 +84,16 @@ readonly class DockerActionManager {
}
public function GetContainerUpdateState(Container $container): VersionState {
$tag = $container->GetImageTag();
$tag = $container->imageTag;
if ($tag === '%AIO_CHANNEL%') {
$tag = $this->GetCurrentChannel();
}
$runningDigests = $this->GetRepoDigestsOfContainer($container->GetIdentifier());
$runningDigests = $this->GetRepoDigestsOfContainer($container->identifier);
if ($runningDigests === null) {
return VersionState::Different;
}
$remoteDigest = $this->GetLatestDigestOfTag($container->GetContainerName(), $tag);
$remoteDigest = $this->GetLatestDigestOfTag($container->containerName, $tag);
if ($remoteDigest === null) {
return VersionState::Equal;
}
@ -112,12 +112,12 @@ readonly class DockerActionManager {
return $runningState;
}
$containerName = $container->GetIdentifier();
$internalPort = $container->GetInternalPort();
$containerName = $container->identifier;
$internalPort = $container->internalPorts;
if ($internalPort === '%APACHE_PORT%') {
$internalPort = $this->configurationManager->GetApachePort();
$internalPort = $this->configurationManager->apachePort;
} elseif ($internalPort === '%TALK_PORT%') {
$internalPort = $this->configurationManager->GetTalkPort();
$internalPort = $this->configurationManager->talkPort;
}
if ($internalPort !== "" && $internalPort !== 'host') {
@ -134,7 +134,7 @@ readonly class DockerActionManager {
}
public function DeleteContainer(Container $container): void {
$url = $this->BuildApiUrl(sprintf('containers/%s?v=true', urlencode($container->GetIdentifier())));
$url = $this->BuildApiUrl(sprintf('containers/%s?v=true', urlencode($container->identifier)));
try {
$this->guzzleClient->delete($url);
} catch (RequestException $e) {
@ -166,17 +166,17 @@ readonly class DockerActionManager {
}
public function StartContainer(Container $container): void {
$url = $this->BuildApiUrl(sprintf('containers/%s/start', urlencode($container->GetIdentifier())));
$url = $this->BuildApiUrl(sprintf('containers/%s/start', urlencode($container->identifier)));
try {
$this->guzzleClient->post($url);
} catch (RequestException $e) {
throw new \Exception("Could not start container " . $container->GetIdentifier() . ": " . $e->getResponse()?->getBody()->getContents());
throw new \Exception("Could not start container " . $container->identifier . ": " . $e->getResponse()?->getBody()->getContents());
}
}
public function CreateVolumes(Container $container): void {
$url = $this->BuildApiUrl('volumes/create');
foreach ($container->GetVolumes()->GetVolumes() as $volume) {
foreach ($container->volumes->GetVolumes() as $volume) {
$forbiddenChars = [
'/',
];
@ -202,10 +202,10 @@ readonly class DockerActionManager {
public function CreateContainer(Container $container): void {
$volumes = [];
foreach ($container->GetVolumes()->GetVolumes() as $volume) {
foreach ($container->volumes->GetVolumes() as $volume) {
// // NEXTCLOUD_MOUNT gets added via bind-mount later on
// if ($container->GetIdentifier() === 'nextcloud-aio-nextcloud') {
// if ($volume->name === $this->configurationManager->GetNextcloudMount()) {
// if ($container->identifier === 'nextcloud-aio-nextcloud') {
// if ($volume->name === $this->configurationManager->nextcloudMount) {
// continue;
// }
// }
@ -228,46 +228,38 @@ readonly class DockerActionManager {
$requestBody['HostConfig']['Binds'] = $volumes;
}
$aioVariables = $container->GetAioVariables()->GetVariables();
foreach ($aioVariables as $variable) {
$config = $this->configurationManager->GetConfig();
$variable = $this->replaceEnvPlaceholders($variable);
$variableArray = explode('=', $variable);
$config[$variableArray[0]] = $variableArray[1];
$this->configurationManager->WriteConfig($config);
sleep(1);
}
$this->configurationManager->setAioVariables($container->aioVariables->GetVariables());
$envs = $container->GetEnvironmentVariables()->GetVariables();
$envs = $container->containerEnvironmentVariables->GetVariables();
// Special thing for the nextcloud container
if ($container->GetIdentifier() === 'nextcloud-aio-nextcloud') {
if ($container->identifier === 'nextcloud-aio-nextcloud') {
$envs[] = $this->GetAllNextcloudExecCommands();
}
foreach ($envs as $key => $env) {
$envs[$key] = $this->replaceEnvPlaceholders($env);
$envs[$key] = $this->configurationManager->replaceEnvPlaceholders($env);
}
if (count($envs) > 0) {
$requestBody['Env'] = $envs;
}
$requestBody['HostConfig']['RestartPolicy']['Name'] = $container->GetRestartPolicy();
$requestBody['HostConfig']['RestartPolicy']['Name'] = $container->restartPolicy;
$requestBody['HostConfig']['ReadonlyRootfs'] = $container->GetReadOnlySetting();
$requestBody['HostConfig']['ReadonlyRootfs'] = $container->readOnlyRootFs;
$exposedPorts = [];
if ($container->GetInternalPort() !== 'host') {
foreach ($container->GetPorts()->GetPorts() as $value) {
if ($container->internalPorts !== 'host') {
foreach ($container->ports->GetPorts() as $value) {
$port = $value->port;
$protocol = $value->protocol;
if ($port === '%APACHE_PORT%') {
$port = $this->configurationManager->GetApachePort();
$port = $this->configurationManager->apachePort;
// Do not expose udp if AIO is in reverse proxy mode
if ($port !== '443' && $protocol === 'udp') {
continue;
}
} else if ($port === '%TALK_PORT%') {
$port = $this->configurationManager->GetTalkPort();
$port = $this->configurationManager->talkPort;
}
$portWithProtocol = $port . '/' . $protocol;
$exposedPorts[$portWithProtocol] = null;
@ -279,17 +271,17 @@ readonly class DockerActionManager {
if (count($exposedPorts) > 0) {
$requestBody['ExposedPorts'] = $exposedPorts;
foreach ($container->GetPorts()->GetPorts() as $value) {
foreach ($container->ports->GetPorts() as $value) {
$port = $value->port;
$protocol = $value->protocol;
if ($port === '%APACHE_PORT%') {
$port = $this->configurationManager->GetApachePort();
$port = $this->configurationManager->apachePort;
// Do not expose udp if AIO is in reverse proxy mode
if ($port !== '443' && $protocol === 'udp') {
continue;
}
} else if ($port === '%TALK_PORT%') {
$port = $this->configurationManager->GetTalkPort();
$port = $this->configurationManager->talkPort;
// Skip publishing talk tcp port if it is set to 443
if ($port === '443' && $protocol === 'tcp') {
continue;
@ -297,7 +289,7 @@ readonly class DockerActionManager {
}
$ipBinding = $value->ipBinding;
if ($ipBinding === '%APACHE_IP_BINDING%') {
$ipBinding = $this->configurationManager->GetApacheIPBinding();
$ipBinding = $this->configurationManager->apacheIpBinding;
// Do not expose if AIO is in internal network mode
if ($ipBinding === '@INTERNAL') {
continue;
@ -314,8 +306,8 @@ readonly class DockerActionManager {
}
$devices = [];
foreach ($container->GetDevices() as $device) {
if ($device === '/dev/dri' && !$this->configurationManager->isDriDeviceEnabled()) {
foreach ($container->devices as $device) {
if ($device === '/dev/dri' && !$this->configurationManager->nextcloudEnableDriDevice) {
continue;
}
$devices[] = ["PathOnHost" => $device, "PathInContainer" => $device, "CgroupPermissions" => "rwm"];
@ -325,7 +317,7 @@ readonly class DockerActionManager {
$requestBody['HostConfig']['Devices'] = $devices;
}
if ($container->isNvidiaGpuEnabled() && $this->configurationManager->isNvidiaGpuEnabled()) {
if ($container->enableNvidiaGpu && $this->configurationManager->enableNvidiaGpu) {
$requestBody['HostConfig']['Runtime'] = 'nvidia';
$requestBody['HostConfig']['DeviceRequests'] = [
[
@ -336,13 +328,13 @@ readonly class DockerActionManager {
];
}
$shmSize = $container->GetShmSize();
$shmSize = $container->shmSize;
if ($shmSize > 0) {
$requestBody['HostConfig']['ShmSize'] = $shmSize;
}
$tmpfs = [];
foreach ($container->GetTmpfs() as $tmp) {
foreach ($container->tmpfs as $tmp) {
$mode = "";
if (str_contains($tmp, ':')) {
$mode = explode(':', $tmp)[1];
@ -354,9 +346,14 @@ readonly class DockerActionManager {
$requestBody['HostConfig']['Tmpfs'] = $tmpfs;
}
$requestBody['HostConfig']['Init'] = $container->GetInit();
$requestBody['HostConfig']['Init'] = $container->init;
$capAdds = $container->GetCapAdds();
$maxShutDownTime = $container->maxShutdownTime;
if ($maxShutDownTime > 0) {
$requestBody['StopTimeout'] = $maxShutDownTime;
}
$capAdds = $container->capAdd;
if (count($capAdds) > 0) {
$requestBody['HostConfig']['CapAdd'] = $capAdds;
}
@ -368,14 +365,14 @@ readonly class DockerActionManager {
// Disable SELinux for AIO containers so that it does not break them
$requestBody['HostConfig']['SecurityOpt'] = ["label:disable"];
if ($container->isApparmorUnconfined()) {
if ($container->apparmorUnconfined) {
$requestBody['HostConfig']['SecurityOpt'] = ["apparmor:unconfined", "label:disable"];
}
$mounts = [];
// Special things for the backup container which should not be exposed in the containers.json
if (str_starts_with($container->GetIdentifier(), 'nextcloud-aio-borgbackup')) {
if (str_starts_with($container->identifier, 'nextcloud-aio-borgbackup')) {
// Additional backup directories
foreach ($this->getAllBackupVolumes() as $additionalBackupVolumes) {
if ($additionalBackupVolumes !== '') {
@ -384,7 +381,7 @@ readonly class DockerActionManager {
}
// Make volumes read only in case of borgbackup container. The viewer makes them writeable
$isReadOnly = $container->GetIdentifier() === 'nextcloud-aio-borgbackup';
$isReadOnly = $container->identifier === 'nextcloud-aio-borgbackup';
foreach ($this->configurationManager->GetAdditionalBackupDirectoriesArray() as $additionalBackupDirectories) {
if ($additionalBackupDirectories !== '') {
@ -397,33 +394,33 @@ readonly class DockerActionManager {
}
// Special things for the talk container which should not be exposed in the containers.json
} elseif ($container->GetIdentifier() === 'nextcloud-aio-talk') {
} elseif ($container->identifier === 'nextcloud-aio-talk') {
// This is needed due to a bug in libwebsockets used in Janus which cannot handle unlimited ulimits
$requestBody['HostConfig']['Ulimits'] = [["Name" => "nofile", "Hard" => 200000, "Soft" => 200000]];
// // Special things for the nextcloud container which should not be exposed in the containers.json
// } elseif ($container->GetIdentifier() === 'nextcloud-aio-nextcloud') {
// foreach ($container->GetVolumes()->GetVolumes() as $volume) {
// if ($volume->name !== $this->configurationManager->GetNextcloudMount()) {
// } elseif ($container->identifier === 'nextcloud-aio-nextcloud') {
// foreach ($container->volumes->GetVolumes() as $volume) {
// if ($volume->name !== $this->configurationManager->nextcloudMount) {
// continue;
// }
// $mounts[] = ["Type" => "bind", "Source" => $volume->name, "Target" => $volume->mountPoint, "ReadOnly" => !$volume->isWritable, "BindOptions" => [ "Propagation" => "rshared"]];
// }
// Special things for the caddy community container
} elseif ($container->GetIdentifier() === 'nextcloud-aio-caddy') {
} elseif ($container->identifier === 'nextcloud-aio-caddy') {
$requestBody['HostConfig']['ExtraHosts'] = ['host.docker.internal:host-gateway'];
// Special things for the collabora container which should not be exposed in the containers.json
} elseif ($container->GetIdentifier() === 'nextcloud-aio-collabora') {
if (!$this->configurationManager->isSeccompDisabled()) {
} elseif ($container->identifier === 'nextcloud-aio-collabora') {
if (!$this->configurationManager->collaboraSeccompDisabled) {
// Load reference seccomp profile for collabora
$seccompProfile = (string)file_get_contents(DataConst::GetCollaboraSeccompProfilePath());
$requestBody['HostConfig']['SecurityOpt'] = ["label:disable", "seccomp=$seccompProfile"];
}
// Additional Collabora options
if ($this->configurationManager->GetAdditionalCollaboraOptions() !== '') {
$requestBody['Cmd'] = [$this->configurationManager->GetAdditionalCollaboraOptions()];
if ($this->configurationManager->collaboraAdditionalOptions !== '') {
$requestBody['Cmd'] = [$this->configurationManager->collaboraAdditionalOptions];
}
}
@ -434,12 +431,12 @@ readonly class DockerActionManager {
// All AIO-managed containers should not be updated externally via watchtower but gracefully by AIO's backup and update feature.
// Also DIUN should not send update notifications. See https://crazymax.dev/diun/providers/docker/#docker-labels
// Additionally set a default org.label-schema.vendor and com.docker.compose.project
$requestBody['Labels'] = ["com.centurylinklabs.watchtower.enable" => "false", "diun.enable" => "false", "org.label-schema.vendor" => "Nextcloud", "com.docker.compose.project" => "nextcloud-aio"];
$requestBody['Labels'] = ["com.centurylinklabs.watchtower.enable" => "false", "wud.watch" => "false", "diun.enable" => "false", "org.label-schema.vendor" => "Nextcloud", "com.docker.compose.project" => "nextcloud-aio"];
// Containers should have a fixed host name. See https://github.com/nextcloud/all-in-one/discussions/6589
$requestBody['Hostname'] = $container->GetIdentifier();
$requestBody['Hostname'] = $container->identifier;
$url = $this->BuildApiUrl('containers/create?name=' . $container->GetIdentifier());
$url = $this->BuildApiUrl('containers/create?name=' . $container->identifier);
try {
$this->guzzleClient->request(
'POST',
@ -449,18 +446,18 @@ readonly class DockerActionManager {
]
);
} catch (RequestException $e) {
throw new \Exception("Could not create container " . $container->GetIdentifier() . ": " . $e->getResponse()?->getBody()->getContents());
throw new \Exception("Could not create container " . $container->identifier . ": " . $e->getResponse()?->getBody()->getContents());
}
}
public function isRegistryReachable(Container $container): bool {
$tag = $container->GetImageTag();
$tag = $container->imageTag;
if ($tag === '%AIO_CHANNEL%') {
$tag = $this->GetCurrentChannel();
}
$remoteDigest = $this->GetLatestDigestOfTag($container->GetContainerName(), $tag);
$remoteDigest = $this->GetLatestDigestOfTag($container->containerName, $tag);
if ($remoteDigest === null) {
return false;
@ -472,7 +469,7 @@ readonly class DockerActionManager {
public function PullImage(Container $container, bool $pullImage = true): void {
// Skip database image pull if the last shutdown was not clean
if ($container->GetIdentifier() === 'nextcloud-aio-database') {
if ($container->identifier === 'nextcloud-aio-database') {
if ($this->GetDatabasecontainerExitCode() > 0) {
$pullImage = false;
error_log('Not pulling the latest database image because the container was not correctly shut down.');
@ -484,7 +481,7 @@ readonly class DockerActionManager {
if ($pullImage) {
if (!$this->isRegistryReachable($container)) {
$pullImage = false;
error_log('Not pulling the ' . $container->GetContainerName() . ' image for the ' . $container->GetIdentifier() . ' container because the registry does not seem to be reachable.');
error_log('Not pulling the ' . $container->containerName . ' image for the ' . $container->identifier . ' container because the registry does not seem to be reachable.');
}
}
@ -503,94 +500,28 @@ readonly class DockerActionManager {
} catch (\Throwable $e) {
$imageIsThere = false;
}
try {
$this->guzzleClient->post($url);
} catch (RequestException $e) {
$message = "Could not pull image " . $imageName . ": " . $e->getResponse()?->getBody()->getContents();
if ($imageIsThere === false) {
throw new \Exception($message);
} else {
error_log($message);
$maxRetries = 3;
for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
try {
$this->guzzleClient->post($url);
break;
} catch (RequestException $e) {
$message = "Could not pull image " . $imageName . " (attempt $attempt/$maxRetries): " . $e->getResponse()?->getBody()->getContents();
if ($attempt === $maxRetries) {
if ($imageIsThere === false) {
throw new \Exception($message);
} else {
error_log($message);
}
} else {
error_log($message . ' Retrying...');
sleep(1);
}
}
}
}
// Replaces placeholders in $envValue with their values.
// E.g. "%NC_DOMAIN%:%APACHE_PORT" becomes "my.nextcloud.com:11000"
private function replaceEnvPlaceholders(string $envValue): string {
// $pattern breaks down as:
// % - matches a literal percent sign
// ([^%]+) - capture group that matches one or more characters that are NOT percent signs
// % - matches the closing percent sign
//
// Assumes literal percent signs are always matched and there is no
// escaping.
$pattern = '/%([^%]+)%/';
$matchCount = preg_match_all($pattern, $envValue, $matches);
if ($matchCount === 0) {
return $envValue;
}
$placeholders = $matches[0]; // ["%PLACEHOLDER1%", "%PLACEHOLDER2%", ...]
$placeholderNames = $matches[1]; // ["PLACEHOLDER1", "PLACEHOLDER2", ...]
$placeholderPatterns = array_map(static fn(string $p) => '/' . preg_quote($p) . '/', $placeholders); // ["/%PLACEHOLDER1%/", ...]
$placeholderValues = array_map($this->getPlaceholderValue(...), $placeholderNames); // ["val1", "val2"]
// Guaranteed to be non-null because we found the placeholders in the preg_match_all.
return (string) preg_replace($placeholderPatterns, $placeholderValues, $envValue);
}
private function getPlaceholderValue(string $placeholder) : string {
return match ($placeholder) {
'NC_DOMAIN' => $this->configurationManager->GetDomain(),
'NC_BASE_DN' => $this->configurationManager->GetBaseDN(),
'AIO_TOKEN' => $this->configurationManager->GetToken(),
'BORGBACKUP_REMOTE_REPO' => $this->configurationManager->GetBorgRemoteRepo(),
'BORGBACKUP_MODE' => $this->configurationManager->GetBackupMode(),
'AIO_URL' => $this->configurationManager->GetAIOURL(),
'SELECTED_RESTORE_TIME' => $this->configurationManager->GetSelectedRestoreTime(),
'RESTORE_EXCLUDE_PREVIEWS' => $this->configurationManager->GetRestoreExcludePreviews(),
'APACHE_PORT' => $this->configurationManager->GetApachePort(),
'APACHE_IP_BINDING' => $this->configurationManager->GetApacheIPBinding(),
'TALK_PORT' => $this->configurationManager->GetTalkPort(),
'TURN_DOMAIN' => $this->configurationManager->GetTurnDomain(),
'NEXTCLOUD_MOUNT' => $this->configurationManager->GetNextcloudMount(),
'BACKUP_RESTORE_PASSWORD' => $this->configurationManager->GetBorgRestorePassword(),
'CLAMAV_ENABLED' => $this->configurationManager->isClamavEnabled() ? 'yes' : '',
'TALK_RECORDING_ENABLED' => $this->configurationManager->isTalkRecordingEnabled() ? 'yes' : '',
'ONLYOFFICE_ENABLED' => $this->configurationManager->isOnlyofficeEnabled() ? 'yes' : '',
'COLLABORA_ENABLED' => $this->configurationManager->isCollaboraEnabled() ? 'yes' : '',
'TALK_ENABLED' => $this->configurationManager->isTalkEnabled() ? 'yes' : '',
'UPDATE_NEXTCLOUD_APPS' => ($this->configurationManager->isDailyBackupRunning() && $this->configurationManager->areAutomaticUpdatesEnabled()) ? 'yes' : '',
'TIMEZONE' => $this->configurationManager->GetTimezone() === '' ? 'Etc/UTC' : $this->configurationManager->GetTimezone(),
'COLLABORA_DICTIONARIES' => $this->configurationManager->GetCollaboraDictionaries() === '' ? 'de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru' : $this->configurationManager->GetCollaboraDictionaries(),
'IMAGINARY_ENABLED' => $this->configurationManager->isImaginaryEnabled() ? 'yes' : '',
'FULLTEXTSEARCH_ENABLED' => $this->configurationManager->isFulltextsearchEnabled() ? 'yes' : '',
'DOCKER_SOCKET_PROXY_ENABLED' => $this->configurationManager->isDockerSocketProxyEnabled() ? 'yes' : '',
'NEXTCLOUD_UPLOAD_LIMIT' => $this->configurationManager->GetNextcloudUploadLimit(),
'NEXTCLOUD_MEMORY_LIMIT' => $this->configurationManager->GetNextcloudMemoryLimit(),
'NEXTCLOUD_MAX_TIME' => $this->configurationManager->GetNextcloudMaxTime(),
'BORG_RETENTION_POLICY' => $this->configurationManager->GetBorgRetentionPolicy(),
'FULLTEXTSEARCH_JAVA_OPTIONS' => $this->configurationManager->GetFulltextsearchJavaOptions(),
'NEXTCLOUD_TRUSTED_CACERTS_DIR' => $this->configurationManager->GetTrustedCacertsDir(),
'ADDITIONAL_DIRECTORIES_BACKUP' => $this->configurationManager->GetAdditionalBackupDirectoriesString() !== '' ? 'yes' : '',
'BORGBACKUP_HOST_LOCATION' => $this->configurationManager->GetBorgBackupHostLocation(),
'APACHE_MAX_SIZE' => (string)($this->configurationManager->GetApacheMaxSize()),
'COLLABORA_SECCOMP_POLICY' => $this->configurationManager->GetCollaboraSeccompPolicy(),
'NEXTCLOUD_STARTUP_APPS' => $this->configurationManager->GetNextcloudStartupApps(),
'NEXTCLOUD_ADDITIONAL_APKS' => $this->configurationManager->GetNextcloudAdditionalApks(),
'NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS' => $this->configurationManager->GetNextcloudAdditionalPhpExtensions(),
'INSTALL_LATEST_MAJOR' => $this->configurationManager->shouldLatestMajorGetInstalled() ? 'yes' : '',
'REMOVE_DISABLED_APPS' => $this->configurationManager->shouldDisabledAppsGetRemoved() ? 'yes' : '',
// Allow to get local ip-address of database container which allows to talk to it even in host mode (the container that requires this needs to be started first then)
'AIO_DATABASE_HOST' => gethostbyname('nextcloud-aio-database'),
// Allow to get local ip-address of caddy container and add it to trusted proxies automatically
'CADDY_IP_ADDRESS' => in_array('caddy', $this->configurationManager->GetEnabledCommunityContainers(), true) ? gethostbyname('nextcloud-aio-caddy') : '',
'WHITEBOARD_ENABLED' => $this->configurationManager->isWhiteboardEnabled() ? 'yes' : '',
default => $this->configurationManager->GetRegisteredSecret($placeholder),
};
}
private function isContainerUpdateAvailable(string $id): string {
$container = $this->containerDefinitionFetcher->GetContainerById($id);
@ -598,7 +529,7 @@ readonly class DockerActionManager {
if ($container->GetUpdateState() === VersionState::Different) {
$updateAvailable = '1';
}
foreach ($container->GetDependsOn() as $dependency) {
foreach ($container->dependsOn as $dependency) {
$updateAvailable .= $this->isContainerUpdateAvailable($dependency);
}
return $updateAvailable;
@ -606,7 +537,7 @@ readonly class DockerActionManager {
public function isAnyUpdateAvailable(): bool {
// return early if instance is not installed
if (!$this->configurationManager->wasStartButtonClicked()) {
if (!$this->configurationManager->wasStartButtonClicked) {
return false;
}
$id = 'nextcloud-aio-apache';
@ -622,10 +553,10 @@ readonly class DockerActionManager {
$container = $this->containerDefinitionFetcher->GetContainerById($id);
$backupVolumes = '';
foreach ($container->GetBackupVolumes() as $backupVolume) {
foreach ($container->backupVolumes as $backupVolume) {
$backupVolumes .= $backupVolume . ' ';
}
foreach ($container->GetDependsOn() as $dependency) {
foreach ($container->dependsOn as $dependency) {
$backupVolumes .= $this->getBackupVolumes($dependency);
}
return $backupVolumes;
@ -641,10 +572,10 @@ readonly class DockerActionManager {
$container = $this->containerDefinitionFetcher->GetContainerById($id);
$nextcloudExecCommands = '';
foreach ($container->GetNextcloudExecCommands() as $execCommand) {
foreach ($container->nextcloudExecCommands as $execCommand) {
$nextcloudExecCommands .= $execCommand . PHP_EOL;
}
foreach ($container->GetDependsOn() as $dependency) {
foreach ($container->dependsOn as $dependency) {
$nextcloudExecCommands .= $this->GetNextcloudExecCommands($dependency);
}
return $nextcloudExecCommands;
@ -776,7 +707,7 @@ readonly class DockerActionManager {
public function sendNotification(Container $container, string $subject, string $message, string $file = '/notify.sh'): void {
if ($this->GetContainerStartingState($container) === ContainerState::Running) {
$containerName = $container->GetIdentifier();
$containerName = $container->identifier;
// schedule the exec
$url = $this->BuildApiUrl(sprintf('containers/%s/exec', urlencode($containerName)));
@ -901,14 +832,14 @@ readonly class DockerActionManager {
// Add a secondary alias for domaincheck container, to keep it as similar to actual apache controller as possible.
// If a reverse-proxy is relying on container name as hostname this allows it to operate as usual and still validate the domain
// The domaincheck container and apache container are never supposed to be active at the same time because they use the same APACHE_PORT anyway, so this doesn't add any new constraints.
$alias = ($container->GetIdentifier() === 'nextcloud-aio-domaincheck') ? 'nextcloud-aio-apache' : '';
$alias = ($container->identifier === 'nextcloud-aio-domaincheck') ? 'nextcloud-aio-apache' : '';
$this->ConnectContainerIdToNetwork($container->GetIdentifier(), $container->GetInternalPort(), alias: $alias);
$this->ConnectContainerIdToNetwork($container->identifier, $container->internalPorts, alias: $alias);
if ($container->GetIdentifier() === 'nextcloud-aio-apache' || $container->GetIdentifier() === 'nextcloud-aio-domaincheck') {
$apacheAdditionalNetwork = $this->configurationManager->GetApacheAdditionalNetwork();
if ($container->identifier === 'nextcloud-aio-apache' || $container->identifier === 'nextcloud-aio-domaincheck') {
$apacheAdditionalNetwork = $this->configurationManager->apacheAdditionalNetwork;
if ($apacheAdditionalNetwork !== '') {
$this->ConnectContainerIdToNetwork($container->GetIdentifier(), $container->GetInternalPort(), $apacheAdditionalNetwork, false, $alias);
$this->ConnectContainerIdToNetwork($container->identifier, $container->internalPorts, $apacheAdditionalNetwork, false, $alias);
}
}
}
@ -917,9 +848,9 @@ readonly class DockerActionManager {
if ($forceStopContainer) {
$maxShutDownTime = 10;
} else {
$maxShutDownTime = $container->GetMaxShutdownTime();
$maxShutDownTime = $container->maxShutdownTime;
}
$url = $this->BuildApiUrl(sprintf('containers/%s/stop?t=%s', urlencode($container->GetIdentifier()), $maxShutDownTime));
$url = $this->BuildApiUrl(sprintf('containers/%s/stop?t=%s', urlencode($container->identifier), $maxShutDownTime));
try {
$this->guzzleClient->post($url);
} catch (RequestException $e) {

View file

@ -3,24 +3,24 @@
<span>
{% if c.GetStartingState().value == 'starting' %}
<span class="status running"></span>
{{ c.GetDisplayName() }}
(<a href="api/docker/logs?id={{ c.GetIdentifier() }}" target="_blank">Starting</a>)
{{ c.displayName }}
(<a href="api/docker/logs?id={{ c.identifier }}" target="_blank">Starting</a>)
{% elseif c.GetRunningState().value == 'running' %}
<span class="status success"></span>
{{ c.GetDisplayName() }}
(<a href="api/docker/logs?id={{ c.GetIdentifier() }}" target="_blank">Running</a>)
{{ c.displayName }}
(<a href="api/docker/logs?id={{ c.identifier }}" target="_blank">Running</a>)
{% else %}
<span class="status error"></span>
{{ c.GetDisplayName() }}
(<a href="api/docker/logs?id={{ c.GetIdentifier() }}" target="_blank">Stopped</a>)
{{ c.displayName }}
(<a href="api/docker/logs?id={{ c.identifier }}" target="_blank">Stopped</a>)
{% endif %}
{% if c.GetDocumentation() != '' %}
(<a target="_blank" href="{{ c.GetDocumentation() }}">docs</a>)
{% if c.documentation != '' %}
(<a target="_blank" href="{{ c.documentation }}">docs</a>)
{% endif %}
</span>
{% if c.GetUiSecret() != '' %}
<details>
<summary>Show password for {{ c.GetDisplayName() }}</summary>
<summary>Show password for {{ c.displayName }}</summary>
<input type="text" value="{{ c.GetUiSecret() }}" readonly>
</details>
{% endif %}

View file

@ -17,7 +17,8 @@
<div class="container">
<main>
<h1>Nextcloud AIO v12.5.0</h1>
{% set aio_version = include('includes/aio-version.twig') %}
<h1>Nextcloud AIO v{{ aio_version }}</h1>
{# Add 2nd tab warning #}
<script type="text/javascript" src="second-tab-warning.js"></script>
@ -26,7 +27,7 @@
<script type="text/javascript" src="timezone.js"></script>
{# js for optional containers and additional containers forms #}
<script type="text/javascript" src="containers-form-submit.js?v4"></script>
<script type="text/javascript" src="containers-form-submit.js?v5"></script>
{% set hasBackupLocation = borg_backup_host_location or borg_remote_repo %}
{% set isAnyRunning = false %}
@ -45,19 +46,19 @@
{% endif %}
{% for container in containers %}
{% if container.GetDisplayName() != '' and container.GetRunningState().value == 'running' %}
{% if container.displayName != '' and container.GetRunningState().value == 'running' %}
{% set isAnyRunning = true %}
{% endif %}
{% if container.GetDisplayName() != '' and container.GetRestartingState().value == 'restarting' %}
{% if container.displayName != '' and container.GetRestartingState().value == 'restarting' %}
{% set isAnyRestarting = true %}
{% endif %}
{% if container.GetIdentifier() == 'nextcloud-aio-watchtower' and container.GetRunningState().value == 'running' %}
{% if container.identifier == 'nextcloud-aio-watchtower' and container.GetRunningState().value == 'running' %}
{% set isWatchtowerRunning = true %}
{% endif %}
{% if container.GetIdentifier() == 'nextcloud-aio-domaincheck' and container.GetRunningState().value == 'running' %}
{% if container.identifier == 'nextcloud-aio-domaincheck' and container.GetRunningState().value == 'running' %}
{% set isDomaincheckRunning = true %}
{% endif %}
{% if container.GetIdentifier() == 'nextcloud-aio-apache' and container.GetStartingState().value == 'starting' %}
{% if container.identifier == 'nextcloud-aio-apache' and container.GetStartingState().value == 'starting' %}
{% set isApacheStarting = true %}
{% endif %}
{% endfor %}
@ -280,7 +281,7 @@
<ul>
{# @var containers \AIO\Container\Container[] #}
{% for container in containers %}
{% if container.GetDisplayName() != '' %}
{% if container.displayName != '' %}
{% include 'components/container-state.twig' with {'c': container} only %}
{% endif %}
{% endfor %}

View file

@ -0,0 +1 @@
12.6.0

Some files were not shown because too many files have changed in this diff Show more