Compare commits

..

No commits in common. "main" and "helm-chart-9.4.1" have entirely different histories.

286 changed files with 5144 additions and 11892 deletions

View file

@ -1,15 +1,12 @@
--- ---
name: 🐛 Bug report - no questions and no support! name: 🐛 Bug report
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 about: Help us improving by reporting a bug
labels: 0. Needs triage labels: bug, 0. Needs triage
--- ---
<!--- <!---
- Before submitting a bug report, please read through the documentation available at https://github.com/nextcloud/all-in-one#faq - If you use Cloudflare Tunnel or Cloudflare Proxy, see https://github.com/nextcloud/all-in-one#notes-on-cloudflare-proxytunnel for known issues/limitations and workarounds.
- Additional documentation is available here: https://github.com/nextcloud/all-in-one/discussions/categories/wiki - For issues with Collabora or Talk, make sure to follow https://github.com/nextcloud/all-in-one/discussions/1358. It may already resolve your issue and makes it easier to help you.
- You should also read through existing questions and their answer here: https://github.com/nextcloud/all-in-one/discussions/categories/questions
- Additional threads can be found here: https://help.nextcloud.com/tag/aio
- Existing feature requests are listed here: https://github.com/nextcloud/all-in-one/discussions/categories/ideas
---> --->
<!--- Please fill out the whole template below --> <!--- Please fill out the whole template below -->
@ -23,17 +20,11 @@ labels: 0. Needs triage
### Actual behavior <!--- Tell us what happens instead --> ### Actual behavior <!--- Tell us what happens instead -->
### Other information ### Host OS <!--- (the host OS on which you are trying to install AIO on) -->
#### Host OS <!--- (the host OS on which you are trying to install AIO on) -->
#### Output of `sudo docker info`
#### Docker run command or docker-compose file that you used #### Nextcloud AIO version <!--- (see Nextcloud AIO interface) -->
#### Output of `sudo docker logs nextcloud-aio-mastercontainer` #### Current channel <!--- (see the channel name in the AIO interface) -->
#### Output of `sudo docker inspect nextcloud-aio-mastercontainer` #### Other valuable info <!--- (like logs, screenshots & Co.) -->
#### Output of `sudo docker ps -a`
#### Other valuable info <!--- (like additional logs, screenshots & Co.) -->

View file

@ -1,7 +1,7 @@
--- ---
name: 📖 Existing feature/documentation enhancement name: 📖 Existing feature/documentation enhancement
about: Suggest an enhancement of an existing feature/documentation - for other types, please use the feature request option below about: Suggest an enhancement of an existing feature/documentation - for other types, please use the feature request option below
labels: 0. Needs triage labels: enhancement, 0. Needs triage
--- ---
<!--- Please fill out the whole template below --> <!--- Please fill out the whole template below -->

View file

@ -1,14 +1,14 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: 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 - name: 💡 Suggest a new feature or discuss one
url: https://github.com/nextcloud/all-in-one/discussions/categories/ideas url: https://github.com/nextcloud/all-in-one/discussions/categories/ideas
about: For new feature requests and discussion of existing ones 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 - name: 💼 Nextcloud Enterprise
url: https://portal.nextcloud.com/ 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 about: If you are a Nextcloud Enterprise customer, or need Professional support, so it can be resolved directly by our dedicated engineers more quickly

183
.github/dependabot.yml vendored
View file

@ -1,62 +1,185 @@
version: 2 version: 2
updates: updates:
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"
directory: ".github/workflows" directory: "/"
schedule: schedule:
interval: "daily" interval: "daily"
time: "12:00" time: "12:00"
open-pull-requests-limit: 10 open-pull-requests-limit: 10
rebase-strategy: "disabled"
labels:
- 3. to review
- dependencies
cooldown:
default-days: 7
- package-ecosystem: composer - package-ecosystem: composer
directory: "/php/" directory: "/php/"
schedule: schedule:
interval: "daily" interval: "daily"
time: "12:00" time: "12:00"
open-pull-requests-limit: 10 open-pull-requests-limit: 10
rebase-strategy: "auto"
labels: labels:
- 3. to review - 3. to review
- dependencies - dependencies
- package-ecosystem: "docker" - package-ecosystem: "docker"
directories: directory: "/Containers/apache"
- "/Containers/alpine"
- "/Containers/apache"
- "/Containers/borgbackup"
- "/Containers/clamav"
- "/Containers/collabora"
- "/Containers/docker-socket-proxy"
- "/Containers/domaincheck"
- "/Containers/fulltextsearch"
- "/Containers/imaginary"
- "/Containers/mastercontainer"
- "/Containers/nextcloud"
- "/Containers/notify-push"
- "/Containers/onlyoffice"
- "/Containers/postgresql"
- "/Containers/redis"
- "/Containers/talk"
- "/Containers/talk-recording"
- "/Containers/watchtower"
- "/Containers/whiteboard"
schedule: schedule:
interval: "daily" interval: "daily"
time: "04:00" time: "12:00"
open-pull-requests-limit: 10 open-pull-requests-limit: 10
rebase-strategy: "disabled"
labels: labels:
- 3. to review - 3. to review
- dependencies - dependencies
- package-ecosystem: "docker"
directory: "/Containers/borgbackup"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/collabora"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/domaincheck"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/mastercontainer"
schedule:
interval: "daily"
time: "12:00"
ignore: ignore:
- dependency-name: "php" - dependency-name: "php"
update-types: ["version-update:semver-major", "version-update:semver-minor"] update-types: ["version-update:semver-major", "version-update:semver-minor"]
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/nextcloud"
schedule:
interval: "daily"
time: "12:00"
ignore:
- dependency-name: "php"
update-types: ["version-update:semver-major", "version-update:semver-minor"]
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/postgresql"
schedule:
interval: "daily"
time: "12:00"
ignore:
- dependency-name: "postgres" - dependency-name: "postgres"
update-types: ["version-update:semver-major"] update-types: ["version-update:semver-major"]
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/redis"
schedule:
interval: "daily"
time: "12:00"
ignore:
- dependency-name: "redis" - dependency-name: "redis"
update-types: ["version-update:semver-major"] update-types: ["version-update:semver-major"]
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/talk"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/talk-recording"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/watchtower"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/clamav"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/onlyoffice"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/imaginary"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/fulltextsearch"
schedule:
interval: "daily"
time: "12:00"
ignore:
- dependency-name: "elasticsearch" - dependency-name: "elasticsearch"
update-types: ["version-update:semver-major"] update-types: ["version-update:semver-major"]
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/notify-push"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/docker-socket-proxy"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies

View file

@ -1,5 +0,0 @@
<!--
- 🚨 SECURITY INFO
-
- Before sending a pull request that fixes a security issue please report it via our HackerOne page (https://hackerone.com/nextcloud) following our security policy (https://nextcloud.com/security/). This allows us to coordinate the fix and release without potentially exposing all Nextcloud servers and users in the meantime.
-->

View file

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

View file

@ -1,29 +0,0 @@
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

51
.github/workflows/command-rebase.yml vendored Normal file
View file

@ -0,0 +1,51 @@
# 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
name: Rebase command
on:
issue_comment:
types: created
permissions:
contents: read
jobs:
rebase:
runs-on: ubuntu-latest
permissions:
contents: none
# On pull requests and if the comment starts with `/rebase`
if: github.event.issue.pull_request != '' && startsWith(github.event.comment.body, '/rebase')
steps:
- name: Add reaction on start
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
repository: ${{ github.event.repository.full_name }}
comment-id: ${{ github.event.comment.id }}
reaction-type: "+1"
- name: Checkout the latest code
uses: actions/checkout@v4 # v3.5.2
with:
fetch-depth: 0
token: ${{ secrets.COMMAND_BOT_PAT }}
- name: Automatic Rebase
uses: cirrus-actions/rebase@b87d48154a87a85666003575337e27b8cd65f691 # 1.8
env:
GITHUB_TOKEN: ${{ secrets.COMMAND_BOT_PAT }}
- name: Add reaction on failure
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
if: failure()
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
repository: ${{ github.event.repository.full_name }}
comment-id: ${{ github.event.comment.id }}
reaction-type: "-1"

View file

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

View file

@ -8,12 +8,12 @@ on:
jobs: jobs:
dependency_updates: dependency_updates:
name: Run dependency update script name: Run dependency update script
runs-on: ubuntu-latest runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/checkout@v4
- uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2 - uses: shivammathur/setup-php@v2
with: with:
php-version: 8.4 php-version: 8.3
extensions: apcu extensions: apcu
- name: Run dependency update script - name: Run dependency update script
run: | run: |
@ -44,7 +44,7 @@ jobs:
)" )"
sed -i "s|pecl install APCu.*\;|pecl install APCu-$apcu_version\;|" ./Containers/mastercontainer/Dockerfile sed -i "s|pecl install APCu.*\;|pecl install APCu-$apcu_version\;|" ./Containers/mastercontainer/Dockerfile
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7 uses: peter-evans/create-pull-request@v6
with: with:
commit-message: php dependency updates commit-message: php dependency updates
signoff: true signoff: true

View file

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

View file

@ -1,50 +0,0 @@
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;
}
}

View file

@ -13,10 +13,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@v4
- name: Turnstyle - name: Turnstyle
uses: softprops/turnstyle@e565d2d86403c5d23533937e95980570545e5586 # v2 uses: softprops/turnstyle@v2
with: with:
continue-after-seconds: 180 continue-after-seconds: 180
env: env:
@ -32,7 +32,7 @@ jobs:
# See https://github.com/helm/chart-releaser-action/issues/6 # See https://github.com/helm/chart-releaser-action/issues/6
- name: Set up Helm - name: Set up Helm
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4 uses: azure/setup-helm@v4
with: with:
version: v3.6.3 version: v3.6.3
@ -41,7 +41,7 @@ jobs:
helm lint ./nextcloud-aio-helm-chart helm lint ./nextcloud-aio-helm-chart
- name: Run chart-releaser - name: Run chart-releaser
uses: helm/chart-releaser-action@cae68fefc6b5f367a0275617c9f83181ba54714f # v1.7.0 uses: helm/chart-releaser-action@v1.6.0
with: with:
mark_as_latest: false mark_as_latest: false
charts_dir: . charts_dir: .

View file

@ -10,7 +10,7 @@ jobs:
name: update to latest imaginary commit on master branch name: update to latest imaginary commit on master branch
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/checkout@v4
- name: Run imaginary-update - name: Run imaginary-update
run: | run: |
# Imaginary # Imaginary
@ -22,7 +22,7 @@ jobs:
sed -i "s|^ENV IMAGINARY_HASH.*$|ENV IMAGINARY_HASH=$imaginary_version|" ./Containers/imaginary/Dockerfile sed -i "s|^ENV IMAGINARY_HASH.*$|ENV IMAGINARY_HASH=$imaginary_version|" ./Containers/imaginary/Dockerfile
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7 uses: peter-evans/create-pull-request@v6
with: with:
commit-message: imaginary-update automated change commit-message: imaginary-update automated change
signoff: true signoff: true

View file

@ -1,37 +1,35 @@
name: Json Validator name: Json Validator
on: on:
pull_request: pull_request:
paths: paths:
- '**.json' - '**.json'
push: push:
branches: branches:
- main - main
paths: paths:
- '**.json' - '**.json'
jobs: jobs:
json-validator: json-validator:
name: Json Validator name: Json Validator
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@v4
- name: Validate Json - name: Validate Json
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install python3-venv -y --no-install-recommends sudo apt-get install python3-pip -y --no-install-recommends
python3 -m venv venv sudo pip3 install json-spec
. venv/bin/activate if ! json validate --schema-file=php/containers-schema.json --document-file=php/containers.json; then
pip3 install json-spec exit 1
if ! json validate --schema-file=php/containers-schema.json --document-file=php/containers.json; then fi
exit 1 JSON_FILES="$(find ./community-containers -name '*.json')"
fi mapfile -t JSON_FILES <<< "$JSON_FILES"
JSON_FILES="$(find ./community-containers -name '*.json')" for file in "${JSON_FILES[@]}"; do
mapfile -t JSON_FILES <<< "$JSON_FILES" json validate --schema-file=php/containers-schema.json --document-file="$file" 2>&1 | tee -a ./json-validator.log
for file in "${JSON_FILES[@]}"; do done
json validate --schema-file=php/containers-schema.json --document-file="$file" 2>&1 | tee -a ./json-validator.log if grep -q "document does not validate with schema.\|invalid JSONFile" ./json-validator.log; then
done exit 1
if grep -q "document does not validate with schema.\|invalid JSONFile" ./json-validator.log; then fi
exit 1
fi

View file

@ -11,12 +11,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Install Helm - name: Install Helm
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4 uses: azure/setup-helm@v4
with: with:
version: v3.11.1 version: v3.11.1

View file

@ -2,9 +2,6 @@
# #
# https://github.com/nextcloud/.github # https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization # 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 name: Lint php
@ -30,18 +27,16 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
php-versions: [ "8.4" ] php-versions: [ "8.3" ]
name: php-lint name: php-lint
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- name: Set up php ${{ matrix.php-versions }} - name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2.36.0 uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # v2
with: with:
php-version: ${{ matrix.php-versions }} php-version: ${{ matrix.php-versions }}
coverage: none coverage: none

View file

