Compare commits

...

132 Commits

Author SHA1 Message Date
Simon L.
7560694535 Merge pull request #7119 from nextcloud/enh/noid/fix-variable-types
nextcloud-entrypoint: fix variable types of fulltextsearch:configure
2025-11-13 11:44:23 +01:00
Simon L.
0b6496799c Merge pull request #7118 from nextcloud/enh/noid/disable-whiteboard
change whiteboard to be disabled by default
2025-11-13 11:44:14 +01:00
Simon L.
c3ab1cc4ba nextcloud-entrypoint: fix variable types of fulltextsearch:configure
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-13 11:42:57 +01:00
Simon L.
0320569260 change whiteboard to be disable by default
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-13 11:08:29 +01:00
Simon L.
eb31220606 Merge pull request #7117 from nextcloud/enh/noid/move-skip-domain-validation
domain-validation: move skipping domain validation log to a different place
2025-11-13 10:33:44 +01:00
Simon L.
e38a0d0a03 domain-validation: move skipping domain validation log to a different place
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-13 10:31:29 +01:00
Simon L.
34385374e5 Merge pull request #7115 from nextcloud/enh/noid/clamav-tmp
clamav: create `/tmp` directory
2025-11-12 14:44:37 +01:00
Simon L.
5a081faee1 clamav: create /tmp directory
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-12 14:44:05 +01:00
Simon L.
edd03058fd Merge pull request #7114 from nextcloud/watchtower-container-update
watchtower container update
2025-11-12 13:21:19 +01:00
Simon L.
58b12d04a5 Merge pull request #7113 from nextcloud/aio-dependency-update
PHP dependency updates
2025-11-12 13:21:03 +01:00
szaimen
5b2cd9d549 watchtower-update automated change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-11-12 12:11:53 +00:00
szaimen
a5fd4b2142 php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-11-12 12:09:02 +00:00
Simon L.
73fb28096a Merge pull request #7110 from nextcloud/feat/workflow-auto-update-all
ci: update all workflow templates from organization template repository
2025-11-12 11:50:57 +01:00
Simon L.
fcba94e4d1 restore some details
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-12 11:49:46 +01:00
Nextcloud bot
1811ba1d38 ci: update all workflow templates from organization template repository
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-11-12 10:35:37 +00:00
Simon L.
2628d43ecd Revert "create dispatch-workflow-repo action"
This reverts commit 738022a936.
2025-11-12 11:14:07 +01:00
Simon L.
738022a936 create dispatch-workflow-repo action
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-12 11:13:06 +01:00
Simon L.
b43346e539 Merge pull request #7107 from nextcloud/dependabot/docker/Containers/fulltextsearch/elasticsearch-8.19.7
build(deps): bump elasticsearch from 8.19.6 to 8.19.7 in /Containers/fulltextsearch
2025-11-12 08:35:10 +01:00
dependabot[bot]
e152bc3e45 build(deps): bump elasticsearch in /Containers/fulltextsearch
Bumps elasticsearch from 8.19.6 to 8.19.7.

---
updated-dependencies:
- dependency-name: elasticsearch
  dependency-version: 8.19.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-12 04:14:11 +00:00
Simon L.
0e4a633c24 Merge pull request #7104 from nextcloud/fix/whiteboard-recording-chrome-imprv
fix whiteboard recording chrome #2
2025-11-11 12:42:44 +01:00
Hoang Pham
ce74283f29 fix whiteboard recording chrome
Signed-off-by: Hoang Pham <hoangmaths96@gmail.com>
2025-11-11 18:28:50 +07:00
Simon L.
693fd9a516 Merge pull request #7103 from nextcloud/fix/whiteboard-recording-chrome
fix whiteboard recording chrome
2025-11-11 11:50:39 +01:00
Hoang Pham
d82e533a4b fix whiteboard recording chrome
Signed-off-by: Hoang Pham <hoangmaths96@gmail.com>
2025-11-11 17:39:10 +07:00
Simon L.
b8a8ea3685 Merge pull request #6548 from nextcloud/enh/noid/caddy-change-to-v3
aio-caddy: update to v3 and further adjustments
2025-11-11 11:27:19 +01:00
Simon L.
2d4d9d76d6 aio-caddy: change to v3 and further adjustments
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-11 11:21:55 +01:00
Simon L.
bf1df2f72e Merge pull request #7102 from nextcloud/enh/noid/fix-clamav
clamav: use default clamd.comf path
2025-11-11 10:46:23 +01:00
Simon L.
1d68592611 clamav: use default clamd.comf path
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-11 10:45:17 +01:00
Simon L.
be8645d319 Merge pull request #7101 from nextcloud/enh/noid/size-uses-M
clamav: size can only use M or K but not G as unit
2025-11-11 10:21:24 +01:00
Simon L.
e44a99ced2 clamav: size can only use M or K but not G as unit
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-11 10:20:47 +01:00
Simon L.
8da65e3dff Merge pull request #7100 from nextcloud/enh/noid/remove-checkduplicate
ConnectContainerIdToNetwork: remove `CheckDuplicate` as it is deprecated
2025-11-11 10:11:10 +01:00
Simon L.
673873da63 ConnectContainerIdToNetwork: remove CheckDuplicate as it is deprecated
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-11 10:07:06 +01:00
Simon L.
93a1ae834f Merge pull request #7099 from nextcloud/enh/7095/hardcode-clamav-size
clamav: set `StreamMaxLength` to `2G`
2025-11-11 09:54:45 +01:00
Simon L.
875ecbd110 Merge pull request #7098 from nextcloud/enh/noid/increase-api-version
increase API version to 1.44
2025-11-11 09:54:21 +01:00
Simon L.
8627366a39 clamav: hardcode StreamMaxLength to 2G
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-11 09:48:17 +01:00
Simon L.
de1f5aeac8 Merge pull request #7097 from nextcloud/dependabot/docker/Containers/docker-socket-proxy/haproxy-3.2.8-alpine
build(deps): bump haproxy from 3.2.7-alpine to 3.2.8-alpine in /Containers/docker-socket-proxy
2025-11-11 09:18:53 +01:00
Simon L.
03e3fd0b16 increase API version to 1.44
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-11 09:18:24 +01:00
dependabot[bot]
6cfa47e072 build(deps): bump haproxy in /Containers/docker-socket-proxy
Bumps haproxy from 3.2.7-alpine to 3.2.8-alpine.

---
updated-dependencies:
- dependency-name: haproxy
  dependency-version: 3.2.8-alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-11 04:14:33 +00:00
