From 91ade7ed94fe576f17d6dc29f6aa86a766abb3da Mon Sep 17 00:00:00 2001
From: Zoey
Date: Fri, 17 Oct 2025 20:26:22 +0200
Subject: [PATCH 01/15] remove libreoffice
see https://github.com/nextcloud/all-in-one/discussions/6997#discussioncomment-14712015
Signed-off-by: Zoey
---
Containers/nextcloud/Dockerfile | 1 -
1 file changed, 1 deletion(-)
diff --git a/Containers/nextcloud/Dockerfile b/Containers/nextcloud/Dockerfile
index 4eae8029..ae54df35 100644
--- a/Containers/nextcloud/Dockerfile
+++ b/Containers/nextcloud/Dockerfile
@@ -230,7 +230,6 @@ RUN set -ex; \
sudo \
grep \
nodejs \
- libreoffice \
bind-tools \
imagemagick \
imagemagick-svg \
From a176ecdd9f10c403038ccbcc9e2b8b58718572c1 Mon Sep 17 00:00:00 2001
From: Zoey
Date: Fri, 17 Oct 2025 20:30:05 +0200
Subject: [PATCH 02/15] remove librewolf from readme
Signed-off-by: Zoey
---
readme.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.md b/readme.md
index 11df8a73..3150c6a2 100644
--- a/readme.md
+++ b/readme.md
@@ -46,7 +46,7 @@ Included are:
- By default confined (good for security) but can [allow access to additional storages](https://github.com/nextcloud/all-in-one#how-to-allow-the-nextcloud-container-to-access-directories-on-the-host) in order to enable the usage of the local external storage feature
- Possibility included to [adjust default installed Nextcloud apps](https://github.com/nextcloud/all-in-one#how-to-change-the-nextcloud-apps-that-are-installed-on-the-first-startup)
- Nextcloud installation is not read only - that means you can apply patches if you should need them (instead of having to wait for the next release for them getting applied)
-- `ffmpeg`, `smbclient`, `libreoffice` and `nodejs` are included by default
+- `ffmpeg`, `smbclient` and `nodejs` are included by default
- Possibility included to [permanently add additional OS packages into the Nextcloud container](https://github.com/nextcloud/all-in-one#how-to-change-the-nextcloud-apps-that-are-installed-on-the-first-startup) without having to build your own Docker image
- Possibility included to [permanently add additional PHP extensions into the Nextcloud container](https://github.com/nextcloud/all-in-one#how-to-add-php-extensions-permanently-to-the-nextcloud-container) without having to build your own Docker image
- Possibility included to [pass the needed device for hardware transcoding](https://github.com/nextcloud/all-in-one#how-to-enable-hardware-acceleration-for-nextcloud) to the Nextcloud container
From 68edc82bf4ac950f4c51cfff3dd00508a582ba45 Mon Sep 17 00:00:00 2001
From: "Simon L."
Date: Wed, 29 Oct 2025 13:30:43 +0100
Subject: [PATCH 03/15] watchtower: revert to building watchtower manually
Signed-off-by: Simon L.
---
.github/workflows/watchtower-update.yml | 36 +++++++++++++++++++++++++
Containers/watchtower/Dockerfile | 12 +++++++--
2 files changed, 46 insertions(+), 2 deletions(-)
create mode 100644 .github/workflows/watchtower-update.yml
diff --git a/.github/workflows/watchtower-update.yml b/.github/workflows/watchtower-update.yml
new file mode 100644
index 00000000..329cd284
--- /dev/null
+++ b/.github/workflows/watchtower-update.yml
@@ -0,0 +1,36 @@
+name: watchtower-update
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: '00 12 * * *'
+
+jobs:
+ watchtower-update:
+ name: update watchtower
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v5
+ - name: Run watchtower-container-update
+ run: |
+ # Watchtower
+ watchtower_version="$(
+ git ls-remote https://github.com/nicholas-fedor/watchtower v* \
+ | cut -d/ -f3 \
+ | sort -V \
+ | grep -E "^v[0-9\.]+$" \
+ | tail -1
+ )"
+ watchtower_commit_hash="$(git ls-remote https://github.com/nicholas-fedor/watchtower $watchtower_version | sed 's/refs.*//')"
+ sed -i "s|^ENV WATCHTOWER_COMMIT_HASH.*$|ENV WATCHTOWER_COMMIT_HASH=$watchtower_commit_hash # $watchtower_version|" ./Containers/watchtower/Dockerfile
+
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7
+ with:
+ commit-message: watchtower-update automated change
+ signoff: true
+ title: watchtower container update
+ body: Automated watchtower container update
+ labels: dependencies, 3. to review
+ milestone: next
+ branch: watchtower-container-update
diff --git a/Containers/watchtower/Dockerfile b/Containers/watchtower/Dockerfile
index c2b38b18..e3858248 100644
--- a/Containers/watchtower/Dockerfile
+++ b/Containers/watchtower/Dockerfile
@@ -1,5 +1,13 @@
# syntax=docker/dockerfile:latest
-FROM ghcr.io/nicholas-fedor/watchtower:1.12.1 AS watchtower
+FROM golang:1.25.3-alpine3.22 AS go
+
+ENV WATCHTOWER_COMMIT_HASH=v1.12.1
+
+RUN set -ex; \
+ apk upgrade --no-cache -a; \
+ apk add --no-cache \
+ build-base; \
+ go install github.com/nicholas-fedor/watchtower@$WATCHTOWER_COMMIT_HASH;
FROM alpine:3.22.2
@@ -7,7 +15,7 @@ RUN set -ex; \
apk upgrade --no-cache -a; \
apk add --no-cache bash ca-certificates tzdata
-COPY --from=watchtower /watchtower /watchtower
+COPY --from=go /go/bin/watchtower /watchtower
COPY --chmod=775 start.sh /start.sh
From f07b015a4170548d420b0903537f4ee72146bac7 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 4 Nov 2025 04:13:53 +0000
Subject: [PATCH 04/15] build(deps): bump redis in /Containers/redis
Bumps redis from 7.2.11-alpine to 7.2.12-alpine.
---
updated-dependencies:
- dependency-name: redis
dependency-version: 7.2.12-alpine
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
Containers/redis/Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Containers/redis/Dockerfile b/Containers/redis/Dockerfile
index 8cb0f973..a44295de 100644
--- a/Containers/redis/Dockerfile
+++ b/Containers/redis/Dockerfile
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:latest
# From https://github.com/docker-library/redis/blob/master/7.2/alpine/Dockerfile
-FROM redis:7.2.11-alpine
+FROM redis:7.2.12-alpine
COPY --chmod=775 start.sh /start.sh
From 1f6c30b93aa830dd609116b566c71e60a5c57a22 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 4 Nov 2025 04:14:11 +0000
Subject: [PATCH 05/15] build(deps): bump nextcloud-releases/whiteboard
Bumps nextcloud-releases/whiteboard from v1.4.0 to v1.4.1.
---
updated-dependencies:
- dependency-name: nextcloud-releases/whiteboard
dependency-version: v1.4.1
dependency-type: direct:production
...
Signed-off-by: dependabot[bot]
---
Containers/whiteboard/Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Containers/whiteboard/Dockerfile b/Containers/whiteboard/Dockerfile
index f90dfdee..90aa72f2 100644
--- a/Containers/whiteboard/Dockerfile
+++ b/Containers/whiteboard/Dockerfile
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:latest
# Probably from this file: https://github.com/nextcloud/whiteboard/blob/main/Dockerfile
-FROM ghcr.io/nextcloud-releases/whiteboard:v1.4.0
+FROM ghcr.io/nextcloud-releases/whiteboard:v1.4.1
USER root
RUN set -ex; \
From 74933c6b83f1231c6439d766347a947ca9c5b322 Mon Sep 17 00:00:00 2001
From: "Simon L."
Date: Tue, 4 Nov 2025 13:42:05 +0100
Subject: [PATCH 06/15] update redis to v8.x
Signed-off-by: Simon L.
---
Containers/redis/Dockerfile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Containers/redis/Dockerfile b/Containers/redis/Dockerfile
index a44295de..7cc1ff84 100644
--- a/Containers/redis/Dockerfile
+++ b/Containers/redis/Dockerfile
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:latest
-# From https://github.com/docker-library/redis/blob/master/7.2/alpine/Dockerfile
-FROM redis:7.2.12-alpine
+# From https://github.com/redis/docker-library-redis/blob/release/8.2/alpine/Dockerfile
+FROM redis:8.2.3-alpine
COPY --chmod=775 start.sh /start.sh
From abf0bbc43157748c8372b37d3bff0f43cb213921 Mon Sep 17 00:00:00 2001
From: "Simon L."
Date: Tue, 4 Nov 2025 13:44:33 +0100
Subject: [PATCH 07/15] dependabot: update redis also to new minor versions
Signed-off-by: Simon L.
---
.github/dependabot.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 0caaabfb..f79c4ce2 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -55,6 +55,6 @@ updates:
- dependency-name: "postgres"
update-types: ["version-update:semver-major"]
- dependency-name: "redis"
- update-types: ["version-update:semver-major", "version-update:semver-minor"]
+ update-types: ["version-update:semver-major"]
- dependency-name: "elasticsearch"
update-types: ["version-update:semver-major"]
From 0ee5ec00366434b22269a13216da364b18430f07 Mon Sep 17 00:00:00 2001
From: "Simon L."
Date: Tue, 4 Nov 2025 13:48:39 +0100
Subject: [PATCH 08/15] docker-image-prune: only remove image with
`label=org.label-schema.vendor=Nextcloud`
Signed-off-by: Simon L.
---
Containers/mastercontainer/cron.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Containers/mastercontainer/cron.sh b/Containers/mastercontainer/cron.sh
index fc8c4081..5829d8da 100644
--- a/Containers/mastercontainer/cron.sh
+++ b/Containers/mastercontainer/cron.sh
@@ -60,7 +60,7 @@ while true; do
fi
# Remove dangling images
- sudo -u www-data docker image prune --force
+ sudo -u www-data docker image prune --filter "label=org.label-schema.vendor=Nextcloud" --force
# Check for available free space
sudo -u www-data php /var/www/docker-aio/php/src/Cron/CheckFreeDiskSpace.php
From f179e5adad0f66ebea3ec6eb5273507a8a21ceb1 Mon Sep 17 00:00:00 2001
From: "Simon L."
Date: Tue, 4 Nov 2025 13:57:22 +0100
Subject: [PATCH 09/15] app: update min and max versions
Signed-off-by: Simon L.
---
app/appinfo/info.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/appinfo/info.xml b/app/appinfo/info.xml
index 8b911c10..832d3ccd 100644
--- a/app/appinfo/info.xml
+++ b/app/appinfo/info.xml
@@ -13,7 +13,7 @@
monitoring
https://github.com/nextcloud/all-in-one/issues
-
+
From b10c9b74bf182448bdc0320c7036e77ec3d362b4 Mon Sep 17 00:00:00 2001
From: "Simon L."
Date: Tue, 4 Nov 2025 14:00:16 +0100
Subject: [PATCH 10/15] nextcloud: update to `32.0.1`
Signed-off-by: Simon L.
---
Containers/nextcloud/Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Containers/nextcloud/Dockerfile b/Containers/nextcloud/Dockerfile
index 35bf5b20..0617db93 100644
--- a/Containers/nextcloud/Dockerfile
+++ b/Containers/nextcloud/Dockerfile
@@ -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=31.0.10
+ENV NEXTCLOUD_VERSION=32.0.1
ENV AIO_TOKEN=123456
ENV AIO_URL=localhost
# AIO settings end # Do not remove or change this line!
From d17ed75d6246a1d25b15bf859babb5fc361a9498 Mon Sep 17 00:00:00 2001
From: "Simon L."
Date: Tue, 4 Nov 2025 14:02:37 +0100
Subject: [PATCH 11/15] aio-interface: hide upgrade notice
Signed-off-by: Simon L.
---
php/templates/containers.twig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/php/templates/containers.twig b/php/templates/containers.twig
index 16a240dc..12b4d81b 100644
--- a/php/templates/containers.twig
+++ b/php/templates/containers.twig
@@ -36,7 +36,7 @@
{% set isBackupOrRestoreRunning = false %}
{% set isApacheStarting = false %}
{# Setting newMajorVersion to '' will hide corresponding options/elements, can be set to an integer like 26 in order to show corresponding elements. If set, also increase installLatestMajor in https://github.com/nextcloud/all-in-one/blob/main/php/src/Controller/DockerController.php #}
- {% set newMajorVersionString = '25 Autumn' %}
+ {% set newMajorVersionString = '' %}
{% if is_backup_container_running == true %}
{% if borg_backup_mode == 'backup' or borg_backup_mode == 'restore' %}
From 21fbb58c96b4cbc8315bfc4af07645b0bfec02b5 Mon Sep 17 00:00:00 2001
From: Lorenzo Moscati
Date: Sat, 23 Aug 2025 01:30:20 +0200
Subject: [PATCH 12/15] Rewrite all AIO interface paths to be relative
Signed-off-by: Lorenzo Moscati
---
php/public/base_path.js | 3 +
php/public/index.php | 6 +-
.../Controller/ConfigurationController.php | 2 +-
php/src/Controller/DockerController.php | 19 +++--
php/src/Controller/LoginController.php | 12 +--
php/src/Middleware/AuthMiddleware.php | 10 ++-
php/templates/already-installed.twig | 6 +-
php/templates/components/container-state.twig | 6 +-
php/templates/containers.twig | 83 ++++++++++---------
.../includes/community-containers.twig | 2 +-
.../includes/optional-containers.twig | 10 +--
php/templates/layout.twig | 4 +-
php/templates/login.twig | 6 +-
php/templates/setup.twig | 6 +-
14 files changed, 96 insertions(+), 79 deletions(-)
create mode 100644 php/public/base_path.js
diff --git a/php/public/base_path.js b/php/public/base_path.js
new file mode 100644
index 00000000..67c1a4a7
--- /dev/null
+++ b/php/public/base_path.js
@@ -0,0 +1,3 @@
+document.addEventListener("DOMContentLoaded", function(event) {
+ document.getElementById("base_path") && (document.getElementById("base_path").value = window.location.pathname.slice(0, -11));
+});
\ No newline at end of file
diff --git a/php/public/index.php b/php/public/index.php
index aac83826..d3fbbeb9 100644
--- a/php/public/index.php
+++ b/php/public/index.php
@@ -178,17 +178,17 @@ $app->get('/', function (\Psr\Http\Message\RequestInterface $request, Response $
$setup = $container->get(\AIO\Data\Setup::class);
if($setup->CanBeInstalled()) {
return $response
- ->withHeader('Location', '/setup')
+ ->withHeader('Location', 'setup')
->withStatus(302);
}
if($authManager->IsAuthenticated()) {
return $response
- ->withHeader('Location', '/containers')
+ ->withHeader('Location', 'containers')
->withStatus(302);
} else {
return $response
- ->withHeader('Location', '/login')
+ ->withHeader('Location', 'login')
->withStatus(302);
}
});
diff --git a/php/src/Controller/ConfigurationController.php b/php/src/Controller/ConfigurationController.php
index ed3be505..5727c364 100644
--- a/php/src/Controller/ConfigurationController.php
+++ b/php/src/Controller/ConfigurationController.php
@@ -161,7 +161,7 @@ readonly class ConfigurationController {
$this->configurationManager->DeleteBorgBackupLocationVars();
}
- return $response->withStatus(201)->withHeader('Location', '/');
+ return $response->withStatus(201)->withHeader('Location', '.');
} catch (InvalidSettingConfigurationException $ex) {
$response->getBody()->write($ex->getMessage());
return $response->withStatus(422);
diff --git a/php/src/Controller/DockerController.php b/php/src/Controller/DockerController.php
index 678bbdc9..dd6b1076 100644
--- a/php/src/Controller/DockerController.php
+++ b/php/src/Controller/DockerController.php
@@ -85,7 +85,7 @@ readonly class DockerController {
public function StartBackupContainerBackup(Request $request, Response $response, array $args) : Response {
$forceStopNextcloud = true;
$this->startBackup($forceStopNextcloud);
- return $response->withStatus(201)->withHeader('Location', '/');
+ return $response->withStatus(201)->withHeader('Location', '.');
}
public function startBackup(bool $forceStopNextcloud = false) : void {
@@ -102,7 +102,7 @@ readonly class DockerController {
public function StartBackupContainerCheck(Request $request, Response $response, array $args) : Response {
$this->checkBackup();
- return $response->withStatus(201)->withHeader('Location', '/');
+ return $response->withStatus(201)->withHeader('Location', '.');
}
public function checkBackup() : void {
@@ -132,7 +132,7 @@ readonly class DockerController {
$id = 'nextcloud-aio-borgbackup';
$this->PerformRecursiveContainerStart($id);
- return $response->withStatus(201)->withHeader('Location', '/');
+ return $response->withStatus(201)->withHeader('Location', '.');
}
public function StartBackupContainerCheckRepair(Request $request, Response $response, array $args) : Response {
@@ -148,7 +148,7 @@ readonly class DockerController {
$config['backup-mode'] = 'check';
$this->configurationManager->WriteConfig($config);
- return $response->withStatus(201)->withHeader('Location', '/');
+ return $response->withStatus(201)->withHeader('Location', '.');
}
public function StartBackupContainerTest(Request $request, Response $response, array $args) : Response {
@@ -163,7 +163,7 @@ readonly class DockerController {
$id = 'nextcloud-aio-borgbackup';
$this->PerformRecursiveContainerStart($id);
- return $response->withStatus(201)->withHeader('Location', '/');
+ return $response->withStatus(201)->withHeader('Location', '.');
}
public function StartContainer(Request $request, Response $response, array $args) : Response
@@ -171,6 +171,7 @@ readonly class DockerController {
$uri = $request->getUri();
$host = $uri->getHost();
$port = $uri->getPort();
+ $path = $request->getParsedBody()['base_path'];
if ($port === 8000) {
error_log('The AIO_URL-port was discovered to be 8000 which is not expected. It is now set to 443.');
$port = 443;
@@ -184,7 +185,7 @@ readonly class DockerController {
$config = $this->configurationManager->GetConfig();
// set AIO_URL
- $config['AIO_URL'] = $host . ':' . $port;
+ $config['AIO_URL'] = $host . ':' . $port . $path;
// set wasStartButtonClicked
$config['wasStartButtonClicked'] = 1;
// set install_latest_major
@@ -204,7 +205,7 @@ readonly class DockerController {
// Temporarily disabled as it leads much faster to docker rate limits
// apcu_clear_cache();
- return $response->withStatus(201)->withHeader('Location', '/');
+ return $response->withStatus(201)->withHeader('Location', '.');
}
public function startTopContainer(bool $pullImage) : void {
@@ -223,7 +224,7 @@ readonly class DockerController {
public function StartWatchtowerContainer(Request $request, Response $response, array $args) : Response {
$this->startWatchtower();
- return $response->withStatus(201)->withHeader('Location', '/');
+ return $response->withStatus(201)->withHeader('Location', '.');
}
public function startWatchtower() : void {
@@ -261,7 +262,7 @@ readonly class DockerController {
$forceStopNextcloud = true;
$this->PerformRecursiveContainerStop($id, $forceStopNextcloud);
- return $response->withStatus(201)->withHeader('Location', '/');
+ return $response->withStatus(201)->withHeader('Location', '.');
}
public function stopTopContainer() : void {
diff --git a/php/src/Controller/LoginController.php b/php/src/Controller/LoginController.php
index 196e7138..233a795e 100644
--- a/php/src/Controller/LoginController.php
+++ b/php/src/Controller/LoginController.php
@@ -19,33 +19,33 @@ readonly class LoginController {
public function TryLogin(Request $request, Response $response, array $args) : Response {
if (!$this->dockerActionManager->isLoginAllowed()) {
$response->getBody()->write("The login is blocked since Nextcloud is running.");
- return $response->withHeader('Location', '/')->withStatus(422);
+ return $response->withHeader('Location', '.')->withStatus(422);
}
$password = $request->getParsedBody()['password'] ?? '';
if($this->authManager->CheckCredentials($password)) {
$this->authManager->SetAuthState(true);
- return $response->withHeader('Location', '/')->withStatus(201);
+ return $response->withHeader('Location', '.')->withStatus(201);
}
$response->getBody()->write("The password is incorrect.");
- return $response->withHeader('Location', '/')->withStatus(422);
+ return $response->withHeader('Location', '.')->withStatus(422);
}
public function GetTryLogin(Request $request, Response $response, array $args) : Response {
$token = $request->getQueryParams()['token'] ?? '';
if($this->authManager->CheckToken($token)) {
$this->authManager->SetAuthState(true);
- return $response->withHeader('Location', '/')->withStatus(302);
+ return $response->withHeader('Location', '../..')->withStatus(302);
}
- return $response->withHeader('Location', '/')->withStatus(302);
+ return $response->withHeader('Location', '../..')->withStatus(302);
}
public function Logout(Request $request, Response $response, array $args) : Response
{
$this->authManager->SetAuthState(false);
return $response
- ->withHeader('Location', '/')
+ ->withHeader('Location', '.')
->withStatus(302);
}
}
diff --git a/php/src/Middleware/AuthMiddleware.php b/php/src/Middleware/AuthMiddleware.php
index f8d44857..a54f47a6 100644
--- a/php/src/Middleware/AuthMiddleware.php
+++ b/php/src/Middleware/AuthMiddleware.php
@@ -27,7 +27,15 @@ readonly class AuthMiddleware {
if(!in_array($request->getUri()->getPath(), $publicRoutes)) {
if(!$this->authManager->IsAuthenticated()) {
$status = 302;
- $headers = ['Location' => '/'];
+ if(count(explode('/', $request->getUri()->getPath())) > 2) {
+ $location = '..';
+ for($i = 0; $i < count(explode('/', $request->getUri()->getPath())) - 3; $i++) {
+ $location = $location . '/..';
+ }
+ } else {
+ $location = '.';
+ }
+ $headers = ['Location' => $location];
$response = new Response($status, $headers);
return $response;
}
diff --git a/php/templates/already-installed.twig b/php/templates/already-installed.twig
index fa18f988..e16e6792 100644
--- a/php/templates/already-installed.twig
+++ b/php/templates/already-installed.twig
@@ -3,11 +3,11 @@
{% block body %}
{% endblock %}
diff --git a/php/templates/components/container-state.twig b/php/templates/components/container-state.twig
index 4cf5dd4e..8375d033 100644
--- a/php/templates/components/container-state.twig
+++ b/php/templates/components/container-state.twig
@@ -4,15 +4,15 @@
{% if c.GetStartingState().value == 'starting' %}
{{ c.GetDisplayName() }}
- (Starting )
+ (Starting )
{% elseif c.GetRunningState().value == 'running' %}
{{ c.GetDisplayName() }}
- (Running )
+ (Running )
{% else %}
{{ c.GetDisplayName() }}
- (Stopped )
+ (Stopped )
{% endif %}
{% if c.GetDocumentation() != '' %}
(docs )
diff --git a/php/templates/containers.twig b/php/templates/containers.twig
index 12b4d81b..1e795149 100644
--- a/php/templates/containers.twig
+++ b/php/templates/containers.twig
@@ -6,9 +6,9 @@
-
+
-
+
@@ -164,7 +164,7 @@
{% endif %}
Choose the backup that you want to restore and click on the button below to restore the selected backup. This will restore the whole AIO instance. Please note that the current AIO passphrase will be kept and the previous AIO passphrase will not be restored from backup!
Important: If the backup that you want to restore contained any community container , you need to restore the same backup a second time after this attempt so that the community container data is also correctly restored.
-
+
@@ -178,7 +178,7 @@
{% endif %}
{% elseif borg_backup_mode == 'restore' %}
{% if backup_exit_code > 0 %}
- Last restore failed! (Logs )
+ Last restore failed! (Logs )
The restore process has unexpectedly failed! Please adjust the path and encryption password, test it and try to restore again!
{% endif %}
{% endif %}
@@ -197,7 +197,7 @@
remote borg repo url
if stored remotely; and the encryption password of the backup archive below and submit all values:
-
+
Local backup location
Remote borg repo
Borg passphrase
@@ -210,7 +210,7 @@
{% endif %}
{% else %}
Everything set! Click on the button below to test the path and encryption password:
-
+
@@ -223,14 +223,14 @@
{% if was_start_button_clicked == true %}
{% if current_channel starts with 'latest' or current_channel starts with 'beta' or current_channel starts with 'develop' %}
- You are running the {{ current_channel }} channel. (Logs )
+ You are running the {{ current_channel }} channel. (Logs )
{% else %}
No channel was found. This means that AIO is not able to update itself and its component and will also not be able to report about updates. Updates need to be done externally.
{% endif %}
{% endif %}
{% if is_backup_container_running == true %}
- Backup container is currently running: {{ borg_backup_mode }} (Logs )
+ Backup container is currently running: {{ borg_backup_mode }} (Logs )
Reload ↻
{% endif %}
@@ -259,7 +259,7 @@
{% else %}
It seems at least one container was not able to start correctly and is currently restarting.
To break this endless loop, you can stop the containers below and investigate the issue in the container logs before starting the containers again.
-
+
@@ -312,7 +312,7 @@
You can find all changes here
{% endif %}
{% endif %}
-
+
@@ -327,31 +327,34 @@
{% endif %}
{% if is_mastercontainer_update_available == true %}
⚠️ A mastercontainer update is available. Please click on the button below to update it.
-
+
{% else %}
{% if was_start_button_clicked == false %}
-
+
+
{% if newMajorVersionString != '' %}
Install Nextcloud Hub {{ newMajorVersionString }} (if unchecked, Nextcloud Hub 10 will get installed)
{% endif %}
{% elseif has_update_available == false %}
-
+
+
{% else %}
-
+
+
{% if bypass_container_update == true %}
{% endif %}
@@ -376,7 +379,7 @@
remote borg repo url and submit it .
You will be provided with an SSH public key for authorization at the remote afterwards.
-
+
Local backup location
Remote borg repo
@@ -393,13 +396,13 @@
{% if is_backup_container_running == false %}
Backup and restore
{% if backup_exit_code > 0 %}
- Last {{ borg_backup_mode }} failed! (Logs )
+ Last {{ borg_backup_mode }} failed! (Logs )
{% if borg_backup_mode == "check" %}
The backup check was not successful. This might indicate a corrupt archive (look at the logs). If that should be the case, you can try to fix it by following this documentation
Reveal repair option
Below is the option to repair the integrity of your backup. Please note: Please only use this after you have read the documentation above! (It will run the command 'borg check --repair' for you.)
-
+
@@ -417,7 +420,7 @@
{% endif %}
You may change the backup path again since the initial backup was not successful. After submitting the new value, you need to click on Create Backup to test the new value.
-
+
Local backup location
Remote borg repo
@@ -427,9 +430,9 @@
{% endif %}
{% elseif backup_exit_code == 0 %}
{% if borg_backup_mode == "backup" %}
- Last {{ borg_backup_mode }} successful on {{ last_backup_time }} UTC! (Logs )
+ Last {{ borg_backup_mode }} successful on {{ last_backup_time }} UTC! (Logs )
{% else %}
- Last {{ borg_backup_mode }} successful! (Logs )
+ Last {{ borg_backup_mode }} successful! (Logs )
{% endif %}
{% endif %}
{% endif %}
@@ -464,7 +467,7 @@
{% if isApacheStarting != true %}
Backup creation
Clicking on the button below will create a backup.
-
+
@@ -479,7 +482,7 @@
{% endif %}
is wrong, you can reset it by clicking on the button below.
-
+
@@ -493,7 +496,7 @@
Backup check
Click on the button below to perform a backup integrity check. This is an option that verifies that your backup is intact. It shouldn't be needed in most situations.
-
+
@@ -501,7 +504,7 @@
Backup restore
Choose the backup that you want to restore and click on the button below to restore the selected backup. This will overwrite all your files with the chosen backup so you should consider creating a backup first. You can run an integrity check before restoring your files but this shouldn't be needed in most situations. Please note that this will not restore additionally chosen backup directories! The restore process should be pretty fast as rsync, which only transfers changed files, is used to restore the chosen backup.
-
+
@@ -515,7 +518,7 @@
Daily backup and automatic updates
{% if daily_backup_time == "" %}
By entering a time below and submitting it, you can enable daily backups. It will create them at the entered time in 24h format. E.g. 04:00 will create backups at 4 am UTC and 16:00 at 4 pm UTC. When creating the backup, containers will be stopped and restarted after the backup is complete.
-
+
@@ -529,7 +532,7 @@
Also your containers, the mastercontainer and, on Saturdays, your Nextcloud apps will be automatically updated.
{% endif %}
To change your backup time first disable Daily Backups, then enter your new backup time, and then re-enable them.
-
+
@@ -539,7 +542,7 @@
Back up additional directories and docker volumes of your host
Below you can enter directories and docker volumes of your host that will be backed up into the same borg backup archive. Make sure to press the submit button after changing anything.
-
+
{{ additional_backup_directories }}
@@ -566,7 +569,7 @@
Click here to change your AIO passphrase
You can change your AIO passphrase below:
-
+
@@ -592,7 +595,7 @@
{% if timezone == "" %}
To get the correct time values for certain Nextcloud features, set the timezone for Nextcloud to the one that your users mainly use. Please note that this setting does not apply to the mastercontainer and any backup option.
You can configure the timezone for Nextcloud below (Do not forget to submit the value!):
-
+
@@ -601,7 +604,7 @@
You need to make sure that the timezone that you enter is valid. An example is Europe/Berlin . You can get valid values by looking at the 'TZ identifier' column of this list: click here . The default is Etc/UTC if nothing is entered.
{% else %}
The timezone for Nextcloud is currently set to {{ timezone }} . You can change the timezone by clicking on the button below.
-
+
@@ -620,6 +623,8 @@
{% endif %}
+
+
{% endblock %}
diff --git a/php/templates/includes/community-containers.twig b/php/templates/includes/community-containers.twig
index f74e3756..66cceb2b 100644
--- a/php/templates/includes/community-containers.twig
+++ b/php/templates/includes/community-containers.twig
@@ -8,7 +8,7 @@
{% endif %}
Show/Hide available Community Containers
-
+
@@ -160,7 +160,7 @@
{% if collabora_dictionaries == "" %}
In order to get the correct dictionaries in Collabora, you may configure the dictionaries below:
-
+
@@ -169,7 +169,7 @@
You need to make sure that the dictionaries that you enter are valid. An example is de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru .
{% else %}
The dictionaries for Collabora are currently set to {{ collabora_dictionaries }} . You can reset them again by clicking on the button below.
-
+
@@ -182,7 +182,7 @@
{% if collabora_additional_options == "" %}
You can configure additional options for collabora below.
(This can be used for configuring the net.content_security_policy and more. Make sure to submit the value!)
-
+
@@ -191,7 +191,7 @@
You need to make sure that the options that you enter are valid. An example is --o:net.content_security_policy=frame-ancestors *.example.com:*; .
{% else %}
The additioinal options for Collabora are currently set to {{ collabora_additional_options }} . You can reset them again by clicking on the button below.
-
+
diff --git a/php/templates/layout.twig b/php/templates/layout.twig
index e20ca3e0..4d842e3d 100644
--- a/php/templates/layout.twig
+++ b/php/templates/layout.twig
@@ -1,8 +1,8 @@
AIO
-
-
+
+
diff --git a/php/templates/login.twig b/php/templates/login.twig
index cf5cc0c3..1c5420c2 100644
--- a/php/templates/login.twig
+++ b/php/templates/login.twig
@@ -3,14 +3,14 @@
{% block body %}
-
-
+
+
Nextcloud Logo
Nextcloud AIO Login
{% if is_login_allowed == true %}
Log in using your Nextcloud AIO passphrase:
-
+
diff --git a/php/templates/setup.twig b/php/templates/setup.twig
index f1d4d1dc..7cc9227a 100644
--- a/php/templates/setup.twig
+++ b/php/templates/setup.twig
@@ -3,14 +3,14 @@
{% block body %}
-
-
+
+
Nextcloud Logo
All-in-One setup
The official Nextcloud installation method. Nextcloud All-in-One provides easy deployment and maintenance with most features included in this one Nextcloud instance.
⚠️ Please note down the passphrase to access the AIO interface and don't lose it!
Passphrase {{ password }}
-
Open Nextcloud AIO login ↗
+
Open Nextcloud AIO login ↗
{% endblock %}
From 3bb9cdf31dc7db3b5d4b41bbbeac59b5fded1163 Mon Sep 17 00:00:00 2001
From: Lorenzo Moscati
Date: Tue, 16 Sep 2025 13:39:01 +0200
Subject: [PATCH 13/15] Guard against null or missing keys.
Signed-off-by: Lorenzo Moscati
---
php/src/Controller/DockerController.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/php/src/Controller/DockerController.php b/php/src/Controller/DockerController.php
index dd6b1076..8473ed57 100644
--- a/php/src/Controller/DockerController.php
+++ b/php/src/Controller/DockerController.php
@@ -171,7 +171,7 @@ readonly class DockerController {
$uri = $request->getUri();
$host = $uri->getHost();
$port = $uri->getPort();
- $path = $request->getParsedBody()['base_path'];
+ $path = $request->getParsedBody()['base_path'] ?? '';
if ($port === 8000) {
error_log('The AIO_URL-port was discovered to be 8000 which is not expected. It is now set to 443.');
$port = 443;
From 10529a597c3292ff8ecc8e51692433240ebe2b9d Mon Sep 17 00:00:00 2001
From: Lorenzo Moscati
Date: Tue, 14 Oct 2025 15:59:28 +0200
Subject: [PATCH 14/15] Added suggested changes
Signed-off-by: Lorenzo Moscati
---
php/public/base_path.js | 8 ++++++--
php/src/Controller/LoginController.php | 2 +-
php/src/Middleware/AuthMiddleware.php | 17 +++++++++++++----
3 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/php/public/base_path.js b/php/public/base_path.js
index 67c1a4a7..a55ed943 100644
--- a/php/public/base_path.js
+++ b/php/public/base_path.js
@@ -1,3 +1,7 @@
-document.addEventListener("DOMContentLoaded", function(event) {
- document.getElementById("base_path") && (document.getElementById("base_path").value = window.location.pathname.slice(0, -11));
+document.addEventListener("DOMContentLoaded", function() {
+ basePath = document.getElementById("base_path")
+ if (basePath) {
+ // Remove '/containers' from the end of the path, to get the base path only
+ basePath.value = window.location.pathname.slice(0, -11);
+ }
});
\ No newline at end of file
diff --git a/php/src/Controller/LoginController.php b/php/src/Controller/LoginController.php
index 233a795e..412ff9df 100644
--- a/php/src/Controller/LoginController.php
+++ b/php/src/Controller/LoginController.php
@@ -45,7 +45,7 @@ readonly class LoginController {
{
$this->authManager->SetAuthState(false);
return $response
- ->withHeader('Location', '.')
+ ->withHeader('Location', '../..')
->withStatus(302);
}
}
diff --git a/php/src/Middleware/AuthMiddleware.php b/php/src/Middleware/AuthMiddleware.php
index a54f47a6..724f1776 100644
--- a/php/src/Middleware/AuthMiddleware.php
+++ b/php/src/Middleware/AuthMiddleware.php
@@ -27,14 +27,23 @@ readonly class AuthMiddleware {
if(!in_array($request->getUri()->getPath(), $publicRoutes)) {
if(!$this->authManager->IsAuthenticated()) {
$status = 302;
- if(count(explode('/', $request->getUri()->getPath())) > 2) {
+
+ // Check the url of the request: split the string by '/' and count the number of elements
+ // Note that the path that gets to this middleware is not aware of any base path managed by a reverse proxy, so if the url is 'https://example.com/AIO/somepage', the path will be 'https://mastercontainer/somepage'
+ if (count(explode('/', $request->getUri()->getPath())) < 2) {
+ // If there are less than 2 elements it means we are somewhere in the root folder (no '/', so no subfolder), so we redirect to the same folder level to offload the redirection to the appropriate page to 'index.php' (specifically, once in the root level the login page will be loaded since we are not authenticated)
+ $location = '.';
+ } else {
+ // If there are 2 or more elements it means we are in a subfolder, so we need to go back to the root folder
+ // In the best case we need to go back by 1 level only
$location = '..';
- for($i = 0; $i < count(explode('/', $request->getUri()->getPath())) - 3; $i++) {
+ // In the worst case we need to go back by n levels, where n is the number of elements - 2 (the first element is not a folder, the second element is already accounted for by the initial '..')
+ for ($i = 1; $i < count(explode('/', $request->getUri()->getPath())) - 2; $i++) {
+ // For each extra level we need to go back by another level
$location = $location . '/..';
}
- } else {
- $location = '.';
}
+
$headers = ['Location' => $location];
$response = new Response($status, $headers);
return $response;
From e614202a9468c8702a40ff488829897a2aa26fd2 Mon Sep 17 00:00:00 2001
From: "Simon L."
Date: Tue, 4 Nov 2025 16:17:44 +0100
Subject: [PATCH 15/15] increase to v12.0.0
Signed-off-by: Simon L.
---
php/templates/containers.twig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/php/templates/containers.twig b/php/templates/containers.twig
index 1e795149..5d479538 100644
--- a/php/templates/containers.twig
+++ b/php/templates/containers.twig
@@ -17,7 +17,7 @@
- Nextcloud AIO v11.11.0
+ Nextcloud AIO v12.0.0
{# Add 2nd tab warning #}