@ -1,42 +0,0 @@
# 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@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
- name: Check GitHub actions
run: uvx zizmor --min-severity medium .github/workflows/*.yml

View file

@ -14,7 +14,7 @@ jobs:
action: action:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: dessant/lock-threads@7266a7ce5c1df01b1c6db85bf8cd86c737dadbe7 # v5 - uses: dessant/lock-threads@v5
with: with:
issue-inactive-days: '14' issue-inactive-days: '14'
process-only: 'issues' process-only: 'issues'

View file

@ -11,7 +11,7 @@ jobs:
name: Run nextcloud-update script name: Run nextcloud-update script
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/checkout@v4
- name: Run nextcloud-update script - name: Run nextcloud-update script
run: | run: |
# Inspired by https://github.com/nextcloud/docker/blob/master/update.sh # Inspired by https://github.com/nextcloud/docker/blob/master/update.sh
@ -25,7 +25,7 @@ jobs:
| sort -V \ | sort -V \
| tail -1 | tail -1
)" )"
sed -i "s|\(pecl install[^;]*APCu-\)[0-9.]*|\1$apcu_version|" ./Containers/nextcloud/Dockerfile sed -i "s|pecl install APCu.*\;|pecl install APCu-$apcu_version\;|" ./Containers/nextcloud/Dockerfile
# Memcached # Memcached
memcached_version="$( memcached_version="$(
@ -36,7 +36,7 @@ jobs:
| sort -V \ | sort -V \
| tail -1 | tail -1
)" )"
sed -i "s|\(pecl install[^;]*memcached-\)[0-9.]*|\1$memcached_version|" ./Containers/nextcloud/Dockerfile sed -i "s|pecl install memcached.* |pecl install memcached-$memcached_version |" ./Containers/nextcloud/Dockerfile
# Redis # Redis
redis_version="$( redis_version="$(
@ -47,18 +47,18 @@ jobs:
| sort -V \ | sort -V \
| tail -1 | tail -1
)" )"
sed -i "s|\(pecl install[^;]*redis-\)[0-9.]*|\1$redis_version|" ./Containers/nextcloud/Dockerfile sed -i "s|pecl install redis.* |pecl install redis-$redis_version |" ./Containers/nextcloud/Dockerfile
# Imagick # Imagick
imagick_version="$( imagick_version="$(
git ls-remote --tags https://github.com/imagick/imagick.git \ git ls-remote --tags https://github.com/mkoppanen/imagick.git \
| cut -d/ -f3 \ | cut -d/ -f3 \
| grep -viE '[a-z]' \ | grep -viE '[a-z]' \
| tr -d '^{}' \ | tr -d '^{}' \
| sort -V \ | sort -V \
| tail -1 | tail -1
)" )"
sed -i "s|\(pecl install[^;]*imagick-\)[0-9.]*|\1$imagick_version|" ./Containers/nextcloud/Dockerfile sed -i "s|pecl install imagick.*\;|pecl install imagick-$imagick_version\;|" ./Containers/nextcloud/Dockerfile
# Igbinary # Igbinary
igbinary_version="$( igbinary_version="$(
@ -69,7 +69,7 @@ jobs:
| sort -V \ | sort -V \
| tail -1 | tail -1
)" )"
sed -i "s|\(pecl install[^;]*igbinary-\)[0-9.]*|\1$igbinary_version|" ./Containers/nextcloud/Dockerfile sed -i "s|pecl install igbinary.*\;|pecl install igbinary-$igbinary_version\;|" ./Containers/nextcloud/Dockerfile
# Nextcloud # Nextcloud
NC_MAJOR="$(grep "ENV NEXTCLOUD_VERSION" ./Containers/nextcloud/Dockerfile | grep -oP '[23][0-9]')" NC_MAJOR="$(grep "ENV NEXTCLOUD_VERSION" ./Containers/nextcloud/Dockerfile | grep -oP '[23][0-9]')"
@ -79,7 +79,7 @@ jobs:
fi fi
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7 uses: peter-evans/create-pull-request@v6
with: with:
commit-message: nextcloud-update automated change commit-message: nextcloud-update automated change
signoff: true signoff: true

View file

@ -16,11 +16,11 @@ jobs:
name: PHP Deprecation Detector name: PHP Deprecation Detector
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/checkout@v4
- name: Set up php - name: Set up php
uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2 uses: shivammathur/setup-php@v2
with: with:
php-version: 8.4 php-version: 8.3
extensions: apcu extensions: apcu
coverage: none coverage: none

View file

@ -1,123 +0,0 @@
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

View file

@ -1,91 +0,0 @@
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

View file

@ -10,12 +10,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/checkout@v4
- name: Set up php - name: Set up php
uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2 uses: shivammathur/setup-php@v2
with: with:
php-version: 8.4 php-version: 8.3
extensions: apcu extensions: apcu
coverage: none coverage: none
@ -30,7 +30,7 @@ jobs:
continue-on-error: true continue-on-error: true
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7 uses: peter-evans/create-pull-request@v6
with: with:
token: ${{ secrets.COMMAND_BOT_PAT }} token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: Update psalm baseline commit-message: Update psalm baseline

View file

@ -2,9 +2,6 @@
# #
# https://github.com/nextcloud/.github # https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization # 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 name: Static analysis
@ -22,9 +19,6 @@ concurrency:
group: psalm-${{ github.head_ref || github.run_id }} group: psalm-${{ github.head_ref || github.run_id }}
cancel-in-progress: true cancel-in-progress: true
permissions:
contents: read
jobs: jobs:
static-analysis: static-analysis:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -32,19 +26,15 @@ jobs:
name: static-psalm-analysis name: static-psalm-analysis
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- name: Set up php - name: Set up php
uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2.36.0 uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # v2
with: with:
php-version: 8.4 php-version: 8.3
extensions: apcu extensions: apcu
coverage: none coverage: none
ini-file: development ini-file: development
# Temporary workaround for missing pcntl_* in PHP 8.3
ini-values: disable_functions=
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -15,9 +15,9 @@ jobs:
name: Check Shell name: Check Shell
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/checkout@v4
- name: Run Shellcheck - name: Run Shellcheck
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0 uses: ludeeus/action-shellcheck@2.0.0
with: with:
check_together: 'yes' check_together: 'yes'
env: env:

View file

@ -10,7 +10,7 @@ jobs:
name: update talk name: update talk
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/checkout@v4
- name: Run talk-container-update - name: Run talk-container-update
run: | run: |
# Recording # Recording
@ -36,7 +36,7 @@ jobs:
# Janus # Janus
janus_version="$( janus_version="$(
git ls-remote https://github.com/meetecho/janus-gateway v1.*.* \ git ls-remote https://github.com/meetecho/janus-gateway v0.*.* \
| cut -d/ -f3 \ | cut -d/ -f3 \
| sort -V \ | sort -V \
| grep -E "^v[0-9]+\.[0-9]+\.[0-9]+$" \ | 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 sed -i "s|^ARG JANUS_VERSION=.*$|ARG JANUS_VERSION=$janus_version|" ./Containers/talk/Dockerfile
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7 uses: peter-evans/create-pull-request@v6
with: with:
commit-message: talk-update automated change commit-message: talk-update automated change
signoff: true signoff: true

View file

@ -24,12 +24,12 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@v4
- name: Set up php ${{ matrix.php-versions }} - name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@7bf05c6b704e0b9bfee22300130a31b5ea68d593 # v2 uses: shivammathur/setup-php@v2
with: with:
php-version: 8.4 php-version: 8.3
extensions: apcu extensions: apcu
coverage: none coverage: none

View file

@ -1,11 +0,0 @@
name: Update Copyright
on:
workflow_dispatch:
jobs:
update-copyright:
name: update copyright
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

View file

@ -11,19 +11,16 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@v4
- name: update helm chart - name: update helm chart
run: | run: |
set -x 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)"
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 export DOCKER_TAG
set +x if [ -n "$DOCKER_TAG" ] && ! grep -q "$DOCKER_TAG" ./nextcloud-aio-helm-chart/templates/nextcloud-aio-nextcloud-deployment.yaml; then
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" sudo bash nextcloud-aio-helm-chart/update-helm.sh "$DOCKER_TAG"
fi fi
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7 uses: peter-evans/create-pull-request@v6
with: with:
commit-message: Helm Chart updates commit-message: Helm Chart updates
signoff: true signoff: true

View file

@ -11,12 +11,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 uses: actions/checkout@v4
- name: update yaml files - name: update yaml files
run: | run: |
sudo bash manual-install/update-yaml.sh sudo bash manual-install/update-yaml.sh
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7 uses: peter-evans/create-pull-request@v6
with: with:
commit-message: Yaml updates commit-message: Yaml updates
signoff: true signoff: true

View file

@ -1,37 +0,0 @@
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

View file

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

View file

@ -1,7 +0,0 @@
# syntax=docker/dockerfile:latest
FROM alpine:3.23.3
RUN set -ex; \
apk upgrade --no-cache -a
LABEL org.label-schema.vendor="Nextcloud"

View file

@ -15,7 +15,6 @@
} }
https://{$ADDITIONAL_TRUSTED_DOMAIN}:443, https://{$ADDITIONAL_TRUSTED_DOMAIN}:443,
http://{$APACHE_HOST}:23973, # For Collabora callback and WOPI requests, see containers.json
{$PROTOCOL}://{$NC_DOMAIN}:{$APACHE_PORT} { {$PROTOCOL}://{$NC_DOMAIN}:{$APACHE_PORT} {
header -Server header -Server
header -X-Powered-By header -X-Powered-By
@ -41,7 +40,7 @@ http://{$APACHE_HOST}:23973, # For Collabora callback and WOPI requests, see con
route /onlyoffice/* { route /onlyoffice/* {
uri strip_prefix /onlyoffice uri strip_prefix /onlyoffice
reverse_proxy {$ONLYOFFICE_HOST}:80 { reverse_proxy {$ONLYOFFICE_HOST}:80 {
header_up X-Forwarded-Host {http.request.hostport}/onlyoffice header_up X-Forwarded-Host {http.request.host}/onlyoffice
header_up X-Forwarded-Proto https header_up X-Forwarded-Proto https
} }
} }
@ -52,12 +51,6 @@ http://{$APACHE_HOST}:23973, # For Collabora callback and WOPI requests, see con
reverse_proxy {$TALK_HOST}:8081 reverse_proxy {$TALK_HOST}:8081
} }
# Whiteboard
route /whiteboard/* {
uri strip_prefix /whiteboard
reverse_proxy {$WHITEBOARD_HOST}:3002
}
# Nextcloud # Nextcloud
route { route {
header Strict-Transport-Security max-age=31536000; header Strict-Transport-Security max-age=31536000;

View file

@ -1,8 +1,8 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
FROM caddy:2.10.2-alpine AS caddy FROM caddy:2.8.4-alpine AS caddy
# From https://github.com/docker-library/httpd/blob/master/2.4/alpine/Dockerfile # From https://github.com/docker-library/httpd/blob/master/2.4/alpine/Dockerfile
FROM httpd:2.4.66-alpine3.23 FROM httpd:2.4.62-alpine3.20
COPY --from=caddy /usr/bin/caddy /usr/bin/caddy COPY --from=caddy /usr/bin/caddy /usr/bin/caddy
@ -81,12 +81,10 @@ RUN set -ex; \
\ \
echo "root:$(openssl rand -base64 12)" | chpasswd echo "root:$(openssl rand -base64 12)" | chpasswd
USER 33 USER www-data
ENTRYPOINT ["/start.sh"] ENTRYPOINT ["/start.sh"]
CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"] CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"]
HEALTHCHECK CMD /healthcheck.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"

View file

@ -3,3 +3,7 @@
nc -z "$NEXTCLOUD_HOST" 9000 || exit 0 nc -z "$NEXTCLOUD_HOST" 9000 || exit 0
nc -z 127.0.0.1 8000 || exit 1 nc -z 127.0.0.1 8000 || exit 1
nc -z 127.0.0.1 "$APACHE_PORT" || 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

View file

@ -46,9 +46,7 @@ echo "$CADDYFILE" > /tmp/Caddyfile
# Change the trusted_proxies in case of reverse proxies # Change the trusted_proxies in case of reverse proxies
if [ "$APACHE_PORT" != '443' ]; then if [ "$APACHE_PORT" != '443' ]; then
# Here the 100.64.0.0/10 range gets added which is the CGNAT range used by Tailscale nodes CADDYFILE="$(sed 's|# trusted_proxies placeholder|trusted_proxies static private_ranges|' /tmp/Caddyfile)"
# 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 else
CADDYFILE="$(sed "s|# trusted_proxies placeholder|trusted_proxies static $IPv4_ADDRESS|" /tmp/Caddyfile)" CADDYFILE="$(sed "s|# trusted_proxies placeholder|trusted_proxies static $IPv4_ADDRESS|" /tmp/Caddyfile)"
fi fi
@ -66,11 +64,6 @@ caddy fmt --overwrite /tmp/Caddyfile
# Add caddy path # Add caddy path
mkdir -p /mnt/data/caddy/ 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 # Fix apache startup
rm -f /usr/local/apache2/logs/httpd.pid rm -f /usr/local/apache2/logs/httpd.pid

View file

@ -9,8 +9,8 @@ logfile_backups=10
loglevel=error loglevel=error
[program:apache] [program:apache]
# Stdout logging is disabled as otherwise the logs are spammed # stdout_logfile=/dev/stdout
stdout_logfile=NONE # stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0 stderr_logfile_maxbytes=0
command=apachectl -DFOREGROUND command=apachectl -DFOREGROUND

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
FROM alpine:3.23.3 FROM alpine:3.20.2
RUN set -ex; \ RUN set -ex; \
\ \
@ -11,19 +11,15 @@ RUN set -ex; \
rsync \ rsync \
fuse \ fuse \
py3-llfuse \ py3-llfuse \
jq \ jq
openssh-client
VOLUME /root VOLUME /root
COPY --chmod=770 *.sh / COPY --chmod=770 *.sh /
COPY borg_excludes /
ENTRYPOINT ["/start.sh"] ENTRYPOINT ["/start.sh"]
# hadolint ignore=DL3002 # hadolint ignore=DL3002
USER root 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" ENV BORG_RETENTION_POLICY="--keep-within=7d --keep-weekly=4 --keep-monthly=6"

View file

@ -34,23 +34,19 @@ for volume in "${DEFAULT_VOLUMES[@]}"; do
done done
# Check if target is mountpoint # Check if target is mountpoint
if [ -z "$BORG_REMOTE_REPO" ] && ! mountpoint -q "$MOUNT_DIR"; then if ! mountpoint -q /mnt/borgbackup; then
echo "$MOUNT_DIR is not a mountpoint which is not allowed." echo "/mnt/borgbackup is not a mountpoint which is not allowed."
exit 1 exit 1
fi fi
# Check if repo is uninitialized # Check if target is empty
if [ "$BORG_MODE" != backup ] && [ "$BORG_MODE" != test ] && ! borg info > /dev/null; then if [ "$BORG_MODE" != backup ] && [ "$BORG_MODE" != test ] && ! [ -f "$BORG_BACKUP_DIRECTORY/config" ]; then
if [ -n "$BORG_REMOTE_REPO" ]; then echo "The repository is empty. Cannot perform check or restore."
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 exit 1
fi fi
# Do not continue if this file exists (needed for simple external blocking) # Do not continue if this file exists (needed for simple external blocking)
if [ -z "$BORG_REMOTE_REPO" ] && [ -f "$BORG_BACKUP_DIRECTORY/aio-lockfile" ]; then if [ -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 "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." 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 exit 1
@ -61,15 +57,6 @@ if [ "$BORG_MODE" = backup ] || [ "$BORG_MODE" = restore ]; then
touch "/nextcloud_aio_volumes/nextcloud_aio_database_dump/backup-is-running" touch "/nextcloud_aio_volumes/nextcloud_aio_database_dump/backup-is-running"
fi 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 # Do the backup
if [ "$BORG_MODE" = backup ]; then if [ "$BORG_MODE" = backup ]; then
@ -84,8 +71,8 @@ if [ "$BORG_MODE" = backup ]; then
echo "database-dump is missing. Cannot perform backup!" echo "database-dump is missing. Cannot perform backup!"
echo "Please check the database container logs!" echo "Please check the database container logs!"
exit 1 exit 1
elif ! [ -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/.ocdata" ] && ! [ -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/.ncdata" ]; then elif ! [ -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/.ocdata" ]; then
echo "The .ncdata or .ocdata file is missing in Nextcloud datadir which means it is invalid!" echo "The .ocdata file is missing in Nextcloud datadir which means it is invalid!"
echo "Is the drive where the datadir is located on still mounted?" echo "Is the drive where the datadir is located on still mounted?"
exit 1 exit 1
fi fi
@ -113,22 +100,15 @@ if [ "$BORG_MODE" = backup ]; then
exit 1 exit 1
fi fi
if [ -z "$BORG_REMOTE_REPO" ]; then # Create backup folder
# Create backup folder mkdir -p "$BORG_BACKUP_DIRECTORY"
mkdir -p "$BORG_BACKUP_DIRECTORY"
fi
# Initialize the repository if can't get info from target # Initialize the repository if the target is empty
if ! borg info > /dev/null; then if ! [ -f "$BORG_BACKUP_DIRECTORY/config" ]; then
# Don't initialize if already initialized # Don't initialize if already initialized
if [ -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config" ]; then if [ -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config" ]; then
if [ -n "$BORG_REMOTE_REPO" ]; then echo "No borg config file was found in the targeted directory."
echo "Borg could not get info from the remote repo." echo "This might happen if the targeted directory is located on an external drive and the drive not connected anymore. You should check this."
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 "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" echo "sudo docker exec nextcloud-aio-mastercontainer rm /mnt/docker-aio-config/data/borg.config"
exit 1 exit 1
@ -136,39 +116,28 @@ if [ "$BORG_MODE" = backup ]; then
echo "Initializing repository..." echo "Initializing repository..."
NEW_REPOSITORY=1 NEW_REPOSITORY=1
if ! borg init --debug --encryption=repokey-blake2; then if ! borg init --debug --encryption=repokey-blake2 "$BORG_BACKUP_DIRECTORY"; then
echo "Could not initialize borg repository." echo "Could not initialize borg repository."
rm -f "$BORG_BACKUP_DIRECTORY/config"
exit 1 exit 1
fi fi
borg config "$BORG_BACKUP_DIRECTORY" additional_free_space 2G
if [ -z "$BORG_REMOTE_REPO" ]; then # Fix too large Borg cache
# borg config only works for local repos; it's up to the remote to ensure the disk isn't full # https://borgbackup.readthedocs.io/en/stable/faq.html#the-borg-cache-eats-way-too-much-disk-space-what-can-i-do
borg config :: additional_free_space 2G 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"
# Fix too large Borg cache # Make a backup from the borg config file
# https://borgbackup.readthedocs.io/en/stable/faq.html#the-borg-cache-eats-way-too-much-disk-space-what-can-i-do if ! [ -f "$BORG_BACKUP_DIRECTORY/config" ]; then
BORG_ID="$(borg config :: id)" echo "The borg config file wasn't created. Something is wrong."
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 exit 1
fi fi
rm -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config" rm -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config"
if [ -n "$BORG_REMOTE_REPO" ]; then if ! cp "$BORG_BACKUP_DIRECTORY/config" "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config"; then
# `borg config` does not support remote repos so instead create a dummy file and rely on the remote to avoid echo "Could not copy config file to second place. Cannot perform backup."
# corruption of the config file (which contains the encryption key). We don't actually use the contents of exit 1
# 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 fi
echo "Repository successfully initialized." echo "Repository successfully initialized."
@ -180,27 +149,13 @@ if [ "$BORG_MODE" = backup ]; then
# Borg options # Borg options
# auto,zstd compression seems to has the best ratio based on: # auto,zstd compression seems to has the best ratio based on:
# https://forum.level1techs.com/t/optimal-compression-for-borg-backups/145870/6 # https://forum.level1techs.com/t/optimal-compression-for-borg-backups/145870/6
BORG_OPTS=(-v --stats --compression "auto,zstd") BORG_OPTS=(-v --stats --compression "auto,zstd" --exclude-caches)
if [ "$NEW_REPOSITORY" = 1 ]; then if [ "$NEW_REPOSITORY" = 1 ]; then
BORG_OPTS+=(--progress) BORG_OPTS+=(--progress)
fi fi
# Exclude the nextcloud log and audit log for GDPR reasons # 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" --exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/lost+found") BORG_EXCLUDE=(--exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud/data/nextcloud.log*" --exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud/data/audit.log")
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 # 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 if ! [ -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config" ]; then
@ -212,9 +167,9 @@ if [ "$BORG_MODE" = backup ]; then
# Create the backup # Create the backup
echo "Starting the backup..." echo "Starting the backup..."
get_start_time get_start_time
if ! borg create "${BORG_OPTS[@]}" "${BORG_INCLUDE[@]}" "${BORG_EXCLUDE[@]}" "::$CURRENT_DATE-nextcloud-aio" "/nextcloud_aio_volumes/" --exclude-from /borg_excludes; then if ! borg create "${BORG_OPTS[@]}" "${BORG_EXCLUDE[@]}" "$BORG_BACKUP_DIRECTORY::$CURRENT_DATE-nextcloud-aio" "/nextcloud_aio_volumes/"; then
echo "Deleting the failed backup archive..." echo "Deleting the failed backup archive..."
borg delete --stats "::$CURRENT_DATE-nextcloud-aio" borg delete --stats "$BORG_BACKUP_DIRECTORY::$CURRENT_DATE-nextcloud-aio"
echo "Backup failed!" echo "Backup failed!"
echo "You might want to check the backup integrity via the AIO interface." echo "You might want to check the backup integrity via the AIO interface."
if [ "$NEW_REPOSITORY" = 1 ]; then if [ "$NEW_REPOSITORY" = 1 ]; then
@ -233,14 +188,14 @@ if [ "$BORG_MODE" = backup ]; then
# Prune archives # Prune archives
echo "Pruning the archives..." echo "Pruning the archives..."
if ! borg prune --stats --glob-archives '*_*-nextcloud-aio' "${BORG_PRUNE_OPTS[@]}"; then if ! borg prune --stats --glob-archives '*_*-nextcloud-aio' "${BORG_PRUNE_OPTS[@]}" "$BORG_BACKUP_DIRECTORY"; then
echo "Failed to prune archives!" echo "Failed to prune archives!"
exit 1 exit 1
fi fi
# Compact archives # Compact archives
echo "Compacting the archives..." echo "Compacting the archives..."
if ! borg compact; then if ! borg compact "$BORG_BACKUP_DIRECTORY"; then
echo "Failed to compact archives!" echo "Failed to compact archives!"
exit 1 exit 1
fi fi
@ -257,19 +212,19 @@ if [ "$BORG_MODE" = backup ]; then
fi fi
done done
echo "Starting the backup for additional volumes..." echo "Starting the backup for additional volumes..."
if ! borg create "${BORG_OPTS[@]}" "::$CURRENT_DATE-additional-docker-volumes" "/docker_volumes/"; then if ! borg create "${BORG_OPTS[@]}" "$BORG_BACKUP_DIRECTORY::$CURRENT_DATE-additional-docker-volumes" "/docker_volumes/"; then
echo "Deleting the failed backup archive..." echo "Deleting the failed backup archive..."
borg delete --stats "::$CURRENT_DATE-additional-docker-volumes" borg delete --stats "$BORG_BACKUP_DIRECTORY::$CURRENT_DATE-additional-docker-volumes"
echo "Backup of additional docker-volumes failed!" echo "Backup of additional docker-volumes failed!"
exit 1 exit 1
fi fi
echo "Pruning additional volumes..." echo "Pruning additional volumes..."
if ! borg prune --stats --glob-archives '*_*-additional-docker-volumes' "${BORG_PRUNE_OPTS[@]}"; then if ! borg prune --stats --glob-archives '*_*-additional-docker-volumes' "${BORG_PRUNE_OPTS[@]}" "$BORG_BACKUP_DIRECTORY"; then
echo "Failed to prune additional docker-volumes archives!" echo "Failed to prune additional docker-volumes archives!"
exit 1 exit 1
fi fi
echo "Compacting additional volumes..." echo "Compacting additional volumes..."
if ! borg compact; then if ! borg compact "$BORG_BACKUP_DIRECTORY"; then
echo "Failed to compact additional docker-volume archives!" echo "Failed to compact additional docker-volume archives!"
exit 1 exit 1
fi fi
@ -287,19 +242,19 @@ if [ "$BORG_MODE" = backup ]; then
EXCLUDE_DIRS+=(--exclude "/host_mounts/$directory/") EXCLUDE_DIRS+=(--exclude "/host_mounts/$directory/")
done done
echo "Starting the backup for additional host mounts..." echo "Starting the backup for additional host mounts..."
if ! borg create "${BORG_OPTS[@]}" "${EXCLUDE_DIRS[@]}" "::$CURRENT_DATE-additional-host-mounts" "/host_mounts/"; then if ! borg create "${BORG_OPTS[@]}" "${EXCLUDE_DIRS[@]}" "$BORG_BACKUP_DIRECTORY::$CURRENT_DATE-additional-host-mounts" "/host_mounts/"; then
echo "Deleting the failed backup archive..." echo "Deleting the failed backup archive..."
borg delete --stats "::$CURRENT_DATE-additional-host-mounts" borg delete --stats "$BORG_BACKUP_DIRECTORY::$CURRENT_DATE-additional-host-mounts"
echo "Backup of additional host-mounts failed!" echo "Backup of additional host-mounts failed!"
exit 1 exit 1
fi fi
echo "Pruning additional host mounts..." echo "Pruning additional host mounts..."
if ! borg prune --stats --glob-archives '*_*-additional-host-mounts' "${BORG_PRUNE_OPTS[@]}"; then if ! borg prune --stats --glob-archives '*_*-additional-host-mounts' "${BORG_PRUNE_OPTS[@]}" "$BORG_BACKUP_DIRECTORY"; then
echo "Failed to prune additional host-mount archives!" echo "Failed to prune additional host-mount archives!"
exit 1 exit 1
fi fi
echo "Compacting additional host mounts..." echo "Compacting additional host mounts..."
if ! borg compact; then if ! borg compact "$BORG_BACKUP_DIRECTORY"; then
echo "Failed to compact additional host-mount archives!" echo "Failed to compact additional host-mount archives!"
exit 1 exit 1
fi fi
@ -321,38 +276,17 @@ fi
if [ "$BORG_MODE" = restore ]; then if [ "$BORG_MODE" = restore ]; then
get_start_time get_start_time
# Pick archive to restore # Perform the restore
if [ -n "$SELECTED_RESTORE_TIME" ]; then if [ -n "$SELECTED_RESTORE_TIME" ]; then
SELECTED_ARCHIVE="$(borg list | grep "nextcloud-aio" | grep "$SELECTED_RESTORE_TIME" | awk -F " " '{print $1}' | head -1)" SELECTED_ARCHIVE="$(borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | grep "$SELECTED_RESTORE_TIME" | awk -F " " '{print $1}' | head -1)"
else else
SELECTED_ARCHIVE="$(borg list | grep "nextcloud-aio" | awk -F " " '{print $1}' | sort -r | head -1)" SELECTED_ARCHIVE="$(borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | awk -F " " '{print $1}' | sort -r | head -1)"
fi fi
echo "Restoring '$SELECTED_ARCHIVE'..." echo "Restoring '$SELECTED_ARCHIVE'..."
mkdir -p /tmp/borg
ADDITIONAL_RSYNC_EXCLUDES=() if ! borg mount "$BORG_BACKUP_DIRECTORY::$SELECTED_ARCHIVE" /tmp/borg; then
ADDITIONAL_BORG_EXCLUDES=() echo "Could not mount the backup!"
ADDITIONAL_FIND_EXCLUDES=() exit 1
# 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 fi
# Save Additional Backup dirs # Save Additional Backup dirs
@ -365,12 +299,27 @@ if [ "$BORG_MODE" = restore ]; then
DAILY_BACKUPTIME="$(cat /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/daily_backup_time)" DAILY_BACKUPTIME="$(cat /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/daily_backup_time)"
fi 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 # Save current aio password
AIO_PASSWORD="$(jq '.password' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)" AIO_PASSWORD="$(jq '.password' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
# Save current backup location vars # Save current path
BORG_LOCATION="$(jq '.borg_backup_host_location' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)" 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 # Save current nextcloud datadir
if grep -q '"nextcloud_datadir":' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json; then if grep -q '"nextcloud_datadir":' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json; then
@ -379,116 +328,21 @@ if [ "$BORG_MODE" = restore ]; then
NEXTCLOUD_DATADIR='""' NEXTCLOUD_DATADIR='""'
fi fi
if [ -z "$BORG_REMOTE_REPO" ]; then # Restore the configuration file
mkdir -p /tmp/borg if ! rsync --archive --human-readable -vv \
if ! borg mount "::$SELECTED_ARCHIVE" /tmp/borg; then /tmp/borg/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json \
echo "Could not mount the backup!" /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json; then
exit 1 RESTORE_FAILED=1
fi echo "Something failed while restoring the configuration.json."
# 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 fi
# Set backup-mode to restore since it was a restore # Set backup-mode to restore since it was a restore
CONTENTS="$(jq '."backup-mode" = "restore"' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)" 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 echo -E "${CONTENTS}" > /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json
# Reset the backup location vars to the currently used one # Reset the backup path to the currently used one
CONTENTS="$(jq ".borg_backup_host_location = $BORG_LOCATION" /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)" 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 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 # Reset the AIO password to the currently used one
CONTENTS="$(jq ".password = $AIO_PASSWORD" /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)" CONTENTS="$(jq ".password = $AIO_PASSWORD" /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json)"
@ -512,6 +366,8 @@ if [ "$BORG_MODE" = restore ]; then
chmod 770 "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/daily_backup_time" chmod 770 "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/daily_backup_time"
fi fi
umount /tmp/borg
if [ "$RESTORE_FAILED" = 1 ]; then if [ "$RESTORE_FAILED" = 1 ]; then
exit 1 exit 1
fi fi
@ -528,12 +384,6 @@ if [ "$BORG_MODE" = restore ]; then
touch "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/fingerprint.update" touch "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/fingerprint.update"
chmod 777 "/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 # Delete redis cache
rm -f "/mnt/redis/dump.rdb" rm -f "/mnt/redis/dump.rdb"
fi fi
@ -544,9 +394,9 @@ if [ "$BORG_MODE" = check ]; then
echo "Checking the backup integrity..." echo "Checking the backup integrity..."
# Perform the check # Perform the check
if ! borg check -v --verify-data; then if ! borg check -v --verify-data "$BORG_BACKUP_DIRECTORY"; then
echo "Some errors were found while checking the backup integrity!" echo "Some errors were found while checking the backup integrity!"
echo "Check the AIO interface for advice on how to proceed now!" echo "Check the AIO interface for advices on how to proceed now!"
exit 1 exit 1
fi fi
@ -562,7 +412,7 @@ if [ "$BORG_MODE" = "check-repair" ]; then
echo "Checking the backup integrity and repairing it..." echo "Checking the backup integrity and repairing it..."
# Perform the check-repair # Perform the check-repair
if ! echo YES | borg check -v --repair; then if ! echo YES | borg check -v --repair "$BORG_BACKUP_DIRECTORY"; then
echo "Some errors were found while checking and repairing the backup integrity!" echo "Some errors were found while checking and repairing the backup integrity!"
exit 1 exit 1
fi fi
@ -575,49 +425,24 @@ fi
# Do the backup test # Do the backup test
if [ "$BORG_MODE" = test ]; then if [ "$BORG_MODE" = test ]; then
if [ -n "$BORG_REMOTE_REPO" ]; then if ! [ -d "$BORG_BACKUP_DIRECTORY" ]; then
if ! borg info > /dev/null; then echo "No 'borg' directory in the given backup directory found!"
echo "Borg could not get info from the remote repo." echo "Only the files/folders below have been found in the given directory."
echo "See the above borg info output for details." ls -a "$MOUNT_DIR"
exit 1 echo "Please adjust the directory so that the borg archive is positioned in a folder named 'borg' inside the given directory!"
fi exit 1
else elif ! [ -f "$BORG_BACKUP_DIRECTORY/config" ]; then
if ! [ -d "$BORG_BACKUP_DIRECTORY" ]; then echo "A 'borg' directory was found but could not find the borg archive."
echo "No 'borg' directory in the given backup directory found!" echo "Only the files/folders below have been found in the borg directory."
echo "Only the files/folders below have been found in the given directory." ls -a "$BORG_BACKUP_DIRECTORY"
ls -a "$MOUNT_DIR" echo "The archive and most importantly the config file must be positioned directly in the 'borg' subfolder."
echo "Please adjust the directory so that the borg archive is positioned in a folder named 'borg' inside the given directory!" exit 1
exit 1 elif ! borg list "$BORG_BACKUP_DIRECTORY"; then
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 "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!" echo "Most likely the entered password was wrong so please adjust it accordingly!"
exit 1 exit 1
else else
if ! borg list | grep "nextcloud-aio"; then echo "Everything looks fine so feel free to continue!"
echo "The backup archive does not contain a valid Nextcloud AIO backup." exit 0
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
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

View file

@ -1,11 +0,0 @@
# 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*

View file

@ -2,7 +2,7 @@
# Variables # Variables
export MOUNT_DIR="/mnt/borgbackup" export MOUNT_DIR="/mnt/borgbackup"
export BORG_BACKUP_DIRECTORY="$MOUNT_DIR/borg" # necessary even when remote to store the aio-lockfile export BORG_BACKUP_DIRECTORY="$MOUNT_DIR/borg"
# Validate BORG_PASSWORD # Validate BORG_PASSWORD
if [ -z "$BORG_PASSWORD" ] && [ -z "$BACKUP_RESTORE_PASSWORD" ]; then if [ -z "$BORG_PASSWORD" ] && [ -z "$BACKUP_RESTORE_PASSWORD" ]; then
@ -18,22 +18,10 @@ else
fi fi
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes
export BORG_RELOCATED_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 # Validate BORG_MODE
if [ "$BORG_MODE" != backup ] && [ "$BORG_MODE" != restore ] && [ "$BORG_MODE" != check ] && [ "$BORG_MODE" != "check-repair" ] && [ "$BORG_MODE" != "test" ] && [ "$BORG_MODE" != "list" ]; then 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', 'test' and 'list'." echo "No correct BORG_MODE mode applied. Valid are 'backup', 'check', 'restore' and 'test'."
exit 1 exit 1
fi fi
@ -48,8 +36,8 @@ fi
rm -f "/nextcloud_aio_volumes/nextcloud_aio_database_dump/backup-is-running" rm -f "/nextcloud_aio_volumes/nextcloud_aio_database_dump/backup-is-running"
# Get a list of all available borg archives # Get a list of all available borg archives
if borg list &>/dev/null; then if borg list "$BORG_BACKUP_DIRECTORY" &>/dev/null; then
borg list | grep "nextcloud-aio" | awk -F " " '{print $1","$3,$4}' > "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list" borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | awk -F " " '{print $1","$3,$4}' > "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list"
else else
echo "" > "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list" echo "" > "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list"
fi fi

View file

@ -1,38 +1,26 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
FROM alpine:3.23.3 # Probably from this file: https://github.com/Cisco-Talos/clamav-docker/blob/main/clamav/1.3/alpine/Dockerfile
FROM clamav/clamav:1.3.1-61
COPY clamav.conf /clamav.conf
COPY --chmod=775 start.script /start.script
RUN set -ex; \ RUN set -ex; \
apk upgrade --no-cache -a; \ apk upgrade --no-cache -a; \
apk add --no-cache tzdata clamav clamav-milter supervisor bash; \ apk add --no-cache tzdata bash; \
mkdir -p /tmp /var/lib/clamav /run/clamav /var/log/supervisord /var/run/supervisord; \ mkdir -p /var/run/clamav /run/lock; \
chmod 777 -R /tmp /run/clamav /var/log/clamav /var/log/supervisord /var/run/supervisord; \ chown -R clamav:clamav /var/run/clamav /run/clamav /var/log/clamav /var/lock /run/lock; \
chown -R 100:100 /var/lib/clamav; \ chmod 777 -R /var/run/clamav /run/clamav /var/log/clamav /var/lock /run/lock /tmp; \
sed -i "s|#\?MaxDirectoryRecursion.*|MaxDirectoryRecursion 30|g" /etc/clamav/clamd.conf; \ sed -i "/^set -eu/r /start.script" /init-unprivileged; \
sed -i "s|#\?MaxScanSize.*|MaxScanSize 2000M|g" /etc/clamav/clamd.conf; \ rm /start.script; \
sed -i "s|#\?MaxFileSize.*|MaxFileSize 2000M|g" /etc/clamav/clamd.conf; \ grep -q 'clamd --foreground &' /init-unprivileged; \
sed -i "s|#\?PCREMaxFileSize.*|PCREMaxFileSize 2000M|g" /etc/clamav/clamd.conf; \ sed -i "s|clamd --foreground \&|clamd --foreground --config-file /tmp/clamd.conf \&|" /init-unprivileged; \
# StreamMaxLength must be synced with av_stream_max_length inside the Nextcloud files_antivirus plugin cat /init-unprivileged
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 VOLUME /var/lib/clamav
ENTRYPOINT ["/start.sh"]
CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"] USER clamav
LABEL com.centurylinklabs.watchtower.enable="false" \
wud.watch="false" \ LABEL com.centurylinklabs.watchtower.enable="false"
org.label-schema.vendor="Nextcloud"
HEALTHCHECK --start-period=60s --retries=9 CMD /healthcheck.sh ENTRYPOINT ["/init-unprivileged"]

View file

@ -0,0 +1,5 @@
# AIO settings
MaxDirectoryRecursion 30
MaxFileSize 10G
PCREMaxFileSize 10G
StreamMaxLength 10G

View file

@ -1,9 +0,0 @@
#!/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

View file

@ -0,0 +1,4 @@
# 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

View file

@ -1,8 +0,0 @@
#!/bin/bash
# Print out clamav version for compliance reasons
clamscan --version
echo "Clamav started"
exec "$@"

View file

@ -1,30 +0,0 @@
[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

View file

@ -1,16 +0,0 @@
# 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"

View file

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

View file

@ -1,15 +1,21 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
# From a file located probably somewhere here: https://github.com/CollaboraOnline/online/blob/master/docker/from-packages/Dockerfile # From a file located probably somewhere here: https://github.com/CollaboraOnline/online/tree/master/docker
FROM collabora/code:25.04.8.2.1 FROM collabora/code:24.04.5.2.1
USER root USER root
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
COPY --chmod=775 healthcheck.sh /healthcheck.sh # 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/*;
USER 1001 USER 100
HEALTHCHECK --start-period=60s --retries=9 CMD /healthcheck.sh HEALTHCHECK CMD nc -z 127.0.0.1 9980 || exit 1
LABEL com.centurylinklabs.watchtower.enable="false" \ LABEL com.centurylinklabs.watchtower.enable="false"
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

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

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
FROM haproxy:3.3.2-alpine FROM haproxy:3.0.3-alpine
# hadolint ignore=DL3002 # hadolint ignore=DL3002
USER root USER root
@ -18,6 +18,4 @@ COPY --chmod=664 haproxy.cfg /haproxy.cfg
ENTRYPOINT ["/start.sh"] ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD /healthcheck.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"

View file

@ -4,18 +4,16 @@ global
maxconn 10 maxconn 10
defaults defaults
timeout connect 30s timeout connect 10s
timeout client 30s timeout client 10s
timeout server 1800s timeout server 10s
frontend http frontend http
mode http mode http
bind :::2375 v4v6 bind :::2375 v4v6
http-request deny unless { src 127.0.0.1 } || { src ::1 } || { src NC_IPV4_PLACEHOLDER } || { src NC_IPV6_PLACEHOLDER } http-request deny unless { src 127.0.0.1 } || { src ::1 } || { src NC_IPV4_PLACEHOLDER } || { src NC_IPV6_PLACEHOLDER }
# docker system _ping # 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 # 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 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 # container inspect: GET containers/%s/logs
@ -24,12 +22,7 @@ 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 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 # 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 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 # container create: POST containers/create?name=%s
# ACL to restrict container name to nc_app_[a-zA-Z0-9_.-]+ # ACL to restrict container name to nc_app_[a-zA-Z0-9_.-]+
@ -40,19 +33,19 @@ frontend http
# ACL to deny if there are any binds # ACL to deny if there are any binds
acl binds_present req.body -m reg -i "\"HostConfig\"\s*:.*\"Binds\"\s*:" acl binds_present req.body -m reg -i "\"HostConfig\"\s*:.*\"Binds\"\s*:"
# ACL to restrict the type of Mounts to volume # ACL to restrict the type of Mounts to volume
acl type_not_volume req.body -m reg -i "\"Mounts\"\s*:\s*\[[^\]]*(\"Type\"\s*:\s*\"(?!volume\b)\w+\"[^\]]*)+\]" acl type_not_volume req.body -m reg -i "\"Mounts\":\s*\[[^\]]*(\"Type\":\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 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(by searching for "Privileged" word in all payload) # ACL to restrict container creation, that it has HostConfig.Privileged not set
acl no_privileged_flag req.body -m reg -i "\"Privileged\"" acl no_privileged_flag req.body -m reg -i "\"HostConfig\":\s?{[^}]*\"Privileged\""
# ACL to allow mount volume with strict pattern for name: nc_app_[a-zA-Z0-9_.-]+_data # 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*\[\s*{[^}]*\"Source\"\s*:\s*\"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\""
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 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 # end of container create
# volume create: POST volumes/create # volume create: POST volumes/create
# restrict name # restrict name
acl nc_app_volume_data req.body -m reg -i "\"Name\"\s*:\s*\"nc_app_[a-zA-Z0-9_.-]+_data\"" acl nc_app_volume_data req.body -m reg -i "\"Name\":\s?\"nc_app_[a-zA-Z0-9_.-]+_data\""
# do not allow to use "device" word e.g., "--opt device=:/path/to/dir" # do not allow to use "device" word e.g., "--opt device=:/path/to/dir"
acl volume_no_device req.body -m reg -i "\"device\"" 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 http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/volumes/create } nc_app_volume_data !volume_no_device METH_POST

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
FROM alpine:3.23.3 FROM alpine:3.20.2
RUN set -ex; \ RUN set -ex; \
apk upgrade --no-cache -a; \ apk upgrade --no-cache -a; \
apk add --no-cache bash lighttpd netcat-openbsd; \ apk add --no-cache bash lighttpd netcat-openbsd; \
@ -17,6 +17,4 @@ USER www-data
ENTRYPOINT ["/start.sh"] ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD nc -z 127.0.0.1 $APACHE_PORT || exit 1 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"

View file

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
# Probably from here https://github.com/elastic/elasticsearch/blob/main/distribution/docker/src/docker/Dockerfile # Probably from here https://github.com/elastic/elasticsearch/blob/main/distribution/docker/src/docker/Dockerfile
FROM elasticsearch:8.19.10 FROM elasticsearch:8.14.3
USER root USER root
@ -14,14 +14,10 @@ RUN set -ex; \
apt-get install -y --no-install-recommends \ apt-get install -y --no-install-recommends \
tzdata \ tzdata \
; \ ; \
rm -rf /var/lib/apt/lists/*; rm -rf /var/lib/apt/lists/*; \
elasticsearch-plugin install --batch ingest-attachment
COPY --chmod=775 healthcheck.sh /healthcheck.sh
USER 1000:0 USER 1000:0
HEALTHCHECK --interval=10s --timeout=5s --start-period=1m --retries=5 CMD /healthcheck.sh HEALTHCHECK CMD nc -z 127.0.0.1 9200 || exit 1
LABEL com.centurylinklabs.watchtower.enable="false" \ LABEL com.centurylinklabs.watchtower.enable="false"
wud.watch="false" \
org.label-schema.vendor="Nextcloud"
ENV ES_JAVA_OPTS="-Xms512M -Xmx512M"

View file

@ -1,3 +0,0 @@
#!/bin/bash
nc -z 127.0.0.1 9200 || exit 1

View file

@ -1,10 +1,9 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
FROM golang:1.25.6-alpine3.23 AS go FROM golang:1.22.5-alpine3.20 AS go
ENV IMAGINARY_HASH=6a274b488759a896aff02f52afee6e50b5e3a3ee ENV IMAGINARY_HASH=6cd9edd1d3fb151eb773c14552886e4fc8e50138
RUN set -ex; \ RUN set -ex; \
apk upgrade --no-cache -a; \
apk add --no-cache \ apk add --no-cache \
vips-dev \ vips-dev \
vips-magick \ vips-magick \
@ -14,7 +13,7 @@ RUN set -ex; \
build-base; \ build-base; \
go install github.com/h2non/imaginary@"$IMAGINARY_HASH"; go install github.com/h2non/imaginary@"$IMAGINARY_HASH";
FROM alpine:3.23.3 FROM alpine:3.20.2
RUN set -ex; \ RUN set -ex; \
apk upgrade --no-cache -a; \ apk upgrade --no-cache -a; \
apk add --no-cache \ apk add --no-cache \
@ -31,17 +30,14 @@ RUN set -ex; \
COPY --from=go /go/bin/imaginary /usr/local/bin/imaginary COPY --from=go /go/bin/imaginary /usr/local/bin/imaginary
COPY --chmod=775 start.sh /start.sh COPY --chmod=775 start.sh /start.sh
COPY --chmod=775 healthcheck.sh /healthcheck.sh
ENV PORT=9000 ENV PORT=9000
USER 65534 USER nobody
# https://github.com/h2non/imaginary#memory-issues # https://github.com/h2non/imaginary#memory-issues
ENV MALLOC_ARENA_MAX=2 ENV MALLOC_ARENA_MAX=2
ENTRYPOINT ["/start.sh"] ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD /healthcheck.sh HEALTHCHECK CMD nc -z 127.0.0.1 "$PORT" || exit 1
LABEL com.centurylinklabs.watchtower.enable="false" \ LABEL com.centurylinklabs.watchtower.enable="false"
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -1,3 +0,0 @@
#!/bin/bash
nc -z 127.0.0.1 "$PORT" || exit 1

View file

@ -1,30 +1,20 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
# Docker CLI is a requirement # Docker CLI is a requirement
FROM docker:29.2.0-cli AS docker FROM docker:27.1.1-cli AS docker
# Caddy is a requirement # Caddy is a requirement
FROM caddy:2.10.2-alpine AS caddy FROM caddy:2.8.4-alpine AS caddy
# From https://github.com/docker-library/php/blob/master/8.4/alpine3.23/fpm/Dockerfile # From https://github.com/docker-library/php/blob/master/8.3/alpine3.20/fpm/Dockerfile
FROM php:8.4.17-fpm-alpine3.23 FROM php:8.3.9-fpm-alpine3.20
EXPOSE 80 EXPOSE 80
EXPOSE 8080 EXPOSE 8080
EXPOSE 8443 EXPOSE 8443
# Overwrite home variable for subservices
ENV HOME=/var/www
COPY --from=caddy /usr/bin/caddy /usr/bin/caddy COPY --from=caddy /usr/bin/caddy /usr/bin/caddy
COPY --from=docker /usr/local/bin/docker /usr/local/bin/docker 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 WORKDIR /var/www/docker-aio
# hadolint ignore=SC2086,DL3047,DL3003,DL3004 # hadolint ignore=SC2086,DL3047,DL3003,DL3004
@ -52,7 +42,7 @@ RUN set -ex; \
apk add --no-cache --virtual .build-deps \ apk add --no-cache --virtual .build-deps \
autoconf \ autoconf \
build-base; \ build-base; \
pecl install APCu-5.1.28; \ pecl install APCu-5.1.23; \
docker-php-ext-enable apcu; \ docker-php-ext-enable apcu; \
rm -r /tmp/pear; \ rm -r /tmp/pear; \
runDeps="$( \ runDeps="$( \
@ -74,11 +64,12 @@ RUN set -ex; \
wget https://getcomposer.org/installer -O - | php -- --install-dir=/usr/local/bin --filename=composer; \ wget https://getcomposer.org/installer -O - | php -- --install-dir=/usr/local/bin --filename=composer; \
chmod +x /usr/local/bin/composer; \ chmod +x /usr/local/bin/composer; \
cd /var/www/docker-aio; \ cd /var/www/docker-aio; \
rm -r ./php/tests; \ 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 {} \; ; \
chown www-data:www-data -R /var/www/docker-aio; \ chown www-data:www-data -R /var/www/docker-aio; \
cd php; \ cd php; \
sudo -E -u www-data composer install --no-dev; \ sudo -u www-data composer install --no-dev; \
sudo -E -u www-data composer clear-cache; \ sudo -u www-data composer clear-cache; \
cd ..; \ cd ..; \
rm -f /usr/local/bin/composer; \ rm -f /usr/local/bin/composer; \
chmod -R 770 /var/www/docker-aio; \ chmod -R 770 /var/www/docker-aio; \
@ -125,10 +116,10 @@ RUN set -ex; \
mkdir /var/log/supervisord; \ mkdir /var/log/supervisord; \
mkdir /var/run/supervisord; mkdir /var/run/supervisord;
# hadolint ignore=DL3048 COPY --chmod=775 *.sh /
LABEL org.label-schema.vendor="Nextcloud" \ COPY --chmod=664 Caddyfile /Caddyfile
wud.watch="false" \ COPY --chmod=664 supervisord.conf /supervisord.conf
com.docker.compose.project="nextcloud-aio" COPY mastercontainer.conf /etc/apache2/sites-available/mastercontainer.conf
# hadolint ignore=DL3002 # hadolint ignore=DL3002
USER root USER root

View file

@ -1,69 +0,0 @@
# 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.

View file

@ -45,29 +45,29 @@ while true; do
# Check for updates and send notification if yes on saturdays # Check for updates and send notification if yes on saturdays
if [ "$(date +%u)" = 6 ]; then if [ "$(date +%u)" = 6 ]; then
sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/UpdateNotification.php sudo -u www-data php /var/www/docker-aio/php/src/Cron/UpdateNotification.php
fi fi
# Check if AIO is outdated # Check if AIO is outdated
sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/OutdatedNotification.php sudo -u www-data php /var/www/docker-aio/php/src/Cron/OutdatedNotification.php
# Remove sessions older than 24h # Remove sessions older than 24h
find "/mnt/docker-aio-config/session/" -mindepth 1 -mmin +1440 -delete find "/mnt/docker-aio-config/session/" -mindepth 1 -mmin +1440 -delete
# Remove nextcloud-aio-domaincheck container # Remove nextcloud-aio-domaincheck container
if sudo -E -u www-data docker ps --format "{{.Names}}" --filter "status=exited" | grep -q "^nextcloud-aio-domaincheck$"; then if sudo -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 sudo -u www-data docker container remove nextcloud-aio-domaincheck
fi fi
# Remove dangling images # Remove dangling images
sudo -E -u www-data docker image prune --filter "label=org.label-schema.vendor=Nextcloud" --force sudo -u www-data docker image prune --force
# Check for available free space # Check for available free space
sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/CheckFreeDiskSpace.php sudo -u www-data php /var/www/docker-aio/php/src/Cron/CheckFreeDiskSpace.php
# Remove mastercontainer from default bridge network # Remove mastercontainer from default bridge network
if sudo -E -u www-data docker inspect nextcloud-aio-mastercontainer --format "{{.NetworkSettings.Networks}}" | grep -q "bridge"; then if sudo -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 sudo -u www-data docker network disconnect bridge nextcloud-aio-mastercontainer
fi fi
# Wait 60s so that the whole loop will not be executed again # Wait 60s so that the whole loop will not be executed again

View file

@ -2,13 +2,6 @@
echo "Daily backup script has started" 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 # Daily backup and backup check cannot be run at the same time
if [ "$DAILY_BACKUP" = 1 ] && [ "$CHECK_BACKUP" = 1 ]; then if [ "$DAILY_BACKUP" = 1 ] && [ "$CHECK_BACKUP" = 1 ]; then
echo "Daily backup and backup check cannot be run at the same time. Exiting..." echo "Daily backup and backup check cannot be run at the same time. Exiting..."
@ -20,19 +13,14 @@ fi
if [ "$LOCK_FILE_PRESENT" = 0 ] || ! [ -f "/mnt/docker-aio-config/data/daily_backup_running" ]; then if [ "$LOCK_FILE_PRESENT" = 0 ] || ! [ -f "/mnt/docker-aio-config/data/daily_backup_running" ]; then
find "/mnt/docker-aio-config/session/" -mindepth 1 -delete find "/mnt/docker-aio-config/session/" -mindepth 1 -delete
fi fi
sudo -E -u www-data touch "/mnt/docker-aio-config/data/daily_backup_running" sudo -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 # Check if apache is running/stopped, watchtower is stopped and backupcontainer is stopped
LOCAL_APACHE_PORT="$(docker inspect nextcloud-aio-apache --format "{{.Config.Env}}" | grep -o 'APACHE_PORT=[0-9]\+' | grep -o '[0-9]\+' | head -1)" 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 if [ -z "$APACHE_PORT" ]; then
echo "APACHE_PORT is not set which is not expected..." echo "APACHE_PORT is not set which is not expected..."
else else
# Connect mastercontainer to nextcloud-aio network to make sure that nextcloud-aio-apache is reachable while docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-apache$" && ! nc -z nextcloud-aio-apache "$APACHE_PORT"; do
# 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" echo "Waiting for apache to become available"
sleep 30 sleep 30
done done
@ -50,7 +38,7 @@ done
if [ "$AUTOMATIC_UPDATES" = 1 ]; then if [ "$AUTOMATIC_UPDATES" = 1 ]; then
echo "Starting mastercontainer update..." 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.)" 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 -E -u www-data php /var/www/docker-aio/php/src/Cron/UpdateMastercontainer.php sudo -u www-data php /var/www/docker-aio/php/src/Cron/UpdateMastercontainer.php
fi fi
# Wait for watchtower to stop # Wait for watchtower to stop
@ -64,23 +52,17 @@ if [ "$AUTOMATIC_UPDATES" = 1 ]; then
done done
fi 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 # Stop containers if required
# shellcheck disable=SC2235 # shellcheck disable=SC2235
if [ "$CHECK_BACKUP" != 1 ] && ([ "$DAILY_BACKUP" != 1 ] || [ "$STOP_CONTAINERS" = 1 ]); then if [ "$CHECK_BACKUP" != 1 ] && ([ "$DAILY_BACKUP" != 1 ] || [ "$STOP_CONTAINERS" = 1 ]); then
echo "Stopping containers..." echo "Stopping containers..."
sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/StopContainers.php sudo -u www-data php /var/www/docker-aio/php/src/Cron/StopContainers.php
fi fi
# Execute the backup itself and some related tasks (also stops the containers) # Execute the backup itself and some related tasks (also stops the containers)
if [ "$DAILY_BACKUP" = 1 ]; then if [ "$DAILY_BACKUP" = 1 ]; then
echo "Creating daily backup..." echo "Creating daily backup..."
sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/CreateBackup.php sudo -u www-data php /var/www/docker-aio/php/src/Cron/CreateBackup.php
if ! docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-borgbackup$"; then 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." echo "Something seems to be wrong: the borg container should be started at this step."
fi fi
@ -93,17 +75,17 @@ fi
# Execute backup check # Execute backup check
if [ "$CHECK_BACKUP" = 1 ]; then if [ "$CHECK_BACKUP" = 1 ]; then
echo "Starting backup check..." echo "Starting backup check..."
sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/CheckBackup.php sudo -u www-data php /var/www/docker-aio/php/src/Cron/CheckBackup.php
fi fi
# Start and/or update containers # Start and/or update containers
if [ "$AUTOMATIC_UPDATES" = 1 ]; then if [ "$AUTOMATIC_UPDATES" = 1 ]; then
echo "Starting and updating containers..." echo "Starting and updating containers..."
sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/StartAndUpdateContainers.php sudo -u www-data php /var/www/docker-aio/php/src/Cron/StartAndUpdateContainers.php
else else
if [ "$START_CONTAINERS" = 1 ]; then if [ "$START_CONTAINERS" = 1 ]; then
echo "Starting containers without updating them..." echo "Starting containers without updating them..."
sudo -E -u www-data php /var/www/docker-aio/php/src/Cron/StartContainers.php sudo -u www-data php /var/www/docker-aio/php/src/Cron/StartContainers.php
fi fi
fi fi

View file

@ -1,5 +1,5 @@
Listen 127.0.0.1:8000 Listen 8000
Listen 8080 https Listen 8080
# Deny access to .ht files # Deny access to .ht files
<Files ".ht*"> <Files ".ht*">
@ -7,8 +7,8 @@ Listen 8080 https
</Files> </Files>
# Http host # Http host
<VirtualHost 127.0.0.1:8000> <VirtualHost *:8000>
ServerName 127.0.0.1 ServerName localhost
# Add error log # Add error log
CustomLog /proc/self/fd/1 proxy CustomLog /proc/self/fd/1 proxy

View file

@ -33,25 +33,17 @@ if [ "$*" != "" ]; then
fi fi
# Check if socket is available and readable # Check if socket is available and readable
if ! [ -e "/var/run/docker.sock" ]; then if ! [ -a "/var/run/docker.sock" ]; then
print_red "Docker socket is not available. Cannot continue." 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 "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 "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 exit 1
elif ! mountpoint -q "/mnt/docker-aio-config"; then elif ! mountpoint -q "/mnt/docker-aio-config"; then
print_red "/mnt/docker-aio-config is not a mountpoint. Cannot proceed!" 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 "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" echo "If you are on TrueNas SCALE, see https://github.com/nextcloud/all-in-one#can-i-run-aio-on-truenas-scale"
exit 1 exit 1
elif mountpoint -q /var/www/docker-aio/php/containers.json; then elif ! sudo -u www-data test -r /var/run/docker.sock; 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..." echo "Trying to fix docker.sock permissions internally..."
DOCKER_GROUP=$(stat -c '%G' /var/run/docker.sock) DOCKER_GROUP=$(stat -c '%G' /var/run/docker.sock)
DOCKER_GROUP_ID=$(stat -c '%g' /var/run/docker.sock) DOCKER_GROUP_ID=$(stat -c '%g' /var/run/docker.sock)
@ -69,68 +61,28 @@ elif ! sudo -E -u www-data test -r /var/run/docker.sock; then
groupadd -g "$DOCKER_GROUP_ID" docker groupadd -g "$DOCKER_GROUP_ID" docker
usermod -aG docker www-data usermod -aG docker www-data
fi fi
if ! sudo -E -u www-data test -r /var/run/docker.sock; then if ! sudo -u www-data test -r /var/run/docker.sock; then
print_red "Docker socket is not readable by the www-data user. Cannot continue." print_red "Docker socket is not readable by the www-data user. Cannot continue."
exit 1 exit 1
fi fi
fi fi
# Get default docker api version # Check if api version is supported
API_VERSION_FILE="$(find ./ -name DockerActionManager.php | head -1)" if ! sudo -u www-data docker info &>/dev/null; then
API_VERSION="$(grep -oP 'const string API_VERSION.*\;' "$API_VERSION_FILE" | grep -oP '[0-9]+.[0-9]+' | head -1)" print_red "Cannot connect to the docker socket. Cannot proceed."
if [ -z "$API_VERSION" ]; then echo "Did you maybe remove group read permissions for the docker socket? AIO needs them in order to access the docker socket."
print_red "Could not get API_VERSION. Something is wrong!" 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 exit 1
fi fi
API_VERSION_FILE="$(find ./ -name DockerActionManager.php | head -1)"
# Check if DOCKER_API_VERSION is set globally API_VERSION="$(grep -oP 'const string API_VERSION.*\;' "$API_VERSION_FILE" | grep -oP '[0-9]+.[0-9]+' | head -1)"
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 # shellcheck disable=SC2001
API_VERSION_NUMB="$(echo "$DOCKER_API_VERSION" | sed 's/\.//')" API_VERSION_NUMB="$(echo "$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/\.//')" LOCAL_API_VERSION_NUMB="$(sudo -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 [ -n "$LOCAL_API_VERSION_NUMB" ] && [ -n "$API_VERSION_NUMB" ]; then
if ! [ "$LOCAL_API_VERSION_NUMB" -ge "$API_VERSION_NUMB" ]; then if ! [ "$LOCAL_API_VERSION_NUMB" -ge "$API_VERSION_NUMB" ]; then
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!" 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!"
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 exit 1
fi fi
else else
@ -139,34 +91,27 @@ else
fi fi
# Check Storage drivers # Check Storage drivers
STORAGE_DRIVER="$(sudo -E -u www-data docker info | grep "Storage Driver")" STORAGE_DRIVER="$(docker info | grep "Storage Driver")"
# Check if vfs is used: https://github.com/nextcloud/all-in-one/discussions/1467 # Check if vfs is used: https://github.com/nextcloud/all-in-one/discussions/1467
if echo "$STORAGE_DRIVER" | grep -q vfs; then if echo "$STORAGE_DRIVER" | grep -q vfs; then
echo "$STORAGE_DRIVER" echo "$STORAGE_DRIVER"
print_red "Warning: It seems like the storage driver vfs is used. This will lead to problems with disk space and performance and is disrecommended!" echo "Warning: It seems like the storage driver vfs is used. This will lead to problems with disk space and performance and is disrecommended!"
elif echo "$STORAGE_DRIVER" | grep -q fuse-overlayfs; then elif echo "$STORAGE_DRIVER" | grep -q fuse-overlayfs; then
echo "$STORAGE_DRIVER" echo "$STORAGE_DRIVER"
print_red "Warning: It seems like the storage driver fuse-overlayfs is used. Please check if you can switch to overlay2 instead." echo "Warning: It seems like the storage driver fuse-overlayfs is used. Please check if you can switch to overlay2 instead."
fi
# Check if snap install
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 fi
# Check if startup command was executed correctly # Check if startup command was executed correctly
if ! sudo -E -u www-data docker ps --format "{{.Names}}" | grep -q "^nextcloud-aio-mastercontainer$"; then if ! sudo -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.) 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! 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" 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 exit 1
elif ! sudo -E -u www-data docker volume ls --format "{{.Name}}" | grep -q "^nextcloud_aio_mastercontainer$"; then elif ! sudo -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.) 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!" Using a different name is not supported since the built-in backup solution will not work in that case!"
exit 1 exit 1
elif ! sudo -E -u www-data docker inspect nextcloud-aio-mastercontainer --format '{{.Mounts}}' | grep -q " nextcloud_aio_mastercontainer "; then elif ! sudo -u www-data docker inspect nextcloud-aio-mastercontainer | grep -q "nextcloud_aio_mastercontainer"; then
print_red "It seems like you did not attach the 'nextcloud_aio_mastercontainer' volume to the mastercontainer? 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!" This is not supported since the built-in backup solution will not work in that case!"
exit 1 exit 1
@ -185,7 +130,7 @@ It is set to '$NEXTCLOUD_DATADIR'."
fi fi
if [ -n "$NEXTCLOUD_MOUNT" ]; then if [ -n "$NEXTCLOUD_MOUNT" ]; then
if ! echo "$NEXTCLOUD_MOUNT" | grep -q "^/" || [ "$NEXTCLOUD_MOUNT" = "/" ]; then if ! echo "$NEXTCLOUD_MOUNT" | grep -q "^/" || [ "$NEXTCLOUD_MOUNT" = "/" ]; then
print_red "You've set NEXTCLOUD_MOUNT but not to an allowed value. print_red "You've set NEXCLOUD_MOUNT but not to an allowed value.
The string must start with '/' and must not be equal to '/'. The string must start with '/' and must not be equal to '/'.
It is set to '$NEXTCLOUD_MOUNT'." It is set to '$NEXTCLOUD_MOUNT'."
exit 1 exit 1
@ -241,14 +186,6 @@ It is set to '$APACHE_IP_BINDING'."
exit 1 exit 1
fi fi
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 [ -n "$TALK_PORT" ]; then
if ! check_if_number "$TALK_PORT"; then if ! check_if_number "$TALK_PORT"; then
print_red "You provided an Talk port but did not only use numbers. print_red "You provided an Talk port but did not only use numbers.
@ -306,18 +243,28 @@ It is set to '$NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS'."
fi fi
fi fi
if [ -n "$AIO_COMMUNITY_CONTAINERS" ]; then if [ -n "$AIO_COMMUNITY_CONTAINERS" ]; then
print_red "You've set AIO_COMMUNITY_CONTAINERS but the option was removed. read -ra AIO_CCONTAINERS <<< "$AIO_COMMUNITY_CONTAINERS"
The community containers get managed via the AIO interface now." 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
fi fi
# Check if ghcr.io is reachable # Check DNS resolution
# Solves issues like https://github.com/nextcloud/all-in-one/discussions/5268 # Prevents issues like https://github.com/nextcloud/all-in-one/discussions/565
if ! curl --no-progress-meter https://ghcr.io/v2/ >/dev/null; then curl https://nextcloud.com &>/dev/null
print_red "Could not reach https://ghcr.io." if [ "$?" = 6 ]; then
echo "Most likely is something blocking access to it." print_red "Could not resolve the host nextcloud.com."
echo "Most likely the DNS resolving does not work."
echo "You should be able to fix this by following https://dockerlabs.collabnix.com/intermediate/networking/Configuring_DNS.html" echo "You should be able to fix this by following https://dockerlabs.collabnix.com/intermediate/networking/Configuring_DNS.html"
echo "Another solution is using https://github.com/nextcloud/all-in-one/tree/main/manual-install" echo "Apart from that, there has been this: https://github.com/nextcloud/all-in-one/discussions/2065"
echo "See https://github.com/nextcloud/all-in-one/blob/main/manual-install/latest.yml"
exit 1 exit 1
fi fi
@ -328,13 +275,6 @@ if [ -n "$TZ" ]; then
# Disable exit since it seems to be by default set on unraid and we dont want to break these instances # Disable exit since it seems to be by default set on unraid and we dont want to break these instances
# exit 1 # exit 1
fi 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 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!" 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!" echo "The correct timezone can be set in the AIO interface later on!"
@ -415,11 +355,6 @@ export TZ=Etc/UTC
# Fix apache startup # Fix apache startup
rm -f /var/run/apache2/httpd.pid 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 # Fix the Caddyfile format
caddy fmt --overwrite /Caddyfile caddy fmt --overwrite /Caddyfile
@ -427,4 +362,4 @@ caddy fmt --overwrite /Caddyfile
chmod 777 /root chmod 777 /root
# Start supervisord # Start supervisord
exec /usr/bin/supervisord -c /supervisord.conf /usr/bin/supervisord -c /supervisord.conf

View file

@ -9,16 +9,16 @@ loglevel=error
user=root user=root
[program:php-fpm] [program:php-fpm]
# Stdout logging is disabled as otherwise the logs are spammed # stdout_logfile=/dev/stdout
stdout_logfile=NONE # stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0 stderr_logfile_maxbytes=0
command=php-fpm command=php-fpm
user=root user=root
[program:apache] [program:apache]
# Stdout logging is disabled as otherwise the logs are spammed # stdout_logfile=/dev/stdout
stdout_logfile=NONE # stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0 stderr_logfile_maxbytes=0
command=httpd -DFOREGROUND command=httpd -DFOREGROUND
@ -58,7 +58,9 @@ user=root
[program:domain-validator] [program:domain-validator]
# Logging is disabled as otherwise all attempts will be logged which spams the logs # Logging is disabled as otherwise all attempts will be logged which spams the logs
stdout_logfile=NONE # stdout_logfile=/dev/stdout
stderr_logfile=NONE # stdout_logfile_maxbytes=0
# stderr_logfile=/dev/stderr
# stderr_logfile_maxbytes=0
command=php -S 127.0.0.1:9876 /var/www/docker-aio/php/domain-validator.php command=php -S 127.0.0.1:9876 /var/www/docker-aio/php/domain-validator.php
user=www-data user=www-data

View file

@ -1,27 +1,22 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
FROM php:8.3.30-fpm-alpine3.23 FROM php:8.2.21-fpm-alpine3.20
ENV PHP_MEMORY_LIMIT=512M ENV PHP_MEMORY_LIMIT=512M
ENV PHP_UPLOAD_LIMIT=16G ENV PHP_UPLOAD_LIMIT=10G
ENV PHP_MAX_TIME=3600 ENV PHP_MAX_TIME=3600
ENV SOURCE_LOCATION=/usr/src/nextcloud ENV SOURCE_LOCATION=/usr/src/nextcloud
ENV REDIS_DB_INDEX=0
# AIO settings start # Do not remove or change this line! # AIO settings start # Do not remove or change this line!
ENV NEXTCLOUD_VERSION=32.0.5 ENV NEXTCLOUD_VERSION=29.0.4
ENV AIO_TOKEN=123456 ENV AIO_TOKEN=123456
ENV AIO_URL=localhost ENV AIO_URL=localhost
# AIO settings end # Do not remove or change this line! # AIO settings end # Do not remove or change this line!
COPY --chmod=775 Containers/nextcloud/*.sh / COPY --chmod=775 *.sh /
COPY --chmod=774 Containers/nextcloud/upgrade.exclude /upgrade.exclude COPY --chmod=774 upgrade.exclude /upgrade.exclude
COPY Containers/nextcloud/config/*.php / COPY config/*.php /
COPY Containers/nextcloud/supervisord.conf /supervisord.conf COPY supervisord.conf /supervisord.conf
COPY root.motd /root.motd
# 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 /mnt/ncdata
VOLUME /var/www/html VOLUME /var/www/html
@ -82,18 +77,19 @@ RUN set -ex; \
; \ ; \
\ \
# pecl will claim success even if one install fails, so we need to perform each install separately # pecl will claim success even if one install fails, so we need to perform each install separately
pecl install -o igbinary-3.2.16; \ pecl install igbinary-3.2.15; \
pecl install APCu-5.1.28; \ pecl install APCu-5.1.23; \
pecl install -D 'enable-memcached-igbinary="yes"' memcached-3.4.0; \ pecl install memcached-3.2.0 \
pecl install -oD 'enable-redis-igbinary="yes" enable-redis-zstd="yes" enable-redis-lz4="yes"' redis-6.3.0; \ --configureoptions 'enable-memcached-igbinary="yes"'; \
pecl install -o imagick-3.8.1; \ pecl install redis-6.0.2 \
--configureoptions 'enable-redis-igbinary="yes" enable-redis-zstd="yes" enable-redis-lz4="yes"'; \
pecl install imagick-3.7.0; \
\ \
docker-php-ext-enable \ docker-php-ext-enable \
igbinary \ igbinary \
apcu \ apcu \
memcached \ memcached \
redis \ redis \
imagick \
; \ ; \
rm -r /tmp/pear; \ rm -r /tmp/pear; \
\ \
@ -112,9 +108,8 @@ RUN set -ex; \
} >> /usr/local/etc/php/conf.d/docker-php-ext-igbinary.ini; \ } >> /usr/local/etc/php/conf.d/docker-php-ext-igbinary.ini; \
\ \
# set recommended PHP.ini settings # set recommended PHP.ini settings
# see https://docs.nextcloud.com/server/stable/admin_manual/installation/server_tuning.html#enable-php-opcache and below # see https://docs.nextcloud.com/server/stable/admin_manual/configuration_server/server_tuning.html#enable-php-opcache
{ \ { \
echo 'opcache.max_accelerated_files=10000'; \
echo 'opcache.memory_consumption=256'; \ echo 'opcache.memory_consumption=256'; \
echo 'opcache.interned_strings_buffer=64'; \ echo 'opcache.interned_strings_buffer=64'; \
echo 'opcache.save_comments=1'; \ echo 'opcache.save_comments=1'; \
@ -123,27 +118,23 @@ RUN set -ex; \
echo 'opcache.jit_buffer_size=8M'; \ echo 'opcache.jit_buffer_size=8M'; \
} > /usr/local/etc/php/conf.d/opcache-recommended.ini; \ } > /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 'memory_limit=${PHP_MEMORY_LIMIT}'; \
echo 'upload_max_filesize=${PHP_UPLOAD_LIMIT}'; \ echo 'upload_max_filesize=${PHP_UPLOAD_LIMIT}'; \
echo 'post_max_size=${PHP_UPLOAD_LIMIT}'; \ echo 'post_max_size=${PHP_UPLOAD_LIMIT}'; \
echo 'max_execution_time=${PHP_MAX_TIME}'; \ echo 'max_execution_time=${PHP_MAX_TIME}'; \
echo 'max_input_time=-1'; \ echo 'max_input_time=${PHP_MAX_TIME}'; \
echo 'default_socket_timeout=${PHP_MAX_TIME}'; \ echo 'default_socket_timeout=600'; \
} > /usr/local/etc/php/conf.d/nextcloud.ini; \ } > /usr/local/etc/php/conf.d/nextcloud.ini; \
\ \
{ \ { \
echo 'session.save_handler = redis'; \ echo 'session.save_handler = redis'; \
echo 'session.save_path = "tcp://${REDIS_HOST}:${REDIS_PORT}?database=${REDIS_DB_INDEX}${REDIS_USER_AUTH}&auth[]=${REDIS_HOST_PASSWORD}"'; \ echo 'session.save_path = "tcp://${REDIS_HOST}:6379?auth=${REDIS_HOST_PASSWORD}"'; \
echo 'redis.session.locking_enabled = 1'; \ echo 'redis.session.locking_enabled = 1'; \
echo 'redis.session.lock_retries = -1'; \ echo 'redis.session.lock_retries = -1'; \
echo 'redis.session.lock_wait_time = 10000'; \ echo 'redis.session.lock_wait_time = 10000'; \
echo 'session.gc_maxlifetime = 86400'; \
} > /usr/local/etc/php/conf.d/redis-session.ini; \ } > /usr/local/etc/php/conf.d/redis-session.ini; \
\ \
mkdir -p /var/www/data; \ mkdir -p /var/www/data; \
@ -157,7 +148,7 @@ RUN set -ex; \
; \ ; \
\ \
curl -fsSL -o nextcloud.tar.bz2 \ curl -fsSL -o nextcloud.tar.bz2 \
"https://github.com/nextcloud-releases/server/releases/download/v${NEXTCLOUD_VERSION}/nextcloud-${NEXTCLOUD_VERSION}.tar.bz2"; \ "https://download.nextcloud.com/server/releases/nextcloud-${NEXTCLOUD_VERSION}.tar.bz2"; \
curl -fsSL -o nextcloud.tar.bz2.asc \ curl -fsSL -o nextcloud.tar.bz2.asc \
"https://download.nextcloud.com/server/releases/nextcloud-${NEXTCLOUD_VERSION}.tar.bz2.asc"; \ "https://download.nextcloud.com/server/releases/nextcloud-${NEXTCLOUD_VERSION}.tar.bz2.asc"; \
export GNUPGHOME="$(mktemp -d)"; \ export GNUPGHOME="$(mktemp -d)"; \
@ -217,8 +208,8 @@ RUN set -ex; \
/var/log/supervisord \ /var/log/supervisord \
/var/run/supervisord \ /var/run/supervisord \
; \ ; \
chmod 777 -R /var/log/supervisord; \ chown www-data:root -R /var/log/supervisord; \
chmod 777 -R /var/run/supervisord; \ chown www-data:root -R /var/run/supervisord; \
\ \
apk add --no-cache \ apk add --no-cache \
bash \ bash \
@ -246,23 +237,33 @@ RUN set -ex; \
sed -i 's/^pm.max_children =.*/pm.max_children = 5000/' /usr/local/etc/php-fpm.d/www.conf; \ 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; \ sed -i 's|access.log = /proc/self/fd/2|access.log = /proc/self/fd/1|' /usr/local/etc/php-fpm.d/docker.conf; \
\ \
echo "[ -n \"\$TERM\" ] && [ -f /root.motd ] && cat /root.motd" >> /root/.bashrc; \ # 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!
\ \
chown www-data:root -R /usr/src && \ chown www-data:root -R /usr/src && \
chmod 777 -R /usr/local/etc/php/conf.d && \ chown www-data:root -R /usr/local/etc/php/conf.d && \
chmod 777 -R /usr/local/etc/php-fpm.d && \ chown www-data:root -R /usr/local/etc/php-fpm.d && \
chmod -R 777 /tmp; \ chmod -R 777 /tmp; \
chmod -R 777 /etc/openldap; \ rm -rf /usr/src/nextcloud/apps/updatenotification; \
\ \
mkdir -p /nc-updater; \ mkdir -p /nc-updater; \
chmod -R 777 /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
# hadolint ignore=DL3002 # hadolint ignore=DL3002
USER root USER root
ENTRYPOINT ["/start.sh"] ENTRYPOINT ["/start.sh"]
CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"] CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"]
HEALTHCHECK CMD /healthcheck.sh HEALTHCHECK --start-period=60s CMD sudo -E -u www-data bash /healthcheck.sh
LABEL com.centurylinklabs.watchtower.enable="false" \ LABEL com.centurylinklabs.watchtower.enable="false"
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -1,35 +0,0 @@
# 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.