Simon L.
767e0d4b9f fix some remaining issues with collabora
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-10 15:52:35 +01:00
Simon L.
cc65481d51 fix some paths and seccompprofile
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-10 15:29:22 +01:00
Simon L.
e15304e28f Merge pull request #7094 from nextcloud/watchtower-container-update
watchtower container update
2025-11-10 14:44:06 +01:00
szaimen
472cfdbcb8 watchtower-update automated change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-11-10 13:42:56 +00:00
Simon L.
6ab60592ad fix detail
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-10 14:42:29 +01:00
Simon L.
da5d4ee5af fix watchtower update script
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-10 14:39:53 +01:00
Simon L.
f7b8ca9757 Merge pull request #7093 from nextcloud/dependabot/github_actions/dot-github/workflows/softprops/turnstyle-3.2.1
build(deps): bump softprops/turnstyle from 3.2.0 to 3.2.1 in /.github/workflows
2025-11-10 14:30:55 +01:00
Simon L.
2137f4ee1e Merge pull request #7091 from nextcloud/imaginary-container-update
Imaginary update
2025-11-10 14:30:25 +01:00
dependabot[bot]
8cd5dd929c build(deps): bump softprops/turnstyle in /.github/workflows
Bumps [softprops/turnstyle](https://github.com/softprops/turnstyle) from 3.2.0 to 3.2.1.
- [Release notes](https://github.com/softprops/turnstyle/releases)
- [Changelog](https://github.com/softprops/turnstyle/blob/master/CHANGELOG.md)
- [Commits](9d692f15fa...2e4451ef94)

---
updated-dependencies:
- dependency-name: softprops/turnstyle
  dependency-version: 3.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 13:22:55 +00:00
szaimen
c2ea69a918 imaginary-update automated change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-11-09 12:03:08 +00:00
Simon L.
e5f744385b Merge pull request #7088 from nextcloud/enh/noid/simplify-domain-validation-logic
simplify `skip_domain_validation` logic a bit
2025-11-08 08:50:35 +01:00
Simon L.
5759d5d364 simplify skip_domain_validation logic a bit
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-08 08:48:29 +01:00
Simon L.
a267fe5cba Merge pull request #7086 from nextcloud/enh/6774/allow-skip-domain-validation
aio-interface: allow to skip domain validation via url-param
2025-11-07 18:09:32 +01:00
Simon L.
858717f740 aio-interface: allow to skip domain validation via url-param
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-07 16:44:15 +01:00
Simon L.
066e495dfe Merge pull request #7085 from nextcloud/dependabot/github_actions/dot-github/workflows/codespell-project/actions-codespell-2.2
build(deps): bump codespell-project/actions-codespell from 2.1 to 2.2 in /.github/workflows
2025-11-07 16:42:58 +01:00
Simon L.
93e59d0e25 Merge pull request #7083 from nextcloud/aio-dependency-update
PHP dependency updates
2025-11-07 16:42:38 +01:00
Simon L.
2c547178be Merge pull request #7084 from nextcloud/nextcloud-container-update
Nextcloud dependency update
2025-11-07 16:42:20 +01:00
dependabot[bot]
72455ccae1 build(deps): bump codespell-project/actions-codespell
Bumps [codespell-project/actions-codespell](https://github.com/codespell-project/actions-codespell) from 2.1 to 2.2.
- [Release notes](https://github.com/codespell-project/actions-codespell/releases)
- [Commits](406322ec52...8f01853be1)

---
updated-dependencies:
- dependency-name: codespell-project/actions-codespell
  dependency-version: '2.2'
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-07 12:42:49 +00:00
szaimen
72b504951a nextcloud-update automated change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-11-07 12:13:22 +00:00
szaimen
82c2d06c72 php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-11-07 12:03:28 +00:00
Simon L.
cc518d1cb2 Merge pull request #7081 from nextcloud/aio-dependency-update
PHP dependency updates
2025-11-06 13:31:18 +01:00
szaimen
5657530508 php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-11-06 12:03:27 +00:00
Simon L.
6f9adffd41 Merge pull request #7080 from nextcloud/enh/noid/remove-delete-logic
borg-init: remove unnecessary delete logic
2025-11-06 12:00:03 +01:00
Simon L.
a7b9c95c6c borg-init: remove unnecessary delete logic
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-06 11:40:14 +01:00
Simon L.
849f052a41 Merge pull request #6814 from nextcloud/enh/noid/collabora-online
collabora: allow to use enterprise container image with support key
2025-11-06 11:24:23 +01:00
Simon L.
0a42584238 collabora: allow to use enterprise container image with support key
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-06 11:21:46 +01:00
Simon L.
d5c532fc27 Merge pull request #7078 from nextcloud/dependabot/docker/Containers/watchtower/golang-1.25.4-alpine3.22
build(deps): bump golang from 1.25.3-alpine3.22 to 1.25.4-alpine3.22 in /Containers/watchtower
2025-11-06 09:00:58 +01:00
Simon L.
fd6f2b663b Merge pull request #7077 from nextcloud/dependabot/docker/Containers/mastercontainer/docker-28.5.2-cli
build(deps): bump docker from 28.5.1-cli to 28.5.2-cli in /Containers/mastercontainer
2025-11-06 09:00:38 +01:00
Simon L.
1d10ed0f9b Merge pull request #7076 from nextcloud/dependabot/docker/Containers/imaginary/golang-1.25.4-alpine3.22
build(deps): bump golang from 1.25.3-alpine3.22 to 1.25.4-alpine3.22 in /Containers/imaginary
2025-11-06 09:00:13 +01:00
dependabot[bot]
2da872244c build(deps): bump golang in /Containers/watchtower
Bumps golang from 1.25.3-alpine3.22 to 1.25.4-alpine3.22.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-06 04:17:20 +00:00
dependabot[bot]
43a2b27180 build(deps): bump docker in /Containers/mastercontainer
Bumps docker from 28.5.1-cli to 28.5.2-cli.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-06 04:16:29 +00:00
dependabot[bot]
29831f4e4b build(deps): bump golang in /Containers/imaginary
Bumps golang from 1.25.3-alpine3.22 to 1.25.4-alpine3.22.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-06 04:16:23 +00:00
Simon L.
1cd153e93e Merge pull request #7075 from nextcloud/watchtower-container-update
watchtower container update
2025-11-05 13:46:34 +01:00
szaimen
c57610b1b9 watchtower-update automated change
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-11-05 12:11:43 +00:00
Simon L.
cc24fd4151 Merge pull request #7073 from nextcloud/enh/noid/fix-psalm-issues
fix further psalm issues
2025-11-05 13:00:14 +01:00
Simon L.
ab20433940 fix further psalm issues
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-05 12:58:18 +01:00
Simon L.
cbcc5259bd Merge pull request #6995 from nextcloud/enh/6964/load-seccomp-profile
collabora: load seccomp profile on the fly
2025-11-05 12:43:53 +01:00
Simon L.
6f945a2369 json_decode: always throw on error and fix other psalm issues
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-05 12:41:41 +01:00
Simon L.
df0f7b8d85 fix return type of dataconst
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-05 12:24:43 +01:00
Simon L.
897e3e7e6e move containers-definition-path to Dataconst
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-05 12:08:57 +01:00
Simon L.
4ba7f1ed64 collabora: load seccomp profile on the fly
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-05 12:08:47 +01:00
Simon L.
d5f40f9eeb Merge pull request #7072 from nextcloud/dependabot/docker/Containers/collabora/collabora/code-25.04.7.1.1
build(deps): bump collabora/code from 25.04.6.2.1 to 25.04.7.1.1 in /Containers/collabora
2025-11-05 08:48:38 +01:00
dependabot[bot]
f1e7460f6e build(deps): bump collabora/code in /Containers/collabora
Bumps collabora/code from 25.04.6.2.1 to 25.04.7.1.1.

---
updated-dependencies:
- dependency-name: collabora/code
  dependency-version: 25.04.7.1.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-05 04:15:07 +00:00
Simon L.
e614202a94 increase to v12.0.0
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-04 16:17:44 +01:00
Simon L.
04f6ac1954 Merge pull request #6867 from Fly7113/aio-interface-relative
Make AIO interface not dependent on absolute location
2025-11-04 15:19:27 +01:00
Lorenzo Moscati
10529a597c Added suggested changes
Signed-off-by: Lorenzo Moscati <lorenzo@moscati.page>
2025-11-04 15:10:41 +01:00
Lorenzo Moscati
3bb9cdf31d Guard against null or missing keys.
Signed-off-by: Lorenzo Moscati <lorenzo@moscati.page>
2025-11-04 15:09:29 +01:00
Lorenzo Moscati
21fbb58c96 Rewrite all AIO interface paths to be relative
Signed-off-by: Lorenzo Moscati <lorenzo@moscati.page>
2025-11-04 15:09:29 +01:00
Simon L.
4581cf7649 Merge pull request #7070 from nextcloud/enh/6920/hide-upgrade-notice
aio-interface: hide upgrade notice
2025-11-04 14:16:29 +01:00
Simon L.
d24f5dd5ba Merge pull request #7069 from nextcloud/enh/6920/update-to-32.0.1
nextcloud: update to `32.0.1`
2025-11-04 14:02:46 +01:00
Simon L.
d17ed75d62 aio-interface: hide upgrade notice
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-04 14:02:37 +01:00
Simon L.
b10c9b74bf nextcloud: update to 32.0.1
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-04 14:00:16 +01:00
Simon L.
7ccf75f34a Merge pull request #7068 from nextcloud/enh/6920/update-app-version
app: update min and max versions
2025-11-04 13:58:33 +01:00
Simon L.
f179e5adad app: update min and max versions
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-04 13:57:22 +01:00
Simon L.
981d5b6092 Merge pull request #7067 from nextcloud/enh/6410/improve-docker-image-prune
docker-image-prune: only remove image with `label=org.label-schema.vendor=Nextcloud`
2025-11-04 13:51:47 +01:00
Simon L.
0ee5ec0036 docker-image-prune: only remove image with label=org.label-schema.vendor=Nextcloud
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-04 13:48:39 +01:00
Simon L.
abf0bbc431 dependabot: update redis also to new minor versions
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-04 13:44:33 +01:00
Simon L.
8627dbf3a2 Merge pull request #7066 from nextcloud/enh/noid/update-redis
update redis to v8.x
2025-11-04 13:43:03 +01:00
Simon L.
74933c6b83 update redis to v8.x
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-11-04 13:42:05 +01:00
Simon L.
2c9442bb10 Merge pull request #7005 from nextcloud/remove-libreoffice
remove libreoffice
2025-11-04 13:36:38 +01:00
Simon L.
e76478a94a Merge pull request #7048 from nextcloud/enh/noid/revert-watchtower-building
watchtower: switch back to building watchtower manually
2025-11-04 13:33:11 +01:00
Simon L.
37c2f65bb1 Merge pull request #7065 from nextcloud/dependabot/docker/Containers/whiteboard/nextcloud-releases/whiteboard-v1.4.1
build(deps): bump nextcloud-releases/whiteboard from v1.4.0 to v1.4.1 in /Containers/whiteboard
2025-11-04 09:06:10 +01:00
Simon L.
f0fcdaddf8 Merge pull request #7064 from nextcloud/dependabot/docker/Containers/redis/redis-7.2.12-alpine
build(deps): bump redis from 7.2.11-alpine to 7.2.12-alpine in /Containers/redis
2025-11-04 09:05:47 +01:00
dependabot[bot]
1f6c30b93a build(deps): bump nextcloud-releases/whiteboard
Bumps nextcloud-releases/whiteboard from v1.4.0 to v1.4.1.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-04 04:14:11 +00:00
dependabot[bot]
f07b015a41 build(deps): bump redis in /Containers/redis
Bumps redis from 7.2.11-alpine to 7.2.12-alpine.

---
updated-dependencies:
- dependency-name: redis
  dependency-version: 7.2.12-alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-04 04:13:53 +00:00
Simon L.
ee7765ca6f Merge pull request #7029 from masterwoot/patch-1
borgbackup: fix typo in backupscript.sh
2025-10-31 15:36:17 +01:00
Simon L.
db5558a6b3 Merge pull request #7032 from winterrific/main
clamav: change clamav-milter OnInfected Action to Reject
2025-10-31 15:35:49 +01:00
Ruben D.
3475a7b5d3 Change Milter OnInfected action to Reject
Signed-off-by: Ruben D. <ruben@winterrific.net>
2025-10-31 15:30:44 +01:00
Simon L.
e4ad677a4c Merge pull request #7046 from nextcloud/aio-dependency-update
PHP dependency updates
2025-10-31 15:30:21 +01:00
Simon L.
dc9a9aed29 Merge pull request #7040 from nextcloud/dependabot/docker/Containers/whiteboard/nextcloud-releases/whiteboard-v1.4.0
build(deps): bump nextcloud-releases/whiteboard from v1.3.0 to v1.4.0 in /Containers/whiteboard
2025-10-31 15:29:34 +01:00
Simon L.
f0552d9d1a Merge pull request #7039 from nextcloud/dependabot/docker/Containers/nextcloud/php-8.3.27-fpm-alpine3.22
build(deps): bump php from 8.3.26-fpm-alpine3.22 to 8.3.27-fpm-alpine3.22 in /Containers/nextcloud
2025-10-31 15:29:14 +01:00
Simon L.
462e42de93 Merge pull request #7038 from nextcloud/dependabot/docker/Containers/docker-socket-proxy/haproxy-3.2.7-alpine
build(deps): bump haproxy from 3.2.6-alpine to 3.2.7-alpine in /Containers/docker-socket-proxy
2025-10-31 15:28:54 +01:00
Simon L.
0f01279f41 Merge pull request #7037 from nextcloud/dependabot/docker/Containers/mastercontainer/php-8.4.14-fpm-alpine3.22
build(deps): bump php from 8.4.13-fpm-alpine3.22 to 8.4.14-fpm-alpine3.22 in /Containers/mastercontainer
2025-10-31 15:28:37 +01:00
Simon L.
505f4c3371 Merge pull request #7022 from nextcloud/jtr/docs-rp-i
docs: restructure and clarify reverse proxy documentation (part one)
2025-10-31 14:15:28 +01:00
Simon L.
296d3e37e8 Merge pull request #7055 from nextcloud/aio-helm-update
Helm Chart updates
2025-10-31 13:28:50 +01:00
szaimen
f88e4aef37 Helm Chart updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-10-31 12:25:33 +00:00
szaimen
727d0d03db php dependency updates
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-10-31 12:03:38 +00:00
Josh
5289da58d6 docs: further enhance reverse proxy / secure tunnel docs
Further updated the guide to clarify the use of reverse proxies and secure tunnels with Nextcloud AIO.

Signed-off-by: Josh <josh.t.richards@gmail.com>
2025-10-30 14:34:46 -04:00
Simon L.
dbaef1f154 Merge pull request #7049 from nextcloud/enh/noid/adjust-externalTrafficPolicy
helm: adjust externalTrafficPolicy only for nextcloud container
2025-10-29 15:01:04 +01:00
Simon L.
e2614defe0 helm: adjust externalTrafficPolicy to Local only for apache container
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-10-29 14:57:53 +01:00
Simon L.
68edc82bf4 watchtower: revert to building watchtower manually
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-10-29 13:42:53 +01:00
Simon L.
6c3f2e41ff add DeepWiki badge to auto-refresh the wiki
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-10-27 18:23:21 +01:00
Simon L.
a09f59bf79 Merge pull request #7042 from nextcloud/dependabot/github_actions/dot-github/workflows/actions/upload-artifact-5
build(deps): bump actions/upload-artifact from 4 to 5 in /.github/workflows
2025-10-27 15:59:07 +01:00
dependabot[bot]
8a3befaddd build(deps): bump actions/upload-artifact in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 14:04:50 +00:00
Simon L.
68f7958c12 update detail
Signed-off-by: Simon L. <szaimen@e.mail.de>
2025-10-27 11:37:12 +01:00
dependabot[bot]
b7c6ab018d build(deps): bump nextcloud-releases/whiteboard
Bumps nextcloud-releases/whiteboard from v1.3.0 to v1.4.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 04:22:30 +00:00
dependabot[bot]
2598f1b983 build(deps): bump php in /Containers/nextcloud
Bumps php from 8.3.26-fpm-alpine3.22 to 8.3.27-fpm-alpine3.22.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 04:22:17 +00:00
dependabot[bot]
19d5ad2a79 build(deps): bump haproxy in /Containers/docker-socket-proxy
Bumps haproxy from 3.2.6-alpine to 3.2.7-alpine.

---
updated-dependencies:
- dependency-name: haproxy
  dependency-version: 3.2.7-alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 04:21:59 +00:00
dependabot[bot]
bf42de65da build(deps): bump php in /Containers/mastercontainer
Bumps php from 8.4.13-fpm-alpine3.22 to 8.4.14-fpm-alpine3.22.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 04:21:21 +00:00
masterwoot
5568c78293 Update backupscript.sh
Typo in string messages, changing from "Nextclouds data directory.." to "Nextcloud's data directory.." as it's in the possessive form.

Signed-off-by: masterwoot <company+github.com@maganti.se>
2025-10-24 09:59:57 +02:00
Josh
d107cccb92 chore: fix typo
Signed-off-by: Josh <josh.t.richards@gmail.com>
2025-10-22 13:39:55 -04:00
Josh
3a7d77a766 fix: make headers consistent
Signed-off-by: Josh <josh.t.richards@gmail.com>
2025-10-22 12:36:09 -04:00
Josh
fb1ca10ab4 docs: Revise reverse proxy docs (first pass)
Updated the reverse proxy documentation for Nextcloud AIO, enhancing clarity and structure. 

Re-organized top section(s).

Added sections to provide context on integrated versus external reverse proxies versus secure tunnels/proxy platforms.

De-duplicated some content.

Signed-off-by: Josh <josh.t.richards@gmail.com>
2025-10-22 12:29:55 -04:00
Zoey
a176ecdd9f remove librewolf from readme
Signed-off-by: Zoey <zoey@z0ey.de>
2025-10-17 20:30:05 +02:00
Zoey
91ade7ed94 remove libreoffice
see https://github.com/nextcloud/all-in-one/discussions/6997#discussioncomment-14712015

Signed-off-by: Zoey <zoey@z0ey.de>
2025-10-17 20:26:22 +02:00
74 changed files with 1537 additions and 391 deletions

View File

@@ -55,6 +55,6 @@ updates:
- dependency-name: "postgres"
update-types: ["version-update:semver-major"]
- dependency-name: "redis"
update-types: ["version-update:semver-major", "version-update:semver-minor"]
update-types: ["version-update:semver-major"]
- dependency-name: "elasticsearch"
update-types: ["version-update:semver-major"]

View File

@@ -14,7 +14,7 @@ jobs:
- name: Check out code
uses: actions/checkout@v5
- name: Check spelling
uses: codespell-project/actions-codespell@406322ec52dd7b488e48c1c4b82e2a8b3a1bf630 # v2
uses: codespell-project/actions-codespell@8f01853be192eb0f849a5c7d721450e7a467c579 # v2
with:
check_filenames: true
check_hidden: true

29
.github/workflows/collabora.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: collabora-update
on:
workflow_dispatch:
schedule:
- cron: '00 12 * * *'
jobs:
collabora-update:
name: update collabora
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Run collabora-profile-update
run: |
rm -f php/cool-seccomp-profile.json
wget https://raw.githubusercontent.com/CollaboraOnline/online/refs/heads/master/docker/cool-seccomp-profile.json
mv cool-seccomp-profile.json php/
- name: Create Pull Request
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
with:
commit-message: collabora-seccomp-update automated change
signoff: true
title: collabora seccomp update
body: Automated collabora seccomp profile update
labels: dependencies, 3. to review
milestone: next
branch: collabora-seccomp-update

View File

@@ -16,7 +16,7 @@ jobs:
uses: actions/checkout@v5
- name: Turnstyle
uses: softprops/turnstyle@9d692f15fa9f84928799bccac2dba6565e024bdf # v2
uses: softprops/turnstyle@2e4451ef94c5969eee533c487092052d4d1a53af # v2
with:
continue-after-seconds: 180
env:

View File

@@ -2,6 +2,9 @@
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Lint php
@@ -33,10 +36,12 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.1.1
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@bf6b4fbd49ca58e4608c9c89fba0b8d90bd2a39f # v2
uses: shivammathur/setup-php@bf6b4fbd49ca58e4608c9c89fba0b8d90bd2a39f # v2.35.5
with:
php-version: ${{ matrix.php-versions }}
coverage: none

View File

@@ -82,7 +82,7 @@ jobs:
exit 1
fi
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v5
if: ${{ !cancelled() }}
with:
name: playwright-report

View File

@@ -2,6 +2,9 @@
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Static analysis
@@ -19,6 +22,9 @@ concurrency:
group: psalm-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
permissions:
contents: read
jobs:
static-analysis:
runs-on: ubuntu-latest
@@ -26,15 +32,19 @@ jobs:
name: static-psalm-analysis
steps:
- name: Checkout
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.1.1
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- name: Set up php
uses: shivammathur/setup-php@bf6b4fbd49ca58e4608c9c89fba0b8d90bd2a39f # v2
uses: shivammathur/setup-php@bf6b4fbd49ca58e4608c9c89fba0b8d90bd2a39f # v2.35.5
with:
php-version: 8.4
extensions: apcu
coverage: none
ini-file: development
# Temporary workaround for missing pcntl_* in PHP 8.3
ini-values: disable_functions=
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

37
.github/workflows/watchtower-update.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
name: watchtower-update
on:
workflow_dispatch:
schedule:
- cron: '00 12 * * *'
jobs:
watchtower-update:
name: update watchtower
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Run watchtower-container-update
run: |
# Watchtower
watchtower_version="$(
git ls-remote https://github.com/nicholas-fedor/watchtower v* \
| cut -d/ -f3 \
| sort -V \
| grep -E "^v[0-9\.]+$" \
| tail -1
)"
watchtower_commit_hash="$(git ls-remote https://github.com/nicholas-fedor/watchtower $watchtower_version | sed 's/refs.*//')"
sed -i "s|^ENV WATCHTOWER_COMMIT_HASH.*$|ENV WATCHTOWER_COMMIT_HASH=$watchtower_commit_hash|" ./Containers/watchtower/Dockerfile
sed -i "s|\$WATCHTOWER_COMMIT_HASH.*$|\$WATCHTOWER_COMMIT_HASH # $watchtower_version|" ./Containers/watchtower/Dockerfile
- name: Create Pull Request
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
with:
commit-message: watchtower-update automated change
signoff: true
title: watchtower container update
body: Automated watchtower container update
labels: dependencies, 3. to review
milestone: next
branch: watchtower-container-update

View File

@@ -138,11 +138,6 @@ if [ "$BORG_MODE" = backup ]; then
NEW_REPOSITORY=1
if ! borg init --debug --encryption=repokey-blake2; then
echo "Could not initialize borg repository."
if [ -z "$BORG_REMOTE_REPO" ]; then
# Originally we checked for presence of the config file instead of calling `borg info`. Likely `borg info`
# will error on a partially initialized repo, so this line is probably no longer necessary
rm -f "$BORG_BACKUP_DIRECTORY/config"
fi
exit 1
fi
@@ -199,7 +194,7 @@ if [ "$BORG_MODE" = backup ]; then
if [ -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/.noaiobackup" ]; then
BORG_EXCLUDE+=(--exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/")
BORG_INCLUDE+=(--pattern="+/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/.noaiobackup")
echo "⚠️⚠️⚠️ '.noaiobackup' file was found in Nextclouds data directory. Excluding the data directory from backup!"
echo "⚠️⚠️⚠️ '.noaiobackup' file was found in Nextcloud's data directory. Excluding the data directory from backup!"
# Exclude preview folder if .noaiobackup file was found
elif [ -f /nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_*/preview/.noaiobackup ]; then
BORG_EXCLUDE+=(--exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_*/preview/")
@@ -344,7 +339,7 @@ if [ "$BORG_MODE" = restore ]; then
ADDITIONAL_RSYNC_EXCLUDES=(--exclude "nextcloud_aio_nextcloud_data/**")
ADDITIONAL_BORG_EXCLUDES=(--exclude "sh:nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/**")
ADDITIONAL_FIND_EXCLUDES=(-o -regex 'nextcloud_aio_volumes/nextcloud_aio_nextcloud_data\(/.*\)?')
echo "⚠️⚠️⚠️ '.noaiobackup' file was found in Nextclouds data directory. Excluding the data directory from restore!"
echo "⚠️⚠️⚠️ '.noaiobackup' file was found in Nextcloud's data directory. Excluding the data directory from restore!"
echo "You might run into problems due to this afterwards as potentially this makes the directory go out of sync with the database."
echo "You might be able to fix this by running 'occ files:scan --all' and 'occ maintenance:repair' and 'occ files:scan-app-data' after the restore."
echo "See https://github.com/nextcloud/all-in-one#how-to-run-occ-commands"

View File

@@ -4,19 +4,21 @@ FROM alpine:3.22.2
RUN set -ex; \
apk upgrade --no-cache -a; \
apk add --no-cache tzdata clamav clamav-milter supervisor bash; \
mkdir -p /var/lib/clamav /run/clamav /var/log/supervisord /var/run/supervisord; \
chmod 777 -R /run/clamav /var/log/clamav /var/log/supervisord /var/run/supervisord; \
mkdir -p /tmp /var/lib/clamav /run/clamav /var/log/supervisord /var/run/supervisord; \
chmod 777 -R /tmp /run/clamav /var/log/clamav /var/log/supervisord /var/run/supervisord; \
chown -R 100:100 /var/lib/clamav; \
sed -i "s|#\?MaxDirectoryRecursion.*|MaxDirectoryRecursion 30|g" /etc/clamav/clamd.conf; \
sed -i "s|#\?MaxScanSize.*|MaxScanSize 2G|g" /etc/clamav/clamd.conf; \
sed -i "s|#\?MaxFileSize.*|MaxFileSize 2G|g" /etc/clamav/clamd.conf; \
sed -i "s|#\?PCREMaxFileSize.*|PCREMaxFileSize 0|g" /etc/clamav/clamd.conf; \
sed -i "s|#\?StreamMaxLength.*|StreamMaxLength aio-placeholder|g" /etc/clamav/clamd.conf; \
sed -i "s|#\?MaxScanSize.*|MaxScanSize 2000M|g" /etc/clamav/clamd.conf; \
sed -i "s|#\?MaxFileSize.*|MaxFileSize 2000M|g" /etc/clamav/clamd.conf; \
sed -i "s|#\?PCREMaxFileSize.*|PCREMaxFileSize 2000M|g" /etc/clamav/clamd.conf; \
# StreamMaxLength must be synced with av_stream_max_length inside the Nextcloud files_antivirus plugin
sed -i "s|#\?StreamMaxLength.*|StreamMaxLength 2000M|g" /etc/clamav/clamd.conf; \
sed -i "s|#\?TCPSocket|TCPSocket|g" /etc/clamav/clamd.conf; \
sed -i "s|^LocalSocket .*|LocalSocket /tmp/clamd.sock|g" /etc/clamav/clamd.conf; \
sed -i "s|Example| |g" /etc/clamav/clamav-milter.conf; \
sed -i "s|#\?MilterSocket inet:7357|MilterSocket inet:7357|g" /etc/clamav/clamav-milter.conf; \
sed -i "s|#\?ClamdSocket unix:/run/clamav/clamd.sock|ClamdSocket unix:/tmp/clamd.sock|g" /etc/clamav/clamav-milter.conf; \
sed -i "s|#\?OnInfected Quarantine|OnInfected Reject|g" /etc/clamav/clamav-milter.conf; \
sed -i "s|#\?AddHeader Replace|AddHeader Add|g" /etc/clamav/clamav-milter.conf; \
sed -i "s|#\?Foreground yes|Foreground yes|g" /etc/clamav/clamav-milter.conf

View File

@@ -1,7 +1,5 @@
#!/bin/bash
sed "s|aio-placeholder|$MAX_SIZE|" /etc/clamav/clamd.conf > /tmp/clamd.conf
# Print out clamav version for compliance reasons
clamscan --version

View File

@@ -13,14 +13,14 @@ stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
command=freshclam --foreground --stdout --daemon --daemon-notify=/tmp/clamd.conf
command=freshclam --foreground --stdout --daemon --daemon-notify=/etc/clamav/clamd.conf
[program:clamd]
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
command=clamd --foreground --config-file=/tmp/clamd.conf
command=clamd --foreground --config-file=/etc/clamav/clamd.conf
[program:milter]
stdout_logfile=/dev/stdout

View File

@@ -0,0 +1,15 @@
# syntax=docker/dockerfile:latest
# From https://gitlab.collabora.com/collabora-online/docker
# hadolint ignore=DL3007
FROM registry.gitlab.collabora.com/collabora-online/docker:latest
USER root
ARG DEBIAN_FRONTEND=noninteractive
COPY --chmod=775 healthcheck.sh /healthcheck.sh
USER 1001
HEALTHCHECK --start-period=60s --retries=9 CMD /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \
org.label-schema.vendor="Nextcloud"

View File

@@ -0,0 +1,7 @@
#!/bin/bash
# Unfortunately, no curl and no nc is installed in the container
# and packages can also not be added as the package list is broken.
# So always exiting 0 for now.
# nc http://127.0.0.1:9980 || exit 1
exit 0

View File

@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:latest
# From a file located probably somewhere here: https://github.com/CollaboraOnline/online/blob/master/docker/from-packages/Dockerfile
FROM collabora/code:25.04.6.2.1
FROM collabora/code:25.04.7.1.1
USER root
ARG DEBIAN_FRONTEND=noninteractive

View File

@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
FROM haproxy:3.2.6-alpine
FROM haproxy:3.2.8-alpine
# hadolint ignore=DL3002
USER root

View File

@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:latest
# Probably from here https://github.com/elastic/elasticsearch/blob/main/distribution/docker/src/docker/Dockerfile
FROM elasticsearch:8.19.6
FROM elasticsearch:8.19.7
USER root

View File

@@ -1,7 +1,7 @@
# syntax=docker/dockerfile:latest
FROM golang:1.25.3-alpine3.22 AS go
FROM golang:1.25.4-alpine3.22 AS go
ENV IMAGINARY_HASH=1d4e251cfcd58ea66f8361f8721d7b8cc85002a3
ENV IMAGINARY_HASH=6a274b488759a896aff02f52afee6e50b5e3a3ee
RUN set -ex; \
apk upgrade --no-cache -a; \

View File

@@ -1,12 +1,12 @@
# syntax=docker/dockerfile:latest
# Docker CLI is a requirement
FROM docker:28.5.1-cli AS docker
FROM docker:28.5.2-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.22/fpm/Dockerfile
FROM php:8.4.13-fpm-alpine3.22
FROM php:8.4.14-fpm-alpine3.22
EXPOSE 80
EXPOSE 8080

View File

@@ -60,7 +60,7 @@ while true; do
fi
# Remove dangling images
sudo -u www-data docker image prune --force
sudo -u www-data docker image prune --filter "label=org.label-schema.vendor=Nextcloud" --force
# Check for available free space
sudo -u www-data php /var/www/docker-aio/php/src/Cron/CheckFreeDiskSpace.php

View File

@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
FROM php:8.3.26-fpm-alpine3.22
FROM php:8.3.27-fpm-alpine3.22
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=31.0.10
ENV NEXTCLOUD_VERSION=32.0.1
ENV AIO_TOKEN=123456
ENV AIO_URL=localhost
# AIO settings end # Do not remove or change this line!
@@ -85,7 +85,7 @@ RUN set -ex; \
pecl install -o igbinary-3.2.16; \
pecl install APCu-5.1.27; \
pecl install -D 'enable-memcached-igbinary="yes"' memcached-3.4.0; \
pecl install -oD 'enable-redis-igbinary="yes" enable-redis-zstd="yes" enable-redis-lz4="yes"' redis-6.2.0; \
pecl install -oD 'enable-redis-igbinary="yes" enable-redis-zstd="yes" enable-redis-lz4="yes"' redis-6.3.0; \
pecl install -o imagick-3.8.0; \
\
docker-php-ext-enable \
@@ -230,7 +230,6 @@ RUN set -ex; \
sudo \
grep \
nodejs \
libreoffice \
bind-tools \
imagemagick \
imagemagick-svg \

View File

@@ -880,7 +880,8 @@ if [ "$CLAMAV_ENABLED" = 'yes' ]; then
php /var/www/html/occ config:app:set files_antivirus av_mode --value="daemon"
php /var/www/html/occ config:app:set files_antivirus av_port --value="3310"
php /var/www/html/occ config:app:set files_antivirus av_host --value="$CLAMAV_HOST"
php /var/www/html/occ config:app:set files_antivirus av_stream_max_length --value="$CLAMAV_MAX_SIZE"
# av_stream_max_length must be synced with StreamMaxLength inside clamav
php /var/www/html/occ config:app:set files_antivirus av_stream_max_length --value="2147483648"
php /var/www/html/occ config:app:set files_antivirus av_max_file_size --value="-1"
php /var/www/html/occ config:app:set files_antivirus av_infected_action --value="only_log"
if [ -n "$CLAMAV_BLOCKLISTED_DIRECTORIES" ]; then
@@ -947,7 +948,7 @@ if [ "$FULLTEXTSEARCH_ENABLED" = 'yes' ]; then
fi
php /var/www/html/occ fulltextsearch:configure '{"search_platform":"OCA\\FullTextSearch_Elasticsearch\\Platform\\ElasticSearchPlatform"}'
php /var/www/html/occ fulltextsearch_elasticsearch:configure "{\"elastic_host\":\"http://$FULLTEXTSEARCH_USER:$FULLTEXTSEARCH_PASSWORD@$FULLTEXTSEARCH_HOST:$FULLTEXTSEARCH_PORT\",\"elastic_index\":\"$FULLTEXTSEARCH_INDEX\"}"
php /var/www/html/occ files_fulltextsearch:configure "{\"files_pdf\":\"1\",\"files_office\":\"1\"}"
php /var/www/html/occ files_fulltextsearch:configure "{\"files_pdf\":true,\"files_office\":true}"
# Do the index
if ! [ -f "$NEXTCLOUD_DATA_DIR/fts-index.done" ]; then

View File

@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:latest
# From https://github.com/docker-library/redis/blob/master/7.2/alpine/Dockerfile
FROM redis:7.2.11-alpine
# From https://github.com/redis/docker-library-redis/blob/release/8.2/alpine/Dockerfile
FROM redis:8.2.3-alpine
COPY --chmod=775 start.sh /start.sh

View File

@@ -1,5 +1,13 @@
# syntax=docker/dockerfile:latest
FROM ghcr.io/nicholas-fedor/watchtower:1.12.1 AS watchtower
FROM golang:1.25.4-alpine3.22 AS go
ENV WATCHTOWER_COMMIT_HASH=87b5518858f6a96e8edf784bdc855d29951643e6
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.12.2
FROM alpine:3.22.2
@@ -7,7 +15,7 @@ RUN set -ex; \
apk upgrade --no-cache -a; \
apk add --no-cache bash ca-certificates tzdata
COPY --from=watchtower /watchtower /watchtower
COPY --from=go /go/bin/watchtower /watchtower
COPY --chmod=775 start.sh /start.sh

View File

@@ -1,12 +1,18 @@
# syntax=docker/dockerfile:latest
# Probably from this file: https://github.com/nextcloud/whiteboard/blob/main/Dockerfile
FROM ghcr.io/nextcloud-releases/whiteboard:v1.3.0
FROM ghcr.io/nextcloud-releases/whiteboard:v1.4.1
USER root
RUN set -ex; \
apk upgrade --no-cache -a; \
apk add --no-cache bash; \
chmod 777 -R /tmp
chmod 777 -R /tmp; \
if [ -f /usr/lib/chromium/chrome_crashpad_handler ]; then \
rm -f /usr/lib/chromium/chrome_crashpad_handler.real; \
mv /usr/lib/chromium/chrome_crashpad_handler /usr/lib/chromium/chrome_crashpad_handler.real; \
printf '%s\n' '#!/bin/sh' "exec /usr/lib/chromium/chrome_crashpad_handler.real --no-periodic-tasks --database=\"\${CRASHPAD_DATABASE:-/tmp/chrome-crashpad}\" \"\$@\"" >/usr/lib/chromium/chrome_crashpad_handler; \
chmod +x /usr/lib/chromium/chrome_crashpad_handler; \
fi
USER 65534
COPY --chmod=775 start.sh /start.sh

View File

@@ -13,7 +13,7 @@
<category>monitoring</category>
<bugs>https://github.com/nextcloud/all-in-one/issues</bugs>
<dependencies>
<nextcloud min-version="30" max-version="31"/>
<nextcloud min-version="31" max-version="32"/>
</dependencies>
<settings>

View File

@@ -5,7 +5,7 @@
"display_name": "Caddy with geoblocking",
"documentation": "https://github.com/nextcloud/all-in-one/tree/main/community-containers/caddy",
"image": "ghcr.io/szaimen/aio-caddy",
"image_tag": "v2",
"image_tag": "v3",
"internal_port": "443",
"restart": "unless-stopped",
"ports": [
@@ -24,7 +24,9 @@
"TZ=%TIMEZONE%",
"NC_DOMAIN=%NC_DOMAIN%",
"APACHE_PORT=%APACHE_PORT%",
"NEXTCLOUD_EXPORTER_CADDY_PASSWORD=%NEXTCLOUD_EXPORTER_CADDY_PASSWORD%"
"NEXTCLOUD_EXPORTER_CADDY_PASSWORD=%NEXTCLOUD_EXPORTER_CADDY_PASSWORD%",
"turn_domain=turn.%NC_DOMAIN%",
"talk_port=443"
],
"volumes": [
{

View File

@@ -4,6 +4,8 @@ This container bundles caddy and auto-configures it for you. It also covers [vau
### Notes
- This container is incompatible with the [npmplus](https://github.com/nextcloud/all-in-one/tree/main/community-containers/npmplus) community container. So make sure that you do not enable both at the same time!
- Make sure that no other service is using port 443 on your host as otherwise the containers will fail to start. You can check this with `sudo netstat -tulpn | grep 443` before installing AIO.
- Starting with AIO v12, the Talk port that was usually exposed on port 3478 is now set to port 443 udp and tcp and reachable via `turn.your-nc-domain.com`. So instead of opening port 3478, you need to configure the mentioned subdomain by using a cname record.
- Starting with AIO v12, you can also limit vaultwarden, stalwart and lldap to certain ip-addresses. You can do so by creating a `allowed-IPs-vaultwarden.txt`, `allowed-IPs-stalwart.txt`, or `allowed-IPs-lldap.txt` file in the `nextcloud-aio-caddy` directory of your admin user and adding the ip-addresses in these files.
- If you want to use this with [vaultwarden](https://github.com/nextcloud/all-in-one/tree/main/community-containers/vaultwarden), make sure that you point `bw.your-nc-domain.com` to your server using a cname record so that caddy can get a certificate automatically for vaultwarden.
- If you want to use this with [stalwart](https://github.com/nextcloud/all-in-one/tree/main/community-containers/stalwart), make sure that you point `mail.your-nc-domain.com` to your server using an A, AAAA or CNAME record so that caddy can get a certificate automatically for stalwart.
- If you want to use this with [jellyfin](https://github.com/nextcloud/all-in-one/tree/main/community-containers/jellyfin), make sure that you point `media.your-nc-domain.com` to your server using a cname record so that caddy can get a certificate automatically for jellyfin.

View File

@@ -67,6 +67,6 @@ docker buildx build --file Containers/nextcloud/Dockerfile --tag ghcr.io/nextclo
# For all other containers
docker buildx build --file Containers/{container}/Dockerfile --tag ghcr.io/nextcloud-releases/aio-{container}:develop --load Containers/{container}
```
1. Stop the containers using the AIO admin interface.
1. Reload the AIO admin interface with the param `bypass_container_update` to avoid overwriting your local changes, e.g. `https://localhost:8080/containers?bypass_container_update`.
1. Stop the containers using the AIO interface.
1. Reload the AIO interface with the param `bypass_container_update` to avoid overwriting your local changes, e.g. `https://localhost:8080/containers?bypass_container_update`.
1. Click "Start and update containers" and test your changes. Containers will not be updated, despite the button text.

View File

@@ -46,6 +46,7 @@ sed -i '/AIO_TOKEN/d' containers.yml
sed -i '/AIO_URL/d' containers.yml
sed -i '/DOCKER_SOCKET_PROXY_ENABLED/d' containers.yml
sed -i '/ADDITIONAL_TRUSTED_PROXY/d' containers.yml
sed -i '/TURN_DOMAIN/d' containers.yml
TCP="$(grep -oP '[%A-Z0-9_]+/tcp' containers.yml | sort -u)"
mapfile -t TCP <<< "$TCP"

View File

@@ -108,7 +108,7 @@ However, if you are unsure check the ghcr.io (https://github.com/nextcloud-relea
Once you see no more activities in the logs or a message like ```NOTICE: ready to handle connections```, we've done it!
#### Now you can handle everything through the AIO admin interface and stop and restart the containers normally.
#### Now you can handle everything through the AIO interface and stop and restart the containers normally.
---

View File

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

View File

@@ -1,7 +1,7 @@
# Nextcloud AIO Helm-chart
> [!NOTE]
> For an enterprise-ready and scalable deployment method based on Helm Charts (also available for Podman), please [contact Nextcloud GmbH](https://nextcloud.com/enterprise/).
> For an enterprise-ready and scalable deployment method based on Helm Charts (also available for Podman and OpenShift), please [contact Nextcloud GmbH](https://nextcloud.com/enterprise/).
> [!IMPORTANT]
> This Helm-Chart is not intended to be used with Ingress as it handles TLS itself via the built-in apache container and exposes a Loadbalancer port itself on the Cluster. See the [apache service](https://github.com/nextcloud/all-in-one/blob/main/nextcloud-aio-helm-chart/templates/nextcloud-aio-apache-service.yaml). However if the Cluster is used behind NAT, you can adjust `APACHE_PORT` to a different one than 443 and do the TLS offloading on an external Reverse Proxy that forwards the traffic to the configured port via http. If you really need the Ingress feature, please [contact Nextcloud GmbH](https://nextcloud.com/enterprise/) as we offer an enterprise-ready and scalable deployment method based on Helm Charts that also allows Ingress to be used.

View File

@@ -61,7 +61,7 @@ spec:
value: "{{ .Values.TIMEZONE }}"
- name: WHITEBOARD_HOST
value: nextcloud-aio-whiteboard
image: ghcr.io/nextcloud-releases/aio-apache:20251015_082711
image: ghcr.io/nextcloud-releases/aio-apache:20251031_122139
readinessProbe:
exec:
command:

View File

@@ -36,7 +36,7 @@ spec:
{{- end }}
initContainers:
- name: init-subpath
image: ghcr.io/nextcloud-releases/aio-alpine:20251015_082711
image: ghcr.io/nextcloud-releases/aio-alpine:20251031_122139
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:20251015_082711
image: ghcr.io/nextcloud-releases/aio-clamav:20251031_122139
readinessProbe:
exec:
command:

View File

@@ -35,7 +35,7 @@ spec:
value: --o:ssl.enable=false --o:ssl.termination=true --o:mount_jail_tree=false --o:logging.level=warning --o:logging.level_startup=warning --o:home_mode.enable=true --o:remote_font_config.url=https://{{ .Values.NC_DOMAIN }}/apps/richdocuments/settings/fonts.json --o:net.post_allow.host[0]=.+
- name: server_name
value: "{{ .Values.NC_DOMAIN }}"
image: ghcr.io/nextcloud-releases/aio-collabora:20251015_082711
image: ghcr.io/nextcloud-releases/aio-collabora:20251031_122139
readinessProbe:
exec:
command:

View File

@@ -35,7 +35,7 @@ spec:
{{- end }}
initContainers:
- name: init-subpath
image: ghcr.io/nextcloud-releases/aio-alpine:20251015_082711
image: ghcr.io/nextcloud-releases/aio-alpine:20251031_122139
command:
- mkdir
- "-p"
@@ -64,7 +64,7 @@ spec:
value: nextcloud
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-postgresql:20251015_082711
image: ghcr.io/nextcloud-releases/aio-postgresql:20251031_122139
readinessProbe:
exec:
command:

View File

@@ -24,7 +24,7 @@ spec:
spec:
initContainers:
- name: init-volumes
image: ghcr.io/nextcloud-releases/aio-alpine:20251015_082711
image: ghcr.io/nextcloud-releases/aio-alpine:20251031_122139
command:
- chmod
- "777"
@@ -54,7 +54,7 @@ spec:
value: basic
- name: xpack.security.enabled
value: "false"
image: ghcr.io/nextcloud-releases/aio-fulltextsearch:20251015_082711
image: ghcr.io/nextcloud-releases/aio-fulltextsearch:20251031_122139
readinessProbe:
exec:
command:

View File

@@ -38,7 +38,7 @@ spec:
value: "{{ .Values.IMAGINARY_SECRET }}"
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-imaginary:20251015_082711
image: ghcr.io/nextcloud-releases/aio-imaginary:20251031_122139
readinessProbe:
exec:
command:

View File

@@ -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:20251015_082711
image: ghcr.io/nextcloud-releases/aio-alpine:20251031_122139
command:
- chmod
- "777"
@@ -188,7 +188,7 @@ spec:
value: "{{ .Values.WHITEBOARD_ENABLED }}"
- name: WHITEBOARD_SECRET
value: "{{ .Values.WHITEBOARD_SECRET }}"
image: ghcr.io/nextcloud-releases/aio-nextcloud:20251015_082711
image: ghcr.io/nextcloud-releases/aio-nextcloud:20251031_122139
{{- 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

@@ -55,7 +55,7 @@ spec:
value: "{{ .Values.REDIS_PASSWORD }}"
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-notify-push:20251015_082711
image: ghcr.io/nextcloud-releases/aio-notify-push:20251031_122139
readinessProbe:
exec:
command:

View File

@@ -24,7 +24,7 @@ spec:
spec:
initContainers:
- name: init-volumes
image: ghcr.io/nextcloud-releases/aio-alpine:20251015_082711
image: ghcr.io/nextcloud-releases/aio-alpine:20251031_122139
command:
- chmod
- "777"
@@ -42,7 +42,7 @@ spec:
value: "{{ .Values.ONLYOFFICE_SECRET }}"
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-onlyoffice:20251015_082711
image: ghcr.io/nextcloud-releases/aio-onlyoffice:20251031_122139
readinessProbe:
exec:
command:

View File

@@ -39,7 +39,7 @@ spec:
value: "{{ .Values.REDIS_PASSWORD }}"
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-redis:20251015_082711
image: ghcr.io/nextcloud-releases/aio-redis:20251031_122139
readinessProbe:
exec:
command:

View File

@@ -52,7 +52,7 @@ spec:
value: "{{ .Values.TURN_SECRET }}"
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-talk:20251015_082711
image: ghcr.io/nextcloud-releases/aio-talk:20251031_122139
readinessProbe:
exec:
command:

View File

@@ -44,7 +44,7 @@ spec:
value: "{{ .Values.RECORDING_SECRET }}"
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-talk-recording:20251015_082711
image: ghcr.io/nextcloud-releases/aio-talk-recording:20251031_122139
readinessProbe:
exec:
command:

View File

@@ -12,7 +12,6 @@ metadata:
spec:
ipFamilyPolicy: PreferDualStack
type: LoadBalancer
externalTrafficPolicy: Local
ports:
- name: "{{ .Values.TALK_PORT }}"
port: {{ .Values.TALK_PORT }}

View File

@@ -48,7 +48,7 @@ spec:
value: redis
- name: TZ
value: "{{ .Values.TIMEZONE }}"
image: ghcr.io/nextcloud-releases/aio-whiteboard:20251015_082711
image: ghcr.io/nextcloud-releases/aio-whiteboard:20251031_122139
readinessProbe:
exec:
command:

View File

@@ -27,7 +27,7 @@ cp latest.yml latest.yml.backup
# Additional config
# shellcheck disable=SC1083
sed -i -E '/^( *- )(NET_RAW|SYS_NICE|MKNOD|SYS_ADMIN|CHOWN|SYS_CHROOT|FOWNER)$/!s/( *- )([A-Z_]+)$/\1\2=${\2}/' latest.yml
sed -i -E '/^( *- )(NET_RAW|SYS_NICE|MKNOD|SYS_ADMIN|CHOWN|SYS_CHROOT|FOWNER|MAC_OVERRIDE|BLOCK_SUSPEND|AUDIT_READ)$/!s/( *- )([A-Z_]+)$/\1\2=${\2}/' latest.yml
cp sample.conf /tmp/
sed -i 's|^|export |' /tmp/sample.conf
# shellcheck disable=SC1091
@@ -252,7 +252,7 @@ find ./ -name '*talk-service.yaml' -exec grep -v '{{ .Values.TALK.*}}\|protocol:
# shellcheck disable=SC1083
find ./ -name '*talk-service.yaml' -exec mv /tmp/talk-service.copy \{} \;
# shellcheck disable=SC1083
find ./ -name '*service.yaml' -exec sed -i "/type: LoadBalancer/a\ \ externalTrafficPolicy: Local" \{} \;
find ./ -name '*apache-service.yaml' -exec sed -i "/type: LoadBalancer/a\ \ externalTrafficPolicy: Local" \{} \;
# shellcheck disable=SC1083
find ./ -name '*service.yaml' -exec sed -i "/^spec:/a\ \ ipFamilyPolicy: PreferDualStack" \{} \;
# shellcheck disable=SC1083
@@ -343,6 +343,21 @@ EOL
# shellcheck disable=SC1083
find ./ -name '*talk-deployment.yaml' -exec sed -i "/^.*\- env:/r /tmp/additional-talk.config" \{} \;
# Additional collabora config
# shellcheck disable=SC1083
find ./ -name '*collabora-deployment.yaml' -exec sed -i "s/image: ghcr.io.*/IMAGE_PLACEHOLDER/" \{} \;
cat << EOL > /tmp/additional-collabora.config
{{- if contains "--o:support_key=" (join " " (.Values.ADDITIONAL_COLLABORA_OPTIONS | default list)) }}
image: ghcr.io/nextcloud-releases/aio-collabora-online:$DOCKER_TAG
{{- else }}
image: ghcr.io/nextcloud-releases/aio-collabora:$DOCKER_TAG
{{- end }}
EOL
# shellcheck disable=SC1083
find ./ -name '*collabora-deployment.yaml' -exec sed -i "/IMAGE_PLACEHOLDER/r /tmp/additional-collabora.config" \{} \;
# shellcheck disable=SC1083
find ./ -name '*collabora-deployment.yaml' -exec sed -i "/IMAGE_PLACEHOLDER/d" \{} \;
cat << EOL > templates/nextcloud-aio-networkpolicy.yaml
{{- if eq .Values.NETWORK_POLICY_ENABLED "yes" }}
# https://github.com/ahmetb/kubernetes-network-policy-recipes/blob/master/04-deny-traffic-from-other-namespaces.md

102
php/composer.lock generated
View File

@@ -1092,16 +1092,16 @@
},
{
"name": "slim/csrf",
"version": "1.5.0",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/slimphp/Slim-Csrf.git",
"reference": "179cbcf40ee1d246d4906aefed42d3e62066974b"
"reference": "a476a61e38451e138c400f6b4ca96037f3c2dd39"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slimphp/Slim-Csrf/zipball/179cbcf40ee1d246d4906aefed42d3e62066974b",
"reference": "179cbcf40ee1d246d4906aefed42d3e62066974b",
"url": "https://api.github.com/repos/slimphp/Slim-Csrf/zipball/a476a61e38451e138c400f6b4ca96037f3c2dd39",
"reference": "a476a61e38451e138c400f6b4ca96037f3c2dd39",
"shasum": ""
},
"require": {
@@ -1112,8 +1112,6 @@
"psr/http-server-middleware": "^1.0"
},
"require-dev": {
"phpspec/prophecy": "^1.19",
"phpspec/prophecy-phpunit": "^2.2",
"phpunit/phpunit": "^9.6",
"squizlabs/php_codesniffer": "^3.10"
},
@@ -1144,9 +1142,9 @@
],
"support": {
"issues": "https://github.com/slimphp/Slim-Csrf/issues",
"source": "https://github.com/slimphp/Slim-Csrf/tree/1.5.0"
"source": "https://github.com/slimphp/Slim-Csrf/tree/1.5.1"
},
"time": "2024-06-08T16:37:18+00:00"
"time": "2025-11-02T14:58:28+00:00"
},
{
"name": "slim/slim",
@@ -1646,16 +1644,16 @@
},
{
"name": "twig/twig",
"version": "v3.21.1",
"version": "v3.22.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d"
"reference": "4509984193026de413baf4ba80f68590a7f2c51d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/285123877d4dd97dd7c11842ac5fb7e86e60d81d",
"reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/4509984193026de413baf4ba80f68590a7f2c51d",
"reference": "4509984193026de413baf4ba80f68590a7f2c51d",
"shasum": ""
},
"require": {
@@ -1709,7 +1707,7 @@
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v3.21.1"
"source": "https://github.com/twigphp/Twig/tree/v3.22.0"
},
"funding": [
{
@@ -1721,7 +1719,7 @@
"type": "tidelift"
}
],
"time": "2025-05-03T07:21:55+00:00"
"time": "2025-10-29T15:56:47+00:00"
}
],
"packages-dev": [
@@ -3757,16 +3755,16 @@
},
{
"name": "spatie/array-to-xml",
"version": "3.4.0",
"version": "3.4.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/array-to-xml.git",
"reference": "7dcfc67d60b0272926dabad1ec01f6b8a5fb5e67"
"reference": "6a740f39415aee8886aea10333403adc77d50791"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/array-to-xml/zipball/7dcfc67d60b0272926dabad1ec01f6b8a5fb5e67",
"reference": "7dcfc67d60b0272926dabad1ec01f6b8a5fb5e67",
"url": "https://api.github.com/repos/spatie/array-to-xml/zipball/6a740f39415aee8886aea10333403adc77d50791",
"reference": "6a740f39415aee8886aea10333403adc77d50791",
"shasum": ""
},
"require": {
@@ -3809,7 +3807,7 @@
"xml"
],
"support": {
"source": "https://github.com/spatie/array-to-xml/tree/3.4.0"
"source": "https://github.com/spatie/array-to-xml/tree/3.4.1"
},
"funding": [
{
@@ -3821,7 +3819,7 @@
"type": "github"
}
],
"time": "2024-12-16T12:45:15+00:00"
"time": "2025-11-12T10:32:50+00:00"
},
{
"name": "sserbin/twig-linter",
@@ -3883,16 +3881,16 @@
},
{
"name": "symfony/console",
"version": "v6.4.26",
"version": "v6.4.27",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "492de6dfd93910d7d7a729c5a04ddcd2b9e99c4f"
"reference": "13d3176cf8ad8ced24202844e9f95af11e2959fc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/492de6dfd93910d7d7a729c5a04ddcd2b9e99c4f",
"reference": "492de6dfd93910d7d7a729c5a04ddcd2b9e99c4f",
"url": "https://api.github.com/repos/symfony/console/zipball/13d3176cf8ad8ced24202844e9f95af11e2959fc",
"reference": "13d3176cf8ad8ced24202844e9f95af11e2959fc",
"shasum": ""
},
"require": {
@@ -3957,7 +3955,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v6.4.26"
"source": "https://github.com/symfony/console/tree/v6.4.27"
},
"funding": [
{
@@ -3977,20 +3975,20 @@
"type": "tidelift"
}
],
"time": "2025-09-26T12:13:46+00:00"
"time": "2025-10-06T10:25:16+00:00"
},
{
"name": "symfony/filesystem",
"version": "v7.3.2",
"version": "v7.3.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd"
"reference": "e9bcfd7837928ab656276fe00464092cc9e1826a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd",
"reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/e9bcfd7837928ab656276fe00464092cc9e1826a",
"reference": "e9bcfd7837928ab656276fe00464092cc9e1826a",
"shasum": ""
},
"require": {
@@ -4027,7 +4025,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v7.3.2"
"source": "https://github.com/symfony/filesystem/tree/v7.3.6"
},
"funding": [
{
@@ -4047,20 +4045,20 @@
"type": "tidelift"
}
],
"time": "2025-07-07T08:17:47+00:00"
"time": "2025-11-05T09:52:27+00:00"
},
{
"name": "symfony/finder",
"version": "v6.4.24",
"version": "v6.4.27",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "73089124388c8510efb8d2d1689285d285937b08"
"reference": "a1b6aa435d2fba50793b994a839c32b6064f063b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/73089124388c8510efb8d2d1689285d285937b08",
"reference": "73089124388c8510efb8d2d1689285d285937b08",
"url": "https://api.github.com/repos/symfony/finder/zipball/a1b6aa435d2fba50793b994a839c32b6064f063b",
"reference": "a1b6aa435d2fba50793b994a839c32b6064f063b",
"shasum": ""
},
"require": {
@@ -4095,7 +4093,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.24"
"source": "https://github.com/symfony/finder/tree/v6.4.27"
},
"funding": [
{
@@ -4115,7 +4113,7 @@
"type": "tidelift"
}
],
"time": "2025-07-15T12:02:45+00:00"
"time": "2025-10-15T18:32:00+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
@@ -4366,16 +4364,16 @@
},
{
"name": "symfony/service-contracts",
"version": "v3.6.0",
"version": "v3.6.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4"
"reference": "45112560a3ba2d715666a509a0bc9521d10b6c43"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
"reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43",
"reference": "45112560a3ba2d715666a509a0bc9521d10b6c43",
"shasum": ""
},
"require": {
@@ -4429,7 +4427,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v3.6.0"
"source": "https://github.com/symfony/service-contracts/tree/v3.6.1"
},
"funding": [
{
@@ -4440,12 +4438,16 @@
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2025-04-25T09:37:31+00:00"
"time": "2025-07-15T11:30:57+00:00"
},
{
"name": "symfony/string",
@@ -4724,16 +4726,16 @@
},
{
"name": "webmozart/assert",
"version": "1.12.0",
"version": "1.12.1",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
"reference": "541057574806f942c94662b817a50f63f7345360"
"reference": "9be6926d8b485f55b9229203f962b51ed377ba68"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/541057574806f942c94662b817a50f63f7345360",
"reference": "541057574806f942c94662b817a50f63f7345360",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68",
"reference": "9be6926d8b485f55b9229203f962b51ed377ba68",
"shasum": ""
},
"require": {
@@ -4776,9 +4778,9 @@
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.12.0"
"source": "https://github.com/webmozarts/assert/tree/1.12.1"
},
"time": "2025-10-20T12:43:39+00:00"
"time": "2025-10-29T15:56:20+00:00"
}
],
"aliases": [],

View File

@@ -229,9 +229,9 @@
"UPDATE_NEXTCLOUD_APPS=%UPDATE_NEXTCLOUD_APPS%",
"TZ=%TIMEZONE%",
"TALK_PORT=%TALK_PORT%",
"TURN_DOMAIN=%TURN_DOMAIN%",
"IMAGINARY_ENABLED=%IMAGINARY_ENABLED%",
"IMAGINARY_HOST=nextcloud-aio-imaginary",
"CLAMAV_MAX_SIZE=%APACHE_MAX_SIZE%",
"PHP_UPLOAD_LIMIT=%NEXTCLOUD_UPLOAD_LIMIT%",
"PHP_MEMORY_LIMIT=%NEXTCLOUD_MEMORY_LIMIT%",
"FULLTEXTSEARCH_ENABLED=%FULLTEXTSEARCH_ENABLED%",
@@ -380,7 +380,7 @@
"internal_port": "9980",
"environment": [
"aliasgroup1=https://%NC_DOMAIN%:443,http://nextcloud-aio-apache:23973",
"extra_params=--o:ssl.enable=false --o:ssl.termination=true --o:mount_jail_tree=false --o:logging.level=warning --o:logging.level_startup=warning --o:home_mode.enable=true %COLLABORA_SECCOMP_POLICY% --o:remote_font_config.url=https://%NC_DOMAIN%/apps/richdocuments/settings/fonts.json --o:net.post_allow.host[0]=.+",
"extra_params=--o:ssl.enable=false --o:ssl.termination=true --o:mount_jail_tree=false --o:logging.disable_server_audit=true --o:logging.level=warning --o:logging.level_startup=warning --o:welcome.enable=false %COLLABORA_SECCOMP_POLICY% --o:remote_font_config.url=https://%NC_DOMAIN%/apps/richdocuments/settings/fonts.json --o:net.post_allow.host[0]=.+",
"dictionaries=%COLLABORA_DICTIONARIES%",
"TZ=%TIMEZONE%",
"server_name=%NC_DOMAIN%",
@@ -399,7 +399,10 @@
"SYS_ADMIN",
"SYS_CHROOT",
"FOWNER",
"CHOWN"
"CHOWN",
"MAC_OVERRIDE",
"BLOCK_SUSPEND",
"AUDIT_READ"
],
"cap_drop": [
"NET_RAW"

View File

@@ -0,0 +1,844 @@
{
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 1,
"archMap": [
{
"architecture": "SCMP_ARCH_X86_64",
"subArchitectures": [
"SCMP_ARCH_X86",
"SCMP_ARCH_X32"
]
},
{
"architecture": "SCMP_ARCH_AARCH64",
"subArchitectures": [
"SCMP_ARCH_ARM"
]
},
{
"architecture": "SCMP_ARCH_MIPS64",
"subArchitectures": [
"SCMP_ARCH_MIPS",
"SCMP_ARCH_MIPS64N32"
]
},
{
"architecture": "SCMP_ARCH_MIPS64N32",
"subArchitectures": [
"SCMP_ARCH_MIPS",
"SCMP_ARCH_MIPS64"
]
},
{
"architecture": "SCMP_ARCH_MIPSEL64",
"subArchitectures": [
"SCMP_ARCH_MIPSEL",
"SCMP_ARCH_MIPSEL64N32"
]
},
{
"architecture": "SCMP_ARCH_MIPSEL64N32",
"subArchitectures": [
"SCMP_ARCH_MIPSEL",
"SCMP_ARCH_MIPSEL64"
]
},
{
"architecture": "SCMP_ARCH_S390X",
"subArchitectures": [
"SCMP_ARCH_S390"
]
},
{
"architecture": "SCMP_ARCH_RISCV64",
"subArchitectures": null
}
],
"syscalls": [
{
"names": [
"unshare",
"mount",
"setns",
"clone",
"chroot",
"umount2"
],
"action": "SCMP_ACT_ALLOW"
},
{
"names": [
"accept",
"accept4",
"access",
"adjtimex",
"alarm",
"bind",
"brk",
"cachestat",
"capget",
"capset",
"chdir",
"chmod",
"chown",
"chown32",
"clock_adjtime",
"clock_adjtime64",
"clock_getres",
"clock_getres_time64",
"clock_gettime",
"clock_gettime64",
"clock_nanosleep",
"clock_nanosleep_time64",
"close",
"close_range",
"connect",
"copy_file_range",
"creat",
"dup",
"dup2",
"dup3",
"epoll_create",
"epoll_create1",
"epoll_ctl",
"epoll_ctl_old",
"epoll_pwait",
"epoll_pwait2",
"epoll_wait",
"epoll_wait_old",
"eventfd",
"eventfd2",
"execve",
"execveat",
"exit",
"exit_group",
"faccessat",
"faccessat2",
"fadvise64",
"fadvise64_64",
"fallocate",
"fanotify_mark",
"fchdir",
"fchmod",
"fchmodat",
"fchmodat2",
"fchown",
"fchown32",
"fchownat",
"fcntl",
"fcntl64",
"fdatasync",
"fgetxattr",
"flistxattr",
"flock",
"fork",
"fremovexattr",
"fsetxattr",
"fstat",
"fstat64",
"fstatat64",
"fstatfs",
"fstatfs64",
"fsync",
"ftruncate",
"ftruncate64",
"futex",
"futex_requeue",
"futex_time64",
"futex_wait",
"futex_waitv",
"futex_wake",
"futimesat",
"getcpu",
"getcwd",
"getdents",
"getdents64",
"getegid",
"getegid32",
"geteuid",
"geteuid32",
"getgid",
"getgid32",
"getgroups",
"getgroups32",
"getitimer",
"getpeername",
"getpgid",
"getpgrp",
"getpid",
"getppid",
"getpriority",
"getrandom",
"getresgid",
"getresgid32",
"getresuid",
"getresuid32",
"getrlimit",
"get_robust_list",
"getrusage",
"getsid",
"getsockname",
"getsockopt",
"get_thread_area",
"gettid",
"gettimeofday",
"getuid",
"getuid32",
"getxattr",
"inotify_add_watch",
"inotify_init",
"inotify_init1",
"inotify_rm_watch",
"io_cancel",
"ioctl",
"io_destroy",
"io_getevents",
"io_pgetevents",
"io_pgetevents_time64",
"ioprio_get",
"ioprio_set",
"io_setup",
"io_submit",
"ipc",
"kill",
"landlock_add_rule",
"landlock_create_ruleset",
"landlock_restrict_self",
"lchown",
"lchown32",
"lgetxattr",
"link",
"linkat",
"listen",
"listxattr",
"llistxattr",
"_llseek",
"lremovexattr",
"lseek",
"lsetxattr",
"lstat",
"lstat64",
"madvise",
"map_shadow_stack",
"membarrier",
"memfd_create",
"memfd_secret",
"mincore",
"mkdir",
"mkdirat",
"mknod",
"mknodat",
"mlock",
"mlock2",
"mlockall",
"mmap",
"mmap2",
"mprotect",
"mq_getsetattr",
"mq_notify",
"mq_open",
"mq_timedreceive",
"mq_timedreceive_time64",
"mq_timedsend",
"mq_timedsend_time64",
"mq_unlink",
"mremap",
"msgctl",
"msgget",
"msgrcv",
"msgsnd",
"msync",
"munlock",
"munlockall",
"munmap",
"name_to_handle_at",
"nanosleep",
"newfstatat",
"_newselect",
"open",
"openat",
"openat2",
"pause",
"pidfd_open",
"pidfd_send_signal",
"pipe",
"pipe2",
"pkey_alloc",
"pkey_free",
"pkey_mprotect",
"poll",
"ppoll",
"ppoll_time64",
"prctl",
"pread64",
"preadv",
"preadv2",
"prlimit64",
"process_mrelease",
"pselect6",
"pselect6_time64",
"pwrite64",
"pwritev",
"pwritev2",
"read",
"readahead",
"readlink",
"readlinkat",
"readv",
"recv",
"recvfrom",
"recvmmsg",
"recvmmsg_time64",
"recvmsg",
"remap_file_pages",
"removexattr",
"rename",
"renameat",
"renameat2",
"restart_syscall",
"rmdir",
"rseq",
"rt_sigaction",
"rt_sigpending",
"rt_sigprocmask",
"rt_sigqueueinfo",
"rt_sigreturn",
"rt_sigsuspend",
"rt_sigtimedwait",
"rt_sigtimedwait_time64",
"rt_tgsigqueueinfo",
"sched_getaffinity",
"sched_getattr",
"sched_getparam",
"sched_get_priority_max",
"sched_get_priority_min",
"sched_getscheduler",
"sched_rr_get_interval",
"sched_rr_get_interval_time64",
"sched_setaffinity",
"sched_setattr",
"sched_setparam",
"sched_setscheduler",
"sched_yield",
"seccomp",
"select",
"semctl",
"semget",
"semop",
"semtimedop",
"semtimedop_time64",
"send",
"sendfile",
"sendfile64",
"sendmmsg",
"sendmsg",
"sendto",
"setfsgid",
"setfsgid32",
"setfsuid",
"setfsuid32",
"setgid",
"setgid32",
"setgroups",
"setgroups32",
"setitimer",
"setpgid",
"setpriority",
"setregid",
"setregid32",
"setresgid",
"setresgid32",
"setresuid",
"setresuid32",
"setreuid",
"setreuid32",
"setrlimit",
"set_robust_list",
"setsid",
"setsockopt",
"set_thread_area",
"set_tid_address",
"setuid",
"setuid32",
"setxattr",
"shmat",
"shmctl",
"shmdt",
"shmget",
"shutdown",
"sigaltstack",
"signalfd",
"signalfd4",
"sigprocmask",
"sigreturn",
"socketcall",
"socketpair",
"splice",
"stat",
"stat64",
"statfs",
"statfs64",
"statx",
"symlink",
"symlinkat",
"sync",
"sync_file_range",
"syncfs",
"sysinfo",
"tee",
"tgkill",
"time",
"timer_create",
"timer_delete",
"timer_getoverrun",
"timer_gettime",
"timer_gettime64",
"timer_settime",
"timer_settime64",
"timerfd_create",
"timerfd_gettime",
"timerfd_gettime64",
"timerfd_settime",
"timerfd_settime64",
"times",
"tkill",
"truncate",
"truncate64",
"ugetrlimit",
"umask",
"uname",
"unlink",
"unlinkat",
"utime",
"utimensat",
"utimensat_time64",
"utimes",
"vfork",
"vmsplice",
"wait4",
"waitid",
"waitpid",
"write",
"writev"
],
"action": "SCMP_ACT_ALLOW"
},
{
"names": [
"process_vm_readv",
"process_vm_writev",
"ptrace"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"minKernel": "4.8"
}
},
{
"names": [
"socket"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 40,
"op": "SCMP_CMP_NE"
}
]
},
{
"names": [
"personality"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 0,
"op": "SCMP_CMP_EQ"
}
]
},
{
"names": [
"personality"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 8,
"op": "SCMP_CMP_EQ"
}
]
},
{
"names": [
"personality"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 131072,
"op": "SCMP_CMP_EQ"
}
]
},
{
"names": [
"personality"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 131080,
"op": "SCMP_CMP_EQ"
}
]
},
{
"names": [
"personality"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 4294967295,
"op": "SCMP_CMP_EQ"
}
]
},
{
"names": [
"sync_file_range2",
"swapcontext"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"arches": [
"ppc64le"
]
}
},
{
"names": [
"arm_fadvise64_64",
"arm_sync_file_range",
"sync_file_range2",
"breakpoint",
"cacheflush",
"set_tls"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"arches": [
"arm",
"arm64"
]
}
},
{
"names": [
"arch_prctl"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"arches": [
"amd64",
"x32"
]
}
},
{
"names": [
"modify_ldt"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"arches": [
"amd64",
"x32",
"x86"
]
}
},
{
"names": [
"s390_pci_mmio_read",
"s390_pci_mmio_write",
"s390_runtime_instr"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"arches": [
"s390",
"s390x"
]
}
},
{
"names": [
"riscv_flush_icache"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"arches": [
"riscv64"
]
}
},
{
"names": [
"open_by_handle_at"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_DAC_READ_SEARCH"
]
}
},
{
"names": [
"bpf",
"clone",
"clone3",
"fanotify_init",
"fsconfig",
"fsmount",
"fsopen",
"fspick",
"lookup_dcookie",
"mount",
"mount_setattr",
"move_mount",
"open_tree",
"perf_event_open",
"quotactl",
"quotactl_fd",
"setdomainname",
"sethostname",
"setns",
"syslog",
"umount",
"umount2",
"unshare"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_SYS_ADMIN"
]
}
},
{
"names": [
"clone"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": 2114060288,
"op": "SCMP_CMP_MASKED_EQ"
}
],
"excludes": {
"caps": [
"CAP_SYS_ADMIN"
],
"arches": [
"s390",
"s390x"
]
}
},
{
"names": [
"clone"
],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 1,
"value": 2114060288,
"op": "SCMP_CMP_MASKED_EQ"
}
],
"comment": "s390 parameter ordering for clone is different",
"includes": {
"arches": [
"s390",
"s390x"
]
},
"excludes": {
"caps": [
"CAP_SYS_ADMIN"
]
}
},
{
"names": [
"clone3"
],
"action": "SCMP_ACT_ERRNO",
"errnoRet": 38,
"excludes": {
"caps": [
"CAP_SYS_ADMIN"
]
}
},
{
"names": [
"reboot"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_SYS_BOOT"
]
}
},
{
"names": [
"chroot"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_SYS_CHROOT"
]
}
},
{
"names": [
"delete_module",
"init_module",
"finit_module"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_SYS_MODULE"
]
}
},
{
"names": [
"acct"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_SYS_PACCT"
]
}
},
{
"names": [
"kcmp",
"pidfd_getfd",
"process_madvise",
"process_vm_readv",
"process_vm_writev",
"ptrace"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_SYS_PTRACE"
]
}
},
{
"names": [
"iopl",
"ioperm"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_SYS_RAWIO"
]
}
},
{
"names": [
"settimeofday",
"stime",
"clock_settime",
"clock_settime64"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_SYS_TIME"
]
}
},
{
"names": [
"vhangup"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_SYS_TTY_CONFIG"
]
}
},
{
"names": [
"get_mempolicy",
"mbind",
"set_mempolicy",
"set_mempolicy_home_node"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_SYS_NICE"
]
}
},
{
"names": [
"syslog"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_SYSLOG"
]
}
},
{
"names": [
"bpf"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_BPF"
]
}
},
{
"names": [
"perf_event_open"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_PERFMON"
]
}
}
]
}

