Merge branch 'main' into patch-1

This commit is contained in:
Simon L. 2026-01-29 14:19:50 +01:00 committed by GitHub
commit 75b1df2c8f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 134 additions and 108 deletions

8
.github/pull_request_template.md vendored Normal file
View file

@ -0,0 +1,8 @@
<!--
- 🚨 SECURITY INFO
-
- Before sending a pull request that fixes a security issue please report it via our HackerOne page (https://hackerone.com/nextcloud) following our security policy (https://nextcloud.com/security/). This allows us to coordinate the fix and release without potentially exposing all Nextcloud servers and users in the meantime.
-->
* Resolves: # <!-- related github issue -->
* [Sign-off message](https://github.com/src-d/guide/blob/master/developer-community/fix-DCO.md) is added to all commits

View file

@ -18,7 +18,7 @@ jobs:
mv cool-seccomp-profile.json php/
- name: Create Pull Request
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
commit-message: collabora-seccomp-update automated change
signoff: true

View file

@ -44,7 +44,7 @@ jobs:
)"
sed -i "s|pecl install APCu.*\;|pecl install APCu-$apcu_version\;|" ./Containers/mastercontainer/Dockerfile
- name: Create Pull Request
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
commit-message: php dependency updates
signoff: true

View file

@ -22,7 +22,7 @@ jobs:
sed -i "s|^ENV IMAGINARY_HASH.*$|ENV IMAGINARY_HASH=$imaginary_version|" ./Containers/imaginary/Dockerfile
- name: Create Pull Request
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
commit-message: imaginary-update automated change
signoff: true

View file

@ -79,7 +79,7 @@ jobs:
fi
- name: Create Pull Request
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
commit-message: nextcloud-update automated change
signoff: true

View file

@ -30,7 +30,7 @@ jobs:
continue-on-error: true
- name: Create Pull Request
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: Update psalm baseline

View file

@ -45,7 +45,7 @@ jobs:
sed -i "s|^ARG JANUS_VERSION=.*$|ARG JANUS_VERSION=$janus_version|" ./Containers/talk/Dockerfile
- name: Create Pull Request
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
commit-message: talk-update automated change
signoff: true

View file

@ -23,7 +23,7 @@ jobs:
sudo bash nextcloud-aio-helm-chart/update-helm.sh "$DOCKER_TAG"
fi
- name: Create Pull Request
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
commit-message: Helm Chart updates
signoff: true

View file

@ -16,7 +16,7 @@ jobs:
run: |
sudo bash manual-install/update-yaml.sh
- name: Create Pull Request
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
commit-message: Yaml updates
signoff: true

View file

@ -26,7 +26,7 @@ jobs:
sed -i "s|\$WATCHTOWER_COMMIT_HASH.*$|\$WATCHTOWER_COMMIT_HASH # $watchtower_version|" ./Containers/watchtower/Dockerfile
- name: Create Pull Request
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
with:
commit-message: watchtower-update automated change
signoff: true

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
FROM alpine:3.23.2
FROM alpine:3.23.3
RUN set -ex; \
apk upgrade --no-cache -a

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
FROM alpine:3.23.2
FROM alpine:3.23.3
RUN set -ex; \
\

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
FROM alpine:3.23.2
FROM alpine:3.23.3
RUN set -ex; \
apk upgrade --no-cache -a; \

View file

@ -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:25.04.8.1.1
FROM collabora/code:25.04.8.2.1
USER root
ARG DEBIAN_FRONTEND=noninteractive

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
FROM alpine:3.23.2
FROM alpine:3.23.3
RUN set -ex; \
apk upgrade --no-cache -a; \
apk add --no-cache bash lighttpd netcat-openbsd; \

View file

@ -14,7 +14,7 @@ RUN set -ex; \
build-base; \
go install github.com/h2non/imaginary@"$IMAGINARY_HASH";
FROM alpine:3.23.2
FROM alpine:3.23.3
RUN set -ex; \
apk upgrade --no-cache -a; \
apk add --no-cache \

View file

@ -182,8 +182,11 @@ if ! [ -f "$NEXTCLOUD_DATA_DIR/skip.update" ]; then
curl -fsSL -o nextcloud.tar.bz2.asc "https://download.nextcloud.com/server/releases/latest-${NEXT_MAJOR}.tar.bz2.asc"
GNUPGHOME="$(mktemp -d)"
export GNUPGHOME
# gpg key from https://nextcloud.com/nextcloud.asc
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 28806A878AE423A28372792ED75899B9A724937A
if ! gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 28806A878AE423A28372792ED75899B9A724937A; then
if ! gpg --batch --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 28806A878AE423A28372792ED75899B9A724937A; then
curl -sSL https://nextcloud.com/nextcloud.asc | gpg --import
fi
fi
gpg --batch --verify nextcloud.tar.bz2.asc nextcloud.tar.bz2
mkdir -p /usr/src/tmp
tar -xjf nextcloud.tar.bz2 -C /usr/src/tmp/

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:latest
FROM alpine:3.23.2
FROM alpine:3.23.3
COPY --chmod=775 start.sh /start.sh
COPY --chmod=775 healthcheck.sh /healthcheck.sh

View file

@ -2,7 +2,7 @@
FROM nats:2.12.4-scratch AS nats
FROM eturnal/eturnal:1.12.2-alpine AS eturnal
FROM strukturag/nextcloud-spreed-signaling:2.0.4 AS signaling
FROM alpine:3.23.2 AS janus
FROM alpine:3.23.3 AS janus
ARG JANUS_VERSION=v1.3.3
WORKDIR /src
@ -35,7 +35,7 @@ RUN set -ex; \
make configs; \
rename -v ".jcfg.sample" ".jcfg" /usr/local/etc/janus/*.jcfg.sample
FROM alpine:3.23.2
FROM alpine:3.23.3
ENV ETURNAL_ETC_DIR="/conf"
ENV SKIP_CERT_VERIFY=false
COPY --from=janus --chmod=777 --chown=1000:1000 /usr/local /usr/local

View file

@ -9,7 +9,7 @@ RUN set -ex; \
build-base; \
go install github.com/nicholas-fedor/watchtower@$WATCHTOWER_COMMIT_HASH # v1.14.0
FROM alpine:3.23.2
FROM alpine:3.23.3
RUN set -ex; \
apk upgrade --no-cache -a; \

View file

@ -47,6 +47,7 @@ sed -i '/AIO_URL/d' containers.yml
sed -i '/DOCKER_SOCKET_PROXY_ENABLED/d' containers.yml
sed -i '/ADDITIONAL_TRUSTED_PROXY/d' containers.yml
sed -i '/TURN_DOMAIN/d' containers.yml
sed -i '/NC_AIO_VERSION/d' containers.yml
TCP="$(grep -oP '[%A-Z0-9_]+/tcp' containers.yml | sort -u)"
mapfile -t TCP <<< "$TCP"

View file

@ -219,6 +219,7 @@
"SIGNALING_SECRET=%SIGNALING_SECRET%",
"ONLYOFFICE_SECRET=%ONLYOFFICE_SECRET%",
"AIO_URL=%AIO_URL%",
"NC_AIO_VERSION=v%AIO_VERSION%",
"NEXTCLOUD_MOUNT=%NEXTCLOUD_MOUNT%",
"CLAMAV_ENABLED=%CLAMAV_ENABLED%",
"CLAMAV_HOST=nextcloud-aio-clamav",

View file

@ -95,10 +95,10 @@ $app->get('/containers', function (Request $request, Response $response, array $
'apache_port' => $configurationManager->apachePort,
'borg_backup_host_location' => $configurationManager->borgBackupHostLocation,
'borg_remote_repo' => $configurationManager->borgRemoteRepo,
'borg_public_key' => $configurationManager->GetBorgPublicKey(),
'nextcloud_password' => $configurationManager->GetAndGenerateSecret('NEXTCLOUD_PASSWORD'),
'borg_public_key' => $configurationManager->getBorgPublicKey(),
'nextcloud_password' => $configurationManager->getAndGenerateSecret('NEXTCLOUD_PASSWORD'),
'containers' => (new \AIO\ContainerDefinitionFetcher($container->get(\AIO\Data\ConfigurationManager::class), $container))->FetchDefinition(),
'borgbackup_password' => $configurationManager->GetAndGenerateSecret('BORGBACKUP_PASSWORD'),
'borgbackup_password' => $configurationManager->getAndGenerateSecret('BORGBACKUP_PASSWORD'),
'is_mastercontainer_update_available' => ( $bypass_mastercontainer_update ? false : $dockerActionManager->IsMastercontainerUpdateAvailable() ),
'has_backup_run_once' => $configurationManager->hasBackupRunOnce(),
'is_backup_container_running' => $dockerActionManager->isBackupContainerRunning(),
@ -107,15 +107,15 @@ $app->get('/containers', function (Request $request, Response $response, array $
'borg_backup_mode' => $configurationManager->backupMode,
'was_start_button_clicked' => $configurationManager->wasStartButtonClicked,
'has_update_available' => $dockerActionManager->isAnyUpdateAvailable(),
'last_backup_time' => $configurationManager->GetLastBackupTime(),
'backup_times' => $configurationManager->GetBackupTimes(),
'last_backup_time' => $configurationManager->getLastBackupTime(),
'backup_times' => $configurationManager->getBackupTimes(),
'current_channel' => $dockerActionManager->GetCurrentChannel(),
'is_clamav_enabled' => $configurationManager->isClamavEnabled,
'is_onlyoffice_enabled' => $configurationManager->isOnlyofficeEnabled,
'is_collabora_enabled' => $configurationManager->isCollaboraEnabled,
'is_talk_enabled' => $configurationManager->isTalkEnabled,
'borg_restore_password' => $configurationManager->borgRestorePassword,
'daily_backup_time' => $configurationManager->GetDailyBackupTime(),
'daily_backup_time' => $configurationManager->getDailyBackupTime(),
'is_daily_backup_running' => $configurationManager->isDailyBackupRunning(),
'timezone' => $configurationManager->timezone,
'skip_domain_validation' => $configurationManager->shouldDomainValidationBeSkipped($skip_domain_validation),
@ -126,7 +126,7 @@ $app->get('/containers', function (Request $request, Response $response, array $
'is_backup_section_enabled' => !$configurationManager->disableBackupSection,
'is_imaginary_enabled' => $configurationManager->isImaginaryEnabled,
'is_fulltextsearch_enabled' => $configurationManager->isFulltextsearchEnabled,
'additional_backup_directories' => $configurationManager->GetAdditionalBackupDirectoriesString(),
'additional_backup_directories' => $configurationManager->getAdditionalBackupDirectoriesString(),
'nextcloud_datadir' => $configurationManager->nextcloudDatadirMount,
'nextcloud_mount' => $configurationManager->nextcloudMount,
'nextcloud_upload_limit' => $configurationManager->nextcloudUploadLimit,

View file

@ -246,7 +246,7 @@ readonly class ContainerDefinitionFetcher {
// All secrets are registered with the configuration when they
// are discovered so they can be later generated at time-of-use.
foreach ($entry['secrets'] as $secret) {
$this->configurationManager->RegisterSecret($secret);
$this->configurationManager->registerSecret($secret);
}
}

View file

@ -20,26 +20,26 @@ readonly class ConfigurationController {
if (isset($request->getParsedBody()['domain'])) {
$domain = $request->getParsedBody()['domain'] ?? '';
$skipDomainValidation = isset($request->getParsedBody()['skip_domain_validation']);
$this->configurationManager->SetDomain($domain, $skipDomainValidation);
$this->configurationManager->setDomain($domain, $skipDomainValidation);
}
if (isset($request->getParsedBody()['current-master-password']) || isset($request->getParsedBody()['new-master-password'])) {
$currentMasterPassword = $request->getParsedBody()['current-master-password'] ?? '';
$newMasterPassword = $request->getParsedBody()['new-master-password'] ?? '';
$this->configurationManager->ChangeMasterPassword($currentMasterPassword, $newMasterPassword);
$this->configurationManager->changeMasterPassword($currentMasterPassword, $newMasterPassword);
}
if (isset($request->getParsedBody()['borg_backup_host_location']) || isset($request->getParsedBody()['borg_remote_repo'])) {
$location = $request->getParsedBody()['borg_backup_host_location'] ?? '';
$borgRemoteRepo = $request->getParsedBody()['borg_remote_repo'] ?? '';
$this->configurationManager->SetBorgLocationVars($location, $borgRemoteRepo);
$this->configurationManager->setBorgLocationVars($location, $borgRemoteRepo);
}
if (isset($request->getParsedBody()['borg_restore_host_location']) || isset($request->getParsedBody()['borg_restore_remote_repo']) || isset($request->getParsedBody()['borg_restore_password'])) {
$restoreLocation = $request->getParsedBody()['borg_restore_host_location'] ?? '';
$borgRemoteRepo = $request->getParsedBody()['borg_restore_remote_repo'] ?? '';
$borgPassword = $request->getParsedBody()['borg_restore_password'] ?? '';
$this->configurationManager->SetBorgRestoreLocationVarsAndPassword($restoreLocation, $borgRemoteRepo, $borgPassword);
$this->configurationManager->setBorgRestoreLocationVarsAndPassword($restoreLocation, $borgRemoteRepo, $borgPassword);
}
if (isset($request->getParsedBody()['daily_backup_time'])) {
@ -54,16 +54,16 @@ readonly class ConfigurationController {
$successNotification = false;
}
$dailyBackupTime = $request->getParsedBody()['daily_backup_time'] ?? '';
$this->configurationManager->SetDailyBackupTime($dailyBackupTime, $enableAutomaticUpdates, $successNotification);
$this->configurationManager->setDailyBackupTime($dailyBackupTime, $enableAutomaticUpdates, $successNotification);
}
if (isset($request->getParsedBody()['delete_daily_backup_time'])) {
$this->configurationManager->DeleteDailyBackupTime();
$this->configurationManager->deleteDailyBackupTime();
}
if (isset($request->getParsedBody()['additional_backup_directories'])) {
$additionalBackupDirectories = $request->getParsedBody()['additional_backup_directories'] ?? '';
$this->configurationManager->SetAdditionalBackupDirectories($additionalBackupDirectories);
$this->configurationManager->setAdditionalBackupDirectories($additionalBackupDirectories);
}
if (isset($request->getParsedBody()['delete_timezone'])) {
@ -112,7 +112,7 @@ readonly class ConfigurationController {
}
if (isset($request->getParsedBody()['delete_collabora_dictionaries'])) {
$this->configurationManager->DeleteCollaboraDictionaries();
$this->configurationManager->deleteCollaboraDictionaries();
}
if (isset($request->getParsedBody()['collabora_dictionaries'])) {
@ -130,7 +130,7 @@ readonly class ConfigurationController {
}
if (isset($request->getParsedBody()['delete_borg_backup_location_vars'])) {
$this->configurationManager->DeleteBorgBackupLocationItems();
$this->configurationManager->deleteBorgBackupLocationItems();
}
return $response->withStatus(201)->withHeader('Location', '.');

View file

@ -119,7 +119,7 @@ class ConfigurationManager
public string $domain {
get => $this->get('domain', '');
set { $this->SetDomain($value); }
set { $this->setDomain($value); }
}
public string $borgBackupHostLocation {
@ -138,7 +138,7 @@ class ConfigurationManager
}
public string $apacheIpBinding {
get => $this->GetEnvironmentalVariableOrConfig('APACHE_IP_BINDING', 'apache_ip_binding', '');
get => $this->getEnvironmentalVariableOrConfig('APACHE_IP_BINDING', 'apache_ip_binding', '');
set { $this->set('apache_ip_binding', $value); }
}
@ -189,106 +189,106 @@ class ConfigurationManager
}
public string $apachePort {
get => $this->GetEnvironmentalVariableOrConfig('APACHE_PORT', 'apache_port', '443');
get => $this->getEnvironmentalVariableOrConfig('APACHE_PORT', 'apache_port', '443');
set { $this->set('apache_port', $value); }
}
public string $talkPort {
get => $this->GetEnvironmentalVariableOrConfig('TALK_PORT', 'talk_port', '3478');
get => $this->getEnvironmentalVariableOrConfig('TALK_PORT', 'talk_port', '3478');
set { $this->set('talk_port', $value); }
}
public string $nextcloudMount {
get => $this->GetEnvironmentalVariableOrConfig('NEXTCLOUD_MOUNT', 'nextcloud_mount', '');
get => $this->getEnvironmentalVariableOrConfig('NEXTCLOUD_MOUNT', 'nextcloud_mount', '');
set { $this->set('nextcloud_mount', $value); }
}
public string $nextcloudDatadirMount {
get => $this->GetEnvironmentalVariableOrConfig('NEXTCLOUD_DATADIR', 'nextcloud_datadir', 'nextcloud_aio_nextcloud_data');
get => $this->getEnvironmentalVariableOrConfig('NEXTCLOUD_DATADIR', 'nextcloud_datadir', 'nextcloud_aio_nextcloud_data');
set { $this->set('nextcloud_datadir_mount', $value); }
}
public string $nextcloudUploadLimit {
get => $this->GetEnvironmentalVariableOrConfig('NEXTCLOUD_UPLOAD_LIMIT', 'nextcloud_upload_limit', '16G');
get => $this->getEnvironmentalVariableOrConfig('NEXTCLOUD_UPLOAD_LIMIT', 'nextcloud_upload_limit', '16G');
set { $this->set('nextcloud_upload_limit', $value); }
}
public string $nextcloudMemoryLimit {
get => $this->GetEnvironmentalVariableOrConfig('NEXTCLOUD_MEMORY_LIMIT', 'nextcloud_memory_limit', '512M');
get => $this->getEnvironmentalVariableOrConfig('NEXTCLOUD_MEMORY_LIMIT', 'nextcloud_memory_limit', '512M');
set { $this->set('nextcloud_memory_limit', $value); }
}
public function GetApacheMaxSize() : int {
public function getApacheMaxSize() : int {
$uploadLimit = (int)rtrim($this->nextcloudUploadLimit, 'G');
return $uploadLimit * 1024 * 1024 * 1024;
}
public string $nextcloudMaxTime {
get => $this->GetEnvironmentalVariableOrConfig('NEXTCLOUD_MAX_TIME', 'nextcloud_max_time', '3600');
get => $this->getEnvironmentalVariableOrConfig('NEXTCLOUD_MAX_TIME', 'nextcloud_max_time', '3600');
set { $this->set('nextcloud_max_time', $value); }
}
public string $borgRetentionPolicy {
get => $this->GetEnvironmentalVariableOrConfig('BORG_RETENTION_POLICY', 'borg_retention_policy', '--keep-within=7d --keep-weekly=4 --keep-monthly=6');
get => $this->getEnvironmentalVariableOrConfig('BORG_RETENTION_POLICY', 'borg_retention_policy', '--keep-within=7d --keep-weekly=4 --keep-monthly=6');
set { $this->set('borg_retention_policy', $value); }
}
public string $fulltextsearchJavaOptions {
get => $this->GetEnvironmentalVariableOrConfig('FULLTEXTSEARCH_JAVA_OPTIONS', 'fulltextsearch_java_options', '-Xms512M -Xmx512M');
get => $this->getEnvironmentalVariableOrConfig('FULLTEXTSEARCH_JAVA_OPTIONS', 'fulltextsearch_java_options', '-Xms512M -Xmx512M');
set { $this->set('fulltextsearch_java_options', $value); }
}
public string $dockerSocketPath {
get => $this->GetEnvironmentalVariableOrConfig('WATCHTOWER_DOCKER_SOCKET_PATH', 'docker_socket_path', '/var/run/docker.sock');
get => $this->getEnvironmentalVariableOrConfig('WATCHTOWER_DOCKER_SOCKET_PATH', 'docker_socket_path', '/var/run/docker.sock');
set { $this->set('docker_socket_path', $value); }
}
public string $trustedCacertsDir {
get => $this->GetEnvironmentalVariableOrConfig('NEXTCLOUD_TRUSTED_CACERTS_DIR', 'trusted_cacerts_dir', '');
get => $this->getEnvironmentalVariableOrConfig('NEXTCLOUD_TRUSTED_CACERTS_DIR', 'trusted_cacerts_dir', '');
set { $this->set('trusted_cacerts_dir', $value); }
}
public string $nextcloudAdditionalApks {
get => trim($this->GetEnvironmentalVariableOrConfig('NEXTCLOUD_ADDITIONAL_APKS', 'nextcloud_additional_apks', 'imagemagick'));
get => trim($this->getEnvironmentalVariableOrConfig('NEXTCLOUD_ADDITIONAL_APKS', 'nextcloud_additional_apks', 'imagemagick'));
set { $this->set('nextcloud_addtional_apks', $value); }
}
public string $nextcloudAdditionalPhpExtensions {
get => trim($this->GetEnvironmentalVariableOrConfig('NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS', 'nextcloud_additional_php_extensions', 'imagick'));
get => trim($this->getEnvironmentalVariableOrConfig('NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS', 'nextcloud_additional_php_extensions', 'imagick'));
set { $this->set('nextcloud_additional_php_extensions', $value); }
}
public bool $collaboraSeccompDisabled {
get => $this->booleanize($this->GetEnvironmentalVariableOrConfig('COLLABORA_SECCOMP_DISABLED', 'collabora_seccomp_disabled', ''));
get => $this->booleanize($this->getEnvironmentalVariableOrConfig('COLLABORA_SECCOMP_DISABLED', 'collabora_seccomp_disabled', ''));
set { $this->set('collabora_seccomp_disabled', $value); }
}
public string $apacheAdditionalNetwork {
get => $this->GetEnvironmentalVariableOrConfig('APACHE_ADDITIONAL_NETWORK', 'apache_additional_network', '');
get => $this->getEnvironmentalVariableOrConfig('APACHE_ADDITIONAL_NETWORK', 'apache_additional_network', '');
set { $this->set('apache_additional_network', $value); }
}
public bool $disableBackupSection {
get => $this->booleanize($this->GetEnvironmentalVariableOrConfig('AIO_DISABLE_BACKUP_SECTION', 'disable_backup_section', ''));
get => $this->booleanize($this->getEnvironmentalVariableOrConfig('AIO_DISABLE_BACKUP_SECTION', 'disable_backup_section', ''));
set { $this->set('disable_backup_section', $value); }
}
public bool $nextcloudEnableDriDevice{
get => $this->booleanize($this->GetEnvironmentalVariableOrConfig('NEXTCLOUD_ENABLE_DRI_DEVICE', 'nextcloud_enable_dri_device', ''));
get => $this->booleanize($this->getEnvironmentalVariableOrConfig('NEXTCLOUD_ENABLE_DRI_DEVICE', 'nextcloud_enable_dri_device', ''));
set { $this->set('nextcloud_enable_dri_device', $value); }
}
public bool $enableNvidiaGpu {
get => $this->booleanize($this->GetEnvironmentalVariableOrConfig('NEXTCLOUD_ENABLE_NVIDIA_GPU', 'enable_nvidia_gpu', ''));
get => $this->booleanize($this->getEnvironmentalVariableOrConfig('NEXTCLOUD_ENABLE_NVIDIA_GPU', 'enable_nvidia_gpu', ''));
set { $this->set('enable_nvidia_gpu', $value); }
}
public bool $nextcloudKeepDisabledApps {
get => $this->booleanize($this->GetEnvironmentalVariableOrConfig('NEXTCLOUD_KEEP_DISABLED_APPS', 'nextcloud_keep_disabled_apps', ''));
get => $this->booleanize($this->getEnvironmentalVariableOrConfig('NEXTCLOUD_KEEP_DISABLED_APPS', 'nextcloud_keep_disabled_apps', ''));
set { $this->set('nextcloud_keep_disabled_apps', $value); }
}
private function GetConfig() : array
private function getConfig() : array
{
if ($this->config === [] && file_exists(DataConst::GetConfigFile()))
{
@ -300,15 +300,15 @@ class ConfigurationManager
}
private function get(string $key, mixed $fallbackValue = null) : mixed {
return $this->GetConfig()[$key] ?? $fallbackValue;
return $this->getConfig()[$key] ?? $fallbackValue;
}
private function set(string $key, mixed $value) : void {
$this->GetConfig();
$this->getConfig();
$this->config[$key] = $value;
// Only write if this isn't called in between startTransaction() and commitTransaction().
if ($this->noWrite !== true) {
$this->WriteConfig();
$this->writeConfig();
}
}
@ -317,7 +317,7 @@ class ConfigurationManager
* followed by a call to commitTransaction(), which then writes all changes to disk.
*/
public function startTransaction() : void {
$this->GetConfig();
$this->getConfig();
$this->noWrite = true;
}
@ -326,13 +326,13 @@ class ConfigurationManager
*/
public function commitTransaction() : void {
try {
$this->WriteConfig();
$this->writeConfig();
} finally {
$this->noWrite = false;
}
}
public function GetAndGenerateSecret(string $secretId) : string {
public function getAndGenerateSecret(string $secretId) : string {
if ($secretId === '') {
return '';
}
@ -344,24 +344,24 @@ class ConfigurationManager
}
if ($secretId === 'BORGBACKUP_PASSWORD' && !file_exists(DataConst::GetBackupSecretFile())) {
$this->DoubleSafeBackupSecret($secrets[$secretId]);
$this->doubleSafeBackupSecret($secrets[$secretId]);
}
return $secrets[$secretId];
}
public function GetRegisteredSecret(string $secretId) : string {
public function getRegisteredSecret(string $secretId) : string {
if ($this->secrets[$secretId]) {
return $this->GetAndGenerateSecret($secretId);
return $this->getAndGenerateSecret($secretId);
}
throw new \Exception("The secret " . $secretId . " was not registered. Please check if it is defined in secrets of containers.json.");
}
public function RegisterSecret(string $secretId) : void {
public function registerSecret(string $secretId) : void {
$this->secrets[$secretId] = true;
}
private function DoubleSafeBackupSecret(string $borgBackupPassword) : void {
private function doubleSafeBackupSecret(string $borgBackupPassword) : void {
file_put_contents(DataConst::GetBackupSecretFile(), $borgBackupPassword);
}
@ -373,7 +373,7 @@ class ConfigurationManager
}
}
public function GetLastBackupTime() : string {
public function getLastBackupTime() : string {
if (!file_exists(DataConst::GetBackupArchivesList())) {
return '';
}
@ -398,7 +398,7 @@ class ConfigurationManager
return $lastBackupTime;
}
public function GetBackupTimes() : array {
public function getBackupTimes() : array {
if (!file_exists(DataConst::GetBackupArchivesList())) {
return [];
}
@ -420,6 +420,14 @@ class ConfigurationManager
return $backupTimes;
}
public function getAioVersion() : string {
$path = DataConst::GetAioVersionFile();
if ($path !== '' && file_exists($path)) {
return trim((string)file_get_contents($path));
}
return '';
}
private function isx64Platform() : bool {
if (php_uname('m') === 'x86_64') {
return true;
@ -433,7 +441,7 @@ class ConfigurationManager
*
* We can't turn this into a private validation method because of the second argument.
*/
public function SetDomain(string $domain, bool $skipDomainValidation) : void {
public function setDomain(string $domain, bool $skipDomainValidation) : void {
// Validate that at least one dot is contained
if (!str_contains($domain, '.')) {
throw new InvalidSettingConfigurationException("Domain must contain at least one dot!");
@ -500,7 +508,7 @@ class ConfigurationManager
}
// Get Instance ID
$instanceID = $this->GetAndGenerateSecret('INSTANCE_ID');
$instanceID = $this->getAndGenerateSecret('INSTANCE_ID');
// set protocol
if ($port !== '443') {
@ -547,7 +555,7 @@ class ConfigurationManager
$this->commitTransaction();
}
public function GetBaseDN() : string {
public function getBaseDN() : string {
$domain = $this->domain;
if ($domain === "") {
return "";
@ -558,15 +566,15 @@ class ConfigurationManager
/**
* @throws InvalidSettingConfigurationException
*/
public function SetBorgLocationVars(string $location, string $repo) : void {
$this->ValidateBorgLocationVars($location, $repo);
public function setBorgLocationVars(string $location, string $repo) : void {
$this->validateBorgLocationVars($location, $repo);
$this->startTransaction();
$this->borgBackupHostLocation = $location;
$this->borgRemoteRepo = $repo;
$this->commitTransaction();
}
private function ValidateBorgLocationVars(string $location, string $repo) : void {
private function validateBorgLocationVars(string $location, string $repo) : void {
if ($location === '' && $repo === '') {
throw new InvalidSettingConfigurationException("Please enter a path or a remote repo url!");
} elseif ($location !== '' && $repo !== '') {
@ -592,11 +600,11 @@ class ConfigurationManager
}
} else {
$this->ValidateBorgRemoteRepo($repo);
$this->validateBorgRemoteRepo($repo);
}
}
private function ValidateBorgRemoteRepo(string $repo) : void {
private function validateBorgRemoteRepo(string $repo) : void {
$commonMsg = "For valid urls, see the remote examples at https://borgbackup.readthedocs.io/en/stable/usage/general.html#repository-urls";
if ($repo === "") {
// Ok, remote repo is optional
@ -607,7 +615,7 @@ class ConfigurationManager
}
}
public function DeleteBorgBackupLocationItems() : void {
public function deleteBorgBackupLocationItems() : void {
// Delete the variables
$this->startTransaction();
$this->borgBackupHostLocation = '';
@ -625,8 +633,8 @@ class ConfigurationManager
/**
* @throws InvalidSettingConfigurationException
*/
public function SetBorgRestoreLocationVarsAndPassword(string $location, string $repo, string $password) : void {
$this->ValidateBorgLocationVars($location, $repo);
public function setBorgRestoreLocationVarsAndPassword(string $location, string $repo, string $password) : void {
$this->validateBorgLocationVars($location, $repo);
if ($password === '') {
throw new InvalidSettingConfigurationException("Please enter the password!");
@ -643,7 +651,7 @@ class ConfigurationManager
/**
* @throws InvalidSettingConfigurationException
*/
public function ChangeMasterPassword(string $currentPassword, string $newPassword) : void {
public function changeMasterPassword(string $currentPassword, string $newPassword) : void {
if ($currentPassword === '') {
throw new InvalidSettingConfigurationException("Please enter your current password.");
}
@ -671,7 +679,7 @@ class ConfigurationManager
/**
* @throws InvalidSettingConfigurationException
*/
private function WriteConfig() : void {
private function writeConfig() : void {
if(!is_dir(DataConst::GetDataDirectory())) {
throw new InvalidSettingConfigurationException(DataConst::GetDataDirectory() . " does not exist! Something was set up falsely!");
}
@ -689,7 +697,7 @@ class ConfigurationManager
$this->config = [];
}
private function GetEnvironmentalVariableOrConfig(string $envVariableName, string $configName, string $defaultValue) : string {
private function getEnvironmentalVariableOrConfig(string $envVariableName, string $configName, string $defaultValue) : string {
$envVariableOutput = getenv($envVariableName);
$configValue = $this->get($configName, '');
if ($envVariableOutput === false) {
@ -708,7 +716,7 @@ class ConfigurationManager
return $envVariableOutput;
}
public function GetBorgPublicKey() : string {
public function getBorgPublicKey() : string {
if (!file_exists(DataConst::GetBackupPublicKey())) {
return "";
}
@ -716,7 +724,7 @@ class ConfigurationManager
return trim((string)file_get_contents(DataConst::GetBackupPublicKey()));
}
public function GetCollaboraSeccompPolicy() : string {
public function getCollaboraSeccompPolicy() : string {
$defaultString = '--o:security.seccomp=';
if (!$this->collaboraSeccompDisabled) {
return $defaultString . 'true';
@ -727,7 +735,7 @@ class ConfigurationManager
/**
* @throws InvalidSettingConfigurationException
*/
public function SetDailyBackupTime(string $time, bool $enableAutomaticUpdates, bool $successNotification) : void {
public function setDailyBackupTime(string $time, bool $enableAutomaticUpdates, bool $successNotification) : void {
if ($time === "") {
throw new InvalidSettingConfigurationException("The daily backup time must not be empty!");
}
@ -749,7 +757,7 @@ class ConfigurationManager
file_put_contents(DataConst::GetDailyBackupTimeFile(), $time);
}
public function GetDailyBackupTime() : string {
public function getDailyBackupTime() : string {
if (!file_exists(DataConst::GetDailyBackupTimeFile())) {
return '';
}
@ -771,7 +779,7 @@ class ConfigurationManager
}
}
public function DeleteDailyBackupTime() : void {
public function deleteDailyBackupTime() : void {
if (file_exists(DataConst::GetDailyBackupTimeFile())) {
unlink(DataConst::GetDailyBackupTimeFile());
}
@ -780,7 +788,7 @@ class ConfigurationManager
/**
* @throws InvalidSettingConfigurationException
*/
public function SetAdditionalBackupDirectories(string $additionalBackupDirectories) : void {
public function setAdditionalBackupDirectories(string $additionalBackupDirectories) : void {
$additionalBackupDirectoriesArray = explode("\n", $additionalBackupDirectories);
$validDirectories = '';
foreach($additionalBackupDirectoriesArray as $entry) {
@ -801,15 +809,15 @@ class ConfigurationManager
}
}
public function GetAdditionalBackupDirectoriesString() : string {
public function getAdditionalBackupDirectoriesString() : string {
if (!file_exists(DataConst::GetAdditionalBackupDirectoriesFile())) {
return '';
}
return (string)file_get_contents(DataConst::GetAdditionalBackupDirectoriesFile());
}
public function GetAdditionalBackupDirectoriesArray() : array {
$additionalBackupDirectories = $this->GetAdditionalBackupDirectoriesString();
public function getAdditionalBackupDirectoriesArray() : array {
$additionalBackupDirectories = $this->getAdditionalBackupDirectoriesString();
$additionalBackupDirectoriesArray = explode("\n", $additionalBackupDirectories);
$additionalBackupDirectoriesArray = array_unique($additionalBackupDirectoriesArray, SORT_REGULAR);
return $additionalBackupDirectoriesArray;
@ -846,7 +854,7 @@ class ConfigurationManager
return false;
}
public function GetNextcloudStartupApps() : string {
public function getNextcloudStartupApps() : string {
$apps = getenv('NEXTCLOUD_STARTUP_APPS');
if (is_string($apps)) {
return trim($apps);
@ -870,7 +878,7 @@ class ConfigurationManager
/**
* Provide an extra method since the corresponding attribute setter prevents setting an empty value.
*/
public function DeleteCollaboraDictionaries() : void {
public function deleteCollaboraDictionaries() : void {
$this->set('collabora_dictionaries', '');
}
@ -999,7 +1007,7 @@ class ConfigurationManager
private function getPlaceholderValue(string $placeholder) : string {
return match ($placeholder) {
'NC_DOMAIN' => $this->domain,
'NC_BASE_DN' => $this->GetBaseDN(),
'NC_BASE_DN' => $this->getBaseDN(),
'AIO_TOKEN' => $this->aioToken,
'BORGBACKUP_REMOTE_REPO' => $this->borgRemoteRepo,
'BORGBACKUP_MODE' => $this->backupMode,
@ -1029,11 +1037,11 @@ class ConfigurationManager
'BORG_RETENTION_POLICY' => $this->borgRetentionPolicy,
'FULLTEXTSEARCH_JAVA_OPTIONS' => $this->fulltextsearchJavaOptions,
'NEXTCLOUD_TRUSTED_CACERTS_DIR' => $this->trustedCacertsDir,
'ADDITIONAL_DIRECTORIES_BACKUP' => $this->GetAdditionalBackupDirectoriesString() !== '' ? 'yes' : '',
'ADDITIONAL_DIRECTORIES_BACKUP' => $this->getAdditionalBackupDirectoriesString() !== '' ? 'yes' : '',
'BORGBACKUP_HOST_LOCATION' => $this->borgBackupHostLocation,
'APACHE_MAX_SIZE' => (string)($this->GetApacheMaxSize()),
'COLLABORA_SECCOMP_POLICY' => $this->GetCollaboraSeccompPolicy(),
'NEXTCLOUD_STARTUP_APPS' => $this->GetNextcloudStartupApps(),
'APACHE_MAX_SIZE' => (string)($this->getApacheMaxSize()),
'COLLABORA_SECCOMP_POLICY' => $this->getCollaboraSeccompPolicy(),
'NEXTCLOUD_STARTUP_APPS' => $this->getNextcloudStartupApps(),
'NEXTCLOUD_ADDITIONAL_APKS' => $this->nextcloudAdditionalApks,
'NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS' => $this->nextcloudAdditionalPhpExtensions,
'INSTALL_LATEST_MAJOR' => $this->installLatestMajor ? 'yes' : '',
@ -1043,7 +1051,8 @@ class ConfigurationManager
// Allow to get local ip-address of caddy container and add it to trusted proxies automatically
'CADDY_IP_ADDRESS' => in_array('caddy', $this->aioCommunityContainers, true) ? gethostbyname('nextcloud-aio-caddy') : '',
'WHITEBOARD_ENABLED' => $this->isWhiteboardEnabled ? 'yes' : '',
default => $this->GetRegisteredSecret($placeholder),
'AIO_VERSION' => $this->getAioVersion(),
default => $this->getRegisteredSecret($placeholder),
};
}

View file

@ -66,4 +66,8 @@ class DataConst {
public static function GetContainersDefinitionPath() : string {
return (string)realpath(__DIR__ . '/../../containers.json');
}
public static function GetAioVersionFile() : string {
return (string)realpath(__DIR__ . '/../../templates/includes/aio-version.twig');
}
}

View file

@ -383,7 +383,7 @@ readonly class DockerActionManager {
// Make volumes read only in case of borgbackup container. The viewer makes them writeable
$isReadOnly = $container->identifier === 'nextcloud-aio-borgbackup';
foreach ($this->configurationManager->GetAdditionalBackupDirectoriesArray() as $additionalBackupDirectories) {
foreach ($this->configurationManager->getAdditionalBackupDirectoriesArray() as $additionalBackupDirectories) {
if ($additionalBackupDirectories !== '') {
if (!str_starts_with($additionalBackupDirectories, '/')) {
$mounts[] = ["Type" => "volume", "Source" => $additionalBackupDirectories, "Target" => "/docker_volumes/" . $additionalBackupDirectories, "ReadOnly" => $isReadOnly];
@ -946,7 +946,7 @@ readonly class DockerActionManager {
}
public function GetAndGenerateSecretWrapper(string $secretId): string {
return $this->configurationManager->GetAndGenerateSecret($secretId);
return $this->configurationManager->getAndGenerateSecret($secretId);
}
public function isNextcloudImageOutdated(): bool {

View file

@ -74,7 +74,7 @@ test('Restore instance', async ({ page: setupPage }) => {
dialog.accept()
});
await containersPage.getByRole('button', { name: 'Start and update containers' }).click();
await expect(containersPage.getByRole('link', { name: 'Open your Nextcloud ↗' })).toBeVisible({ timeout: 5 * 60 * 1000 });
await expect(containersPage.getByRole('link', { name: 'Open your Nextcloud ↗' })).toBeVisible({ timeout: 8 * 60 * 1000 });
await expect(containersPage.getByRole('main')).toContainText(initialNextcloudPassword);
// Verify that containers are all stopped