View file

@ -13,9 +13,6 @@ $CONFIG = array (
), ),
), ),
); );
if (getenv('APPS_ALLOWLIST')) { if (getenv('APPS_ALLOWLIST') !== false) {
$CONFIG['appsallowlist'] = explode(" ", getenv('APPS_ALLOWLIST')); $CONFIG['appsallowlist'] = explode(" ", getenv('APPS_ALLOWLIST'));
} }
if (getenv('NEXTCLOUD_APP_STORE_URL')) {
$CONFIG['appstoreurl'] = getenv('NEXTCLOUD_APP_STORE_URL');
}

View file

@ -1,5 +0,0 @@
<?php
// Check if NEXTCLOUD_TRUSTED_CERTIFICATES_ are configured
if (str_contains(implode(' ', array_keys(getenv())), 'NEXTCLOUD_TRUSTED_CERTIFICATES_')) {
$CONFIG['default_certificates_bundle_path'] = '/var/www/html/data/certificates/ca-bundle.crt';
}

View file

@ -1,17 +0,0 @@
<?php
if (getenv('NEXTCLOUD_TRUSTED_CERTIFICATES_POSTGRES')) {
$CONFIG = array(
'pgsql_ssl' => 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',
),
);
}

View file

@ -1,13 +0,0 @@
<?php
if (getenv('HTTP_PROXY')) {
$CONFIG['proxy'] = getenv('HTTP_PROXY');
}
if (getenv('HTTPS_PROXY')) {
$CONFIG['proxy'] = getenv('HTTPS_PROXY');
}
if (getenv('PROXY_USER_PASSWORD')) {
$CONFIG['proxyuserpwd'] = getenv('PROXY_USER_PASSWORD');
}
if (getenv('NO_PROXY')) {
$CONFIG['proxyexclude'] = explode(',', getenv('NO_PROXY'));
}