View File

@@ -1,23 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="6.13.1@1e3b7f0a8ab32b23197b91107adc0a7ed8a05b51">
<file src="src/ContainerDefinitionFetcher.php">
<PossiblyFalseArgument>
<code><![CDATA[file_get_contents($path)]]></code>
<code><![CDATA[file_get_contents(__DIR__ . '/../containers.json')]]></code>
</PossiblyFalseArgument>
</file>
<file src="src/Controller/DockerController.php">
<InvalidOperand>
<code><![CDATA[$port]]></code>
</InvalidOperand>
</file>
<file src="src/Data/ConfigurationManager.php">
<FalsableReturnStatement>
<code><![CDATA[$additionalBackupDirectories]]></code>
</FalsableReturnStatement>
<InvalidFalsableReturnType>
<code><![CDATA[string]]></code>
</InvalidFalsableReturnType>
<PossiblyFalseArgument>
<code><![CDATA[$ch]]></code>
<code><![CDATA[$ch]]></code>
@@ -25,26 +13,8 @@
<code><![CDATA[$ch]]></code>
<code><![CDATA[$ch]]></code>
<code><![CDATA[$ch]]></code>
<code><![CDATA[$configContent]]></code>
<code><![CDATA[$content]]></code>
<code><![CDATA[$content]]></code>
<code><![CDATA[$dailyBackupFile]]></code>
<code><![CDATA[$dailyBackupFile]]></code>
<code><![CDATA[file_get_contents(DataConst::GetBackupPublicKey())]]></code>
</PossiblyFalseArgument>
</file>
<file src="src/Data/DataConst.php">
<FalsableReturnStatement>
<code><![CDATA[realpath(__DIR__ . '/../../../community-containers/')]]></code>
<code><![CDATA[realpath(__DIR__ . '/../../data/')]]></code>
<code><![CDATA[realpath(__DIR__ . '/../../session/')]]></code>
</FalsableReturnStatement>
<InvalidFalsableReturnType>
<code><![CDATA[string]]></code>
<code><![CDATA[string]]></code>
<code><![CDATA[string]]></code>
</InvalidFalsableReturnType>
</file>
<file src="src/Docker/DockerActionManager.php">
<PossiblyFalseArgument>
<code><![CDATA[$line]]></code>

