mirror of
https://github.com/nextcloud/all-in-one.git
synced 2026-06-10 08:37:02 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 29b4bad3ff | |||
| b55ab5eef4 | |||
| fa98d22724 |
@@ -1,5 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
6078222f7c61540504fa9892729f4a04 lint-php.yml
|
||||
9fe5efdf1113d7fe92ba1f54f1111c4f psalm.yml
|
||||
9dc6b717be0006fc7974a50351686fd7 sync-workflow-templates.yml
|
||||
@@ -31,7 +31,6 @@ updates:
|
||||
- "/Containers/collabora"
|
||||
- "/Containers/docker-socket-proxy"
|
||||
- "/Containers/domaincheck"
|
||||
- "/Containers/eurooffice"
|
||||
- "/Containers/fulltextsearch"
|
||||
- "/Containers/imaginary"
|
||||
- "/Containers/mastercontainer"
|
||||
|
||||
@@ -8,7 +8,15 @@
|
||||
|
||||
name: Lint php
|
||||
|
||||
on: pull_request
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'php/**'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'php/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -18,27 +26,11 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
runs-on: ubuntu-latest-low
|
||||
outputs:
|
||||
php-min: ${{ steps.versions.outputs.php-min }}
|
||||
php-max: ${{ steps.versions.outputs.php-max }}
|
||||
steps:
|
||||
- name: Checkout app
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Get version matrix
|
||||
id: versions
|
||||
uses: icewind1991/nextcloud-version-matrix@8a7bac6300b2f0f3100088b297995a229558ddba # v1.3.2
|
||||
|
||||
php-lint:
|
||||
runs-on: ubuntu-latest
|
||||
needs: matrix
|
||||
strategy:
|
||||
matrix:
|
||||
php-versions: ['${{ needs.matrix.outputs.php-min }}', '${{ needs.matrix.outputs.php-max }}']
|
||||
php-versions: [ "8.5" ]
|
||||
|
||||
name: php-lint
|
||||
|
||||
@@ -49,17 +41,16 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # 2.37.1
|
||||
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.37.0
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
|
||||
coverage: none
|
||||
ini-file: development
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Lint
|
||||
run: composer run lint
|
||||
run: cd php && composer run lint
|
||||
|
||||
summary:
|
||||
permissions:
|
||||
|
||||
@@ -30,99 +30,11 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version: 24.15.0
|
||||
|
||||
- name: Install dependencies
|
||||
run: cd php/tests && npm ci
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: cd php/tests && npx playwright install --with-deps chromium
|
||||
|
||||
- name: Set up php 8.5
|
||||
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.37.0
|
||||
with:
|
||||
extensions: apcu
|
||||
php-version: 8.5
|
||||
coverage: none
|
||||
ini-file: development
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Adjust some things and fix permissions
|
||||
run: |
|
||||
cd php
|
||||
rm -r ./data
|
||||
rm -r ./session
|
||||
composer install --no-dev
|
||||
composer clear-cache
|
||||
sudo chmod 777 -R ../
|
||||
|
||||
- name: Start fresh development server
|
||||
run: |
|
||||
docker rm --force nextcloud-aio-{mastercontainer,apache,notify-push,nextcloud,redis,database,domaincheck,whiteboard,imaginary,talk,collabora,borgbackup} || true
|
||||
docker volume rm nextcloud_aio_{mastercontainer,apache,database,database_dump,nextcloud,nextcloud_data,redis,backup_cache,elasticsearch} || true
|
||||
docker pull ghcr.io/nextcloud-releases/all-in-one:develop
|
||||
docker run \
|
||||
-d \
|
||||
--init \
|
||||
--name nextcloud-aio-mastercontainer \
|
||||
--restart always \
|
||||
--publish 8080:8080 \
|
||||
--volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
|
||||
--volume ./php:/var/www/docker-aio/php \
|
||||
--volume ./Containers/mastercontainer/internal.Caddyfile:/internal.Caddyfile \
|
||||
--volume ./Containers/mastercontainer/headers.Caddyfile:/headers.Caddyfile \
|
||||
--volume ./Containers/mastercontainer/start.sh:/start.sh \
|
||||
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
|
||||
--env SKIP_DOMAIN_VALIDATION=true \
|
||||
--env APACHE_PORT=11000 \
|
||||
ghcr.io/nextcloud-releases/all-in-one:develop
|
||||
echo Waiting for 10 seconds for the development container to start ...
|
||||
sleep 10
|
||||
|
||||
- name: Run Playwright tests for initial setup
|
||||
run: |
|
||||
cd php/tests
|
||||
export DEBUG=pw:api
|
||||
if ! npx playwright test tests/initial-setup.spec.js; then
|
||||
docker logs nextcloud-aio-mastercontainer
|
||||
docker logs nextcloud-aio-borgbackup
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Start fresh development server
|
||||
run: |
|
||||
docker rm --force nextcloud-aio-{mastercontainer,apache,notify-push,nextcloud,redis,database,domaincheck,whiteboard,imaginary,talk,collabora,borgbackup} || true
|
||||
docker volume rm nextcloud_aio_{mastercontainer,apache,database,database_dump,nextcloud,nextcloud_data,redis,backup_cache,elasticsearch} || true
|
||||
docker run \
|
||||
-d \
|
||||
--init \
|
||||
--name nextcloud-aio-mastercontainer \
|
||||
--restart always \
|
||||
--publish 8080:8080 \
|
||||
--volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
|
||||
--volume ./php:/var/www/docker-aio/php \
|
||||
--volume ./Containers/mastercontainer/internal.Caddyfile:/internal.Caddyfile \
|
||||
--volume ./Containers/mastercontainer/headers.Caddyfile:/headers.Caddyfile \
|
||||
--volume ./Containers/mastercontainer/start.sh:/start.sh \
|
||||
--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
|
||||
run: ./php/tests/run.sh ./tests/initial-setup.spec.js
|
||||
|
||||
- name: Run Playwright tests for backup restore
|
||||
run: |
|
||||
cd php/tests
|
||||
export DEBUG=pw:api
|
||||
if ! npx playwright test tests/restore-instance.spec.js; then
|
||||
docker logs nextcloud-aio-mastercontainer
|
||||
docker logs nextcloud-aio-borgbackup
|
||||
exit 1
|
||||
fi
|
||||
run: ./php/tests/run.sh ./tests/restore-instance.spec.js
|
||||
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: ${{ !cancelled() }}
|
||||
|
||||
@@ -15,72 +15,15 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
||||
with:
|
||||
node-version: 24.15.0
|
||||
|
||||
- name: Install dependencies
|
||||
run: cd php/tests && npm ci
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: cd php/tests && npx playwright install --with-deps chromium
|
||||
|
||||
- name: Start fresh development server
|
||||
run: |
|
||||
docker rm --force nextcloud-aio-{mastercontainer,apache,notify-push,nextcloud,redis,database,domaincheck,whiteboard,imaginary,talk,collabora,borgbackup} || true
|
||||
docker volume rm nextcloud_aio_{mastercontainer,apache,database,database_dump,nextcloud,nextcloud_data,redis,backup_cache,elasticsearch} || true
|
||||
docker pull ghcr.io/nextcloud-releases/all-in-one:develop
|
||||
docker run \
|
||||
-d \
|
||||
--init \
|
||||
--name nextcloud-aio-mastercontainer \
|
||||
--restart always \
|
||||
--publish 8080:8080 \
|
||||
--volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
|
||||
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
|
||||
--env SKIP_DOMAIN_VALIDATION=true \
|
||||
--env APACHE_PORT=11000 \
|
||||
ghcr.io/nextcloud-releases/all-in-one:develop
|
||||
echo Waiting for 10 seconds for the development container to start ...
|
||||
sleep 10
|
||||
|
||||
- name: Run Playwright tests for initial setup
|
||||
run: |
|
||||
cd php/tests
|
||||
export DEBUG=pw:api
|
||||
if ! npx playwright test tests/initial-setup.spec.js; then
|
||||
docker logs nextcloud-aio-mastercontainer
|
||||
docker logs nextcloud-aio-borgbackup
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Start fresh development server
|
||||
run: |
|
||||
docker rm --force nextcloud-aio-{mastercontainer,apache,notify-push,nextcloud,redis,database,domaincheck,whiteboard,imaginary,talk,collabora,borgbackup} || true
|
||||
docker volume rm nextcloud_aio_{mastercontainer,apache,database,database_dump,nextcloud,nextcloud_data,redis,backup_cache,elasticsearch} || true
|
||||
docker run \
|
||||
-d \
|
||||
--init \
|
||||
--name nextcloud-aio-mastercontainer \
|
||||
--restart always \
|
||||
--publish 8080:8080 \
|
||||
--volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
|
||||
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
|
||||
--env SKIP_DOMAIN_VALIDATION=false \
|
||||
--env APACHE_PORT=11000 \
|
||||
ghcr.io/nextcloud-releases/all-in-one:develop
|
||||
echo Waiting for 10 seconds for the development container to start ...
|
||||
sleep 10
|
||||
env:
|
||||
TEST_CODE_FROM_IMAGE: yes
|
||||
run: ./run.sh ./tests/initial-setup.spec.js
|
||||
|
||||
- name: Run Playwright tests for backup restore
|
||||
run: |
|
||||
cd php/tests
|
||||
export DEBUG=pw:api
|
||||
if ! npx playwright test tests/restore-instance.spec.js; then
|
||||
docker logs nextcloud-aio-mastercontainer
|
||||
docker logs nextcloud-aio-borgbackup
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
TEST_CODE_FROM_IMAGE: yes
|
||||
run: ./php/tests/run.sh ./tests/restore-instance.spec.js
|
||||
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: ${{ !cancelled() }}
|
||||
|
||||
+19
-23
@@ -8,7 +8,15 @@
|
||||
|
||||
name: Static analysis
|
||||
|
||||
on: pull_request
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'php/**'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'php/**'
|
||||
|
||||
concurrency:
|
||||
group: psalm-${{ github.head_ref || github.run_id }}
|
||||
@@ -28,32 +36,20 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Get php version
|
||||
id: versions
|
||||
uses: icewind1991/nextcloud-version-matrix@8a7bac6300b2f0f3100088b297995a229558ddba # v1.3.2
|
||||
|
||||
- name: Check enforcement of minimum PHP version ${{ steps.versions.outputs.php-min }} in psalm.xml
|
||||
run: grep 'phpVersion="${{ steps.versions.outputs.php-min }}' psalm.xml
|
||||
|
||||
- name: Set up php${{ steps.versions.outputs.php-available }}
|
||||
uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # 2.37.1
|
||||
- name: Set up php
|
||||
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.37.0
|
||||
with:
|
||||
php-version: ${{ steps.versions.outputs.php-available }}
|
||||
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
|
||||
php-version: 8.5
|
||||
extensions: apcu
|
||||
coverage: none
|
||||
ini-file: development
|
||||
# Temporary workaround for missing pcntl_* in PHP 8.3
|
||||
ini-values: disable_functions=
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install dependencies
|
||||
- name: Install dependencies and run psalm
|
||||
run: |
|
||||
composer remove nextcloud/ocp --dev --no-scripts
|
||||
composer i
|
||||
|
||||
- name: Install nextcloud/ocp
|
||||
run: composer require --dev nextcloud/ocp:dev-${{ steps.versions.outputs.branches-max }} --ignore-platform-reqs --with-dependencies
|
||||
|
||||
- name: Run coding standards check
|
||||
run: composer run psalm -- --threads=1 --monochrome --no-progress --output-format=github
|
||||
set -x
|
||||
cd php
|
||||
composer install
|
||||
composer run psalm
|
||||
|
||||
@@ -26,7 +26,6 @@ jobs:
|
||||
matrix:
|
||||
branches:
|
||||
- ${{ github.event.repository.default_branch }}
|
||||
- 'stable34'
|
||||
- 'stable33'
|
||||
- 'stable32'
|
||||
|
||||
@@ -123,7 +122,7 @@ jobs:
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
|
||||
with:
|
||||
token: ${{ secrets.COMMAND_BOT_WORKFLOWS }}
|
||||
token: ${{ secrets.COMMAND_BOT_WORKFLOWS }} # zizmor: ignore[secrets-outside-env]
|
||||
commit-message: 'ci(actions): Update workflow templates from organization template repository'
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: nextcloud-command <nextcloud-command@users.noreply.github.com>
|
||||
|
||||
@@ -47,14 +47,7 @@ http://{$APACHE_HOST}.nextcloud-aio:23973, # For Collabora callback and WOPI req
|
||||
uri strip_prefix /onlyoffice
|
||||
reverse_proxy {$ONLYOFFICE_HOST}:80 {
|
||||
header_up X-Forwarded-Host {http.request.hostport}/onlyoffice
|
||||
}
|
||||
}
|
||||
|
||||
# EuroOffice
|
||||
route /eurooffice/* {
|
||||
uri strip_prefix /eurooffice
|
||||
reverse_proxy {$EUROOFFICE_HOST}:80 {
|
||||
header_up X-Forwarded-Host {http.request.hostport}/eurooffice
|
||||
header_up X-Forwarded-Proto https
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM caddy:2.11.4-alpine AS caddy
|
||||
FROM caddy:2.11.3-alpine AS caddy
|
||||
|
||||
# From https://github.com/docker-library/httpd/blob/master/2.4/alpine/Dockerfile
|
||||
FROM httpd:2.4.67-alpine3.23
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
# From a file located probably somewhere here: https://github.com/CollaboraOnline/online/blob/master/docker/from-packages/Dockerfile
|
||||
FROM collabora/code:26.04.1.3.1
|
||||
FROM collabora/code:25.04.10.3.1
|
||||
|
||||
USER root
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM haproxy:3.4.0-alpine
|
||||
FROM haproxy:3.3.10-alpine
|
||||
|
||||
# hadolint ignore=DL3002
|
||||
USER root
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM ghcr.io/euro-office/documentserver:v9.3.1-beta.1
|
||||
|
||||
# USER root is probably used
|
||||
|
||||
COPY --chmod=775 healthcheck.sh /healthcheck.sh
|
||||
|
||||
HEALTHCHECK --start-period=60s --retries=9 CMD /healthcheck.sh
|
||||
LABEL com.centurylinklabs.watchtower.enable="false" \
|
||||
wud.watch="false" \
|
||||
dockhand.update="false" \
|
||||
org.opencontainers.image.title="EuroOffice for Nextcloud AIO" \
|
||||
org.opencontainers.image.description="EuroOffice Document Server for Nextcloud All-in-One" \
|
||||
org.opencontainers.image.url="https://github.com/nextcloud/all-in-one" \
|
||||
org.opencontainers.image.source="https://github.com/nextcloud/all-in-one" \
|
||||
org.opencontainers.image.vendor="Nextcloud" \
|
||||
org.opencontainers.image.documentation="https://github.com/nextcloud/all-in-one/blob/main/readme.md"
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$AIO_LOG_LEVEL" = 'debug' ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
nc -z 127.0.0.1 80 || exit 1
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM golang:1.26.4-alpine3.23 AS go
|
||||
FROM golang:1.26.3-alpine3.23 AS go
|
||||
|
||||
ENV IMAGINARY_HASH=6a274b488759a896aff02f52afee6e50b5e3a3ee
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ FROM docker:29.5.2-cli AS docker
|
||||
ARG CADDY_REMOTE_HOST_HASH=e80a9931765a8dbcbb47db415863387f0df0e1b3
|
||||
|
||||
# Caddy is a requirement
|
||||
FROM caddy:2.11.4-builder-alpine AS caddy
|
||||
FROM caddy:2.11.3-builder-alpine AS caddy
|
||||
RUN set -ex; \
|
||||
xcaddy build --with github.com/muety/caddy-remote-host@"$CADDY_REMOTE_HOST_HASH"; \
|
||||
/usr/bin/caddy list-modules
|
||||
|
||||
@@ -2,5 +2,4 @@
|
||||
$CONFIG = array (
|
||||
'one-click-instance' => true,
|
||||
'one-click-instance.user-limit' => 100,
|
||||
'update_channel' => 'stable',
|
||||
);
|
||||
|
||||
@@ -419,12 +419,41 @@ EOF
|
||||
|
||||
# AIO update to latest start # Do not remove or change this line!
|
||||
if [ "$INSTALL_LATEST_MAJOR" = yes ]; then
|
||||
if ! bash /upgrade-latest-major.sh; then
|
||||
echo "Upgrade to latest major version failed! Check the output above for details."
|
||||
php /var/www/html/occ config:system:set updatedirectory --value="/nc-updater"
|
||||
INSTALLED_AT="$(php /var/www/html/occ config:app:get core installedat)"
|
||||
if [ -n "${INSTALLED_AT}" ]; then
|
||||
# Set the installdat to 00 which will allow to skip staging and install the next major directly
|
||||
# shellcheck disable=SC2001
|
||||
INSTALLED_AT="$(echo "${INSTALLED_AT}" | sed "s|[0-9][0-9]$|00|")"
|
||||
php /var/www/html/occ config:app:set core installedat --value="${INSTALLED_AT}"
|
||||
fi
|
||||
php /var/www/html/updater/updater.phar --no-interaction --no-backup
|
||||
if ! php /var/www/html/occ -V || php /var/www/html/occ status | grep maintenance | grep -q 'true'; then
|
||||
echo "Installation of Nextcloud failed!"
|
||||
touch "$NEXTCLOUD_DATA_DIR/install.failed"
|
||||
exit 1
|
||||
fi
|
||||
# shellcheck disable=SC2016
|
||||
installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')"
|
||||
INSTALLED_MAJOR="${installed_version%%.*}"
|
||||
IMAGE_MAJOR="${image_version%%.*}"
|
||||
# If a valid upgrade path, trigger the Nextcloud built-in Updater
|
||||
if ! [ "$INSTALLED_MAJOR" -gt "$IMAGE_MAJOR" ]; then
|
||||
php /var/www/html/updater/updater.phar --no-interaction --no-backup
|
||||
if ! php /var/www/html/occ -V || php /var/www/html/occ status | grep maintenance | grep -q 'true'; then
|
||||
echo "Installation of Nextcloud failed!"
|
||||
# TODO: Add a hint here about what to do / where to look / updater.log?
|
||||
touch "$NEXTCLOUD_DATA_DIR/install.failed"
|
||||
exit 1
|
||||
fi
|
||||
# shellcheck disable=SC2016
|
||||
installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')"
|
||||
fi
|
||||
php /var/www/html/occ config:system:set updatechecker --type=bool --value=true
|
||||
php /var/www/html/occ app:enable nextcloud-aio --force
|
||||
php /var/www/html/occ db:add-missing-columns
|
||||
php /var/www/html/occ db:add-missing-primary-keys
|
||||
yes | php /var/www/html/occ db:convert-filecache-bigint
|
||||
fi
|
||||
# AIO update to latest end # Do not remove or change this line!
|
||||
|
||||
@@ -867,58 +896,6 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
# EuroOffice
|
||||
if [ "$EUROOFFICE_ENABLED" = 'yes' ]; then
|
||||
# Determine EuroOffice port based on host pattern
|
||||
if echo "$EUROOFFICE_HOST" | grep -q "nextcloud-.*-eurooffice"; then
|
||||
EUROOFFICE_PORT=80
|
||||
else
|
||||
EUROOFFICE_PORT=443
|
||||
fi
|
||||
|
||||
count=0
|
||||
while ! nc -z "$EUROOFFICE_HOST" "$EUROOFFICE_PORT" && [ "$count" -lt 90 ]; do
|
||||
echo "Waiting for EuroOffice to become available..."
|
||||
count=$((count+5))
|
||||
sleep 5
|
||||
done
|
||||
if [ "$count" -ge 90 ]; then
|
||||
bash /notify.sh "EuroOffice did not start in time!" "Skipping initialization and disabling eurooffice app."
|
||||
php /var/www/html/occ app:disable eurooffice
|
||||
else
|
||||
# Install or enable EuroOffice app as needed
|
||||
if ! [ -d "/var/www/html/custom_apps/eurooffice" ]; then
|
||||
php /var/www/html/occ app:install eurooffice
|
||||
elif [ "$(php /var/www/html/occ config:app:get eurooffice enabled)" != "yes" ]; then
|
||||
php /var/www/html/occ app:enable eurooffice
|
||||
elif [ "$SKIP_UPDATE" != 1 ]; then
|
||||
php /var/www/html/occ app:update eurooffice
|
||||
fi
|
||||
|
||||
# Set EuroOffice configuration
|
||||
php /var/www/html/occ config:system:set eurooffice editors_check_interval --value="0" --type=integer
|
||||
php /var/www/html/occ config:system:set eurooffice jwt_secret --value="$EUROOFFICE_SECRET"
|
||||
php /var/www/html/occ config:app:set eurooffice jwt_secret --value="$EUROOFFICE_SECRET"
|
||||
php /var/www/html/occ config:system:set eurooffice jwt_header --value="AuthorizationJwt"
|
||||
|
||||
# Adjust the EuroOffice host if using internal pattern
|
||||
if echo "$EUROOFFICE_HOST" | grep -q "nextcloud-.*-eurooffice"; then
|
||||
EUROOFFICE_HOST="$NC_DOMAIN/eurooffice"
|
||||
export EUROOFFICE_HOST
|
||||
fi
|
||||
|
||||
php /var/www/html/occ config:app:set eurooffice DocumentServerUrl --value="https://$EUROOFFICE_HOST"
|
||||
fi
|
||||
else
|
||||
# Remove EuroOffice app if disabled and removal is requested
|
||||
if [ "$REMOVE_DISABLED_APPS" = yes ] && \
|
||||
[ -d "/var/www/html/custom_apps/eurooffice" ] && \
|
||||
[ -n "$EUROOFFICE_SECRET" ] && \
|
||||
[ "$(php /var/www/html/occ config:system:get eurooffice jwt_secret)" = "$EUROOFFICE_SECRET" ]; then
|
||||
php /var/www/html/occ app:remove eurooffice
|
||||
fi
|
||||
fi
|
||||
|
||||
# Talk
|
||||
if [ "$TALK_ENABLED" = 'yes' ]; then
|
||||
set -x
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
PHP_CLI="php"
|
||||
if [[ "$EUID" = 0 ]]; then
|
||||
PHP_CLI="sudo -u www-data -E $PHP_CLI"
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
image_version="$($PHP_CLI -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')"
|
||||
export IMAGE_MAJOR="${image_version%%.*}"
|
||||
|
||||
$PHP_CLI /var/www/html/occ config:system:set updatedirectory --value="/nc-updater"
|
||||
INSTALLED_AT="$($PHP_CLI /var/www/html/occ config:app:get core installedat)"
|
||||
if [ -n "${INSTALLED_AT}" ]; then
|
||||
# Set the installedat to 00 which will allow to skip staging and install the next major directly
|
||||
# shellcheck disable=SC2001
|
||||
INSTALLED_AT="$(echo "${INSTALLED_AT}" | sed "s|[0-9][0-9]$|00|")"
|
||||
$PHP_CLI /var/www/html/occ config:app:set core installedat --value="${INSTALLED_AT}"
|
||||
fi
|
||||
$PHP_CLI /var/www/html/updater/updater.phar --no-interaction --no-backup
|
||||
if ! $PHP_CLI /var/www/html/occ -V || $PHP_CLI /var/www/html/occ status | grep maintenance | grep -q 'true'; then
|
||||
echo "Installation of Nextcloud failed!"
|
||||
touch "$NEXTCLOUD_DATA_DIR/install.failed"
|
||||
exit 1
|
||||
fi
|
||||
# shellcheck disable=SC2016
|
||||
installed_version="$($PHP_CLI -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')"
|
||||
export INSTALLED_MAJOR="${installed_version%%.*}"
|
||||
# If a valid upgrade path, trigger the Nextcloud built-in Updater
|
||||
if ! $PHP_CLI -r "version_compare(getenv('INSTALLED_MAJOR'), getenv('IMAGE_MAJOR'), '>') || exit(1);"; then
|
||||
$PHP_CLI /var/www/html/updater/updater.phar --no-interaction --no-backup
|
||||
if ! $PHP_CLI /var/www/html/occ -V || $PHP_CLI /var/www/html/occ status | grep maintenance | grep -q 'true'; then
|
||||
echo "Installation of Nextcloud failed!"
|
||||
# TODO: Add a hint here about what to do / where to look / updater.log?
|
||||
touch "$NEXTCLOUD_DATA_DIR/install.failed"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
$PHP_CLI /var/www/html/occ config:system:set updatechecker --type=bool --value=true
|
||||
$PHP_CLI /var/www/html/occ app:enable nextcloud-aio --force
|
||||
$PHP_CLI /var/www/html/occ db:add-missing-columns
|
||||
$PHP_CLI /var/www/html/occ db:add-missing-primary-keys
|
||||
yes | $PHP_CLI /var/www/html/occ db:convert-filecache-bigint
|
||||
@@ -4,4 +4,4 @@ if [ "$AIO_LOG_LEVEL" = 'debug' ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
nc -z 127.0.0.1 1234 || exit 1
|
||||
nc -z 127.0.0.1 1234 || nc -z ::1 1234 || exit 1
|
||||
|
||||
@@ -58,13 +58,21 @@ extensionaudio = .m4a
|
||||
extensionvideo = .mp4"
|
||||
fi
|
||||
|
||||
# Detect IPv6 availability to choose the right listen address
|
||||
RECORDING_LISTEN="0.0.0.0:1234"
|
||||
if ! grep -q "1" /sys/module/ipv6/parameters/disable 2>/dev/null \
|
||||
&& ! grep -q "1" /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null \
|
||||
&& ! grep -q "1" /proc/sys/net/ipv6/conf/default/disable_ipv6 2>/dev/null; then
|
||||
RECORDING_LISTEN="[::]:1234"
|
||||
fi
|
||||
|
||||
cat << RECORDING_CONF > "/conf/recording.conf"
|
||||
[logs]
|
||||
# 30 means Warning
|
||||
level = ${TALK_RECORDING_LOG_LEVEL}
|
||||
|
||||
[http]
|
||||
listen = 0.0.0.0:1234
|
||||
listen = ${RECORDING_LISTEN}
|
||||
|
||||
[backend]
|
||||
allowall = ${ALLOW_ALL}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM nats:2.14.2-scratch AS nats
|
||||
FROM nats:2.14.1-scratch AS nats
|
||||
FROM eturnal/eturnal:1.12.2-alpine AS eturnal
|
||||
FROM strukturag/nextcloud-spreed-signaling:2.1.1 AS signaling
|
||||
FROM alpine:3.23.4 AS janus
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM golang:1.26.4-alpine3.23 AS go
|
||||
FROM golang:1.26.3-alpine3.23 AS go
|
||||
|
||||
ENV WATCHTOWER_COMMIT_HASH=9d0048403a7242943084bede951f6f966f7691ba
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ for variable in "${DEPLOYMENTS[@]}"; do
|
||||
sed -i "/^ spec:/r /tmp/initcontainers.clamav" "$variable"
|
||||
elif echo "$variable" | grep -q "nextcloud-deployment.yaml"; then
|
||||
sed -i "/^ spec:/r /tmp/initcontainers.nextcloud" "$variable"
|
||||
elif echo "$variable" | grep -q "fulltextsearch" || echo "$variable" | grep -q "onlyoffice" || echo "$variable" | grep -q "eurooffice" || echo "$variable" | grep -q "collabora"; then
|
||||
elif echo "$variable" | grep -q "fulltextsearch" || echo "$variable" | grep -q "onlyoffice" || echo "$variable" | grep -q "collabora"; then
|
||||
sed -i "/^ spec:/r /tmp/initcontainers" "$variable"
|
||||
fi
|
||||
volumeNames="$(grep -A1 mountPath "$variable" | grep -v mountPath | sed 's|.*name: ||' | sed '/^--$/d')"
|
||||
@@ -499,7 +499,7 @@ cat << EOL > /tmp/security.conf
|
||||
{{- end }}
|
||||
EOL
|
||||
# shellcheck disable=SC1083
|
||||
find ./ \( -not -name '*collabora-deployment.yaml*' -not -name '*apache-deployment.yaml*' -not -name '*onlyoffice-deployment.yaml*' -not -name '*eurooffice-deployment.yaml*' -name "*deployment.yaml" \) -exec sed -i "/^ securityContext:$/r /tmp/security.conf" \{} \;
|
||||
find ./ \( -not -name '*collabora-deployment.yaml*' -not -name '*apache-deployment.yaml*' -not -name '*onlyoffice-deployment.yaml*' -name "*deployment.yaml" \) -exec sed -i "/^ securityContext:$/r /tmp/security.conf" \{} \;
|
||||
|
||||
# shellcheck disable=SC1083
|
||||
find ./ -name '*collabora-deployment.yaml*' -exec sed -i "/ADDITIONAL_COLLABORA_OPTIONS_PLACEHOLDER/d" \{} \;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
"documentation": "https://github.com/nextcloud/all-in-one/discussions/2105",
|
||||
"depends_on": [
|
||||
"nextcloud-aio-onlyoffice",
|
||||
"nextcloud-aio-eurooffice",
|
||||
"nextcloud-aio-collabora",
|
||||
"nextcloud-aio-talk",
|
||||
"nextcloud-aio-notify-push",
|
||||
@@ -48,7 +47,6 @@
|
||||
"APACHE_PORT=%APACHE_PORT%",
|
||||
"AIO_LOG_LEVEL=%AIO_LOG_LEVEL%",
|
||||
"ONLYOFFICE_HOST=nextcloud-aio-onlyoffice",
|
||||
"EUROOFFICE_HOST=nextcloud-aio-eurooffice",
|
||||
"TZ=%TIMEZONE%",
|
||||
"APACHE_MAX_SIZE=%APACHE_MAX_SIZE%",
|
||||
"APACHE_MAX_TIME=%NEXTCLOUD_MAX_TIME%",
|
||||
@@ -225,7 +223,6 @@
|
||||
"TURN_SECRET=%TURN_SECRET%",
|
||||
"SIGNALING_SECRET=%SIGNALING_SECRET%",
|
||||
"ONLYOFFICE_SECRET=%ONLYOFFICE_SECRET%",
|
||||
"EUROOFFICE_SECRET=%EUROOFFICE_SECRET%",
|
||||
"AIO_URL=%AIO_URL%",
|
||||
"AIO_LOG_LEVEL=%AIO_LOG_LEVEL%",
|
||||
"NC_AIO_VERSION=v%AIO_VERSION%",
|
||||
@@ -233,12 +230,10 @@
|
||||
"CLAMAV_ENABLED=%CLAMAV_ENABLED%",
|
||||
"CLAMAV_HOST=nextcloud-aio-clamav",
|
||||
"ONLYOFFICE_ENABLED=%ONLYOFFICE_ENABLED%",
|
||||
"EUROOFFICE_ENABLED=%EUROOFFICE_ENABLED%",
|
||||
"COLLABORA_ENABLED=%COLLABORA_ENABLED%",
|
||||
"COLLABORA_HOST=nextcloud-aio-collabora",
|
||||
"TALK_ENABLED=%TALK_ENABLED%",
|
||||
"ONLYOFFICE_HOST=nextcloud-aio-onlyoffice",
|
||||
"EUROOFFICE_HOST=nextcloud-aio-eurooffice",
|
||||
"UPDATE_NEXTCLOUD_APPS=%UPDATE_NEXTCLOUD_APPS%",
|
||||
"TZ=%TIMEZONE%",
|
||||
"TALK_PORT=%TALK_PORT%",
|
||||
@@ -362,7 +357,6 @@
|
||||
"secrets": [
|
||||
"REDIS_PASSWORD",
|
||||
"ONLYOFFICE_SECRET",
|
||||
"EUROOFFICE_SECRET",
|
||||
"RECORDING_SECRET"
|
||||
],
|
||||
"restart": "unless-stopped",
|
||||
@@ -764,50 +758,6 @@
|
||||
"NET_RAW"
|
||||
]
|
||||
},
|
||||
{
|
||||
"container_name": "nextcloud-aio-eurooffice",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"display_name": "EuroOffice",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-eurooffice",
|
||||
"init": true,
|
||||
"healthcheck": {
|
||||
"start_period": "60s",
|
||||
"test": "/healthcheck.sh",
|
||||
"interval": "30s",
|
||||
"timeout": "30s",
|
||||
"start_interval": "5s",
|
||||
"retries": 9
|
||||
},
|
||||
"expose": [
|
||||
"80"
|
||||
],
|
||||
"internal_port": "80",
|
||||
"environment": [
|
||||
"AIO_LOG_LEVEL=%AIO_LOG_LEVEL%",
|
||||
"LOG_LEVEL=%AIO_LOG_LEVEL%",
|
||||
"TZ=%TIMEZONE%",
|
||||
"JWT_ENABLED=true",
|
||||
"JWT_HEADER=AuthorizationJwt",
|
||||
"JWT_SECRET=%EUROOFFICE_SECRET%"
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
"source": "nextcloud_aio_eurooffice",
|
||||
"destination": "/var/lib/euro-office",
|
||||
"writeable": true
|
||||
}
|
||||
],
|
||||
"secrets": [
|
||||
"EUROOFFICE_SECRET"
|
||||
],
|
||||
"restart": "unless-stopped",
|
||||
"profiles": [
|
||||
"eurooffice"
|
||||
],
|
||||
"cap_drop": [
|
||||
"NET_RAW"
|
||||
]
|
||||
},
|
||||
{
|
||||
"container_name": "nextcloud-aio-imaginary",
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
|
||||
@@ -22,11 +22,9 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
// Office suite radio buttons
|
||||
const collaboraRadio = document.getElementById('office-collabora');
|
||||
const onlyofficeRadio = document.getElementById('office-onlyoffice');
|
||||
const euroofficeRadio = document.getElementById('office-eurooffice');
|
||||
const noneRadio = document.getElementById('office-none');
|
||||
const collaboraHidden = document.getElementById('collabora');
|
||||
const onlyofficeHidden = document.getElementById('onlyoffice');
|
||||
const euroofficeHidden = document.getElementById('eurooffice');
|
||||
let initialOfficeSelection = null;
|
||||
|
||||
optionsContainersCheckboxes.forEach(checkbox => {
|
||||
@@ -38,13 +36,11 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
});
|
||||
|
||||
// Store initial office suite selection
|
||||
if (collaboraRadio && onlyofficeRadio && euroofficeRadio && noneRadio) {
|
||||
if (collaboraRadio && onlyofficeRadio && noneRadio) {
|
||||
if (collaboraRadio.checked) {
|
||||
initialOfficeSelection = 'collabora';
|
||||
} else if (onlyofficeRadio.checked) {
|
||||
initialOfficeSelection = 'onlyoffice';
|
||||
} else if (euroofficeRadio.checked) {
|
||||
initialOfficeSelection = 'eurooffice';
|
||||
} else {
|
||||
initialOfficeSelection = 'none';
|
||||
}
|
||||
@@ -61,28 +57,20 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
});
|
||||
|
||||
// Check office suite changes and sync to hidden inputs
|
||||
if (collaboraRadio && onlyofficeRadio && euroofficeRadio && noneRadio && collaboraHidden && onlyofficeHidden && euroofficeHidden) {
|
||||
if (collaboraRadio && onlyofficeRadio && noneRadio && collaboraHidden && onlyofficeHidden) {
|
||||
let currentOfficeSelection = null;
|
||||
if (collaboraRadio.checked) {
|
||||
currentOfficeSelection = 'collabora';
|
||||
collaboraHidden.value = 'on';
|
||||
onlyofficeHidden.value = '';
|
||||
euroofficeHidden.value = '';
|
||||
} else if (onlyofficeRadio.checked) {
|
||||
currentOfficeSelection = 'onlyoffice';
|
||||
collaboraHidden.value = '';
|
||||
onlyofficeHidden.value = 'on';
|
||||
euroofficeHidden.value = '';
|
||||
} else if (euroofficeRadio.checked) {
|
||||
currentOfficeSelection = 'eurooffice';
|
||||
collaboraHidden.value = '';
|
||||
onlyofficeHidden.value = '';
|
||||
euroofficeHidden.value = 'on';
|
||||
} else {
|
||||
currentOfficeSelection = 'none';
|
||||
collaboraHidden.value = '';
|
||||
onlyofficeHidden.value = '';
|
||||
euroofficeHidden.value = '';
|
||||
}
|
||||
|
||||
if (currentOfficeSelection !== initialOfficeSelection) {
|
||||
@@ -156,10 +144,9 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
handleTalkVisibility(); // Ensure talk-recording is correctly initialized
|
||||
|
||||
// Add event listeners for office suite radio buttons
|
||||
if (collaboraRadio && onlyofficeRadio && euroofficeRadio && noneRadio) {
|
||||
if (collaboraRadio && onlyofficeRadio && noneRadio) {
|
||||
collaboraRadio.addEventListener('change', checkForOptionContainerChanges);
|
||||
onlyofficeRadio.addEventListener('change', checkForOptionContainerChanges);
|
||||
euroofficeRadio.addEventListener('change', checkForOptionContainerChanges);
|
||||
noneRadio.addEventListener('change', checkForOptionContainerChanges);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,12 +27,6 @@ document.addEventListener("DOMContentLoaded", function(event) {
|
||||
const onlyoffice = document.getElementById("office-onlyoffice");
|
||||
onlyoffice.disabled = true;
|
||||
|
||||
// EuroOffice
|
||||
const eurooffice = document.getElementById("office-eurooffice");
|
||||
if (eurooffice) {
|
||||
eurooffice.disabled = true;
|
||||
}
|
||||
|
||||
// Imaginary
|
||||
let imaginary = document.getElementById("imaginary");
|
||||
imaginary.disabled = true;
|
||||
|
||||
@@ -104,7 +104,6 @@ $app->post('/api/docker/backup-test', AIO\Controller\DockerController::class . '
|
||||
$app->post('/api/docker/restore', AIO\Controller\DockerController::class . ':StartBackupContainerRestore');
|
||||
$app->post('/api/docker/stop', AIO\Controller\DockerController::class . ':StopContainer');
|
||||
$app->post('/api/docker/backup-reset-location', AIO\Controller\DockerController::class . ':DeleteBorgBackupConfig');
|
||||
$app->post('/api/docker/nextcloud-upgrade-to-latest-major', AIO\Controller\DockerController::class . ':RunNextcloudUpgradeToLatestMajor');
|
||||
$app->post('/api/docker/prune', AIO\Controller\DockerController::class . ':SystemPrune');
|
||||
$app->get('/api/docker/logs', AIO\Controller\DockerController::class . ':GetLogs');
|
||||
$app->post('/api/auth/login', AIO\Controller\LoginController::class . ':TryLogin');
|
||||
@@ -153,7 +152,6 @@ $app->get('/containers', function (Request $request, Response $response, array $
|
||||
'current_channel' => $dockerActionManager->GetCurrentChannel(),
|
||||
'is_clamav_enabled' => $configurationManager->isClamavEnabled,
|
||||
'is_onlyoffice_enabled' => $configurationManager->isOnlyofficeEnabled,
|
||||
'is_eurooffice_enabled' => $configurationManager->isEuroofficeEnabled,
|
||||
'is_collabora_enabled' => $configurationManager->isCollaboraEnabled,
|
||||
'is_talk_enabled' => $configurationManager->isTalkEnabled,
|
||||
'borg_restore_password' => $configurationManager->borgRestorePassword,
|
||||
|
||||
+4
-14
@@ -483,7 +483,7 @@ input[type="checkbox"]:disabled:not(:checked) + label {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
align-self: start;
|
||||
width: min(600px, calc(100vw - 4rem));
|
||||
width: min(700px, calc(100vw - 4rem));
|
||||
height: min(400px, calc(100vh - 14rem));
|
||||
border-radius: var(--border-radius-large);
|
||||
border: solid thin rgb(192, 192, 192);
|
||||
@@ -606,15 +606,13 @@ input[type="checkbox"]:disabled:not(:checked) + label {
|
||||
}
|
||||
|
||||
#office-collabora:checked + .office-card,
|
||||
#office-onlyoffice:checked + .office-card,
|
||||
#office-eurooffice:checked + .office-card {
|
||||
#office-onlyoffice:checked + .office-card {
|
||||
border-color: var(--color-nextcloud-blue);
|
||||
background: linear-gradient(135deg, rgba(0, 130, 201, 0.08) 0%, rgba(0, 130, 201, 0.02) 100%);
|
||||
}
|
||||
|
||||
[data-theme="dark"] #office-collabora:checked + .office-card,
|
||||
[data-theme="dark"] #office-onlyoffice:checked + .office-card,
|
||||
[data-theme="dark"] #office-eurooffice:checked + .office-card {
|
||||
[data-theme="dark"] #office-onlyoffice:checked + .office-card {
|
||||
background: linear-gradient(135deg, rgba(0, 145, 242, 0.15) 0%, rgba(0, 145, 242, 0.03) 100%);
|
||||
}
|
||||
|
||||
@@ -633,21 +631,13 @@ input[type="checkbox"]:disabled:not(:checked) + label {
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
|
||||
.office-powered-by {
|
||||
margin: 4px 0 0;
|
||||
font-size: 13px;
|
||||
color: var(--color-main-text);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.office-checkmark {
|
||||
flex-shrink: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#office-collabora:checked + .office-card .office-checkmark,
|
||||
#office-onlyoffice:checked + .office-card .office-checkmark,
|
||||
#office-eurooffice:checked + .office-card .office-checkmark {
|
||||
#office-onlyoffice:checked + .office-card .office-checkmark {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,10 +78,6 @@ readonly class ContainerDefinitionFetcher {
|
||||
if (!$this->configurationManager->isOnlyofficeEnabled) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($entry['container_name'] === 'nextcloud-aio-eurooffice') {
|
||||
if (!$this->configurationManager->isEuroofficeEnabled) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($entry['container_name'] === 'nextcloud-aio-collabora') {
|
||||
if (!$this->configurationManager->isCollaboraEnabled) {
|
||||
continue;
|
||||
@@ -198,10 +194,6 @@ readonly class ContainerDefinitionFetcher {
|
||||
if (!$this->configurationManager->isOnlyofficeEnabled) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($value === 'nextcloud-aio-eurooffice') {
|
||||
if (!$this->configurationManager->isEuroofficeEnabled) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($value === 'nextcloud-aio-collabora') {
|
||||
if (!$this->configurationManager->isCollaboraEnabled) {
|
||||
continue;
|
||||
|
||||
@@ -81,19 +81,12 @@ readonly class ConfigurationController {
|
||||
if ($officeSuiteChoice === 'collabora') {
|
||||
$this->configurationManager->isCollaboraEnabled = true;
|
||||
$this->configurationManager->isOnlyofficeEnabled = false;
|
||||
$this->configurationManager->isEuroofficeEnabled = false;
|
||||
} elseif ($officeSuiteChoice === 'onlyoffice') {
|
||||
$this->configurationManager->isCollaboraEnabled = false;
|
||||
$this->configurationManager->isOnlyofficeEnabled = true;
|
||||
$this->configurationManager->isEuroofficeEnabled = false;
|
||||
} elseif ($officeSuiteChoice === 'eurooffice') {
|
||||
$this->configurationManager->isCollaboraEnabled = false;
|
||||
$this->configurationManager->isOnlyofficeEnabled = false;
|
||||
$this->configurationManager->isEuroofficeEnabled = true;
|
||||
} else {
|
||||
$this->configurationManager->isCollaboraEnabled = false;
|
||||
$this->configurationManager->isOnlyofficeEnabled = false;
|
||||
$this->configurationManager->isEuroofficeEnabled = false;
|
||||
}
|
||||
$this->configurationManager->isClamavEnabled = isset($request->getParsedBody()['clamav']);
|
||||
$this->configurationManager->isTalkEnabled = isset($request->getParsedBody()['talk']);
|
||||
|
||||
@@ -14,7 +14,6 @@ use Slim\Psr7\NonBufferedBody;
|
||||
|
||||
readonly class DockerController {
|
||||
private const string TOP_CONTAINER = 'nextcloud-aio-apache';
|
||||
private const string LATEST_MAJOR_VERSION = '34';
|
||||
|
||||
public function __construct(
|
||||
private DockerActionManager $dockerActionManager,
|
||||
@@ -222,7 +221,7 @@ readonly class DockerController {
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['install_latest_major'])) {
|
||||
$installLatestMajor = self::LATEST_MAJOR_VERSION;
|
||||
$installLatestMajor = '34';
|
||||
} else {
|
||||
$installLatestMajor = '';
|
||||
}
|
||||
@@ -299,7 +298,7 @@ readonly class DockerController {
|
||||
}
|
||||
|
||||
if ($addToStreamingResponseBody !== null) {
|
||||
$addToStreamingResponseBody("Stopping container", $container);
|
||||
$addToStreamingResponseBody($container, "Stopping container");
|
||||
}
|
||||
|
||||
// Stop itself first and then all the dependencies
|
||||
@@ -334,30 +333,14 @@ readonly class DockerController {
|
||||
return $response->withStatus(201)->withHeader('Location', '.');
|
||||
}
|
||||
|
||||
public function RunNextcloudUpgradeToLatestMajor(Request $request, Response $response, array $args) : Response {
|
||||
$this->configurationManager->installLatestMajor = self::LATEST_MAJOR_VERSION;
|
||||
|
||||
// Get streaming response start and closure
|
||||
$nonbufResp = $this->startStreamingResponse($response);
|
||||
$addToStreamingResponseBody = $this->getAddToStreamingResponseBody($nonbufResp);
|
||||
|
||||
$this->dockerActionManager->RunNextcloudUpgradeToLatestMajor($addToStreamingResponseBody);
|
||||
|
||||
// We automatically reload after 10s so that the output can be read or copied if necessary
|
||||
$addToStreamingResponseBody("Automatically reloading the page after 10s.");
|
||||
sleep(10);
|
||||
|
||||
// End streaming response
|
||||
$this->finalizeStreamingResponse($nonbufResp);
|
||||
return $nonbufResp;
|
||||
}
|
||||
|
||||
public function SystemPrune(Request $request, Response $response, array $args) : Response {
|
||||
// Get streaming response start and closure
|
||||
$nonbufResp = $this->startStreamingResponse($response);
|
||||
|
||||
$body = $nonbufResp->getBody();
|
||||
$addToStreamingResponseBody = $this->getAddToStreamingResponseBody($nonbufResp);
|
||||
$addToStreamingResponseBody = function (string $message) use ($body) : void {
|
||||
$body->write("<div>$message</div>");
|
||||
};
|
||||
|
||||
$this->dockerActionManager->SystemPrune($addToStreamingResponseBody);
|
||||
|
||||
@@ -418,7 +401,7 @@ readonly class DockerController {
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="overlay-iframe">
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../style.css?v11" media="all" />
|
||||
<link rel="stylesheet" href="../../style.css?v9" media="all" />
|
||||
<script type="text/javascript" src="../../apply-theme.js?v1"></script>
|
||||
<script type="text/javascript" src="../../scroll-into-view.js"></script>
|
||||
</head>
|
||||
@@ -443,17 +426,12 @@ readonly class DockerController {
|
||||
return $nonbufResp;
|
||||
}
|
||||
|
||||
private function getAddToStreamingResponseBody(Response $nonbufResp) : \Closure {
|
||||
private function getAddToStreamingResponseBody(Response $nonbufResp) : ?\Closure {
|
||||
// Create a closure to pass around to the code, which should to the logging (because it e.g. decides
|
||||
// if it'll actually pull an image), but which should not need to know anything about the
|
||||
// wanted markup or formatting.
|
||||
$addToStreamingResponseBody = function (string $message, ?Container $container = null) use ($nonbufResp) : void {
|
||||
// Strip ANSI codes.
|
||||
$message = preg_replace('/\e[[][A-Za-z0-9];?[0-9]*m?/', '', $message);
|
||||
if ($container) {
|
||||
$message = "{$container->displayName}: {$message}";
|
||||
}
|
||||
$nonbufResp->getBody()->write("<div>" . htmlspecialchars("{$message}", ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . "</div>");
|
||||
$addToStreamingResponseBody = function (Container $container, string $message) use ($nonbufResp) : void {
|
||||
$nonbufResp->getBody()->write("<div>{$container->displayName}: {$message}</div>");
|
||||
};
|
||||
|
||||
return $addToStreamingResponseBody;
|
||||
|
||||
@@ -99,11 +99,6 @@ class ConfigurationManager
|
||||
set { $this->set('isOnlyofficeEnabled', $value); }
|
||||
}
|
||||
|
||||
public bool $isEuroofficeEnabled {
|
||||
get => $this->get('isEuroofficeEnabled', false);
|
||||
set { $this->set('isEuroofficeEnabled', $value); }
|
||||
}
|
||||
|
||||
public bool $isCollaboraEnabled {
|
||||
// Type-cast because old configs could have 1/0 for this key.
|
||||
get => (bool) $this->get('isCollaboraEnabled', true);
|
||||
@@ -1092,7 +1087,6 @@ class ConfigurationManager
|
||||
'CLAMAV_ENABLED' => $this->isClamavEnabled ? 'yes' : '',
|
||||
'TALK_RECORDING_ENABLED' => $this->isTalkRecordingEnabled ? 'yes' : '',
|
||||
'ONLYOFFICE_ENABLED' => $this->isOnlyofficeEnabled ? 'yes' : '',
|
||||
'EUROOFFICE_ENABLED' => $this->isEuroofficeEnabled ? 'yes' : '',
|
||||
'COLLABORA_ENABLED' => $this->isCollaboraEnabled ? 'yes' : '',
|
||||
'TALK_ENABLED' => $this->isTalkEnabled ? 'yes' : '',
|
||||
'UPDATE_NEXTCLOUD_APPS' => ($this->isDailyBackupRunning() && $this->areAutomaticUpdatesEnabled()) ? 'yes' : '',
|
||||
|
||||
@@ -12,7 +12,6 @@ use AIO\Data\DataConst;
|
||||
use AIO\Helper\NetworkHelper;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use GuzzleHttp\Psr7\Utils;
|
||||
use http\Env\Response;
|
||||
|
||||
readonly class DockerActionManager {
|
||||
@@ -49,7 +48,7 @@ readonly class DockerActionManager {
|
||||
public function GetContainerRunningState(Container $container): ContainerState {
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($container->identifier)));
|
||||
try {
|
||||
$response = $this->sendHttpRequest('GET', $url);
|
||||
$response = $this->guzzleClient->get($url);
|
||||
} catch (RequestException $e) {
|
||||
if ($e->getCode() === 404) {
|
||||
return ContainerState::ImageDoesNotExist;
|
||||
@@ -69,7 +68,7 @@ readonly class DockerActionManager {
|
||||
public function GetContainerRestartingState(Container $container): ContainerState {
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($container->identifier)));
|
||||
try {
|
||||
$response = $this->sendHttpRequest('GET', $url);
|
||||
$response = $this->guzzleClient->get($url);
|
||||
} catch (RequestException $e) {
|
||||
if ($e->getCode() === 404) {
|
||||
return ContainerState::ImageDoesNotExist;
|
||||
@@ -139,7 +138,7 @@ readonly class DockerActionManager {
|
||||
public function DeleteContainer(Container $container): void {
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s?v=true', urlencode($container->identifier)));
|
||||
try {
|
||||
$this->sendHttpRequest('DELETE', $url);
|
||||
$this->guzzleClient->delete($url);
|
||||
} catch (RequestException $e) {
|
||||
if ($e->getCode() !== 404) {
|
||||
throw $e;
|
||||
@@ -156,7 +155,7 @@ readonly class DockerActionManager {
|
||||
// Delete the borg cache volume
|
||||
$url = $this->BuildApiUrl('volumes/nextcloud_aio_backup_cache');
|
||||
try {
|
||||
$this->sendHttpRequest('DELETE', $url);
|
||||
$this->guzzleClient->delete($url);
|
||||
error_log('nextcloud_aio_backup_cache volume deleted successfully.');
|
||||
} catch (RequestException $e) {
|
||||
if ($e->getCode() !== 404) {
|
||||
@@ -175,7 +174,7 @@ readonly class DockerActionManager {
|
||||
urlencode($id),
|
||||
$since
|
||||
));
|
||||
$responseBody = (string)$this->sendHttpRequest('GET', $url)->getBody();
|
||||
$responseBody = (string)$this->guzzleClient->get($url)->getBody();
|
||||
|
||||
$response = "";
|
||||
$separator = "\r\n";
|
||||
@@ -195,9 +194,9 @@ readonly class DockerActionManager {
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/start', urlencode($container->identifier)));
|
||||
try {
|
||||
if ($addToStreamingResponseBody !== null) {
|
||||
$addToStreamingResponseBody("Starting container", $container);
|
||||
$addToStreamingResponseBody($container, "Starting container");
|
||||
}
|
||||
$this->sendHttpRequest('POST', $url);
|
||||
$this->guzzleClient->post($url);
|
||||
} catch (RequestException $e) {
|
||||
throw new \Exception("Could not start container " . $container->identifier . ": " . $e->getResponse()?->getBody()->getContents());
|
||||
}
|
||||
@@ -216,7 +215,7 @@ readonly class DockerActionManager {
|
||||
|
||||
$firstChar = substr($volume->name, 0, 1);
|
||||
if (!in_array($firstChar, $forbiddenChars)) {
|
||||
$this->sendHttpRequest(
|
||||
$this->guzzleClient->request(
|
||||
'POST',
|
||||
$url,
|
||||
[
|
||||
@@ -495,7 +494,7 @@ readonly class DockerActionManager {
|
||||
|
||||
$url = $this->BuildApiUrl('containers/create?name=' . $container->identifier);
|
||||
try {
|
||||
$this->sendHttpRequest(
|
||||
$this->guzzleClient->request(
|
||||
'POST',
|
||||
$url,
|
||||
[
|
||||
@@ -552,10 +551,10 @@ readonly class DockerActionManager {
|
||||
$imageIsThere = true;
|
||||
try {
|
||||
if ($addToStreamingResponseBody) {
|
||||
$addToStreamingResponseBody("Pulling image", $container);
|
||||
$addToStreamingResponseBody($container, "Pulling image");
|
||||
}
|
||||
$imageUrl = $this->BuildApiUrl(sprintf('images/%s/json', $encodedImageName));
|
||||
$this->sendHttpRequest('GET', $imageUrl)->getBody()->getContents();
|
||||
$this->guzzleClient->get($imageUrl)->getBody()->getContents();
|
||||
} catch (\Throwable $e) {
|
||||
$imageIsThere = false;
|
||||
}
|
||||
@@ -563,7 +562,7 @@ readonly class DockerActionManager {
|
||||
$maxRetries = 3;
|
||||
for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
|
||||
try {
|
||||
$this->sendHttpRequest('POST', $url);
|
||||
$this->guzzleClient->post($url);
|
||||
break;
|
||||
} catch (RequestException $e) {
|
||||
$message = "Could not pull image " . $imageName . " (attempt $attempt/$maxRetries): " . $e->getResponse()?->getBody()->getContents();
|
||||
@@ -648,11 +647,11 @@ readonly class DockerActionManager {
|
||||
private function GetRepoDigestsOfContainer(string $containerName): ?array {
|
||||
try {
|
||||
$containerUrl = $this->BuildApiUrl(sprintf('containers/%s/json', $containerName));
|
||||
$containerOutput = json_decode($this->sendHttpRequest('GET', $containerUrl)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
$containerOutput = json_decode($this->guzzleClient->get($containerUrl)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
$imageName = $containerOutput['Image'];
|
||||
|
||||
$imageUrl = $this->BuildApiUrl(sprintf('images/%s/json', $imageName));
|
||||
$imageOutput = json_decode($this->sendHttpRequest('GET', $imageUrl)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
$imageOutput = json_decode($this->guzzleClient->get($imageUrl)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
if (!isset($imageOutput['RepoDigests'])) {
|
||||
error_log('RepoDigests is not set of container ' . $containerName);
|
||||
@@ -696,7 +695,7 @@ readonly class DockerActionManager {
|
||||
$containerName = 'nextcloud-aio-mastercontainer';
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/json', $containerName));
|
||||
try {
|
||||
$output = json_decode($this->sendHttpRequest('GET', $url)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
$output = json_decode($this->guzzleClient->get($url)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
$imageNameArray = explode(':', $output['Config']['Image']);
|
||||
if (count($imageNameArray) === 2) {
|
||||
$imageName = $imageNameArray[0];
|
||||
@@ -723,7 +722,7 @@ readonly class DockerActionManager {
|
||||
$containerName = 'nextcloud-aio-mastercontainer';
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/json', $containerName));
|
||||
try {
|
||||
$output = json_decode($this->sendHttpRequest('GET', $url)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
$output = json_decode($this->guzzleClient->get($url)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
$tagArray = explode(':', $output['Config']['Image']);
|
||||
if (count($tagArray) === 2) {
|
||||
$tag = $tagArray[1];
|
||||
@@ -764,37 +763,26 @@ readonly class DockerActionManager {
|
||||
}
|
||||
|
||||
public function sendNotification(Container $container, string $subject, string $message, string $file = '/notify.sh'): void {
|
||||
$this->execCommandInContainer($container, ['bash', $file, $subject, $message]);
|
||||
}
|
||||
|
||||
public function execCommandInContainer(Container $container, array $cmd, ?\Closure $outputCallback = null): void {
|
||||
if ($cmd === []) {
|
||||
throw new \InvalidArgumentException('$cmd must not be empty.');
|
||||
}
|
||||
foreach ($cmd as $arg) {
|
||||
if (!is_string($arg) || $arg === '') {
|
||||
throw new \InvalidArgumentException('Every element of $cmd must be a non-empty string.');
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->GetContainerStartingState($container) !== ContainerState::Running) {
|
||||
return;
|
||||
}
|
||||
if ($this->GetContainerStartingState($container) === ContainerState::Running) {
|
||||
|
||||
$containerName = $container->identifier;
|
||||
|
||||
// Create exec instance
|
||||
// schedule the exec
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/exec', urlencode($containerName)));
|
||||
$response = json_decode(
|
||||
$this->sendHttpRequest(
|
||||
$this->guzzleClient->request(
|
||||
'POST',
|
||||
$url,
|
||||
[
|
||||
'json' => [
|
||||
'AttachStdout' => true,
|
||||
'AttachStderr' => true,
|
||||
'Tty' => true,
|
||||
'Cmd' => $cmd,
|
||||
'Cmd' => [
|
||||
'bash',
|
||||
$file,
|
||||
$subject,
|
||||
$message
|
||||
],
|
||||
],
|
||||
]
|
||||
)->getBody()->getContents(),
|
||||
@@ -803,30 +791,20 @@ readonly class DockerActionManager {
|
||||
JSON_THROW_ON_ERROR,
|
||||
);
|
||||
|
||||
$execId = $response['Id'];
|
||||
$id = $response['Id'];
|
||||
|
||||
// Start exec
|
||||
$url = $this->BuildApiUrl(sprintf('exec/%s/start', $execId));
|
||||
$requestOptions = [
|
||||
// start the exec
|
||||
$url = $this->BuildApiUrl(sprintf('exec/%s/start', $id));
|
||||
$this->guzzleClient->request(
|
||||
'POST',
|
||||
$url,
|
||||
[
|
||||
'json' => [
|
||||
'Detach' => false,
|
||||
'Tty' => true,
|
||||
],
|
||||
];
|
||||
if ($outputCallback !== null) {
|
||||
$requestOptions['stream'] = true;
|
||||
}
|
||||
|
||||
$startResponse = $this->sendHttpRequest('POST', $url, $requestOptions);
|
||||
|
||||
if ($outputCallback !== null) {
|
||||
$body = $startResponse->getBody();
|
||||
while (!$body->eof()) {
|
||||
$line = rtrim(Utils::readLine($body), "\r");;
|
||||
if ($line !== '') {
|
||||
$outputCallback($line);
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -837,7 +815,7 @@ readonly class DockerActionManager {
|
||||
);
|
||||
|
||||
try {
|
||||
$this->sendHttpRequest(
|
||||
$this->guzzleClient->request(
|
||||
'POST',
|
||||
$url,
|
||||
[
|
||||
@@ -858,7 +836,7 @@ readonly class DockerActionManager {
|
||||
if ($createNetwork) {
|
||||
$url = $this->BuildApiUrl('networks/create');
|
||||
try {
|
||||
$this->sendHttpRequest(
|
||||
$this->guzzleClient->request(
|
||||
'POST',
|
||||
$url,
|
||||
[
|
||||
@@ -887,7 +865,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
|
||||
try {
|
||||
$this->sendHttpRequest(
|
||||
$this->guzzleClient->request(
|
||||
'POST',
|
||||
$url,
|
||||
[
|
||||
@@ -932,7 +910,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/stop?t=%s', urlencode($container->identifier), $maxShutDownTime));
|
||||
try {
|
||||
$this->sendHttpRequest('POST', $url);
|
||||
$this->guzzleClient->post($url);
|
||||
} catch (RequestException $e) {
|
||||
if ($e->getCode() !== 404 && $e->getCode() !== 304) {
|
||||
throw $e;
|
||||
@@ -944,7 +922,7 @@ readonly class DockerActionManager {
|
||||
$containerName = 'nextcloud-aio-borgbackup';
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($containerName)));
|
||||
try {
|
||||
$response = $this->sendHttpRequest('GET', $url);
|
||||
$response = $this->guzzleClient->get($url);
|
||||
} catch (RequestException $e) {
|
||||
if ($e->getCode() === 404) {
|
||||
return -1;
|
||||
@@ -966,7 +944,7 @@ readonly class DockerActionManager {
|
||||
$containerName = 'nextcloud-aio-database';
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/json', urlencode($containerName)));
|
||||
try {
|
||||
$response = $this->sendHttpRequest('GET', $url);
|
||||
$response = $this->guzzleClient->get($url);
|
||||
} catch (RequestException $e) {
|
||||
if ($e->getCode() === 404) {
|
||||
return -1;
|
||||
@@ -1006,7 +984,7 @@ readonly class DockerActionManager {
|
||||
$imageName = $imageName . ':' . $this->GetCurrentChannel();
|
||||
try {
|
||||
$imageUrl = $this->BuildApiUrl(sprintf('images/%s/json', $imageName));
|
||||
$imageOutput = json_decode($this->sendHttpRequest('GET', $imageUrl)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
$imageOutput = json_decode($this->guzzleClient->get($imageUrl)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
if (!isset($imageOutput['Created'])) {
|
||||
error_log('Created is not set of image ' . $imageName);
|
||||
@@ -1051,11 +1029,6 @@ readonly class DockerActionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public function RunNextcloudUpgradeToLatestMajor(\Closure $addToStreamingResponseBody): void {
|
||||
$container = $this->containerDefinitionFetcher->GetContainerById('nextcloud-aio-nextcloud');
|
||||
$this->execCommandInContainer($container, ['bash', '/upgrade-latest-major.sh'], $addToStreamingResponseBody);
|
||||
}
|
||||
|
||||
public function SystemPrune(?\Closure $addToStreamingResponseBody = null): void {
|
||||
$endpoints = [
|
||||
// Remove stopped containers
|
||||
@@ -1084,7 +1057,7 @@ readonly class DockerActionManager {
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $this->sendHttpRequest('POST', $url);
|
||||
$response = $this->guzzleClient->post($url);
|
||||
if ($addToStreamingResponseBody !== null) {
|
||||
$data = json_decode((string)$response->getBody(), true);
|
||||
$deleted = 0;
|
||||
@@ -1122,12 +1095,4 @@ readonly class DockerActionManager {
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
protected function sendHttpRequest(string $httpMethod, string $url, array $requestOptions = []): \Psr\Http\Message\ResponseInterface {
|
||||
if (($requestOptions['stream'] ?? null) === true) {
|
||||
$requestOptions['proxy'] = 'unix:///var/run/docker.sock';
|
||||
}
|
||||
return $this->guzzleClient->request($httpMethod, $url, $requestOptions);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,7 +27,7 @@
|
||||
<script type="text/javascript" src="timezone.js?v1"></script>
|
||||
|
||||
{# js for optional containers and additional containers forms #}
|
||||
<script type="text/javascript" src="containers-form-submit.js?v8"></script>
|
||||
<script type="text/javascript" src="containers-form-submit.js?v7"></script>
|
||||
|
||||
{% set hasBackupLocation = borg_backup_host_location or borg_remote_repo %}
|
||||
{% set isAnyRunning = false %}
|
||||
@@ -298,12 +298,7 @@
|
||||
{% if newMajorVersionString != '' and isAnyRunning == true and isApacheStarting != true %}
|
||||
<details>
|
||||
<summary>Note about <strong>Nextcloud Hub {{ newMajorVersionString }}</strong></summary>
|
||||
<p>If you haven't upgraded to Nextcloud Hub {{ newMajorVersionString }} yet and want to do that now, feel free to click the button below. ⚠️ Warning: make sure to create a backup before clicking the button as the update can go wrong and will leave your instance in a broken state!</p>
|
||||
<form method="POST" action="api/docker/nextcloud-upgrade-to-latest-major" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Upgrade to Nextcloud Hub {{ newMajorVersionString }}" data-confirm="Upgrade to Nextcloud Hub {{ newMajorVersionString }}? You should consider creating a backup first." />
|
||||
</form>
|
||||
<p>If you haven't upgraded to Nextcloud Hub {{ newMajorVersionString }} yet and want to do that now, feel free to follow <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/8223">this documentation</a></strong></p>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
@@ -1 +1 @@
|
||||
13.2.0
|
||||
13.1.0
|
||||
|
||||
@@ -14,42 +14,6 @@
|
||||
<p>Choose your preferred office suite. Only one can be enabled at a time.</p>
|
||||
{% endif %}
|
||||
<div class="office-suite-cards">
|
||||
<input
|
||||
type="radio"
|
||||
id="office-eurooffice"
|
||||
name="office_suite_choice"
|
||||
value="eurooffice"
|
||||
class="office-radio"
|
||||
{% if is_eurooffice_enabled == true %}
|
||||
checked="checked"
|
||||
{% endif %}
|
||||
>
|
||||
<label class="office-card{{ isAnyRunning ? ' office-card-disabled' : '' }}" for="office-eurooffice">
|
||||
<div class="office-card-header">
|
||||
<div>
|
||||
<h4>Nextcloud Office</h4>
|
||||
<p class="office-powered-by">powered by Euro-Office</p>
|
||||
</div>
|
||||
<svg class="office-checkmark" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="12" r="10" fill="var(--color-nextcloud-blue)"/>
|
||||
<path d="M7 12L10.5 15.5L17 9" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<ul class="office-features">
|
||||
<li>Good Nextcloud integration</li>
|
||||
<li>Open source</li>
|
||||
<li>Best performance</li>
|
||||
<li>Limited ODF compatibility</li>
|
||||
<li>Best Microsoft compatibility</li>
|
||||
<li>Good security</li>
|
||||
</ul>
|
||||
{% if isAnyRunning == false %}
|
||||
<a href="https://github.com/Euro-Office" target="_blank" class="office-learn-more" data-stop-event-propagation="true">
|
||||
Learn more
|
||||
</a>
|
||||
{% endif %}
|
||||
</label>
|
||||
<input type="hidden" id="eurooffice" name="eurooffice" value="" data-initial-state="{% if is_eurooffice_enabled == true %}true{% else %}false{% endif %}">
|
||||
<input
|
||||
type="radio"
|
||||
id="office-collabora"
|
||||
@@ -62,10 +26,7 @@
|
||||
>
|
||||
<label class="office-card{{ isAnyRunning ? ' office-card-disabled' : '' }}" for="office-collabora">
|
||||
<div class="office-card-header">
|
||||
<div>
|
||||
<h4>Nextcloud Office</h4>
|
||||
<p class="office-powered-by">powered by Collabora Online</p>
|
||||
</div>
|
||||
<svg class="office-checkmark" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="12" r="10" fill="var(--color-nextcloud-blue)"/>
|
||||
<path d="M7 12L10.5 15.5L17 9" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
@@ -75,9 +36,9 @@
|
||||
<li>Best Nextcloud integration</li>
|
||||
<li>Open source</li>
|
||||
<li>Good performance</li>
|
||||
<li>Best security: documents never leave your server</li>
|
||||
<li>Best ODF compatibility</li>
|
||||
<li>Best support for legacy files</li>
|
||||
<li>Best security: documents never leave your server</li>
|
||||
</ul>
|
||||
{% if isAnyRunning == false %}
|
||||
<a href="https://www.collaboraoffice.com/code/" target="_blank" class="office-learn-more" data-stop-event-propagation="true">
|
||||
@@ -99,22 +60,18 @@
|
||||
>
|
||||
<label class="office-card{{ isAnyRunning ? ' office-card-disabled' : '' }}" for="office-onlyoffice">
|
||||
<div class="office-card-header">
|
||||
<div>
|
||||
<h4>ONLYOFFICE</h4>
|
||||
<p class="office-powered-by">by Ascensio System SIA</p>
|
||||
</div>
|
||||
<h4>OnlyOffice</h4>
|
||||
<svg class="office-checkmark" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="12" r="10" fill="var(--color-nextcloud-blue)"/>
|
||||
<path d="M7 12L10.5 15.5L17 9" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<ul class="office-features">
|
||||
<li>OK Nextcloud integration</li>
|
||||
<li>Open Core</li>
|
||||
<li>Good Nextcloud integration</li>
|
||||
<li>Open core</li>
|
||||
<li>Best performance</li>
|
||||
<li>Limited ODF compatibility</li>
|
||||
<li>Best Microsoft compatibility</li>
|
||||
<li>Good security</li>
|
||||
<li>Limited ODF compatibility</li>
|
||||
</ul>
|
||||
{% if isAnyRunning == false %}
|
||||
<a href="https://www.onlyoffice.com/" target="_blank" class="office-learn-more" data-stop-event-propagation="true">
|
||||
@@ -133,7 +90,7 @@
|
||||
name="office_suite_choice"
|
||||
value=""
|
||||
class="office-radio"
|
||||
{% if is_collabora_enabled == false and is_onlyoffice_enabled == false and is_eurooffice_enabled == false %}
|
||||
{% if is_collabora_enabled == false and is_onlyoffice_enabled == false %}
|
||||
checked="checked"
|
||||
{% endif %}
|
||||
>
|
||||
@@ -267,7 +224,7 @@
|
||||
</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 %}
|
||||
<script type="text/javascript" src="disable-containers.js?v1"></script>
|
||||
<script type="text/javascript" src="disable-containers.js"></script>
|
||||
{% endif %}
|
||||
|
||||
{% if is_collabora_enabled == true and isAnyRunning == false and was_start_button_clicked == true %}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>AIO</title>
|
||||
<link rel="stylesheet" href="style.css?v11" media="all" />
|
||||
<link rel="stylesheet" href="style.css?v10" media="all" />
|
||||
<link rel="icon" href="img/favicon.png">
|
||||
<script type="text/javascript" src="forms.js?v2"></script>
|
||||
<script type="text/javascript" src="toggle-dark-mode.js?v2"></script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<head>
|
||||
<title>AIO</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<link rel="stylesheet" href="style.css?v11">
|
||||
<link rel="stylesheet" href="style.css?v1">
|
||||
<link rel="stylesheet" href="logs.css?v1">
|
||||
<link rel="icon" href="img/favicon.png">
|
||||
<script src="apply-theme.js?v1"></script>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
FROM docker.io/library/composer:latest
|
||||
|
||||
RUN pecl bundle -d /usr/src/php/ext apcu \
|
||||
&& docker-php-ext-install apcu
|
||||
@@ -0,0 +1,107 @@
|
||||
# This setup expects that you run the services via profiles!
|
||||
# Usage: docker compose --profile local-code up
|
||||
# or: docker compose --profile code-from-image up
|
||||
|
||||
name: nextcloud-aio
|
||||
services:
|
||||
composer:
|
||||
image: localhost/composer:latest
|
||||
build: Containers/composer
|
||||
pull_policy: never
|
||||
volumes:
|
||||
- ..:/app
|
||||
working_dir: /app
|
||||
command: |-
|
||||
bash -c '
|
||||
test -d ./data && rm -r ./data
|
||||
test -d ./session && rm -r ./session
|
||||
composer install --no-dev
|
||||
composer clear-cache
|
||||
'
|
||||
app-base:
|
||||
image: ghcr.io/nextcloud-releases/all-in-one:develop${ARM64_SUFFIX-}
|
||||
pull_policy: always # Always pull so we don't risk to run into the "Update for mastercontainer" page.
|
||||
init: true
|
||||
restart: always
|
||||
network_mode: bridge
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- backup_vol:/mnt/test
|
||||
profiles:
|
||||
- none
|
||||
environment:
|
||||
SKIP_DOMAIN_VALIDATION: ${SKIP_DOMAIN_VALIDATION-true}
|
||||
APACHE_PORT: 11000
|
||||
entrypoint: bash /start.sh
|
||||
|
||||
app-code-from-image:
|
||||
extends: app-base
|
||||
container_name: nextcloud-aio-mastercontainer
|
||||
profiles:
|
||||
- code-from-image
|
||||
|
||||
app-local-code:
|
||||
extends: app-base
|
||||
container_name: nextcloud-aio-mastercontainer
|
||||
depends_on:
|
||||
composer:
|
||||
condition: service_completed_successfully
|
||||
volumes:
|
||||
- ..:/var/www/docker-aio/php
|
||||
- ../../Containers/mastercontainer/internal.Caddyfile:/internal.Caddyfile
|
||||
- ../../Containers/mastercontainer/headers.Caddyfile:/headers.Caddyfile
|
||||
- ../../Containers/mastercontainer/start.sh:/start.sh
|
||||
profiles:
|
||||
- local-code
|
||||
|
||||
test-runner-base:
|
||||
image: mcr.microsoft.com/playwright:v1.56.1
|
||||
volumes:
|
||||
- ..:/app
|
||||
working_dir: /app
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
ports:
|
||||
- '9323:9323' # to view test reports
|
||||
profiles:
|
||||
- none
|
||||
environment:
|
||||
BASE_URL: "https://host.docker.internal:8080"
|
||||
DEBUG: "pw:api"
|
||||
command: |-
|
||||
bash -c "
|
||||
cd tests
|
||||
# Install dependencies
|
||||
npm ci
|
||||
# Run the initial setup tests
|
||||
npx playwright test "${TESTS_FILE-}"
|
||||
exit $?
|
||||
"
|
||||
|
||||
test-runner-code-from-image:
|
||||
extends: test-runner-base
|
||||
container_name: test-runner
|
||||
profiles:
|
||||
- code-from-image
|
||||
depends_on:
|
||||
app:
|
||||
condition: service_healthy
|
||||
|
||||
|
||||
test-runner-local-code:
|
||||
extends: test-runner-base
|
||||
container_name: test-runner
|
||||
profiles:
|
||||
- local-code
|
||||
depends_on:
|
||||
app-local-code:
|
||||
condition: service_healthy
|
||||
|
||||
volumes:
|
||||
nextcloud_aio_mastercontainer:
|
||||
name: nextcloud_aio_mastercontainer
|
||||
backup_vol:
|
||||
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [[ "$1" = -* ]]; then
|
||||
echo "Usage $(basename $0) [PLAYWRIGHT_TESTS_FILE]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd $(dirname $0)/../..
|
||||
|
||||
DOCO="docker compose -f ./php/tests/compose.yaml"
|
||||
|
||||
if [[ $(uname -m) = 'arm64' ]]; then
|
||||
export ARM64_SUFFIX='-arm64'
|
||||
fi
|
||||
|
||||
run_tests() {
|
||||
export TESTS_FILE="$1"
|
||||
export SKIP_DOMAIN_VALIDATION
|
||||
|
||||
if [[ -n "$TEST_CODE_FROM_IMAGE" ]]; then
|
||||
profile="code-from-image"
|
||||
else
|
||||
profile="local-code"
|
||||
fi
|
||||
|
||||
# Clean up old containers and volumes
|
||||
docker container rm --force nextcloud-aio-{mastercontainer,apache,notify-push,nextcloud,redis,database,domaincheck,whiteboard,imaginary,talk,collabora,borgbackup} > /dev/null 2>&1
|
||||
docker volume rm nextcloud_aio_{mastercontainer,apache,database,database_dump,nextcloud,nextcloud_data,redis,backup_cache,elasticsearch} > /dev/null 2>&1
|
||||
$DOCO --profile $profile down -v
|
||||
sleep 1
|
||||
|
||||
echo -e "\n 📣 Running playwright tests for ${TESTS_FILE}\n"
|
||||
if ! $DOCO --profile $profile run --remove-orphans test-runner-$profile; then
|
||||
for container in nextcloud-aio-{mastercontainer,borgbackup}; do
|
||||
if docker container list --format="{{ .Names }}" | grep -q "$container"; then
|
||||
echo -e "\n 📣 Log output from container ${container}:\n"
|
||||
docker logs nextcloud-aio-mastercontainer
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
if [[ -n "$1" ]]; then
|
||||
if [[ ! -f "$1" ]]; then
|
||||
echo "Error: file '$1' does not exist."
|
||||
exit 1
|
||||
fi
|
||||
# Not using coreutil's `realpath --relative-to` here since that is not available on BSD/mac systems.
|
||||
fullpath="$(realpath "$1")"
|
||||
prefix="$(realpath ./php/tests)"
|
||||
relpath="${fullpath#"$prefix"/}"
|
||||
|
||||
: ${SKIP_DOMAIN_VALIDATION:-false}
|
||||
run_tests "$relpath"
|
||||
else
|
||||
SKIP_DOMAIN_VALIDATION=true
|
||||
run_tests tests/initial-setup.spec.js
|
||||
sleep 1
|
||||
SKIP_DOMAIN_VALIDATION=false
|
||||
run_tests tests/restore-instance.spec.js
|
||||
fi
|
||||
@@ -69,7 +69,7 @@ test('Initial setup', async ({ page: setupPage }) => {
|
||||
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)}`
|
||||
const borgBackupLocation = `/tmp/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();
|
||||
|
||||
@@ -32,7 +32,7 @@ test('Restore instance', async ({ page: setupPage }) => {
|
||||
|
||||
// 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_host_location').fill('/tmp/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()
|
||||
|
||||
@@ -118,7 +118,6 @@ flowchart TB
|
||||
subgraph OPT[" 🧩 Optional Built-in Containers (enable in AIO interface) "]
|
||||
COLLA(["📄 Nextcloud Office"]):::opt
|
||||
OO(["📄 OnlyOffice\nDocument Server"]):::opt
|
||||
EO(["📄 EuroOffice\nDocument Server"]):::opt
|
||||
TALK(["🎙️ Talk\nVideo & Voice calls"]):::opt
|
||||
TALKREC(["🎬 Talk Recording"]):::opt
|
||||
FTS(["🔎 Full-text Search\n(Elasticsearch)"]):::opt
|
||||
|
||||
@@ -523,7 +523,6 @@ server {
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:11000$request_uri; # Adjust to match APACHE_PORT and APACHE_IP_BINDING. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md#adapting-the-sample-web-server-configurations-below
|
||||
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
proxy_set_header X-Forwarded-Scheme $scheme;
|
||||
|
||||
@@ -13,7 +13,7 @@ For the below to work, it is important that you have a domain that you point ont
|
||||
- [ ] Below that you should see a section `Optional addons` which shows a checkbox list with addons that can be enabled or disabled.
|
||||
- [ ] Collabora, Imaginary, Talk and Whiteboard should be enabled, the rest disabled
|
||||
- [ ] Unchecking/Checking any of these should insert a button that allows to save the set config
|
||||
- [ ] Only one of Collabora, OnlyOffice and EuroOffice should be selectable at the same time
|
||||
- [ ] Checking OnlyOffice and Collabora at the same time should show a warning that this is not supported and should not saving the new config
|
||||
- [ ] Recommended is to uncheck all options now
|
||||
- [ ] Clicking on the save button should reload the page and activate the new config
|
||||
- [ ] Clickig on the `Start containers` button should finally reveal a big spinning wheel that should block all elements on the side of being clicked.
|
||||
|
||||
Reference in New Issue
Block a user