View file

@ -9,15 +9,13 @@ if (getenv('REDIS_HOST')) {
), ),
); );
if (getenv('REDIS_PORT')) { if (getenv('REDIS_HOST_PORT') !== false) {
$CONFIG['redis']['port'] = (int) getenv('REDIS_PORT'); $CONFIG['redis']['port'] = (int) getenv('REDIS_HOST_PORT');
} elseif (getenv('REDIS_HOST')[0] != '/') {
$CONFIG['redis']['port'] = 6379;
} }
if (getenv('REDIS_DB_INDEX')) { if (getenv('REDIS_DB_INDEX') !== false) {
$CONFIG['redis']['dbindex'] = (int) 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'));
}
} }

View file

@ -4,34 +4,26 @@ if (getenv('OBJECTSTORE_S3_BUCKET')) {
$use_path = getenv('OBJECTSTORE_S3_USEPATH_STYLE'); $use_path = getenv('OBJECTSTORE_S3_USEPATH_STYLE');
$use_legacyauth = getenv('OBJECTSTORE_S3_LEGACYAUTH'); $use_legacyauth = getenv('OBJECTSTORE_S3_LEGACYAUTH');
$autocreate = getenv('OBJECTSTORE_S3_AUTOCREATE'); $autocreate = getenv('OBJECTSTORE_S3_AUTOCREATE');
$multibucket = getenv('OBJECTSTORE_S3_MULTIBUCKET');
$CONFIG = array( $CONFIG = array(
'objectstore' => array( 'objectstore' => array(
'class' => '\OC\Files\ObjectStore\S3', 'class' => '\OC\Files\ObjectStore\S3',
'arguments' => array( 'arguments' => array(
'multibucket' => $multibucket === 'true',
'num_buckets' => (int)getenv('OBJECTSTORE_S3_NUM_BUCKETS') ?: 64,
'bucket' => getenv('OBJECTSTORE_S3_BUCKET'), 'bucket' => getenv('OBJECTSTORE_S3_BUCKET'),
'key' => getenv('OBJECTSTORE_S3_KEY') ?: '', 'key' => getenv('OBJECTSTORE_S3_KEY') ?: '',
'secret' => getenv('OBJECTSTORE_S3_SECRET') ?: '', 'secret' => getenv('OBJECTSTORE_S3_SECRET') ?: '',
'sse_c_key' => getenv('OBJECTSTORE_S3_SSE_C_KEY') ?: '',
'region' => getenv('OBJECTSTORE_S3_REGION') ?: '', 'region' => getenv('OBJECTSTORE_S3_REGION') ?: '',
'hostname' => getenv('OBJECTSTORE_S3_HOST') ?: '', 'hostname' => getenv('OBJECTSTORE_S3_HOST') ?: '',
'port' => getenv('OBJECTSTORE_S3_PORT') ?: '', 'port' => getenv('OBJECTSTORE_S3_PORT') ?: '',
'storageClass' => getenv('OBJECTSTORE_S3_STORAGE_CLASS') ?: '', 'storageClass' => getenv('OBJECTSTORE_S3_STORAGE_CLASS') ?: '',
'objectPrefix' => getenv("OBJECTSTORE_S3_OBJECT_PREFIX") ? getenv("OBJECTSTORE_S3_OBJECT_PREFIX") : "urn:oid:", 'objectPrefix' => getenv("OBJECTSTORE_S3_OBJECT_PREFIX") ? getenv("OBJECTSTORE_S3_OBJECT_PREFIX") : "urn:oid:",
'autocreate' => strtolower($autocreate) !== 'false', 'autocreate' => (strtolower($autocreate) === 'false' || $autocreate == false) ? false : true,
'use_ssl' => strtolower($use_ssl) !== 'false', 'use_ssl' => (strtolower($use_ssl) === 'false' || $use_ssl == false) ? false : true,
// required for some non Amazon S3 implementations // required for some non Amazon S3 implementations
'use_path_style' => strtolower($use_path) === 'true', 'use_path_style' => $use_path == true && strtolower($use_path) !== 'false',
// required for older protocol versions // required for older protocol versions
'legacy_auth' => strtolower($use_legacyauth) === 'true', 'legacy_auth' => $use_legacyauth == true && strtolower($use_legacyauth) !== 'false'
'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;
}
}

View file

@ -18,14 +18,3 @@ if (getenv('SMTP_HOST') && getenv('MAIL_FROM_ADDRESS') && getenv('MAIL_DOMAIN'))
$CONFIG['mail_smtppassword'] = ''; $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',
)
)
);
}

View file

@ -11,106 +11,39 @@ directory_empty() {
} }
run_upgrade_if_needed_due_to_app_update() { run_upgrade_if_needed_due_to_app_update() {
if php /var/www/html/occ status | grep maintenance | grep -q true; then
php /var/www/html/occ maintenance:mode --off
fi
if php /var/www/html/occ status | grep needsDbUpgrade | grep -q true; then if php /var/www/html/occ status | grep needsDbUpgrade | grep -q true; then
# Disable integrity check temporarily until next update
php /var/www/html/occ config:system:set integrity.check.disabled --type bool --value true
php /var/www/html/occ upgrade php /var/www/html/occ upgrade
php /var/www/html/occ app:enable nextcloud-aio --force php /var/www/html/occ app:enable nextcloud-aio --force
fi fi
} }
# Create cert bundle # Only start container if redis is accessible
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 # shellcheck disable=SC2153
while ! nc -z "$REDIS_HOST" "$REDIS_PORT"; do while ! nc -z "$REDIS_HOST" "6379"; do
echo "Waiting for Redis to start..." echo "Waiting for redis to start..."
sleep 5 sleep 5
done done
# Check permissions in ncdata # Check permissions in ncdata
test_file="$NEXTCLOUD_DATA_DIR/this-is-a-test-file" touch "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" &>/dev/null
touch "$test_file" if ! [ -f "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" ]; then
if ! [ -f "$test_file" ]; then echo "The www-data user doesn't seem to have access rights in the datadir.
echo "The www-data user does not appear to have access rights to the data directory." Most likely are the files located on a drive that does not follow linux permissions.
echo "It is possible that the files are on a filesystem that does not support standard Linux permissions," Please adjust the permissions like mentioned below.
echo "or the permissions simply need to be adjusted. Please change the permissions as described below." The found permissions are:
echo "Current permissions are:" $(stat -c "%u:%g %a" "$NEXTCLOUD_DATA_DIR")
stat -c "%u:%g %a" "$NEXTCLOUD_DATA_DIR" (userID:groupID permissions)
echo "(userID:groupID permissions)" but they should be:
echo "They should be:" 33:0 750
echo "33:0 750" (userID:groupID permissions)
echo "(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.
echo "Also, ensure that all parent directories on the host of your chosen data directory are publicly readable." Additionally, if you want to use a Fuse-mount as datadir, set 'allow_other' as additional mount option.
echo "For example: sudo chmod +r /mnt (adjust this command as needed)." For SMB/CIFS mounts as datadir, see https://github.com/nextcloud/all-in-one#can-i-use-a-cifssmb-share-as-nextclouds-datadir"
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 exit 1
fi fi
rm -f "$test_file" rm "$NEXTCLOUD_DATA_DIR/this-is-a-test-file"
if [ -f /var/www/html/version.php ]; then if [ -f /var/www/html/version.php ]; then
# shellcheck disable=SC2016 # shellcheck disable=SC2016
@ -132,31 +65,26 @@ fi
# Don't start the container if Nextcloud is not compatible with the PHP version # 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 if [ -f "/var/www/html/lib/versioncheck.php" ] && ! php /var/www/html/lib/versioncheck.php; then
echo "Your installed Nextcloud version is not compatible with the PHP version provided by this image." echo "It seems like your installed Nextcloud is not compatible with the by the container provided PHP version."
echo "This typically occurs when you restore an older Nextcloud backup that does not support the" 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 "PHP version included in this image." 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 "Please restore a more recent backup that includes a compatible Nextcloud version." 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 "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 exit 1
fi fi
# Do not start the container if the last update failed # Do not start the container if the last update failed
if [ -f "$NEXTCLOUD_DATA_DIR/update.failed" ]; then if [ -f "$NEXTCLOUD_DATA_DIR/update.failed" ]; then
echo "The last Nextcloud update failed." echo "The last Nextcloud update failed."
echo "Please restore from a backup and try again." echo "Please restore from backup and try again!"
echo "If you do not have a backup, you can delete the update.failed file in the data directory" 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 "to allow the container to start again."
exit 1 exit 1
fi fi
# Do not start the container if the install failed # Do not start the container if the install failed
if [ -f "$NEXTCLOUD_DATA_DIR/install.failed" ]; then if [ -f "$NEXTCLOUD_DATA_DIR/install.failed" ]; then
echo "The initial Nextcloud installation failed." echo "The initial Nextcloud installation failed."
echo "For more information about what went wrong, check the logs above." echo "Please reset AIO properly and try again. For further clues what went wrong, check the logs above."
echo "Please reset AIO properly and try again." echo "See https://github.com/nextcloud/all-in-one#how-to-properly-reset-the-instance"
echo "See:"
echo " https://github.com/nextcloud/all-in-one#how-to-properly-reset-the-instance"
exit 1 exit 1
fi fi
@ -182,11 +110,8 @@ 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" curl -fsSL -o nextcloud.tar.bz2.asc "https://download.nextcloud.com/server/releases/latest-${NEXT_MAJOR}.tar.bz2.asc"
GNUPGHOME="$(mktemp -d)" GNUPGHOME="$(mktemp -d)"
export GNUPGHOME export GNUPGHOME
if ! gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 28806A878AE423A28372792ED75899B9A724937A; then # gpg key from https://nextcloud.com/nextcloud.asc
if ! gpg --batch --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 28806A878AE423A28372792ED75899B9A724937A; then gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 28806A878AE423A28372792ED75899B9A724937A
curl -sSL https://nextcloud.com/nextcloud.asc | gpg --import
fi
fi
gpg --batch --verify nextcloud.tar.bz2.asc nextcloud.tar.bz2 gpg --batch --verify nextcloud.tar.bz2.asc nextcloud.tar.bz2
mkdir -p /usr/src/tmp mkdir -p /usr/src/tmp
tar -xjf nextcloud.tar.bz2 -C /usr/src/tmp/ tar -xjf nextcloud.tar.bz2 -C /usr/src/tmp/
@ -203,54 +128,45 @@ if ! [ -f "$NEXTCLOUD_DATA_DIR/skip.update" ]; then
rm -r /usr/src/tmp rm -r /usr/src/tmp
rm -r /usr/src/temp-nextcloud rm -r /usr/src/temp-nextcloud
# shellcheck disable=SC2016 # 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%%.*}" IMAGE_MAJOR="${image_version%%.*}"
set +ex set +ex
# Do not skip major versions end # Do not remove or change this line! # Do not skip major versions end # Do not remove or change this line!
fi fi
if [ "$installed_version" != "0.0.0.0" ]; then if [ "$installed_version" != "0.0.0.0" ]; then
# Check connection to appstore start # Do not remove or change this line!
while true; do while true; do
echo -e "Checking connection to the app store..." echo -e "Checking connection to appstore"
APPSTORE_URL="https://apps.nextcloud.com/api/v1" CURL_STATUS="$(curl -LI "https://apps.nextcloud.com/" -o /dev/null -w '%{http_code}\n' -s)"
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" ]] if [[ "$CURL_STATUS" = "200" ]]
then then
echo "App store is reachable." echo "Appstore is reachable"
break break
else else
echo "Curl did not return a 200 status. Is the app store reachable?" echo "Curl didn't produce a 200 status, is appstore reachable?"
sleep 5 sleep 5
fi fi
done done
# Check connection to appstore end # Do not remove or change this line!
run_upgrade_if_needed_due_to_app_update run_upgrade_if_needed_due_to_app_update
php /var/www/html/occ maintenance:mode --off 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')" 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 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" APPSTORAGE="no-export-done"
else else
mapfile -t NC_APPS_ARRAY <<< "$NC_APPS" mapfile -t NC_APPS_ARRAY <<< "$NC_APPS"
declare -Ag APPSTORAGE declare -Ag APPSTORAGE
echo "Disabling apps before the update to make the update procedure safer. This can take a while..." echo "Disabling apps before the update in order to make the update procedure more safe. This can take a while..."
for app in "${NC_APPS_ARRAY[@]}"; do for app in "${NC_APPS_ARRAY[@]}"; do
if APPSTORAGE[$app]="$(php /var/www/html/occ config:app:get "$app" enabled)"; then if APPSTORAGE[$app]="$(php /var/www/html/occ config:app:get "$app" enabled)"; then
php /var/www/html/occ app:disable "$app" php /var/www/html/occ app:disable "$app"
else else
APPSTORAGE[$app]="" APPSTORAGE[$app]=""
echo "Not disabling $app because the occ command to get its enabled state failed." echo "Not disabling $app because the occ command to get the enabled state was failing."
fi fi
done done
fi fi
@ -262,63 +178,29 @@ if ! [ -f "$NEXTCLOUD_DATA_DIR/skip.update" ]; then
php /var/www/html/occ app:update --all php /var/www/html/occ app:update --all
run_upgrade_if_needed_due_to_app_update 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 fi
echo "Initializing Nextcloud $image_version ..." echo "Initializing nextcloud $image_version ..."
rsync -rlD --delete --exclude-from=/upgrade.exclude "$SOURCE_LOCATION/" /var/www/html/
# 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 for dir in config data custom_apps themes; do
if [ ! -d "/var/www/html/$dir" ] || directory_empty "/var/www/html/$dir"; then if [ ! -d "/var/www/html/$dir" ] || directory_empty "/var/www/html/$dir"; then
rsync -rlD \ rsync -rlD --include "/$dir/" --exclude '/*' "$SOURCE_LOCATION/" /var/www/html/
--include "/$dir/" \
--exclude '/*' \
"$SOURCE_LOCATION/" \
/var/www/html/
fi fi
done 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 --delete \ rsync -rlD --include '/version.php' --exclude '/*' "$SOURCE_LOCATION/" /var/www/html/
--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" echo "Initializing finished"
################ #install
# Fresh Install
################
if [ "$installed_version" = "0.0.0.0" ]; then if [ "$installed_version" = "0.0.0.0" ]; then
echo "New Nextcloud instance." echo "New Nextcloud instance."
@ -332,31 +214,21 @@ if ! [ -f "$NEXTCLOUD_DATA_DIR/skip.update" ]; then
INSTALL_OPTIONS+=(--data-dir "$NEXTCLOUD_DATA_DIR") INSTALL_OPTIONS+=(--data-dir "$NEXTCLOUD_DATA_DIR")
fi fi
# Skip the default permission check (we do our own) # We do our own permission check so the permission check is not needed
cat > /var/www/html/config/datadir.permission.config.php <<'EOF' cat << DATADIR_PERMISSION_CONF > /var/www/html/config/datadir.permission.config.php
<?php <?php
$CONFIG = array ( \$CONFIG = array (
'check_data_directory_permissions' => false 'check_data_directory_permissions' => false
); );
EOF DATADIR_PERMISSION_CONF
echo "Installing with $DATABASE_TYPE database" echo "Installing with PostgreSQL database"
# Set a default value for POSTGRES_PORT # Set a default value for POSTGRES_PORT
if [ -z "$POSTGRES_PORT" ]; then if [ -z "$POSTGRES_PORT" ]; then
POSTGRES_PORT=5432 POSTGRES_PORT=5432
fi 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..." echo "Starting Nextcloud installation..."
if ! php /var/www/html/occ maintenance:install "${INSTALL_OPTIONS[@]}"; then if ! php /var/www/html/occ maintenance:install "${INSTALL_OPTIONS[@]}"; then
echo "Installation of Nextcloud failed!" echo "Installation of Nextcloud failed!"
@ -378,7 +250,7 @@ EOF
if [ "$try" -ge "$max_retries" ]; then if [ "$try" -ge "$max_retries" ]; then
echo "Installation of Nextcloud failed!" echo "Installation of Nextcloud failed!"
echo "Installation errors: $(cat /var/www/html/data/nextcloud.log)" echo "Install errors: $(cat /var/www/html/data/nextcloud.log)"
touch "$NEXTCLOUD_DATA_DIR/install.failed" touch "$NEXTCLOUD_DATA_DIR/install.failed"
exit 1 exit 1
fi fi
@ -390,10 +262,6 @@ EOF
# unset admin password # unset admin password
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! # AIO update to latest start # Do not remove or change this line!
if [ "$INSTALL_LATEST_MAJOR" = yes ]; then if [ "$INSTALL_LATEST_MAJOR" = yes ]; then
php /var/www/html/occ config:system:set updatedirectory --value="/nc-updater" php /var/www/html/occ config:system:set updatedirectory --value="/nc-updater"
@ -414,19 +282,18 @@ EOF
installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')" installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')"
INSTALLED_MAJOR="${installed_version%%.*}" INSTALLED_MAJOR="${installed_version%%.*}"
IMAGE_MAJOR="${image_version%%.*}" IMAGE_MAJOR="${image_version%%.*}"
# If a valid upgrade path, trigger the Nextcloud built-in Updater
if ! [ "$INSTALLED_MAJOR" -gt "$IMAGE_MAJOR" ]; then if ! [ "$INSTALLED_MAJOR" -gt "$IMAGE_MAJOR" ]; then
php /var/www/html/updater/updater.phar --no-interaction --no-backup 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 if ! php /var/www/html/occ -V || php /var/www/html/occ status | grep maintenance | grep -q 'true'; then
echo "Installation of Nextcloud failed!" 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" touch "$NEXTCLOUD_DATA_DIR/install.failed"
exit 1 exit 1
fi fi
# shellcheck disable=SC2016 # shellcheck disable=SC2016
installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')" installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')"
fi fi
php /var/www/html/occ config:system:set updatechecker --type=bool --value=true php /var/www/html/occ app:disable updatenotification
rm -rf /var/www/html/apps/updatenotification
php /var/www/html/occ app:enable nextcloud-aio --force 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-columns
php /var/www/html/occ db:add-missing-primary-keys php /var/www/html/occ db:add-missing-primary-keys
@ -472,13 +339,15 @@ EOF
php /var/www/html/occ config:system:set activity_expire_days --value="30" --type=integer 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 simpleSignUpLink.shown --type=bool --value=false
php /var/www/html/occ config:system:set share_folder --value="/Shared" 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 # Install some apps by default
if [ -n "$STARTUP_APPS" ]; then if [ -n "$STARTUP_APPS" ]; then
read -ra STARTUP_APPS_ARRAY <<< "$STARTUP_APPS" read -ra STARTUP_APPS_ARRAY <<< "$STARTUP_APPS"
for app in "${STARTUP_APPS_ARRAY[@]}"; do for app in "${STARTUP_APPS_ARRAY[@]}"; do
if ! echo "$app" | grep -q '^-'; then if ! echo "$app" | grep -q '^-'; then
if [ -z "$(find /var/www/html/apps /var/www/html/custom_apps -type d -maxdepth 1 -mindepth 1 -name "$app" )" ]; then if [ -z "$(find /var/www/html/apps -type d -maxdepth 1 -mindepth 1 -name "$app" )" ]; then
# If not shipped, install and enable the app # If not shipped, install and enable the app
php /var/www/html/occ app:install "$app" php /var/www/html/occ app:install "$app"
else else
@ -496,11 +365,11 @@ EOF
#upgrade #upgrade
else else
touch "$NEXTCLOUD_DATA_DIR/update.failed" 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 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 if ! php /var/www/html/occ upgrade || ! php /var/www/html/occ -V; then
echo "Upgrade failed. Please restore from backup." 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 exit 1
fi fi
@ -508,7 +377,7 @@ EOF
installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')" installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')"
rm "$NEXTCLOUD_DATA_DIR/update.failed" rm "$NEXTCLOUD_DATA_DIR/update.failed"
bash /notify.sh "Nextcloud update to $image_version successful!" "You may inspect the Nextcloud container logs for more information." bash /notify.sh "Nextcloud update to $image_version successful!" "Feel free to inspect the Nextcloud container logs for more info."
php /var/www/html/occ app:update --all php /var/www/html/occ app:update --all
@ -516,7 +385,7 @@ EOF
# Restore app status # Restore app status
if [ "${APPSTORAGE[0]}" != "no-export-done" ]; then if [ "${APPSTORAGE[0]}" != "no-export-done" ]; then
echo "Restoring app statuses. This may take a while..." echo "Restoring the status of apps. This can take a while..."
for app in "${!APPSTORAGE[@]}"; do for app in "${!APPSTORAGE[@]}"; do
if [ -n "${APPSTORAGE[$app]}" ]; then if [ -n "${APPSTORAGE[$app]}" ]; then
if [ "${APPSTORAGE[$app]}" != "no" ]; then if [ "${APPSTORAGE[$app]}" != "no" ]; then
@ -528,13 +397,13 @@ EOF
php /var/www/html/occ maintenance:mode --off php /var/www/html/occ maintenance:mode --off
fi fi
run_upgrade_if_needed_due_to_app_update run_upgrade_if_needed_due_to_app_update
echo "The $app app could not be re-enabled, probably because it is not compatible with the new Nextcloud version." echo "The $app app could not get enabled. Probably because it is not compatible with the new Nextcloud version."
if [ "$app" = apporder ]; then if [ "$app" = apporder ]; then
CUSTOM_HINT="The apporder app was deprecated. A possible replacement is the side_menu app, aka 'Custom menu'." CUSTOM_HINT="The apporder app was deprecated. A possible replacement is the side_menu app, aka 'Custom menu'."
else else
CUSTOM_HINT="Most likely, it is not compatible with the new Nextcloud version." CUSTOM_HINT="Most likely because it is not compatible with the new Nextcloud version."
fi fi
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." 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."
continue continue
fi fi
# Only restore the group settings, if the app was enabled (and is thus compatible with the new NC version) # Only restore the group settings, if the app was enabled (and is thus compatible with the new NC version)
@ -550,21 +419,14 @@ EOF
run_upgrade_if_needed_due_to_app_update 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 # Apply optimization
echo "Performing some optimizations..." echo "Doing some optimizations..."
php /var/www/html/occ maintenance:repair
if [ "$NEXTCLOUD_SKIP_DATABASE_OPTIMIZATION" != yes ]; then 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 php /var/www/html/occ db:add-missing-indices
php /var/www/html/occ db:add-missing-columns php /var/www/html/occ db:add-missing-columns
php /var/www/html/occ db:add-missing-primary-keys php /var/www/html/occ db:add-missing-primary-keys
yes | php /var/www/html/occ db:convert-filecache-bigint yes | php /var/www/html/occ db:convert-filecache-bigint
else
php /var/www/html/occ maintenance:repair
fi fi
fi fi
fi fi
@ -587,10 +449,10 @@ if [ -z "$OBJECTSTORE_S3_BUCKET" ] && [ -z "$OBJECTSTORE_SWIFT_URL" ]; then
# Check if appdata is present # Check if appdata is present
# If not, something broke (e.g. changing ncdatadir after aio was first started) # 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 if [ -z "$(find "$NEXTCLOUD_DATA_DIR/" -maxdepth 1 -mindepth 1 -type d -name "appdata_*")" ]; then
echo "Appdata is not present. Did you change the datadir after the initial Nextcloud installation? This is not supported!" echo "Appdata is not present. Did you maybe 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 "See https://github.com/nextcloud/all-in-one#how-to-change-the-default-location-of-nextclouds-datadir"
echo "If you moved the datadir to an external drive, make sure that the drive is still mounted." echo "If you adjusted the datadir to be located on an external drive, make sure that the drive is still mounted!"
echo "The following was found in the datadir:" echo "In the datadir was found:"
ls -la "$NEXTCLOUD_DATA_DIR/" ls -la "$NEXTCLOUD_DATA_DIR/"
exit 1 exit 1
fi fi
@ -611,12 +473,6 @@ if [ -f "$NEXTCLOUD_DATA_DIR/fingerprint.update" ]; then
rm "$NEXTCLOUD_DATA_DIR/fingerprint.update" rm "$NEXTCLOUD_DATA_DIR/fingerprint.update"
fi 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! # AIO one-click settings start # Do not remove or change this line!
# Apply one-click-instance settings # Apply one-click-instance settings
echo "Applying one-click-instance settings..." echo "Applying one-click-instance settings..."
@ -643,13 +499,6 @@ 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: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:app:set admin_audit logfile --value="/var/www/html/data/audit.log"
php /var/www/html/occ config:system:set updatedirectory --value="/nc-updater" 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 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" php /var/www/html/occ config:app:set serverinfo token --value="$SERVERINFO_TOKEN"
fi fi
@ -665,7 +514,6 @@ 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 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 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 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 config:system:set htaccess.RewriteBase --value="/"
php /var/www/html/occ maintenance:update:htaccess php /var/www/html/occ maintenance:update:htaccess
@ -715,17 +563,12 @@ if [ -n "$ADDITIONAL_TRUSTED_PROXY" ]; then
php /var/www/html/occ config:system:set trusted_proxies 2 --value="$ADDITIONAL_TRUSTED_PROXY" php /var/www/html/occ config:system:set trusted_proxies 2 --value="$ADDITIONAL_TRUSTED_PROXY"
fi fi
# Get ipv4-address of Nextcloud # Get ipv4-address of Nextcloud
if [ -z "$NEXTCLOUD_HOST" ]; then IPv4_ADDRESS="$(dig nextcloud-aio-nextcloud A +short +search | head -1)"
export NEXTCLOUD_HOST="nextcloud-aio-nextcloud"
fi
IPv4_ADDRESS="$(dig "$NEXTCLOUD_HOST" A +short +search | head -1)"
# Bring it in CIDR notation # Bring it in CIDR notation
# shellcheck disable=SC2001 # shellcheck disable=SC2001
IPv4_ADDRESS="$(echo "$IPv4_ADDRESS" | sed 's|[0-9]\+$|0/16|')" IPv4_ADDRESS="$(echo "$IPv4_ADDRESS" | sed 's|[0-9]\+$|0/16|')"
if [ -n "$IPv4_ADDRESS" ]; then php /var/www/html/occ config:system:set trusted_proxies 10 --value="$IPv4_ADDRESS"
php /var/www/html/occ config:system:set trusted_proxies 10 --value="$IPv4_ADDRESS"
fi
if [ -n "$ADDITIONAL_TRUSTED_DOMAIN" ]; then if [ -n "$ADDITIONAL_TRUSTED_DOMAIN" ]; then
php /var/www/html/occ config:system:set trusted_domains 2 --value="$ADDITIONAL_TRUSTED_DOMAIN" php /var/www/html/occ config:system:set trusted_domains 2 --value="$ADDITIONAL_TRUSTED_DOMAIN"
@ -739,10 +582,6 @@ if [ "$COLLABORA_ENABLED" = 'yes' ]; then
COLLABORA_HOST="$NC_DOMAIN" COLLABORA_HOST="$NC_DOMAIN"
fi fi
set +x set +x
# Remove richdcoumentscode if it should be incorrectly installed
if [ -d "/var/www/html/custom_apps/richdocumentscode" ]; then
php /var/www/html/occ app:remove richdocumentscode
fi
if ! [ -d "/var/www/html/custom_apps/richdocuments" ]; then if ! [ -d "/var/www/html/custom_apps/richdocuments" ]; then
php /var/www/html/occ app:install richdocuments php /var/www/html/occ app:install richdocuments
elif [ "$(php /var/www/html/occ config:app:get richdocuments enabled)" != "yes" ]; then elif [ "$(php /var/www/html/occ config:app:get richdocuments enabled)" != "yes" ]; then
@ -764,7 +603,7 @@ if [ "$COLLABORA_ENABLED" = 'yes' ]; then
fi fi
fi fi
else else
echo "Warning: No IPv4 address found for $COLLABORA_HOST." echo "Warning: No ipv4-address found for $COLLABORA_HOST."
fi fi
if [ -n "$COLLABORA_IPv6_ADDRESS" ]; then if [ -n "$COLLABORA_IPv6_ADDRESS" ]; then
if ! echo "$COLLABORA_ALLOW_LIST" | grep -q "$COLLABORA_IPv6_ADDRESS"; then if ! echo "$COLLABORA_ALLOW_LIST" | grep -q "$COLLABORA_IPv6_ADDRESS"; then
@ -775,10 +614,10 @@ if [ "$COLLABORA_ENABLED" = 'yes' ]; then
fi fi
fi fi
else else
echo "No IPv6 address found for $COLLABORA_HOST." echo "No ipv6-address found for $COLLABORA_HOST."
fi fi
if [ -n "$COLLABORA_ALLOW_LIST" ]; then if [ -n "$COLLABORA_ALLOW_LIST" ]; then
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' 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'
if ! echo "$COLLABORA_ALLOW_LIST" | grep -q "$PRIVATE_IP_RANGES"; then if ! echo "$COLLABORA_ALLOW_LIST" | grep -q "$PRIVATE_IP_RANGES"; then
COLLABORA_ALLOW_LIST+=",$PRIVATE_IP_RANGES" COLLABORA_ALLOW_LIST+=",$PRIVATE_IP_RANGES"
fi fi
@ -789,7 +628,7 @@ if [ "$COLLABORA_ENABLED" = 'yes' ]; then
fi fi
php /var/www/html/occ config:app:set richdocuments wopi_allowlist --value="$COLLABORA_ALLOW_LIST" php /var/www/html/occ config:app:set richdocuments wopi_allowlist --value="$COLLABORA_ALLOW_LIST"
else else
echo "Warning: wopi_allowlist is empty; this should not be the case!" echo "Warning: wopi_allowlist is empty which should not be the case!"
fi fi
else else
if [ "$REMOVE_DISABLED_APPS" = yes ] && [ -d "/var/www/html/custom_apps/richdocuments" ]; then if [ "$REMOVE_DISABLED_APPS" = yes ] && [ -d "/var/www/html/custom_apps/richdocuments" ]; then
@ -799,52 +638,23 @@ fi
# OnlyOffice # OnlyOffice
if [ "$ONLYOFFICE_ENABLED" = 'yes' ]; then if [ "$ONLYOFFICE_ENABLED" = 'yes' ]; then
# Determine OnlyOffice port based on host pattern while ! nc -z "$ONLYOFFICE_HOST" 80; do
if echo "$ONLYOFFICE_HOST" | grep -q "nextcloud-.*-onlyoffice"; then echo "waiting for OnlyOffice to become available..."
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 sleep 5
done done
if [ "$count" -ge 90 ]; then if ! [ -d "/var/www/html/custom_apps/onlyoffice" ]; then
bash /notify.sh "Onlyoffice did not start in time!" "Skipping initialization and disabling onlyoffice app." php /var/www/html/occ app:install onlyoffice
php /var/www/html/occ app:disable onlyoffice elif [ "$(php /var/www/html/occ config:app:get onlyoffice enabled)" != "yes" ]; then
else php /var/www/html/occ app:enable onlyoffice
# Install or enable OnlyOffice app as needed elif [ "$SKIP_UPDATE" != 1 ]; then
if ! [ -d "/var/www/html/custom_apps/onlyoffice" ]; then php /var/www/html/occ app:update onlyoffice
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 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 else
# 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
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 php /var/www/html/occ app:remove onlyoffice
fi fi
fi fi
@ -890,16 +700,14 @@ fi
if [ -d "/var/www/html/custom_apps/spreed" ]; then if [ -d "/var/www/html/custom_apps/spreed" ]; then
if [ "$TALK_RECORDING_ENABLED" = 'yes' ]; then if [ "$TALK_RECORDING_ENABLED" = 'yes' ]; then
while ! nc -z "$TALK_RECORDING_HOST" 1234; do 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 sleep 5
done done
# TODO: migrate to occ command if that becomes available # TODO: migrate to occ command if that becomes available
RECORDING_SERVERS_STRING="{\"servers\":[{\"server\":\"http://$TALK_RECORDING_HOST:1234/\",\"verify\":true}],\"secret\":\"$RECORDING_SECRET\"}" 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" php /var/www/html/occ config:app:set spreed recording_servers --value="$RECORDING_SERVERS_STRING"
else else
if [ "$REMOVE_DISABLED_APPS" = yes ]; then php /var/www/html/occ config:app:delete spreed recording_servers
php /var/www/html/occ config:app:delete spreed recording_servers
fi
fi fi
fi fi
@ -907,12 +715,12 @@ fi
if [ "$CLAMAV_ENABLED" = 'yes' ]; then if [ "$CLAMAV_ENABLED" = 'yes' ]; then
count=0 count=0
while ! nc -z "$CLAMAV_HOST" 3310 && [ "$count" -lt 90 ]; do 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)) count=$((count+5))
sleep 5 sleep 5
done done
if [ "$count" -ge 90 ]; then if [ "$count" -ge 90 ]; then
bash /notify.sh "ClamAV did not start in time!" "Skipping initialization and disabling files_antivirus app." echo "Clamav did not start in time. Skipping initialization and disabling files_antivirus app."
php /var/www/html/occ app:disable files_antivirus php /var/www/html/occ app:disable files_antivirus
else else
if ! [ -d "/var/www/html/custom_apps/files_antivirus" ]; then if ! [ -d "/var/www/html/custom_apps/files_antivirus" ]; then
@ -925,13 +733,9 @@ 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_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_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_host --value="$CLAMAV_HOST"
# 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="$CLAMAV_MAX_SIZE"
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="$CLAMAV_MAX_SIZE"
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" 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 fi
else else
if [ "$REMOVE_DISABLED_APPS" = yes ] && [ -d "/var/www/html/custom_apps/files_antivirus" ]; then if [ "$REMOVE_DISABLED_APPS" = yes ] && [ -d "/var/www/html/custom_apps/files_antivirus" ]; then
@ -942,7 +746,6 @@ fi
# Imaginary # Imaginary
if [ "$IMAGINARY_ENABLED" = 'yes' ]; then 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 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_url --value="http://$IMAGINARY_HOST:9000"
php /var/www/html/occ config:system:set preview_imaginary_key --value="$IMAGINARY_SECRET" php /var/www/html/occ config:system:set preview_imaginary_key --value="$IMAGINARY_SECRET"
else else
@ -952,63 +755,50 @@ else
php /var/www/html/occ config:system:delete enabledPreviewProviders 20 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 21
php /var/www/html/occ config:system:delete enabledPreviewProviders 22 php /var/www/html/occ config:system:delete enabledPreviewProviders 22
php /var/www/html/occ config:system:delete enabledPreviewProviders 23
fi fi
fi fi
# Fulltextsearch # Fulltextsearch
if [ "$FULLTEXTSEARCH_ENABLED" = 'yes' ]; then if [ "$FULLTEXTSEARCH_ENABLED" = 'yes' ]; then
count=0 while ! nc -z "$FULLTEXTSEARCH_HOST" 9200; do
while ! nc -z "$FULLTEXTSEARCH_HOST" "$FULLTEXTSEARCH_PORT" && [ "$count" -lt 90 ]; do echo "waiting for Fulltextsearch to become available..."
echo "Waiting for Fulltextsearch to become available..."
count=$((count+5))
sleep 5 sleep 5
done done
if [ "$count" -ge 90 ]; then if ! [ -d "/var/www/html/custom_apps/fulltextsearch" ]; then
echo "Fulltextsearch did not start in time. Skipping initialization and disabling fulltextsearch apps." php /var/www/html/occ app:install fulltextsearch
php /var/www/html/occ app:disable fulltextsearch elif [ "$(php /var/www/html/occ config:app:get fulltextsearch enabled)" != "yes" ]; then
php /var/www/html/occ app:disable fulltextsearch_elasticsearch php /var/www/html/occ app:enable fulltextsearch
php /var/www/html/occ app:disable files_fulltextsearch elif [ "$SKIP_UPDATE" != 1 ]; then
else php /var/www/html/occ app:update fulltextsearch
if [ -z "$FULLTEXTSEARCH_PROTOCOL" ]; then fi
FULLTEXTSEARCH_PROTOCOL="http" if ! [ -d "/var/www/html/custom_apps/fulltextsearch_elasticsearch" ]; then
fi php /var/www/html/occ app:install fulltextsearch_elasticsearch
if ! [ -d "/var/www/html/custom_apps/fulltextsearch" ]; then elif [ "$(php /var/www/html/occ config:app:get fulltextsearch_elasticsearch enabled)" != "yes" ]; then
php /var/www/html/occ app:install fulltextsearch php /var/www/html/occ app:enable fulltextsearch_elasticsearch
elif [ "$(php /var/www/html/occ config:app:get fulltextsearch enabled)" != "yes" ]; then elif [ "$SKIP_UPDATE" != 1 ]; then
php /var/www/html/occ app:enable fulltextsearch php /var/www/html/occ app:update fulltextsearch_elasticsearch
elif [ "$SKIP_UPDATE" != 1 ]; then fi
php /var/www/html/occ app:update fulltextsearch if ! [ -d "/var/www/html/custom_apps/files_fulltextsearch" ]; then
fi php /var/www/html/occ app:install files_fulltextsearch
if ! [ -d "/var/www/html/custom_apps/fulltextsearch_elasticsearch" ]; then elif [ "$(php /var/www/html/occ config:app:get files_fulltextsearch enabled)" != "yes" ]; then
php /var/www/html/occ app:install fulltextsearch_elasticsearch php /var/www/html/occ app:enable files_fulltextsearch
elif [ "$(php /var/www/html/occ config:app:get fulltextsearch_elasticsearch enabled)" != "yes" ]; then elif [ "$SKIP_UPDATE" != 1 ]; then
php /var/www/html/occ app:enable fulltextsearch_elasticsearch php /var/www/html/occ app:update files_fulltextsearch
elif [ "$SKIP_UPDATE" != 1 ]; then fi
php /var/www/html/occ app:update fulltextsearch_elasticsearch php /var/www/html/occ fulltextsearch:configure '{"search_platform":"OCA\\FullTextSearch_Elasticsearch\\Platform\\ElasticSearchPlatform"}'
fi php /var/www/html/occ fulltextsearch_elasticsearch:configure "{\"elastic_host\":\"http://elastic:$FULLTEXTSEARCH_PASSWORD@$FULLTEXTSEARCH_HOST:9200\",\"elastic_index\":\"nextcloud-aio\"}"
if ! [ -d "/var/www/html/custom_apps/files_fulltextsearch" ]; then php /var/www/html/occ files_fulltextsearch:configure "{\"files_pdf\":\"1\",\"files_office\":\"1\"}"
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 # Do the index
if ! [ -f "$NEXTCLOUD_DATA_DIR/fts-index.done" ]; then if ! [ -f "$NEXTCLOUD_DATA_DIR/fts-index.done" ]; then
echo "Waiting 10 seconds before activating fulltextsearch..." echo "Waiting 10s before activating FTS..."
sleep 10 sleep 10
echo "Activating fulltextsearch..." echo "Activating fulltextsearch..."
if php /var/www/html/occ fulltextsearch:test && php /var/www/html/occ fulltextsearch:index "{\"errors\": \"reset\"}" --no-readline; then 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" touch "$NEXTCLOUD_DATA_DIR/fts-index.done"
else else
echo "Fulltextsearch failed. Could not index." 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" echo "Feel free to follow https://github.com/nextcloud/all-in-one/discussions/1709 if you want to skip the indexing in the future."
fi
fi fi
fi fi
else else
@ -1026,37 +816,19 @@ else
fi fi
# Docker socket proxy # Docker socket proxy
# app_api is a shipped app if version_greater "$installed_version" "27.1.2.0"; then
if [ -d "/var/www/html/custom_apps/app_api" ]; then if [ "$DOCKER_SOCKET_PROXY_ENABLED" = 'yes' ]; then
php /var/www/html/occ app:disable app_api if ! [ -d "/var/www/html/custom_apps/app_api" ]; then
rm -r "/var/www/html/custom_apps/app_api" php /var/www/html/occ app:install app_api
fi elif [ "$(php /var/www/html/occ config:app:get app_api enabled)" != "yes" ]; then
if [ "$DOCKER_SOCKET_PROXY_ENABLED" = 'yes' ]; then php /var/www/html/occ app:enable app_api
if [ "$(php /var/www/html/occ config:app:get app_api enabled)" != "yes" ]; then elif [ "$SKIP_UPDATE" != 1 ]; then
php /var/www/html/occ app:enable app_api php /var/www/html/occ app:update app_api
fi fi
else else
if [ "$REMOVE_DISABLED_APPS" = yes ]; then if [ "$REMOVE_DISABLED_APPS" = yes ] && [ -d "/var/www/html/custom_apps/app_api" ]; then
if [ "$(php /var/www/html/occ config:app:get app_api enabled)" != "no" ]; then php /var/www/html/occ app:remove app_api
php /var/www/html/occ app:disable app_api
fi fi
fi
fi
# Whiteboard app
if [ "$WHITEBOARD_ENABLED" = 'yes' ]; then
if ! [ -d "/var/www/html/custom_apps/whiteboard" ]; then
php /var/www/html/occ app:install whiteboard
elif [ "$(php /var/www/html/occ config:app:get whiteboard enabled)" != "yes" ]; then
php /var/www/html/occ app:enable whiteboard
elif [ "$SKIP_UPDATE" != 1 ]; then
php /var/www/html/occ app:update whiteboard
fi
php /var/www/html/occ config:app:set whiteboard collabBackendUrl --value="https://$NC_DOMAIN/whiteboard"
php /var/www/html/occ config:app:set whiteboard jwt_secret_key --value="$WHITEBOARD_SECRET"
else
if [ "$REMOVE_DISABLED_APPS" = yes ] && [ -d "/var/www/html/custom_apps/whiteboard" ]; then
php /var/www/html/occ app:remove whiteboard
fi fi
fi fi