7
php/public/base_path.js Normal file
View File

@@ -0,0 +1,7 @@
document.addEventListener("DOMContentLoaded", function() {
basePath = document.getElementById("base_path")
if (basePath) {
// Remove '/containers' from the end of the path, to get the base path only
basePath.value = window.location.pathname.slice(0, -11);
}
});

View File

@@ -87,6 +87,7 @@ $app->get('/containers', function (Request $request, Response $response, array $
$params = $request->getQueryParams();
$bypass_mastercontainer_update = isset($params['bypass_mastercontainer_update']);
$bypass_container_update = isset($params['bypass_container_update']);
$skip_domain_validation = isset($params['skip_domain_validation']);
return $view->render($response, 'containers.twig', [
'domain' => $configurationManager->GetDomain(),
@@ -116,7 +117,7 @@ $app->get('/containers', function (Request $request, Response $response, array $
'daily_backup_time' => $configurationManager->GetDailyBackupTime(),
'is_daily_backup_running' => $configurationManager->isDailyBackupRunning(),
'timezone' => $configurationManager->GetTimezone(),
'skip_domain_validation' => $configurationManager->shouldDomainValidationBeSkipped(),
'skip_domain_validation' => $configurationManager->shouldDomainValidationBeSkipped($skip_domain_validation),
'talk_port' => $configurationManager->GetTalkPort(),
'collabora_dictionaries' => $configurationManager->GetCollaboraDictionaries(),
'collabora_additional_options' => $configurationManager->GetAdditionalCollaboraOptions(),
@@ -178,17 +179,17 @@ $app->get('/', function (\Psr\Http\Message\RequestInterface $request, Response $
$setup = $container->get(\AIO\Data\Setup::class);
if($setup->CanBeInstalled()) {
return $response
->withHeader('Location', '/setup')
->withHeader('Location', 'setup')
->withStatus(302);
}
if($authManager->IsAuthenticated()) {
return $response
->withHeader('Location', '/containers')
->withHeader('Location', 'containers')
->withStatus(302);
} else {
return $response
->withHeader('Location', '/login')
->withHeader('Location', 'login')
->withStatus(302);
}
});

View File

@@ -38,13 +38,13 @@ readonly class ContainerDefinitionFetcher {
*/
private function GetDefinition(): array
{
$data = json_decode(file_get_contents(__DIR__ . '/../containers.json'), true);
$data = json_decode((string)file_get_contents(DataConst::GetContainersDefinitionPath()), true, 512, JSON_THROW_ON_ERROR);
$additionalContainerNames = [];
foreach ($this->configurationManager->GetEnabledCommunityContainers() as $communityContainer) {
if ($communityContainer !== '') {
$path = DataConst::GetCommunityContainersDirectory() . '/' . $communityContainer . '/' . $communityContainer . '.json';
$additionalData = json_decode(file_get_contents($path), true);
$additionalData = json_decode((string)file_get_contents($path), true, 512, JSON_THROW_ON_ERROR);
$data = array_merge_recursive($data, $additionalData);
if (isset($additionalData['aio_services_v1'][0]['display_name']) && $additionalData['aio_services_v1'][0]['display_name'] !== '') {
// Store container_name of community containers in variable for later
@@ -67,6 +67,9 @@ readonly class ContainerDefinitionFetcher {
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()) {
continue;

View File

@@ -19,7 +19,8 @@ readonly class ConfigurationController {
try {
if (isset($request->getParsedBody()['domain'])) {
$domain = $request->getParsedBody()['domain'] ?? '';
$this->configurationManager->SetDomain($domain);
$skipDomainValidation = isset($request->getParsedBody()['skip_domain_validation']);
$this->configurationManager->SetDomain($domain, $skipDomainValidation);
}
if (isset($request->getParsedBody()['current-master-password']) || isset($request->getParsedBody()['new-master-password'])) {
@@ -161,7 +162,7 @@ readonly class ConfigurationController {
$this->configurationManager->DeleteBorgBackupLocationVars();
}
return $response->withStatus(201)->withHeader('Location', '/');
return $response->withStatus(201)->withHeader('Location', '.');
} catch (InvalidSettingConfigurationException $ex) {
$response->getBody()->write($ex->getMessage());
return $response->withStatus(422);

View File

@@ -85,7 +85,7 @@ readonly class DockerController {
public function StartBackupContainerBackup(Request $request, Response $response, array $args) : Response {
$forceStopNextcloud = true;
$this->startBackup($forceStopNextcloud);
return $response->withStatus(201)->withHeader('Location', '/');
return $response->withStatus(201)->withHeader('Location', '.');
}
public function startBackup(bool $forceStopNextcloud = false) : void {
@@ -102,7 +102,7 @@ readonly class DockerController {
public function StartBackupContainerCheck(Request $request, Response $response, array $args) : Response {
$this->checkBackup();
return $response->withStatus(201)->withHeader('Location', '/');
return $response->withStatus(201)->withHeader('Location', '.');
}
public function checkBackup() : void {
@@ -132,7 +132,7 @@ readonly class DockerController {
$id = 'nextcloud-aio-borgbackup';
$this->PerformRecursiveContainerStart($id);
return $response->withStatus(201)->withHeader('Location', '/');
return $response->withStatus(201)->withHeader('Location', '.');
}
public function StartBackupContainerCheckRepair(Request $request, Response $response, array $args) : Response {
@@ -148,7 +148,7 @@ readonly class DockerController {
$config['backup-mode'] = 'check';
$this->configurationManager->WriteConfig($config);
return $response->withStatus(201)->withHeader('Location', '/');
return $response->withStatus(201)->withHeader('Location', '.');
}
public function StartBackupContainerTest(Request $request, Response $response, array $args) : Response {
@@ -163,7 +163,7 @@ readonly class DockerController {
$id = 'nextcloud-aio-borgbackup';
$this->PerformRecursiveContainerStart($id);
return $response->withStatus(201)->withHeader('Location', '/');
return $response->withStatus(201)->withHeader('Location', '.');
}
public function StartContainer(Request $request, Response $response, array $args) : Response
@@ -171,6 +171,7 @@ readonly class DockerController {
$uri = $request->getUri();
$host = $uri->getHost();
$port = $uri->getPort();
$path = $request->getParsedBody()['base_path'] ?? '';
if ($port === 8000) {
error_log('The AIO_URL-port was discovered to be 8000 which is not expected. It is now set to 443.');
$port = 443;
@@ -184,7 +185,7 @@ readonly class DockerController {
$config = $this->configurationManager->GetConfig();
// set AIO_URL
$config['AIO_URL'] = $host . ':' . $port;
$config['AIO_URL'] = $host . ':' . $port . $path;
// set wasStartButtonClicked
$config['wasStartButtonClicked'] = 1;
// set install_latest_major
@@ -204,7 +205,7 @@ readonly class DockerController {
// Temporarily disabled as it leads much faster to docker rate limits
// apcu_clear_cache();
return $response->withStatus(201)->withHeader('Location', '/');
return $response->withStatus(201)->withHeader('Location', '.');
}
public function startTopContainer(bool $pullImage) : void {
@@ -223,7 +224,7 @@ readonly class DockerController {
public function StartWatchtowerContainer(Request $request, Response $response, array $args) : Response {
$this->startWatchtower();
return $response->withStatus(201)->withHeader('Location', '/');
return $response->withStatus(201)->withHeader('Location', '.');
}
public function startWatchtower() : void {
@@ -261,7 +262,7 @@ readonly class DockerController {
$forceStopNextcloud = true;
$this->PerformRecursiveContainerStop($id, $forceStopNextcloud);
return $response->withStatus(201)->withHeader('Location', '/');
return $response->withStatus(201)->withHeader('Location', '.');
}
public function stopTopContainer() : void {

View File

@@ -19,33 +19,33 @@ readonly class LoginController {
public function TryLogin(Request $request, Response $response, array $args) : Response {
if (!$this->dockerActionManager->isLoginAllowed()) {
$response->getBody()->write("The login is blocked since Nextcloud is running.");
return $response->withHeader('Location', '/')->withStatus(422);
return $response->withHeader('Location', '.')->withStatus(422);
}
$password = $request->getParsedBody()['password'] ?? '';
if($this->authManager->CheckCredentials($password)) {
$this->authManager->SetAuthState(true);
return $response->withHeader('Location', '/')->withStatus(201);
return $response->withHeader('Location', '.')->withStatus(201);
}
$response->getBody()->write("The password is incorrect.");
return $response->withHeader('Location', '/')->withStatus(422);
return $response->withHeader('Location', '.')->withStatus(422);
}
public function GetTryLogin(Request $request, Response $response, array $args) : Response {
$token = $request->getQueryParams()['token'] ?? '';
if($this->authManager->CheckToken($token)) {
$this->authManager->SetAuthState(true);
return $response->withHeader('Location', '/')->withStatus(302);
return $response->withHeader('Location', '../..')->withStatus(302);
}
return $response->withHeader('Location', '/')->withStatus(302);
return $response->withHeader('Location', '../..')->withStatus(302);
}
public function Logout(Request $request, Response $response, array $args) : Response
{
$this->authManager->SetAuthState(false);
return $response
->withHeader('Location', '/')
->withHeader('Location', '../..')
->withStatus(302);
}
}

View File

@@ -13,7 +13,7 @@ class ConfigurationManager
{
if(file_exists(DataConst::GetConfigFile()))
{
$configContent = file_get_contents(DataConst::GetConfigFile());
$configContent = (string)file_get_contents(DataConst::GetConfigFile());
return json_decode($configContent, true, 512, JSON_THROW_ON_ERROR);
}
@@ -80,10 +80,7 @@ class ConfigurationManager
return '';
}
$content = file_get_contents(DataConst::GetBackupArchivesList());
if ($content === '') {
return '';
}
$content = (string)file_get_contents(DataConst::GetBackupArchivesList());
$lastBackupLines = explode("\n", $content);
$lastBackupLine = "";
@@ -108,10 +105,7 @@ class ConfigurationManager
return [];
}
$content = file_get_contents(DataConst::GetBackupArchivesList());
if ($content === '') {
return [];
}
$content = (string)file_get_contents(DataConst::GetBackupArchivesList());
$backupLines = explode("\n", $content);
$backupTimes = [];
@@ -170,10 +164,10 @@ class ConfigurationManager
public function isWhiteboardEnabled() : bool {
$config = $this->GetConfig();
if (isset($config['isWhiteboardEnabled']) && $config['isWhiteboardEnabled'] === 0) {
return false;
} else {
if (isset($config['isWhiteboardEnabled']) && $config['isWhiteboardEnabled'] === 1) {
return true;
} else {
return false;
}
}
@@ -294,7 +288,7 @@ class ConfigurationManager
/**
* @throws InvalidSettingConfigurationException
*/
public function SetDomain(string $domain) : void {
public function SetDomain(string $domain, bool $skipDomainValidation) : void {
// Validate that at least one dot is contained
if (!str_contains($domain, '.')) {
throw new InvalidSettingConfigurationException("Domain must contain at least one dot!");
@@ -321,8 +315,9 @@ class ConfigurationManager
}
// Skip domain validation if opted in to do so
if (!$this->shouldDomainValidationBeSkipped()) {
if ($this->shouldDomainValidationBeSkipped($skipDomainValidation)) {
error_log('Skipping domain validation');
} else {
$dnsRecordIP = gethostbyname($domain);
if ($dnsRecordIP === $domain) {
$dnsRecordIP = '';
@@ -575,6 +570,15 @@ class ConfigurationManager
return $this->GetEnvironmentalVariableOrConfig($envVariableName, $configName, $defaultValue);
}
public function GetTurnDomain() : string {
$config = $this->GetConfig();
if(!isset($config['turn_domain'])) {
$config['turn_domain'] = '';
}
return $config['turn_domain'];
}
/**
* @throws InvalidSettingConfigurationException
*/
@@ -636,7 +640,7 @@ class ConfigurationManager
return "";
}
return trim(file_get_contents(DataConst::GetBackupPublicKey()));
return trim((string)file_get_contents(DataConst::GetBackupPublicKey()));
}
public function GetBorgRestorePassword() : string {
@@ -795,7 +799,7 @@ class ConfigurationManager
if (!file_exists(DataConst::GetDailyBackupTimeFile())) {
return '';
}
$dailyBackupFile = file_get_contents(DataConst::GetDailyBackupTimeFile());
$dailyBackupFile = (string)file_get_contents(DataConst::GetDailyBackupTimeFile());
$dailyBackupFileArray = explode("\n", $dailyBackupFile);
return $dailyBackupFileArray[0];
}
@@ -804,7 +808,7 @@ class ConfigurationManager
if (!file_exists(DataConst::GetDailyBackupTimeFile())) {
return false;
}
$dailyBackupFile = file_get_contents(DataConst::GetDailyBackupTimeFile());
$dailyBackupFile = (string)file_get_contents(DataConst::GetDailyBackupTimeFile());
$dailyBackupFileArray = explode("\n", $dailyBackupFile);
if (isset($dailyBackupFileArray[1]) && $dailyBackupFileArray[1] === 'automaticUpdatesAreNotEnabled') {
return false;
@@ -855,8 +859,7 @@ class ConfigurationManager
if (!file_exists(DataConst::GetAdditionalBackupDirectoriesFile())) {
return '';
}
$additionalBackupDirectories = file_get_contents(DataConst::GetAdditionalBackupDirectoriesFile());
return $additionalBackupDirectories;
return (string)file_get_contents(DataConst::GetAdditionalBackupDirectoriesFile());
}
public function GetAdditionalBackupDirectoriesArray() : array {
@@ -905,8 +908,8 @@ class ConfigurationManager
$this->WriteConfig($config);
}
public function shouldDomainValidationBeSkipped() : bool {
if (getenv('SKIP_DOMAIN_VALIDATION') === 'true') {
public function shouldDomainValidationBeSkipped(bool $skipDomainValidation) : bool {
if ($skipDomainValidation || getenv('SKIP_DOMAIN_VALIDATION') === 'true') {
return true;
}
return false;
@@ -978,6 +981,13 @@ class ConfigurationManager
return $config['collabora_additional_options'];
}
public function isCollaboraSubscriptionEnabled() : bool {
if (str_contains($this->GetAdditionalCollaboraOptions(), '--o:support_key=')) {
return true;
}
return false;
}
public function DeleteAdditionalCollaboraOptions() : void {
$config = $this->GetConfig();
$config['collabora_additional_options'] = '';
@@ -1040,7 +1050,7 @@ class ConfigurationManager
apcu_add($filePath, $fileContents);
}
}
$json = is_string($fileContents) ? json_decode($fileContents, true) : false;
$json = is_string($fileContents) ? json_decode($fileContents, true, 512, JSON_THROW_ON_ERROR) : false;
if(is_array($json) && is_array($json['aio_services_v1'])) {
foreach ($json['aio_services_v1'] as $service) {
$documentation = is_string($service['documentation']) ? $service['documentation'] : '';

View File

@@ -8,7 +8,7 @@ class DataConst {
return '/mnt/docker-aio-config/data/';
}
return realpath(__DIR__ . '/../../data/');
return (string)realpath(__DIR__ . '/../../data/');
}
public static function GetSessionDirectory() : string {
@@ -16,7 +16,7 @@ class DataConst {
return '/mnt/docker-aio-config/session/';
}
return realpath(__DIR__ . '/../../session/');
return (string)realpath(__DIR__ . '/../../session/');
}
public static function GetConfigFile() : string {
@@ -56,6 +56,14 @@ class DataConst {
}
public static function GetCommunityContainersDirectory() : string {
return realpath(__DIR__ . '/../../../community-containers/');
return (string)realpath(__DIR__ . '/../../../community-containers/');
}
public static function GetCollaboraSeccompProfilePath() : string {
return (string)realpath(__DIR__ . '/../../cool-seccomp-profile.json');
}
public static function GetContainersDefinitionPath() : string {
return (string)realpath(__DIR__ . '/../../containers.json');
}
}

View File

@@ -7,12 +7,13 @@ use AIO\Container\ContainerState;
use AIO\Container\VersionState;
use AIO\ContainerDefinitionFetcher;
use AIO\Data\ConfigurationManager;
use AIO\Data\DataConst;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use http\Env\Response;
readonly class DockerActionManager {
private const string API_VERSION = 'v1.41';
private const string API_VERSION = 'v1.44';
private Client $guzzleClient;
public function __construct(
@@ -47,7 +48,7 @@ readonly class DockerActionManager {
throw $e;
}
$responseBody = json_decode((string)$response->getBody(), true);
$responseBody = json_decode((string)$response->getBody(), true, 512, JSON_THROW_ON_ERROR);
if ($responseBody['State']['Running'] === true) {
return ContainerState::Running;
@@ -67,7 +68,7 @@ readonly class DockerActionManager {
throw $e;
}
$responseBody = json_decode((string)$response->getBody(), true);
$responseBody = json_decode((string)$response->getBody(), true, 512, JSON_THROW_ON_ERROR);
if ($responseBody['State']['Restarting'] === true) {
return ContainerState::Restarting;
@@ -282,6 +283,10 @@ readonly class DockerActionManager {
}
} else if ($port === '%TALK_PORT%') {
$port = $this->configurationManager->GetTalkPort();
// Skip publishing talk port if it is set to the same value like the apache port
if ($port === $this->configurationManager->GetApachePort()) {
continue;
}
}
$ipBinding = $value->ipBinding;
if ($ipBinding === '%APACHE_IP_BINDING%') {
@@ -383,9 +388,10 @@ readonly class DockerActionManager {
}
}
}
// Special things for the talk container which should not be exposed in the containers.json
// Special things for the talk container which should not be exposed in the containers.json
} elseif ($container->GetIdentifier() === 'nextcloud-aio-talk') {
// This is needed due to a bug in libwebsockets which cannot handle unlimited ulimits
// 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') {
@@ -395,11 +401,18 @@ readonly class DockerActionManager {
// }
// $mounts[] = ["Type" => "bind", "Source" => $volume->name, "Target" => $volume->mountPoint, "ReadOnly" => !$volume->isWritable, "BindOptions" => [ "Propagation" => "rshared"]];
// }
// Special things for the caddy community container
// Special things for the caddy community container
} elseif ($container->GetIdentifier() === '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
// Special things for the collabora container which should not be exposed in the containers.json
} elseif ($container->GetIdentifier() === 'nextcloud-aio-collabora') {
// 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()];
}
@@ -529,6 +542,7 @@ readonly class DockerActionManager {
'RESTORE_EXCLUDE_PREVIEWS' => $this->configurationManager->GetRestoreExcludePreviews(),
'APACHE_PORT' => $this->configurationManager->GetApachePort(),
'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' : '',
@@ -633,11 +647,11 @@ readonly class DockerActionManager {
private function GetRepoDigestsOfContainer(string $containerName): ?array {
try {
$containerUrl = $this->BuildApiUrl(sprintf('containers/%s/json', $containerName));
$containerOutput = json_decode($this->guzzleClient->get($containerUrl)->getBody()->getContents(), true);
$containerOutput = json_decode($this->guzzleClient->get($containerUrl)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
$imageName = $containerOutput['Image'];
$imageUrl = $this->BuildApiUrl(sprintf('images/%s/json', $imageName));
$imageOutput = json_decode($this->guzzleClient->get($imageUrl)->getBody()->getContents(), true);
$imageOutput = json_decode($this->guzzleClient->get($imageUrl)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
if (!isset($imageOutput['RepoDigests'])) {
error_log('RepoDigests is not set of container ' . $containerName);
@@ -681,7 +695,7 @@ readonly class DockerActionManager {
$containerName = 'nextcloud-aio-mastercontainer';
$url = $this->BuildApiUrl(sprintf('containers/%s/json', $containerName));
try {
$output = json_decode($this->guzzleClient->get($url)->getBody()->getContents(), true);
$output = json_decode($this->guzzleClient->get($url)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
$imageNameArray = explode(':', $output['Config']['Image']);
if (count($imageNameArray) === 2) {
$imageName = $imageNameArray[0];
@@ -708,7 +722,7 @@ readonly class DockerActionManager {
$containerName = 'nextcloud-aio-mastercontainer';
$url = $this->BuildApiUrl(sprintf('containers/%s/json', $containerName));
try {
$output = json_decode($this->guzzleClient->get($url)->getBody()->getContents(), true);
$output = json_decode($this->guzzleClient->get($url)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
$tagArray = explode(':', $output['Config']['Image']);
if (count($tagArray) === 2) {
$tag = $tagArray[1];
@@ -772,7 +786,9 @@ readonly class DockerActionManager {
],
]
)->getBody()->getContents(),
true
true,
512,
JSON_THROW_ON_ERROR,
);
$id = $response['Id'];
@@ -826,7 +842,6 @@ readonly class DockerActionManager {
[
'json' => [
'Name' => $network,
'CheckDuplicate' => true,
'Driver' => 'bridge',
'Internal' => false,
]
@@ -914,7 +929,7 @@ readonly class DockerActionManager {
throw $e;
}
$responseBody = json_decode((string)$response->getBody(), true);
$responseBody = json_decode((string)$response->getBody(), true, 512, JSON_THROW_ON_ERROR);
$exitCode = $responseBody['State']['ExitCode'];
if (is_int($exitCode)) {
@@ -936,7 +951,7 @@ readonly class DockerActionManager {
throw $e;
}
$responseBody = json_decode((string)$response->getBody(), true);
$responseBody = json_decode((string)$response->getBody(), true, 512, JSON_THROW_ON_ERROR);
$exitCode = $responseBody['State']['ExitCode'];
if (is_int($exitCode)) {
@@ -968,7 +983,7 @@ readonly class DockerActionManager {
$imageName = $imageName . ':' . $this->GetCurrentChannel();
try {
$imageUrl = $this->BuildApiUrl(sprintf('images/%s/json', $imageName));
$imageOutput = json_decode($this->guzzleClient->get($imageUrl)->getBody()->getContents(), true);
$imageOutput = json_decode($this->guzzleClient->get($imageUrl)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
if (!isset($imageOutput['Created'])) {
error_log('Created is not set of image ' . $imageName);

View File

@@ -30,7 +30,7 @@ readonly class DockerHubManager {
'https://auth.docker.io/token?service=registry.docker.io&scope=repository:' . $name . ':pull'
);
$body = $authTokenRequest->getBody()->getContents();
$decodedBody = json_decode($body, true);
$decodedBody = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
if(isset($decodedBody['token'])) {
$authToken = $decodedBody['token'];
$manifestRequest = $this->guzzleClient->request(

View File

@@ -31,7 +31,7 @@ readonly class GitHubContainerRegistryManager
'https://ghcr.io/token?scope=repository:' . $name . ':pull'
);
$body = $authTokenRequest->getBody()->getContents();
$decodedBody = json_decode($body, true);
$decodedBody = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
if (isset($decodedBody['token'])) {
$authToken = $decodedBody['token'];
$manifestRequest = $this->guzzleClient->request(

View File

@@ -27,7 +27,24 @@ readonly class AuthMiddleware {
if(!in_array($request->getUri()->getPath(), $publicRoutes)) {
if(!$this->authManager->IsAuthenticated()) {
$status = 302;
$headers = ['Location' => '/'];
// Check the url of the request: split the string by '/' and count the number of elements
// Note that the path that gets to this middleware is not aware of any base path managed by a reverse proxy, so if the url is 'https://example.com/AIO/somepage', the path will be 'https://mastercontainer/somepage'
if (count(explode('/', $request->getUri()->getPath())) < 2) {
// If there are less than 2 elements it means we are somewhere in the root folder (no '/', so no subfolder), so we redirect to the same folder level to offload the redirection to the appropriate page to 'index.php' (specifically, once in the root level the login page will be loaded since we are not authenticated)
$location = '.';
} else {
// If there are 2 or more elements it means we are in a subfolder, so we need to go back to the root folder
// In the best case we need to go back by 1 level only
$location = '..';
// In the worst case we need to go back by n levels, where n is the number of elements - 2 (the first element is not a folder, the second element is already accounted for by the initial '..')
for ($i = 1; $i < count(explode('/', $request->getUri()->getPath())) - 2; $i++) {
// For each extra level we need to go back by another level
$location = $location . '/..';
}
}
$headers = ['Location' => $location];
$response = new Response($status, $headers);
return $response;
}

View File

@@ -3,11 +3,11 @@
{% block body %}
<div class="login">
<svg class="nextcloud-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 142 100" width="142" height="100">
<use href="/img/nextcloud-logo.svg#logo"></use>
<use href="/img/nextcloud-logo.svg#Nextcloud"></use>
<use href="img/nextcloud-logo.svg#logo"></use>
<use href="img/nextcloud-logo.svg#Nextcloud"></use>
<text x="10" y="50" fill="var(--color-nextcloud-logo)" class="fallback-text">Nextcloud Logo</text>
</svg>
<h2>Nextcloud All-In-One is already installed</h2>
<a href="/" class="button">Open Nextcloud AIO</a>
<a href="." class="button">Open Nextcloud AIO</a>
</div>
{% endblock %}

View File

@@ -4,15 +4,15 @@
{% if c.GetStartingState().value == 'starting' %}
<span class="status running"></span>
{{ c.GetDisplayName() }}
(<a href="/api/docker/logs?id={{ c.GetIdentifier() }}" target="_blank">Starting</a>)
(<a href="api/docker/logs?id={{ c.GetIdentifier() }}" 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>)
(<a href="api/docker/logs?id={{ c.GetIdentifier() }}" target="_blank">Running</a>)
{% else %}
<span class="status error"></span>
{{ c.GetDisplayName() }}
(<a href="/api/docker/logs?id={{ c.GetIdentifier() }}" target="_blank">Stopped</a>)
(<a href="api/docker/logs?id={{ c.GetIdentifier() }}" target="_blank">Stopped</a>)
{% endif %}
{% if c.GetDocumentation() != '' %}
(<a target="_blank" href="{{ c.GetDocumentation() }}">docs</a>)

View File

@@ -6,9 +6,9 @@
</head>
<header>
<svg class="logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 142 71" width="62" height="50">
<use href="/img/nextcloud-logo.svg#logo"></use>
<use href="img/nextcloud-logo.svg#logo"></use>
</svg>
<form method="POST" action="/api/auth/logout">
<form method="POST" action="api/auth/logout">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Log out" />
@@ -17,7 +17,7 @@
<div class="container">
<main>
<h1>Nextcloud AIO v11.11.0</h1>
<h1>Nextcloud AIO v12.0.0</h1>
{# Add 2nd tab warning #}
<script type="text/javascript" src="second-tab-warning.js"></script>
@@ -36,7 +36,7 @@
{% set isBackupOrRestoreRunning = false %}
{% set isApacheStarting = false %}
{# Setting newMajorVersion to '' will hide corresponding options/elements, can be set to an integer like 26 in order to show corresponding elements. If set, also increase installLatestMajor in https://github.com/nextcloud/all-in-one/blob/main/php/src/Controller/DockerController.php #}
{% set newMajorVersionString = '25 Autumn' %}
{% set newMajorVersionString = '' %}
{% if is_backup_container_running == true %}
{% if borg_backup_mode == 'backup' or borg_backup_mode == 'restore' %}
@@ -63,11 +63,11 @@
{% endfor %}
{% if is_daily_backup_running == true %}
<p><span class="status running"></span> Daily backup currently running. (<a href="/api/docker/logs?id=nextcloud-aio-mastercontainer" target="_blank">Mastercontainer logs</a>) (<a href="/api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Borg backup container logs</a>)</p>
<p><span class="status running"></span> Daily backup currently running. (<a href="api/docker/logs?id=nextcloud-aio-mastercontainer" target="_blank">Mastercontainer logs</a>) (<a href="api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Borg backup container logs</a>)</p>
{% if automatic_updates == true %}
<p>This will update your containers, the mastercontainer and, on Saturdays, your Nextcloud apps if the backup is successful.</p>
{% if is_mastercontainer_update_available == true %}
<p>When the mastercontainer is updated it will restart, making it unavailable for a moment. (<a href="/api/docker/logs?id=nextcloud-aio-watchtower" target="_blank">Logs</a>)</p>
<p>When the mastercontainer is updated it will restart, making it unavailable for a moment. (<a href="api/docker/logs?id=nextcloud-aio-watchtower" target="_blank">Logs</a>)</p>
{% endif %}
{% endif %}
{% if has_update_available == false %}
@@ -78,7 +78,7 @@
<p><a href="" class="button reload">Reload ↻</a></p>
<p>If the daily backup is stuck somehow, you can unstick it by running <strong>sudo docker exec nextcloud-aio-mastercontainer rm /mnt/docker-aio-config/data/daily_backup_running</strong> and afterwards reloading this interface.</p>
{% elseif isWatchtowerRunning == true %}
<p><span class="status running"></span> Mastercontainer update currently running. Once the update is complete the mastercontainer will restart, making it unavailable for a moment. Please wait until it's done. (<a href="/api/docker/logs?id=nextcloud-aio-watchtower" target="_blank">Logs</a>)</p>
<p><span class="status running"></span> Mastercontainer update currently running. Once the update is complete the mastercontainer will restart, making it unavailable for a moment. Please wait until it's done. (<a href="api/docker/logs?id=nextcloud-aio-watchtower" target="_blank">Logs</a>)</p>
<p><a href="" class="button reload">Reload ↻</a></p>
{% else %}
{% if is_backup_container_running == false and domain == "" %}
@@ -88,7 +88,7 @@
{% elseif is_mastercontainer_update_available == true %}
<h2>Mastercontainer update</h2>
<p>⚠️ A mastercontainer update is available. Please click on the button below to update it. Afterwards, you will be able to proceed with the setup.</p>
<form method="POST" action="/api/docker/watchtower" class="xhr">
<form method="POST" action="api/docker/watchtower" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Update mastercontainer" />
@@ -108,10 +108,13 @@
{% if skip_domain_validation == true %}
<p><strong>Please note:</strong> The domain validation is disabled so any domain will be accepted here! Make sure you do not make a typo here as you will not be able to change it afterwards!</p>
{% endif %}
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<input type="text" id="domain" name="domain" value="{{ domain }}" placeholder="nextcloud.yourdomain.com"/>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
{% if skip_domain_validation == true %}
<input type="hidden" name="skip_domain_validation" value="{{skip_domain_validation}}">
{% endif %}
<input type="submit" value="Submit domain" />
</form>
{% if skip_domain_validation == false %}
@@ -137,7 +140,7 @@
{% if hasBackupLocation %}
{% if borg_backup_mode in ['test', 'check'] %}
{% if backup_exit_code > 0 %}
<p><span class="status error"></span> Last {{ borg_backup_mode }} failed! (<a href="/api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
<p><span class="status error"></span> Last {{ borg_backup_mode }} failed! (<a href="api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
{% if borg_backup_mode == 'test' %}
<p>Please adjust the path and/or the encryption password in order to make it work!</p>
{% elseif borg_backup_mode == 'check' %}
@@ -145,7 +148,7 @@
<details>
<summary>Reveal repair option</summary>
<p>Below is the option to repair the integrity of your backup. <strong>Please note:</strong> Please only use this after you have read the documentation above! (It will run the command 'borg check --repair' for you.)</p>
<form method="POST" action="/api/docker/backup-check-repair" class="xhr">
<form method="POST" action="api/docker/backup-check-repair" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Check and repair backup integrity" onclick="return confirm('Check and repair backup integrity? Are you sure that you want to check and repair the backup integrity? This should only be done after reading the mentioned documentation.')"/>
@@ -153,10 +156,10 @@
</details>
{% endif %}
{% elseif backup_exit_code == 0 %}
<p><span class="status success"></span> Last {{ borg_backup_mode }} successful! (<a href="/api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
<p><span class="status success"></span> Last {{ borg_backup_mode }} successful! (<a href="api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
{% if borg_backup_mode == 'test' %}
<p>Feel free to check the integrity of the backup archive below before starting the restore process in order to make ensure that the restore will work. This can take a long time though depending on the size of the backup archive and is thus not required.</p>
<form method="POST" action="/api/docker/backup-check" class="xhr">
<form method="POST" action="api/docker/backup-check" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Check backup integrity"/>
@@ -164,7 +167,7 @@
{% endif %}
<p>Choose the backup that you want to restore and click on the button below to restore the selected backup. This will restore the whole AIO instance. Please note that the current AIO passphrase will be kept and the previous AIO passphrase will not be restored from backup!</p>
<p><strong>Important:</strong> If the backup that you want to restore contained any <a target="_blank" href="https://github.com/nextcloud/all-in-one/tree/main/community-containers#community-containers">community container</a>, you need to restore the same backup a second time after this attempt so that the community container data is also correctly restored.</p>
<form method="POST" action="/api/docker/restore" class="xhr" id="restore_selection">
<form method="POST" action="api/docker/restore" class="xhr" id="restore_selection">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<select id="selected_restore_time" name="selected_restore_time" form="restore_selection">
@@ -178,7 +181,7 @@
{% endif %}
{% elseif borg_backup_mode == 'restore' %}
{% if backup_exit_code > 0 %}
<p><span class="status error"></span> Last restore failed! (<a href="/api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
<p><span class="status error"></span> Last restore failed! (<a href="api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
<p>The restore process has unexpectedly failed! Please adjust the path and encryption password, test it and try to restore again!</p>
{% endif %}
{% endif %}
@@ -197,7 +200,7 @@
<a target="_blank" href="https://borgbackup.readthedocs.io/en/stable/usage/general.html#repository-urls">remote borg repo url</a>
if stored remotely; and the encryption password of the backup archive below and submit all values:
</p>
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<label>Local backup location</label> <input type="text" id="borg_restore_host_location" name="borg_restore_host_location" value="{{borg_backup_host_location}}" placeholder="/mnt/backup"/><br>
<label>Remote borg repo</label> <input type="text" name="borg_restore_remote_repo" value="{{borg_remote_repo}}" placeholder="ssh://user@host:port/path/to/repo"/><br>
<label>Borg passphrase</label> <input type="text" id="borg_restore_password" name="borg_restore_password" value="{{borg_restore_password}}" placeholder="encryption password"/><br>
@@ -210,7 +213,7 @@
{% endif %}
{% else %}
<p><strong>Everything set!</strong> Click on the button below to test the path and encryption password:</p>
<form method="POST" action="/api/docker/backup-test" class="xhr">
<form method="POST" action="api/docker/backup-test" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Test path and encryption password"/>
@@ -223,14 +226,14 @@
{% if was_start_button_clicked == true %}
{% if current_channel starts with 'latest' or current_channel starts with 'beta' or current_channel starts with 'develop' %}
<p>You are running the <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-switch-the-channel"><strong>{{ current_channel }}</strong></a> channel. (<a href="/api/docker/logs?id=nextcloud-aio-mastercontainer" target="_blank">Logs</a>)</p>
<p>You are running the <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-switch-the-channel"><strong>{{ current_channel }}</strong></a> channel. (<a href="api/docker/logs?id=nextcloud-aio-mastercontainer" target="_blank">Logs</a>)</p>
{% else %}
<p>No channel was found. This means that AIO is not able to update itself and its component and will also not be able to report about updates. Updates need to be done externally.</p>
{% endif %}
{% endif %}
{% if is_backup_container_running == true %}
<p><span class="status running"></span> Backup container is currently running: {{ borg_backup_mode }} (<a href="/api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
<p><span class="status running"></span> Backup container is currently running: {{ borg_backup_mode }} (<a href="api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
<p><a href="" class="button reload">Reload ↻</a></p>
{% endif %}
@@ -259,7 +262,7 @@
{% else %}
<p>It seems at least one container was not able to start correctly and is currently restarting.</p>
<p>To break this endless loop, you can stop the containers below and investigate the issue in the container logs before starting the containers again.</p>
<form method="POST" action="/api/docker/stop" class="xhr">
<form method="POST" action="api/docker/stop" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Stop containers" />
@@ -312,7 +315,7 @@
<p>You can find all changes <a target="_blank" href="https://github.com/nextcloud-releases/all-in-one/commits/main"><strong>here</strong></a></p>
{% endif %}
{% endif %}
<form method="POST" action="/api/docker/stop" class="xhr">
<form method="POST" action="api/docker/stop" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Stop containers" />
@@ -327,31 +330,34 @@
{% endif %}
{% if is_mastercontainer_update_available == true %}
<p>⚠️ A mastercontainer update is available. Please click on the button below to update it.</p>
<form method="POST" action="/api/docker/watchtower" class="xhr">
<form method="POST" action="api/docker/watchtower" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Update mastercontainer" />
</form>
{% else %}
{% if was_start_button_clicked == false %}
<form method="POST" action="/api/docker/start" class="xhr">
<form method="POST" action="api/docker/start" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input id="base_path" type="hidden" name="base_path" value="">
{% if newMajorVersionString != '' %}
<input type="checkbox" id="install_latest_major" name="install_latest_major"><label for="install_latest_major">Install Nextcloud Hub {{ newMajorVersionString }} (if unchecked, Nextcloud Hub 10 will get installed)</label><br>
{% endif %}
<input type="submit" value="Download and start containers" />
</form>
{% elseif has_update_available == false %}
<form method="POST" action="/api/docker/start" class="xhr">
<form method="POST" action="api/docker/start" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input id="base_path" type="hidden" name="base_path" value="">
<input type="submit" value="Start containers" />
</form>
{% else %}
<form method="POST" action="/api/docker/start" class="xhr">
<form method="POST" action="api/docker/start" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input id="base_path" type="hidden" name="base_path" value="">
{% if bypass_container_update == true %}
<input type="hidden" name="bypass_container_update" value="{{bypass_container_update}}">
{% endif %}
@@ -376,7 +382,7 @@
<a target="_blank" href="https://borgbackup.readthedocs.io/en/stable/usage/general.html#repository-urls">remote borg repo url and submit it</a>.
You will be provided with an SSH public key for authorization at the remote afterwards.
</p>
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<label>Local backup location</label> <input type="text" id="borg_backup_host_location" name="borg_backup_host_location" placeholder="/mnt/backup"/><br>
<label>Remote borg repo</label> <input type="text" name="borg_remote_repo" placeholder="ssh://user@host:port/path/to/repo"/><br>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
@@ -393,13 +399,13 @@
{% if is_backup_container_running == false %}
<h2>Backup and restore</h2>
{% if backup_exit_code > 0 %}
<p><span class="status error"></span> Last {{ borg_backup_mode }} failed! (<a href="/api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
<p><span class="status error"></span> Last {{ borg_backup_mode }} failed! (<a href="api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
{% if borg_backup_mode == "check" %}
<p>The backup check was not successful. This might indicate a corrupt archive (look at the logs). If that should be the case, you can try to fix it by following <a target="_blank" href="https://borgbackup.readthedocs.io/en/stable/faq.html#i-get-an-integrityerror-or-similar-what-now"><strong>this documentation</strong></a></p>
<details>
<summary>Reveal repair option</summary>
<p>Below is the option to repair the integrity of your backup. <strong>Please note:</strong> Please only use this after you have read the documentation above! (It will run the command 'borg check --repair' for you.)</p>
<form method="POST" action="/api/docker/backup-check-repair" class="xhr">
<form method="POST" action="api/docker/backup-check-repair" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Check and repair backup integrity" onclick="return confirm('Check and repair backup integrity? Are you sure that you want to check and repair the backup integrity? This should only be done after reading the mentioned documentation.')"/>
@@ -417,7 +423,7 @@
{% endif %}
<p>You may change the backup path again since the initial backup was not successful. After submitting the new value, you need to click on <strong>Create Backup</strong> to test the new value.</p>
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<label>Local backup location</label> <input type="text" name="borg_backup_host_location" placeholder="/mnt/backup"/><br>
<label>Remote borg repo</label> <input type="text" name="borg_remote_repo" placeholder="ssh://user@host:port/path/to/repo"/><br>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
@@ -427,9 +433,9 @@
{% endif %}
{% elseif backup_exit_code == 0 %}
{% if borg_backup_mode == "backup" %}
<p><span class="status success"></span> Last {{ borg_backup_mode }} successful on {{ last_backup_time }} UTC! (<a href="/api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
<p><span class="status success"></span> Last {{ borg_backup_mode }} successful on {{ last_backup_time }} UTC! (<a href="api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
{% else %}
<p><span class="status success"></span> Last {{ borg_backup_mode }} successful! (<a href="/api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
<p><span class="status success"></span> Last {{ borg_backup_mode }} successful! (<a href="api/docker/logs?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
{% endif %}
{% endif %}
{% endif %}
@@ -464,7 +470,7 @@
{% if isApacheStarting != true %}
<h3>Backup creation</h3>
<p>Clicking on the button below will create a backup.</p>
<form method="POST" action="/api/docker/backup" class="xhr">
<form method="POST" action="api/docker/backup" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Create backup" onclick="return confirm('Create backup? Are you sure that you want to create a backup? This will stop all running containers and create the backup.')" />
@@ -479,7 +485,7 @@
{% endif %}
is wrong, you can reset it by clicking on the button below.
</p>
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<input type="hidden" name="delete_borg_backup_location_vars" value="yes"/>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
@@ -493,7 +499,7 @@
<h3>Backup check</h3>
<p>Click on the button below to perform a backup integrity check. This is an option that verifies that your backup is intact. It shouldn't be needed in most situations.</p>
<form method="POST" action="/api/docker/backup-check" class="xhr">
<form method="POST" action="api/docker/backup-check" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="submit" value="Check backup integrity" onclick="return confirm('Check backup integrity? Are you sure that you want to check the backup? This can take a long time depending on the size of your backup.')" />
@@ -501,7 +507,7 @@
<h3>Backup restore</h3>
<p>Choose the backup that you want to restore and click on the button below to restore the selected backup. This will overwrite all your files with the chosen backup so you should consider creating a backup first. You can run an integrity check before restoring your files but this shouldn't be needed in most situations. Please note that this will not restore additionally chosen backup directories! The restore process should be pretty fast as rsync, which only transfers changed files, is used to restore the chosen backup.</p>
<form method="POST" action="/api/docker/restore" class="xhr" id="restore_selection">
<form method="POST" action="api/docker/restore" class="xhr" id="restore_selection">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<select id="selected_restore_time" name="selected_restore_time" form="restore_selection">
@@ -515,7 +521,7 @@
<h3>Daily backup and automatic updates</h3>
{% if daily_backup_time == "" %}
<p>By entering a time below and submitting it, you can enable daily backups. It will create them at the entered time in 24h format. E.g. <strong>04:00</strong> will create backups at 4 am UTC and <strong>16:00</strong> at 4 pm UTC. When creating the backup, containers will be stopped and restarted after the backup is complete.</p>
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<input type="text" name="daily_backup_time" placeholder="04:00"/>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
@@ -529,7 +535,7 @@
Also your containers, the mastercontainer and, on Saturdays, your Nextcloud apps will be automatically updated.
{% endif %}
<p>To change your backup time first disable Daily Backups, then enter your new backup time, and then re-enable them.</p>
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<input type="hidden" name="delete_daily_backup_time" value="yes"/>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
@@ -539,7 +545,7 @@
<h3>Back up additional directories and docker volumes of your host</h3>
<p>Below you can enter directories and docker volumes of your host that will be backed up into the same borg backup archive. Make sure to press the submit button after changing anything.</p>
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<textarea id="additional_backup_directories" name="additional_backup_directories" rows="4" cols="50" placeholder="/directory/on/the/host&#10;my_custom_docker_volume">{{ additional_backup_directories }}</textarea>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
@@ -566,7 +572,7 @@
<details>
<summary>Click here to change your AIO passphrase</summary>
<p>You can change your AIO passphrase below:</p>
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<input type="password" autocomplete="current-password" name="current-master-password" placeholder="Your current AIO passphrase" id="current-master-password" oninput="showPassword('current-master-password')">
<input type="password" autocomplete="new-password" name="new-master-password" placeholder="Your new AIO passphrase" id="new-master-password" oninput="showPassword('new-master-password')">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
@@ -592,7 +598,7 @@
{% if timezone == "" %}
<p>To get the correct time values for certain Nextcloud features, set the timezone for Nextcloud to the one that your users mainly use. Please note that this setting does not apply to the mastercontainer and any backup option.</p>
<p>You can configure the timezone for Nextcloud below (Do not forget to submit the value!):</p>
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<input type="text" id="timezone" name="timezone" placeholder="Europe/Berlin" />
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
@@ -601,7 +607,7 @@
<p>You need to make sure that the timezone that you enter is valid. An example is <strong>Europe/Berlin</strong>. You can get valid values by looking at the 'TZ identifier' column of this list: <a target="_blank" href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List"><strong>click here</strong></a>. The default is <strong>Etc/UTC</strong> if nothing is entered.</p>
{% else %}
<p>The timezone for Nextcloud is currently set to <strong>{{ timezone }}</strong>. You can change the timezone by clicking on the button below.</p>
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<input type="hidden" name="delete_timezone" value="yes"/>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
@@ -620,6 +626,8 @@
<script type="text/javascript" src="before-unload.js"></script>
{% endif %}
<script type="text/javascript" src="base_path.js"></script>
</main>
</div>
{% endblock %}

View File

@@ -8,7 +8,7 @@
{% endif %}
<details>
<summary>Show/Hide available Community Containers</summary>
<form id="community-form" method="POST" action="/api/configuration" class="xhr">
<form id="community-form" method="POST" action="api/configuration" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="hidden" name="community-form" value="community-form">

View File

@@ -5,7 +5,7 @@
{% else %}
<p><strong>Please note:</strong> Make sure to save your changes by clicking <strong>Save changes</strong> below the list of optional containers. The changes will not be auto-saved.</p>
{% endif %}
<form id="options-form" method="POST" action="/api/configuration" class="xhr">
<form id="options-form" method="POST" action="api/configuration" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input type="hidden" name="options-form" value="options-form">
@@ -160,7 +160,7 @@
{% if collabora_dictionaries == "" %}
<p>In order to get the correct dictionaries in Collabora, you may configure the dictionaries below:</p>
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<input type="text" name="collabora_dictionaries" placeholder="de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru" />
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
@@ -169,7 +169,7 @@
<p>You need to make sure that the dictionaries that you enter are valid. An example is <strong>de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru</strong>.</p>
{% else %}
<p>The dictionaries for Collabora are currently set to <strong>{{ collabora_dictionaries }}</strong>. You can reset them again by clicking on the button below.</p>
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<input type="hidden" name="delete_collabora_dictionaries" value="yes"/>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
@@ -182,7 +182,7 @@
{% if collabora_additional_options == "" %}
<p>You can configure additional options for collabora below.</p>
<p>(This can be used for configuring the net.content_security_policy and more. Make sure to submit the value!)</p>
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<input type="text" name="collabora_additional_options" />
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
@@ -191,7 +191,7 @@
<p>You need to make sure that the options that you enter are valid. An example is <strong>--o:net.content_security_policy=frame-ancestors *.example.com:*;</strong>.</p>
{% else %}
<p>The additioinal options for Collabora are currently set to <strong>{{ collabora_additional_options }}</strong>. You can reset them again by clicking on the button below.</p>
<form method="POST" action="/api/configuration" class="xhr">
<form method="POST" action="api/configuration" class="xhr">
<input type="hidden" name="delete_collabora_additional_options" value="yes"/>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">

View File

@@ -1,8 +1,8 @@
<html>
<head>
<title>AIO</title>
<link rel="stylesheet" href="/style.css?v6" media="all" />
<link rel="icon" href="/img/favicon.png">
<link rel="stylesheet" href="style.css?v6" media="all" />
<link rel="icon" href="img/favicon.png">
<script type="text/javascript" src="forms.js"></script>
<script type="text/javascript" src="toggle-dark-mode.js"></script>
</head>

View File

@@ -3,14 +3,14 @@
{% block body %}
<div class="login">
<svg class="nextcloud-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 142 100" width="142" height="100">
<use href="/img/nextcloud-logo.svg#logo"></use>
<use href="/img/nextcloud-logo.svg#Nextcloud"></use>
<use href="img/nextcloud-logo.svg#logo"></use>
<use href="img/nextcloud-logo.svg#Nextcloud"></use>
<text x="10" y="50" fill="var(--color-nextcloud-logo)" class="fallback-text">Nextcloud Logo</text>
</svg>
<h1>Nextcloud AIO Login</h1>
{% if is_login_allowed == true %}
<p>Log in using your Nextcloud AIO passphrase:</p>
<form method="POST" action="/api/auth/login" class="xhr">
<form method="POST" action="api/auth/login" class="xhr">
<input type="password" autocomplete="current-password" name="password" placeholder="Password" id="master-password" oninput="showPassword('master-password')">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">

View File

@@ -3,14 +3,14 @@
{% block body %}
<div class="login">
<svg class="nextcloud-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 142 100" width="142" height="100">
<use href="/img/nextcloud-logo.svg#logo"></use>
<use href="/img/nextcloud-logo.svg#Nextcloud"></use>
<use href="img/nextcloud-logo.svg#logo"></use>
<use href="img/nextcloud-logo.svg#Nextcloud"></use>
<text x="10" y="50" fill="var(--color-nextcloud-logo)" class="fallback-text">Nextcloud Logo</text>
</svg>
<h1>All-in-One setup</h1>
<p>The official Nextcloud installation method. Nextcloud All-in-One provides easy deployment and maintenance with most features included in this one Nextcloud instance.</p>
<p>⚠️ <strong>Please note down the passphrase to access the AIO interface and don't lose it!</strong></p>
<strong>Passphrase</strong><br/><span id="initial-password" class="monospace">{{ password }}</span><br>
<a href="/" class="button" target="_blank">Open Nextcloud AIO login ↗</a>
<a href="." class="button" target="_blank">Open Nextcloud AIO login ↗</a>
</div>
{% endblock %}

View File

@@ -46,7 +46,7 @@ Included are:
- By default confined (good for security) but can [allow access to additional storages](https://github.com/nextcloud/all-in-one#how-to-allow-the-nextcloud-container-to-access-directories-on-the-host) in order to enable the usage of the local external storage feature
- Possibility included to [adjust default installed Nextcloud apps](https://github.com/nextcloud/all-in-one#how-to-change-the-nextcloud-apps-that-are-installed-on-the-first-startup)
- Nextcloud installation is not read only - that means you can apply patches if you should need them (instead of having to wait for the next release for them getting applied)
- `ffmpeg`, `smbclient`, `libreoffice` and `nodejs` are included by default
- `ffmpeg`, `smbclient` and `nodejs` are included by default
- Possibility included to [permanently add additional OS packages into the Nextcloud container](https://github.com/nextcloud/all-in-one#how-to-change-the-nextcloud-apps-that-are-installed-on-the-first-startup) without having to build your own Docker image
- Possibility included to [permanently add additional PHP extensions into the Nextcloud container](https://github.com/nextcloud/all-in-one#how-to-add-php-extensions-permanently-to-the-nextcloud-container) without having to build your own Docker image
- Possibility included to [pass the needed device for hardware transcoding](https://github.com/nextcloud/all-in-one#how-to-enable-hardware-acceleration-for-nextcloud) to the Nextcloud container
@@ -376,6 +376,8 @@ Apart from that there is now a community container that can be added to the AIO
### How to skip the domain validation?
If you are completely sure that you've configured everything correctly and are not able to pass the domain validation, you may skip the domain validation by adding `--env SKIP_DOMAIN_VALIDATION=true` to the docker run command of the mastercontainer (but before the last line `ghcr.io/nextcloud-releases/all-in-one:latest`! If it was started already, you will need to stop the mastercontainer, remove it (no data will be lost) and recreate it using the docker run command that you initially used).
Alternatively, if the container is already running, reload the AIO interface with the param `skip_domain_validation` to skip the domain validation on the fly: e.g. `https://ip.address.of.the.server:8080/containers?skip_domain_validation`.
### How to resolve firewall problems with Fedora Linux, RHEL OS, CentOS, SUSE Linux and others?
It is known that Linux distros that use [firewalld](https://firewalld.org) as their firewall daemon have problems with docker networks. In case the containers are not able to communicate with each other, you may change your firewalld to use the iptables backend by running:
```
@@ -1143,3 +1145,11 @@ AIO ships its own update notifications implementation. It checks if container up
### Huge docker logs
If you should run into issues with huge docker logs, you can adjust the log size by following https://docs.docker.com/config/containers/logging/local/#usage. However for the included AIO containers, this should usually not be needed because almost all of them have the log level set to warn so they should not produce many logs.
<details>
<summary>Badges</summary>
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/nextcloud/all-in-one)
</details>

View File

@@ -1,80 +1,156 @@
# Reverse Proxy Documentation
> [!NOTE]
> Please note that AIO comes secured with TLS out-of-the-box. So you don't need to necessarily set up your own reverse proxy if you only want to run Nextcloud AIO which is much easier. See [the normal readme](https://github.com/nextcloud/all-in-one?tab=readme-ov-file#how-to-use-this) in that case. However if port 443 should already be used because you already run a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else), you need to follow this reverse proxy documentation to set up Nextcloud AIO.
> [!TIP]
> If you don't have a domain yet, [Tailscale is recommended](https://github.com/nextcloud/all-in-one/discussions/6817). If you don't have a reverse proxy yet, [Caddy is recommended](https://github.com/nextcloud/all-in-one/discussions/575).
# Using a reverse proxy or secure tunnel to access Nextcloud AIO
## Introduction
In order to run Nextcloud behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else), you need to:
1. add a specific config to your web server or reverse proxy. [See the documentation below.](#1-configure-the-reverse-proxy)
2. specify the port that AIO's integrated Apache container shall use via the environmental variable `APACHE_PORT` (that runs inside its own container and published this port on the host) and adjust the `docker run` command of AIO. [See the documentation below.](#2-use-this-startup-command).
3. Open the AIO interface at port `8080` and type in and validate your domain. [See the documentation below.](#4-open-the-aio-interface)
Here one example with all reverse proxy settings for Linux:
```
sudo docker run \
--init \
--sig-proxy=false \
--name nextcloud-aio-mastercontainer \
--restart always \
--publish 8080:8080 \
--env APACHE_PORT=11000 \
--env APACHE_IP_BINDING=0.0.0.0 \
--env APACHE_ADDITIONAL_NETWORK="" \
--env SKIP_DOMAIN_VALIDATION=false \
--volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
ghcr.io/nextcloud-releases/all-in-one:latest
```
This guide explains how to connect to Nextcloud AIO securely via HTTPS (TLS) using a reverse proxy or a secure tunneling platform. It covers several potential scenarios:
<details>
- **Integrated**: AIO's built-in reverse proxy with automatic HTTPS
- **External**: An external reverse proxy (such as Caddy or Nginx or Cloudflare Proxy)
- **Secure tunnel**: Tunneling services for private network access or public access without port forwarding (such as Tailscale Serve or Cloudflare Tunnel)
<summary>Explanation of the command</summary>
## Choosing Your Approach
- `sudo docker run` This command spins up a new docker container. Docker commands can optionally be used without `sudo` if the user is added to the docker group (this is not the same as docker rootless, see FAQ in the normal readme).
- `--init` This option makes sure that no zombie-processes are created, ever. See [the Docker documentation](https://docs.docker.com/reference/cli/docker/container/run/#init).
- `--sig-proxy=false` This option allows to exit the container shell that gets attached automatically when using `docker run` by using `[CTRL] + [C]` without shutting down the container.
- `--name nextcloud-aio-mastercontainer` This is the name of the container. This line is not allowed to be changed, since mastercontainer updates would fail.
- `--restart always` This is the "restart policy". `always` means that the container should always get started with the Docker daemon. See the Docker documentation for further detail about restart policies: https://docs.docker.com/config/containers/start-containers-automatically/
- `--publish 8080:8080` This means that port 8080 of the container should get published on the host using port 8080. This port is used for the AIO interface and uses a self-signed certificate by default. You can also use a different host port if port 8080 is already used on your host, for example `--publish 8081:8080` (only the first port can be changed for the host, the second port is for the container and must remain at 8080).
- `--env APACHE_PORT=11000` This is the port that is published on the host that runs Docker and Nextcloud AIO at which the reverse proxy should point at.
- `--env APACHE_IP_BINDING=0.0.0.0` This can be modified to allow access to the published port on the host only from certain ip-addresses. [See this documentation](#3-limit-the-access-to-the-apache-container)
- `--env APACHE_ADDITIONAL_NETWORK=""` This can be used to put the sibling apache container that is created by AIO into a specified network - useful if your reverse proxy runs as a container on the same host. [See this documentation](#adapting-the-sample-web-server-configurations-below)
- `--env SKIP_DOMAIN_VALIDATION=false` This can be set to `true` if the domain validation does not work and you are sure that you configured everything correctly after you followed [the debug documentation](#7-how-to-debug-things).
- `--volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config` This means that the files that are created by the mastercontainer will be stored in a docker volume that is called `nextcloud_aio_mastercontainer`. This line is not allowed to be changed, since built-in backups would fail later on.
- `--volume /var/run/docker.sock:/var/run/docker.sock:ro` The docker socket is mounted into the container which is used for spinning up all the other containers and for further features. It needs to be adjusted on Windows/macOS and on docker rootless. See the applicable documentation on this. If adjusting, don't forget to also set `WATCHTOWER_DOCKER_SOCKET_PATH`! If you dislike this, see https://github.com/nextcloud/all-in-one/tree/main/manual-install.
- `ghcr.io/nextcloud-releases/all-in-one:latest` This is the docker container image that is used.
- Further options can be set using environment variables, for example `--env NEXTCLOUD_DATADIR="/mnt/ncdata"` (This is an example for Linux. See [this](https://github.com/nextcloud/all-in-one#how-to-change-the-default-location-of-nextclouds-datadir) for other OS' and for an explanation of what this value does. This specific one needs to be specified upon the first startup if you want to change it to a specific path instead of the default Docker volume). To see explanations and examples for further variables (like changing the location of Nextcloud's datadir or mounting some locations as external storage into the Nextcloud container), read through this readme and look at the docker-compose file: https://github.com/nextcloud/all-in-one/blob/main/compose.yaml
</details>
> [!Note]
> If you run into troubles, see [the debug section](#7-how-to-debug-things).
---
> [!IMPORTANT]
> If you need HTTPS between Nextcloud and the reverse proxy because it is running on a different server in the same network, simply add another reverse proxy to the chain that runs on the same server like AIO and takes care of HTTPS proxying (most likely via self-signed certificates). Another option would be to create a VPN between the server that runs AIO and the server that runs the reverse proxy which takes care of encrypting the connection.
> [!TIP]
> If AIO's internal reverse proxy meets your needs, you may not need to set up your own reverse proxy. See the next section to assess whether this is the case.
> [!NOTE]
> Since the Apache container gets created by the mastercontainer, there is **NO** way to provide custom docker labels or custom environmental variables for the Apache container. So please do not attempt to do this because it will fail!
> If your goal is to use AIO purely locally, refer to the [Local instance documentation](https://github.com/nextcloud/all-in-one/blob/main/local-instance.md). Local instance setups don't require domain validation.
## Content
### When to use each approach
The process to run Nextcloud behind a reverse proxy consists of at least steps 1, 2 and 4:
1. **Configure the reverse proxy! See [point 1](#1-configure-the-reverse-proxy)**
1. **Use this startup command! See [point 2](#2-use-this-startup-command)**
1. Optional: if the reverse proxy is installed on the same host and in the host network, you should limit the apache container to only listen on localhost. See [point 3](#3-limit-the-access-to-the-apache-container)
1. **Open the AIO interface. See [point 4](#4-open-the-aio-interface)**
1. Optional: if the reverse proxy is outside the host network, configure AIO to trust it. See [point 5](#5-optional-configure-aio-for-reverse-proxies-that-connect-to-nextcloud-using-an-ip-address-and-not-localhost-nor-127001)
1. Optional: get a valid certificate for the AIO interface! See [point 6](#6-optional-get-a-valid-certificate-for-the-aio-interface)
1. Optional: how to debug things? See [point 7](#7-how-to-debug-things)
| Approach | Best for | Requirements | Inbound Ports Required |
|----------|----------|--------------|---------------|
| **Integrated** | Simple setups, single service on port 443 | Public IP, dedicated port 443 | Yes (443) |
| **External Reverse Proxy** (including Cloudflare Proxy) | Multiple services, existing web server, or users wanting DDoS protection | Existing reverse proxy, willingness to set one up, or Cloudflare account | Yes (443) |
| **Cloudflare Tunnel** | No port forwarding possible/desired, public access | Cloudflare account | No |
| **Tailscale Serve** | Private access (tailnet only) | Tailscale account | No |
| **Tailscale Funnel** | Public access via Tailscale | Tailscale account | No |
## 1. Configure the reverse proxy
## Implementation Details
### Integrated: Using AIO's internal reverse proxy with built-in HTTPS support
Nextcloud AIO is secured with TLS (HTTPS) out of the box via its internal reverse proxy. The integrated HTTPS support works well if your goal is to make AIO accessible from the public Internet and to ensure all traffic is encrypted with HTTPS.
Requirements:
- A public IP address that is reachable from the Internet (it does **not** need to be static, but it must not be behind carrier-grade NAT, which some ISPs use to share IP addresses among multiple customers).
- Port `443/tcp` on that IP must be available for AIO's exclusive use, and it must be opened/forwarded on your internet-facing firewall/router to the AIO host.[^talkPort]
**If AIO's integrated HTTPS support and internal reverse proxy meet your requirements, you do not need to proceed further. Follow the [standard Nextcloud AIO instructions](https://github.com/nextcloud/all-in-one?tab=readme-ov-file#how-to-use-this).**
### External: Using AIO with an external reverse proxy (e.g., *Caddy, Nginx, Cloudflare Proxy*)
**When you use an external reverse proxy, you disable AIO's built-in HTTPS support** because your reverse proxy will handle HTTPS/TLS certificates and encryption instead. This approach is necessary when:
- Port 443 is already in use by another service
- You want to run multiple web services on the same IP address
- You already have an existing reverse proxy infrastructure
A reverse proxy (or a web server acting as a reverse proxy) enables multiple web applications to share the same IP address and/or port (for example `443/tcp`) by directing traffic based on each application's hostname (often called "virtual hosts"). Incoming requests reach the reverse proxy and are then forwarded to the appropriate internal IP address, port, or container based on the requested hostname.
**Types of external reverse proxies:**
- **Self-hosted** (Caddy, Nginx, Apache, Traefik, HAProxy, etc.) - You manage the reverse proxy on your own server or separate server
- **Cloudflare Proxy** (orange-clouded DNS) - Cloudflare provides the reverse proxy at their edge network with DDoS protection and CDN benefits. This is distinct from Cloudflare Tunnel, though Tunnel can optionally use these proxy features when publishing routes.
Most notably, an external reverse proxy allows you to:
- share one external IP address among multiple hostnames/web applications, and
- use a different internal port than the externally used port.
Using an existing external reverse proxy is required in particular if port `443/tcp` on your public IP is already in use by another web application or by an existing web server/reverse proxy (for example Caddy or Nginx).
> [!NOTE]
> Cloudflare **Tunnel** and Cloudflare **Proxy** are different approaches:
> - **Cloudflare Tunnel** doesn't require opening any inbound ports on your firewall.
> - **Cloudflare Proxy** still requires port 443 exposed on your server.
> [!TIP]
> Examples of web servers or reverse proxies you might already be running include Apache, Caddy, Nginx, Traefik, and HAProxy — but only if they are bound to port `443/tcp` on the IP address you plan to associate with AIO.
> [!NOTE]
> An external reverse proxy can also facilitate other routing approaches, but Nextcloud AIO only supports having its own dedicated hostname (e.g., `cloud.example.com`). You cannot run it in a subfolder like `example.com/nextcloud/`.[^shared]
### Secure tunnel: Using AIO with a secure tunneling service (*Tailscale, Cloudflare*)
Cloudflare and Tailscale offer secure tunneling services that let you access your Nextcloud without opening ports on your firewall.
#### Private network access
For Nextcloud AIO, you can use:
- **Cloudflare Tunnel (`cloudflared`)** - Secure outbound-only tunnels that don't require exposing ports
- **Tailscale Serve** - Expose services privately on your Tailscale network (tailnet only)
Both options provide private network access to your Nextcloud AIO instance.
#### Public Internet access (without port forwarding)
To make your Nextcloud AIO instance accessible from the public Internet (not just your private network), you can use:
- **Cloudflare Tunnel** with public routes enabled (which combines Cloudflare Tunnel with Cloudflare's proxy features)
- **Tailscale Funnel** - Expose services to the public Internet via Tailscale's infrastructure
**Comparison of Cloudflare and Tailscale options:**
| Feature | Access Scope | Inbound Ports Required | Use Case |
|---------|--------------|----------------|----------|
| **Cloudflare Tunnel** | Public Internet | None | Public access without port forwarding |
| **Tailscale Serve** | Your Tailscale network only | None | Private access for you and invited users |
| **Tailscale Funnel** | Public Internet | None | Public access through Tailscale |
> [!TIP]
> Because of how [Cloudflare's Tunnel/Proxy operate](https://github.com/nextcloud/all-in-one/tree/main?tab=readme-ov-file#notes-on-cloudflare-proxytunnel), we recommend using Tailscale with Nextcloud when possible. Tailscale typically offers better performance and fewer trade-offs/limitations for Nextcloud.
>
> **For private/personal use**: [Tailscale Serve](https://tailscale.com/kb/1312/serve) is ideal - it keeps your Nextcloud completely private to your tailnet.
>
> **For public access without port forwarding**: Use [Tailscale Funnel](https://tailscale.com/kb/1223/funnel).
## Configuration and Deployment
> [!NOTE]
> These instructions assume you already have a domain name pointing to your server's public IP address. If you don't have a domain yet, see the recommendations below.
### Quick overview
To run Nextcloud AIO behind an external reverse proxy or secure tunneling/proxying service (instead of using AIO's integrated reverse proxy), the basic process is:
1. Configure your web server or reverse proxy with the specific settings for AIO.
2. Specify the port that AIO's integrated Apache container will use.
3. Open the AIO interface and validate your domain.
The sections below provide detailed instructions for each step.
> [!TIP]
> If you don't have a domain yet, we recommend using [an approach using Tailscale](https://github.com/nextcloud/all-in-one/discussions/6817). If you don't have an external reverse proxy yet, we recommend [Caddy](https://github.com/nextcloud/all-in-one/discussions/575).
### Step-by-Step Instructions
The process to run Nextcloud AIO behind a reverse proxy has three required steps and three optional steps:
**Required steps:**
1. **Configure** your web server or reverse proxy with the specific settings for AIO. See ["Configuring your reverse proxy"](#1-configure-the-reverse-proxy) below.
2. **Specify** the port that AIO's integrated Apache container will use via the environment variable `APACHE_PORT`, and update the `docker run` command or your Compose file accordingly. See ["Use this startup command"](#2-use-this-startup-command) below.
- *Optional*: Limit the access to the Apache container. See ["Limit the access to the Apache container"](#3-limit-the-access-to-the-apache-container).
3. **Open** the AIO interface at port `8080`, enter your domain, and validate it. See ["Open the AIO interface"](#4-open-the-aio-interface) below.
**Optional steps:**
4. Configure additional settings if your reverse proxy uses an IP address to connect to AIO. See ["Configure AIO for IP-based reverse proxies"](#5-optional-configure-aio-for-reverse-proxies-that-connect-to-nextcloud-using-an-ip-address-and-not-localhost-nor-127001).
5. Get a valid certificate for the AIO interface. See ["Get a valid certificate for the AIO interface"](#6-optional-get-a-valid-certificate-for-the-aio-interface).
6. Debug things if needed. See ["How to debug things"](#7-how-to-debug-things).
> [!NOTE]
> If you run into troubles, see [the debug section](#7-how-to-debug-things).
> [!IMPORTANT]
> If you need HTTPS between Nextcloud and the reverse proxy (because the reverse proxy runs on a different server), you have two options:
>
> 1. **Add a local reverse proxy**: Install another reverse proxy on the same server as AIO to handle HTTPS (typically with self-signed certificates)
> 2. **Use a VPN**: Create a VPN tunnel between the AIO server and the reverse proxy server to encrypt the connection
> [!NOTE]
> Since the Apache container gets created by the mastercontainer, there is **NO** way to provide custom Docker labels or custom environmental variables for the Apache container. So please do not attempt to do this because it will fail!
### 1. Configure the reverse proxy
#### Adapting the sample web server configurations below
### Adapting the sample web server configurations below
1. Replace `<your-nc-domain>` with the domain on which you want to run Nextcloud.
1. Adjust the port `11000` to match your chosen `APACHE_PORT`.
1. Adjust `localhost` or `127.0.0.1` to point to the Nextcloud server IP or domain depending on where the reverse proxy is running. See the following options.
@@ -108,7 +184,7 @@ The process to run Nextcloud behind a reverse proxy consists of at least steps 1
</details>
### Apache
##### Apache
<details>
@@ -188,7 +264,7 @@ To make the config work you can run the following command:
</details>
### Caddy (recommended)
##### Caddy (recommended)
<details>
@@ -211,7 +287,7 @@ The Caddyfile is a text file called `Caddyfile` (no extension) which if you
</details>
### Caddy with ACME DNS-challenge
##### Caddy with ACME DNS-challenge
<details>
@@ -239,7 +315,7 @@ You can get AIO running using the ACME DNS-challenge. Here is how to do it.
</details>
### OpenLiteSpeed
##### OpenLiteSpeed
<details>
@@ -249,7 +325,7 @@ You can find the OpenLiteSpeed reverse proxy guide by @MorrowShore here: https:/
</details>
### Citrix ADC VPX / Citrix Netscaler
##### Citrix ADC VPX / Citrix Netscaler
<details>
@@ -259,7 +335,7 @@ For a reverse proxy example guide for Citrix ADC VPX / Citrix Netscaler, see thi
</details>
### Cloudflare Tunnel
##### Cloudflare Tunnel
<details>
@@ -278,7 +354,7 @@ Although it does not seem like it is the case but from AIO perspective a Cloudfl
</details>
### HaProxy
##### HAProxy
<details>
@@ -375,7 +451,7 @@ backend Nextcloud
</details>
### Nginx, Freenginx, Openresty, Angie
##### Nginx, Freenginx, Openresty, Angie
<details>
@@ -474,7 +550,7 @@ server {
</details>
### NPMplus (Fork of Nginx-Proxy-Manager - NPM)
##### NPMplus (Fork of Nginx-Proxy-Manager - NPM)
<details>
@@ -505,7 +581,7 @@ Second, see these screenshots for a working config:
</details>
### Nginx-Proxy-Manager - NPM
##### Nginx-Proxy-Manager - NPM
<details>
@@ -538,7 +614,7 @@ Also change `<you>@<your-mail-provider-domain>` to a mail address of yours.
</details>
### Nginx-Proxy
##### Nginx-Proxy
<details>
@@ -554,7 +630,7 @@ Apart from that, there is a [manual-install](https://github.com/nextcloud/all-in
</details>
### Node.js with Express
##### Node.js with Express
<details>
@@ -641,7 +717,7 @@ httpServer.on('upgrade', (req, socket, head) => {
</details>
### Synology Reverse Proxy
##### Synology Reverse Proxy
<details>
@@ -659,7 +735,27 @@ See these screenshots for a working config:
</details>
### Traefik 2
##### Tailscale (Serve)
<details>
<summary>Click here to expand</summary>
Tailscale can be used to provide private access to your Nextcloud AIO instance without opening ports on your firewall. With **Tailscale Serve**, your Nextcloud is accessible only to devices on your Tailscale network (tailnet) via a secure HTTPS domain.
For a detailed setup guide using Tailscale Serve with Nextcloud AIO, see this guide by [@Perseus333](https://github.com/Perseus333): https://github.com/nextcloud/all-in-one/discussions/6817
The guide covers:
- Setting up system-wide (non-containerized) Tailscale as a reverse proxy
- Configuring Nextcloud AIO to work with Tailscale Serve
- Using Tailscale's MagicDNS to provide automatic HTTPS certificates
- Private access via your tailnet (e.g., `yourserver.tail0a12b3.ts.net`)
⚠️ **Please note:** This guide covers **Tailscale Serve** for private tailnet access. If you need public Internet access, consider using **Tailscale Funnel**.
</details>
##### Traefik 2
<details>
@@ -751,7 +847,7 @@ The examples below define the dynamic configuration in YAML files. If you rather
</details>
### Traefik 3
##### Traefik 3
<details>
@@ -837,7 +933,7 @@ The examples below define the dynamic configuration in YAML files. If you rather
</details>
### IIS with ARR and URL Rewrite
##### IIS with ARR and URL Rewrite
<details>
@@ -907,18 +1003,7 @@ Add the following `web.config` file to the root of the site you created as the r
</details>
### Tailscale
<details>
<summary>click here to expand</summary>
For a reverse proxy example guide for Tailscale, see this guide by [@Perseus333](https://github.com/Perseus333): https://github.com/nextcloud/all-in-one/discussions/6817
</details>
### Others
##### Others
<details>
@@ -928,7 +1013,7 @@ Config examples for other reverse proxies are currently not documented. Pull req
</details>
## 2. Use this startup command
### 2. Use this startup command
After adjusting your reverse proxy config, use the following command to start AIO:<br>
@@ -951,6 +1036,27 @@ sudo docker run \
ghcr.io/nextcloud-releases/all-in-one:latest
```
<details>
<summary>Explanation of the command</summary>
- `sudo docker run` This command spins up a new docker container. Docker commands can optionally be used without `sudo` if the user is added to the docker group (this is not the same as docker rootless, see FAQ in the normal readme).
- `--init` This option makes sure that no zombie-processes are created, ever. See [the Docker documentation](https://docs.docker.com/reference/cli/docker/container/run/#init).
- `--sig-proxy=false` This option allows to exit the container shell that gets attached automatically when using `docker run` by using `[CTRL] + [C]` without shutting down the container.
- `--name nextcloud-aio-mastercontainer` This is the name of the container. This line is not allowed to be changed, since mastercontainer updates would fail.
- `--restart always` This is the "restart policy". `always` means that the container should always get started with the Docker daemon. See the Docker documentation for further detail about restart policies: https://docs.docker.com/config/containers/start-containers-automatically/
- `--publish 8080:8080` This means that port 8080 of the container should get published on the host using port 8080. This port is used for the AIO interface and uses a self-signed certificate by default. You can also use a different host port if port 8080 is already used on your host, for example `--publish 8081:8080` (only the first port can be changed for the host, the second port is for the container and must remain at 8080).
- `--env APACHE_PORT=11000` This is the port that is published on the host that runs Docker and Nextcloud AIO at which the reverse proxy should point at.
- `--env APACHE_IP_BINDING=0.0.0.0` This can be modified to allow access to the published port on the host only from certain ip-addresses. [See this documentation](#3-limit-the-access-to-the-apache-container)
- `--env APACHE_ADDITIONAL_NETWORK=""` This can be used to put the sibling apache container that is created by AIO into a specified network - useful if your reverse proxy runs as a container on the same host. [See this documentation](#adapting-the-sample-web-server-configurations-below)
- `--env SKIP_DOMAIN_VALIDATION=false` This can be set to `true` if the domain validation does not work and you are sure that you configured everything correctly after you followed [the debug documentation](#7-how-to-debug-things). Also see [this documentation](https://github.com/nextcloud/all-in-one#how-to-skip-the-domain-validation).
- `--volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config` This means that the files that are created by the mastercontainer will be stored in a docker volume that is called `nextcloud_aio_mastercontainer`. This line is not allowed to be changed, since built-in backups would fail later on.
- `--volume /var/run/docker.sock:/var/run/docker.sock:ro` The docker socket is mounted into the container which is used for spinning up all the other containers and for further features. It needs to be adjusted on Windows/macOS and on docker rootless. See the applicable documentation on this. If adjusting, don't forget to also set `WATCHTOWER_DOCKER_SOCKET_PATH`! If you dislike this, see https://github.com/nextcloud/all-in-one/tree/main/manual-install.
- `ghcr.io/nextcloud-releases/all-in-one:latest` This is the docker container image that is used.
- Further options can be set using environment variables, for example `--env NEXTCLOUD_DATADIR="/mnt/ncdata"` (This is an example for Linux. See [this](https://github.com/nextcloud/all-in-one#how-to-change-the-default-location-of-nextclouds-datadir) for other OS' and for an explanation of what this value does. This specific one needs to be specified upon the first startup if you want to change it to a specific path instead of the default Docker volume). To see explanations and examples for further variables (like changing the location of Nextcloud's datadir or mounting some locations as external storage into the Nextcloud container), read through this readme and look at the docker-compose file: https://github.com/nextcloud/all-in-one/blob/main/compose.yaml
</details>
Note: you may be interested in adjusting Nextclouds datadir to store the files in a different location than the default docker volume. See [this documentation](https://github.com/nextcloud/all-in-one#how-to-change-the-default-location-of-nextclouds-datadir) on how to do it.
You should also think about limiting the Apache container to listen only on localhost in case the reverse proxy is running on the same host and in the host network, by providing an additional environmental variable to this docker run command. See [point 3](#3-limit-the-access-to-the-apache-container).
@@ -989,38 +1095,38 @@ On Synology DSM see https://github.com/nextcloud/all-in-one#how-to-run-aio-on-sy
Simply translate the docker run command into a docker-compose file. You can have a look at [this file](https://github.com/nextcloud/all-in-one/blob/main/compose.yaml) for some inspiration but you will need to modify it either way. You can find further examples here: https://github.com/nextcloud/all-in-one/discussions/588
## 3. Limit the access to the Apache container
### 3. Limit the access to the Apache container
Use this environment variable during the initial startup of the mastercontainer to make the apache container only listen on localhost: `--env APACHE_IP_BINDING=127.0.0.1`. **Attention:** This is only recommended to be set if you use `localhost` in your reverse proxy config to connect to your AIO instance. If you use an ip-address instead of localhost, you should set it to `0.0.0.0`.
## 4. Open the AIO interface
### 4. Open the AIO interface
After starting AIO, you should be able to access the AIO Interface via `https://ip.address.of.the.host:8080` and type in and validate the domain that you have configured.<br>
⚠️ **Important:** do always use an ip-address if you access this port and not a domain as HSTS might block access to it later! (It is also expected that this port uses a self-signed certificate due to security concerns which you need to accept in your browser)<br>
Enter your domain in the AIO interface that you've used in the reverse proxy config and you should be done. Please do not forget to open/forward port `3478/TCP` and `3478/UDP` in your firewall/router for the Talk container!
## 5. Optional: Configure AIO for reverse proxies that connect to nextcloud using an ip-address and not localhost nor 127.0.0.1
### 5. Optional: Configure AIO for reverse proxies that connect to nextcloud using an ip-address and not localhost nor 127.0.0.1
If your reverse proxy connects to nextcloud using an ip-address and not localhost or 127.0.0.1<sup>*</sup> you must make the following configuration changes
<small>*: The IP address it uses to connect to AIO is not in a private IP range such as these: `127.0.0.1/8,192.168.0.0/16,172.16.0.0/12,10.0.0.0/8,fd00::/8,::1`</small>
### Nextcloud trusted proxies
#### Nextcloud trusted proxies
Add the IP it uses connect to AIO to the Nextcloud trusted_proxies like this:
```
sudo docker exec --user www-data -it nextcloud-aio-nextcloud php occ config:system:set trusted_proxies 2 --value=ip.address.of.proxy
```
### Collabora WOPI allow list
#### Collabora WOPI allow list
If your reverse proxy connects to Nextcloud with an IP address that is different from the one for your domain<sup>*</sup> and you are using the Collabora server then you must also add the IP to the WOPI request allow list via `Administration Settings > Administration > Office > Allow list for WOPI requests`.
<small>*: For example, the reverse proxy has a public globally routable IP and connects to your AIO instance via Tailscale with an IP in the `100.64.0.0/10` range, or you are using a Cloudflare tunnel ([cloudflare notes](https://github.com/nextcloud/all-in-one?tab=readme-ov-file#notes-on-cloudflare-proxytunnel): You must add all [Cloudflare IP-Ranges](https://www.cloudflare.com/ips/) to the WOPI allowlist.)</small>
### External reverse proxies connecting via VPN (e.g. Tailscale)
#### External reverse proxies connecting via VPN (e.g. Tailscale)
If your reverse proxy is outside your LAN and connecting via VPN such as Tailscale, you may want to set `APACHE_IP_BINDING=AIO.VPN.host.IP` to ensure only traffic coming from the VPN can connect.
## 6. Optional: get a valid certificate for the AIO interface
### 6. Optional: get a valid certificate for the AIO interface
If you want to also access your AIO interface publicly with a valid certificate, you can add e.g. the following config to your Caddyfile:
@@ -1037,7 +1143,8 @@ https://<your-nc-domain>:8443 {
Afterwards should the AIO interface be accessible via `https://ip.address.of.the.host:8443`. You can alternatively change the domain to a different subdomain by using `https://<your-alternative-domain>:443` instead of `https://<your-nc-domain>:8443` in the Caddyfile and use that to access the AIO interface.
## 7. How to debug things?
### 7. How to debug things?
<a id="how-to-debug"></a> <!-- for external linking -->
<a id="6-how-to-debug-things"></a> <!-- For backwards compatibility-->
@@ -1055,9 +1162,10 @@ If something does not work, follow the steps below:
1. Check if you have a public IPv4- and public IPv6-address. If you only have a public IPv6-address (e.g. due to DS-Lite), make sure to enable IPv6 in Docker and your whole networking infrastructure (e.g. also by adding an AAAA DNS-entry to your domain)!
1. [Enable Hairpin NAT in your router](https://github.com/nextcloud/all-in-one/discussions/5849) or [set up a local DNS server and add a custom dns-record](https://github.com/nextcloud/all-in-one#how-can-i-access-nextcloud-locally) that allows the server to reach itself locally
1. Try to configure everything from scratch - if it still does not work by following https://github.com/nextcloud/all-in-one#how-to-properly-reset-the-instance.
1. As last resort, you may disable the domain validation by adding `--env SKIP_DOMAIN_VALIDATION=true` to the docker run command. But only use this if you are completely sure that you've correctly configured everything!
1. As last resort, you may disable the domain validation by adding `--env SKIP_DOMAIN_VALIDATION=true` to the docker run command. But only use this if you are completely sure that you've correctly configured everything! Also see [this documentation](https://github.com/nextcloud/all-in-one#how-to-skip-the-domain-validation).
### 8. Removing the reverse proxy
## 8. Removing the reverse proxy
If you, at some point, want to remove the reverse proxy, here are some general steps:
1. Stop all running containers in the AIO Interface.
2. Stop and remove the mastercontainer.
@@ -1075,3 +1183,10 @@ If you, at some point, want to remove the reverse proxy, here are some general s
*The first command ensures that the Apache container is listening on all available network interfaces and the second command configures it to listen to port 443.*
5. Restart all other containers in the AIO interface.
---
## Footnotes:
[^talkPort]: Ports 3478/TCP and 3478/UDP are also required if using Nextcloud Talk (but they're less likely to conflict with existing services).
[^shared]: Other Nextcloud Server deployment methods (but not AIO) can be deployed behind shared hostnames and accessed via subfolder-based URLs. For example, this is supported with Bare Metal (Archive) and the micro-services Docker image, among others. Note that pure subfolder deployments are less and less required these days, with the broad support for virtual host based access (including at the reverse proxy level), which easily facilitates port IP address and external port sharing.