mirror of
https://github.com/nextcloud/all-in-one.git
synced 2026-05-23 03:40:19 +00:00
Compare commits
68 Commits
szaimen-pa
...
helm-chart
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c242195a8 | ||
|
|
3f0abf2b31 | ||
|
|
6b20209886 | ||
|
|
410dc0e489 | ||
|
|
cf507d6159 | ||
|
|
91152877c9 | ||
|
|
4da3a06458 | ||
|
|
b70b5f6486 | ||
|
|
e4f34da3bb | ||
|
|
8fef1b084e | ||
|
|
636554ee50 | ||
|
|
c44a3533a5 | ||
|
|
c1a435b077 | ||
|
|
ec762a8a66 | ||
|
|
c1bf30980c | ||
|
|
58e5d8534b | ||
|
|
4d7ab6c453 | ||
|
|
bdda7c2178 | ||
|
|
6e0569678d | ||
|
|
590694c638 | ||
|
|
fe4f568d02 | ||
|
|
4cf066cfce | ||
|
|
225918320a | ||
|
|
7e5d8a20d2 | ||
|
|
974f443455 | ||
|
|
e3e1ddf983 | ||
|
|
94bb848352 | ||
|
|
70aa75ef06 | ||
|
|
e70af15e81 | ||
|
|
9652e39be2 | ||
|
|
053cf7cbbe | ||
|
|
d25b2e85ef | ||
|
|
bfcddbab73 | ||
|
|
da0775863d | ||
|
|
dd989ee87f | ||
|
|
ffd71ba47e | ||
|
|
ebe971d18d | ||
|
|
8d717221b3 | ||
|
|
3111f2b748 | ||
|
|
66dc3051e6 | ||
|
|
c66fa6e2a9 | ||
|
|
7b0b0139dd | ||
|
|
73268f1bd2 | ||
|
|
970c1212c0 | ||
|
|
2e04fdaa8c | ||
|
|
bf7f818410 | ||
|
|
8b2e9b4a5a | ||
|
|
e9ab05c5b7 | ||
|
|
67814f32d8 | ||
|
|
270ad0ecea | ||
|
|
0e4ffe65f0 | ||
|
|
0348be71d4 | ||
|
|
5cc47f8c88 | ||
|
|
fd01a9a70b | ||
|
|
39b6c92d86 | ||
|
|
f0f6e24825 | ||
|
|
426eca6aab | ||
|
|
1ddda8eb6e | ||
|
|
09a7141955 | ||
|
|
14d6579893 | ||
|
|
a803d1c098 | ||
|
|
2df9b8af50 | ||
|
|
a16c7e28c2 | ||
|
|
afb355d9e1 | ||
|
|
70711b8b05 | ||
|
|
c2a88d5698 | ||
|
|
270302d74f | ||
|
|
eba86c3ad1 |
3
.github/pull_request_template.md
vendored
3
.github/pull_request_template.md
vendored
@@ -3,6 +3,3 @@
|
||||
-
|
||||
- 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
|
||||
|
||||
2
.github/workflows/lint-yaml.yml
vendored
2
.github/workflows/lint-yaml.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
line-length: warning
|
||||
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
||||
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
|
||||
|
||||
- name: Check GitHub actions
|
||||
run: uvx zizmor --min-severity medium .github/workflows/*.yml
|
||||
|
||||
@@ -79,7 +79,8 @@ RUN set -ex; \
|
||||
chmod 777 -R /usr/local/apache2/logs; \
|
||||
rm -rf /usr/local/apache2/cgi-bin/; \
|
||||
\
|
||||
echo "root:$(openssl rand -base64 12)" | chpasswd
|
||||
echo "root:$(openssl rand -base64 12)" | chpasswd; \
|
||||
apk --no-cache del openssl
|
||||
|
||||
USER 33
|
||||
|
||||
|
||||
@@ -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.2.1
|
||||
FROM collabora/code:25.04.8.3.1
|
||||
|
||||
USER root
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM haproxy:3.3.2-alpine
|
||||
FROM haproxy:3.3.3-alpine
|
||||
|
||||
# hadolint ignore=DL3002
|
||||
USER root
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
# Probably from here https://github.com/elastic/elasticsearch/blob/main/distribution/docker/src/docker/Dockerfile
|
||||
FROM elasticsearch:8.19.10
|
||||
FROM elasticsearch:8.19.11
|
||||
|
||||
USER root
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM golang:1.25.6-alpine3.23 AS go
|
||||
FROM golang:1.26.0-alpine3.23 AS go
|
||||
|
||||
ENV IMAGINARY_HASH=6a274b488759a896aff02f52afee6e50b5e3a3ee
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
# Docker CLI is a requirement
|
||||
FROM docker:29.2.0-cli AS docker
|
||||
FROM docker:29.2.1-cli AS docker
|
||||
|
||||
# Caddy is a requirement
|
||||
FROM caddy:2.10.2-alpine AS caddy
|
||||
|
||||
@@ -166,7 +166,7 @@ elif ! sudo -E -u www-data docker volume ls --format "{{.Name}}" | grep -q "^nex
|
||||
print_red "It seems like you did not give the mastercontainer volume the correct name? (The 'nextcloud_aio_mastercontainer' volume was not found.)
|
||||
Using a different name is not supported since the built-in backup solution will not work in that case!"
|
||||
exit 1
|
||||
elif ! sudo -E -u www-data docker inspect nextcloud-aio-mastercontainer --format '{{.Mounts}}' | grep -q " nextcloud_aio_mastercontainer "; then
|
||||
elif ! sudo -E -u www-data docker inspect nextcloud-aio-mastercontainer | grep -q "nextcloud_aio_mastercontainer"; then
|
||||
print_red "It seems like you did not attach the 'nextcloud_aio_mastercontainer' volume to the mastercontainer?
|
||||
This is not supported since the built-in backup solution will not work in that case!"
|
||||
exit 1
|
||||
|
||||
@@ -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=32.0.5
|
||||
ENV NEXTCLOUD_VERSION=32.0.6
|
||||
ENV AIO_TOKEN=123456
|
||||
ENV AIO_URL=localhost
|
||||
# AIO settings end # Do not remove or change this line!
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
# From https://github.com/docker-library/postgres/blob/master/17/alpine3.23/Dockerfile
|
||||
FROM postgres:17.7-alpine
|
||||
FROM postgres:17.8-alpine
|
||||
|
||||
COPY --chmod=775 start.sh /start.sh
|
||||
COPY --chmod=775 healthcheck.sh /healthcheck.sh
|
||||
|
||||
@@ -10,6 +10,7 @@ RUN set -ex; \
|
||||
\
|
||||
# Give root a random password
|
||||
echo "root:$(openssl rand -base64 12)" | chpasswd; \
|
||||
apk --no-cache del openssl; \
|
||||
\
|
||||
# Get rid of unused binaries
|
||||
rm -f /usr/local/bin/gosu;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM python:3.14.2-alpine3.23
|
||||
FROM python:3.14.3-alpine3.23
|
||||
|
||||
COPY --chmod=775 start.sh /start.sh
|
||||
COPY --chmod=775 healthcheck.sh /healthcheck.sh
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
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 strukturag/nextcloud-spreed-signaling:2.1.0 AS signaling
|
||||
FROM alpine:3.23.3 AS janus
|
||||
|
||||
ARG JANUS_VERSION=v1.3.3
|
||||
ARG JANUS_VERSION=v1.4.0
|
||||
WORKDIR /src
|
||||
RUN set -ex; \
|
||||
apk upgrade --no-cache -a; \
|
||||
|
||||
@@ -25,7 +25,9 @@ certificate = /etc/nginx/ssl/server.crt
|
||||
key = /etc/nginx/ssl/server.key
|
||||
|
||||
[app]
|
||||
# Set to "true" to install pprof debug handlers.
|
||||
# Set to "true" to install pprof debug handlers. Access will only be possible
|
||||
# from IPs allowed through the "allowed_ips" option below.
|
||||
#
|
||||
# See "https://golang.org/pkg/net/http/pprof/" for further information.
|
||||
debug = false
|
||||
|
||||
@@ -270,8 +272,9 @@ connectionsperhost = 8
|
||||
#SA = NA
|
||||
|
||||
[stats]
|
||||
# Comma-separated list of IP addresses that are allowed to access the stats
|
||||
# endpoint. Leave empty (or commented) to only allow access from "127.0.0.1".
|
||||
# Comma-separated list of IP addresses that are allowed to access the debug,
|
||||
# stats and metrics endpoints.
|
||||
# Leave empty (or commented) to only allow access from localhost.
|
||||
#allowed_ips =
|
||||
|
||||
[etcd]
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM golang:1.25.6-alpine3.23 AS go
|
||||
FROM golang:1.26.0-alpine3.23 AS go
|
||||
|
||||
ENV WATCHTOWER_COMMIT_HASH=f522ce27e1fbe4618da54833025a95be62aa838a
|
||||
ENV WATCHTOWER_COMMIT_HASH=b09b3a5c5e1094b746575a19a7fc0135c8908c9d
|
||||
|
||||
RUN set -ex; \
|
||||
apk upgrade --no-cache -a; \
|
||||
apk add --no-cache \
|
||||
build-base; \
|
||||
go install github.com/nicholas-fedor/watchtower@$WATCHTOWER_COMMIT_HASH # v1.14.0
|
||||
go install github.com/nicholas-fedor/watchtower@$WATCHTOWER_COMMIT_HASH # v1.14.1
|
||||
|
||||
FROM alpine:3.23.3
|
||||
|
||||
|
||||
@@ -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.5.4
|
||||
FROM ghcr.io/nextcloud-releases/whiteboard:v1.5.6
|
||||
|
||||
USER root
|
||||
RUN set -ex; \
|
||||
|
||||
@@ -33,6 +33,7 @@ There is a testing-VM available for the maintainer of AIO that allows for some f
|
||||
Additionally, there are now E2E tests available that can be run via https://github.com/nextcloud/all-in-one/actions/workflows/playwright.yml
|
||||
|
||||
## How to promote builds from develop to beta
|
||||
1. Verify that GitHub Services are running correctly: https://www.githubstatus.com/
|
||||
1. Verify that no job is running here: https://github.com/nextcloud-releases/all-in-one/actions/workflows/build_images.yml
|
||||
2. Go to https://github.com/nextcloud-releases/all-in-one/actions/workflows/promote-to-beta.yml, click on `Run workflow`.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: nextcloud-aio-helm-chart
|
||||
description: A generated Helm Chart for Nextcloud AIO from Skippbox Kompose
|
||||
version: 12.5.0
|
||||
version: 12.7.0
|
||||
apiVersion: v2
|
||||
keywords:
|
||||
- latest
|
||||
|
||||
@@ -61,7 +61,7 @@ spec:
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
- name: WHITEBOARD_HOST
|
||||
value: nextcloud-aio-whiteboard
|
||||
image: ghcr.io/nextcloud-releases/aio-apache:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-apache:20260218_123804
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -36,7 +36,7 @@ spec:
|
||||
{{- end }}
|
||||
initContainers:
|
||||
- name: init-subpath
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260218_123804
|
||||
command:
|
||||
- mkdir
|
||||
- "-p"
|
||||
@@ -59,7 +59,7 @@ spec:
|
||||
value: "{{ .Values.NEXTCLOUD_UPLOAD_LIMIT }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-clamav:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-clamav:20260218_123804
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -36,9 +36,9 @@ spec:
|
||||
- name: server_name
|
||||
value: "{{ .Values.NC_DOMAIN }}"
|
||||
{{- if contains "--o:support_key=" (join " " (.Values.ADDITIONAL_COLLABORA_OPTIONS | default list)) }}
|
||||
image: ghcr.io/nextcloud-releases/aio-collabora-online:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-collabora-online:20260218_123804
|
||||
{{- else }}
|
||||
image: ghcr.io/nextcloud-releases/aio-collabora:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-collabora:20260218_123804
|
||||
{{- end }}
|
||||
readinessProbe:
|
||||
exec:
|
||||
|
||||
@@ -35,7 +35,7 @@ spec:
|
||||
{{- end }}
|
||||
initContainers:
|
||||
- name: init-subpath
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260218_123804
|
||||
command:
|
||||
- mkdir
|
||||
- "-p"
|
||||
@@ -64,7 +64,7 @@ spec:
|
||||
value: nextcloud
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-postgresql:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-postgresql:20260218_123804
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -24,7 +24,7 @@ spec:
|
||||
spec:
|
||||
initContainers:
|
||||
- name: init-volumes
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260218_123804
|
||||
command:
|
||||
- chmod
|
||||
- "777"
|
||||
@@ -54,7 +54,7 @@ spec:
|
||||
value: basic
|
||||
- name: xpack.security.enabled
|
||||
value: "false"
|
||||
image: ghcr.io/nextcloud-releases/aio-fulltextsearch:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-fulltextsearch:20260218_123804
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -38,7 +38,7 @@ spec:
|
||||
value: "{{ .Values.IMAGINARY_SECRET }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-imaginary:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-imaginary:20260218_123804
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -38,7 +38,7 @@ spec:
|
||||
# AIO settings start # Do not remove or change this line!
|
||||
initContainers:
|
||||
- name: init-volumes
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260218_123804
|
||||
command:
|
||||
- chmod
|
||||
- "777"
|
||||
@@ -190,7 +190,7 @@ spec:
|
||||
value: "{{ .Values.WHITEBOARD_ENABLED }}"
|
||||
- name: WHITEBOARD_SECRET
|
||||
value: "{{ .Values.WHITEBOARD_SECRET }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-nextcloud:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-nextcloud:20260218_123804
|
||||
{{- if eq (.Values.RPSS_ENABLED | default "no") "yes" }} # AIO-config - do not change this comment!
|
||||
securityContext:
|
||||
# The items below only work in container context
|
||||
|
||||
@@ -57,7 +57,7 @@ spec:
|
||||
value: "6379"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-notify-push:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-notify-push:20260218_123804
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -24,7 +24,7 @@ spec:
|
||||
spec:
|
||||
initContainers:
|
||||
- name: init-volumes
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260218_123804
|
||||
command:
|
||||
- chmod
|
||||
- "777"
|
||||
@@ -42,7 +42,7 @@ spec:
|
||||
value: "{{ .Values.ONLYOFFICE_SECRET }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-onlyoffice:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-onlyoffice:20260218_123804
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -39,7 +39,7 @@ spec:
|
||||
value: "{{ .Values.REDIS_PASSWORD }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-redis:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-redis:20260218_123804
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -52,7 +52,7 @@ spec:
|
||||
value: "{{ .Values.TURN_SECRET }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-talk:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-talk:20260218_123804
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -44,7 +44,7 @@ spec:
|
||||
value: "{{ .Values.RECORDING_SECRET }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-talk-recording:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-talk-recording:20260218_123804
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -50,7 +50,7 @@ spec:
|
||||
value: redis
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-whiteboard:20260122_105751
|
||||
image: ghcr.io/nextcloud-releases/aio-whiteboard:20260218_123804
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -407,7 +407,7 @@ rm latest.yml
|
||||
mv latest.yml.backup latest.yml
|
||||
|
||||
# Get version of AIO
|
||||
AIO_VERSION="$(grep 'Nextcloud AIO ' ../php/templates/includes/aio-version.twig | grep -oP '[0-9]+.[0-9]+.[0-9]+')"
|
||||
AIO_VERSION="$(grep -oP '[0-9]+.[0-9]+.[0-9]+' ../php/templates/includes/aio-version.twig)"
|
||||
sed -i "s|^version:.*|version: $AIO_VERSION|" ../helm-chart/Chart.yaml
|
||||
|
||||
# Conversion of sample.conf
|
||||
|
||||
76
php/composer.lock
generated
76
php/composer.lock
generated
@@ -391,27 +391,27 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/serializable-closure",
|
||||
"version": "v2.0.8",
|
||||
"version": "v2.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/serializable-closure.git",
|
||||
"reference": "7581a4407012f5f53365e11bafc520fd7f36bc9b"
|
||||
"reference": "8f631589ab07b7b52fead814965f5a800459cb3e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/7581a4407012f5f53365e11bafc520fd7f36bc9b",
|
||||
"reference": "7581a4407012f5f53365e11bafc520fd7f36bc9b",
|
||||
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/8f631589ab07b7b52fead814965f5a800459cb3e",
|
||||
"reference": "8f631589ab07b7b52fead814965f5a800459cb3e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"illuminate/support": "^10.0|^11.0|^12.0",
|
||||
"illuminate/support": "^10.0|^11.0|^12.0|^13.0",
|
||||
"nesbot/carbon": "^2.67|^3.0",
|
||||
"pestphp/pest": "^2.36|^3.0|^4.0",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"symfony/var-dumper": "^6.2.0|^7.0.0"
|
||||
"symfony/var-dumper": "^6.2.0|^7.0.0|^8.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@@ -448,7 +448,7 @@
|
||||
"issues": "https://github.com/laravel/serializable-closure/issues",
|
||||
"source": "https://github.com/laravel/serializable-closure"
|
||||
},
|
||||
"time": "2026-01-08T16:22:46+00:00"
|
||||
"time": "2026-02-03T06:55:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/fast-route",
|
||||
@@ -2888,29 +2888,29 @@
|
||||
},
|
||||
{
|
||||
"name": "doctrine/deprecations",
|
||||
"version": "1.1.5",
|
||||
"version": "1.1.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/deprecations.git",
|
||||
"reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38"
|
||||
"reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38",
|
||||
"reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38",
|
||||
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca",
|
||||
"reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpunit/phpunit": "<=7.5 || >=13"
|
||||
"phpunit/phpunit": "<=7.5 || >=14"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9 || ^12 || ^13",
|
||||
"phpstan/phpstan": "1.4.10 || 2.1.11",
|
||||
"doctrine/coding-standard": "^9 || ^12 || ^14",
|
||||
"phpstan/phpstan": "1.4.10 || 2.1.30",
|
||||
"phpstan/phpstan-phpunit": "^1.0 || ^2",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12.4 || ^13.0",
|
||||
"psr/log": "^1 || ^2 || ^3"
|
||||
},
|
||||
"suggest": {
|
||||
@@ -2930,9 +2930,9 @@
|
||||
"homepage": "https://www.doctrine-project.org/",
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/deprecations/issues",
|
||||
"source": "https://github.com/doctrine/deprecations/tree/1.1.5"
|
||||
"source": "https://github.com/doctrine/deprecations/tree/1.1.6"
|
||||
},
|
||||
"time": "2025-04-07T20:06:18+00:00"
|
||||
"time": "2026-02-07T07:09:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "felixfbecker/language-server-protocol",
|
||||
@@ -3697,29 +3697,29 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/diff",
|
||||
"version": "7.0.0",
|
||||
"version": "8.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/diff.git",
|
||||
"reference": "7ab1ea946c012266ca32390913653d844ecd085f"
|
||||
"reference": "a2b6d09d7729ee87d605a439469f9dcc39be5ea3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f",
|
||||
"reference": "7ab1ea946c012266ca32390913653d844ecd085f",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/a2b6d09d7729ee87d605a439469f9dcc39be5ea3",
|
||||
"reference": "a2b6d09d7729ee87d605a439469f9dcc39be5ea3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.3"
|
||||
"php": ">=8.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^12.0",
|
||||
"phpunit/phpunit": "^13.0",
|
||||
"symfony/process": "^7.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "7.0-dev"
|
||||
"dev-main": "8.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -3752,15 +3752,27 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/diff/issues",
|
||||
"security": "https://github.com/sebastianbergmann/diff/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/7.0.0"
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/8.0.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sebastianbergmann",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://liberapay.com/sebastianbergmann",
|
||||
"type": "liberapay"
|
||||
},
|
||||
{
|
||||
"url": "https://thanks.dev/u/gh/sebastianbergmann",
|
||||
"type": "thanks_dev"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/sebastian/diff",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-07T04:55:46+00:00"
|
||||
"time": "2026-02-06T04:42:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/array-to-xml",
|
||||
@@ -4551,16 +4563,16 @@
|
||||
},
|
||||
{
|
||||
"name": "vimeo/psalm",
|
||||
"version": "6.14.3",
|
||||
"version": "6.15.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vimeo/psalm.git",
|
||||
"reference": "d0b040a91f280f071c1abcb1b77ce3822058725a"
|
||||
"reference": "28dc127af1b5aecd52314f6f645bafc10d0e11f9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/vimeo/psalm/zipball/d0b040a91f280f071c1abcb1b77ce3822058725a",
|
||||
"reference": "d0b040a91f280f071c1abcb1b77ce3822058725a",
|
||||
"url": "https://api.github.com/repos/vimeo/psalm/zipball/28dc127af1b5aecd52314f6f645bafc10d0e11f9",
|
||||
"reference": "28dc127af1b5aecd52314f6f645bafc10d0e11f9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4584,7 +4596,7 @@
|
||||
"netresearch/jsonmapper": "^5.0",
|
||||
"nikic/php-parser": "^5.0.0",
|
||||
"php": "~8.1.31 || ~8.2.27 || ~8.3.16 || ~8.4.3 || ~8.5.0",
|
||||
"sebastian/diff": "^4.0 || ^5.0 || ^6.0 || ^7.0",
|
||||
"sebastian/diff": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0",
|
||||
"spatie/array-to-xml": "^2.17.0 || ^3.0",
|
||||
"symfony/console": "^6.0 || ^7.0 || ^8.0",
|
||||
"symfony/filesystem": "~6.3.12 || ~6.4.3 || ^7.0.3 || ^8.0",
|
||||
@@ -4665,7 +4677,7 @@
|
||||
"issues": "https://github.com/vimeo/psalm/issues",
|
||||
"source": "https://github.com/vimeo/psalm"
|
||||
},
|
||||
"time": "2025-12-23T15:36:48+00:00"
|
||||
"time": "2026-02-07T19:27:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "wapmorgan/php-deprecation-detector",
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
$domain = $_GET['domain'] ?? '';
|
||||
$domain = '';
|
||||
if (isset($_GET['domain']) && is_string($_GET['domain'])) {
|
||||
$domain = $_GET['domain'];
|
||||
}
|
||||
|
||||
if (!str_contains($domain, '.')) {
|
||||
http_response_code(400);
|
||||
|
||||
@@ -1,38 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="6.14.3@d0b040a91f280f071c1abcb1b77ce3822058725a">
|
||||
<file src="public/index.php">
|
||||
<MixedArgument>
|
||||
<code><![CDATA[$container->get(Guard::class)]]></code>
|
||||
<code><![CDATA[$container->get(\AIO\Auth\AuthManager::class)]]></code>
|
||||
<code><![CDATA[$container->get(\AIO\Data\ConfigurationManager::class)]]></code>
|
||||
</MixedArgument>
|
||||
</file>
|
||||
<file src="src/ContainerDefinitionFetcher.php">
|
||||
<MixedArgumentTypeCoercion>
|
||||
<code><![CDATA[$backupVolumes]]></code>
|
||||
<code><![CDATA[$capAdd]]></code>
|
||||
<code><![CDATA[$devices]]></code>
|
||||
</MixedArgumentTypeCoercion>
|
||||
</file>
|
||||
<file src="src/Controller/ConfigurationController.php">
|
||||
<PossiblyNullIterator>
|
||||
<code><![CDATA[$request->getParsedBody()]]></code>
|
||||
</PossiblyNullIterator>
|
||||
</file>
|
||||
<file src="src/DependencyInjection.php">
|
||||
<MixedArgument>
|
||||
<code><![CDATA[$container->get(DockerHubManager::class)]]></code>
|
||||
<code><![CDATA[$container->get(GitHubContainerRegistryManager::class)]]></code>
|
||||
<code><![CDATA[$container->get(\AIO\Auth\PasswordGenerator::class)]]></code>
|
||||
<code><![CDATA[$container->get(\AIO\ContainerDefinitionFetcher::class)]]></code>
|
||||
<code><![CDATA[$container->get(\AIO\Data\ConfigurationManager::class)]]></code>
|
||||
<code><![CDATA[$container->get(\AIO\Data\ConfigurationManager::class)]]></code>
|
||||
<code><![CDATA[$container->get(\AIO\Data\ConfigurationManager::class)]]></code>
|
||||
</MixedArgument>
|
||||
</file>
|
||||
<file src="src/Docker/DockerActionManager.php">
|
||||
<MixedOperand>
|
||||
<code><![CDATA[$output['Config']['Image']]]></code>
|
||||
</MixedOperand>
|
||||
</file>
|
||||
</files>
|
||||
<files psalm-version="6.15.1@28dc127af1b5aecd52314f6f645bafc10d0e11f9"/>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
errorBaseline="psalm-baseline.xml"
|
||||
findUnusedBaselineEntry="true"
|
||||
findUnusedCode="false"
|
||||
errorLevel="1"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="templates"/>
|
||||
|
||||
@@ -20,9 +20,7 @@ use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
/** @var \DI\Container */
|
||||
$container = \AIO\DependencyInjection::GetContainer();
|
||||
/** @var \AIO\Data\DataConst */
|
||||
$dataConst = $container->get(\AIO\Data\DataConst::class);
|
||||
ini_set('session.save_path', $dataConst->GetSessionDirectory());
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Auth;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Auth;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Container;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Container;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Container;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Container;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Container;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Container;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Container;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Container;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Container;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO;
|
||||
|
||||
@@ -22,10 +23,8 @@ readonly class ContainerDefinitionFetcher {
|
||||
|
||||
public function GetContainerById(string $id): Container
|
||||
{
|
||||
/** @var array */
|
||||
$containers = $this->FetchDefinition();
|
||||
|
||||
/** @psalm-var \AIO\Container\Container $container */
|
||||
foreach ($containers as $container) {
|
||||
if ($container->identifier === $id) {
|
||||
return $container;
|
||||
@@ -40,26 +39,22 @@ readonly class ContainerDefinitionFetcher {
|
||||
*/
|
||||
private function GetDefinition(): array
|
||||
{
|
||||
/** @psalm-var array $data */
|
||||
$data = json_decode((string)file_get_contents(DataConst::GetContainersDefinitionPath()), true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
$additionalContainerNames = [];
|
||||
/** @psalm-var string $communityContainer */
|
||||
foreach ($this->configurationManager->aioCommunityContainers as $communityContainer) {
|
||||
if ($communityContainer !== '') {
|
||||
$path = DataConst::GetCommunityContainersDirectory() . '/' . $communityContainer . '/' . $communityContainer . '.json';
|
||||
/** @psalm-var array $additionalData */
|
||||
$additionalData = json_decode((string)file_get_contents($path), true, 512, JSON_THROW_ON_ERROR);
|
||||
$data = array_merge_recursive($data, $additionalData);
|
||||
if (isset($additionalData['aio_services_v1'][0]['display_name']) && $additionalData['aio_services_v1'][0]['display_name'] !== '') {
|
||||
// Store container_name of community containers in variable for later
|
||||
$additionalContainerNames[] = (string) $additionalData['aio_services_v1'][0]['container_name'];
|
||||
$additionalContainerNames[] = $additionalData['aio_services_v1'][0]['container_name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$containers = [];
|
||||
/** @psalm-var array $entry */
|
||||
foreach ($data['aio_services_v1'] as $entry) {
|
||||
if ($entry['container_name'] === 'nextcloud-aio-clamav') {
|
||||
if (!$this->configurationManager->isClamavEnabled) {
|
||||
@@ -104,13 +99,12 @@ readonly class ContainerDefinitionFetcher {
|
||||
|
||||
$ports = new ContainerPorts();
|
||||
if (isset($entry['ports'])) {
|
||||
/** @psalm-var array $value */
|
||||
foreach ($entry['ports'] as $value) {
|
||||
$ports->AddPort(
|
||||
new ContainerPort(
|
||||
(string) $value['port_number'],
|
||||
(string) $value['ip_binding'],
|
||||
(string) $value['protocol']
|
||||
$value['port_number'],
|
||||
$value['ip_binding'],
|
||||
$value['protocol']
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -118,7 +112,6 @@ readonly class ContainerDefinitionFetcher {
|
||||
|
||||
$volumes = new ContainerVolumes();
|
||||
if (isset($entry['volumes'])) {
|
||||
/** @psalm-var array $value */
|
||||
foreach ($entry['volumes'] as $value) {
|
||||
if($value['source'] === '%BORGBACKUP_HOST_LOCATION%') {
|
||||
$value['source'] = $this->configurationManager->borgBackupHostLocation;
|
||||
@@ -155,9 +148,9 @@ readonly class ContainerDefinitionFetcher {
|
||||
}
|
||||
$volumes->AddVolume(
|
||||
new ContainerVolume(
|
||||
(string) $value['source'],
|
||||
(string) $value['destination'],
|
||||
(bool) $value['writeable']
|
||||
$value['source'],
|
||||
$value['destination'],
|
||||
$value['writeable']
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -165,18 +158,15 @@ readonly class ContainerDefinitionFetcher {
|
||||
|
||||
$dependsOn = [];
|
||||
if (isset($entry['depends_on'])) {
|
||||
/** @var array */
|
||||
$valueDependsOn = $entry['depends_on'];
|
||||
if ($entry['container_name'] === 'nextcloud-aio-apache') {
|
||||
// Add community containers first and default ones last so that aio_variables works correctly
|
||||
$valueDependsOnTemp = [];
|
||||
/** @psalm-var string $containerName */
|
||||
foreach ($additionalContainerNames as $containerName) {
|
||||
$valueDependsOnTemp[] = $containerName;
|
||||
}
|
||||
$valueDependsOn = array_merge_recursive($valueDependsOnTemp, $valueDependsOn);
|
||||
}
|
||||
/** @psalm-var string $value */
|
||||
foreach ($valueDependsOn as $value) {
|
||||
if ($value === 'nextcloud-aio-clamav') {
|
||||
if (!$this->configurationManager->isClamavEnabled) {
|
||||
@@ -221,7 +211,6 @@ readonly class ContainerDefinitionFetcher {
|
||||
|
||||
$variables = new ContainerEnvironmentVariables();
|
||||
if (isset($entry['environment'])) {
|
||||
/** @psalm-var string $value */
|
||||
foreach ($entry['environment'] as $value) {
|
||||
$variables->AddVariable($value);
|
||||
}
|
||||
@@ -229,7 +218,6 @@ readonly class ContainerDefinitionFetcher {
|
||||
|
||||
$aioVariables = new AioVariables();
|
||||
if (isset($entry['aio_variables'])) {
|
||||
/** @psalm-var string $value */
|
||||
foreach ($entry['aio_variables'] as $value) {
|
||||
$aioVariables->AddVariable($value);
|
||||
}
|
||||
@@ -237,28 +225,27 @@ readonly class ContainerDefinitionFetcher {
|
||||
|
||||
$displayName = '';
|
||||
if (isset($entry['display_name'])) {
|
||||
$displayName = (string) $entry['display_name'];
|
||||
$displayName = $entry['display_name'];
|
||||
}
|
||||
|
||||
$restartPolicy = '';
|
||||
if (isset($entry['restart'])) {
|
||||
$restartPolicy = (string) $entry['restart'];
|
||||
$restartPolicy = $entry['restart'];
|
||||
}
|
||||
|
||||
$maxShutdownTime = 10;
|
||||
if (isset($entry['stop_grace_period'])) {
|
||||
$maxShutdownTime = (int) $entry['stop_grace_period'];
|
||||
$maxShutdownTime = $entry['stop_grace_period'];
|
||||
}
|
||||
|
||||
$internalPort = '';
|
||||
if (isset($entry['internal_port'])) {
|
||||
$internalPort = (string) $entry['internal_port'];
|
||||
$internalPort = $entry['internal_port'];
|
||||
}
|
||||
|
||||
if (isset($entry['secrets'])) {
|
||||
// All secrets are registered with the configuration when they
|
||||
// are discovered so they can be later generated at time-of-use.
|
||||
/** @psalm-var string $secret */
|
||||
foreach ($entry['secrets'] as $secret) {
|
||||
$this->configurationManager->registerSecret($secret);
|
||||
}
|
||||
@@ -266,78 +253,73 @@ readonly class ContainerDefinitionFetcher {
|
||||
|
||||
$uiSecret = '';
|
||||
if (isset($entry['ui_secret'])) {
|
||||
$uiSecret = (string) $entry['ui_secret'];
|
||||
$uiSecret = $entry['ui_secret'];
|
||||
}
|
||||
|
||||
$devices = [];
|
||||
if (isset($entry['devices'])) {
|
||||
/** @var array */
|
||||
$devices = $entry['devices'];
|
||||
}
|
||||
|
||||
$enableNvidiaGpu = false;
|
||||
if (isset($entry['enable_nvidia_gpu'])) {
|
||||
$enableNvidiaGpu = (bool) $entry['enable_nvidia_gpu'];
|
||||
$enableNvidiaGpu = $entry['enable_nvidia_gpu'];
|
||||
}
|
||||
|
||||
$capAdd = [];
|
||||
if (isset($entry['cap_add'])) {
|
||||
/** @var array */
|
||||
$capAdd = $entry['cap_add'];
|
||||
}
|
||||
|
||||
$shmSize = -1;
|
||||
if (isset($entry['shm_size'])) {
|
||||
$shmSize = (int) $entry['shm_size'];
|
||||
$shmSize = $entry['shm_size'];
|
||||
}
|
||||
|
||||
$apparmorUnconfined = false;
|
||||
if (isset($entry['apparmor_unconfined'])) {
|
||||
$apparmorUnconfined = (bool) $entry['apparmor_unconfined'];
|
||||
$apparmorUnconfined = $entry['apparmor_unconfined'];
|
||||
}
|
||||
|
||||
$backupVolumes = [];
|
||||
if (isset($entry['backup_volumes'])) {
|
||||
/** @var array */
|
||||
$backupVolumes = $entry['backup_volumes'];
|
||||
}
|
||||
|
||||
$nextcloudExecCommands = [];
|
||||
if (isset($entry['nextcloud_exec_commands'])) {
|
||||
/** @var array */
|
||||
$nextcloudExecCommands = $entry['nextcloud_exec_commands'];
|
||||
}
|
||||
|
||||
$readOnlyRootFs = false;
|
||||
if (isset($entry['read_only'])) {
|
||||
$readOnlyRootFs = (bool) $entry['read_only'];
|
||||
$readOnlyRootFs = $entry['read_only'];
|
||||
}
|
||||
|
||||
$tmpfs = [];
|
||||
if (isset($entry['tmpfs'])) {
|
||||
/** @var array */
|
||||
$tmpfs = $entry['tmpfs'];
|
||||
}
|
||||
|
||||
$init = true;
|
||||
if (isset($entry['init'])) {
|
||||
$init = (bool) $entry['init'];
|
||||
$init = $entry['init'];
|
||||
}
|
||||
|
||||
$imageTag = '%AIO_CHANNEL%';
|
||||
if (isset($entry['image_tag'])) {
|
||||
$imageTag = (string) $entry['image_tag'];
|
||||
$imageTag = $entry['image_tag'];
|
||||
}
|
||||
|
||||
$documentation = '';
|
||||
if (isset($entry['documentation'])) {
|
||||
$documentation = (string) $entry['documentation'];
|
||||
$documentation = $entry['documentation'];
|
||||
}
|
||||
|
||||
$containers[] = new Container(
|
||||
(string) $entry['container_name'],
|
||||
$entry['container_name'],
|
||||
$displayName,
|
||||
(string) $entry['image'],
|
||||
$entry['image'],
|
||||
$restartPolicy,
|
||||
$maxShutdownTime,
|
||||
$ports,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Controller;
|
||||
|
||||
@@ -19,34 +20,26 @@ readonly class ConfigurationController {
|
||||
try {
|
||||
$this->configurationManager->startTransaction();
|
||||
if (isset($request->getParsedBody()['domain'])) {
|
||||
/** @var string */
|
||||
$domain = $request->getParsedBody()['domain'] ?? '';
|
||||
$skipDomainValidation = isset($request->getParsedBody()['skip_domain_validation']);
|
||||
$this->configurationManager->setDomain($domain, $skipDomainValidation);
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['current-master-password']) || isset($request->getParsedBody()['new-master-password'])) {
|
||||
/** @var string */
|
||||
$currentMasterPassword = $request->getParsedBody()['current-master-password'] ?? '';
|
||||
/** @var string */
|
||||
$newMasterPassword = $request->getParsedBody()['new-master-password'] ?? '';
|
||||
$this->configurationManager->changeMasterPassword($currentMasterPassword, $newMasterPassword);
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['borg_backup_host_location']) || isset($request->getParsedBody()['borg_remote_repo'])) {
|
||||
/** @var string */
|
||||
$location = $request->getParsedBody()['borg_backup_host_location'] ?? '';
|
||||
/** @var string */
|
||||
$borgRemoteRepo = $request->getParsedBody()['borg_remote_repo'] ?? '';
|
||||
$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'])) {
|
||||
/** @var string */
|
||||
$restoreLocation = $request->getParsedBody()['borg_restore_host_location'] ?? '';
|
||||
/** @var string */
|
||||
$borgRemoteRepo = $request->getParsedBody()['borg_restore_remote_repo'] ?? '';
|
||||
/** @var string */
|
||||
$borgPassword = $request->getParsedBody()['borg_restore_password'] ?? '';
|
||||
$this->configurationManager->setBorgRestoreLocationVarsAndPassword($restoreLocation, $borgRemoteRepo, $borgPassword);
|
||||
}
|
||||
@@ -62,7 +55,6 @@ readonly class ConfigurationController {
|
||||
} else {
|
||||
$successNotification = false;
|
||||
}
|
||||
/** @var string */
|
||||
$dailyBackupTime = $request->getParsedBody()['daily_backup_time'] ?? '';
|
||||
$this->configurationManager->setDailyBackupTime($dailyBackupTime, $enableAutomaticUpdates, $successNotification);
|
||||
}
|
||||
@@ -72,7 +64,6 @@ readonly class ConfigurationController {
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['additional_backup_directories'])) {
|
||||
/** @var string */
|
||||
$additionalBackupDirectories = $request->getParsedBody()['additional_backup_directories'] ?? '';
|
||||
$this->configurationManager->setAdditionalBackupDirectories($additionalBackupDirectories);
|
||||
}
|
||||
@@ -82,13 +73,11 @@ readonly class ConfigurationController {
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['timezone'])) {
|
||||
/** @var string */
|
||||
$timezone = $request->getParsedBody()['timezone'] ?? '';
|
||||
$this->configurationManager->timezone = $timezone;
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['options-form'])) {
|
||||
/** @var string */
|
||||
$officeSuiteChoice = $request->getParsedBody()['office_suite_choice'] ?? '';
|
||||
|
||||
if ($officeSuiteChoice === 'collabora') {
|
||||
@@ -114,7 +103,7 @@ readonly class ConfigurationController {
|
||||
$cc = $this->configurationManager->listAvailableCommunityContainers();
|
||||
$enabledCC = [];
|
||||
/**
|
||||
* @psalm-var string $item
|
||||
* @psalm-suppress PossiblyNullIterator
|
||||
*/
|
||||
foreach ($request->getParsedBody() as $item) {
|
||||
if (array_key_exists($item , $cc)) {
|
||||
@@ -129,7 +118,6 @@ readonly class ConfigurationController {
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['collabora_dictionaries'])) {
|
||||
/** @var string */
|
||||
$collaboraDictionaries = $request->getParsedBody()['collabora_dictionaries'] ?? '';
|
||||
$this->configurationManager->collaboraDictionaries = $collaboraDictionaries;
|
||||
}
|
||||
@@ -139,7 +127,6 @@ readonly class ConfigurationController {
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['collabora_additional_options'])) {
|
||||
/** @var string */
|
||||
$additionalCollaboraOptions = $request->getParsedBody()['collabora_additional_options'] ?? '';
|
||||
$this->configurationManager->collaboraAdditionalOptions = $additionalCollaboraOptions;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Controller;
|
||||
|
||||
@@ -125,7 +126,6 @@ readonly class DockerController {
|
||||
public function StartBackupContainerRestore(Request $request, Response $response, array $args) : Response {
|
||||
$this->configurationManager->startTransaction();
|
||||
$this->configurationManager->backupMode = 'restore';
|
||||
/** @var string */
|
||||
$this->configurationManager->selectedRestoreTime = $request->getParsedBody()['selected_restore_time'] ?? '';
|
||||
$this->configurationManager->restoreExcludePreviews = isset($request->getParsedBody()['restore-exclude-previews']);
|
||||
$this->configurationManager->commitTransaction();
|
||||
@@ -172,7 +172,6 @@ readonly class DockerController {
|
||||
$uri = $request->getUri();
|
||||
$host = $uri->getHost();
|
||||
$port = $uri->getPort();
|
||||
/** @var string */
|
||||
$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.');
|
||||
@@ -180,7 +179,7 @@ readonly class DockerController {
|
||||
}
|
||||
|
||||
if (isset($request->getParsedBody()['install_latest_major'])) {
|
||||
$installLatestMajor = '32';
|
||||
$installLatestMajor = '33';
|
||||
} else {
|
||||
$installLatestMajor = '';
|
||||
}
|
||||
@@ -286,7 +285,6 @@ readonly class DockerController {
|
||||
return;
|
||||
// Don't start if domaincheck is already running
|
||||
} elseif ($domaincheckContainer->GetRunningState() === ContainerState::Running) {
|
||||
/** @psalm-var mixed $domaincheckWasStarted */
|
||||
$domaincheckWasStarted = apcu_fetch($cacheKey);
|
||||
// Start domaincheck again when 10 minutes are over by not returning here
|
||||
if($domaincheckWasStarted !== false && is_string($domaincheckWasStarted)) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Controller;
|
||||
|
||||
@@ -21,7 +22,6 @@ readonly class LoginController {
|
||||
$response->getBody()->write("The login is blocked since Nextcloud is running.");
|
||||
return $response->withHeader('Location', '.')->withStatus(422);
|
||||
}
|
||||
/** @var string */
|
||||
$password = $request->getParsedBody()['password'] ?? '';
|
||||
if($this->authManager->CheckCredentials($password)) {
|
||||
$this->authManager->SetAuthState(true);
|
||||
@@ -33,7 +33,6 @@ readonly class LoginController {
|
||||
}
|
||||
|
||||
public function GetTryLogin(Request $request, Response $response, array $args) : Response {
|
||||
/** @var string */
|
||||
$token = $request->getQueryParams()['token'] ?? '';
|
||||
if($this->authManager->CheckToken($token)) {
|
||||
$this->authManager->SetAuthState(true);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Data;
|
||||
|
||||
@@ -114,7 +115,7 @@ class ConfigurationManager
|
||||
// Type-cast because old configs could have 1/0 for this key.
|
||||
get => (bool) $this->get('isFulltextsearchEnabled', false);
|
||||
// Elasticsearch does not work on kernels without seccomp anymore. See https://github.com/nextcloud/all-in-one/discussions/5768
|
||||
set { $this->set('isFulltextsearchEnabled', ($this->collaboraSeccompDisabled && $value)); }
|
||||
set { $this->set('isFulltextsearchEnabled', (!$this->collaboraSeccompDisabled && $value)); }
|
||||
}
|
||||
|
||||
public string $domain {
|
||||
@@ -288,7 +289,6 @@ class ConfigurationManager
|
||||
if ($this->config === [] && file_exists(DataConst::GetConfigFile()))
|
||||
{
|
||||
$configContent = (string)file_get_contents(DataConst::GetConfigFile());
|
||||
/** @var array */
|
||||
$this->config = json_decode($configContent, true, 512, JSON_THROW_ON_ERROR);
|
||||
}
|
||||
|
||||
@@ -333,7 +333,6 @@ class ConfigurationManager
|
||||
return '';
|
||||
}
|
||||
|
||||
/** @var array */
|
||||
$secrets = $this->get('secrets', []);
|
||||
if (!isset($secrets[$secretId])) {
|
||||
$secrets[$secretId] = bin2hex(random_bytes(24));
|
||||
@@ -341,10 +340,10 @@ class ConfigurationManager
|
||||
}
|
||||
|
||||
if ($secretId === 'BORGBACKUP_PASSWORD' && !file_exists(DataConst::GetBackupSecretFile())) {
|
||||
$this->doubleSafeBackupSecret((string)$secrets[$secretId]);
|
||||
$this->doubleSafeBackupSecret($secrets[$secretId]);
|
||||
}
|
||||
|
||||
return (string)$secrets[$secretId];
|
||||
return $secrets[$secretId];
|
||||
}
|
||||
|
||||
public function getRegisteredSecret(string $secretId) : string {
|
||||
@@ -468,17 +467,15 @@ class ConfigurationManager
|
||||
if ($this->shouldDomainValidationBeSkipped($skipDomainValidation)) {
|
||||
error_log('Skipping domain validation');
|
||||
} else {
|
||||
/** @var string */
|
||||
$dnsRecordIP = gethostbyname($domain);
|
||||
if ($dnsRecordIP === $domain) {
|
||||
$dnsRecordIP = '';
|
||||
}
|
||||
|
||||
if (empty($dnsRecordIP)) {
|
||||
/** @var array */
|
||||
$record = dns_get_record($domain, DNS_AAAA);
|
||||
if (isset($record[0]['ipv6']) && !empty($record[0]['ipv6'])) {
|
||||
$dnsRecordIP = (string) $record[0]['ipv6'];
|
||||
$dnsRecordIP = $record[0]['ipv6'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -698,13 +695,12 @@ class ConfigurationManager
|
||||
|
||||
private function getEnvironmentalVariableOrConfig(string $envVariableName, string $configName, string $defaultValue) : string {
|
||||
$envVariableOutput = getenv($envVariableName);
|
||||
/** @var mixed */
|
||||
$configValue = $this->get($configName, '');
|
||||
if ($envVariableOutput === false) {
|
||||
if ($configValue === '') {
|
||||
return $defaultValue;
|
||||
}
|
||||
return (string) $configValue;
|
||||
return $configValue;
|
||||
}
|
||||
|
||||
if (file_exists(DataConst::GetConfigFile())) {
|
||||
@@ -924,7 +920,6 @@ class ConfigurationManager
|
||||
$dir = array_diff($dir, array('..', '.', 'readme.md'));
|
||||
foreach ($dir as $id) {
|
||||
$filePath = DataConst::GetCommunityContainersDirectory() . '/' . $id . '/' . $id . '.json';
|
||||
/** @psalm-var mixed $fileContents */
|
||||
$fileContents = apcu_fetch($filePath);
|
||||
if (!is_string($fileContents)) {
|
||||
$fileContents = file_get_contents($filePath);
|
||||
@@ -932,11 +927,8 @@ class ConfigurationManager
|
||||
apcu_add($filePath, $fileContents);
|
||||
}
|
||||
}
|
||||
|
||||
/** @psalm-var array $json */
|
||||
$json = is_string($fileContents) ? json_decode($fileContents, true, 512, JSON_THROW_ON_ERROR) : false;
|
||||
if(isset($json['aio_services_v1']) && is_array($json['aio_services_v1'])) {
|
||||
/** @psalm-var array $service */
|
||||
if(is_array($json) && is_array($json['aio_services_v1'])) {
|
||||
foreach ($json['aio_services_v1'] as $service) {
|
||||
$documentation = is_string($service['documentation']) ? $service['documentation'] : '';
|
||||
if (is_string($service['display_name'])) {
|
||||
@@ -969,9 +961,8 @@ class ConfigurationManager
|
||||
return;
|
||||
}
|
||||
$this->startTransaction();
|
||||
/** @psalm-var string $variable */
|
||||
foreach ($input as $variable) {
|
||||
if (!str_contains($variable, '=')) {
|
||||
if (!is_string($variable) || !str_contains($variable, '=')) {
|
||||
error_log("Invalid input: '$variable' is not a string or does not contain an equal sign ('=')");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Data;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Data;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Docker;
|
||||
|
||||
@@ -54,10 +55,9 @@ readonly class DockerActionManager {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/** @var array */
|
||||
$responseBody = json_decode((string)$response->getBody(), true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
if ($responseBody['State']['Running'] ?? false === true) {
|
||||
if ($responseBody['State']['Running'] === true) {
|
||||
return ContainerState::Running;
|
||||
} else {
|
||||
return ContainerState::Stopped;
|
||||
@@ -75,10 +75,9 @@ readonly class DockerActionManager {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/** @var array */
|
||||
$responseBody = json_decode((string)$response->getBody(), true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
if ($responseBody['State']['Restarting'] ?? false === true) {
|
||||
if ($responseBody['State']['Restarting'] === true) {
|
||||
return ContainerState::Restarting;
|
||||
} else {
|
||||
return ContainerState::NotRestarting;
|
||||
@@ -100,7 +99,6 @@ readonly class DockerActionManager {
|
||||
return VersionState::Equal;
|
||||
}
|
||||
|
||||
/** @psalm-var string $runningDigest */
|
||||
foreach ($runningDigests as $runningDigest) {
|
||||
if ($runningDigest === $remoteDigest) {
|
||||
return VersionState::Equal;
|
||||
@@ -337,7 +335,6 @@ readonly class DockerActionManager {
|
||||
}
|
||||
|
||||
$tmpfs = [];
|
||||
/** @psalm-var string $tmp */
|
||||
foreach ($container->tmpfs as $tmp) {
|
||||
$mode = "";
|
||||
if (str_contains($tmp, ':')) {
|
||||
@@ -378,7 +375,6 @@ readonly class DockerActionManager {
|
||||
// Special things for the backup container which should not be exposed in the containers.json
|
||||
if (str_starts_with($container->identifier, 'nextcloud-aio-borgbackup')) {
|
||||
// Additional backup directories
|
||||
/** @psalm-var string $additionalBackupVolumes */
|
||||
foreach ($this->getAllBackupVolumes() as $additionalBackupVolumes) {
|
||||
if ($additionalBackupVolumes !== '') {
|
||||
$mounts[] = ["Type" => "volume", "Source" => $additionalBackupVolumes, "Target" => "/nextcloud_aio_volumes/" . $additionalBackupVolumes, "ReadOnly" => false];
|
||||
@@ -388,7 +384,6 @@ readonly class DockerActionManager {
|
||||
// Make volumes read only in case of borgbackup container. The viewer makes them writeable
|
||||
$isReadOnly = $container->identifier === 'nextcloud-aio-borgbackup';
|
||||
|
||||
/** @psalm-var string $additionalBackupDirectories */
|
||||
foreach ($this->configurationManager->getAdditionalBackupDirectoriesArray() as $additionalBackupDirectories) {
|
||||
if ($additionalBackupDirectories !== '') {
|
||||
if (!str_starts_with($additionalBackupDirectories, '/')) {
|
||||
@@ -584,7 +579,6 @@ readonly class DockerActionManager {
|
||||
$container = $this->containerDefinitionFetcher->GetContainerById($id);
|
||||
|
||||
$nextcloudExecCommands = '';
|
||||
/** @psalm-var string $execCommand */
|
||||
foreach ($container->nextcloudExecCommands as $execCommand) {
|
||||
$nextcloudExecCommands .= $execCommand . PHP_EOL;
|
||||
}
|
||||
@@ -602,12 +596,10 @@ readonly class DockerActionManager {
|
||||
private function GetRepoDigestsOfContainer(string $containerName): ?array {
|
||||
try {
|
||||
$containerUrl = $this->BuildApiUrl(sprintf('containers/%s/json', $containerName));
|
||||
/** @var array */
|
||||
$containerOutput = json_decode($this->guzzleClient->get($containerUrl)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
$imageName = (string) $containerOutput['Image'];
|
||||
$imageName = $containerOutput['Image'];
|
||||
|
||||
$imageUrl = $this->BuildApiUrl(sprintf('images/%s/json', $imageName));
|
||||
/** @var array */
|
||||
$imageOutput = json_decode($this->guzzleClient->get($imageUrl)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
if (!isset($imageOutput['RepoDigests'])) {
|
||||
@@ -622,7 +614,6 @@ readonly class DockerActionManager {
|
||||
|
||||
$repoDigestArray = [];
|
||||
$oneDigestGiven = false;
|
||||
/** @psalm-var string $repoDigest */
|
||||
foreach ($imageOutput['RepoDigests'] as $repoDigest) {
|
||||
$digestPosition = strpos($repoDigest, '@');
|
||||
if ($digestPosition === false) {
|
||||
@@ -645,7 +636,6 @@ readonly class DockerActionManager {
|
||||
|
||||
private function GetCurrentImageName(): string {
|
||||
$cacheKey = 'aio-image-name';
|
||||
/** @psalm-var mixed $imageName */
|
||||
$imageName = apcu_fetch($cacheKey);
|
||||
if ($imageName !== false && is_string($imageName)) {
|
||||
return $imageName;
|
||||
@@ -654,14 +644,13 @@ readonly class DockerActionManager {
|
||||
$containerName = 'nextcloud-aio-mastercontainer';
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/json', $containerName));
|
||||
try {
|
||||
/** @var array */
|
||||
$output = json_decode($this->guzzleClient->get($url)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
$imageNameArray = explode(':', (string) $output['Config']['Image']);
|
||||
$imageNameArray = explode(':', $output['Config']['Image']);
|
||||
if (count($imageNameArray) === 2) {
|
||||
$imageName = $imageNameArray[0];
|
||||
} else {
|
||||
error_log("No tag was found when getting the current channel. You probably did not follow the documentation correctly. Changing the imageName to the default " . (string) $output['Config']['Image']);
|
||||
$imageName = (string) $output['Config']['Image'];
|
||||
error_log("No tag was found when getting the current channel. You probably did not follow the documentation correctly. Changing the imageName to the default " . $output['Config']['Image']);
|
||||
$imageName = $output['Config']['Image'];
|
||||
}
|
||||
apcu_add($cacheKey, $imageName);
|
||||
return $imageName;
|
||||
@@ -674,7 +663,6 @@ readonly class DockerActionManager {
|
||||
|
||||
public function GetCurrentChannel(): string {
|
||||
$cacheKey = 'aio-ChannelName';
|
||||
/** @psalm-var mixed $channelName */
|
||||
$channelName = apcu_fetch($cacheKey);
|
||||
if ($channelName !== false && is_string($channelName)) {
|
||||
return $channelName;
|
||||
@@ -683,9 +671,8 @@ readonly class DockerActionManager {
|
||||
$containerName = 'nextcloud-aio-mastercontainer';
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/json', $containerName));
|
||||
try {
|
||||
/** @var array */
|
||||
$output = json_decode($this->guzzleClient->get($url)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
$tagArray = explode(':', (string) $output['Config']['Image']);
|
||||
$tagArray = explode(':', $output['Config']['Image']);
|
||||
if (count($tagArray) === 2) {
|
||||
$tag = $tagArray[1];
|
||||
} else {
|
||||
@@ -716,7 +703,6 @@ readonly class DockerActionManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @psalm-var string $runningDigest */
|
||||
foreach ($runningDigests as $runningDigest) {
|
||||
if ($remoteDigest === $runningDigest) {
|
||||
return false;
|
||||
@@ -732,7 +718,6 @@ readonly class DockerActionManager {
|
||||
|
||||
// schedule the exec
|
||||
$url = $this->BuildApiUrl(sprintf('containers/%s/exec', urlencode($containerName)));
|
||||
/** @var array */
|
||||
$response = json_decode(
|
||||
$this->guzzleClient->request(
|
||||
'POST',
|
||||
@@ -755,7 +740,7 @@ readonly class DockerActionManager {
|
||||
JSON_THROW_ON_ERROR,
|
||||
);
|
||||
|
||||
$id = (string) $response['Id'];
|
||||
$id = $response['Id'];
|
||||
|
||||
// start the exec
|
||||
$url = $this->BuildApiUrl(sprintf('exec/%s/start', $id));
|
||||
@@ -894,11 +879,9 @@ readonly class DockerActionManager {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/** @var array */
|
||||
$responseBody = json_decode((string)$response->getBody(), true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
/** @var null|int */
|
||||
$exitCode = $responseBody['State']['ExitCode'] ?? null;
|
||||
$exitCode = $responseBody['State']['ExitCode'];
|
||||
if (is_int($exitCode)) {
|
||||
return $exitCode;
|
||||
} else {
|
||||
@@ -918,11 +901,9 @@ readonly class DockerActionManager {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/** @var array */
|
||||
$responseBody = json_decode((string)$response->getBody(), true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
/** @var null|int */
|
||||
$exitCode = $responseBody['State']['ExitCode'] ?? null;
|
||||
$exitCode = $responseBody['State']['ExitCode'];
|
||||
if (is_int($exitCode)) {
|
||||
return $exitCode;
|
||||
} else {
|
||||
@@ -952,7 +933,6 @@ readonly class DockerActionManager {
|
||||
$imageName = $imageName . ':' . $this->GetCurrentChannel();
|
||||
try {
|
||||
$imageUrl = $this->BuildApiUrl(sprintf('images/%s/json', $imageName));
|
||||
/** @var array */
|
||||
$imageOutput = json_decode($this->guzzleClient->get($imageUrl)->getBody()->getContents(), true, 512, JSON_THROW_ON_ERROR);
|
||||
|
||||
if (!isset($imageOutput['Created'])) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Docker;
|
||||
|
||||
@@ -17,7 +18,6 @@ readonly class DockerHubManager {
|
||||
public function GetLatestDigestOfTag(string $name, string $tag) : ?string {
|
||||
$cacheKey = 'dockerhub-manifest-' . $name . $tag;
|
||||
|
||||
/** @psalm-var mixed $cachedVersion */
|
||||
$cachedVersion = apcu_fetch($cacheKey);
|
||||
if($cachedVersion !== false && is_string($cachedVersion)) {
|
||||
return $cachedVersion;
|
||||
@@ -31,10 +31,9 @@ readonly class DockerHubManager {
|
||||
'https://auth.docker.io/token?service=registry.docker.io&scope=repository:' . $name . ':pull'
|
||||
);
|
||||
$body = $authTokenRequest->getBody()->getContents();
|
||||
/** @var array */
|
||||
$decodedBody = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
|
||||
if(isset($decodedBody['token'])) {
|
||||
$authToken = (string) $decodedBody['token'];
|
||||
$authToken = $decodedBody['token'];
|
||||
$manifestRequest = $this->guzzleClient->request(
|
||||
'HEAD',
|
||||
'https://registry-1.docker.io/v2/'.$name.'/manifests/' . $tag,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Docker;
|
||||
|
||||
@@ -18,7 +18,6 @@ readonly class GitHubContainerRegistryManager
|
||||
{
|
||||
$cacheKey = 'ghcr-manifest-' . $name . $tag;
|
||||
|
||||
/** @psalm-var mixed $cachedVersion */
|
||||
$cachedVersion = apcu_fetch($cacheKey);
|
||||
if ($cachedVersion !== false && is_string($cachedVersion)) {
|
||||
return $cachedVersion;
|
||||
@@ -32,10 +31,9 @@ readonly class GitHubContainerRegistryManager
|
||||
'https://ghcr.io/token?scope=repository:' . $name . ':pull'
|
||||
);
|
||||
$body = $authTokenRequest->getBody()->getContents();
|
||||
/** @var array */
|
||||
$decodedBody = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
|
||||
if (isset($decodedBody['token'])) {
|
||||
$authToken = (string) $decodedBody['token'];
|
||||
$authToken = $decodedBody['token'];
|
||||
$manifestRequest = $this->guzzleClient->request(
|
||||
'HEAD',
|
||||
'https://ghcr.io/v2/' . $name . '/manifests/' . $tag,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Middleware;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Twig;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Twig;
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
{% if c.documentation != '' %}
|
||||
(<a target="_blank" href="{{ c.documentation }}">docs</a>)
|
||||
{% endif %}
|
||||
{% if c.GetUpdateState().value == 'different' %}
|
||||
⚠️ Update available
|
||||
{% endif %}
|
||||
</span>
|
||||
{% if c.GetUiSecret() != '' %}
|
||||
<details>
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
{% 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 = '' %}
|
||||
{% set newMajorVersionString = '26 Winter' %}
|
||||
{% set oldMajorVersionString = '25 Autumn' %}
|
||||
|
||||
{% if is_backup_container_running == true %}
|
||||
{% if borg_backup_mode == 'backup' or borg_backup_mode == 'restore' %}
|
||||
@@ -297,7 +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 follow <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/6865">this documentation</a></strong></p>
|
||||
<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/7523">this documentation</a></strong></p>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -343,7 +344,7 @@
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input id="base_path" type="hidden" name="base_path" value="">
|
||||
{% if newMajorVersionString != '' %}
|
||||
<input type="checkbox" id="install_latest_major" name="install_latest_major"><label for="install_latest_major">Install Nextcloud Hub {{ newMajorVersionString }} (if unchecked, Nextcloud Hub 10 will get installed)</label><br>
|
||||
<input type="checkbox" id="install_latest_major" name="install_latest_major"><label for="install_latest_major">Install Nextcloud Hub {{ newMajorVersionString }} (if unchecked, Nextcloud Hub {{ oldMajorVersionString }} will get installed)</label><br>
|
||||
{% endif %}
|
||||
<input type="submit" value="Download and start containers" />
|
||||
</form>
|
||||
|
||||
@@ -1 +1 @@
|
||||
12.6.1
|
||||
12.7.0
|
||||
|
||||
@@ -72,8 +72,8 @@
|
||||
<li>Good Nextcloud integration</li>
|
||||
<li>Open core</li>
|
||||
<li>Best performance</li>
|
||||
<li>Limited ODF compatibility</li>
|
||||
<li>Best Microsoft compatibility</li>
|
||||
<li>Limited ODF compatibility</li>
|
||||
</ul>
|
||||
{% if isAnyRunning == false %}
|
||||
<a href="https://www.onlyoffice.com/" target="_blank" class="office-learn-more" onclick="event.stopPropagation();">
|
||||
|
||||
38
readme.md
38
readme.md
@@ -7,7 +7,9 @@ The official Nextcloud installation method. Nextcloud AIO provides easy deployme
|
||||
|
||||
Included are:
|
||||
- Nextcloud
|
||||
- High performance backend for Nextcloud Files
|
||||
- High performance backend for Nextcloud Files (Client Push)
|
||||
- Redis & APCU for performant caching
|
||||
- PostgreSQL as database
|
||||
- Nextcloud Office (optional)
|
||||
- High performance backend for Nextcloud Talk and TURN-server (optional)
|
||||
- Nextcloud Talk Recording-server (optional)
|
||||
@@ -88,9 +90,10 @@ Included are:
|
||||
## How to use this?
|
||||
|
||||
The steps below are written for Linux. For platform-specific guidance see:
|
||||
- macOS: [How to run AIO on macOS](#how-to-run-aio-on-macos)
|
||||
- Windows: [How to run AIO on Windows](#how-to-run-aio-on-windows)
|
||||
- Synology DSM: [How to run AIO on Synology DSM](#how-to-run-aio-on-synology-dsm)
|
||||
- macOS: [How to run AIO on macOS?](#how-to-run-aio-on-macos)
|
||||
- Windows: [How to run AIO on Windows?](#how-to-run-aio-on-windows)
|
||||
- Unraid: [How to run AIO on Unraid?](#how-to-run-aio-on-unraid)
|
||||
- Synology DSM: [How to run AIO on Synology DSM?](#how-to-run-aio-on-synology-dsm)
|
||||
- TrueNAS SCALE: [Can I run AIO on TrueNAS SCALE?](#can-i-run-aio-on-truenas-scale)
|
||||
|
||||
> [!IMPORTANT]
|
||||
@@ -203,6 +206,7 @@ https://your-domain-that-points-to-this-server.tld:8443
|
||||
- [Are other ports than the default 443 for Nextcloud supported?](#are-other-ports-than-the-default-443-for-nextcloud-supported)
|
||||
- [Can I run Nextcloud in a subdirectory on my domain?](#can-i-run-nextcloud-in-a-subdirectory-on-my-domain)
|
||||
- [How can I access Nextcloud locally?](#how-can-i-access-nextcloud-locally)
|
||||
- [How to overwrite the local DNS resolution for some domains or add extra hosts to the containers?](#how-to-overwrite-the-local-dns-resolution-for-some-domains-or-add-extra-hosts-to-the-containers)
|
||||
- [How to skip the domain validation?](#how-to-skip-the-domain-validation)
|
||||
- [How to resolve firewall problems with Fedora Linux, RHEL OS, CentOS, SUSE Linux and others?](#how-to-resolve-firewall-problems-with-fedora-linux-rhel-os-centos-suse-linux-and-others)
|
||||
- [What can I do to fix the internal or reserved ip-address error?](#what-can-i-do-to-fix-the-internal-or-reserved-ip-address-error)
|
||||
@@ -237,6 +241,7 @@ https://your-domain-that-points-to-this-server.tld:8443
|
||||
- [Guides](#guides)
|
||||
- [How to run AIO on macOS?](#how-to-run-aio-on-macos)
|
||||
- [How to run AIO on Windows?](#how-to-run-aio-on-windows)
|
||||
- [How to run AIO on Unraid?](#how-to-run-aio-on-unraid)
|
||||
- [How to run AIO on Synology DSM](#how-to-run-aio-on-synology-dsm)
|
||||
- [How to run AIO with Portainer?](#how-to-run-aio-with-portainer)
|
||||
- [Can I run AIO on TrueNAS SCALE?](#can-i-run-aio-on-truenas-scale)
|
||||
@@ -375,6 +380,12 @@ Now that this is out of the way, the recommended way how to access Nextcloud loc
|
||||
- https://dockerlabs.collabnix.com/intermediate/networking/Configuring_DNS.html
|
||||
Apart from that there is now a community container that can be added to the AIO stack: https://github.com/nextcloud/all-in-one/tree/main/community-containers/pi-hole
|
||||
|
||||
### How to overwrite the local DNS resolution for some domains or add extra hosts to the containers?
|
||||
|
||||
For some use cases, you might need to overwrite the local DNS resolution of some domains inside the containers. On Linux, you can do so either by using a local DNS server as described in the section above and add a local DNS entry into the dns server and make your containers use that DNS server.
|
||||
|
||||
On Linux, depending on your network and docker configuration, it might also work to simply edit the `/etc/hosts` file. Add your custom entry like `172.18.0.1 mail.example.com` as additional line to the file and restart docker which should automatically push the entry to all docker containers.
|
||||
|
||||
### How to skip the domain validation?
|
||||
If you are completely sure that you've configured everything correctly and are not able to pass the domain validation, you may skip the domain validation by adding `--env SKIP_DOMAIN_VALIDATION=true` to the docker run command of the mastercontainer (but before the last line `ghcr.io/nextcloud-releases/all-in-one:latest`! If it was started already, you will need to stop the mastercontainer, remove it (no data will be lost) and recreate it using the docker run command that you initially used).
|
||||
|
||||
@@ -598,6 +609,23 @@ Also, you may be interested in adjusting Nextcloud's Datadir to store the files
|
||||
> [!NOTE]
|
||||
> Almost all commands in this project's documentation use `sudo docker ...`. Since `sudo` is not available on Windows, you simply remove `sudo` from the commands and they should work.
|
||||
|
||||
### How to run AIO on Unraid?
|
||||
|
||||
Generally on Unraid, before installing Nextcloud AIO, you should make sure to specify a directory for all docker related files instead of using the default docker image before continuing the installation process. See this guide for more details: https://forums.unraid.net/topic/103924-how-to-turn-my-docker-file-to-a-docker-folder/#comment-962317
|
||||
|
||||
Additionally, you might need to create a custom user script to start all sibling containers of AIO automatically whenever the server reboots (since the docker plugin in Unraid does not respect the normal docker restart-policy that is configured for all AIO containers). See the User scripts docs: https://docs.unraid.net/unraid-os/using-unraid-to/run-docker-containers/managing-and-customizing-containers/#user-scripts-plugin. You would need to use a script like the one below and use the schedule option `@reboot` to start the containers automatically.
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Wait 120 seconds for other server components to start correctly
|
||||
sleep 120
|
||||
|
||||
# Execute the actual command
|
||||
docker exec --env START_CONTAINERS=1 nextcloud-aio-mastercontainer /daily-backup.sh`
|
||||
```
|
||||
|
||||
Apart from that, the installation of AIO should work like on "normal" Linux. So refer to the Linux instructions for installation.
|
||||
|
||||
### How to run AIO on Synology DSM
|
||||
On Synology, there are two things different in comparison to Linux: instead of using `--volume /var/run/docker.sock:/var/run/docker.sock:ro`, you need to use `--volume /volume1/docker/docker.sock:/var/run/docker.sock:ro` to run it. You also need to add `--env WATCHTOWER_DOCKER_SOCKET_PATH="/volume1/docker/docker.sock"`to the docker run command of the mastercontainer (but before the last line `ghcr.io/nextcloud-releases/all-in-one:latest`). Additionally, you likely need to adjust the internally used api version. See [this documentation](#how-to-adjust-the-internally-used-docker-api-version). Apart from that it should work and behave the same like on Linux. Obviously the Synology Docker GUI will not work with that so you will need to either use SSH or create a user-defined script task in the task scheduler as the user 'root' in order to run the command.
|
||||
|
||||
@@ -854,7 +882,7 @@ Be aware that this solution does not back up files and folders that are mounted
|
||||
Backed up will get all important data of your Nextcloud AIO instance required to restore the instance, like the database, your files and configuration files of the mastercontainer and else. Files and folders that are mounted into Nextcloud using the external storage app are not getting backed up. There is currently no way to exclude the data directory because it would require hacks like running files:scan and would make the backup solution much more unreliable (since the database and your files/folders need to stay in sync). If you still don't want your datadirectory to be backed up, see https://github.com/nextcloud/all-in-one#how-to-enable-automatic-updates-without-creating-a-backup-beforehand for options (there is a hint what needs to be backed up in which order).
|
||||
|
||||
### How to adjust borgs retention policy?
|
||||
The built-in borg-based backup solution has by default a retention policy of `--keep-within=7d --keep-weekly=4 --keep-monthly=6`. See https://borgbackup.readthedocs.io/en/stable/usage/prune.html for what these values mean. You can adjust the retention policy by providing `--env BORG_RETENTION_POLICY="--keep-within=7d --keep-weekly=4 --keep-monthly=6"` to the docker run command of the mastercontainer (but before the last line `ghcr.io/nextcloud-releases/all-in-one:latest`! If it was started already, you will need to stop the mastercontainer, remove it (no data will be lost) and recreate it using the docker run command that you initially used) and customize the value to your fitting. ⚠️ Please make sure that this value is valid, otherwise backup pruning will bug out!
|
||||
The built-in borg-based backup solution has by default a retention policy of `--keep-within=7d --keep-weekly=4 --keep-monthly=6`. See https://borgbackup.readthedocs.io/en/stable/usage/prune.html for what these values mean. You can adjust the retention policy by providing `--env BORG_RETENTION_POLICY="--keep-within=7d --keep-weekly=4 --keep-monthly=6"` to the docker run command of the mastercontainer (but before the last line `ghcr.io/nextcloud-releases/all-in-one:latest`! If it was started already, you will need to stop the mastercontainer, remove it (no data will be lost) and recreate it using the docker run command that you initially used) and customize the value to your fitting. ⚠️ Please make sure that this value is valid, otherwise backup pruning will bug out! Also, don't include the `-a` or `--glob-archives` option, since AIO already provides it and you can't override it. See https://github.com/nextcloud/all-in-one/pull/7616
|
||||
|
||||
### How to migrate from AIO to AIO?
|
||||
If you have the borg backup feature enabled, you can copy it over to the new host and restore from the backup. This guide assumes the new installation data dir will be on `/mnt/datadir`, you can adjust the steps if it's elsewhere.
|
||||
|
||||
Reference in New Issue
Block a user