View file

@ -20,7 +20,7 @@ mapfile -t NC_USERS <<< "$NC_USERS"
for user in "${NC_USERS[@]}" for user in "${NC_USERS[@]}"
do do
echo "Posting '$SUBJECT' to: $user" echo "Posting '$SUBJECT' to: $user"
"${COMMAND[@]}" notification:generate "$user" "$NC_DOMAIN: $SUBJECT" -l "$MESSAGE" --object-type='update' --object-id="$SUBJECT" "${COMMAND[@]}" notification:generate "$user" "$NC_DOMAIN: $SUBJECT" -l "$MESSAGE"
done done
echo "Done!" echo "Done!"

View file

@ -28,7 +28,7 @@ done
for admin in "${NC_ADMIN_USER[@]}" for admin in "${NC_ADMIN_USER[@]}"
do do
echo "Posting '$SUBJECT' to: $admin" echo "Posting '$SUBJECT' to: $admin"
"${COMMAND[@]}" notification:generate "$admin" "$NC_DOMAIN: $SUBJECT" -l "$MESSAGE" --object-type='update' --object-id="$SUBJECT" "${COMMAND[@]}" notification:generate "$admin" "$NC_DOMAIN: $SUBJECT" -l "$MESSAGE"
done done
echo "Done!" echo "Done!"

