Compare commits

...

92 commits

Author SHA1 Message Date
Pablo Zmdl
fec5bbc3c4 Move all properties to the top of the file
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
3499a07f7c Make nextcloudKeepDisabledApps an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
9069b8f14c Make 'enableNvidiaGpu' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
f5a035c450 Make 'nextcloudEnableDriDevice' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
76b871fc86 Make 'disableBackupSection' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
5f41443cc2 Make 'apacheAdditionalNetwork' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
0a208136cb Make 'collaboraSeccompDisabled' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
17f7663a64 Helper to booleanize environment-or-config-values
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
eb9abfae80 Make 'nextcloudAdditionalPhpExtensions' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
7530a408ec Make 'nextcloudAdditionalApks' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
be7bf8cf80 Make 'trustedCacertsDir' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
39984bcf8d Make 'dockerSocketPath' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
c23d98eb6a Make 'fulltextsearchJavaOptions' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
c8b133acf3 Make 'borgRetentionPolicy' an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
c8ae70f01d Move get-configurable-aio-variables.sh into php/ folder
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
b4c515e09f Camelize property nextcloud_memory_limit => nextcloudMemoryLimit
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
ed8d66dae2 Camelize property nextcloud_upload_limit => nextcloudUploadLimit
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
49e38961d3 Camelize property nextcloud_datadir_mount => nextcloudDatadirMount
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
b1dcdc1713 Camelize property nextcloud_mount => nextcloudMount
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
1091f0e8fe Camelize property talk_port => talkPort
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
5812660aad Camelize property apache_port => apachePort
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
0f52e047d2 Camelize property turn_domain => turnDomain
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
010b56cf12 Camelize property aio_community_containers => aioCommunityContainers
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
315881bb88 Camelize property collabora_additional_options => collaboraAdditionalOptions
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
b94395424c Camelize property collabora_dictionaries => collaboraDictionaries
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
df51a1974e Camelize property nextcloud_max_time => nextcloudMaxTime
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
e062e75cf9 Camelize key names from aio_variables from container specs
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
c11553c591 Camelize property apache_ip_binding => apacheIpBinding
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
ad9fbaeb9d Camelize property borg_restore_password => borgRestorePassword
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
f60d726f47 Camelize property borg_remote_repo => borgRemoteRepo
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
a81f91c11f Camelize property borg_backup_host_location => borgBackupHostLocation
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
0165b7cbde Camelize property install_latest_major => installLatestMajor
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
f281a7d045 Camelize property AIO_URL => aioUrl
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
6fe84a9fb2 Camelize property instance_restore_attempt => instanceRestoreAttempt
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
f0b1d91558 Camelize property AIO_TOKEN => aioToken
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
a16b02293a 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-26 10:50:55 +01:00
Pablo Zmdl
cc596c2b27 Type-cast get values to fix handling old config data
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
81858c4975 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-26 10:50:55 +01:00
Pablo Zmdl
b4364366f5 Replace setMultiple() by startTransaction() and commitTransaction()
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
a676223c05 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-26 10:50:55 +01:00
Pablo Zmdl
e40ce75759 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-26 10:50:55 +01:00
Pablo Zmdl
78626a60d2 Type for Closure argument
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
de2f8c9c99 Make psalm accept the property-hooks for virtual attributes
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
d4b016d024 Simplify some code a little bit
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
903ee42815 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-26 10:50:55 +01:00
Pablo Zmdl
05d98dfc75 Set multiple attributes at once
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
9119953b3e Remove residue code
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
0939b94397 Privatize GetConfig() and WriteConfig()
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
8cec4ab2bf Make nextcloud_max_time an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
abd761fe2f Make nextcloud_memory_limit an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
531c7c6fb6 Make nextcloud_datadir_mount an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
aa94ad05e8 Make nextcloud_mount an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
bc21ea9795 Make nextcloud_upload_limit an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
cf60cbe9bc Make talk_port an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
3f37b77255 Make apache_port an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
ac7ce99f6b Make apache_ip_binding an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
ab27265ed8 Make turn_domain an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
41be41b70a Make aio_community_containers an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
062930dbb4 Make collabora_additional_options an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
283efc20e9 Make collabora_dictionaries an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
cc62f83c86 Make timezone an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
16cfcc28be Make borg_restore_password an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
6311551252 Make borg_remote_repo an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
6488498bad Make borg_backup_host_location an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
8c4b05d768 Make domain an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:55 +01:00
Pablo Zmdl
7c60c69268 Make isFulltextsearchEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
16ce71412f Make isImaginaryEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
4203078701 Make isTalkRecordingEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
aca1ec163d Make isTalkEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
32e1f84bc9 Make isCollaboraEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
958b1dd28f Make isOnlyofficeEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
b6a1dc3731 Make isClamavEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
5226d9ff63 Make instance_restore_attempt an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
351abb8e65 Make isDockerSocketProxyEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
24859fd706 Make backupMode an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
462160aaa5 Make isWhiteboardEnabled an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
385eba66df Make restoreExcludePreviews an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
d3248746cc Make selectedRestoreTime an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
206ad7995a Make install_latest_major an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
cc2a6dde65 Make AIO_URL an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
3b26cd7b22 Make wasStartButtonClicked an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
c4c04ebcf4 Make password an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
4318488937 Make AIO_TOKEN an attribute
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
2d7f360706 Adapt GetAndGenerateSecret() to get() and set()
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
683cfe1292 Adapt GetEnvironmentalVariableOrConfig() to get() and set()
Signed-off-by: Pablo Zmdl <pablo@nextcloud.com>
2026-01-26 10:50:54 +01:00
Pablo Zmdl
a1df2fd33b 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-26 10:50:54 +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
12 changed files with 636 additions and 846 deletions

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

