mirror of
https://github.com/nextcloud/all-in-one.git
synced 2026-05-21 10:50:10 +00:00
Compare commits
102 Commits
v10.7.0
...
Anvil5465-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d5b39b98a | ||
|
|
25c580bca3 | ||
|
|
80920778fb | ||
|
|
d3ac48f352 | ||
|
|
13e9829a85 | ||
|
|
7cb96aed74 | ||
|
|
ecb2e1ad87 | ||
|
|
378346c9c1 | ||
|
|
edbdac6af4 | ||
|
|
a4fa22ec22 | ||
|
|
fa87a5ca6a | ||
|
|
c65eb16a15 | ||
|
|
3dffd46e8b | ||
|
|
7f76f622e1 | ||
|
|
ac2c97a08e | ||
|
|
d5c195aa0c | ||
|
|
5d090018f9 | ||
|
|
b8d08fc77b | ||
|
|
4669ad430c | ||
|
|
348a08a720 | ||
|
|
167c2dc389 | ||
|
|
4c14fa9b13 | ||
|
|
9b8a9de565 | ||
|
|
b9a04858ca | ||
|
|
91e99dcba9 | ||
|
|
6b9e68d55f | ||
|
|
0ed524baba | ||
|
|
7eabc59328 | ||
|
|
8ddd123568 | ||
|
|
b1f2d6f691 | ||
|
|
2cc4c6813f | ||
|
|
91ca184262 | ||
|
|
6d1f1c1aeb | ||
|
|
f876b23c0b | ||
|
|
d6446d5f03 | ||
|
|
c1b60f9a51 | ||
|
|
e37611a759 | ||
|
|
4f68d3ed1c | ||
|
|
43f73ccbfe | ||
|
|
a4aa1baf54 | ||
|
|
38254f76ab | ||
|
|
80ae736633 | ||
|
|
0e0dc0da6f | ||
|
|
4e922c0943 | ||
|
|
1fbc3074dd | ||
|
|
4cb258e7d2 | ||
|
|
f90631125e | ||
|
|
7062b6aa90 | ||
|
|
38a11c4624 | ||
|
|
c525f802d5 | ||
|
|
c973834733 | ||
|
|
ccc6487877 | ||
|
|
1b6524b904 | ||
|
|
47964fc16c | ||
|
|
63d9343972 | ||
|
|
d164eea1ee | ||
|
|
fbb71586e8 | ||
|
|
8fe6821038 | ||
|
|
36dc60e9d2 | ||
|
|
77dd56bade | ||
|
|
4b644d2fe7 | ||
|
|
b5132b14ff | ||
|
|
af4700d863 | ||
|
|
016dde1e47 | ||
|
|
e97d4b0a3e | ||
|
|
a6246f9544 | ||
|
|
04224e8745 | ||
|
|
be0a738e8c | ||
|
|
a0c8724d98 | ||
|
|
47df5053c8 | ||
|
|
113cd76c6a | ||
|
|
8d1a4653a0 | ||
|
|
a661b488c3 | ||
|
|
aa452b4613 | ||
|
|
fe310624ed | ||
|
|
405fc57bf4 | ||
|
|
0b02764897 | ||
|
|
945f1341fd | ||
|
|
5b6990dfbc | ||
|
|
9e95d96656 | ||
|
|
e6bf224a9a | ||
|
|
06b31c5680 | ||
|
|
53abc41cde | ||
|
|
30b9a05263 | ||
|
|
0615fe2250 | ||
|
|
37d6241550 | ||
|
|
5ab4a4da4e | ||
|
|
b0c191079d | ||
|
|
d21ade09d3 | ||
|
|
6bab6712ce | ||
|
|
b3261d908a | ||
|
|
3083458245 | ||
|
|
a03622ce0a | ||
|
|
f55ef08c73 | ||
|
|
88127f607b | ||
|
|
1ed7e54ca6 | ||
|
|
c2ac5c64d6 | ||
|
|
0a4eac4d4b | ||
|
|
4893a0dfc1 | ||
|
|
a7861f2dca | ||
|
|
bf4636e8d6 | ||
|
|
0e88a15edb |
2
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@@ -5,8 +5,10 @@ labels: 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.
|
||||
- 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.
|
||||
|
||||
--->
|
||||
|
||||
<!--- Please fill out the whole template below -->
|
||||
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
5
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 📘 Documentation on Nextcloud AIO
|
||||
url: https://github.com/nextcloud/all-in-one#faq
|
||||
about: Please read the docs first before submitting any report or request!
|
||||
- name: ⛑️ General questions and support
|
||||
url: https://help.nextcloud.com/tag/aio
|
||||
about: For general questions, support and help
|
||||
@@ -11,4 +14,4 @@ contact_links:
|
||||
about: For questions specifically about AIO
|
||||
- name: 💼 Nextcloud Enterprise
|
||||
url: https://portal.nextcloud.com/
|
||||
about: If you are a Nextcloud Enterprise customer, or need Professional support, so it can be resolved directly by our dedicated engineers more quickly
|
||||
about: If you are a Nextcloud Enterprise customer, or need Professional support, so it can be resolved directly by our dedicated engineers more quickly
|
||||
|
||||
2
.github/dependabot.yml
vendored
2
.github/dependabot.yml
vendored
@@ -1,7 +1,7 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
directory: ".github/workflows"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "12:00"
|
||||
|
||||
2
.github/workflows/codespell.yml
vendored
2
.github/workflows/codespell.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- name: Check spelling
|
||||
uses: codespell-project/actions-codespell@v2
|
||||
uses: codespell-project/actions-codespell@406322ec52dd7b488e48c1c4b82e2a8b3a1bf630 # v2
|
||||
with:
|
||||
check_filenames: true
|
||||
check_hidden: true
|
||||
|
||||
4
.github/workflows/dependency-updates.yml
vendored
4
.github/workflows/dependency-updates.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: shivammathur/setup-php@v2
|
||||
- uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2
|
||||
with:
|
||||
php-version: 8.3
|
||||
extensions: apcu
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
)"
|
||||
sed -i "s|pecl install APCu.*\;|pecl install APCu-$apcu_version\;|" ./Containers/mastercontainer/Dockerfile
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
|
||||
with:
|
||||
commit-message: php dependency updates
|
||||
signoff: true
|
||||
|
||||
6
.github/workflows/helm-release.yml
vendored
6
.github/workflows/helm-release.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Turnstyle
|
||||
uses: softprops/turnstyle@v2
|
||||
uses: softprops/turnstyle@25dcee5c3fcb84375f3a3f93a3c97ed0d42cfcdc # v2
|
||||
with:
|
||||
continue-after-seconds: 180
|
||||
env:
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
|
||||
# See https://github.com/helm/chart-releaser-action/issues/6
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@v4
|
||||
uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4
|
||||
with:
|
||||
version: v3.6.3
|
||||
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
helm lint ./nextcloud-aio-helm-chart
|
||||
|
||||
- name: Run chart-releaser
|
||||
uses: helm/chart-releaser-action@v1.7.0
|
||||
uses: helm/chart-releaser-action@cae68fefc6b5f367a0275617c9f83181ba54714f # v1.7.0
|
||||
with:
|
||||
mark_as_latest: false
|
||||
charts_dir: .
|
||||
|
||||
2
.github/workflows/imaginary-update.yml
vendored
2
.github/workflows/imaginary-update.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
sed -i "s|^ENV IMAGINARY_HASH.*$|ENV IMAGINARY_HASH=$imaginary_version|" ./Containers/imaginary/Dockerfile
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
|
||||
with:
|
||||
commit-message: imaginary-update automated change
|
||||
signoff: true
|
||||
|
||||
2
.github/workflows/lint-helm.yml
vendored
2
.github/workflows/lint-helm.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Helm
|
||||
uses: azure/setup-helm@v4
|
||||
uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4
|
||||
with:
|
||||
version: v3.11.1
|
||||
|
||||
|
||||
2
.github/workflows/lint-php.yml
vendored
2
.github/workflows/lint-php.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # v2
|
||||
uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
coverage: none
|
||||
|
||||
2
.github/workflows/lock-threads.yml
vendored
2
.github/workflows/lock-threads.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
action:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v5
|
||||
- uses: dessant/lock-threads@1bf7ec25051fe7c00bdd17e6a7cf3d7bfb7dc771 # v5
|
||||
with:
|
||||
issue-inactive-days: '14'
|
||||
process-only: 'issues'
|
||||
|
||||
2
.github/workflows/nextcloud-update.yml
vendored
2
.github/workflows/nextcloud-update.yml
vendored
@@ -85,7 +85,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
|
||||
with:
|
||||
commit-message: nextcloud-update automated change
|
||||
signoff: true
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up php
|
||||
uses: shivammathur/setup-php@v2
|
||||
uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2
|
||||
with:
|
||||
php-version: 8.3
|
||||
extensions: apcu
|
||||
|
||||
77
.github/workflows/playwright.yml
vendored
Normal file
77
.github/workflows/playwright.yml
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
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@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
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 && DEBUG=pw:api npx playwright test tests/initial-setup.spec.js
|
||||
|
||||
- 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 && DEBUG=pw:api npx playwright test tests/restore-instance.spec.js
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: playwright-report
|
||||
path: php/tests/playwright-report/
|
||||
retention-days: 14
|
||||
overwrite: true
|
||||
4
.github/workflows/psalm-update-baseline.yml
vendored
4
.github/workflows/psalm-update-baseline.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up php
|
||||
uses: shivammathur/setup-php@v2
|
||||
uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2
|
||||
with:
|
||||
php-version: 8.3
|
||||
extensions: apcu
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
continue-on-error: true
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
|
||||
with:
|
||||
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||
commit-message: Update psalm baseline
|
||||
|
||||
2
.github/workflows/psalm.yml
vendored
2
.github/workflows/psalm.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
|
||||
- name: Set up php
|
||||
uses: shivammathur/setup-php@a4e22b60bbb9c1021113f2860347b0759f66fe5d # v2
|
||||
uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2
|
||||
with:
|
||||
php-version: 8.3
|
||||
extensions: apcu
|
||||
|
||||
2
.github/workflows/shellcheck.yml
vendored
2
.github/workflows/shellcheck.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run Shellcheck
|
||||
uses: ludeeus/action-shellcheck@2.0.0
|
||||
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0
|
||||
with:
|
||||
check_together: 'yes'
|
||||
env:
|
||||
|
||||
2
.github/workflows/talk.yml
vendored
2
.github/workflows/talk.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
||||
sed -i "s|^ARG JANUS_VERSION=.*$|ARG JANUS_VERSION=$janus_version|" ./Containers/talk/Dockerfile
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
|
||||
with:
|
||||
commit-message: talk-update automated change
|
||||
signoff: true
|
||||
|
||||
2
.github/workflows/twig-lint.yml
vendored
2
.github/workflows/twig-lint.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@v2
|
||||
uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2
|
||||
with:
|
||||
php-version: 8.3
|
||||
extensions: apcu
|
||||
|
||||
7
.github/workflows/update-helm.yml
vendored
7
.github/workflows/update-helm.yml
vendored
@@ -14,13 +14,16 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
- name: update helm chart
|
||||
run: |
|
||||
DOCKER_TAG="$(curl -L -s 'https://registry.hub.docker.com/v2/repositories/nextcloud/all-in-one/tags?page_size=1024' | jq '."results"[]["name"]' | sed 's|"||g' | grep '^20[0-9_]\+' | grep -v latest | sort -r | head -1)"
|
||||
set -x
|
||||
GHCR_TOKEN="$(curl https://ghcr.io/token?scope=repository:nextcloud-releases/nce-php-fpm-mgmt:pull | jq '.token' | sed 's|"||g')"
|
||||
DOCKER_TAG="$(curl -H "Authorization: Bearer ${GHCR_TOKEN}" -L -s 'https://ghcr.io/v2/nextcloud-releases/all-in-one/tags/list?page_size=1024' | jq '.tags' | sed 's|"||g;s|[[:space:]]||g' | grep '^20[0-9_]\+' | grep -v latest | sort -r | head -1)"
|
||||
export DOCKER_TAG
|
||||
set +x
|
||||
if [ -n "$DOCKER_TAG" ] && ! grep -q "$DOCKER_TAG" ./nextcloud-aio-helm-chart/templates/nextcloud-aio-nextcloud-deployment.yaml; then
|
||||
sudo bash nextcloud-aio-helm-chart/update-helm.sh "$DOCKER_TAG"
|
||||
fi
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
|
||||
with:
|
||||
commit-message: Helm Chart updates
|
||||
signoff: true
|
||||
|
||||
2
.github/workflows/update-yaml.yml
vendored
2
.github/workflows/update-yaml.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
run: |
|
||||
sudo bash manual-install/update-yaml.sh
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
|
||||
with:
|
||||
commit-message: Yaml updates
|
||||
signoff: true
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
# Probably from this file: https://github.com/Cisco-Talos/clamav-docker/blob/main/clamav/1.3/alpine/Dockerfile
|
||||
FROM clamav/clamav:1.4.2-28
|
||||
|
||||
COPY clamav.conf /clamav.conf
|
||||
COPY --chmod=775 start.script /start.script
|
||||
FROM alpine:3.21.3
|
||||
|
||||
RUN set -ex; \
|
||||
apk upgrade --no-cache -a; \
|
||||
apk add --no-cache tzdata bash; \
|
||||
mkdir -p /var/run/clamav /run/lock; \
|
||||
chown -R clamav:clamav /var/run/clamav /run/clamav /var/log/clamav /var/lock /run/lock; \
|
||||
chmod 777 -R /var/run/clamav /run/clamav /var/log/clamav /var/lock /run/lock /tmp; \
|
||||
sed -i "/^set -eu/r /start.script" /init-unprivileged; \
|
||||
rm /start.script; \
|
||||
grep -q 'clamd --foreground &' /init-unprivileged; \
|
||||
sed -i "s|clamd --foreground \&|clamd --foreground --config-file /tmp/clamd.conf \&|" /init-unprivileged; \
|
||||
cat /init-unprivileged
|
||||
apk add --no-cache tzdata clamav supervisor bash; \
|
||||
mkdir -p /run/clamav /var/log/supervisord /var/run/supervisord; \
|
||||
chmod 777 -R /run/clamav /var/log/clamav /var/log/supervisord /var/run/supervisord; \
|
||||
sed -i "s|#\?MaxDirectoryRecursion.*|MaxDirectoryRecursion 30|g" /etc/clamav/clamd.conf; \
|
||||
sed -i "s|#\?MaxFileSize.*|MaxFileSize 2G|g" /etc/clamav/clamd.conf; \
|
||||
sed -i "s|#\?PCREMaxFileSize.*|PCREMaxFileSize aio-placeholder|g" /etc/clamav/clamd.conf; \
|
||||
sed -i "s|#\?StreamMaxLength.*|StreamMaxLength aio-placeholder|g" /etc/clamav/clamd.conf; \
|
||||
sed -i "s|#\?TCPSocket|TCPSocket|g" /etc/clamav/clamd.conf; \
|
||||
freshclam --foreground --stdout
|
||||
|
||||
VOLUME /var/lib/clamav
|
||||
COPY --chmod=775 start.sh /start.sh
|
||||
COPY --chmod=775 healthcheck.sh /healthcheck.sh
|
||||
COPY --chmod=664 supervisord.conf /supervisord.conf
|
||||
|
||||
USER 100
|
||||
|
||||
VOLUME /var/lib/clamav
|
||||
ENTRYPOINT ["/start.sh"]
|
||||
CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"]
|
||||
LABEL com.centurylinklabs.watchtower.enable="false"
|
||||
|
||||
HEALTHCHECK --start-period=60s --retries=9 CMD clamdcheck.sh
|
||||
|
||||
ENTRYPOINT ["/init-unprivileged"]
|
||||
HEALTHCHECK --start-period=60s --retries=9 CMD /healthcheck.sh
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# AIO settings
|
||||
MaxDirectoryRecursion 30
|
||||
MaxFileSize 16G
|
||||
PCREMaxFileSize 16G
|
||||
StreamMaxLength 16G
|
||||
9
Containers/clamav/healthcheck.sh
Normal file
9
Containers/clamav/healthcheck.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$(echo "PING" | nc 127.0.0.1 3310)" != "PONG" ]; then
|
||||
echo "ERROR: Unable to contact server"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Clamd is up"
|
||||
exit 0
|
||||
@@ -1,4 +0,0 @@
|
||||
# Adjust settings
|
||||
cat /etc/clamav/clamd.conf > /tmp/clamd.conf
|
||||
CLAMAV_FILE="$(sed "s|16G|$MAX_SIZE|" /clamav.conf)"
|
||||
echo "$CLAMAV_FILE" >> /tmp/clamd.conf
|
||||
7
Containers/clamav/start.sh
Normal file
7
Containers/clamav/start.sh
Normal file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
sed "s|aio-placeholder|$MAX_SIZE|" /etc/clamav/clamd.conf > /tmp/clamd.conf
|
||||
|
||||
echo "Clamav started"
|
||||
|
||||
exec "$@"
|
||||
23
Containers/clamav/supervisord.conf
Normal file
23
Containers/clamav/supervisord.conf
Normal file
@@ -0,0 +1,23 @@
|
||||
[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
|
||||
|
||||
[program:clamd]
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
command=clamd --foreground --config-file=/tmp/clamd.conf
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM haproxy:3.1.5-alpine
|
||||
FROM haproxy:3.1.6-alpine
|
||||
|
||||
# hadolint ignore=DL3002
|
||||
USER root
|
||||
|
||||
@@ -13,7 +13,7 @@ frontend http
|
||||
bind :::2375 v4v6
|
||||
http-request deny unless { src 127.0.0.1 } || { src ::1 } || { src NC_IPV4_PLACEHOLDER } || { src NC_IPV6_PLACEHOLDER }
|
||||
# docker system _ping
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/_ping } METH_GET
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/_ping$ } METH_GET
|
||||
# container inspect: GET containers/%s/json
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/nc_app_[a-zA-Z0-9_.-]+/json } METH_GET
|
||||
# container inspect: GET containers/%s/logs
|
||||
@@ -38,19 +38,19 @@ frontend http
|
||||
# ACL to deny if there are any binds
|
||||
acl binds_present req.body -m reg -i "\"HostConfig\"\s*:.*\"Binds\"\s*:"
|
||||
# ACL to restrict the type of Mounts to volume
|
||||
acl type_not_volume req.body -m reg -i "\"Mounts\":\s*\[[^\]]*(\"Type\":\s*\"(?!volume\b)\w+\"[^\]]*)+\]"
|
||||
acl type_not_volume req.body -m reg -i "\"Mounts\"\s*:\s*\[[^\]]*(\"Type\"\s*:\s*\"(?!volume\b)\w+\"[^\]]*)+\]"
|
||||
http-request deny if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/create } nc_app_container_name !one_mount_volume binds_present type_not_volume METH_POST
|
||||
|
||||
# ACL to restrict container creation, that it has HostConfig.Privileged not set
|
||||
acl no_privileged_flag req.body -m reg -i "\"HostConfig\":\s?{[^}]*\"Privileged\""
|
||||
# ACL to restrict container creation, that it has HostConfig.Privileged(by searching for "Privileged" word in all payload)
|
||||
acl no_privileged_flag req.body -m reg -i "\"Privileged\""
|
||||
# ACL to allow mount volume with strict pattern for name: nc_app_[a-zA-Z0-9_.-]+_data
|
||||
acl nc_app_volume_data_only req.body -m reg -i "\"Mounts\":\s?\[\s?{[^}]*\"Source\":\s?\"nc_app_[a-zA-Z0-9_.-]+_data\""
|
||||
acl nc_app_volume_data_only req.body -m reg -i "\"Mounts\"\s*:\s*\[\s*{[^}]*\"Source\"\s*:\s*\"nc_app_[a-zA-Z0-9_.-]+_data\""
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers/create } nc_app_container_name !no_privileged_flag nc_app_volume_data_only METH_POST
|
||||
# end of container create
|
||||
|
||||
# volume create: POST volumes/create
|
||||
# restrict name
|
||||
acl nc_app_volume_data req.body -m reg -i "\"Name\":\s?\"nc_app_[a-zA-Z0-9_.-]+_data\""
|
||||
acl nc_app_volume_data req.body -m reg -i "\"Name\"\s*:\s*\"nc_app_[a-zA-Z0-9_.-]+_data\""
|
||||
# do not allow to use "device" word e.g., "--opt device=:/path/to/dir"
|
||||
acl volume_no_device req.body -m reg -i "\"device\""
|
||||
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/volumes/create } nc_app_volume_data !volume_no_device METH_POST
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
# Probably from here https://github.com/elastic/elasticsearch/blob/main/distribution/docker/src/docker/Dockerfile
|
||||
FROM elasticsearch:8.17.2
|
||||
FROM elasticsearch:8.17.3
|
||||
|
||||
USER root
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM golang:1.24.0-alpine3.21 AS go
|
||||
FROM golang:1.24.1-alpine3.21 AS go
|
||||
|
||||
ENV IMAGINARY_HASH=1d4e251cfcd58ea66f8361f8721d7b8cc85002a3
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
# Docker CLI is a requirement
|
||||
FROM docker:28.0.1-cli AS docker
|
||||
FROM docker:28.0.2-cli AS docker
|
||||
|
||||
# Caddy is a requirement
|
||||
FROM caddy:2.9.1-alpine AS caddy
|
||||
|
||||
# From https://github.com/docker-library/php/blob/master/8.3/alpine3.21/fpm/Dockerfile
|
||||
FROM php:8.3.17-fpm-alpine3.21
|
||||
FROM php:8.3.19-fpm-alpine3.21
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 8080
|
||||
@@ -66,6 +66,7 @@ RUN set -ex; \
|
||||
cd /var/www/docker-aio; \
|
||||
git clone https://github.com/nextcloud-releases/all-in-one.git --depth 1 .; \
|
||||
find ./ -maxdepth 1 -mindepth 1 -not -path ./php -not -path ./community-containers -exec rm -r {} \; ; \
|
||||
rm -r ./php/tests; \
|
||||
chown www-data:www-data -R /var/www/docker-aio; \
|
||||
cd php; \
|
||||
sudo -u www-data composer install --no-dev; \
|
||||
|
||||
@@ -283,10 +283,10 @@ if [ "$?" = 6 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if auth.docker.io is reachable
|
||||
# Check if ghcr.io is reachable
|
||||
# Solves issues like https://github.com/nextcloud/all-in-one/discussions/5268
|
||||
if ! curl https://auth.docker.io/token 2>&1 | grep -q token; then
|
||||
print_red "Could not reach https://auth.docker.io."
|
||||
if ! curl https://ghcr.io &>/dev/null; then
|
||||
print_red "Could not reach https://ghcr.io."
|
||||
echo "Most likely is something blocking access to it."
|
||||
echo "You should be able to fix this by using https://github.com/nextcloud/all-in-one/tree/main/manual-install"
|
||||
exit 1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM php:8.3.17-fpm-alpine3.21
|
||||
FROM php:8.3.19-fpm-alpine3.21
|
||||
|
||||
ENV PHP_MEMORY_LIMIT=512M
|
||||
ENV PHP_UPLOAD_LIMIT=16G
|
||||
@@ -8,7 +8,7 @@ ENV SOURCE_LOCATION=/usr/src/nextcloud
|
||||
ENV REDIS_DB_INDEX=0
|
||||
|
||||
# AIO settings start # Do not remove or change this line!
|
||||
ENV NEXTCLOUD_VERSION=30.0.6
|
||||
ENV NEXTCLOUD_VERSION=30.0.8
|
||||
ENV AIO_TOKEN=123456
|
||||
ENV AIO_URL=localhost
|
||||
# AIO settings end # Do not remove or change this line!
|
||||
@@ -142,7 +142,7 @@ RUN set -ex; \
|
||||
echo 'post_max_size=${PHP_UPLOAD_LIMIT}'; \
|
||||
echo 'max_execution_time=${PHP_MAX_TIME}'; \
|
||||
echo 'max_input_time=${PHP_MAX_TIME}'; \
|
||||
echo 'default_socket_timeout=600'; \
|
||||
echo 'default_socket_timeout=${PHP_MAX_TIME}'; \
|
||||
} > /usr/local/etc/php/conf.d/nextcloud.ini; \
|
||||
\
|
||||
{ \
|
||||
|
||||
@@ -33,7 +33,7 @@ while ! nc -z "$REDIS_HOST" "6379"; do
|
||||
done
|
||||
|
||||
# Check permissions in ncdata
|
||||
touch "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" &>/dev/null
|
||||
touch "$NEXTCLOUD_DATA_DIR/this-is-a-test-file"
|
||||
if ! [ -f "$NEXTCLOUD_DATA_DIR/this-is-a-test-file" ]; then
|
||||
echo "The www-data user doesn't seem to have access rights in the datadir.
|
||||
Most likely are the files located on a drive that does not follow linux permissions.
|
||||
@@ -535,6 +535,13 @@ php /var/www/html/occ config:system:set upgrade.cli-upgrade-link --value="https:
|
||||
php /var/www/html/occ config:system:set logfile --value="/var/www/html/data/nextcloud.log"
|
||||
php /var/www/html/occ config:app:set admin_audit logfile --value="/var/www/html/data/audit.log"
|
||||
php /var/www/html/occ config:system:set updatedirectory --value="/nc-updater"
|
||||
if [ -n "$NEXTCLOUD_SKELETON_DIRECTORY" ]; then
|
||||
if [ "$NEXTCLOUD_SKELETON_DIRECTORY" = "empty" ]; then
|
||||
php /var/www/html/occ config:system:set skeletondirectory --value=""
|
||||
else
|
||||
php /var/www/html/occ config:system:set skeletondirectory --value="$NEXTCLOUD_SKELETON_DIRECTORY"
|
||||
fi
|
||||
fi
|
||||
if [ -n "$SERVERINFO_TOKEN" ] && [ -z "$(php /var/www/html/occ config:app:get serverinfo token)" ]; then
|
||||
php /var/www/html/occ config:app:set serverinfo token --value="$SERVERINFO_TOKEN"
|
||||
fi
|
||||
|
||||
@@ -60,8 +60,14 @@ elif [ "$DATABASE_TYPE" != postgres ] && [ "$DATABASE_TYPE" != mysql ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Use the correct Postgres username
|
||||
if [ "$POSTGRES_USER" = nextcloud ]; then
|
||||
POSTGRES_USER="oc_$POSTGRES_USER"
|
||||
export POSTGRES_USER
|
||||
fi
|
||||
|
||||
# Set sensitive values as env
|
||||
export DATABASE_URL="$DATABASE_TYPE://oc_$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB"
|
||||
export DATABASE_URL="$DATABASE_TYPE://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB"
|
||||
export REDIS_URL="redis://$REDIS_USER:$REDIS_HOST_PASSWORD@$REDIS_HOST/$REDIS_DB_INDEX"
|
||||
|
||||
# Run it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
# From https://github.com/ONLYOFFICE/Docker-DocumentServer/blob/master/Dockerfile
|
||||
FROM onlyoffice/documentserver:8.3.1.1
|
||||
FROM onlyoffice/documentserver:8.3.2.1
|
||||
|
||||
# USER root is probably used
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM nats:2.10.26-scratch AS nats
|
||||
FROM nats:2.11.0-scratch AS nats
|
||||
FROM eturnal/eturnal:1.12.1 AS eturnal
|
||||
FROM strukturag/nextcloud-spreed-signaling:2.0.2 AS signaling
|
||||
FROM alpine:3.21.3 AS janus
|
||||
|
||||
ARG JANUS_VERSION=v1.3.0
|
||||
ARG JANUS_VERSION=v1.3.1
|
||||
WORKDIR /src
|
||||
RUN set -ex; \
|
||||
apk add --no-cache \
|
||||
|
||||
@@ -5,7 +5,8 @@ FROM ghcr.io/nextcloud-releases/whiteboard:v1.0.5
|
||||
USER root
|
||||
RUN set -ex; \
|
||||
apk upgrade --no-cache -a; \
|
||||
apk add --no-cache bash
|
||||
apk add --no-cache bash; \
|
||||
chmod 777 -R /tmp
|
||||
USER 65534
|
||||
|
||||
COPY --chmod=775 start.sh /start.sh
|
||||
|
||||
12
community-containers/helloworld/helloworld.json
Normal file
12
community-containers/helloworld/helloworld.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"aio_services_v1": [
|
||||
{
|
||||
"container_name": "nextcloud-aio-helloworld",
|
||||
"display_name": "Hello world",
|
||||
"documentation": "https://github.com/nextcloud/all-in-one/tree/main/community-containers/helloworld",
|
||||
"image": "ghcr.io/docjyj/aio-helloworld",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"restart": "unless-stopped"
|
||||
}
|
||||
]
|
||||
}
|
||||
8
community-containers/helloworld/readme.md
Normal file
8
community-containers/helloworld/readme.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## Hello World
|
||||
This container is a template for creating a community container.
|
||||
|
||||
### Repository
|
||||
https://github.com/docjyj/aio-helloworld
|
||||
|
||||
### Maintainer
|
||||
https://github.com/docjyj
|
||||
12
community-containers/mollysocket/readme.md
Normal file
12
community-containers/mollysocket/readme.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## MollySocket
|
||||
This container bundles MollySocket and auto-configures it for you.
|
||||
|
||||
### Notes
|
||||
- This container is only intended to be used over https behind a reverse proxy. You can You can set up a reverse proxy following [these instructions](https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md) OR use the Caddy community container that will automatically configure mollysocket.$NC_DOMAIN to redirect to your MollySocket.
|
||||
- See [here](https://github.com/nextcloud/all-in-one/tree/main/community-containers#community-containers) how to add it to the AIO stack.
|
||||
|
||||
### Repository
|
||||
https://github.com/mollyim/mollysocket
|
||||
|
||||
### Maintainer
|
||||
https://github.com/Anvil5465
|
||||
@@ -4,8 +4,8 @@
|
||||
"container_name": "nextcloud-aio-nocodb",
|
||||
"display_name": "NocoDB",
|
||||
"documentation": "https://github.com/nextcloud/all-in-one/tree/main/community-containers/nocodb",
|
||||
"image": "docjyj/aio-nocodb",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"image": "nocodb/nocodb",
|
||||
"image_tag": "latest",
|
||||
"internal_port": "10028",
|
||||
"restart": "unless-stopped",
|
||||
"ports": [
|
||||
|
||||
@@ -22,7 +22,7 @@ This is an alternative of **Airtable**.
|
||||
- See https://github.com/nextcloud/all-in-one/tree/main/community-containers#community-containers how to add it to the AIO stack
|
||||
|
||||
### Repository
|
||||
https://github.com/docjyJ/aio-nocodb
|
||||
https://github.com/nocodb/nocodb
|
||||
|
||||
### Maintainer
|
||||
https://github.com/docjyJ
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"container_name": "nextcloud-aio-npmplus",
|
||||
"display_name": "NPMplus",
|
||||
"documentation": "https://github.com/nextcloud/all-in-one/tree/main/community-containers/npmplus",
|
||||
"image": "zoeyvid/npmplus",
|
||||
"image": "ghcr.io/zoeyvid/npmplus",
|
||||
"image_tag": "latest",
|
||||
"internal_port": "host",
|
||||
"restart": "unless-stopped",
|
||||
|
||||
15
community-containers/smbserver/readme.md
Normal file
15
community-containers/smbserver/readme.md
Normal file
@@ -0,0 +1,15 @@
|
||||
## SMB-server
|
||||
This container bundles an SMB-server and allows to configure it via a graphical shell script.
|
||||
|
||||
### Notes
|
||||
- This container should only be run in home networks
|
||||
- This container currently only works on amd64. See https://github.com/szaimen/aio-smbserver/issues/3
|
||||
- After adding and starting the container, you need to visit `https://internal.ip.of.server:5803` in order to log in with the `smbserver` user and the password that you can see next to the container in the AIO interface. (The web page uses a self-signed certificate, so you need to accept the warning). Then type in `bash /smbserver.sh` and you will see a graphical UI for configuring the smb-server interactively.
|
||||
- The config data of SMB-server will be automatically included in AIOs backup solution!
|
||||
- See https://github.com/nextcloud/all-in-one/tree/main/community-containers#community-containers how to add it to the AIO stack
|
||||
|
||||
### Repository
|
||||
https://github.com/szaimen/aio-smbserver/
|
||||
|
||||
### Maintainer
|
||||
https://github.com/szaimen
|
||||
60
community-containers/smbserver/smbserver.json
Normal file
60
community-containers/smbserver/smbserver.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"aio_services_v1": [
|
||||
{
|
||||
"container_name": "nextcloud-aio-smbserver",
|
||||
"display_name": "SMB-server",
|
||||
"documentation": "https://github.com/nextcloud/all-in-one/tree/main/community-containers/smbserver",
|
||||
"image": "szaimen/aio-smbserver",
|
||||
"image_tag": "v1",
|
||||
"internal_port": "5803",
|
||||
"restart": "unless-stopped",
|
||||
"ports": [
|
||||
{
|
||||
"ip_binding": "",
|
||||
"port_number": "5803",
|
||||
"protocol": "tcp"
|
||||
},
|
||||
{
|
||||
"ip_binding": "",
|
||||
"port_number": "445",
|
||||
"protocol": "tcp"
|
||||
},
|
||||
{
|
||||
"ip_binding": "",
|
||||
"port_number": "139",
|
||||
"protocol": "tcp"
|
||||
}
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
"source": "nextcloud_aio_smbserver",
|
||||
"destination": "/smbserver",
|
||||
"writeable": true
|
||||
},
|
||||
{
|
||||
"source": "%NEXTCLOUD_DATADIR%",
|
||||
"destination": "/mnt/ncdata",
|
||||
"writeable": true
|
||||
},
|
||||
{
|
||||
"source": "%NEXTCLOUD_MOUNT%",
|
||||
"destination": "/mnt",
|
||||
"writeable": true
|
||||
}
|
||||
],
|
||||
"environment": [
|
||||
"TZ=%TIMEZONE%",
|
||||
"WEB_AUTHENTICATION_USERNAME=smbserver",
|
||||
"WEB_AUTHENTICATION_PASSWORD=%SMBSERVER_PASSWORD%",
|
||||
"WEB_LISTENING_PORT=5803"
|
||||
],
|
||||
"secrets": [
|
||||
"SMBSERVER_PASSWORD"
|
||||
],
|
||||
"ui_secret": "SMBSERVER_PASSWORD",
|
||||
"backup_volumes": [
|
||||
"nextcloud_aio_smbserver"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -4,8 +4,8 @@
|
||||
"container_name": "nextcloud-aio-stalwart",
|
||||
"display_name": "Stalwart",
|
||||
"documentation": "https://github.com/nextcloud/all-in-one/tree/main/community-containers/stalwart",
|
||||
"image": "docjyj/aio-stalwart",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"image": "ghcr.io/docjyj/aio-stalwart",
|
||||
"image_tag": "v3",
|
||||
"internal_port": "10003",
|
||||
"restart": "unless-stopped",
|
||||
"ports": [
|
||||
|
||||
@@ -11,7 +11,7 @@ sudo docker run \
|
||||
--publish 8443:8443 \
|
||||
--volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
|
||||
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
|
||||
nextcloud/all-in-one:develop
|
||||
ghcr.io/nextcloud-releases/all-in-one:develop
|
||||
```
|
||||
And you are done :)
|
||||
It will now also select the developer channel for all other containers automatically.
|
||||
@@ -19,6 +19,9 @@ It will now also select the developer channel for all other containers automatic
|
||||
## How to publish new releases?
|
||||
Simply use https://github.com/nextcloud/all-in-one/issues/180 as template.
|
||||
|
||||
## How to update existing instances to a new major Nextcloud version?
|
||||
Simply use https://github.com/nextcloud/all-in-one/issues/6198 as template.
|
||||
|
||||
## How to build new containers
|
||||
Go to https://github.com/nextcloud-releases/all-in-one/actions/workflows/repo-sync.yml and run the workflow that will first sync the repo and then build new container that automatically get published to `develop` and `develop-arm64`.
|
||||
|
||||
@@ -27,6 +30,8 @@ Before testing, make sure that at least the amd64 containers are built successfu
|
||||
|
||||
There is a testing-VM available for the maintainer of AIO that allows for some final testing before releasing new version. See [this](https://cloud.nextcloud.com/apps/collectives/Nextcloud%20Handbook/Technical/AIO%20testing%20VM?fileId=6350152) for details.
|
||||
|
||||
Additionally, there are now E2E tests available that can be run via https://github.com/nextcloud/all-in-one/actions/workflows/playwright.yml
|
||||
|
||||
## How to promote builds from develop to beta
|
||||
1. Verify that no job is running here: https://github.com/nextcloud-releases/all-in-one/actions/workflows/build_images.yml
|
||||
2. Go to https://github.com/nextcloud-releases/all-in-one/actions/workflows/promote-to-beta.yml, click on `Run workflow`.
|
||||
|
||||
@@ -341,7 +341,7 @@ services:
|
||||
init: false
|
||||
healthcheck:
|
||||
start_period: 60s
|
||||
test: clamdcheck.sh
|
||||
test: /healthcheck.sh
|
||||
interval: 30s
|
||||
timeout: 30s
|
||||
start_interval: 5s
|
||||
@@ -351,7 +351,6 @@ services:
|
||||
environment:
|
||||
- TZ=${TIMEZONE}
|
||||
- MAX_SIZE=${NEXTCLOUD_UPLOAD_LIMIT}
|
||||
- CLAMD_STARTUP_TIMEOUT=90
|
||||
volumes:
|
||||
- nextcloud_aio_clamav:/var/lib/clamav:rw
|
||||
restart: unless-stopped
|
||||
@@ -359,9 +358,11 @@ services:
|
||||
- clamav
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /var/lock
|
||||
- /var/log/clamav
|
||||
- /tmp
|
||||
- /var/log/clamav
|
||||
- /run/clamav
|
||||
- /var/log/supervisord
|
||||
- /var/run/supervisord
|
||||
cap_drop:
|
||||
- NET_RAW
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ First, install docker and docker-compose (v2) if not already done. Then simply r
|
||||
git clone https://github.com/nextcloud/all-in-one.git
|
||||
cd all-in-one/manual-install
|
||||
```
|
||||
Then copy the sample.conf to default environment file, e.g. `cp sample.conf .env`, open the new conf file, e.g. with `nano .env`, edit all values that are marked with `# TODO!`, close and save the file. (Note: there is no clamav image for arm64).<br>
|
||||
Then copy the sample.conf to default environment file, e.g. `cp sample.conf .env`, open the new conf file, e.g. with `nano .env`, edit all values that are marked with `# TODO!`, close and save the file.<br>
|
||||
⚠️ **Warning**: Do not use the symbols `@` and `:` in your passwords. These symbols are used to build database connection strings. You will experience issues when using these symbols! Also please note that values inside the latest.yaml that are not exposed as variables are not officially supported to be changed. See for example [this report](https://github.com/nextcloud/all-in-one/issues/5612).
|
||||
|
||||
Now copy the provided yaml file to a compose.yaml file by running `cp latest.yml compose.yaml`.
|
||||
@@ -32,9 +32,9 @@ Now copy the provided yaml file to a compose.yaml file by running `cp latest.yml
|
||||
Now you should be ready to go with `sudo docker compose up`.
|
||||
|
||||
## Docker profiles
|
||||
The default profile of `latest.yml` only provide the minimum necessary services: nextcloud, database, redis and apache. To get optional services collabora, talk, whiteboard, talk-recording, clamav, imaginary or fulltextsearch use additional arguments for each of them, for example `--profile collabora`. (Note: there is no clamav image for arm64).
|
||||
The default profile of `latest.yml` only provide the minimum necessary services: nextcloud, database, redis and apache. To get optional services collabora, talk, whiteboard, talk-recording, clamav, imaginary or fulltextsearch use additional arguments for each of them, for example `--profile collabora`.
|
||||
|
||||
For a complete all-in-one with collabora use `sudo docker compose --profile collabora --profile talk --profile talk-recording --profile clamav --profile imaginary --profile fulltextsearch --profile whiteboard up`. (Note: there is no clamav image for arm64).
|
||||
For a complete all-in-one with collabora use `sudo docker compose --profile collabora --profile talk --profile talk-recording --profile clamav --profile imaginary --profile fulltextsearch --profile whiteboard up`.
|
||||
|
||||
## How to update?
|
||||
Since the AIO containers may change in the future, it is highly recommended to strictly follow the following procedure whenever you want to upgrade your containers.
|
||||
|
||||
@@ -75,7 +75,7 @@ do
|
||||
done
|
||||
|
||||
sed -i 's|_ENABLED=|_ENABLED="no" # Setting this to "yes" (with quotes) enables the option in Nextcloud automatically.|' sample.conf
|
||||
sed -i 's|CLAMAV_ENABLED=no.*|CLAMAV_ENABLED="no" # Setting this to "yes" (with quotes) enables the option in Nextcloud automatically. Note: arm64 has no clamav support|' sample.conf
|
||||
sed -i 's|CLAMAV_ENABLED=no.*|CLAMAV_ENABLED="no" # Setting this to "yes" (with quotes) enables the option in Nextcloud automatically.|' sample.conf
|
||||
sed -i 's|TALK_ENABLED=no|TALK_ENABLED="yes"|' sample.conf
|
||||
sed -i 's|COLLABORA_ENABLED=no|COLLABORA_ENABLED="yes"|' sample.conf
|
||||
sed -i 's|COLLABORA_DICTIONARIES=|COLLABORA_DICTIONARIES="de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru" # You can change this in order to enable other dictionaries for collabora|' sample.conf
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: nextcloud-aio-helm-chart
|
||||
description: A generated Helm Chart for Nextcloud AIO from Skippbox Kompose
|
||||
version: 10.6.1
|
||||
version: 10.9.0
|
||||
apiVersion: v2
|
||||
keywords:
|
||||
- latest
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
> [!NOTE]
|
||||
> For an enterprise-ready and scalable deployment method based on Helm Charts (also available for Podman), please [contact Nextcloud GmbH](https://nextcloud.com/enterprise/).
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This Helm-Chart is not intended to be used with Ingress as it handles TLS itself via the built-in apache container and exposes a Loadbalancer port itself on the Cluster. See the [apache service](https://github.com/nextcloud/all-in-one/blob/main/nextcloud-aio-helm-chart/templates/nextcloud-aio-apache-service.yaml). However if the Cluster is used behind NAT, you can adjust `APACHE_PORT` to a different one than 443 and do the TLS offloading on an external Reverse Proxy that forwards the traffic to the configured port via http. If you really need the Ingress feature, please [contact Nextcloud GmbH](https://nextcloud.com/enterprise/) as we offer an enterprise-ready and scalable deployment method based on Helm Charts that also allows Ingress to be used.
|
||||
|
||||
You can run the containers that are build for AIO with Kubernetes using this Helm chart. This comes with a few downsides, that are discussed below.
|
||||
|
||||
### Advantages
|
||||
|
||||
@@ -61,7 +61,7 @@ spec:
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
- name: WHITEBOARD_HOST
|
||||
value: nextcloud-aio-whiteboard
|
||||
image: nextcloud/aio-apache:20250225_125724
|
||||
image: nextcloud/aio-apache:20250325_084656
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -55,17 +55,15 @@ spec:
|
||||
{{- end }}
|
||||
containers:
|
||||
- env:
|
||||
- name: CLAMD_STARTUP_TIMEOUT
|
||||
value: "90"
|
||||
- name: MAX_SIZE
|
||||
value: "{{ .Values.NEXTCLOUD_UPLOAD_LIMIT }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: nextcloud/aio-clamav:20250225_125724
|
||||
image: nextcloud/aio-clamav:20250325_084656
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- clamdcheck.sh
|
||||
- /healthcheck.sh
|
||||
failureThreshold: 9
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 30
|
||||
@@ -73,7 +71,7 @@ spec:
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- clamdcheck.sh
|
||||
- /healthcheck.sh
|
||||
failureThreshold: 9
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 30
|
||||
|
||||
@@ -35,7 +35,7 @@ spec:
|
||||
value: --o:ssl.enable=false --o:ssl.termination=true --o:mount_jail_tree=false --o:logging.level=warning --o:home_mode.enable=true --o:remote_font_config.url=https://{{ .Values.NC_DOMAIN }}/apps/richdocuments/settings/fonts.json --o:net.post_allow.host[0]=.+
|
||||
- name: server_name
|
||||
value: "{{ .Values.NC_DOMAIN }}"
|
||||
image: nextcloud/aio-collabora:20250225_125724
|
||||
image: nextcloud/aio-collabora:20250325_084656
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -64,7 +64,7 @@ spec:
|
||||
value: nextcloud
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: nextcloud/aio-postgresql:20250225_125724
|
||||
image: nextcloud/aio-postgresql:20250325_084656
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -54,7 +54,7 @@ spec:
|
||||
value: basic
|
||||
- name: xpack.security.enabled
|
||||
value: "false"
|
||||
image: nextcloud/aio-fulltextsearch:20250225_125724
|
||||
image: nextcloud/aio-fulltextsearch:20250325_084656
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -38,7 +38,7 @@ spec:
|
||||
value: "{{ .Values.IMAGINARY_SECRET }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: nextcloud/aio-imaginary:20250225_125724
|
||||
image: nextcloud/aio-imaginary:20250325_084656
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -180,7 +180,7 @@ spec:
|
||||
value: "{{ .Values.WHITEBOARD_ENABLED }}"
|
||||
- name: WHITEBOARD_SECRET
|
||||
value: "{{ .Values.WHITEBOARD_SECRET }}"
|
||||
image: nextcloud/aio-nextcloud:20250225_125724
|
||||
image: nextcloud/aio-nextcloud:20250325_084656
|
||||
{{- if eq (.Values.RPSS_ENABLED | default "no") "yes" }} # AIO-config - do not change this comment!
|
||||
securityContext:
|
||||
# The items below only work in container context
|
||||
|
||||
@@ -55,7 +55,7 @@ spec:
|
||||
value: "{{ .Values.REDIS_PASSWORD }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: nextcloud/aio-notify-push:20250225_125724
|
||||
image: nextcloud/aio-notify-push:20250325_084656
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -42,7 +42,7 @@ spec:
|
||||
value: "{{ .Values.ONLYOFFICE_SECRET }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: nextcloud/aio-onlyoffice:20250225_125724
|
||||
image: nextcloud/aio-onlyoffice:20250325_084656
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -39,7 +39,7 @@ spec:
|
||||
value: "{{ .Values.REDIS_PASSWORD }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: nextcloud/aio-redis:20250225_125724
|
||||
image: nextcloud/aio-redis:20250325_084656
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -52,7 +52,7 @@ spec:
|
||||
value: "{{ .Values.TURN_SECRET }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: nextcloud/aio-talk:20250225_125724
|
||||
image: nextcloud/aio-talk:20250325_084656
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -44,7 +44,7 @@ spec:
|
||||
value: "{{ .Values.RECORDING_SECRET }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: nextcloud/aio-talk-recording:20250225_125724
|
||||
image: nextcloud/aio-talk-recording:20250325_084656
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -48,7 +48,7 @@ spec:
|
||||
value: redis
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: nextcloud/aio-whiteboard:20250225_125724
|
||||
image: nextcloud/aio-whiteboard:20250325_084656
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -302,6 +302,8 @@ cat << EOL > /tmp/additional.config
|
||||
value: "{{ .Values.SERVERINFO_TOKEN }}"
|
||||
- name: NEXTCLOUD_DEFAULT_QUOTA
|
||||
value: "{{ .Values.NEXTCLOUD_DEFAULT_QUOTA }}"
|
||||
- name: NEXTCLOUD_SKELETON_DIRECTORY
|
||||
value: "{{ .Values.NEXTCLOUD_SKELETON_DIRECTORY | default "" }}"
|
||||
- name: NEXTCLOUD_MAINTENANCE_WINDOW
|
||||
value: "{{ .Values.NEXTCLOUD_MAINTENANCE_WINDOW }}"
|
||||
EOL
|
||||
@@ -414,6 +416,7 @@ APPS_ALLOWLIST: # This allows to configure allowed apps that will be show
|
||||
ADDITIONAL_TRUSTED_PROXY: # Allows to add one additional ip-address to Nextcloud's trusted proxies and to the Office WOPI-allowlist automatically. Set it e.g. like this: 'your.public.ip-address'. You can also use an ip-range here.
|
||||
ADDITIONAL_TRUSTED_DOMAIN: # Allows to add one domain to Nextcloud's trusted domains and also generates a certificate automatically for it
|
||||
NEXTCLOUD_DEFAULT_QUOTA: "10 GB" # Allows to adjust the default quota that will be taken into account in Nextcloud for new users. Setting it to "unlimited" will set it to unlimited
|
||||
NEXTCLOUD_SKELETON_DIRECTORY: # Allows to adjust the sekeleton dir for Nextcloud. Setting it to "empty" will set the value to an empty string "" which will turn off the setting for new users in Nextcloud.
|
||||
NEXTCLOUD_MAINTENANCE_WINDOW: # Allows to define the maintenance window for Nextcloud. See https://docs.nextcloud.com/server/stable/admin_manual/configuration_server/background_jobs_configuration.html#parameters for possible values
|
||||
SMTP_HOST: # (empty by default): The hostname of the SMTP server.
|
||||
SMTP_SECURE: # (empty by default): Set to 'ssl' to use SSL, or 'tls' to use STARTTLS.
|
||||
|
||||
14
php/composer.lock
generated
14
php/composer.lock
generated
@@ -557,16 +557,16 @@
|
||||
},
|
||||
{
|
||||
"name": "php-di/php-di",
|
||||
"version": "7.0.8",
|
||||
"version": "7.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-DI/PHP-DI.git",
|
||||
"reference": "98ddc81f8f768a2ad39e4cbe737285eaeabe577a"
|
||||
"reference": "d8480267f5cf239650debba704f3ecd15b638cde"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/98ddc81f8f768a2ad39e4cbe737285eaeabe577a",
|
||||
"reference": "98ddc81f8f768a2ad39e4cbe737285eaeabe577a",
|
||||
"url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/d8480267f5cf239650debba704f3ecd15b638cde",
|
||||
"reference": "d8480267f5cf239650debba704f3ecd15b638cde",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -583,7 +583,7 @@
|
||||
"friendsofphp/proxy-manager-lts": "^1",
|
||||
"mnapoli/phpunit-easymock": "^1.3",
|
||||
"phpunit/phpunit": "^9.6",
|
||||
"vimeo/psalm": "^4.6"
|
||||
"vimeo/psalm": "^5|^6"
|
||||
},
|
||||
"suggest": {
|
||||
"friendsofphp/proxy-manager-lts": "Install it if you want to use lazy injection (version ^1)"
|
||||
@@ -614,7 +614,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHP-DI/PHP-DI/issues",
|
||||
"source": "https://github.com/PHP-DI/PHP-DI/tree/7.0.8"
|
||||
"source": "https://github.com/PHP-DI/PHP-DI/tree/7.0.9"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -626,7 +626,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-01-28T21:02:46+00:00"
|
||||
"time": "2025-02-28T12:46:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-di/slim-bridge",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"image": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"pattern": "^[a-z0-9/-]+$"
|
||||
"pattern": "^(ghcr.io/)?[a-z0-9/-]+$"
|
||||
},
|
||||
"expose": {
|
||||
"type": "array",
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"nextcloud-aio-whiteboard"
|
||||
],
|
||||
"display_name": "Apache",
|
||||
"image": "nextcloud/aio-apache",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-apache",
|
||||
"user": "33",
|
||||
"init": true,
|
||||
"healthcheck": {
|
||||
@@ -84,7 +84,7 @@
|
||||
"container_name": "nextcloud-aio-database",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"display_name": "Database",
|
||||
"image": "nextcloud/aio-postgresql",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-postgresql",
|
||||
"user": "999",
|
||||
"init": true,
|
||||
"healthcheck": {
|
||||
@@ -149,7 +149,7 @@
|
||||
"nextcloud-aio-docker-socket-proxy"
|
||||
],
|
||||
"display_name": "Nextcloud",
|
||||
"image": "nextcloud/aio-nextcloud",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-nextcloud",
|
||||
"init": true,
|
||||
"healthcheck": {
|
||||
"start_period": "0s",
|
||||
@@ -271,7 +271,7 @@
|
||||
"container_name": "nextcloud-aio-notify-push",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"display_name": "Notify Push",
|
||||
"image": "nextcloud/aio-notify-push",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-notify-push",
|
||||
"user": "33",
|
||||
"init": true,
|
||||
"healthcheck": {
|
||||
@@ -319,7 +319,7 @@
|
||||
"container_name": "nextcloud-aio-redis",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"display_name": "Redis",
|
||||
"image": "nextcloud/aio-redis",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-redis",
|
||||
"user": "999",
|
||||
"init": true,
|
||||
"healthcheck": {
|
||||
@@ -361,7 +361,7 @@
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"documentation": "https://github.com/nextcloud/all-in-one/discussions/1358",
|
||||
"display_name": "Collabora",
|
||||
"image": "nextcloud/aio-collabora",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-collabora",
|
||||
"init": true,
|
||||
"healthcheck": {
|
||||
"start_period": "60s",
|
||||
@@ -404,7 +404,7 @@
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"documentation": "https://github.com/nextcloud/all-in-one/discussions/1358",
|
||||
"display_name": "Talk",
|
||||
"image": "nextcloud/aio-talk",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-talk",
|
||||
"user": "1000",
|
||||
"init": true,
|
||||
"healthcheck": {
|
||||
@@ -466,7 +466,7 @@
|
||||
"container_name": "nextcloud-aio-talk-recording",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"display_name": "Talk Recording",
|
||||
"image": "nextcloud/aio-talk-recording",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-talk-recording",
|
||||
"user": "122",
|
||||
"init": true,
|
||||
"healthcheck": {
|
||||
@@ -518,7 +518,7 @@
|
||||
{
|
||||
"container_name": "nextcloud-aio-borgbackup",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"image": "nextcloud/aio-borgbackup",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-borgbackup",
|
||||
"init": true,
|
||||
"environment": [
|
||||
"BORG_REMOTE_REPO=%BORGBACKUP_REMOTE_REPO%",
|
||||
@@ -586,7 +586,7 @@
|
||||
{
|
||||
"container_name": "nextcloud-aio-watchtower",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"image": "nextcloud/aio-watchtower",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-watchtower",
|
||||
"init": true,
|
||||
"environment": [
|
||||
"CONTAINER_TO_UPDATE=nextcloud-aio-mastercontainer"
|
||||
@@ -606,7 +606,7 @@
|
||||
{
|
||||
"container_name": "nextcloud-aio-domaincheck",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"image": "nextcloud/aio-domaincheck",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-domaincheck",
|
||||
"init": true,
|
||||
"ports": [
|
||||
{
|
||||
@@ -637,12 +637,12 @@
|
||||
"container_name": "nextcloud-aio-clamav",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"display_name": "ClamAV",
|
||||
"image": "nextcloud/aio-clamav",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-clamav",
|
||||
"user": "100",
|
||||
"init": false,
|
||||
"healthcheck": {
|
||||
"start_period": "60s",
|
||||
"test": "clamdcheck.sh",
|
||||
"test": "/healthcheck.sh",
|
||||
"interval": "30s",
|
||||
"timeout": "30s",
|
||||
"start_interval": "5s",
|
||||
@@ -654,8 +654,7 @@
|
||||
"internal_port": "3310",
|
||||
"environment": [
|
||||
"TZ=%TIMEZONE%",
|
||||
"MAX_SIZE=%NEXTCLOUD_UPLOAD_LIMIT%",
|
||||
"CLAMD_STARTUP_TIMEOUT=90"
|
||||
"MAX_SIZE=%NEXTCLOUD_UPLOAD_LIMIT%"
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
@@ -670,9 +669,11 @@
|
||||
],
|
||||
"read_only": true,
|
||||
"tmpfs": [
|
||||
"/var/lock",
|
||||
"/tmp",
|
||||
"/var/log/clamav",
|
||||
"/tmp"
|
||||
"/run/clamav",
|
||||
"/var/log/supervisord",
|
||||
"/var/run/supervisord"
|
||||
],
|
||||
"cap_drop": [
|
||||
"NET_RAW"
|
||||
@@ -682,7 +683,7 @@
|
||||
"container_name": "nextcloud-aio-onlyoffice",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"display_name": "OnlyOffice",
|
||||
"image": "nextcloud/aio-onlyoffice",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-onlyoffice",
|
||||
"init": true,
|
||||
"healthcheck": {
|
||||
"start_period": "60s",
|
||||
@@ -728,7 +729,7 @@
|
||||
"container_name": "nextcloud-aio-imaginary",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"display_name": "Imaginary",
|
||||
"image": "nextcloud/aio-imaginary",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-imaginary",
|
||||
"user": "65534",
|
||||
"init": true,
|
||||
"healthcheck": {
|
||||
@@ -770,7 +771,7 @@
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"documentation": "https://github.com/nextcloud/all-in-one/discussions/1709",
|
||||
"display_name": "Fulltextsearch",
|
||||
"image": "nextcloud/aio-fulltextsearch",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-fulltextsearch",
|
||||
"init": false,
|
||||
"healthcheck": {
|
||||
"start_period": "60s",
|
||||
@@ -818,7 +819,7 @@
|
||||
"container_name": "nextcloud-aio-docker-socket-proxy",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"display_name": "Docker Socket Proxy",
|
||||
"image": "nextcloud/aio-docker-socket-proxy",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-docker-socket-proxy",
|
||||
"init": true,
|
||||
"internal_port": "2375",
|
||||
"environment": [
|
||||
@@ -844,7 +845,7 @@
|
||||
"container_name": "nextcloud-aio-whiteboard",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"display_name": "Whiteboard",
|
||||
"image": "nextcloud/aio-whiteboard",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-whiteboard",
|
||||
"user": "65534",
|
||||
"init": true,
|
||||
"healthcheck": {
|
||||
|
||||
@@ -102,7 +102,6 @@ $app->get('/containers', function (Request $request, Response $response, array $
|
||||
'last_backup_time' => $configurationManager->GetLastBackupTime(),
|
||||
'backup_times' => $configurationManager->GetBackupTimes(),
|
||||
'current_channel' => $dockerActionManger->GetCurrentChannel(),
|
||||
'is_x64_platform' => $configurationManager->isx64Platform(),
|
||||
'is_clamav_enabled' => $configurationManager->isClamavEnabled(),
|
||||
'is_onlyoffice_enabled' => $configurationManager->isOnlyofficeEnabled(),
|
||||
'is_collabora_enabled' => $configurationManager->isCollaboraEnabled(),
|
||||
|
||||
@@ -132,7 +132,7 @@ class ConfigurationManager
|
||||
}
|
||||
}
|
||||
|
||||
public function isx64Platform() : bool {
|
||||
private function isx64Platform() : bool {
|
||||
if (php_uname('m') === 'x86_64') {
|
||||
return true;
|
||||
} else {
|
||||
@@ -140,11 +140,7 @@ class ConfigurationManager
|
||||
}
|
||||
}
|
||||
|
||||
public function isClamavEnabled() : bool {
|
||||
if (!$this->isx64Platform()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isClamavEnabled() : bool {
|
||||
$config = $this->GetConfig();
|
||||
if (isset($config['isClamavEnabled']) && $config['isClamavEnabled'] === 1) {
|
||||
return true;
|
||||
@@ -904,7 +900,7 @@ class ConfigurationManager
|
||||
}
|
||||
|
||||
public function shouldDomainValidationBeSkipped() : bool {
|
||||
if (getenv('SKIP_DOMAIN_VALIDATION') !== false) {
|
||||
if (getenv('SKIP_DOMAIN_VALIDATION') === 'true') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace AIO;
|
||||
|
||||
use AIO\Docker\DockerHubManager;
|
||||
use DI\Container;
|
||||
use AIO\Docker\GitHubContainerRegistryManager;
|
||||
|
||||
class DependencyInjection
|
||||
{
|
||||
@@ -15,6 +16,11 @@ class DependencyInjection
|
||||
new DockerHubManager()
|
||||
);
|
||||
|
||||
$container->set(
|
||||
GitHubContainerRegistryManager::class,
|
||||
new GitHubContainerRegistryManager()
|
||||
);
|
||||
|
||||
$container->set(
|
||||
\AIO\Data\ConfigurationManager::class,
|
||||
new \AIO\Data\ConfigurationManager()
|
||||
@@ -24,7 +30,8 @@ class DependencyInjection
|
||||
new \AIO\Docker\DockerActionManager(
|
||||
$container->get(\AIO\Data\ConfigurationManager::class),
|
||||
$container->get(\AIO\ContainerDefinitionFetcher::class),
|
||||
$container->get(DockerHubManager::class)
|
||||
$container->get(DockerHubManager::class),
|
||||
$container->get(GitHubContainerRegistryManager::class)
|
||||
)
|
||||
);
|
||||
$container->set(
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
namespace AIO\Docker;
|
||||
|
||||
use AIO\Container\Container;
|
||||
use AIO\Container\VersionState;
|
||||
use AIO\Container\ContainerState;
|
||||
use AIO\Container\VersionState;
|
||||
use AIO\ContainerDefinitionFetcher;
|
||||
use AIO\Data\ConfigurationManager;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use AIO\ContainerDefinitionFetcher;
|
||||
use http\Env\Response;
|
||||
|
||||
readonly class DockerActionManager {
|
||||
@@ -16,18 +16,19 @@ readonly class DockerActionManager {
|
||||
private Client $guzzleClient;
|
||||
|
||||
public function __construct(
|
||||
private ConfigurationManager $configurationManager,
|
||||
private ContainerDefinitionFetcher $containerDefinitionFetcher,
|
||||
private DockerHubManager $dockerHubManager
|
||||
private ConfigurationManager $configurationManager,
|
||||
private ContainerDefinitionFetcher $containerDefinitionFetcher,
|
||||
private DockerHubManager $dockerHubManager,
|
||||
private GitHubContainerRegistryManager $gitHubContainerRegistryManager
|
||||
) {
|
||||
$this->guzzleClient = new Client(['curl' => [CURLOPT_UNIX_SOCKET_PATH => '/var/run/docker.sock']]);
|
||||
}
|
||||
|
||||
private function BuildApiUrl(string $url) : string {
|
||||
private function BuildApiUrl(string $url): string {
|
||||
return sprintf('http://127.0.0.1/%s/%s', self::API_VERSION, $url);
|
||||
}
|
||||
|
||||
private function BuildImageName(Container $container) : string {
|
||||
private function BuildImageName(Container $container): string {
|
||||
$tag = $container->GetImageTag();
|
||||
if ($tag === '%AIO_CHANNEL%') {
|
||||
$tag = $this->GetCurrentChannel();
|
||||
@@ -35,8 +36,7 @@ readonly class DockerActionManager {
|
||||
return $container->GetContainerName() . ':' . $tag;
|
||||
}
|
||||
|
||||
public function GetContainerRunningState(Container $container) : ContainerState
|
||||
{
|
||||
public function GetContainerRunningState(Container $container): ContainerState {
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($container->GetIdentifier())));
|
||||
try {
|
||||
$response = $this->guzzleClient->get($url);
|
||||
@@ -56,8 +56,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function GetContainerRestartingState(Container $container) : ContainerState
|
||||
{
|
||||
public function GetContainerRestartingState(Container $container): ContainerState {
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($container->GetIdentifier())));
|
||||
try {
|
||||
$response = $this->guzzleClient->get($url);
|
||||
@@ -77,8 +76,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function GetContainerUpdateState(Container $container) : VersionState
|
||||
{
|
||||
public function GetContainerUpdateState(Container $container): VersionState {
|
||||
$tag = $container->GetImageTag();
|
||||
if ($tag === '%AIO_CHANNEL%') {
|
||||
$tag = $this->GetCurrentChannel();
|
||||
@@ -88,12 +86,12 @@ readonly class DockerActionManager {
|
||||
if ($runningDigests === null) {
|
||||
return VersionState::Different;
|
||||
}
|
||||
$remoteDigest = $this->dockerHubManager->GetLatestDigestOfTag($container->GetContainerName(), $tag);
|
||||
$remoteDigest = $this->GetLatestDigestOfTag($container->GetContainerName(), $tag);
|
||||
if ($remoteDigest === null) {
|
||||
return VersionState::Equal;
|
||||
}
|
||||
|
||||
foreach($runningDigests as $runningDigest) {
|
||||
foreach ($runningDigests as $runningDigest) {
|
||||
if ($runningDigest === $remoteDigest) {
|
||||
return VersionState::Equal;
|
||||
}
|
||||
@@ -101,8 +99,7 @@ readonly class DockerActionManager {
|
||||
return VersionState::Different;
|
||||
}
|
||||
|
||||
public function GetContainerStartingState(Container $container) : ContainerState
|
||||
{
|
||||
public function GetContainerStartingState(Container $container): ContainerState {
|
||||
$runningState = $this->GetContainerRunningState($container);
|
||||
if ($runningState === ContainerState::Stopped || $runningState === ContainerState::ImageDoesNotExist) {
|
||||
return $runningState;
|
||||
@@ -110,9 +107,9 @@ readonly class DockerActionManager {
|
||||
|
||||
$containerName = $container->GetIdentifier();
|
||||
$internalPort = $container->GetInternalPort();
|
||||
if($internalPort === '%APACHE_PORT%') {
|
||||
if ($internalPort === '%APACHE_PORT%') {
|
||||
$internalPort = $this->configurationManager->GetApachePort();
|
||||
} elseif($internalPort === '%TALK_PORT%') {
|
||||
} elseif ($internalPort === '%TALK_PORT%') {
|
||||
$internalPort = $this->configurationManager->GetTalkPort();
|
||||
}
|
||||
|
||||
@@ -129,7 +126,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function DeleteContainer(Container $container) : void {
|
||||
public function DeleteContainer(Container $container): void {
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s?v=true', urlencode($container->GetIdentifier())));
|
||||
try {
|
||||
$this->guzzleClient->delete($url);
|
||||
@@ -140,8 +137,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function GetLogs(string $id) : string
|
||||
{
|
||||
public function GetLogs(string $id): string {
|
||||
$url = $this->BuildApiUrl(
|
||||
sprintf(
|
||||
'containers/%s/logs?stdout=true&stderr=true×tamps=true',
|
||||
@@ -162,7 +158,7 @@ readonly class DockerActionManager {
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function StartContainer(Container $container) : void {
|
||||
public function StartContainer(Container $container): void {
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/start', urlencode($container->GetIdentifier())));
|
||||
try {
|
||||
$this->guzzleClient->post($url);
|
||||
@@ -171,10 +167,9 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function CreateVolumes(Container $container): void
|
||||
{
|
||||
public function CreateVolumes(Container $container): void {
|
||||
$url = $this->BuildApiUrl('volumes/create');
|
||||
foreach($container->GetVolumes()->GetVolumes() as $volume) {
|
||||
foreach ($container->GetVolumes()->GetVolumes() as $volume) {
|
||||
$forbiddenChars = [
|
||||
'/',
|
||||
];
|
||||
@@ -184,7 +179,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
|
||||
$firstChar = substr($volume->name, 0, 1);
|
||||
if(!in_array($firstChar, $forbiddenChars)) {
|
||||
if (!in_array($firstChar, $forbiddenChars)) {
|
||||
$this->guzzleClient->request(
|
||||
'POST',
|
||||
$url,
|
||||
@@ -198,7 +193,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function CreateContainer(Container $container) : void {
|
||||
public function CreateContainer(Container $container): void {
|
||||
$volumes = [];
|
||||
foreach ($container->GetVolumes()->GetVolumes() as $volume) {
|
||||
// // NEXTCLOUD_MOUNT gets added via bind-mount later on
|
||||
@@ -226,12 +221,12 @@ readonly class DockerActionManager {
|
||||
$requestBody['HostConfig']['Binds'] = $volumes;
|
||||
}
|
||||
|
||||
foreach($container->GetSecrets() as $secret) {
|
||||
foreach ($container->GetSecrets() as $secret) {
|
||||
$this->configurationManager->GetAndGenerateSecret($secret);
|
||||
}
|
||||
|
||||
$aioVariables = $container->GetAioVariables()->GetVariables();
|
||||
foreach($aioVariables as $variable) {
|
||||
foreach ($aioVariables as $variable) {
|
||||
$config = $this->configurationManager->GetConfig();
|
||||
$variableArray = explode('=', $variable);
|
||||
$config[$variableArray[0]] = $variableArray[1];
|
||||
@@ -244,7 +239,7 @@ readonly class DockerActionManager {
|
||||
if ($container->GetIdentifier() === 'nextcloud-aio-nextcloud') {
|
||||
$envs[] = $this->GetAllNextcloudExecCommands();
|
||||
}
|
||||
foreach($envs as $key => $env) {
|
||||
foreach ($envs as $key => $env) {
|
||||
// TODO: This whole block below is a hack and needs to get reworked in order to support multiple substitutions per line by default for all envs
|
||||
if (str_starts_with($env, 'extra_params=')) {
|
||||
$env = str_replace('%COLLABORA_SECCOMP_POLICY%', $this->configurationManager->GetCollaboraSeccompPolicy(), $env);
|
||||
@@ -256,12 +251,12 @@ readonly class DockerActionManager {
|
||||
// Original implementation
|
||||
$patterns = ['/%(.*)%/'];
|
||||
|
||||
if(preg_match($patterns[0], $env, $out) === 1) {
|
||||
if (preg_match($patterns[0], $env, $out) === 1) {
|
||||
$replacements = array();
|
||||
|
||||
if($out[1] === 'NC_DOMAIN') {
|
||||
if ($out[1] === 'NC_DOMAIN') {
|
||||
$replacements[1] = $this->configurationManager->GetDomain();
|
||||
} elseif($out[1] === 'NC_BASE_DN') {
|
||||
} elseif ($out[1] === 'NC_BASE_DN') {
|
||||
$replacements[1] = $this->configurationManager->GetBaseDN();
|
||||
} elseif ($out[1] === 'AIO_TOKEN') {
|
||||
$replacements[1] = $this->configurationManager->GetToken();
|
||||
@@ -391,10 +386,10 @@ readonly class DockerActionManager {
|
||||
} else {
|
||||
$replacements[1] = '';
|
||||
}
|
||||
// Allow to get local ip-address of database container which allows to talk to it even in host mode (the container that requires this needs to be started first then)
|
||||
// Allow to get local ip-address of database container which allows to talk to it even in host mode (the container that requires this needs to be started first then)
|
||||
} elseif ($out[1] === 'AIO_DATABASE_HOST') {
|
||||
$replacements[1] = gethostbyname('nextcloud-aio-database');
|
||||
// Allow to get local ip-address of caddy container and add it to trusted proxies automatically
|
||||
// Allow to get local ip-address of caddy container and add it to trusted proxies automatically
|
||||
} elseif ($out[1] === 'CADDY_IP_ADDRESS') {
|
||||
$replacements[1] = '';
|
||||
$communityContainers = $this->configurationManager->GetEnabledCommunityContainers();
|
||||
@@ -419,7 +414,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
if(count($envs) > 0) {
|
||||
if (count($envs) > 0) {
|
||||
$requestBody['Env'] = $envs;
|
||||
}
|
||||
|
||||
@@ -429,7 +424,7 @@ readonly class DockerActionManager {
|
||||
|
||||
$exposedPorts = [];
|
||||
if ($container->GetInternalPort() !== 'host') {
|
||||
foreach($container->GetPorts()->GetPorts() as $value) {
|
||||
foreach ($container->GetPorts()->GetPorts() as $value) {
|
||||
$port = $value->port;
|
||||
$protocol = $value->protocol;
|
||||
if ($port === '%APACHE_PORT%') {
|
||||
@@ -449,7 +444,7 @@ readonly class DockerActionManager {
|
||||
$requestBody['HostConfig']['NetworkMode'] = 'host';
|
||||
}
|
||||
|
||||
if(count($exposedPorts) > 0) {
|
||||
if (count($exposedPorts) > 0) {
|
||||
$requestBody['ExposedPorts'] = $exposedPorts;
|
||||
foreach ($container->GetPorts()->GetPorts() as $value) {
|
||||
$port = $value->port;
|
||||
@@ -474,16 +469,16 @@ readonly class DockerActionManager {
|
||||
$portWithProtocol = $port . '/' . $protocol;
|
||||
$requestBody['HostConfig']['PortBindings'][$portWithProtocol] = [
|
||||
[
|
||||
'HostPort' => $port,
|
||||
'HostIp' => $ipBinding,
|
||||
'HostPort' => $port,
|
||||
'HostIp' => $ipBinding,
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$devices = [];
|
||||
foreach($container->GetDevices() as $device) {
|
||||
if ($device === '/dev/dri' && ! $this->configurationManager->isDriDeviceEnabled()) {
|
||||
foreach ($container->GetDevices() as $device) {
|
||||
if ($device === '/dev/dri' && !$this->configurationManager->isDriDeviceEnabled()) {
|
||||
continue;
|
||||
}
|
||||
$devices[] = ["PathOnHost" => $device, "PathInContainer" => $device, "CgroupPermissions" => "rwm"];
|
||||
@@ -510,7 +505,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
|
||||
$tmpfs = [];
|
||||
foreach($container->GetTmpfs() as $tmp) {
|
||||
foreach ($container->GetTmpfs() as $tmp) {
|
||||
$mode = "";
|
||||
if (str_contains($tmp, ':')) {
|
||||
$mode = explode(':', $tmp)[1];
|
||||
@@ -519,7 +514,7 @@ readonly class DockerActionManager {
|
||||
$tmpfs[$tmp] = $mode;
|
||||
}
|
||||
if (count($tmpfs) > 0) {
|
||||
$requestBody['HostConfig']['Tmpfs'] = $tmpfs;
|
||||
$requestBody['HostConfig']['Tmpfs'] = $tmpfs;
|
||||
}
|
||||
|
||||
$requestBody['HostConfig']['Init'] = $container->GetInit();
|
||||
@@ -563,22 +558,22 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Special things for the talk container which should not be exposed in the containers.json
|
||||
// Special things for the talk container which should not be exposed in the containers.json
|
||||
} elseif ($container->GetIdentifier() === 'nextcloud-aio-talk') {
|
||||
// This is needed due to a bug in libwebsockets which cannot handle unlimited ulimits
|
||||
$requestBody['HostConfig']['Ulimits'] = [["Name" => "nofile", "Hard" => 200000, "Soft" => 200000]];
|
||||
// // Special things for the nextcloud container which should not be exposed in the containers.json
|
||||
// } elseif ($container->GetIdentifier() === 'nextcloud-aio-nextcloud') {
|
||||
// foreach ($container->GetVolumes()->GetVolumes() as $volume) {
|
||||
// if ($volume->name !== $this->configurationManager->GetNextcloudMount()) {
|
||||
// continue;
|
||||
// }
|
||||
// $mounts[] = ["Type" => "bind", "Source" => $volume->name, "Target" => $volume->mountPoint, "ReadOnly" => !$volume->isWritable, "BindOptions" => [ "Propagation" => "rshared"]];
|
||||
// }
|
||||
// Special things for the caddy community container
|
||||
// // Special things for the nextcloud container which should not be exposed in the containers.json
|
||||
// } elseif ($container->GetIdentifier() === 'nextcloud-aio-nextcloud') {
|
||||
// foreach ($container->GetVolumes()->GetVolumes() as $volume) {
|
||||
// if ($volume->name !== $this->configurationManager->GetNextcloudMount()) {
|
||||
// continue;
|
||||
// }
|
||||
// $mounts[] = ["Type" => "bind", "Source" => $volume->name, "Target" => $volume->mountPoint, "ReadOnly" => !$volume->isWritable, "BindOptions" => [ "Propagation" => "rshared"]];
|
||||
// }
|
||||
// Special things for the caddy community container
|
||||
} elseif ($container->GetIdentifier() === 'nextcloud-aio-caddy') {
|
||||
$requestBody['HostConfig']['ExtraHosts'] = ['host.docker.internal:host-gateway'];
|
||||
// Special things for the collabora container which should not be exposed in the containers.json
|
||||
// Special things for the collabora container which should not be exposed in the containers.json
|
||||
} elseif ($container->GetIdentifier() === 'nextcloud-aio-collabora') {
|
||||
if ($this->configurationManager->GetAdditionalCollaboraOptions() !== '') {
|
||||
$requestBody['Cmd'] = [$this->configurationManager->GetAdditionalCollaboraOptions()];
|
||||
@@ -604,13 +599,13 @@ readonly class DockerActionManager {
|
||||
|
||||
}
|
||||
|
||||
public function isDockerHubReachable(Container $container) : bool {
|
||||
public function isDockerHubReachable(Container $container): bool {
|
||||
$tag = $container->GetImageTag();
|
||||
if ($tag === '%AIO_CHANNEL%') {
|
||||
$tag = $this->GetCurrentChannel();
|
||||
}
|
||||
|
||||
$remoteDigest = $this->dockerHubManager->GetLatestDigestOfTag($container->GetContainerName(), $tag);
|
||||
$remoteDigest = $this->GetLatestDigestOfTag($container->GetContainerName(), $tag);
|
||||
|
||||
if ($remoteDigest === null) {
|
||||
return false;
|
||||
@@ -619,8 +614,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function PullImage(Container $container) : void
|
||||
{
|
||||
public function PullImage(Container $container): void {
|
||||
$imageName = $this->BuildImageName($container);
|
||||
$encodedImageName = urlencode($imageName);
|
||||
$url = $this->BuildApiUrl(sprintf('images/create?fromImage=%s', $encodedImageName));
|
||||
@@ -643,8 +637,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
private function isContainerUpdateAvailable(string $id) : string
|
||||
{
|
||||
private function isContainerUpdateAvailable(string $id): string {
|
||||
$container = $this->containerDefinitionFetcher->GetContainerById($id);
|
||||
|
||||
$updateAvailable = "";
|
||||
@@ -657,7 +650,7 @@ readonly class DockerActionManager {
|
||||
return $updateAvailable;
|
||||
}
|
||||
|
||||
public function isAnyUpdateAvailable() : bool {
|
||||
public function isAnyUpdateAvailable(): bool {
|
||||
// return early if instance is not installed
|
||||
if (!$this->configurationManager->wasStartButtonClicked()) {
|
||||
return false;
|
||||
@@ -671,8 +664,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
private function getBackupVolumes(string $id) : string
|
||||
{
|
||||
private function getBackupVolumes(string $id): string {
|
||||
$container = $this->containerDefinitionFetcher->GetContainerById($id);
|
||||
|
||||
$backupVolumes = '';
|
||||
@@ -685,14 +677,13 @@ readonly class DockerActionManager {
|
||||
return $backupVolumes;
|
||||
}
|
||||
|
||||
private function getAllBackupVolumes() : array {
|
||||
private function getAllBackupVolumes(): array {
|
||||
$id = 'nextcloud-aio-apache';
|
||||
$backupVolumesArray = explode(' ', $this->getBackupVolumes($id));
|
||||
return array_unique($backupVolumesArray);
|
||||
}
|
||||
|
||||
private function GetNextcloudExecCommands(string $id) : string
|
||||
{
|
||||
private function GetNextcloudExecCommands(string $id): string {
|
||||
$container = $this->containerDefinitionFetcher->GetContainerById($id);
|
||||
|
||||
$nextcloudExecCommands = '';
|
||||
@@ -705,13 +696,12 @@ readonly class DockerActionManager {
|
||||
return $nextcloudExecCommands;
|
||||
}
|
||||
|
||||
private function GetAllNextcloudExecCommands() : string
|
||||
{
|
||||
private function GetAllNextcloudExecCommands(): string {
|
||||
$id = 'nextcloud-aio-apache';
|
||||
return 'NEXTCLOUD_EXEC_COMMANDS=' . $this->GetNextcloudExecCommands($id);
|
||||
}
|
||||
|
||||
private function GetRepoDigestsOfContainer(string $containerName) : ?array {
|
||||
private function GetRepoDigestsOfContainer(string $containerName): ?array {
|
||||
try {
|
||||
$containerUrl = $this->BuildApiUrl(sprintf('containers/%s/json', $containerName));
|
||||
$containerOutput = json_decode($this->guzzleClient->get($containerUrl)->getBody()->getContents(), true);
|
||||
@@ -732,7 +722,7 @@ readonly class DockerActionManager {
|
||||
|
||||
$repoDigestArray = [];
|
||||
$oneDigestGiven = false;
|
||||
foreach($imageOutput['RepoDigests'] as $repoDigest) {
|
||||
foreach ($imageOutput['RepoDigests'] as $repoDigest) {
|
||||
$digestPosition = strpos($repoDigest, '@');
|
||||
if ($digestPosition === false) {
|
||||
error_log('Somehow the RepoDigest of ' . $containerName . ' does not contain a @.');
|
||||
@@ -752,10 +742,37 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function GetCurrentChannel() : string {
|
||||
private function GetCurrentImageName(): string {
|
||||
$cacheKey = 'aio-image-name';
|
||||
$imageName = apcu_fetch($cacheKey);
|
||||
if ($imageName !== false && is_string($imageName)) {
|
||||
return $imageName;
|
||||
}
|
||||
|
||||
$containerName = 'nextcloud-aio-mastercontainer';
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/json', $containerName));
|
||||
try {
|
||||
$output = json_decode($this->guzzleClient->get($url)->getBody()->getContents(), true);
|
||||
$imageNameArray = explode(':', $output['Config']['Image']);
|
||||
if (count($imageNameArray) === 2) {
|
||||
$imageName = $imageNameArray[0];
|
||||
} else {
|
||||
error_log("No tag was found when getting the current channel. You probably did not follow the documentation correctly. Changing the imageName to the default " . $output['Config']['Image']);
|
||||
$imageName = $output['Config']['Image'];
|
||||
}
|
||||
apcu_add($cacheKey, $imageName);
|
||||
return $imageName;
|
||||
} catch (\Exception $e) {
|
||||
error_log('Could not get current imageName ' . $e->getMessage());
|
||||
}
|
||||
|
||||
return 'nextcloud/all-in-one';
|
||||
}
|
||||
|
||||
public function GetCurrentChannel(): string {
|
||||
$cacheKey = 'aio-ChannelName';
|
||||
$channelName = apcu_fetch($cacheKey);
|
||||
if($channelName !== false && is_string($channelName)) {
|
||||
if ($channelName !== false && is_string($channelName)) {
|
||||
return $channelName;
|
||||
}
|
||||
|
||||
@@ -763,9 +780,8 @@ readonly class DockerActionManager {
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/json', $containerName));
|
||||
try {
|
||||
$output = json_decode($this->guzzleClient->get($url)->getBody()->getContents(), true);
|
||||
$containerChecksum = $output['Image'];
|
||||
$tagArray = explode(':', $output['Config']['Image']);
|
||||
if (count($tagArray) === 2) {
|
||||
if (count($tagArray) === 2) {
|
||||
$tag = $tagArray[1];
|
||||
} else {
|
||||
error_log("No tag was found when getting the current channel. You probably did not follow the documentation correctly. Changing the channel to the default 'latest'.");
|
||||
@@ -780,9 +796,8 @@ readonly class DockerActionManager {
|
||||
return 'latest';
|
||||
}
|
||||
|
||||
public function IsMastercontainerUpdateAvailable() : bool
|
||||
{
|
||||
$imageName = 'nextcloud/all-in-one';
|
||||
public function IsMastercontainerUpdateAvailable(): bool {
|
||||
$imageName = $this->GetCurrentImageName();
|
||||
$containerName = 'nextcloud-aio-mastercontainer';
|
||||
|
||||
$tag = $this->GetCurrentChannel();
|
||||
@@ -791,7 +806,7 @@ readonly class DockerActionManager {
|
||||
if ($runningDigests === null) {
|
||||
return true;
|
||||
}
|
||||
$remoteDigest = $this->dockerHubManager->GetLatestDigestOfTag($imageName, $tag);
|
||||
$remoteDigest = $this->GetLatestDigestOfTag($imageName, $tag);
|
||||
if ($remoteDigest === null) {
|
||||
return false;
|
||||
}
|
||||
@@ -804,8 +819,7 @@ readonly class DockerActionManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function sendNotification(Container $container, string $subject, string $message, string $file = '/notify.sh') : void
|
||||
{
|
||||
public function sendNotification(Container $container, string $subject, string $message, string $file = '/notify.sh'): void {
|
||||
if ($this->GetContainerStartingState($container) === ContainerState::Running) {
|
||||
|
||||
$containerName = $container->GetIdentifier();
|
||||
@@ -849,8 +863,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
private function DisconnectContainerFromBridgeNetwork(string $id) : void
|
||||
{
|
||||
private function DisconnectContainerFromBridgeNetwork(string $id): void {
|
||||
|
||||
$url = $this->BuildApiUrl(
|
||||
sprintf('networks/%s/disconnect', 'bridge')
|
||||
@@ -870,8 +883,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
private function ConnectContainerIdToNetwork(string $id, string $internalPort, string $network = 'nextcloud-aio', bool $createNetwork = true, string $alias = '') : void
|
||||
{
|
||||
private function ConnectContainerIdToNetwork(string $id, string $internalPort, string $network = 'nextcloud-aio', bool $createNetwork = true, string $alias = ''): void {
|
||||
if ($internalPort === 'host') {
|
||||
return;
|
||||
}
|
||||
@@ -902,9 +914,9 @@ readonly class DockerActionManager {
|
||||
$url = $this->BuildApiUrl(
|
||||
sprintf('networks/%s/connect', $network)
|
||||
);
|
||||
$jsonPayload = [ 'Container' => $id ];
|
||||
if ($alias !== '' ) {
|
||||
$jsonPayload['EndpointConfig'] = ['Aliases' => [ $alias ]];
|
||||
$jsonPayload = ['Container' => $id];
|
||||
if ($alias !== '') {
|
||||
$jsonPayload['EndpointConfig'] = ['Aliases' => [$alias]];
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -923,15 +935,13 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function ConnectMasterContainerToNetwork() : void
|
||||
{
|
||||
public function ConnectMasterContainerToNetwork(): void {
|
||||
$this->ConnectContainerIdToNetwork('nextcloud-aio-mastercontainer', '');
|
||||
// Don't disconnect here since it slows down the initial login by a lot. Is getting done during cron.sh instead.
|
||||
// $this->DisconnectContainerFromBridgeNetwork('nextcloud-aio-mastercontainer');
|
||||
}
|
||||
|
||||
public function ConnectContainerToNetwork(Container $container) : void
|
||||
{
|
||||
public function ConnectContainerToNetwork(Container $container): void {
|
||||
// Add a secondary alias for domaincheck container, to keep it as similar to actual apache controller as possible.
|
||||
// If a reverse-proxy is relying on container name as hostname this allows it to operate as usual and still validate the domain
|
||||
// The domaincheck container and apache container are never supposed to be active at the same time because they use the same APACHE_PORT anyway, so this doesn't add any new constraints.
|
||||
@@ -947,7 +957,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function StopContainer(Container $container) : void {
|
||||
public function StopContainer(Container $container): void {
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/stop?t=%s', urlencode($container->GetIdentifier()), $container->GetMaxShutdownTime()));
|
||||
try {
|
||||
$this->guzzleClient->post($url);
|
||||
@@ -958,8 +968,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function GetBackupcontainerExitCode() : int
|
||||
{
|
||||
public function GetBackupcontainerExitCode(): int {
|
||||
$containerName = 'nextcloud-aio-borgbackup';
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($containerName)));
|
||||
try {
|
||||
@@ -981,8 +990,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function GetDatabasecontainerExitCode() : int
|
||||
{
|
||||
public function GetDatabasecontainerExitCode(): int {
|
||||
$containerName = 'nextcloud-aio-database';
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($containerName)));
|
||||
try {
|
||||
@@ -1004,7 +1012,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function isLoginAllowed() : bool {
|
||||
public function isLoginAllowed(): bool {
|
||||
$id = 'nextcloud-aio-apache';
|
||||
$apacheContainer = $this->containerDefinitionFetcher->GetContainerById($id);
|
||||
if ($this->GetContainerStartingState($apacheContainer) === ContainerState::Running) {
|
||||
@@ -1013,7 +1021,7 @@ readonly class DockerActionManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isBackupContainerRunning() : bool {
|
||||
public function isBackupContainerRunning(): bool {
|
||||
$id = 'nextcloud-aio-borgbackup';
|
||||
$backupContainer = $this->containerDefinitionFetcher->GetContainerById($id);
|
||||
if ($this->GetContainerRunningState($backupContainer) === ContainerState::Running) {
|
||||
@@ -1022,7 +1030,7 @@ readonly class DockerActionManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
private function GetCreatedTimeOfNextcloudImage() : ?string {
|
||||
private function GetCreatedTimeOfNextcloudImage(): ?string {
|
||||
$imageName = 'nextcloud/aio-nextcloud' . ':' . $this->GetCurrentChannel();
|
||||
try {
|
||||
$imageUrl = $this->BuildApiUrl(sprintf('images/%s/json', $imageName));
|
||||
@@ -1039,11 +1047,11 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function GetAndGenerateSecretWrapper(string $secretId) : string {
|
||||
public function GetAndGenerateSecretWrapper(string $secretId): string {
|
||||
return $this->configurationManager->GetAndGenerateSecret($secretId);
|
||||
}
|
||||
|
||||
public function isNextcloudImageOutdated() : bool {
|
||||
public function isNextcloudImageOutdated(): bool {
|
||||
$createdTime = $this->GetCreatedTimeOfNextcloudImage();
|
||||
|
||||
if ($createdTime === null) {
|
||||
@@ -1057,4 +1065,13 @@ readonly class DockerActionManager {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function GetLatestDigestOfTag(string $imageName, string $tag): ?string {
|
||||
$prefix = 'ghcr.io/';
|
||||
if (str_starts_with($imageName, $prefix)) {
|
||||
return $this->gitHubContainerRegistryManager->GetLatestDigestOfTag(str_replace($prefix, '', $imageName), $tag);
|
||||
} else {
|
||||
return $this->dockerHubManager->GetLatestDigestOfTag($imageName, $tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
62
php/src/Docker/GitHubContainerRegistryManager.php
Normal file
62
php/src/Docker/GitHubContainerRegistryManager.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace AIO\Docker;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
readonly class GitHubContainerRegistryManager
|
||||
{
|
||||
private Client $guzzleClient;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->guzzleClient = new Client();
|
||||
}
|
||||
|
||||
public function GetLatestDigestOfTag(string $name, string $tag): ?string
|
||||
{
|
||||
$cacheKey = 'ghcr-manifest-' . $name . $tag;
|
||||
|
||||
$cachedVersion = apcu_fetch($cacheKey);
|
||||
if ($cachedVersion !== false && is_string($cachedVersion)) {
|
||||
return $cachedVersion;
|
||||
}
|
||||
|
||||
// If one of the links below should ever become outdated, we can still upgrade the mastercontainer via the webinterface manually by opening '/api/docker/getwatchtower'
|
||||
|
||||
try {
|
||||
$authTokenRequest = $this->guzzleClient->request(
|
||||
'GET',
|
||||
'https://ghcr.io/token?scope=repository:' . $name . ':pull'
|
||||
);
|
||||
$body = $authTokenRequest->getBody()->getContents();
|
||||
$decodedBody = json_decode($body, true);
|
||||
if (isset($decodedBody['token'])) {
|
||||
$authToken = $decodedBody['token'];
|
||||
$manifestRequest = $this->guzzleClient->request(
|
||||
'HEAD',
|
||||
'https://ghcr.io/v2/' . $name . '/manifests/' . $tag,
|
||||
[
|
||||
'headers' => [
|
||||
'Accept' => 'application/vnd.oci.image.index.v1+json,application/vnd.docker.distribution.manifest.list.v2+json,application/vnd.docker.distribution.manifest.v2+json',
|
||||
'Authorization' => 'Bearer ' . $authToken,
|
||||
],
|
||||
]
|
||||
);
|
||||
$responseHeaders = $manifestRequest->getHeader('docker-content-digest');
|
||||
if (count($responseHeaders) === 1) {
|
||||
$latestVersion = $responseHeaders[0];
|
||||
apcu_add($cacheKey, $latestVersion, 600);
|
||||
return $latestVersion;
|
||||
}
|
||||
}
|
||||
|
||||
error_log('Could not get digest of container ' . $name . ':' . $tag);
|
||||
return null;
|
||||
} catch (\Exception $e) {
|
||||
error_log('Could not get digest of container ' . $name . ':' . $tag . ' ' . $e->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
27
php/templates/components/container-state.twig
Normal file
27
php/templates/components/container-state.twig
Normal file
@@ -0,0 +1,27 @@
|
||||
{# @var c \App\Containers\Container #}
|
||||
<li>
|
||||
<span>
|
||||
{% if c.GetStartingState().value == 'starting' %}
|
||||
<span class="status running"></span>
|
||||
{{ c.GetDisplayName() }}
|
||||
(<a href="/api/docker/logs?id={{ c.GetIdentifier() }}" target="_blank">Starting</a>)
|
||||
{% elseif c.GetRunningState().value == 'running' %}
|
||||
<span class="status success"></span>
|
||||
{{ c.GetDisplayName() }}
|
||||
(<a href="/api/docker/logs?id={{ c.GetIdentifier() }}" target="_blank">Running</a>)
|
||||
{% else %}
|
||||
<span class="status error"></span>
|
||||
{{ c.GetDisplayName() }}
|
||||
(<a href="/api/docker/logs?id={{ c.GetIdentifier() }}" target="_blank">Stopped</a>)
|
||||
{% endif %}
|
||||
{% if c.GetDocumentation() != '' %}
|
||||
(<a target="_blank" href="{{ c.GetDocumentation() }}">docs</a>)
|
||||
{% endif %}
|
||||
</span>
|
||||
{% if c.GetUiSecret() != '' %}
|
||||
<details>
|
||||
<summary>Show password for {{ c.GetDisplayName() }}</summary>
|
||||
<input type="text" value="{{ c.GetUiSecret() }}" readonly>
|
||||
</details>
|
||||
{% endif %}
|
||||
</li>
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<div class="container">
|
||||
<main>
|
||||
<h1>Nextcloud AIO v10.7.0</h1>
|
||||
<h1>Nextcloud AIO v10.10.0</h1>
|
||||
|
||||
{# Add 2nd tab warning #}
|
||||
<script type="text/javascript" src="second-tab-warning.js"></script>
|
||||
@@ -106,7 +106,7 @@
|
||||
<p><strong>Please note:</strong> The domain validation is disabled so any domain will be accepted here! Make sure you do not make a typo here as you will not be able to change it afterwards!</p>
|
||||
{% endif %}
|
||||
<form method="POST" action="/api/configuration" class="xhr">
|
||||
<input type="text" name="domain" value="{{ domain }}" placeholder="nextcloud.yourdomain.com"/>
|
||||
<input type="text" id="domain" name="domain" value="{{ domain }}" placeholder="nextcloud.yourdomain.com"/>
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Submit domain" />
|
||||
@@ -195,9 +195,9 @@
|
||||
if stored remotely; and the encryption password of the backup archive below:
|
||||
</p>
|
||||
<form method="POST" action="/api/configuration" class="xhr">
|
||||
<label>Local backup location</label> <input type="text" name="borg_restore_host_location" value="{{borg_backup_host_location}}" placeholder="/mnt/backup"/><br>
|
||||
<label>Local backup location</label> <input type="text" id="borg_restore_host_location" name="borg_restore_host_location" value="{{borg_backup_host_location}}" placeholder="/mnt/backup"/><br>
|
||||
<label>Remote borg repo</label> <input type="text" name="borg_restore_remote_repo" value="{{borg_remote_repo}}" placeholder="ssh://user@host:port/path/to/repo"/><br>
|
||||
<label>Borg passphrase</label> <input type="text" name="borg_restore_password" value="{{borg_restore_password}}" placeholder="encryption password"/><br>
|
||||
<label>Borg passphrase</label> <input type="text" id="borg_restore_password" name="borg_restore_password" value="{{borg_restore_password}}" placeholder="encryption password"/><br>
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Submit location and encryption password" />
|
||||
@@ -241,9 +241,9 @@
|
||||
<p>Initial Nextcloud username: <strong>admin</strong></p>
|
||||
{% if hasBackupLocation %}
|
||||
{# nextcloud_password needs to be duplicated due to a bug in Firefox. See https://github.com/nextcloud/all-in-one/issues/638. #}
|
||||
<p>Initial Nextcloud password: <strong>{{ nextcloud_password }}</strong></p></details>
|
||||
<p>Initial Nextcloud password: <strong id="initial-nextcloud-password">{{ nextcloud_password }}</strong></p></details>
|
||||
{% else %}
|
||||
<p>Initial Nextcloud password: <strong>{{ nextcloud_password }}</strong></p>
|
||||
<p>Initial Nextcloud password: <strong id="initial-nextcloud-password">{{ nextcloud_password }}</strong></p>
|
||||
{% endif %}
|
||||
<p><a href="https://{{ domain }}" class="button" target="_blank">Open your Nextcloud ↗</a></p>
|
||||
{% if not hasBackupLocation %}
|
||||
@@ -275,39 +275,7 @@
|
||||
{# @var containers \AIO\Container\Container[] #}
|
||||
{% for container in containers %}
|
||||
{% if container.GetDisplayName() != '' %}
|
||||
<li>
|
||||
{% if container.GetStartingState().value == 'starting' %}
|
||||
<span class="status running"></span>
|
||||
<span>{{ container.GetDisplayName() }} (<a href="/api/docker/logs?id={{ container.GetIdentifier() }}" target="_blank">Starting</a>)
|
||||
{% if container.GetDocumentation() != '' %}
|
||||
(<a target="_blank" href="{{ container.GetDocumentation() }}">docs</a>)
|
||||
{% endif %}
|
||||
{% if container.GetUiSecret() != '' %}
|
||||
(password: {{ container.GetUiSecret() }})
|
||||
{% endif %}
|
||||
</span>
|
||||
{% elseif container.GetRunningState().value == 'running' %}
|
||||
<span class="status success"></span>
|
||||
<span>{{ container.GetDisplayName() }} (<a href="/api/docker/logs?id={{ container.GetIdentifier() }}" target="_blank">Running</a>)
|
||||
{% if container.GetDocumentation() != '' %}
|
||||
(<a target="_blank" href="{{ container.GetDocumentation() }}">docs</a>)
|
||||
{% endif %}
|
||||
{% if container.GetUiSecret() != '' %}
|
||||
(password: {{ container.GetUiSecret() }})
|
||||
{% endif %}
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="status error"></span>
|
||||
<span>{{ container.GetDisplayName() }} (<a href="/api/docker/logs?id={{ container.GetIdentifier() }}" target="_blank">Stopped</a>)
|
||||
{% if container.GetDocumentation() != '' %}
|
||||
(<a target="_blank" href="{{ container.GetDocumentation() }}">docs</a>)
|
||||
{% endif %}
|
||||
{% if container.GetUiSecret() != '' %}
|
||||
(password: {{ container.GetUiSecret() }})
|
||||
{% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% include 'components/container-state.twig' with {'c': container} only %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
@@ -402,7 +370,7 @@
|
||||
<a target="_blank" href="https://borgbackup.readthedocs.io/en/stable/usage/general.html#repository-urls">remote borg repo url</a>.
|
||||
</p>
|
||||
<form method="POST" action="/api/configuration" class="xhr">
|
||||
<label>Local backup location</label> <input type="text" name="borg_backup_host_location" placeholder="/mnt/backup"/><br>
|
||||
<label>Local backup location</label> <input type="text" id="borg_backup_host_location" name="borg_backup_host_location" placeholder="/mnt/backup"/><br>
|
||||
<label>Remote borg repo</label> <input type="text" name="borg_remote_repo" placeholder="ssh://user@host:port/path/to/repo"/><br>
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
@@ -440,7 +408,7 @@
|
||||
To try again, click <strong>Create backup</strong>.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<p>You may change the backup path again since the initial backup was not successful. After submitting the new value, you need to click on <strong>Create Backup</strong> to test the new value.</p>
|
||||
<form method="POST" action="/api/configuration" class="xhr">
|
||||
<label>Local backup location</label> <input type="text" name="borg_backup_host_location" placeholder="/mnt/backup"/><br>
|
||||
@@ -465,7 +433,7 @@
|
||||
<summary>Click here to reveal all backup options (including an option for automatic updates)</summary>
|
||||
{% endif %}
|
||||
<h3>Backup information</h3>
|
||||
<p>This is your encryption password for backups: <strong>{{ borgbackup_password }}</strong></p>
|
||||
<p>This is your encryption password for backups: <strong id="borg-backup-password">{{ borgbackup_password }}</strong></p>
|
||||
<p>Please save this password in a safe place. You won't be able to restore from backup if you lose this password!</p>
|
||||
<p>All important data from your Nextcloud AIO instance such as the database, your files and the mastercontainer's configuration files, will be backed up.</p>
|
||||
<p>The backup uses a tool called <a target="_blank" href="https://github.com/borgbackup/borg#what-is-borgbackup"><strong>BorgBackup</strong></a>, a well-known server backup tool that efficiently backs up your files and encrypts them on the fly.</p>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
data-initial-state="false"
|
||||
{% endif %}
|
||||
>
|
||||
<label for="clamav">ClamAV (Antivirus backend for Nextcloud, only supported on x86_64, needs ~1GB additional RAM)</label>
|
||||
<label for="clamav">ClamAV (Antivirus backend for Nextcloud, needs ~1GB additional RAM)</label>
|
||||
</p>
|
||||
<p>
|
||||
<input
|
||||
@@ -146,10 +146,8 @@
|
||||
<script type="text/javascript" src="options-form-submit.js?v3"></script>
|
||||
</form>
|
||||
<p><strong>Minimal system requirements:</strong> When any optional container is enabled, at least 2GB RAM, a dual-core CPU and 40GB system storage are required. When enabling ClamAV, Nextcloud Talk Recording-server or Fulltextsearch, at least 3GB RAM are required. For Talk Recording-server additional 2 vCPUs are required. When enabling everything, at least 5GB RAM and a quad-core CPU are required. Recommended are at least 1GB more RAM than the minimal requirement. For further advice and recommendations see <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/1335">this documentation</a></strong></p>
|
||||
{% if isAnyRunning == true or is_x64_platform == false %}
|
||||
<script type="text/javascript" src="disable-clamav.js"></script>
|
||||
{% endif %}
|
||||
{% if isAnyRunning == true %}
|
||||
<script type="text/javascript" src="disable-clamav.js"></script>
|
||||
<script type="text/javascript" src="disable-docker-socket-proxy.js"></script>
|
||||
<script type="text/javascript" src="disable-talk.js"></script>
|
||||
<script type="text/javascript" src="disable-collabora.js"></script>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<h1>All-in-One setup</h1>
|
||||
<p>The official Nextcloud installation method. Nextcloud All-in-One provides easy deployment and maintenance with most features included in this one Nextcloud instance.</p>
|
||||
<p>⚠️ <strong>Please note down the passphrase to access the AIO interface and don't lose it!</strong></p>
|
||||
<strong>Passphrase</strong><br/><span class="monospace">{{ password }}</span><br>
|
||||
<strong>Passphrase</strong><br/><span id="initial-password" class="monospace">{{ password }}</span><br>
|
||||
<a href="/" class="button" target="_blank">Open Nextcloud AIO login ↗</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
7
php/tests/.gitignore
vendored
Normal file
7
php/tests/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
# Playwright
|
||||
node_modules/
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
97
php/tests/package-lock.json
generated
Normal file
97
php/tests/package-lock.json
generated
Normal file
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"name": "e2e",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "e2e",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.51.1",
|
||||
"@types/node": "^22.13.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.51.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.51.1.tgz",
|
||||
"integrity": "sha512-nM+kEaTSAoVlXmMPH10017vn3FSiFqr/bh4fKg9vmAdMfd9SDqRZNvPSiAHADc/itWak+qPvMPZQOPwCBW7k7Q==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright": "1.51.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.13.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz",
|
||||
"integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.51.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.1.tgz",
|
||||
"integrity": "sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.51.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.51.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.1.tgz",
|
||||
"integrity": "sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.20.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
||||
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
8
php/tests/package.json
Normal file
8
php/tests/package.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "nextcloud-aio-mastercontainer-tests",
|
||||
"version": "1.0.0",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.51.1"
|
||||
}
|
||||
}
|
||||
29
php/tests/playwright.config.js
Normal file
29
php/tests/playwright.config.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import { defineConfig, devices } from '@playwright/test'
|
||||
|
||||
/**
|
||||
* @see https://playwright.dev/docs/test-configuration
|
||||
*/
|
||||
export default defineConfig({
|
||||
testDir: './tests',
|
||||
fullyParallel: false,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: 0,
|
||||
workers: 1,
|
||||
reporter: [
|
||||
['list'],
|
||||
['html'],
|
||||
],
|
||||
use: {
|
||||
baseURL: process.env.BASE_URL ?? 'http://localhost:8080',
|
||||
trace: 'on',
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: {
|
||||
...devices['Desktop Chrome'],
|
||||
ignoreHTTPSErrors: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
96
php/tests/tests/initial-setup.spec.js
Normal file
96
php/tests/tests/initial-setup.spec.js
Normal file
@@ -0,0 +1,96 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { writeFileSync } from 'node:fs'
|
||||
|
||||
test('Initial setup', async ({ page: setupPage }) => {
|
||||
test.setTimeout(10 * 60 * 1000)
|
||||
|
||||
// Extract initial password
|
||||
await setupPage.goto('./setup');
|
||||
const password = await setupPage.locator('#initial-password').innerText()
|
||||
const containersPagePromise = setupPage.waitForEvent('popup');
|
||||
await setupPage.getByRole('link', { name: 'Open Nextcloud AIO login ↗' }).click();
|
||||
const containersPage = await containersPagePromise;
|
||||
|
||||
// Log in and wait for redirect
|
||||
await containersPage.locator('#master-password').click();
|
||||
await containersPage.locator('#master-password').fill(password);
|
||||
await containersPage.getByRole('button', { name: 'Log in' }).click();
|
||||
await containersPage.waitForURL('./containers');
|
||||
|
||||
// Reject IP addresses
|
||||
await containersPage.locator('#domain').click();
|
||||
await containersPage.locator('#domain').fill('1.1.1.1');
|
||||
await containersPage.getByRole('button', { name: 'Submit domain' }).click();
|
||||
await expect(containersPage.locator('body')).toContainText('Please enter a domain and not an IP-address!');
|
||||
|
||||
// Accept example.com (requires disabled domain validation)
|
||||
await containersPage.locator('#domain').click();
|
||||
await containersPage.locator('#domain').fill('example.com');
|
||||
await containersPage.getByRole('button', { name: 'Submit domain' }).click();
|
||||
|
||||
// Disable all additional containers
|
||||
await containersPage.locator('#talk').uncheck();
|
||||
await containersPage.getByRole('checkbox', { name: 'Whiteboard' }).uncheck();
|
||||
await containersPage.getByRole('checkbox', { name: 'Imaginary' }).uncheck();
|
||||
await containersPage.getByRole('checkbox', { name: 'Collabora' }).uncheck();
|
||||
await containersPage.getByRole('button', { name: 'Save changes' }).click();
|
||||
await expect(containersPage.locator('#talk')).not.toBeChecked()
|
||||
await expect(containersPage.getByRole('checkbox', { name: 'Whiteboard' })).not.toBeChecked()
|
||||
await expect(containersPage.getByRole('checkbox', { name: 'Imaginary' })).not.toBeChecked()
|
||||
await expect(containersPage.getByRole('checkbox', { name: 'Collabora' })).not.toBeChecked()
|
||||
|
||||
// Reject invalid time zones
|
||||
await containersPage.locator('#timezone').click();
|
||||
await containersPage.locator('#timezone').fill('Invalid time zone');
|
||||
containersPage.once('dialog', dialog => {
|
||||
console.log(`Dialog message: ${dialog.message()}`)
|
||||
dialog.accept()
|
||||
});
|
||||
await containersPage.getByRole('button', { name: 'Submit timezone' }).click();
|
||||
await expect(containersPage.locator('body')).toContainText('The entered timezone does not seem to be a valid timezone!')
|
||||
|
||||
// Accept valid time zone
|
||||
await containersPage.locator('#timezone').click();
|
||||
await containersPage.locator('#timezone').fill('Europe/Berlin');
|
||||
containersPage.once('dialog', dialog => {
|
||||
console.log(`Dialog message: ${dialog.message()}`)
|
||||
dialog.accept()
|
||||
});
|
||||
await containersPage.getByRole('button', { name: 'Submit timezone' }).click();
|
||||
|
||||
// Start containers and wait for starting message
|
||||
await containersPage.getByRole('button', { name: 'Download and start containers' }).click();
|
||||
await expect(containersPage.getByRole('main')).toContainText('Containers are currently starting.', { timeout: 3 * 60 * 1000 });
|
||||
await expect(containersPage.getByRole('link', { name: 'Open your Nextcloud ↗' })).toBeVisible({ timeout: 2 * 60 * 1000 });
|
||||
await expect(containersPage.getByRole('link', { name: 'Open your Nextcloud ↗' })).toHaveAttribute('href', 'https://example.com');
|
||||
|
||||
// Extract initial nextcloud password
|
||||
await expect(containersPage.getByRole('main')).toContainText('Initial Nextcloud password:')
|
||||
const initialNextcloudPassword = await containersPage.locator('#initial-nextcloud-password').innerText();
|
||||
|
||||
// Set backup location and create backup
|
||||
const borgBackupLocation = `/mnt/test/aio-${Math.floor(Math.random() * 2147483647)}`
|
||||
await containersPage.locator('#borg_backup_host_location').click();
|
||||
await containersPage.locator('#borg_backup_host_location').fill(borgBackupLocation);
|
||||
await containersPage.getByRole('button', { name: 'Submit backup location' }).click();
|
||||
containersPage.once('dialog', dialog => {
|
||||
console.log(`Dialog message: ${dialog.message()}`)
|
||||
dialog.accept()
|
||||
});
|
||||
await containersPage.getByRole('button', { name: 'Create backup' }).click();
|
||||
await expect(containersPage.getByRole('main')).toContainText('Backup container is currently running:', { timeout: 3 * 60 * 1000 });
|
||||
await expect(containersPage.getByRole('main')).toContainText('Last backup successful on', { timeout: 3 * 60 * 1000 });
|
||||
await containersPage.getByText('Click here to reveal all backup options').click();
|
||||
await expect(containersPage.locator('#borg-backup-password')).toBeVisible();
|
||||
const borgBackupPassword = await containersPage.locator('#borg-backup-password').innerText();
|
||||
|
||||
// Assert that all containers are stopped
|
||||
await expect(containersPage.getByRole('button', { name: 'Start containers' })).toBeVisible();
|
||||
|
||||
// Save passwords for restore backup test
|
||||
writeFileSync('test_data.json', JSON.stringify({
|
||||
initialNextcloudPassword,
|
||||
borgBackupLocation,
|
||||
borgBackupPassword,
|
||||
}))
|
||||
});
|
||||
79
php/tests/tests/restore-instance.spec.js
Normal file
79
php/tests/tests/restore-instance.spec.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { readFileSync } from 'node:fs';
|
||||
|
||||
test('Restore instance', async ({ page: setupPage }) => {
|
||||
test.setTimeout(10 * 60 * 1000)
|
||||
|
||||
// Load passwords from previous test
|
||||
const {
|
||||
initialNextcloudPassword,
|
||||
borgBackupLocation,
|
||||
borgBackupPassword,
|
||||
} = JSON.parse(readFileSync('test_data.json'))
|
||||
|
||||
// Extract initial password
|
||||
await setupPage.goto('./setup');
|
||||
const password = await setupPage.locator('#initial-password').innerText()
|
||||
const containersPagePromise = setupPage.waitForEvent('popup');
|
||||
await setupPage.getByRole('link', { name: 'Open Nextcloud AIO login ↗' }).click();
|
||||
const containersPage = await containersPagePromise;
|
||||
|
||||
// Log in and wait for redirect
|
||||
await containersPage.locator('#master-password').click();
|
||||
await containersPage.locator('#master-password').fill(password);
|
||||
await containersPage.getByRole('button', { name: 'Log in' }).click();
|
||||
await containersPage.waitForURL('./containers');
|
||||
|
||||
// Reject example.com (requires enabled domain validation)
|
||||
await containersPage.locator('#domain').click();
|
||||
await containersPage.locator('#domain').fill('example.com');
|
||||
await containersPage.getByRole('button', { name: 'Submit domain' }).click();
|
||||
await expect(containersPage.locator('body')).toContainText('Domain does not point to this server or the reverse proxy is not configured correctly.');
|
||||
|
||||
// Reject invalid backup location
|
||||
await containersPage.locator('#borg_restore_host_location').click();
|
||||
await containersPage.locator('#borg_restore_host_location').fill('/mnt/test/aio-incorrect-path');
|
||||
await containersPage.locator('#borg_restore_password').click();
|
||||
await containersPage.locator('#borg_restore_password').fill(borgBackupPassword);
|
||||
await containersPage.getByRole('button', { name: 'Submit location and encryption password' }).click()
|
||||
await containersPage.getByRole('button', { name: 'Test path and encryption' }).click();
|
||||
await expect(containersPage.getByRole('main')).toContainText('Last test failed!', { timeout: 60 * 1000 });
|
||||
|
||||
// Reject invalid backup password
|
||||
await containersPage.locator('#borg_restore_host_location').click();
|
||||
await containersPage.locator('#borg_restore_host_location').fill(borgBackupLocation);
|
||||
await containersPage.locator('#borg_restore_password').click();
|
||||
await containersPage.locator('#borg_restore_password').fill('foobar');
|
||||
await containersPage.getByRole('button', { name: 'Submit location and encryption password' }).click()
|
||||
await containersPage.getByRole('button', { name: 'Test path and encryption' }).click();
|
||||
await expect(containersPage.getByRole('main')).toContainText('Last test failed!', { timeout: 60 * 1000 });
|
||||
|
||||
// Accept correct backup location and password
|
||||
await containersPage.locator('#borg_restore_host_location').click();
|
||||
await containersPage.locator('#borg_restore_host_location').fill(borgBackupLocation);
|
||||
await containersPage.locator('#borg_restore_password').click();
|
||||
await containersPage.locator('#borg_restore_password').fill(borgBackupPassword);
|
||||
await containersPage.getByRole('button', { name: 'Submit location and encryption password' }).click()
|
||||
await containersPage.getByRole('button', { name: 'Test path and encryption' }).click();
|
||||
|
||||
// Check integrity and restore backup
|
||||
await containersPage.getByRole('button', { name: 'Check backup integrity' }).click();
|
||||
await expect(containersPage.getByRole('main')).toContainText('Last check successful!', { timeout: 5 * 60 * 1000 });
|
||||
await containersPage.getByRole('button', { name: 'Restore selected backup' }).click();
|
||||
await expect(containersPage.getByRole('main')).toContainText('Backup container is currently running:');
|
||||
|
||||
// Verify a successful backup restore
|
||||
await expect(containersPage.getByRole('main')).toContainText('Last restore successful!', { timeout: 3 * 60 * 1000 });
|
||||
await expect(containersPage.getByRole('main')).toContainText('⚠️ Container updates are available. Click on Stop containers and Start and update containers to update them. You should consider creating a backup first.');
|
||||
containersPage.once('dialog', dialog => {
|
||||
console.log(`Dialog message: ${dialog.message()}`)
|
||||
dialog.accept()
|
||||
});
|
||||
await containersPage.getByRole('button', { name: 'Start and update containers' }).click();
|
||||
await expect(containersPage.getByRole('link', { name: 'Open your Nextcloud ↗' })).toBeVisible({ timeout: 5 * 60 * 1000 });
|
||||
await expect(containersPage.getByRole('main')).toContainText(initialNextcloudPassword);
|
||||
|
||||
// Verify that containers are all stopped
|
||||
await containersPage.getByRole('button', { name: 'Stop containers' }).click();
|
||||
await expect(containersPage.getByRole('button', { name: 'Start containers' })).toBeVisible({ timeout: 60 * 1000 });
|
||||
});
|
||||
@@ -351,7 +351,7 @@ If you get an error during the domain validation which states that your ip-addre
|
||||
### Which CPU architectures are supported?
|
||||
You can check this on Linux by running: `uname -m`
|
||||
- x86_64/x64/amd64
|
||||
- aarch64/arm64/armv8 (Note: ClamAV is currently not supported on this CPU architecture)
|
||||
- aarch64/arm64/armv8
|
||||
|
||||
### Disrecommended VPS providers
|
||||
- *Older* Strato VPS using Virtuozzo caused problems though ones from Q3 2023 and later should work.
|
||||
@@ -486,6 +486,9 @@ In certain situations you might want to keep Nextcloud apps that are disabled in
|
||||
> Doing this might cause unintended problems in Nextcloud if an app that requires an external dependency is still installed but the external dependency not for example.
|
||||
|
||||
### How to trust user-defined Certification Authorities (CA)?
|
||||
> [!NOTE]
|
||||
> Please note, that this feature is only intended to make LDAPS connections with self-signed certificates work. It will not make other interconnectivity between the different containers work, as they expect a valid publicly trusted certificate like one from Let's Encrypt.
|
||||
|
||||
For some applications it might be necessary to establish a secure connection to another host/server which is using a certificate issued by a Certification Authority that is not trusted out of the box. An example could be configuring LDAPS against a domain controller (Active Directory or Samba-based) of an organization.
|
||||
|
||||
You can make the Nextcloud container trust any Certification Authority by providing the environmental variable `NEXTCLOUD_TRUSTED_CACERTS_DIR` to the docker run command of the mastercontainer (but before the last line `nextcloud/all-in-one:latest`! If it was started already, you will need to stop the mastercontainer, remove it (no data will be lost) and recreate it using the docker run command that you initially used). The value of the variables should be set to the absolute paths of the directory on the host, which contains one or more Certification Authorities certificates. You should use X.509 certificates, Base64 encoded. (Other formats may work but have not been tested!) All the certificates in the directory will be trusted.
|
||||
|
||||
@@ -478,12 +478,16 @@ Second, see these screenshots for a working config:
|
||||
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
<!--  -->
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
`proxy_set_header Accept-Encoding $http_accept_encoding;`
|
||||
|
||||
⚠️ **Please note:** Nextcloud will complain that X-XXS-Protection is set to the wrong value, this is intended by NPMplus. <br>
|
||||
⚠️ **Please note:** look into [this](#adapting-the-sample-web-server-configurations-below) to adapt the above example configuration.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user