View file

@ -1,4 +1,4 @@
Warning: You have logged in into the Nextcloud container as root user. 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. 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 -E -u www-data php occ <your-command>' in order to run occ commands. Apart from that, you can use 'sudo -u www-data -E php occ <your-command>' in order to run occ commands.
Of course <your-command> needs to be substituted with the command that you want to use. Of course <your-command> needs to be substituted with the command that you want to use.

View file

@ -1,10 +1,7 @@
#!/bin/bash #!/bin/bash
# Wait until the apache container is ready # Wait 15s for domain to be reachable
while ! nc -z "$APACHE_HOST" "$APACHE_PORT"; do sleep 15
echo "Waiting for $APACHE_HOST to become available..."
sleep 15
done
if [ -n "$NEXTCLOUD_EXEC_COMMANDS" ]; then if [ -n "$NEXTCLOUD_EXEC_COMMANDS" ]; then
echo "#!/bin/bash" > /tmp/nextcloud-exec-commands echo "#!/bin/bash" > /tmp/nextcloud-exec-commands
@ -19,13 +16,11 @@ else
echo "Activating Collabora config..." echo "Activating Collabora config..."
php /var/www/html/occ richdocuments:activate-config php /var/www/html/occ richdocuments:activate-config
fi 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 fi
signal_handler() { sleep inf
exit 0
}
trap signal_handler SIGINT SIGTERM
sleep inf &
wait $!

