diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md
index b7808e1c..aca2e718 100644
--- a/.github/ISSUE_TEMPLATE/Bug_report.md
+++ b/.github/ISSUE_TEMPLATE/Bug_report.md
@@ -1,12 +1,15 @@
---
-name: 🐛 Bug report
-about: Help us improving by reporting a bug
+name: 🐛 Bug report - no questions and no support!
+about: Help us improving by reporting a bug - this category is not for questions and also not for support! Please use one of the options below for questions and support
labels: 0. Needs triage
---
@@ -27,4 +30,10 @@ labels: 0. Needs triage
#### Docker run command or docker-compose file that you used
-#### Other valuable info
+#### Output of `sudo docker logs nextcloud-aio-mastercontainer`
+
+#### Output of `sudo docker inspect nextcloud-aio-mastercontainer`
+
+#### Output of `sudo docker ps -a`
+
+#### Other valuable info
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index bb669bb6..72ae238a 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,14 +1,14 @@
blank_issues_enabled: false
contact_links:
+ - name: 📘 Documentation on Nextcloud AIO
+ url: https://github.com/nextcloud/all-in-one#faq
+ about: Please read the docs first before submitting any report or request!
+ - name: ⛑️ Questions and support
+ url: https://help.nextcloud.com/tag/aio
+ about: For questions, support and help
- name: 💡 Suggest a new feature or discuss one
url: https://github.com/nextcloud/all-in-one/discussions/categories/ideas
about: For new feature requests and discussion of existing ones
- - name: ❓ Questions on AIO
- url: https://github.com/nextcloud/all-in-one/discussions/categories/questions
- about: For questions regarding AIO
- - name: ⛑️ Community Support and Help
- url: https://help.nextcloud.com/tag/aio
- about: For other types of questions
- name: 💼 Nextcloud Enterprise
url: https://portal.nextcloud.com/
- about: If you are a Nextcloud Enterprise customer, or need Professional support, so it can be resolved directly by our dedicated engineers more quickly
\ No newline at end of file
+ about: If you are a Nextcloud Enterprise customer, or need Professional support, so it can be resolved directly by our dedicated engineers more quickly
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index dc4b2021..7fe1067e 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,22 +1,30 @@
version: 2
updates:
- package-ecosystem: "github-actions"
- directory: "/"
+ directory: ".github/workflows"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
+ rebase-strategy: "disabled"
+ labels:
+ - 3. to review
+ - dependencies
+ cooldown:
+ default-days: 7
- package-ecosystem: composer
directory: "/php/"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
+ rebase-strategy: "auto"
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directories:
+ - "/Containers/alpine"
- "/Containers/apache"
- "/Containers/borgbackup"
- "/Containers/clamav"
@@ -39,6 +47,7 @@ updates:
interval: "daily"
time: "04:00"
open-pull-requests-limit: 10
+ rebase-strategy: "disabled"
labels:
- 3. to review
- dependencies
@@ -48,6 +57,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"]
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 00000000..5d1441b4
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,5 @@
+
diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml
index eeaeb427..475940a9 100644
--- a/.github/workflows/codespell.yml
+++ b/.github/workflows/codespell.yml
@@ -12,9 +12,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code
- uses: actions/checkout@v4
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check spelling
- uses: codespell-project/actions-codespell@v2
+ uses: codespell-project/actions-codespell@8f01853be192eb0f849a5c7d721450e7a467c579 # v2
with:
check_filenames: true
check_hidden: true
diff --git a/.github/workflows/collabora.yml b/.github/workflows/collabora.yml
new file mode 100644
index 00000000..a61067f3
--- /dev/null
+++ b/.github/workflows/collabora.yml
@@ -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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ - name: Run collabora-profile-update
+ run: |
+ rm -f php/cool-seccomp-profile.json
+ wget https://raw.githubusercontent.com/CollaboraOnline/online/refs/heads/main/docker/cool-seccomp-profile.json
+ mv cool-seccomp-profile.json php/
+
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # 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
diff --git a/.github/workflows/community-containers.yml b/.github/workflows/community-containers.yml
index 2df5173d..5271bfa8 100644
--- a/.github/workflows/community-containers.yml
+++ b/.github/workflows/community-containers.yml
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
- uses: actions/checkout@v4
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Validate structure
run: |
CONTAINERS="$(find ./community-containers -mindepth 1 -maxdepth 1 -type d)"
diff --git a/.github/workflows/dependency-updates.yml b/.github/workflows/dependency-updates.yml
index b131ab58..3805a0d0 100644
--- a/.github/workflows/dependency-updates.yml
+++ b/.github/workflows/dependency-updates.yml
@@ -8,12 +8,12 @@ on:
jobs:
dependency_updates:
name: Run dependency update script
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: shivammathur/setup-php@v2
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ - uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2
with:
- php-version: 8.3
+ php-version: 8.4
extensions: apcu
- name: Run dependency update script
run: |
@@ -44,7 +44,7 @@ jobs:
)"
sed -i "s|pecl install APCu.*\;|pecl install APCu-$apcu_version\;|" ./Containers/mastercontainer/Dockerfile
- name: Create Pull Request
- uses: peter-evans/create-pull-request@v7
+ uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
commit-message: php dependency updates
signoff: true
diff --git a/.github/workflows/docker-lint.yml b/.github/workflows/docker-lint.yml
index b1a2cd87..3f09bb98 100644
--- a/.github/workflows/docker-lint.yml
+++ b/.github/workflows/docker-lint.yml
@@ -25,7 +25,7 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install hadolint
run: |
diff --git a/.github/workflows/fail-on-prerelease.yml b/.github/workflows/fail-on-prerelease.yml
new file mode 100644
index 00000000..a5b876c3
--- /dev/null
+++ b/.github/workflows/fail-on-prerelease.yml
@@ -0,0 +1,50 @@
+name: Block if prerelease is present
+
+on:
+ pull_request:
+
+permissions:
+ contents: read
+
+jobs:
+ check-latest-release:
+ runs-on: ubuntu-latest
+ steps:
+ - name: "Check latest published release isn't a prerelease"
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v6
+ with:
+ script: |
+ const tags = await github.rest.repos.listTags({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ per_page: 1
+ });
+
+ if (!tags.data || tags.data.length === 0) {
+ core.info('No tags found for this repository; skipping prerelease check.');
+ return;
+ }
+
+ const latestTag = tags.data[0].name;
+ core.info(`Latest tag found: ${latestTag}`);
+
+ try {
+ const { data } = await github.rest.repos.getReleaseByTag({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ tag: latestTag
+ });
+
+ if (data.prerelease) {
+ core.setFailed(`Release for tag ${latestTag} (${data.tag_name}) is a prerelease. Blocking merges to main as we need to wait for the prerelease to become stable.`);
+ } else {
+ core.info(`Release for tag ${latestTag} (${data.tag_name}) is not a prerelease.`);
+ }
+
+ } catch (err) {
+ if (err.status === 404) {
+ core.info(`No release found for tag ${latestTag}; skipping prerelease check.`);
+ } else {
+ throw err;
+ }
+ }
diff --git a/.github/workflows/helm-release.yml b/.github/workflows/helm-release.yml
index 1548cb2d..ba3b865d 100644
--- a/.github/workflows/helm-release.yml
+++ b/.github/workflows/helm-release.yml
@@ -13,10 +13,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Turnstyle
- uses: softprops/turnstyle@v2
+ uses: softprops/turnstyle@e565d2d86403c5d23533937e95980570545e5586 # v2
with:
continue-after-seconds: 180
env:
@@ -32,7 +32,7 @@ jobs:
# See https://github.com/helm/chart-releaser-action/issues/6
- name: Set up Helm
- uses: azure/setup-helm@v4
+ uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
with:
version: v3.6.3
@@ -41,7 +41,7 @@ jobs:
helm lint ./nextcloud-aio-helm-chart
- name: Run chart-releaser
- uses: helm/chart-releaser-action@v1.6.0
+ uses: helm/chart-releaser-action@cae68fefc6b5f367a0275617c9f83181ba54714f # v1.7.0
with:
mark_as_latest: false
charts_dir: .
diff --git a/.github/workflows/imaginary-update.yml b/.github/workflows/imaginary-update.yml
index 85c64a6e..05050a20 100644
--- a/.github/workflows/imaginary-update.yml
+++ b/.github/workflows/imaginary-update.yml
@@ -10,7 +10,7 @@ jobs:
name: update to latest imaginary commit on master branch
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Run imaginary-update
run: |
# Imaginary
@@ -22,7 +22,7 @@ jobs:
sed -i "s|^ENV IMAGINARY_HASH.*$|ENV IMAGINARY_HASH=$imaginary_version|" ./Containers/imaginary/Dockerfile
- name: Create Pull Request
- uses: peter-evans/create-pull-request@v7
+ uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
commit-message: imaginary-update automated change
signoff: true
diff --git a/.github/workflows/json-validator.yml b/.github/workflows/json-validator.yml
index 86e269e9..8c0a7f45 100644
--- a/.github/workflows/json-validator.yml
+++ b/.github/workflows/json-validator.yml
@@ -1,35 +1,37 @@
-name: Json Validator
-
-on:
- pull_request:
- paths:
- - '**.json'
- push:
- branches:
- - main
- paths:
- - '**.json'
-
-jobs:
- json-validator:
- name: Json Validator
- runs-on: ubuntu-latest
- steps:
- - name: Checkout code
- uses: actions/checkout@v4
- - name: Validate Json
- run: |
- sudo apt-get update
- sudo apt-get install python3-pip -y --no-install-recommends
- sudo pip3 install json-spec
- if ! json validate --schema-file=php/containers-schema.json --document-file=php/containers.json; then
- exit 1
- fi
- JSON_FILES="$(find ./community-containers -name '*.json')"
- mapfile -t JSON_FILES <<< "$JSON_FILES"
- for file in "${JSON_FILES[@]}"; do
- json validate --schema-file=php/containers-schema.json --document-file="$file" 2>&1 | tee -a ./json-validator.log
- done
- if grep -q "document does not validate with schema.\|invalid JSONFile" ./json-validator.log; then
- exit 1
- fi
+name: Json Validator
+
+on:
+ pull_request:
+ paths:
+ - '**.json'
+ push:
+ branches:
+ - main
+ paths:
+ - '**.json'
+
+jobs:
+ json-validator:
+ name: Json Validator
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ - name: Validate Json
+ run: |
+ sudo apt-get update
+ sudo apt-get install python3-venv -y --no-install-recommends
+ python3 -m venv venv
+ . venv/bin/activate
+ pip3 install json-spec
+ if ! json validate --schema-file=php/containers-schema.json --document-file=php/containers.json; then
+ exit 1
+ fi
+ JSON_FILES="$(find ./community-containers -name '*.json')"
+ mapfile -t JSON_FILES <<< "$JSON_FILES"
+ for file in "${JSON_FILES[@]}"; do
+ json validate --schema-file=php/containers-schema.json --document-file="$file" 2>&1 | tee -a ./json-validator.log
+ done
+ if grep -q "document does not validate with schema.\|invalid JSONFile" ./json-validator.log; then
+ exit 1
+ fi
diff --git a/.github/workflows/lint-helm.yml b/.github/workflows/lint-helm.yml
index 41779d5c..61e51450 100644
--- a/.github/workflows/lint-helm.yml
+++ b/.github/workflows/lint-helm.yml
@@ -11,12 +11,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Install Helm
- uses: azure/setup-helm@v4
+ uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
with:
version: v3.11.1
diff --git a/.github/workflows/lint-php.yml b/.github/workflows/lint-php.yml
index 69db96dd..c0d2d577 100644
--- a/.github/workflows/lint-php.yml
+++ b/.github/workflows/lint-php.yml
@@ -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
@@ -27,16 +30,18 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- php-versions: [ "8.3" ]
+ php-versions: [ "8.4" ]
name: php-lint
steps:
- name: Checkout
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ with:
+ persist-credentials: false
- name: Set up php ${{ matrix.php-versions }}
- uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # v2
+ uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2.36.0
with:
php-version: ${{ matrix.php-versions }}
coverage: none
diff --git a/.github/workflows/lint-yaml.yml b/.github/workflows/lint-yaml.yml
new file mode 100644
index 00000000..e36b8f4c
--- /dev/null
+++ b/.github/workflows/lint-yaml.yml
@@ -0,0 +1,42 @@
+# This workflow is provided via the organization template repository
+#
+# 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 YAML
+
+on:
+ pull_request:
+ paths:
+ - '**.yml'
+
+permissions:
+ contents: read
+
+jobs:
+ yaml-lint:
+ runs-on: ubuntu-latest
+
+ name: yaml
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.1
+ with:
+ persist-credentials: false
+
+ - name: GitHub action templates lint
+ uses: ibiqlik/action-yamllint@2576378a8e339169678f9939646ee3ee325e845c # v3.1.1
+ with:
+ file_or_dir: .github/workflows
+ config_data: |
+ line-length: warning
+
+ - name: Install the latest version of uv
+ uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
+
+ - name: Check GitHub actions
+ run: uvx zizmor --min-severity medium .github/workflows/*.yml
diff --git a/.github/workflows/lock-threads.yml b/.github/workflows/lock-threads.yml
index e4e2cc32..bda40ee2 100644
--- a/.github/workflows/lock-threads.yml
+++ b/.github/workflows/lock-threads.yml
@@ -14,7 +14,7 @@ jobs:
action:
runs-on: ubuntu-latest
steps:
- - uses: dessant/lock-threads@v5
+ - uses: dessant/lock-threads@7266a7ce5c1df01b1c6db85bf8cd86c737dadbe7 # v5
with:
issue-inactive-days: '14'
process-only: 'issues'
diff --git a/.github/workflows/nextcloud-update.yml b/.github/workflows/nextcloud-update.yml
index 4812a68c..b2475290 100644
--- a/.github/workflows/nextcloud-update.yml
+++ b/.github/workflows/nextcloud-update.yml
@@ -11,7 +11,7 @@ jobs:
name: Run nextcloud-update script
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Run nextcloud-update script
run: |
# Inspired by https://github.com/nextcloud/docker/blob/master/update.sh
@@ -51,7 +51,7 @@ jobs:
# Imagick
imagick_version="$(
- git ls-remote --tags https://github.com/Imagick/imagick.git \
+ git ls-remote --tags https://github.com/imagick/imagick.git \
| cut -d/ -f3 \
| grep -viE '[a-z]' \
| tr -d '^{}' \
@@ -79,7 +79,7 @@ jobs:
fi
- name: Create Pull Request
- uses: peter-evans/create-pull-request@v7
+ uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
commit-message: nextcloud-update automated change
signoff: true
diff --git a/.github/workflows/php-deprecation-detector.yml b/.github/workflows/php-deprecation-detector.yml
index aed16094..38b0fa8d 100644
--- a/.github/workflows/php-deprecation-detector.yml
+++ b/.github/workflows/php-deprecation-detector.yml
@@ -16,11 +16,11 @@ jobs:
name: PHP Deprecation Detector
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up php
- uses: shivammathur/setup-php@v2
+ uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2
with:
- php-version: 8.3
+ php-version: 8.4
extensions: apcu
coverage: none
diff --git a/.github/workflows/playwright-on-push.yml b/.github/workflows/playwright-on-push.yml
new file mode 100644
index 00000000..40277e57
--- /dev/null
+++ b/.github/workflows/playwright-on-push.yml
@@ -0,0 +1,123 @@
+name: Playwright Tests on push
+
+on:
+ pull_request:
+ paths:
+ - 'php/**'
+ push:
+ branches:
+ - main
+ paths:
+ - 'php/**'
+
+concurrency:
+ group: playwright-${{ github.head_ref || github.run_id }}
+ cancel-in-progress: true
+
+env:
+ BASE_URL: https://localhost:8080
+
+jobs:
+ test:
+ timeout-minutes: 60
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6
+ with:
+ node-version: lts/*
+
+ - name: Install dependencies
+ run: cd php/tests && npm ci
+
+ - name: Install Playwright Browsers
+ run: cd php/tests && npx playwright install --with-deps chromium
+
+ - name: Set up php 8.4
+ uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2.36.0
+ with:
+ extensions: apcu
+ php-version: 8.4
+ coverage: none
+ ini-file: development
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Adjust some things and fix permissions
+ run: |
+ cd php
+ rm -r ./data
+ rm -r ./session
+ composer install --no-dev
+ composer clear-cache
+ sudo chmod 777 -R ./
+
+ - name: Start fresh development server
+ run: |
+ docker rm --force nextcloud-aio-{mastercontainer,apache,notify-push,nextcloud,redis,database,domaincheck,whiteboard,imaginary,talk,collabora,borgbackup} || true
+ docker volume rm nextcloud_aio_{mastercontainer,apache,database,database_dump,nextcloud,nextcloud_data,redis,backup_cache,elasticsearch} || true
+ docker pull ghcr.io/nextcloud-releases/all-in-one:develop
+ docker run \
+ -d \
+ --init \
+ --name nextcloud-aio-mastercontainer \
+ --restart always \
+ --publish 8080:8080 \
+ --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
+ --volume ./php:/var/www/docker-aio/php \
+ --volume /var/run/docker.sock:/var/run/docker.sock:ro \
+ --env SKIP_DOMAIN_VALIDATION=true \
+ --env APACHE_PORT=11000 \
+ ghcr.io/nextcloud-releases/all-in-one:develop
+ echo Waiting for 10 seconds for the development container to start ...
+ sleep 10
+
+ - name: Run Playwright tests for initial setup
+ run: |
+ cd php/tests
+ export DEBUG=pw:api
+ if ! npx playwright test tests/initial-setup.spec.js; then
+ docker logs nextcloud-aio-mastercontainer
+ docker logs nextcloud-aio-borgbackup
+ exit 1
+ fi
+
+ - name: Start fresh development server
+ run: |
+ docker rm --force nextcloud-aio-{mastercontainer,apache,notify-push,nextcloud,redis,database,domaincheck,whiteboard,imaginary,talk,collabora,borgbackup} || true
+ docker volume rm nextcloud_aio_{mastercontainer,apache,database,database_dump,nextcloud,nextcloud_data,redis,backup_cache,elasticsearch} || true
+ docker run \
+ -d \
+ --init \
+ --name nextcloud-aio-mastercontainer \
+ --restart always \
+ --publish 8080:8080 \
+ --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
+ --volume ./php:/var/www/docker-aio/php \
+ --volume /var/run/docker.sock:/var/run/docker.sock:ro \
+ --env SKIP_DOMAIN_VALIDATION=false \
+ --env APACHE_PORT=11000 \
+ ghcr.io/nextcloud-releases/all-in-one:develop
+ echo Waiting for 10 seconds for the development container to start ...
+ sleep 10
+
+ - name: Run Playwright tests for backup restore
+ run: |
+ cd php/tests
+ export DEBUG=pw:api
+ if ! npx playwright test tests/restore-instance.spec.js; then
+ docker logs nextcloud-aio-mastercontainer
+ docker logs nextcloud-aio-borgbackup
+ exit 1
+ fi
+
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
+ if: ${{ !cancelled() }}
+ with:
+ name: playwright-report
+ path: php/tests/playwright-report/
+ retention-days: 14
+ overwrite: true
diff --git a/.github/workflows/playwright-on-workflow-dispatch.yml b/.github/workflows/playwright-on-workflow-dispatch.yml
new file mode 100644
index 00000000..6d2f6d32
--- /dev/null
+++ b/.github/workflows/playwright-on-workflow-dispatch.yml
@@ -0,0 +1,91 @@
+name: Playwright Tests
+
+on:
+ workflow_dispatch:
+
+env:
+ BASE_URL: https://localhost:8080
+
+jobs:
+ test:
+ timeout-minutes: 60
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6
+ with:
+ node-version: lts/*
+
+ - name: Install dependencies
+ run: cd php/tests && npm ci
+
+ - name: Install Playwright Browsers
+ run: cd php/tests && npx playwright install --with-deps chromium
+
+ - name: Start fresh development server
+ run: |
+ docker rm --force nextcloud-aio-{mastercontainer,apache,notify-push,nextcloud,redis,database,domaincheck,whiteboard,imaginary,talk,collabora,borgbackup} || true
+ docker volume rm nextcloud_aio_{mastercontainer,apache,database,database_dump,nextcloud,nextcloud_data,redis,backup_cache,elasticsearch} || true
+ docker pull ghcr.io/nextcloud-releases/all-in-one:develop
+ docker run \
+ -d \
+ --init \
+ --name nextcloud-aio-mastercontainer \
+ --restart always \
+ --publish 8080:8080 \
+ --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
+ --volume /var/run/docker.sock:/var/run/docker.sock:ro \
+ --env SKIP_DOMAIN_VALIDATION=true \
+ --env APACHE_PORT=11000 \
+ ghcr.io/nextcloud-releases/all-in-one:develop
+ echo Waiting for 10 seconds for the development container to start ...
+ sleep 10
+
+ - name: Run Playwright tests for initial setup
+ run: |
+ cd php/tests
+ export DEBUG=pw:api
+ if ! npx playwright test tests/initial-setup.spec.js; then
+ docker logs nextcloud-aio-mastercontainer
+ docker logs nextcloud-aio-borgbackup
+ exit 1
+ fi
+
+ - name: Start fresh development server
+ run: |
+ docker rm --force nextcloud-aio-{mastercontainer,apache,notify-push,nextcloud,redis,database,domaincheck,whiteboard,imaginary,talk,collabora,borgbackup} || true
+ docker volume rm nextcloud_aio_{mastercontainer,apache,database,database_dump,nextcloud,nextcloud_data,redis,backup_cache,elasticsearch} || true
+ docker run \
+ -d \
+ --init \
+ --name nextcloud-aio-mastercontainer \
+ --restart always \
+ --publish 8080:8080 \
+ --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
+ --volume /var/run/docker.sock:/var/run/docker.sock:ro \
+ --env SKIP_DOMAIN_VALIDATION=false \
+ --env APACHE_PORT=11000 \
+ ghcr.io/nextcloud-releases/all-in-one:develop
+ echo Waiting for 10 seconds for the development container to start ...
+ sleep 10
+
+ - name: Run Playwright tests for backup restore
+ run: |
+ cd php/tests
+ export DEBUG=pw:api
+ if ! npx playwright test tests/restore-instance.spec.js; then
+ docker logs nextcloud-aio-mastercontainer
+ docker logs nextcloud-aio-borgbackup
+ exit 1
+ fi
+
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
+ if: ${{ !cancelled() }}
+ with:
+ name: playwright-report
+ path: php/tests/playwright-report/
+ retention-days: 14
+ overwrite: true
diff --git a/.github/workflows/psalm-update-baseline.yml b/.github/workflows/psalm-update-baseline.yml
index f4bf7198..bcbb12c3 100644
--- a/.github/workflows/psalm-update-baseline.yml
+++ b/.github/workflows/psalm-update-baseline.yml
@@ -10,12 +10,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up php
- uses: shivammathur/setup-php@v2
+ uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2
with:
- php-version: 8.3
+ php-version: 8.4
extensions: apcu
coverage: none
@@ -30,7 +30,7 @@ jobs:
continue-on-error: true
- name: Create Pull Request
- uses: peter-evans/create-pull-request@v7
+ uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: Update psalm baseline
diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml
index e4775674..2bab876e 100644
--- a/.github/workflows/psalm.yml
+++ b/.github/workflows/psalm.yml
@@ -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@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ with:
+ persist-credentials: false
- name: Set up php
- uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # v2
+ uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2.36.0
with:
- php-version: 8.3
+ 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 }}
diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml
index 697b1807..b051c355 100644
--- a/.github/workflows/shellcheck.yml
+++ b/.github/workflows/shellcheck.yml
@@ -15,9 +15,9 @@ jobs:
name: Check Shell
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Run Shellcheck
- uses: ludeeus/action-shellcheck@2.0.0
+ uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0
with:
check_together: 'yes'
env:
diff --git a/.github/workflows/talk.yml b/.github/workflows/talk.yml
index ee366a64..b19e1cb5 100644
--- a/.github/workflows/talk.yml
+++ b/.github/workflows/talk.yml
@@ -10,7 +10,7 @@ jobs:
name: update talk
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Run talk-container-update
run: |
# Recording
@@ -36,7 +36,7 @@ jobs:
# Janus
janus_version="$(
- git ls-remote https://github.com/meetecho/janus-gateway v0.*.* \
+ git ls-remote https://github.com/meetecho/janus-gateway v1.*.* \
| cut -d/ -f3 \
| sort -V \
| grep -E "^v[0-9]+\.[0-9]+\.[0-9]+$" \
@@ -45,7 +45,7 @@ jobs:
sed -i "s|^ARG JANUS_VERSION=.*$|ARG JANUS_VERSION=$janus_version|" ./Containers/talk/Dockerfile
- name: Create Pull Request
- uses: peter-evans/create-pull-request@v7
+ uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
commit-message: talk-update automated change
signoff: true
diff --git a/.github/workflows/twig-lint.yml b/.github/workflows/twig-lint.yml
index 4544f993..27b8776d 100644
--- a/.github/workflows/twig-lint.yml
+++ b/.github/workflows/twig-lint.yml
@@ -24,12 +24,12 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@v4
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up php ${{ matrix.php-versions }}
- uses: shivammathur/setup-php@v2
+ uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2
with:
- php-version: 8.3
+ php-version: 8.4
extensions: apcu
coverage: none
diff --git a/.github/workflows/update-copyright.yml b/.github/workflows/update-copyright.yml
index fa00f9b1..103851c9 100644
--- a/.github/workflows/update-copyright.yml
+++ b/.github/workflows/update-copyright.yml
@@ -8,4 +8,4 @@ jobs:
name: update copyright
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
diff --git a/.github/workflows/update-helm.yml b/.github/workflows/update-helm.yml
index 43b37c8f..92cbb978 100644
--- a/.github/workflows/update-helm.yml
+++ b/.github/workflows/update-helm.yml
@@ -11,16 +11,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
- uses: actions/checkout@v4
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: update helm chart
run: |
- DOCKER_TAG="$(curl -L -s 'https://registry.hub.docker.com/v2/repositories/nextcloud/all-in-one/tags?page_size=1024' | jq '."results"[]["name"]' | sed 's|"||g' | grep '^20[0-9_]\+' | grep -v latest | sort -r | head -1)"
+ set -x
+ GHCR_TOKEN="$(curl https://ghcr.io/token?scope=repository:nextcloud-releases/nce-php-fpm-mgmt:pull | jq '.token' | sed 's|"||g')"
+ DOCKER_TAG="$(curl -H "Authorization: Bearer ${GHCR_TOKEN}" -L -s 'https://ghcr.io/v2/nextcloud-releases/all-in-one/tags/list?page_size=1024' | jq '.tags' | sed 's|"||g;s|[[:space:]]||g;s|,||g' | grep '^20[0-9_]\+' | grep -v latest | sort -r | head -1)"
export DOCKER_TAG
- if [ -n "$DOCKER_TAG" ] && ! grep -q "$DOCKER_TAG" ./nextcloud-aio-helm-chart/templates/nextcloud-aio-nextcloud-deployment.yaml; then
+ set +x
+ if [ -n "$DOCKER_TAG" ] && ! grep -q "aio-nextcloud:$DOCKER_TAG" ./nextcloud-aio-helm-chart/templates/nextcloud-aio-nextcloud-deployment.yaml; then
sudo bash nextcloud-aio-helm-chart/update-helm.sh "$DOCKER_TAG"
fi
- name: Create Pull Request
- uses: peter-evans/create-pull-request@v7
+ uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
commit-message: Helm Chart updates
signoff: true
diff --git a/.github/workflows/update-yaml.yml b/.github/workflows/update-yaml.yml
index 93a560fc..6e150261 100644
--- a/.github/workflows/update-yaml.yml
+++ b/.github/workflows/update-yaml.yml
@@ -11,12 +11,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
- uses: actions/checkout@v4
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: update yaml files
run: |
sudo bash manual-install/update-yaml.sh
- name: Create Pull Request
- uses: peter-evans/create-pull-request@v7
+ uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
commit-message: Yaml updates
signoff: true
diff --git a/.github/workflows/watchtower-update.yml b/.github/workflows/watchtower-update.yml
new file mode 100644
index 00000000..ecd82a69
--- /dev/null
+++ b/.github/workflows/watchtower-update.yml
@@ -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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ - 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@c0f553fe549906ede9cf27b5156039d195d2ece0 # 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
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..fec85a59
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,13 @@
+
+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.
diff --git a/Containers/alpine/Dockerfile b/Containers/alpine/Dockerfile
new file mode 100644
index 00000000..1098b4c4
--- /dev/null
+++ b/Containers/alpine/Dockerfile
@@ -0,0 +1,7 @@
+# syntax=docker/dockerfile:latest
+FROM alpine:3.23.3
+
+RUN set -ex; \
+ apk upgrade --no-cache -a
+
+LABEL org.label-schema.vendor="Nextcloud"
diff --git a/Containers/apache/Caddyfile b/Containers/apache/Caddyfile
index d635f329..4b92d807 100644
--- a/Containers/apache/Caddyfile
+++ b/Containers/apache/Caddyfile
@@ -15,6 +15,7 @@
}
https://{$ADDITIONAL_TRUSTED_DOMAIN}:443,
+http://{$APACHE_HOST}:23973, # For Collabora callback and WOPI requests, see containers.json
{$PROTOCOL}://{$NC_DOMAIN}:{$APACHE_PORT} {
header -Server
header -X-Powered-By
@@ -40,7 +41,7 @@ https://{$ADDITIONAL_TRUSTED_DOMAIN}:443,
route /onlyoffice/* {
uri strip_prefix /onlyoffice
reverse_proxy {$ONLYOFFICE_HOST}:80 {
- header_up X-Forwarded-Host {http.request.host}/onlyoffice
+ header_up X-Forwarded-Host {http.request.hostport}/onlyoffice
header_up X-Forwarded-Proto https
}
}
diff --git a/Containers/apache/Dockerfile b/Containers/apache/Dockerfile
index b118fd95..9ccadfb8 100644
--- a/Containers/apache/Dockerfile
+++ b/Containers/apache/Dockerfile
@@ -1,8 +1,8 @@
# syntax=docker/dockerfile:latest
-FROM caddy:2.8.4-alpine AS caddy
+FROM caddy:2.10.2-alpine AS caddy
# From https://github.com/docker-library/httpd/blob/master/2.4/alpine/Dockerfile
-FROM httpd:2.4.62-alpine3.20
+FROM httpd:2.4.66-alpine3.23
COPY --from=caddy /usr/bin/caddy /usr/bin/caddy
@@ -81,10 +81,12 @@ RUN set -ex; \
\
echo "root:$(openssl rand -base64 12)" | chpasswd
-USER www-data
+USER 33
ENTRYPOINT ["/start.sh"]
CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"]
HEALTHCHECK CMD /healthcheck.sh
-LABEL com.centurylinklabs.watchtower.enable="false"
+LABEL com.centurylinklabs.watchtower.enable="false" \
+ wud.watch="false" \
+ org.label-schema.vendor="Nextcloud"
diff --git a/Containers/apache/healthcheck.sh b/Containers/apache/healthcheck.sh
index 15235352..e9c1fad4 100644
--- a/Containers/apache/healthcheck.sh
+++ b/Containers/apache/healthcheck.sh
@@ -3,7 +3,3 @@
nc -z "$NEXTCLOUD_HOST" 9000 || exit 0
nc -z 127.0.0.1 8000 || exit 1
nc -z 127.0.0.1 "$APACHE_PORT" || exit 1
-if ! nc -z "$NC_DOMAIN" 443; then
- echo "Could not reach $NC_DOMAIN on port 443."
- exit 1
-fi
diff --git a/Containers/apache/start.sh b/Containers/apache/start.sh
index 9d69eb47..02a2f2ad 100644
--- a/Containers/apache/start.sh
+++ b/Containers/apache/start.sh
@@ -46,7 +46,9 @@ echo "$CADDYFILE" > /tmp/Caddyfile
# Change the trusted_proxies in case of reverse proxies
if [ "$APACHE_PORT" != '443' ]; then
- CADDYFILE="$(sed 's|# trusted_proxies placeholder|trusted_proxies static private_ranges|' /tmp/Caddyfile)"
+ # Here the 100.64.0.0/10 range gets added which is the CGNAT range used by Tailscale nodes
+ # See https://github.com/nextcloud/all-in-one/pull/6703 for reference
+ CADDYFILE="$(sed 's|# trusted_proxies placeholder|trusted_proxies static private_ranges 100.64.0.0/10|' /tmp/Caddyfile)"
else
CADDYFILE="$(sed "s|# trusted_proxies placeholder|trusted_proxies static $IPv4_ADDRESS|" /tmp/Caddyfile)"
fi
@@ -64,6 +66,11 @@ caddy fmt --overwrite /tmp/Caddyfile
# Add caddy path
mkdir -p /mnt/data/caddy/
+# Fix caddy startup
+if [ -d "/mnt/data/caddy/locks" ]; then
+ rm -rf /mnt/data/caddy/locks/*
+fi
+
# Fix apache startup
rm -f /usr/local/apache2/logs/httpd.pid
diff --git a/Containers/apache/supervisord.conf b/Containers/apache/supervisord.conf
index d6a93803..7ab935e4 100644
--- a/Containers/apache/supervisord.conf
+++ b/Containers/apache/supervisord.conf
@@ -9,8 +9,8 @@ logfile_backups=10
loglevel=error
[program:apache]
-# stdout_logfile=/dev/stdout
-# stdout_logfile_maxbytes=0
+# Stdout logging is disabled as otherwise the logs are spammed
+stdout_logfile=NONE
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
command=apachectl -DFOREGROUND
diff --git a/Containers/borgbackup/Dockerfile b/Containers/borgbackup/Dockerfile
index 2f54145f..6e3180cb 100644
--- a/Containers/borgbackup/Dockerfile
+++ b/Containers/borgbackup/Dockerfile
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
-FROM alpine:3.20.3
+FROM alpine:3.23.3
RUN set -ex; \
\
@@ -11,15 +11,19 @@ RUN set -ex; \
rsync \
fuse \
py3-llfuse \
- jq
+ jq \
+ openssh-client
VOLUME /root
COPY --chmod=770 *.sh /
+COPY borg_excludes /
ENTRYPOINT ["/start.sh"]
# hadolint ignore=DL3002
USER root
-LABEL com.centurylinklabs.watchtower.enable="false"
+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"
diff --git a/Containers/borgbackup/backupscript.sh b/Containers/borgbackup/backupscript.sh
index 739d5f16..b7b96147 100644
--- a/Containers/borgbackup/backupscript.sh
+++ b/Containers/borgbackup/backupscript.sh
@@ -34,19 +34,23 @@ for volume in "${DEFAULT_VOLUMES[@]}"; do
done
# Check if target is mountpoint
-if ! mountpoint -q /mnt/borgbackup; then
- echo "/mnt/borgbackup is not a mountpoint which is not allowed."
+if [ -z "$BORG_REMOTE_REPO" ] && ! mountpoint -q "$MOUNT_DIR"; then
+ echo "$MOUNT_DIR is not a mountpoint which is not allowed."
exit 1
fi
-# Check if target is empty
-if [ "$BORG_MODE" != backup ] && [ "$BORG_MODE" != test ] && ! [ -f "$BORG_BACKUP_DIRECTORY/config" ]; then
- echo "The repository is empty. Cannot perform check or restore."
+# Check if repo is uninitialized
+if [ "$BORG_MODE" != backup ] && [ "$BORG_MODE" != test ] && ! borg info > /dev/null; then
+ if [ -n "$BORG_REMOTE_REPO" ]; then
+ echo "The repository is uninitialized or cannot connect to remote. Cannot perform check or restore."
+ else
+ echo "The repository is uninitialized. Cannot perform check or restore."
+ fi
exit 1
fi
# Do not continue if this file exists (needed for simple external blocking)
-if [ -f "$BORG_BACKUP_DIRECTORY/aio-lockfile" ]; then
+if [ -z "$BORG_REMOTE_REPO" ] && [ -f "$BORG_BACKUP_DIRECTORY/aio-lockfile" ]; then
echo "Not continuing because aio-lockfile exists – it seems like a script is externally running which is locking the backup archive."
echo "If this should not be the case, you can fix this by deleting the 'aio-lockfile' file from the backup archive directory."
exit 1
@@ -57,6 +61,15 @@ if [ "$BORG_MODE" = backup ] || [ "$BORG_MODE" = restore ]; then
touch "/nextcloud_aio_volumes/nextcloud_aio_database_dump/backup-is-running"
fi
+if [ -n "$BORG_REMOTE_REPO" ] && ! [ -f "$BORGBACKUP_KEY" ]; then
+ echo "First run, creating borg ssh key"
+ ssh-keygen -f "$BORGBACKUP_KEY" -N ""
+ echo "You should configure the remote to accept this public key"
+fi
+if [ -n "$BORG_REMOTE_REPO" ] && [ -f "$BORGBACKUP_KEY.pub" ]; then
+ echo "Your public ssh key for borgbackup is: $(cat "$BORGBACKUP_KEY.pub")"
+fi
+
# Do the backup
if [ "$BORG_MODE" = backup ]; then
@@ -100,15 +113,22 @@ if [ "$BORG_MODE" = backup ]; then
exit 1
fi
- # Create backup folder
- mkdir -p "$BORG_BACKUP_DIRECTORY"
+ if [ -z "$BORG_REMOTE_REPO" ]; then
+ # Create backup folder
+ mkdir -p "$BORG_BACKUP_DIRECTORY"
+ fi
- # Initialize the repository if the target is empty
- if ! [ -f "$BORG_BACKUP_DIRECTORY/config" ]; then
+ # Initialize the repository if can't get info from target
+ if ! borg info > /dev/null; then
# Don't initialize if already initialized
if [ -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config" ]; then
- echo "No borg config file was found in the targeted directory."
- echo "This might happen if the targeted directory is located on an external drive and the drive not connected anymore. You should check this."
+ if [ -n "$BORG_REMOTE_REPO" ]; then
+ echo "Borg could not get info from the remote repo."
+ echo "This might be a failure to connect to the remote server. See the above borg info output for details."
+ else
+ echo "Borg could not get info from the targeted directory."
+ echo "This might happen if the targeted directory is located on an external drive and the drive not connected anymore. You should check this."
+ fi
echo "If you instead want to initialize a new backup repository, you may delete the 'borg.config' file that is stored in the mastercontainer volume manually, which will allow you to initialize a new borg repository in the chosen directory:"
echo "sudo docker exec nextcloud-aio-mastercontainer rm /mnt/docker-aio-config/data/borg.config"
exit 1
@@ -116,28 +136,39 @@ if [ "$BORG_MODE" = backup ]; then
echo "Initializing repository..."
NEW_REPOSITORY=1
- if ! borg init --debug --encryption=repokey-blake2 "$BORG_BACKUP_DIRECTORY"; then
+ if ! borg init --debug --encryption=repokey-blake2; then
echo "Could not initialize borg repository."
- rm -f "$BORG_BACKUP_DIRECTORY/config"
exit 1
fi
- borg config "$BORG_BACKUP_DIRECTORY" additional_free_space 2G
- # Fix too large Borg cache
- # https://borgbackup.readthedocs.io/en/stable/faq.html#the-borg-cache-eats-way-too-much-disk-space-what-can-i-do
- BORG_ID="$(borg config "$BORG_BACKUP_DIRECTORY" id)"
- rm -r "/root/.cache/borg/$BORG_ID/chunks.archive.d"
- touch "/root/.cache/borg/$BORG_ID/chunks.archive.d"
+ if [ -z "$BORG_REMOTE_REPO" ]; then
+ # borg config only works for local repos; it's up to the remote to ensure the disk isn't full
+ borg config :: additional_free_space 2G
- # Make a backup from the borg config file
- if ! [ -f "$BORG_BACKUP_DIRECTORY/config" ]; then
- echo "The borg config file wasn't created. Something is wrong."
+ # Fix too large Borg cache
+ # https://borgbackup.readthedocs.io/en/stable/faq.html#the-borg-cache-eats-way-too-much-disk-space-what-can-i-do
+ BORG_ID="$(borg config :: id)"
+ rm -r "/root/.cache/borg/$BORG_ID/chunks.archive.d"
+ touch "/root/.cache/borg/$BORG_ID/chunks.archive.d"
+ fi
+
+ if ! borg info > /dev/null; then
+ echo "Borg can't get info from the repo it created. Something is wrong."
exit 1
fi
+
rm -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config"
- if ! cp "$BORG_BACKUP_DIRECTORY/config" "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config"; then
- echo "Could not copy config file to second place. Cannot perform backup."
- exit 1
+ if [ -n "$BORG_REMOTE_REPO" ]; then
+ # `borg config` does not support remote repos so instead create a dummy file and rely on the remote to avoid
+ # corruption of the config file (which contains the encryption key). We don't actually use the contents of
+ # this file anywhere, so a touch is all we need so we remember we already initialized the repo.
+ touch "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config"
+ else
+ # Make a backup from the borg config file
+ if ! cp "$BORG_BACKUP_DIRECTORY/config" "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config"; then
+ echo "Could not copy config file to second place. Cannot perform backup."
+ exit 1
+ fi
fi
echo "Repository successfully initialized."
@@ -149,13 +180,27 @@ if [ "$BORG_MODE" = backup ]; then
# Borg options
# auto,zstd compression seems to has the best ratio based on:
# https://forum.level1techs.com/t/optimal-compression-for-borg-backups/145870/6
- BORG_OPTS=(-v --stats --compression "auto,zstd" --exclude-caches)
+ BORG_OPTS=(-v --stats --compression "auto,zstd")
if [ "$NEW_REPOSITORY" = 1 ]; then
BORG_OPTS+=(--progress)
fi
# Exclude the nextcloud log and audit log for GDPR reasons
- BORG_EXCLUDE=(--exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud/data/nextcloud.log*" --exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud/data/audit.log")
+ BORG_EXCLUDE=(--exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud/data/nextcloud.log*" --exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud/data/audit.log" --exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/lost+found")
+ BORG_INCLUDE=()
+
+ # Exclude datadir if .noaiobackup file was found
+ # shellcheck disable=SC2144
+ 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 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/")
+ BORG_INCLUDE+=(--pattern="+/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_*/preview/.noaiobackup")
+ echo "⚠️⚠️⚠️ '.noaiobackup' file was found in the preview directory. Excluding the preview directory from backup!"
+ fi
# Make sure that there is always a borg.config file before creating a new backup
if ! [ -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config" ]; then
@@ -167,9 +212,9 @@ if [ "$BORG_MODE" = backup ]; then
# Create the backup
echo "Starting the backup..."
get_start_time
- if ! borg create "${BORG_OPTS[@]}" "${BORG_EXCLUDE[@]}" "$BORG_BACKUP_DIRECTORY::$CURRENT_DATE-nextcloud-aio" "/nextcloud_aio_volumes/"; then
+ if ! borg create "${BORG_OPTS[@]}" "${BORG_INCLUDE[@]}" "${BORG_EXCLUDE[@]}" "::$CURRENT_DATE-nextcloud-aio" "/nextcloud_aio_volumes/" --exclude-from /borg_excludes; then
echo "Deleting the failed backup archive..."
- borg delete --stats "$BORG_BACKUP_DIRECTORY::$CURRENT_DATE-nextcloud-aio"
+ borg delete --stats "::$CURRENT_DATE-nextcloud-aio"
echo "Backup failed!"
echo "You might want to check the backup integrity via the AIO interface."
if [ "$NEW_REPOSITORY" = 1 ]; then
@@ -188,14 +233,14 @@ if [ "$BORG_MODE" = backup ]; then
# Prune archives
echo "Pruning the archives..."
- if ! borg prune --stats --glob-archives '*_*-nextcloud-aio' "${BORG_PRUNE_OPTS[@]}" "$BORG_BACKUP_DIRECTORY"; then
+ if ! borg prune --stats --glob-archives '*_*-nextcloud-aio' "${BORG_PRUNE_OPTS[@]}"; then
echo "Failed to prune archives!"
exit 1
fi
# Compact archives
echo "Compacting the archives..."
- if ! borg compact "$BORG_BACKUP_DIRECTORY"; then
+ if ! borg compact; then
echo "Failed to compact archives!"
exit 1
fi
@@ -212,19 +257,19 @@ if [ "$BORG_MODE" = backup ]; then
fi
done
echo "Starting the backup for additional volumes..."
- if ! borg create "${BORG_OPTS[@]}" "$BORG_BACKUP_DIRECTORY::$CURRENT_DATE-additional-docker-volumes" "/docker_volumes/"; then
+ if ! borg create "${BORG_OPTS[@]}" "::$CURRENT_DATE-additional-docker-volumes" "/docker_volumes/"; then
echo "Deleting the failed backup archive..."
- borg delete --stats "$BORG_BACKUP_DIRECTORY::$CURRENT_DATE-additional-docker-volumes"
+ borg delete --stats "::$CURRENT_DATE-additional-docker-volumes"
echo "Backup of additional docker-volumes failed!"
exit 1
fi
echo "Pruning additional volumes..."
- if ! borg prune --stats --glob-archives '*_*-additional-docker-volumes' "${BORG_PRUNE_OPTS[@]}" "$BORG_BACKUP_DIRECTORY"; then
+ if ! borg prune --stats --glob-archives '*_*-additional-docker-volumes' "${BORG_PRUNE_OPTS[@]}"; then
echo "Failed to prune additional docker-volumes archives!"
exit 1
fi
echo "Compacting additional volumes..."
- if ! borg compact "$BORG_BACKUP_DIRECTORY"; then
+ if ! borg compact; then
echo "Failed to compact additional docker-volume archives!"
exit 1
fi
@@ -242,19 +287,19 @@ if [ "$BORG_MODE" = backup ]; then
EXCLUDE_DIRS+=(--exclude "/host_mounts/$directory/")
done
echo "Starting the backup for additional host mounts..."
- if ! borg create "${BORG_OPTS[@]}" "${EXCLUDE_DIRS[@]}" "$BORG_BACKUP_DIRECTORY::$CURRENT_DATE-additional-host-mounts" "/host_mounts/"; then
+ if ! borg create "${BORG_OPTS[@]}" "${EXCLUDE_DIRS[@]}" "::$CURRENT_DATE-additional-host-mounts" "/host_mounts/"; then
echo "Deleting the failed backup archive..."
- borg delete --stats "$BORG_BACKUP_DIRECTORY::$CURRENT_DATE-additional-host-mounts"
+ borg delete --stats "::$CURRENT_DATE-additional-host-mounts"
echo "Backup of additional host-mounts failed!"
exit 1
fi
echo "Pruning additional host mounts..."
- if ! borg prune --stats --glob-archives '*_*-additional-host-mounts' "${BORG_PRUNE_OPTS[@]}" "$BORG_BACKUP_DIRECTORY"; then
+ if ! borg prune --stats --glob-archives '*_*-additional-host-mounts' "${BORG_PRUNE_OPTS[@]}"; then
echo "Failed to prune additional host-mount archives!"
exit 1
fi
echo "Compacting additional host mounts..."
- if ! borg compact "$BORG_BACKUP_DIRECTORY"; then
+ if ! borg compact; then
echo "Failed to compact additional host-mount archives!"
exit 1
fi
@@ -276,17 +321,38 @@ fi
if [ "$BORG_MODE" = restore ]; then
get_start_time
- # Perform the restore
+ # Pick archive to restore
if [ -n "$SELECTED_RESTORE_TIME" ]; then
- SELECTED_ARCHIVE="$(borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | grep "$SELECTED_RESTORE_TIME" | awk -F " " '{print $1}' | head -1)"
+ SELECTED_ARCHIVE="$(borg list | grep "nextcloud-aio" | grep "$SELECTED_RESTORE_TIME" | awk -F " " '{print $1}' | head -1)"
else
- SELECTED_ARCHIVE="$(borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | awk -F " " '{print $1}' | sort -r | head -1)"
+ SELECTED_ARCHIVE="$(borg list | grep "nextcloud-aio" | awk -F " " '{print $1}' | sort -r | head -1)"
fi
echo "Restoring '$SELECTED_ARCHIVE'..."
- mkdir -p /tmp/borg
- if ! borg mount "$BORG_BACKUP_DIRECTORY::$SELECTED_ARCHIVE" /tmp/borg; then
- echo "Could not mount the backup!"
- exit 1
+
+ ADDITIONAL_RSYNC_EXCLUDES=()
+ ADDITIONAL_BORG_EXCLUDES=()
+ ADDITIONAL_FIND_EXCLUDES=()
+ # Exclude datadir if .noaiobackup file was found
+ # shellcheck disable=SC2144
+ if [ -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/.noaiobackup" ]; then
+ # Keep these 3 in sync. Beware, the pattern syntax and the paths differ
+ 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 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"
+ # Exclude previews from restore if selected to speed up process or exclude preview folder if .noaiobackup file was found
+ elif [ -n "$RESTORE_EXCLUDE_PREVIEWS" ] || [ -f /nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_*/preview/.noaiobackup ]; then
+ # Keep these 3 in sync. Beware, the pattern syntax and the paths differ
+ ADDITIONAL_RSYNC_EXCLUDES=(--exclude "nextcloud_aio_nextcloud_data/appdata_*/preview/**")
+ ADDITIONAL_BORG_EXCLUDES=(--exclude "sh:nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_*/preview/**")
+ ADDITIONAL_FIND_EXCLUDES=(-o -regex 'nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_[^/]*/preview\(/.*\)?')
+ echo "⚠️⚠️⚠️ Excluding previews 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-app-data preview' after the restore."
+ echo "See https://github.com/nextcloud/all-in-one#how-to-run-occ-commands"
fi
# Save Additional Backup dirs
@@ -299,27 +365,12 @@ if [ "$BORG_MODE" = restore ]; then
DAILY_BACKUPTIME="$(cat /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/daily_backup_time)"
fi
- # Restore everything except the configuration file
- if ! rsync --stats --archive --human-readable -vv --delete \
- --exclude "nextcloud_aio_apache/caddy/**" \
- --exclude "nextcloud_aio_mastercontainer/caddy/**" \
- --exclude "nextcloud_aio_nextcloud/data/nextcloud.log*" \
- --exclude "nextcloud_aio_nextcloud/data/audit.log" \
- --exclude "nextcloud_aio_mastercontainer/certs/**" \
- --exclude "nextcloud_aio_mastercontainer/data/configuration.json" \
- --exclude "nextcloud_aio_mastercontainer/data/daily_backup_running" \
- --exclude "nextcloud_aio_mastercontainer/data/session_date_file" \
- --exclude "nextcloud_aio_mastercontainer/session/**" \
- /tmp/borg/nextcloud_aio_volumes/ /nextcloud_aio_volumes/; then
- RESTORE_FAILED=1
- echo "Something failed while restoring from backup."
- fi
-
# Save current aio password
AIO_PASSWORD="$(jq '.password' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
- # Save current path
+ # Save current backup location vars
BORG_LOCATION="$(jq '.borg_backup_host_location' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
+ REMOTE_REPO="$(jq '.borg_remote_repo' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
# Save current nextcloud datadir
if grep -q '"nextcloud_datadir":' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json; then
@@ -328,21 +379,116 @@ if [ "$BORG_MODE" = restore ]; then
NEXTCLOUD_DATADIR='""'
fi
- # Restore the configuration file
- if ! rsync --archive --human-readable -vv \
- /tmp/borg/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json \
- /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json; then
- RESTORE_FAILED=1
- echo "Something failed while restoring the configuration.json."
+ if [ -z "$BORG_REMOTE_REPO" ]; then
+ mkdir -p /tmp/borg
+ if ! borg mount "::$SELECTED_ARCHIVE" /tmp/borg; then
+ echo "Could not mount the backup!"
+ exit 1
+ fi
+
+ # Restore everything except the configuration file
+ #
+ # These exclude patterns need to be kept in sync with the borg_excludes file and the find excludes in this file,
+ # which use a different syntax (patterns appear in 3 places in total)
+ if ! rsync --stats --archive --human-readable -vv --delete \
+ --exclude "nextcloud_aio_apache/caddy/**" \
+ --exclude "nextcloud_aio_mastercontainer/caddy/**" \
+ --exclude "nextcloud_aio_nextcloud/data/nextcloud.log*" \
+ --exclude "nextcloud_aio_nextcloud/data/audit.log" \
+ --exclude "nextcloud_aio_mastercontainer/certs/**" \
+ --exclude "nextcloud_aio_mastercontainer/data/configuration.json" \
+ --exclude "nextcloud_aio_mastercontainer/data/daily_backup_running" \
+ --exclude "nextcloud_aio_mastercontainer/data/session_date_file" \
+ --exclude "nextcloud_aio_mastercontainer/session/**" \
+ --exclude "nextcloud_aio_nextcloud_data/lost+found" \
+ "${ADDITIONAL_RSYNC_EXCLUDES[@]}" \
+ /tmp/borg/nextcloud_aio_volumes/ /nextcloud_aio_volumes/; then
+ RESTORE_FAILED=1
+ echo "Something failed while restoring from backup."
+ fi
+
+ # Restore the configuration file
+ if ! rsync --archive --human-readable -vv \
+ /tmp/borg/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json \
+ /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json; then
+ RESTORE_FAILED=1
+ echo "Something failed while restoring the configuration.json."
+ fi
+
+ if ! umount /tmp/borg; then
+ echo "Failed to unmount the borg archive but should still be able to restore successfully"
+ fi
+ else
+ # Restore nearly everything
+ #
+ # borg mount is really slow for remote repos (did not check whether it's slow for local repos too),
+ # using extract to /tmp would require temporarily storing a second copy of the data.
+ # So instead extract directly on top of the destination with exclude patterns for the config, but
+ # then we do still need to delete local files which are not present in the archive.
+ #
+ # Older backups may still contain files we've since excluded, so we have to exclude on extract as well.
+ cd / # borg extract has no destination arg and extracts to CWD
+ if ! borg extract "::$SELECTED_ARCHIVE" --progress --exclude-from /borg_excludes "${ADDITIONAL_BORG_EXCLUDES[@]}" --pattern '+nextcloud_aio_volumes/**'
+ then
+ RESTORE_FAILED=1
+ echo "Failed to extract backup archive."
+ else
+ # Delete files/dirs present locally, but not in the backup archive, excluding conf files
+ # https://unix.stackexchange.com/a/759341
+ # This comm does not support -z, but I doubt any file names would have \n in them
+ #
+ # These find patterns need to be kept in sync with the borg_excludes file and the rsync excludes in this
+ # file, which use a different syntax (patterns appear in 3 places in total)
+ echo "Deleting local files which do not exist in the backup"
+ if ! find nextcloud_aio_volumes \
+ -not \( \
+ -path nextcloud_aio_volumes/nextcloud_aio_apache/caddy \
+ -o -path "nextcloud_aio_volumes/nextcloud_aio_apache/caddy/*" \
+ -o -path nextcloud_aio_volumes/nextcloud_aio_mastercontainer/caddy \
+ -o -path "nextcloud_aio_volumes/nextcloud_aio_mastercontainer/caddy/*" \
+ -o -path nextcloud_aio_volumes/nextcloud_aio_mastercontainer/certs \
+ -o -path "nextcloud_aio_volumes/nextcloud_aio_mastercontainer/certs/*" \
+ -o -path nextcloud_aio_volumes/nextcloud_aio_mastercontainer/session \
+ -o -path "nextcloud_aio_volumes/nextcloud_aio_mastercontainer/session/*" \
+ -o -path "nextcloud_aio_volumes/nextcloud_aio_nextcloud/data/nextcloud.log*" \
+ -o -path nextcloud_aio_volumes/nextcloud_aio_nextcloud/data/audit.log \
+ -o -path nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/daily_backup_running \
+ -o -path nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/session_date_file \
+ -o -path "nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/id_borg*" \
+ -o -path "nextcloud_aio_nextcloud_data/lost+found" \
+ "${ADDITIONAL_FIND_EXCLUDES[@]}" \
+ \) \
+ | LC_ALL=C sort \
+ | LC_ALL=C comm -23 - \
+ <(borg list "::$SELECTED_ARCHIVE" --short --exclude-from /borg_excludes --pattern '+nextcloud_aio_volumes/**' | LC_ALL=C sort) \
+ > /tmp/local_files_not_in_backup
+ then
+ RESTORE_FAILED=1
+ echo "Failed to delete local files not in backup archive."
+ else
+ # More robust than e.g. xargs as I got a ~"args line too long" error while testing that, but it's slower
+ # https://stackoverflow.com/a/21848934
+ while IFS= read -r file
+ do rm -vrf -- "$file" || DELETE_FAILED=1
+ done < /tmp/local_files_not_in_backup
+
+ if [ "$DELETE_FAILED" = 1 ]; then
+ RESTORE_FAILED=1
+ echo "Failed to delete (some) local files not in backup archive."
+ fi
+ fi
+ fi
fi
# Set backup-mode to restore since it was a restore
CONTENTS="$(jq '."backup-mode" = "restore"' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
echo -E "${CONTENTS}" > /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json
- # Reset the backup path to the currently used one
+ # Reset the backup location vars to the currently used one
CONTENTS="$(jq ".borg_backup_host_location = $BORG_LOCATION" /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
echo -E "${CONTENTS}" > /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json
+ CONTENTS="$(jq ".borg_remote_repo = $REMOTE_REPO" /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
+ echo -E "${CONTENTS}" > /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json
# Reset the AIO password to the currently used one
CONTENTS="$(jq ".password = $AIO_PASSWORD" /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
@@ -366,8 +512,6 @@ if [ "$BORG_MODE" = restore ]; then
chmod 770 "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/daily_backup_time"
fi
- umount /tmp/borg
-
if [ "$RESTORE_FAILED" = 1 ]; then
exit 1
fi
@@ -384,6 +528,12 @@ if [ "$BORG_MODE" = restore ]; then
touch "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/fingerprint.update"
chmod 777 "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/fingerprint.update"
+ # Add file to Netcloud container to trigger a preview scan the next time it starts
+ if [ -n "$RESTORE_EXCLUDE_PREVIEWS" ]; then
+ touch "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/trigger-preview.scan"
+ chmod 777 "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/trigger-preview.scan"
+ fi
+
# Delete redis cache
rm -f "/mnt/redis/dump.rdb"
fi
@@ -394,9 +544,9 @@ if [ "$BORG_MODE" = check ]; then
echo "Checking the backup integrity..."
# Perform the check
- if ! borg check -v --verify-data "$BORG_BACKUP_DIRECTORY"; then
+ if ! borg check -v --verify-data; then
echo "Some errors were found while checking the backup integrity!"
- echo "Check the AIO interface for advices on how to proceed now!"
+ echo "Check the AIO interface for advice on how to proceed now!"
exit 1
fi
@@ -412,7 +562,7 @@ if [ "$BORG_MODE" = "check-repair" ]; then
echo "Checking the backup integrity and repairing it..."
# Perform the check-repair
- if ! echo YES | borg check -v --repair "$BORG_BACKUP_DIRECTORY"; then
+ if ! echo YES | borg check -v --repair; then
echo "Some errors were found while checking and repairing the backup integrity!"
exit 1
fi
@@ -425,24 +575,49 @@ fi
# Do the backup test
if [ "$BORG_MODE" = test ]; then
- if ! [ -d "$BORG_BACKUP_DIRECTORY" ]; then
- echo "No 'borg' directory in the given backup directory found!"
- echo "Only the files/folders below have been found in the given directory."
- ls -a "$MOUNT_DIR"
- echo "Please adjust the directory so that the borg archive is positioned in a folder named 'borg' inside the given directory!"
- exit 1
- elif ! [ -f "$BORG_BACKUP_DIRECTORY/config" ]; then
- echo "A 'borg' directory was found but could not find the borg archive."
- echo "Only the files/folders below have been found in the borg directory."
- ls -a "$BORG_BACKUP_DIRECTORY"
- echo "The archive and most importantly the config file must be positioned directly in the 'borg' subfolder."
- exit 1
- elif ! borg list "$BORG_BACKUP_DIRECTORY"; then
+ if [ -n "$BORG_REMOTE_REPO" ]; then
+ if ! borg info > /dev/null; then
+ echo "Borg could not get info from the remote repo."
+ echo "See the above borg info output for details."
+ exit 1
+ fi
+ else
+ if ! [ -d "$BORG_BACKUP_DIRECTORY" ]; then
+ echo "No 'borg' directory in the given backup directory found!"
+ echo "Only the files/folders below have been found in the given directory."
+ ls -a "$MOUNT_DIR"
+ echo "Please adjust the directory so that the borg archive is positioned in a folder named 'borg' inside the given directory!"
+ exit 1
+ elif ! [ -f "$BORG_BACKUP_DIRECTORY/config" ]; then
+ echo "A 'borg' directory was found but could not find the borg archive."
+ echo "Only the files/folders below have been found in the borg directory."
+ ls -a "$BORG_BACKUP_DIRECTORY"
+ echo "The archive and most importantly the config file must be positioned directly in the 'borg' subfolder."
+ exit 1
+ fi
+ fi
+
+ if ! borg list >/dev/null; then
echo "The entered path seems to be valid but could not open the backup archive."
echo "Most likely the entered password was wrong so please adjust it accordingly!"
exit 1
else
- echo "Everything looks fine so feel free to continue!"
- exit 0
+ if ! borg list | grep "nextcloud-aio"; then
+ echo "The backup archive does not contain a valid Nextcloud AIO backup."
+ echo "Most likely was the archive not created via Nextcloud AIO."
+ exit 1
+ else
+ echo "Everything looks fine so feel free to continue!"
+ exit 0
+ fi
fi
fi
+
+if [ "$BORG_MODE" = list ]; then
+ echo "Updating backup list..."
+ if ! borg info > /dev/null; then
+ echo "Could not update the backup list."
+ exit 1
+ fi
+ # The update gets done automatically in the wrapper start.sh script.
+fi
diff --git a/Containers/borgbackup/borg_excludes b/Containers/borgbackup/borg_excludes
new file mode 100644
index 00000000..bbe6adaa
--- /dev/null
+++ b/Containers/borgbackup/borg_excludes
@@ -0,0 +1,11 @@
+# These patterns need to be kept in sync with rsync and find excludes in backupscript.sh,
+# which use a different syntax (patterns appear in 3 places in total)
+nextcloud_aio_volumes/nextcloud_aio_apache/caddy/
+nextcloud_aio_volumes/nextcloud_aio_mastercontainer/caddy/
+nextcloud_aio_volumes/nextcloud_aio_nextcloud/data/nextcloud.log*
+nextcloud_aio_volumes/nextcloud_aio_nextcloud/data/audit.log
+nextcloud_aio_volumes/nextcloud_aio_mastercontainer/certs/
+nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/daily_backup_running
+nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/session_date_file
+nextcloud_aio_volumes/nextcloud_aio_mastercontainer/session/
+nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/id_borg*
\ No newline at end of file
diff --git a/Containers/borgbackup/start.sh b/Containers/borgbackup/start.sh
index e8d93f58..bb7a8a6a 100644
--- a/Containers/borgbackup/start.sh
+++ b/Containers/borgbackup/start.sh
@@ -2,7 +2,7 @@
# Variables
export MOUNT_DIR="/mnt/borgbackup"
-export BORG_BACKUP_DIRECTORY="$MOUNT_DIR/borg"
+export BORG_BACKUP_DIRECTORY="$MOUNT_DIR/borg" # necessary even when remote to store the aio-lockfile
# Validate BORG_PASSWORD
if [ -z "$BORG_PASSWORD" ] && [ -z "$BACKUP_RESTORE_PASSWORD" ]; then
@@ -18,10 +18,22 @@ else
fi
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes
export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes
+if [ -n "$BORG_REMOTE_REPO" ]; then
+ export BORG_REPO="$BORG_REMOTE_REPO"
+
+ # Location to create the borg ssh pub/priv key
+ export BORGBACKUP_KEY="/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/id_borg"
+
+ # Accept any host key the first time connecting to the remote. Strictly speaking should be provided by user but you'd
+ # have to be very unlucky to get MitM'ed on your first connection.
+ export BORG_RSH="ssh -o StrictHostKeyChecking=accept-new -i $BORGBACKUP_KEY"
+else
+ export BORG_REPO="$BORG_BACKUP_DIRECTORY"
+fi
# Validate BORG_MODE
-if [ "$BORG_MODE" != backup ] && [ "$BORG_MODE" != restore ] && [ "$BORG_MODE" != check ] && [ "$BORG_MODE" != "check-repair" ] && [ "$BORG_MODE" != test ]; then
- echo "No correct BORG_MODE mode applied. Valid are 'backup', 'check', 'restore' and 'test'."
+if [ "$BORG_MODE" != backup ] && [ "$BORG_MODE" != restore ] && [ "$BORG_MODE" != check ] && [ "$BORG_MODE" != "check-repair" ] && [ "$BORG_MODE" != "test" ] && [ "$BORG_MODE" != "list" ]; then
+ echo "No correct BORG_MODE mode applied. Valid are 'backup', 'check', 'restore', 'test' and 'list'."
exit 1
fi
@@ -36,8 +48,8 @@ fi
rm -f "/nextcloud_aio_volumes/nextcloud_aio_database_dump/backup-is-running"
# Get a list of all available borg archives
-if borg list "$BORG_BACKUP_DIRECTORY" &>/dev/null; then
- borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | awk -F " " '{print $1","$3,$4}' > "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list"
+if borg list &>/dev/null; then
+ borg list | grep "nextcloud-aio" | awk -F " " '{print $1","$3,$4}' > "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list"
else
echo "" > "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list"
fi
diff --git a/Containers/clamav/Dockerfile b/Containers/clamav/Dockerfile
index 8deede4e..6910ae1c 100644
--- a/Containers/clamav/Dockerfile
+++ b/Containers/clamav/Dockerfile
@@ -1,26 +1,38 @@
# syntax=docker/dockerfile:latest
-# Probably from this file: https://github.com/Cisco-Talos/clamav-docker/blob/main/clamav/1.3/alpine/Dockerfile
-FROM clamav/clamav:1.4.1-8
-
-COPY clamav.conf /clamav.conf
-COPY --chmod=775 start.script /start.script
+FROM alpine:3.23.3
RUN set -ex; \
apk upgrade --no-cache -a; \
- apk add --no-cache tzdata bash; \
- mkdir -p /var/run/clamav /run/lock; \
- chown -R clamav:clamav /var/run/clamav /run/clamav /var/log/clamav /var/lock /run/lock; \
- chmod 777 -R /var/run/clamav /run/clamav /var/log/clamav /var/lock /run/lock /tmp; \
- sed -i "/^set -eu/r /start.script" /init-unprivileged; \
- rm /start.script; \
- grep -q 'clamd --foreground &' /init-unprivileged; \
- sed -i "s|clamd --foreground \&|clamd --foreground --config-file /tmp/clamd.conf \&|" /init-unprivileged; \
- cat /init-unprivileged
+ apk add --no-cache tzdata clamav clamav-milter supervisor bash; \
+ 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 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
+COPY --chmod=775 start.sh /start.sh
+COPY --chmod=775 healthcheck.sh /healthcheck.sh
+COPY --chmod=664 supervisord.conf /supervisord.conf
+
+USER 100
+RUN set -ex; \
+ freshclam --foreground --stdout
VOLUME /var/lib/clamav
-
-USER clamav
-
-LABEL com.centurylinklabs.watchtower.enable="false"
-
-ENTRYPOINT ["/init-unprivileged"]
+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
diff --git a/Containers/clamav/clamav.conf b/Containers/clamav/clamav.conf
deleted file mode 100644
index 0b781bd3..00000000
--- a/Containers/clamav/clamav.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-# AIO settings
-MaxDirectoryRecursion 30
-MaxFileSize 10G
-PCREMaxFileSize 10G
-StreamMaxLength 10G
diff --git a/Containers/clamav/healthcheck.sh b/Containers/clamav/healthcheck.sh
new file mode 100644
index 00000000..fe8b5daa
--- /dev/null
+++ b/Containers/clamav/healthcheck.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+if [ "$(echo "PING" | nc 127.0.0.1 3310)" != "PONG" ]; then
+ echo "ERROR: Unable to contact server"
+ exit 1
+fi
+
+echo "Clamd is up"
+exit 0
diff --git a/Containers/clamav/start.script b/Containers/clamav/start.script
deleted file mode 100644
index c9a530ab..00000000
--- a/Containers/clamav/start.script
+++ /dev/null
@@ -1,4 +0,0 @@
-# Adjust settings
-cat /etc/clamav/clamd.conf > /tmp/clamd.conf
-CLAMAV_FILE="$(sed "s|10G|$MAX_SIZE|" /clamav.conf)"
-echo "$CLAMAV_FILE" >> /tmp/clamd.conf
diff --git a/Containers/clamav/start.sh b/Containers/clamav/start.sh
new file mode 100644
index 00000000..609120c1
--- /dev/null
+++ b/Containers/clamav/start.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# Print out clamav version for compliance reasons
+clamscan --version
+
+echo "Clamav started"
+
+exec "$@"
diff --git a/Containers/clamav/supervisord.conf b/Containers/clamav/supervisord.conf
new file mode 100644
index 00000000..1895ceb6
--- /dev/null
+++ b/Containers/clamav/supervisord.conf
@@ -0,0 +1,30 @@
+[supervisord]
+nodaemon=true
+nodaemon=true
+logfile=/var/log/supervisord/supervisord.log
+pidfile=/var/run/supervisord/supervisord.pid
+childlogdir=/var/log/supervisord/
+logfile_maxbytes=50MB
+logfile_backups=10
+loglevel=error
+
+[program:freshclam]
+stdout_logfile=/dev/stdout
+stdout_logfile_maxbytes=0
+stderr_logfile=/dev/stderr
+stderr_logfile_maxbytes=0
+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=/etc/clamav/clamd.conf
+
+[program:milter]
+stdout_logfile=/dev/stdout
+stdout_logfile_maxbytes=0
+stderr_logfile=/dev/stderr
+stderr_logfile_maxbytes=0
+command=clamav-milter --config-file=/etc/clamav/clamav-milter.conf
\ No newline at end of file
diff --git a/Containers/collabora-online/Dockerfile b/Containers/collabora-online/Dockerfile
new file mode 100644
index 00000000..ec8b63f0
--- /dev/null
+++ b/Containers/collabora-online/Dockerfile
@@ -0,0 +1,16 @@
+# 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" \
+ wud.watch="false" \
+ org.label-schema.vendor="Nextcloud"
diff --git a/Containers/collabora-online/healthcheck.sh b/Containers/collabora-online/healthcheck.sh
new file mode 100644
index 00000000..45e9278b
--- /dev/null
+++ b/Containers/collabora-online/healthcheck.sh
@@ -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
diff --git a/Containers/collabora/Dockerfile b/Containers/collabora/Dockerfile
index 2c0fcad8..d1693da0 100644
--- a/Containers/collabora/Dockerfile
+++ b/Containers/collabora/Dockerfile
@@ -1,21 +1,15 @@
# syntax=docker/dockerfile:latest
-# From a file located probably somewhere here: https://github.com/CollaboraOnline/online/tree/master/docker
-FROM collabora/code:24.04.8.2.1
+# From a file located probably somewhere here: https://github.com/CollaboraOnline/online/blob/master/docker/from-packages/Dockerfile
+FROM collabora/code:25.04.8.2.1
USER root
ARG DEBIAN_FRONTEND=noninteractive
-# hadolint ignore=DL3008
-RUN set -ex; \
- \
- apt-get update; \
- apt-get install -y --no-install-recommends \
- tzdata \
- netcat-openbsd \
- ; \
- rm -rf /var/lib/apt/lists/*;
+COPY --chmod=775 healthcheck.sh /healthcheck.sh
-USER 100
+USER 1001
-HEALTHCHECK CMD nc -z 127.0.0.1 9980 || exit 1
-LABEL com.centurylinklabs.watchtower.enable="false"
+HEALTHCHECK --start-period=60s --retries=9 CMD /healthcheck.sh
+LABEL com.centurylinklabs.watchtower.enable="false" \
+ wud.watch="false" \
+ org.label-schema.vendor="Nextcloud"
diff --git a/Containers/collabora/healthcheck.sh b/Containers/collabora/healthcheck.sh
new file mode 100644
index 00000000..45e9278b
--- /dev/null
+++ b/Containers/collabora/healthcheck.sh
@@ -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
diff --git a/Containers/docker-socket-proxy/Dockerfile b/Containers/docker-socket-proxy/Dockerfile
index a6e2a10c..ffc867a8 100644
--- a/Containers/docker-socket-proxy/Dockerfile
+++ b/Containers/docker-socket-proxy/Dockerfile
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
-FROM haproxy:3.0.5-alpine
+FROM haproxy:3.3.2-alpine
# hadolint ignore=DL3002
USER root
@@ -18,4 +18,6 @@ COPY --chmod=664 haproxy.cfg /haproxy.cfg
ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD /healthcheck.sh
-LABEL com.centurylinklabs.watchtower.enable="false"
+LABEL com.centurylinklabs.watchtower.enable="false" \
+ wud.watch="false" \
+ org.label-schema.vendor="Nextcloud"
diff --git a/Containers/docker-socket-proxy/haproxy.cfg b/Containers/docker-socket-proxy/haproxy.cfg
index 66a0c594..632df434 100644
--- a/Containers/docker-socket-proxy/haproxy.cfg
+++ b/Containers/docker-socket-proxy/haproxy.cfg
@@ -4,16 +4,18 @@ global
maxconn 10
defaults
- timeout connect 10s
- timeout client 10s
- timeout server 10s
+ timeout connect 30s
+ timeout client 30s
+ timeout server 1800s
frontend http
mode http
bind :::2375 v4v6
http-request deny unless { src 127.0.0.1 } || { src ::1 } || { src NC_IPV4_PLACEHOLDER } || { src NC_IPV6_PLACEHOLDER }
# docker system _ping
- http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/_ping } METH_GET
+ http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/_ping$ } METH_GET
+ # docker inspect image: GET images/%s/json
+ http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/images/.*/json } METH_GET
# container inspect: GET containers/%s/json
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/nc_app_[a-zA-Z0-9_.-]+/json } METH_GET
# container inspect: GET containers/%s/logs
@@ -22,7 +24,12 @@ frontend http
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/nc_app_[a-zA-Z0-9_.-]+/((start)|(stop)) } METH_POST
# container rm: DELETE containers/%s
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/nc_app_[a-zA-Z0-9_.-]+ } METH_DELETE
-
+ # container update/exec: POST containers/%s/update containers/%s/exec
+ http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/nc_app_[a-zA-Z0-9_.-]+/((update)|(exec)) } METH_POST
+ # container put: PUT containers/%s/archive
+ http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/nc_app_[a-zA-Z0-9_.-]+/archive } METH_PUT
+ # run exec instance: POST exec/%s
+ http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/exec/[a-zA-Z0-9_.-]+/start } METH_POST
# container create: POST containers/create?name=%s
# ACL to restrict container name to nc_app_[a-zA-Z0-9_.-]+
@@ -33,19 +40,19 @@ frontend http
# ACL to deny if there are any binds
acl binds_present req.body -m reg -i "\"HostConfig\"\s*:.*\"Binds\"\s*:"
# ACL to restrict the type of Mounts to volume
- acl type_not_volume req.body -m reg -i "\"Mounts\":\s*\[[^\]]*(\"Type\":\s*\"(?!volume\b)\w+\"[^\]]*)+\]"
+ acl type_not_volume req.body -m reg -i "\"Mounts\"\s*:\s*\[[^\]]*(\"Type\"\s*:\s*\"(?!volume\b)\w+\"[^\]]*)+\]"
http-request deny if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/create } nc_app_container_name !one_mount_volume binds_present type_not_volume METH_POST
- # ACL to restrict container creation, that it has HostConfig.Privileged not set
- acl no_privileged_flag req.body -m reg -i "\"HostConfig\":\s?{[^}]*\"Privileged\""
+ # ACL to restrict container creation, that it has HostConfig.Privileged(by searching for "Privileged" word in all payload)
+ acl no_privileged_flag req.body -m reg -i "\"Privileged\""
# ACL to allow mount volume with strict pattern for name: nc_app_[a-zA-Z0-9_.-]+_data
- acl nc_app_volume_data_only req.body -m reg -i "\"Mounts\":\s?\[\s?{[^}]*\"Source\":\s?\"nc_app_[a-zA-Z0-9_.-]+_data\""
+ acl nc_app_volume_data_only req.body -m reg -i "\"Mounts\"\s*:\s*\[\s*{[^}]*\"Source\"\s*:\s*\"nc_app_[a-zA-Z0-9_.-]+_data\""
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/create } nc_app_container_name !no_privileged_flag nc_app_volume_data_only METH_POST
# end of container create
# volume create: POST volumes/create
# restrict name
- acl nc_app_volume_data req.body -m reg -i "\"Name\":\s?\"nc_app_[a-zA-Z0-9_.-]+_data\""
+ acl nc_app_volume_data req.body -m reg -i "\"Name\"\s*:\s*\"nc_app_[a-zA-Z0-9_.-]+_data\""
# do not allow to use "device" word e.g., "--opt device=:/path/to/dir"
acl volume_no_device req.body -m reg -i "\"device\""
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/volumes/create } nc_app_volume_data !volume_no_device METH_POST
diff --git a/Containers/domaincheck/Dockerfile b/Containers/domaincheck/Dockerfile
index 130a0001..374aba4a 100644
--- a/Containers/domaincheck/Dockerfile
+++ b/Containers/domaincheck/Dockerfile
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
-FROM alpine:3.20.3
+FROM alpine:3.23.3
RUN set -ex; \
apk upgrade --no-cache -a; \
apk add --no-cache bash lighttpd netcat-openbsd; \
@@ -17,4 +17,6 @@ USER www-data
ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD nc -z 127.0.0.1 $APACHE_PORT || exit 1
-LABEL com.centurylinklabs.watchtower.enable="false"
+LABEL com.centurylinklabs.watchtower.enable="false" \
+ wud.watch="false" \
+ org.label-schema.vendor="Nextcloud"
diff --git a/Containers/fulltextsearch/Dockerfile b/Containers/fulltextsearch/Dockerfile
index 873e9ba9..ff1e923f 100644
--- a/Containers/fulltextsearch/Dockerfile
+++ b/Containers/fulltextsearch/Dockerfile
@@ -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.15.2
+FROM elasticsearch:8.19.10
USER root
@@ -14,10 +14,14 @@ RUN set -ex; \
apt-get install -y --no-install-recommends \
tzdata \
; \
- rm -rf /var/lib/apt/lists/*; \
- elasticsearch-plugin install --batch ingest-attachment
+ rm -rf /var/lib/apt/lists/*;
+
+COPY --chmod=775 healthcheck.sh /healthcheck.sh
USER 1000:0
-HEALTHCHECK CMD nc -z 127.0.0.1 9200 || exit 1
-LABEL com.centurylinklabs.watchtower.enable="false"
+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"
diff --git a/Containers/fulltextsearch/healthcheck.sh b/Containers/fulltextsearch/healthcheck.sh
new file mode 100644
index 00000000..5e888ea6
--- /dev/null
+++ b/Containers/fulltextsearch/healthcheck.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+nc -z 127.0.0.1 9200 || exit 1
diff --git a/Containers/imaginary/Dockerfile b/Containers/imaginary/Dockerfile
index f07bb428..b108ac18 100644
--- a/Containers/imaginary/Dockerfile
+++ b/Containers/imaginary/Dockerfile
@@ -1,9 +1,10 @@
# syntax=docker/dockerfile:latest
-FROM golang:1.23.2-alpine3.20 AS go
+FROM golang:1.25.6-alpine3.23 AS go
-ENV IMAGINARY_HASH=8f36a26c448be8c151a3878404b75fcd1cd3cf0c
+ENV IMAGINARY_HASH=6a274b488759a896aff02f52afee6e50b5e3a3ee
RUN set -ex; \
+ apk upgrade --no-cache -a; \
apk add --no-cache \
vips-dev \
vips-magick \
@@ -13,7 +14,7 @@ RUN set -ex; \
build-base; \
go install github.com/h2non/imaginary@"$IMAGINARY_HASH";
-FROM alpine:3.20.3
+FROM alpine:3.23.3
RUN set -ex; \
apk upgrade --no-cache -a; \
apk add --no-cache \
@@ -30,14 +31,17 @@ RUN set -ex; \
COPY --from=go /go/bin/imaginary /usr/local/bin/imaginary
COPY --chmod=775 start.sh /start.sh
+COPY --chmod=775 healthcheck.sh /healthcheck.sh
ENV PORT=9000
-USER nobody
+USER 65534
# https://github.com/h2non/imaginary#memory-issues
ENV MALLOC_ARENA_MAX=2
ENTRYPOINT ["/start.sh"]
-HEALTHCHECK CMD nc -z 127.0.0.1 "$PORT" || exit 1
-LABEL com.centurylinklabs.watchtower.enable="false"
+HEALTHCHECK CMD /healthcheck.sh
+LABEL com.centurylinklabs.watchtower.enable="false" \
+ wud.watch="false" \
+ org.label-schema.vendor="Nextcloud"
diff --git a/Containers/imaginary/healthcheck.sh b/Containers/imaginary/healthcheck.sh
new file mode 100644
index 00000000..46d700fc
--- /dev/null
+++ b/Containers/imaginary/healthcheck.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+nc -z 127.0.0.1 "$PORT" || exit 1
diff --git a/Containers/mastercontainer/Dockerfile b/Containers/mastercontainer/Dockerfile
index ecfb35de..f3079ca7 100644
--- a/Containers/mastercontainer/Dockerfile
+++ b/Containers/mastercontainer/Dockerfile
@@ -1,20 +1,30 @@
# syntax=docker/dockerfile:latest
# Docker CLI is a requirement
-FROM docker:27.3.1-cli AS docker
+FROM docker:29.2.0-cli AS docker
# Caddy is a requirement
-FROM caddy:2.8.4-alpine AS caddy
+FROM caddy:2.10.2-alpine AS caddy
-# From https://github.com/docker-library/php/blob/master/8.3/alpine3.20/fpm/Dockerfile
-FROM php:8.3.12-fpm-alpine3.20
+# From https://github.com/docker-library/php/blob/master/8.4/alpine3.23/fpm/Dockerfile
+FROM php:8.4.17-fpm-alpine3.23
EXPOSE 80
EXPOSE 8080
EXPOSE 8443
+# Overwrite home variable for subservices
+ENV HOME=/var/www
+
COPY --from=caddy /usr/bin/caddy /usr/bin/caddy
COPY --from=docker /usr/local/bin/docker /usr/local/bin/docker
+COPY community-containers /var/www/docker-aio/community-containers
+COPY php /var/www/docker-aio/php
+COPY --chmod=775 Containers/mastercontainer/*.sh /
+COPY --chmod=664 Containers/mastercontainer/Caddyfile /Caddyfile
+COPY --chmod=664 Containers/mastercontainer/supervisord.conf /supervisord.conf
+COPY Containers/mastercontainer/mastercontainer.conf /etc/apache2/sites-available/mastercontainer.conf
+
WORKDIR /var/www/docker-aio
# hadolint ignore=SC2086,DL3047,DL3003,DL3004
@@ -42,7 +52,7 @@ RUN set -ex; \
apk add --no-cache --virtual .build-deps \
autoconf \
build-base; \
- pecl install APCu-5.1.24; \
+ pecl install APCu-5.1.28; \
docker-php-ext-enable apcu; \
rm -r /tmp/pear; \
runDeps="$( \
@@ -64,12 +74,11 @@ RUN set -ex; \
wget https://getcomposer.org/installer -O - | php -- --install-dir=/usr/local/bin --filename=composer; \
chmod +x /usr/local/bin/composer; \
cd /var/www/docker-aio; \
- git clone https://github.com/nextcloud-releases/all-in-one.git --depth 1 .; \
- find ./ -maxdepth 1 -mindepth 1 -not -path ./php -not -path ./community-containers -exec rm -r {} \; ; \
+ rm -r ./php/tests; \
chown www-data:www-data -R /var/www/docker-aio; \
cd php; \
- sudo -u www-data composer install --no-dev; \
- sudo -u www-data composer clear-cache; \
+ sudo -E -u www-data composer install --no-dev; \
+ sudo -E -u www-data composer clear-cache; \
cd ..; \
rm -f /usr/local/bin/composer; \
chmod -R 770 /var/www/docker-aio; \
@@ -116,10 +125,10 @@ RUN set -ex; \
mkdir /var/log/supervisord; \
mkdir /var/run/supervisord;
-COPY --chmod=775 *.sh /
-COPY --chmod=664 Caddyfile /Caddyfile
-COPY --chmod=664 supervisord.conf /supervisord.conf
-COPY mastercontainer.conf /etc/apache2/sites-available/mastercontainer.conf
+# hadolint ignore=DL3048
+LABEL org.label-schema.vendor="Nextcloud" \
+ wud.watch="false" \
+ com.docker.compose.project="nextcloud-aio"
# hadolint ignore=DL3002
USER root
diff --git a/Containers/mastercontainer/README.md b/Containers/mastercontainer/README.md
new file mode 100644
index 00000000..de6b535d
--- /dev/null
+++ b/Containers/mastercontainer/README.md
@@ -0,0 +1,69 @@
+# Nextcloud All-in-One `mastercontainer`
+
+This folder contains the OCI/Docker container definition, along with associated resources and
+configuration files, for building the `mastercontainer` as part of the Nextcloud All-in-One
+project. This container hosts [the Nextcloud AIO interface](
+https://github.com/nextcloud/all-in-one/tree/main/php)[^app], and a dedicated PHP environment
+for it (which is completely independent of the Nextcloud Server).
+
+## Overview
+
+The mastercontainer acts as the central orchestration service for the deployment and management
+of all other containers in the Nextcloud All-in-One stack. It hosts:
+
+- A dedicated PHP SAPI/backend (php-fpm) for AIO itself (not Nextcloud Server)
+- An Apache service for accessing the AIO interface via a self-signed HTTPS VirtualHost on 8080/tcp
+- A Caddy reverse proxy service enabling HTTPS access to the AIO frontend on port 8443/tcp.
+ - Caddy will automatically issue a Let's Encrypt issued certificate if port 80 and 8443
+ is open/forwarded and a domain pointer is in place; then, simply open the Nextcloud AIO interface using the
+ domain (`https://your-domain-that-points-to-this-server.tld:8443`). The Let's Encrypt certificate request will
+ use an [ACME HTTP-01](https://letsencrypt.org/docs/challenge-types/#http-01-challenge) challenge.
+- Miscellaneous support services specific to AIO (backup management, health checks, etc.)
+
+## Key Responsibilities
+
+- Orchestrates the deployment and lifecycle of all Nextcloud service containers
+- Handles initial setup and container configuration
+- Coordinates image updates
+- Monitors general system health
+
+It triggers the initial installation and ensures the smooth operation of the Nextcloud
+All-in-One stack.
+
+## Contents
+
+- **Dockerfile**: Instructions for building the mastercontainer image.
+- **Entrypoint script**: The `start.sh` script is used for container initialization and runtime
+ configuration before starting supervisord.
+- [**Nextcloud All-in-One Controller App**](https://github.com/nextcloud/all-in-one/tree/main/php): The
+ core AIO orchestrator that handles configuration and settings for the containers.
+- **Supervisor**: The `supervisord.conf` file defines the long-running services hosted within
+ the container (php-fpm, cron, etc.)
+
+## Usage
+
+This container should be used as the trigger image when deploying the Nextcloud All-in-One
+stack in a Docker or other OCI-compliant container environment. For detailed deployment
+instructions, refer to the [project documentation](
+https://github.com/nextcloud/all-in-one).
+
+## Related Resources
+
+- [Main Repository](https://github.com/nextcloud/all-in-one)
+- [Documentation](https://github.com/nextcloud/all-in-one#readme)
+
+## Contributing
+
+Contributions are welcome! Please follow the Nextcloud project's guidelines and submit pull
+requests or issues via the main repository.
+
+## License
+
+This folder and its contents are licensed under the
+[GNU AGPLv3](https://www.gnu.org/licenses/agpl-3.0.html), in line with the rest of Nextcloud
+All-in-One.
+
+[^app]: The Nextcloud All-in-One interface allows users to install, configure, and
+manage their Nextcloud instance and related containers via a secure web interface and API.
+It automates and simplifies complex tasks such as container orchestration, backups, updates,
+and service management for users deploying Nextcloud in Docker environments.
diff --git a/Containers/mastercontainer/cron.sh b/Containers/mastercontainer/cron.sh
index fc8c4081..67af80e7 100644
--- a/Containers/mastercontainer/cron.sh
+++ b/Containers/mastercontainer/cron.sh
@@ -45,29 +45,29 @@ while true; do
# Check for updates and send notification if yes on saturdays
if [ "$(date +%u)" = 6 ]; then
- sudo -u www-data php /var/www/docker-aio/php/src/Cron/UpdateNotification.php
+ sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/UpdateNotification.php
fi
# Check if AIO is outdated
- sudo -u www-data php /var/www/docker-aio/php/src/Cron/OutdatedNotification.php
+ sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/OutdatedNotification.php
# Remove sessions older than 24h
find "/mnt/docker-aio-config/session/" -mindepth 1 -mmin +1440 -delete
# Remove nextcloud-aio-domaincheck container
- if sudo -u www-data docker ps --format "{{.Names}}" --filter "status=exited" | grep -q "^nextcloud-aio-domaincheck$"; then
- sudo -u www-data docker container remove nextcloud-aio-domaincheck
+ if sudo -E -u www-data docker ps --format "{{.Names}}" --filter "status=exited" | grep -q "^nextcloud-aio-domaincheck$"; then
+ sudo -E -u www-data docker container remove nextcloud-aio-domaincheck
fi
# Remove dangling images
- sudo -u www-data docker image prune --force
+ sudo -E -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
+ sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/CheckFreeDiskSpace.php
# Remove mastercontainer from default bridge network
- if sudo -u www-data docker inspect nextcloud-aio-mastercontainer --format "{{.NetworkSettings.Networks}}" | grep -q "bridge"; then
- sudo -u www-data docker network disconnect bridge nextcloud-aio-mastercontainer
+ if sudo -E -u www-data docker inspect nextcloud-aio-mastercontainer --format "{{.NetworkSettings.Networks}}" | grep -q "bridge"; then
+ sudo -E -u www-data docker network disconnect bridge nextcloud-aio-mastercontainer
fi
# Wait 60s so that the whole loop will not be executed again
diff --git a/Containers/mastercontainer/daily-backup.sh b/Containers/mastercontainer/daily-backup.sh
index 56302c80..89ef3cd5 100644
--- a/Containers/mastercontainer/daily-backup.sh
+++ b/Containers/mastercontainer/daily-backup.sh
@@ -2,6 +2,13 @@
echo "Daily backup script has started"
+# Check if initial configuration has been done, otherwise this script should do nothing.
+CONFIG_FILE=/mnt/docker-aio-config/data/configuration.json
+if ! [ -f "$CONFIG_FILE" ] || (! grep -q "wasStartButtonClicked.*1" "$CONFIG_FILE" && ! grep -q "wasStartButtonClicked.*true" "$CONFIG_FILE"); then
+ echo "Initial configuration via AIO interface not done yet. Exiting..."
+ exit 0
+fi
+
# Daily backup and backup check cannot be run at the same time
if [ "$DAILY_BACKUP" = 1 ] && [ "$CHECK_BACKUP" = 1 ]; then
echo "Daily backup and backup check cannot be run at the same time. Exiting..."
@@ -13,14 +20,19 @@ fi
if [ "$LOCK_FILE_PRESENT" = 0 ] || ! [ -f "/mnt/docker-aio-config/data/daily_backup_running" ]; then
find "/mnt/docker-aio-config/session/" -mindepth 1 -delete
fi
-sudo -u www-data touch "/mnt/docker-aio-config/data/daily_backup_running"
+sudo -E -u www-data touch "/mnt/docker-aio-config/data/daily_backup_running"
# Check if apache is running/stopped, watchtower is stopped and backupcontainer is stopped
-APACHE_PORT="$(docker inspect nextcloud-aio-apache --format "{{.Config.Env}}" | grep -o 'APACHE_PORT=[0-9]\+' | grep -o '[0-9]\+' | head -1)"
-if [ -z "$APACHE_PORT" ]; then
+LOCAL_APACHE_PORT="$(docker inspect nextcloud-aio-apache --format "{{.Config.Env}}" | grep -o 'APACHE_PORT=[0-9]\+' | grep -o '[0-9]\+' | head -1)"
+if [ -z "$LOCAL_APACHE_PORT" ]; then
echo "APACHE_PORT is not set which is not expected..."
else
- while docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-apache$" && ! nc -z nextcloud-aio-apache "$APACHE_PORT"; do
+ # Connect mastercontainer to nextcloud-aio network to make sure that nextcloud-aio-apache is reachable
+ # Prevent issues like https://github.com/nextcloud/all-in-one/discussions/5222
+ docker network connect nextcloud-aio nextcloud-aio-mastercontainer &>/dev/null
+
+ # Wait for apache to start
+ while docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-apache$" && ! nc -z nextcloud-aio-apache "$LOCAL_APACHE_PORT"; do
echo "Waiting for apache to become available"
sleep 30
done
@@ -38,7 +50,7 @@ done
if [ "$AUTOMATIC_UPDATES" = 1 ]; then
echo "Starting mastercontainer update..."
echo "(The script might get exited due to that. In order to update all the other containers correctly, you need to run this script with the same settings a second time.)"
- sudo -u www-data php /var/www/docker-aio/php/src/Cron/UpdateMastercontainer.php
+ sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/UpdateMastercontainer.php
fi
# Wait for watchtower to stop
@@ -52,17 +64,23 @@ if [ "$AUTOMATIC_UPDATES" = 1 ]; then
done
fi
+# Update container images to reduce downtime later on
+if [ "$AUTOMATIC_UPDATES" = 1 ]; then
+ echo "Updating container images..."
+ sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/PullContainerImages.php
+fi
+
# Stop containers if required
# shellcheck disable=SC2235
if [ "$CHECK_BACKUP" != 1 ] && ([ "$DAILY_BACKUP" != 1 ] || [ "$STOP_CONTAINERS" = 1 ]); then
echo "Stopping containers..."
- sudo -u www-data php /var/www/docker-aio/php/src/Cron/StopContainers.php
+ sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/StopContainers.php
fi
# Execute the backup itself and some related tasks (also stops the containers)
if [ "$DAILY_BACKUP" = 1 ]; then
echo "Creating daily backup..."
- sudo -u www-data php /var/www/docker-aio/php/src/Cron/CreateBackup.php
+ sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/CreateBackup.php
if ! docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-borgbackup$"; then
echo "Something seems to be wrong: the borg container should be started at this step."
fi
@@ -75,17 +93,17 @@ fi
# Execute backup check
if [ "$CHECK_BACKUP" = 1 ]; then
echo "Starting backup check..."
- sudo -u www-data php /var/www/docker-aio/php/src/Cron/CheckBackup.php
+ sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/CheckBackup.php
fi
# Start and/or update containers
if [ "$AUTOMATIC_UPDATES" = 1 ]; then
echo "Starting and updating containers..."
- sudo -u www-data php /var/www/docker-aio/php/src/Cron/StartAndUpdateContainers.php
+ sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/StartAndUpdateContainers.php
else
if [ "$START_CONTAINERS" = 1 ]; then
echo "Starting containers without updating them..."
- sudo -u www-data php /var/www/docker-aio/php/src/Cron/StartContainers.php
+ sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/StartContainers.php
fi
fi
diff --git a/Containers/mastercontainer/mastercontainer.conf b/Containers/mastercontainer/mastercontainer.conf
index 6a7d37dd..7d294694 100644
--- a/Containers/mastercontainer/mastercontainer.conf
+++ b/Containers/mastercontainer/mastercontainer.conf
@@ -1,5 +1,5 @@
-Listen 8000
-Listen 8080
+Listen 127.0.0.1:8000
+Listen 8080 https
# Deny access to .ht files
@@ -7,8 +7,8 @@ Listen 8080
# Http host
-
- ServerName localhost
+
+ ServerName 127.0.0.1
# Add error log
CustomLog /proc/self/fd/1 proxy
diff --git a/Containers/mastercontainer/start.sh b/Containers/mastercontainer/start.sh
index f87527cb..a65e29ae 100644
--- a/Containers/mastercontainer/start.sh
+++ b/Containers/mastercontainer/start.sh
@@ -33,17 +33,25 @@ if [ "$*" != "" ]; then
fi
# Check if socket is available and readable
-if ! [ -a "/var/run/docker.sock" ]; then
+if ! [ -e "/var/run/docker.sock" ]; then
print_red "Docker socket is not available. Cannot continue."
echo "Please make sure to mount the docker socket into /var/run/docker.sock inside the container!"
echo "If you did this by purpose because you don't want the container to have access to the docker socket, see https://github.com/nextcloud/all-in-one/tree/main/manual-install."
+ echo "And https://github.com/nextcloud/all-in-one/blob/main/manual-install/latest.yml"
exit 1
elif ! mountpoint -q "/mnt/docker-aio-config"; then
print_red "/mnt/docker-aio-config is not a mountpoint. Cannot proceed!"
echo "Please make sure to mount the nextcloud_aio_mastercontainer docker volume into /mnt/docker-aio-config inside the container!"
echo "If you are on TrueNas SCALE, see https://github.com/nextcloud/all-in-one#can-i-run-aio-on-truenas-scale"
exit 1
-elif ! sudo -u www-data test -r /var/run/docker.sock; then
+elif mountpoint -q /var/www/docker-aio/php/containers.json; then
+ print_red "/var/www/docker-aio/php/containers.json is a mountpoint. Cannot proceed!"
+ echo "This is a not-supported customization of the mastercontainer!"
+ echo "Please remove this bind-mount from the mastercontainer."
+ echo "If you need to customize things, feel free to use https://github.com/nextcloud/all-in-one/tree/main/manual-install"
+ echo "See https://github.com/nextcloud/all-in-one/blob/main/manual-install/latest.yml"
+ exit 1
+elif ! sudo -E -u www-data test -r /var/run/docker.sock; then
echo "Trying to fix docker.sock permissions internally..."
DOCKER_GROUP=$(stat -c '%G' /var/run/docker.sock)
DOCKER_GROUP_ID=$(stat -c '%g' /var/run/docker.sock)
@@ -61,28 +69,68 @@ elif ! sudo -u www-data test -r /var/run/docker.sock; then
groupadd -g "$DOCKER_GROUP_ID" docker
usermod -aG docker www-data
fi
- if ! sudo -u www-data test -r /var/run/docker.sock; then
+ if ! sudo -E -u www-data test -r /var/run/docker.sock; then
print_red "Docker socket is not readable by the www-data user. Cannot continue."
exit 1
fi
fi
-# Check if api version is supported
-if ! sudo -u www-data docker info &>/dev/null; then
- print_red "Cannot connect to the docker socket. Cannot proceed."
- echo "Did you maybe remove group read permissions for the docker socket? AIO needs them in order to access the docker socket."
- echo "If SELinux is enabled on your host, see https://github.com/nextcloud/all-in-one#are-there-known-problems-when-selinux-is-enabled"
- echo "If you are on TrueNas SCALE, see https://github.com/nextcloud/all-in-one#can-i-run-aio-on-truenas-scale"
- exit 1
-fi
+# Get default docker api version
API_VERSION_FILE="$(find ./ -name DockerActionManager.php | head -1)"
API_VERSION="$(grep -oP 'const string API_VERSION.*\;' "$API_VERSION_FILE" | grep -oP '[0-9]+.[0-9]+' | head -1)"
+if [ -z "$API_VERSION" ]; then
+ print_red "Could not get API_VERSION. Something is wrong!"
+ exit 1
+fi
+
+# Check if DOCKER_API_VERSION is set globally
+if [ -n "$DOCKER_API_VERSION" ]; then
+ if ! echo "$DOCKER_API_VERSION" | grep -q '^[0-9].[0-9]\+$'; then
+ print_red "You've set DOCKER_API_VERSION but not to an allowed value.
+The string must be a version number like e.g. '1.44'.
+It is set to '$DOCKER_API_VERSION'."
+ exit 1
+ fi
+ print_red "DOCKER_API_VERSION was found to be set to '$DOCKER_API_VERSION'."
+ print_red "Please note that only v$API_VERSION is officially supported and tested by the maintainers of Nextcloud AIO."
+ print_red "So you run on your own risk and things might break without warning."
+else
+ # Export docker api version to use it everywhere
+ export DOCKER_API_VERSION="$API_VERSION"
+fi
+
+# Set a fallback docker api version. Needed for api version check.
+# The check will not work otherwise on old docker versions
+FALLBACK_DOCKER_API_VERSION="1.41"
+
+# Check if docker info can be used
+if ! sudo -E -u www-data docker info &>/dev/null; then
+ if ! sudo -E -u www-data DOCKER_API_VERSION="$FALLBACK_DOCKER_API_VERSION" docker info &>/dev/null; then
+ print_red "Cannot connect to the docker socket. Cannot proceed."
+ echo "Did you maybe remove group read permissions for the docker socket? AIO needs them in order to access the docker socket."
+ echo "If SELinux is enabled on your host, see https://github.com/nextcloud/all-in-one#are-there-known-problems-when-selinux-is-enabled"
+ echo "If you are on TrueNas SCALE, see https://github.com/nextcloud/all-in-one#can-i-run-aio-on-truenas-scale"
+ echo "On macOS, see https://github.com/nextcloud/all-in-one#how-to-run-aio-on-macos"
+ echo "Another possibility might be that Docker api v$API_VERSION is not supported by your docker daemon."
+ echo "In that case, you should report this to https://github.com/nextcloud/all-in-one/issues"
+ echo ""
+ exit 1
+ fi
+fi
+
+# Docker api version check
# shellcheck disable=SC2001
-API_VERSION_NUMB="$(echo "$API_VERSION" | sed 's/\.//')"
-LOCAL_API_VERSION_NUMB="$(sudo -u www-data docker version | grep -i "api version" | grep -oP '[0-9]+.[0-9]+' | head -1 | sed 's/\.//')"
+API_VERSION_NUMB="$(echo "$DOCKER_API_VERSION" | sed 's/\.//')"
+LOCAL_API_VERSION_NUMB="$(sudo -E -u www-data docker version | grep -i "api version" | grep -oP '[0-9]+.[0-9]+' | head -1 | sed 's/\.//')"
+if [ -z "$LOCAL_API_VERSION_NUMB" ]; then
+ LOCAL_API_VERSION_NUMB="$(sudo -E -u www-data DOCKER_API_VERSION="$FALLBACK_DOCKER_API_VERSION" docker version | grep -i "api version" | grep -oP '[0-9]+.[0-9]+' | head -1 | sed 's/\.//')"
+fi
if [ -n "$LOCAL_API_VERSION_NUMB" ] && [ -n "$API_VERSION_NUMB" ]; then
if ! [ "$LOCAL_API_VERSION_NUMB" -ge "$API_VERSION_NUMB" ]; then
- print_red "Docker API v$API_VERSION is not supported by your docker engine. Cannot proceed. Please upgrade your docker engine if you want to run Nextcloud AIO!"
+ print_red "Docker API v$DOCKER_API_VERSION is not supported by your docker engine. Cannot proceed. Please upgrade your docker engine if you want to run Nextcloud AIO!"
+ echo "Alternatively, set the DOCKER_API_VERSION environmental variable to a compatible version."
+ echo "However please note that only v$API_VERSION is officially supported and tested by the maintainers of Nextcloud AIO."
+ echo "See https://github.com/nextcloud/all-in-one#how-to-adjust-the-internally-used-docker-api-version"
exit 1
fi
else
@@ -91,7 +139,7 @@ else
fi
# Check Storage drivers
-STORAGE_DRIVER="$(sudo -u www-data docker info | grep "Storage Driver")"
+STORAGE_DRIVER="$(sudo -E -u www-data docker info | grep "Storage Driver")"
# Check if vfs is used: https://github.com/nextcloud/all-in-one/discussions/1467
if echo "$STORAGE_DRIVER" | grep -q vfs; then
echo "$STORAGE_DRIVER"
@@ -102,23 +150,23 @@ elif echo "$STORAGE_DRIVER" | grep -q fuse-overlayfs; then
fi
# Check if snap install
-if sudo -u www-data docker info | grep "Docker Root Dir" | grep "/var/snap/docker/"; then
+if sudo -E -u www-data docker info | grep "Docker Root Dir" | grep "/var/snap/docker/"; then
print_red "Warning: It looks like your installation uses docker installed via snap."
print_red "This comes with some limitations and is disrecommended by the docker maintainers."
print_red "See for example https://github.com/nextcloud/all-in-one/discussions/4890#discussioncomment-10386752"
fi
# Check if startup command was executed correctly
-if ! sudo -u www-data docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-mastercontainer$"; then
+if ! sudo -E -u www-data docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-mastercontainer$"; then
print_red "It seems like you did not give the mastercontainer the correct name? (The 'nextcloud-aio-mastercontainer' container was not found.)
Using a different name is not supported since mastercontainer updates will not work in that case!
If you are on docker swarm and try to run AIO, see https://github.com/nextcloud/all-in-one#can-i-run-this-with-docker-swarm"
exit 1
-elif ! sudo -u www-data docker volume ls --format "{{.Name}}" | grep -q "^nextcloud_aio_mastercontainer$"; then
+elif ! sudo -E -u www-data docker volume ls --format "{{.Name}}" | grep -q "^nextcloud_aio_mastercontainer$"; then
print_red "It seems like you did not give the mastercontainer volume the correct name? (The 'nextcloud_aio_mastercontainer' volume was not found.)
Using a different name is not supported since the built-in backup solution will not work in that case!"
exit 1
-elif ! sudo -u www-data docker inspect nextcloud-aio-mastercontainer | grep -q "nextcloud_aio_mastercontainer"; then
+elif ! sudo -E -u www-data docker inspect nextcloud-aio-mastercontainer --format '{{.Mounts}}' | grep -q " nextcloud_aio_mastercontainer "; then
print_red "It seems like you did not attach the 'nextcloud_aio_mastercontainer' volume to the mastercontainer?
This is not supported since the built-in backup solution will not work in that case!"
exit 1
@@ -137,7 +185,7 @@ It is set to '$NEXTCLOUD_DATADIR'."
fi
if [ -n "$NEXTCLOUD_MOUNT" ]; then
if ! echo "$NEXTCLOUD_MOUNT" | grep -q "^/" || [ "$NEXTCLOUD_MOUNT" = "/" ]; then
- print_red "You've set NEXCLOUD_MOUNT but not to an allowed value.
+ print_red "You've set NEXTCLOUD_MOUNT but not to an allowed value.
The string must start with '/' and must not be equal to '/'.
It is set to '$NEXTCLOUD_MOUNT'."
exit 1
@@ -193,6 +241,14 @@ It is set to '$APACHE_IP_BINDING'."
exit 1
fi
fi
+if [ -n "$APACHE_ADDITIONAL_NETWORK" ]; then
+ if ! echo "$APACHE_ADDITIONAL_NETWORK" | grep -q "^[a-zA-Z0-9._-]\+$"; then
+ print_red "You've set APACHE_ADDITIONAL_NETWORK but not to an allowed value.
+It needs to be a string with letters, numbers, hyphens and underscores.
+It is set to '$APACHE_ADDITIONAL_NETWORK'."
+ exit 1
+ fi
+fi
if [ -n "$TALK_PORT" ]; then
if ! check_if_number "$TALK_PORT"; then
print_red "You provided an Talk port but did not only use numbers.
@@ -250,28 +306,18 @@ It is set to '$NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS'."
fi
fi
if [ -n "$AIO_COMMUNITY_CONTAINERS" ]; then
- read -ra AIO_CCONTAINERS <<< "$AIO_COMMUNITY_CONTAINERS"
- for container in "${AIO_CCONTAINERS[@]}"; do
- if ! [ -d "/var/www/docker-aio/community-containers/$container" ]; then
- print_red "The community container $container was not found!"
- FAIL_CCONTAINERS=1
- fi
- done
- if [ -n "$FAIL_CCONTAINERS" ]; then
- print_red "You've set AIO_COMMUNITY_CONTAINERS but at least one container was not found.
-It is set to '$AIO_COMMUNITY_CONTAINERS'."
- exit 1
- fi
+ print_red "You've set AIO_COMMUNITY_CONTAINERS but the option was removed.
+The community containers get managed via the AIO interface now."
fi
-# Check DNS resolution
-# Prevents issues like https://github.com/nextcloud/all-in-one/discussions/565
-curl https://nextcloud.com &>/dev/null
-if [ "$?" = 6 ]; then
- print_red "Could not resolve the host nextcloud.com."
- echo "Most likely the DNS resolving does not work."
+# Check if ghcr.io is reachable
+# Solves issues like https://github.com/nextcloud/all-in-one/discussions/5268
+if ! curl --no-progress-meter https://ghcr.io/v2/ >/dev/null; then
+ print_red "Could not reach https://ghcr.io."
+ echo "Most likely is something blocking access to it."
echo "You should be able to fix this by following https://dockerlabs.collabnix.com/intermediate/networking/Configuring_DNS.html"
- echo "Apart from that, there has been this: https://github.com/nextcloud/all-in-one/discussions/2065"
+ echo "Another solution is using https://github.com/nextcloud/all-in-one/tree/main/manual-install"
+ echo "See https://github.com/nextcloud/all-in-one/blob/main/manual-install/latest.yml"
exit 1
fi
@@ -282,6 +328,13 @@ if [ -n "$TZ" ]; then
# Disable exit since it seems to be by default set on unraid and we dont want to break these instances
# exit 1
fi
+# Check that http proxy or no_proxy variable is not set which AIO does not support
+if [ -n "$HTTP_PROXY" ] || [ -n "$http_proxy" ] || [ -n "$HTTPS_PROXY" ] || [ -n "$https_proxy" ] || [ -n "$NO_PROXY" ] || [ -n "$no_proxy" ]; then
+ print_red "The environmental variable HTTP_PROXY, http_proxy, HTTPS_PROXY, https_proxy, NO_PROXY or no_proxy has been set which is not supported by AIO."
+ echo "If you need this, then you should use https://github.com/nextcloud/all-in-one/tree/main/manual-install"
+ echo "See https://github.com/nextcloud/all-in-one/blob/main/manual-install/latest.yml"
+ exit 1
+fi
if mountpoint -q /etc/localtime; then
print_red "/etc/localtime has been mounted into the container which is not allowed because AIO only supports running in the default Etc/UTC timezone!"
echo "The correct timezone can be set in the AIO interface later on!"
@@ -362,6 +415,11 @@ export TZ=Etc/UTC
# Fix apache startup
rm -f /var/run/apache2/httpd.pid
+# Fix caddy startup
+if [ -d "/mnt/docker-aio-config/caddy/locks" ]; then
+ rm -rf /mnt/docker-aio-config/caddy/locks/*
+fi
+
# Fix the Caddyfile format
caddy fmt --overwrite /Caddyfile
@@ -369,4 +427,4 @@ caddy fmt --overwrite /Caddyfile
chmod 777 /root
# Start supervisord
-/usr/bin/supervisord -c /supervisord.conf
+exec /usr/bin/supervisord -c /supervisord.conf
diff --git a/Containers/mastercontainer/supervisord.conf b/Containers/mastercontainer/supervisord.conf
index f64c9725..fa5d0845 100644
--- a/Containers/mastercontainer/supervisord.conf
+++ b/Containers/mastercontainer/supervisord.conf
@@ -9,16 +9,16 @@ loglevel=error
user=root
[program:php-fpm]
-# stdout_logfile=/dev/stdout
-# stdout_logfile_maxbytes=0
+# Stdout logging is disabled as otherwise the logs are spammed
+stdout_logfile=NONE
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
command=php-fpm
user=root
[program:apache]
-# stdout_logfile=/dev/stdout
-# stdout_logfile_maxbytes=0
+# Stdout logging is disabled as otherwise the logs are spammed
+stdout_logfile=NONE
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
command=httpd -DFOREGROUND
@@ -58,9 +58,7 @@ user=root
[program:domain-validator]
# Logging is disabled as otherwise all attempts will be logged which spams the logs
-# stdout_logfile=/dev/stdout
-# stdout_logfile_maxbytes=0
-# stderr_logfile=/dev/stderr
-# stderr_logfile_maxbytes=0
+stdout_logfile=NONE
+stderr_logfile=NONE
command=php -S 127.0.0.1:9876 /var/www/docker-aio/php/domain-validator.php
user=www-data
diff --git a/Containers/nextcloud/Dockerfile b/Containers/nextcloud/Dockerfile
index 90fac1a8..c6d9bf7e 100644
--- a/Containers/nextcloud/Dockerfile
+++ b/Containers/nextcloud/Dockerfile
@@ -1,23 +1,27 @@
# syntax=docker/dockerfile:latest
-FROM php:8.2.24-fpm-alpine3.20
+FROM php:8.3.30-fpm-alpine3.23
ENV PHP_MEMORY_LIMIT=512M
-ENV PHP_UPLOAD_LIMIT=10G
+ENV PHP_UPLOAD_LIMIT=16G
ENV PHP_MAX_TIME=3600
ENV SOURCE_LOCATION=/usr/src/nextcloud
ENV REDIS_DB_INDEX=0
# AIO settings start # Do not remove or change this line!
-ENV NEXTCLOUD_VERSION=29.0.8
+ENV NEXTCLOUD_VERSION=32.0.5
ENV AIO_TOKEN=123456
ENV AIO_URL=localhost
# AIO settings end # Do not remove or change this line!
-COPY --chmod=775 *.sh /
-COPY --chmod=774 upgrade.exclude /upgrade.exclude
-COPY config/*.php /
-COPY supervisord.conf /supervisord.conf
-COPY root.motd /root.motd
+COPY --chmod=775 Containers/nextcloud/*.sh /
+COPY --chmod=774 Containers/nextcloud/upgrade.exclude /upgrade.exclude
+COPY Containers/nextcloud/config/*.php /
+COPY Containers/nextcloud/supervisord.conf /supervisord.conf
+
+# AIO cloning start # Do not remove or change this line!
+COPY app /usr/src/nextcloud/apps/nextcloud-aio
+COPY Containers/nextcloud/root.motd /root.motd
+# AIO cloning end # Do not remove or change this line!
VOLUME /mnt/ncdata
VOLUME /var/www/html
@@ -78,17 +82,18 @@ RUN set -ex; \
; \
\
# pecl will claim success even if one install fails, so we need to perform each install separately
- pecl install igbinary-3.2.16; \
- pecl install APCu-5.1.24; \
- pecl install -D 'enable-memcached-igbinary="yes"' memcached-3.2.0; \
- pecl install -D 'enable-redis-igbinary="yes" enable-redis-zstd="yes" enable-redis-lz4="yes"' redis-6.1.0; \
- pecl install imagick-3.7.0; \
+ pecl install -o igbinary-3.2.16; \
+ pecl install APCu-5.1.28; \
+ 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.3.0; \
+ pecl install -o imagick-3.8.1; \
\
docker-php-ext-enable \
igbinary \
apcu \
memcached \
redis \
+ imagick \
; \
rm -r /tmp/pear; \
\
@@ -107,8 +112,9 @@ RUN set -ex; \
} >> /usr/local/etc/php/conf.d/docker-php-ext-igbinary.ini; \
\
# set recommended PHP.ini settings
-# see https://docs.nextcloud.com/server/stable/admin_manual/configuration_server/server_tuning.html#enable-php-opcache
+# see https://docs.nextcloud.com/server/stable/admin_manual/installation/server_tuning.html#enable-php-opcache and below
{ \
+ echo 'opcache.max_accelerated_files=10000'; \
echo 'opcache.memory_consumption=256'; \
echo 'opcache.interned_strings_buffer=64'; \
echo 'opcache.save_comments=1'; \
@@ -117,23 +123,27 @@ RUN set -ex; \
echo 'opcache.jit_buffer_size=8M'; \
} > /usr/local/etc/php/conf.d/opcache-recommended.ini; \
\
- echo 'apc.enable_cli=1' >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini; \
+ { \
+ echo 'apc.enable_cli=1'; \
+ echo 'apc.shm_size=64M'; \
+ } >> /usr/local/etc/php/conf.d/docker-php-ext-apcu.ini; \
\
{ \
echo 'memory_limit=${PHP_MEMORY_LIMIT}'; \
echo 'upload_max_filesize=${PHP_UPLOAD_LIMIT}'; \
echo 'post_max_size=${PHP_UPLOAD_LIMIT}'; \
echo 'max_execution_time=${PHP_MAX_TIME}'; \
- echo 'max_input_time=${PHP_MAX_TIME}'; \
- echo 'default_socket_timeout=600'; \
+ echo 'max_input_time=-1'; \
+ echo 'default_socket_timeout=${PHP_MAX_TIME}'; \
} > /usr/local/etc/php/conf.d/nextcloud.ini; \
\
{ \
echo 'session.save_handler = redis'; \
- echo 'session.save_path = "tcp://${REDIS_HOST}:6379/${REDIS_DB_INDEX}?auth=${REDIS_HOST_PASSWORD}"'; \
+ echo 'session.save_path = "tcp://${REDIS_HOST}:${REDIS_PORT}?database=${REDIS_DB_INDEX}${REDIS_USER_AUTH}&auth[]=${REDIS_HOST_PASSWORD}"'; \
echo 'redis.session.locking_enabled = 1'; \
echo 'redis.session.lock_retries = -1'; \
echo 'redis.session.lock_wait_time = 10000'; \
+ echo 'session.gc_maxlifetime = 86400'; \
} > /usr/local/etc/php/conf.d/redis-session.ini; \
\
mkdir -p /var/www/data; \
@@ -147,7 +157,7 @@ RUN set -ex; \
; \
\
curl -fsSL -o nextcloud.tar.bz2 \
- "https://download.nextcloud.com/server/releases/nextcloud-${NEXTCLOUD_VERSION}.tar.bz2"; \
+ "https://github.com/nextcloud-releases/server/releases/download/v${NEXTCLOUD_VERSION}/nextcloud-${NEXTCLOUD_VERSION}.tar.bz2"; \
curl -fsSL -o nextcloud.tar.bz2.asc \
"https://download.nextcloud.com/server/releases/nextcloud-${NEXTCLOUD_VERSION}.tar.bz2.asc"; \
export GNUPGHOME="$(mktemp -d)"; \
@@ -207,8 +217,8 @@ RUN set -ex; \
/var/log/supervisord \
/var/run/supervisord \
; \
- chown www-data:root -R /var/log/supervisord; \
- chown www-data:root -R /var/run/supervisord; \
+ chmod 777 -R /var/log/supervisord; \
+ chmod 777 -R /var/run/supervisord; \
\
apk add --no-cache \
bash \
@@ -236,33 +246,23 @@ RUN set -ex; \
sed -i 's/^pm.max_children =.*/pm.max_children = 5000/' /usr/local/etc/php-fpm.d/www.conf; \
sed -i 's|access.log = /proc/self/fd/2|access.log = /proc/self/fd/1|' /usr/local/etc/php-fpm.d/docker.conf; \
\
-# AIO cloning start # Do not remove or change this line!
- rm -rf /tmp/nextcloud-aio && \
- mkdir -p /tmp/nextcloud-aio && \
- cd /tmp/nextcloud-aio && \
- git clone https://github.com/nextcloud-releases/all-in-one.git --depth 1 .; \
- mkdir -p /usr/src/nextcloud/apps/nextcloud-aio; \
- cp -r ./app/* /usr/src/nextcloud/apps/nextcloud-aio/; \
- echo "[ -n \"\$TERM\" ] && cat /root.motd" >> /root/.bashrc; \
-# AIO cloning end # Do not remove or change this line!
+ echo "[ -n \"\$TERM\" ] && [ -f /root.motd ] && cat /root.motd" >> /root/.bashrc; \
\
chown www-data:root -R /usr/src && \
- chown www-data:root -R /usr/local/etc/php/conf.d && \
- chown www-data:root -R /usr/local/etc/php-fpm.d && \
+ chmod 777 -R /usr/local/etc/php/conf.d && \
+ chmod 777 -R /usr/local/etc/php-fpm.d && \
chmod -R 777 /tmp; \
- rm -rf /usr/src/nextcloud/apps/updatenotification; \
+ chmod -R 777 /etc/openldap; \
\
mkdir -p /nc-updater; \
- chown -R www-data:www-data /nc-updater; \
- chmod -R 770 /nc-updater; \
- \
-# Give root a random password
- echo "root:$(openssl rand -base64 12)" | chpasswd
+ chmod -R 777 /nc-updater
# hadolint ignore=DL3002
USER root
ENTRYPOINT ["/start.sh"]
CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"]
-HEALTHCHECK --start-period=60s CMD sudo -E -u www-data bash /healthcheck.sh
-LABEL com.centurylinklabs.watchtower.enable="false"
+HEALTHCHECK CMD /healthcheck.sh
+LABEL com.centurylinklabs.watchtower.enable="false" \
+ wud.watch="false" \
+ org.label-schema.vendor="Nextcloud"
diff --git a/Containers/nextcloud/README.md b/Containers/nextcloud/README.md
new file mode 100644
index 00000000..574afd03
--- /dev/null
+++ b/Containers/nextcloud/README.md
@@ -0,0 +1,35 @@
+# Nextcloud All-in-One ``nextcloud`` Container
+
+This folder contains the OCI/Docker container definition, along with associated resources and configuration files, for building the `nextcloud` container as part of the [Nextcloud All-in-One](https://github.com/nextcloud/all-in-one) project. This container hosts PHP and the Nextcloud Server application.
+
+## Overview
+
+The Nextcloud container provides the core Nextcloud application environment, including the necessary dependencies and configuration for seamless integration into the All-in-One stack. The container hosts:
+
+- The PHP SAPI/backend (php-fpm)
+- Nextcloud background jobs and scheduled tasks, which are handled via cron
+- Miscellaneous minor support services specific to AIO's Nextcloud deployment (health and exec)
+
+## Contents
+
+- **Dockerfile**: Instructions for building the Nextcloud container image.
+- **Entrypoint script**: The `start.sh` script is used for container initialization and runtime configuration before starting supervisord.
+- **Nextcloud configuration files**: Specific to running in a containerized setting and/or within AIO.
+- **Supervisor**: The `supervisord.conf` file defines the long-running services hosted within the container (php-fpm, cron, etc.).
+
+## Usage
+
+This container is intended to be used as part of the All-in-One deployment and is not meant to be used on its own. Among other requirements, it needs a web server container (which AIO provides in a dedicated Apache container). It is designed to be orchestrated by the [All-in-One mastercontainer](https://github.com/nextcloud/all-in-one/tree/main/Containers/mastercontainer) or used within an [AIO Manual Installation](https://github.com/nextcloud/all-in-one/tree/main/manual-install) or [AIO Helm chart](https://github.com/nextcloud/all-in-one/tree/main/nextcloud-aio-helm-chart).
+
+## Documentation
+
+- [Nextcloud All-in-One Documentation](https://github.com/nextcloud/all-in-one#readme)
+- [Nextcloud Documentation](https://docs.nextcloud.com/)
+
+## Contributing
+
+Contributions are welcome! Please follow the Nextcloud project's guidelines and submit pull requests or issues via the main repository.
+
+## License
+
+This folder and its contents are licensed under the [GNU AGPLv3](https://www.gnu.org/licenses/agpl-3.0.html), in line with the rest of Nextcloud All-in-One.
diff --git a/Containers/nextcloud/config/apps.config.php b/Containers/nextcloud/config/apps.config.php
index c890e787..99bf5e40 100644
--- a/Containers/nextcloud/config/apps.config.php
+++ b/Containers/nextcloud/config/apps.config.php
@@ -16,3 +16,6 @@ $CONFIG = array (
if (getenv('APPS_ALLOWLIST')) {
$CONFIG['appsallowlist'] = explode(" ", getenv('APPS_ALLOWLIST'));
}
+if (getenv('NEXTCLOUD_APP_STORE_URL')) {
+ $CONFIG['appstoreurl'] = getenv('NEXTCLOUD_APP_STORE_URL');
+}
diff --git a/Containers/nextcloud/config/certificates-bundle.config.php b/Containers/nextcloud/config/certificates-bundle.config.php
new file mode 100644
index 00000000..cc05b06a
--- /dev/null
+++ b/Containers/nextcloud/config/certificates-bundle.config.php
@@ -0,0 +1,5 @@
+ array(
+ 'mode' => 'verify-ca',
+ 'rootcert' => '/var/www/html/data/certificates/ca-bundle.crt',
+ ),
+ );
+}
+if (getenv('NEXTCLOUD_TRUSTED_CERTIFICATES_MYSQL')) {
+ $CONFIG = array(
+ 'dbdriveroptions' => array(
+ PDO::MYSQL_ATTR_SSL_CA => '/var/www/html/data/certificates/ca-bundle.crt',
+ ),
+ );
+}
+
diff --git a/Containers/nextcloud/config/redis.config.php b/Containers/nextcloud/config/redis.config.php
index c99a9ec1..b59fe4ea 100644
--- a/Containers/nextcloud/config/redis.config.php
+++ b/Containers/nextcloud/config/redis.config.php
@@ -9,13 +9,15 @@ if (getenv('REDIS_HOST')) {
),
);
- if (getenv('REDIS_HOST_PORT')) {
- $CONFIG['redis']['port'] = (int) getenv('REDIS_HOST_PORT');
- } elseif (getenv('REDIS_HOST')[0] != '/') {
- $CONFIG['redis']['port'] = 6379;
+ if (getenv('REDIS_PORT')) {
+ $CONFIG['redis']['port'] = (int) getenv('REDIS_PORT');
}
if (getenv('REDIS_DB_INDEX')) {
$CONFIG['redis']['dbindex'] = (int) getenv('REDIS_DB_INDEX');
}
+
+ if (getenv('REDIS_USER_AUTH') !== false) {
+ $CONFIG['redis']['user'] = str_replace("&auth[]=", "", getenv('REDIS_USER_AUTH'));
+ }
}
diff --git a/Containers/nextcloud/config/s3.config.php b/Containers/nextcloud/config/s3.config.php
index f902bde8..6ea06697 100644
--- a/Containers/nextcloud/config/s3.config.php
+++ b/Containers/nextcloud/config/s3.config.php
@@ -4,26 +4,34 @@ if (getenv('OBJECTSTORE_S3_BUCKET')) {
$use_path = getenv('OBJECTSTORE_S3_USEPATH_STYLE');
$use_legacyauth = getenv('OBJECTSTORE_S3_LEGACYAUTH');
$autocreate = getenv('OBJECTSTORE_S3_AUTOCREATE');
+ $multibucket = getenv('OBJECTSTORE_S3_MULTIBUCKET');
$CONFIG = array(
'objectstore' => array(
'class' => '\OC\Files\ObjectStore\S3',
'arguments' => array(
+ 'multibucket' => $multibucket === 'true',
+ 'num_buckets' => (int)getenv('OBJECTSTORE_S3_NUM_BUCKETS') ?: 64,
'bucket' => getenv('OBJECTSTORE_S3_BUCKET'),
'key' => getenv('OBJECTSTORE_S3_KEY') ?: '',
'secret' => getenv('OBJECTSTORE_S3_SECRET') ?: '',
- 'sse_c_key' => getenv('OBJECTSTORE_S3_SSE_C_KEY') ?: '',
'region' => getenv('OBJECTSTORE_S3_REGION') ?: '',
'hostname' => getenv('OBJECTSTORE_S3_HOST') ?: '',
'port' => getenv('OBJECTSTORE_S3_PORT') ?: '',
'storageClass' => getenv('OBJECTSTORE_S3_STORAGE_CLASS') ?: '',
'objectPrefix' => getenv("OBJECTSTORE_S3_OBJECT_PREFIX") ? getenv("OBJECTSTORE_S3_OBJECT_PREFIX") : "urn:oid:",
- 'autocreate' => (strtolower($autocreate) === 'false' || $autocreate == false) ? false : true,
- 'use_ssl' => (strtolower($use_ssl) === 'false' || $use_ssl == false) ? false : true,
+ 'autocreate' => strtolower($autocreate) !== 'false',
+ 'use_ssl' => strtolower($use_ssl) !== 'false',
// required for some non Amazon S3 implementations
- 'use_path_style' => $use_path == true && strtolower($use_path) !== 'false',
+ 'use_path_style' => strtolower($use_path) === 'true',
// required for older protocol versions
- 'legacy_auth' => $use_legacyauth == true && strtolower($use_legacyauth) !== 'false'
+ 'legacy_auth' => strtolower($use_legacyauth) === 'true',
+ 'use_nextcloud_bundle' => 1,
)
)
);
-}
+
+ $sse_c_key = getenv('OBJECTSTORE_S3_SSE_C_KEY');
+ if ($sse_c_key) {
+ $CONFIG['objectstore']['arguments']['sse_c_key'] = $sse_c_key;
+ }
+}
diff --git a/Containers/nextcloud/config/smtp.config.php b/Containers/nextcloud/config/smtp.config.php
index 40cfdf94..b57f9b68 100644
--- a/Containers/nextcloud/config/smtp.config.php
+++ b/Containers/nextcloud/config/smtp.config.php
@@ -18,3 +18,14 @@ if (getenv('SMTP_HOST') && getenv('MAIL_FROM_ADDRESS') && getenv('MAIL_DOMAIN'))
$CONFIG['mail_smtppassword'] = '';
}
}
+
+if (getenv('NEXTCLOUD_TRUSTED_CERTIFICATES_MAILER')) {
+ $CONFIG = array(
+ 'mail_smtpstreamoptions' => array(
+ 'ssl' => array(
+ 'verify_peer_name' => false,
+ 'cafile' => '/var/www/html/data/certificates/ca-bundle.crt',
+ )
+ )
+ );
+}
diff --git a/Containers/nextcloud/entrypoint.sh b/Containers/nextcloud/entrypoint.sh
index 1abbcd5e..d4b4f253 100644
--- a/Containers/nextcloud/entrypoint.sh
+++ b/Containers/nextcloud/entrypoint.sh
@@ -20,31 +20,97 @@ run_upgrade_if_needed_due_to_app_update() {
fi
}
-# Only start container if redis is accessible
+# Create cert bundle
+if env | grep -q NEXTCLOUD_TRUSTED_CERTIFICATES_; then
+
+ # Enable debug mode
+ set -x
+
+ # Default vars
+ CERTIFICATES_ROOT_DIR="/var/www/html/data/certificates"
+ CERTIFICATE_BUNDLE="/var/www/html/data/certificates/ca-bundle.crt"
+
+ # Remove old root certs and recreate them with current ones
+ rm -rf "$CERTIFICATES_ROOT_DIR"
+ mkdir -p "$CERTIFICATES_ROOT_DIR"
+
+ # Retrieve default root cert bundle
+ if ! [ -f "$SOURCE_LOCATION/resources/config/ca-bundle.crt" ]; then
+ echo "Root ca-bundle not found. Only concattening configured NEXTCLOUD_TRUSTED_CERTIFICATES files!"
+ # Recreate cert file
+ touch "$CERTIFICATE_BUNDLE"
+ else
+ # Write default bundle to the target ca file
+ cat "$SOURCE_LOCATION/resources/config/ca-bundle.crt" > "$CERTIFICATE_BUNDLE"
+ fi
+
+ # Iterate through certs
+ TRUSTED_CERTIFICATES="$(env | grep NEXTCLOUD_TRUSTED_CERTIFICATES_ | grep -oP '^[A-Z_a-z0-9]+')"
+ mapfile -t TRUSTED_CERTIFICATES <<< "$TRUSTED_CERTIFICATES"
+ for certificate in "${TRUSTED_CERTIFICATES[@]}"; do
+
+ # Create new line
+ echo "" >> "$CERTIFICATE_BUNDLE"
+
+ # Check if variable is an actual cert
+ if echo "${!certificate}" | grep -q "BEGIN CERTIFICATE" && echo "${!certificate}" | grep -q "END CERTIFICATE"; then
+ # Write out cert to bundle
+ echo "${!certificate}" >> "$CERTIFICATE_BUNDLE"
+ fi
+
+ # Create file in cert dir for extra logic in other places
+ if ! [ -f "$CERTIFICATES_ROOT_DIR/$CERTIFICATE_NAME" ]; then
+ touch "$CERTIFICATES_ROOT_DIR/$CERTIFICATE_NAME"
+ fi
+
+ done
+
+ # Backwards compatibility with older instances
+ if [ -f "/var/www/html/config/postgres.config.php" ]; then
+ sed -i "s|/var/www/html/data/certificates/POSTGRES|/var/www/html/data/certificates/ca-bundle.crt|" /var/www/html/config/postgres.config.php
+ sed -i "s|/var/www/html/data/certificates/MYSQL|/var/www/html/data/certificates/ca-bundle.crt|" /var/www/html/config/postgres.config.php
+ fi
+
+ # Print out bundle one last time
+ cat "$CERTIFICATE_BUNDLE"
+
+ # Disable debug mode
+ set +x
+fi
+
+# Adjust DATABASE_TYPE to by Nextcloud supported value
+if [ "$DATABASE_TYPE" = postgres ]; then
+ export DATABASE_TYPE=pgsql
+fi
+
+# Only start container if Redis is accessible
# shellcheck disable=SC2153
-while ! nc -z "$REDIS_HOST" "6379"; do
- echo "Waiting for redis to start..."
+while ! nc -z "$REDIS_HOST" "$REDIS_PORT"; do
+ echo "Waiting for Redis to start..."
sleep 5
done
# Check permissions in ncdata
-touch "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" &>/dev/null
-if ! [ -f "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" ]; then
- echo "The www-data user doesn't seem to have access rights in the datadir.
-Most likely are the files located on a drive that does not follow linux permissions.
-Please adjust the permissions like mentioned below.
-The found permissions are:
-$(stat -c "%u:%g %a" "$NEXTCLOUD_DATA_DIR")
-(userID:groupID permissions)
-but they should be:
-33:0 750
-(userID:groupID permissions)
-Also make sure that the parent directories on the host of the directory that you've chosen as datadir are publicly readable with e.g. 'sudo chmod +r /mnt' (adjust the command accordingly to your case) and the same for all subdirectories.
-Additionally, if you want to use a Fuse-mount as datadir, set 'allow_other' as additional mount option.
-For SMB/CIFS mounts as datadir, see https://github.com/nextcloud/all-in-one#can-i-use-a-cifssmb-share-as-nextclouds-datadir"
+test_file="$NEXTCLOUD_DATA_DIR/this-is-a-test-file"
+touch "$test_file"
+if ! [ -f "$test_file" ]; then
+ echo "The www-data user does not appear to have access rights to the data directory."
+ echo "It is possible that the files are on a filesystem that does not support standard Linux permissions,"
+ echo "or the permissions simply need to be adjusted. Please change the permissions as described below."
+ echo "Current permissions are:"
+ stat -c "%u:%g %a" "$NEXTCLOUD_DATA_DIR"
+ echo "(userID:groupID permissions)"
+ echo "They should be:"
+ echo "33:0 750"
+ echo "(userID:groupID permissions)"
+ echo "Also, ensure that all parent directories on the host of your chosen data directory are publicly readable."
+ echo "For example: sudo chmod +r /mnt (adjust this command as needed)."
+ echo "If you want to use a FUSE mount as the data directory, add 'allow_other' as an additional mount option."
+ echo "For SMB/CIFS mounts as the data directory, see:"
+ echo " https://github.com/nextcloud/all-in-one#can-i-use-a-cifssmb-share-as-nextclouds-datadir"
exit 1
fi
-rm "$NEXTCLOUD_DATA_DIR/this-is-a-test-file"
+rm -f "$test_file"
if [ -f /var/www/html/version.php ]; then
# shellcheck disable=SC2016
@@ -66,26 +132,31 @@ fi
# Don't start the container if Nextcloud is not compatible with the PHP version
if [ -f "/var/www/html/lib/versioncheck.php" ] && ! php /var/www/html/lib/versioncheck.php; then
- echo "It seems like your installed Nextcloud is not compatible with the by the container provided PHP version."
- echo "This most likely happened because you tried to restore an old Nextcloud version from backup that is not compatible with the PHP version that comes with the container."
- echo "Please try to restore a more recent backup which contains a Nextcloud version that is compatible with the PHP version that comes with the container."
- echo "If you do not have a more recent backup, feel free to have a look at this documentation: https://github.com/nextcloud/all-in-one/blob/main/manual-upgrade.md"
+ echo "Your installed Nextcloud version is not compatible with the PHP version provided by this image."
+ echo "This typically occurs when you restore an older Nextcloud backup that does not support the"
+ echo "PHP version included in this image."
+ echo "Please restore a more recent backup that includes a compatible Nextcloud version."
+ echo "If you do not have a more recent backup, refer to the manual upgrade documentation:"
+ echo " https://github.com/nextcloud/all-in-one/blob/main/manual-upgrade.md"
exit 1
fi
# Do not start the container if the last update failed
if [ -f "$NEXTCLOUD_DATA_DIR/update.failed" ]; then
echo "The last Nextcloud update failed."
- echo "Please restore from backup and try again!"
- echo "If you do not have a backup in place, you can simply delete the update.failed file in the datadir which will allow the container to start again."
+ echo "Please restore from a backup and try again."
+ echo "If you do not have a backup, you can delete the update.failed file in the data directory"
+ echo "to allow the container to start again."
exit 1
fi
# Do not start the container if the install failed
if [ -f "$NEXTCLOUD_DATA_DIR/install.failed" ]; then
echo "The initial Nextcloud installation failed."
- echo "Please reset AIO properly and try again. For further clues what went wrong, check the logs above."
- echo "See https://github.com/nextcloud/all-in-one#how-to-properly-reset-the-instance"
+ echo "For more information about what went wrong, check the logs above."
+ echo "Please reset AIO properly and try again."
+ echo "See:"
+ echo " https://github.com/nextcloud/all-in-one#how-to-properly-reset-the-instance"
exit 1
fi
@@ -100,20 +171,6 @@ if ! [ -f "$NEXTCLOUD_DATA_DIR/skip.update" ]; then
# Write output to logfile.
exec > >(tee -i "/var/www/html/data/update.log")
exec 2>&1
- # Run built-in upgrader if version is below 28.0.2 to upgrade to 28.0.x first
- touch "$NEXTCLOUD_DATA_DIR/update.failed"
- if ! version_greater "$installed_version" "28.0.1.20"; then
- php /var/www/html/updater/updater.phar --no-interaction --no-backup
- if ! php /var/www/html/occ upgrade || php /var/www/html/occ status | grep maintenance | grep -q 'true'; then
- echo "Upgrade failed. Please restore from backup."
- bash /notify.sh "Nextcloud update to $image_version failed!" "Please restore from backup!"
- exit 1
- fi
- rm "$NEXTCLOUD_DATA_DIR/update.failed"
- # shellcheck disable=SC2016
- installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')"
- INSTALLED_MAJOR="${installed_version%%.*}"
- fi
fi
if [ "$installed_version" != "0.0.0.0" ] && [ "$((IMAGE_MAJOR - INSTALLED_MAJOR))" -gt 1 ]; then
@@ -125,8 +182,11 @@ if ! [ -f "$NEXTCLOUD_DATA_DIR/skip.update" ]; then
curl -fsSL -o nextcloud.tar.bz2.asc "https://download.nextcloud.com/server/releases/latest-${NEXT_MAJOR}.tar.bz2.asc"
GNUPGHOME="$(mktemp -d)"
export GNUPGHOME
- # gpg key from https://nextcloud.com/nextcloud.asc
- gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 28806A878AE423A28372792ED75899B9A724937A
+ if ! gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 28806A878AE423A28372792ED75899B9A724937A; then
+ if ! gpg --batch --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 28806A878AE423A28372792ED75899B9A724937A; then
+ curl -sSL https://nextcloud.com/nextcloud.asc | gpg --import
+ fi
+ fi
gpg --batch --verify nextcloud.tar.bz2.asc nextcloud.tar.bz2
mkdir -p /usr/src/tmp
tar -xjf nextcloud.tar.bz2 -C /usr/src/tmp/
@@ -143,45 +203,54 @@ if ! [ -f "$NEXTCLOUD_DATA_DIR/skip.update" ]; then
rm -r /usr/src/tmp
rm -r /usr/src/temp-nextcloud
# shellcheck disable=SC2016
- image_version="$(php -r "require $SOURCE_LOCATION/version.php; echo implode('.', \$OC_Version);")"
+ image_version="$(php -r "require '$SOURCE_LOCATION/version.php'; echo implode('.', \$OC_Version);")"
IMAGE_MAJOR="${image_version%%.*}"
set +ex
# Do not skip major versions end # Do not remove or change this line!
fi
if [ "$installed_version" != "0.0.0.0" ]; then
+# Check connection to appstore start # Do not remove or change this line!
while true; do
- echo -e "Checking connection to appstore"
- CURL_STATUS="$(curl -LI "https://apps.nextcloud.com/" -o /dev/null -w '%{http_code}\n' -s)"
+ echo -e "Checking connection to the app store..."
+ APPSTORE_URL="https://apps.nextcloud.com/api/v1"
+ if grep -q appstoreurl /var/www/html/config/config.php; then
+ set -x
+ APPSTORE_URL="$(grep appstoreurl /var/www/html/config/config.php | grep -oP 'https://.*v[0-9]+')"
+ set +x
+ fi
+ # Default appstoreurl parameter in config.php defaults to 'https://apps.nextcloud.com/api/v1' so we check for the apps.json file stored in there
+ CURL_STATUS="$(curl -LI "$APPSTORE_URL"/apps.json -o /dev/null -w '%{http_code}\n' -s)"
if [[ "$CURL_STATUS" = "200" ]]
then
- echo "Appstore is reachable"
+ echo "App store is reachable."
break
else
- echo "Curl didn't produce a 200 status, is appstore reachable?"
+ echo "Curl did not return a 200 status. Is the app store reachable?"
sleep 5
fi
done
+# Check connection to appstore end # Do not remove or change this line!
run_upgrade_if_needed_due_to_app_update
php /var/www/html/occ maintenance:mode --off
- echo "Getting and backing up the status of apps for later, this might take a while..."
+ echo "Getting and backing up the status of apps for later; this might take a while..."
NC_APPS="$(find /var/www/html/custom_apps/ -type d -maxdepth 1 -mindepth 1 | sed 's|/var/www/html/custom_apps/||g')"
if [ -z "$NC_APPS" ]; then
- echo "No apps detected, aborting export of app status..."
+ echo "No apps detected. Aborting export of app status..."
APPSTORAGE="no-export-done"
else
mapfile -t NC_APPS_ARRAY <<< "$NC_APPS"
declare -Ag APPSTORAGE
- echo "Disabling apps before the update in order to make the update procedure more safe. This can take a while..."
+ echo "Disabling apps before the update to make the update procedure safer. This can take a while..."
for app in "${NC_APPS_ARRAY[@]}"; do
if APPSTORAGE[$app]="$(php /var/www/html/occ config:app:get "$app" enabled)"; then
php /var/www/html/occ app:disable "$app"
else
APPSTORAGE[$app]=""
- echo "Not disabling $app because the occ command to get the enabled state was failing."
+ echo "Not disabling $app because the occ command to get its enabled state failed."
fi
done
fi
@@ -193,29 +262,63 @@ if ! [ -f "$NEXTCLOUD_DATA_DIR/skip.update" ]; then
php /var/www/html/occ app:update --all
run_upgrade_if_needed_due_to_app_update
-
- # Fix removing the updatenotification for old instances
- UPDATENOTIFICATION_STATUS="$(php /var/www/html/occ config:app:get updatenotification enabled)"
- if [ -d "/var/www/html/apps/updatenotification" ]; then
- php /var/www/html/occ app:disable updatenotification
- elif [ "$UPDATENOTIFICATION_STATUS" != "no" ] && [ -n "$UPDATENOTIFICATION_STATUS" ]; then
- php /var/www/html/occ config:app:set updatenotification enabled --value="no"
- fi
fi
- echo "Initializing nextcloud $image_version ..."
- rsync -rlD --delete --exclude-from=/upgrade.exclude "$SOURCE_LOCATION/" /var/www/html/
+ echo "Initializing Nextcloud $image_version ..."
+ # Copy over initial data from Nextcloud archive
+ rsync -rlD --delete \
+ --exclude-from=/upgrade.exclude \
+ "$SOURCE_LOCATION/" \
+ /var/www/html/
+
+ # Copy custom_apps from Nextcloud archive
+ if ! directory_empty "$SOURCE_LOCATION/custom_apps"; then
+ set -x
+ for app in "$SOURCE_LOCATION/custom_apps"/*; do
+ app_id="$(basename "$app")"
+ mkdir -p "/var/www/html/custom_apps/$app_id"
+ rsync -rlD --delete \
+ --include "/$app_id/" \
+ --exclude '/*' \
+ "$SOURCE_LOCATION/custom_apps/" \
+ /var/www/html/custom_apps/
+ done
+ set +x
+ fi
+
+ # Copy these from Nextcloud archive if they don't exist yet (i.e. new install)
for dir in config data custom_apps themes; do
if [ ! -d "/var/www/html/$dir" ] || directory_empty "/var/www/html/$dir"; then
- rsync -rlD --include "/$dir/" --exclude '/*' "$SOURCE_LOCATION/" /var/www/html/
+ rsync -rlD \
+ --include "/$dir/" \
+ --exclude '/*' \
+ "$SOURCE_LOCATION/" \
+ /var/www/html/
fi
done
- rsync -rlD --delete --include '/config/' --exclude '/*' --exclude '/config/CAN_INSTALL' --exclude '/config/config.sample.php' --exclude '/config/config.php' "$SOURCE_LOCATION/" /var/www/html/
- rsync -rlD --include '/version.php' --exclude '/*' "$SOURCE_LOCATION/" /var/www/html/
+
+ rsync -rlD --delete \
+ --include '/config/' \
+ --exclude '/*' \
+ --exclude '/config/CAN_INSTALL' \
+ --exclude '/config/config.sample.php' \
+ --exclude '/config/config.php' \
+ "$SOURCE_LOCATION/" \
+ /var/www/html/
+
+ rsync -rlD \
+ --include '/version.php' \
+ --exclude '/*' \
+ "$SOURCE_LOCATION/" \
+ /var/www/html/
+
echo "Initializing finished"
- #install
+ ################
+ # Fresh Install
+ ################
+
if [ "$installed_version" = "0.0.0.0" ]; then
echo "New Nextcloud instance."
@@ -229,21 +332,31 @@ if ! [ -f "$NEXTCLOUD_DATA_DIR/skip.update" ]; then
INSTALL_OPTIONS+=(--data-dir "$NEXTCLOUD_DATA_DIR")
fi
- # We do our own permission check so the permission check is not needed
- cat << DATADIR_PERMISSION_CONF > /var/www/html/config/datadir.permission.config.php
+ # Skip the default permission check (we do our own)
+ cat > /var/www/html/config/datadir.permission.config.php <<'EOF'
false
-);
-DATADIR_PERMISSION_CONF
+ $CONFIG = array (
+ 'check_data_directory_permissions' => false
+ );
+EOF
- echo "Installing with PostgreSQL database"
+ echo "Installing with $DATABASE_TYPE database"
# Set a default value for POSTGRES_PORT
if [ -z "$POSTGRES_PORT" ]; then
- POSTGRES_PORT=5432
+ POSTGRES_PORT=5432
fi
- INSTALL_OPTIONS+=(--database pgsql --database-name "$POSTGRES_DB" --database-user "$POSTGRES_USER" --database-pass "$POSTGRES_PASSWORD" --database-host "$POSTGRES_HOST" --database-port "$POSTGRES_PORT")
+ # Add database options to INSTALL_OPTIONS
+ # shellcheck disable=SC2153
+ INSTALL_OPTIONS+=(
+ --database "$DATABASE_TYPE"
+ --database-name "$POSTGRES_DB"
+ --database-user "$POSTGRES_USER"
+ --database-pass "$POSTGRES_PASSWORD"
+ --database-host "$POSTGRES_HOST"
+ --database-port "$POSTGRES_PORT"
+ )
+
echo "Starting Nextcloud installation..."
if ! php /var/www/html/occ maintenance:install "${INSTALL_OPTIONS[@]}"; then
echo "Installation of Nextcloud failed!"
@@ -265,7 +378,7 @@ DATADIR_PERMISSION_CONF
if [ "$try" -ge "$max_retries" ]; then
echo "Installation of Nextcloud failed!"
- echo "Install errors: $(cat /var/www/html/data/nextcloud.log)"
+ echo "Installation errors: $(cat /var/www/html/data/nextcloud.log)"
touch "$NEXTCLOUD_DATA_DIR/install.failed"
exit 1
fi
@@ -277,6 +390,10 @@ DATADIR_PERMISSION_CONF
# unset admin password
unset ADMIN_PASSWORD
+ # Enable the updatenotification app but disable its UI and server update notifications
+ php /var/www/html/occ config:system:set updatechecker --type=bool --value=false
+ php /var/www/html/occ config:app:set updatenotification notify_groups --value="[]"
+
# AIO update to latest start # Do not remove or change this line!
if [ "$INSTALL_LATEST_MAJOR" = yes ]; then
php /var/www/html/occ config:system:set updatedirectory --value="/nc-updater"
@@ -297,18 +414,19 @@ DATADIR_PERMISSION_CONF
installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')"
INSTALLED_MAJOR="${installed_version%%.*}"
IMAGE_MAJOR="${image_version%%.*}"
+ # If a valid upgrade path, trigger the Nextcloud built-in Updater
if ! [ "$INSTALLED_MAJOR" -gt "$IMAGE_MAJOR" ]; then
php /var/www/html/updater/updater.phar --no-interaction --no-backup
if ! php /var/www/html/occ -V || php /var/www/html/occ status | grep maintenance | grep -q 'true'; then
echo "Installation of Nextcloud failed!"
+ # TODO: Add a hint here about what to do / where to look / updater.log?
touch "$NEXTCLOUD_DATA_DIR/install.failed"
exit 1
fi
# shellcheck disable=SC2016
installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')"
fi
- php /var/www/html/occ app:disable updatenotification
- rm -rf /var/www/html/apps/updatenotification
+ php /var/www/html/occ config:system:set updatechecker --type=bool --value=true
php /var/www/html/occ app:enable nextcloud-aio --force
php /var/www/html/occ db:add-missing-columns
php /var/www/html/occ db:add-missing-primary-keys
@@ -354,15 +472,13 @@ DATADIR_PERMISSION_CONF
php /var/www/html/occ config:system:set activity_expire_days --value="30" --type=integer
php /var/www/html/occ config:system:set simpleSignUpLink.shown --type=bool --value=false
php /var/www/html/occ config:system:set share_folder --value="/Shared"
- # Not needed anymore with the removal of the updatenotification app:
- # php /var/www/html/occ config:app:set updatenotification notify_groups --value="[]"
# Install some apps by default
if [ -n "$STARTUP_APPS" ]; then
read -ra STARTUP_APPS_ARRAY <<< "$STARTUP_APPS"
for app in "${STARTUP_APPS_ARRAY[@]}"; do
if ! echo "$app" | grep -q '^-'; then
- if [ -z "$(find /var/www/html/apps -type d -maxdepth 1 -mindepth 1 -name "$app" )" ]; then
+ if [ -z "$(find /var/www/html/apps /var/www/html/custom_apps -type d -maxdepth 1 -mindepth 1 -name "$app" )" ]; then
# If not shipped, install and enable the app
php /var/www/html/occ app:install "$app"
else
@@ -380,11 +496,11 @@ DATADIR_PERMISSION_CONF
#upgrade
else
touch "$NEXTCLOUD_DATA_DIR/update.failed"
- echo "Upgrading nextcloud from $installed_version to $image_version..."
+ echo "Upgrading Nextcloud from $installed_version to $image_version..."
php /var/www/html/occ config:system:delete integrity.check.disabled
if ! php /var/www/html/occ upgrade || ! php /var/www/html/occ -V; then
echo "Upgrade failed. Please restore from backup."
- bash /notify.sh "Nextcloud update to $image_version failed!" "Please restore from backup!"
+ bash /notify.sh "Nextcloud update to $image_version failed!" "Please restore from backup."
exit 1
fi
@@ -392,7 +508,7 @@ DATADIR_PERMISSION_CONF
installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')"
rm "$NEXTCLOUD_DATA_DIR/update.failed"
- bash /notify.sh "Nextcloud update to $image_version successful!" "Feel free to inspect the Nextcloud container logs for more info."
+ bash /notify.sh "Nextcloud update to $image_version successful!" "You may inspect the Nextcloud container logs for more information."
php /var/www/html/occ app:update --all
@@ -400,7 +516,7 @@ DATADIR_PERMISSION_CONF
# Restore app status
if [ "${APPSTORAGE[0]}" != "no-export-done" ]; then
- echo "Restoring the status of apps. This can take a while..."
+ echo "Restoring app statuses. This may take a while..."
for app in "${!APPSTORAGE[@]}"; do
if [ -n "${APPSTORAGE[$app]}" ]; then
if [ "${APPSTORAGE[$app]}" != "no" ]; then
@@ -412,13 +528,13 @@ DATADIR_PERMISSION_CONF
php /var/www/html/occ maintenance:mode --off
fi
run_upgrade_if_needed_due_to_app_update
- echo "The $app app could not get enabled. Probably because it is not compatible with the new Nextcloud version."
+ echo "The $app app could not be re-enabled, probably because it is not compatible with the new Nextcloud version."
if [ "$app" = apporder ]; then
CUSTOM_HINT="The apporder app was deprecated. A possible replacement is the side_menu app, aka 'Custom menu'."
else
- CUSTOM_HINT="Most likely because it is not compatible with the new Nextcloud version."
+ CUSTOM_HINT="Most likely, it is not compatible with the new Nextcloud version."
fi
- bash /notify.sh "Could not enable the $app app after the Nextcloud update!" "$CUSTOM_HINT Feel free to look at the Nextcloud update logs and force-enable the app again from the app-store UI."
+ bash /notify.sh "Could not re-enable the $app app after the Nextcloud update!" "$CUSTOM_HINT Feel free to review the Nextcloud update logs and force-enable the app again if you wish."
continue
fi
# Only restore the group settings, if the app was enabled (and is thus compatible with the new NC version)
@@ -434,8 +550,13 @@ DATADIR_PERMISSION_CONF
run_upgrade_if_needed_due_to_app_update
+ # Enable the updatenotification app but disable its UI and server update notifications
+ php /var/www/html/occ config:system:set updatechecker --type=bool --value=false
+ php /var/www/html/occ app:enable updatenotification
+ php /var/www/html/occ config:app:set updatenotification notify_groups --value="[]"
+
# Apply optimization
- echo "Doing some optimizations..."
+ echo "Performing some optimizations..."
if [ "$NEXTCLOUD_SKIP_DATABASE_OPTIMIZATION" != yes ]; then
php /var/www/html/occ maintenance:repair --include-expensive
php /var/www/html/occ db:add-missing-indices
@@ -466,10 +587,10 @@ if [ -z "$OBJECTSTORE_S3_BUCKET" ] && [ -z "$OBJECTSTORE_SWIFT_URL" ]; then
# Check if appdata is present
# If not, something broke (e.g. changing ncdatadir after aio was first started)
if [ -z "$(find "$NEXTCLOUD_DATA_DIR/" -maxdepth 1 -mindepth 1 -type d -name "appdata_*")" ]; then
- echo "Appdata is not present. Did you maybe change the datadir after the initial Nextcloud installation? This is not supported!"
+ echo "Appdata is not present. Did you change the datadir after the initial Nextcloud installation? This is not supported!"
echo "See https://github.com/nextcloud/all-in-one#how-to-change-the-default-location-of-nextclouds-datadir"
- echo "If you adjusted the datadir to be located on an external drive, make sure that the drive is still mounted!"
- echo "In the datadir was found:"
+ echo "If you moved the datadir to an external drive, make sure that the drive is still mounted."
+ echo "The following was found in the datadir:"
ls -la "$NEXTCLOUD_DATA_DIR/"
exit 1
fi
@@ -490,6 +611,12 @@ if [ -f "$NEXTCLOUD_DATA_DIR/fingerprint.update" ]; then
rm "$NEXTCLOUD_DATA_DIR/fingerprint.update"
fi
+# Perform preview scan if previews were excluded from restore
+if [ -f "$NEXTCLOUD_DATA_DIR/trigger-preview.scan" ]; then
+ php /var/www/html/occ files:scan-app-data preview -vvv
+ rm "$NEXTCLOUD_DATA_DIR/trigger-preview.scan"
+fi
+
# AIO one-click settings start # Do not remove or change this line!
# Apply one-click-instance settings
echo "Applying one-click-instance settings..."
@@ -516,6 +643,13 @@ php /var/www/html/occ config:system:set upgrade.cli-upgrade-link --value="https:
php /var/www/html/occ config:system:set logfile --value="/var/www/html/data/nextcloud.log"
php /var/www/html/occ config:app:set admin_audit logfile --value="/var/www/html/data/audit.log"
php /var/www/html/occ config:system:set updatedirectory --value="/nc-updater"
+if [ -n "$NEXTCLOUD_SKELETON_DIRECTORY" ]; then
+ if [ "$NEXTCLOUD_SKELETON_DIRECTORY" = "empty" ]; then
+ php /var/www/html/occ config:system:set skeletondirectory --value=""
+ else
+ php /var/www/html/occ config:system:set skeletondirectory --value="$NEXTCLOUD_SKELETON_DIRECTORY"
+ fi
+fi
if [ -n "$SERVERINFO_TOKEN" ] && [ -z "$(php /var/www/html/occ config:app:get serverinfo token)" ]; then
php /var/www/html/occ config:app:set serverinfo token --value="$SERVERINFO_TOKEN"
fi
@@ -531,6 +665,7 @@ php /var/www/html/occ config:system:set allow_local_remote_servers --type=bool -
php /var/www/html/occ config:system:set davstorage.request_timeout --value="$PHP_MAX_TIME" --type=int
php /var/www/html/occ config:system:set trusted_domains 1 --value="$NC_DOMAIN"
php /var/www/html/occ config:system:set overwrite.cli.url --value="https://$NC_DOMAIN/"
+php /var/www/html/occ config:system:set documentation_url.server_logs --value="https://github.com/nextcloud/all-in-one/discussions/5425"
php /var/www/html/occ config:system:set htaccess.RewriteBase --value="/"
php /var/www/html/occ maintenance:update:htaccess
@@ -580,12 +715,17 @@ if [ -n "$ADDITIONAL_TRUSTED_PROXY" ]; then
php /var/www/html/occ config:system:set trusted_proxies 2 --value="$ADDITIONAL_TRUSTED_PROXY"
fi
-# Get ipv4-address of Nextcloud
-IPv4_ADDRESS="$(dig nextcloud-aio-nextcloud A +short +search | head -1)"
+# Get ipv4-address of Nextcloud
+if [ -z "$NEXTCLOUD_HOST" ]; then
+ export NEXTCLOUD_HOST="nextcloud-aio-nextcloud"
+fi
+IPv4_ADDRESS="$(dig "$NEXTCLOUD_HOST" A +short +search | head -1)"
# Bring it in CIDR notation
# shellcheck disable=SC2001
IPv4_ADDRESS="$(echo "$IPv4_ADDRESS" | sed 's|[0-9]\+$|0/16|')"
-php /var/www/html/occ config:system:set trusted_proxies 10 --value="$IPv4_ADDRESS"
+if [ -n "$IPv4_ADDRESS" ]; then
+ php /var/www/html/occ config:system:set trusted_proxies 10 --value="$IPv4_ADDRESS"
+fi
if [ -n "$ADDITIONAL_TRUSTED_DOMAIN" ]; then
php /var/www/html/occ config:system:set trusted_domains 2 --value="$ADDITIONAL_TRUSTED_DOMAIN"
@@ -624,7 +764,7 @@ if [ "$COLLABORA_ENABLED" = 'yes' ]; then
fi
fi
else
- echo "Warning: No ipv4-address found for $COLLABORA_HOST."
+ echo "Warning: No IPv4 address found for $COLLABORA_HOST."
fi
if [ -n "$COLLABORA_IPv6_ADDRESS" ]; then
if ! echo "$COLLABORA_ALLOW_LIST" | grep -q "$COLLABORA_IPv6_ADDRESS"; then
@@ -635,10 +775,10 @@ if [ "$COLLABORA_ENABLED" = 'yes' ]; then
fi
fi
else
- echo "No ipv6-address found for $COLLABORA_HOST."
+ echo "No IPv6 address found for $COLLABORA_HOST."
fi
if [ -n "$COLLABORA_ALLOW_LIST" ]; then
- PRIVATE_IP_RANGES='127.0.0.1/8,192.168.0.0/16,172.16.0.0/12,10.0.0.0/8,fd00::/8,::1'
+ PRIVATE_IP_RANGES='127.0.0.0/8,192.168.0.0/16,172.16.0.0/12,10.0.0.0/8,100.64.0.0/10,fd00::/8,::1/128'
if ! echo "$COLLABORA_ALLOW_LIST" | grep -q "$PRIVATE_IP_RANGES"; then
COLLABORA_ALLOW_LIST+=",$PRIVATE_IP_RANGES"
fi
@@ -649,7 +789,7 @@ if [ "$COLLABORA_ENABLED" = 'yes' ]; then
fi
php /var/www/html/occ config:app:set richdocuments wopi_allowlist --value="$COLLABORA_ALLOW_LIST"
else
- echo "Warning: wopi_allowlist is empty which should not be the case!"
+ echo "Warning: wopi_allowlist is empty; this should not be the case!"
fi
else
if [ "$REMOVE_DISABLED_APPS" = yes ] && [ -d "/var/www/html/custom_apps/richdocuments" ]; then
@@ -659,23 +799,52 @@ fi
# OnlyOffice
if [ "$ONLYOFFICE_ENABLED" = 'yes' ]; then
- while ! nc -z "$ONLYOFFICE_HOST" 80; do
- echo "waiting for OnlyOffice to become available..."
+ # Determine OnlyOffice port based on host pattern
+ if echo "$ONLYOFFICE_HOST" | grep -q "nextcloud-.*-onlyoffice"; then
+ ONLYOFFICE_PORT=80
+ else
+ ONLYOFFICE_PORT=443
+ fi
+
+ count=0
+ while ! nc -z "$ONLYOFFICE_HOST" "$ONLYOFFICE_PORT" && [ "$count" -lt 90 ]; do
+ echo "Waiting for OnlyOffice to become available..."
+ count=$((count+5))
sleep 5
done
- if ! [ -d "/var/www/html/custom_apps/onlyoffice" ]; then
- php /var/www/html/occ app:install onlyoffice
- elif [ "$(php /var/www/html/occ config:app:get onlyoffice enabled)" != "yes" ]; then
- php /var/www/html/occ app:enable onlyoffice
- elif [ "$SKIP_UPDATE" != 1 ]; then
- php /var/www/html/occ app:update onlyoffice
+ if [ "$count" -ge 90 ]; then
+ bash /notify.sh "Onlyoffice did not start in time!" "Skipping initialization and disabling onlyoffice app."
+ php /var/www/html/occ app:disable onlyoffice
+ else
+ # Install or enable OnlyOffice app as needed
+ if ! [ -d "/var/www/html/custom_apps/onlyoffice" ]; then
+ php /var/www/html/occ app:install onlyoffice
+ elif [ "$(php /var/www/html/occ config:app:get onlyoffice enabled)" != "yes" ]; then
+ php /var/www/html/occ app:enable onlyoffice
+ elif [ "$SKIP_UPDATE" != 1 ]; then
+ php /var/www/html/occ app:update onlyoffice
+ fi
+
+ # Set OnlyOffice configuration
+ php /var/www/html/occ config:system:set onlyoffice editors_check_interval --value="0" --type=integer
+ php /var/www/html/occ config:system:set onlyoffice jwt_secret --value="$ONLYOFFICE_SECRET"
+ php /var/www/html/occ config:app:set onlyoffice jwt_secret --value="$ONLYOFFICE_SECRET"
+ php /var/www/html/occ config:system:set onlyoffice jwt_header --value="AuthorizationJwt"
+
+ # Adjust the OnlyOffice host if using internal pattern
+ if echo "$ONLYOFFICE_HOST" | grep -q "nextcloud-.*-onlyoffice"; then
+ ONLYOFFICE_HOST="$NC_DOMAIN/onlyoffice"
+ export ONLYOFFICE_HOST
+ fi
+
+ php /var/www/html/occ config:app:set onlyoffice DocumentServerUrl --value="https://$ONLYOFFICE_HOST"
fi
- php /var/www/html/occ config:system:set onlyoffice jwt_secret --value="$ONLYOFFICE_SECRET"
- php /var/www/html/occ config:app:set onlyoffice jwt_secret --value="$ONLYOFFICE_SECRET"
- php /var/www/html/occ config:system:set onlyoffice jwt_header --value="AuthorizationJwt"
- php /var/www/html/occ config:app:set onlyoffice DocumentServerUrl --value="https://$NC_DOMAIN/onlyoffice"
else
- if [ "$REMOVE_DISABLED_APPS" = yes ] && [ -d "/var/www/html/custom_apps/onlyoffice" ] && [ -n "$ONLYOFFICE_SECRET" ] && [ "$(php /var/www/html/occ config:system:get onlyoffice jwt_secret)" = "$ONLYOFFICE_SECRET" ]; then
+ # Remove OnlyOffice app if disabled and removal is requested
+ if [ "$REMOVE_DISABLED_APPS" = yes ] && \
+ [ -d "/var/www/html/custom_apps/onlyoffice" ] && \
+ [ -n "$ONLYOFFICE_SECRET" ] && \
+ [ "$(php /var/www/html/occ config:system:get onlyoffice jwt_secret)" = "$ONLYOFFICE_SECRET" ]; then
php /var/www/html/occ app:remove onlyoffice
fi
fi
@@ -721,14 +890,16 @@ fi
if [ -d "/var/www/html/custom_apps/spreed" ]; then
if [ "$TALK_RECORDING_ENABLED" = 'yes' ]; then
while ! nc -z "$TALK_RECORDING_HOST" 1234; do
- echo "waiting for Talk Recording to become available..."
+ echo "Waiting for Talk Recording to become available..."
sleep 5
done
# TODO: migrate to occ command if that becomes available
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
@@ -736,12 +907,12 @@ fi
if [ "$CLAMAV_ENABLED" = 'yes' ]; then
count=0
while ! nc -z "$CLAMAV_HOST" 3310 && [ "$count" -lt 90 ]; do
- echo "waiting for clamav to become available..."
+ echo "Waiting for ClamAV to become available..."
count=$((count+5))
sleep 5
done
if [ "$count" -ge 90 ]; then
- echo "Clamav did not start in time. Skipping initialization and disabling files_antivirus app."
+ bash /notify.sh "ClamAV did not start in time!" "Skipping initialization and disabling files_antivirus app."
php /var/www/html/occ app:disable files_antivirus
else
if ! [ -d "/var/www/html/custom_apps/files_antivirus" ]; then
@@ -754,9 +925,13 @@ 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"
- php /var/www/html/occ config:app:set files_antivirus av_max_file_size --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
+ php /var/www/html/occ config:app:set files_antivirus av_blocklisted_directories --value="$CLAMAV_BLOCKLISTED_DIRECTORIES"
+ fi
fi
else
if [ "$REMOVE_DISABLED_APPS" = yes ] && [ -d "/var/www/html/custom_apps/files_antivirus" ]; then
@@ -767,6 +942,7 @@ fi
# Imaginary
if [ "$IMAGINARY_ENABLED" = 'yes' ]; then
php /var/www/html/occ config:system:set enabledPreviewProviders 0 --value="OC\\Preview\\Imaginary"
+ php /var/www/html/occ config:system:set enabledPreviewProviders 23 --value="OC\\Preview\\ImaginaryPDF"
php /var/www/html/occ config:system:set preview_imaginary_url --value="http://$IMAGINARY_HOST:9000"
php /var/www/html/occ config:system:set preview_imaginary_key --value="$IMAGINARY_SECRET"
else
@@ -776,50 +952,63 @@ else
php /var/www/html/occ config:system:delete enabledPreviewProviders 20
php /var/www/html/occ config:system:delete enabledPreviewProviders 21
php /var/www/html/occ config:system:delete enabledPreviewProviders 22
+ php /var/www/html/occ config:system:delete enabledPreviewProviders 23
fi
fi
# Fulltextsearch
if [ "$FULLTEXTSEARCH_ENABLED" = 'yes' ]; then
- while ! nc -z "$FULLTEXTSEARCH_HOST" 9200; do
- echo "waiting for Fulltextsearch to become available..."
+ count=0
+ while ! nc -z "$FULLTEXTSEARCH_HOST" "$FULLTEXTSEARCH_PORT" && [ "$count" -lt 90 ]; do
+ echo "Waiting for Fulltextsearch to become available..."
+ count=$((count+5))
sleep 5
done
- if ! [ -d "/var/www/html/custom_apps/fulltextsearch" ]; then
- php /var/www/html/occ app:install fulltextsearch
- elif [ "$(php /var/www/html/occ config:app:get fulltextsearch enabled)" != "yes" ]; then
- php /var/www/html/occ app:enable fulltextsearch
- elif [ "$SKIP_UPDATE" != 1 ]; then
- php /var/www/html/occ app:update fulltextsearch
- fi
- if ! [ -d "/var/www/html/custom_apps/fulltextsearch_elasticsearch" ]; then
- php /var/www/html/occ app:install fulltextsearch_elasticsearch
- elif [ "$(php /var/www/html/occ config:app:get fulltextsearch_elasticsearch enabled)" != "yes" ]; then
- php /var/www/html/occ app:enable fulltextsearch_elasticsearch
- elif [ "$SKIP_UPDATE" != 1 ]; then
- php /var/www/html/occ app:update fulltextsearch_elasticsearch
- fi
- if ! [ -d "/var/www/html/custom_apps/files_fulltextsearch" ]; then
- php /var/www/html/occ app:install files_fulltextsearch
- elif [ "$(php /var/www/html/occ config:app:get files_fulltextsearch enabled)" != "yes" ]; then
- php /var/www/html/occ app:enable files_fulltextsearch
- elif [ "$SKIP_UPDATE" != 1 ]; then
- php /var/www/html/occ app:update files_fulltextsearch
- 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://elastic:$FULLTEXTSEARCH_PASSWORD@$FULLTEXTSEARCH_HOST:9200\",\"elastic_index\":\"nextcloud-aio\"}"
- php /var/www/html/occ files_fulltextsearch:configure "{\"files_pdf\":\"1\",\"files_office\":\"1\"}"
+ if [ "$count" -ge 90 ]; then
+ echo "Fulltextsearch did not start in time. Skipping initialization and disabling fulltextsearch apps."
+ php /var/www/html/occ app:disable fulltextsearch
+ php /var/www/html/occ app:disable fulltextsearch_elasticsearch
+ php /var/www/html/occ app:disable files_fulltextsearch
+ else
+ if [ -z "$FULLTEXTSEARCH_PROTOCOL" ]; then
+ FULLTEXTSEARCH_PROTOCOL="http"
+ fi
+ if ! [ -d "/var/www/html/custom_apps/fulltextsearch" ]; then
+ php /var/www/html/occ app:install fulltextsearch
+ elif [ "$(php /var/www/html/occ config:app:get fulltextsearch enabled)" != "yes" ]; then
+ php /var/www/html/occ app:enable fulltextsearch
+ elif [ "$SKIP_UPDATE" != 1 ]; then
+ php /var/www/html/occ app:update fulltextsearch
+ fi
+ if ! [ -d "/var/www/html/custom_apps/fulltextsearch_elasticsearch" ]; then
+ php /var/www/html/occ app:install fulltextsearch_elasticsearch
+ elif [ "$(php /var/www/html/occ config:app:get fulltextsearch_elasticsearch enabled)" != "yes" ]; then
+ php /var/www/html/occ app:enable fulltextsearch_elasticsearch
+ elif [ "$SKIP_UPDATE" != 1 ]; then
+ php /var/www/html/occ app:update fulltextsearch_elasticsearch
+ fi
+ if ! [ -d "/var/www/html/custom_apps/files_fulltextsearch" ]; then
+ php /var/www/html/occ app:install files_fulltextsearch
+ elif [ "$(php /var/www/html/occ config:app:get files_fulltextsearch enabled)" != "yes" ]; then
+ php /var/www/html/occ app:enable files_fulltextsearch
+ elif [ "$SKIP_UPDATE" != 1 ]; then
+ php /var/www/html/occ app:update files_fulltextsearch
+ 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\":\"$FULLTEXTSEARCH_PROTOCOL://$FULLTEXTSEARCH_USER:$FULLTEXTSEARCH_PASSWORD@$FULLTEXTSEARCH_HOST:$FULLTEXTSEARCH_PORT\",\"elastic_index\":\"$FULLTEXTSEARCH_INDEX\"}"
+ 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
- echo "Waiting 10s before activating FTS..."
- sleep 10
- echo "Activating fulltextsearch..."
- if php /var/www/html/occ fulltextsearch:test && php /var/www/html/occ fulltextsearch:index "{\"errors\": \"reset\"}" --no-readline; then
- touch "$NEXTCLOUD_DATA_DIR/fts-index.done"
- else
- echo "Fulltextsearch failed. Could not index."
- echo "Feel free to follow https://github.com/nextcloud/all-in-one/discussions/1709 if you want to skip the indexing in the future."
+ # Do the index
+ if ! [ -f "$NEXTCLOUD_DATA_DIR/fts-index.done" ]; then
+ echo "Waiting 10 seconds before activating fulltextsearch..."
+ sleep 10
+ echo "Activating fulltextsearch..."
+ if php /var/www/html/occ fulltextsearch:test && php /var/www/html/occ fulltextsearch:index "{\"errors\": \"reset\"}" --no-readline; then
+ touch "$NEXTCLOUD_DATA_DIR/fts-index.done"
+ else
+ echo "Fulltextsearch failed. Could not index."
+ echo "If you want to skip indexing in the future, see https://github.com/nextcloud/all-in-one/discussions/1709"
+ fi
fi
fi
else
@@ -837,17 +1026,20 @@ else
fi
# Docker socket proxy
+# app_api is a shipped app
+if [ -d "/var/www/html/custom_apps/app_api" ]; then
+ php /var/www/html/occ app:disable app_api
+ rm -r "/var/www/html/custom_apps/app_api"
+fi
if [ "$DOCKER_SOCKET_PROXY_ENABLED" = 'yes' ]; then
- if ! [ -d "/var/www/html/custom_apps/app_api" ]; then
- php /var/www/html/occ app:install app_api
- elif [ "$(php /var/www/html/occ config:app:get app_api enabled)" != "yes" ]; then
+ if [ "$(php /var/www/html/occ config:app:get app_api enabled)" != "yes" ]; then
php /var/www/html/occ app:enable app_api
- elif [ "$SKIP_UPDATE" != 1 ]; then
- php /var/www/html/occ app:update app_api
fi
else
- if [ "$REMOVE_DISABLED_APPS" = yes ] && [ -d "/var/www/html/custom_apps/app_api" ]; then
- php /var/www/html/occ app:remove app_api
+ if [ "$REMOVE_DISABLED_APPS" = yes ]; then
+ if [ "$(php /var/www/html/occ config:app:get app_api enabled)" != "no" ]; then
+ php /var/www/html/occ app:disable app_api
+ fi
fi
fi
diff --git a/Containers/nextcloud/notify-all.sh b/Containers/nextcloud/notify-all.sh
index b11130d1..f4dfa0fd 100644
--- a/Containers/nextcloud/notify-all.sh
+++ b/Containers/nextcloud/notify-all.sh
@@ -20,7 +20,7 @@ mapfile -t NC_USERS <<< "$NC_USERS"
for user in "${NC_USERS[@]}"
do
echo "Posting '$SUBJECT' to: $user"
- "${COMMAND[@]}" notification:generate "$user" "$NC_DOMAIN: $SUBJECT" -l "$MESSAGE"
+ "${COMMAND[@]}" notification:generate "$user" "$NC_DOMAIN: $SUBJECT" -l "$MESSAGE" --object-type='update' --object-id="$SUBJECT"
done
echo "Done!"
diff --git a/Containers/nextcloud/notify.sh b/Containers/nextcloud/notify.sh
index f74ec16b..2ac4ceac 100644
--- a/Containers/nextcloud/notify.sh
+++ b/Containers/nextcloud/notify.sh
@@ -28,7 +28,7 @@ done
for admin in "${NC_ADMIN_USER[@]}"
do
echo "Posting '$SUBJECT' to: $admin"
- "${COMMAND[@]}" notification:generate "$admin" "$NC_DOMAIN: $SUBJECT" -l "$MESSAGE"
+ "${COMMAND[@]}" notification:generate "$admin" "$NC_DOMAIN: $SUBJECT" -l "$MESSAGE" --object-type='update' --object-id="$SUBJECT"
done
echo "Done!"
diff --git a/Containers/nextcloud/root.motd b/Containers/nextcloud/root.motd
index d3cae8a9..00cb4805 100644
--- a/Containers/nextcloud/root.motd
+++ b/Containers/nextcloud/root.motd
@@ -1,4 +1,4 @@
Warning: You have logged in into the Nextcloud container as root user.
See https://github.com/nextcloud/all-in-one#how-to-run-occ-commands if you want to run occ commands.
-Apart from that, you can use 'sudo -u www-data -E php occ ' in order to run occ commands.
+Apart from that, you can use 'sudo -E -u www-data php occ ' in order to run occ commands.
Of course needs to be substituted with the command that you want to use.
diff --git a/Containers/nextcloud/run-exec-commands.sh b/Containers/nextcloud/run-exec-commands.sh
index ab3abab7..e8066881 100644
--- a/Containers/nextcloud/run-exec-commands.sh
+++ b/Containers/nextcloud/run-exec-commands.sh
@@ -1,7 +1,10 @@
#!/bin/bash
-# Wait 15s for domain to be reachable
-sleep 15
+# Wait until the apache container is ready
+while ! nc -z "$APACHE_HOST" "$APACHE_PORT"; do
+ echo "Waiting for $APACHE_HOST to become available..."
+ sleep 15
+done
if [ -n "$NEXTCLOUD_EXEC_COMMANDS" ]; then
echo "#!/bin/bash" > /tmp/nextcloud-exec-commands
@@ -16,11 +19,13 @@ else
echo "Activating Collabora config..."
php /var/www/html/occ richdocuments:activate-config
fi
- # OnlyOffice must work also if using manual-install
- if [ "$ONLYOFFICE_ENABLED" = yes ]; then
- echo "Activating OnlyOffice config..."
- php /var/www/html/occ onlyoffice:documentserver --check
- fi
fi
-sleep inf
+signal_handler() {
+ exit 0
+}
+
+trap signal_handler SIGINT SIGTERM
+
+sleep inf &
+wait $!
diff --git a/Containers/nextcloud/start.sh b/Containers/nextcloud/start.sh
index 0bbea739..a5f38534 100644
--- a/Containers/nextcloud/start.sh
+++ b/Containers/nextcloud/start.sh
@@ -8,7 +8,7 @@ fi
# Only start container if database is accessible
# POSTGRES_HOST must be set in the containers env vars and POSTGRES_PORT has a default above
# shellcheck disable=SC2153
-while ! sudo -u www-data nc -z "$POSTGRES_HOST" "$POSTGRES_PORT"; do
+while ! sudo -E -u www-data nc -z "$POSTGRES_HOST" "$POSTGRES_PORT"; do
echo "Waiting for database to start..."
sleep 5
done
@@ -17,10 +17,15 @@ done
POSTGRES_USER="oc_$POSTGRES_USER"
export POSTGRES_USER
+# Check that db type is not empty
+if [ -z "$DATABASE_TYPE" ]; then
+ export DATABASE_TYPE=postgres
+fi
+
# Fix false database connection on old instances
if [ -f "/var/www/html/config/config.php" ]; then
sleep 2
- while ! sudo -u www-data psql -d "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB" -c "select now()"; do
+ while ! sudo -E -u www-data psql -d "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB" -c "select now()"; do
echo "Waiting for the database to start..."
sleep 5
done
@@ -51,12 +56,12 @@ fi
set +x
# Check datadir permissions
-sudo -u www-data touch "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" &>/dev/null
+sudo -E -u www-data touch "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" &>/dev/null
if ! [ -f "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" ]; then
chown -R www-data:root "$NEXTCLOUD_DATA_DIR"
chmod 750 -R "$NEXTCLOUD_DATA_DIR"
fi
-sudo -u www-data rm -f "$NEXTCLOUD_DATA_DIR/this-is-a-test-file"
+sudo -E -u www-data rm -f "$NEXTCLOUD_DATA_DIR/this-is-a-test-file"
# Install additional dependencies
if [ -n "$ADDITIONAL_APKS" ]; then
@@ -81,13 +86,15 @@ fi
# Install additional php extensions
if [ -n "$ADDITIONAL_PHP_EXTENSIONS" ]; then
if ! [ -f "/additional-php-extensions-are-installed" ]; then
+ # Allow to disable imagick without having to enable it each time
+ if ! echo "$ADDITIONAL_PHP_EXTENSIONS" | grep -q imagick; then
+ # Remove the ini file as there is no docker-php-ext-disable script available
+ rm /usr/local/etc/php/conf.d/docker-php-ext-imagick.ini
+ fi
read -ra ADDITIONAL_PHP_EXTENSIONS_ARRAY <<< "$ADDITIONAL_PHP_EXTENSIONS"
for app in "${ADDITIONAL_PHP_EXTENSIONS_ARRAY[@]}"; do
if [ "$app" = imagick ]; then
- echo "Enabling Imagick..."
- if ! docker-php-ext-enable imagick >/dev/null; then
- echo "Could not install PHP extension imagick!"
- fi
+ # imagick is already enabled by default, so does not need to be enabled anymore.
continue
fi
# shellcheck disable=SC2086
diff --git a/Containers/nextcloud/supervisord.conf b/Containers/nextcloud/supervisord.conf
index 184074af..1db885e9 100644
--- a/Containers/nextcloud/supervisord.conf
+++ b/Containers/nextcloud/supervisord.conf
@@ -39,5 +39,7 @@ stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
-command=nc -lk 9001
+# Restart the netcat command once a day to ensure that it stays reachable
+# See https://github.com/nextcloud/all-in-one/issues/6334
+command=timeout 86400 nc -lk 9001
user=www-data
diff --git a/Containers/notify-push/Dockerfile b/Containers/notify-push/Dockerfile
index b0fc0fd2..838c847c 100644
--- a/Containers/notify-push/Dockerfile
+++ b/Containers/notify-push/Dockerfile
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
-FROM alpine:3.20.3
+FROM alpine:3.23.3
COPY --chmod=775 start.sh /start.sh
COPY --chmod=775 healthcheck.sh /healthcheck.sh
@@ -11,6 +11,7 @@ RUN set -ex; \
netcat-openbsd \
tzdata \
bash \
+ jq \
openssl; \
# Give root a random password
echo "root:$(openssl rand -base64 12)" | chpasswd; \
@@ -21,4 +22,6 @@ USER 33
ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD /healthcheck.sh
-LABEL com.centurylinklabs.watchtower.enable="false"
+LABEL com.centurylinklabs.watchtower.enable="false" \
+ wud.watch="false" \
+ org.label-schema.vendor="Nextcloud"
diff --git a/Containers/notify-push/start.sh b/Containers/notify-push/start.sh
index 1f77b0f1..26d74333 100644
--- a/Containers/notify-push/start.sh
+++ b/Containers/notify-push/start.sh
@@ -1,13 +1,13 @@
#!/bin/bash
if [ -z "$NEXTCLOUD_HOST" ]; then
- echo "NEXTCLOUD_HOST need to be provided. Exiting!"
+ echo "NEXTCLOUD_HOST needs to be provided. Exiting!"
exit 1
elif [ -z "$POSTGRES_HOST" ]; then
- echo "POSTGRES_HOST need to be provided. Exiting!"
+ echo "POSTGRES_HOST needs to be provided. Exiting!"
exit 1
elif [ -z "$REDIS_HOST" ]; then
- echo "REDIS_HOST need to be provided. Exiting!"
+ echo "REDIS_HOST needs to be provided. Exiting!"
exit 1
fi
@@ -52,10 +52,39 @@ fi
if [ -z "$REDIS_DB_INDEX" ]; then
REDIS_DB_INDEX=0
fi
+# Set a default value for REDIS_PORT
+if [ -z "$REDIS_PORT" ]; then
+ REDIS_PORT=6379
+fi
+# Set a default for db type
+if [ -z "$DATABASE_TYPE" ]; then
+ DATABASE_TYPE=postgres
+elif [ "$DATABASE_TYPE" != postgres ] && [ "$DATABASE_TYPE" != mysql ]; then
+ echo "DB type must be either postgres or mysql"
+ exit 1
+fi
+
+# Use the correct Postgres username
+if [ "$POSTGRES_USER" = nextcloud ]; then
+ POSTGRES_USER="oc_$POSTGRES_USER"
+ export POSTGRES_USER
+fi
+
+# URL-encode passwords
+POSTGRES_PASSWORD="$(jq -rn --arg v "$POSTGRES_PASSWORD" '$v|@uri')"
+REDIS_HOST_PASSWORD="$(jq -rn --arg v "$REDIS_HOST_PASSWORD" '$v|@uri')"
+
+# Postgres root cert
+if [ -f "/nextcloud/data/certificates/POSTGRES" ]; then
+ CERT_OPTIONS="?sslmode=verify-ca&sslrootcert=/nextcloud/data/certificates/ca-bundle.crt"
+# Mysql root cert
+elif [ -f "/nextcloud/data/certificates/MYSQL" ]; then
+ CERT_OPTIONS="?sslmode=verify-ca&ssl-ca=/nextcloud/data/certificates/ca-bundle.crt"
+fi
# Set sensitive values as env
-export DATABASE_URL="postgres://oc_$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB"
-export REDIS_URL="redis://:$REDIS_HOST_PASSWORD@$REDIS_HOST/$REDIS_DB_INDEX"
+export DATABASE_URL="$DATABASE_TYPE://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB$CERT_OPTIONS"
+export REDIS_URL="redis://$REDIS_USER:$REDIS_HOST_PASSWORD@$REDIS_HOST:$REDIS_PORT/$REDIS_DB_INDEX"
# Run it
/nextcloud/custom_apps/notify_push/bin/"$CPU_ARCH"/notify_push \
diff --git a/Containers/onlyoffice/Dockerfile b/Containers/onlyoffice/Dockerfile
index ad694376..13b4d456 100644
--- a/Containers/onlyoffice/Dockerfile
+++ b/Containers/onlyoffice/Dockerfile
@@ -1,8 +1,12 @@
# syntax=docker/dockerfile:latest
# From https://github.com/ONLYOFFICE/Docker-DocumentServer/blob/master/Dockerfile
-FROM onlyoffice/documentserver:8.1.3.2
+FROM onlyoffice/documentserver:9.2.1.1
# USER root is probably used
-HEALTHCHECK CMD nc -z 127.0.0.1 80 || exit 1
-LABEL com.centurylinklabs.watchtower.enable="false"
+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"
diff --git a/Containers/onlyoffice/healthcheck.sh b/Containers/onlyoffice/healthcheck.sh
new file mode 100644
index 00000000..7a9d79d0
--- /dev/null
+++ b/Containers/onlyoffice/healthcheck.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+nc -z 127.0.0.1 80 || exit 1
diff --git a/Containers/postgresql/Dockerfile b/Containers/postgresql/Dockerfile
index 64d66403..56090f26 100644
--- a/Containers/postgresql/Dockerfile
+++ b/Containers/postgresql/Dockerfile
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:latest
-# From https://github.com/docker-library/postgres/blob/master/16/alpine3.20/Dockerfile
-FROM postgres:16.4-alpine
+# From https://github.com/docker-library/postgres/blob/master/17/alpine3.23/Dockerfile
+FROM postgres:17.7-alpine
COPY --chmod=775 start.sh /start.sh
COPY --chmod=775 healthcheck.sh /healthcheck.sh
@@ -39,8 +39,10 @@ RUN set -ex; \
VOLUME /mnt/data
-USER postgres
+USER 999
ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD /healthcheck.sh
-LABEL com.centurylinklabs.watchtower.enable="false"
+LABEL com.centurylinklabs.watchtower.enable="false" \
+ wud.watch="false" \
+ org.label-schema.vendor="Nextcloud"
diff --git a/Containers/postgresql/healthcheck.sh b/Containers/postgresql/healthcheck.sh
index f72aeecf..9f303a3a 100644
--- a/Containers/postgresql/healthcheck.sh
+++ b/Containers/postgresql/healthcheck.sh
@@ -2,4 +2,6 @@
test -f "/mnt/data/backup-is-running" && exit 0
+psql -d "postgresql://oc_$POSTGRES_USER:$POSTGRES_PASSWORD@127.0.0.1:11000/$POSTGRES_DB" -c "select now()" && exit 0
+
psql -d "postgresql://oc_$POSTGRES_USER:$POSTGRES_PASSWORD@127.0.0.1:5432/$POSTGRES_DB" -c "select now()" || exit 1
diff --git a/Containers/postgresql/start.sh b/Containers/postgresql/start.sh
index 10e46550..551bb10e 100644
--- a/Containers/postgresql/start.sh
+++ b/Containers/postgresql/start.sh
@@ -99,7 +99,7 @@ if ( [ -f "$DATADIR/PG_VERSION" ] && [ "$PG_MAJOR" != "$(cat "$DATADIR/PG_VERSIO
fi
# Get the Owner
- DB_OWNER="$(grep -a "$GREP_STRING" "$DUMP_FILE" | head -1 | grep -oP 'Owner:.*$' | sed 's|Owner:||;s| ||g')"
+ DB_OWNER="$(grep -a "$GREP_STRING" "$DUMP_FILE" | head -1 | grep -oP 'Owner:.*$' | sed 's|Owner:||;s|[[:space:]]||g')"
if [ "$DB_OWNER" = "$POSTGRES_USER" ]; then
echo "Unfortunately was the found database owner of the dump file the same as the POSTGRES_USER $POSTGRES_USER"
echo "It is not possible to import a database dump from this database owner."
@@ -128,7 +128,9 @@ EOSQL
fi
# Shut down the database to be able to start it again
- pg_ctl stop -m fast
+ # The smart mode disallows new connections, then waits for all existing clients to disconnect and any online backup to finish
+ # Wait for 1800s to make sure that a checkpoint is completed successfully
+ pg_ctl stop -m smart -t 1800
# Change database port back to default
export PGPORT=5432
diff --git a/Containers/redis/Dockerfile b/Containers/redis/Dockerfile
index f5fc22e5..cc9181ad 100644
--- a/Containers/redis/Dockerfile
+++ b/Containers/redis/Dockerfile
@@ -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.6-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
@@ -14,8 +14,12 @@ RUN set -ex; \
# Get rid of unused binaries
rm -f /usr/local/bin/gosu;
-USER redis
+COPY --chmod=775 healthcheck.sh /healthcheck.sh
+
+USER 999
ENTRYPOINT ["/start.sh"]
-HEALTHCHECK CMD redis-cli -a $REDIS_HOST_PASSWORD PING || exit 1
-LABEL com.centurylinklabs.watchtower.enable="false"
+HEALTHCHECK CMD /healthcheck.sh
+LABEL com.centurylinklabs.watchtower.enable="false" \
+ wud.watch="false" \
+ org.label-schema.vendor="Nextcloud"
diff --git a/Containers/redis/healthcheck.sh b/Containers/redis/healthcheck.sh
new file mode 100644
index 00000000..6588229f
--- /dev/null
+++ b/Containers/redis/healthcheck.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+redis-cli -a "$REDIS_HOST_PASSWORD" PING || exit 1
diff --git a/Containers/talk-recording/Dockerfile b/Containers/talk-recording/Dockerfile
index 41ad1c14..8df5b89e 100644
--- a/Containers/talk-recording/Dockerfile
+++ b/Containers/talk-recording/Dockerfile
@@ -1,11 +1,13 @@
# syntax=docker/dockerfile:latest
-FROM python:3.13.0-alpine3.20
+FROM python:3.14.2-alpine3.23
COPY --chmod=775 start.sh /start.sh
+COPY --chmod=775 healthcheck.sh /healthcheck.sh
-ENV RECORDING_VERSION=v0.1
+ENV RECORDING_VERSION=v0.2.1
ENV ALLOW_ALL=false
ENV HPB_PROTOCOL=https
+ENV NC_PROTOCOL=https
ENV SKIP_VERIFY=false
ENV HPB_PATH=/standalone-signaling/
@@ -28,7 +30,7 @@ RUN set -ex; \
build-base \
linux-headers \
geckodriver; \
- useradd -d /tmp --system recording; \
+ useradd -d /tmp --system recording -u 122; \
# Give root a random password
echo "root:$(openssl rand -base64 12)" | chpasswd; \
git clone --recursive https://github.com/nextcloud/nextcloud-talk-recording --depth=1 --single-branch --branch "$RECORDING_VERSION" /src; \
@@ -48,10 +50,13 @@ RUN set -ex; \
build-base \
linux-headers;
+VOLUME /tmp
WORKDIR /tmp
-USER recording
+USER 122
ENTRYPOINT ["/start.sh"]
CMD ["python", "-m", "nextcloud.talk.recording", "--config", "/conf/recording.conf"]
-HEALTHCHECK CMD nc -z 127.0.0.1 1234 || exit 1
-LABEL com.centurylinklabs.watchtower.enable="false"
+HEALTHCHECK CMD /healthcheck.sh
+LABEL com.centurylinklabs.watchtower.enable="false" \
+ wud.watch="false" \
+ org.label-schema.vendor="Nextcloud"
diff --git a/Containers/talk-recording/healthcheck.sh b/Containers/talk-recording/healthcheck.sh
new file mode 100644
index 00000000..8397ab3c
--- /dev/null
+++ b/Containers/talk-recording/healthcheck.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+nc -z 127.0.0.1 1234 || exit 1
diff --git a/Containers/talk-recording/recording.conf b/Containers/talk-recording/recording.conf
index 99515528..cc8bd495 100644
--- a/Containers/talk-recording/recording.conf
+++ b/Containers/talk-recording/recording.conf
@@ -1,3 +1,5 @@
+# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+# SPDX-License-Identifier: AGPL-3.0-or-later
[logs]
# Log level based on numeric values of Python logging levels:
# - Critical: 50
@@ -12,6 +14,11 @@
# IP and port to listen on for HTTP requests.
#listen = 127.0.0.1:8000
+[app]
+# Comma separated list of trusted proxies (IPs or CIDR networks) that may set
+# the "X-Forwarded-For" header.
+#trustedproxies =
+
[backend]
# Allow any hostname as backend endpoint. This is extremely insecure and should
# only be used during development.
@@ -100,6 +107,18 @@
# ffmpeg. The options given here fully override the default global options.
#common = ffmpeg -loglevel level+warning -n
+# The (additional) options given to ffmpeg for the audio input. The options
+# given here extend the default options for the audio input, although they do
+# not override them.
+# Default options: '-f pulse -i {AUDIO_SOURCE}'
+#inputaudio =
+
+# The (additional) options given to ffmpeg for the video input. The options
+# given here extend the default options for the video input, although they do
+# not override them.
+# Default options: '-f x11grab -draw_mouse 0 -video_size {WIDTH}x{HEIGHT} -i {VIDEO_SOURCE}'
+#inputvideo =
+
# The options given to ffmpeg to encode the audio output. The options given here
# fully override the default options for the audio output.
#outputaudio = -c:a libopus
@@ -120,4 +139,31 @@
# will use Google Chrome, or Chromium if Google Chrome is not installed.
# Allowed values: firefox, chrome
# Defaults to firefox
-# browser = firefox
+#browser = firefox
+
+# Path to the Selenium driver to use for recordings.
+# If set the driver must match the browser being used (for example,
+# "/usr/bin/geckodriver" for "firefox"). If no driver is explicitly set Selenium
+# Manager will try to find the right one in $PATH, downloading it as a fallback.
+# Note that Selenium Manager does not work in some architectures (for example,
+# Linux on arm64/aarch64), so in those architectures the driver must be
+# explicitly set.
+#driverPath =
+
+# Path to the browser executable to use for recordings.
+# If set the executable must match the browser being used (for example,
+# "/usr/bin/firefox-esr" for "firefox"). If no executable is explicitly set
+# Selenium Manager will try to find the right one in $PATH. Depending on the
+# installed Selenium version if the executable is not found Selenium Manager may
+# also download the browser as a fallback.
+# Note that Selenium Manager does not work in some architectures (for example,
+# Linux on arm64/aarch64); in those architectures the Selenium driver will try
+# to find the executable, but the executable may need to be explicitly set if
+# not found by the driver.
+#browserPath =
+
+[stats]
+# Comma-separated list of IP addresses (or CIDR networks) that are allowed to
+# access the stats endpoint.
+# Leave commented to only allow access from "127.0.0.1".
+#allowed_ips =
diff --git a/Containers/talk-recording/start.sh b/Containers/talk-recording/start.sh
index 14a893a4..b49e5e9c 100644
--- a/Containers/talk-recording/start.sh
+++ b/Containers/talk-recording/start.sh
@@ -16,6 +16,9 @@ if [ -z "$HPB_DOMAIN" ]; then
export HPB_DOMAIN="$NC_DOMAIN"
fi
+# Delete all contents on startup to start fresh
+rm -fr /tmp/{*,.*}
+
cat << RECORDING_CONF > "/conf/recording.conf"
[logs]
# 30 means Warning
@@ -36,7 +39,7 @@ videoheight = 1080
directory = /tmp
[backend-1]
-url = ${HPB_PROTOCOL}://${NC_DOMAIN}
+url = ${NC_PROTOCOL}://${NC_DOMAIN}
secret = ${RECORDING_SECRET}
skipverify = ${SKIP_VERIFY}
@@ -56,6 +59,8 @@ extensionvideo = .webm
[recording]
browser = firefox
+driverPath = /usr/bin/geckodriver
+browserPath = /usr/bin/firefox
RECORDING_CONF
exec "$@"
diff --git a/Containers/talk/Dockerfile b/Containers/talk/Dockerfile
index 0d0631c8..e8d3d72f 100644
--- a/Containers/talk/Dockerfile
+++ b/Containers/talk/Dockerfile
@@ -1,12 +1,13 @@
# syntax=docker/dockerfile:latest
-FROM nats:2.10.21-scratch AS nats
-FROM eturnal/eturnal:1.12.0 AS eturnal
-FROM strukturag/nextcloud-spreed-signaling:2.0.0 AS signaling
-FROM alpine:3.20.3 AS janus
+FROM nats:2.12.4-scratch AS nats
+FROM eturnal/eturnal:1.12.2-alpine AS eturnal
+FROM strukturag/nextcloud-spreed-signaling:2.0.4 AS signaling
+FROM alpine:3.23.3 AS janus
-ARG JANUS_VERSION=v0.14.4
+ARG JANUS_VERSION=v1.3.3
WORKDIR /src
RUN set -ex; \
+ apk upgrade --no-cache -a; \
apk add --no-cache \
ca-certificates \
git \
@@ -34,8 +35,9 @@ RUN set -ex; \
make configs; \
rename -v ".jcfg.sample" ".jcfg" /usr/local/etc/janus/*.jcfg.sample
-FROM alpine:3.20.3
+FROM alpine:3.23.3
ENV ETURNAL_ETC_DIR="/conf"
+ENV SKIP_CERT_VERIFY=false
COPY --from=janus --chmod=777 --chown=1000:1000 /usr/local /usr/local
COPY --from=eturnal --chmod=777 --chown=1000:1000 /opt/eturnal /opt/eturnal
COPY --from=nats --chmod=777 --chown=1000:1000 /nats-server /usr/local/bin/nats-server
@@ -99,9 +101,11 @@ RUN set -ex; \
ln -s /opt/eturnal/bin/stun /usr/local/bin/stun; \
ln -s /opt/eturnal/bin/eturnalctl /usr/local/bin/eturnalctl
-USER eturnal
+USER 1000
ENTRYPOINT ["/start.sh"]
CMD ["supervisord", "-c", "/supervisord.conf"]
HEALTHCHECK CMD /healthcheck.sh
-LABEL com.centurylinklabs.watchtower.enable="false"
+LABEL com.centurylinklabs.watchtower.enable="false" \
+ wud.watch="false" \
+ org.label-schema.vendor="Nextcloud"
diff --git a/Containers/talk/server.conf.in b/Containers/talk/server.conf.in
index 85630d5a..8f437e30 100644
--- a/Containers/talk/server.conf.in
+++ b/Containers/talk/server.conf.in
@@ -84,7 +84,8 @@ internalsecret = the-shared-secret-for-internal-clients
# For backend type "etcd":
# Key prefix of backend entries. All keys below will be watched and assumed to
# contain a JSON document with the following entries:
-# - "url": Url of the Nextcloud instance.
+# - "urls": List of urls of the Nextcloud instance.
+# - "url": Url of the Nextcloud instance (deprecated).
# - "secret": Shared secret for requests from and to the backend servers.
#
# Additional optional entries:
@@ -93,8 +94,8 @@ internalsecret = the-shared-secret-for-internal-clients
# - "sessionlimit": Number of sessions that are allowed to connect.
#
# Example:
-# "/signaling/backend/one" -> {"url": "https://nextcloud.domain1.invalid", ...}
-# "/signaling/backend/two" -> {"url": "https://domain2.invalid/nextcloud", ...}
+# "/signaling/backend/one" -> {"urls": ["https://nextcloud.domain1.invalid"], ...}
+# "/signaling/backend/two" -> {"urls": ["https://domain2.invalid/nextcloud"], ...}
#backendprefix = /signaling/backend
# Allow any hostname as backend endpoint. This is extremely insecure and should
@@ -122,8 +123,8 @@ connectionsperhost = 8
# Backend configurations as defined in the "[backend]" section above. The
# section names must match the ids used in "backends" above.
#[backend-id]
-# URL of the Nextcloud instance
-#url = https://cloud.domain.invalid
+# Comma-separated list of urls of the Nextcloud instance
+#urls = https://cloud.domain.invalid
# Shared secret for requests from and to the backend servers. Leave empty to use
# the common shared secret from above.
@@ -143,8 +144,8 @@ connectionsperhost = 8
#maxscreenbitrate = 2097152
#[another-backend]
-# URL of the Nextcloud instance
-#url = https://cloud.otherdomain.invalid
+# Comma-separated list of urls of the Nextcloud instance
+#urls = https://cloud.otherdomain.invalid
# Shared secret for requests from and to the backend servers. Leave empty to use
# the common shared secret from above.
@@ -179,6 +180,13 @@ connectionsperhost = 8
# proxy server that is used.
#maxscreenbitrate = 2097152
+# List of IP addresses / subnets that are allowed to be used by clients in
+# candidates. The allowed list has preference over the blocked list below.
+#allowedcandidates = 10.0.0.0/8
+
+# List of IP addresses / subnets to filter from candidates received by clients.
+#blockedcandidates = 1.2.3.0/24
+
# For type "proxy": timeout in seconds for requests to the proxy server.
#proxytimeout = 2
diff --git a/Containers/talk/start.sh b/Containers/talk/start.sh
index e73525b8..f89949f3 100644
--- a/Containers/talk/start.sh
+++ b/Containers/talk/start.sh
@@ -30,14 +30,23 @@ if [ -n "$IPv4_ADDRESS_TALK" ] && [ "$IPv4_ADDRESS_TALK_RELAY" = "$IPv4_ADDRESS_
IPv4_ADDRESS_TALK=""
fi
+set -x
+IP_BINDING="::"
+if grep -q "1" /sys/module/ipv6/parameters/disable \
+|| grep -q "1" /proc/sys/net/ipv6/conf/all/disable_ipv6 \
+|| grep -q "1" /proc/sys/net/ipv6/conf/default/disable_ipv6; then
+ IP_BINDING="0.0.0.0"
+fi
+set +x
+
# Turn
cat << TURN_CONF > "/conf/eturnal.yml"
eturnal:
listen:
- - ip: "::"
+ - ip: "$IP_BINDING"
port: $TALK_PORT
transport: udp
- - ip: "::"
+ - ip: "$IP_BINDING"
port: $TALK_PORT
transport: tcp
log_dir: stdout
@@ -86,9 +95,10 @@ backends = backend-1
allowall = false
timeout = 10
connectionsperhost = 8
+skipverify = ${SKIP_CERT_VERIFY}
[backend-1]
-url = https://${NC_DOMAIN}
+urls = https://${NC_DOMAIN}
secret = ${SIGNALING_SECRET}
maxstreambitrate = ${TALK_MAX_STREAM_BITRATE}
maxscreenbitrate = ${TALK_MAX_SCREEN_BITRATE}
diff --git a/Containers/watchtower/Dockerfile b/Containers/watchtower/Dockerfile
index 076cb0d5..fc9ea093 100644
--- a/Containers/watchtower/Dockerfile
+++ b/Containers/watchtower/Dockerfile
@@ -1,14 +1,21 @@
# syntax=docker/dockerfile:latest
-# From https://github.com/containrrr/watchtower/blob/main/dockerfiles/Dockerfile.self-contained
-FROM containrrr/watchtower:1.7.1 AS watchtower
+FROM golang:1.25.6-alpine3.23 AS go
-FROM alpine:3.20.3
+ENV WATCHTOWER_COMMIT_HASH=f522ce27e1fbe4618da54833025a95be62aa838a
RUN set -ex; \
apk upgrade --no-cache -a; \
- apk add --no-cache bash
+ apk add --no-cache \
+ build-base; \
+ go install github.com/nicholas-fedor/watchtower@$WATCHTOWER_COMMIT_HASH # v1.14.0
-COPY --from=watchtower /watchtower /watchtower
+FROM alpine:3.23.3
+
+RUN set -ex; \
+ apk upgrade --no-cache -a; \
+ apk add --no-cache bash ca-certificates tzdata
+
+COPY --from=go /go/bin/watchtower /watchtower
COPY --chmod=775 start.sh /start.sh
@@ -16,4 +23,6 @@ COPY --chmod=775 start.sh /start.sh
USER root
ENTRYPOINT ["/start.sh"]
-LABEL com.centurylinklabs.watchtower.enable="false"
+LABEL com.centurylinklabs.watchtower.enable="false" \
+ wud.watch="false" \
+ org.label-schema.vendor="Nextcloud"
diff --git a/Containers/watchtower/start.sh b/Containers/watchtower/start.sh
index 2c7a1835..cf16e7a4 100644
--- a/Containers/watchtower/start.sh
+++ b/Containers/watchtower/start.sh
@@ -1,7 +1,7 @@
#!/bin/bash
# Check if socket is available and readable
-if ! [ -a "/var/run/docker.sock" ]; then
+if ! [ -e "/var/run/docker.sock" ]; then
echo "Docker socket is not available. Cannot continue."
exit 1
elif ! test -r /var/run/docker.sock; then
@@ -9,6 +9,13 @@ elif ! test -r /var/run/docker.sock; then
exit 1
fi
+if [ -f /run/.containerenv ]; then
+ # If running under podman disable memory_swappiness setting in watchtower.
+ # It is a necessary workaround until https://github.com/containers/podman/issues/23824 gets fixed.
+ echo "Running under Podman. Setting WATCHTOWER_DISABLE_MEMORY_SWAPPINESS to 1."
+ export WATCHTOWER_DISABLE_MEMORY_SWAPPINESS=1
+fi
+
if [ -n "$CONTAINER_TO_UPDATE" ]; then
exec /watchtower --cleanup --debug --run-once "$CONTAINER_TO_UPDATE"
else
diff --git a/Containers/whiteboard/Dockerfile b/Containers/whiteboard/Dockerfile
index 00e5b26f..c83dd46b 100644
--- a/Containers/whiteboard/Dockerfile
+++ b/Containers/whiteboard/Dockerfile
@@ -1,14 +1,27 @@
# syntax=docker/dockerfile:latest
-FROM ghcr.io/nextcloud-releases/whiteboard:v1.0.4
+# Probably from this file: https://github.com/nextcloud/whiteboard/blob/main/Dockerfile
+FROM ghcr.io/nextcloud-releases/whiteboard:v1.5.4
USER root
RUN set -ex; \
- apk upgrade --no-cache -a; \
- apk add --no-cache bash
-USER nobody
+ apk add --no-cache bash jq; \
+ chmod 777 -R /tmp; \
+ if [ -f /usr/lib/chromium/chrome_crashpad_handler ] && [ ! -f /usr/lib/chromium/chrome_crashpad_handler.real ]; then \
+ 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
+COPY --chmod=775 healthcheck.sh /healthcheck.sh
+
+HEALTHCHECK CMD /healthcheck.sh
+
+WORKDIR /tmp
ENTRYPOINT ["/start.sh"]
-LABEL com.centurylinklabs.watchtower.enable="false"
+LABEL com.centurylinklabs.watchtower.enable="false" \
+ wud.watch="false" \
+ org.label-schema.vendor="Nextcloud"
diff --git a/Containers/whiteboard/healthcheck.sh b/Containers/whiteboard/healthcheck.sh
new file mode 100644
index 00000000..5909db82
--- /dev/null
+++ b/Containers/whiteboard/healthcheck.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+nc -z "$REDIS_HOST" "$REDIS_PORT" || exit 0
+nc -z 127.0.0.1 3002 || exit 1
diff --git a/Containers/whiteboard/start.sh b/Containers/whiteboard/start.sh
index 8816ee7f..e0babd7f 100644
--- a/Containers/whiteboard/start.sh
+++ b/Containers/whiteboard/start.sh
@@ -1,7 +1,7 @@
#!/bin/bash
# Only start container if nextcloud is accessible
-while ! nc -z "$REDIS_HOST" 6379; do
+while ! nc -z "$REDIS_HOST" "$REDIS_PORT"; do
echo "Waiting for redis to start..."
sleep 5
done
@@ -11,7 +11,10 @@ if [ -z "$REDIS_DB_INDEX" ]; then
REDIS_DB_INDEX=0
fi
-export REDIS_URL="redis://:$REDIS_HOST_PASSWORD@$REDIS_HOST/$REDIS_DB_INDEX"
+# URL-encode password
+REDIS_HOST_PASSWORD="$(jq -rn --arg v "$REDIS_HOST_PASSWORD" '$v|@uri')"
+
+export REDIS_URL="redis://$REDIS_USER:$REDIS_HOST_PASSWORD@$REDIS_HOST:$REDIS_PORT/$REDIS_DB_INDEX"
# Run it
-exec npm run server:start
+exec npm --prefix /app run server:start
diff --git a/app/appinfo/info.xml b/app/appinfo/info.xml
index e064273d..832d3ccd 100644
--- a/app/appinfo/info.xml
+++ b/app/appinfo/info.xml
@@ -5,7 +5,7 @@
Nextcloud All-in-OneProvides a login link for admins.Add a link to the admin settings that gives access to the Nextcloud All-in-One admin interface
- 0.6.0
+ 0.8.0agplAzulAllInOne
@@ -13,20 +13,11 @@
monitoringhttps://github.com/nextcloud/all-in-one/issues
-
+ OCA\AllInOne\Settings\Admin
-
-
diff --git a/app/templates/admin.php b/app/templates/admin.php
index 8256dfab..4812ad90 100644
--- a/app/templates/admin.php
+++ b/app/templates/admin.php
@@ -10,7 +10,7 @@ declare(strict_types=1);
*/
/** @var array $_ */ ?>
\ No newline at end of file
diff --git a/php/templates/containers.twig b/php/templates/containers.twig
index 4017cf8c..8e437bc2 100644
--- a/php/templates/containers.twig
+++ b/php/templates/containers.twig
@@ -6,9 +6,9 @@
-
+
-
-
Nextcloud has an upload limit of {{ nextcloud_upload_limit }} configured (for public link uploads. Bigger uploads are always possible when users are logged in). See the NEXTCLOUD_UPLOAD_LIMIT documentation on how to change this.
+
Nextcloud has an upload limit of {{ nextcloud_upload_limit }} configured (for public link uploads. Bigger uploads are always possible when users are logged in). See the NEXTCLOUD_UPLOAD_LIMIT documentation on how to change this.
-
For Nextcloud, a memory limit of {{ nextcloud_memory_limit }} per PHP process is configured. See the NEXTCLOUD_MEMORY_LIMIT documentation on how to change this.
+
For Nextcloud, a memory limit of {{ nextcloud_memory_limit }} per PHP process is configured. See the NEXTCLOUD_MEMORY_LIMIT documentation on how to change this.
-
Nextcloud has a timeout of {{ nextcloud_max_time }} seconds configured (important for big file uploads). See the NEXTCLOUD_MAX_TIME documentation on how to change this.
+
Nextcloud has a timeout of {{ nextcloud_max_time }} seconds configured (important for big file uploads). See the NEXTCLOUD_MAX_TIME documentation on how to change this.
- {% if is_dri_device_enabled == true %}
- The /dev/dri device which is needed for hardware transcoding is getting attached to the Nextcloud container.
+ {% if is_dri_device_enabled == true and is_nvidia_gpu_enabled == true %}
+ Hardware acceleration is enabled with the /dev/dri device and the Nvidia runtime.
+ {% elseif is_dri_device_enabled == true %}
+ Hardware acceleration is enabled with the /dev/dri device.
+ {% elseif is_nvidia_gpu_enabled == true %}
+ Hardware acceleration is enabled with the Nvidia runtime.
{% else %}
- The /dev/dri device which is needed for hardware transcoding is not attached to the Nextcloud container.
+ Hardware acceleration is not enabled. It's recommended to enable hardware transcoding for better performance.
{% endif %}
- See the NEXTCLOUD_ENABLE_DRI_DEVICE documentation on how to change this.
For further documentation on AIO, refer to this page. You can use the browser search [CTRL]+[F] to search through the documentation. Additional documentation can be found here.
+
For further documentation on AIO, refer to this page. You can use the browser search [CTRL]+[F] to search through the documentation. Additional documentation can be found here.
On Synology it could be /volume1/docker/nextcloud/backup.
For macOS it may be /var/backup.
On Windows it might be /run/desktop/mnt/host/c/backup. (This path is equivalent to 'C:\backup' on your Windows host so you need to translate the path accordingly. Hint: the path that you enter needs to start with '/run/desktop/mnt/host/'. Append to that the exact location on your windows host, e.g. 'c/backup' which is equivalent to 'C:\backup'.) ⚠️ Please note: This does not work with external drives like USB or network drives and only with internal drives like SATA or NVME drives.
-
Another option is to enter a specific volume name here: nextcloud_aio_backupdir. This volume needs to be created beforehand manually by you in order to be able to use it. See this documentation for an example.
+
Another option is to enter a specific volume name here: nextcloud_aio_backupdir. This volume needs to be created beforehand manually by you in order to be able to use it. See this documentation for an example.
diff --git a/php/templates/includes/community-containers.twig b/php/templates/includes/community-containers.twig
new file mode 100644
index 00000000..66cceb2b
--- /dev/null
+++ b/php/templates/includes/community-containers.twig
@@ -0,0 +1,42 @@
+
Community Containers
+
In this section you can enable or disable optional Community Containers that are not included by default in the main installation. These containers are provided by the community and can be useful for various purposes and are automatically integrated in AIOs backup solution and update mechanisms.
+
⚠️ Caution: Community Containers are maintained by the community and not officially by Nextcloud. Some containers may not be compatible with your system, may not work as expected or may discontinue. Use them at your own risk. Please read the documentation for each container first before adding any as some are also incompatible between each other! Never add all of them at the same time!
+{% if isAnyRunning == true %}
+
Please note: You can enable or disable the options below only when your containers are stopped.
+{% else %}
+
Please note: Make sure to save your changes by clicking Save changes below the list of Community Containers. The changes will not be auto-saved.
+{% endif %}
+
+ Show/Hide available Community Containers
+
+
+
+
+ {% for cc in community_containers %}
+
+
+
+
+ {% endfor %}
+
+
+
+
diff --git a/php/templates/includes/optional-containers.twig b/php/templates/includes/optional-containers.twig
new file mode 100644
index 00000000..eabcb139
--- /dev/null
+++ b/php/templates/includes/optional-containers.twig
@@ -0,0 +1,273 @@
+
Optional containers
+
In this section you can enable or disable optional containers.
+{% if isAnyRunning == true %}
+
Please note: You can enable or disable the options below only when your containers are stopped.
+{% else %}
+
Please note: Make sure to save your changes by clicking Save changes below the list of optional containers. The changes will not be auto-saved.
+{% endif %}
+
+
+
+
+
Office Suite
+ {% if isAnyRunning == false %}
+
Choose your preferred office suite. Only one can be enabled at a time.
+ {% endif %}
+
+
+
+
+
+
+
+
+ {% if isAnyRunning == false %}
+
+
+
+
+ {% endif %}
+
+
Additional Optional Containers
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Minimal system requirements: When any optional container is enabled, at least 2GB RAM, a dual-core CPU and 40GB system storage are required. When enabling ClamAV, Nextcloud Talk Recording-server or Fulltextsearch, at least 3GB RAM are required. For Talk Recording-server additional 2 vCPUs are required. When enabling everything, at least 5GB RAM and a quad-core CPU are required. Recommended are at least 1GB more RAM than the minimal requirement. For further advice and recommendations see this documentation
+{% if isAnyRunning == true %}
+
+
+
+
+
+
+
+
+
+{% endif %}
+
+{% if is_collabora_enabled == true and isAnyRunning == false and was_start_button_clicked == true %}
+
Nextcloud Office dictionaries
+
+ {% if collabora_dictionaries == "" %}
+
In order to get the correct dictionaries in Nextcloud Office, you may configure the dictionaries below:
+
+
+
+
+
+
+
You need to make sure that the dictionaries that you enter are valid. An example is de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru.
+ {% else %}
+
The dictionaries for Nextcloud Office are currently set to {{ collabora_dictionaries }}. You can reset them again by clicking on the button below.
+
+
+
+
+
+
+ {% endif %}
+
+
Additional Nextcloud Office options
+
+ {% if collabora_additional_options == "" %}
+
You can configure additional options for Nextcloud Office below.
+
(This can be used for configuring the net.content_security_policy and more. Make sure to submit the value!)
+
+
+
+
+
+
+
You need to make sure that the options that you enter are valid. An example is --o:net.content_security_policy=frame-ancestors *.example.com:*;.
+ {% else %}
+
The additioinal options for Nextcloud Office are currently set to {{ collabora_additional_options }}. You can reset them again by clicking on the button below.