Compare commits

...

45 commits

Author SHA1 Message Date
Josh
4a2d5bbfda chore: some additional refvisions
Signed-off-by: Josh <josh.t.richards@gmail.com>
2026-01-23 10:54:37 -05:00
Josh
9c464bcf1d refactor(app/public): tidy up bootstrapper/main endpoint
Signed-off-by: Josh <josh.t.richards@gmail.com>
2026-01-23 10:54:37 -05:00
Simon L.
74443aaacc
Merge pull request #7477 from nextcloud/docjyJ-patch-2
Some checks failed
Codespell / Check spelling (push) Has been cancelled
Validate community containers / Validate community containers (push) Has been cancelled
Json Validator / Json Validator (push) Has been cancelled
deprecate nocodb community container
2026-01-23 14:22:42 +01:00
Simon L.
33614b276b
Merge pull request #7475 from nextcloud/dev/ench/noid/conduct
Add Code of conduct
2026-01-23 14:18:45 +01:00
Simon L.
034c6edea9
Merge pull request #7479 from nextcloud/dependabot/github_actions/dot-github/workflows/actions/checkout-6.0.2
build(deps): bump actions/checkout from 6.0.1 to 6.0.2 in /.github/workflows
2026-01-23 14:17:38 +01:00
dependabot[bot]
0e868c4570
build(deps): bump actions/checkout in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](https://github.com/actions/checkout/compare/v6.0.1...v6.0.2)

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

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

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

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

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

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

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-21 04:10:21 +00:00
Simon L.
f58465f930 DockeractionManager: rewrite PullImage function to re-try 3 times before failing
Signed-off-by: Simon L. <szaimen@e.mail.de>
2026-01-20 10:48:17 +01:00
dependabot[bot]
dbabfe14f0
build(deps): bump golang in /Containers/watchtower
Bumps golang from 1.25.5-alpine3.23 to 1.25.6-alpine3.23.

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

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

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

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

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
- uses: actions/setup-node@v6
with:

View file

@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
- uses: actions/setup-node@v6
with:

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

13
CODE_OF_CONDUCT.md Normal file
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

48
php/composer.lock generated
View file

@ -3111,20 +3111,20 @@
},
{
"name": "league/uri",
"version": "7.7.0",
"version": "7.8.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri.git",
"reference": "8d587cddee53490f9b82bf203d3a9aa7ea4f9807"
"reference": "4436c6ec8d458e4244448b069cc572d088230b76"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/uri/zipball/8d587cddee53490f9b82bf203d3a9aa7ea4f9807",
"reference": "8d587cddee53490f9b82bf203d3a9aa7ea4f9807",
"url": "https://api.github.com/repos/thephpleague/uri/zipball/4436c6ec8d458e4244448b069cc572d088230b76",
"reference": "4436c6ec8d458e4244448b069cc572d088230b76",
"shasum": ""
},
"require": {
"league/uri-interfaces": "^7.7",
"league/uri-interfaces": "^7.8",
"php": "^8.1",
"psr/http-factory": "^1"
},
@ -3138,11 +3138,11 @@
"ext-gmp": "to improve IPV4 host parsing",
"ext-intl": "to handle IDN host with the best performance",
"ext-uri": "to use the PHP native URI class",
"jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain",
"league/uri-components": "Needed to easily manipulate URI objects components",
"league/uri-polyfill": "Needed to backport the PHP URI extension for older versions of PHP",
"jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain",
"league/uri-components": "to provide additional tools to manipulate URI objects components",
"league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP",
"php-64bit": "to improve IPV4 host parsing",
"rowbot/url": "to handle WHATWG URL",
"rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
"symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
},
"type": "library",
@ -3197,7 +3197,7 @@
"docs": "https://uri.thephpleague.com",
"forum": "https://thephpleague.slack.com",
"issues": "https://github.com/thephpleague/uri-src/issues",
"source": "https://github.com/thephpleague/uri/tree/7.7.0"
"source": "https://github.com/thephpleague/uri/tree/7.8.0"
},
"funding": [
{
@ -3205,20 +3205,20 @@
"type": "github"
}
],
"time": "2025-12-07T16:02:06+00:00"
"time": "2026-01-14T17:24:56+00:00"
},
{
"name": "league/uri-interfaces",
"version": "7.7.0",
"version": "7.8.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/uri-interfaces.git",
"reference": "62ccc1a0435e1c54e10ee6022df28d6c04c2946c"
"reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/62ccc1a0435e1c54e10ee6022df28d6c04c2946c",
"reference": "62ccc1a0435e1c54e10ee6022df28d6c04c2946c",
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c5c5cd056110fc8afaba29fa6b72a43ced42acd4",
"reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4",
"shasum": ""
},
"require": {
@ -3231,7 +3231,7 @@
"ext-gmp": "to improve IPV4 host parsing",
"ext-intl": "to handle IDN host with the best performance",
"php-64bit": "to improve IPV4 host parsing",
"rowbot/url": "to handle WHATWG URL",
"rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
"symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
},
"type": "library",
@ -3281,7 +3281,7 @@
"docs": "https://uri.thephpleague.com",
"forum": "https://thephpleague.slack.com",
"issues": "https://github.com/thephpleague/uri-src/issues",
"source": "https://github.com/thephpleague/uri-interfaces/tree/7.7.0"
"source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.0"
},
"funding": [
{
@ -3289,7 +3289,7 @@
"type": "github"
}
],
"time": "2025-12-07T16:03:21+00:00"
"time": "2026-01-15T06:54:53+00:00"
},
{
"name": "netresearch/jsonmapper",
@ -3455,16 +3455,16 @@
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "6.0.0",
"version": "6.0.1",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "02600c041e7d0f4b7d1fe1d260565ec525472fa9"
"reference": "2f5cbed597cb261d1ea458f3da3a9ad32e670b1e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/02600c041e7d0f4b7d1fe1d260565ec525472fa9",
"reference": "02600c041e7d0f4b7d1fe1d260565ec525472fa9",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/2f5cbed597cb261d1ea458f3da3a9ad32e670b1e",
"reference": "2f5cbed597cb261d1ea458f3da3a9ad32e670b1e",
"shasum": ""
},
"require": {
@ -3514,9 +3514,9 @@
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/6.0.0"
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/6.0.1"
},
"time": "2026-01-07T20:22:53+00:00"
"time": "2026-01-20T15:30:42+00:00"
},
{
"name": "phpdocumentor/type-resolver",

View file

@ -1,148 +1,210 @@
<?php
declare(strict_types=1);
// increase memory limit to 2GB
ini_set('memory_limit', '2048M');
/**
* Entry point/Bootstrapper for the Nextcloud All-in-One Web UI & API.
* Initializes DI container, configures PHP, registers routes & middleware.
*/
// set max execution time to 2h just in case of a very slow internet connection
ini_set('max_execution_time', '7200');
// Log whole log messages
ini_set('log_errors_max_len', '0');
require __DIR__ . '/../vendor/autoload.php';
use DI\Container;
use Slim\Csrf\Guard;
use Slim\Factory\AppFactory;
use Slim\Routing\RouteCollectorProxy;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
require __DIR__ . '/../vendor/autoload.php';
//-------------------------------------------------
// Configuration Constants
//-------------------------------------------------
const AIO_MEMORY_LIMIT = '2048M';
const AIO_MAX_EXECUTION_TIME = '7200'; // (2h) in case of a very slow internet connection
const AIO_SESSION_MAX_LIFETIME = '86400'; // (24h)
const AIO_COOKIE_LIFETIME = '0'; // Auto logout on browser close
const AIO_LOG_ERRORS_MAX_LEN = '0'; // Log whole log messages
const AIO_TWIG_CACHE_PATH = false; // e.g., __DIR__ . '/../var/twig-cache'
const AIO_DISPLAY_ERRORS = false;
//-------------------------------------------------
// PHP Settings
//-------------------------------------------------
ini_set('memory_limit', AIO_MEMORY_LIMIT);
ini_set('max_execution_time', AIO_MAX_EXECUTION_TIME);
ini_set('session.cookie_lifetime', AIO_COOKIE_LIFETIME);
ini_set('session.gc_maxlifetime', AIO_SESSION_MAX_LIFETIME);
ini_set('log_errors_max_len', AIO_LOG_ERRORS_MAX_LEN);
//-------------------------------------------------
// Dependency Injection
//-------------------------------------------------
$container = \AIO\DependencyInjection::GetContainer();
AppFactory::setContainer($container);
// Session directory depends on application config:
$dataConst = $container->get(\AIO\Data\DataConst::class);
ini_set('session.save_path', $dataConst->GetSessionDirectory());
// Auto logout on browser close
ini_set('session.cookie_lifetime', '0');
# Keep session for 24h max
ini_set('session.gc_maxlifetime', '86400');
// Create app
AppFactory::setContainer($container);
//-------------------------------------------------
// Application Creation and Core Middleware
//-------------------------------------------------
$app = AppFactory::create();
$responseFactory = $app->getResponseFactory();
// Register Middleware On Container
$container->set(Guard::class, function () use ($responseFactory) {
// Register CSRF middleware (container-only)
$container->set(Guard::class, function () use ($responseFactory): Guard {
$guard = new Guard($responseFactory);
$guard->setPersistentTokenMode(true);
return $guard;
});
// Register Middleware To Be Executed On All Routes
session_start();
// Activate CSRF middleware for all routes
$app->add(Guard::class);
// Create Twig
$twig = Twig::create(__DIR__ . '/../templates/', ['cache' => false]);
// Setup and activate Twig middleware
$twig = Twig::create(__DIR__ . '/../templates/',
[ 'cache' => AIO_TWIG_CACHE_PATH ]
);
$app->add(TwigMiddleware::create($app, $twig));
// Add CSRF extension to Twig so templates can access CSRF tokens
$twig->addExtension(new \AIO\Twig\CsrfExtension($container->get(Guard::class)));
// Auth Middleware
// Establish and activate authentication middleware for all routes
$app->add(new \AIO\Middleware\AuthMiddleware($container->get(\AIO\Auth\AuthManager::class)));
// API
$app->post('/api/docker/watchtower', AIO\Controller\DockerController::class . ':StartWatchtowerContainer');
$app->get('/api/docker/getwatchtower', AIO\Controller\DockerController::class . ':StartWatchtowerContainer');
$app->post('/api/docker/start', AIO\Controller\DockerController::class . ':StartContainer');
$app->post('/api/docker/backup', AIO\Controller\DockerController::class . ':StartBackupContainerBackup');
$app->post('/api/docker/backup-check', AIO\Controller\DockerController::class . ':StartBackupContainerCheck');
$app->post('/api/docker/backup-list', AIO\Controller\DockerController::class . ':StartBackupContainerList');
$app->post('/api/docker/backup-check-repair', AIO\Controller\DockerController::class . ':StartBackupContainerCheckRepair');
$app->post('/api/docker/backup-test', AIO\Controller\DockerController::class . ':StartBackupContainerTest');
$app->post('/api/docker/restore', AIO\Controller\DockerController::class . ':StartBackupContainerRestore');
$app->post('/api/docker/stop', AIO\Controller\DockerController::class . ':StopContainer');
$app->get('/api/docker/logs', AIO\Controller\DockerController::class . ':GetLogs');
$app->post('/api/auth/login', AIO\Controller\LoginController::class . ':TryLogin');
$app->get('/api/auth/getlogin', AIO\Controller\LoginController::class . ':GetTryLogin');
$app->post('/api/auth/logout', AIO\Controller\LoginController::class . ':Logout');
$app->post('/api/configuration', \AIO\Controller\ConfigurationController::class . ':SetConfig');
//-------------------------------------------------
// API Routes
//-------------------------------------------------
$app->group('/api/docker', function (RouteCollectorProxy $group): void {
// Docker Container management
$group->post('/watchtower', AIO\Controller\DockerController::class . ':StartWatchtowerContainer');
$group->get('/getwatchtower', AIO\Controller\DockerController::class . ':StartWatchtowerContainer');
$group->post('/start', AIO\Controller\DockerController::class . ':StartContainer');
$group->post('/stop', AIO\Controller\DockerController::class . ':StopContainer');
$group->get('/logs', AIO\Controller\DockerController::class . ':GetLogs');
// Backups
$group->post('/backup', AIO\Controller\DockerController::class . ':StartBackupContainerBackup');
$group->post('/backup-check', AIO\Controller\DockerController::class . ':StartBackupContainerCheck');
$group->post('/backup-list', AIO\Controller\DockerController::class . ':StartBackupContainerList');
$group->post('/backup-check-repair', AIO\Controller\DockerController::class . ':StartBackupContainerCheckRepair');
$group->post('/backup-test', AIO\Controller\DockerController::class . ':StartBackupContainerTest');
$group->post('/restore', AIO\Controller\DockerController::class . ':StartBackupContainerRestore');
});
// Views
$app->get('/containers', function (Request $request, Response $response, array $args) use ($container) {
// Auth-related
$app->group('/api/auth', function (RouteCollectorProxy $group): void {
$group->post('/login', AIO\Controller\LoginController::class . ':TryLogin');
$group->get('/getlogin', AIO\Controller\LoginController::class . ':GetTryLogin');
$group->post('/logout', AIO\Controller\LoginController::class . ':Logout');
});
// Configuration endpoints
$app->post('/api/configuration', AIO\Controller\ConfigurationController::class . ':SetConfig');
//-------------------------------------------------
// Views Routes
//-------------------------------------------------
// Containers
$app->get('/containers', function (Request $request, Response $response, array $args) use ($container): Response {
$view = Twig::fromRequest($request);
$view->addExtension(new \AIO\Twig\ClassExtension());
/** @var \AIO\Data\ConfigurationManager $configurationManager */
$configurationManager = $container->get(\AIO\Data\ConfigurationManager::class);
/** @var \AIO\Docker\DockerActionManager $dockerActionManager */
$dockerActionManager = $container->get(\AIO\Docker\DockerActionManager::class);
/** @var \AIO\Controller\DockerController $dockerController */
$dockerController = $container->get(\AIO\Controller\DockerController::class);
// Ensure master container is attached to the required Docker network
$dockerActionManager->ConnectMasterContainerToNetwork();
// Ensure the domaincheck container is started for domain configuration validation
$dockerController->StartDomaincheckContainer();
// Check if bypass_mastercontainer_update is provided on the URL, a special developer mode to bypass a mastercontainer update and use local image.
// URL parameters
$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']);
$bypassMastercontainerUpdate = isset($params['bypass_mastercontainer_update']);
$bypassContainerUpdate = isset($params['bypass_container_update']);
$skipDomainValidation = isset($params['skip_domain_validation']);
return $view->render($response, 'containers.twig', [
// === Instance & Domain Information ===
'domain' => $configurationManager->GetDomain(),
'timezone' => $configurationManager->GetTimezone(),
'current_channel' => $dockerActionManager->GetCurrentChannel(),
// ---- Ports & Networking ----
'apache_port' => $configurationManager->GetApachePort(),
'talk_port' => $configurationManager->GetTalkPort(),
// ---- Containers & Status ----
'containers' => (new \AIO\ContainerDefinitionFetcher($configurationManager, $container))->FetchDefinition(),
'is_mastercontainer_update_available' => $bypassMastercontainerUpdate ? false : $dockerActionManager->IsMastercontainerUpdateAvailable(),
'was_start_button_clicked' => $configurationManager->wasStartButtonClicked(),
'has_update_available' => $dockerActionManager->isAnyUpdateAvailable(),
'automatic_updates' => $configurationManager->areAutomaticUpdatesEnabled(),
// ---- Backups ----
'borg_backup_host_location' => $configurationManager->GetBorgBackupHostLocation(),
'borg_remote_repo' => $configurationManager->GetBorgRemoteRepo(),
'borg_public_key' => $configurationManager->GetBorgPublicKey(),
'nextcloud_password' => $configurationManager->GetAndGenerateSecret('NEXTCLOUD_PASSWORD'),
'containers' => (new \AIO\ContainerDefinitionFetcher($container->get(\AIO\Data\ConfigurationManager::class), $container))->FetchDefinition(),
'borgbackup_password' => $configurationManager->GetAndGenerateSecret('BORGBACKUP_PASSWORD'),
'is_mastercontainer_update_available' => ( $bypass_mastercontainer_update ? false : $dockerActionManager->IsMastercontainerUpdateAvailable() ),
'has_backup_run_once' => $configurationManager->hasBackupRunOnce(),
'is_backup_container_running' => $dockerActionManager->isBackupContainerRunning(),
'backup_exit_code' => $dockerActionManager->GetBackupcontainerExitCode(),
'is_instance_restore_attempt' => $configurationManager->isInstanceRestoreAttempt(),
'borg_backup_mode' => $configurationManager->GetBackupMode(),
'was_start_button_clicked' => $configurationManager->wasStartButtonClicked(),
'has_update_available' => $dockerActionManager->isAnyUpdateAvailable(),
'last_backup_time' => $configurationManager->GetLastBackupTime(),
'backup_times' => $configurationManager->GetBackupTimes(),
'current_channel' => $dockerActionManager->GetCurrentChannel(),
'is_clamav_enabled' => $configurationManager->isClamavEnabled(),
'is_onlyoffice_enabled' => $configurationManager->isOnlyofficeEnabled(),
'is_collabora_enabled' => $configurationManager->isCollaboraEnabled(),
'is_talk_enabled' => $configurationManager->isTalkEnabled(),
'borg_restore_password' => $configurationManager->GetBorgRestorePassword(),
'daily_backup_time' => $configurationManager->GetDailyBackupTime(),
'is_daily_backup_running' => $configurationManager->isDailyBackupRunning(),
'timezone' => $configurationManager->GetTimezone(),
'skip_domain_validation' => $configurationManager->shouldDomainValidationBeSkipped($skip_domain_validation),
'talk_port' => $configurationManager->GetTalkPort(),
'collabora_dictionaries' => $configurationManager->GetCollaboraDictionaries(),
'collabora_additional_options' => $configurationManager->GetAdditionalCollaboraOptions(),
'automatic_updates' => $configurationManager->areAutomaticUpdatesEnabled(),
'is_backup_section_enabled' => $configurationManager->isBackupSectionEnabled(),
'is_imaginary_enabled' => $configurationManager->isImaginaryEnabled(),
'is_fulltextsearch_enabled' => $configurationManager->isFulltextsearchEnabled(),
'additional_backup_directories' => $configurationManager->GetAdditionalBackupDirectoriesString(),
// ---- Nextcloud and PHP Config ----
'nextcloud_password' => $configurationManager->GetAndGenerateSecret('NEXTCLOUD_PASSWORD'),
'nextcloud_datadir' => $configurationManager->GetNextcloudDatadirMount(),
'nextcloud_mount' => $configurationManager->GetNextcloudMount(),
'nextcloud_upload_limit' => $configurationManager->GetNextcloudUploadLimit(),
'nextcloud_max_time' => $configurationManager->GetNextcloudMaxTime(),
'nextcloud_memory_limit' => $configurationManager->GetNextcloudMemoryLimit(),
// ---- Feature/App Enablement ----
'is_clamav_enabled' => $configurationManager->isClamavEnabled(),
'is_onlyoffice_enabled' => $configurationManager->isOnlyofficeEnabled(),
'is_collabora_enabled' => $configurationManager->isCollaboraEnabled(),
'is_talk_enabled' => $configurationManager->isTalkEnabled(),
'is_backup_section_enabled' => $configurationManager->isBackupSectionEnabled(),
'is_imaginary_enabled' => $configurationManager->isImaginaryEnabled(),
'is_fulltextsearch_enabled' => $configurationManager->isFulltextsearchEnabled(),
'is_dri_device_enabled' => $configurationManager->isDriDeviceEnabled(),
'is_nvidia_gpu_enabled' => $configurationManager->isNvidiaGpuEnabled(),
'is_talk_recording_enabled' => $configurationManager->isTalkRecordingEnabled(),
'is_docker_socket_proxy_enabled' => $configurationManager->isDockerSocketProxyEnabled(),
'is_whiteboard_enabled' => $configurationManager->isWhiteboardEnabled(),
// ---- Integration-specific Customization ----
'collabora_dictionaries' => $configurationManager->GetCollaboraDictionaries(),
'collabora_additional_options' => $configurationManager->GetAdditionalCollaboraOptions(),
// ---- Community Containers ----
'community_containers' => $configurationManager->listAvailableCommunityContainers(),
'community_containers_enabled' => $configurationManager->GetEnabledCommunityContainers(),
'bypass_container_update' => $bypass_container_update,
// ---- Misc Flags ----
'skip_domain_validation' => $configurationManager->shouldDomainValidationBeSkipped($skipDomainValidation),
'bypass_container_update' => $bypassContainerUpdate,
]);
})->setName('profile');
$app->get('/login', function (Request $request, Response $response, array $args) use ($container) {
});
// Login
$app->get('/login', function (Request $request, Response $response, array $args) use ($container): Response {
$view = Twig::fromRequest($request);
/** @var \AIO\Docker\DockerActionManager $dockerActionManager */
$dockerActionManager = $container->get(\AIO\Docker\DockerActionManager::class);
@ -150,51 +212,46 @@ $app->get('/login', function (Request $request, Response $response, array $args)
'is_login_allowed' => $dockerActionManager->isLoginAllowed(),
]);
});
$app->get('/setup', function (Request $request, Response $response, array $args) use ($container) {
// Setup
$app->get('/setup', function (Request $request, Response $response, array $args) use ($container): Response {
$view = Twig::fromRequest($request);
/** @var \AIO\Data\Setup $setup */
$setup = $container->get(\AIO\Data\Setup::class);
if(!$setup->CanBeInstalled()) {
return $view->render(
$response,
'already-installed.twig'
);
if (!$setup->CanBeInstalled()) {
return $view->render($response, 'already-installed.twig');
}
return $view->render(
$response,
'setup.twig',
[
return $view->render($response, 'setup.twig', [
'password' => $setup->Setup(),
]
);
]);
});
// Auth Redirector
$app->get('/', function (\Psr\Http\Message\RequestInterface $request, Response $response, array $args) use ($container) {
//-------------------------------------------------
// Root Redirector
//-------------------------------------------------
$app->get('/', function (Request $request, Response $response, array $args) use ($container): Response {
/** @var \AIO\Auth\AuthManager $authManager */
$authManager = $container->get(\AIO\Auth\AuthManager::class);
/** @var \AIO\Data\Setup $setup */
$setup = $container->get(\AIO\Data\Setup::class);
if($setup->CanBeInstalled()) {
return $response
->withHeader('Location', 'setup')
->withStatus(302);
}
if($authManager->IsAuthenticated()) {
return $response
->withHeader('Location', 'containers')
->withStatus(302);
} else {
return $response
->withHeader('Location', 'login')
->withStatus(302);
if ($setup->CanBeInstalled()) {
return $response->withHeader('Location', 'setup')->withStatus(302);
}
if ($authManager->IsAuthenticated()) {
return $response->withHeader('Location', 'containers')->withStatus(302);
}
return $response->withHeader('Location', 'login')->withStatus(302);
});
$errorMiddleware = $app->addErrorMiddleware(false, true, true);
//-------------------------------------------------
// Error Middleware
//-------------------------------------------------
// TODO: Figure out why the default plain text renderer is being used by logging
// TODO: Change logging to not generate stack traces for 404s
// TODO: Change logging to log the path
$errorMiddleware = $app->addErrorMiddleware(AIO_DISPLAY_ERRORS, true, true);
$app->run();

View file

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

View file

@ -25,7 +25,7 @@ readonly class ContainerDefinitionFetcher {
$containers = $this->FetchDefinition();
foreach ($containers as $container) {
if ($container->GetIdentifier() === $id) {
if ($container->identifier === $id) {
return $container;
}
}

View file

@ -23,7 +23,7 @@ readonly class DockerController {
$container = $this->containerDefinitionFetcher->GetContainerById($id);
// Start all dependencies first and then itself
foreach($container->GetDependsOn() as $dependency) {
foreach($container->dependsOn as $dependency) {
$this->PerformRecursiveContainerStart($dependency, $pullImage);
}
@ -46,7 +46,7 @@ readonly class DockerController {
$container = $this->containerDefinitionFetcher->GetContainerById($id);
// Pull all dependencies first and then itself
foreach($container->GetDependsOn() as $dependency) {
foreach($container->dependsOn as $dependency) {
$this->PerformRecursiveImagePull($dependency);
}
@ -255,7 +255,7 @@ readonly class DockerController {
// We want to stop the Nextcloud container after 10s and not wait for the configured stop_grace_period
$this->dockerActionManager->StopContainer($container, $forceStopNextcloud);
}
foreach($container->GetDependsOn() as $dependency) {
foreach($container->dependsOn as $dependency) {
$this->PerformRecursiveContainerStop($dependency, $forceStopNextcloud);
}
}

View file

@ -36,15 +36,15 @@ readonly class DockerActionManager {
}
private function BuildImageName(Container $container): string {
$tag = $container->GetImageTag();
$tag = $container->imageTag;
if ($tag === '%AIO_CHANNEL%') {
$tag = $this->GetCurrentChannel();
}
return $container->GetContainerName() . ':' . $tag;
return $container->containerName . ':' . $tag;
}
public function GetContainerRunningState(Container $container): ContainerState {
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($container->GetIdentifier())));
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($container->identifier)));
try {
$response = $this->guzzleClient->get($url);
} catch (RequestException $e) {
@ -64,7 +64,7 @@ readonly class DockerActionManager {
}
public function GetContainerRestartingState(Container $container): ContainerState {
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($container->GetIdentifier())));
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($container->identifier)));
try {
$response = $this->guzzleClient->get($url);
} catch (RequestException $e) {
@ -84,16 +84,16 @@ readonly class DockerActionManager {
}
public function GetContainerUpdateState(Container $container): VersionState {
$tag = $container->GetImageTag();
$tag = $container->imageTag;
if ($tag === '%AIO_CHANNEL%') {
$tag = $this->GetCurrentChannel();
}
$runningDigests = $this->GetRepoDigestsOfContainer($container->GetIdentifier());
$runningDigests = $this->GetRepoDigestsOfContainer($container->identifier);
if ($runningDigests === null) {
return VersionState::Different;
}
$remoteDigest = $this->GetLatestDigestOfTag($container->GetContainerName(), $tag);
$remoteDigest = $this->GetLatestDigestOfTag($container->containerName, $tag);
if ($remoteDigest === null) {
return VersionState::Equal;
}
@ -112,8 +112,8 @@ readonly class DockerActionManager {
return $runningState;
}
$containerName = $container->GetIdentifier();
$internalPort = $container->GetInternalPort();
$containerName = $container->identifier;
$internalPort = $container->internalPorts;
if ($internalPort === '%APACHE_PORT%') {
$internalPort = $this->configurationManager->GetApachePort();
} elseif ($internalPort === '%TALK_PORT%') {
@ -134,7 +134,7 @@ readonly class DockerActionManager {
}
public function DeleteContainer(Container $container): void {
$url = $this->BuildApiUrl(sprintf('containers/%s?v=true', urlencode($container->GetIdentifier())));
$url = $this->BuildApiUrl(sprintf('containers/%s?v=true', urlencode($container->identifier)));
try {
$this->guzzleClient->delete($url);
} catch (RequestException $e) {
@ -166,17 +166,17 @@ readonly class DockerActionManager {
}
public function StartContainer(Container $container): void {
$url = $this->BuildApiUrl(sprintf('containers/%s/start', urlencode($container->GetIdentifier())));
$url = $this->BuildApiUrl(sprintf('containers/%s/start', urlencode($container->identifier)));
try {
$this->guzzleClient->post($url);
} catch (RequestException $e) {
throw new \Exception("Could not start container " . $container->GetIdentifier() . ": " . $e->getResponse()?->getBody()->getContents());
throw new \Exception("Could not start container " . $container->identifier . ": " . $e->getResponse()?->getBody()->getContents());
}
}
public function CreateVolumes(Container $container): void {
$url = $this->BuildApiUrl('volumes/create');
foreach ($container->GetVolumes()->GetVolumes() as $volume) {
foreach ($container->volumes->GetVolumes() as $volume) {
$forbiddenChars = [
'/',
];
@ -202,9 +202,9 @@ readonly class DockerActionManager {
public function CreateContainer(Container $container): void {
$volumes = [];
foreach ($container->GetVolumes()->GetVolumes() as $volume) {
foreach ($container->volumes->GetVolumes() as $volume) {
// // NEXTCLOUD_MOUNT gets added via bind-mount later on
// if ($container->GetIdentifier() === 'nextcloud-aio-nextcloud') {
// if ($container->identifier === 'nextcloud-aio-nextcloud') {
// if ($volume->name === $this->configurationManager->GetNextcloudMount()) {
// continue;
// }
@ -228,7 +228,7 @@ readonly class DockerActionManager {
$requestBody['HostConfig']['Binds'] = $volumes;
}
$aioVariables = $container->GetAioVariables()->GetVariables();
$aioVariables = $container->aioVariables->GetVariables();
foreach ($aioVariables as $variable) {
$config = $this->configurationManager->GetConfig();
$variable = $this->replaceEnvPlaceholders($variable);
@ -238,9 +238,9 @@ readonly class DockerActionManager {
sleep(1);
}
$envs = $container->GetEnvironmentVariables()->GetVariables();
$envs = $container->containerEnvironmentVariables->GetVariables();
// Special thing for the nextcloud container
if ($container->GetIdentifier() === 'nextcloud-aio-nextcloud') {
if ($container->identifier === 'nextcloud-aio-nextcloud') {
$envs[] = $this->GetAllNextcloudExecCommands();
}
foreach ($envs as $key => $env) {
@ -251,13 +251,13 @@ readonly class DockerActionManager {
$requestBody['Env'] = $envs;
}
$requestBody['HostConfig']['RestartPolicy']['Name'] = $container->GetRestartPolicy();
$requestBody['HostConfig']['RestartPolicy']['Name'] = $container->restartPolicy;
$requestBody['HostConfig']['ReadonlyRootfs'] = $container->GetReadOnlySetting();
$requestBody['HostConfig']['ReadonlyRootfs'] = $container->readOnlyRootFs;
$exposedPorts = [];
if ($container->GetInternalPort() !== 'host') {
foreach ($container->GetPorts()->GetPorts() as $value) {
if ($container->internalPorts !== 'host') {
foreach ($container->ports->GetPorts() as $value) {
$port = $value->port;
$protocol = $value->protocol;
if ($port === '%APACHE_PORT%') {
@ -279,7 +279,7 @@ readonly class DockerActionManager {
if (count($exposedPorts) > 0) {
$requestBody['ExposedPorts'] = $exposedPorts;
foreach ($container->GetPorts()->GetPorts() as $value) {
foreach ($container->ports->GetPorts() as $value) {
$port = $value->port;
$protocol = $value->protocol;
if ($port === '%APACHE_PORT%') {
@ -314,7 +314,7 @@ readonly class DockerActionManager {
}
$devices = [];
foreach ($container->GetDevices() as $device) {
foreach ($container->devices as $device) {
if ($device === '/dev/dri' && !$this->configurationManager->isDriDeviceEnabled()) {
continue;
}
@ -325,7 +325,7 @@ readonly class DockerActionManager {
$requestBody['HostConfig']['Devices'] = $devices;
}
if ($container->isNvidiaGpuEnabled() && $this->configurationManager->isNvidiaGpuEnabled()) {
if ($container->enableNvidiaGpu && $this->configurationManager->isNvidiaGpuEnabled()) {
$requestBody['HostConfig']['Runtime'] = 'nvidia';
$requestBody['HostConfig']['DeviceRequests'] = [
[
@ -336,13 +336,13 @@ readonly class DockerActionManager {
];
}
$shmSize = $container->GetShmSize();
$shmSize = $container->shmSize;
if ($shmSize > 0) {
$requestBody['HostConfig']['ShmSize'] = $shmSize;
}
$tmpfs = [];
foreach ($container->GetTmpfs() as $tmp) {
foreach ($container->tmpfs as $tmp) {
$mode = "";
if (str_contains($tmp, ':')) {
$mode = explode(':', $tmp)[1];
@ -354,9 +354,14 @@ readonly class DockerActionManager {
$requestBody['HostConfig']['Tmpfs'] = $tmpfs;
}
$requestBody['HostConfig']['Init'] = $container->GetInit();
$requestBody['HostConfig']['Init'] = $container->init;
$capAdds = $container->GetCapAdds();
$maxShutDownTime = $container->maxShutdownTime;
if ($maxShutDownTime > 0) {
$requestBody['StopTimeout'] = $maxShutDownTime;
}
$capAdds = $container->capAdd;
if (count($capAdds) > 0) {
$requestBody['HostConfig']['CapAdd'] = $capAdds;
}
@ -368,14 +373,14 @@ readonly class DockerActionManager {
// Disable SELinux for AIO containers so that it does not break them
$requestBody['HostConfig']['SecurityOpt'] = ["label:disable"];
if ($container->isApparmorUnconfined()) {
if ($container->apparmorUnconfined) {
$requestBody['HostConfig']['SecurityOpt'] = ["apparmor:unconfined", "label:disable"];
}
$mounts = [];
// Special things for the backup container which should not be exposed in the containers.json
if (str_starts_with($container->GetIdentifier(), 'nextcloud-aio-borgbackup')) {
if (str_starts_with($container->identifier, 'nextcloud-aio-borgbackup')) {
// Additional backup directories
foreach ($this->getAllBackupVolumes() as $additionalBackupVolumes) {
if ($additionalBackupVolumes !== '') {
@ -384,7 +389,7 @@ readonly class DockerActionManager {
}
// Make volumes read only in case of borgbackup container. The viewer makes them writeable
$isReadOnly = $container->GetIdentifier() === 'nextcloud-aio-borgbackup';
$isReadOnly = $container->identifier === 'nextcloud-aio-borgbackup';
foreach ($this->configurationManager->GetAdditionalBackupDirectoriesArray() as $additionalBackupDirectories) {
if ($additionalBackupDirectories !== '') {
@ -397,12 +402,12 @@ readonly class DockerActionManager {
}
// Special things for the talk container which should not be exposed in the containers.json
} elseif ($container->GetIdentifier() === 'nextcloud-aio-talk') {
} elseif ($container->identifier === 'nextcloud-aio-talk') {
// This is needed due to a bug in libwebsockets used in Janus which cannot handle unlimited ulimits
$requestBody['HostConfig']['Ulimits'] = [["Name" => "nofile", "Hard" => 200000, "Soft" => 200000]];
// // Special things for the nextcloud container which should not be exposed in the containers.json
// } elseif ($container->GetIdentifier() === 'nextcloud-aio-nextcloud') {
// foreach ($container->GetVolumes()->GetVolumes() as $volume) {
// } elseif ($container->identifier === 'nextcloud-aio-nextcloud') {
// foreach ($container->volumes->GetVolumes() as $volume) {
// if ($volume->name !== $this->configurationManager->GetNextcloudMount()) {
// continue;
// }
@ -410,11 +415,11 @@ readonly class DockerActionManager {
// }
// Special things for the caddy community container
} elseif ($container->GetIdentifier() === 'nextcloud-aio-caddy') {
} elseif ($container->identifier === 'nextcloud-aio-caddy') {
$requestBody['HostConfig']['ExtraHosts'] = ['host.docker.internal:host-gateway'];
// Special things for the collabora container which should not be exposed in the containers.json
} elseif ($container->GetIdentifier() === 'nextcloud-aio-collabora') {
} elseif ($container->identifier === 'nextcloud-aio-collabora') {
if (!$this->configurationManager->isSeccompDisabled()) {
// Load reference seccomp profile for collabora
$seccompProfile = (string)file_get_contents(DataConst::GetCollaboraSeccompProfilePath());
@ -434,12 +439,12 @@ readonly class DockerActionManager {
// All AIO-managed containers should not be updated externally via watchtower but gracefully by AIO's backup and update feature.
// Also DIUN should not send update notifications. See https://crazymax.dev/diun/providers/docker/#docker-labels
// Additionally set a default org.label-schema.vendor and com.docker.compose.project
$requestBody['Labels'] = ["com.centurylinklabs.watchtower.enable" => "false", "diun.enable" => "false", "org.label-schema.vendor" => "Nextcloud", "com.docker.compose.project" => "nextcloud-aio"];
$requestBody['Labels'] = ["com.centurylinklabs.watchtower.enable" => "false", "wud.watch" => "false", "diun.enable" => "false", "org.label-schema.vendor" => "Nextcloud", "com.docker.compose.project" => "nextcloud-aio"];
// Containers should have a fixed host name. See https://github.com/nextcloud/all-in-one/discussions/6589
$requestBody['Hostname'] = $container->GetIdentifier();
$requestBody['Hostname'] = $container->identifier;
$url = $this->BuildApiUrl('containers/create?name=' . $container->GetIdentifier());
$url = $this->BuildApiUrl('containers/create?name=' . $container->identifier);
try {
$this->guzzleClient->request(
'POST',
@ -449,18 +454,18 @@ readonly class DockerActionManager {
]
);
} catch (RequestException $e) {
throw new \Exception("Could not create container " . $container->GetIdentifier() . ": " . $e->getResponse()?->getBody()->getContents());
throw new \Exception("Could not create container " . $container->identifier . ": " . $e->getResponse()?->getBody()->getContents());
}
}
public function isRegistryReachable(Container $container): bool {
$tag = $container->GetImageTag();
$tag = $container->imageTag;
if ($tag === '%AIO_CHANNEL%') {
$tag = $this->GetCurrentChannel();
}
$remoteDigest = $this->GetLatestDigestOfTag($container->GetContainerName(), $tag);
$remoteDigest = $this->GetLatestDigestOfTag($container->containerName, $tag);
if ($remoteDigest === null) {
return false;
@ -472,7 +477,7 @@ readonly class DockerActionManager {
public function PullImage(Container $container, bool $pullImage = true): void {
// Skip database image pull if the last shutdown was not clean
if ($container->GetIdentifier() === 'nextcloud-aio-database') {
if ($container->identifier === 'nextcloud-aio-database') {
if ($this->GetDatabasecontainerExitCode() > 0) {
$pullImage = false;
error_log('Not pulling the latest database image because the container was not correctly shut down.');
@ -484,7 +489,7 @@ readonly class DockerActionManager {
if ($pullImage) {
if (!$this->isRegistryReachable($container)) {
$pullImage = false;
error_log('Not pulling the ' . $container->GetContainerName() . ' image for the ' . $container->GetIdentifier() . ' container because the registry does not seem to be reachable.');
error_log('Not pulling the ' . $container->containerName . ' image for the ' . $container->identifier . ' container because the registry does not seem to be reachable.');
}
}
@ -503,14 +508,24 @@ readonly class DockerActionManager {
} catch (\Throwable $e) {
$imageIsThere = false;
}
try {
$this->guzzleClient->post($url);
} catch (RequestException $e) {
$message = "Could not pull image " . $imageName . ": " . $e->getResponse()?->getBody()->getContents();
if ($imageIsThere === false) {
throw new \Exception($message);
} else {
error_log($message);
$maxRetries = 3;
for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
try {
$this->guzzleClient->post($url);
break;
} catch (RequestException $e) {
$message = "Could not pull image " . $imageName . " (attempt $attempt/$maxRetries): " . $e->getResponse()?->getBody()->getContents();
if ($attempt === $maxRetries) {
if ($imageIsThere === false) {
throw new \Exception($message);
} else {
error_log($message);
}
} else {
error_log($message . ' Retrying...');
sleep(1);
}
}
}
}
@ -598,7 +613,7 @@ readonly class DockerActionManager {
if ($container->GetUpdateState() === VersionState::Different) {
$updateAvailable = '1';
}
foreach ($container->GetDependsOn() as $dependency) {
foreach ($container->dependsOn as $dependency) {
$updateAvailable .= $this->isContainerUpdateAvailable($dependency);
}
return $updateAvailable;
@ -622,10 +637,10 @@ readonly class DockerActionManager {
$container = $this->containerDefinitionFetcher->GetContainerById($id);
$backupVolumes = '';
foreach ($container->GetBackupVolumes() as $backupVolume) {
foreach ($container->backupVolumes as $backupVolume) {
$backupVolumes .= $backupVolume . ' ';
}
foreach ($container->GetDependsOn() as $dependency) {
foreach ($container->dependsOn as $dependency) {
$backupVolumes .= $this->getBackupVolumes($dependency);
}
return $backupVolumes;
@ -641,10 +656,10 @@ readonly class DockerActionManager {
$container = $this->containerDefinitionFetcher->GetContainerById($id);
$nextcloudExecCommands = '';
foreach ($container->GetNextcloudExecCommands() as $execCommand) {
foreach ($container->nextcloudExecCommands as $execCommand) {
$nextcloudExecCommands .= $execCommand . PHP_EOL;
}
foreach ($container->GetDependsOn() as $dependency) {
foreach ($container->dependsOn as $dependency) {
$nextcloudExecCommands .= $this->GetNextcloudExecCommands($dependency);
}
return $nextcloudExecCommands;
@ -776,7 +791,7 @@ readonly class DockerActionManager {
public function sendNotification(Container $container, string $subject, string $message, string $file = '/notify.sh'): void {
if ($this->GetContainerStartingState($container) === ContainerState::Running) {
$containerName = $container->GetIdentifier();
$containerName = $container->identifier;
// schedule the exec
$url = $this->BuildApiUrl(sprintf('containers/%s/exec', urlencode($containerName)));
@ -901,14 +916,14 @@ readonly class DockerActionManager {
// Add a secondary alias for domaincheck container, to keep it as similar to actual apache controller as possible.
// If a reverse-proxy is relying on container name as hostname this allows it to operate as usual and still validate the domain
// The domaincheck container and apache container are never supposed to be active at the same time because they use the same APACHE_PORT anyway, so this doesn't add any new constraints.
$alias = ($container->GetIdentifier() === 'nextcloud-aio-domaincheck') ? 'nextcloud-aio-apache' : '';
$alias = ($container->identifier === 'nextcloud-aio-domaincheck') ? 'nextcloud-aio-apache' : '';
$this->ConnectContainerIdToNetwork($container->GetIdentifier(), $container->GetInternalPort(), alias: $alias);
$this->ConnectContainerIdToNetwork($container->identifier, $container->internalPorts, alias: $alias);
if ($container->GetIdentifier() === 'nextcloud-aio-apache' || $container->GetIdentifier() === 'nextcloud-aio-domaincheck') {
if ($container->identifier === 'nextcloud-aio-apache' || $container->identifier === 'nextcloud-aio-domaincheck') {
$apacheAdditionalNetwork = $this->configurationManager->GetApacheAdditionalNetwork();
if ($apacheAdditionalNetwork !== '') {
$this->ConnectContainerIdToNetwork($container->GetIdentifier(), $container->GetInternalPort(), $apacheAdditionalNetwork, false, $alias);
$this->ConnectContainerIdToNetwork($container->identifier, $container->internalPorts, $apacheAdditionalNetwork, false, $alias);
}
}
}
@ -917,9 +932,9 @@ readonly class DockerActionManager {
if ($forceStopContainer) {
$maxShutDownTime = 10;
} else {
$maxShutDownTime = $container->GetMaxShutdownTime();
$maxShutDownTime = $container->maxShutdownTime;
}
$url = $this->BuildApiUrl(sprintf('containers/%s/stop?t=%s', urlencode($container->GetIdentifier()), $maxShutDownTime));
$url = $this->BuildApiUrl(sprintf('containers/%s/stop?t=%s', urlencode($container->identifier), $maxShutDownTime));
try {
$this->guzzleClient->post($url);
} catch (RequestException $e) {

View file

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

View file

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

View file

@ -0,0 +1 @@
12.5.0