View file

@ -8,7 +8,7 @@ fi
# Only start container if database is accessible # Only start container if database is accessible
# POSTGRES_HOST must be set in the containers env vars and POSTGRES_PORT has a default above # POSTGRES_HOST must be set in the containers env vars and POSTGRES_PORT has a default above
# shellcheck disable=SC2153 # shellcheck disable=SC2153
while ! sudo -E -u www-data nc -z "$POSTGRES_HOST" "$POSTGRES_PORT"; do while ! sudo -u www-data nc -z "$POSTGRES_HOST" "$POSTGRES_PORT"; do
echo "Waiting for database to start..." echo "Waiting for database to start..."
sleep 5 sleep 5
done done
@ -17,15 +17,10 @@ done
POSTGRES_USER="oc_$POSTGRES_USER" POSTGRES_USER="oc_$POSTGRES_USER"
export 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 # Fix false database connection on old instances
if [ -f "/var/www/html/config/config.php" ]; then if [ -f "/var/www/html/config/config.php" ]; then
sleep 2 sleep 2
while ! sudo -E -u www-data psql -d "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB" -c "select now()"; do while ! sudo -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..." echo "Waiting for the database to start..."
sleep 5 sleep 5
done done
@ -56,12 +51,12 @@ fi
set +x set +x
# Check datadir permissions # Check datadir permissions
sudo -E -u www-data touch "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" &>/dev/null sudo -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 if ! [ -f "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" ]; then
chown -R www-data:root "$NEXTCLOUD_DATA_DIR" chown -R www-data:root "$NEXTCLOUD_DATA_DIR"
chmod 750 -R "$NEXTCLOUD_DATA_DIR" chmod 750 -R "$NEXTCLOUD_DATA_DIR"
fi fi
sudo -E -u www-data rm -f "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" sudo -u www-data rm -f "$NEXTCLOUD_DATA_DIR/this-is-a-test-file"
# Install additional dependencies # Install additional dependencies
if [ -n "$ADDITIONAL_APKS" ]; then if [ -n "$ADDITIONAL_APKS" ]; then
@ -86,15 +81,13 @@ fi
# Install additional php extensions # Install additional php extensions
if [ -n "$ADDITIONAL_PHP_EXTENSIONS" ]; then if [ -n "$ADDITIONAL_PHP_EXTENSIONS" ]; then
if ! [ -f "/additional-php-extensions-are-installed" ]; 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" read -ra ADDITIONAL_PHP_EXTENSIONS_ARRAY <<< "$ADDITIONAL_PHP_EXTENSIONS"
for app in "${ADDITIONAL_PHP_EXTENSIONS_ARRAY[@]}"; do for app in "${ADDITIONAL_PHP_EXTENSIONS_ARRAY[@]}"; do
if [ "$app" = imagick ]; then if [ "$app" = imagick ]; then
# imagick is already enabled by default, so does not need to be enabled anymore. echo "Enabling Imagick..."
if ! docker-php-ext-enable imagick >/dev/null; then
echo "Could not install PHP extension imagick!"
fi
continue continue
fi fi
# shellcheck disable=SC2086 # shellcheck disable=SC2086