48
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": [
@ -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.32",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "5547f2e1f0ca8e2e7abe490156b62da778cfbe2b"
"reference": "3ec24885c1d9ababbb9c8f63bb42fea3c8c9b6de"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/5547f2e1f0ca8e2e7abe490156b62da778cfbe2b",
"reference": "5547f2e1f0ca8e2e7abe490156b62da778cfbe2b",
"url": "https://api.github.com/repos/symfony/finder/zipball/3ec24885c1d9ababbb9c8f63bb42fea3c8c9b6de",
"reference": "3ec24885c1d9ababbb9c8f63bb42fea3c8c9b6de",
"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.32"
},
"funding": [
{
@ -4122,7 +4122,7 @@
"type": "tidelift"
}
],
"time": "2025-12-11T14:52:17+00:00"
"time": "2026-01-10T14:09:00+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 }' php/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

@ -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,42 +103,42 @@ $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');

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

@ -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,27 @@ 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);
} 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->isClamavEnabled = isset($request->getParsedBody()['clamav']);
$this->configurationManager->isOnlyofficeEnabled = isset($request->getParsedBody()['onlyoffice']);
$this->configurationManager->isCollaboraEnabled = isset($request->getParsedBody()['collabora']);
$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 +101,7 @@ readonly class ConfigurationController {
$enabledCC[] = $item;
}
}
$this->configurationManager->SetEnabledCommunityContainers($enabledCC);
$this->configurationManager->aioCommunityContainers = $enabledCC;
}
if (isset($request->getParsedBody()['delete_collabora_dictionaries'])) {
@ -146,16 +110,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

@ -89,7 +89,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 +109,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 +140,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,19 +178,18 @@ 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
@ -213,10 +208,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 +236,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');
}
@ -277,7 +269,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;
}

File diff suppressed because it is too large Load diff

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

@ -115,9 +115,9 @@ readonly class DockerActionManager {
$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') {
@ -205,7 +205,7 @@ readonly class DockerActionManager {
foreach ($container->volumes->GetVolumes() as $volume) {
// // NEXTCLOUD_MOUNT gets added via bind-mount later on
// if ($container->identifier === 'nextcloud-aio-nextcloud') {
// if ($volume->name === $this->configurationManager->GetNextcloudMount()) {
// if ($volume->name === $this->configurationManager->nextcloudMount) {
// continue;
// }
// }
@ -228,15 +228,7 @@ readonly class DockerActionManager {
$requestBody['HostConfig']['Binds'] = $volumes;
}
$aioVariables = $container->aioVariables->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->containerEnvironmentVariables->GetVariables();
// Special thing for the nextcloud container
@ -244,7 +236,7 @@ readonly class DockerActionManager {
$envs[] = $this->GetAllNextcloudExecCommands();
}
foreach ($envs as $key => $env) {
$envs[$key] = $this->replaceEnvPlaceholders($env);
$envs[$key] = $this->configurationManager->replaceEnvPlaceholders($env);
}
if (count($envs) > 0) {
@ -261,13 +253,13 @@ readonly class DockerActionManager {
$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;
@ -283,13 +275,13 @@ readonly class DockerActionManager {
$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;
@ -315,7 +307,7 @@ readonly class DockerActionManager {
$devices = [];
foreach ($container->devices as $device) {
if ($device === '/dev/dri' && !$this->configurationManager->isDriDeviceEnabled()) {
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->enableNvidiaGpu && $this->configurationManager->isNvidiaGpuEnabled()) {
if ($container->enableNvidiaGpu && $this->configurationManager->enableNvidiaGpu) {
$requestBody['HostConfig']['Runtime'] = 'nvidia';
$requestBody['HostConfig']['DeviceRequests'] = [
[
@ -408,7 +400,7 @@ readonly class DockerActionManager {
// // Special things for the nextcloud container which should not be exposed in the containers.json
// } elseif ($container->identifier === 'nextcloud-aio-nextcloud') {
// foreach ($container->volumes->GetVolumes() as $volume) {
// if ($volume->name !== $this->configurationManager->GetNextcloudMount()) {
// if ($volume->name !== $this->configurationManager->nextcloud_mount) {
// continue;
// }
// $mounts[] = ["Type" => "bind", "Source" => $volume->name, "Target" => $volume->mountPoint, "ReadOnly" => !$volume->isWritable, "BindOptions" => [ "Propagation" => "rshared"]];
@ -420,15 +412,15 @@ readonly class DockerActionManager {
// Special things for the collabora container which should not be exposed in the containers.json
} elseif ($container->identifier === 'nextcloud-aio-collabora') {
if (!$this->configurationManager->isSeccompDisabled()) {
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];
}
}
@ -530,82 +522,6 @@ readonly class DockerActionManager {
}
}
// 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);
@ -621,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';
@ -921,7 +837,7 @@ readonly class DockerActionManager {
$this->ConnectContainerIdToNetwork($container->identifier, $container->internalPorts, alias: $alias);
if ($container->identifier === 'nextcloud-aio-apache' || $container->identifier === 'nextcloud-aio-domaincheck') {
$apacheAdditionalNetwork = $this->configurationManager->GetApacheAdditionalNetwork();
$apacheAdditionalNetwork = $this->configurationManager->apacheAdditionalNetwork;
if ($apacheAdditionalNetwork !== '') {
$this->ConnectContainerIdToNetwork($container->identifier, $container->internalPorts, $apacheAdditionalNetwork, false, $alias);
}