View file

@ -39,7 +39,5 @@ stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0 stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0 stderr_logfile_maxbytes=0
# Restart the netcat command once a day to ensure that it stays reachable command=nc -lk 9001
# See https://github.com/nextcloud/all-in-one/issues/6334
command=timeout 86400 nc -lk 9001
user=www-data user=www-data

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
FROM alpine:3.23.3 FROM alpine:3.20.2
COPY --chmod=775 start.sh /start.sh COPY --chmod=775 start.sh /start.sh
COPY --chmod=775 healthcheck.sh /healthcheck.sh COPY --chmod=775 healthcheck.sh /healthcheck.sh
@ -11,7 +11,6 @@ RUN set -ex; \
netcat-openbsd \ netcat-openbsd \
tzdata \ tzdata \
bash \ bash \
jq \
openssl; \ openssl; \
# Give root a random password # Give root a random password
echo "root:$(openssl rand -base64 12)" | chpasswd; \ echo "root:$(openssl rand -base64 12)" | chpasswd; \
@ -22,6 +21,4 @@ USER 33
ENTRYPOINT ["/start.sh"] ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD /healthcheck.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"

View file

@ -1,13 +1,13 @@
#!/bin/bash #!/bin/bash
if [ -z "$NEXTCLOUD_HOST" ]; then if [ -z "$NEXTCLOUD_HOST" ]; then
echo "NEXTCLOUD_HOST needs to be provided. Exiting!" echo "NEXTCLOUD_HOST need to be provided. Exiting!"
exit 1 exit 1
elif [ -z "$POSTGRES_HOST" ]; then elif [ -z "$POSTGRES_HOST" ]; then
echo "POSTGRES_HOST needs to be provided. Exiting!" echo "POSTGRES_HOST need to be provided. Exiting!"
exit 1 exit 1
elif [ -z "$REDIS_HOST" ]; then elif [ -z "$REDIS_HOST" ]; then
echo "REDIS_HOST needs to be provided. Exiting!" echo "REDIS_HOST need to be provided. Exiting!"
exit 1 exit 1
fi fi
@ -48,43 +48,9 @@ echo "notify-push was started"
if [ -z "$POSTGRES_PORT" ]; then if [ -z "$POSTGRES_PORT" ]; then
POSTGRES_PORT=5432 POSTGRES_PORT=5432
fi fi
# Set a default for redis db index
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 # Set sensitive values as env
export DATABASE_URL="$DATABASE_TYPE://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB$CERT_OPTIONS" export DATABASE_URL="postgres://oc_$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB"
export REDIS_URL="redis://$REDIS_USER:$REDIS_HOST_PASSWORD@$REDIS_HOST:$REDIS_PORT/$REDIS_DB_INDEX" export REDIS_URL="redis://:$REDIS_HOST_PASSWORD@$REDIS_HOST"
# Run it # Run it
/nextcloud/custom_apps/notify_push/bin/"$CPU_ARCH"/notify_push \ /nextcloud/custom_apps/notify_push/bin/"$CPU_ARCH"/notify_push \

View file

@ -1,12 +1,8 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
# From https://github.com/ONLYOFFICE/Docker-DocumentServer/blob/master/Dockerfile # From https://github.com/ONLYOFFICE/Docker-DocumentServer/blob/master/Dockerfile
FROM onlyoffice/documentserver:9.2.1.1 FROM onlyoffice/documentserver:8.1.1.1
# USER root is probably used # USER root is probably used
COPY --chmod=775 healthcheck.sh /healthcheck.sh HEALTHCHECK CMD nc -z 127.0.0.1 80 || 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"

View file

@ -1,3 +0,0 @@
#!/bin/bash
nc -z 127.0.0.1 80 || exit 1

View file

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
# From https://github.com/docker-library/postgres/blob/master/17/alpine3.23/Dockerfile # From https://github.com/docker-library/postgres/blob/master/16/alpine3.20/Dockerfile
FROM postgres:17.7-alpine FROM postgres:16.3-alpine
COPY --chmod=775 start.sh /start.sh COPY --chmod=775 start.sh /start.sh
COPY --chmod=775 healthcheck.sh /healthcheck.sh COPY --chmod=775 healthcheck.sh /healthcheck.sh
@ -39,10 +39,8 @@ RUN set -ex; \
VOLUME /mnt/data VOLUME /mnt/data
USER 999 USER postgres
ENTRYPOINT ["/start.sh"] ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD /healthcheck.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"

View file

@ -2,6 +2,4 @@
test -f "/mnt/data/backup-is-running" && exit 0 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 psql -d "postgresql://oc_$POSTGRES_USER:$POSTGRES_PASSWORD@127.0.0.1:5432/$POSTGRES_DB" -c "select now()" || exit 1

View file

@ -99,7 +99,7 @@ if ( [ -f "$DATADIR/PG_VERSION" ] && [ "$PG_MAJOR" != "$(cat "$DATADIR/PG_VERSIO
fi fi
# Get the Owner # Get the Owner
DB_OWNER="$(grep -a "$GREP_STRING" "$DUMP_FILE" | head -1 | grep -oP 'Owner:.*$' | sed 's|Owner:||;s|[[:space:]]||g')" DB_OWNER="$(grep -a "$GREP_STRING" "$DUMP_FILE" | head -1 | grep -oP 'Owner:.*$' | sed 's|Owner:||;s| ||g')"
if [ "$DB_OWNER" = "$POSTGRES_USER" ]; then 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 "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." echo "It is not possible to import a database dump from this database owner."
@ -128,9 +128,7 @@ EOSQL
fi fi
# Shut down the database to be able to start it again # Shut down the database to be able to start it again
# The smart mode disallows new connections, then waits for all existing clients to disconnect and any online backup to finish pg_ctl stop -m fast
# 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 # Change database port back to default
export PGPORT=5432 export PGPORT=5432

View file

@ -1,6 +1,6 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
# From https://github.com/redis/docker-library-redis/blob/release/8.2/alpine/Dockerfile # From https://github.com/docker-library/redis/blob/master/7.2/alpine/Dockerfile
FROM redis:8.2.3-alpine FROM redis:7.2.5-alpine
COPY --chmod=775 start.sh /start.sh COPY --chmod=775 start.sh /start.sh
@ -14,12 +14,8 @@ RUN set -ex; \
# Get rid of unused binaries # Get rid of unused binaries
rm -f /usr/local/bin/gosu; rm -f /usr/local/bin/gosu;
COPY --chmod=775 healthcheck.sh /healthcheck.sh USER redis
USER 999
ENTRYPOINT ["/start.sh"] ENTRYPOINT ["/start.sh"]
HEALTHCHECK CMD /healthcheck.sh HEALTHCHECK CMD redis-cli -a $REDIS_HOST_PASSWORD PING || exit 1
LABEL com.centurylinklabs.watchtower.enable="false" \ LABEL com.centurylinklabs.watchtower.enable="false"
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -1,3 +0,0 @@
#!/bin/bash
redis-cli -a "$REDIS_HOST_PASSWORD" PING || exit 1

View file

@ -1,13 +1,11 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
FROM python:3.14.2-alpine3.23 FROM python:3.12.4-alpine3.20
COPY --chmod=775 start.sh /start.sh COPY --chmod=775 start.sh /start.sh
COPY --chmod=775 healthcheck.sh /healthcheck.sh
ENV RECORDING_VERSION=v0.2.1 ENV RECORDING_VERSION=v0.1
ENV ALLOW_ALL=false ENV ALLOW_ALL=false
ENV HPB_PROTOCOL=https ENV HPB_PROTOCOL=https
ENV NC_PROTOCOL=https
ENV SKIP_VERIFY=false ENV SKIP_VERIFY=false
ENV HPB_PATH=/standalone-signaling/ ENV HPB_PATH=/standalone-signaling/
@ -30,7 +28,7 @@ RUN set -ex; \
build-base \ build-base \
linux-headers \ linux-headers \
geckodriver; \ geckodriver; \
useradd -d /tmp --system recording -u 122; \ useradd -d /tmp --system recording; \
# Give root a random password # Give root a random password
echo "root:$(openssl rand -base64 12)" | chpasswd; \ 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; \ git clone --recursive https://github.com/nextcloud/nextcloud-talk-recording --depth=1 --single-branch --branch "$RECORDING_VERSION" /src; \
@ -50,13 +48,10 @@ RUN set -ex; \
build-base \ build-base \
linux-headers; linux-headers;
VOLUME /tmp
WORKDIR /tmp WORKDIR /tmp
USER 122 USER recording
ENTRYPOINT ["/start.sh"] ENTRYPOINT ["/start.sh"]
CMD ["python", "-m", "nextcloud.talk.recording", "--config", "/conf/recording.conf"] CMD ["python", "-m", "nextcloud.talk.recording", "--config", "/conf/recording.conf"]
HEALTHCHECK CMD /healthcheck.sh HEALTHCHECK CMD nc -z 127.0.0.1 1234 || exit 1
LABEL com.centurylinklabs.watchtower.enable="false" \ LABEL com.centurylinklabs.watchtower.enable="false"
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

View file

@ -1,3 +0,0 @@
#!/bin/bash
nc -z 127.0.0.1 1234 || exit 1

View file

@ -1,5 +1,3 @@
# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: AGPL-3.0-or-later
[logs] [logs]
# Log level based on numeric values of Python logging levels: # Log level based on numeric values of Python logging levels:
# - Critical: 50 # - Critical: 50
@ -14,11 +12,6 @@
# IP and port to listen on for HTTP requests. # IP and port to listen on for HTTP requests.
#listen = 127.0.0.1:8000 #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] [backend]
# Allow any hostname as backend endpoint. This is extremely insecure and should # Allow any hostname as backend endpoint. This is extremely insecure and should
# only be used during development. # only be used during development.
@ -107,18 +100,6 @@
# ffmpeg. The options given here fully override the default global options. # ffmpeg. The options given here fully override the default global options.
#common = ffmpeg -loglevel level+warning -n #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 # The options given to ffmpeg to encode the audio output. The options given here
# fully override the default options for the audio output. # fully override the default options for the audio output.
#outputaudio = -c:a libopus #outputaudio = -c:a libopus
@ -139,31 +120,4 @@
# will use Google Chrome, or Chromium if Google Chrome is not installed. # will use Google Chrome, or Chromium if Google Chrome is not installed.
# Allowed values: firefox, chrome # Allowed values: firefox, chrome
# Defaults to firefox # 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 =

View file

@ -16,9 +16,6 @@ if [ -z "$HPB_DOMAIN" ]; then
export HPB_DOMAIN="$NC_DOMAIN" export HPB_DOMAIN="$NC_DOMAIN"
fi fi
# Delete all contents on startup to start fresh
rm -fr /tmp/{*,.*}
cat << RECORDING_CONF > "/conf/recording.conf" cat << RECORDING_CONF > "/conf/recording.conf"
[logs] [logs]
# 30 means Warning # 30 means Warning
@ -39,7 +36,7 @@ videoheight = 1080
directory = /tmp directory = /tmp
[backend-1] [backend-1]
url = ${NC_PROTOCOL}://${NC_DOMAIN} url = ${HPB_PROTOCOL}://${NC_DOMAIN}
secret = ${RECORDING_SECRET} secret = ${RECORDING_SECRET}
skipverify = ${SKIP_VERIFY} skipverify = ${SKIP_VERIFY}
@ -59,8 +56,6 @@ extensionvideo = .webm
[recording] [recording]
browser = firefox browser = firefox
driverPath = /usr/bin/geckodriver
browserPath = /usr/bin/firefox
RECORDING_CONF RECORDING_CONF
exec "$@" exec "$@"

View file

@ -1,13 +1,12 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
FROM nats:2.12.4-scratch AS nats FROM nats:2.10.18-scratch AS nats
FROM eturnal/eturnal:1.12.2-alpine AS eturnal FROM eturnal/eturnal:1.12.0 AS eturnal
FROM strukturag/nextcloud-spreed-signaling:2.0.4 AS signaling FROM strukturag/nextcloud-spreed-signaling:1.3.2 AS signaling
FROM alpine:3.23.3 AS janus FROM alpine:3.20.2 AS janus
ARG JANUS_VERSION=v1.3.3 ARG JANUS_VERSION=v0.14.3
WORKDIR /src WORKDIR /src
RUN set -ex; \ RUN set -ex; \
apk upgrade --no-cache -a; \
apk add --no-cache \ apk add --no-cache \
ca-certificates \ ca-certificates \
git \ git \
@ -35,9 +34,8 @@ RUN set -ex; \
make configs; \ make configs; \
rename -v ".jcfg.sample" ".jcfg" /usr/local/etc/janus/*.jcfg.sample rename -v ".jcfg.sample" ".jcfg" /usr/local/etc/janus/*.jcfg.sample
FROM alpine:3.23.3 FROM alpine:3.20.2
ENV ETURNAL_ETC_DIR="/conf" ENV ETURNAL_ETC_DIR="/conf"
ENV SKIP_CERT_VERIFY=false
COPY --from=janus --chmod=777 --chown=1000:1000 /usr/local /usr/local 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=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 COPY --from=nats --chmod=777 --chown=1000:1000 /nats-server /usr/local/bin/nats-server
@ -101,11 +99,9 @@ RUN set -ex; \
ln -s /opt/eturnal/bin/stun /usr/local/bin/stun; \ ln -s /opt/eturnal/bin/stun /usr/local/bin/stun; \
ln -s /opt/eturnal/bin/eturnalctl /usr/local/bin/eturnalctl ln -s /opt/eturnal/bin/eturnalctl /usr/local/bin/eturnalctl
USER 1000 USER eturnal
ENTRYPOINT ["/start.sh"] ENTRYPOINT ["/start.sh"]
CMD ["supervisord", "-c", "/supervisord.conf"] CMD ["supervisord", "-c", "/supervisord.conf"]
HEALTHCHECK CMD /healthcheck.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"

View file

@ -55,15 +55,6 @@ blockkey = -encryption-key-
# value as configured in the respective internal services. # value as configured in the respective internal services.
internalsecret = the-shared-secret-for-internal-clients internalsecret = the-shared-secret-for-internal-clients
[federation]
# If set to "true", certificate validation of federation targets will be skipped.
# This should only be enabled during development, e.g. to work with self-signed
# certificates.
#skipverify = false
# Timeout in seconds for requests to federation targets.
#timeout = 10
[backend] [backend]
# Type of backend configuration. # Type of backend configuration.
# Defaults to "static". # Defaults to "static".
@ -84,8 +75,7 @@ internalsecret = the-shared-secret-for-internal-clients
# For backend type "etcd": # For backend type "etcd":
# Key prefix of backend entries. All keys below will be watched and assumed to # Key prefix of backend entries. All keys below will be watched and assumed to
# contain a JSON document with the following entries: # contain a JSON document with the following entries:
# - "urls": List of urls of the Nextcloud instance. # - "url": Url of the Nextcloud instance.
# - "url": Url of the Nextcloud instance (deprecated).
# - "secret": Shared secret for requests from and to the backend servers. # - "secret": Shared secret for requests from and to the backend servers.
# #
# Additional optional entries: # Additional optional entries:
@ -94,8 +84,8 @@ internalsecret = the-shared-secret-for-internal-clients
# - "sessionlimit": Number of sessions that are allowed to connect. # - "sessionlimit": Number of sessions that are allowed to connect.
# #
# Example: # Example:
# "/signaling/backend/one" -> {"urls": ["https://nextcloud.domain1.invalid"], ...} # "/signaling/backend/one" -> {"url": "https://nextcloud.domain1.invalid", ...}
# "/signaling/backend/two" -> {"urls": ["https://domain2.invalid/nextcloud"], ...} # "/signaling/backend/two" -> {"url": "https://domain2.invalid/nextcloud", ...}
#backendprefix = /signaling/backend #backendprefix = /signaling/backend
# Allow any hostname as backend endpoint. This is extremely insecure and should # Allow any hostname as backend endpoint. This is extremely insecure and should
@ -123,8 +113,8 @@ connectionsperhost = 8
# Backend configurations as defined in the "[backend]" section above. The # Backend configurations as defined in the "[backend]" section above. The
# section names must match the ids used in "backends" above. # section names must match the ids used in "backends" above.
#[backend-id] #[backend-id]
# Comma-separated list of urls of the Nextcloud instance # URL of the Nextcloud instance
#urls = https://cloud.domain.invalid #url = https://cloud.domain.invalid
# Shared secret for requests from and to the backend servers. Leave empty to use # Shared secret for requests from and to the backend servers. Leave empty to use
# the common shared secret from above. # the common shared secret from above.
@ -144,8 +134,8 @@ connectionsperhost = 8
#maxscreenbitrate = 2097152 #maxscreenbitrate = 2097152
#[another-backend] #[another-backend]
# Comma-separated list of urls of the Nextcloud instance # URL of the Nextcloud instance
#urls = https://cloud.otherdomain.invalid #url = https://cloud.otherdomain.invalid
# Shared secret for requests from and to the backend servers. Leave empty to use # Shared secret for requests from and to the backend servers. Leave empty to use
# the common shared secret from above. # the common shared secret from above.
@ -180,13 +170,6 @@ connectionsperhost = 8
# proxy server that is used. # proxy server that is used.
#maxscreenbitrate = 2097152 #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. # For type "proxy": timeout in seconds for requests to the proxy server.
#proxytimeout = 2 #proxytimeout = 2

View file

@ -30,23 +30,14 @@ if [ -n "$IPv4_ADDRESS_TALK" ] && [ "$IPv4_ADDRESS_TALK_RELAY" = "$IPv4_ADDRESS_
IPv4_ADDRESS_TALK="" IPv4_ADDRESS_TALK=""
fi 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 # Turn
cat << TURN_CONF > "/conf/eturnal.yml" cat << TURN_CONF > "/conf/eturnal.yml"
eturnal: eturnal:
listen: listen:
- ip: "$IP_BINDING" - ip: "::"
port: $TALK_PORT port: $TALK_PORT
transport: udp transport: udp
- ip: "$IP_BINDING" - ip: "::"
port: $TALK_PORT port: $TALK_PORT
transport: tcp transport: tcp
log_dir: stdout log_dir: stdout
@ -95,10 +86,9 @@ backends = backend-1
allowall = false allowall = false
timeout = 10 timeout = 10
connectionsperhost = 8 connectionsperhost = 8
skipverify = ${SKIP_CERT_VERIFY}
[backend-1] [backend-1]
urls = https://${NC_DOMAIN} url = https://${NC_DOMAIN}
secret = ${SIGNALING_SECRET} secret = ${SIGNALING_SECRET}
maxstreambitrate = ${TALK_MAX_STREAM_BITRATE} maxstreambitrate = ${TALK_MAX_STREAM_BITRATE}
maxscreenbitrate = ${TALK_MAX_SCREEN_BITRATE} maxscreenbitrate = ${TALK_MAX_SCREEN_BITRATE}

View file

@ -1,21 +1,13 @@
# syntax=docker/dockerfile:latest # syntax=docker/dockerfile:latest
FROM golang:1.25.6-alpine3.23 AS go # From https://github.com/containrrr/watchtower/blob/main/dockerfiles/Dockerfile.self-contained
FROM containrrr/watchtower:1.7.1 AS watchtower
ENV WATCHTOWER_COMMIT_HASH=f522ce27e1fbe4618da54833025a95be62aa838a FROM alpine:3.20.2
RUN set -ex; \ RUN apk upgrade --no-cache -a; \
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
FROM alpine:3.23.3 COPY --from=watchtower /watchtower /watchtower
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 COPY --chmod=775 start.sh /start.sh
@ -23,6 +15,4 @@ COPY --chmod=775 start.sh /start.sh
USER root USER root
ENTRYPOINT ["/start.sh"] ENTRYPOINT ["/start.sh"]
LABEL com.centurylinklabs.watchtower.enable="false" \ LABEL com.centurylinklabs.watchtower.enable="false"
wud.watch="false" \
org.label-schema.vendor="Nextcloud"

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